summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gdbinit133
-rw-r--r--.gitattributes261
-rw-r--r--EXTENSIONS4
-rw-r--r--Makefile.global6
-rw-r--r--NEWS950
-rw-r--r--README.NEW-OUTPUT-API142
-rw-r--r--README.PARAMETER_PARSING_API1
-rw-r--r--README.RELEASE_PROCESS34
-rw-r--r--README.input_filter22
-rw-r--r--TODO136
-rw-r--r--TODO-5.14
-rw-r--r--TODO-PHP589
-rw-r--r--TSRM/TSRM.c16
-rw-r--r--TSRM/TSRM.h7
-rw-r--r--TSRM/acconfig.h1
-rw-r--r--TSRM/build.mk2
-rw-r--r--TSRM/configure.in4
-rw-r--r--TSRM/tsrm.m42
-rw-r--r--TSRM/tsrm_virtual_cwd.c58
-rw-r--r--TSRM/tsrm_virtual_cwd.h10
-rw-r--r--TSRM/tsrm_win32.c12
-rw-r--r--TSRM/tsrm_win32.h4
-rwxr-xr-xUPGRADING1294
-rw-r--r--UPGRADING.INTERNALS190
-rw-r--r--Zend/Makefile.am2
-rw-r--r--Zend/README.ZEND_MM3
-rw-r--r--Zend/Zend.dsp12
-rw-r--r--Zend/Zend.m441
-rw-r--r--Zend/ZendTS.dsp12
-rw-r--r--Zend/acconfig.h127
-rw-r--r--Zend/bench.php1
-rw-r--r--Zend/build.mk2
-rw-r--r--Zend/configure.in99
-rw-r--r--Zend/micro_bench.php358
-rw-r--r--Zend/tests/026.phpt2
-rw-r--r--Zend/tests/033.phpt4
-rw-r--r--Zend/tests/argument_restriction_001.phpt16
-rw-r--r--Zend/tests/argument_restriction_002.phpt16
-rw-r--r--Zend/tests/argument_restriction_003.phpt19
-rw-r--r--Zend/tests/argument_restriction_004.phpt17
-rw-r--r--Zend/tests/argument_restriction_005.phpt11
-rw-r--r--Zend/tests/argument_restriction_006.phpt16
-rw-r--r--Zend/tests/array_type_hint_001.phpt2
-rw-r--r--Zend/tests/binary-32bit.phpt154
-rw-r--r--Zend/tests/binary.phpt154
-rw-r--r--Zend/tests/bug31098.phpt16
-rw-r--r--Zend/tests/bug35655.phpt1
-rw-r--r--Zend/tests/bug39018.phpt39
-rw-r--r--Zend/tests/bug39304.phpt9
-rw-r--r--Zend/tests/bug39304_2_4.phpt18
-rw-r--r--Zend/tests/bug42767.phpt1
-rw-r--r--Zend/tests/bug47981.phpt4
-rw-r--r--Zend/tests/bug51421.phpt18
-rw-r--r--Zend/tests/bug52041.phpt49
-rw-r--r--Zend/tests/bug52237.phpt1
-rw-r--r--Zend/tests/bug52614.phpt83
-rw-r--r--Zend/tests/bug52940.phpt23
-rw-r--r--Zend/tests/bug53347.phpt17
-rw-r--r--Zend/tests/bug53511.phpt33
-rw-r--r--Zend/tests/bug53748.phpt39
-rw-r--r--Zend/tests/bug54262.phpt2
-rw-r--r--Zend/tests/bug54547.phpt21
-rw-r--r--Zend/tests/bug55086.phpt36
-rw-r--r--Zend/tests/bug55135.phpt38
-rw-r--r--Zend/tests/bug55137.phpt26
-rw-r--r--Zend/tests/bug55247.phpt33
-rw-r--r--Zend/tests/bug55305.phpt16
-rw-r--r--Zend/tests/bug55339.phpt31
-rw-r--r--Zend/tests/bug55445.phpt8
-rw-r--r--Zend/tests/bug55578.phpt20
-rw-r--r--Zend/tests/bug55705.phpt9
-rw-r--r--Zend/tests/bug55825.phpt17
-rw-r--r--Zend/tests/bug60139.phpt2
-rw-r--r--Zend/tests/bug60169.phpt11
-rw-r--r--Zend/tests/bug60350.phpt11
-rw-r--r--Zend/tests/bug60362.phpt74
-rw-r--r--Zend/tests/bug60444.phpt18
-rw-r--r--Zend/tests/bug60536_001.phpt25
-rw-r--r--Zend/tests/bug60536_002.phpt40
-rw-r--r--Zend/tests/bug60536_003.phpt46
-rw-r--r--Zend/tests/bug60536_004.phpt37
-rw-r--r--Zend/tests/bug60536_005.phpt38
-rw-r--r--Zend/tests/bug60573.phpt84
-rw-r--r--Zend/tests/bug60611.phpt27
-rw-r--r--Zend/tests/bug60613.phpt18
-rw-r--r--Zend/tests/bug60978.phpt10
-rw-r--r--Zend/tests/bug61011.phpt35
-rw-r--r--Zend/tests/bug61225.phpt9
-rw-r--r--Zend/tests/bug61442.phpt30
-rw-r--r--Zend/tests/bug61761.phpt19
-rw-r--r--Zend/tests/bug61782.phpt29
-rw-r--r--Zend/tests/bug62005.phpt2
-rw-r--r--Zend/tests/bug62097.phpt17
-rw-r--r--Zend/tests/bug62358.phpt32
-rw-r--r--Zend/tests/bug62653.phpt33
-rw-r--r--Zend/tests/bug62680.phpt2
-rw-r--r--Zend/tests/bug62892.phpt21
-rw-r--r--Zend/tests/bug62907.phpt22
-rw-r--r--Zend/tests/bug62956.phpt20
-rw-r--r--Zend/tests/bug63173.phpt12
-rw-r--r--Zend/tests/bug63219.phpt18
-rw-r--r--Zend/tests/bug63305.phpt43
-rw-r--r--Zend/tests/bug63336.phpt24
-rw-r--r--Zend/tests/callable_type_hint_001.phpt39
-rw-r--r--Zend/tests/callable_type_hint_002.phpt27
-rw-r--r--Zend/tests/callable_type_hint_003.phpt21
-rw-r--r--Zend/tests/cast_to_string.phptbin621 -> 721 bytes
-rw-r--r--Zend/tests/class_exists_003.phpt6
-rw-r--r--Zend/tests/closure_005.phpt74
-rw-r--r--Zend/tests/closure_007.phpt38
-rw-r--r--Zend/tests/closure_020.phpt6
-rw-r--r--Zend/tests/closure_024.phpt26
-rw-r--r--Zend/tests/closure_026.phpt11
-rw-r--r--Zend/tests/closure_036.phpt33
-rw-r--r--Zend/tests/closure_037.phpt47
-rw-r--r--Zend/tests/closure_038.phpt58
-rw-r--r--Zend/tests/closure_039.phpt58
-rw-r--r--Zend/tests/closure_040.phpt45
-rw-r--r--Zend/tests/closure_041.phpt106
-rw-r--r--Zend/tests/closure_042.phpt29
-rw-r--r--Zend/tests/closure_043.phpt86
-rw-r--r--Zend/tests/closure_044.phpt78
-rw-r--r--Zend/tests/closure_045.phpt19
-rw-r--r--Zend/tests/closure_046.phpt70
-rw-r--r--Zend/tests/concat_001.phpt20
-rw-r--r--Zend/tests/constants_005.phpt3
-rw-r--r--Zend/tests/debug_backtrace_limit.phpt133
-rw-r--r--Zend/tests/debug_print_backtrace_limit.phpt31
-rw-r--r--Zend/tests/declare_001.phpt20
-rw-r--r--Zend/tests/declare_002.phpt31
-rw-r--r--Zend/tests/declare_003.phpt24
-rw-r--r--Zend/tests/declare_004.phpt27
-rw-r--r--Zend/tests/dereference_001.phpt51
-rw-r--r--Zend/tests/dereference_002.phpt79
-rw-r--r--Zend/tests/dereference_003.phpt46
-rw-r--r--Zend/tests/dereference_004.phpt27
-rw-r--r--Zend/tests/dereference_005.phpt38
-rw-r--r--Zend/tests/dereference_006.phpt30
-rw-r--r--Zend/tests/dereference_007.phpt37
-rw-r--r--Zend/tests/dereference_008.phpt33
-rw-r--r--Zend/tests/dereference_009.phpt26
-rw-r--r--Zend/tests/dereference_010.phpt27
-rw-r--r--Zend/tests/dereference_011.phpt45
-rw-r--r--Zend/tests/dereference_012.phpt56
-rw-r--r--Zend/tests/dereference_013.phpt38
-rw-r--r--Zend/tests/dereference_014.phpt34
-rw-r--r--Zend/tests/empty_str_offset.phpt89
-rw-r--r--Zend/tests/error_reporting01.phpt2
-rw-r--r--Zend/tests/error_reporting05.phpt2
-rw-r--r--Zend/tests/error_reporting06.phpt2
-rw-r--r--Zend/tests/error_reporting07.phpt2
-rw-r--r--Zend/tests/error_reporting10.phpt4
-rw-r--r--Zend/tests/fr47160.phpt150
-rw-r--r--Zend/tests/function_arguments_001.phpt2
-rw-r--r--Zend/tests/function_arguments_002.phpt2
-rw-r--r--Zend/tests/gc_022.phpt2
-rw-r--r--Zend/tests/gc_029.phpt2
-rw-r--r--Zend/tests/gc_029_zts.phpt37
-rw-r--r--Zend/tests/indexing_001.phpt2
-rw-r--r--Zend/tests/indirect_call_array_001.phpt11
-rw-r--r--Zend/tests/indirect_call_array_002.phpt11
-rw-r--r--Zend/tests/indirect_call_array_003.phpt38
-rw-r--r--Zend/tests/indirect_call_array_004.phpt71
-rw-r--r--Zend/tests/indirect_method_call_001.phpt20
-rw-r--r--Zend/tests/indirect_method_call_002.phpt32
-rw-r--r--Zend/tests/indirect_method_call_003.phpt23
-rw-r--r--Zend/tests/indirect_method_call_004.phpt26
-rw-r--r--Zend/tests/indirect_method_call_005.phpt16
-rw-r--r--Zend/tests/indirect_property_access.phpt26
-rw-r--r--Zend/tests/indirect_reference_this.phpt2
-rw-r--r--Zend/tests/isset_003.phpt4
-rw-r--r--Zend/tests/isset_003_2_4.phpt42
-rw-r--r--Zend/tests/isset_str_offset.phpt89
-rw-r--r--Zend/tests/magic_by_ref_010.phpt30
-rw-r--r--Zend/tests/method_static_var.phpt30
-rw-r--r--Zend/tests/multibyte/multibyte_encoding_001.phpt3
-rw-r--r--Zend/tests/multibyte/multibyte_encoding_002.phpt3
-rw-r--r--Zend/tests/multibyte/multibyte_encoding_003.phptbin449 -> 471 bytes
-rw-r--r--Zend/tests/multibyte/multibyte_encoding_004.phpt5
-rw-r--r--Zend/tests/multibyte/multibyte_encoding_005.phpt5
-rw-r--r--Zend/tests/multibyte/multibyte_encoding_006.phptbin599 -> 629 bytes
-rw-r--r--Zend/tests/nowdoc_013.phpt1
-rw-r--r--Zend/tests/nowdoc_014.phpt1
-rw-r--r--Zend/tests/ns_071.phpt2
-rw-r--r--Zend/tests/ns_086.phpt8
-rw-r--r--Zend/tests/objects_002.phpt2
-rw-r--r--Zend/tests/objects_003.phpt2
-rw-r--r--Zend/tests/objects_004.phpt2
-rw-r--r--Zend/tests/objects_005.phpt2
-rw-r--r--Zend/tests/objects_006.phpt2
-rw-r--r--Zend/tests/objects_007.phpt2
-rw-r--r--Zend/tests/objects_008.phpt2
-rw-r--r--Zend/tests/objects_009.phpt2
-rw-r--r--Zend/tests/offset_assign.phpt8
-rw-r--r--Zend/tests/offset_string.phpt24
-rw-r--r--Zend/tests/result_unused.phpt29
-rw-r--r--Zend/tests/str_offset_001.phpt51
-rw-r--r--Zend/tests/str_offset_002.phpt9
-rw-r--r--Zend/tests/trait_exists_001.phpt21
-rw-r--r--Zend/tests/trait_exists_002.phpt21
-rw-r--r--Zend/tests/trait_exists_003.phpt24
-rw-r--r--Zend/tests/traits/bug54441.phpt19
-rw-r--r--Zend/tests/traits/bug55137.phpt26
-rw-r--r--Zend/tests/traits/bug55214.phpt71
-rw-r--r--Zend/tests/traits/bug55355.phpt46
-rw-r--r--Zend/tests/traits/bug55372.phpt28
-rw-r--r--Zend/tests/traits/bug55424.phpt35
-rw-r--r--Zend/tests/traits/bug55524.phpt15
-rw-r--r--Zend/tests/traits/bug55554a.phpt34
-rw-r--r--Zend/tests/traits/bug55554b.phpt56
-rw-r--r--Zend/tests/traits/bug55554c.phpt46
-rw-r--r--Zend/tests/traits/bug55554d.phpt32
-rw-r--r--Zend/tests/traits/bug55554e.phpt30
-rw-r--r--Zend/tests/traits/bug55554f.phpt29
-rw-r--r--Zend/tests/traits/bug55554g.phpt29
-rw-r--r--Zend/tests/traits/bug60145.phpt17
-rw-r--r--Zend/tests/traits/bug60153.phpt19
-rw-r--r--Zend/tests/traits/bug60165a.phpt17
-rw-r--r--Zend/tests/traits/bug60165b.phpt17
-rw-r--r--Zend/tests/traits/bug60165c.phpt22
-rw-r--r--Zend/tests/traits/bug60165d.phpt21
-rw-r--r--Zend/tests/traits/bug60173.phpt12
-rw-r--r--Zend/tests/traits/bug60217a.phpt26
-rw-r--r--Zend/tests/traits/bug60217b.phpt26
-rw-r--r--Zend/tests/traits/bug60217c.phpt26
-rw-r--r--Zend/tests/traits/bug60369.phpt17
-rw-r--r--Zend/tests/traits/bug60717.phpt73
-rw-r--r--Zend/tests/traits/bug60809.phpt36
-rw-r--r--Zend/tests/traits/bug61052.phpt18
-rw-r--r--Zend/tests/traits/bug61998.phpt68
-rw-r--r--Zend/tests/traits/bugs/abstract-methods01.phpt19
-rw-r--r--Zend/tests/traits/bugs/abstract-methods02.phpt26
-rw-r--r--Zend/tests/traits/bugs/abstract-methods03.phpt22
-rw-r--r--Zend/tests/traits/bugs/abstract-methods04.phpt36
-rw-r--r--Zend/tests/traits/bugs/abstract-methods05.phpt25
-rw-r--r--Zend/tests/traits/bugs/abstract-methods06.phpt26
-rw-r--r--Zend/tests/traits/bugs/alias-semantics.phpt23
-rw-r--r--Zend/tests/traits/bugs/alias-semantics02.phpt25
-rw-r--r--Zend/tests/traits/bugs/alias01.phpt26
-rw-r--r--Zend/tests/traits/bugs/case-sensitive.phpt23
-rw-r--r--Zend/tests/traits/bugs/interfaces.phpt19
-rw-r--r--Zend/tests/traits/bugs/missing-trait.phpt15
-rw-r--r--Zend/tests/traits/bugs/overridding-conflicting-methods.phpt31
-rw-r--r--Zend/tests/traits/bugs/overridding-conflicting-property-initializer.phpt23
-rw-r--r--Zend/tests/traits/conflict001.phpt25
-rw-r--r--Zend/tests/traits/conflict002.phpt32
-rw-r--r--Zend/tests/traits/conflict003.phpt31
-rw-r--r--Zend/tests/traits/error_001.phpt28
-rw-r--r--Zend/tests/traits/error_002.phpt12
-rw-r--r--Zend/tests/traits/error_003.phpt15
-rw-r--r--Zend/tests/traits/error_004.phpt15
-rw-r--r--Zend/tests/traits/error_005.phpt15
-rw-r--r--Zend/tests/traits/error_006.phpt15
-rw-r--r--Zend/tests/traits/error_007.phpt13
-rw-r--r--Zend/tests/traits/error_008.phpt12
-rw-r--r--Zend/tests/traits/error_009.phpt12
-rw-r--r--Zend/tests/traits/error_010.phpt27
-rw-r--r--Zend/tests/traits/error_011.phpt26
-rw-r--r--Zend/tests/traits/error_012.phpt19
-rw-r--r--Zend/tests/traits/error_013.phpt19
-rw-r--r--Zend/tests/traits/error_014.phpt23
-rw-r--r--Zend/tests/traits/error_015.phpt26
-rw-r--r--Zend/tests/traits/error_016.phpt12
-rw-r--r--Zend/tests/traits/flattening001.phpt42
-rw-r--r--Zend/tests/traits/flattening002.phpt28
-rw-r--r--Zend/tests/traits/flattening003.phpt32
-rw-r--r--Zend/tests/traits/get_declared_traits_001.phpt19
-rw-r--r--Zend/tests/traits/get_declared_traits_002.phpt20
-rw-r--r--Zend/tests/traits/get_declared_traits_003.phpt25
-rw-r--r--Zend/tests/traits/inheritance001.phpt24
-rw-r--r--Zend/tests/traits/inheritance002.phpt27
-rw-r--r--Zend/tests/traits/inheritance003.phpt38
-rw-r--r--Zend/tests/traits/interface_001.phpt25
-rw-r--r--Zend/tests/traits/interface_002.phpt24
-rw-r--r--Zend/tests/traits/interface_003.phpt27
-rw-r--r--Zend/tests/traits/language001.phpt21
-rw-r--r--Zend/tests/traits/language002.phpt32
-rw-r--r--Zend/tests/traits/language003.phpt29
-rw-r--r--Zend/tests/traits/language004.phpt31
-rw-r--r--Zend/tests/traits/language005.phpt40
-rw-r--r--Zend/tests/traits/language006.phpt31
-rw-r--r--Zend/tests/traits/language007.phpt30
-rw-r--r--Zend/tests/traits/language008a.phpt23
-rw-r--r--Zend/tests/traits/language008b.phpt30
-rw-r--r--Zend/tests/traits/language009.phpt36
-rw-r--r--Zend/tests/traits/language010.phpt30
-rw-r--r--Zend/tests/traits/language011.phpt30
-rw-r--r--Zend/tests/traits/language012.phpt27
-rw-r--r--Zend/tests/traits/language013.phpt37
-rw-r--r--Zend/tests/traits/methods_001.phpt39
-rw-r--r--Zend/tests/traits/methods_002.phpt28
-rw-r--r--Zend/tests/traits/methods_003.phpt24
-rw-r--r--Zend/tests/traits/noctor001.phpt28
-rw-r--r--Zend/tests/traits/property001.phpt41
-rw-r--r--Zend/tests/traits/property002.phpt32
-rw-r--r--Zend/tests/traits/property003.phpt30
-rw-r--r--Zend/tests/traits/property004.phpt30
-rw-r--r--Zend/tests/traits/property005.phpt40
-rw-r--r--Zend/tests/traits/property006.phpt37
-rw-r--r--Zend/tests/traits/property007.phpt38
-rw-r--r--Zend/tests/traits/property008.phpt62
-rw-r--r--Zend/tests/traits/property009.phpt59
-rw-r--r--Zend/tests/traits/static_001.phpt22
-rw-r--r--Zend/tests/traits/static_002.phpt23
-rw-r--r--Zend/tests/traits/static_003.phpt27
-rw-r--r--Zend/tests/traits/static_004.phpt22
-rw-r--r--Zend/tests/traits/static_forward_static_call.phpt28
-rw-r--r--Zend/tests/traits/static_get_called_class.phpt24
-rw-r--r--Zend/tests/traits/trait_constant_001.phpt36
-rw-r--r--Zend/tests/traits/trait_constant_002.phpt27
-rw-r--r--Zend/tests/unset_cv05.phpt10
-rw-r--r--Zend/tests/unset_cv06.phpt17
-rw-r--r--Zend/tests/unset_cv07.phpt2
-rw-r--r--Zend/tests/unset_cv08.phpt2
-rw-r--r--Zend/zend.c200
-rw-r--r--Zend/zend.h171
-rw-r--r--Zend/zend_API.c604
-rw-r--r--Zend/zend_API.h180
-rw-r--r--Zend/zend_alloc.c212
-rw-r--r--Zend/zend_alloc.h34
-rw-r--r--Zend/zend_builtin_functions.c301
-rw-r--r--Zend/zend_builtin_functions.h2
-rw-r--r--Zend/zend_closures.c241
-rw-r--r--Zend/zend_closures.h3
-rw-r--r--Zend/zend_compile.c3708
-rw-r--r--Zend/zend_compile.h266
-rw-r--r--Zend/zend_constants.c143
-rw-r--r--Zend/zend_constants.h1
-rw-r--r--Zend/zend_dtrace.c108
-rw-r--r--Zend/zend_dtrace.d37
-rw-r--r--Zend/zend_dtrace.h48
-rw-r--r--Zend/zend_errors.h2
-rw-r--r--Zend/zend_exceptions.c32
-rw-r--r--Zend/zend_execute.c856
-rw-r--r--Zend/zend_execute.h103
-rw-r--r--Zend/zend_execute_API.c281
-rw-r--r--Zend/zend_extensions.h2
-rw-r--r--Zend/zend_fast_cache.h141
-rw-r--r--Zend/zend_float.c20
-rw-r--r--Zend/zend_gc.c185
-rw-r--r--Zend/zend_gc.h2
-rw-r--r--Zend/zend_globals.h47
-rw-r--r--Zend/zend_hash.c193
-rw-r--r--Zend/zend_hash.h15
-rw-r--r--Zend/zend_highlight.c23
-rw-r--r--Zend/zend_highlight.h1
-rw-r--r--Zend/zend_indent.c8
-rw-r--r--Zend/zend_ini.c10
-rw-r--r--Zend/zend_ini.h2
-rw-r--r--Zend/zend_ini_scanner.c2
-rw-r--r--Zend/zend_ini_scanner_defs.h2
-rw-r--r--Zend/zend_interfaces.c2
-rw-r--r--Zend/zend_interfaces.h2
-rw-r--r--Zend/zend_iterators.c6
-rw-r--r--Zend/zend_language_parser.y483
-rw-r--r--Zend/zend_language_scanner.c5326
-rw-r--r--Zend/zend_language_scanner.h7
-rw-r--r--Zend/zend_language_scanner.l611
-rw-r--r--Zend/zend_language_scanner_defs.h2
-rw-r--r--Zend/zend_list.c17
-rw-r--r--Zend/zend_list.h14
-rw-r--r--Zend/zend_modules.h4
-rw-r--r--Zend/zend_multibyte.c1194
-rw-r--r--Zend/zend_multibyte.h78
-rw-r--r--Zend/zend_multiply.h12
-rw-r--r--Zend/zend_object_handlers.c543
-rw-r--r--Zend/zend_object_handlers.h33
-rw-r--r--Zend/zend_objects.c92
-rw-r--r--Zend/zend_objects_API.c15
-rw-r--r--Zend/zend_objects_API.h2
-rw-r--r--Zend/zend_opcode.c295
-rw-r--r--Zend/zend_operators.c128
-rw-r--r--Zend/zend_operators.h461
-rw-r--r--Zend/zend_ptr_stack.c5
-rw-r--r--Zend/zend_ptr_stack.h17
-rw-r--r--Zend/zend_signal.c414
-rw-r--r--Zend/zend_signal.h108
-rw-r--r--Zend/zend_stack.c12
-rw-r--r--Zend/zend_stream.c5
-rw-r--r--Zend/zend_stream.h2
-rw-r--r--Zend/zend_string.c233
-rw-r--r--Zend/zend_string.h73
-rw-r--r--Zend/zend_strtod.c67
-rw-r--r--Zend/zend_strtod.h7
-rw-r--r--Zend/zend_types.h2
-rw-r--r--Zend/zend_variables.c62
-rw-r--r--Zend/zend_variables.h16
-rw-r--r--Zend/zend_vm_def.h3293
-rw-r--r--Zend/zend_vm_execute.h27932
-rw-r--r--Zend/zend_vm_execute.skl19
-rw-r--r--Zend/zend_vm_gen.php214
-rw-r--r--Zend/zend_vm_opcodes.h6
-rw-r--r--acconfig.h.in1
-rw-r--r--acinclude.m4159
-rw-r--r--build/build.mk1
-rw-r--r--build/build2.mk8
-rwxr-xr-xbuild/buildcheck.sh25
-rwxr-xr-xbuildconf7
-rw-r--r--configure.in283
-rw-r--r--ext/bz2/bz2.c22
-rw-r--r--ext/calendar/tests/jdtomonthname.phpt4
-rw-r--r--ext/com_dotnet/com_com.c10
-rw-r--r--ext/com_dotnet/com_dotnet.c4
-rw-r--r--ext/com_dotnet/com_handlers.c27
-rw-r--r--ext/com_dotnet/com_misc.c2
-rw-r--r--ext/com_dotnet/com_olechar.c4
-rw-r--r--ext/com_dotnet/com_persist.c46
-rw-r--r--ext/com_dotnet/com_saproxy.c14
-rw-r--r--ext/com_dotnet/com_typeinfo.c4
-rw-r--r--ext/com_dotnet/com_variant.c6
-rw-r--r--ext/com_dotnet/com_wrapper.c20
-rw-r--r--ext/com_dotnet/php_com_dotnet_internal.h3
-rw-r--r--ext/curl/interface.c101
-rw-r--r--ext/curl/streams.c4
-rw-r--r--ext/curl/tests/bug55767.phpt53
-rw-r--r--ext/curl/tests/bug63363.phpt29
-rw-r--r--ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt4
-rw-r--r--ext/curl/tests/curl_setopt_basic001.phpt35
-rw-r--r--ext/date/lib/parse_date.c100
-rw-r--r--ext/date/lib/parse_date.re2
-rw-r--r--ext/date/lib/parse_iso_intervals.c2
-rw-r--r--ext/date/php_date.c109
-rw-r--r--ext/date/php_date.h2
-rw-r--r--ext/date/tests/bug52062.phpt2
-rw-r--r--ext/date/tests/bug62561.phpt16
-rw-r--r--ext/date/tests/bug62896.phpt42
-rw-r--r--ext/date/tests/date-lenient-create.phpt149
-rw-r--r--ext/date/tests/date-lenient.phpt146
-rw-r--r--ext/date/tests/date_default_timezone_get-1-win32.phpt4
-rw-r--r--ext/date/tests/date_default_timezone_get-1.phpt4
-rw-r--r--ext/date/tests/date_default_timezone_get-2-win32.phpt20
-rw-r--r--ext/date/tests/date_default_timezone_get-2.phpt2
-rw-r--r--ext/date/tests/date_default_timezone_set-1.phpt4
-rw-r--r--ext/dba/config.m437
-rw-r--r--ext/dba/dba.c32
-rw-r--r--ext/dba/dba_db4.c2
-rw-r--r--ext/dba/dba_tcadb.c221
-rw-r--r--ext/dba/libflatfile/flatfile.c1
-rw-r--r--ext/dba/libinifile/inifile.c1
-rw-r--r--ext/dba/php_tcadb.h (renamed from sapi/cli/php_cli_readline.h)26
-rw-r--r--ext/dba/tests/dba_cdb_make.phpt3
-rw-r--r--ext/dba/tests/dba_tcadb.phpt50
-rw-r--r--ext/dom/attr.c2
-rw-r--r--ext/dom/document.c74
-rw-r--r--ext/dom/dom_iterators.c4
-rw-r--r--ext/dom/domerrorhandler.c2
-rw-r--r--ext/dom/domimplementation.c7
-rw-r--r--ext/dom/element.c24
-rw-r--r--ext/dom/namednodemap.c12
-rw-r--r--ext/dom/node.c28
-rw-r--r--ext/dom/nodelist.c4
-rw-r--r--ext/dom/php_dom.c24
-rw-r--r--ext/dom/tests/DOMAttr_value_basic_001.phpt4
-rw-r--r--ext/dom/tests/DOMAttr_value_basic_002.phpt4
-rw-r--r--ext/dom/tests/DOMCharacterData_data_error_002.phpt4
-rw-r--r--ext/dom/tests/DOMCharacterData_length_error_001.phpt4
-rw-r--r--ext/dom/tests/DOMDocument_loadHTML_error1.phpt2
-rw-r--r--ext/dom/tests/DOMDocument_saveHTML_variant2.phpt26
-rw-r--r--ext/dom/tests/bug47430.phpt4
-rw-r--r--ext/dom/text.c2
-rw-r--r--ext/dom/xml_common.h8
-rw-r--r--ext/dom/xpath.c9
-rw-r--r--ext/enchant/enchant.c21
-rw-r--r--ext/ereg/config.w322
-rw-r--r--ext/ereg/ereg.c76
-rw-r--r--ext/ereg/php_ereg.h16
-rw-r--r--ext/ereg/tests/ereg_replace_variation_001.phpt5
-rw-r--r--ext/ereg/tests/ereg_replace_variation_002.phpt5
-rw-r--r--ext/ereg/tests/ereg_replace_variation_003.phpt5
-rw-r--r--ext/ereg/tests/ereg_variation_001.phpt5
-rw-r--r--ext/ereg/tests/ereg_variation_002.phpt5
-rw-r--r--ext/ereg/tests/eregi_replace_variation_001.phpt5
-rw-r--r--ext/ereg/tests/eregi_replace_variation_002.phpt5
-rw-r--r--ext/ereg/tests/eregi_replace_variation_003.phpt5
-rw-r--r--ext/ereg/tests/eregi_variation_001.phpt5
-rw-r--r--ext/ereg/tests/eregi_variation_002.phpt5
-rw-r--r--ext/ereg/tests/split_variation_001.phpt5
-rw-r--r--ext/ereg/tests/split_variation_002.phpt5
-rw-r--r--ext/ereg/tests/split_variation_003.phpt5
-rw-r--r--ext/ereg/tests/spliti_variation_001.phpt5
-rw-r--r--ext/ereg/tests/spliti_variation_002.phpt5
-rw-r--r--ext/ereg/tests/spliti_variation_003.phpt5
-rw-r--r--ext/ereg/tests/sql_regcase_variation_001.phpt5
-rw-r--r--ext/exif/exif.c156
-rw-r--r--ext/exif/tests/bug34704.phpt1
-rw-r--r--ext/exif/tests/exif002.phpt1
-rw-r--r--ext/exif/tests/exif006.phpt90
-rw-r--r--ext/fileinfo/config.w3226
-rw-r--r--ext/fileinfo/fileinfo.c23
-rw-r--r--ext/fileinfo/libmagic.patch235
-rw-r--r--ext/fileinfo/libmagic/apprentice.c42
-rw-r--r--ext/fileinfo/libmagic/print.c3
-rw-r--r--ext/fileinfo/php_fileinfo.h2
-rw-r--r--ext/fileinfo/tests/finfo_open_001.phpt20
-rw-r--r--ext/fileinfo/tests/finfo_open_error-win32.phpt17
-rw-r--r--ext/fileinfo/tests/finfo_open_error.phpt10
-rw-r--r--ext/filter/filter.c23
-rw-r--r--ext/filter/filter_private.h6
-rw-r--r--ext/filter/logical_filters.c7
-rw-r--r--ext/filter/sanitizing_filters.c15
-rw-r--r--ext/filter/tests/bug39763.phpt19
-rw-r--r--ext/filter/tests/bug42718-2.phpt3
-rw-r--r--ext/filter/tests/bug42718.phpt1
-rw-r--r--ext/filter/tests/bug49510.phpt36
-rw-r--r--ext/ftp/ftp.c12
-rw-r--r--ext/ftp/php_ftp.c32
-rw-r--r--ext/gd/config.m450
-rw-r--r--ext/gd/config.w328
-rw-r--r--ext/gd/gd.c116
-rw-r--r--ext/gd/gd_ctx.c100
-rw-r--r--ext/gd/libgd/gd.h5
-rw-r--r--ext/gd/libgd/gd_io.h1
-rw-r--r--ext/gd/libgd/gd_webp.c201
-rw-r--r--ext/gd/libgd/webpimg.c900
-rw-r--r--ext/gd/libgd/webpimg.h181
-rw-r--r--ext/gd/php_gd.h15
-rw-r--r--ext/gmp/gmp.c8
-rw-r--r--ext/gmp/tests/022-win32.phpt90
-rw-r--r--ext/gmp/tests/022.phpt3
-rw-r--r--ext/gmp/tests/gmp_nextprime-win32.phpt45
-rw-r--r--ext/gmp/tests/gmp_nextprime.phpt3
-rw-r--r--ext/hash/config.m46
-rw-r--r--ext/hash/config.w324
-rw-r--r--ext/hash/hash.c23
-rw-r--r--ext/hash/hash_adler32.c11
-rw-r--r--ext/hash/hash_fnv.c229
-rw-r--r--ext/hash/hash_joaat.c99
-rw-r--r--ext/hash/hash_md.c4
-rw-r--r--ext/hash/hash_salsa.c224
-rw-r--r--ext/hash/hash_sha.c4
-rw-r--r--ext/hash/hash_tiger.c80
-rw-r--r--ext/hash/php_hash.h5
-rw-r--r--ext/hash/php_hash_fnv.h79
-rw-r--r--ext/hash/php_hash_joaat.h (renamed from main/safe_mode.h)38
-rw-r--r--ext/hash/tests/fnv132.phpt202
-rw-r--r--ext/hash/tests/fnv164.phpt202
-rw-r--r--ext/hash/tests/hash_algos.phpt92
-rw-r--r--ext/hash/tests/hash_copy_001.phpt156
-rw-r--r--ext/hash/tests/hash_file_basic1.phpt2
-rw-r--r--ext/hash/tests/hash_hmac_basic.phpt2
-rw-r--r--ext/hash/tests/hash_hmac_file_basic.phpt2
-rw-r--r--ext/hash/tests/joaat.phpt34
-rw-r--r--ext/hash/tests/mhash_001.phpt4
-rw-r--r--ext/hash/tests/mhash_003.phpt2
-rw-r--r--ext/hash/tests/mhash_004.phpt2
-rw-r--r--ext/hash/tests/tiger.phpt11
-rw-r--r--ext/iconv/iconv.c265
-rw-r--r--ext/iconv/tests/bug52211.phpt17
-rw-r--r--ext/iconv/tests/translit-utf8.phpt1
-rw-r--r--ext/imap/php_imap.c22
-rw-r--r--ext/imap/tests/imap_errors_basic.phpt2
-rw-r--r--ext/interbase/ibase_query.c9
-rw-r--r--ext/interbase/interbase.rc81
-rw-r--r--ext/intl/collator/collator_class.c3
-rw-r--r--ext/intl/common/common_error.c11
-rw-r--r--ext/intl/config.m418
-rw-r--r--ext/intl/config.w3216
-rw-r--r--ext/intl/dateformat/dateformat_class.c3
-rw-r--r--ext/intl/doc/collator_api.php8
-rw-r--r--ext/intl/doc/common_api.php4
-rw-r--r--ext/intl/doc/datefmt_api.php4
-rw-r--r--ext/intl/doc/formatter_api.php4
-rw-r--r--ext/intl/doc/msgfmt_api.php4
-rw-r--r--ext/intl/formatter/formatter_class.c3
-rw-r--r--ext/intl/grapheme/grapheme_string.c14
-rw-r--r--ext/intl/idn/idn.c238
-rw-r--r--ext/intl/intl_convert.c4
-rw-r--r--ext/intl/locale/locale_class.c2
-rw-r--r--ext/intl/msgformat/msgformat_class.c3
-rw-r--r--ext/intl/normalizer/normalizer_class.c2
-rw-r--r--ext/intl/normalizer/normalizer_normalize.c6
-rw-r--r--ext/intl/php_intl.c66
-rw-r--r--ext/intl/resourcebundle/resourcebundle.c2
-rw-r--r--ext/intl/resourcebundle/resourcebundle_class.c25
-rw-r--r--ext/intl/spoofchecker/spoofchecker.c60
-rw-r--r--ext/intl/spoofchecker/spoofchecker.h24
-rw-r--r--ext/intl/spoofchecker/spoofchecker_class.c210
-rw-r--r--ext/intl/spoofchecker/spoofchecker_class.h76
-rw-r--r--ext/intl/spoofchecker/spoofchecker_create.c59
-rw-r--r--ext/intl/spoofchecker/spoofchecker_create.h24
-rw-r--r--ext/intl/spoofchecker/spoofchecker_main.c142
-rw-r--r--ext/intl/spoofchecker/spoofchecker_main.h27
-rw-r--r--ext/intl/tests/bug55562.phpt13
-rw-r--r--ext/intl/tests/bug62915-2.phpt6
-rw-r--r--ext/intl/tests/formatter_get_error.phpt2
-rw-r--r--ext/intl/tests/idn_uts46_basic.phpt53
-rw-r--r--ext/intl/tests/idn_uts46_errors.phpt89
-rw-r--r--ext/intl/tests/locale_accept.phpt2
-rw-r--r--ext/intl/tests/locale_get_display_script2.phpt2
-rw-r--r--ext/intl/tests/locale_get_display_script3.phpt275
-rw-r--r--ext/intl/tests/resourcebundle_null_mandatory_args.phpt28
-rw-r--r--ext/intl/tests/spoofchecker_001.phpt23
-rw-r--r--ext/intl/tests/spoofchecker_002.phpt20
-rw-r--r--ext/intl/tests/spoofchecker_003.phpt25
-rw-r--r--ext/intl/tests/spoofchecker_004.phpt28
-rw-r--r--ext/intl/tests/transliterator_clone.phpt21
-rw-r--r--ext/intl/tests/transliterator_create_basic.phpt20
-rw-r--r--ext/intl/tests/transliterator_create_error.phpt21
-rw-r--r--ext/intl/tests/transliterator_create_from_rule_basic.phpt28
-rw-r--r--ext/intl/tests/transliterator_create_from_rule_error.phpt53
-rw-r--r--ext/intl/tests/transliterator_create_inverse_basic.phpt32
-rw-r--r--ext/intl/tests/transliterator_create_inverse_error.phpt21
-rw-r--r--ext/intl/tests/transliterator_get_error_code_basic.phpt25
-rw-r--r--ext/intl/tests/transliterator_get_error_code_error.phpt24
-rw-r--r--ext/intl/tests/transliterator_get_error_message_basic.phpt25
-rw-r--r--ext/intl/tests/transliterator_get_error_message_error.phpt24
-rw-r--r--ext/intl/tests/transliterator_list_ids_basic.phpt16
-rw-r--r--ext/intl/tests/transliterator_list_ids_error.phpt18
-rw-r--r--ext/intl/tests/transliterator_property_id.phpt21
-rw-r--r--ext/intl/tests/transliterator_transliterate_basic.phpt20
-rw-r--r--ext/intl/tests/transliterator_transliterate_error.phpt60
-rw-r--r--ext/intl/tests/transliterator_transliterate_variant1.phpt37
-rw-r--r--ext/intl/transliterator/transliterator.c138
-rw-r--r--ext/intl/transliterator/transliterator.h29
-rw-r--r--ext/intl/transliterator/transliterator_class.c434
-rw-r--r--ext/intl/transliterator/transliterator_class.h65
-rw-r--r--ext/intl/transliterator/transliterator_methods.c542
-rw-r--r--ext/intl/transliterator/transliterator_methods.h38
-rw-r--r--ext/json/JSON_parser.c29
-rw-r--r--ext/json/JSON_parser.h9
-rw-r--r--ext/json/config.w321
-rw-r--r--ext/json/json.c178
-rw-r--r--ext/json/php_json.h24
-rw-r--r--ext/json/tests/008.phpt17
-rw-r--r--ext/json/tests/bug53946.phpt16
-rw-r--r--ext/json/tests/bug61978.phpt47
-rw-r--r--ext/json/tests/json_decode_error.phpt4
-rw-r--r--ext/json/tests/json_encode_basic.phpt2
-rw-r--r--ext/json/tests/json_encode_numeric.phpt26
-rw-r--r--ext/json/tests/json_encode_pretty_print.phpt40
-rw-r--r--ext/json/tests/json_encode_unescaped_slashes.phpt12
-rw-r--r--ext/json/tests/serialize.phpt80
-rw-r--r--ext/json/utf8_to_utf16.c15
-rw-r--r--ext/json/utf8_to_utf16.h2
-rw-r--r--ext/ldap/config.w3211
-rw-r--r--ext/ldap/ldap.c208
-rw-r--r--ext/ldap/tests/ldap_control_paged_results_variation1.phpt56
-rw-r--r--ext/ldap/tests/ldap_control_paged_results_variation2.phpt72
-rw-r--r--ext/ldap/tests/ldap_control_paged_results_variation3.phpt100
-rw-r--r--ext/libxml/libxml.c271
-rw-r--r--ext/libxml/php_libxml.h4
-rw-r--r--ext/libxml/tests/libxml_set_external_entity_loader_basic.phpt48
-rw-r--r--ext/libxml/tests/libxml_set_external_entity_loader_error1.phpt39
-rw-r--r--ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt72
-rw-r--r--ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt45
-rw-r--r--ext/mbstring/config.m48
-rw-r--r--ext/mbstring/config.w3210
-rw-r--r--ext/mbstring/libmbfl/NEWS30
-rw-r--r--ext/mbstring/libmbfl/filters/Makefile.am30
-rw-r--r--ext/mbstring/libmbfl/filters/emoji2uni.h1227
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_ascii.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_base64.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_big5.c133
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_big5.h5
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c23
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp850.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp866.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp932.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp936.c146
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c10
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c6
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c78
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.h43
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_gb18030.c473
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_gb18030.h43
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_htmlent.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_hz.c12
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c6
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022_kr.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.c168
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.h44
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c433
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.h43
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_jis.c4
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_qprint.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis.c11
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c725
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.h49
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c700
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.h44
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c927
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.h70
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c4
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_open.h1
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_uhc.c1
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf32.c11
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf7.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf8.c219
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c362
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.h55
-rwxr-xr-xext/mbstring/libmbfl/filters/mk_emoji_tbl.pl425
-rw-r--r--ext/mbstring/libmbfl/filters/sjis_mac2uni.h349
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_table_cp932_ext.h35
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_table_cp936.h283
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_table_gb18030.h233
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_table_jis.h59
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_table_jis2004.h5067
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_table_uhc.h90
-rw-r--r--ext/mbstring/libmbfl/mbfl/eaw_table.h32
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfilter.c364
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfilter.h16
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_consts.h5
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_convert.c42
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_encoding.c22
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_encoding.h14
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_ident.c48
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_ident.h2
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c4
-rw-r--r--ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk7
-rw-r--r--ext/mbstring/libmbfl/tests/emoji.c119
-rw-r--r--ext/mbstring/mb_gpc.c70
-rw-r--r--ext/mbstring/mb_gpc.h9
-rw-r--r--ext/mbstring/mbstring.c1435
-rw-r--r--ext/mbstring/mbstring.h46
-rw-r--r--ext/mbstring/php_mbregex.c123
-rw-r--r--ext/mbstring/php_mbregex.h2
-rw-r--r--ext/mbstring/tests/bug20087.phpt2
-rw-r--r--ext/mbstring/tests/bug28220.phpt2
-rw-r--r--ext/mbstring/tests/bug40685.phpt7
-rw-r--r--ext/mbstring/tests/bug43301.phpt2
-rw-r--r--ext/mbstring/tests/bug49536.phpt2
-rw-r--r--ext/mbstring/tests/bug60306.phpt11
-rw-r--r--ext/mbstring/tests/htmlent.phpt1
-rw-r--r--ext/mbstring/tests/illformed_utf_sequences.phpt241
-rw-r--r--ext/mbstring/tests/mb_encoding_aliases.phpt18
-rw-r--r--ext/mbstring/tests/mb_ereg_replace_callback.phpt15
-rw-r--r--ext/mbstring/tests/mb_internal_encoding_variation2.phpt4
-rw-r--r--ext/mbstring/tests/mb_parse_str.phpt3
-rw-r--r--ext/mbstring/tests/mb_parse_str02.phpt3
-rw-r--r--ext/mbstring/tests/mb_str_functions_opt-parameter.phpt30
-rw-r--r--ext/mbstring/tests/pictogram1.phpt172
-rw-r--r--ext/mbstring/tests/zend_multibyte-10.phpt1
-rw-r--r--ext/mcrypt/mcrypt.c2
-rw-r--r--ext/mcrypt/tests/blowfish.phpt10
-rw-r--r--ext/mssql/php_mssql.c20
-rw-r--r--ext/mysql/config.m428
-rw-r--r--ext/mysql/php_mysql.c52
-rw-r--r--ext/mysql/tests/bug55473.phpt10
-rw-r--r--ext/mysql/tests/mysql_pconn_kill.phpt2
-rw-r--r--ext/mysql/tests/mysql_phpinfo.phpt2
-rw-r--r--ext/mysql/tests/mysql_query_load_data_openbasedir.phpt10
-rw-r--r--ext/mysqli/config.m416
-rw-r--r--ext/mysqli/config.w321
-rw-r--r--ext/mysqli/mysqli.c217
-rw-r--r--ext/mysqli/mysqli_api.c27
-rw-r--r--ext/mysqli/mysqli_driver.c16
-rw-r--r--ext/mysqli/mysqli_fe.c13
-rw-r--r--ext/mysqli/mysqli_fe.h4
-rw-r--r--ext/mysqli/mysqli_libmysql.h24
-rw-r--r--ext/mysqli/mysqli_mysqlnd.h4
-rw-r--r--ext/mysqli/mysqli_nonapi.c112
-rw-r--r--ext/mysqli/mysqli_priv.h24
-rw-r--r--ext/mysqli/mysqli_prop.c177
-rw-r--r--ext/mysqli/mysqli_report.h2
-rw-r--r--ext/mysqli/mysqli_result_iterator.c182
-rw-r--r--ext/mysqli/mysqli_warning.c49
-rw-r--r--ext/mysqli/php_mysqli_structs.h50
-rw-r--r--ext/mysqli/tests/057.phpt3
-rw-r--r--ext/mysqli/tests/bug34810.phpt11
-rw-r--r--ext/mysqli/tests/bug55582.phpt2
-rw-r--r--ext/mysqli/tests/mysqli_auth_pam.phpt98
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt49
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt25
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt18
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt8
-rw-r--r--ext/mysqli/tests/mysqli_fetch_array_large.phpt4
-rw-r--r--ext/mysqli/tests/mysqli_fetch_object.phpt29
-rw-r--r--ext/mysqli/tests/mysqli_fetch_object_oo.phpt30
-rw-r--r--ext/mysqli/tests/mysqli_free_result.phpt3
-rw-r--r--ext/mysqli/tests/mysqli_get_cache_stats_off.phpt56
-rw-r--r--ext/mysqli/tests/mysqli_kill.phpt26
-rw-r--r--ext/mysqli/tests/mysqli_magic_quotes.phpt128
-rw-r--r--ext/mysqli/tests/mysqli_options_openbasedir.phpt3
-rw-r--r--ext/mysqli/tests/mysqli_phpinfo.phpt2
-rw-r--r--ext/mysqli/tests/mysqli_query_iterators.phpt201
-rw-r--r--ext/mysqli/tests/mysqli_real_connect.phpt48
-rw-r--r--ext/mysqli/tests/mysqli_real_connect_pconn.phpt2
-rw-r--r--ext/mysqli/tests/mysqli_stmt_affected_rows.phpt2
-rw-r--r--ext/mysqlnd/CREDITS2
-rw-r--r--ext/mysqlnd/config.w329
-rw-r--r--ext/mysqlnd/config9.m47
-rw-r--r--ext/mysqlnd/mysqlnd.c2145
-rw-r--r--ext/mysqlnd/mysqlnd.h150
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.c726
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.h100
-rw-r--r--ext/mysqlnd/mysqlnd_auth.c477
-rw-r--r--ext/mysqlnd/mysqlnd_bt.c484
-rw-r--r--ext/mysqlnd/mysqlnd_charset.c45
-rw-r--r--ext/mysqlnd/mysqlnd_charset.h14
-rw-r--r--ext/mysqlnd/mysqlnd_debug.c1121
-rw-r--r--ext/mysqlnd/mysqlnd_debug.h75
-rw-r--r--ext/mysqlnd/mysqlnd_driver.c304
-rw-r--r--ext/mysqlnd/mysqlnd_enum_n_def.h15
-rw-r--r--ext/mysqlnd/mysqlnd_ext_plugin.c226
-rw-r--r--ext/mysqlnd/mysqlnd_ext_plugin.h72
-rw-r--r--ext/mysqlnd/mysqlnd_loaddata.c81
-rw-r--r--ext/mysqlnd/mysqlnd_net.c419
-rw-r--r--ext/mysqlnd/mysqlnd_net.h10
-rw-r--r--ext/mysqlnd/mysqlnd_plugin.c209
-rw-r--r--ext/mysqlnd/mysqlnd_priv.h99
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c442
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c43
-rw-r--r--ext/mysqlnd/mysqlnd_result.c221
-rw-r--r--ext/mysqlnd/mysqlnd_result.h7
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.c10
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.h4
-rw-r--r--ext/mysqlnd/mysqlnd_reverse_api.c100
-rw-r--r--ext/mysqlnd/mysqlnd_reverse_api.h50
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.c323
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.h6
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h491
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c612
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.h82
-rw-r--r--ext/mysqlnd/php_mysqlnd.c118
-rw-r--r--ext/mysqlnd/php_mysqlnd.h6
-rw-r--r--ext/oci8/tests/null_byte_1.phpt20
-rw-r--r--ext/oci8/tests/oci8safemode.phpt23
-rw-r--r--ext/odbc/birdstep.c6
-rw-r--r--ext/odbc/php_odbc.c12
-rw-r--r--ext/openssl/openssl.c515
-rw-r--r--ext/openssl/php_openssl.h3
-rw-r--r--ext/openssl/tests/004.phpt2
-rw-r--r--ext/openssl/tests/011.phpt15
-rw-r--r--ext/openssl/tests/bug54060.phpt2
-rw-r--r--ext/openssl/tests/bug54061.phpt4
-rw-r--r--ext/openssl/tests/bug55646.phpt38
-rw-r--r--ext/openssl/tests/openssl_decrypt_error.phpt2
-rw-r--r--ext/openssl/xp_ssl.c10
-rw-r--r--ext/pcntl/pcntl.c16
-rw-r--r--ext/pcntl/php_signal.c15
-rw-r--r--ext/pcntl/tests/pcntl_exec_3.phpt2
-rw-r--r--ext/pcntl/tests/pcntl_signal.phpt6
-rw-r--r--ext/pcre/php_pcre.c62
-rw-r--r--ext/pcre/tests/002.phpt2
-rw-r--r--ext/pcre/tests/bug33200.phpt13
-rw-r--r--ext/pcre/tests/null_bytes.phpt42
-rw-r--r--ext/pcre/tests/preg_match_all_basic.phpt12
-rw-r--r--ext/pcre/tests/preg_match_all_error.phpt7
-rw-r--r--ext/pdo/pdo.c2
-rw-r--r--ext/pdo/pdo_dbh.c80
-rw-r--r--ext/pdo/pdo_stmt.c121
-rw-r--r--ext/pdo/php_pdo_driver.h11
-rw-r--r--ext/pdo/tests/bug61292.phpt36
-rw-r--r--ext/pdo/tests/pdo_test.inc3
-rw-r--r--ext/pdo_dblib/config.m410
-rw-r--r--ext/pdo_dblib/db.php31
-rw-r--r--ext/pdo_dblib/dblib_driver.c94
-rw-r--r--ext/pdo_dblib/dblib_stmt.c379
-rw-r--r--ext/pdo_dblib/php_pdo_dblib_int.h21
-rw-r--r--ext/pdo_dblib/tests/bug_38955.phpt57
-rw-r--r--ext/pdo_dblib/tests/bug_45876.phpt35
-rw-r--r--ext/pdo_dblib/tests/bug_47588.phpt45
-rw-r--r--ext/pdo_dblib/tests/bug_50755.phpt29
-rw-r--r--ext/pdo_dblib/tests/config.inc26
-rw-r--r--ext/pdo_firebird/EXPERIMENTAL0
-rw-r--r--ext/pdo_firebird/config.m42
-rw-r--r--ext/pdo_firebird/firebird_driver.c2
-rw-r--r--ext/pdo_firebird/tests/bug_47415.phpt1
-rw-r--r--ext/pdo_firebird/tests/bug_48877.phpt1
-rw-r--r--ext/pdo_firebird/tests/bug_53280.phpt1
-rw-r--r--ext/pdo_firebird/tests/connect.phpt1
-rw-r--r--ext/pdo_firebird/tests/ddl.phpt1
-rw-r--r--ext/pdo_firebird/tests/execute.phpt1
-rw-r--r--ext/pdo_firebird/tests/rowCount.phpt1
-rwxr-xr-xext/pdo_mysql/config.m458
-rw-r--r--ext/pdo_mysql/mysql_driver.c47
-rw-r--r--ext/pdo_mysql/mysql_statement.c44
-rw-r--r--ext/pdo_mysql/pdo_mysql.c29
-rw-r--r--ext/pdo_mysql/php_pdo_mysql_int.h2
-rw-r--r--ext/pdo_mysql/tests/bug_61207.phpt57
-rw-r--r--ext/pdo_mysql/tests/common.phpt2
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql___construct.phpt2
-rw-r--r--ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt4
-rwxr-xr-xext/pdo_oci/config.m410
-rw-r--r--ext/pdo_oci/oci_driver.c4
-rwxr-xr-xext/pdo_odbc/config.m410
-rw-r--r--ext/pdo_odbc/pdo_odbc.c4
-rw-r--r--ext/pdo_pgsql/config.m410
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c14
-rw-r--r--ext/pdo_pgsql/tests/is_in_transaction.phpt66
-rw-r--r--ext/pdo_sqlite/config.m412
-rw-r--r--ext/pdo_sqlite/sqlite_driver.c9
-rw-r--r--ext/pdo_sqlite/tests/bug60104.phpt21
-rw-r--r--ext/pgsql/config.m41
-rw-r--r--ext/pgsql/pgsql.c198
-rw-r--r--ext/pgsql/php_pgsql.h2
-rw-r--r--ext/pgsql/tests/08escape.phpt37
-rw-r--r--ext/phar/func_interceptors.c30
-rw-r--r--ext/phar/phar.c54
-rw-r--r--ext/phar/phar/pharcommand.inc8
-rw-r--r--ext/phar/phar_internal.h6
-rw-r--r--ext/phar/phar_object.c22
-rw-r--r--ext/phar/phar_path_check.c2
-rw-r--r--ext/phar/stream.c2
-rw-r--r--ext/phar/tests/008.phpt2
-rw-r--r--ext/phar/tests/009.phpt1
-rw-r--r--ext/phar/tests/010.phpt1
-rw-r--r--ext/phar/tests/011.phpt1
-rw-r--r--ext/phar/tests/012.phpt1
-rw-r--r--ext/phar/tests/018.phpt3
-rw-r--r--ext/phar/tests/019b.phpt1
-rw-r--r--ext/phar/tests/019c.phpt1
-rw-r--r--ext/phar/tests/020.phpt3
-rw-r--r--ext/phar/tests/021.phpt3
-rw-r--r--ext/phar/tests/022.phpt1
-rw-r--r--ext/phar/tests/028.phpt1
-rw-r--r--ext/phar/tests/cache_list/copyonwrite1.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite10.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite11.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite12.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite13.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite14.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite15.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite16.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite17.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite18.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite19.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite2.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite20.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite21.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite22.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite23.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite24.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite25.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite3.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite4.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite4a.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite5.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite6.phar.phpt1
-rw-r--r--ext/phar/tests/cache_list/copyonwrite7.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite8.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/copyonwrite9.phar.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller1.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller10.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller11.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller12.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller13.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller14.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller15.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller16.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller17.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller18.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller19.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller2.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller20.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller21.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller22.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller23.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller24.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller25.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller26.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller27.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller28.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller29.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller3.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller30.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller31.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller32.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller33.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller34.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller4.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller5.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller6.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller7.phpt1
-rw-r--r--ext/phar/tests/cache_list/frontcontroller8.phpt3
-rw-r--r--ext/phar/tests/cache_list/frontcontroller9.phpt3
-rw-r--r--ext/phar/tests/delete.phpt3
-rw-r--r--ext/phar/tests/fatal_error_webphar.phpt3
-rw-r--r--ext/phar/tests/fgc_edgecases.phpt26
-rw-r--r--ext/phar/tests/file_get_contents.phpt3
-rw-r--r--ext/phar/tests/files/stuboflength1041.phar.inc21
-rw-r--r--ext/phar/tests/fopen.phpt3
-rw-r--r--ext/phar/tests/fopen_edgecases2.phpt2
-rw-r--r--ext/phar/tests/front.phar.phpt1
-rw-r--r--ext/phar/tests/frontcontroller1.phpt2
-rw-r--r--ext/phar/tests/frontcontroller10.phpt1
-rw-r--r--ext/phar/tests/frontcontroller12.phpt3
-rw-r--r--ext/phar/tests/frontcontroller13.phpt3
-rw-r--r--ext/phar/tests/frontcontroller14.phpt2
-rw-r--r--ext/phar/tests/frontcontroller15.phpt1
-rw-r--r--ext/phar/tests/frontcontroller16.phpt1
-rw-r--r--ext/phar/tests/frontcontroller17.phpt2
-rw-r--r--ext/phar/tests/frontcontroller18.phpt2
-rw-r--r--ext/phar/tests/frontcontroller19.phpt2
-rw-r--r--ext/phar/tests/frontcontroller2.phpt1
-rw-r--r--ext/phar/tests/frontcontroller20.phpt2
-rw-r--r--ext/phar/tests/frontcontroller21.phpt3
-rw-r--r--ext/phar/tests/frontcontroller22.phpt3
-rw-r--r--ext/phar/tests/frontcontroller23.phpt3
-rw-r--r--ext/phar/tests/frontcontroller24.phpt3
-rw-r--r--ext/phar/tests/frontcontroller25.phpt3
-rw-r--r--ext/phar/tests/frontcontroller26.phpt4
-rw-r--r--ext/phar/tests/frontcontroller27.phpt3
-rw-r--r--ext/phar/tests/frontcontroller28.phpt1
-rw-r--r--ext/phar/tests/frontcontroller29.phpt3
-rw-r--r--ext/phar/tests/frontcontroller3.phpt1
-rw-r--r--ext/phar/tests/frontcontroller30.phpt4
-rw-r--r--ext/phar/tests/frontcontroller31.phpt3
-rw-r--r--ext/phar/tests/frontcontroller32.phpt3
-rw-r--r--ext/phar/tests/frontcontroller33.phpt3
-rw-r--r--ext/phar/tests/frontcontroller34.phpt1
-rw-r--r--ext/phar/tests/frontcontroller4.phpt2
-rw-r--r--ext/phar/tests/frontcontroller5.phpt2
-rw-r--r--ext/phar/tests/frontcontroller6.phpt4
-rw-r--r--ext/phar/tests/frontcontroller7.phpt2
-rw-r--r--ext/phar/tests/frontcontroller8.phpt4
-rw-r--r--ext/phar/tests/frontcontroller9.phpt3
-rw-r--r--ext/phar/tests/include_path_advanced.phpt3
-rw-r--r--ext/phar/tests/mounteddir.phpt1
-rw-r--r--ext/phar/tests/opendir.phpt3
-rw-r--r--ext/phar/tests/opendir_edgecases.phpt4
-rw-r--r--ext/phar/tests/phar_gobyebye.phpt2
-rw-r--r--ext/phar/tests/phar_gzip.phpt3
-rw-r--r--ext/phar/tests/phar_magic.phpt1
-rw-r--r--ext/phar/tests/phar_mount.phpt1
-rw-r--r--ext/phar/tests/readfile.phpt3
-rw-r--r--ext/phar/tests/readfile_edgecases.phpt4
-rw-r--r--ext/phar/tests/rename.phpt3
-rw-r--r--ext/phar/tests/rename_dir.phpt1
-rw-r--r--ext/phar/tests/rename_dir_and_mount.phpt1
-rw-r--r--ext/phar/tests/rmdir.phpt1
-rw-r--r--ext/phar/tests/security.phpt3
-rw-r--r--ext/phar/tests/stat.phpt3
-rw-r--r--ext/phar/tests/withphar.phpt2
-rw-r--r--ext/phar/tests/withphar_web.phpt2
-rw-r--r--ext/phar/util.c9
-rw-r--r--ext/posix/posix.c27
-rw-r--r--ext/posix/tests/posix_access.phpt5
-rw-r--r--ext/posix/tests/posix_access_error_modes.phpt7
-rw-r--r--ext/posix/tests/posix_access_error_wrongparams.phpt5
-rw-r--r--ext/posix/tests/posix_access_safemode.phpt5
-rw-r--r--ext/posix/tests/posix_getgrgid_variation.phpt10
-rw-r--r--ext/posix/tests/posix_getpgid_variation.phpt10
-rw-r--r--ext/posix/tests/posix_getpwuid_variation.phpt10
-rw-r--r--ext/posix/tests/posix_kill_variation1.phpt10
-rw-r--r--ext/posix/tests/posix_kill_variation2.phpt10
-rw-r--r--ext/posix/tests/posix_mkfifo_safemode.phpt5
-rw-r--r--ext/posix/tests/posix_setgid_error.phpt1
-rw-r--r--ext/posix/tests/posix_strerror_variation1.phpt10
-rw-r--r--ext/posix/tests/posix_times_basic.phpt10
-rw-r--r--ext/pspell/pspell.c40
-rw-r--r--ext/readline/config.m423
-rw-r--r--ext/readline/readline.c30
-rw-r--r--ext/readline/readline_cli.c (renamed from sapi/cli/php_cli_readline.c)345
-rw-r--r--ext/readline/readline_cli.h43
-rw-r--r--ext/reflection/php_reflection.c1262
-rw-r--r--ext/reflection/php_reflection.h1
-rw-r--r--ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt2
-rw-r--r--ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt61
-rw-r--r--ext/reflection/tests/ReflectionClass_isCloneable_001.phpt71
-rw-r--r--ext/reflection/tests/ReflectionClass_isCloneable_002.phpt25
-rw-r--r--ext/reflection/tests/ReflectionClass_newInstanceArgs_002.phpt2
-rw-r--r--ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt33
-rw-r--r--ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt2
-rw-r--r--ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt61
-rw-r--r--ext/reflection/tests/ReflectionClass_toString_001.phpt38
-rw-r--r--ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt7
-rw-r--r--ext/reflection/tests/ReflectionExtension_isPersistant.phpt11
-rw-r--r--ext/reflection/tests/ReflectionExtension_isTemporary.phpt11
-rw-r--r--ext/reflection/tests/ReflectionFunction_getClosureScopeClass.phpt31
-rw-r--r--ext/reflection/tests/ReflectionFunction_getClosureThis.phpt17
-rw-r--r--ext/reflection/tests/ReflectionFunction_getClosure_basic.phpt37
-rw-r--r--ext/reflection/tests/ReflectionFunction_getClosure_error.phpt27
-rw-r--r--ext/reflection/tests/ReflectionMethod_getClosureThis.phpt53
-rw-r--r--ext/reflection/tests/ReflectionMethod_getClosure_basic.phpt55
-rw-r--r--ext/reflection/tests/ReflectionMethod_getClosure_error.phpt73
-rw-r--r--ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt82
-rw-r--r--ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt2
-rw-r--r--ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt52
-rw-r--r--ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt30
-rw-r--r--ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt23
-rw-r--r--ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt84
-rw-r--r--ext/reflection/tests/bug40431.phpt4
-rw-r--r--ext/reflection/tests/bug47254.phpt1
-rw-r--r--ext/reflection/tests/bug60357.phpt10
-rw-r--r--ext/reflection/tests/closures_003_v1.phpt25
-rw-r--r--ext/reflection/tests/closures_004.phpt43
-rw-r--r--ext/reflection/tests/traits001.phpt70
-rw-r--r--ext/reflection/tests/traits002.phpt54
-rw-r--r--ext/reflection/tests/traits003.phpt30
-rw-r--r--ext/reflection/tests/traits004.phpt58
-rw-r--r--ext/reflection/tests/traits005.phpt41
-rw-r--r--ext/session/config.m42
-rw-r--r--ext/session/config.w322
-rw-r--r--ext/session/mod_files.c18
-rw-r--r--ext/session/mod_user.c42
-rw-r--r--ext/session/mod_user_class.c144
-rw-r--r--ext/session/package.xml1
-rw-r--r--ext/session/php_session.h46
-rw-r--r--ext/session/session.c849
-rw-r--r--ext/session/tests/001.phpt14
-rw-r--r--ext/session/tests/003.phpt10
-rw-r--r--ext/session/tests/004.phpt16
-rw-r--r--ext/session/tests/005.phpt41
-rw-r--r--ext/session/tests/006.phpt18
-rw-r--r--ext/session/tests/007.phpt67
-rw-r--r--ext/session/tests/008-php4.2.3.phpt78
-rw-r--r--ext/session/tests/009.phpt25
-rw-r--r--ext/session/tests/010.phpt3
-rw-r--r--ext/session/tests/011.phpt3
-rw-r--r--ext/session/tests/012.phpt10
-rw-r--r--ext/session/tests/013.phpt4
-rw-r--r--ext/session/tests/014.phpt4
-rw-r--r--ext/session/tests/019.phpt16
-rw-r--r--ext/session/tests/bug24592.phpt1
-rw-r--r--ext/session/tests/bug26862.phpt1
-rw-r--r--ext/session/tests/bug55688.phpt15
-rw-r--r--ext/session/tests/bug60634_error_5.phpt2
-rw-r--r--ext/session/tests/bug61728.phpt39
-rw-r--r--ext/session/tests/rfc1867.phpt129
-rw-r--r--ext/session/tests/rfc1867_cleanup.phpt83
-rw-r--r--ext/session/tests/rfc1867_disabled.phpt76
-rw-r--r--ext/session/tests/rfc1867_disabled_2.phpt76
-rw-r--r--ext/session/tests/rfc1867_inter.phpt133
-rw-r--r--ext/session/tests/rfc1867_invalid_settings-win.phpt19
-rw-r--r--ext/session/tests/rfc1867_invalid_settings.phpt20
-rw-r--r--ext/session/tests/rfc1867_invalid_settings_2-win.phpt19
-rw-r--r--ext/session/tests/rfc1867_invalid_settings_2.phpt20
-rw-r--r--ext/session/tests/rfc1867_no_name.phpt76
-rw-r--r--ext/session/tests/rfc1867_sid_cookie.phpt128
-rw-r--r--ext/session/tests/rfc1867_sid_get.phpt126
-rw-r--r--ext/session/tests/rfc1867_sid_get_2.phpt128
-rw-r--r--ext/session/tests/rfc1867_sid_invalid.phpt79
-rw-r--r--ext/session/tests/rfc1867_sid_only_cookie.phpt128
-rw-r--r--ext/session/tests/rfc1867_sid_only_cookie_2.phpt80
-rw-r--r--ext/session/tests/rfc1867_sid_post.phpt124
-rw-r--r--ext/session/tests/session_encode_basic.phpt4
-rw-r--r--ext/session/tests/session_id_variation2.phpt2
-rw-r--r--ext/session/tests/session_is_registered_basic.phpt318
-rw-r--r--ext/session/tests/session_is_registered_variation1.phpt109
-rw-r--r--ext/session/tests/session_is_registered_variation2.phpt75
-rw-r--r--ext/session/tests/session_is_registered_variation3.phpt72
-rw-r--r--ext/session/tests/session_register_basic.phpt364
-rw-r--r--ext/session/tests/session_register_variation1.phpt159
-rw-r--r--ext/session/tests/session_register_variation2.phpt43
-rw-r--r--ext/session/tests/session_register_variation3.phpt46
-rw-r--r--ext/session/tests/session_register_variation4.phpt47
-rw-r--r--ext/session/tests/session_save_path_variation5.phpt3
-rw-r--r--ext/session/tests/session_set_save_handler_class_001.phpt68
-rw-r--r--ext/session/tests/session_set_save_handler_class_002.phpt113
-rw-r--r--ext/session/tests/session_set_save_handler_class_003.phpt78
-rw-r--r--ext/session/tests/session_set_save_handler_class_004.phpt48
-rw-r--r--ext/session/tests/session_set_save_handler_class_005.phpt54
-rw-r--r--ext/session/tests/session_set_save_handler_class_006.phpt54
-rw-r--r--ext/session/tests/session_set_save_handler_class_007.phpt74
-rw-r--r--ext/session/tests/session_set_save_handler_class_008.phpt65
-rw-r--r--ext/session/tests/session_set_save_handler_class_009.phpt62
-rw-r--r--ext/session/tests/session_set_save_handler_class_010.phpt63
-rw-r--r--ext/session/tests/session_set_save_handler_class_011.phpt66
-rw-r--r--ext/session/tests/session_set_save_handler_class_012.phpt59
-rw-r--r--ext/session/tests/session_set_save_handler_class_013.phpt56
-rw-r--r--ext/session/tests/session_set_save_handler_class_014.phpt30
-rw-r--r--ext/session/tests/session_set_save_handler_class_015.phpt24
-rw-r--r--ext/session/tests/session_set_save_handler_iface_001.phpt113
-rw-r--r--ext/session/tests/session_set_save_handler_iface_002.phpt90
-rw-r--r--ext/session/tests/session_status.phpt24
-rw-r--r--ext/session/tests/session_status_disabled.phpt17
-rw-r--r--ext/session/tests/session_unregister_basic.phpt225
-rw-r--r--ext/session/tests/session_unregister_variation1.phpt159
-rw-r--r--ext/session/tests/session_unregister_variation2.phpt47
-rw-r--r--ext/session/tests/session_unregister_variation3.phpt48
-rw-r--r--ext/session/tests/sessionhandler_open_001.phpt19
-rw-r--r--ext/shmop/shmop.c2
-rw-r--r--ext/simplexml/simplexml.c71
-rw-r--r--ext/simplexml/tests/034.phpt6
-rw-r--r--ext/simplexml/tests/bug48601.phpt2
-rw-r--r--ext/simplexml/tests/bug51615.phpt4
-rw-r--r--ext/simplexml/tests/feature55218.phpt117
-rw-r--r--ext/snmp/CREDITS2
-rw-r--r--ext/snmp/config.m4174
-rw-r--r--ext/snmp/config.w323
-rw-r--r--ext/snmp/php_snmp.h54
-rw-r--r--ext/snmp/snmp.c2590
-rw-r--r--ext/snmp/tests/README46
-rw-r--r--ext/snmp/tests/bug60749.phpt28
-rw-r--r--ext/snmp/tests/clean.inc4
-rw-r--r--ext/snmp/tests/generic_timeout_error.phpt27
-rw-r--r--ext/snmp/tests/ipv6.phpt25
-rw-r--r--ext/snmp/tests/skipif.inc13
-rw-r--r--ext/snmp/tests/snmp-object-errno-errstr.phpt147
-rw-r--r--ext/snmp/tests/snmp-object-error.phpt122
-rw-r--r--ext/snmp/tests/snmp-object-properties.phpt208
-rw-r--r--ext/snmp/tests/snmp-object-setSecurity_error.phpt66
-rw-r--r--ext/snmp/tests/snmp-object.phpt234
-rw-r--r--ext/snmp/tests/snmp2_get.phpt104
-rw-r--r--ext/snmp/tests/snmp2_getnext.phpt39
-rw-r--r--ext/snmp/tests/snmp2_real_walk.phpt86
-rw-r--r--ext/snmp/tests/snmp2_set-nomib.phpt59
-rw-r--r--ext/snmp/tests/snmp2_set.phpt248
-rw-r--r--ext/snmp/tests/snmp2_walk.phpt99
-rw-r--r--ext/snmp/tests/snmp3-error.phpt76
-rw-r--r--ext/snmp/tests/snmp3.phpt127
-rw-r--r--ext/snmp/tests/snmp_get_quick_print.phpt41
-rw-r--r--ext/snmp/tests/snmp_get_valueretrieval.phpt53
-rw-r--r--ext/snmp/tests/snmp_getvalue.phpt83
-rw-r--r--ext/snmp/tests/snmp_include.inc31
-rw-r--r--ext/snmp/tests/snmp_read_mib.phpt34
-rw-r--r--ext/snmp/tests/snmp_set_enum_print.phpt28
-rw-r--r--ext/snmp/tests/snmp_set_oid_output_format.phpt32
-rw-r--r--ext/snmp/tests/snmpd.conf25
-rw-r--r--ext/snmp/tests/snmpget.phpt106
-rw-r--r--ext/snmp/tests/snmpgetnext.phpt39
-rw-r--r--ext/snmp/tests/snmprealwalk.phpt86
-rw-r--r--ext/snmp/tests/snmpset-nomib.phpt60
-rw-r--r--ext/snmp/tests/snmpset.phpt248
-rw-r--r--ext/snmp/tests/snmpwalk.phpt99
-rw-r--r--ext/snmp/tests/wrong_hostname.phpt22
-rw-r--r--ext/soap/TODO.old1
-rw-r--r--ext/soap/php_encoding.c389
-rw-r--r--ext/soap/php_encoding.h16
-rw-r--r--ext/soap/php_http.c16
-rw-r--r--ext/soap/php_packet_soap.c20
-rw-r--r--ext/soap/php_sdl.c10
-rw-r--r--ext/soap/php_xml.c26
-rw-r--r--ext/soap/php_xml.h7
-rw-r--r--ext/soap/soap.c359
-rw-r--r--ext/soap/tests/bugs/bug31422.phpt1
-rw-r--r--ext/soap/tests/error_handler.phpt17
-rw-r--r--ext/sockets/config.m421
-rw-r--r--ext/sockets/config.w323
-rw-r--r--ext/sockets/multicast.c545
-rw-r--r--ext/sockets/multicast.h92
-rw-r--r--ext/sockets/php_sockets.h10
-rw-r--r--ext/sockets/sockets.c618
-rw-r--r--ext/sockets/tests/bug63000.phpt22
-rw-r--r--ext/sockets/tests/mcast_helpers.php.inc8
-rw-r--r--ext/sockets/tests/mcast_ipv4_recv.phpt197
-rw-r--r--ext/sockets/tests/mcast_ipv4_send.phpt65
-rw-r--r--ext/sockets/tests/mcast_ipv4_send_error.phpt79
-rw-r--r--ext/sockets/tests/mcast_ipv6_recv.phpt223
-rw-r--r--ext/sockets/tests/mcast_ipv6_recv_limited.phpt131
-rw-r--r--ext/sockets/tests/mcast_ipv6_send.phpt70
-rw-r--r--ext/sockets/tests/socket_import_stream-1.phpt26
-rw-r--r--ext/sockets/tests/socket_import_stream-2.phpt49
-rw-r--r--ext/sockets/tests/socket_import_stream-3.phpt46
-rw-r--r--ext/sockets/tests/socket_import_stream-4-win.phpt106
-rw-r--r--ext/sockets/tests/socket_import_stream-4.phpt100
-rw-r--r--ext/sockets/tests/socket_import_stream-5.phpt23
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt4
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt4
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_unix.phpt4
-rw-r--r--ext/sockets/tests/socket_set_option_seolinger.phpt9
-rw-r--r--ext/spl/examples/dbaarray.inc5
-rw-r--r--ext/spl/internal/regexiterator.inc7
-rw-r--r--ext/spl/php_spl.c49
-rw-r--r--ext/spl/php_spl.h1
-rw-r--r--ext/spl/spl_array.c461
-rw-r--r--ext/spl/spl_directory.c96
-rw-r--r--ext/spl/spl_dllist.c124
-rw-r--r--ext/spl/spl_fixedarray.c17
-rw-r--r--ext/spl/spl_functions.c12
-rw-r--r--ext/spl/spl_functions.h1
-rw-r--r--ext/spl/spl_heap.c7
-rw-r--r--ext/spl/spl_iterators.c184
-rw-r--r--ext/spl/spl_iterators.h11
-rw-r--r--ext/spl/spl_observer.c271
-rw-r--r--ext/spl/tests/CallbackFilterIteratorTest-002.phpt50
-rw-r--r--ext/spl/tests/CallbackFilterIteratorTest.phpt133
-rw-r--r--ext/spl/tests/RecursiveCallbackFilterIteratorTest.phpt138
-rw-r--r--ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt50
-rw-r--r--ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt56
-rw-r--r--ext/spl/tests/SplDoublyLinkedList_serialization.phpt67
-rw-r--r--ext/spl/tests/SplFileObject_current_basic.phpt18
-rw-r--r--ext/spl/tests/SplFileObject_current_error001.phpt19
-rw-r--r--ext/spl/tests/SplFileObject_current_variation001.phpt21
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv.phpt106
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_002.phpt42
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_error.phpt35
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation1.phpt826
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation10.phpt327
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation11.phpt826
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation12.phpt827
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation13.phpt29
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation14.phpt29
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation5.phpt826
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation6.phpt829
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation7.phpt829
-rw-r--r--ext/spl/tests/SplFileObject_fputcsv_variation8.phpt829
-rw-r--r--ext/spl/tests/SplFileObject_fwrite_variation_003.phpt22
-rw-r--r--ext/spl/tests/SplFileObject_getchildren_basic.phpt12
-rw-r--r--ext/spl/tests/SplFileObject_getchildren_error001.phpt12
-rw-r--r--ext/spl/tests/SplFileObject_getflags_basic.phpt22
-rw-r--r--ext/spl/tests/SplFileObject_getflags_error001.phpt26
-rw-r--r--ext/spl/tests/SplFileObject_getflags_error002.phpt21
-rw-r--r--ext/spl/tests/SplFileObject_getflags_variation001.phpt29
-rw-r--r--ext/spl/tests/SplFileObject_haschildren_basic.phpt12
-rw-r--r--ext/spl/tests/SplFileObject_haschildren_error001.phpt12
-rw-r--r--ext/spl/tests/SplFileObject_key_basic.phpt19
-rw-r--r--ext/spl/tests/SplFileObject_key_error001.phpt22
-rw-r--r--ext/spl/tests/SplFileObject_key_error002.phpt22
-rw-r--r--ext/spl/tests/SplFileObject_key_error003.phpt15
-rw-r--r--ext/spl/tests/SplFileObject_next_basic.phpt22
-rw-r--r--ext/spl/tests/SplFileObject_next_variation001.phpt24
-rw-r--r--ext/spl/tests/SplFileObject_next_variation002.phpt30
-rw-r--r--ext/spl/tests/SplFileObject_rewind_basic.phpt21
-rw-r--r--ext/spl/tests/SplFileObject_rewind_error001.phpt18
-rw-r--r--ext/spl/tests/SplFileObject_rewind_variation001.phpt28
-rw-r--r--ext/spl/tests/SplFileObject_seek_basic.phpt19
-rw-r--r--ext/spl/tests/SplFileObject_seek_error002.phpt18
-rw-r--r--ext/spl/tests/SplFileObject_setCsvControl_basic.phpt30
-rw-r--r--ext/spl/tests/SplFileObject_setCsvControl_error001.phpt24
-rw-r--r--ext/spl/tests/SplFileObject_setCsvControl_error002.phpt24
-rw-r--r--ext/spl/tests/SplFileObject_setCsvControl_error003.phpt26
-rw-r--r--ext/spl/tests/SplFileObject_setCsvControl_variation001.phpt30
-rw-r--r--ext/spl/tests/SplObjectStorage_getHash.phpt60
-rw-r--r--ext/spl/tests/SplObjectStorage_unserialize_bad.phpt6
-rw-r--r--ext/spl/tests/SplObjectStorage_unserialize_nested.phpt2
-rw-r--r--ext/spl/tests/arrayObject___construct_basic2.phpt4
-rw-r--r--ext/spl/tests/arrayObject___construct_basic3.phpt4
-rw-r--r--ext/spl/tests/arrayObject___construct_basic4.phpt10
-rw-r--r--ext/spl/tests/arrayObject___construct_basic5.phpt10
-rw-r--r--ext/spl/tests/arrayObject_asort_basic1.phpt20
-rw-r--r--ext/spl/tests/arrayObject_ksort_basic1.phpt26
-rw-r--r--ext/spl/tests/arrayObject_magicMethods1.phpt4
-rw-r--r--ext/spl/tests/arrayObject_magicMethods3.phpt4
-rw-r--r--ext/spl/tests/arrayObject_magicMethods4.phpt4
-rw-r--r--ext/spl/tests/arrayObject_magicMethods6.phpt4
-rw-r--r--ext/spl/tests/arrayObject_setFlags_basic1.phpt4
-rw-r--r--ext/spl/tests/array_001.phpt8
-rw-r--r--ext/spl/tests/array_004.phpt111
-rw-r--r--ext/spl/tests/array_008.phpt29
-rw-r--r--ext/spl/tests/array_010.phpt8
-rw-r--r--ext/spl/tests/bug45622.phpt2
-rw-r--r--ext/spl/tests/bug45622b.phpt4
-rw-r--r--ext/spl/tests/bug49263.phpt2
-rw-r--r--ext/spl/tests/bug52238.phpt2
-rw-r--r--ext/spl/tests/bug53515.phpt2
-rw-r--r--ext/spl/tests/bug54323.phpt24
-rw-r--r--ext/spl/tests/bug60082.phpt23
-rw-r--r--ext/spl/tests/bug60201.phpt30
-rw-r--r--ext/spl/tests/bug61453.phpt19
-rw-r--r--ext/spl/tests/bug61527.phpt92
-rw-r--r--ext/spl/tests/bug62328.phpt24
-rw-r--r--ext/spl/tests/bug62433.phpt18
-rw-r--r--ext/spl/tests/bug62978.phpt8
-rw-r--r--ext/spl/tests/class_uses_basic.phpt33
-rw-r--r--ext/spl/tests/class_uses_basic2.phpt69
-rw-r--r--ext/spl/tests/class_uses_variation.phpt45
-rw-r--r--ext/spl/tests/class_uses_variation1.phpt221
-rw-r--r--ext/spl/tests/class_uses_variation2.phpt261
-rw-r--r--ext/spl/tests/dllist_001.phpt12
-rw-r--r--ext/spl/tests/dllist_004.phpt7
-rw-r--r--ext/spl/tests/dllist_005.phpt7
-rw-r--r--ext/spl/tests/fileobject_getmaxlinelen_error001.phpt14
-rw-r--r--ext/spl/tests/fileobject_setmaxlinelen_error001.phpt17
-rw-r--r--ext/spl/tests/fileobject_setmaxlinelen_error002.phpt12
-rw-r--r--ext/spl/tests/fileobject_setmaxlinelen_error003.phpt12
-rw-r--r--ext/spl/tests/filesystemiterator_flags.phpt40
-rw-r--r--ext/spl/tests/fixedarray_001.phpt2
-rw-r--r--ext/spl/tests/fixedarray_002.phpt2
-rw-r--r--ext/spl/tests/iterator_026.phpt4
-rw-r--r--ext/spl/tests/iterator_041b.phpt13
-rw-r--r--ext/spl/tests/iterator_044.phpt16
-rw-r--r--ext/spl/tests/iterator_047.phpt8
-rw-r--r--ext/spl/tests/iterator_050.phpt4
-rw-r--r--ext/spl/tests/iterator_052.phpt4
-rw-r--r--ext/spl/tests/iterator_054.phpt2
-rw-r--r--ext/spl/tests/regexiterator_getregex.phpt29
-rw-r--r--ext/spl/tests/spl_004.phpt2
-rw-r--r--ext/sqlite/CREDITS2
-rw-r--r--ext/sqlite/Makefile.frag2
-rw-r--r--ext/sqlite/README14
-rw-r--r--ext/sqlite/TODO19
-rw-r--r--ext/sqlite/config.m4157
-rw-r--r--ext/sqlite/config.w3239
-rw-r--r--ext/sqlite/libsqlite/README37
-rw-r--r--ext/sqlite/libsqlite/VERSION1
-rw-r--r--ext/sqlite/libsqlite/src/attach.c311
-rw-r--r--ext/sqlite/libsqlite/src/auth.c219
-rw-r--r--ext/sqlite/libsqlite/src/btree.c3584
-rw-r--r--ext/sqlite/libsqlite/src/btree.h156
-rw-r--r--ext/sqlite/libsqlite/src/btree_rb.c1488
-rw-r--r--ext/sqlite/libsqlite/src/build.c2156
-rw-r--r--ext/sqlite/libsqlite/src/config_static.w32.h1
-rw-r--r--ext/sqlite/libsqlite/src/copy.c110
-rw-r--r--ext/sqlite/libsqlite/src/date.c881
-rw-r--r--ext/sqlite/libsqlite/src/delete.c393
-rw-r--r--ext/sqlite/libsqlite/src/encode.c257
-rw-r--r--ext/sqlite/libsqlite/src/expr.c1662
-rw-r--r--ext/sqlite/libsqlite/src/func.c658
-rw-r--r--ext/sqlite/libsqlite/src/hash.c356
-rw-r--r--ext/sqlite/libsqlite/src/hash.h109
-rw-r--r--ext/sqlite/libsqlite/src/insert.c919
-rwxr-xr-xext/sqlite/libsqlite/src/libsqlite.dsp353
-rw-r--r--ext/sqlite/libsqlite/src/main.c1143
-rw-r--r--ext/sqlite/libsqlite/src/opcodes.c140
-rw-r--r--ext/sqlite/libsqlite/src/opcodes.h138
-rw-r--r--ext/sqlite/libsqlite/src/os.c1850
-rw-r--r--ext/sqlite/libsqlite/src/os.h191
-rw-r--r--ext/sqlite/libsqlite/src/pager.c2220
-rw-r--r--ext/sqlite/libsqlite/src/pager.h107
-rw-r--r--ext/sqlite/libsqlite/src/parse.c3355
-rw-r--r--ext/sqlite/libsqlite/src/parse.h130
-rw-r--r--ext/sqlite/libsqlite/src/parse.y897
-rw-r--r--ext/sqlite/libsqlite/src/pragma.c712
-rw-r--r--ext/sqlite/libsqlite/src/printf.c858
-rw-r--r--ext/sqlite/libsqlite/src/random.c97
-rw-r--r--ext/sqlite/libsqlite/src/select.c2434
-rw-r--r--ext/sqlite/libsqlite/src/sqlite.h.in886
-rw-r--r--ext/sqlite/libsqlite/src/sqlite.w32.h764
-rw-r--r--ext/sqlite/libsqlite/src/sqliteInt.h1270
-rw-r--r--ext/sqlite/libsqlite/src/sqlite_config.w32.h8
-rw-r--r--ext/sqlite/libsqlite/src/table.c203
-rw-r--r--ext/sqlite/libsqlite/src/tokenize.c679
-rw-r--r--ext/sqlite/libsqlite/src/trigger.c764
-rw-r--r--ext/sqlite/libsqlite/src/update.c459
-rw-r--r--ext/sqlite/libsqlite/src/util.c1134
-rw-r--r--ext/sqlite/libsqlite/src/vacuum.c305
-rw-r--r--ext/sqlite/libsqlite/src/vdbe.c4921
-rw-r--r--ext/sqlite/libsqlite/src/vdbe.h112
-rw-r--r--ext/sqlite/libsqlite/src/vdbeInt.h303
-rw-r--r--ext/sqlite/libsqlite/src/vdbeaux.c1061
-rw-r--r--ext/sqlite/libsqlite/src/where.c1235
-rw-r--r--ext/sqlite/package.xml136
-rw-r--r--ext/sqlite/pdo_sqlite2.c638
-rw-r--r--ext/sqlite/php_sqlite.def43
-rw-r--r--ext/sqlite/php_sqlite.h107
-rw-r--r--ext/sqlite/sess_sqlite.c201
-rw-r--r--ext/sqlite/sqlite.c3448
-rw-r--r--ext/sqlite/sqlite.dsp339
-rw-r--r--ext/sqlite/sqlite.php36
-rw-r--r--ext/sqlite/tests/blankdb.inc3
-rw-r--r--ext/sqlite/tests/blankdb_oo.inc3
-rw-r--r--ext/sqlite/tests/bug26911.phpt12
-rw-r--r--ext/sqlite/tests/bug28112.phpt16
-rw-r--r--ext/sqlite/tests/bug35248.phpt15
-rw-r--r--ext/sqlite/tests/bug38759.phpt18
-rw-r--r--ext/sqlite/tests/bug48679.phpt20
-rw-r--r--ext/sqlite/tests/pdo/common.phpt12
-rw-r--r--ext/sqlite/tests/sqlite_001.phpt16
-rw-r--r--ext/sqlite/tests/sqlite_002.phpt32
-rw-r--r--ext/sqlite/tests/sqlite_003.phpt52
-rw-r--r--ext/sqlite/tests/sqlite_004.phpt49
-rw-r--r--ext/sqlite/tests/sqlite_005.phpt50
-rw-r--r--ext/sqlite/tests/sqlite_006.phpt55
-rw-r--r--ext/sqlite/tests/sqlite_007.phpt52
-rw-r--r--ext/sqlite/tests/sqlite_008.phpt46
-rw-r--r--ext/sqlite/tests/sqlite_009.phpt46
-rw-r--r--ext/sqlite/tests/sqlite_010.phpt81
-rw-r--r--ext/sqlite/tests/sqlite_011.phpt34
-rw-r--r--ext/sqlite/tests/sqlite_012.phpt38
-rw-r--r--ext/sqlite/tests/sqlite_013.phpt78
-rw-r--r--ext/sqlite/tests/sqlite_014.phpt120
-rw-r--r--ext/sqlite/tests/sqlite_015.phpt49
-rw-r--r--ext/sqlite/tests/sqlite_016.phpt45
-rw-r--r--ext/sqlite/tests/sqlite_017.phpt33
-rw-r--r--ext/sqlite/tests/sqlite_018.phpt14
-rw-r--r--ext/sqlite/tests/sqlite_019.phpt47
-rw-r--r--ext/sqlite/tests/sqlite_022.phpt101
-rw-r--r--ext/sqlite/tests/sqlite_023.phpt105
-rw-r--r--ext/sqlite/tests/sqlite_024.phpt76
-rw-r--r--ext/sqlite/tests/sqlite_025.phpt38
-rw-r--r--ext/sqlite/tests/sqlite_026.phpt27
-rw-r--r--ext/sqlite/tests/sqlite_027.phpt15
-rw-r--r--ext/sqlite/tests/sqlite_closures_001.phpt54
-rw-r--r--ext/sqlite/tests/sqlite_closures_002.phpt52
-rw-r--r--ext/sqlite/tests/sqlite_exec_basic.phpt34
-rw-r--r--ext/sqlite/tests/sqlite_exec_error.phpt44
-rw-r--r--ext/sqlite/tests/sqlite_last_error_basic.phpt48
-rw-r--r--ext/sqlite/tests/sqlite_last_error_error.phpt47
-rw-r--r--ext/sqlite/tests/sqlite_oo_001.phpt17
-rw-r--r--ext/sqlite/tests/sqlite_oo_002.phpt41
-rw-r--r--ext/sqlite/tests/sqlite_oo_003.phpt51
-rw-r--r--ext/sqlite/tests/sqlite_oo_008.phpt43
-rw-r--r--ext/sqlite/tests/sqlite_oo_009.phpt43
-rw-r--r--ext/sqlite/tests/sqlite_oo_010.phpt44
-rw-r--r--ext/sqlite/tests/sqlite_oo_011.phpt33
-rw-r--r--ext/sqlite/tests/sqlite_oo_012.phpt35
-rw-r--r--ext/sqlite/tests/sqlite_oo_013.phpt75
-rw-r--r--ext/sqlite/tests/sqlite_oo_014.phpt118
-rw-r--r--ext/sqlite/tests/sqlite_oo_015.phpt47
-rw-r--r--ext/sqlite/tests/sqlite_oo_016.phpt42
-rw-r--r--ext/sqlite/tests/sqlite_oo_020.phpt66
-rw-r--r--ext/sqlite/tests/sqlite_oo_021.phpt48
-rw-r--r--ext/sqlite/tests/sqlite_oo_022.phpt98
-rw-r--r--ext/sqlite/tests/sqlite_oo_024.phpt74
-rw-r--r--ext/sqlite/tests/sqlite_oo_025.phpt103
-rw-r--r--ext/sqlite/tests/sqlite_oo_026.phpt56
-rw-r--r--ext/sqlite/tests/sqlite_oo_027.phpt42
-rw-r--r--ext/sqlite/tests/sqlite_oo_028.phpt25
-rw-r--r--ext/sqlite/tests/sqlite_oo_029.phpt53
-rw-r--r--ext/sqlite/tests/sqlite_oo_030.phpt44
-rw-r--r--ext/sqlite/tests/sqlite_popen_basic.phpt27
-rw-r--r--ext/sqlite/tests/sqlite_popen_error.phpt34
-rw-r--r--ext/sqlite/tests/sqlite_session_001.phpt46
-rw-r--r--ext/sqlite/tests/sqlite_session_002.phpt54
-rw-r--r--ext/sqlite/tests/sqlite_spl_001.phpt125
-rw-r--r--ext/sqlite/tests/sqlite_spl_002.phpt29
-rw-r--r--ext/sqlite/tests/sqlite_spl_003.phpt28
-rw-r--r--ext/sqlite/tests/sqlitedatabase_arrayquery.phpt23
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.c22
-rw-r--r--ext/sqlite3/php_sqlite3.h2
-rw-r--r--ext/sqlite3/sqlite3.c13
-rw-r--r--ext/sqlite3/tests/bug53463.phpt2
-rw-r--r--ext/sqlite3/tests/sqlite3_15_open_error.phpt4
-rw-r--r--ext/standard/array.c50
-rw-r--r--ext/standard/assert.c50
-rw-r--r--ext/standard/basic_functions.c434
-rw-r--r--ext/standard/basic_functions.h31
-rw-r--r--ext/standard/browscap.c4
-rw-r--r--ext/standard/config.m44
-rw-r--r--ext/standard/credits.c1
-rw-r--r--ext/standard/credits_ext.h15
-rw-r--r--ext/standard/crypt_sha256.c2
-rw-r--r--ext/standard/crypt_sha512.c2
-rw-r--r--ext/standard/cyr_convert.c2
-rw-r--r--ext/standard/datetime.c21
-rw-r--r--ext/standard/dir.c39
-rw-r--r--ext/standard/dl.c3
-rw-r--r--ext/standard/dns.c60
-rw-r--r--ext/standard/dns_win32.c61
-rw-r--r--ext/standard/exec.c57
-rw-r--r--ext/standard/file.c318
-rw-r--r--ext/standard/file.h6
-rw-r--r--ext/standard/filestat.c316
-rw-r--r--ext/standard/formatted_print.c3
-rw-r--r--ext/standard/fsock.c2
-rw-r--r--ext/standard/ftok.c10
-rw-r--r--ext/standard/ftp_fopen_wrapper.c5
-rw-r--r--ext/standard/head.c41
-rw-r--r--ext/standard/head.h1
-rw-r--r--ext/standard/html.c2471
-rw-r--r--ext/standard/html.h40
-rw-r--r--ext/standard/html_tables.h6235
-rw-r--r--ext/standard/html_tables/ents_basic.txt5
-rw-r--r--ext/standard/html_tables/ents_basic_apos.txt5
-rw-r--r--ext/standard/html_tables/ents_html401.txt253
-rw-r--r--ext/standard/html_tables/ents_html5.txt2125
-rw-r--r--ext/standard/html_tables/ents_xhtml.txt253
-rw-r--r--ext/standard/html_tables/html_table_gen.php812
-rw-r--r--ext/standard/html_tables/mappings/8859-1.TXT303
-rw-r--r--ext/standard/html_tables/mappings/8859-15.TXT303
-rw-r--r--ext/standard/html_tables/mappings/8859-5.TXT303
-rw-r--r--ext/standard/html_tables/mappings/CP1251.TXT274
-rw-r--r--ext/standard/html_tables/mappings/CP1252.TXT274
-rw-r--r--ext/standard/html_tables/mappings/CP866.TXT275
-rw-r--r--ext/standard/html_tables/mappings/KOI8-R.TXT302
-rw-r--r--ext/standard/html_tables/mappings/ROMAN.TXT370
-rw-r--r--ext/standard/http.c46
-rw-r--r--ext/standard/http_fopen_wrapper.c11
-rw-r--r--ext/standard/image.c73
-rw-r--r--ext/standard/incomplete_class.c16
-rw-r--r--ext/standard/info.c694
-rw-r--r--ext/standard/iptc.c16
-rw-r--r--ext/standard/link.c47
-rw-r--r--ext/standard/link_win32.c15
-rw-r--r--ext/standard/mail.c75
-rw-r--r--ext/standard/math.c59
-rw-r--r--ext/standard/md5.c4
-rw-r--r--ext/standard/pack.c1
-rw-r--r--ext/standard/pageinfo.c38
-rw-r--r--ext/standard/pageinfo.h4
-rw-r--r--ext/standard/php_array.h2
-rw-r--r--ext/standard/php_crypt_r.c7
-rw-r--r--ext/standard/php_dir.h4
-rw-r--r--ext/standard/php_ext_syslog.h1
-rw-r--r--ext/standard/php_http.h2
-rw-r--r--ext/standard/php_image.h1
-rw-r--r--ext/standard/php_incomplete_class.h2
-rw-r--r--ext/standard/php_math.h3
-rw-r--r--ext/standard/php_string.h10
-rw-r--r--ext/standard/php_var.h80
-rw-r--r--ext/standard/proc_open.c82
-rw-r--r--ext/standard/quot_print.c7
-rw-r--r--ext/standard/sha1.c4
-rw-r--r--ext/standard/streamsfuncs.c91
-rw-r--r--ext/standard/streamsfuncs.h1
-rw-r--r--ext/standard/string.c698
-rw-r--r--ext/standard/syslog.c91
-rw-r--r--ext/standard/tests/array/002.phpt40
-rw-r--r--ext/standard/tests/array/array_change_key_case_variation7.phpt28
-rw-r--r--ext/standard/tests/array/array_change_key_case_variation8.phpt6
-rw-r--r--ext/standard/tests/array/array_combine_error2.phpt5
-rw-r--r--ext/standard/tests/array/array_combine_variation3.phpt5
-rw-r--r--ext/standard/tests/array/array_combine_variation4.phpt5
-rw-r--r--ext/standard/tests/array/array_combine_variation5.phpt5
-rw-r--r--ext/standard/tests/array/array_diff_variation9.phpt56
-rw-r--r--ext/standard/tests/array/array_fill_object.phpt2
-rw-r--r--ext/standard/tests/array/array_fill_object_2_4.phpt434
-rw-r--r--ext/standard/tests/array/array_intersect_assoc_variation9.phpt24
-rw-r--r--ext/standard/tests/array/array_intersect_variation9.phpt92
-rw-r--r--ext/standard/tests/array/array_key_exists_variation4.phpt15
-rw-r--r--ext/standard/tests/array/array_map_variation19.phpt2
-rw-r--r--ext/standard/tests/array/array_merge_variation9.phpt15
-rw-r--r--ext/standard/tests/array/array_multisort_basic1.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_basic2.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_case.phpt73
-rw-r--r--ext/standard/tests/array/array_multisort_error.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_incase.phpt73
-rw-r--r--ext/standard/tests/array/array_multisort_natural.phpt61
-rw-r--r--ext/standard/tests/array/array_multisort_natural_case.phpt73
-rw-r--r--ext/standard/tests/array/array_multisort_natural_incase.phpt73
-rw-r--r--ext/standard/tests/array/array_multisort_variation1.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation10.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation11.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation2.phpt4
-rw-r--r--ext/standard/tests/array/array_multisort_variation3.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation4.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation5.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation6.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation7.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation8.phpt2
-rw-r--r--ext/standard/tests/array/array_multisort_variation9.phpt2
-rw-r--r--ext/standard/tests/array/array_push_variation4.phpt110
-rw-r--r--ext/standard/tests/array/array_slice_variation9.phpt25
-rw-r--r--ext/standard/tests/array/array_unique_variation8.phpt28
-rw-r--r--ext/standard/tests/array/array_values_variation6.phpt16
-rw-r--r--ext/standard/tests/array/arsort_basic.phpt120
-rw-r--r--ext/standard/tests/array/arsort_variation2.phpt6
-rw-r--r--ext/standard/tests/array/arsort_variation5.phpt12
-rw-r--r--ext/standard/tests/array/asort_basic.phpt122
-rw-r--r--ext/standard/tests/array/asort_variation2.phpt4
-rw-r--r--ext/standard/tests/array/asort_variation5.phpt12
-rw-r--r--ext/standard/tests/array/bug29253.phpt2
-rw-r--r--ext/standard/tests/array/bug33940.phpt63
-rw-r--r--ext/standard/tests/array/current_variation5.phpt2
-rw-r--r--ext/standard/tests/array/each_variation4.phpt31
-rw-r--r--ext/standard/tests/array/krsort_basic.phpt157
-rw-r--r--ext/standard/tests/array/krsort_variation2.phpt4
-rw-r--r--ext/standard/tests/array/krsort_variation5.phpt12
-rw-r--r--ext/standard/tests/array/ksort_basic.phpt158
-rw-r--r--ext/standard/tests/array/ksort_variation2.phpt4
-rw-r--r--ext/standard/tests/array/ksort_variation5.phpt12
-rw-r--r--ext/standard/tests/array/natcasesort_variation4.phpt6
-rw-r--r--ext/standard/tests/array/range_variation.phpt2
-rw-r--r--ext/standard/tests/array/rsort_basic.phpt128
-rw-r--r--ext/standard/tests/array/rsort_variation4.phpt18
-rw-r--r--ext/standard/tests/array/rsort_variation5.phpt26
-rw-r--r--ext/standard/tests/array/sort_basic.phpt130
-rw-r--r--ext/standard/tests/array/sort_variation2.phpt4
-rw-r--r--ext/standard/tests/array/sort_variation5.phpt24
-rw-r--r--ext/standard/tests/assert/assert04.phpt5
-rw-r--r--ext/standard/tests/assert/assert_basic6.phpt26
-rw-r--r--ext/standard/tests/assert/assert_error1.phpt11
-rw-r--r--ext/standard/tests/assert/assert_error2.phpt30
-rw-r--r--ext/standard/tests/assert/assert_error3.phpt21
-rw-r--r--ext/standard/tests/assert/assert_error4.phpt21
-rw-r--r--ext/standard/tests/class_object/AutoTrait.inc5
-rw-r--r--ext/standard/tests/class_object/class_exists_variation_001.phpt5
-rw-r--r--ext/standard/tests/class_object/class_exists_variation_002.phpt5
-rw-r--r--ext/standard/tests/class_object/get_class_methods_variation_001.phpt5
-rw-r--r--ext/standard/tests/class_object/get_class_variation_001.phpt2
-rw-r--r--ext/standard/tests/class_object/get_declared_traits_basic_001.phpt56
-rw-r--r--ext/standard/tests/class_object/get_declared_traits_error_001.phpt27
-rw-r--r--ext/standard/tests/class_object/get_declared_traits_variation1.phpt41
-rw-r--r--ext/standard/tests/class_object/get_object_vars_variation_003.phpt2
-rw-r--r--ext/standard/tests/class_object/get_parent_class_variation_002.phpt5
-rw-r--r--ext/standard/tests/class_object/is_a_variation_001.phpt2
-rw-r--r--ext/standard/tests/class_object/is_a_variation_002.phpt2
-rw-r--r--ext/standard/tests/class_object/is_subclass_of_variation_001.phpt5
-rw-r--r--ext/standard/tests/class_object/is_subclass_of_variation_002.phpt5
-rw-r--r--ext/standard/tests/class_object/is_subclass_of_variation_004.phpt5
-rw-r--r--ext/standard/tests/class_object/method_exists_variation_001.phpt5
-rw-r--r--ext/standard/tests/class_object/method_exists_variation_002.phpt5
-rw-r--r--ext/standard/tests/class_object/trait_class_exists_variation_003.phpt18
-rw-r--r--ext/standard/tests/class_object/trait_exists_basic_001.phpt57
-rw-r--r--ext/standard/tests/class_object/trait_exists_error_001.phpt42
-rw-r--r--ext/standard/tests/class_object/trait_exists_variation_001.phpt187
-rw-r--r--ext/standard/tests/class_object/trait_exists_variation_002.phpt198
-rw-r--r--ext/standard/tests/dir/chdir_variation1.phpt4
-rw-r--r--ext/standard/tests/dir/dir_variation1-win32.phpt170
-rw-r--r--ext/standard/tests/dir/dir_variation5-win32.phpt37
-rw-r--r--ext/standard/tests/dir/dir_variation6-win32.phpt61
-rw-r--r--ext/standard/tests/dir/dir_variation8-win32.phpt68
-rw-r--r--ext/standard/tests/dir/dir_variation9-win32.phpt125
-rw-r--r--ext/standard/tests/dir/opendir_error2-win32.phpt47
-rw-r--r--ext/standard/tests/dir/opendir_variation1-win32.phpt248
-rw-r--r--ext/standard/tests/dir/readdir_variation4.phpt2
-rw-r--r--ext/standard/tests/dir/scandir_basic.phpt2
-rw-r--r--ext/standard/tests/dir/scandir_error2-win32.phpt51
-rw-r--r--ext/standard/tests/dir/scandir_variation1-win32.phpt289
-rw-r--r--ext/standard/tests/dir/scandir_variation1.phpt4
-rw-r--r--ext/standard/tests/dir/scandir_variation10.phpt79
-rw-r--r--ext/standard/tests/dir/scandir_variation3.phpt2
-rw-r--r--ext/standard/tests/dir/scandir_variation6-win32.phpt84
-rw-r--r--ext/standard/tests/dir/scandir_variation8.phpt2
-rw-r--r--ext/standard/tests/file/005_variation2-win32.phpt8
-rw-r--r--ext/standard/tests/file/005_variation2.phpt6
-rw-r--r--ext/standard/tests/file/007_error.phpt4
-rw-r--r--ext/standard/tests/file/bug22414.phpt3
-rw-r--r--ext/standard/tests/file/bug38450_3.phpt2
-rw-r--r--ext/standard/tests/file/bug39863.phpt3
-rw-r--r--ext/standard/tests/file/bug52820.phpt22
-rw-r--r--ext/standard/tests/file/bug55124.phpt18
-rw-r--r--ext/standard/tests/file/chmod_variation3.phpt10
-rw-r--r--ext/standard/tests/file/copy_variation4.phptbin4468 -> 4966 bytes
-rw-r--r--ext/standard/tests/file/disk_free_space_variation.phpt32
-rw-r--r--ext/standard/tests/file/disk_total_space_variation.phpt16
-rw-r--r--ext/standard/tests/file/fclose_variation1.phpt15
-rw-r--r--ext/standard/tests/file/file_get_contents_variation8-win32.phpt15
-rw-r--r--ext/standard/tests/file/file_get_contents_variation8.phpt13
-rw-r--r--ext/standard/tests/file/file_put_contents_variation8-win32.phpt4
-rw-r--r--ext/standard/tests/file/file_put_contents_variation8.phptbin2229 -> 2388 bytes
-rw-r--r--ext/standard/tests/file/file_variation2.phpt10
-rw-r--r--ext/standard/tests/file/filegroup_variation2.phpt2
-rw-r--r--ext/standard/tests/file/filegroup_variation3.phpt8
-rw-r--r--ext/standard/tests/file/fileinode_variation2.phpt2
-rw-r--r--ext/standard/tests/file/fileinode_variation3.phpt8
-rw-r--r--ext/standard/tests/file/fileowner_variation2.phpt2
-rw-r--r--ext/standard/tests/file/fileowner_variation3.phpt8
-rw-r--r--ext/standard/tests/file/fileperms_variation2.phpt2
-rw-r--r--ext/standard/tests/file/fileperms_variation3.phpt8
-rw-r--r--ext/standard/tests/file/fnmatch_error.phpt6
-rw-r--r--ext/standard/tests/file/fnmatch_variation.phpt134
-rw-r--r--ext/standard/tests/file/fpassthru_variation1.phpt2
-rw-r--r--ext/standard/tests/file/fseek_variation1.phpt2
-rw-r--r--ext/standard/tests/file/glob_variation-win32.phpt28
-rw-r--r--ext/standard/tests/file/glob_variation.phpt28
-rw-r--r--ext/standard/tests/file/is_dir_variation3.phpt2
-rw-r--r--ext/standard/tests/file/is_dir_variation4.phpt8
-rw-r--r--ext/standard/tests/file/is_executable_variation1.phpt8
-rw-r--r--ext/standard/tests/file/is_executable_variation3.phpt2
-rw-r--r--ext/standard/tests/file/is_file_error.phpt2
-rw-r--r--ext/standard/tests/file/is_file_variation3.phpt2
-rw-r--r--ext/standard/tests/file/is_file_variation4.phpt8
-rw-r--r--ext/standard/tests/file/is_readable_variation1.phpt12
-rw-r--r--ext/standard/tests/file/is_readable_variation3.phpt2
-rw-r--r--ext/standard/tests/file/is_writable_variation1.phpt26
-rw-r--r--ext/standard/tests/file/is_writable_variation3.phpt4
-rw-r--r--ext/standard/tests/file/lchown_error.phpt4
-rw-r--r--ext/standard/tests/file/lstat_stat_error.phpt4
-rw-r--r--ext/standard/tests/file/lstat_stat_variation7.phpt2
-rw-r--r--ext/standard/tests/file/magic_quotes.phpt77
-rw-r--r--ext/standard/tests/file/mkdir_rmdir_variation2.phpt6
-rw-r--r--ext/standard/tests/file/parse_ini_file_variation3.phpt4
-rw-r--r--ext/standard/tests/file/parse_ini_file_variation4.phpt10
-rw-r--r--ext/standard/tests/file/readfile_variation10-win32.phpt18
-rw-r--r--ext/standard/tests/file/readfile_variation10.phptbin1852 -> 1869 bytes
-rw-r--r--ext/standard/tests/file/rename_variation13-win32.phptbin3962 -> 5058 bytes
-rw-r--r--ext/standard/tests/file/rename_variation13.phpt14
-rw-r--r--ext/standard/tests/file/rename_variation7-win32.phpt6
-rw-r--r--ext/standard/tests/file/stat_error-win32.phpt2
-rw-r--r--ext/standard/tests/file/stream_enclosed.phpt20
-rw-r--r--ext/standard/tests/file/stream_rfc2397_006.phpt7
-rw-r--r--ext/standard/tests/file/tempnam_variation3-win32.phpt5
-rw-r--r--ext/standard/tests/file/tempnam_variation3.phpt6
-rw-r--r--ext/standard/tests/file/tempnam_variation7-win32.phpt10
-rw-r--r--ext/standard/tests/file/tempnam_variation7.phpt8
-rw-r--r--ext/standard/tests/file/umask_basic.phpt2
-rw-r--r--ext/standard/tests/file/umask_variation3.phpt6
-rw-r--r--ext/standard/tests/file/userstreams_005.phpt63
-rw-r--r--ext/standard/tests/file/userstreams_006.phpt38
-rw-r--r--ext/standard/tests/file/userstreams_007.phpt49
-rw-r--r--ext/standard/tests/file/windows_links/bug48746.phpt2
-rw-r--r--ext/standard/tests/file/windows_links/bug48746_1.phpt2
-rw-r--r--ext/standard/tests/file/windows_links/bug48746_2.phpt2
-rw-r--r--ext/standard/tests/file/windows_links/bug48746_3.phpt2
-rw-r--r--ext/standard/tests/filters/php_user_filter_01.phpt2
-rw-r--r--ext/standard/tests/filters/php_user_filter_02.phpt2
-rw-r--r--ext/standard/tests/filters/php_user_filter_03.phpt2
-rw-r--r--ext/standard/tests/general_functions/bug27678.phpt4
-rw-r--r--ext/standard/tests/general_functions/bug41518.phpt7
-rw-r--r--ext/standard/tests/general_functions/bug55371.phpt10
-rw-r--r--ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt2
-rw-r--r--ext/standard/tests/general_functions/debug_zval_dump_b.phptbin7279 -> 5004 bytes
-rw-r--r--ext/standard/tests/general_functions/debug_zval_dump_b_64bit.phptbin7279 -> 5004 bytes
-rw-r--r--ext/standard/tests/general_functions/debug_zval_dump_o.phpt2
-rw-r--r--ext/standard/tests/general_functions/debug_zval_dump_v.phpt11
-rw-r--r--ext/standard/tests/general_functions/get_cfg_var_variation8.phpt37
-rw-r--r--ext/standard/tests/general_functions/get_magic_quotes_gpc.phpt39
-rw-r--r--ext/standard/tests/general_functions/get_magic_quotes_runtime.phpt52
-rw-r--r--ext/standard/tests/general_functions/getservbyname_variation10.phpt6
-rw-r--r--ext/standard/tests/general_functions/getservbyname_variation9.phpt6
-rw-r--r--ext/standard/tests/general_functions/import_request.phpt4
-rw-r--r--ext/standard/tests/general_functions/import_request1.phpt2
-rw-r--r--ext/standard/tests/general_functions/import_request2.phpt2
-rw-r--r--ext/standard/tests/general_functions/import_request3.phpt2
-rw-r--r--ext/standard/tests/general_functions/ob_get_flush_error.phpt2
-rw-r--r--ext/standard/tests/general_functions/parse_ini_basic.data4
-rw-r--r--ext/standard/tests/general_functions/parse_ini_basic.phpt4
-rw-r--r--ext/standard/tests/general_functions/parse_ini_booleans.phpt8
-rw-r--r--ext/standard/tests/general_functions/phpinfo.phpt3
-rw-r--r--ext/standard/tests/general_functions/proc_nice_error.phpt19
-rw-r--r--ext/standard/tests/general_functions/putenv_error1.phpt26
-rw-r--r--ext/standard/tests/general_functions/putenv_error2.phpt20
-rw-r--r--ext/standard/tests/general_functions/set_magic_quotes_runtime_basic.phpt24
-rw-r--r--ext/standard/tests/general_functions/set_magic_quotes_runtime_variation1.phpt204
-rw-r--r--ext/standard/tests/general_functions/strval.phpt8
-rw-r--r--ext/standard/tests/general_functions/sys_getloadavg.phpt13
-rw-r--r--ext/standard/tests/general_functions/var_export_error2.phpt3
-rw-r--r--ext/standard/tests/general_functions/var_export_error3.phpt3
-rw-r--r--ext/standard/tests/image/getimagesizefromstring1.phpt49
-rw-r--r--ext/standard/tests/image/test.gifbin0 -> 2523 bytes
-rw-r--r--ext/standard/tests/mail/mail_basic2.phpt17
-rw-r--r--ext/standard/tests/mail/mail_variation2.phpt15
-rw-r--r--ext/standard/tests/math/bug45712.phpt2
-rw-r--r--ext/standard/tests/math/bug62112.phptbin0 -> 143 bytes
-rw-r--r--ext/standard/tests/math/number_format_multichar.phpt77
-rw-r--r--ext/standard/tests/misc/syslog_vars_variation1.phpt11
-rw-r--r--ext/standard/tests/misc/syslog_vars_variation2.phpt52
-rw-r--r--ext/standard/tests/network/define_syslog_variables_basic-win32.phpt107
-rw-r--r--ext/standard/tests/network/define_syslog_variables_basic.phpt126
-rw-r--r--ext/standard/tests/network/define_syslog_variables_error.phpt29
-rw-r--r--ext/standard/tests/network/define_syslog_variables_variation.phpt92
-rw-r--r--ext/standard/tests/network/define_syslog_variables_variation2-win32.phpt96
-rw-r--r--ext/standard/tests/network/define_syslog_variables_variation2.phpt96
-rw-r--r--ext/standard/tests/network/gethostbyname_basic001.phpt1
-rw-r--r--ext/standard/tests/network/gethostbyname_basic002.phpt15
-rw-r--r--ext/standard/tests/network/gethostbyname_error004.phpt1
-rw-r--r--ext/standard/tests/network/getmxrr.phpt1
-rw-r--r--ext/standard/tests/network/ip2long_variation1.phpt2
-rw-r--r--ext/standard/tests/serialize/bug36424.phpt72
-rw-r--r--ext/standard/tests/serialize/bug62836_1.phpt34
-rw-r--r--ext/standard/tests/serialize/bug62836_2.phpt37
-rw-r--r--ext/standard/tests/serialize/serialization_miscTypes_001.phptbin7586 -> 7617 bytes
-rw-r--r--ext/standard/tests/streams/bug40459.phpt103
-rw-r--r--ext/standard/tests/streams/bug49936.phpt13
-rw-r--r--ext/standard/tests/streams/bug53427.phpt27
-rw-r--r--ext/standard/tests/streams/bug54623.phpt4
-rw-r--r--ext/standard/tests/streams/stream_set_chunk_size.phpt93
-rw-r--r--ext/standard/tests/strings/add-and-stripslashes.phpt12
-rw-r--r--ext/standard/tests/strings/addslashes_variation3.phpt196
-rw-r--r--ext/standard/tests/strings/bug22904.phpt30
-rw-r--r--ext/standard/tests/strings/bug44703.phpt12
-rw-r--r--ext/standard/tests/strings/bug49785.phpt293
-rw-r--r--ext/standard/tests/strings/bug54322.phpt9
-rw-r--r--ext/standard/tests/strings/bug54454.phpt8
-rw-r--r--ext/standard/tests/strings/bug55871.phpt47
-rw-r--r--ext/standard/tests/strings/bug60965.phpt10
-rw-r--r--ext/standard/tests/strings/bug61374.phpt7
-rw-r--r--ext/standard/tests/strings/bug61660.phpt11
-rw-r--r--ext/standard/tests/strings/bug62462.phpt17
-rw-r--r--ext/standard/tests/strings/crypt_blowfish.phpt32
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic1.phpt1094
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic2.phpt2494
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic3.phpt36
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic4.phpt352
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic5.phpt1598
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic6.phpt249
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic7.phpt342
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic8.phpt93
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_basic9.phpt95
-rw-r--r--ext/standard/tests/strings/get_html_translation_table_variation1.phpt108
-rw-r--r--ext/standard/tests/strings/highlight_file.phpt1
-rw-r--r--ext/standard/tests/strings/html_entity_decode1.phpt67
-rw-r--r--ext/standard/tests/strings/html_entity_decode2.phpt33
-rw-r--r--ext/standard/tests/strings/html_entity_decode3.phpt193
-rw-r--r--ext/standard/tests/strings/html_entity_decode_cp866.phpt533
-rw-r--r--ext/standard/tests/strings/html_entity_decode_html4.phpt504
-rw-r--r--ext/standard/tests/strings/html_entity_decode_html5.phpt4264
-rw-r--r--ext/standard/tests/strings/html_entity_decode_iso8859-15.phpt405
-rw-r--r--ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt405
-rw-r--r--ext/standard/tests/strings/html_entity_decode_koi8-r.phpt533
-rw-r--r--ext/standard/tests/strings/html_entity_decode_macroman.phpt540
-rw-r--r--ext/standard/tests/strings/html_entity_decode_win1251.phpt537
-rw-r--r--ext/standard/tests/strings/html_entity_decode_win1252.phpt169
-rw-r--r--ext/standard/tests/strings/htmlentities.phpt10
-rw-r--r--ext/standard/tests/strings/htmlentities04.phpt3
-rw-r--r--ext/standard/tests/strings/htmlentities05.phpt9
-rw-r--r--ext/standard/tests/strings/htmlentities06.phpt7
-rw-r--r--ext/standard/tests/strings/htmlentities07.phpt8
-rw-r--r--ext/standard/tests/strings/htmlentities08.phpt9
-rw-r--r--ext/standard/tests/strings/htmlentities09.phpt9
-rw-r--r--ext/standard/tests/strings/htmlentities13.phpt5
-rw-r--r--ext/standard/tests/strings/htmlentities14.phpt5
-rw-r--r--ext/standard/tests/strings/htmlentities15.phpt5
-rw-r--r--ext/standard/tests/strings/htmlentities16.phpt12
-rw-r--r--ext/standard/tests/strings/htmlentities18.phpt4
-rw-r--r--ext/standard/tests/strings/htmlentities19.phpt30
-rw-r--r--ext/standard/tests/strings/htmlentities20.phpt199
-rw-r--r--ext/standard/tests/strings/htmlentities21.phpt198
-rw-r--r--ext/standard/tests/strings/htmlentities22.phpt283
-rw-r--r--ext/standard/tests/strings/htmlentities23.phpt95
-rw-r--r--ext/standard/tests/strings/htmlentities24.phpt (renamed from ext/standard/tests/file/htmlentities19.phpt)12
-rw-r--r--ext/standard/tests/strings/htmlentities_html5.phpt1623
-rw-r--r--ext/standard/tests/strings/htmlspecialchars.phpt (renamed from ext/standard/tests/file/htmlspecialchars.phpt)0
-rw-r--r--ext/standard/tests/strings/htmlspecialchars_decode_variation7.phpt192
-rw-r--r--ext/standard/tests/strings/http_build_query_error.phpt13
-rw-r--r--ext/standard/tests/strings/http_build_query_variation1.phpt30
-rw-r--r--ext/standard/tests/strings/http_build_query_variation2.phpt39
-rw-r--r--ext/standard/tests/strings/http_build_query_variation3.phpt27
-rw-r--r--ext/standard/tests/strings/md5_file.phptbin2837 -> 2849 bytes
-rw-r--r--ext/standard/tests/strings/nl_langinfo_variation1.phpt104
-rw-r--r--ext/standard/tests/strings/parse_str_basic3.phptbin5243 -> 5141 bytes
-rw-r--r--ext/standard/tests/strings/print_variation1.phpt6
-rw-r--r--ext/standard/tests/strings/quoted_printable_encode_002.phptbin7290 -> 7292 bytes
-rw-r--r--ext/standard/tests/strings/sha1_file.phpt4
-rw-r--r--ext/standard/tests/strings/stripslashes_variation5.phptbin8397 -> 0 bytes
-rw-r--r--ext/standard/tests/strings/strrchr_variation5.phpt12
-rw-r--r--ext/standard/tests/strings/strspn_variation6.phpt10
-rw-r--r--ext/standard/tests/strings/strtok_variation6.phpt2
-rw-r--r--ext/standard/tests/strings/strtolower.phptbin5049 -> 3889 bytes
-rw-r--r--ext/standard/tests/strings/strtoupper1.phptbin5060 -> 3900 bytes
-rw-r--r--ext/standard/tests/strings/strval.phpt4
-rw-r--r--ext/standard/tests/strings/substr_compare.phpt2
-rw-r--r--ext/standard/tests/time/strptime_basic.phpt1
-rw-r--r--ext/standard/tests/time/strptime_parts.phpt76
-rw-r--r--ext/standard/tests/url/base64_encode_variation_001.phpt5
-rw-r--r--ext/standard/tests/url/bug63162.phpt38
-rw-r--r--ext/standard/tests/url/parse_url_relative_scheme.phpt11
-rw-r--r--ext/standard/tests/url/parse_url_variation_001.phpt5
-rw-r--r--ext/standard/tests/url/parse_url_variation_002_32bit.phpt5
-rw-r--r--ext/standard/tests/url/parse_url_variation_002_64bit.phpt5
-rw-r--r--ext/standard/tests/url/rawurldecode_variation_001.phpt5
-rw-r--r--ext/standard/tests/url/rawurlencode_variation_001.phpt5
-rw-r--r--ext/standard/tests/url/urldecode_variation_001.phpt5
-rw-r--r--ext/standard/tests/url/urlencode_variation_001.phpt5
-rw-r--r--ext/standard/type.c7
-rw-r--r--ext/standard/url.c6
-rw-r--r--ext/standard/url.h3
-rw-r--r--ext/standard/url_scanner_ex.c10
-rw-r--r--ext/standard/url_scanner_ex.re8
-rw-r--r--ext/standard/user_filters.c5
-rw-r--r--ext/standard/var.c93
-rw-r--r--ext/standard/var_unserializer.c150
-rw-r--r--ext/standard/var_unserializer.re80
-rw-r--r--ext/standard/winver.h9
-rw-r--r--ext/sybase_ct/php_sybase_ct.c25
-rw-r--r--ext/sysvmsg/sysvmsg.c2
-rw-r--r--ext/sysvmsg/tests/006.phpt2
-rw-r--r--ext/sysvsem/tests/sysv.phpt2
-rw-r--r--ext/tidy/examples/cleanhtml.php2
-rw-r--r--ext/tidy/examples/cleanhtml5.php2
-rw-r--r--ext/tidy/php_tidy.h1
-rw-r--r--ext/tidy/tests/019.phpt2
-rw-r--r--ext/tidy/tests/022.phpt2
-rw-r--r--ext/tidy/tidy.c309
-rw-r--r--ext/tokenizer/tests/bug54089.phpt274
-rw-r--r--ext/tokenizer/tests/token_get_all_basic.phpt18
-rw-r--r--ext/tokenizer/tests/token_get_all_error.phpt2
-rw-r--r--ext/tokenizer/tests/token_get_all_variation1.phpt26
-rw-r--r--ext/tokenizer/tests/token_get_all_variation10.phpt148
-rw-r--r--ext/tokenizer/tests/token_get_all_variation11.phpt238
-rw-r--r--ext/tokenizer/tests/token_get_all_variation12.phpt223
-rw-r--r--ext/tokenizer/tests/token_get_all_variation13.phpt228
-rw-r--r--ext/tokenizer/tests/token_get_all_variation14.phpt56
-rw-r--r--ext/tokenizer/tests/token_get_all_variation15.phpt154
-rw-r--r--ext/tokenizer/tests/token_get_all_variation16.phpt47
-rw-r--r--ext/tokenizer/tests/token_get_all_variation17.phpt114
-rw-r--r--ext/tokenizer/tests/token_get_all_variation18.phpt18
-rw-r--r--ext/tokenizer/tests/token_get_all_variation19.phpt2
-rw-r--r--ext/tokenizer/tests/token_get_all_variation2.phpt82
-rw-r--r--ext/tokenizer/tests/token_get_all_variation3.phpt112
-rw-r--r--ext/tokenizer/tests/token_get_all_variation4.phpt154
-rw-r--r--ext/tokenizer/tests/token_get_all_variation5.phpt150
-rw-r--r--ext/tokenizer/tests/token_get_all_variation6.phpt88
-rw-r--r--ext/tokenizer/tests/token_get_all_variation7.phpt54
-rw-r--r--ext/tokenizer/tests/token_get_all_variation8.phpt180
-rw-r--r--ext/tokenizer/tests/token_get_all_variation9.phpt82
-rw-r--r--ext/tokenizer/tokenizer.c37
-rw-r--r--ext/tokenizer/tokenizer_data.c8
-rwxr-xr-xext/tokenizer/tokenizer_data_gen.sh2
-rw-r--r--ext/wddx/tests/bug48562.phpt6
-rw-r--r--ext/wddx/wddx.c4
-rw-r--r--ext/xml/config.w322
-rw-r--r--ext/xml/tests/bug62328.phpt21
-rw-r--r--ext/xml/tests/utf8_decode_variation1.phpt2
-rw-r--r--ext/xml/tests/utf8_encode_variation1.phpt2
-rw-r--r--ext/xml/tests/xml001.phpt2
-rw-r--r--ext/xml/tests/xml002.phpt2
-rw-r--r--ext/xml/tests/xml003.phpt2
-rw-r--r--ext/xml/tests/xml004.phpt2
-rw-r--r--ext/xml/tests/xml_closures_001.phpt2
-rw-r--r--ext/xml/tests/xml_error_string_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_get_current_byte_index_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_get_current_column_number_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_get_current_line_number_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_get_error_code_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parse_into_struct_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parse_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parser_create_ns_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parser_create_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parser_free_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parser_get_option_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parser_get_option_variation2.phpt2
-rw-r--r--ext/xml/tests/xml_parser_set_option_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_parser_set_option_variation2.phpt2
-rw-r--r--ext/xml/tests/xml_parser_set_option_variation3.phpt2
-rw-r--r--ext/xml/tests/xml_set_character_data_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_default_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_element_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_end_namespace_decl_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_external_entity_ref_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_notation_decl_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_object_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_object_variation2.phpt2
-rw-r--r--ext/xml/tests/xml_set_processing_instruction_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_start_namespace_decl_handler_variation1.phpt2
-rw-r--r--ext/xml/tests/xml_set_unparsed_entity_decl_handler_variation1.phpt2
-rw-r--r--ext/xml/xml.c102
-rw-r--r--ext/xmlreader/php_xmlreader.c26
-rw-r--r--ext/xmlwriter/php_xmlwriter.c6
-rw-r--r--ext/xsl/php_xsl.c7
-rw-r--r--ext/xsl/php_xsl.h2
-rw-r--r--ext/xsl/tests/bug54446.phpt95
-rw-r--r--ext/xsl/tests/bug54446_with_ini.phpt40
-rw-r--r--ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcnostring.phpt6
-rw-r--r--ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcundef.phpt6
-rw-r--r--ext/xsl/xsl_fe.h3
-rw-r--r--ext/xsl/xsltprocessor.c95
-rw-r--r--ext/zip/php_zip.c117
-rw-r--r--ext/zlib/CREDITS2
-rw-r--r--ext/zlib/config0.m49
-rw-r--r--ext/zlib/php_zlib.h54
-rw-r--r--ext/zlib/tests/001.phpt2
-rw-r--r--ext/zlib/tests/003.phpt2
-rw-r--r--ext/zlib/tests/004.phpt23
-rw-r--r--ext/zlib/tests/006.phpt2
-rw-r--r--ext/zlib/tests/007.phpt16
-rw-r--r--ext/zlib/tests/bug55544-win.phptbin0 -> 427 bytes
-rw-r--r--ext/zlib/tests/bug55544.phptbin0 -> 430 bytes
-rw-r--r--ext/zlib/tests/bug60761.phpt108
-rw-r--r--ext/zlib/tests/bug61287.phpt24
-rw-r--r--ext/zlib/tests/bug61443.phpt15
-rw-r--r--ext/zlib/tests/bug61820.phpt23
-rw-r--r--ext/zlib/tests/data.inc2
-rw-r--r--ext/zlib/tests/gzcompress_basic1.phpt6
-rw-r--r--ext/zlib/tests/gzcompress_error1.phpt28
-rw-r--r--ext/zlib/tests/gzcompress_variation1.phpt6
-rw-r--r--ext/zlib/tests/gzdeflate_basic1.phpt2
-rw-r--r--ext/zlib/tests/gzdeflate_error1.phpt18
-rw-r--r--ext/zlib/tests/gzencode_basic1.phpt27
-rw-r--r--ext/zlib/tests/gzencode_error1.phpt8
-rw-r--r--ext/zlib/tests/gzencode_variation1.phpt6
-rw-r--r--ext/zlib/tests/gzencode_variation2-win32.phpt40
-rw-r--r--ext/zlib/tests/gzencode_variation2.phpt8
-rw-r--r--ext/zlib/tests/gzfile_basic.phpt2
-rw-r--r--ext/zlib/tests/gzfile_basic2.phpt2
-rw-r--r--ext/zlib/tests/gzfile_variation1.phpt10
-rw-r--r--ext/zlib/tests/gzfile_variation6.phpt4
-rw-r--r--ext/zlib/tests/gzinflate-bug42663.phpt11
-rw-r--r--ext/zlib/tests/gzinflate_length.phpt2
-rw-r--r--ext/zlib/tests/gzreadgzwrite.phpt9
-rw-r--r--ext/zlib/tests/gzreadgzwriteplain.phpt15
-rw-r--r--ext/zlib/tests/gzuncompress_error1.phpt8
-rw-r--r--ext/zlib/tests/gzwrite_variation1.phpt2
-rw-r--r--ext/zlib/tests/ob_001.phpt20
-rw-r--r--ext/zlib/tests/ob_002.phpt18
-rw-r--r--ext/zlib/tests/ob_003.phpt23
-rw-r--r--ext/zlib/tests/ob_004.phpt24
-rw-r--r--ext/zlib/tests/ob_005.phpt22
-rw-r--r--ext/zlib/tests/ob_gzhandler_legacy_002.phpt24
-rw-r--r--ext/zlib/tests/readgzfile_variation14.phpt2
-rw-r--r--ext/zlib/tests/readgzfile_variation4.phpt9
-rw-r--r--ext/zlib/tests/readgzfile_variation5.phpt9
-rw-r--r--ext/zlib/tests/readgzfile_variation6.phpt1
-rw-r--r--ext/zlib/tests/readgzfile_variation7.phpt7
-rw-r--r--ext/zlib/tests/zlib_filter_inflate2.phpt4
-rw-r--r--ext/zlib/zlib.c1667
-rw-r--r--ext/zlib/zlib_filter.c25
-rw-r--r--ext/zlib/zlib_fopen_wrapper.c2
-rw-r--r--main/SAPI.c341
-rw-r--r--main/SAPI.h18
-rw-r--r--main/fopen_wrappers.c147
-rw-r--r--main/fopen_wrappers.h3
-rw-r--r--main/main.c446
-rw-r--r--main/network.c6
-rw-r--r--main/output.c1671
-rw-r--r--main/php.h32
-rw-r--r--main/php3_compat.h122
-rw-r--r--main/php_content_types.c6
-rw-r--r--main/php_globals.h20
-rw-r--r--main/php_ini.c63
-rw-r--r--main/php_logos.c2
-rw-r--r--main/php_main.h1
-rw-r--r--main/php_network.h5
-rw-r--r--main/php_open_temporary_file.c2
-rw-r--r--main/php_output.h299
-rw-r--r--main/php_streams.h24
-rw-r--r--main/php_variables.c337
-rw-r--r--main/php_version.h8
-rw-r--r--main/rfc1867.c391
-rw-r--r--main/rfc1867.h15
-rw-r--r--main/safe_mode.c276
-rw-r--r--main/snprintf.c6
-rw-r--r--main/spprintf.c2
-rw-r--r--main/streams/cast.c2
-rw-r--r--main/streams/glob_wrapper.c2
-rw-r--r--main/streams/memory.c18
-rw-r--r--main/streams/php_stream_context.h6
-rw-r--r--main/streams/plain_wrapper.c284
-rw-r--r--main/streams/streams.c103
-rw-r--r--main/streams/userspace.c508
-rw-r--r--main/streams/xp_socket.c4
-rwxr-xr-xmakedist8
-rw-r--r--pear/Makefile.frag2
-rw-r--r--php.ini-development289
-rw-r--r--php.ini-production291
-rwxr-xr-xrun-tests.php5
-rw-r--r--sapi/apache/mod_php5.c16
-rw-r--r--sapi/apache/php_apache.c19
-rw-r--r--sapi/apache2filter/php_functions.c4
-rw-r--r--sapi/apache2filter/sapi_apache2.c26
-rw-r--r--sapi/apache2handler/config.w3223
-rw-r--r--sapi/apache2handler/php_functions.c6
-rw-r--r--sapi/apache2handler/sapi_apache2.c36
-rw-r--r--sapi/apache_hooks/mod_php5.c29
-rw-r--r--sapi/apache_hooks/php_apache.c26
-rw-r--r--sapi/apache_hooks/sapi_apache.c10
-rw-r--r--sapi/cgi/Makefile.frag9
-rw-r--r--sapi/cgi/cgi_main.c686
-rw-r--r--sapi/cgi/config9.m432
-rw-r--r--sapi/cgi/fastcgi.c517
-rw-r--r--sapi/cgi/fastcgi.h45
-rw-r--r--sapi/cgi/tests/apache_request_headers.phpt51
-rw-r--r--sapi/cli/CREDITS2
-rw-r--r--sapi/cli/Makefile.frag8
-rw-r--r--sapi/cli/README4
-rw-r--r--sapi/cli/cli.h52
-rw-r--r--sapi/cli/config.m431
-rw-r--r--sapi/cli/config.w325
-rw-r--r--sapi/cli/php.1.in10
-rw-r--r--sapi/cli/php_cli.c604
-rw-r--r--sapi/cli/php_cli_server.c2422
-rw-r--r--sapi/cli/php_cli_server.h (renamed from ext/hash/php_hash_salsa.h)39
-rw-r--r--sapi/cli/php_http_parser.c1608
-rw-r--r--sapi/cli/php_http_parser.h180
-rw-r--r--sapi/cli/tests/007.phpt4
-rw-r--r--sapi/cli/tests/008.phpt4
-rw-r--r--sapi/cli/tests/009.phpt8
-rw-r--r--sapi/cli/tests/011.phpt4
-rw-r--r--sapi/cli/tests/012.phpt32
-rw-r--r--sapi/cli/tests/014.phpt4
-rw-r--r--sapi/cli/tests/016.phpt2
-rw-r--r--sapi/cli/tests/bug61679.phpt43
-rw-r--r--sapi/cli/tests/bug61977.phpt157
-rw-r--r--sapi/cli/tests/php_cli_server.inc62
-rw-r--r--sapi/cli/tests/php_cli_server_001.phpt16
-rw-r--r--sapi/cli/tests/php_cli_server_002.phpt20
-rw-r--r--sapi/cli/tests/php_cli_server_003.phpt18
-rw-r--r--sapi/cli/tests/php_cli_server_004.phpt48
-rw-r--r--sapi/cli/tests/php_cli_server_005.phpt71
-rw-r--r--sapi/cli/tests/php_cli_server_006.phpt42
-rw-r--r--sapi/cli/tests/php_cli_server_007.phpt40
-rw-r--r--sapi/cli/tests/php_cli_server_008.phpt68
-rw-r--r--sapi/cli/tests/php_cli_server_009.phpt93
-rw-r--r--sapi/cli/tests/php_cli_server_010.phpt75
-rw-r--r--sapi/cli/tests/php_cli_server_011.phpt41
-rw-r--r--sapi/cli/tests/php_cli_server_012.phpt55
-rw-r--r--sapi/cli/tests/php_cli_server_013.phpt108
-rw-r--r--sapi/cli/tests/php_cli_server_014.phpt80
-rw-r--r--sapi/cli/tests/php_cli_server_015.phpt49
-rw-r--r--sapi/cli/tests/php_cli_server_016.phpt46
-rw-r--r--sapi/cli/tests/php_cli_server_017.phpt44
-rw-r--r--sapi/cli/tests/php_cli_server_018.phpt44
-rw-r--r--sapi/continuity/capi.c3
-rw-r--r--sapi/embed/config.w321
-rw-r--r--sapi/embed/php_embed.c2
-rw-r--r--sapi/fpm/Makefile.frag13
-rw-r--r--sapi/fpm/config.m424
-rw-r--r--sapi/fpm/fpm/fpm_main.c41
-rw-r--r--sapi/fpm/fpm/fpm_php_trace.c2
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.c8
-rw-r--r--sapi/fpm/fpm/fpm_request.c4
-rw-r--r--sapi/fpm/fpm/fpm_scoreboard.c5
-rw-r--r--sapi/fpm/fpm/fpm_scoreboard.h3
-rw-r--r--sapi/fpm/fpm/fpm_sockets.c2
-rw-r--r--sapi/fpm/fpm/fpm_status.c16
-rw-r--r--sapi/fpm/php-fpm.conf.in4
-rw-r--r--sapi/litespeed/Makefile.frag8
-rw-r--r--sapi/litespeed/config.m49
-rw-r--r--sapi/milter/Makefile.frag8
-rw-r--r--sapi/milter/config.m43
-rw-r--r--sapi/milter/php_milter.c12
-rw-r--r--sapi/nsapi/nsapi.c43
-rw-r--r--sapi/phttpd/phttpd.c8
-rw-r--r--scripts/php-config.in1
-rw-r--r--scripts/phpize.in1
-rw-r--r--scripts/phpize.m45
-rw-r--r--tests/basic/011.phpt7
-rw-r--r--tests/basic/012.phpt7
-rw-r--r--tests/basic/022.phpt1
-rw-r--r--tests/basic/023.phpt2
-rw-r--r--tests/basic/024.phpt1
-rw-r--r--tests/basic/025.phpt1
-rw-r--r--tests/basic/026.phpt1
-rw-r--r--tests/basic/027.phpt1
-rw-r--r--tests/basic/028.phpt105
-rw-r--r--tests/basic/029.phpt51
-rw-r--r--tests/basic/bug46313-win.phpt65
-rw-r--r--tests/basic/bug46313.phpt63
-rw-r--r--tests/basic/bug46759.phpt20
-rw-r--r--tests/basic/bug51709_1.phpt2
-rw-r--r--tests/basic/bug51709_2.phpt2
-rw-r--r--tests/basic/bug54514.phpt12
-rw-r--r--tests/basic/enable_post_data_reading_01.phpt22
-rw-r--r--tests/basic/enable_post_data_reading_02.phpt28
-rw-r--r--tests/basic/enable_post_data_reading_03.phpt23
-rw-r--r--tests/basic/enable_post_data_reading_04.phpt23
-rw-r--r--tests/basic/magic_quotes_gpc.phpt11
-rw-r--r--tests/basic/req44164.phpt17
-rw-r--r--tests/classes/array_access_010.phpt8
-rw-r--r--tests/classes/ctor_in_interface_01.phpt2
-rw-r--r--tests/classes/ctor_in_interface_02.phpt3
-rw-r--r--tests/classes/ctor_in_interface_03.phpt2
-rw-r--r--tests/classes/ctor_in_interface_04.phpt2
-rw-r--r--tests/classes/implicit_instantiation_001.phpt18
-rw-r--r--tests/classes/inheritance_003.phpt2
-rw-r--r--tests/classes/inheritance_004.phpt2
-rw-r--r--tests/classes/is_a.phpt378
-rw-r--r--tests/classes/method_override_optional_arg_001.phpt2
-rw-r--r--tests/classes/method_override_optional_arg_002.phpt2
-rw-r--r--tests/classes/type_hinting_003.phpt2
-rw-r--r--tests/classes/type_hinting_005a.phpt4
-rw-r--r--tests/classes/type_hinting_005b.phpt4
-rw-r--r--tests/classes/type_hinting_005c.phpt4
-rw-r--r--tests/classes/type_hinting_005d.phpt4
-rw-r--r--tests/lang/019.phpt2
-rw-r--r--tests/lang/array_shortcut_001.phpt13
-rw-r--r--tests/lang/array_shortcut_002.phpt13
-rw-r--r--tests/lang/array_shortcut_003.phpt13
-rw-r--r--tests/lang/array_shortcut_005.phpt20
-rw-r--r--tests/lang/bug19943.phpt4
-rw-r--r--tests/lang/bug21820.phpt4
-rw-r--r--tests/lang/bug29566.phpt2
-rw-r--r--tests/lang/bug35176.phpt5
-rw-r--r--tests/lang/bug55754.phpt14
-rw-r--r--tests/lang/bug7515.phpt3
-rw-r--r--tests/lang/engine_assignExecutionOrder_008.phpt14
-rw-r--r--tests/lang/foreachLoop.016.phpt10
-rw-r--r--tests/lang/short_tags.004.phpt10
-rw-r--r--tests/output/bug46897.phpt4
-rw-r--r--tests/output/bug60282.phpt12
-rw-r--r--tests/output/bug60321.phpt9
-rw-r--r--tests/output/bug60322.phpt8
-rw-r--r--tests/output/bug60768.phpt25
-rw-r--r--tests/output/ob_013.phpt72
-rw-r--r--tests/output/ob_017.phpt12
-rw-r--r--tests/output/ob_get_clean_basic_001.phpt2
-rw-r--r--tests/output/ob_get_status.phpt23
-rw-r--r--tests/output/ob_start_basic_004.phpt18
-rw-r--r--tests/output/ob_start_basic_005.phpt4
-rw-r--r--tests/output/ob_start_basic_006.phpt51
-rw-r--r--tests/output/ob_start_basic_unerasable_002.phpt8
-rw-r--r--tests/output/ob_start_basic_unerasable_003.phpt9
-rw-r--r--tests/output/ob_start_basic_unerasable_004.phpt9
-rw-r--r--tests/output/ob_start_basic_unerasable_005.phpt4
-rw-r--r--tests/output/ob_start_error_001.phpt11
-rw-r--r--tests/output/ob_start_error_002.phpt17
-rw-r--r--tests/output/ob_start_error_003.phpt6
-rw-r--r--tests/output/ob_start_error_004.phpt6
-rw-r--r--tests/security/magic_quotes_gpc.phpt13
-rw-r--r--tests/security/open_basedir_linkinfo.phpt11
-rw-r--r--tests/security/open_basedir_readlink.phpt8
-rw-r--r--tests/strings/004.phpt1
-rw-r--r--tests/strings/bug26703.phpt1
-rw-r--r--tests/strings/offsets_chaining_1.phpt3
-rw-r--r--tests/strings/offsets_chaining_2.phpt3
-rw-r--r--tests/strings/offsets_chaining_3.phpt3
-rw-r--r--tests/strings/offsets_chaining_4.phpt3
-rw-r--r--tests/strings/offsets_chaining_5.phpt8
-rw-r--r--tests/strings/offsets_general.phpt11
-rw-r--r--win32/build/Makefile20
-rw-r--r--win32/build/config.w3244
-rw-r--r--win32/build/config.w32.h.in2
-rw-r--r--win32/build/config.w32.phpize.in7
-rw-r--r--win32/build/confutils.js16
-rw-r--r--win32/build/libs_version.txt3
-rw-r--r--win32/install.txt12
-rw-r--r--win32/php5dll.dsp4
-rw-r--r--win32/php5dllts.dsp4
-rw-r--r--win32/syslog.reg4
-rw-r--r--win32/winutil.c2
-rw-r--r--win32/winutil.h4
2254 files changed, 147130 insertions, 99581 deletions
diff --git a/.gdbinit b/.gdbinit
index 2445825455..e7a565dfa9 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -1,6 +1,19 @@
+define set_ts
+ set $tsrm_ls = $arg0
+end
+
+document set_ts
+ set the ts resource, it is impossible for gdb to
+ call ts_resource_ex while no process is running,
+ but we could get the resource from the argument
+ of frame info.
+end
+
define ____executor_globals
if basic_functions_module.zts
- set $tsrm_ls = ts_resource_ex(0, 0)
+ if !$tsrm_ls
+ set $tsrm_ls = ts_resource_ex(0, 0)
+ end
set $eg = ((zend_executor_globals*) (*((void ***) $tsrm_ls))[executor_globals_id-1])
set $cg = ((zend_compiler_globals*) (*((void ***) $tsrm_ls))[compiler_globals_id-1])
else
@@ -37,9 +50,101 @@ end
define dump_bt
set $t = $arg0
while $t
- printf "[0x%08x] ", $t
- if $t->function_state.function->common.function_name
- printf "%s() ", $t->function_state.function->common.function_name
+ printf "[%p] ", $t
+ set $fst = $t->function_state
+ if $fst.function->common.function_name
+ if $fst.arguments
+ set $count = (int)*($fst.arguments)
+
+ if $t->object
+ if $fst.function.common.scope
+ printf "%s->", $fst.function.common.scope->name
+ else
+ if !$eg
+ ____executor_globals
+ end
+
+ set $known_class = 0
+ if $eg
+ set $handle = $t->object.value.obj.handle
+ set $handlers = $t->object.value.obj.handlers
+ set $zobj = (zend_object *)$eg.objects_store.object_buckets[$handle].bucket.obj.object
+
+ if $handlers->get_class_entry == &zend_std_object_get_class
+ set $known_class = 1
+
+ if $handlers.get_class_name
+ if $handlers.get_class_name != &zend_std_object_get_class_name
+ set $known_class = 0
+ end
+ end
+
+ if $known_class
+ printf "%s->", $zobj->ce.name
+ end
+ end
+ end
+
+ if !$known_class
+ printf "(Unknown)->"
+ end
+ end
+ else
+ if $fst.function.common.scope
+ printf "%s::", $fst.function.common.scope->name
+ end
+ end
+
+ printf "%s(", $fst.function->common.function_name
+ while $count > 0
+ set $zvalue = *(zval **)($fst.arguments - $count)
+ set $type = $zvalue->type
+ if $type == 0
+ printf "NULL"
+ end
+ if $type == 1
+ printf "%ld", $zvalue->value.lval
+ end
+ if $type == 2
+ printf "%lf", $zvalue->value.dval
+ end
+ if $type == 3
+ if $zvalue->value.lval
+ printf "true"
+ else
+ printf "false"
+ end
+ end
+ if $type == 4
+ printf "array(%d)[%p]", $zvalue->value.ht->nNumOfElements, $zvalue
+ end
+ if $type == 5
+ printf "object[%p]", $zvalue
+ end
+ if $type == 6
+ ____print_str $zvalue->value.str.val $zvalue->value.str.len
+ end
+ if $type == 7
+ printf "resource(#%d)", $zvalue->value.lval
+ end
+ if $type == 8
+ printf "constant"
+ end
+ if $type == 9
+ printf "const_array"
+ end
+ if $type > 9
+ printf "unknown type %d", $type
+ end
+ set $count = $count -1
+ if $count > 0
+ printf ", "
+ end
+ end
+ printf ") "
+ else
+ printf "%s() ", $fst.function->common.function_name
+ end
else
printf "??? "
end
@@ -167,7 +272,7 @@ define ____printzv
____executor_globals
set $zvalue = $arg0
- printf "[0x%08x] ", $zvalue
+ printf "[%p] ", $zvalue
if $zvalue == $eg.uninitialized_zval_ptr
printf "*uninitialized* "
@@ -208,7 +313,7 @@ end
define print_const_table
set $ind = 1
- printf "[0x%08x] {\n", $arg0
+ printf "[%p] {\n", $arg0
____print_const_table $arg0
printf "}\n"
end
@@ -248,7 +353,7 @@ end
define print_ht
set $ind = 1
- printf "[0x%08x] {\n", $arg0
+ printf "[%p] {\n", $arg0
____print_ht $arg0 1
printf "}\n"
end
@@ -259,7 +364,7 @@ end
define print_htptr
set $ind = 1
- printf "[0x%08x] {\n", $arg0
+ printf "[%p] {\n", $arg0
____print_ht $arg0 0
printf "}\n"
end
@@ -270,7 +375,7 @@ end
define print_htstr
set $ind = 1
- printf "[0x%08x] {\n", $arg0
+ printf "[%p] {\n", $arg0
____print_ht $arg0 2
printf "}\n"
end
@@ -306,7 +411,7 @@ end
define print_ft
set $ind = 1
- printf "[0x%08x] {\n", $arg0
+ printf "[%p] {\n", $arg0
____print_ft $arg0
printf "}\n"
end
@@ -383,7 +488,7 @@ end
define print_pi
set $pi = $arg0
- printf "[0x%08x] {\n", $pi
+ printf "[%p] {\n", $pi
printf " h = %lu\n", $pi->h
printf " flags = %d (", $pi->flags
if $pi->flags & 0x100
@@ -439,7 +544,7 @@ define printzn
set $optype = "IS_UNUSED"
end
- printf "[0x%08x] %s", $znode, $optype
+ printf "[%p] %s", $znode, $optype
if $znode->op_type == 1
printf ": "
@@ -519,7 +624,7 @@ define zmemcheck
else
set $filename = $filename + 1
end
- printf " 0x%08x ", $aptr
+ printf " %p ", $aptr
if $p->size == sizeof(struct _zval_struct) && ((struct _zval_struct *)$aptr)->type >= 0 && ((struct _zval_struct *)$aptr)->type < 10
printf "ZVAL?(%-2d) ", $p->size
else
@@ -549,7 +654,7 @@ define zmemcheck
end
end
if $not_found
- printf "no such block that begins at 0x%08x.\n", $aptr
+ printf "no such block that begins at %p.\n", $aptr
end
if $arg0 == 0
printf "-------------------------------------------------------------------------------\n"
diff --git a/.gitattributes b/.gitattributes
index 862575bbb8..9ed6e5f4b9 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -23,152 +23,153 @@ sapi/continuity/capi.c ident
Zend/RFCs/002.txt ident
Zend/RFCs/003.txt ident
NEWS merge=NEWS
-/ext/bz2/tests/005.phpt -crlf
-/ext/dom/tests/dom005.phpt -crlf
-/ext/dom/tests/DOMImplementation_createDocumentType_basic.phpt -crlf
-/ext/ereg/tests/009.phpt -crlf
-/ext/iconv/tests/eucjp2sjis.phpt -crlf
-/ext/iconv/tests/eucjp2utf8.phpt -crlf
-/ext/iconv/tests/iconv_stream_filter_delimiter.phpt -crlf
-/ext/iconv/tests/iconv_stream_filter.phpt -crlf
-/ext/mbstring/tests/mb_split-compat-01.phpt -crlf
-/ext/phar/tests/005.phpt -crlf
-/ext/phar/tests/phar_commitwrite.phpt -crlf
-/ext/phar/tests/phar_create_in_cwd.phpt -crlf
-/ext/phar/tests/phar_mount.phpt -crlf
-/ext/reflection/tests/009.phpt -crlf
-/ext/reflection/tests/025.phpt -crlf
-/ext/standard/tests/general_functions/highlight_heredoc.phpt -crlf
-/ext/standard/tests/general_functions/parse_ini_file.phpt -crlf
-/ext/standard/tests/general_functions/parse_ini_string_002.phpt -crlf
-/ext/standard/tests/strings/006.phpt -crlf
-/ext/standard/tests/strings/addslashes_variation2.phpt -crlf
-/ext/standard/tests/strings/addslashes_variation3.phpt -crlf
-/ext/standard/tests/strings/bug21453.phpt -crlf
-/ext/standard/tests/strings/chop_variation3.phpt -crlf
-/ext/standard/tests/strings/chunk_split_variation11.phpt -crlf
-/ext/standard/tests/strings/chunk_split_variation12.phpt -crlf
-/ext/standard/tests/strings/chunk_split_variation4.phpt -crlf
-/ext/standard/tests/strings/crc32_variation2.phpt -crlf
-/ext/standard/tests/strings/crc32_variation3.phpt -crlf
-/ext/standard/tests/strings/crc32_variation4.phpt -crlf
+/ext/bz2/tests/with_strings.phpt -crlf
+/ext/dom/tests/bug40836.phpt -crlf
+/ext/dom/tests/domelement.phpt -crlf
+/ext/ereg/tests/eregi_basic_002.phpt -crlf
+/ext/iconv/tests/iconv004.phpt -crlf
+/ext/iconv/tests/iconv_basic.phpt -crlf
+/ext/iconv/tests/iconv_strpos.phpt -crlf
+/ext/iconv/tests/iconv_strpos_variation2.phpt -crlf
+/ext/mbstring/tests/mb_strtoupper_error2.phpt -crlf
+/ext/phar/tests/delete_in_phar_confirm.phpt -crlf
+/ext/phar/tests/frontcontroller12.phpt -crlf
+/ext/phar/tests/security.phpt -crlf
+/ext/phar/tests/test_signaturealgos.phpt -crlf
+/ext/reflection/tests/ReflectionMethod_invokeArgs_basic.phpt -crlf
+/ext/reflection/tests/ReflectionProperty_getModifiers_basic.phpt -crlf
+/ext/spl/tests/dllist_007.phpt -crlf
+/ext/spl/tests/iterator_012.phpt -crlf
+/ext/spl/tests/SplArray_fromArray.phpt -crlf
+/ext/standard/tests/dir/scandir_variation3.phpt -crlf
+/ext/standard/tests/general_functions/escapeshellcmd-win32.phpt -crlf
+/ext/standard/tests/general_functions/set_magic_quotes_runtime_error.phpt -crlf
+/ext/standard/tests/strings/bug26817.phpt -crlf
+/ext/standard/tests/strings/bug26973.phpt -crlf
+/ext/standard/tests/strings/bug27457.phpt -crlf
+/ext/standard/tests/strings/bug28386.phpt -crlf
+/ext/standard/tests/strings/bug37262.phpt -crlf
+/ext/standard/tests/strings/bug40637.phpt -crlf
+/ext/standard/tests/strings/bug40915.phpt -crlf
+/ext/standard/tests/strings/bug61374.phpt -crlf
+/ext/standard/tests/strings/chop_error.phpt -crlf
+/ext/standard/tests/strings/chop_variation2.phpt -crlf
+/ext/standard/tests/strings/chunk_split_variation10.phpt -crlf
+/ext/standard/tests/strings/chunk_split_variation8.phpt -crlf
+/ext/standard/tests/strings/count_chars_variation2.phpt -crlf
+/ext/standard/tests/strings/dirname_error.phpt -crlf
+/ext/standard/tests/strings/fprintf_variation_007_64bit.phpt -crlf
/ext/standard/tests/strings/highlight_file.phpt -crlf
-/ext/standard/tests/strings/htmlentities_html4.phpt -crlf
-/ext/standard/tests/strings/lcfirst.phpt -crlf
-/ext/standard/tests/strings/ltrim.phpt -crlf
-/ext/standard/tests/strings/nl2br_variation2.phpt -crlf
-/ext/standard/tests/strings/php_strip_whitespace.phpt -crlf
+/ext/standard/tests/strings/htmlentities03.phpt -crlf
+/ext/standard/tests/strings/htmlentities04.phpt -crlf
+/ext/standard/tests/strings/htmlentities08.phpt -crlf
+/ext/standard/tests/strings/htmlentities15.phpt -crlf
+/ext/standard/tests/strings/http_build_query.phpt -crlf
+/ext/standard/tests/strings/metaphone.phpt -crlf
+/ext/standard/tests/strings/ord_error.phpt -crlf
+/ext/standard/tests/strings/printf_basic2.phpt -crlf
+/ext/standard/tests/strings/printf_variation2.phpt -crlf
+/ext/standard/tests/strings/quoted_printable_decode_basic.phpt -crlf
/ext/standard/tests/strings/rtrim.phpt -crlf
-/ext/standard/tests/strings/sprintf_f_2.phpt -crlf
-/ext/standard/tests/strings/sprintf_variation15.phpt -crlf
-/ext/standard/tests/strings/strcspn_variation6.phpt -crlf
-/ext/standard/tests/strings/strcspn_variation7.phpt -crlf
-/ext/standard/tests/strings/strcspn_variation8.phpt -crlf
-/ext/standard/tests/strings/stripos_variation1.phpt -crlf
-/ext/standard/tests/strings/stripos_variation3.phpt -crlf
-/ext/standard/tests/strings/stripos_variation4.phpt -crlf
-/ext/standard/tests/strings/stripos_variation5.phpt -crlf
-/ext/standard/tests/strings/stripos_variation6.phpt -crlf
+/ext/standard/tests/strings/setlocale_variation1.phpt -crlf
+/ext/standard/tests/strings/sha1_basic.phpt -crlf
+/ext/standard/tests/strings/similar_text_basic.phpt -crlf
+/ext/standard/tests/strings/soundex.phpt -crlf
+/ext/standard/tests/strings/sprintf_basic1.phpt -crlf
+/ext/standard/tests/strings/sprintf_basic4.phpt -crlf
+/ext/standard/tests/strings/sprintf_basic7.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation12.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation28.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation29.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation30.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation31.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation38.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation42.phpt -crlf
+/ext/standard/tests/strings/sprintf_variation6.phpt -crlf
+/ext/standard/tests/strings/sscanf_basic2.phpt -crlf
+/ext/standard/tests/strings/sscanf_basic3.phpt -crlf
+/ext/standard/tests/strings/str_getcsv_001.phpt -crlf
+/ext/standard/tests/strings/stripcslashes_basic.phpt -crlf
+/ext/standard/tests/strings/stripos_variation11.phpt -crlf
+/ext/standard/tests/strings/stripos_variation13.phpt -crlf
+/ext/standard/tests/strings/stripslashes_variation1.phpt -crlf
/ext/standard/tests/strings/stripslashes_variation2.phpt -crlf
-/ext/standard/tests/strings/stripslashes_variation3.phpt -crlf
-/ext/standard/tests/strings/stripslashes_variation4.phpt -crlf
-/ext/standard/tests/strings/stripslashes_variation5.phpt -crlf
-/ext/standard/tests/strings/str_ireplace.phpt -crlf
-/ext/standard/tests/strings/strnatcmp_basic.phpt -crlf
-/ext/standard/tests/strings/strncasecmp_variation9.phpt -crlf
-/ext/standard/tests/strings/strpos.phpt -crlf
-/ext/standard/tests/strings/strrchr_variation1.phpt -crlf
-/ext/standard/tests/strings/strrchr_variation2.phpt -crlf
-/ext/standard/tests/strings/strrchr_variation3.phpt -crlf
-/ext/standard/tests/strings/strrchr_variation4.phpt -crlf
-/ext/standard/tests/strings/strrchr_variation6.phpt -crlf
-/ext/standard/tests/strings/strrchr_variation7.phpt -crlf
-/ext/standard/tests/strings/str_replace.phpt -crlf
-/ext/standard/tests/strings/strrev_variation3.phpt -crlf
-/ext/standard/tests/strings/strrev_variation4.phpt -crlf
-/ext/standard/tests/strings/strripos_variation1.phpt -crlf
-/ext/standard/tests/strings/strripos_variation2.phpt -crlf
-/ext/standard/tests/strings/strripos_variation3.phpt -crlf
-/ext/standard/tests/strings/strripos_variation4.phpt -crlf
-/ext/standard/tests/strings/strripos_variation5.phpt -crlf
-/ext/standard/tests/strings/strrpos_variation1.phpt -crlf
-/ext/standard/tests/strings/strrpos_variation2.phpt -crlf
-/ext/standard/tests/strings/strrpos_variation3.phpt -crlf
+/ext/standard/tests/strings/stristr_error.phpt -crlf
+/ext/standard/tests/strings/strnatcasecmp_basic.phpt -crlf
+/ext/standard/tests/strings/strncasecmp_variation6.phpt -crlf
+/ext/standard/tests/strings/strncasecmp_variation7.phpt -crlf
+/ext/standard/tests/strings/strncasecmp_variation8.phpt -crlf
+/ext/standard/tests/strings/strrchr_error.phpt -crlf
+/ext/standard/tests/strings/strrchr.phpt -crlf
+/ext/standard/tests/strings/strrchr_variation11.phpt -crlf
+/ext/standard/tests/strings/strrpos_error.phpt -crlf
/ext/standard/tests/strings/strrpos_variation4.phpt -crlf
-/ext/standard/tests/strings/strrpos_variation5.phpt -crlf
-/ext/standard/tests/strings/strrpos_variation6.phpt -crlf
-/ext/standard/tests/strings/strspn_variation5.phpt -crlf
-/ext/standard/tests/strings/strspn_variation6.phpt -crlf
-/ext/standard/tests/strings/strspn_variation7.phpt -crlf
-/ext/standard/tests/strings/strspn_variation8.phpt -crlf
-/ext/standard/tests/strings/strstr.phpt -crlf
-/ext/standard/tests/strings/strtok_variation1.phpt -crlf
-/ext/standard/tests/strings/strtok_variation3.phpt -crlf
-/ext/standard/tests/strings/strtr_variation1.phpt -crlf
-/ext/standard/tests/strings/strtr_variation2.phpt -crlf
-/ext/standard/tests/strings/str_word_count.phpt -crlf
-/ext/standard/tests/strings/trim1.phpt -crlf
-/ext/standard/tests/strings/ucfirst.phpt -crlf
-/ext/standard/tests/strings/vfprintf_variation10.phpt -crlf
+/ext/standard/tests/strings/strrpos_variation8.phpt -crlf
+/ext/standard/tests/strings/strstr2.phpt -crlf
+/ext/standard/tests/strings/strtok_error.phpt -crlf
+/ext/standard/tests/strings/strtok_variation2.phpt -crlf
+/ext/standard/tests/strings/strtolower-win32.phpt -crlf
+/ext/standard/tests/strings/substr_compare.phpt -crlf
+/ext/standard/tests/strings/ucwords_variation1.phpt -crlf
+/ext/standard/tests/strings/unpack.phpt -crlf
+/ext/standard/tests/strings/vfprintf_basic7_64bit.phpt -crlf
+/ext/standard/tests/strings/vfprintf_variation11_64bit.phpt -crlf
+/ext/standard/tests/strings/vfprintf_variation12_64bit.phpt -crlf
/ext/standard/tests/strings/vfprintf_variation12.phpt -crlf
-/ext/standard/tests/strings/vfprintf_variation16.phpt -crlf
-/ext/standard/tests/strings/vfprintf_variation18.phpt -crlf
-/ext/standard/tests/strings/vfprintf_variation4.phpt -crlf
-/ext/standard/tests/strings/vfprintf_variation6.phpt -crlf
+/ext/standard/tests/strings/vfprintf_variation13_64bit.phpt -crlf
/ext/standard/tests/strings/vfprintf_variation7.phpt -crlf
-/ext/standard/tests/strings/vfprintf_variation8.phpt -crlf
+/ext/standard/tests/strings/vprintf_basic2.phpt -crlf
+/ext/standard/tests/strings/vprintf_basic7_64bit.phpt -crlf
/ext/standard/tests/strings/vprintf_variation10.phpt -crlf
-/ext/standard/tests/strings/vprintf_variation12.phpt -crlf
-/ext/standard/tests/strings/vprintf_variation14.phpt -crlf
-/ext/standard/tests/strings/vprintf_variation18.phpt -crlf
+/ext/standard/tests/strings/vprintf_variation14_64bit.phpt -crlf
+/ext/standard/tests/strings/vprintf_variation17.phpt -crlf
/ext/standard/tests/strings/vprintf_variation4.phpt -crlf
-/ext/standard/tests/strings/vprintf_variation6.phpt -crlf
-/ext/standard/tests/strings/vprintf_variation7.phpt -crlf
-/ext/standard/tests/strings/vprintf_variation8.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation10.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation12.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation14.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation16.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation4.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation6.phpt -crlf
+/ext/standard/tests/strings/vsprintf_basic4.phpt -crlf
+/ext/standard/tests/strings/vsprintf_basic8.phpt -crlf
+/ext/standard/tests/strings/vsprintf_variation12_64bit.phpt -crlf
+/ext/standard/tests/strings/vsprintf_variation13_64bit.phpt -crlf
+/ext/standard/tests/strings/vsprintf_variation15_64bit.phpt -crlf
+/ext/standard/tests/strings/vsprintf_variation17.phpt -crlf
+/ext/standard/tests/strings/vsprintf_variation4_64bit.phpt -crlf
/ext/standard/tests/strings/vsprintf_variation7.phpt -crlf
-/ext/standard/tests/strings/vsprintf_variation8.phpt -crlf
/ext/standard/tests/strings/wordwrap.phpt -crlf
-/ext/tidy/tests/010.phpt -crlf
-/ext/tidy/tests/012.phpt -crlf
-/ext/tidy/tests/025.phpt -crlf
-/ext/tidy/tests/030.phpt -crlf
+/ext/standard/tests/strings/wordwrap_variation5.phpt -crlf
+/ext/standard/tests/url/rawurldecode_variation_001.phpt -crlf
+/ext/tidy/tests/009.phpt -crlf
+/ext/tidy/tests/013.phpt -crlf
+/ext/tidy/tests/021.phpt -crlf
+/ext/tidy/tests/tidy_error.phpt -crlf
+/ext/tokenizer/tests/002.phpt -crlf
/ext/tokenizer/tests/bug26463.phpt -crlf
+/ext/tokenizer/tests/token_get_all_error.phpt -crlf
+/ext/tokenizer/tests/token_get_all_variation11.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation12.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation13.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation14.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation15.phpt -crlf
-/ext/tokenizer/tests/token_get_all_variation16.phpt -crlf
-/ext/tokenizer/tests/token_get_all_variation17.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation18.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation19.phpt -crlf
-/ext/tokenizer/tests/token_get_all_variation4.phpt -crlf
+/ext/tokenizer/tests/token_get_all_variation1.phpt -crlf
+/ext/tokenizer/tests/token_get_all_variation2.phpt -crlf
+/ext/tokenizer/tests/token_get_all_variation3.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation5.phpt -crlf
-/ext/tokenizer/tests/token_get_all_variation6.phpt -crlf
-/ext/tokenizer/tests/token_get_all_variation7.phpt -crlf
/ext/tokenizer/tests/token_get_all_variation8.phpt -crlf
-/ext/tokenizer/tests/token_get_all_variation9.phpt -crlf
-/ext/xml/tests/bug26614_libxml.phpt -crlf
-/ext/xmlwriter/tests/004.phpt -crlf
-/ext/xmlwriter/tests/OO_004.phpt -crlf
-/ext/zlib/tests/005.phpt -crlf
-/ext/zlib/tests/gzfile_basic2.phpt -crlf
-/ext/zlib/tests/gzfile_basic.phpt -crlf
-/ext/zlib/tests/gzfilegzreadfile.phpt -crlf
-/ext/zlib/tests/readgzfile_basic2.phpt -crlf
-/ext/zlib/tests/readgzfile_basic.phpt -crlf
-/sapi/cli/tests/014.phpt -crlf
-/tests/run-test/test010.phpt -crlf
-/Zend/tests/bug35655.phpt -crlf
-/Zend/tests/bug48930.phpt -crlf
-/Zend/tests/bug61095.phpt -crlf
-/Zend/tests/heredoc_017.phpt -crlf
-/Zend/tests/heredoc_018.phpt -crlf
-/Zend/tests/nowdoc_013.phpt -crlf
-/Zend/tests/nowdoc_014.phpt -crlf
-/Zend/tests/nowdoc_015.phpt -crlf
+/ext/xml/tests/bug32001b.phpt -crlf
+/ext/xmlwriter/tests/OO_003.phpt -crlf
+/ext/xmlwriter/tests/xmlwriter_write_attribute_ns_error_001.phpt -crlf
+/ext/zlib/tests/008.phpt -crlf
+/ext/zlib/tests/gzopen_variation4.phpt -crlf
+/ext/zlib/tests/gzrewind_error.phpt -crlf
+/ext/zlib/tests/readgzfile_variation7.phpt -crlf
+/ext/zlib/tests/readgzfile_variation8.phpt -crlf
+/ext/zlib/tests/zlib_scheme_stat_basic.phpt -crlf
+/sapi/cli/tests/006.phpt -crlf
+/tests/run-test/test009.phpt -crlf
+/Zend/tests/012.phpt -crlf
+/Zend/tests/bug28072.phpt -crlf
+/Zend/tests/bug38624.phpt -crlf
+/Zend/tests/bug40784.phpt -crlf
+/Zend/tests/bug43053.phpt -crlf
+/Zend/tests/bug51176.phpt -crlf
+/Zend/tests/each_003.phpt -crlf
+/Zend/tests/errmsg_006.phpt -crlf
diff --git a/EXTENSIONS b/EXTENSIONS
index 2fa80523f7..5308582023 100644
--- a/EXTENSIONS
+++ b/EXTENSIONS
@@ -497,8 +497,8 @@ STATUS: Working
SINCE: 4.0.3
-------------------------------------------------------------------------------
EXTENSION: snmp
-PRIMARY MAINTAINER: Rasmus Lerdorf <rasmus@php.net>, Pierre-Alain Joye <pajoye@php.net>
-MAINTENANCE: Odd Fixes
+PRIMARY MAINTAINER: Boris Lytochkin <lytboris@php.net>, Rasmus Lerdorf <rasmus@php.net>, Pierre-Alain Joye <pajoye@php.net>
+MAINTENANCE: Maintained
STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: sockets
diff --git a/Makefile.global b/Makefile.global
index 8dad0e4bf1..b30c318fc4 100644
--- a/Makefile.global
+++ b/Makefile.global
@@ -13,6 +13,8 @@ all: $(all_targets)
build-modules: $(PHP_MODULES) $(PHP_ZEND_EX)
+build-binaries: $(PHP_BINARIES)
+
libphp$(PHP_MAJOR_VERSION).la: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@
-@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1
@@ -35,6 +37,8 @@ install-sapi: $(OVERALL_TARGET)
fi
@$(INSTALL_IT)
+install-binaries: build-binaries $(install_binary_targets)
+
install-modules: build-modules
@test -d modules && \
$(mkinstalldirs) $(INSTALL_ROOT)$(EXTENSION_DIR)
@@ -79,7 +83,7 @@ PHP_TEST_SHARED_EXTENSIONS = ` \
. $$i; $(top_srcdir)/build/shtool echo -n -- " -d $(ZEND_EXT_TYPE)=$(top_builddir)/modules/$$dlname"; \
done; \
fi`
-PHP_DEPRECATED_DIRECTIVES_REGEX = '^(define_syslog_variables|register_(globals|long_arrays)?|safe_mode|magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?)[\t\ ]*='
+PHP_DEPRECATED_DIRECTIVES_REGEX = '^(magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?)[\t\ ]*='
test: all
-@if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \
diff --git a/NEWS b/NEWS
index ba969501ec..74dab3cbfb 100644
--- a/NEWS
+++ b/NEWS
@@ -1,54 +1,83 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-?? ??? 2012, PHP 5.3.19
+?? ??? 2012, PHP 5.4.9
+
+- Core:
+ . Fixed bug #63305 (zend_mm_heap corrupted with traits). (Dmitry, Laruence)
+ . Fixed bug #63369 ((un)serialize() leaves dangling pointers, causes crashes).
+ (Tony, Andrew Sitnikov)
+
+- Curl:
+ . Fixed bug #63363 (Curl silently accepts boolean true for SSL_VERIFYHOST).
+ Patch by John Jawed GitHub PR #221 (Anthony)
+
+- Fileinfo:
+ . Fixed bug #63248 (Load multiple magic files from a directory under Windows).
+ (Anatoliy)
- Libxml
. Fixed bug #63389 (Missing context check on libxml_set_streams_context()
causes memleak). (Laruence)
-- MySQL:
- . Fixed compilation failure on mixed 32/64 bit systems. (Andrey)
-
- OCI8:
. Fixed bug #63265 (Add ORA-00028 to the PHP_OCI_HANDLE_ERROR macro)
(Chris Jones)
- PCRE:
+ . Fixed bug #63180 (Corruption of hash tables). (Dmitry)
. Fixed bug #63055 (Segfault in zend_gc with SF2 testsuite).
(Dmitry, Laruence)
. Fixed bug #63284 (Upgrade PCRE to 8.31). (Anatoliy)
-- PDO:
- . Fixed bug #63235 (buffer overflow in use of SQLGetDiagRec).
- (Martin Osvald, Remi)
-
-- Streams:
- . Fixed bug #63240 (stream_get_line() return contains delimiter string).
- (Tjerk, Gustavo)
-
- Phar:
. Fixed bug #63297 (Phar fails to write an openssl based signature).
(Anatoliy)
-18 Oct 2012, PHP 5.3.18
+18 Oct 2012, PHP 5.4.8
+
+- CLI server:
+ . Implemented FR #63242 (Default error page in PHP built-in web server uses
+ outdated html/css). (pascal.chevrel@free.fr)
+ . Changed response to unknown HTTP method to 501 according to RFC.
+ (Niklas Lindgren).
+ . Support HTTP PATCH method. Patch by Niklas Lindgren, GitHub PR #190.
+ (Lars)
- Core:
+ . Fixed bug #63219 (Segfault when aliasing trait method when autoloader
+ throws excpetion). (Laruence)
+ . Added optional second argument for assert() to specify custom message. Patch
+ by Lonny Kapelushnik (lonny@lonnylot.com). (Lars)
+ . Support building PHP with the native client toolchain. (Stuart Langley)
+ . Added --offline option for tests. (Remi)
+ . Fixed bug #63162 (parse_url does not match password component). (husman)
. Fixed bug #63111 (is_callable() lies for abstract static method). (Dmitry)
. Fixed bug #63093 (Segfault while load extension failed in zts-build).
(Laruence)
. Fixed bug #62976 (Notice: could not be converted to int when comparing
some builtin classes). (Laruence)
+ . Fixed bug #62955 (Only one directive is loaded from "Per Directory Values"
+ Windows registry). (aserbulov at parallels dot com)
+ . Fixed bug #62907 (Double free when use traits). (Dmitry)
. Fixed bug #61767 (Shutdown functions not called in certain error
situation). (Dmitry)
- . Fixed bug #61442 (exception threw in __autoload can not be catched).
- (Laruence)
. Fixed bug #60909 (custom error handler throwing Exception + fatal error
= no shutdown function). (Dmitry)
+ . Fixed bug #60723 (error_log error time has changed to UTC ignoring default
+ timezone). (Laruence)
- cURL:
. Fixed bug #62085 (file_get_contents a remote file by Curl wrapper will
cause cpu Soaring). (Pierrick)
+- Date:
+ . Fixed bug #62896 ("DateTime->modify('+0 days')" modifies DateTime object)
+ (Lonny Kapelushnik)
+ . Fixed bug #62561 (DateTime add 'P1D' adds 25 hours). (Lonny Kapelushnik)
+
+- DOM:
+ . Fixed bug #63015 (Incorrect arginfo for DOMErrorHandler). (Rob)
+
- FPM:
. Fixed bug #62954 (startup problems fpm / php-fpm). (fat)
. Fixed bug #62886 (PHP-FPM may segfault/hang on startup). (fat)
@@ -57,12 +86,23 @@ PHP NEWS
. Fixed bug #62887 (Only /status?plain&full gives "last request cpu"). (fat)
. Fixed bug #62216 (Add PID to php-fpm init.d script). (fat)
-- Intl:
- . Fix bug #62915 (defective cloning in several intl classes). (Gustavo)
-
- OCI8:
. Fixed bug #60901 (Improve "tail" syntax for AIX installation) (Chris Jones)
+- OpenSSL:
+ . Implemented FR #61421 (OpenSSL signature verification missing RMD160,
+ SHA224, SHA256, SHA384, SHA512). (Mark Jones)
+
+- PDO:
+ . Fixed bug #63258 (seg fault with PDO and dblib using DBSETOPT(H->link,
+ DBQUOTEDIDENT, 1)). (Laruence)
+ . Fixed bug #63235 (buffer overflow in use of SQLGetDiagRec).
+ (Martin Osvald, Remi)
+
+- PDO Firebird:
+ . Fixed bug #63214 (Large PDO Firebird Queries).
+ (james at kenjim dot com)
+
- SOAP
. Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).
(Dmitry)
@@ -71,49 +111,101 @@ PHP NEWS
. Bug #62987 (Assigning to ArrayObject[null][something] overrides all
undefined variables). (Laruence)
-13 Sep 2012, PHP 5.3.17
+- mbstring:
+ . Allow passing null as a default value to mb_substr() and mb_strcut(). Patch
+ by Alexander Moskaliov via GitHub PR #133. (Lars)
+
+- Filter extension:
+ . Bug #49510: Boolean validation fails with FILTER_NULL_ON_FAILURE with empty
+ string or false. (Lars)
+
+- Sockets
+ . Fixed bug #63000 (MCAST_JOIN_GROUP on OSX is broken, merge of PR 185 by
+ Igor Wiedler). (Lars)
+
+13 Sep 2012, PHP 5.4.7
- Core:
. Fixed bug (segfault while build with zts and GOTO vm-kind). (Laruence)
- . Fixed bug #62955 (Only one directive is loaded from "Per Directory Values"
- Windows registry). (aserbulov at parallels dot com)
- . Fixed bug #62763 (register_shutdown_function and extending class).
+ . Fixed bug #62844 (parse_url() does not recognize //). (Andrew Faulds).
+ . Fixed bug #62829 (stdint.h included on platform where HAVE_STDINT_H is not
+ set). (Felipe)
+ . Fixed bug #62763 (register_shutdown_function and extending class).
(Laruence)
+ . Fixed bug #62725 (Calling exit() in a shutdown function does not return
+ the exit value). (Laruence)
. Fixed bug #62744 (dangling pointers made by zend_disable_class). (Laruence)
- . Fixed bug #62716 (munmap() is called with the incorrect length).
+ . Fixed bug #62716 (munmap() is called with the incorrect length).
(slangley@google.com)
- . Fixed bug ##62460 (php binaries installed as binary.dSYM). (Reeze Xia)
+ . Fixed bug #62358 (Segfault when using traits a lot). (Laruence)
+ . Fixed bug #62328 (implementing __toString and a cast to string fails)
+ (Laruence)
+ . Fixed bug #51363 (Fatal error raised by var_export() not caught by error
+ handler). (Lonny Kapelushnik)
+ . Fixed bug #40459 (Stat and Dir stream wrapper methods do not call
+ constructor). (Stas)
- CURL:
+ . Fixed bug #62912 (CURLINFO_PRIMARY_* AND CURLINFO_LOCAL_* not exposed).
+ (Pierrick)
. Fixed bug #62839 (curl_copy_handle segfault with CURLOPT_FILE). (Pierrick)
- . Fixed bug #62499 (curl_setopt($ch, CURLOPT_COOKIEFILE, "") returns false).
- (r.hampartsumyan@gmail.com, Laruence)
-
- - DateTime:
- . Fixed bug #62852 (Unserialize invalid DateTime causes crash).
- (reeze.xia@gmail.com)
- . Fixed bug #62500 (Segfault in DateInterval class when extended). (Laruence)
-- MySQLnd:
- . Fixed bug #62885 (mysqli_poll - Segmentation fault). (Laruence)
+- Intl:
+ . Fixed Spoofchecker not being registered on ICU 49.1. (Gustavo)
+ . Fix bug #62933 (ext/intl compilation error on icu 3.4.1). (Gustavo)
+ . Fix bug #62915 (defective cloning in several intl classes). (Gustavo)
+
+- Installation:
+ . Fixed bug #62460 (php binaries installed as binary.dSYM). (Reeze Xia)
+
+- PCRE:
+ . Fixed bug #55856 (preg_replace should fail on trailing garbage).
+ (reg dot php at alf dot nu)
- PDO:
. Fixed bug #62685 (Wrong return datatype in PDO::inTransaction()). (Laruence)
+- Reflection:
+ . Fixed bug #62892 (ReflectionClass::getTraitAliases crashes on importing
+ trait methods as private). (Felipe)
+ . Fixed bug #62715 (ReflectionParameter::isDefaultValueAvailable() wrong
+ result). (Laruence)
+
- Session:
. Fixed bug (segfault due to retval is not initialized). (Laruence)
+ . Fixed bug (segfault due to PS(mod_user_implemented) not be reseted
+ when close handler call exit). (Laruence)
+
+- SOAP
+ . Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).
+ (Dmitry)
- SPL:
. Fixed bug #62904 (Crash when cloning an object which inherits SplFixedArray)
(Laruence)
+ . Implemented FR #62840 (Add sort flag to ArrayObject::ksort). (Laruence)
+
+- Standard:
+ . Fixed bug #62836 (Seg fault or broken object references on unserialize()).
+ (Laruence)
+
+- FPM:
+ . Merged PR 121 by minitux to add support for slow request counting on PHP
+ FPM status page. (Lars)
-- Enchant:
- . Fixed bug #62838 (enchant_dict_quick_check() destroys zval, but fails to
- initialize it). (Tony, Mateusz Goik).
+16 Aug 2012, PHP 5.4.6
-16 Aug 2012, PHP 5.3.16
+- CLI Server:
+ . Implemented FR #62700 (have the console output 'Listening on
+ http://localhost:8000'). (pascal.chevrel@free.fr)
- Core:
+ . Fixed bug #62661 (Interactive php-cli crashes if include() is used in
+ auto_prepend_file). (Laruence)
+ . Fixed bug #62653: (unset($array[$float]) causes a crash). (Nikita Popov,
+ Laruence)
+ . Fixed bug #62565 (Crashes due non-initialized internal properties_table).
+ (Felipe)
. Fixed bug #60194 (--with-zend-multibyte and --enable-debug reports LEAK
with run-test.php). (Laruence)
@@ -123,53 +215,88 @@ PHP NEWS
- DateTime:
. Fixed Bug #62500 (Segfault in DateInterval class when extended). (Laruence)
+
+- Fileinfo:
+ . Fixed bug #61964 (finfo_open with directory causes invalid free).
+ (reeze.xia@gmail.com)
+
+- Intl:
+ . Fixed bug #62564 (Extending MessageFormatter and adding property causes
+ crash). (Felipe)
+
+- MySQLnd:
+ . Fixed bug #62594 (segfault in mysqlnd_res_meta::set_mode). (Laruence)
+
+- readline:
+ . Fixed bug #62612 (readline extension compilation fails with
+ sapi/cli/cli.h: No such file). (Johannes)
- Reflection:
- . Fixed bug #62715 (ReflectionParameter::isDefaultValueAvailable() wrong
- result). (Laruence)
+ . Implemented FR #61602 (Allow access to name of constant used as default
+ value). (reeze.xia@gmail.com)
+
+- SimpleXML:
+ . Implemented FR #55218 Get namespaces from current node. (Lonny)
- SPL:
. Fixed bug #62616 (ArrayIterator::count() from IteratorIterator instance
gives Segmentation fault). (Laruence, Gustavo)
+ . Fixed bug #61527 (ArrayIterator gives misleading notice on next() when
+ moved to the end). (reeze.xia@gmail.com)
+- Streams:
+ . Fixed bug #62597 (segfault in php_stream_wrapper_log_error with ZTS build).
+ (Laruence)
-19 Jul 2012, PHP 5.3.15
-
-- Zend Engine:
- . Fixed bug #51094 (parse_ini_file() with INI_SCANNER_RAW cuts a value that
- includes a semi-colon). (Pierrick)
+- Zlib:
+ . Fixed bug #55544 (ob_gzhandler always conflicts with
+ zlib.output_compression). (Laruence)
-- COM:
- . Fixed bug #62146 com_dotnet cannot be built shared. (Johannes)
+19 Jul 2012, PHP 5.4.5
- Core:
- . Fixed potential overflow in _php_stream_scandir, CVE-2012-2688. (Jason
- Powell, Stas)
- . Fixed bug #62432 (ReflectionMethod random corrupt memory on high
- concurrent). (Johannes)
. Fixed bug #62443 (Crypt SHA256/512 Segfaults With Malformed
Salt). (Anthony Ferrara)
+ . Fixed bug #62432 (ReflectionMethod random corrupt memory on high
+ concurrent). (Johannes)
+ . Fixed bug #62373 (serialize() generates wrong reference to the object).
+ (Moriyoshi)
+ . Fixed bug #62357 (compile failure: (S) Arguments missing for built-in
+ function __memcmp). (Laruence)
+ . Fixed bug #61998 (Using traits with method aliases appears to result in
+ crash during execution). (Dmitry)
+ . Fixed bug #51094 (parse_ini_file() with INI_SCANNER_RAW cuts a value that
+ includes a semi-colon). (Pierrick)
+ . Fixed potential overflow in _php_stream_scandir (CVE-2012-2688).
+ (Jason Powell, Stas)
-- Fileinfo:
- . Fixed magic file regex support. (Felipe)
+- EXIF:
+ . Fixed information leak in ext exif (discovered by Martin Noga,
+ Matthew "j00ru" Jurczyk, Gynvael Coldwind)
- FPM:
- . Fixed bug #61045 (fpm don't send error log to fastcgi clients). (fat)
+ . Fixed bug #62205 (php-fpm segfaults (null passed to strstr)). (fat)
+ . Fixed bug #62160 (Add process.priority to set nice(2) priorities). (fat)
+ . Fixed bug #62153 (when using unix sockets, multiples FPM instances
+ . Fixed bug #62033 (php-fpm exits with status 0 on some failures to start).
+ (fat)
+ . Fixed bug #61839 (Unable to cross-compile PHP with --enable-fpm). (fat)
. Fixed bug #61835 (php-fpm is not allowed to run as root). (fat)
. Fixed bug #61295 (php-fpm should not fail with commented 'user'
+ . Fixed bug #61218 (FPM drops connection while receiving some binary values
+ in FastCGI requests). (fat)
+ . Fixed bug #61045 (fpm don't send error log to fastcgi clients). (fat)
for non-root start). (fat)
. Fixed bug #61026 (FPM pools can listen on the same address). (fat)
- . Fixed bug #62033 (php-fpm exits with status 0 on some failures to start).
- (fat)
- . Fixed bug #62153 (when using unix sockets, multiples FPM instances
can be launched without errors). (fat)
- . Fixed bug #62160 (Add process.priority to set nice(2) priorities). (fat)
- . Fixed bug #61218 (FPM drops connection while receiving some binary values
- in FastCGI requests). (fat)
- . Fixed bug #62205 (php-fpm segfaults (null passed to strstr)). (fat)
+
+- Iconv:
+ . Fix bug #55042 (Erealloc in iconv.c unsafe). (Stas)
- Intl:
. Fixed bug #62083 (grapheme_extract() memory leaks). (Gustavo)
+ . ResourceBundle constructor now accepts NULL for the first two arguments.
+ (Gustavo)
. Fixed bug #62081 (IntlDateFormatter constructor leaks memory when called
twice). (Gustavo)
. Fixed bug #62070 (Collator::getSortKey() returns garbage). (Gustavo)
@@ -178,25 +305,34 @@ PHP NEWS
. Fixed bug #60785 (memory leak in IntlDateFormatter constructor). (Gustavo)
- JSON:
- . Reverted fix for bug #61537. (Johannes)
+ . Fixed bug #61359 (json_encode() calls too many reallocs). (Stas)
+
+- libxml:
+ . Fixed bug #62266 (Custom extension segfaults during xmlParseFile with FPM
+ SAPI). (Gustavo)
- Phar:
. Fixed bug #62227 (Invalid phar stream path causes crash). (Felipe)
+- Readline:
+ . Fixed bug #62186 (readline fails to compile - void function should not
+ return a value). (Johannes)
+
- Reflection:
. Fixed bug #62384 (Attempting to invoke a Closure more than once causes
segfault). (Felipe)
. Fixed bug #62202 (ReflectionParameter::getDefaultValue() memory leaks
with constant). (Laruence)
+- Sockets:
+ . Fixed bug #62025 (__ss_family was changed on AIX 5.3). (Felipe)
+
- SPL:
+ . Fixed bug #62433 (Inconsistent behavior of RecursiveDirectoryIterator to
+ dot files). (Laruence)
. Fixed bug #62262 (RecursiveArrayIterator does not implement Countable).
(Nikita Popov)
-- SQLite:
- . Fixed open_basedir bypass, CVE-2012-3365. (Johannes, reported by Yury
- Maryshev)
-
- XML Writer:
. Fixed bug #62064 (memory leak in the XML Writer module).
(jean-pierre dot lozi at lip6 dot fr)
@@ -204,6 +340,670 @@ PHP NEWS
- Zip:
. Upgraded libzip to 0.10.1 (Anatoliy)
+14 Jun 2012, PHP 5.4.4
+
+- COM:
+ . Fixed bug #62146 com_dotnet cannot be built shared. (Johannes)
+
+- CLI Server:
+ . Implemented FR #61977 (Need CLI web-server support for files with .htm &
+ svg extensions). (Sixd, Laruence)
+ . Improved performance while sending error page, this also fixed
+ bug #61785 (Memory leak when access a non-exists file without router).
+ (Laruence)
+ . Fixed bug #61546 (functions related to current script failed when chdir()
+ in cli sapi). (Laruence, reeze.xia@gmail.com)
+
+- Core:
+ . Fixed missing bound check in iptcparse(). (chris at chiappa.net)
+ . Fixed CVE-2012-2143. (Solar Designer)
+ . Fixed bug #62097 (fix for for bug #54547). (Gustavo)
+ . Fixed bug #62005 (unexpected behavior when incrementally assigning to a
+ member of a null object). (Laruence)
+ . Fixed bug #61978 (Object recursion not detected for classes that implement
+ JsonSerializable). (Felipe)
+ . Fixed bug #61991 (long overflow in realpath_cache_get()). (Anatoliy)
+ . Fixed bug #61922 (ZTS build doesn't accept zend.script_encoding config).
+ (Laruence)
+ . Fixed bug #61827 (incorrect \e processing on Windows) (Anatoliy)
+ . Fixed bug #61782 (__clone/__destruct do not match other methods when checking
+ access controls). (Stas)
+ . Fixed bug #61764 ('I' unpacks n as signed if n > 2^31-1 on LP64). (Gustavo)
+ . Fixed bug #61761 ('Overriding' a private static method with a different
+ signature causes crash). (Laruence)
+ . Fixed bug #61730 (Segfault from array_walk modifying an array passed by
+ reference). (Laruence)
+ . Fixed bug #61728 (PHP crash when calling ob_start in request_shutdown
+ phase). (Laruence)
+ . Fixed bug #61713 (Logic error in charset detection for htmlentities).
+ (Anatoliy)
+ . Fixed bug #61660 (bin2hex(hex2bin($data)) != $data). (Nikita Popov)
+ . Fixed bug #61650 (ini parser crashes when using ${xxxx} ini variables
+ (without apache2)). (Laruence)
+ . Fixed bug #61605 (header_remove() does not remove all headers). (Laruence)
+ . Fixed bug #54547 (wrong equality of string numbers). (Gustavo)
+ . Fixed bug #54197 ([PATH=] sections incompatibility with user_ini.filename
+ set to null). (Anatoliy)
+ . Changed php://fd to be available only for CLI.
+
+- CURL:
+ . Fixed bug #61948 (CURLOPT_COOKIEFILE '' raises open_basedir restriction).
+ (Laruence)
+
+- Fileinfo
+ . Fixed bug #61812 (Uninitialised value used in libmagic).
+ (Laruence, Gustavo)
+ . Fixed bug #61566 failure caused by the posix lseek and read versions
+ under windows in cdf_read(). (Anatoliy)
+ . Fixed bug #61565 where php_stream_open_wrapper_ex tries to open a
+ directory descriptor under windows. (Anatoliy)
+
+- Intl
+ . Fixed bug #62082 (Memory corruption in internal function
+ get_icu_disp_value_src_php()). (Gustavo)
+
+- Libxml:
+ . Fixed bug #61617 (Libxml tests failed(ht is already destroyed)).
+ (Laruence)
+
+- PDO:
+ . Fixed bug #61755 (A parsing bug in the prepared statements can lead to
+ access violations). (Johannes)
+
+- Phar:
+ . Fixed bug #61065 (Secunia SA44335, CVE-2012-2386). (Rasmus)
+
+- Pgsql:
+ . Added pg_escape_identifier/pg_escape_literal. (Yasuo Ohgaki)
+
+- Streams:
+ . Fixed bug #61961 (file_get_contents leaks when access empty file with
+ maxlen set). (Reeze)
+
+- Zlib:
+ . Fixed bug #61820 (using ob_gzhandler will complain about headers already
+ sent when no compression). (Mike)
+ . Fixed bug #61443 (can't change zlib.output_compression on the fly). (Mike)
+ . Fixed bug #60761 (zlib.output_compression fails on refresh). (Mike)
+
+08 May 2012, PHP 5.4.3
+
+- CGI
+ . Re-Fix PHP-CGI query string parameter vulnerability, CVE-2012-1823.
+ (Stas)
+ . Fix bug #61807 - Buffer Overflow in apache_request_headers.
+ (nyt-php at countercultured dot net).
+
+03 May 2012, PHP 5.4.2
+
+- Fix PHP-CGI query string parameter vulnerability, CVE-2012-1823. (Rasmus)
+
+26 Apr 2012, PHP 5.4.1
+
+- CLI Server:
+ . Fixed bug #61461 (missing checks around malloc() calls). (Ilia)
+ . Implemented FR #60850 (Built in web server does not set
+ $_SERVER['SCRIPT_FILENAME'] when using router). (Laruence)
+ . "Connection: close" instead of "Connection: closed" (Gustavo)
+
+- Core:
+ . Fixed crash in ZTS using same class in many threads. (Johannes)
+ . Fixed bug #61374 (html_entity_decode tries to decode code points that don't
+ exist in ISO-8859-1). (Gustavo)
+ . Fixed bug #61273 (call_user_func_array with more than 16333 arguments
+ leaks / crashes). (Laruence)
+ . Fixed bug #61225 (Incorrect lexing of 0b00*+<NUM>). (Pierrick)
+ . Fixed bug #61165 (Segfault - strip_tags()). (Laruence)
+ . Fixed bug #61106 (Segfault when using header_register_callback). (Nikita
+ Popov)
+ . Fixed bug #61087 (Memory leak in parse_ini_file when specifying
+ invalid scanner mode). (Nikic, Laruence)
+ . Fixed bug #61072 (Memory leak when restoring an exception handler).
+ (Nikic, Laruence)
+ . Fixed bug #61058 (array_fill leaks if start index is PHP_INT_MAX).
+ (Laruence)
+ . Fixed bug #61052 (Missing error check in trait 'insteadof' clause). (Stefan)
+ . Fixed bug #61011 (Crash when an exception is thrown by __autoload
+ accessing a static property). (Laruence)
+ . Fixed bug #61000 (Exceeding max nesting level doesn't delete numerical
+ vars). (Laruence)
+ . Fixed bug #60978 (exit code incorrect). (Laruence)
+ . Fixed bug #60911 (Confusing error message when extending traits). (Stefan)
+ . Fixed bug #60801 (strpbrk() mishandles NUL byte). (Adam)
+ . Fixed bug #60717 (Order of traits in use statement can cause a fatal
+ error). (Stefan)
+ . Fixed bug #60573 (type hinting with "self" keyword causes weird errors).
+ (Laruence)
+ . Fixed bug #60569 (Nullbyte truncates Exception $message). (Ilia)
+ . Fixed bug #52719 (array_walk_recursive crashes if third param of the
+ function is by reference). (Nikita Popov)
+ . Improve performance of set_exception_handler while doing reset (Laruence)
+
+- fileinfo:
+ . Fix fileinfo test problems. (Anatoliy Belsky)
+
+- FPM
+ . Fixed bug #61430 (Transposed memset() params in sapi/fpm/fpm/fpm_shm.c).
+ (michaelhood at gmail dot com, Ilia)
+
+- Ibase
+ . Fixed bug #60947 (Segmentation fault while executing ibase_db_info).
+ (Ilia)
+
+- Installation
+ . Fixed bug #61172 (Add Apache 2.4 support). (Chris Jones)
+
+- Intl:
+ . Fixed bug #61487 (Incorrent bounds checking in grapheme_strpos).
+ (Stas)
+
+- mbstring:
+ . MFH mb_ereg_replace_callback() for security enhancements. (Rui)
+
+- mysqli
+ . Fixed bug #61003 (mysql_stat() require a valid connection). (Johannes).
+
+- mysqlnd
+ . Fixed bug #61704 (Crash apache, phpinfo() threading issue). (Johannes)
+ . Fixed bug #60948 (mysqlnd FTBFS when -Wformat-security is enabled).
+ (Johannes)
+
+- PDO
+ . Fixed bug #61292 (Segfault while calling a method on an overloaded PDO
+ object). (Laruence)
+
+- PDO_mysql
+ . Fixed bug #61207 (PDO::nextRowset() after a multi-statement query doesn't
+ always work). (Johannes)
+ . Fixed bug #61194 (PDO should export compression flag with myslqnd).
+ (Johannes)
+
+- PDO_odbc
+ . Fixed bug #61212 (PDO ODBC Segfaults on SQL_SUCESS_WITH_INFO). (Ilia)
+
+- Phar
+ . Fixed bug #61184 (Phar::webPhar() generates headers with trailing NUL
+ bytes). (Nikita Popov)
+
+- Readline:
+ . Fixed bug #61088 (Memory leak in readline_callback_handler_install).
+ (Nikic, Laruence)
+
+- Reflection:
+ . Implemented FR #61602 (Allow access to the name of constant
+ used as function/method parameter's default value). (reeze.xia@gmail.com)
+ . Fixed bug #60968 (Late static binding doesn't work with
+ ReflectionMethod::invokeArgs()). (Laruence)
+
+- Session
+ . Fixed bug #60634 (Segmentation fault when trying to die() in
+ SessionHandler::write()). (Ilia)
+
+- SOAP
+ . Fixed bug #61423 (gzip compression fails). (Ilia)
+ . Fixed bug #60887 (SoapClient ignores user_agent option and sends no
+ User-Agent header). (carloschilazo at gmail dot com)
+ . Fixed bug #60842, #51775 (Chunked response parsing error when
+ chunksize length line is > 10 bytes). (Ilia)
+ . Fixed bug #49853 (Soap Client stream context header option ignored).
+ (Dmitry)
+
+- SPL:
+ . Fixed bug #61453 (SplObjectStorage does not identify objects correctly).
+ (Gustavo)
+ . Fixed bug #61347 (inconsistent isset behavior of Arrayobject). (Laruence)
+
+- Standard:
+ . Fixed memory leak in substr_replace. (Pierrick)
+ . Make max_file_uploads ini directive settable outside of php.ini (Rasmus)
+ . Fixed bug #61409 (Bad formatting on phpinfo()). (Jakub Vrana)
+ . Fixed bug #60222 (time_nanosleep() does validate input params). (Ilia)
+ . Fixed bug #60106 (stream_socket_server silently truncates long unix socket
+ paths). (Ilia)
+
+- XMLRPC:
+ . Fixed bug #61264 (xmlrpc_parse_method_descriptions leaks temporary
+ variable). (Nikita Popov)
+ . Fixed bug #61097 (Memory leak in xmlrpc functions copying zvals). (Nikita
+ Popov)
+
+- Zlib:
+ . Fixed bug #61306 (initialization of global inappropriate for ZTS). (Gustavo)
+ . Fixed bug #61287 (A particular string fails to decompress). (Mike)
+ . Fixed bug #61139 (gzopen leaks when specifying invalid mode). (Nikita Popov)
+
+01 Mar 2012, PHP 5.4.0
+
+- Installation:
+ . autoconf 2.59+ is now supported (and required) for generating the
+ configure script with ./buildconf. Autoconf 2.60+ is desirable
+ otherwise the configure help order may be incorrect. (Rasmus, Chris Jones)
+
+- Removed legacy features:
+ . break/continue $var syntax. (Dmitry)
+ . Safe mode and all related php.ini options. (Kalle)
+ . register_globals and register_long_arrays php.ini options. (Kalle)
+ . import_request_variables(). (Kalle)
+ . allow_call_time_pass_reference. (Pierrick)
+ . define_syslog_variables php.ini option and its associated function. (Kalle)
+ . highlight.bg php.ini option. (Kalle)
+ . safe_mode, safe_mode_gid, safe_mode_include_dir,
+ safe_mode_exec_dir, safe_mode_allowed_env_vars and
+ safe_mode_protected_env_vars php.ini options.
+ . zend.ze1_compatibility_mode php.ini option.
+ . Session bug compatibility mode (session.bug_compat_42 and
+ session.bug_compat_warn php.ini options). (Kalle)
+ . session_is_registered(), session_register() and session_unregister()
+ functions. (Kalle)
+ . y2k_compliance php.ini option. (Kalle)
+ . magic_quotes_gpc, magic_quotes_runtime and magic_quotes_sybase
+ php.ini options. get_magic_quotes_gpc, get_magic_quotes_runtime are kept
+ but always return false, set_magic_quotes_runtime raises an
+ E_CORE_ERROR. (Pierrick, Pierre)
+ . Removed support for putenv("TZ=..") for setting the timezone. (Derick)
+ . Removed the timezone guessing algorithm in case the timezone isn't set with
+ date.timezone or date_default_timezone_set(). Instead of a guessed
+ timezone, "UTC" is now used instead. (Derick)
+
+- Moved extensions to PECL:
+ . ext/sqlite. (Note: the ext/sqlite3 and ext/pdo_sqlite extensions are
+ not affected) (Johannes)
+
+- General improvements:
+ . Added short array syntax support ([1,2,3]), see UPGRADING guide for full
+ details. (rsky0711 at gmail . com, sebastian.deutsch at 9elements . com,
+ Pierre)
+ . Added binary number format (0b001010). (Jonah dot Harris at gmail dot com)
+ . Added support for Class::{expr}() syntax (Pierrick)
+ . Added multibyte support by default. Previously PHP had to be compiled
+ with --enable-zend-multibyte. Now it can be enabled or disabled through
+ the zend.multibyte directive in php.ini. (Dmitry)
+ . Removed compile time dependency from ext/mbstring (Dmitry)
+ . Added support for Traits. (Stefan, with fixes by Dmitry and Laruence)
+ . Added closure $this support back. (Stas)
+ . Added array dereferencing support. (Felipe)
+ . Added callable typehint. (Hannes)
+ . Added indirect method call through array. FR #47160. (Felipe)
+ . Added DTrace support. (David Soria Parra)
+ . Added class member access on instantiation (e.g. (new foo)->bar()) support.
+ (Felipe)
+ . <?= is now always available regardless of the short_open_tag setting. (Rasmus)
+ . Implemented Zend Signal Handling (configurable option --enable-zend-signals,
+ off by default). (Lucas Nealan, Arnaud Le Blanc, Brian Shire, Ilia)
+ . Improved output layer, see README.NEW-OUTPUT-API for internals. (Mike)
+ . Improved UNIX build system to allow building multiple PHP binary SAPIs and
+ one SAPI module the same time. FR #53271, FR #52419. (Jani)
+ . Implemented closure rebinding as parameter to bindTo. (Gustavo Lopes)
+ . Improved the warning message of incompatible arguments. (Laruence)
+ . Improved ternary operator performance when returning arrays. (Arnaud, Dmitry)
+ . Changed error handlers to only generate docref links when the docref_root
+ php.ini setting is not empty. (Derick)
+ . Changed silent conversion of array to string to produce a notice. (Patrick)
+ . Changed default encoding from ISO-8859-1 to UTF-8 when not specified in
+ htmlspecialchars and htmlentities. (Rasmus)
+ . Changed casting of null/''/false into an Object when adding a property
+ from E_STRICT into a warning. (Scott)
+ . Changed E_ALL to include E_STRICT. (Stas)
+ . Disabled Windows CRT warning by default, can be enabled again using the
+ php.ini directive windows_show_crt_warnings. (Pierre)
+ . Fixed bug #55378: Binary number literal returns float number though its
+ value is small enough. (Derick)
+
+- Improved Zend Engine memory usage: (Dmitry)
+ . Improved parse error messages. (Felipe)
+ . Replaced zend_function.pass_rest_by_reference by
+ ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags.
+ . Replaced zend_function.return_reference by ZEND_ACC_RETURN_REFERENCE
+ in zend_function.fn_flags.
+ . Removed zend_arg_info.required_num_args as it was only needed for internal
+ functions. Now the first arg_info for internal functions (which has special
+ meaning) is represented by the zend_internal_function_info structure.
+ . Moved zend_op_array.size, size_var, size_literal, current_brk_cont,
+ backpatch_count into CG(context) as they are used only during compilation.
+ . Moved zend_op_array.start_op into EG(start_op) as it's used only for
+ 'interactive' execution of a single top-level op-array.
+ . Replaced zend_op_array.done_pass_two by ZEND_ACC_DONE_PASS_TWO in
+ zend_op_array.fn_flags.
+ . op_array.vars array is trimmed (reallocated) during pass_two.
+ . Replaced zend_class_entry.constants_updated by ZEND_ACC_CONSTANTS_UPDATED
+ in zend_class_entry.ce_flags.
+ . Reduced the size of zend_class_entry by sharing the same memory space
+ by different information for internal and user classes.
+ See zend_class_entry.info union.
+ . Reduced size of temp_variable.
+
+- Improved Zend Engine - performance tweaks and optimizations: (Dmitry)
+ . Inlined most probable code-paths for arithmetic operations directly into
+ executor.
+ . Eliminated unnecessary iterations during request startup/shutdown.
+ . Changed $GLOBALS into a JIT autoglobal, so it's initialized only if used.
+ (this may affect opcode caches!)
+ . Improved performance of @ (silence) operator.
+ . Simplified string offset reading. Given $str="abc" then $str[1][0] is now
+ a legal construct.
+ . Added caches to eliminate repeatable run-time bindings of functions,
+ classes, constants, methods and properties.
+ . Added concept of interned strings. All strings constants known at compile
+ time are allocated in a single copy and never changed.
+ . ZEND_RECV now always has IS_CV as its result.
+ . ZEND_CATCH now has to be used only with constant class names.
+ . ZEND_FETCH_DIM_? may fetch array and dimension operands in different order.
+ . Simplified ZEND_FETCH_*_R operations. They can't be used with the
+ EXT_TYPE_UNUSED flag any more. This is a very rare and useless case.
+ ZEND_FREE might be required after them instead.
+ . Split ZEND_RETURN into two new instructions ZEND_RETURN and
+ ZEND_RETURN_BY_REF.
+ . Optimized access to global constants using values with pre-calculated
+ hash_values from the literals table.
+ . Optimized access to static properties using executor specialization.
+ A constant class name may be used as a direct operand of ZEND_FETCH_*
+ instruction without previous ZEND_FETCH_CLASS.
+ . zend_stack and zend_ptr_stack allocation is delayed until actual usage.
+
+- Other improvements to Zend Engine:
+ . Added an optimization which saves memory and emalloc/efree calls for empty
+ HashTables. (Stas, Dmitry)
+ . Added ability to reset user opcode handlers (Yoram).
+ . Changed the structure of op_array.opcodes. The constant values are moved from
+ opcode operands into a separate literal table. (Dmitry)
+ . Fixed (disabled) inline-caching for ZEND_OVERLOADED_FUNCTION methods.
+ (Dmitry)
+
+- Improved core functions:
+ . Enforce an extended class' __construct arguments to match the
+ abstract constructor in the base class.
+ . Disallow reusing superglobal names as parameter names.
+ . Added optional argument to debug_backtrace() and debug_print_backtrace()
+ to limit the amount of stack frames returned. (Sebastian, Patrick)
+ . Added hex2bin() function. (Scott)
+ . number_format() no longer truncates multibyte decimal points and thousand
+ separators to the first byte. FR #53457. (Adam)
+ . Added support for object references in recursive serialize() calls.
+ FR #36424. (Mike)
+ . Added support for SORT_NATURAL and SORT_FLAG_CASE in array
+ sort functions (sort, rsort, ksort, krsort, asort, arsort and
+ array_multisort). FR#55158 (Arpad)
+ . Added stream metadata API support and stream_metadata() stream class
+ handler. (Stas)
+ . User wrappers can now define a stream_truncate() method that responds
+ to truncation, e.g. through ftruncate(). FR #53888. (Gustavo)
+ . Improved unserialize() performance.
+ (galaxy dot mipt at gmail dot com, Kalle)
+ . Changed array_combine() to return empty array instead of FALSE when both
+ parameter arrays are empty. FR #34857. (joel.perras@gmail.com)
+ . Fixed bug #61095 (Incorect lexing of 0x00*+<NUM>). (Etienne)
+ . Fixed bug #60965 (Buffer overflow on htmlspecialchars/entities with
+ $double=false). (Gustavo)
+ . Fixed bug #60895 (Possible invalid handler usage in windows random
+ functions). (Pierre)
+ . Fixed bug #60879 (unserialize() Does not invoke __wakeup() on object).
+ (Pierre, Steve)
+ . Fixed bug #60825 (Segfault when running symfony 2 tests).
+ (Dmitry, Laruence)
+ . Fixed bug #60627 (httpd.worker segfault on startup with php_value).
+ . Fixed bug #60613 (Segmentation fault with $cls->{expr}() syntax). (Dmitry)
+ . Fixed bug #60611 (Segmentation fault with Cls::{expr}() syntax). (Laruence)
+ (Laruence)
+ . Fixed bug #60558 (Invalid read and writes). (Laruence)
+ . Fixed bug #60444 (Segmentation fault with include & class extending).
+ (Laruence, Dmitry).
+ . Fixed bug #60362 (non-existent sub-sub keys should not have values).
+ (Laruence, alan_k, Stas)
+ . Fixed bug #60350 (No string escape code for ESC (ascii 27), normally \e).
+ (php at mickweiss dot com)
+ . Fixed bug #60321 (ob_get_status(true) no longer returns an array when
+ buffer is empty). (Pierrick)
+ . Fixed bug #60282 (Segfault when using ob_gzhandler() with open buffers).
+ (Laruence)
+ . Fixed bug #60240 (invalid read/writes when unserializing specially crafted
+ strings). (Mike)
+ . Fixed bug #60227 (header() cannot detect the multi-line header with
+ CR(0x0D)). (rui)
+ . Fixed bug #60174 (Notice when array in method prototype error).
+ (Laruence)
+ . Fixed bug #60169 (Conjunction of ternary and list crashes PHP).
+ (Laruence)
+ . Fixed bug #60038 (SIGALRM cause segfault in php_error_cb). (Laruence)
+ (klightspeed at netspace dot net dot au)
+ . Fixed bug #55871 (Interruption in substr_replace()). (Stas)
+ . Fixed bug #55801 (Behavior of unserialize has changed). (Mike)
+ . Fixed bug #55758 (Digest Authenticate missed in 5.4) . (Laruence)
+ . Fixed bug #55748 (multiple NULL Pointer Dereference with zend_strndup())
+ (CVE-2011-4153). (Stas)
+ . Fixed bug #55124 (recursive mkdir fails with current (dot) directory in path).
+ (Pierre)
+ . Fixed bug #55084 (Function registered by header_register_callback is
+ called only once per process). (Hannes)
+ . Implement FR #54514 (Get php binary path during script execution).
+ (Laruence)
+ . Fixed bug #52211 (iconv() returns part of string on error). (Felipe)
+ . Fixed bug #51860 (Include fails with toplevel symlink to /). (Dmitry)
+
+- Improved generic SAPI support:
+ . Added $_SERVER['REQUEST_TIME_FLOAT'] to include microsecond precision.
+ (Patrick)
+ . Added header_register_callback() which is invoked immediately
+ prior to the sending of headers and after default headers have
+ been added. (Scott)
+ . Added http_response_code() function. FR #52555. (Paul Dragoonis, Kalle)
+ . Fixed bug #55500 (Corrupted $_FILES indices lead to security concern).
+ (CVE-2012-1172). (Stas)
+ . Fixed bug #54374 (Insufficient validating of upload name leading to
+ corrupted $_FILES indices). (CVE-2012-1172). (Stas, lekensteyn at gmail dot com)
+
+- Improved CLI SAPI:
+ . Added built-in web server that is intended for testing purpose.
+ (Moriyoshi, Laruence, and fixes by Pierre, Derick, Arpad,
+ chobieee at gmail dot com)
+ . Added command line option --rz <name> which shows information of the
+ named Zend extension. (Johannes)
+ . Interactive readline shell improvements: (Johannes)
+ . Added "cli.pager" php.ini setting to set a pager for output.
+ . Added "cli.prompt" php.ini setting to configure the shell prompt.
+ . Added shortcut #inisetting=value to change php.ini settings at run-time.
+ . Changed shell not to terminate on fatal errors.
+ . Interactive shell works with shared readline extension. FR #53878.
+
+- Improved CGI/FastCGI SAPI: (Dmitry)
+ . Added apache compatible functions: apache_child_terminate(),
+ getallheaders(), apache_request_headers() and apache_response_headers()
+ . Improved performance of FastCGI request parsing.
+ . Fixed reinitialization of SAPI callbacks after php_module_startup().
+ (Dmitry)
+
+- Improved PHP-FPM SAPI:
+ . Removed EXPERIMENTAL flag. (fat)
+ . Fixed bug #60659 (FPM does not clear auth_user on request accept).
+ (bonbons at linux-vserver dot org)
+
+- Improved Litespeed SAPI:
+ . Fixed bug #55769 (Make Fails with "Missing Separator" error). (Adam)
+
+- Improved Date extension:
+ . Added the + modifier to parseFromFormat to allow trailing text in the
+ string to parse without throwing an error. (Stas, Derick)
+
+- Improved DBA extension:
+ . Added Tokyo Cabinet abstract DB support. (Michael Maclean)
+ . Added Berkeley DB 5 support. (Johannes, Chris Jones)
+
+- Improved DOM extension:
+ . Added the ability to pass options to loadHTML (Chregu, fxmulder at gmail dot com)
+
+- Improved filesystem functions:
+ . scandir() now accepts SCANDIR_SORT_NONE as a possible sorting_order value.
+ FR #53407. (Adam)
+
+- Improved HASH extension:
+ . Added Jenkins's one-at-a-time hash support. (Martin Jansen)
+ . Added FNV-1 hash support. (Michael Maclean)
+ . Made Adler32 algorithm faster. FR #53213. (zavasek at yandex dot ru)
+ . Removed Salsa10/Salsa20, which are actually stream ciphers (Mike)
+ . Fixed bug #60221 (Tiger hash output byte order) (Mike)
+
+- Improved intl extension:
+ . Added Spoofchecker class, allows checking for visibly confusable characters and
+ other security issues. (Scott)
+ . Added Transliterator class, allowing transliteration of strings.
+ (Gustavo)
+ . Added support for UTS #46. (Gustavo)
+ . Fixed build on Fedora 15 / Ubuntu 11. (Hannes)
+ . Fixed bug #55562 (grapheme_substr() returns false on big length). (Stas)
+
+- Improved JSON extension:
+ . Added new json_encode() option JSON_UNESCAPED_UNICODE. FR #53946.
+ (Alexander, Gwynne)
+ . Added JsonSerializable interface. (Sara)
+ . Added JSON_BIGINT_AS_STRING, extended json_decode() sig with $options.
+ (Sara)
+ . Added support for JSON_NUMERIC_CHECK option in json_encode() that converts
+ numeric strings to integers. (Ilia)
+ . Added new json_encode() option JSON_UNESCAPED_SLASHES. FR #49366. (Adam)
+ . Added new json_encode() option JSON_PRETTY_PRINT. FR #44331. (Adam)
+
+- Improved LDAP extension:
+ . Added paged results support. FR #42060. (ando@OpenLDAP.org,
+ iarenuno@eteo.mondragon.edu, jeanseb@au-fil-du.net, remy.saissy@gmail.com)
+
+- Improved mbstring extension:
+ . Added Shift_JIS/UTF-8 Emoji (pictograms) support. (Rui)
+ . Added JIS X0213:2004 (Shift_JIS-2004, EUC-JP-2004, ISO-2022-JP-2004)
+ support. (Rui)
+ . Ill-formed UTF-8 check for security enhancements. (Rui)
+ . Added MacJapanese (Shift_JIS) and gb18030 encoding support. (Rui)
+ . Added encode/decode in hex format to mb_[en|de]code_numericentity(). (Rui)
+ . Added user JIS X0213:2004 (Shift_JIS-2004, EUC-JP-2004, ISO-2022-JP-2004)
+ support. (Rui)
+ . Added the user defined area for CP936 and CP950 (Rui).
+ . Fixed bug #60306 (Characters lost while converting from cp936 to utf8).
+ (Laruence)
+
+- Improved MySQL extensions:
+ . MySQL: Deprecated mysql_list_dbs(). FR #50667. (Andrey)
+ . mysqlnd: Added named pipes support. FR #48082. (Andrey)
+ . MySQLi: Added iterator support in MySQLi. mysqli_result implements
+ Traversable. (Andrey, Johannes)
+ . PDO_mysql: Removed support for linking with MySQL client libraries older
+ than 4.1. (Johannes)
+ . ext/mysql, mysqli and pdo_mysql now use mysqlnd by default. (Johannes)
+ . Fixed bug #55473 (mysql_pconnect leaks file descriptors on reconnect).
+ (Andrey, Laruence)
+ . Fixed bug #55653 (PS crash with libmysql when binding same variable as
+ param and out). (Laruence)
+
+- Improved OpenSSL extension:
+ . Added AES support. FR #48632. (yonas dot y at gmail dot com, Pierre)
+ . Added no padding option to openssl_encrypt()/openssl_decrypt(). (Scott)
+ . Use php's implementation for Windows Crypto API in
+ openssl_random_pseudo_bytes. (Pierre)
+ . On error in openssl_random_pseudo_bytes() made sure we set strong result
+ to false. (Scott)
+ . Fixed possible attack in SSL sockets with SSL 3.0 / TLS 1.0.
+ CVE-2011-3389. (Scott)
+ . Fixed bug #61124 (Crash when decoding an invalid base64 encoded string).
+ (me at ktamura dot com, Scott)
+
+- Improved PDO:
+ . Fixed PDO objects binary incompatibility. (Dmitry)
+
+- PDO DBlib driver:
+ . Added nextRowset support.
+ . Fixed bug #50755 (PDO DBLIB Fails with OOM).
+
+- Improved PostgreSQL extension:
+ . Added support for "extra" parameter for PGNotify().
+ (r dot i dot k at free dot fr, Ilia)
+
+- Improved PCRE extension:
+ . Changed third parameter of preg_match_all() to optional. FR #53238. (Adam)
+
+- Improved Readline extension:
+ . Fixed bug #54450 (Enable callback support when built against libedit).
+ (fedora at famillecollet dot com, Hannes)
+
+- Improved Reflection extension:
+ . Added ReflectionClass::newInstanceWithoutConstructor() to create a new
+ instance of a class without invoking its constructor. FR #55490.
+ (Sebastian)
+ . Added ReflectionExtension::isTemporary() and
+ ReflectionExtension::isPersistent() methods. (Johannes)
+ . Added ReflectionZendExtension class. (Johannes)
+ . Added ReflectionClass::isCloneable(). (Felipe)
+
+- Improved Session extension:
+ . Expose session status via new function, session_status (FR #52982) (Arpad)
+ . Added support for object-oriented session handlers. (Arpad)
+ . Added support for storing upload progress feedback in session data. (Arnaud)
+ . Changed session.entropy_file to default to /dev/urandom or /dev/arandom if
+ either is present at compile time. (Rasmus)
+ . Fixed bug #60860 (session.save_handler=user without defined function core
+ dumps). (Felipe)
+ . Implement FR #60551 (session_set_save_handler should support a core's
+ session handler interface). (Arpad)
+ . Fixed bug #60640 (invalid return values). (Arpad)
+
+- Improved SNMP extension (Boris Lytochkin):
+ . Added OO API. FR #53594 (php-snmp rewrite).
+ . Sanitized return values of existing functions. Now it returns FALSE on
+ failure.
+ . Allow ~infinite OIDs in GET/GETNEXT/SET queries. Autochunk them to max_oids
+ upon request.
+ . Introducing unit tests for extension with ~full coverage.
+ . IPv6 support. (FR #42918)
+ . Way of representing OID value can now be changed when SNMP_VALUE_OBJECT
+ is used for value output mode. Use or'ed SNMP_VALUE_LIBRARY(default if
+ not specified) or SNMP_VALUE_PLAIN. (FR #54502)
+ . Fixed bug #60749 (SNMP module should not strip non-standard SNMP port
+ from hostname). (Boris Lytochkin)
+ . Fixed bug #60585 (php build fails with USE flag snmp when IPv6 support
+ is disabled). (Boris Lytochkin)
+ . Fixed bug #53862 (snmp_set_oid_output_format does not allow returning to default)
+ . Fixed bug #46065 (snmp_set_quick_print() persists between requests)
+ . Fixed bug #45893 (Snmp buffer limited to 2048 char)
+ . Fixed bug #44193 (snmp v3 noAuthNoPriv doesn't work)
+
+- Improved SOAP extension:
+ . Added new SoapClient option "keep_alive". FR #60329. (Pierrick)
+ . Fixed basic HTTP authentication for WSDL sub requests. (Dmitry)
+
+- Improved SPL extension:
+ . Added RegexIterator::getRegex() method. (Joshua Thijssen)
+ . Added SplObjectStorage::getHash() hook. (Etienne)
+ . Added CallbackFilterIterator and RecursiveCallbackFilterIterator. (Arnaud)
+ . Added missing class_uses(..) as pointed out by #55266 (Stefan)
+ . Immediately reject wrong usages of directories under Spl(Temp)FileObject
+ and friends. (Etienne, Pierre)
+ . FilesystemIterator, GlobIterator and (Recursive)DirectoryIterator now use
+ the default stream context. (Hannes)
+ . Fixed bug #60201 (SplFileObject::setCsvControl does not expose third
+ argument via Reflection). (Peter)
+ . Fixed bug #55287 (spl_classes() not includes CallbackFilter classes)
+ (sasezaki at gmail dot com, salathe)
+
+- Improved Sysvshm extension:
+ . Fixed bug #55750 (memory copy issue in sysvshm extension).
+ (Ilia, jeffhuang9999 at gmail dot com)
+
+- Improved Tidy extension:
+ . Fixed bug #54682 (Tidy::diagnose() NULL pointer dereference).
+ (Maksymilian Arciemowicz, Felipe)
+
+- Improved Tokenizer extension:
+ . Fixed bug #54089 (token_get_all with regards to __halt_compiler is
+ not binary safe). (Nikita Popov)
+
+- Improved XSL extension:
+ . Added XsltProcessor::setSecurityPrefs($options) and getSecurityPrefs() to
+ define forbidden operations within XSLT stylesheets, default is not to
+ enable write operations from XSLT. Bug #54446 (Chregu, Nicolas Gregoire)
+ . XSL doesn't stop transformation anymore, if a PHP function can't be called
+ (Christian)
+
+- Improved ZLIB extension:
+ . Re-implemented non-file related functionality. (Mike)
+ . Fixed bug #55544 (ob_gzhandler always conflicts with zlib.output_compression).
+ (Mike)
+
14 Jun 2012, PHP 5.3.14
- CLI SAPI:
@@ -274,8 +1074,10 @@ PHP NEWS
26 Apr 2012, PHP 5.3.11
- Core:
- . Fixed bug #61650 (ini parser crashes when using ${xxxx} ini variables
- (without apache2)). (Laruence)
+ . Fixed bug #61605 (header_remove() does not remove all headers).
+ (Laruence)
+ . Fixed bug #61541 (Segfault when using ob_* in output_callback).
+ (reeze.xia@gmail.com)
. Fixed bug #61273 (call_user_func_array with more than 16333 arguments
leaks / crashes). (Laruence)
. Fixed bug #61165 (Segfault - strip_tags()). (Laruence)
@@ -322,17 +1124,14 @@ PHP NEWS
. Fixed bug #61172 (Add Apache 2.4 support). (Chris Jones)
- Fileinfo
- . Upgraded libmagic to 5.11 (Pierre, Anatoliy)
- . Fixed bug #61565 where php_stream_open_wrapper_ex tries to open a
- directory descriptor under windows. (Anatoliy)
- . Fixed bug #61566 failure caused by the posix lseek and read versions
- under windows in cdf_read(). (Anatoliy)
. Fixed bug #61173 (Unable to detect error from finfo constructor). (Gustavo)
- Firebird Database extension (ibase):
. Fixed bug #60802 (ibase_trans() gives segfault when passing params).
- Libxml:
+ . Fixed bug #61617 (Libxml tests failed(ht is already destroyed)).
+ (Laruence)
. Fixed bug #61367 (open_basedir bypass using libxml RSHUTDOWN).
(Tim Starling)
@@ -355,10 +1154,6 @@ PHP NEWS
- PDO_Sqlite extension:
. Add createCollation support. (Damien)
-- pgsql:
- . Fixed bug #60718 (Compile problem with libpq (PostgreSQL 7.3 or less).
- (Yasuo Ohgaki)
-
- Phar:
. Fixed bug #61184 (Phar::webPhar() generates headers with trailing NUL
bytes). (Nikic)
@@ -540,8 +1335,6 @@ PHP NEWS
for small images). (Florian)
- Intl:
- . Fixed bug #61487 (Incorrent bounds checking in grapheme_strpos).
- (Stas)
. Fixed bug #60192 (SegFault when Collator not constructed
properly). (Florian)
. Fixed memory leak in several Intl locale functions. (Felipe)
@@ -645,6 +1438,7 @@ PHP NEWS
- Postgres:
. Fixed bug #60244 (pg_fetch_* functions do not validate that row param
is >0). (Ilia)
+ . Added PGSQL_LIBPQ_VERSION/PGSQL_LIBPQ_VERSION_STR constants. (Yasuo)
- Reflection:
. Fixed bug #60367 (Reflection and Late Static Binding). (Laruence)
diff --git a/README.NEW-OUTPUT-API b/README.NEW-OUTPUT-API
new file mode 100644
index 0000000000..7d9cc1016f
--- /dev/null
+++ b/README.NEW-OUTPUT-API
@@ -0,0 +1,142 @@
+$Id: README.NEW-OUTPUT-API 219039 2006-08-30 07:39:09Z mike $
+
+
+API adjustment to the old output control code:
+
+ Everything now resides beneath the php_output namespace,
+ and there's an API call for every output handler op.
+
+ Checking output control layers status:
+ // Using OG()
+ php_output_get_status(TSRMLS_C);
+
+ Starting the default output handler:
+ // php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
+ php_output_start_default(TSRMLS_C);
+
+ Starting an user handler by zval:
+ // php_start_ob_buffer(zhandler, chunk_size, erase TSRMLS_CC);
+ php_output_start_user(zhandler, chunk_size, flags TSRMLS_CC);
+
+ Starting an internal handler whithout context:
+ // php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase TSRMLS_CC);
+ php_output_start_internal(handler_name, handler_name_len, my_php_output_handler_func_t, chunk_size, flags TSRMLS_CC);
+
+ Starting an internal handler with context:
+ // not possible with old API
+ php_output_handler *h;
+ h = php_output_handler_create_internal(handler_name, handler_name_len, my_php_output_handler_context_func_t, chunk_size, flags TSRMLS_CC);
+ php_output_handler_set_context(h, my_context, my_context_dtor);
+ php_output_handler_start(h TSRMLS_CC);
+
+ Testing whether a certain output handler has already been started:
+ // php_ob_handler_used("output handler name" TSRMLS_CC);
+ php_output_handler_started(handler_name, handler_name_len TSRMLS_CC);
+
+ Flushing one output buffer:
+ // php_ob_end_buffer(1, 1 TSRMLS_CC);
+ php_output_flush(TSRMLS_C);
+
+ Flushing all output buffers:
+ // not possible with old API
+ php_output_flush_all(TSRMLS_C);
+
+ Cleaning one output buffer:
+ // php_ob_end_buffer(0, 1 TSRMLS_CC);
+ php_output_clean(TSRMLS_C);
+
+ Cleaning all output buffers:
+ // not possible with old API
+ php_output_clean_all(TSRMLS_C);
+
+ Discarding one output buffer:
+ // php_ob_end_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
+
+ Discarding all output buffers:
+ // php_ob_end_buffers(0 TSRMLS_CC);
+ php_output_discard_all(TSRMLS_C);
+
+ Stopping (and dropping) one output buffer:
+ // php_ob_end_buffer(1, 0 TSRMLS_CC)
+ php_output_end(TSRMLS_C);
+
+ Stopping (and dropping) all output buffers:
+ // php_ob_end_buffers(1, 0 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
+
+ Retrieving output buffers contents:
+ // php_ob_get_buffer(zstring TSRMLS_CC);
+ php_output_get_contents(zstring TSRMLS_CC);
+
+ Retrieving output buffers length:
+ // php_ob_get_length(zlength TSRMLS_CC);
+ php_output_get_length(zlength TSRMLS_CC);
+
+ Retrieving output buffering level:
+ // OG(nesting_level);
+ php_output_get_level(TSRMLS_C);
+
+ Issue a warning because of an output handler conflict:
+ // php_ob_init_conflict("to be started handler name", "to be tested if already started handler name" TSRMLS_CC);
+ php_output_handler_conflict(new_handler_name, new_handler_name_len, set_handler_name, set_handler_name_len TSRMLS_CC);
+
+ Registering a conflict checking function, which will be checked prior starting the handler:
+ // not possible with old API, unless hardcoding into output.c
+ php_output_handler_conflict_register(handler_name, handler_name_len, my_php_output_handler_conflict_check_t TSRMLS_CC);
+
+ Registering a reverse conflict checking function, which will be checked prior starting the specified foreign handler:
+ // not possible with old API
+ php_output_handler_reverse_conflict_register(foreign_handler_name, foreign_handler_name_len, my_php_output_handler_conflict_check_t TSRMLS_CC);
+
+ Facilitating a context from within an output handler callable with ob_start():
+ // not possible with old API
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr TSRMLS_CC);
+
+ Disabling of the output handler by itself:
+ //not possible with old API
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL TSRMLS_CC);
+
+ Marking an output handler immutable by itself because of irreversibility of its operation:
+ // not possible with old API
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
+
+ Restarting the output handler because of a CLEAN operation:
+ // not possible with old API
+ if (flags & PHP_OUTPUT_HANDLER_CLEAN) { ... }
+
+ Recognizing by the output handler itself if it gets discarded:
+ // not possible with old API
+ if ((flags & PHP_OUTPUT_HANDLER_CLEAN) && (flags & PHP_OUTPUT_HANDLER_FINAL)) { ... }
+
+
+Output handler hooks
+
+ The output handler can change its abilities at runtime. Eg. the gz handler can
+ remove the CLEANABLE and REMOVABLE bits when the first output has passed through it;
+ or handlers implemented in C to be used with ob_start() can contain a non-global
+ context:
+ PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ
+ pass a void*** pointer as second arg to receive the address of a pointer
+ pointer to the opaque field of the output handler context
+ PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS
+ pass a int* pointer as second arg to receive the flags set for the output handler
+ PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL
+ pass a int* pointer as second arg to receive the level of this output handler
+ (starts with 0)
+ PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE
+ the second arg is ignored; marks the output handler to be neither cleanable
+ nor removable
+ PHP_OUTPUT_HANDLER_HOOK_DISABLE
+ the second arg is ignored; marks the output handler as disabled
+
+
+Open questions
+
+ Should the userland API be adjusted and unified?
+
+ Many bits of the manual (and very first implementation) do not comply
+ with the behaviour of the current (to be obsoleted) code, thus should
+ the manual or the behaviour be adjusted?
+
+END
diff --git a/README.PARAMETER_PARSING_API b/README.PARAMETER_PARSING_API
index 8d297670c6..927e48188c 100644
--- a/README.PARAMETER_PARSING_API
+++ b/README.PARAMETER_PARSING_API
@@ -51,6 +51,7 @@ Type specifiers
L - long, limits out-of-range numbers to LONG_MAX/LONG_MIN (long)
o - object of any type (zval*)
O - object of specific type given by class entry (zval*, zend_class_entry)
+ p - valid path (string without null bytes in the middle) and its length (char*, int)
r - resource (zval*)
s - string (with possible null bytes) and its length (char*, int)
z - the actual zval (zval*)
diff --git a/README.RELEASE_PROCESS b/README.RELEASE_PROCESS
index b6209686c7..3fa944ee3b 100644
--- a/README.RELEASE_PROCESS
+++ b/README.RELEASE_PROCESS
@@ -50,38 +50,30 @@ Rolling a non stable release (alpha/beta/RC)
2. run the "scripts/dev/credits" script in php-src and commit the changes in the
credits files in ext/standard.
-3. Bump the version numbers in ``main/php_version.h``, ``configure.in`` and possibly ``NEWS``.
-Do not use abbreviations for alpha and beta.
-
-4. Commit those changes and note the revision id.
-
-5. tag the repository with the version. To do the tag in a fast way do a svn copy on the server using full URLs. You should use the revision id from the above commit to prevent mistakes in case there was a commit in between. f.e. "``svn cp https://svn.php.net/repository/php/php-src/branches/PHP_5_3@308399 https://svn.php.net/repository/php/php-src/tags/php_5_3_6RC1``"
-(of course, you need to change that to the version you're rolling an RC for). Mail php-internals to announce the tag so tests/validation/check can be done prior to package it. It is especially important for RCs.
+3. Checkout the release branch for this release (e.g., PHP-5.4.2).
-6. Bump up the version numbers in ``main/php_version.h``, ``configure.in``
-and possibly ``NEWS`` again, to the **next** version. F.e. if the release
-candidate was "4.4.1RC1" then the new one should be "4.4.1RC2-dev" - regardless
-if we get a new RC or not. This is to make sure ``version_compare()`` can
-correctly work.
+4. Bump the version numbers in ``main/php_version.h``, ``configure.in`` and possibly ``NEWS``.
+Do not use abbreviations for alpha and beta.
-7. Commit those changes
+5. Commit these changes to the branch with ``git commit -a``.
-8. Log in onto the snaps box and go into the correct tree (f.e. the PHP_4_4
-branch if you're rolling 4.4.x releases).
+6. Tag the repository with the version, e.g.:
+``git tag -u YOURKEYID php-5.4.2RC2``
-9. You do not have to update the tree, but of course you can with "``svn up``".
+7. Push the changes to the main repo:
+``git push --tags origin HEAD``
-10. run: ``./makedist php 4.4.1RC1``, this will export the tree, create configure
+8. run: ``./makedist 5.4.2RC2``, this will export the tree, create configure
and build two tarballs (one gz and one bz2).
-11. Copy those two tarballs to www.php.net, in your homedir there should be a
+9. Copy those two tarballs to www.php.net, in your homedir there should be a
directory "downloads/". Copy them into there, so that the system can generate
MD5 sums. If you do not have this directory, talk to Derick.
-12. Now the RC can be found on http://downloads.php.net/yourname,
+10. Now the RC can be found on http://downloads.php.net/yourname,
f.e. http://downloads.php.net/derick/
-13. Once the release has been tagged, contact the PHP Windows development team
+11. Once the release has been tagged, contact the PHP Windows development team
(internals-win@lists.php.net) so that Windows binaries can be created. Once
those are made, they should be placed into the same directory as the source snapshots.
@@ -115,7 +107,7 @@ Derick) run the following commands for you:
4. Update ``php.git/include/version.inc`` (x=major version number)
- a. ``$PHP_x_RC`` = "5.3.0RC1"
+ a. ``$PHP_x_RC`` = "5.4.0RC1"
b. ``$PHP_x_RC_DATE`` = "06 September 2007"
diff --git a/README.input_filter b/README.input_filter
index 488ca82a7b..e2941d029e 100644
--- a/README.input_filter
+++ b/README.input_filter
@@ -19,9 +19,7 @@ A simple implementation might look like the following. This stores the
original raw user data and adds a my_get_raw() function while the normal
$_POST, $_GET and $_COOKIE arrays are only populated with stripped
data. In this simple example all I am doing is calling strip_tags() on
-the data. If register_globals is turned on, the default globals that
-are created will be stripped ($foo) while a $RAW_foo is created with the
-original user input.
+the data.
ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
zval *post_array;
@@ -155,8 +153,6 @@ PHP_FUNCTION(my_get_raw)
int var_len;
zval **tmp;
zval *array_ptr = NULL;
- HashTable *hash_ptr;
- char *raw_var;
if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
return;
@@ -174,23 +170,15 @@ PHP_FUNCTION(my_get_raw)
break;
}
- if(!array_ptr) RETURN_FALSE;
-
- /*
- * I'm changing the variable name here because when running with register_globals on,
- * the variable will end up in the global symbol table
- */
- raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
- strcpy(raw_var, "RAW_");
- strlcat(raw_var,var,var_len+5);
- hash_ptr = HASH_OF(array_ptr);
+ if(!array_ptr) {
+ RETURN_FALSE;
+ }
- if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
+ if(zend_hash_find(HASH_OF(array_ptr), var, var_len+5, (void **)&tmp) == SUCCESS) {
*return_value = **tmp;
zval_copy_ctor(return_value);
} else {
RETVAL_FALSE;
}
- efree(raw_var);
}
diff --git a/TODO b/TODO
deleted file mode 100644
index c3c5fab8da..0000000000
--- a/TODO
+++ /dev/null
@@ -1,136 +0,0 @@
-Things to do or at least think about doing in the future. Name in
-parenthesis means that person has taken on this project.
-
-Zend
-----
- * Allow foreach ($array as $k => list($a, $b)) syntax for multi
- dimensional arrays.
- * Look at replacing c-lib call tolower().
- * Make hash API functions work with HASH_OF() to save time.
- * Native large number support (probably with GNU GMP)
- * Const'ify APIs. Right now, many functions leave parameters untouched,
- but don't declare those as const. This makes interaction with other
- interfaces difficult which pass const parameters to us.
-
-
-global
-------
- * Make sure that all ZTS globals get destructed. Most ts_allocate_id()
- calls should have a dtor entry.
- * on some platforms unimplemented function will just do nothing
- (e.g. symlink) they should print a warning or not even be defined!
- (DONE ?)
- * --enable-all in configure. (--enable-shared=max ...)
- * make configure print out a summary when it's done (like XEmacs)
- * replace standard functions which work on static data with
- reentrancy-safe functions (DONE?).
- * make SAPI conform to CGI/1.1. Currently, all SAPI modules
- define REMOTE_ADDR etc. themselves and reach only various level
- of compliance.
- * see what functions might need to be changed to use HashPosition, so
- that the internal array pointer is not affected.
- * Move most extensions and PEAR packages out of the PHP CVS tree,
- include them again during release packaging.
-
- Other
- * use thread-safe resolver functions (either require BIND 8 or adns).
- * implement javadoc based function docs template system.
- * provide optional IPv6 support (seems to be done?).
- * find a better way to implement script timeouts. SIGVTALRM is used
- by some POSIX threads implementations (i.e. OpenBSD) and is not
- available in ZTS mode.
- * Implement flush feature suitable for nested output buffers.
-
-Streams
--------
- * Route filestat.c through the wrapper layer; isolate the statcache code
- so that it is independent of php functions and can be applied to any
- stream/path.
- * Implement generalized connection pool for stated protocols such as
- ftp and http/1.1 (using keep-alive) to avoid having to negotiate
- new command/request stream for each subsequent call; Possibly store
- resources in contexts (creating a default context if necessary) to
- allow segmentation of connection pools.
- * Add a method to take ownership of the memory buffer in memory streams so
- that generating string values for zvals doesn't require an estrdup.
- * bundle and use curl lib for fopen wrapper.
-
-documentation
--------------
- * Add remarks in the documentation which functions are not implemented
- on win32.
- * Add remarks in the documentation which functions are not binary-safe.
- * Update curl documentation (DONE?)
- * Add developer documentation.
- * Add detailed documentation for Java extension.
-
-ext/curl
---------
- * Have a warning scheme for when people use unsupported features.
-
-ext/oci8
---------
- * All OCIFetch*() functions should return 0 for no more data and false on
- error.
- * Have a flag that trims trailing spaces from CHAR fields on retrieval.
- * Make allow_call_time_pass_reference=Off working.
- * For additional todo information, see oci8.c, in ext/oci8
-
-ext/odbc
---------
- For PHP 4.3.0:
- * update all php_error calls to php_error_docref where valid
- * integrate EXPERIMENTAL ODBC update for use in PHP 5.0, use for
- testing purposes only.
-
- For PHP 5.0.0
- * Activate EXPERIMENTAL ODBC codebase update
-
-ext/pcre
---------
- * Allow user to set PCRE_NOTEMPTY, PCRE_ANCHORED at execution time, maybe
-
-ext/pcntl
----------
- * Change internal callback handler to use TICKS
- * Remove all zend_extension code
- * Add object callback support to pcntl_signal()
-
-ext/session
------------
- For PHP 4.3.0:
- * session_abort() to abort session. ie: Do not save session data.
- * Allow unset($_SESSION) or unset($HTTP_SESSION_VARS) to unset
- session vars regardless of register_globals setting.
-
- Other:
- * Maybe implement finer-grained session variables that could be
- locked individually.
- * Write a network-transparent storage back-end with fallover
- facilities
- * Provide a callback facility which is executed upon encountering
- an unknown class name during deserialization
-
-ext/standard
-------------
- * Add a version number to data serialized via serialize().
- * Possibly modify parsing of GPC data to automatically create arrays if
- variable name is seen more than once.
- * Implement regex-cache for url-functions.
- * Move socket related functions to fsock.c.
-
-ext/wddx
---------
- * See if we can support the remaining data types:
- binary
-
- http://www.wddx.org/WDDX_SDK_10a/7__References/WDDX_DTD.htm
- (Andrei)
-
- * implement wddx_packet_as_javascript(). (Andrei)
-
-other cool stuff
-----------------
- * PVM extension
-
-vim:et:sw=4:ts=4
diff --git a/TODO-5.1 b/TODO-5.1
deleted file mode 100644
index d2690f6e3b..0000000000
--- a/TODO-5.1
+++ /dev/null
@@ -1,4 +0,0 @@
-Zend Engine
------------
- - Look at making zend_constant value member be a zval* instead of zval. (Andi)
- - Implement inheritance rules for type hints. (Marcus)
diff --git a/TODO-PHP5 b/TODO-PHP5
deleted file mode 100644
index 1bb22e2bda..0000000000
--- a/TODO-PHP5
+++ /dev/null
@@ -1,89 +0,0 @@
-Component: Zend Engine 2
-
- Important stuff to finish: PPP members/PPP methods,
- support of overloaded extensions, possibly differentiate
- between class and namespace as discussed with Stig in
- Germany.
-Responsibility: Zeev, Andi, Stas
-Time frame: Couple of months for first part and extensions will be
- ongoing while PHP is being fixed.
- Things to leave for later versions: Native aggregation
- support, accessing static members via object and not class.
-
-
-Component: Aggregation
-Responsibility: Andi, Stig?
-Time frame: ?
-
-
-Component: Redesign of API Versioning
-Responsibility: ?
-Time frame: 1 month
-
-
-Component: Thread Safety
- Identify the extensions that are not thread safe by design
- or due to dependant libraries and identify them as such.
- If possible try to resolve thread safety issue via code
- improvements (if php code or patches will be accepted by
- library maintainers). For situations where thread safety
- cannot easily be acheived a flag in the extension API is
- set so PHP can identify non-thread safe extensions. These
- extensions will not be loaded in a ZTS compiled binary
- (unless it is cli/cgi).
-
-Responsibility: ?
-Time frame: ?
-
-
-Component: SAPI
- Environment variables defined in the CGI spec need to be
- verified in each SAPI module that they conform to the CGI
- spec correctly. If they do not, the SAPI module needs to
- fix the variable prior to script execution. Having this
- conformity will aid in having PHP scripts run correctly
- under different sapi modules.
-
-Responsibility: Shane Caraveo & each sapi module owner
-Timeframe: ? (but shouldn't be much effort, most modules are probably ok)
-
-
-Component: RPC Abstraction Layer
- Porting java, com, dotnet, xmlrpc, corba, soap and python, srm
- (are there more ?) to work with the new oo api and preferably
- by using ext/rpc.
-Responsibility: Harald
-Time frame: 2 months (but i have to wait for a few engine features first)
-
-
-Component: OO Extensions
- Each OO extension has to be revised and rewritten to fit into
- the new OO model. We should decide which extensions are a must
- to have for the release and which can be ported by the maintainer
- later as a separate pecl release.
- A list of extensions to be extended that have to be investigated:
- * browscap
- * aggregate
- * all *sql extensions (*_fetch_object)
- * domxml (seems like christian is rewriting it anyways)
- * ming
-Responsibility: Harald (, extension maintainers)
-
-
-Component: Abstract Data Types (ADT)
-Responsibility: Sterling, Harald
-Time frame: ?
-
-
-Component: Test Suite
- Extending the test suite with atleast a test for every
- function in an extension that doesn't require external
- resources. Also developing an automated test thing which
- cvs ups's, compiles and tests the build on a daily base on
- as much platforms/extensions as possible.
-
- The test suite will also be extended to support threaded
- testing and testing for differing sapi modules (via http
- calls or other methods).
-Reponsibility: Derick (, extension maintainers)
-Time frame: 3 months
diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c
index 41368a4987..efdea5c880 100644
--- a/TSRM/TSRM.c
+++ b/TSRM/TSRM.c
@@ -710,6 +710,22 @@ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
#endif
}
+/*
+ Changes the signal mask of the calling thread
+*/
+#ifdef HAVE_SIGPROCMASK
+TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+ TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Changed sigmask in thread: %ld", tsrm_thread_id()));
+ /* TODO: add support for other APIs */
+#ifdef PTHREADS
+ return pthread_sigmask(how, set, oldset);
+#else
+ return sigprocmask(how, set, oldset);
+#endif
+}
+#endif
+
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler)
{
diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h
index d3d6f9b2d7..b232429d4d 100644
--- a/TSRM/TSRM.h
+++ b/TSRM/TSRM.h
@@ -90,6 +90,10 @@ typedef struct {
# define MUTEX_T beos_ben *
#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
typedef void (*ts_allocate_ctor)(void *, void ***);
typedef void (*ts_allocate_dtor)(void *, void ***);
@@ -138,6 +142,9 @@ TSRM_API MUTEX_T tsrm_mutex_alloc(void);
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp);
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp);
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp);
+#ifdef HAVE_SIGPROCMASK
+TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset);
+#endif
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler);
TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler);
diff --git a/TSRM/acconfig.h b/TSRM/acconfig.h
deleted file mode 100644
index 2b94cf35e7..0000000000
--- a/TSRM/acconfig.h
+++ /dev/null
@@ -1 +0,0 @@
-#undef PTHREADS
diff --git a/TSRM/build.mk b/TSRM/build.mk
index aac1a8b982..f5756af72c 100644
--- a/TSRM/build.mk
+++ b/TSRM/build.mk
@@ -33,7 +33,7 @@ $(makefile_in_files): $(makefile_am_files)
aclocal.m4: configure.in acinclude.m4
aclocal
-$(config_h_in): configure.in acconfig.h
+$(config_h_in): configure.in
# explicitly remove target since autoheader does not seem to work
# correctly otherwise (timestamps are not updated)
@rm -f $@
diff --git a/TSRM/configure.in b/TSRM/configure.in
index acfdd00b35..6f10f5ab13 100644
--- a/TSRM/configure.in
+++ b/TSRM/configure.in
@@ -7,6 +7,10 @@ AC_INIT(TSRM.c)
AM_INIT_AUTOMAKE(TSRM, 1.0, nodefine)
AM_CONFIG_HEADER(tsrm_config.h)
+AH_TOP([
+#undef PTHREADS
+])
+
sinclude(tsrm.m4)
TSRM_BASIC_CHECKS
diff --git a/TSRM/tsrm.m4 b/TSRM/tsrm.m4
index 85e6a83a83..b53a4bb805 100644
--- a/TSRM/tsrm.m4
+++ b/TSRM/tsrm.m4
@@ -30,6 +30,8 @@ AC_REQUIRE([AC_PROG_RANLIB])dnl
AC_CHECK_HEADERS(stdarg.h)
+AC_CHECK_FUNCS(sigprocmask)
+
])
diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c
index e734406837..683d6a4d52 100644
--- a/TSRM/tsrm_virtual_cwd.c
+++ b/TSRM/tsrm_virtual_cwd.c
@@ -277,18 +277,6 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){
}
/* }}} */
-CWD_API int php_sys_stat(const char *path, struct stat *buf) /* {{{ */
-{
- return php_sys_stat_ex(path, buf, 0);
-}
-/* }}} */
-
-CWD_API int php_sys_lstat(const char *path, struct stat *buf) /* {{{ */
-{
- return php_sys_stat_ex(path, buf, 1);
-}
-/* }}} */
-
CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat) /* {{{ */
{
WIN32_FILE_ATTRIBUTE_DATA data;
@@ -718,7 +706,6 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p
} else {
CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + r->path_len + 1 + r->realpath_len + 1;
}
-
free(r);
} else if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
memcmp(path, (*bucket)->path, path_len) == 0) {
@@ -1152,7 +1139,7 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
/* Resolve path relatively to state and put the real path into state */
/* returns 0 for ok, 1 for error */
-CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath) /* {{{ */
+CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath TSRMLS_DC) /* {{{ */
{
int path_length = strlen(path);
char resolved_path[MAXPATHLEN];
@@ -1162,7 +1149,6 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
int ret;
int add_slash;
void *tmp;
- TSRMLS_FETCH();
if (path_length == 0 || path_length >= MAXPATHLEN-1) {
#ifdef TSRM_WIN32
@@ -1363,7 +1349,7 @@ verify:
CWD_API int virtual_chdir(const char *path TSRMLS_DC) /* {{{ */
{
- return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH)?-1:0;
+ return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH TSRMLS_CC)?-1:0;
}
/* }}} */
@@ -1431,7 +1417,7 @@ CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC) /* {
new_state.cwd_length = 0;
}
- if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)==0) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH TSRMLS_CC)==0) {
int len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;
memcpy(real_path, new_state.cwd, len);
@@ -1453,7 +1439,7 @@ CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_f
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH);
+ retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH TSRMLS_CC);
*filepath = new_state.cwd;
@@ -1478,7 +1464,7 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC) /* {{{
}
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return NULL;
}
@@ -1496,13 +1482,13 @@ CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC) /* {{{ */
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
#if defined(TSRM_WIN32)
- ret = tsrm_win32_access(new_state.cwd, mode);
+ ret = tsrm_win32_access(new_state.cwd, mode TSRMLS_CC);
#else
ret = access(new_state.cwd, mode);
#endif
@@ -1569,7 +1555,7 @@ CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC) /
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1592,7 +1578,7 @@ CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC) /* {{{ */
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1611,7 +1597,7 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1638,7 +1624,7 @@ CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...) /* {{{ */
int f;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1666,7 +1652,7 @@ CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC) /* {{{ */
int f;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1685,14 +1671,14 @@ CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC) /* {{{ */
int retval;
CWD_STATE_COPY(&old_state, &CWDG(cwd));
- if (virtual_file_ex(&old_state, oldname, NULL, CWD_EXPAND)) {
+ if (virtual_file_ex(&old_state, oldname, NULL, CWD_EXPAND TSRMLS_CC)) {
CWD_STATE_FREE(&old_state);
return -1;
}
oldname = old_state.cwd;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, newname, NULL, CWD_EXPAND)) {
+ if (virtual_file_ex(&new_state, newname, NULL, CWD_EXPAND TSRMLS_CC)) {
CWD_STATE_FREE(&old_state);
CWD_STATE_FREE(&new_state);
return -1;
@@ -1721,7 +1707,7 @@ CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ */
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1739,7 +1725,7 @@ CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC) /* {{{ *
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1757,7 +1743,7 @@ CWD_API int virtual_unlink(const char *path TSRMLS_DC) /* {{{ */
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1775,7 +1761,7 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC) /* {{{ */
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1796,7 +1782,7 @@ CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC) /* {{{ */
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return -1;
}
@@ -1818,7 +1804,7 @@ CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC) /* {{{ */
DIR *retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH TSRMLS_CC)) {
CWD_STATE_FREE(&new_state);
return NULL;
}
@@ -1833,7 +1819,7 @@ CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC) /* {{{ */
#ifdef TSRM_WIN32
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) /* {{{ */
{
- return popen_ex(command, type, CWDG(cwd).cwd, NULL);
+ return popen_ex(command, type, CWDG(cwd).cwd, NULL TSRMLS_CC);
}
/* }}} */
#elif defined(NETWARE)
@@ -1956,7 +1942,7 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC) /* {{{
new_state.cwd_length = 0;
}
- if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH TSRMLS_CC)) {
free(new_state.cwd);
return NULL;
}
diff --git a/TSRM/tsrm_virtual_cwd.h b/TSRM/tsrm_virtual_cwd.h
index c13e88d592..2c4085894f 100644
--- a/TSRM/tsrm_virtual_cwd.h
+++ b/TSRM/tsrm_virtual_cwd.h
@@ -131,8 +131,8 @@ typedef unsigned short mode_t;
#ifdef TSRM_WIN32
CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat);
-CWD_API int php_sys_stat(const char *path, struct stat *buf);
-CWD_API int php_sys_lstat(const char *path, struct stat *buf);
+# define php_sys_stat(path, buf) php_sys_stat_ex(path, buf, 0)
+# define php_sys_lstat(path, buf) php_sys_stat_ex(path, buf, 1)
CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len);
#else
# define php_sys_stat stat
@@ -201,7 +201,7 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li
#define CWD_FILEPATH 1 /* resolve symlinks if file is exist otherwise expand */
#define CWD_REALPATH 2 /* call realpath(), resolve symlinks. File must exist */
-CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath);
+CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath TSRMLS_DC);
CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC);
@@ -267,7 +267,7 @@ CWD_API realpath_cache_bucket** realpath_cache_get_buckets(TSRMLS_D);
#define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path TSRMLS_CC)
#define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname TSRMLS_CC)
#define VCWD_STAT(path, buff) virtual_stat(path, buff TSRMLS_CC)
-#define VCWD_LSTAT(path, buff) virtual_lstat(path, buff TSRMLS_CC)
+# define VCWD_LSTAT(path, buff) virtual_lstat(path, buff TSRMLS_CC)
#define VCWD_UNLINK(path) virtual_unlink(path TSRMLS_CC)
#define VCWD_MKDIR(pathname, mode) virtual_mkdir(pathname, mode TSRMLS_CC)
#define VCWD_RMDIR(pathname) virtual_rmdir(pathname TSRMLS_CC)
@@ -310,7 +310,7 @@ CWD_API realpath_cache_bucket** realpath_cache_get_buckets(TSRMLS_D);
#define VCWD_OPENDIR(pathname) opendir(pathname)
#define VCWD_POPEN(command, type) popen(command, type)
#if defined(TSRM_WIN32)
-#define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode)
+#define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode TSRMLS_CC)
#else
#define VCWD_ACCESS(pathname, mode) access(pathname, mode)
#endif
diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c
index 9e029f60af..b40af77c44 100644
--- a/TSRM/tsrm_win32.c
+++ b/TSRM/tsrm_win32.c
@@ -190,7 +190,7 @@ Finished:
return NULL;
}
-TSRM_API int tsrm_win32_access(const char *pathname, int mode)
+TSRM_API int tsrm_win32_access(const char *pathname, int mode TSRMLS_DC)
{
time_t t;
HANDLE thread_token;
@@ -208,8 +208,6 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
realpath_cache_bucket * bucket = NULL;
char * real_path = NULL;
- TSRMLS_FETCH();
-
if (mode == 1 /*X_OK*/) {
DWORD type;
return GetBinaryType(pathname, &type) ? 0 : -1;
@@ -448,10 +446,12 @@ static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
TSRM_API FILE *popen(const char *command, const char *type)
{
- return popen_ex(command, type, NULL, NULL);
+ TSRMLS_FETCH();
+
+ return popen_ex(command, type, NULL, NULL TSRMLS_CC);
}
-TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
+TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env TSRMLS_DC)
{
FILE *stream = NULL;
int fno, type_len = strlen(type), read, mode;
@@ -469,8 +469,6 @@ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd,
HANDLE token_user = NULL;
BOOL asuser = TRUE;
- TSRMLS_FETCH();
-
if (!type) {
return NULL;
}
diff --git a/TSRM/tsrm_win32.h b/TSRM/tsrm_win32.h
index 4e645b2d54..56835f802b 100644
--- a/TSRM/tsrm_win32.h
+++ b/TSRM/tsrm_win32.h
@@ -95,10 +95,10 @@ char * tsrm_win32_get_path_sid_key(const char *pathname TSRMLS_DC);
TSRM_API void tsrm_win32_startup(void);
TSRM_API void tsrm_win32_shutdown(void);
-TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env);
+TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env TSRMLS_DC);
TSRM_API FILE *popen(const char *command, const char *type);
TSRM_API int pclose(FILE *stream);
-TSRM_API int tsrm_win32_access(const char *pathname, int mode);
+TSRM_API int tsrm_win32_access(const char *pathname, int mode TSRMLS_DC);
TSRM_API int win32_utime(const char *filename, struct utimbuf *buf);
TSRM_API int shmget(int key, int size, int flags);
diff --git a/UPGRADING b/UPGRADING
index 9d62054bd6..68102b8447 100755
--- a/UPGRADING
+++ b/UPGRADING
@@ -1,705 +1,815 @@
$Id$
-UPGRADE NOTES - PHP 5.3
-
-1. Reserved words and classes
-2. Changes made to existing functions
-3. Changes made to existing methods
-4. Changes made to existing classes
-5. Deprecated
-6. Undeprecated
-7. Extensions:
- a. moved out to PECL and actively maintained there
- b. no longer maintained
- c. with changed behaviour
- d. no longer possible to disable
-8. Changes in SAPI support
-9. Changes in INI directives
-10. Syntax additions
+PHP 5.4 UPGRADE NOTES
+
+===========
+0. Contents
+===========
+
+1. Changes to INI directives
+2. Changes to reserved words and classes
+3. Changes to engine behavior
+4. Changes to existing functions
+5. Changes to existing classes
+6. Changes to existing methods
+7. Deprecated Functionality
+8. Removed Functionality
+ a. Removed features
+ b. Removed functions
+ c. Removed syntax
+ d. Removed hash algorithms
+9. Extension Changes:
+ a. Extensions no longer maintained
+ b. Extensions with changed behavior
+10. Changes in SAPI support
11. Windows support
-12. New in PHP 5.3:
- a. New libraries
- b. New extensions
- c. New stream wrappers
- d. New stream filters
- e. New functions
- f. New global constants
- g. New classes
- h. New methods
- i. New class constants
+12. New in PHP 5.4:
+ a. New features
+ b. Syntax additions
+ c. New functions
+ d. New global constants
+ e. New classes
+ f. New methods
+ g. New hash algorithms
=============================
-1. Reserved words and classes
+1. Changes to INI directives
=============================
-- **namespace** and **goto** are now reserved keywords.
+- PHP 5.4 now checks at compile time if /dev/urandom or /dev/arandom
+ are present. If either is available, session.entropy_file now
+ defaults to that file and session.entropy_length defaults to 32.
+ This provides non-blocking entropy to session id generation. If you
+ do not want extra entropy for your session ids, add:
+
+ session.entropy_file=
+ session.entropy_length=0
+
+ to your php.ini to preserve pre-PHP 5.4 behavior.
+
+- Deprecated php.ini directives will now throw an E_CORE_WARNING's
+ instead of the previous E_WARNING's.
+
+- The following php.ini directives are no longer available in PHP 5.4
+ and will now throw an E_CORE_ERROR upon startup:
+ - allow_call_time_pass_reference
+ - define_syslog_variables
+ - highlight.bg
+ - magic_quotes_gpc
+ - magic_quotes_runtime
+ - magic_quotes_sybase
+ - register_globals
+ - register_long_arrays
+ - safe_mode
+ - safe_mode_gid
+ - safe_mode_include_dir
+ - safe_mode_exec_dir
+ - safe_mode_allowed_env_vars
+ - safe_mode_protected_env_vars
+ - session.bug_compat_42
+ - session.bug_compat_warn
+ - y2k_compliance
+ - zend.ze1_compatibility_mode
+
+- the following new php.ini directives were added:
+ - max_input_vars - specifies how many GET/POST/COOKIE input
+ variables may be accepted. The default value is 1000.
+
+- E_ALL now includes E_STRICT.
+
+- The recommended production value for error_reporting changed to E_ALL &
+ ~E_DEPRECATED & ~E_STRICT.
+
+- Added new session support directives:
+ session.upload_progress.enabled
+ session.upload_progress.cleanup
+ session.upload_progress.prefix
+ session.upload_progress.name
+ session.upload_progress.freq
+ session.upload_progress.min_freq
+
+- Added a zend.multibyte directive as a replacement of the PHP compile time
+ configuration option --enable-zend-multibyte. Now the Zend Engine always
+ contains code for multibyte support, which can be enabled or disabled at
+ runtime. Note: It doesn't make a lot of sense to enable this option if
+ ext/mbstring is not enabled, because most functionality is implemented by
+ mbstrings callbacks.
+
+- Added zend.script_encoding. This value will be used unless a
+ "declare(encoding=...)" directive appears at the top of the script.
+
+- Added zend.signal_check to check for replaced signal handlers on shutdown
+
+- Added enable_post_data_reading, which is enabled by default. When it's
+ disabled, the POST data is not read (or processed); the behavior is similar
+ to that of other request methods with body, like PUT. This allows reading
+ the raw POST data in multipart requests and reading/processing the POST data
+ in a stream fashion (through php://input) without having it copied in memory
+ multiple times.
+
+- Added windows_show_crt_warning. This directive shows the CRT warnings when
+ enabled. These warnings were displayed by default until now. It is disabled
+ by default.
+
+- Added cli.pager to set a pager for CLI interactive shell output.
+
+- Added cli.prompt to configure the CLI interactive shell prompt.
+
+- Added cli_server.color to enable the CLI web server to use ANSI color coding
+ in terminal output.
+
+========================================
+2. Changes to reserved words and classes
+========================================
+
+- "callable", "insteadof" and "trait" are now reserved words.
-- **Closure** is now a reserved class. (Used by lambda and closure.)
-
-=====================================
-2. Changes made to existing functions
-=====================================
-
-- Paths containing NULL (like /some/path\0foo.txt) are now considered invalid.
- See http://news.php.net/php.internals/50191
-
-- The HTTP stream wrapper now considers all status codes from 200 to 399 to be
- successful.
-
-- The array functions natsort(), natcasesort(), usort(), uasort(), uksort(),
- array_flip(), and array_unique() no longer accept objects passed as arguments.
- If you need to use them to access an object's properties, you must cast the
- object to an array first.
-
-- var_dump() output now includes private object members.
-
-- session_start() now returns FALSE when the session startup fails.
-
-- property_exists() now checks the existence of a property independent of
- accessibility (like method_exists()).
-
-- The $initial parameter for array_reduce can now be of any type.
-
-- clearstatcache() no longer clears the realpath cache by default.
-
-- realpath() is no longer system-dependent and works identically on all
- platforms.
-
-- call_user_func() now propagates $this even if the callee is the parent class.
-
-- The filesystem functions opendir(), scandir(), and dir() now use the default
- context if no context argument is passed.
-
-- The behaviour of functions with by-reference parameters called by value has
- changed. Where previously the function would accept the by-value argument, a
- warning is now emitted and all by-ref parameters are set to NULL.
-
-- There is now native support for the following math functions: asinh(),
- acosh(), atanh(), log1p(), and expm1().
-
-- In the GD extension, there is now pixelation support available through
- the imagefilter() function.
-
-- crypt() now has Blowfish and extended DES support, and crypt() features are
- now 100% portable. PHP has its own internal crypt implementation which drops
- into place when system support for crypt or crypt_r() is not found.
-
-- get_cfg_var() is now able to return "array" INI options.
-
-- Stream wrappers can now be used by the include_path INI directive.
+=============================
+3. Changes to engine behavior
+=============================
-- These functions now take new parameters:
- clearstatcache(): $clear_realpath_cache and $filename.
- copy(): $context
- fgetcsv(): $escape
- ini_get_all(): $details
- json_encode(): $options
- json_decode(): $depth
- nl2br(): $is_xhtml
- parse_ini_file(): $scanner_mode
- round(): $mode
- stream_context_create(): $params
- strstr(), stristr(): $before_needle
- sybase_connect(): $new
+- The __construct arguments of an extended abstract constructor must
+ now match:
-- And new mode option for fopen: 'n' (O_NONBLOCK)
+ abstract class Base
+ {
+ abstract public function __construct();
+ }
+ class Foo extends Base
+ {
+ public function __construct($bar) {}
+ }
-- The new mysqlnd library necessitates using MySQL's newer 41-byte password
- format. Continued use of the old 16 byte passwords will cause mysql_connect()
- and other related functions to produce the following error message:
- "mysqlnd cannot connect to MySQL 4.1+ using old authentication"
+ This now emits a Fatal error due the incompatible declaration.
-- The dl() function is now disabled by default, and only available under the
- cli, cgi, and embed SAPIs.
+- In previous versions, superglobal names could be used for parameter
+ names, thereby shadowing the corresponding superglobal. In PHP 5.4
+ this now causes a fatal error such as "Cannot re-assign auto-global
+ variable GLOBALS".
+
+- Turning null, false or an empty string into an object by adding a
+ property will now emit a warning instead of an E_STRICT error.
-- mail() now supports the logging of sent mail.
+ $test = null;
+ $test->baz = 1;
-- stream_select(), stream_set_blocking(), stream_set_timeout(), and
- stream_set_write_buffer() now work with user-space stream wrappers.
+ To create a generic object you can use StdClass:
-- getopt() accepts "long options" now on all platforms.
- Optional values and using = as a separator for short options are now
- supported.
+ $test = new StdClass;
+ $test->baz = 1;
+- Converting an array to a string now will cause an E_NOTICE warning.
-===================================
-3. Changes made to existing methods
-===================================
+- Non-numeric string offsets, e.g. $a['foo'] where $a is a string, now
+ return false on isset() and true on empty(), and produce warning if
+ trying to use them. Offsets of types double, bool and null produce
+ notice. Numeric strings ($a['2']) still work as before.
-- The magic methods __get(), __set(), __isset(), __unset(), and __call() should
- always be public and can no longer be static. Method signatures are enforced.
+ Note that offsets like '12.3' and '5 and a half' are considered
+ non-numeric and produce warning, but are converted to 12 and 5
+ respectively for backwards compatibility reasons.
-- The __call() magic method is now invoked on access to private and protected
- methods.
+- Long numeric strings that do not fit in integer or double (such as
+ "92233720368547758070") are compared using string comparison if
+ they could otherwise result in precision loss - since 5.4.4.
-- The __toString() magic method can no longer accept arguments.
+- Closures now support scopes and $this and can be rebound to
+ objects using Closure::bind() and Closure::bindTo().
-- There is a new magic method, __callStatic().
+- <?= is now always available regardless of the short_open_tag
+ setting.
-- Internal count() vs. count_elements() handler resolution rules have changed.
- (This could potentially break custom PHP extensions.)
+- Parse error messages are changed to contain more information about
+ the error.
-- The trailing / has been removed from SplFileInfo and other related directory
- classes.
+- __clone and __destruct since 5.4.4 follow the same scoping rules as
+ the rest of the methods (see bug #61782 for details).
-- SplFileInfo::getpathinfo() now returns information about the path name.
+================================
+4. Changes to existing functions
+================================
-- There are new parameters in:
- Exception::__construct(): $previous
+- array_combine now returns array() instead of FALSE when two empty arrays are
+ provided as parameters.
-===================================
-4. Changes made to existing classes
-===================================
+- dns_get_record() has an extra parameter which allows requesting DNS records
+ by numeric type and makes the result include only the raw data of the
+ response.
-- SplObjectStorage now has ArrayAccess support. It is also now possible to
- store associative information with objects in SplObjectStorage.
-
-=====================
-4.1 New in PHP 5.3.9
-=====================
+- call_user_func_array() no longer allows call-time pass by reference.
-- Write operations within XSLT (for example with the extension sax:output) are
- disabled by default. You can define what is forbidden with the INI option
- xsl.security_prefs. This option will be marked as deprecated in 5.4 again.
- Use the method XsltProcess::setSecurityPrefs($options) there.
+- the default character set for htmlspecialchars() and htmlentities() is
+ now UTF-8. In previous versions it was ISO-8859-1. Note that changing
+ your output charset via the php.ini default_charset directive does not
+ affect htmlspecialchars/htmlentities unless you are passing "" (an
+ empty string) as the encoding parameter to your htmlspecialchars/htmlentities
+ calls.
-- the following new directives were added
+- htmlentities() and htmlspecialchars() are stricter in the code units they
+ accept for the asian encodings. For Big5-HKSCS, the octets 0x80 and 0xFF are
+ rejected. For GB2312/EUC-CN, the octets 0x8E, 0x8F, 0xA0 and 0xFF are
+ rejected. For SJIS, the octets 0x80, 0xA0, 0xFD, 0xFE and 0xFF are rejected,
+ except maybe after a valid starting byte. For EUC-JP, the octets 0xA0 and
+ 0xFF are rejected.
- - max_input_vars - specifies how many GET/POST/COOKIE input variables may be
- accepted. default value 1000.
+- htmlentities() now emits an E_STRICT warning when used with asian characters,
+ as in that case htmlentities has (and already had before this version) the
+ same functionality as htmlspecialchars.
-=============
-5. Deprecated
-=============
+- htmlentities() no longer numerically encodes high characters for single-byte
+ encodings (except when there's actually a corresponding named entity). This
+ behavior was not documented and was inconsistent with that for "UTF-8".
-- define_syslog_variables() is deprecated.
+- html_entity_decode() and htmlspecialchars_decode() behave more consistently,
+ now decoding entities in malformed strings such as "&&amp;" or "&#&amp;".
-- set_socket_blocking() is deprecated.
+- htmlentities(), htmlspecialchars(), html_entity_decode(), and
+ htmlspecialchars_decode: Added the flags ENT_HTML401, ENT_XML1, ENT_XHTML,
+ and ENT_HTML5. The behavior of these functions including, but not limited to,
+ the characters that are encoded and the entities that are decoded depend on
+ the document type that is specified by those flags.
-- call_user_method() and call_user_method_array() are now deprecated. Use
- call_user_func() and call_user_func_array() instead.
+- htmlentities() and htmlspecialchars() with !$double_encode do more strict
+ checks on the validity of the entities. Numerical entities are checked for a
+ valid range (0 to 0x10FFFF); if the flag ENT_DISALLOWED is given, the
+ validity of such numerical entity in the target document type is also
+ checked. Named entities are checked for necessary existence in the target
+ document type instead of only checking whether they were constituted by
+ alphanumeric characters.
-- dl() is deprecated.
+- The flag ENT_DISALLOWED was added. In addition to the behavior described in
+ the item before, it also makes htmlentities() and htmlspecialchars()
+ substitute characters that appear literally in the argument string and which
+ are not allowed in the target document type with U+FFFD (UTF-8) or &#xFFFD;.
-- The set_magic_quotes_runtime() function is now deprecated.
+- The flag ENT_SUBSTITUTE was added. This flag makes invalid multibyte
+ sequences be replaced by U+FFFD (UTF-8) or &#FFFD; by htmlspecialchars() and
+ htmlentities(). It is an alternative to the default behavior, which just
+ returns an empty string and to ENT_IGNORE, which is a security risk. The
+ behavior follows the recommendations of Unicode Technical Report #36.
-- mysql_listtables(), mysql_dropdb(), mysql_createdb(), mysql_list_tables(),
- mysql_drop_db(), and mysql_create_db() are now deprecated.
+- htmlspecialchars_decode() and html_entity_decode() now decode &apos; if the
+ document type is ENT_XML1, ENT_XHTML, or ENT_HTML5.
-- All ereg functions are now deprecated and emit E_DEPRECATED errors:
- sql_regcase(), spliti(), split(), ereg_replace(), eregi(),
- ereg_replace(), and ereg().
- Use the PCRE family of functions (preg_*()) instead.
+- Charset detection with $charset == '' no longer turns to mbstring's
+ internal encoding defined through mb_internal_encoding(). Only the encoding
+ defined through the php.ini setting mbstring.internal_encoding is considered.
-- mcrypt_generic_end() is deprecated.
+- number_format() no longer truncates multibyte decimal points and thousand
+ separators to the first byte.
-- mysql_db_query() is deprecated.
+- The third parameter ($matches) to preg_match_all() is now optional. If
+ omitted, the function will simply return the number of times the pattern was
+ matched in the subject and will have no other side effects.
-- mysql_escape_string() is deprecated.
+- The second argument of scandir() now accepts SCANDIR_SORT_NONE (2) as a
+ possible value. This value results in scandir() performing no sorting: on
+ local filesystems, this allows files to be returned in native filesystem
+ order.
-- session_register(), session_unregister(), and session_is_registered() are now
- deprecated. Use the $_SESSION superglobal array instead.
+- stream_select() now preserves the keys of the passed array, be they numeric or
+ strings. This breaks code that iterated the resulting stream array using a
+ numeric index, but makes easier to identify which of the passed streams are
+ present in the result.
-- Comments starting with '#' are now deprecated in .INI files.
+- stream_set_write_buffer() no longer disables the read buffer of a plain
+ stream when 0 is given as the second argument.
-- The following INI directives will now emit an E_DEPRECATED warning
- upon startup if they are activated:
+- stream_set_write_buffer() no longer changes the chunk size in socket streams.
- - define_syslog_variables
- - register_globals
- - register_long_arrays
- - safe_mode
- - magic_quotes_gpc
- - magic_quotes_runtime
- - magic_quotes_sybase
+- fclose() closes streams with resource refcount > 1; it doesn't merely
+ decrement the resource refcount.
-- The is_dst parameter to mktime() is deprecated.
+- socket_set_options() and socket_get_options() now support multicast options.
-- Assigning the return value of "new" by reference is deprecated
+- The raw data parameter in openssl_encrypt() and openssl_decrypt() is now an
+ options integer rather than a boolean. A value of true produces the same
+ behavior.
-- Call-time pass-by-reference has been deprecated
+- Write operations within XSLT (for example with the extension sax:output) are
+ disabled by default. You can define what is forbidden with the method
+ XsltProcess::setSecurityPrefs($options).
-- Usage of {} to access string offsets is deprecated
+- Added AES support to OpenSSL.
-- Passing locale category name as string to setlocale() is deprecated.
+- openssl_csr_new() expects the textual data to be in UTF-8.
-===============
-6. Undeprecated
-===============
+- Added no-padding option to openssl_encrypt() and openssl_decrypt().
-- By popular request, is_a() is no longer deprecated.
+- Added a "no_ticket" SSL context option to disable the SessionTicket TLS
+ extension.
-==============
-7. Extensions:
-==============
+- Added new json_encode() options: JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES,
+ JSON_NUMERIC_CHECK, JSON_BIGINT_AS_STRING, JSON_UNESCAPED_UNICODE.
- a. moved out to PECL and actively maintained there
+- Added Tokyo Cabinet and Berkley DB 5 support to DBA extension.
- - fdf
- - ming
- - ncurses
+- Added support for CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE
+ to cURL.
- b. no longer maintained
+- Added optional argument to debug_backtrace() and debug_print_backtrace()
+ to limit the amount of stack frames returned.
- - dbase
- - fbsql
- - msql
- - sybase (use sybase_ct, which is still in PHP core)
- - mhash (hash has full BC layer)
- - mime_magic (use fileinfo, has full BC layer)
+- Fixed crypt_blowfish handling of 8-bit characters. crypt() in Blowfish mode
+ now supports hashes marked $2a$, $2x$, $2y$ and $2z$.
- c. with changed behaviour
+- mbstring now supports following encodings: Shift_JIS/UTF-8 Emoji,
+ JIS X0213:2004 (Shift_JIS-2004, EUC-JP-2004, ISO-2022-JP-2004),
+ MacJapanese (Shift_JIS), gb18030.
- - dns: dns_check_record() will now return an extra "entries" index,
- containing the TXT elements.
+- Added encode and decode in hex format to mb_encode_numericentity() and
+ mb_decode_numericentity().
- - datetime: date/time functions will no longer use the TZ environment
- variable to guess which timezone should be used.
+- Added support for SORT_NATURAL and SORT_FLAG_CASE in array sort functions:
+ sort(), rsort(), ksort(), krsort(), asort(), arsort() and array_multisort().
- - cURL now supports SSH
+- is_a() and is_subclass_of() now have third boolean parameter, which specifies
+ if the first argument can be a string class name. Default if false for is_a
+ and true for is_subclass_of() for BC reasons.
- - hash: The SHA-224 and salsa hash algorithms are now supported.
+- ob_start() will now treat a chunk size of 1 as meaning 1 byte, rather than
+ the previous special case behavior of treating it as 4096 bytes.
- - mbstring: Now supports CP850 encoding.
+- idn_to_ascii() and idn_to_utf8() now take two extra parameters, one indicating
+ the variant (IDNA 2003 or UTS #46) and another, passed by reference, to return
+ details about the operation in case UTS #46 is chosen.
- - oci8: Database Resident Connection Pooling (DRCP) and Fast Application
- Notification (FAN) are now supported.
+- gzencode() used with FORCE_DEFLATE now generates RFC1950 compliant data.
- Oracle External Authentication is now supported (except on Windows).
+- ob_start() no longer starts multiple output buffers when passed
+ array("callback1", "callback2", "callback3", ...).
- The oci8 function oci_bind_by_name() now supports SQLT_AFC (aka the
- CHAR datatype).
+- Since 5.4.4, "php://fd" stream syntax is available only in CLI build.
- Calling oci_close() on a persistent connection, or when the variable
- that references a persistent connection goes out of scope, will now
- trigger a roll back of an uncommitted transaction. To avoid unexpected
- behavior explicitly issue a commit or roll back as needed. The old
- behavior can be enabled with the INI directive
- oci8.old_oci_close_semantics.
+- Since 5.4.5, resourcebundle_create() accepts null for the first two arguments.
- - openssl: OpenSSL digest and cipher functions are now supported.
- It is also now possible to access the internal values of DSA, RSA and
- DH keys.
+- Since 5.4.6, SimpleXMLElement::getDocNamespaces() has and extra parameter which
+ allows for toggling if the list of namespaces starts from the document root
+ or from the node you call the method on
- - session: Sessions will no longer store session-files in "/tmp" when
- open_basedir restrictions apply, unless "/tmp" is explicitly added to
- the list of allowed paths.
+- Since 5.4.7, ctor is always called when new user stream wrapper object is created.
+ Before, it was called only when stream_open was called.
- - SOAP: Now supports sending user-supplied HTTP headers.
+==============================
+5. Changes to existing classes
+==============================
- - MySQLi: Now supports persistent connections by prepending the hostname
- with "p:".
+- Classes that implement stream wrappers can define a method called
+ stream_truncate that will respond to truncation, e.g. through ftruncate.
+ Strictly speaking, this is an addition to the user-space stream wrapper
+ template, not a change to an actual class.
- - imagepstext now rejects invalid antialiasing steps and raises a warning.
+- Classes that implement stream wrappers can define a method called
+ stream_metadata that will be called on touch(), chmod(), chgrp(), chown().
- d. no longer possible to disable
+- Arrays cast from SimpleXMLElement now always contain all nodes instead of
+ just the first matching node.
- - PCRE
- - Reflection
- - SPL
+- All SimpleXMLElement children are now always printed when using var_dump(),
+ var_export(), and print_r().
-==========================
-8. Changes in SAPI support
-==========================
+- Added iterator support in MySQLi. mysqli_result implements Traversable.
-- A new "litespeed" SAPI is now available.
+==============================
+6. Changes to existing methods
+==============================
-- FastCGI is now always enabled and can not be disabled. See sapi/cgi/CHANGES
- for more details.
+- DateTime::parseFromFormat() now has a "+" modifier to allow trailing text in
+ the string to parse without throwing an error.
-- A new CGI SAPI option, -T, can be used to measure execution time of a script
- repeated several times.
-
-- CGI/FastCGI now has support for .htaccess style user-defined php.ini files.
- See the new user_ini.filename and user_ini.cache_ttl INI directives.
+- Added the ability to pass options to DOMDocument::loadHTML().
-============================
-9. Changes in INI directives
-============================
+- FilesystemIterator, GlobIterator and (Recursive)DirectoryIterator now use
+ the default stream context.
-- zend_extension_debug and zend_extension_ts have been removed. Always use the
- zend_extension directive to load Zend Extensions.
+- Since 5.4.5, the constructor of ResourceBundle accepts NULL for the first two
+ arguments.
-- zend.ze1_compatibility_mode has been removed. If this INI directive is set to
- on, then an E_ERROR is emitted at startup.
+===========================
+7. Deprecated Functionality
+===========================
-- There is now support for special sections: [PATH=/opt/httpd/www.example.com/]
- and [HOST=www.example.com]. Directives set in these sections cannot be
- overridden by user-defined INI files or at runtime.
+- The following functions are deprecated in PHP 5.4:
+ - mcrypt_generic_end(): use mcrypt_generic_deinit() instead
+ - mysql_list_dbs()
-- Added mbstring.http_output_conv_mimetype. This directive specifies the
- regex pattern of content types for which mb_output_handler() is activated.
+========================
+8. Removed Functionality
+========================
-- It is now possible to use the full path to load modules using the "extension"
- directive.
+a. Removed features
-- "INI variables" can now be used almost anywhere in a php.ini file.
+ The following features have been removed from PHP 5.4:
-- It is now possible to use alphanumeric or variable indices in INI option
- arrays.
+ - Magic quotes
+ - Register globals
+ - Safe mode
+ - Session extension bug compatibility mode
+ - Y2K compliance mode
-- open_basedir is now PHP_INI_ALL
+b. Removed functions
-- Runtime tightening of open_basedir restrictions is now possible.
+ The following functions are no longer available in PHP 5.4:
-- The default value of session.use_only_cookies has changed to "1".
+ - define_syslog_variables()
+ - import_request_variables()
+ - session_is_registered()
+ - session_register()
+ - session_unregister()
+ - set_magic_quotes_runtime()
+ - mysqli_bind_param() (alias of mysqli_stmt_bind_param())
+ - mysqli_bind_result() (alias of mysqli_stmt_bind_result())
+ - mysqli_client_encoding() (alias of mysqli_character_set_name())
+ - mysqli_fetch() (alias of mysqli_stmt_fetch())
+ - mysqli_param_count() (alias of mysqli_stmt_param_count())
+ - mysqli_get_metadata() (alias of mysqli_stmt_result_metadata())
+ - mysqli_send_long_data() (alias of mysqli_stmt_send_long_data())
+ - mysqli::client_encoding() (alias of mysqli::character_set_name)
+ - mysqli_stmt::stmt() (never worked/always throws, undocumented)
-- The default value of oci8.default_prefetch has been changed from 10 to 100.
+c. Removed syntax
-- A new directive, request_order, controls the behavior of $_REQUEST
- independently of variables_order.
-- A new directive, called windows.show_crt_warning, has been introduced.
- This directive shows the CRT warnings when enabled. These warnings were
- displayed by default until now. It is disabled by default.
+ - break $var;
+ - continue $var;
-- New INI directives:
- - mail.add_x_header
- - user_ini.filename
- - user_ini.cache_ttl
- - exit_on_timeout
- - mysqli.allow_persistent
- - mysqli.default_host
- - mysqli.default_socket
- - mysqli.allow_local_infile
- - mysqli.cache_size
- - oci8.connection_class
- - oci8.events
- - pdo_mysql.default_socket
- - pdo_mysql.cache_size
- - sqlite3.extension_dir
- - mysql.default_socket
- - mysql.allow_local_infile
- - mysql.cache_size
- - mysqlnd.collect_statistics
- - mysqlnd.collect_memory_statistics
- - mysqlnd.net_cmd_buffer_size
- - mysqlnd.net_read_buffer_size
- - mysqlnd.log_mask
+d. Removed hash algorithms
+ - Salsa10 and Salsa20, which are actually stream ciphers
====================
-10. Syntax additions
+9. Extension Changes
====================
-- NOWDOC: Similar to HEREDOC, but with single quotes:
-
- <<<'LABEL' ...
-
- Static HEREDOCs can be used to initialize static variables and class members
- or constants:
-
- static $foo = <<<LABEL
- No variables here...
- LABEL;
-
-- HEREDOC now supports wrapping the identifier with double-quotes, to complement
- the NOWDOC syntax:
-
- <<<"LABEL" ...
-
-- The ?: operator has been introduced:
-
- var_dump(0 ?: 'Hello!');
-
-- Namespaces were added:
-
- namespace my\name;
- $obj = new \my\name\MyClass;
-
-- Dynamic access to static methods is now possible:
-
- $foo::myFunc();
-
-- Exceptions can now be nested:
-
- class MyCustomException extends Exception {}
- try {
- throw new MyCustomException("Something happend", 112);
- } catch(Exception $e) {
- throw new InvalidArgumentException("You are doing it wrong!", 911, $e);
- }
-
-- Exceptions can now be handled in destructors.
-
-- A garbage collector has been added and is enabled by default.
+a. Extensions no longer maintained
+
+ - ext/sqlite is no longer part of the base distribution and has been moved
+ to PECL. Use sqlite3 or PDO_SQLITE instead.
+
+b. Extensions with changed behavior
+
+ - The MySQL extensions (ext/mysql, mysqli and PDO_MYSQL) use mysqlnd
+ as the default library now. It is still possible to use libmysql by
+ specifying a path to the configure options.
+
+ - PDO_MYSQL: Support for linking with MySQL client libraries older
+ than 4.1 is removed.
+
+ - The session extension now can hook into the file upload feature
+ in order to provide upload progress information through session
+ variables.
+
+ - SNMP extension
+ - Functions in SNMP extension now returns FALSE on every error
+ condition including SNMP-related (no such instance, end of MIB,
+ etc). Thus, in patricular, breaks previous behavior of get/walk
+ functions returning an empty string on SNMP-related errors.
+ - Multi OID get/getnext/set queries are now supported.
+ - New constants added for use in snmp_set_oid_output_format()
+ function.
+ - Function snmp_set_valueretrieval() changed it's behavior:
+ SNMP_VALUE_OBJECT can be combined with one of
+ SNMP_VALUE_PLAIN or SNMP_VALUE_LIBRARY resulting OID value
+ changes. When no SNMP_VALUE_PLAIN or SNMP_VALUE_LIBRARY
+ is supplied with SNMP_VALUE_OBJECT, SNMP_VALUE_LIBRARY is used.
+ Prior to 5.4.0 when no SNMP_VALUE_PLAIN or SNMP_VALUE_LIBRARY
+ was supplied with SNMP_VALUE_OBJECT, SNMP_VALUE_PLAIN was used.
+ - Added feature-rich OO API (SNMP class)
+ - Dropped UCD-SNMP compatibility code. Consider upgrading to
+ net-snmp v5.3+. Net-SNMP v5.4+ is required for Windows version.
+ - In sake of adding support for IPv6 DNS name resolution of
+ remote SNMP agent (peer) is done by extension now, not by Net-SNMP
+ library anymore.
+
+ - Date extension
+ - Setting the timezone with the TZ environment variable is no longer
+ supported, instead date.timezone and/or date_default_timezone_set()
+ have to be used.
+ - The extension will no longer guess the default timezone if none
+ is set with date.timezone and/or date_default_timezone_set().
+ Instead it will always fall back to "UTC".
+
+ - Hash extension
+ - the output of the tiger hash family has been corrected, see
+ https://bugs.php.net/61307
+
+===========================
+10. Changes in SAPI support
+===========================
+
+- A REQUEST_TIME_FLOAT value returns a floating point number indicating the
+ time with microsecond precision. All SAPIs providing this value should be
+ returning float and not time_t.
+
+- apache_child_terminate(), getallheaders(), apache_request_headers()
+ and apache_response_headers() are now supported on FastCGI.
+
+- The interactive shell allows a shortcut #inisetting=value to change php.ini
+ settings at run-time.
+
+- The interactive shell now works with the shared readline extension.
+
+- The interactive shell no longer terminates on fatal errors.
+
+- A new PHP CLI command line option --rz <name> shows information about the
+ named Zend extension.
===================
11. Windows support
===================
-- The minimum Windows version is now Windows 2000. (Windows 98, ME and NT4 are
- no longer supported).
-
-- PHP Windows binaries target i586 or later. i386 and i486 are not supported.
-
-- Support for the IIS SAPI has been dropped. Use the FastCGI SAPI instead
- (available for IIS5 and later)). FastCGI is the recommended way to use PHP
- with IIS (see http://php.iis.net/).
-
-- A new build is available based on the latest Visual C++ Compiler (VC9).
- Its use is recommended with FastCGI or CLI. Apache's Windows binaries are not
- compatible with VC9; however, you can use Apache Lounge's build
- (http://apachelounge.com).
-
-- The x64 binaries are for experimental usage only. They are not meant to be
- used in production.
+- is_link now works properly for symbolic links on Windows Vista
+ or later. Earlier systems do not support symbolic links.
-- A new site is available to download Windows releases as well as Windows-only
- releases: http://windows.php.net. Windows-specific releases will be made to
- fix security issues in the bundled libraries (libpng, openssl, etc.). Please
- note that this site does not replace the main PHP site as a source of PHP
- news, resources, or documentation.
-
-- Windows support has been added for the following functions: getopt(),
- imagecolorclosesthwb(), mcrypt_create_iv(), inet_ntop(), inet_pton(),
- getmxrr(), checkdnsrr(), dns_get_record(), linkinfo(), readlink(),
- symlink(), link(), fnmatch(), stream_socket_pair(), time_nanosleep(),
- time_sleep_until(), and socket_create_pair().
-
-- Crypt supports now all available algorithms on Windows (blowfish included).
+- As of PHP 5.4.5 and above the COM extension isn't compiled statically in PHP
+ anymore but shared. It'll still be delivered with the standard PHP release but
+ must be activated manually with the "extension = php_com_dotnet.dll" directive
+ in php.ini.
-- Improved portability of stat(), touch(), filemtime(), filesize() and related
- functions (100% portable for the available data).
+==================
+12. New in PHP 5.4
+==================
-- It is now possible to create hard links on Windows using the link() function,
- and symbolic links using the symlink() function. Hard links are available
- as of Windows 2000 and symbolic links as of Windows Vista.
+a. New Features
-- The PDO_OCI php_pdo_oci8.dll library (for use with Oracle version 8 client
- libraries) is no longer being built. Instead, use php_pdo_oci.dll (note no
- '8') with Oracle 10 or 11 client libraries. Connection to other database
- versions is still supported.
+ - A built-in CLI web server for testing purposes is now available:
+ $ php -S 127.0.0.1:8888
-- For the OCI8 extension, a new library php_oci8_11g.dll is available in
- addition to php_oci8.dll. Only one can be enabled at any time. Use
- php_oci8.dll with Oracle 10.2 client libraries. Use php_oci8_11g.dll with
- Oracle 11 client libraries. Connection to other database versions is still
- supported.
+ - File Upload Progress support is implemented in the Session extension.
-- Firebird and SNMP support are no longer available on Windows. Firebird support
- may be reintroduced in the future.
+b. Syntax additions
-- As of PHP 5.3.15 and above the COM extension isn't compiled statically in PHP
- anymore but shared. It'll still be delivered with the standard PHP release but
- must be activated manually with the "extension = php_com_dotnet.dll" directive
- in php.ini.
+ - Traits:
+ trait HelloWorld {
+ public function sayHello() {
+ echo 'Hello World!';
+ }
+ }
-=====================
-11.1 New in PHP 5.3.4
-=====================
+ class CanIGetHello {
+ use HelloWorld;
+ }
-- open_basedir supports now symbolic links (checks the target).
-- is_link and SplFileInfo symbolic links related method are now fully supported
- (on Windows Vista or later).
+ $hello = new CanIGetHello();
+ $hello->sayHello();
-===================
-12. New in PHP 5.3:
-===================
+ - Function call result array access, e.g.:
+ foo()[0]
+ $foo->bar()[0]
- a. New libraries
-
- - mysqlnd is a new core library shipped with PHP. It is a PHP-specific
- replacement for libmysql and is recommended for all installations for
- increased performance.
-
- b. New extensions
-
- - enchant
- - fileinfo (replaces mime_magic)
- - intl
- - Phar
- - SQLite3
-
- c. New stream wrappers
-
- - glob:// stream wrapper
- - phar:// stream wrapper for accessing phar archives
-
- d. New stream filters
-
- - "dechunk" (HTTP/1.1 chunked transfer encoding)
- - The bz2.decompress filter now supports concatenation
-
- e. New functions
-
- - Core: gc_collect_cycles()
- gc_enabled()
- gc_enable()
- gc_disable()
- class_alias()
- get_called_class()
- forward_static_call()
- forward_static_call_array()
- str_getcsv()
- quoted_printable_encode()
- lcfirst()
- - Array: array_replace()
- array_replace_recursive()
- - Date: date_add()
- date_sub()
- date_diff()
- date_parse_from_format()
- date_create_from_format()
- date_get_last_errors()
- timezone_version_get()
- - INI: parse_ini_string()
- - GMP: gmp_testbit()
- - Hash: hash_copy()
- - IMAP: imap_gc()
- imap_utf8_to_mutf7()
- imap_mutf7_to_utf8()
- - JSON: json_last_error()
- - libxml: libxml_disable_entity_loader
- - MySQLi: mysqli_fetch_all()
- mysqli_get_connection_stats()
- mysqli_poll()
- mysqli_reap_async_query()
- - Network: gethostname()
- header_remove()
- - OpenSSL: openssl_random_pseudo_bytes()
- - PCNTL: pcntl_signal_dispatch()
- pcntl_sigprocmask()
- pcntl_sigwaitinfo()
- pcntl_sigtimedwait()
- - PCRE: preg_filter()
- - SHM: msg_queue_exists()
- shm_has_var()
- - Streams: stream_supports_lock()
- stream_context_set_default()
- stream_context_get_params()
- - Userspace stream wrappers:
- stream_cast()
- stream_set_options()
-
- f. New global constants
-
- - Core: E_DEPRECATED
- E_USER_DEPRECATED
- __DIR__
- __NAMESPACE__
- PHP_MAXPATHLEN
- PHP_WINDOWS_VERSION_MAJOR
- PHP_WINDOWS_VERSION_MINOR
- PHP_WINDOWS_VERSION_BUILD
- PHP_WINDOWS_VERSION_PLATFORM
- PHP_WINDOWS_VERSION_SP_MAJOR
- PHP_WINDOWS_VERSION_SP_MINOR
- PHP_WINDOWS_VERSION_SUITEMASK
- PHP_WINDOWS_VERSION_PRODUCTTYPE
- PHP_WINDOWS_NT_DOMAIN_CONTROLLER
- PHP_WINDOWS_NT_SERVER
- PHP_WINDOWS_NT_WORKSTATION
- - INI: INI_SCANNER_NORMAL
- INI_SCANNER_RAW
- - cURL CURLOPT_PROGRESSFUNCTION
- - GD: IMG_FILTER_PIXELATE
- - JSON: JSON_ERROR_NONE
- JSON_ERROR_DEPTH
- JSON_ERROR_STATE_MISMATCH
- JSON_ERROR_CTRL_CHAR
- JSON_ERROR_SYNTAX
- JSON_FORCE_OBJECT
- JSON_HEX_TAG
- JSON_HEX_AMP
- JSON_HEX_APOS
- JSON_HEX_QUOT
- - LDAP: LDAP_OPT_NETWORK_TIMEOUT
- - libxml: LIBXML_LOADED_VERSION
- - PCRE: PREG_BAD_UTF8_OFFSET_ERROR
- - PCNTL: SIG_BLOCK
- SIG_UNBLOCK
- SIG_SETMASK
- SI_USER
- SI_NOINFO
- SI_KERNEL
- SI_QUEUE
- SI_TIMER
- SI_MESGQ
- SI_ASYNCIO
- SI_SIGIO
- SI_TKILL
- CLD_EXITED
- CLD_KILLED
- CLD_DUMPED
- CLD_TRAPPED
- CLD_STOPPED
- CLD_CONTINUED
- TRAP_BRKPT
- TRAP_TRACE
- POLL_IN
- POLL_OUT
- POLL_MSG
- POLL_ERR
- POLL_PRI
- POLL_HUP
- ILL_ILLOPC
- ILL_ILLOPN
- ILL_ILLADR
- ILL_ILLTRP
- ILL_PRVOPC
- ILL_PRVREG
- ILL_COPROC
- ILL_BADSTK
- FPE_INTDIV
- FPE_INTOVF
- FPE_FLTDIV
- FPE_FLTOVF
- FPE_FLTUND
- FPE_FLTRES
- FPE_FLTINV
- FPE_FLTSUB
- SEGV_MAPERR
- SEGV_ACCERR
- BUS_ADRALN
- BUS_ADRERR
- BUS_OBJERR
-
- g. New classes
-
- - Date: DateInterval
- DatePeriod
- - Phar: Phar
- PharData
- PharFileInfo
- PharException
- - SPL SplDoublyLinkedList
- SplStack
- SplQueue
- SplHeap
- SplMinHeap
- SplMaxHeap
- SplPriorityQueue
- SplFixedArray
- FilesystemIterator
- GlobIterator
- RecursiveTreeIterator
- MultipleIterator
-
- h. New methods
-
- - Date: DateTime::diff()
- DateTime::add()
- DateTime::sub()
- DateTime::createFromFormat()
- DateTime::getLastErrors()
- - DOM: DOMNode::getLineNo()
- - Exception: Exception::getPrevious()
- - PDO_Firebird: PDO::setAttribute()
- - Reflection: ReflectionProperty::setAccessible()
- ReflectionFunction::inNamespace()
- ReflectionFunction::getNamespaceName()
- ReflectionFunction::getShortName()
- ReflectionClass::inNamespace()
- ReflectionClass::getNamespaceName()
- ReflectionClass::getShortName()
- - SPL: DirectoryIterator::getExtension()
- SplFileInfo::getExtension()
- SplObjectStorage::addAll()
- SplObjectStorage::removeAll()
- - XSL: XSLTProcessor::setProfiling()
-
- i. New class constants
-
- - PDO_Firebird: PDO::FB_ATTR_DATE_FORMAT
- PDO::FB_ATTR_TIME_FORMAT
- PDO::FB_ATTR_TIMESTAMP_FORMAT
+ - Callable typehint indicating argument must be callable:
+ function foo(callable $do) {
+ }
+ foo("strcmp");
+ foo(function() {});
+ $o = new ArrayObject();
+ foo(array($o, "count"));
+
+ - Short array syntax:
+ $a = [1, 2, 3, 4];
+ $a = ['one' => 1, 'two' => 2, 'three' => 3, 'four' => 4];
+ $a = ['one' => 1, 2, 'three' => 3, 4];
+
+ - Binary number format:
+ 0b00100 0b010101
+
+ - Chained string array offsets now work.
+ $a = "abc";
+ echo $a[0][0];
+
+ - Anonymous functions now support using $this and class scope.
+ Anonymous function can be declared as "static" to ignore the scope.
+
+ - Class::{expr}() syntax is now supported:
+ class A {
+ static function foo() {
+ echo "Hello world!\n";
+ }
+ }
+ $x = "f";
+ $y = "o";
+ A::{$x.$y.$y}();
+
+ - Class member access on instantiation:
+ (new foo)->method()
+ (new foo)->property
+ (new foo)[0]
+
+
+c. New functions
+
+ - Core:
+ - get_declared_traits()
+ - getimagesizefromstring()
+ - hex2bin()
+ - header_register_callback()
+ - http_response_code()
+ - stream_set_chunk_size()
+ - socket_import_stream()
+ - trait_exists()
+
+ - Intl:
+ - transliterator_create()
+ - transliterator_create_from_rules()
+ - transliterator_create_inverse()
+ - transliterator_get_error_code()
+ - transliterator_get_error_message()
+ - transliterator_list_ids()
+ - transliterator_transliterate()
+
+ - LDAP:
+ - ldap_control_paged_result()
+ - ldap_control_paged_result_response()
+
+ - libxml:
+ - libxml_set_external_entity_loader()
+
+ - mysqli:
+ - mysqli_error_list()
+ - mysqli_stmt_error_list()
+
+ - pgsql
+ - pg_escape_identifier() (5.4.4)
+ - pg_escape_literal() (5.4.4)
+
+ - Session:
+ - session_register_shutdown()
+ - session_status()
+
+ - SPL
+ - class_uses()
+
+d. New global constants
+
+ - CURLOPT_MAX_RECV_SPEED_LARGE
+ - CURLOPT_MAX_SEND_SPEED_LARGE
+ - ENT_DISALLOWED
+ - ENT_HTML401
+ - ENT_HTML5
+ - ENT_SUBSTITUTE
+ - ENT_XHTML
+ - ENT_XML1
+ - IPPROTO_IP
+ - IPPROTO_IPV6
+ - IPV6_MULTICAST_HOPS
+ - IPV6_MULTICAST_IF
+ - IPV6_MULTICAST_LOOP
+ - IP_MULTICAST_IF
+ - IP_MULTICAST_LOOP
+ - IP_MULTICAST_TTL
+ - JSON_BIGINT_AS_STRING
+ - JSON_OBJECT_AS_ARRAY
+ - JSON_PRETTY_PRINT
+ - JSON_UNESCAPED_SLASHES
+ - JSON_UNESCAPED_UNICODE
+ - LIBXML_HTML_NODEFDTD
+ - LIBXML_HTML_NOIMPLIED
+ - LIBXML_PEDANTIC
+ - MCAST_JOIN_GROUP
+ - MCAST_LEAVE_GROUP
+ - MCAST_BLOCK_SOURCE
+ - MCAST_UNBLOCK_SOURCE
+ - MCAST_JOIN_SOURCE_GROUP
+ - MCAST_LEAVE_SOURCE_GROUP
+ - OPENSSL_CIPHER_AES_128_CBC
+ - OPENSSL_CIPHER_AES_192_CBC
+ - OPENSSL_CIPHER_AES_256_CBC
+ - OPENSSL_RAW_DATA
+ - OPENSSL_ZERO_PADDING
+ - PHP_OUTPUT_HANDLER_CLEAN
+ - PHP_OUTPUT_HANDLER_CLEANABLE
+ - PHP_OUTPUT_HANDLER_DISABLED
+ - PHP_OUTPUT_HANDLER_FINAL
+ - PHP_OUTPUT_HANDLER_FLUSH
+ - PHP_OUTPUT_HANDLER_FLUSHABLE
+ - PHP_OUTPUT_HANDLER_REMOVABLE
+ - PHP_OUTPUT_HANDLER_STARTED
+ - PHP_OUTPUT_HANDLER_STDFLAGS
+ - PHP_OUTPUT_HANDLER_WRITE
+ - PHP_QUERY_RFC1738
+ - PHP_QUERY_RFC3986
+ - PHP_SESSION_ACTIVE
+ - PHP_SESSION_DISABLED
+ - PHP_SESSION_NONE
+ - SCANDIR_SORT_ASCENDING
+ - SCANDIR_SORT_DESCENDING
+ - SCANDIR_SORT_NONE
+ - SORT_FLAG_CASE
+ - SORT_NATURAL
+ - STREAM_META_ACCESS
+ - STREAM_META_GROUP
+ - STREAM_META_GROUP_NAME
+ - STREAM_META_OWNER
+ - STREAM_META_OWNER_NAME
+ - STREAM_META_TOUCH
+ - T_CALLABLE
+ - T_INSTEADOF
+ - T_TRAIT
+ - T_TRAIT_C
+ - ZLIB_ENCODING_DEFLATE
+ - ZLIB_ENCODING_GZIP
+ - ZLIB_ENCODING_RAW
+ - U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR
+ - IDNA_CHECK_BIDI
+ - IDNA_CHECK_CONTEXTJ
+ - IDNA_NONTRANSITIONAL_TO_ASCII
+ - IDNA_NONTRANSITIONAL_TO_UNICODE
+ - INTL_IDNA_VARIANT_2003
+ - INTL_IDNA_VARIANT_UTS46
+ - IDNA_ERROR_EMPTY_LABEL
+ - IDNA_ERROR_LABEL_TOO_LONG
+ - IDNA_ERROR_DOMAIN_NAME_TOO_LONG
+ - IDNA_ERROR_LEADING_HYPHEN
+ - IDNA_ERROR_TRAILING_HYPHEN
+ - IDNA_ERROR_HYPHEN_3_4
+ - IDNA_ERROR_LEADING_COMBINING_MARK
+ - IDNA_ERROR_DISALLOWED
+ - IDNA_ERROR_PUNYCODE
+ - IDNA_ERROR_LABEL_HAS_DOT
+ - IDNA_ERROR_INVALID_ACE_LABEL
+ - IDNA_ERROR_BIDI
+ - IDNA_ERROR_CONTEXTJ
+
+e. New classes
+
+ - Reflection:
+ - ReflectionZendExtension
+
+ - Intl:
+ - Transliterator
+ - Spoofchecker
+
+ - JSON:
+ - JsonSerializable
+
+ - Session:
+ - SessionHandler
+
+ - SNMP:
+ - SNMP
+
+ - SPL:
+ - CallbackFilterIterator
+ - RecursiveCallbackFilterIterator
+
+f. New methods
+
+ - Closure:
+ - Closure::bind()
+ - Closure::bindTo()
+
+ - Reflection:
+ - ReflectionClass::getTraitAliases()
+ - ReflectionClass::getTraitNames()
+ - ReflectionClass::getTraits()
+ - ReflectionClass::isCloneable()
+ - ReflectionClass::isTrait()
+ - ReflectionClass::newInstanceWithoutConstructor()
+ - ReflectionExtension::isPersistent()
+ - ReflectionExtension::isTemporary()
+ - ReflectionFunction::getClosure()
+ - ReflectionFunction::getClosureScopeClass()
+ - ReflectionFunction::getClosureThis()
+ - ReflectionFunctionAbstract::getClosureScopeClass()
+ - ReflectionFunctionAbstract::getClosureThis()
+ - ReflectionMethod::getClosure()
+ - ReflectionMethod::getClosureScopeClass()
+ - ReflectionMethod::getClosureThis()
+ - ReflectionObject::getTraitAliases()
+ - ReflectionObject::getTraitNames()
+ - ReflectionObject::getTraits()
+ - ReflectionObject::isCloneable()
+ - ReflectionObject::isTrait()
+ - ReflectionObject::newInstanceWithoutConstructor()
+ - ReflectionParameter::canBePassedByValue()
+ - ReflectionParameter::isCallable()
+
+ - PDO_DBLIB:
+ - PDO::newRowset()
+
+ - SPL:
+ - DirectoryIterator::getExtension()
+ - RegexIterator::getRegex()
+ - SplDoublyLinkedList::serialize()
+ - SplDoublyLinkedList::unserialize()
+ - SplFileInfo::getExtension()
+ - SplFileObject::fputcsv()
+ - SplObjectStorage::getHash()
+ - SplQueue::serialize
+ - SplQueue::unserialize
+ - SplStack::serialize
+ - SplStack::unserialize
+ - SplTempFileObject::fputcsv
+
+ - XSLT:
+ - XsltProcessor::setSecurityPrefs()
+ - XsltProcessor::getSecurityPrefs()
+
+ - Zlib:
+ - zlib_decode()
+ - zlib_encode()
+
+g. New Hash algorithms
+
+ - fnv132
+ - fnv164
+ - joaat
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index 86ab778ffa..e9d0adf554 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -1,23 +1,207 @@
$Id$
-UPGRADE NOTES - PHP 5.3.4
+UPGRADE NOTES - PHP X.Y
1. Internal API changes
+ a. virtual_file_ex
+ b. stat/lstat support
+ c. readlink support
+ d. layout of some core ZE structures (zend_op_array, zend_class_entry, ...)
+ e. Zend\zend_fast_cache.h has been removed
+ f. streams that enclose private streams
+ g. leak_variable
+ h. API Signature changes
+ i. new TSRM function expand_filepath_with_mode
+
+2. Build system changes
+ a. Unix build system changes
+ b. Windows build system changes
+
========================
1. Internal API changes
========================
- a. stat/lstat support
+ a. virtual_file_ex
+
+virtual_file_ex takes now a TSRM context as last parameter:
+CWD_API int virtual_file_ex(cwd_state *state, const char *path,
+ verify_path_func verify_path, int use_realpath TSRLS_DC);
+
+
+ b. stat/lstat support
lstat is now available on all platforms. On unix-like platform
php_sys_lstat is an alias to lstat (when avaible). On Windows it is now
available using php_sys_lstat. php_sys_stat and php_sys_lstat usage is recommended
instead of calling lstat directly, to ensure portability.
- b. readlink support
+
+ c. readlink support
readlink is now available on all platforms. On unix-like platform
php_sys_readlink is an alias to readlink (when avaible). On Windows it is now
available using php_sys_readlink. php_sys_readlink usage is recommended
instead of calling readlink directly, to ensure portability.
+
+
+ d. layout of some core ZE structures (zend_op_array, zend_class_entry, ...)
+
+. zend_function.pass_rest_by_reference is replaced by
+ ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags
+. zend_function.return_reference is replaced by ZEND_ACC_RETURN_REFERENCE
+ in zend_function.fn_flags
+. zend_arg_info.required_num_args removed. it was needed only for internal
+ functions. Now the first arg_info for internal function (which has special
+ meaning) is represented by zend_internal_function_info structure.
+. zend_op_array.size, size_var, size_literal, current_brk_cont,
+ backpatch_count moved into CG(context), because they are used only during
+ compilation.
+. zend_op_array.start_op is moved into EG(start_op), because it's used
+ only for 'interactive' execution of single top-level op-array.
+. zend_op_array.done_pass_two is replaced by ZEND_ACC_DONE_PASS_TWO in
+ zend_op_array.fn_flags.
+. op_array.vars array is trimmed (reallocated) during pass_two.
+. zend_class_entry.constants_updated is replaced by
+ ZEND_ACC_CONSTANTS_UPDATED in zend_class_entry.ce_flags
+. the size of zend_class_entry is reduced by sharing the same memory space
+ by different information for internal and user classes.
+ See zend_class_inttry.info union.
+
+
+ e. Zend\zend_fast_cache.h
+
+It should not have been used anymore since php5, but now this header has
+been removed. The following macros are not available anymore:
+
+ZEND_FAST_ALLOC(p, type, fc_type)
+ZEND_FAST_FREE(p, fc_type)
+ZEND_FAST_ALLOC_REL(p, type, fc_type)
+ZEND_FAST_FREE_REL(p, fc_type)
+
+Use emalloc, emalloc_rel, efree or efree_rel instead.
+
+
+ f. Streams that enclose private streams
+
+Some streams, like the temp:// stream, may enclose private streams. If the
+outer stream leaks due to a programming error or is not exposed through a
+zval (and therefore is not deleted when all the zvals are gone), it will
+be destroyed on shutdown.
+The problem is that the outer usually wants itself to close the inner stream,
+so that it may do any other shutdown action that requires the inner stream to
+be live (e.g. commit data to it). If the outer stream is exposed through a
+zval and the inner one isn't, this is not a problem because the outer stream
+will be freed when the zval is destroyed, which happens before the resources
+are destroyed on shutdown.
+On resource list shutdown, the cleanup happens in reverse order of resource
+creation, so if the inner stream was created in the opener of the outer stream,
+it will be destroyed first.
+The following functions were added to the streams API to force a predictable
+destruction order:
+
+PHPAPI php_stream *php_stream_encloses(php_stream *enclosing, php_stream *enclosed);
+#define php_stream_free_enclosed(stream_enclosed, close_options)
+PHPAPI int _php_stream_free_enclosed(php_stream *stream_enclosed, int close_options TSRMLS_DC);
+
+Additionally, the following member was added to php_stream:
+
+ struct _php_stream *enclosing_stream;
+
+and the following macro was added:
+
+#define PHP_STREAM_FREE_IGNORE_ENCLOSING 32
+
+The function php_stream_encloses declares the first stream encloses the second.
+This has the effect that, when the inner stream is closed from a resource
+destructor it will abort and try to free its enclosing stream instead.
+To prevent this from happening when the inner stream is freed from the outer
+stream, the macro php_stream_free_enclosed should be used instead of
+php_stream_free/php_stream_close/php_stream_pclose, or the flag
+PHP_STREAM_FREE_IGNORE_ENCLOSING should be directly passed to php_stream_free.
+The outer stream cannot abstain, in its close callback, from closing the inner
+stream or clear the enclosing_stream pointer in its enclosed stream by calling
+php_stream_encloses with the 2nd argument NULL. If this is not done, there will
+be problems, so observe this requirement when using php_stream_encloses.
+
+
+ g. leak_variable
+
+The function leak_variable(variable [, leak_data]) was added. It is only
+available on debug builds. It increments the refcount of a zval or, if the
+second argument is true and the variable is either an object or a resource
+it increments the refcounts of those objects instead.
+
+
+ h. API Signature changes
+
+. zend_list_insert
+ ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC);
+ call: zend_list_insert(a, SOMETYPE TSRMLS_CC);
+ NB: If zend_list_insert is used to register a resource,
+ ZEND_REGISTER_RESOURCE could be used instead.
+
+. php_le_stream_context(TSRMLS_C)
+ PHPAPI php_stream_context *php_stream_context_alloc(TSRMLS_D)
+ call: context = php_stream_context_alloc(TSRMLS_C);
+
+. php_stream_context_alloc
+ PHPAPI php_stream_context *php_stream_context_alloc(TSRMLS_D);
+ call: context = php_stream_context_alloc(TSRMLS_C);
+
+. sapi_get_request_time(TSRMLS_D);
+ SAPI_API double sapi_get_request_time(TSRMLS_D);
+
+. sapi_register_default_post_reader
+ SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D) TSRMLS_DC);
+
+. sapi_register_treat_data
+ SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC) TSRMLS_DC);
+
+. sapi_register_input_filter
+ SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D) TSRMLS_DC);
+
+. tsrm_win32_access
+ TSRM_API int tsrm_win32_access(const char *pathname, int mode TSRMLS_DC);
+
+. popen_ex (win32)
+ TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env TSRMLS_DC);
+
+. php_get_current_user
+ PHPAPI php_get_current_user(TSRMLS_D)
+ Call: char *user = php_get_current_user(TSRMLS_C);
+
+. php_idate
+ PHPAPI php_idate(char format, time_t ts, int localtime TSRMLS_DC)
+ Call: int ret = php_idate(format, ts, localtime TSRMLS_CC)
+
+. php_escape_html_entities
+ (size_t parameters were ints, previous "quote_style" (now flags) has expanded meaning)
+ PHPAPI char *php_escape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC);
+
+. php_escape_html_entities_ex
+ PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset, zend_bool double_encode TSRMLS_DC);
+
+. php_unescape_html_entities
+ PHPAPI char *php_unescape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC);
+
+ i.
+ PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode TSRMLS_DC);
+ expand_filepath_with_mode lets define how realpath will behave, using one of the existing mode: CWD_EXPAND , CWD_FILEPATH or CWD_REALPATH.
+
+========================
+2. Build system changes
+========================
+
+ a. Unix build system changes
+
+ - Changes in SAPI module build:
+ . When adding new binary SAPI (executable, like CLI/CGI/FPM) use CLI config.m4 and Makefile.frag files as templates and replace CLI/cli with your SAPI name.
+
+ - New macros:
+ . PHP_INIT_DTRACE(providerdesc, header-file, sources [, module])
+
+
+ b. Windows build system changes
+ -
+
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 219d2d3fc9..5ec4590fef 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -17,7 +17,7 @@ libZend_la_SOURCES=\
zend_objects_API.c zend_ts_hash.c zend_stream.c \
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
- zend_strtod.c zend_closures.c zend_float.c
+ zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
diff --git a/Zend/README.ZEND_MM b/Zend/README.ZEND_MM
index c1a21419df..ff882e5d41 100644
--- a/Zend/README.ZEND_MM
+++ b/Zend/README.ZEND_MM
@@ -9,7 +9,7 @@ allocation overhead and speedup memory management.
The new manager's "configure" has no "--disable-zend-memory-manager" option,
but it has "--enable-malloc-mm" instead. It is enabled by default in DEBUG
-build and disabled by default in RELEASE build. when enabled it allows selecting
+build and disabled by default in RELEASE build. When enabled it allows selecting
between malloc and emalloc at runtime so you can use internal and external memory
debuggers without recompilation.
@@ -32,6 +32,7 @@ that valgrind can correctly track the memory leaks in shared extensions. For
this there is the ZEND_DONT_UNLOAD_MODULES environment variable. If set, then
DL_UNLOAD() is skipped during the shutdown of shared extensions.
+
Tweaking:
---------
diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp
index 0a7ed77534..ebe01978c4 100644
--- a/Zend/Zend.dsp
+++ b/Zend/Zend.dsp
@@ -243,6 +243,10 @@ SOURCE=.\zend_stream.c
# End Source File
# Begin Source File
+SOURCE=.\zend_string.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
@@ -315,10 +319,6 @@ SOURCE=.\zend_extensions.h
# End Source File
# Begin Source File
-SOURCE=.\zend_fast_cache.h
-# End Source File
-# Begin Source File
-
SOURCE=.\zend_globals.h
# End Source File
# Begin Source File
@@ -411,6 +411,10 @@ SOURCE=.\zend_stream.h
# End Source File
# Begin Source File
+SOURCE=.\zend_string.h
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4
index 6b1f705bee..945409eb1e 100644
--- a/Zend/Zend.m4
+++ b/Zend/Zend.m4
@@ -176,13 +176,6 @@ AC_ARG_ENABLE(inline-optimization,
ZEND_INLINE_OPTIMIZATION=yes
])
-AC_ARG_ENABLE(zend-multibyte,
-[ --enable-zend-multibyte Compile with zend multibyte support], [
- ZEND_MULTIBYTE=$enableval
-],[
- ZEND_MULTIBYTE=no
-])
-
AC_MSG_CHECKING([virtual machine dispatch method])
AC_MSG_RESULT($PHP_ZEND_VM)
@@ -195,9 +188,6 @@ AC_MSG_RESULT($ZEND_INLINE_OPTIMIZATION)
AC_MSG_CHECKING(whether to enable Zend debugging)
AC_MSG_RESULT($ZEND_DEBUG)
-AC_MSG_CHECKING(whether to enable Zend multibyte)
-AC_MSG_RESULT($ZEND_MULTIBYTE)
-
case $PHP_ZEND_VM in
SWITCH)
AC_DEFINE(ZEND_VM_KIND,ZEND_VM_KIND_SWITCH,[virtual machine dispatch method])
@@ -232,10 +222,6 @@ if test "$ZEND_MAINTAINER_ZTS" = "yes"; then
LIBZEND_CPLUSPLUS_CHECKS
fi
-if test "$ZEND_MULTIBYTE" = "yes"; then
- AC_DEFINE(ZEND_MULTIBYTE, 1, [ ])
-fi
-
changequote({,})
if test -n "$GCC" && test "$ZEND_INLINE_OPTIMIZATION" != "yes"; then
INLINE_CFLAGS=`echo $ac_n "$CFLAGS $ac_c" | sed s/-O[0-9s]*//`
@@ -406,8 +392,28 @@ int main()
AC_CHECK_FUNCS(mremap)
+
+AC_ARG_ENABLE(zend-signals,
+[ --enable-zend-signals Use zend signal handling],[
+ ZEND_SIGNALS=$enableval
+],[
+ ZEND_SIGNALS=no
+])
+
+AC_CHECK_FUNC(sigaction, [
+ AC_DEFINE(HAVE_SIGACTION, 1, [Whether sigaction() is available])
+], [
+ ZEND_SIGNALS=no
])
+if test "$ZEND_SIGNALS" = "yes"; then
+ AC_DEFINE(ZEND_SIGNALS, 1, [Use zend signal handling])
+ CFLAGS="$CFLAGS -DZEND_SIGNALS"
+fi
+
+AC_MSG_CHECKING(whether to enable zend signal handling)
+AC_MSG_RESULT($ZEND_SIGNALS)
+])
AC_DEFUN([LIBZEND_CPLUSPLUS_CHECKS],[
@@ -419,4 +425,11 @@ if test -r "/dev/urandom" && test -c "/dev/urandom"; then
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(whether /dev/arandom exists)
+ if test -r "/dev/arandom" && test -c "/dev/arandom"; then
+ AC_DEFINE([HAVE_DEV_ARANDOM], 1, [Define if the target system has /dev/arandom device])
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
fi
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp
index 2295b89ebb..3494cd4e17 100644
--- a/Zend/ZendTS.dsp
+++ b/Zend/ZendTS.dsp
@@ -273,6 +273,10 @@ SOURCE=.\zend_stream.c
# End Source File
# Begin Source File
+SOURCE=.\zend_string.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
@@ -345,10 +349,6 @@ SOURCE=.\zend_extensions.h
# End Source File
# Begin Source File
-SOURCE=.\zend_fast_cache.h
-# End Source File
-# Begin Source File
-
SOURCE=.\zend_globals.h
# End Source File
# Begin Source File
@@ -445,6 +445,10 @@ SOURCE=.\zend_stream.h
# End Source File
# Begin Source File
+SOURCE=.\zend_string.h
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
diff --git a/Zend/acconfig.h b/Zend/acconfig.h
deleted file mode 100644
index aa09420a4d..0000000000
--- a/Zend/acconfig.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | Zend Engine |
- +----------------------------------------------------------------------+
- | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.zend.com/license/2_00.txt. |
- | If you did not receive a copy of the Zend license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@zend.com so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Andi Gutmans <andi@zend.com> |
- | Zeev Suraski <zeev@zend.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-#if defined(__GNUC__) && __GNUC__ >= 4
-# define ZEND_API __attribute__ ((visibility("default")))
-# define ZEND_DLEXPORT __attribute__ ((visibility("default")))
-#else
-# define ZEND_API
-# define ZEND_DLEXPORT
-#endif
-
-#define ZEND_DLIMPORT
-
-@TOP@
-
-#undef uint
-#undef ulong
-
-/* Define if you want to enable memory limit support */
-#define MEMORY_LIMIT 0
-
-@BOTTOM@
-
-#ifndef ZEND_ACCONFIG_H_NO_C_PROTOS
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifdef HAVE_IEEEFP_H
-# include <ieeefp.h>
-#endif
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-
-#if ZEND_BROKEN_SPRINTF
-int zend_sprintf(char *buffer, const char *format, ...);
-#else
-# define zend_sprintf sprintf
-#endif
-
-#include <math.h>
-
-/* To enable the is_nan, is_infinite and is_finite PHP functions */
-#ifdef NETWARE
- #define HAVE_ISNAN 1
- #define HAVE_ISINF 1
- #define HAVE_ISFINITE 1
-#endif
-
-#ifndef zend_isnan
-#ifdef HAVE_ISNAN
-#define zend_isnan(a) isnan(a)
-#elif defined(HAVE_FPCLASS)
-#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
-#else
-#define zend_isnan(a) 0
-#endif
-#endif
-
-#ifdef HAVE_ISINF
-#define zend_isinf(a) isinf(a)
-#elif defined(INFINITY)
-/* Might not work, but is required by ISO C99 */
-#define zend_isinf(a) (((a)==INFINITY)?1:0)
-#elif defined(HAVE_FPCLASS)
-#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
-#else
-#define zend_isinf(a) 0
-#endif
-
-#ifdef HAVE_FINITE
-#define zend_finite(a) finite(a)
-#elif defined(HAVE_ISFINITE) || defined(isfinite)
-#define zend_finite(a) isfinite(a)
-#elif defined(fpclassify)
-#define zend_finite(a) ((fpclassify((a))!=FP_INFINITE&&fpclassify((a))!=FP_NAN)?1:0)
-#else
-#define zend_finite(a) (zend_isnan(a) ? 0 : zend_isinf(a) ? 0 : 1)
-#endif
-
-#endif /* ifndef ZEND_ACCONFIG_H_NO_C_PROTOS */
-
-#ifdef NETWARE
-#ifdef USE_WINSOCK
-#/*This detection against winsock is of no use*/ undef HAVE_SOCKLEN_T
-#/*This detection against winsock is of no use*/ undef HAVE_SYS_SOCKET_H
-#endif
-#endif
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- */
diff --git a/Zend/bench.php b/Zend/bench.php
index 42b333fceb..5f771803cc 100644
--- a/Zend/bench.php
+++ b/Zend/bench.php
@@ -3,7 +3,6 @@ if (function_exists("date_default_timezone_set")) {
date_default_timezone_set("UTC");
}
-date_default_timezone_set('UTC');
function simple() {
$a = 0;
for ($i = 0; $i < 1000000; $i++)
diff --git a/Zend/build.mk b/Zend/build.mk
index 6105ff12c4..3c83a6fe82 100644
--- a/Zend/build.mk
+++ b/Zend/build.mk
@@ -33,7 +33,7 @@ $(makefile_in_files): $(makefile_am_files)
aclocal.m4: configure.in acinclude.m4
aclocal
-$(config_h_in): configure.in acconfig.h
+$(config_h_in): configure.in
# explicitly remove target since autoheader does not seem to work
# correctly otherwise (timestamps are not updated)
@rm -f $@
diff --git a/Zend/configure.in b/Zend/configure.in
index f53d8af6e5..2f24abc7e3 100644
--- a/Zend/configure.in
+++ b/Zend/configure.in
@@ -11,6 +11,105 @@ AM_PROG_CC_STDC
ZEND_VERSION=$VERSION
AC_ZEND_C_BIGENDIAN
+AH_TOP([
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ZEND_API __attribute__ ((visibility("default")))
+# define ZEND_DLEXPORT __attribute__ ((visibility("default")))
+#else
+# define ZEND_API
+# define ZEND_DLEXPORT
+#endif
+
+#define ZEND_DLIMPORT
+
+#undef uint
+#undef ulong
+
+/* Define if you want to enable memory limit support */
+#define MEMORY_LIMIT 0
+])
+
+AH_BOTTOM([
+#ifndef ZEND_ACCONFIG_H_NO_C_PROTOS
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if ZEND_BROKEN_SPRINTF
+int zend_sprintf(char *buffer, const char *format, ...);
+#else
+# define zend_sprintf sprintf
+#endif
+
+#include <math.h>
+
+/* To enable the is_nan, is_infinite and is_finite PHP functions */
+#ifdef NETWARE
+ #define HAVE_ISNAN 1
+ #define HAVE_ISINF 1
+ #define HAVE_ISFINITE 1
+#endif
+
+#ifndef zend_isnan
+#ifdef HAVE_ISNAN
+#define zend_isnan(a) isnan(a)
+#elif defined(HAVE_FPCLASS)
+#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
+#else
+#define zend_isnan(a) 0
+#endif
+#endif
+
+#ifdef HAVE_ISINF
+#define zend_isinf(a) isinf(a)
+#elif defined(INFINITY)
+/* Might not work, but is required by ISO C99 */
+#define zend_isinf(a) (((a)==INFINITY)?1:0)
+#elif defined(HAVE_FPCLASS)
+#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
+#else
+#define zend_isinf(a) 0
+#endif
+
+#ifdef HAVE_FINITE
+#define zend_finite(a) finite(a)
+#elif defined(HAVE_ISFINITE) || defined(isfinite)
+#define zend_finite(a) isfinite(a)
+#elif defined(fpclassify)
+#define zend_finite(a) ((fpclassify((a))!=FP_INFINITE&&fpclassify((a))!=FP_NAN)?1:0)
+#else
+#define zend_finite(a) (zend_isnan(a) ? 0 : zend_isinf(a) ? 0 : 1)
+#endif
+
+#endif /* ifndef ZEND_ACCONFIG_H_NO_C_PROTOS */
+
+#ifdef NETWARE
+#ifdef USE_WINSOCK
+#/*This detection against winsock is of no use*/ undef HAVE_SOCKLEN_T
+#/*This detection against winsock is of no use*/ undef HAVE_SYS_SOCKET_H
+#endif
+#endif
+])
+
dnl We want this one before the checks, so the checks can modify CFLAGS.
test -z "$CFLAGS" && auto_cflags=1
diff --git a/Zend/micro_bench.php b/Zend/micro_bench.php
new file mode 100644
index 0000000000..70525882eb
--- /dev/null
+++ b/Zend/micro_bench.php
@@ -0,0 +1,358 @@
+<?php
+
+function hallo() {
+}
+
+function simpleucall($n) {
+ for ($i = 0; $i < $n; $i++)
+ hallo();
+}
+
+function simpleudcall($n) {
+ for ($i = 0; $i < $n; $i++)
+ hallo2();
+}
+
+function hallo2() {
+}
+
+function simpleicall($n) {
+ for ($i = 0; $i < $n; $i++)
+ func_num_args();
+}
+
+class Foo {
+ static $a = 0;
+ public $b = 0;
+ const TEST = 0;
+
+ static function read_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = self::$a;
+ }
+ }
+
+ static function write_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ self::$a = 0;
+ }
+ }
+
+ static function isset_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = isset(self::$a);
+ }
+ }
+
+ static function empty_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = empty(self::$a);
+ }
+ }
+
+ static function f() {
+ }
+
+ static function call_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ self::f();
+ }
+ }
+
+ function read_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $this->b;
+ }
+ }
+
+ function write_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $this->b = 0;
+ }
+ }
+
+ function assign_add_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $this->b += 2;
+ }
+ }
+
+ function pre_inc_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ ++$this->b;
+ }
+ }
+
+ function pre_dec_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ --$this->b;
+ }
+ }
+
+ function post_inc_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $this->b++;
+ }
+ }
+
+ function post_dec_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $this->b--;
+ }
+ }
+
+ function isset_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = isset($this->b);
+ }
+ }
+
+ function empty_prop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = empty($this->b);
+ }
+ }
+
+ function g() {
+ }
+
+ function call($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $this->g();
+ }
+ }
+
+ function read_const($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $this::TEST;
+ }
+ }
+
+}
+
+function read_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = Foo::$a;
+ }
+}
+
+function write_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ Foo::$a = 0;
+ }
+}
+
+function isset_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = isset(Foo::$a);
+ }
+}
+
+function empty_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = empty(Foo::$a);
+ }
+}
+
+function call_static($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ Foo::f();
+ }
+}
+
+function create_object($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = new Foo();
+ }
+}
+
+define('TEST', null);
+
+function read_const($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = TEST;
+ }
+}
+
+function read_auto_global($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $_GET;
+ }
+}
+
+$g_var = 0;
+
+function read_global_var($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $GLOBALS['g_var'];
+ }
+}
+
+function read_hash($n) {
+ $hash = array('test' => 0);
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $hash['test'];
+ }
+}
+
+function read_str_offset($n) {
+ $str = "test";
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $str[1];
+ }
+}
+
+function issetor($n) {
+ $val = array(0,1,2,3,4,5,6,7,8,9);
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $val ?: null;
+ }
+}
+
+function issetor2($n) {
+ $f = false; $j = 0;
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $f ?: $j + 1;
+ }
+}
+
+function ternary($n) {
+ $val = array(0,1,2,3,4,5,6,7,8,9);
+ $f = false;
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $f ? null : $val;
+ }
+}
+
+function ternary2($n) {
+ $f = false; $j = 0;
+ for ($i = 0; $i < $n; ++$i) {
+ $x = $f ? $f : $j + 1;
+ }
+}
+
+/*****/
+
+function empty_loop($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ }
+}
+
+function getmicrotime()
+{
+ $t = gettimeofday();
+ return ($t['sec'] + $t['usec'] / 1000000);
+}
+
+function start_test()
+{
+ ob_start();
+ return getmicrotime();
+}
+
+function end_test($start, $name, $overhead = null)
+{
+ global $total;
+ global $last_time;
+ $end = getmicrotime();
+ ob_end_clean();
+ $last_time = $end-$start;
+ $total += $last_time;
+ $num = number_format($last_time,3);
+ $pad = str_repeat(" ", 24-strlen($name)-strlen($num));
+ if (is_null($overhead)) {
+ echo $name.$pad.$num."\n";
+ } else {
+ $num2 = number_format($last_time - $overhead,3);
+ echo $name.$pad.$num." ".$num2."\n";
+ }
+ ob_start();
+ return getmicrotime();
+}
+
+function total()
+{
+ global $total;
+ $pad = str_repeat("-", 24);
+ echo $pad."\n";
+ $num = number_format($total,3);
+ $pad = str_repeat(" ", 24-strlen("Total")-strlen($num));
+ echo "Total".$pad.$num."\n";
+}
+
+const N = 5000000;
+
+$t0 = $t = start_test();
+empty_loop(N);
+$t = end_test($t, 'empty_loop');
+$overhead = $last_time;
+simpleucall(N);
+$t = end_test($t, 'func()', $overhead);
+simpleudcall(N);
+$t = end_test($t, 'undef_func()', $overhead);
+simpleicall(N);
+$t = end_test($t, 'int_func()', $overhead);
+Foo::read_static(N);
+$t = end_test($t, '$x = self::$x', $overhead);
+Foo::write_static(N);
+$t = end_test($t, 'self::$x = 0', $overhead);
+Foo::isset_static(N);
+$t = end_test($t, 'isset(self::$x)', $overhead);
+Foo::empty_static(N);
+$t = end_test($t, 'empty(self::$x)', $overhead);
+read_static(N);
+$t = end_test($t, '$x = Foo::$x', $overhead);
+write_static(N);
+$t = end_test($t, 'Foo::$x = 0', $overhead);
+isset_static(N);
+$t = end_test($t, 'isset(Foo::$x)', $overhead);
+empty_static(N);
+$t = end_test($t, 'empty(Foo::$x)', $overhead);
+Foo::call_static(N);
+$t = end_test($t, 'self::f()', $overhead);
+call_static(N);
+$t = end_test($t, 'Foo::f()', $overhead);
+$x = new Foo();
+$x->read_prop(N);
+$t = end_test($t, '$x = $this->x', $overhead);
+$x->write_prop(N);
+$t = end_test($t, '$this->x = 0', $overhead);
+$x->assign_add_prop(N);
+$t = end_test($t, '$this->x += 2', $overhead);
+$x->pre_inc_prop(N);
+$t = end_test($t, '++$this->x', $overhead);
+$x->pre_dec_prop(N);
+$t = end_test($t, '--$this->x', $overhead);
+$x->post_inc_prop(N);
+$t = end_test($t, '$this->x++', $overhead);
+$x->post_dec_prop(N);
+$t = end_test($t, '$this->x--', $overhead);
+$x->isset_prop(N);
+$t = end_test($t, 'isset($this->x)', $overhead);
+$x->empty_prop(N);
+$t = end_test($t, 'empty($this->x)', $overhead);
+$x->call(N);
+$t = end_test($t, '$this->f()', $overhead);
+$x->read_const(N);
+$t = end_test($t, '$x = Foo::TEST', $overhead);
+create_object(N);
+$t = end_test($t, 'new Foo()', $overhead);
+read_const(N);
+$t = end_test($t, '$x = TEST', $overhead);
+read_auto_global(N);
+$t = end_test($t, '$x = $_GET', $overhead);
+read_global_var(N);
+$t = end_test($t, '$x = $GLOBALS[\'v\']', $overhead);
+read_hash(N);
+$t = end_test($t, '$x = $hash[\'v\']', $overhead);
+read_str_offset(N);
+$t = end_test($t, '$x = $str[0]', $overhead);
+issetor(N);
+$t = end_test($t, '$x = $a ?: null', $overhead);
+issetor2(N);
+$t = end_test($t, '$x = $f ?: tmp', $overhead);
+ternary(N);
+$t = end_test($t, '$x = $f ? $f : $a', $overhead);
+ternary2(N);
+$t = end_test($t, '$x = $f ? $f : tmp', $overhead);
+total($t0, "Total");
diff --git a/Zend/tests/026.phpt b/Zend/tests/026.phpt
index 784b12c69b..5fa0e1677c 100644
--- a/Zend/tests/026.phpt
+++ b/Zend/tests/026.phpt
@@ -21,5 +21,5 @@ print "ok\n";
Notice: Trying to get property of non-object in %s on line %d
ok
-Strict Standards: Creating default object from empty value in %s on line %d
+Warning: Creating default object from empty value in %s on line %d
ok
diff --git a/Zend/tests/033.phpt b/Zend/tests/033.phpt
index c8651159a6..17319e0d61 100644
--- a/Zend/tests/033.phpt
+++ b/Zend/tests/033.phpt
@@ -26,6 +26,6 @@ Notice: Undefined variable: arr in %s on line %d
Notice: Trying to get property of non-object in %s on line %d
-Strict Standards: Creating default object from empty value in %s on line %d
+Warning: Creating default object from empty value in %s on line %d
-Strict Standards: Creating default object from empty value in %s on line %d
+Warning: Creating default object from empty value in %s on line %d
diff --git a/Zend/tests/argument_restriction_001.phpt b/Zend/tests/argument_restriction_001.phpt
new file mode 100644
index 0000000000..e62ad300c9
--- /dev/null
+++ b/Zend/tests/argument_restriction_001.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #55719 (Argument restriction should come with a more specific error message)
+--FILE--
+<?php
+Class Base {
+ public function &test($foo, array $bar, $option = NULL, $extra = "lllllllllllllllllllllllllllllllllllllllllllllllllll") {
+ }
+}
+
+class Sub extends Base {
+ public function &test() {
+ }
+}
+?>
+--EXPECTF--
+Strict Standards: Declaration of Sub::test() should be compatible with & Base::test($foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_001.php on line %d
diff --git a/Zend/tests/argument_restriction_002.phpt b/Zend/tests/argument_restriction_002.phpt
new file mode 100644
index 0000000000..c6a472e0f5
--- /dev/null
+++ b/Zend/tests/argument_restriction_002.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #55719 (Argument restriction should come with a more specific error message)
+--FILE--
+<?php
+Abstract Class Base {
+ public function test($foo, array &$bar, $option = NULL, $extra = 3.141592653589793238462643383279502884197169399375105 ) {
+ }
+}
+
+class Sub extends Base {
+ public function test($foo, array &$bar) {
+ }
+}
+?>
+--EXPECTF--
+Strict Standards: Declaration of Sub::test() should be compatible with Base::test($foo, array &$bar, $option = NULL, $extra = 3.1415926535898) in %sargument_restriction_002.php on line %d
diff --git a/Zend/tests/argument_restriction_003.phpt b/Zend/tests/argument_restriction_003.phpt
new file mode 100644
index 0000000000..393581fcfc
--- /dev/null
+++ b/Zend/tests/argument_restriction_003.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #55719 (Argument restriction should come with a more specific error message)
+--FILE--
+<?php
+class Foo {
+}
+
+Abstract Class Base {
+ public function test(Foo $foo, array $bar, $option = NULL, $extra = "lllllllllllllllllllllllllllllllllllllllllllllllllll") {
+ }
+}
+
+class Sub extends Base {
+ public function test() {
+ }
+}
+?>
+--EXPECTF--
+Strict Standards: Declaration of Sub::test() should be compatible with Base::test(Foo $foo, array $bar, $option = NULL, $extra = 'llllllllll...') in %sargument_restriction_003.php on line %d
diff --git a/Zend/tests/argument_restriction_004.phpt b/Zend/tests/argument_restriction_004.phpt
new file mode 100644
index 0000000000..599b3e1604
--- /dev/null
+++ b/Zend/tests/argument_restriction_004.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #55719 (Argument restriction should come with a more specific error message)
+--FILE--
+<?php
+class Foo {
+}
+
+Abstract Class Base {
+ abstract public function test(Foo $foo, array $bar, $option = NULL, $extra = 16777215) ;
+}
+
+class Sub extends Base {
+ public function test(Foo $foo, array $bar, $option = NULL, $extra = 0xffffff ) {
+ }
+}
+?>
+--EXPECTF--
diff --git a/Zend/tests/argument_restriction_005.phpt b/Zend/tests/argument_restriction_005.phpt
new file mode 100644
index 0000000000..2826fe6a81
--- /dev/null
+++ b/Zend/tests/argument_restriction_005.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #55719 (Argument restriction should come with a more specific error message)
+--FILE--
+<?php
+class Sub implements ArrayAccess {
+ public function offsetSet() {
+ }
+}
+?>
+--EXPECTF--
+Fatal error: Declaration of Sub::offsetSet() must be compatible with ArrayAccess::offsetSet($offset, $value) in %sargument_restriction_005.php on line %d
diff --git a/Zend/tests/argument_restriction_006.phpt b/Zend/tests/argument_restriction_006.phpt
new file mode 100644
index 0000000000..948fc304c7
--- /dev/null
+++ b/Zend/tests/argument_restriction_006.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #60174 (Notice when array in method prototype error)
+--FILE--
+<?php
+Abstract Class Base {
+ public function test($foo, $extra = array("test")) {
+ }
+}
+
+class Sub extends Base {
+ public function test($foo, $extra) {
+ }
+}
+?>
+--EXPECTF--
+Strict Standards: Declaration of Sub::test() should be compatible with Base::test($foo, $extra = Array) in %sargument_restriction_006.php on line %d
diff --git a/Zend/tests/array_type_hint_001.phpt b/Zend/tests/array_type_hint_001.phpt
index 533319b6ea..a676992778 100644
--- a/Zend/tests/array_type_hint_001.phpt
+++ b/Zend/tests/array_type_hint_001.phpt
@@ -12,4 +12,4 @@ foo(123);
--EXPECTF--
3
-Catchable fatal error: Argument 1 passed to foo() must be an array, integer given, called in %sarray_type_hint_001.php on line 7 and defined in %sarray_type_hint_001.php on line 2
+Catchable fatal error: Argument 1 passed to foo() must be of the type array, integer given, called in %sarray_type_hint_001.php on line 7 and defined in %sarray_type_hint_001.php on line 2
diff --git a/Zend/tests/binary-32bit.phpt b/Zend/tests/binary-32bit.phpt
new file mode 100644
index 0000000000..4b87aded4f
--- /dev/null
+++ b/Zend/tests/binary-32bit.phpt
@@ -0,0 +1,154 @@
+--TEST--
+testing binary literals
+--INI--
+precision=14
+--SKIPIF--
+<?php if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only"); ?>
+--FILE--
+<?php
+var_dump(0b1);
+var_dump(0b11);
+var_dump(0b111);
+var_dump(0b1111);
+var_dump(0b11111);
+var_dump(0b111111);
+var_dump(0b1111111);
+var_dump(0b11111111);
+var_dump(0b111111111);
+var_dump(0b1111111111);
+var_dump(0b11111111111);
+var_dump(0b111111111111);
+var_dump(0b1111111111111);
+var_dump(0b11111111111111);
+var_dump(0b111111111111111);
+var_dump(0b1111111111111111);
+var_dump(0b11111111111111111);
+var_dump(0b111111111111111111);
+var_dump(0b1111111111111111111);
+var_dump(0b11111111111111111111);
+var_dump(0b111111111111111111111);
+var_dump(0b1111111111111111111111);
+var_dump(0b11111111111111111111111);
+var_dump(0b111111111111111111111111);
+var_dump(0b1111111111111111111111111);
+var_dump(0b11111111111111111111111111);
+var_dump(0b111111111111111111111111111);
+var_dump(0b1111111111111111111111111111);
+var_dump(0b11111111111111111111111111111);
+var_dump(0b111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111111111);
+
+var_dump(-0b1111111111111111111111111111111111111111111111111111111111111111);
+var_dump(-0b111111111111111111111111111111111111111111111111111111111111111);
+var_dump(-0b11111111111111111111111111111111111111111111111111111111111111);
+var_dump(-0b111111111111111111111111111111111);
+var_dump(-0b11111111111111111111111111111111);
+var_dump(-0b1111111111111111111111111111111);
+var_dump(-0b111111111111111111111111111111);
+var_dump(-0b1);
+--EXPECT--
+int(1)
+int(3)
+int(7)
+int(15)
+int(31)
+int(63)
+int(127)
+int(255)
+int(511)
+int(1023)
+int(2047)
+int(4095)
+int(8191)
+int(16383)
+int(32767)
+int(65535)
+int(131071)
+int(262143)
+int(524287)
+int(1048575)
+int(2097151)
+int(4194303)
+int(8388607)
+int(16777215)
+int(33554431)
+int(67108863)
+int(134217727)
+int(268435455)
+int(536870911)
+int(1073741823)
+int(2147483647)
+float(4294967295)
+float(8589934591)
+float(17179869183)
+float(34359738367)
+float(68719476735)
+float(137438953471)
+float(274877906943)
+float(549755813887)
+float(1099511627775)
+float(2199023255551)
+float(4398046511103)
+float(8796093022207)
+float(17592186044415)
+float(35184372088831)
+float(70368744177663)
+float(1.4073748835533E+14)
+float(2.8147497671066E+14)
+float(5.6294995342131E+14)
+float(1.1258999068426E+15)
+float(2.2517998136852E+15)
+float(4.5035996273705E+15)
+float(9.007199254741E+15)
+float(1.8014398509482E+16)
+float(3.6028797018964E+16)
+float(7.2057594037928E+16)
+float(1.4411518807586E+17)
+float(2.8823037615171E+17)
+float(5.7646075230342E+17)
+float(1.1529215046068E+18)
+float(2.3058430092137E+18)
+float(4.6116860184274E+18)
+float(9.2233720368548E+18)
+float(1.844674407371E+19)
+float(-1.844674407371E+19)
+float(-9.2233720368548E+18)
+float(-4.6116860184274E+18)
+float(-8589934591)
+float(-4294967295)
+int(-2147483647)
+int(-1073741823)
+int(-1)
diff --git a/Zend/tests/binary.phpt b/Zend/tests/binary.phpt
new file mode 100644
index 0000000000..039cf80ce4
--- /dev/null
+++ b/Zend/tests/binary.phpt
@@ -0,0 +1,154 @@
+--TEST--
+testing binary literals
+--INI--
+precision=32
+--SKIPIF--
+<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only"); ?>
+--FILE--
+<?php
+var_dump(0b1);
+var_dump(0b11);
+var_dump(0b111);
+var_dump(0b1111);
+var_dump(0b11111);
+var_dump(0b111111);
+var_dump(0b1111111);
+var_dump(0b11111111);
+var_dump(0b111111111);
+var_dump(0b1111111111);
+var_dump(0b11111111111);
+var_dump(0b111111111111);
+var_dump(0b1111111111111);
+var_dump(0b11111111111111);
+var_dump(0b111111111111111);
+var_dump(0b1111111111111111);
+var_dump(0b11111111111111111);
+var_dump(0b111111111111111111);
+var_dump(0b1111111111111111111);
+var_dump(0b11111111111111111111);
+var_dump(0b111111111111111111111);
+var_dump(0b1111111111111111111111);
+var_dump(0b11111111111111111111111);
+var_dump(0b111111111111111111111111);
+var_dump(0b1111111111111111111111111);
+var_dump(0b11111111111111111111111111);
+var_dump(0b111111111111111111111111111);
+var_dump(0b1111111111111111111111111111);
+var_dump(0b11111111111111111111111111111);
+var_dump(0b111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b111111111111111111111111111111111111111111111111111111111111111 + 1);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b1111111111111111111111111111111111111111111111111111111111111111 + 1);
+var_dump(0b11111111111111111111111111111111111111111111111111111111111111111);
+var_dump(0b11111111111111111111111111111111111111111111111111111111111111111 + 1);
+
+var_dump(-0b1111111111111111111111111111111111111111111111111111111111111111);
+var_dump(-0b111111111111111111111111111111111111111111111111111111111111111);
+var_dump(-0b11111111111111111111111111111111111111111111111111111111111111);
+var_dump(-0b1);
+--EXPECT--
+int(1)
+int(3)
+int(7)
+int(15)
+int(31)
+int(63)
+int(127)
+int(255)
+int(511)
+int(1023)
+int(2047)
+int(4095)
+int(8191)
+int(16383)
+int(32767)
+int(65535)
+int(131071)
+int(262143)
+int(524287)
+int(1048575)
+int(2097151)
+int(4194303)
+int(8388607)
+int(16777215)
+int(33554431)
+int(67108863)
+int(134217727)
+int(268435455)
+int(536870911)
+int(1073741823)
+int(2147483647)
+int(4294967295)
+int(8589934591)
+int(17179869183)
+int(34359738367)
+int(68719476735)
+int(137438953471)
+int(274877906943)
+int(549755813887)
+int(1099511627775)
+int(2199023255551)
+int(4398046511103)
+int(8796093022207)
+int(17592186044415)
+int(35184372088831)
+int(70368744177663)
+int(140737488355327)
+int(281474976710655)
+int(562949953421311)
+int(1125899906842623)
+int(2251799813685247)
+int(4503599627370495)
+int(9007199254740991)
+int(18014398509481983)
+int(36028797018963967)
+int(72057594037927935)
+int(144115188075855871)
+int(288230376151711743)
+int(576460752303423487)
+int(1152921504606846975)
+int(2305843009213693951)
+int(4611686018427387903)
+int(9223372036854775807)
+float(9223372036854775808)
+float(18446744073709549568)
+float(18446744073709549568)
+float(36893488147419099136)
+float(36893488147419099136)
+float(-18446744073709549568)
+int(-9223372036854775807)
+int(-4611686018427387903)
+int(-1)
diff --git a/Zend/tests/bug31098.phpt b/Zend/tests/bug31098.phpt
index c8626abef1..23cec9bbf4 100644
--- a/Zend/tests/bug31098.phpt
+++ b/Zend/tests/bug31098.phpt
@@ -17,13 +17,12 @@ var_dump(isset($a['b']));
$simpleString = "Bogus String Text";
echo isset($simpleString->wrong)?"bug\n":"ok\n";
-echo isset($simpleString["wrong"])?"ok\n":"bug\n";
+echo isset($simpleString["wrong"])?"bug\n":"ok\n";
echo isset($simpleString[-1])?"bug\n":"ok\n";
echo isset($simpleString[0])?"ok\n":"bug\n";
echo isset($simpleString["0"])?"ok\n":"bug\n";
echo isset($simpleString["16"])?"ok\n":"bug\n";
echo isset($simpleString["17"])?"bug\n":"ok\n";
-echo isset($simpleString["wrong"][0])?"bug\n":"ok\n";
echo $simpleString->wrong === null?"ok\n":"bug\n";
echo $simpleString["wrong"] === "B"?"ok\n":"bug\n";
echo $simpleString["0"] === "B"?"ok\n":"bug\n";
@@ -35,9 +34,8 @@ bool(false)
bool(false)
bool(false)
bool(false)
-bool(true)
-bool(true)
-ok
+bool(false)
+bool(false)
ok
ok
ok
@@ -46,8 +44,12 @@ ok
ok
ok
-Notice: Trying to get property of non-object in %sbug31098.php on line %d
-ok
+Notice: Trying to get property of non-object in %s on line %d
ok
+
+Warning: Illegal string offset 'wrong' in %s on line %d
ok
ok
+
+Warning: Illegal string offset 'wrong' in %s on line %d
+ok \ No newline at end of file
diff --git a/Zend/tests/bug35655.phpt b/Zend/tests/bug35655.phpt
index 10d9c0c746..bbb137799a 100644
--- a/Zend/tests/bug35655.phpt
+++ b/Zend/tests/bug35655.phpt
@@ -4,7 +4,6 @@ Bug #35655 (whitespace following end of heredoc is lost)
highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
-highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
--FILE--
diff --git a/Zend/tests/bug39018.phpt b/Zend/tests/bug39018.phpt
index 6de9092c9f..32566ba864 100644
--- a/Zend/tests/bug39018.phpt
+++ b/Zend/tests/bug39018.phpt
@@ -6,7 +6,7 @@ Bug #39018 (Error control operator '@' fails to suppress "Uninitialized string o
error_reporting(E_ALL);
$a = 'foo';
-$a[11111111111];
+$a[111111111111111111111];
$a = '';
@@ -62,21 +62,42 @@ print "\nDone\n";
?>
--EXPECTF--
+Notice: String offset cast occurred in %s on line %d
-Notice: Uninitialized string offset: 0 in %s on line 12
+Notice: Uninitialized string offset: 0 in %s on line %d
-Notice: Uninitialized string offset: %i in %s on line 16
+Notice: Uninitialized string offset: 0 in %s on line %d
-Notice: Uninitialized string offset: 4 in %s on line 28
+Notice: String offset cast occurred in %s on line %d
-Notice: Uninitialized string offset: 4 in %s on line 34
+Notice: Uninitialized string offset: %i in %s on line %d
-Notice: Uninitialized string offset: 4 in %s on line 38
+Notice: String offset cast occurred in %s on line %d
-Notice: Uninitialized string offset: 4 in %s on line 42
+Notice: Uninitialized string offset: %i in %s on line %d
-Notice: Uninitialized string offset: 4 in %s on line 46
+Notice: Uninitialized string offset: 0 in %s on line %d
-Notice: Uninitialized string offset: 12 in %s on line 52
+Notice: Uninitialized string offset: 4 in %s on line %d
+
+Notice: Uninitialized string offset: 4 in %s on line %d
+
+Notice: Uninitialized string offset: 4 in %s on line %d
+
+Notice: Uninitialized string offset: 4 in %s on line %d
+
+Notice: Uninitialized string offset: 4 in %s on line %d
+
+Notice: String offset cast occurred in %s on line %d
+
+Notice: Uninitialized string offset: 12 in %s on line %d
+
+Notice: String offset cast occurred in %s on line %d
+
+Notice: Uninitialized string offset: 12 in %s on line %d
+
+Notice: String offset cast occurred in %s on line %d
+
+Notice: String offset cast occurred in %s on line %d
b
Done
diff --git a/Zend/tests/bug39304.phpt b/Zend/tests/bug39304.phpt
index 0129d21348..8303b82573 100644
--- a/Zend/tests/bug39304.phpt
+++ b/Zend/tests/bug39304.phpt
@@ -4,8 +4,13 @@ Bug #39304 (Segmentation fault with list unpacking of string offset)
<?php
$s = "";
list($a, $b) = $s[0];
+echo "I am alive";
?>
--EXPECTF--
-Notice: Uninitialized string offset: 0 in %sbug39304.php on line 3
+Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d
+
+Notice: Uninitialized string offset: 1 in %sbug39304.php on line %d
+
+Notice: Uninitialized string offset: 0 in %sbug39304.php on line %d
+I am alive
-Fatal error: Cannot use string offset as an array in %sbug39304.php on line 3
diff --git a/Zend/tests/bug39304_2_4.phpt b/Zend/tests/bug39304_2_4.phpt
new file mode 100644
index 0000000000..b0e6ddc72c
--- /dev/null
+++ b/Zend/tests/bug39304_2_4.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #39304 (Segmentation fault with list unpacking of string offset)
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+ $s = "";
+ list($a, $b) = $s[0];
+ var_dump($a,$b);
+?>
+--EXPECTF--
+Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d
+
+Notice: Uninitialized string offset: 1 in %sbug39304_2_4.php on line %d
+
+Notice: Uninitialized string offset: 0 in %sbug39304_2_4.php on line %d
+string(0) ""
+string(0) ""
diff --git a/Zend/tests/bug42767.phpt b/Zend/tests/bug42767.phpt
index 484918cdb7..b57177e4b5 100644
--- a/Zend/tests/bug42767.phpt
+++ b/Zend/tests/bug42767.phpt
@@ -4,7 +4,6 @@ Bug #42767 (highlight_string() truncates trailing comments)
highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
-highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
--FILE--
diff --git a/Zend/tests/bug47981.phpt b/Zend/tests/bug47981.phpt
index 2d68d3706f..c0fd69abf9 100644
--- a/Zend/tests/bug47981.phpt
+++ b/Zend/tests/bug47981.phpt
@@ -14,6 +14,4 @@ class b implements a { function f($a=1) {}}
class c extends b {function f() {}}
?>
--EXPECTF--
-string(62) "Declaration of c::f() should be compatible with that of b::f()"
-
-
+string(60) "Declaration of c::f() should be compatible with b::f($a = 1)"
diff --git a/Zend/tests/bug51421.phpt b/Zend/tests/bug51421.phpt
new file mode 100644
index 0000000000..bc1758c300
--- /dev/null
+++ b/Zend/tests/bug51421.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #51421 (Abstract __construct constructor argument list not enforced)
+--FILE--
+<?php
+
+class ExampleClass {}
+
+abstract class TestInterface {
+ abstract public function __construct(ExampleClass $var);
+}
+
+class Test extends TestInterface {
+ public function __construct() {}
+}
+
+?>
+--EXPECTF--
+Fatal error: Declaration of Test::__construct() must be compatible with TestInterface::__construct(ExampleClass $var) in %s on line %d
diff --git a/Zend/tests/bug52041.phpt b/Zend/tests/bug52041.phpt
index b481b894da..c4b9f97ee5 100644
--- a/Zend/tests/bug52041.phpt
+++ b/Zend/tests/bug52041.phpt
@@ -13,38 +13,63 @@ foo()->a->b++;
foo()->a += 2;
foo()->a->b += 2;
-//foo()[0] = 1;
-//foo()[0][0] = 2;
-//foo()[0]++;
-//foo()[0][0]++;
-//foo()[0] += 2;
-//foo()[0][0] += 2;
+foo()[0] = 1;
+foo()[0][0] = 2;
+foo()[0]++;
+foo()[0][0]++;
+foo()[0] += 2;
+foo()[0][0] += 2;
+
var_dump(foo());
?>
--EXPECTF--
Notice: Undefined variable: x in %sbug52041.php on line 3
-Strict Standards: Creating default object from empty value in %sbug52041.php on line 6
+Warning: Creating default object from empty value in %sbug52041.php on line 6
+
+Notice: Undefined variable: x in %sbug52041.php on line 3
+
+Warning: Creating default object from empty value in %sbug52041.php on line 7
+
+Notice: Undefined variable: x in %sbug52041.php on line 3
+
+Warning: Creating default object from empty value in %sbug52041.php on line 8
Notice: Undefined variable: x in %sbug52041.php on line 3
-Strict Standards: Creating default object from empty value in %sbug52041.php on line 7
+Warning: Creating default object from empty value in %sbug52041.php on line 9
Notice: Undefined variable: x in %sbug52041.php on line 3
-Strict Standards: Creating default object from empty value in %sbug52041.php on line 8
+Warning: Creating default object from empty value in %sbug52041.php on line 10
Notice: Undefined variable: x in %sbug52041.php on line 3
-Strict Standards: Creating default object from empty value in %sbug52041.php on line 9
+Warning: Creating default object from empty value in %sbug52041.php on line 11
Notice: Undefined variable: x in %sbug52041.php on line 3
-Strict Standards: Creating default object from empty value in %sbug52041.php on line 10
+Notice: Undefined variable: x in %sbug52041.php on line 3
Notice: Undefined variable: x in %sbug52041.php on line 3
-Strict Standards: Creating default object from empty value in %sbug52041.php on line 11
+Notice: Undefined offset: 0 in %sbug52041.php on line 15
+
+Notice: Undefined variable: x in %sbug52041.php on line 3
+
+Notice: Undefined offset: 0 in %sbug52041.php on line 16
+
+Notice: Undefined offset: 0 in %sbug52041.php on line 16
+
+Notice: Undefined variable: x in %sbug52041.php on line 3
+
+Notice: Undefined offset: 0 in %sbug52041.php on line 17
+
+Notice: Undefined variable: x in %sbug52041.php on line 3
+
+Notice: Undefined offset: 0 in %sbug52041.php on line 18
+
+Notice: Undefined offset: 0 in %sbug52041.php on line 18
Notice: Undefined variable: x in %sbug52041.php on line 3
NULL
diff --git a/Zend/tests/bug52237.phpt b/Zend/tests/bug52237.phpt
index a466a8ce02..0b54787aa9 100644
--- a/Zend/tests/bug52237.phpt
+++ b/Zend/tests/bug52237.phpt
@@ -7,5 +7,6 @@ preg_match('//', '', $data->info);
var_dump($data);
?>
--EXPECTF--
+
Warning: Attempt to modify property of non-object in %sbug52237.php on line 3
string(4) "test"
diff --git a/Zend/tests/bug52614.phpt b/Zend/tests/bug52614.phpt
new file mode 100644
index 0000000000..d220881679
--- /dev/null
+++ b/Zend/tests/bug52614.phpt
@@ -0,0 +1,83 @@
+--TEST--
+Bug #52614 (Memory leak when writing on uninitialized variable returned from method call)
+--FILE--
+<?php
+class foo {
+ public $a1;
+ public $a2 = array();
+ public $a3;
+ public $o1;
+ public $o2;
+
+ public function f1() {
+ return $this->a1;
+ }
+
+ public function f2() {
+ return $this->a2;
+ }
+
+ public function f3() {
+ $this->a3 = array();
+ return $this->a3;
+ }
+
+ public function f4() {
+ return $this->o1;
+ }
+
+ public function f5() {
+ $this->o2 = new stdClass;
+ return $this->o2;
+ }
+
+ public function &f6() {
+ return $this->a1;
+ }
+
+ public function f7(&$x) {
+ $x = 2;
+ }
+
+}
+
+$foo = new foo;
+
+$foo->f1()[0] = 1;
+var_dump($foo->a1);
+
+$foo->f2()[0] = 1;
+var_dump($foo->a2);
+
+$foo->f3()[0] = 1;
+var_dump($foo->a3);
+
+$foo->f4()->a = 1;
+var_dump($foo->o1);
+
+$foo->f5()->a = 1;
+var_dump($foo->o2);
+
+$foo->a1[0] = 1;
+$foo->f7($foo->f6()[0]);
+var_dump($foo->a1[0]);
+$foo->f1()[0]++;
+var_dump($foo->a1[0]);
+$foo->f6()[0]++;
+var_dump($foo->a1[0]);
+--EXPECTF--
+NULL
+array(0) {
+}
+array(0) {
+}
+
+Warning: Creating default object from empty value in %sbug52614.php on line 52
+NULL
+object(stdClass)#%d (1) {
+ ["a"]=>
+ int(1)
+}
+int(2)
+int(2)
+int(3)
diff --git a/Zend/tests/bug52940.phpt b/Zend/tests/bug52940.phpt
new file mode 100644
index 0000000000..f8d31c0dbe
--- /dev/null
+++ b/Zend/tests/bug52940.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #52940 (call_user_func_array still allows call-time pass-by-reference)
+--FILE--
+<?php
+function foo($a) {
+ $a++;
+ var_dump($a);
+}
+function bar(&$a) {
+ $a++;
+ var_dump($a);
+}
+$a = 1;
+call_user_func_array("foo", array(&$a));
+var_dump($a);
+call_user_func_array("bar", array(&$a));
+var_dump($a);
+?>
+--EXPECT--
+int(2)
+int(1)
+int(2)
+int(2)
diff --git a/Zend/tests/bug53347.phpt b/Zend/tests/bug53347.phpt
new file mode 100644
index 0000000000..66e4ec261d
--- /dev/null
+++ b/Zend/tests/bug53347.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #53347 Segfault accessing static method
+--FILE--
+<?php class ezcConsoleOutput
+{
+ protected static $color = array( 'gray' => 30 );
+
+ public static function isValidFormatCode( $type, $key )
+ {
+ return isset( self::${$type}[$key] );
+ }
+}
+
+var_dump( ezcConsoleOutput::isValidFormatCode( 'color', 'gray' ) );
+?>
+--EXPECT--
+bool(true)
diff --git a/Zend/tests/bug53511.phpt b/Zend/tests/bug53511.phpt
new file mode 100644
index 0000000000..88f0cbe8f4
--- /dev/null
+++ b/Zend/tests/bug53511.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #53511 (Exceptions are lost in case an exception is thrown in catch operator)
+--FILE--
+<?php
+class Foo {
+ function __destruct() {
+ throw new Exception("ops 1");
+ }
+}
+
+function test() {
+ $e = new Foo();
+ try {
+ throw new Exception("ops 2");
+ } catch (Exception $e) {
+ echo $e->getMessage()."\n";
+ }
+}
+
+test();
+echo "bug\n";
+--EXPECTF--
+Fatal error: Uncaught exception 'Exception' with message 'ops 2' in %sbug53511.php:11
+Stack trace:
+#0 %sbug53511.php(17): test()
+#1 {main}
+
+Next exception 'Exception' with message 'ops 1' in %sbug53511.php:4
+Stack trace:
+#0 %sbug53511.php(12): Foo->__destruct()
+#1 %sbug53511.php(17): test()
+#2 {main}
+ thrown in %sbug53511.php on line 4
diff --git a/Zend/tests/bug53748.phpt b/Zend/tests/bug53748.phpt
new file mode 100644
index 0000000000..2f171fe455
--- /dev/null
+++ b/Zend/tests/bug53748.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Bug #53748 (Using traits lead to a segmentation fault)
+--FILE--
+<?php
+
+trait Singleton {
+ protected static $instances=array();
+ abstract protected function __construct($config);
+ public static function getInstance($config) {
+ if (!isset(self::$instances[$serialize = serialize($config)])) {
+ self::$instances[$serialize] = new self($config);
+ }
+ return self::$instances[$serialize];
+ }
+}
+
+class MyHelloWorld {
+ use Singleton;
+ public function __construct($config)
+ {
+ var_dump( $config);
+ }
+}
+
+
+$o= myHelloWorld::getInstance(1);
+$o= myHelloWorld::getInstance(1);
+$o= myHelloWorld::getInstance(2);
+$o= myHelloWorld::getInstance(array(1=>2));
+$o= myHelloWorld::getInstance(array(1=>2));
+
+?>
+--EXPECTF--
+int(1)
+int(2)
+array(1) {
+ [1]=>
+ int(2)
+}
diff --git a/Zend/tests/bug54262.phpt b/Zend/tests/bug54262.phpt
index 1b9d3513cc..17a6ea6381 100644
--- a/Zend/tests/bug54262.phpt
+++ b/Zend/tests/bug54262.phpt
@@ -9,7 +9,7 @@ $simpleString["wrong"] = "f";
echo "ok\n";
?>
--EXPECTF--
-bool(true)
+bool(false)
Warning: Attempt to modify property of non-object in %sbug54262.php on line 4
diff --git a/Zend/tests/bug54547.phpt b/Zend/tests/bug54547.phpt
new file mode 100644
index 0000000000..452cbb8a53
--- /dev/null
+++ b/Zend/tests/bug54547.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #54547: wrong equality of string numbers near LONG_MAX with 64-bit longs
+--SKIPIF--
+<?php
+if (PHP_INT_MAX !== 9223372036854775807)
+ die("skip for 64-bit long systems only");
+--FILE--
+<?php
+var_dump("9223372036854775807" == "9223372036854775808");
+var_dump("-9223372036854775808" == "-9223372036854775809");
+var_dump("0x7fffffffffffffff" == "9223372036854775808");
+
+/* not exactly what the bug is about, but closely related problem: */
+var_dump("999223372036854775807"=="999223372036854775808");
+var_dump("899223372036854775807">"00999223372036854775807");
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
diff --git a/Zend/tests/bug55086.phpt b/Zend/tests/bug55086.phpt
new file mode 100644
index 0000000000..9a5c747b9f
--- /dev/null
+++ b/Zend/tests/bug55086.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #55086 (Namespace alias does not work inside trait's use block)
+--FILE--
+<?php
+namespace N1 {
+
+ trait T1 {
+ public function hello() { return 'hello from t1'; }
+ }
+
+ trait T2 {
+ public function hello() { return 'hello from t2'; }
+ }
+
+}
+namespace N2 {
+ use N1\T1;
+ use N1\T2;
+ class A {
+ use T1, T2 {
+ T1::hello insteadof T2;
+ T1::hello as foo;
+ }
+ }
+ $a = new A;
+ echo $a->hello(), PHP_EOL;
+ echo $a->foo(), PHP_EOL;
+ try {
+ } catch(namespace \Foo $e)
+ {
+ }
+}
+?>
+--EXPECT--
+hello from t1
+hello from t1
diff --git a/Zend/tests/bug55135.phpt b/Zend/tests/bug55135.phpt
new file mode 100644
index 0000000000..f6d0aafaca
--- /dev/null
+++ b/Zend/tests/bug55135.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #55135 (Array keys are no longer type casted in unset())
+--FILE--
+<?php
+// This fails.
+$array = array(1 => 2);
+$a = "1";
+unset($array[$a]);
+print_r($array);
+
+// Those works.
+$array = array(1 => 2);
+$a = 1;
+unset($array[$a]);
+print_r($array);
+
+$array = array(1 => 2);
+unset($array[1]);
+print_r($array);
+
+$array = array(1 => 2);
+$a = 1;
+unset($array["1"]);
+print_r($array);
+?>
+--EXPECT--
+Array
+(
+)
+Array
+(
+)
+Array
+(
+)
+Array
+(
+)
diff --git a/Zend/tests/bug55137.phpt b/Zend/tests/bug55137.phpt
new file mode 100644
index 0000000000..4a4e6e61a2
--- /dev/null
+++ b/Zend/tests/bug55137.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #55137 (Changing trait static method visibility)
+--FILE--
+<?php
+
+trait A {
+ protected static function foo() { echo "abc\n"; }
+ private static function bar() { echo "def\n"; }
+}
+
+
+class B {
+ use A {
+ A::foo as public;
+ A::bar as public baz;
+ }
+}
+
+B::foo();
+B::baz();
+
+
+?>
+--EXPECT--
+abc
+def
diff --git a/Zend/tests/bug55247.phpt b/Zend/tests/bug55247.phpt
new file mode 100644
index 0000000000..6fa893f892
--- /dev/null
+++ b/Zend/tests/bug55247.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Request #55247 (Parser problem with static calls using string method name)
+--FILE--
+<?php
+class Test{
+ public static function __callStatic($method, $arguments)
+ {
+ echo $method . PHP_EOL;
+ }
+ public function __call($method, $arguments)
+ {
+ echo $method . PHP_EOL;
+ }
+}
+
+$method = 'method';
+
+$test = new Test();
+
+$test->method();
+$test->$method();
+$test->{'method'}();
+
+Test::method();
+Test::$method();
+Test::{'method'}();
+--EXPECT--
+method
+method
+method
+method
+method
+method
diff --git a/Zend/tests/bug55305.phpt b/Zend/tests/bug55305.phpt
new file mode 100644
index 0000000000..7f0749a315
--- /dev/null
+++ b/Zend/tests/bug55305.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #55305 (ref lost: 1st ref instantiated in class def, 2nd ref made w/o instantiating)
+--FILE--
+<?php
+class Foo {
+ var $foo = "test";
+}
+
+$f = new Foo();
+$f->bar =& $f->foo;
+var_dump($f->foo);
+var_dump($f->bar);
+?>
+--EXPECT--
+string(4) "test"
+string(4) "test"
diff --git a/Zend/tests/bug55339.phpt b/Zend/tests/bug55339.phpt
deleted file mode 100644
index 7d5ab4a782..0000000000
--- a/Zend/tests/bug55339.phpt
+++ /dev/null
@@ -1,31 +0,0 @@
---TEST--
-Bug #55339 (Segfault with allow_call_time_pass_reference = Off)
---INI--
-allow_call_time_pass_reference=off
---FILE--
-<?php
-function error_handler($errno, $errstr, $errfile, $errline) {
- eval(';');
-}
-
-set_error_handler('error_handler');
-
-eval(<<<'EOF'
-function foo()
-{
- $array = array();
- foreach ($array as $key => $value) {
- bar($key, &$value);
- }
-}
-
-function bar()
-{
-
-}
-EOF
-);
-
-echo "OK\n";
---EXPECT--
-OK
diff --git a/Zend/tests/bug55445.phpt b/Zend/tests/bug55445.phpt
new file mode 100644
index 0000000000..0f36ac5d88
--- /dev/null
+++ b/Zend/tests/bug55445.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #55445 (Lexer error with short open tags)
+--INI--
+short_open_tag=0
+--FILE--
+<?php $u = "chris"; ?><p>Welcome <?= $u ?></p>
+--EXPECTF--
+<p>Welcome chris</p>
diff --git a/Zend/tests/bug55578.phpt b/Zend/tests/bug55578.phpt
new file mode 100644
index 0000000000..4a8604a23b
--- /dev/null
+++ b/Zend/tests/bug55578.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #55578 (Segfault on implode/concat)
+--FILE--
+<?php
+$options = array();
+
+class Foo {
+ public function __toString() {
+ return 'Foo';
+ }
+}
+
+function test($options, $queryPart) {
+ return ''. (0 ? 1 : $queryPart);
+}
+
+var_dump(test($options, new Foo()));
+?>
+--EXPECT--
+string(3) "Foo"
diff --git a/Zend/tests/bug55705.phpt b/Zend/tests/bug55705.phpt
new file mode 100644
index 0000000000..69220bfdeb
--- /dev/null
+++ b/Zend/tests/bug55705.phpt
@@ -0,0 +1,9 @@
+--TEST--
+Bug #55705 (Omitting a callable typehinted argument causes a segfault)
+--FILE--
+<?php
+function f(callable $c) {}
+f();
+?>
+--EXPECTF--
+Catchable fatal error: Argument 1 passed to f() must be callable, none given, called in %s on line 3 and defined in %s on line %d
diff --git a/Zend/tests/bug55825.phpt b/Zend/tests/bug55825.phpt
new file mode 100644
index 0000000000..23fc933ee6
--- /dev/null
+++ b/Zend/tests/bug55825.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #55825 (Missing initial value of static locals in trait methods)
+--FILE--
+<?php
+trait T1 {
+ public function inc() {
+ static $x=1;
+ echo $x++ . "\n";
+ }
+}
+class C { use T1; }
+$c1 = new C;
+$c1->inc();
+$c1->inc();
+--EXPECT--
+1
+2
diff --git a/Zend/tests/bug60139.phpt b/Zend/tests/bug60139.phpt
index 2465b0e0a5..d5926b28f0 100644
--- a/Zend/tests/bug60139.phpt
+++ b/Zend/tests/bug60139.phpt
@@ -28,5 +28,5 @@ new Bar;
var_dump(gc_collect_cycles());
?>
--EXPECT--
-int(0)
+int(2)
int(2)
diff --git a/Zend/tests/bug60169.phpt b/Zend/tests/bug60169.phpt
new file mode 100644
index 0000000000..f97574191c
--- /dev/null
+++ b/Zend/tests/bug60169.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #60169 (Conjunction of ternary and list crashes PHP)
+--FILE--
+<?php
+error_reporting(0);
+$arr = array("test");
+list($a,$b) = is_array($arr)? $arr : $arr;
+list($c,$d) = is_array($arr)?: NULL;
+echo "ok\n";
+--EXPECT--
+ok
diff --git a/Zend/tests/bug60350.phpt b/Zend/tests/bug60350.phpt
new file mode 100644
index 0000000000..3facd54ac2
--- /dev/null
+++ b/Zend/tests/bug60350.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #60350 No string escape code for ESC (ascii 27), normally \e
+--FILE--
+<?php
+$str = "\e";
+if (ord($str) == 27) {
+ echo "Works";
+}
+?>
+--EXPECT--
+Works
diff --git a/Zend/tests/bug60362.phpt b/Zend/tests/bug60362.phpt
new file mode 100644
index 0000000000..e8d16ea4cb
--- /dev/null
+++ b/Zend/tests/bug60362.phpt
@@ -0,0 +1,74 @@
+--TEST--
+Bug #60362: non-existent sub-sub keys should not have values
+--FILE--
+<?php
+$arr = array('exists' => 'foz');
+
+if (isset($arr['exists']['non_existent'])) {
+ echo "sub-key 'non_existent' is set: ";
+ var_dump($arr['exists']['non_existent']);
+} else {
+ echo "sub-key 'non_existent' is not set.\n";
+}
+if (isset($arr['exists'][1])) {
+ echo "sub-key 1 is set: ";
+ var_dump($arr['exists'][1]);
+} else {
+ echo "sub-key 1 is not set.\n";
+}
+
+echo "-------------------\n";
+if (isset($arr['exists']['non_existent']['sub_sub'])) {
+ echo "sub-key 'sub_sub' is set: ";
+ var_dump($arr['exists']['non_existent']['sub_sub']);
+} else {
+ echo "sub-sub-key 'sub_sub' is not set.\n";
+}
+if (isset($arr['exists'][1][0])) {
+ echo "sub-sub-key 0 is set: ";
+ var_dump($arr['exists'][1][0]);
+} else {
+ echo "sub-sub-key 0 is not set.\n";
+}
+
+echo "-------------------\n";
+if (empty($arr['exists']['non_existent'])) {
+ echo "sub-key 'non_existent' is empty.\n";
+} else {
+ echo "sub-key 'non_existent' is not empty: ";
+ var_dump($arr['exists']['non_existent']);
+}
+if (empty($arr['exists'][1])) {
+ echo "sub-key 1 is empty.\n";
+} else {
+ echo "sub-key 1 is not empty: ";
+ var_dump($arr['exists'][1]);
+}
+
+echo "-------------------\n";
+if (empty($arr['exists']['non_existent']['sub_sub'])) {
+ echo "sub-sub-key 'sub_sub' is empty.\n";
+} else {
+ echo "sub-sub-key 'sub_sub' is not empty: ";
+ var_dump($arr['exists']['non_existent']['sub_sub']);
+}
+if (empty($arr['exists'][1][0])) {
+ echo "sub-sub-key 0 is empty.\n";
+} else {
+ echo "sub-sub-key 0 is not empty: ";
+ var_dump($arr['exists'][1][0]);
+}
+echo "DONE";
+--EXPECT--
+sub-key 'non_existent' is not set.
+sub-key 1 is set: string(1) "o"
+-------------------
+sub-sub-key 'sub_sub' is not set.
+sub-sub-key 0 is set: string(1) "o"
+-------------------
+sub-key 'non_existent' is empty.
+sub-key 1 is not empty: string(1) "o"
+-------------------
+sub-sub-key 'sub_sub' is empty.
+sub-sub-key 0 is not empty: string(1) "o"
+DONE
diff --git a/Zend/tests/bug60444.phpt b/Zend/tests/bug60444.phpt
new file mode 100644
index 0000000000..38f81bc413
--- /dev/null
+++ b/Zend/tests/bug60444.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #60444 (Segmentation fault with include & class extending)
+--FILE--
+<?php
+class Foo {
+ public function __construct() {
+ eval("class Bar extends Foo {}");
+ Some::foo($this);
+ }
+}
+class Some {
+ public static function foo(Foo $foo) {
+ }
+}
+new Foo;
+echo "done\n";
+--EXPECT--
+done
diff --git a/Zend/tests/bug60536_001.phpt b/Zend/tests/bug60536_001.phpt
new file mode 100644
index 0000000000..916646727d
--- /dev/null
+++ b/Zend/tests/bug60536_001.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #60536 (Traits Segfault)
+--FILE--
+<?php
+trait T { private $x = 0; }
+class X {
+ use T;
+}
+class Y extends X {
+ use T;
+ function x() {
+ return ++$this->x;
+ }
+}
+class Z extends Y {
+ function z() {
+ return ++$this->x;
+ }
+}
+$a = new Z();
+$a->x();
+echo "DONE";
+?>
+--EXPECTF--
+DONE
diff --git a/Zend/tests/bug60536_002.phpt b/Zend/tests/bug60536_002.phpt
new file mode 100644
index 0000000000..0bca98382e
--- /dev/null
+++ b/Zend/tests/bug60536_002.phpt
@@ -0,0 +1,40 @@
+--TEST--
+The same rules are applied for properties that are defined in the class hierarchy. Thus, if the properties are compatible, a notice is issued, if not a fatal error occures. (relevant with #60536)
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+ private $hello;
+}
+
+trait THello1 {
+ private $hello;
+}
+
+echo "PRE-CLASS-GUARD\n";
+class Notice extends Base {
+ use THello1;
+ private $hello;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now we do the test for a fatal error
+
+class TraitsTest {
+ use THello1;
+ public $hello;
+}
+
+echo "POST-CLASS-GUARD2\n";
+
+$t = new TraitsTest;
+$t->hello = "foo";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD
+
+Fatal error: TraitsTest and THello1 define the same property ($hello) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d
diff --git a/Zend/tests/bug60536_003.phpt b/Zend/tests/bug60536_003.phpt
new file mode 100644
index 0000000000..d944a0a41e
--- /dev/null
+++ b/Zend/tests/bug60536_003.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Properties should be initialized correctly (relevant to #60536)
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+ private $hello = 0;
+}
+
+trait AHelloProperty {
+ private $hello = 0;
+}
+
+class BaseWithTPropB {
+ use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+ use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+ use AHelloProperty;
+}
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+object(SubclassA)#%d (2) {
+ ["hello":"SubclassA":private]=>
+ int(0)
+ ["hello":"BaseWithPropA":private]=>
+ int(0)
+}
+object(SubclassB)#%d (2) {
+ ["hello":"SubclassB":private]=>
+ int(0)
+ ["hello":"BaseWithTPropB":private]=>
+ int(0)
+}
diff --git a/Zend/tests/bug60536_004.phpt b/Zend/tests/bug60536_004.phpt
new file mode 100644
index 0000000000..4f20836093
--- /dev/null
+++ b/Zend/tests/bug60536_004.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling. (relevant to #60536)
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+ private $hello;
+}
+
+trait THello1 {
+ private $hello;
+}
+
+// Now we use the trait, which happens to introduce another private variable
+// but they are distinct, and not related to each other, so no warning.
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassNoNotice extends Base {
+ use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself,
+// that should give the expected strict warning.
+
+class Notice extends Base {
+ use THello1;
+ private $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %sbug60536_004.php on line %d
+POST-CLASS-GUARD2
diff --git a/Zend/tests/bug60536_005.phpt b/Zend/tests/bug60536_005.phpt
new file mode 100644
index 0000000000..378adcc9c0
--- /dev/null
+++ b/Zend/tests/bug60536_005.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling. (relevant to #60536)
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+ protected $hello;
+}
+
+trait THello1 {
+ protected $hello;
+}
+
+// Protected and public are handle more strict with a warning then what is
+// expected from normal inheritance since they can have easier coliding semantics
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassProducesNotice extends Base {
+ use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself, too.
+
+class Notice extends Base {
+ use THello1;
+ protected $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Strict Standards: Base and THello1 define the same property ($hello) in the composition of SameNameInSubClassProducesNotice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2
diff --git a/Zend/tests/bug60573.phpt b/Zend/tests/bug60573.phpt
new file mode 100644
index 0000000000..d41a5f3ec3
--- /dev/null
+++ b/Zend/tests/bug60573.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Bug #60573 (type hinting with "self" keyword causes weird errors)
+--FILE--
+<?php
+class Foo1 {
+
+public function setSelf(self $s) { }
+
+}
+
+class Bar1 extends Foo1 {
+
+public function setSelf(parent $s) { }
+
+}
+
+class Foo2 {
+
+public function setSelf(Foo2 $s) { }
+
+}
+
+class Bar2 extends Foo2 {
+
+public function setSelf(parent $s) { }
+
+}
+
+class Base {
+}
+
+class Foo3 extends Base{
+
+public function setSelf(parent $s) { }
+
+}
+
+class Bar3 extends Foo3 {
+
+public function setSelf(Base $s) { }
+
+}
+
+class Foo4 {
+
+public function setSelf(self $s) { }
+
+}
+
+class Bar4 extends Foo4 {
+
+public function setSelf(self $s) { }
+
+}
+
+class Foo5 extends Base {
+
+public function setSelf(parent $s) { }
+
+}
+
+class Bar5 extends Foo5 {
+
+public function setSelf(parent $s) { }
+
+}
+
+abstract class Foo6 extends Base {
+
+abstract public function setSelf(parent $s);
+
+}
+
+class Bar6 extends Foo6 {
+
+public function setSelf(Foo6 $s) { }
+
+}
+--EXPECTF--
+Strict Standards: Declaration of Bar4::setSelf() should be compatible with Foo4::setSelf(Foo4 $s) in %sbug60573.php on line %d
+
+Strict Standards: Declaration of Bar5::setSelf() should be compatible with Foo5::setSelf(Base $s) in %sbug60573.php on line %d
+
+Fatal error: Declaration of Bar6::setSelf() must be compatible with Foo6::setSelf(Base $s) in %sbug60573.php on line %d
diff --git a/Zend/tests/bug60611.phpt b/Zend/tests/bug60611.phpt
new file mode 100644
index 0000000000..abd04b0891
--- /dev/null
+++ b/Zend/tests/bug60611.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #60611 (Segmentation fault with Cls::{expr}() syntax)
+--FILE--
+<?php
+class Cls {
+ function __call($name, $arg) {
+ }
+ static function __callStatic($name, $arg) {
+ }
+}
+
+$cls = new Cls;
+$cls->{0}();
+$cls->{1.0}();
+$cls->{true}();
+$cls->{false}();
+$cls->{null}();
+
+Cls::{0}();
+Cls::{1.0}();
+Cls::{true}();
+Cls::{false}();
+Cls::{null}();
+
+?>
+--EXPECTF--
+Fatal error: Method name must be a string in %sbug60611.php on line %d
diff --git a/Zend/tests/bug60613.phpt b/Zend/tests/bug60613.phpt
new file mode 100644
index 0000000000..a9db68dea9
--- /dev/null
+++ b/Zend/tests/bug60613.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #60613 (Segmentation fault with $cls->{expr}() syntax)
+--FILE--
+<?php
+class Cls {
+ function __call($name, $arg) {
+ }
+}
+
+$cls = new Cls();
+$cls->{0}();
+$cls->{1.0}();
+$cls->{true}();
+$cls->{false}();
+$cls->{null}();
+echo "ok\n";
+--EXPECTF--
+Fatal error: Method name must be a string in %sbug60613.php on line %d
diff --git a/Zend/tests/bug60978.phpt b/Zend/tests/bug60978.phpt
new file mode 100644
index 0000000000..5dc6fe31e7
--- /dev/null
+++ b/Zend/tests/bug60978.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #60978 (exit code incorrect)
+--FILE--
+<?php
+$php = getenv('TEST_PHP_EXECUTABLE');
+exec($php . ' -n -r "exit(2);"', $output, $exit_code);
+echo $exit_code;
+?>
+--EXPECT--
+2
diff --git a/Zend/tests/bug61011.phpt b/Zend/tests/bug61011.phpt
new file mode 100644
index 0000000000..bce0e33209
--- /dev/null
+++ b/Zend/tests/bug61011.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #61011 (Crash when an exception is thrown by __autoload accessing a static property)
+--FILE--
+<?php
+function __autoload($name) {
+ throw new Exception($name);
+}
+try {
+ echo AAA::$a; //zend_fetch_var_address_helper
+} catch (Exception $e) {
+ try {
+ echo AAA::XXX; //ZEND_FETCH_CONSTANT
+ } catch (Exception $e) {
+ try {
+ echo AAA::foo(); //ZEND_INIT_STATIC_METHOD_CALL
+ } catch (Exception $e) {
+ try {
+ unset(AAA::$a); // ZEND_UNSET_VAR
+ } catch (Exception $e){
+ try {
+ isset(AAAA::$a); // ZEND_ISSET_ISEMPTY_VAR
+ } catch (Exception $e) {
+ try {
+ $a = array("AAA", "foo");
+ $a(); //ZEND_INIT_FCALL_BY_NAME
+ } catch (Exception $e) {
+ }
+ }
+ }
+ }
+ }
+}
+echo 'okey';
+--EXPECT--
+okey
diff --git a/Zend/tests/bug61225.phpt b/Zend/tests/bug61225.phpt
new file mode 100644
index 0000000000..33d74bd561
--- /dev/null
+++ b/Zend/tests/bug61225.phpt
@@ -0,0 +1,9 @@
+--TEST--
+Bug #61225 (Lexing 0b0*+<NUM> incorectly)
+--FILE--
+<?php
+echo 0b00+1;
+echo "\n";
+?>
+--EXPECT--
+1
diff --git a/Zend/tests/bug61442.phpt b/Zend/tests/bug61442.phpt
deleted file mode 100644
index 3af534fec9..0000000000
--- a/Zend/tests/bug61442.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-Bug #61442 (exception threw in __autoload can not be catched)
---FILE--
-<?php
-function __autoload($name) {
- throw new Exception("Unable to load $name");
-}
-
-try {
- $obj = new NonLoadableClass();
-} catch (Exception $e) {
- var_dump($e->getMessage());
-}
-
-try {
- $obj = NonLoadableClass::a();
-} catch (Exception $e) {
- var_dump($e->getMessage());
-}
-
-try {
- $obj = NonLoadableClass::UNDEFINED_CONST;
-} catch (Exception $e) {
- var_dump($e->getMessage());
-}
-
---EXPECTF--
-string(31) "Unable to load NonLoadableClass"
-string(31) "Unable to load NonLoadableClass"
-string(31) "Unable to load NonLoadableClass"
diff --git a/Zend/tests/bug61761.phpt b/Zend/tests/bug61761.phpt
new file mode 100644
index 0000000000..24c69ae792
--- /dev/null
+++ b/Zend/tests/bug61761.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #61761 ('Overriding' a private static method with a different signature causes crash)
+--FILE--
+<?php
+
+class A
+{
+ private static function test($a) { }
+}
+
+class B extends A
+{
+ private static function test($a, $b) { }
+}
+
+?>
+==DONE==
+--EXPECTF--
+==DONE==
diff --git a/Zend/tests/bug61782.phpt b/Zend/tests/bug61782.phpt
new file mode 100644
index 0000000000..95bf4e6cff
--- /dev/null
+++ b/Zend/tests/bug61782.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #61782 (__clone/__destruct do not match other methods when checking access controls)
+--FILE--
+<?php
+ abstract class BaseClass {
+ abstract protected function __clone();
+ }
+
+ class MommasBoy extends BaseClass {
+ protected function __clone() {
+ echo __METHOD__, "\n";
+ }
+ }
+
+ class LatchkeyKid extends BaseClass {
+ public function __construct() {
+ echo 'In ', __CLASS__, ":\n";
+ $kid = new MommasBoy();
+ $kid = clone $kid;
+ }
+ public function __clone() {}
+ }
+
+ $obj = new LatchkeyKid();
+echo "DONE\n";
+--EXPECT--
+In LatchkeyKid:
+MommasBoy::__clone
+DONE
diff --git a/Zend/tests/bug62005.phpt b/Zend/tests/bug62005.phpt
index 4ff4b2ca9a..c99b28726f 100644
--- a/Zend/tests/bug62005.phpt
+++ b/Zend/tests/bug62005.phpt
@@ -8,7 +8,7 @@ function add_points($player, $points) {
}
add_points(NULL, 2);
--EXPECTF--
-Strict Standards: Creating default object from empty value in %sbug62005.php on line %d
+Warning: Creating default object from empty value in %sbug62005.php on line %d
stdClass Object
(
[energy] => 2
diff --git a/Zend/tests/bug62097.phpt b/Zend/tests/bug62097.phpt
new file mode 100644
index 0000000000..07e93bfa88
--- /dev/null
+++ b/Zend/tests/bug62097.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #62097: fix for bug #54547 is wrong for 32-bit machines
+--SKIPIF--
+<?php
+if (PHP_INT_MAX !== 2147483647)
+ die('skip for system with 32-bit wide longs only');
+--FILE--
+<?php
+var_dump("02147483647" == "2147483647",
+ "02147483648" == "2147483648",
+ "09007199254740991" == "9007199254740991",
+ "09007199254740992" == "9007199254740992");
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(false)
diff --git a/Zend/tests/bug62358.phpt b/Zend/tests/bug62358.phpt
new file mode 100644
index 0000000000..35d8b483d9
--- /dev/null
+++ b/Zend/tests/bug62358.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #62358 (Segfault when using traits a lot)
+--SKIPIF--
+<?php
+if (getenv("USE_ZEND_ALLOC") !== "0") {
+ die("skip Need Zend MM enabled");
+}
+?>
+--FILE--
+<?php
+
+trait T {
+ public function foo() {
+ echo "from T";
+ }
+}
+
+interface I {
+ public function foo();
+}
+
+abstract class A implements I{
+ use T;
+}
+
+class B extends A {
+ public function foo($var) {
+ }
+}
+?>
+--EXPECTF--
+Strict Standards: Declaration of B::foo() should be compatible with A::foo() in %sbug62358.php on line %d
diff --git a/Zend/tests/bug62653.phpt b/Zend/tests/bug62653.phpt
new file mode 100644
index 0000000000..96299f16ea
--- /dev/null
+++ b/Zend/tests/bug62653.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #62653: unset($array[$float]) causes a crash
+--FILE--
+<?php
+$array = array("5"=>"bar");
+$foo = "10.0000"; // gettype($foo) = "string"
+$foo /= 2; //Makes $foo = 5 but still gettype($foo) = "double"
+unset($array[$foo]);
+print_r($array);
+
+$array = array("5"=>"bar");
+$foo = "5";
+unset($array[(float)$foo]);
+print_r($array);
+
+$array = array("5"=>"bar");
+$foo = "10.0000";
+$foo /= 2; //Makes $foo = 5 but still gettype($foo) = "double"
+$name = "foo";
+unset($array[$$name]);
+print_r($array);
+
+?>
+--EXPECT--
+Array
+(
+)
+Array
+(
+)
+Array
+(
+)
diff --git a/Zend/tests/bug62680.phpt b/Zend/tests/bug62680.phpt
index 804dece415..e2a2366e7a 100644
--- a/Zend/tests/bug62680.phpt
+++ b/Zend/tests/bug62680.phpt
@@ -1,7 +1,5 @@
--TEST--
Bug #62680 (Function isset() throws fatal error on set array if non-existent key depth >= 3)
---XFAIL--
-see https://bugs.php.net/62680
--FILE--
<?php
$array = array("");
diff --git a/Zend/tests/bug62892.phpt b/Zend/tests/bug62892.phpt
new file mode 100644
index 0000000000..e6b0e60ff3
--- /dev/null
+++ b/Zend/tests/bug62892.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #62892 (ReflectionClass::getTraitAliases crashes on importing trait methods as private)
+--FILE--
+<?php
+
+trait myTrait {
+ public function run() {}
+}
+
+class myClass {
+ use myTrait {
+ MyTrait::run as private;
+ }
+}
+$class = new \ReflectionClass('myClass');
+var_dump($class->getTraitAliases());
+
+?>
+--EXPECTF--
+array(0) {
+}
diff --git a/Zend/tests/bug62907.phpt b/Zend/tests/bug62907.phpt
new file mode 100644
index 0000000000..53ab17cb32
--- /dev/null
+++ b/Zend/tests/bug62907.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #62907 (Double free when use traits)
+--FILE--
+<?php
+function __autoload($name) {
+ if ($name == "B") {
+ eval ("abstract class B extends A { }");
+ } else if ($name == "A") {
+ eval ("abstract class A { use T { T::__construct as __asconstruct; }}");
+ } else if ($name == "T") {
+ eval ("trait T { public function __construct() { } }");
+ }
+ return TRUE;
+}
+
+class C extends B {
+ public function __construct() {
+ }
+}
+echo "okey";
+--EXPECT--
+okey
diff --git a/Zend/tests/bug62956.phpt b/Zend/tests/bug62956.phpt
new file mode 100644
index 0000000000..c8694d5bea
--- /dev/null
+++ b/Zend/tests/bug62956.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #62956: "incompatible" signatures for private methods should not cause E_STRICT
+--FILE--
+<?php
+class Base
+{
+ private function test()
+ {}
+}
+
+class Extension extends Base
+{
+ private function test($arg)
+ {}
+}
+
+?>
+==DONE==
+--EXPECT--
+==DONE==
diff --git a/Zend/tests/bug63173.phpt b/Zend/tests/bug63173.phpt
new file mode 100644
index 0000000000..36ebf203d2
--- /dev/null
+++ b/Zend/tests/bug63173.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #63173: Crash when invoking invalid array callback
+--FILE--
+<?php
+
+// the important part here are the indexes 1 and 2
+$callback = [1 => 0, 2 => 0];
+$callback();
+
+?>
+--EXPECTF--
+Fatal error: Array callback has to contain indices 0 and 1 in %s on line %d
diff --git a/Zend/tests/bug63219.phpt b/Zend/tests/bug63219.phpt
new file mode 100644
index 0000000000..999be4a853
--- /dev/null
+++ b/Zend/tests/bug63219.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #63219 (Segfault when aliasing trait method when autoloader throws excpetion)
+--FILE--
+<?php
+trait TFoo {
+ public function fooMethod(){}
+}
+
+class C {
+ use TFoo {
+ Typo::fooMethod as tf;
+ }
+}
+
+echo "okey";
+?>
+--EXPECTF--
+Fatal error: Could not find trait Typo in %sbug63219.php on line %d
diff --git a/Zend/tests/bug63305.phpt b/Zend/tests/bug63305.phpt
new file mode 100644
index 0000000000..4bd3a4dbeb
--- /dev/null
+++ b/Zend/tests/bug63305.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #63305 (zend_mm_heap corrupted with traits)
+--FILE--
+<?php
+new Attachment("");
+
+function __autoload($class) {
+ switch ($class) {
+ case "Attachment":
+ eval(<<<'PHP'
+class Attachment extends File {
+}
+PHP
+ );
+ break;
+ case "File":
+ eval(<<<'PHP'
+class File {
+ use TDatabaseObject {
+ TDatabaseObject::__construct as private databaseObjectConstruct;
+ }
+ public function __construct() {
+ }
+}
+PHP
+ );
+ break;
+ case "TDatabaseObject":
+ eval(<<<'PHP'
+trait TDatabaseObject {
+ public function __construct() {
+ }
+}
+PHP
+ );
+ break;
+ }
+ return TRUE;
+}
+echo "okey";
+?>
+--EXPECT--
+okey
diff --git a/Zend/tests/bug63336.phpt b/Zend/tests/bug63336.phpt
new file mode 100644
index 0000000000..d2c3d41131
--- /dev/null
+++ b/Zend/tests/bug63336.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #63336 (invalid E_NOTICE error occur)
+--XFAIL--
+Bug is not fixed yet
+--FILE--
+<?php
+error_reporting(E_ALL | E_NOTICE );
+define("TEST", "123");
+class Base {
+ const DUMMY = "XXX";
+ public function foo($var=TEST, $more=null) { return true; }
+ public function bar($more=self::DUMMY) { return true; }
+}
+
+class Child extends Base {
+ const DUMMY = "DDD";
+ public function foo($var=TEST, array $more = array()) { return true; }
+ public function bar($var, $more=self::DUMMY) { return true; }
+}
+?>
+--EXPECT--
+Strict Standards: Declaration of Child::foo() should be compatible with Base::foo($var = '123', $more = NULL) in %sbug63336.php on line %d
+
+Strict Standards: Declaration of Child::bar() should be compatible with Base::bar($var, $more = 'XXX') in %sbug63336.php on line %d
diff --git a/Zend/tests/callable_type_hint_001.phpt b/Zend/tests/callable_type_hint_001.phpt
new file mode 100644
index 0000000000..36643fa64d
--- /dev/null
+++ b/Zend/tests/callable_type_hint_001.phpt
@@ -0,0 +1,39 @@
+--TEST--
+callable type hint#001
+--FILE--
+<?php
+
+class bar {
+ function baz() {}
+ static function foo() {}
+}
+function foo(callable $bar) {
+ var_dump($bar);
+}
+$closure = function () {};
+
+foo("strpos");
+foo("foo");
+foo(array("bar", "baz"));
+foo(array("bar", "foo"));
+foo($closure);
+--EXPECTF--
+string(6) "strpos"
+string(3) "foo"
+
+Strict Standards: Non-static method bar::baz() should not be called statically in %scallable_type_hint_001.php on line %d
+array(2) {
+ [0]=>
+ string(3) "bar"
+ [1]=>
+ string(3) "baz"
+}
+array(2) {
+ [0]=>
+ string(3) "bar"
+ [1]=>
+ string(3) "foo"
+}
+object(Closure)#%d (0) {
+}
+
diff --git a/Zend/tests/callable_type_hint_002.phpt b/Zend/tests/callable_type_hint_002.phpt
new file mode 100644
index 0000000000..b1b7339c31
--- /dev/null
+++ b/Zend/tests/callable_type_hint_002.phpt
@@ -0,0 +1,27 @@
+--TEST--
+callable type hint#002 - Reflection
+--FILE--
+<?php
+
+class bar {
+ static function foo(callable $arg) {}
+}
+function foo(callable $bar) {
+}
+$closure = function (callable $arg) {};
+
+$rf = new ReflectionFunction("foo");
+var_dump($rf->getParameters()[0]->isCallable());
+
+$rm = new ReflectionMethod("bar", "foo");
+var_dump($rm->getParameters()[0]->isCallable());
+
+$rc = new ReflectionFunction($closure);
+var_dump($rc->getParameters()[0]->isCallable());
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+
diff --git a/Zend/tests/callable_type_hint_003.phpt b/Zend/tests/callable_type_hint_003.phpt
new file mode 100644
index 0000000000..83f5090afa
--- /dev/null
+++ b/Zend/tests/callable_type_hint_003.phpt
@@ -0,0 +1,21 @@
+--TEST--
+callable type hint#003
+--FILE--
+<?php
+
+function foo(callable $a, $b, callable $c) {
+ var_dump($a, $b, $c);
+}
+function bar(callable $a = null) {
+ var_dump($a);
+}
+
+foo("strpos", 123, "strpos");
+bar("substr");
+?>
+--EXPECT--
+string(6) "strpos"
+int(123)
+string(6) "strpos"
+string(6) "substr"
+
diff --git a/Zend/tests/cast_to_string.phpt b/Zend/tests/cast_to_string.phpt
index d06daa2e7c..f8b57a22c5 100644
--- a/Zend/tests/cast_to_string.phpt
+++ b/Zend/tests/cast_to_string.phpt
Binary files differ
diff --git a/Zend/tests/class_exists_003.phpt b/Zend/tests/class_exists_003.phpt
index ad7bafa3a7..cba4675099 100644
--- a/Zend/tests/class_exists_003.phpt
+++ b/Zend/tests/class_exists_003.phpt
@@ -1,5 +1,5 @@
--TEST--
-Checking if exists interface, abstract and final class
+Checking if exists interface, trait, abstract and final class
--FILE--
<?php
@@ -9,12 +9,16 @@ abstract class b { }
final class c { }
+trait d {}
+
var_dump(class_exists('a'));
var_dump(class_exists('b'));
var_dump(class_exists('c'));
+var_dump(class_exists('d'));
?>
--EXPECT--
bool(false)
bool(true)
bool(true)
+bool(false)
diff --git a/Zend/tests/closure_005.phpt b/Zend/tests/closure_005.phpt
new file mode 100644
index 0000000000..4e32faa017
--- /dev/null
+++ b/Zend/tests/closure_005.phpt
@@ -0,0 +1,74 @@
+--TEST--
+Closure 005: Lambda inside class, lifetime of $this
+--FILE--
+<?php
+
+class A {
+ private $x;
+
+ function __construct($x) {
+ $this->x = $x;
+ }
+
+ function __destruct() {
+ echo "Destroyed\n";
+ }
+
+ function getIncer($val) {
+ return function() use ($val) {
+ $this->x += $val;
+ };
+ }
+
+ function getPrinter() {
+ return function() {
+ echo $this->x."\n";
+ };
+ }
+
+ function getError() {
+ return static function() {
+ echo $this->x."\n";
+ };
+ }
+
+ function printX() {
+ echo $this->x."\n";
+ }
+}
+
+$a = new A(3);
+$incer = $a->getIncer(2);
+$printer = $a->getPrinter();
+$error = $a->getError();
+
+$a->printX();
+$printer();
+$incer();
+$a->printX();
+$printer();
+
+unset($a);
+
+$incer();
+$printer();
+
+unset($incer);
+$printer();
+
+unset($printer);
+
+$error();
+
+echo "Done\n";
+?>
+--EXPECTF--
+3
+3
+5
+5
+7
+7
+Destroyed
+
+Fatal error: Using $this when not in object context in %sclosure_005.php on line 28
diff --git a/Zend/tests/closure_007.phpt b/Zend/tests/closure_007.phpt
new file mode 100644
index 0000000000..89cd06d8a1
--- /dev/null
+++ b/Zend/tests/closure_007.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Closure 007: Nested lambdas in classes
+--FILE--
+<?php
+
+class A {
+ private $x = 0;
+
+ function getClosureGetter () {
+ return function () {
+ return function () {
+ $this->x++;
+ };
+ };
+ }
+
+ function printX () {
+ echo $this->x."\n";
+ }
+}
+
+$a = new A;
+$a->printX();
+$getClosure = $a->getClosureGetter();
+$a->printX();
+$closure = $getClosure();
+$a->printX();
+$closure();
+$a->printX();
+
+echo "Done\n";
+?>
+--EXPECT--
+0
+0
+0
+1
+Done
diff --git a/Zend/tests/closure_020.phpt b/Zend/tests/closure_020.phpt
index 9d04a9af54..bec2bedd7f 100644
--- a/Zend/tests/closure_020.phpt
+++ b/Zend/tests/closure_020.phpt
@@ -23,16 +23,18 @@ var_dump($y()->test);
?>
--EXPECTF--
-object(foo)#%d (%d) {
+object(foo)#%d (2) {
["test":"foo":private]=>
int(3)
["a"]=>
- object(Closure)#%d (1) {
+ object(Closure)#%d (2) {
["static"]=>
array(1) {
["a"]=>
*RECURSION*
}
+ ["this"]=>
+ *RECURSION*
}
}
bool(true)
diff --git a/Zend/tests/closure_024.phpt b/Zend/tests/closure_024.phpt
index 504e81efd9..74083f73bc 100644
--- a/Zend/tests/closure_024.phpt
+++ b/Zend/tests/closure_024.phpt
@@ -1,16 +1,26 @@
--TEST--
-Closure 024: Trying to clone the Closure object
+Closure 024: Clone the Closure object
--FILE--
<?php
-$a = function () {
- return clone function () {
- return 1;
- };
-};
+$a = 1;
+$c = function($add) use(&$a) { return $a+$add; };
-$a();
+$cc = clone $c;
+echo $c(10)."\n";
+echo $cc(10)."\n";
+
+$a++;
+
+echo $c(10)."\n";
+echo $cc(10)."\n";
+
+echo "Done.\n";
?>
--EXPECTF--
-Fatal error: Trying to clone an uncloneable object of class Closure in %s on line %d
+11
+11
+12
+12
+Done. \ No newline at end of file
diff --git a/Zend/tests/closure_026.phpt b/Zend/tests/closure_026.phpt
index f9e6bd5e25..150cc86584 100644
--- a/Zend/tests/closure_026.phpt
+++ b/Zend/tests/closure_026.phpt
@@ -32,7 +32,9 @@ object(foo)#%d (1) {
["a"]=>
array(1) {
[0]=>
- object(Closure)#%d (0) {
+ object(Closure)#%d (1) {
+ ["this"]=>
+ *RECURSION*
}
}
}
@@ -41,7 +43,12 @@ int(1)
string(1) "a"
array(1) {
[0]=>
- object(Closure)#%d (0) {
+ object(Closure)#%d (1) {
+ ["this"]=>
+ object(foo)#%d (1) {
+ ["a"]=>
+ *RECURSION*
+ }
}
}
int(1)
diff --git a/Zend/tests/closure_036.phpt b/Zend/tests/closure_036.phpt
new file mode 100644
index 0000000000..77d7ce6906
--- /dev/null
+++ b/Zend/tests/closure_036.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Closure 036: Rebinding closures, keep calling scope
+--FILE--
+<?php
+
+class A {
+ private $x;
+
+ public function __construct($v) {
+ $this->x = $v;
+ }
+
+ public function getIncrementor() {
+ return function() { return ++$this->x; };
+ }
+}
+
+$a = new A(0);
+$b = new A(10);
+
+$ca = $a->getIncrementor();
+$cb = $ca->bindTo($b);
+$cb2 = Closure::bind($ca, $b);
+
+var_dump($ca());
+var_dump($cb());
+var_dump($cb2());
+
+?>
+--EXPECTF--
+int(1)
+int(11)
+int(12) \ No newline at end of file
diff --git a/Zend/tests/closure_037.phpt b/Zend/tests/closure_037.phpt
new file mode 100644
index 0000000000..4b24c85d16
--- /dev/null
+++ b/Zend/tests/closure_037.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Closure 037: self:: and static:: within closures
+--FILE--
+<?php
+class A {
+ private $x = 0;
+
+ function getClosure () {
+ return function () {
+ $this->x++;
+ self::printX();
+ self::print42();
+ static::print42();
+ };
+ }
+
+ function printX () {
+ echo $this->x."\n";
+ }
+
+ function print42() {
+ echo "42\n";
+ }
+}
+
+class B extends A {
+ function print42() {
+ echo "forty two\n";
+ }
+}
+
+$a = new A;
+$closure = $a->getClosure();
+$closure();
+$b = new B;
+$closure = $b->getClosure();
+$closure();
+?>
+Done.
+--EXPECTF--
+1
+42
+42
+1
+42
+forty two
+Done. \ No newline at end of file
diff --git a/Zend/tests/closure_038.phpt b/Zend/tests/closure_038.phpt
new file mode 100644
index 0000000000..fef0734786
--- /dev/null
+++ b/Zend/tests/closure_038.phpt
@@ -0,0 +1,58 @@
+--TEST--
+Closure 038: Rebinding closures, change scope, different runtime type
+--FILE--
+<?php
+
+class A {
+ private $x;
+
+ public function __construct($v) {
+ $this->x = $v;
+ }
+
+ public function getIncrementor() {
+ return function() { return ++$this->x; };
+ }
+}
+class B extends A {
+ private $x;
+ public function __construct($v) {
+ parent::__construct($v);
+ $this->x = $v*2;
+ }
+}
+
+$a = new A(0);
+$b = new B(10);
+
+$ca = $a->getIncrementor();
+var_dump($ca());
+
+echo "Testing with scope given as object", "\n";
+
+$cb = $ca->bindTo($b, $b);
+$cb2 = Closure::bind($ca, $b, $b);
+var_dump($cb());
+var_dump($cb2());
+
+echo "Testing with scope as string", "\n";
+
+$cb = $ca->bindTo($b, 'B');
+$cb2 = Closure::bind($ca, $b, 'B');
+var_dump($cb());
+var_dump($cb2());
+
+$cb = $ca->bindTo($b, NULL);
+var_dump($cb());
+
+?>
+--EXPECTF--
+int(1)
+Testing with scope given as object
+int(21)
+int(22)
+Testing with scope as string
+int(23)
+int(24)
+
+Fatal error: Cannot access private property B::$x in %s on line %d
diff --git a/Zend/tests/closure_039.phpt b/Zend/tests/closure_039.phpt
new file mode 100644
index 0000000000..c6a727c0fa
--- /dev/null
+++ b/Zend/tests/closure_039.phpt
@@ -0,0 +1,58 @@
+--TEST--
+Closure 039: Rebinding closures, change scope, same runtime type
+--FILE--
+<?php
+
+class A {
+ private $x;
+
+ public function __construct($v) {
+ $this->x = $v;
+ }
+
+ public function getIncrementor() {
+ return function() { return ++$this->x; };
+ }
+}
+class B extends A {
+ private $x;
+ public function __construct($v) {
+ parent::__construct($v);
+ $this->x = $v*2;
+ }
+}
+
+$a = new B(-5);
+$b = new B(10);
+
+$ca = $a->getIncrementor();
+var_dump($ca());
+
+echo "Testing with scope given as object", "\n";
+
+$cb = $ca->bindTo($b, $b);
+$cb2 = Closure::bind($ca, $b, $b);
+var_dump($cb());
+var_dump($cb2());
+
+echo "Testing with scope as string", "\n";
+
+$cb = $ca->bindTo($b, 'B');
+$cb2 = Closure::bind($ca, $b, 'B');
+var_dump($cb());
+var_dump($cb2());
+
+$cb = $ca->bindTo($b, NULL);
+var_dump($cb());
+
+?>
+--EXPECTF--
+int(-4)
+Testing with scope given as object
+int(21)
+int(22)
+Testing with scope as string
+int(23)
+int(24)
+
+Fatal error: Cannot access private property B::$x in %s on line %d
diff --git a/Zend/tests/closure_040.phpt b/Zend/tests/closure_040.phpt
new file mode 100644
index 0000000000..a1b6cd604a
--- /dev/null
+++ b/Zend/tests/closure_040.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Closure 040: Rebinding closures, bad arguments
+--FILE--
+<?php
+
+class A {
+ private $x;
+ private static $xs = 10;
+
+ public function __construct($v) {
+ $this->x = $v;
+ }
+
+ public function getIncrementor() {
+ return function() { return ++$this->x; };
+ }
+ public function getStaticIncrementor() {
+ return static function() { return ++static::$xs; };
+ }
+}
+
+$a = new A(20);
+
+$ca = $a->getIncrementor();
+$cas = $a->getStaticIncrementor();
+
+$ca->bindTo($a, array());
+$ca->bindTo(array(), 'A');
+$ca->bindTo($a, array(), "");
+$ca->bindTo();
+$cas->bindTo($a, 'A');
+
+?>
+--EXPECTF--
+Notice: Array to string conversion in %s on line %d
+
+Warning: Class 'Array' not found in %s on line %d
+
+Warning: Closure::bindTo() expects parameter 1 to be object, array given in %s on line 25
+
+Warning: Closure::bindTo() expects at most 2 parameters, 3 given in %s on line %d
+
+Warning: Closure::bindTo() expects at least 1 parameter, 0 given in %s on line %d
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
diff --git a/Zend/tests/closure_041.phpt b/Zend/tests/closure_041.phpt
new file mode 100644
index 0000000000..79cf9f3380
--- /dev/null
+++ b/Zend/tests/closure_041.phpt
@@ -0,0 +1,106 @@
+--TEST--
+Closure 041: Rebinding: preservation of previous scope when not given as arg unless impossible
+--FILE--
+<?php
+
+/* It's impossible to preserve the previous scope when doing so would break
+ * the invariants that, for non-static closures, having a scope is equivalent
+ * to having a bound instance. */
+
+$staticUnscoped = static function () {
+ echo "scoped to A: "; var_dump(isset(A::$priv));
+ echo "bound: ", isset($this)?get_class($this):"no";
+};
+
+$nonstaticUnscoped = function () {
+ echo "scoped to A: "; var_dump(isset(A::$priv));
+ echo "bound: ", isset($this)?get_class($this):"no";
+};
+
+class A {
+ private static $priv = 7;
+ function getClosure() {
+ return function () {
+ echo "scoped to A: "; var_dump(isset(A::$priv));
+ echo "bound: ", isset($this)?get_class($this):"no";
+ };
+ }
+ function getStaticClosure() {
+ return static function () {
+ echo "scoped to A: "; var_dump(isset(A::$priv));
+ echo "bound: ", isset($this)?get_class($this):"no";
+ };
+ }
+}
+class B extends A {}
+
+$a = new A();
+$staticScoped = $a->getStaticClosure();
+$nonstaticScoped = $a->getClosure();
+
+echo "Before binding", "\n";
+$staticUnscoped(); echo "\n";
+$nonstaticUnscoped(); echo "\n";
+$staticScoped(); echo "\n";
+$nonstaticScoped(); echo "\n";
+
+echo "After binding, no instance", "\n";
+$d = $staticUnscoped->bindTo(null); $d(); echo "\n";
+$d = $nonstaticUnscoped->bindTo(null); $d(); echo "\n";
+$d = $staticScoped->bindTo(null); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(null); $d(); echo "\n";
+//$d should have been turned to static
+$d->bindTo($d);
+
+echo "After binding, with same-class instance for the bound ones", "\n";
+$d = $staticUnscoped->bindTo(new A); $d(); echo "\n";
+$d = $nonstaticUnscoped->bindTo(new A); $d(); echo " (should be scoped to dummy class)\n";
+$d = $staticScoped->bindTo(new A); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(new A); $d(); echo "\n";
+
+echo "After binding, with different instance for the bound ones", "\n";
+$d = $nonstaticUnscoped->bindTo(new B); $d(); echo " (should be scoped to dummy class)\n";
+$d = $nonstaticScoped->bindTo(new B); $d(); echo "\n";
+
+echo "Done.\n";
+
+--EXPECTF--
+Before binding
+scoped to A: bool(false)
+bound: no
+scoped to A: bool(false)
+bound: no
+scoped to A: bool(true)
+bound: no
+scoped to A: bool(true)
+bound: A
+After binding, no instance
+scoped to A: bool(false)
+bound: no
+scoped to A: bool(false)
+bound: no
+scoped to A: bool(true)
+bound: no
+scoped to A: bool(true)
+bound: no
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+After binding, with same-class instance for the bound ones
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+scoped to A: bool(false)
+bound: no
+scoped to A: bool(false)
+bound: A (should be scoped to dummy class)
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+scoped to A: bool(true)
+bound: no
+scoped to A: bool(true)
+bound: A
+After binding, with different instance for the bound ones
+scoped to A: bool(false)
+bound: B (should be scoped to dummy class)
+scoped to A: bool(true)
+bound: B
+Done. \ No newline at end of file
diff --git a/Zend/tests/closure_042.phpt b/Zend/tests/closure_042.phpt
new file mode 100644
index 0000000000..8969765bcd
--- /dev/null
+++ b/Zend/tests/closure_042.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Closure 042: Binding an instance to a non-scoped non-static closures gives it a dummy scope
+--SKIPIF--
+<?php if(!extension_loaded("reflection")) print "skip no reflection"; ?>
+--FILE--
+<?php
+
+$c = function() { var_dump($this); };
+$d = $c->bindTo(new stdClass);
+$d();
+$rm = new ReflectionFunction($d);
+var_dump($rm->getClosureScopeClass()->name); //dummy sope is Closure
+
+//should have the same effect
+$d = $c->bindTo(new stdClass, NULL);
+$d();
+$rm = new ReflectionFunction($d);
+var_dump($rm->getClosureScopeClass()->name); //dummy sope is Closure
+
+echo "Done.\n";
+
+--EXPECTF--
+object(stdClass)#%d (0) {
+}
+string(7) "Closure"
+object(stdClass)#%d (0) {
+}
+string(7) "Closure"
+Done.
diff --git a/Zend/tests/closure_043.phpt b/Zend/tests/closure_043.phpt
new file mode 100644
index 0000000000..98c88fda39
--- /dev/null
+++ b/Zend/tests/closure_043.phpt
@@ -0,0 +1,86 @@
+--TEST--
+Closure 043: Scope/bounding combination invariants; static closures
+--FILE--
+<?php
+/* Whether it's scoped or not, a static closure cannot have
+ * a bound instance. It should also not be automatically converted
+ * to a non-static instance when attempting to bind one */
+
+$staticUnscoped = static function () { var_dump(isset(A::$priv)); var_dump(isset($this)); };
+
+class A {
+ private static $priv = 7;
+ static function getStaticClosure() {
+ return static function() { var_dump(isset(A::$priv)); var_dump(isset($this)); };
+ }
+}
+
+$staticScoped = A::getStaticClosure();
+
+echo "Before binding", "\n";
+$staticUnscoped(); echo "\n";
+$staticScoped(); echo "\n";
+
+echo "After binding, null scope, no instance", "\n";
+$d = $staticUnscoped->bindTo(null, null); $d(); echo "\n";
+$d = $staticScoped->bindTo(null, null); $d(); echo "\n";
+
+echo "After binding, null scope, with instance", "\n";
+$d = $staticUnscoped->bindTo(new A, null); $d(); echo "\n";
+$d = $staticScoped->bindTo(new A, null); $d(); echo "\n";
+
+echo "After binding, with scope, no instance", "\n";
+$d = $staticUnscoped->bindTo(null, 'A'); $d(); echo "\n";
+$d = $staticScoped->bindTo(null, 'A'); $d(); echo "\n";
+
+echo "After binding, with scope, with instance", "\n";
+$d = $staticUnscoped->bindTo(new A, 'A'); $d(); echo "\n";
+$d = $staticScoped->bindTo(new A, 'A'); $d(); echo "\n";
+
+echo "Done.\n";
+
+--EXPECTF--
+Before binding
+bool(false)
+bool(false)
+
+bool(true)
+bool(false)
+
+After binding, null scope, no instance
+bool(false)
+bool(false)
+
+bool(false)
+bool(false)
+
+After binding, null scope, with instance
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+bool(false)
+bool(false)
+
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+bool(false)
+bool(false)
+
+After binding, with scope, no instance
+bool(true)
+bool(false)
+
+bool(true)
+bool(false)
+
+After binding, with scope, with instance
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+bool(true)
+bool(false)
+
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+bool(true)
+bool(false)
+
+Done.
diff --git a/Zend/tests/closure_044.phpt b/Zend/tests/closure_044.phpt
new file mode 100644
index 0000000000..d2644c0401
--- /dev/null
+++ b/Zend/tests/closure_044.phpt
@@ -0,0 +1,78 @@
+--TEST--
+Closure 044: Scope/bounding combination invariants; non static closures
+--FILE--
+<?php
+/* A non-static closure has a bound instance if it has a scope
+ * and does't have an instance if it has no scope */
+
+$nonstaticUnscoped = function () { var_dump(isset(A::$priv)); var_dump(isset($this)); };
+
+class A {
+ private static $priv = 7;
+ function getClosure() {
+ return function() { var_dump(isset(A::$priv)); var_dump(isset($this)); };
+ }
+}
+
+$a = new A();
+$nonstaticScoped = $a->getClosure();
+
+echo "Before binding", "\n";
+$nonstaticUnscoped(); echo "\n";
+$nonstaticScoped(); echo "\n";
+
+echo "After binding, null scope, no instance", "\n";
+$d = $nonstaticUnscoped->bindTo(null, null); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(null, null); $d(); echo "\n";
+
+echo "After binding, null scope, with instance", "\n";
+$d = $nonstaticUnscoped->bindTo(new A, null); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(new A, null); $d(); echo "\n";
+
+echo "After binding, with scope, no instance", "\n";
+$d = $nonstaticUnscoped->bindTo(null, 'A'); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(null, 'A'); $d(); echo "\n";
+
+echo "After binding, with scope, with instance", "\n";
+$d = $nonstaticUnscoped->bindTo(new A, 'A'); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(new A, 'A'); $d(); echo "\n";
+
+echo "Done.\n";
+
+--EXPECTF--
+Before binding
+bool(false)
+bool(false)
+
+bool(true)
+bool(true)
+
+After binding, null scope, no instance
+bool(false)
+bool(false)
+
+bool(false)
+bool(false)
+
+After binding, null scope, with instance
+bool(false)
+bool(true)
+
+bool(false)
+bool(true)
+
+After binding, with scope, no instance
+bool(true)
+bool(false)
+
+bool(true)
+bool(false)
+
+After binding, with scope, with instance
+bool(true)
+bool(true)
+
+bool(true)
+bool(true)
+
+Done.
diff --git a/Zend/tests/closure_045.phpt b/Zend/tests/closure_045.phpt
new file mode 100644
index 0000000000..4115691761
--- /dev/null
+++ b/Zend/tests/closure_045.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Closure 045: Closures created in static methods are static, even without the keyword
+--FILE--
+<?php
+
+class A {
+static function foo() {
+ return function () {};
+}
+}
+
+$a = A::foo();
+$a->bindTo(new A);
+
+echo "Done.\n";
+
+--EXPECTF--
+Warning: Cannot bind an instance to a static closure in %s on line %d
+Done.
diff --git a/Zend/tests/closure_046.phpt b/Zend/tests/closure_046.phpt
new file mode 100644
index 0000000000..30a9d3e1b1
--- /dev/null
+++ b/Zend/tests/closure_046.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Closure 046: Rebinding: preservation of previous scope when "static" given as scope arg (same as closure #041)
+--FILE--
+<?php
+
+/* It's impossible to preserve the previous scope when doing so would break
+ * the invariants that, for non-static closures, having a scope is equivalent
+ * to having a bound instance. */
+
+$nonstaticUnscoped = function () { var_dump(isset(A::$priv)); var_dump(isset($this)); };
+
+class A {
+ private static $priv = 7;
+ function getClosure() {
+ return function() { var_dump(isset(A::$priv)); var_dump(isset($this)); };
+ }
+}
+class B extends A {}
+
+$a = new A();
+$nonstaticScoped = $a->getClosure();
+
+echo "Before binding", "\n";
+$nonstaticUnscoped(); echo "\n";
+$nonstaticScoped(); echo "\n";
+
+echo "After binding, no instance", "\n";
+$d = $nonstaticUnscoped->bindTo(null, "static"); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(null, "static"); $d(); echo "\n";
+//$d should have been turned to static
+$d->bindTo($d);
+
+echo "After binding, with same-class instance for the bound one", "\n";
+$d = $nonstaticUnscoped->bindTo(new A, "static"); $d(); echo "\n";
+$d = $nonstaticScoped->bindTo(new A, "static"); $d(); echo "\n";
+
+echo "After binding, with different instance for the bound one", "\n";
+$d = $nonstaticScoped->bindTo(new B, "static"); $d(); echo "\n";
+
+echo "Done.\n";
+
+--EXPECTF--
+Before binding
+bool(false)
+bool(false)
+
+bool(true)
+bool(true)
+
+After binding, no instance
+bool(false)
+bool(false)
+
+bool(true)
+bool(false)
+
+
+Warning: Cannot bind an instance to a static closure in %s on line %d
+After binding, with same-class instance for the bound one
+bool(false)
+bool(true)
+
+bool(true)
+bool(true)
+
+After binding, with different instance for the bound one
+bool(true)
+bool(true)
+
+Done.
diff --git a/Zend/tests/concat_001.phpt b/Zend/tests/concat_001.phpt
index d7bc525c4f..1307c28930 100644
--- a/Zend/tests/concat_001.phpt
+++ b/Zend/tests/concat_001.phpt
@@ -50,26 +50,46 @@ var_dump($d.$d);
echo "Done\n";
?>
--EXPECTF--
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(24) "Arraythis is test object"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(16) "Arraysome string"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(8) "Array222"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(13) "Array2323.444"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(10) "ArrayArray"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(24) "this is test objectArray"
string(30) "this is test objectsome string"
string(22) "this is test object222"
string(27) "this is test object2323.444"
string(38) "this is test objectthis is test object"
string(30) "some stringthis is test object"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(16) "some stringArray"
string(14) "some string222"
string(19) "some string2323.444"
string(22) "some stringsome string"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(8) "222Array"
string(22) "222this is test object"
string(14) "222some string"
string(11) "2222323.444"
string(6) "222222"
+
+Notice: Array to string conversion in %sconcat_001.php on line %d
string(13) "2323.444Array"
string(27) "2323.444this is test object"
string(19) "2323.444some string"
diff --git a/Zend/tests/constants_005.phpt b/Zend/tests/constants_005.phpt
index 55f90fd94f..d2a205b784 100644
--- a/Zend/tests/constants_005.phpt
+++ b/Zend/tests/constants_005.phpt
@@ -7,5 +7,6 @@ define("ZEND_THREAD_safe", 123);
var_dump(ZEND_THREAD_safe);
?>
--EXPECTF--
-bool(%s)
+Notice: Use of undefined constant ZEND_THREAD_safe - assumed 'ZEND_THREAD_safe' in %s on line %d
+string(16) "ZEND_THREAD_safe"
int(123)
diff --git a/Zend/tests/debug_backtrace_limit.phpt b/Zend/tests/debug_backtrace_limit.phpt
new file mode 100644
index 0000000000..985c2cccb3
--- /dev/null
+++ b/Zend/tests/debug_backtrace_limit.phpt
@@ -0,0 +1,133 @@
+--TEST--
+debug_backtrace limit
+--FILE--
+<?php
+function a() {
+ b();
+}
+
+function b() {
+ c();
+}
+
+function c() {
+ print_r(debug_backtrace(0, 1));
+ print_r(debug_backtrace(0, 2));
+ print_r(debug_backtrace(0, 0));
+ print_r(debug_backtrace(0, 4));
+}
+
+a();
+?>
+--EXPECTF--
+Array
+(
+ [0] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 7
+ [function] => c
+ [args] => Array
+ (
+ )
+
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 7
+ [function] => c
+ [args] => Array
+ (
+ )
+
+ )
+
+ [1] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 3
+ [function] => b
+ [args] => Array
+ (
+ )
+
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 7
+ [function] => c
+ [args] => Array
+ (
+ )
+
+ )
+
+ [1] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 3
+ [function] => b
+ [args] => Array
+ (
+ )
+
+ )
+
+ [2] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 17
+ [function] => a
+ [args] => Array
+ (
+ )
+
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 7
+ [function] => c
+ [args] => Array
+ (
+ )
+
+ )
+
+ [1] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 3
+ [function] => b
+ [args] => Array
+ (
+ )
+
+ )
+
+ [2] => Array
+ (
+ [file] => %sdebug_backtrace_limit.php
+ [line] => 17
+ [function] => a
+ [args] => Array
+ (
+ )
+
+ )
+
+)
diff --git a/Zend/tests/debug_print_backtrace_limit.phpt b/Zend/tests/debug_print_backtrace_limit.phpt
new file mode 100644
index 0000000000..5100387bd6
--- /dev/null
+++ b/Zend/tests/debug_print_backtrace_limit.phpt
@@ -0,0 +1,31 @@
+--TEST--
+debug_print_backtrace limit
+--FILE--
+<?php
+function a() {
+ b();
+}
+
+function b() {
+ c();
+}
+
+function c() {
+ debug_print_backtrace(0, 1);
+ debug_print_backtrace(0, 2);
+ debug_print_backtrace(0, 0);
+ debug_print_backtrace(0, 4);
+}
+
+a();
+?>
+--EXPECTF--
+#0 c() called at [%sdebug_print_backtrace_limit.php:7]
+#0 c() called at [%sdebug_print_backtrace_limit.php:7]
+#1 b() called at [%sdebug_print_backtrace_limit.php:3]
+#0 c() called at [%sdebug_print_backtrace_limit.php:7]
+#1 b() called at [%sdebug_print_backtrace_limit.php:3]
+#2 a() called at [%sdebug_print_backtrace_limit.php:17]
+#0 c() called at [%sdebug_print_backtrace_limit.php:7]
+#1 b() called at [%sdebug_print_backtrace_limit.php:3]
+#2 a() called at [%sdebug_print_backtrace_limit.php:17]
diff --git a/Zend/tests/declare_001.phpt b/Zend/tests/declare_001.phpt
index 14c9a453d6..21d797880e 100644
--- a/Zend/tests/declare_001.phpt
+++ b/Zend/tests/declare_001.phpt
@@ -2,21 +2,29 @@
Testing declare statement with several type values
--SKIPIF--
<?php
-if (in_array("detect_unicode", array_keys(ini_get_all()))) {
- die("skip");
+if (!extension_loaded("mbstring")) {
+ die("skip Requires ext/mbstring");
}
?>
+--INI--
+zend.multibyte=1
--FILE--
<?php
declare(encoding = 1);
-declare(encoding = 1123131232131312321);
+declare(encoding = 112313123213131232100);
declare(encoding = NULL);
-declare(encoding = M_PI);
declare(encoding = 'utf-8');
+declare(encoding = M_PI);
print 'DONE';
?>
---EXPECT--
-DONE
+--EXPECTF--
+Warning: Unsupported encoding [1] in %sdeclare_001.php on line %d
+
+Warning: Unsupported encoding [1.1231312321313E+20] in %sdeclare_001.php on line %d
+
+Warning: Unsupported encoding [] in %sdeclare_001.php on line %d
+
+Fatal error: Cannot use constants as encoding in %sdeclare_001.php on line %d
diff --git a/Zend/tests/declare_002.phpt b/Zend/tests/declare_002.phpt
new file mode 100644
index 0000000000..19844556f1
--- /dev/null
+++ b/Zend/tests/declare_002.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Testing declare statement with several type values
+--SKIPIF--
+<?php
+if (!ini_get("zend.multibyte")) {
+ die("skip Requires zend.multibyte=1");
+}
+if (!extension_loaded("mbstring")) {
+ die("skip Requires ext/mbstring");
+}
+?>
+--FILE--
+<?php
+
+declare(encoding = 1);
+declare(encoding = 1123131232131312321);
+declare(encoding = NULL);
+declare(encoding = 'utf-8');
+declare(encoding = M_PI);
+
+print 'DONE';
+
+?>
+--EXPECTF--
+Warning: Unsupported encoding [%d] in %sdeclare_002.php on line 3
+
+Warning: Unsupported encoding [%f] in %sdeclare_002.php on line 4
+
+Warning: Unsupported encoding [] in %sdeclare_002.php on line 5
+
+Fatal error: Cannot use constants as encoding in %sdeclare_002.php on line 7
diff --git a/Zend/tests/declare_003.phpt b/Zend/tests/declare_003.phpt
new file mode 100644
index 0000000000..2980f7589b
--- /dev/null
+++ b/Zend/tests/declare_003.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Testing declare statement with several type values
+--INI--
+precision=15
+zend.multibyte=1
+--FILE--
+<?php
+
+declare(encoding = 1);
+declare(encoding = 11111111111111);
+declare(encoding = NULL);
+declare(encoding = M_PI);
+
+print 'DONE';
+
+?>
+--EXPECTF--
+Warning: Unsupported encoding [1] in %sdeclare_003.php on line %d
+
+Warning: Unsupported encoding [11111111111111] in %sdeclare_003.php on line %d
+
+Warning: Unsupported encoding [] in %sdeclare_003.php on line %d
+
+Fatal error: Cannot use constants as encoding in %sdeclare_003.php on line %d
diff --git a/Zend/tests/declare_004.phpt b/Zend/tests/declare_004.phpt
new file mode 100644
index 0000000000..a2ba51ac9c
--- /dev/null
+++ b/Zend/tests/declare_004.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Testing declare statement with several type values
+--SKIPIF--
+<?php
+if (!ini_get("zend.multibyte")) {
+ die("skip Requires zend.multibyte=1");
+}
+?>
+--FILE--
+<?php
+
+declare(encoding = 1);
+declare(encoding = 1123131232131312321);
+declare(encoding = NULL);
+declare(encoding = M_PI);
+
+print 'DONE';
+
+?>
+--EXPECTF--
+Warning: Unsupported encoding [%d] in %sdeclare_004.php on line 3
+
+Warning: Unsupported encoding [%f] in %sdeclare_004.php on line 4
+
+Warning: Unsupported encoding [] in %sdeclare_004.php on line 5
+
+Fatal error: Cannot use constants as encoding in %sdeclare_004.php on line 6
diff --git a/Zend/tests/dereference_001.phpt b/Zend/tests/dereference_001.phpt
new file mode 100644
index 0000000000..e09ad2992a
--- /dev/null
+++ b/Zend/tests/dereference_001.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Testing array dereference
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+function a() {
+ return array(1,array(5));
+}
+var_dump(a()[1][0]); // int(5)
+
+function b() {
+ return array();
+}
+var_dump(b()[0]); // Notice: Undefined offset: 0
+
+class foo {
+ public $y = 1;
+
+ public function test() {
+ return array(array(array('foobar')));
+ }
+}
+
+function c() {
+ return array(new foo);
+}
+var_dump(c()[0]->y); // int(1)
+
+function d() {
+ $obj = new foo;
+ return $obj->test();
+}
+var_dump(d()[0][0][0][3]); // string(1) "b"
+
+function e() {
+ $y = 'bar';
+ $x = array('a' => 'foo', 'b' => $y);
+ return $x;
+}
+var_dump(e()['b']); // string(3) "bar"
+
+?>
+--EXPECTF--
+int(5)
+
+Notice: Undefined offset: 0 in %s on line %d
+NULL
+int(1)
+string(1) "b"
+string(3) "bar"
diff --git a/Zend/tests/dereference_002.phpt b/Zend/tests/dereference_002.phpt
new file mode 100644
index 0000000000..022ff370d2
--- /dev/null
+++ b/Zend/tests/dereference_002.phpt
@@ -0,0 +1,79 @@
+--TEST--
+Testing array dereference on method calls
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public function bar() {
+ $x = array();
+ $x[] = 3;
+ $x[] = array(1, 5);
+ $x[] = new foo;
+ return $x;
+ }
+}
+
+$foo = new foo;
+
+var_dump($x = $foo->bar()[1]);
+var_dump($foo->bar()[1][1]);
+var_dump($x[0]);
+var_dump($x = $foo->bar()[2]);
+var_dump($x->bar());
+var_dump($x->bar()[0]);
+
+$x = array();
+$x[] = new foo;
+var_dump($x[0]->bar()[2]);
+var_dump($foo->bar()[2]->bar()[1]);
+var_dump($foo->bar()[2]->bar()[2]->bar()[1][0]);
+var_dump($foo->bar()[2]->bar()[2]->bar()[1][0][1]);
+var_dump($foo->bar()[2]->bar()[2]->bar()[4]);
+var_dump($foo->bar()[3]->bar());
+
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(5)
+}
+int(5)
+int(1)
+object(foo)#2 (0) {
+}
+array(3) {
+ [0]=>
+ int(3)
+ [1]=>
+ array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(5)
+ }
+ [2]=>
+ object(foo)#3 (0) {
+ }
+}
+int(3)
+object(foo)#3 (0) {
+}
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(5)
+}
+int(1)
+NULL
+
+Notice: Undefined offset: 4 in %s on line %d
+NULL
+
+Notice: Undefined offset: 3 in %s on line %d
+
+Fatal error: Call to a member function bar() on a non-object in %s on line %d
diff --git a/Zend/tests/dereference_003.phpt b/Zend/tests/dereference_003.phpt
new file mode 100644
index 0000000000..3a54875964
--- /dev/null
+++ b/Zend/tests/dereference_003.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Testing array dereference on method calls
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $x = 2;
+ public function a() {
+ $x = array();
+ $x[] = new foo;
+ return $x;
+ }
+ public function b() {
+ return array(1.2, array(new self));
+ }
+ public function c() {
+ $a = array();
+ $b = &$a;
+ $b[] = true;
+ return $a;
+ }
+ public function d() {
+ return $this->b();
+ }
+}
+
+$foo = new foo;
+
+var_dump($foo->a()[0]->x);
+var_dump($foo->a()[0]);
+var_dump($foo->b()[1][0]->a()[0]->x);
+var_dump($foo->c()[0]);
+var_dump($foo->d()[0]);
+
+?>
+--EXPECTF--
+int(2)
+object(foo)#%d (1) {
+ ["x"]=>
+ int(2)
+}
+int(2)
+bool(true)
+float(1.2)
diff --git a/Zend/tests/dereference_004.phpt b/Zend/tests/dereference_004.phpt
new file mode 100644
index 0000000000..a77cf032ed
--- /dev/null
+++ b/Zend/tests/dereference_004.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Testing array dereference on __invoke() result
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $x = array();
+ public function __construct() {
+ $h = array();
+ $h[] = new stdclass;
+ $this->x = $h;
+ }
+ public function __invoke() {
+ return $this->x;
+ }
+}
+
+
+$fo = new foo;
+var_dump($fo()[0]);
+
+?>
+--EXPECTF--
+object(stdClass)#%d (0) {
+}
diff --git a/Zend/tests/dereference_005.phpt b/Zend/tests/dereference_005.phpt
new file mode 100644
index 0000000000..cca87571cd
--- /dev/null
+++ b/Zend/tests/dereference_005.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Testing array dereference on object that implements ArrayAccess
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class obj implements arrayaccess {
+ private $container = array();
+ public function __construct() {
+ $this->container = array(
+ "one" => 1,
+ "two" => 2,
+ "three" => 3,
+ );
+ }
+ public function offsetSet($offset, $value) {
+ $this->container[$offset] = $value;
+ }
+ public function offsetExists($offset) {
+ return isset($this->container[$offset]);
+ }
+ public function offsetUnset($offset) {
+ unset($this->container[$offset]);
+ }
+ public function offsetGet($offset) {
+ return isset($this->container[$offset]) ? $this->container[$offset] : null;
+ }
+}
+
+function x() {
+ return new obj;
+}
+var_dump(x()['two']);
+
+?>
+--EXPECT--
+int(2)
diff --git a/Zend/tests/dereference_006.phpt b/Zend/tests/dereference_006.phpt
new file mode 100644
index 0000000000..61a07353a4
--- /dev/null
+++ b/Zend/tests/dereference_006.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Testing array dereference and references
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+function &foo(&$foo) {
+ return $foo;
+}
+
+$a = array(1);
+foo($a)[0] = 2;
+var_dump($a);
+
+foo($a)[] = 3;
+var_dump($a);
+
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ int(2)
+}
+array(2) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(3)
+}
diff --git a/Zend/tests/dereference_007.phpt b/Zend/tests/dereference_007.phpt
new file mode 100644
index 0000000000..2f7d66fd2e
--- /dev/null
+++ b/Zend/tests/dereference_007.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Trying to write on method return
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $x = array();
+
+ public function b() {
+ return $this->x;
+ }
+
+ public function c() {
+ return $x;
+ }
+
+ static public function d() {
+
+ }
+}
+
+$foo = new foo;
+
+$foo->b()[0] = 1;
+
+$foo->c()[100] = 2;
+
+foo::d()[] = 3;
+
+print "ok\n";
+
+?>
+--EXPECTF--
+Notice: Undefined variable: x in %s on line %d
+ok
diff --git a/Zend/tests/dereference_008.phpt b/Zend/tests/dereference_008.phpt
new file mode 100644
index 0000000000..01c828f0c8
--- /dev/null
+++ b/Zend/tests/dereference_008.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Testing array dereference with dynamic method name and references
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $x = array(1);
+
+ public function &b() {
+ return $this->x;
+ }
+}
+
+$foo = new foo;
+
+$a = 'b';
+var_dump($foo->$a()[0]);
+
+$h = &$foo->$a();
+$h[] = 2;
+var_dump($foo->$a());
+
+?>
+--EXPECT--
+int(1)
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+}
diff --git a/Zend/tests/dereference_009.phpt b/Zend/tests/dereference_009.phpt
new file mode 100644
index 0000000000..e579c44bae
--- /dev/null
+++ b/Zend/tests/dereference_009.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Testing array dereference with references
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+$a = array();
+
+function &a() {
+ return $GLOBALS['a'];
+}
+
+var_dump($h =& a());
+$h[] = 1;
+var_dump(a()[0]);
+
+$h[] = array($h);
+var_dump(a()[1][0][0]);
+
+?>
+--EXPECT--
+array(0) {
+}
+int(1)
+int(1)
diff --git a/Zend/tests/dereference_010.phpt b/Zend/tests/dereference_010.phpt
new file mode 100644
index 0000000000..6acda77ba8
--- /dev/null
+++ b/Zend/tests/dereference_010.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Testing dereference in non-array values
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+function a() {
+ return 1;
+}
+
+$a = 1;
+var_dump($a[1]);
+var_dump(a()[1]);
+
+function b() {
+ return new stdClass;
+}
+
+var_dump(b()[1]);
+
+?>
+--EXPECTF--
+NULL
+NULL
+
+Fatal error: Cannot use object of type stdClass as array in %s on line %d
diff --git a/Zend/tests/dereference_011.phpt b/Zend/tests/dereference_011.phpt
new file mode 100644
index 0000000000..17dc8b346b
--- /dev/null
+++ b/Zend/tests/dereference_011.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Testing array dereference with chaining
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $arr;
+
+ public function &a() {
+ return $this->arr;
+ }
+}
+
+$foo = new foo;
+
+$h = &$foo->a();
+$h[] = 1;
+$h[] = $foo;
+var_dump($foo->a()[1]->arr[1]->a()[1]->arr[1]->arr[0]);
+var_dump($foo->a()[1]);
+var_dump($foo->a()[1]->arr[1]);
+
+?>
+--EXPECTF--
+int(1)
+object(foo)#%d (1) {
+ ["arr"]=>
+ &array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ *RECURSION*
+ }
+}
+object(foo)#%d (1) {
+ ["arr"]=>
+ &array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ *RECURSION*
+ }
+}
diff --git a/Zend/tests/dereference_012.phpt b/Zend/tests/dereference_012.phpt
new file mode 100644
index 0000000000..f3ba774f06
--- /dev/null
+++ b/Zend/tests/dereference_012.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Testing array dereferencing on return of a method with and without reference
+--FILE--
+<?php
+
+class foo {
+ static $x = array();
+
+ public function &a() {
+ self::$x = array(1, 2, 3);
+ return self::$x;
+ }
+
+ public function b() {
+ $x = array(1);
+ $x[] = 2;
+ return $x;
+ }
+}
+
+$foo = new foo;
+
+// Changing the static variable
+$foo->a()[0] = 2;
+var_dump($foo::$x);
+
+$foo->b()[] = new stdClass;
+
+$h = $foo->b();
+var_dump($h);
+
+$h[0] = 3;
+var_dump($h);
+
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+}
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+}
+array(2) {
+ [0]=>
+ int(3)
+ [1]=>
+ int(2)
+}
diff --git a/Zend/tests/dereference_013.phpt b/Zend/tests/dereference_013.phpt
new file mode 100644
index 0000000000..cfd89e71b5
--- /dev/null
+++ b/Zend/tests/dereference_013.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Testing array dereferencing on array returned from __call method
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $x = array(2);
+
+ public function __call($x, $y) {
+ if (count($this->x) == 1) {
+ $this->x[] = $y[0];
+ }
+ return $this->x;
+ }
+}
+
+$foo = new foo;
+
+$x = array(1);
+
+$foo->b($x)[1] = 3;
+
+var_dump($foo->b()[0]);
+var_dump($foo->b()[1]);
+var_dump($foo->b()[2]);
+
+?>
+--EXPECTF--
+int(2)
+array(1) {
+ [0]=>
+ int(1)
+}
+
+Notice: Undefined offset: %d in %s on line %d
+NULL
diff --git a/Zend/tests/dereference_014.phpt b/Zend/tests/dereference_014.phpt
new file mode 100644
index 0000000000..62dffd3698
--- /dev/null
+++ b/Zend/tests/dereference_014.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Trying to create an object from dereferencing uninitialized variable
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+class foo {
+ public $x;
+ static public $y;
+
+ public function a() {
+ return $this->x;
+ }
+
+ static public function b() {
+ return self::$y;
+ }
+}
+
+$foo = new foo;
+$h = $foo->a()[0]->a;
+var_dump($h);
+
+$h = foo::b()[1]->b;
+var_dump($h);
+
+?>
+--EXPECTF--
+Notice: Trying to get property of non-object in %s on line %d
+NULL
+
+Notice: Trying to get property of non-object in %s on line %d
+NULL
diff --git a/Zend/tests/empty_str_offset.phpt b/Zend/tests/empty_str_offset.phpt
new file mode 100644
index 0000000000..486c052dc4
--- /dev/null
+++ b/Zend/tests/empty_str_offset.phpt
@@ -0,0 +1,89 @@
+--TEST--
+Testing empty() with string offsets
+--FILE--
+<?php
+
+print "- empty ---\n";
+
+$str = "test0123";
+
+var_dump(empty($str[-1]));
+var_dump(empty($str[0]));
+var_dump(empty($str[1]));
+var_dump(empty($str[4])); // 0
+var_dump(empty($str[5])); // 1
+var_dump(empty($str[8]));
+var_dump(empty($str[10000]));
+// non-numeric offsets
+print "- string ---\n";
+var_dump(empty($str['-1']));
+var_dump(empty($str['0']));
+var_dump(empty($str['1']));
+var_dump(empty($str['4'])); // 0
+var_dump(empty($str['1.5']));
+var_dump(empty($str['good']));
+var_dump(empty($str['3 and a half']));
+print "- bool ---\n";
+var_dump(empty($str[true]));
+var_dump(empty($str[false]));
+var_dump(empty($str[false][true]));
+print "- null ---\n";
+var_dump(empty($str[null]));
+print "- double ---\n";
+var_dump(empty($str[-1.1]));
+var_dump(empty($str[-0.8]));
+var_dump(empty($str[-0.1]));
+var_dump(empty($str[0.2]));
+var_dump(empty($str[0.9]));
+var_dump(empty($str[M_PI]));
+var_dump(empty($str[100.5001]));
+print "- array ---\n";
+var_dump(empty($str[array()]));
+var_dump(empty($str[array(1,2,3)]));
+print "- object ---\n";
+var_dump(empty($str[new stdClass()]));
+print "- resource ---\n";
+$f = fopen(__FILE__, 'r');
+var_dump(empty($str[$f]));
+print "done\n";
+
+?>
+--EXPECTF--
+- empty ---
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+bool(false)
+bool(true)
+bool(true)
+- string ---
+bool(true)
+bool(false)
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+- bool ---
+bool(false)
+bool(false)
+bool(true)
+- null ---
+bool(false)
+- double ---
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+- array ---
+bool(true)
+bool(true)
+- object ---
+bool(true)
+- resource ---
+bool(true)
+done
diff --git a/Zend/tests/error_reporting01.phpt b/Zend/tests/error_reporting01.phpt
index 096977065c..5153d41eab 100644
--- a/Zend/tests/error_reporting01.phpt
+++ b/Zend/tests/error_reporting01.phpt
@@ -22,5 +22,5 @@ var_dump(error_reporting());
echo "Done\n";
?>
--EXPECT--
-int(30719)
+int(32767)
Done
diff --git a/Zend/tests/error_reporting05.phpt b/Zend/tests/error_reporting05.phpt
index 2bf392d7c9..fe5374c4f7 100644
--- a/Zend/tests/error_reporting05.phpt
+++ b/Zend/tests/error_reporting05.phpt
@@ -30,5 +30,5 @@ echo "Done\n";
Notice: Undefined variable: undef_value in %s on line %d
Notice: Undefined variable: undef_name in %s on line %d
-int(30719)
+int(32767)
Done
diff --git a/Zend/tests/error_reporting06.phpt b/Zend/tests/error_reporting06.phpt
index beb91bf094..285a623f2b 100644
--- a/Zend/tests/error_reporting06.phpt
+++ b/Zend/tests/error_reporting06.phpt
@@ -26,5 +26,5 @@ var_dump(error_reporting());
echo "Done\n";
?>
--EXPECTF--
-int(30719)
+int(32767)
Done
diff --git a/Zend/tests/error_reporting07.phpt b/Zend/tests/error_reporting07.phpt
index 5da970c158..c63efae604 100644
--- a/Zend/tests/error_reporting07.phpt
+++ b/Zend/tests/error_reporting07.phpt
@@ -26,5 +26,5 @@ var_dump(error_reporting());
echo "Done\n";
?>
--EXPECTF--
-int(30719)
+int(32767)
Done
diff --git a/Zend/tests/error_reporting10.phpt b/Zend/tests/error_reporting10.phpt
index 7205acda3e..12b1db57ba 100644
--- a/Zend/tests/error_reporting10.phpt
+++ b/Zend/tests/error_reporting10.phpt
@@ -30,6 +30,6 @@ var_dump(error_reporting());
echo "Done\n";
?>
--EXPECTF--
-int(30719)
-int(30711)
+int(32767)
+int(32759)
Done
diff --git a/Zend/tests/fr47160.phpt b/Zend/tests/fr47160.phpt
new file mode 100644
index 0000000000..809e1f1603
--- /dev/null
+++ b/Zend/tests/fr47160.phpt
@@ -0,0 +1,150 @@
+--TEST--
+Calling method from array
+--FILE--
+<?php
+
+class Hello {
+ public function world($x) {
+ echo "Hello, $x\n"; return $this;
+ }
+}
+
+class Hello2 {
+ static public function world($x) {
+ echo "Hello, $x\n";
+ }
+}
+
+class Magic {
+ public function __call($f, $a) {
+ printf("%s called (%s)!\n", __METHOD__, $f);
+ }
+}
+
+class Magic2 {
+ public static function __callStatic($f, $a) {
+ printf("%s called (%s)!\n", __METHOD__, $f);
+ }
+}
+
+class Magic3 {
+ public static function __callStatic($f, $a) {
+ printf("%s called (%s)!\n", __METHOD__, $f);
+ }
+ public function __call($f, $a) {
+ printf("%s called (%s)!\n", __METHOD__, $f);
+ }
+}
+
+$f = array('Hello','world');
+var_dump($f('you'));
+var_dump(call_user_func($f, 'you'));
+
+printf("-----\n");
+
+$h= new Hello;
+$f = array($h,'world');
+var_dump($f('again'));
+var_dump(call_user_func($f, 'again'));
+
+printf("-----\n");
+
+function bar() {
+ return array(new Hello,'world');
+}
+$f = bar();
+var_dump($f('there'));
+var_dump(call_user_func($f, 'there'));
+
+printf("-----\n");
+
+$x = function ($c,$v) { return array($c, $v); };
+
+$c = new Hello;
+$m = 'world';
+$f = $x($c, $m);
+var_dump($f('devs'));
+var_dump(call_user_func($f, 'devs'));
+
+printf("-----\n");
+
+$f = array(new Magic, 'foo');
+$f();
+call_user_func($f);
+
+printf("-----\n");
+
+$f = array('Magic2', 'foo');
+$f();
+call_user_func($f);
+
+
+printf("-----\n");
+
+$f = array('Magic3', 'foo');
+$f();
+call_user_func($f);
+
+printf("-----\n");
+
+$f = array(new Magic3, 'foo');
+$f();
+call_user_func($f);
+
+printf("-----\n");
+
+$f = array(new Hello2, 'world');
+var_dump($f('you'));
+var_dump(call_user_func($f, 'you'));
+
+?>
+--EXPECTF--
+Strict Standards: Non-static method Hello::world() should not be called statically in %s on line %d
+Hello, you
+
+Notice: Undefined variable: this in %s on line %d
+NULL
+
+Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method Hello::world() should not be called statically in %s on line %d
+Hello, you
+
+Notice: Undefined variable: this in %s on line %d
+NULL
+-----
+Hello, again
+object(Hello)#1 (0) {
+}
+Hello, again
+object(Hello)#1 (0) {
+}
+-----
+Hello, there
+object(Hello)#2 (0) {
+}
+Hello, there
+object(Hello)#2 (0) {
+}
+-----
+Hello, devs
+object(Hello)#4 (0) {
+}
+Hello, devs
+object(Hello)#4 (0) {
+}
+-----
+Magic::__call called (foo)!
+Magic::__call called (foo)!
+-----
+Magic2::__callStatic called (foo)!
+Magic2::__callStatic called (foo)!
+-----
+Magic3::__callStatic called (foo)!
+Magic3::__callStatic called (foo)!
+-----
+Magic3::__call called (foo)!
+Magic3::__call called (foo)!
+-----
+Hello, you
+NULL
+Hello, you
+NULL
diff --git a/Zend/tests/function_arguments_001.phpt b/Zend/tests/function_arguments_001.phpt
index bf0cd4a206..8e3d34d31d 100644
--- a/Zend/tests/function_arguments_001.phpt
+++ b/Zend/tests/function_arguments_001.phpt
@@ -5,5 +5,5 @@ Argument parsing error #001
function foo($arg1 string) {}
?>
--EXPECTF--
-Parse error: syntax error, unexpected T_STRING, expecting ')' in %sfunction_arguments_001.php on line %d
+Parse error: %s error, %s)%s in %sfunction_arguments_001.php on line %d
diff --git a/Zend/tests/function_arguments_002.phpt b/Zend/tests/function_arguments_002.phpt
index 79dd31f337..1b5b7bd908 100644
--- a/Zend/tests/function_arguments_002.phpt
+++ b/Zend/tests/function_arguments_002.phpt
@@ -5,5 +5,5 @@ Argument parsing error #002
function foo($arg1/) {}
?>
--EXPECTF--
-Parse error: syntax error, unexpected '/', expecting ')' in %sfunction_arguments_002.php on line %d
+Parse error: %s error, %s)%s in %sfunction_arguments_002.php on line %d
diff --git a/Zend/tests/gc_022.phpt b/Zend/tests/gc_022.phpt
index 5d7bb8494b..cb9e50a43e 100644
--- a/Zend/tests/gc_022.phpt
+++ b/Zend/tests/gc_022.phpt
@@ -7,7 +7,7 @@ zend.enable_gc=1
<?php
$a = array(array());
$a[0][0] =& $a[0];
-$s = array(1) + unserialize(serialize(&$a[0]));
+$s = array(1) + unserialize(serialize($a[0]));
var_dump(gc_collect_cycles());
echo "ok\n"
?>
diff --git a/Zend/tests/gc_029.phpt b/Zend/tests/gc_029.phpt
index 438053414a..edd231760c 100644
--- a/Zend/tests/gc_029.phpt
+++ b/Zend/tests/gc_029.phpt
@@ -1,5 +1,7 @@
--TEST--
GC 029: GC and destructors
+--SKIPIF--
+<?php if (PHP_ZTS) { print "skip only for no-zts build"; }
--INI--
zend.enable_gc=1
--FILE--
diff --git a/Zend/tests/gc_029_zts.phpt b/Zend/tests/gc_029_zts.phpt
new file mode 100644
index 0000000000..fc77e1f3bd
--- /dev/null
+++ b/Zend/tests/gc_029_zts.phpt
@@ -0,0 +1,37 @@
+--TEST--
+GC 029: GC and destructors
+--SKIPIF--
+<?php if (!PHP_ZTS) { print "skip only for zts build"; }
+--INI--
+zend.enable_gc=1
+--FILE--
+<?php
+class Foo {
+ public $bar;
+ public $x = array(1,2,3);
+ function __destruct() {
+ if ($this->bar !== null) {
+ $this->x = null;
+ unset($this->bar);
+ }
+ }
+}
+class Bar {
+ public $foo;
+ function __destruct() {
+ if ($this->foo !== null) {
+ unset($this->foo);
+ }
+ }
+
+}
+$foo = new Foo();
+$bar = new Bar();
+$foo->bar = $bar;
+$bar->foo = $foo;
+unset($foo);
+unset($bar);
+var_dump(gc_collect_cycles());
+?>
+--EXPECT--
+int(3)
diff --git a/Zend/tests/indexing_001.phpt b/Zend/tests/indexing_001.phpt
index 83c2c8d528..0e466ab8ce 100644
--- a/Zend/tests/indexing_001.phpt
+++ b/Zend/tests/indexing_001.phpt
@@ -71,6 +71,8 @@ array(1) {
}
}
+Warning: Illegal string offset 'foo' in %s on line %d
+
Notice: Array to string conversion in %s on line %d
string(1) "A"
diff --git a/Zend/tests/indirect_call_array_001.phpt b/Zend/tests/indirect_call_array_001.phpt
new file mode 100644
index 0000000000..56675b81a5
--- /dev/null
+++ b/Zend/tests/indirect_call_array_001.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Indirect method call by array - Invalid class name
+--FILE--
+<?php
+
+$arr = array('a', 'b');
+$arr();
+
+?>
+--EXPECTF--
+Fatal error: Class 'a' not found in %s on line %d
diff --git a/Zend/tests/indirect_call_array_002.phpt b/Zend/tests/indirect_call_array_002.phpt
new file mode 100644
index 0000000000..013fa559fe
--- /dev/null
+++ b/Zend/tests/indirect_call_array_002.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Indirect method call by array - Invalid method name
+--FILE--
+<?php
+
+$arr = array('stdclass', 'b');
+$arr();
+
+?>
+--EXPECTF--
+Fatal error: Call to undefined method stdClass::b() in %s on line %d
diff --git a/Zend/tests/indirect_call_array_003.phpt b/Zend/tests/indirect_call_array_003.phpt
new file mode 100644
index 0000000000..498c580c48
--- /dev/null
+++ b/Zend/tests/indirect_call_array_003.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Indirect method call by array - Calling __call() and __callStatic()
+--FILE--
+<?php
+
+class foo {
+ public function __call($a, $b) {
+ printf("From %s:\n", __METHOD__);
+ var_dump($a);
+ var_dump($this);
+ }
+ static public function __callStatic($a, $b) {
+ printf("From %s:\n", __METHOD__);
+ var_dump($a);
+ var_dump($this);
+ }
+}
+
+$arr = array('foo', 'abc');
+$arr();
+
+$foo = new foo;
+$arr = array($foo, 'abc');
+$arr();
+
+
+?>
+--EXPECTF--
+From foo::__callStatic:
+string(3) "abc"
+
+Notice: Undefined variable: this in %s on line %d
+NULL
+From foo::__call:
+string(3) "abc"
+object(foo)#%d (0) {
+}
+
diff --git a/Zend/tests/indirect_call_array_004.phpt b/Zend/tests/indirect_call_array_004.phpt
new file mode 100644
index 0000000000..350f720648
--- /dev/null
+++ b/Zend/tests/indirect_call_array_004.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Indirect method call by array - Testing exception and method magics
+--FILE--
+<?php
+
+class foo {
+ static public function abc() {
+ throw new Exception('foo');
+ }
+ public function __call($a, $b) {
+ printf("From %s:\n", __METHOD__);
+ throw new Exception($a);
+ }
+ static public function __callStatic($a, $b) {
+ printf("From %s:\n", __METHOD__);
+ throw new Exception($a);
+ }
+}
+
+
+$arr = array('foo', 'abc');
+
+try {
+ $arr();
+}
+catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+$arr = array('foo', '123');
+
+try {
+ $arr();
+}
+catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+
+echo "------\n";
+
+$foo = new foo;
+$arr = array($foo, 'abc');
+
+try {
+ $arr();
+}
+catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+
+$foo = new foo;
+$arr = array($foo, '123');
+
+try {
+ $arr();
+}
+catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECTF--
+foo
+From foo::__callStatic:
+123
+------
+foo
+From foo::__call:
+123
diff --git a/Zend/tests/indirect_method_call_001.phpt b/Zend/tests/indirect_method_call_001.phpt
new file mode 100644
index 0000000000..7018eaa740
--- /dev/null
+++ b/Zend/tests/indirect_method_call_001.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Testing indirect method call and exceptions
+--FILE--
+<?php
+
+class foo {
+ public function __construct() {
+ throw new Exception('foobar');
+ }
+}
+
+try {
+ $X = (new foo)->Inexistent(3);
+} catch (Exception $e) {
+ var_dump($e->getMessage()); // foobar
+}
+
+?>
+--EXPECT--
+string(6) "foobar"
diff --git a/Zend/tests/indirect_method_call_002.phpt b/Zend/tests/indirect_method_call_002.phpt
new file mode 100644
index 0000000000..1589533bdc
--- /dev/null
+++ b/Zend/tests/indirect_method_call_002.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Indirect method call with chaining
+--FILE--
+<?php
+
+class foo {
+ public $x = 'testing';
+
+ public function bar() {
+ return "foo";
+ }
+ public function baz() {
+ return new self;
+ }
+ static function xyz() {
+ }
+}
+
+var_dump((new foo())->bar()); // string(3) "foo"
+var_dump((new foo())->baz()->x); // string(7) "testing"
+var_dump((new foo())->baz()->baz()->bar()); // string(3) "foo"
+var_dump((new foo())->xyz()); // NULL
+(new foo())->www();
+
+?>
+--EXPECTF--
+string(3) "foo"
+string(7) "testing"
+string(3) "foo"
+NULL
+
+Fatal error: Call to undefined method foo::www() in %s on line %d
diff --git a/Zend/tests/indirect_method_call_003.phpt b/Zend/tests/indirect_method_call_003.phpt
new file mode 100644
index 0000000000..3df495422d
--- /dev/null
+++ b/Zend/tests/indirect_method_call_003.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Testing indirect method call
+--FILE--
+<?php
+
+class foo {
+ public $x = 1;
+
+ public function getX() {
+ return $this->x;
+ }
+ public function setX($val) {
+ $this->x = $val;
+ return $this;
+ }
+}
+
+$X = (new foo)->setX(10)->getX();
+var_dump($X); // int(10)
+
+?>
+--EXPECT--
+int(10)
diff --git a/Zend/tests/indirect_method_call_004.phpt b/Zend/tests/indirect_method_call_004.phpt
new file mode 100644
index 0000000000..689600d1f4
--- /dev/null
+++ b/Zend/tests/indirect_method_call_004.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Indirect method call and cloning
+--FILE--
+<?php
+
+
+class bar {
+ public $z;
+
+ public function __construct() {
+ $this->z = new stdclass;
+ }
+ public function getZ() {
+ return $this->z;
+ }
+}
+
+var_dump(clone (new bar)->z);
+var_dump(clone (new bar)->getZ());
+
+?>
+--EXPECTF--
+object(stdClass)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
diff --git a/Zend/tests/indirect_method_call_005.phpt b/Zend/tests/indirect_method_call_005.phpt
new file mode 100644
index 0000000000..4f4b3631c0
--- /dev/null
+++ b/Zend/tests/indirect_method_call_005.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Testing array dereferencing from instance with ArrayObject
+--FILE--
+<?php
+
+class foo extends ArrayObject {
+ public function __construct($arr) {
+ parent::__construct($arr);
+ }
+}
+
+var_dump( (new foo( array(1, array(4, 5), 3) ))[1][0] ); // int(4)
+
+?>
+--EXPECT--
+int(4)
diff --git a/Zend/tests/indirect_property_access.phpt b/Zend/tests/indirect_property_access.phpt
new file mode 100644
index 0000000000..3645687f41
--- /dev/null
+++ b/Zend/tests/indirect_property_access.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Testing indirect property access
+--FILE--
+<?php
+
+class foo {
+ public $x = 1;
+}
+
+class bar {
+ public $y = 'foo';
+}
+
+$x = 'bar';
+
+$bar = new bar;
+
+var_dump((new bar)->y); // foo
+var_dump((new $x)->y); // foo
+var_dump((new $bar->y)->x); // 1
+
+?>
+--EXPECT--
+string(3) "foo"
+string(3) "foo"
+int(1)
diff --git a/Zend/tests/indirect_reference_this.phpt b/Zend/tests/indirect_reference_this.phpt
index 05419d6c3d..c344bd03ff 100644
--- a/Zend/tests/indirect_reference_this.phpt
+++ b/Zend/tests/indirect_reference_this.phpt
@@ -10,4 +10,4 @@ $x->f("this");
?>
--EXPECTF--
object(X)#%d (0) {
-} \ No newline at end of file
+}
diff --git a/Zend/tests/isset_003.phpt b/Zend/tests/isset_003.phpt
index 68c26f80f0..4db42a933b 100644
--- a/Zend/tests/isset_003.phpt
+++ b/Zend/tests/isset_003.phpt
@@ -29,10 +29,10 @@ bool(true)
bool(false)
bool(false)
-Notice: Undefined variable: d in %s on line %d
-
Notice: Undefined variable: c in %s on line %d
+Notice: Undefined variable: d in %s on line %d
+
Notice: Trying to get property of non-object in %s on line %d
bool(false)
bool(true)
diff --git a/Zend/tests/isset_003_2_4.phpt b/Zend/tests/isset_003_2_4.phpt
new file mode 100644
index 0000000000..c05f3e26f4
--- /dev/null
+++ b/Zend/tests/isset_003_2_4.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Testing isset accessing undefined array itens and properties
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+
+$a = 'foo';
+$b =& $a;
+
+var_dump(isset($b));
+
+var_dump(isset($a[0], $b[1]));
+
+var_dump(isset($a[0]->a));
+
+var_dump(isset($c[0][1][2]->a->b->c->d));
+
+var_dump(isset(${$a}->{$b->$c[$d]}));
+
+var_dump(isset($GLOBALS));
+
+var_dump(isset($GLOBALS[1]));
+
+var_dump(isset($GLOBALS[1]->$GLOBALS));
+
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+
+Notice: Undefined variable: c in %s on line %d
+
+Notice: Undefined variable: d in %s on line %d
+
+Notice: Trying to get property of non-object in %s on line %d
+bool(false)
+bool(true)
+bool(false)
+bool(false)
diff --git a/Zend/tests/isset_str_offset.phpt b/Zend/tests/isset_str_offset.phpt
new file mode 100644
index 0000000000..7a9164a381
--- /dev/null
+++ b/Zend/tests/isset_str_offset.phpt
@@ -0,0 +1,89 @@
+--TEST--
+Testing isset with string offsets
+--FILE--
+<?php
+
+print "- isset ---\n";
+
+$str = "test0123";
+
+var_dump(isset($str[-1]));
+var_dump(isset($str[0]));
+var_dump(isset($str[1]));
+var_dump(isset($str[4])); // 0
+var_dump(isset($str[5])); // 1
+var_dump(isset($str[8]));
+var_dump(isset($str[10000]));
+// non-numeric offsets
+print "- string ---\n";
+var_dump(isset($str['-1']));
+var_dump(isset($str['0']));
+var_dump(isset($str['1']));
+var_dump(isset($str['4'])); // 0
+var_dump(isset($str['1.5']));
+var_dump(isset($str['good']));
+var_dump(isset($str['3 and a half']));
+print "- bool ---\n";
+var_dump(isset($str[true]));
+var_dump(isset($str[false]));
+var_dump(isset($str[false][true]));
+print "- null ---\n";
+var_dump(isset($str[null]));
+print "- double ---\n";
+var_dump(isset($str[-1.1]));
+var_dump(isset($str[-0.8]));
+var_dump(isset($str[-0.1]));
+var_dump(isset($str[0.2]));
+var_dump(isset($str[0.9]));
+var_dump(isset($str[M_PI]));
+var_dump(isset($str[100.5001]));
+print "- array ---\n";
+var_dump(isset($str[array()]));
+var_dump(isset($str[array(1,2,3)]));
+print "- object ---\n";
+var_dump(isset($str[new stdClass()]));
+print "- resource ---\n";
+$f = fopen(__FILE__, 'r');
+var_dump(isset($str[$f]));
+print "done\n";
+
+?>
+--EXPECTF--
+- isset ---
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+- string ---
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+- bool ---
+bool(true)
+bool(true)
+bool(false)
+- null ---
+bool(true)
+- double ---
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+- array ---
+bool(false)
+bool(false)
+- object ---
+bool(false)
+- resource ---
+bool(false)
+done
diff --git a/Zend/tests/magic_by_ref_010.phpt b/Zend/tests/magic_by_ref_010.phpt
deleted file mode 100644
index 0a45fb9113..0000000000
--- a/Zend/tests/magic_by_ref_010.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-passing arguments by ref to a method handled by __call()
---INI--
-allow_call_time_pass_reference=1
---FILE--
-<?php
-
-class Foo {
- function __call($method, $args)
- {
- print $args[0]."\n";
- $args[0] = 5;
- print $args[0]."\n";
- return true;
- }
-}
-
-$v = 'str';
-$o = new Foo();
-$o->test(&$v);
-
-var_dump($v);
-
-echo "Done\n";
-?>
---EXPECTF--
-str
-5
-int(5)
-Done
diff --git a/Zend/tests/method_static_var.phpt b/Zend/tests/method_static_var.phpt
new file mode 100644
index 0000000000..c5e82fef72
--- /dev/null
+++ b/Zend/tests/method_static_var.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Initial value of static var in method depends on the include time of the class definition
+--XFAIL--
+Maybe not a bug
+--FILE--
+<?php
+class Foo {
+ public function __construct() {
+ eval("class Bar extends Foo {}");
+ }
+ public static function test() {
+ static $i = 0;
+ var_dump(++$i);
+ }
+}
+
+foo::test();
+new Foo;
+foo::test();
+
+/**
+ * function_add_ref() makes a clone of static variables for inherited functions, so $i in Bar::test gets initial value 1
+ */
+Bar::test();
+Bar::test();
+--EXPECT--
+int(1)
+int(2)
+int(1)
+int(2)
diff --git a/Zend/tests/multibyte/multibyte_encoding_001.phpt b/Zend/tests/multibyte/multibyte_encoding_001.phpt
index 19b6064cfa..38aa80a40a 100644
--- a/Zend/tests/multibyte/multibyte_encoding_001.phpt
+++ b/Zend/tests/multibyte/multibyte_encoding_001.phpt
@@ -2,7 +2,7 @@
Zend Multibyte and ShiftJIS
--SKIPIF--
<?php
-if (!in_array("detect_unicode", array_keys(ini_get_all()))) {
+if (!in_array("zend.detect_unicode", array_keys(ini_get_all()))) {
die("skip Requires configure --enable-zend-multibyte option");
}
if (!extension_loaded("mbstring")) {
@@ -10,6 +10,7 @@ if (!extension_loaded("mbstring")) {
}
?>
--INI--
+zend.multibyte=1
mbstring.internal_encoding=SJIS
--FILE--
<?php
diff --git a/Zend/tests/multibyte/multibyte_encoding_002.phpt b/Zend/tests/multibyte/multibyte_encoding_002.phpt
index 813222d82d..6e1ad80c9f 100644
--- a/Zend/tests/multibyte/multibyte_encoding_002.phpt
+++ b/Zend/tests/multibyte/multibyte_encoding_002.phpt
@@ -2,7 +2,7 @@
Zend Multibyte and UTF-8 BOM
--SKIPIF--
<?php
-if (!in_array("detect_unicode", array_keys(ini_get_all()))) {
+if (!in_array("zend.detect_unicode", array_keys(ini_get_all()))) {
die("skip Requires configure --enable-zend-multibyte option");
}
if (!extension_loaded("mbstring")) {
@@ -10,6 +10,7 @@ if (!extension_loaded("mbstring")) {
}
?>
--INI--
+zend.multibyte=1
mbstring.internal_encoding=iso-8859-1
--FILE--
<?php
diff --git a/Zend/tests/multibyte/multibyte_encoding_003.phpt b/Zend/tests/multibyte/multibyte_encoding_003.phpt
index badfcc5a63..0f873dd07c 100644
--- a/Zend/tests/multibyte/multibyte_encoding_003.phpt
+++ b/Zend/tests/multibyte/multibyte_encoding_003.phpt
Binary files differ
diff --git a/Zend/tests/multibyte/multibyte_encoding_004.phpt b/Zend/tests/multibyte/multibyte_encoding_004.phpt
index 5a26b7c213..6d121d6680 100644
--- a/Zend/tests/multibyte/multibyte_encoding_004.phpt
+++ b/Zend/tests/multibyte/multibyte_encoding_004.phpt
@@ -2,7 +2,7 @@
test for mbstring script_encoding for flex unsafe encoding (Shift_JIS)
--SKIPIF--
<?php
-if (!in_array("detect_unicode", array_keys(ini_get_all()))) {
+if (!in_array("zend.detect_unicode", array_keys(ini_get_all()))) {
die("skip Requires configure --enable-zend-multibyte option");
}
if (!extension_loaded("mbstring")) {
@@ -10,7 +10,8 @@ if (!extension_loaded("mbstring")) {
}
?>
--INI--
-mbstring.script_encoding=Shift_JIS
+zend.multibyte=1
+zend.script_encoding=Shift_JIS
mbstring.internal_encoding=Shift_JIS
--FILE--
<?php
diff --git a/Zend/tests/multibyte/multibyte_encoding_005.phpt b/Zend/tests/multibyte/multibyte_encoding_005.phpt
index 3946238e50..6fee687483 100644
--- a/Zend/tests/multibyte/multibyte_encoding_005.phpt
+++ b/Zend/tests/multibyte/multibyte_encoding_005.phpt
@@ -2,7 +2,7 @@
encoding conversion from script encoding into internal encoding
--SKIPIF--
<?php
-if (!in_array("detect_unicode", array_keys(ini_get_all()))) {
+if (!in_array("zend.detect_unicode", array_keys(ini_get_all()))) {
die("skip Requires configure --enable-zend-multibyte option");
}
if (!extension_loaded("mbstring")) {
@@ -10,8 +10,9 @@ if (!extension_loaded("mbstring")) {
}
?>
--INI--
+zend.multibyte=1
mbstring.encoding_translation = On
-mbstring.script_encoding=Shift_JIS
+zend.script_encoding=Shift_JIS
mbstring.internal_encoding=UTF-8
--FILE--
<?php
diff --git a/Zend/tests/multibyte/multibyte_encoding_006.phpt b/Zend/tests/multibyte/multibyte_encoding_006.phpt
index da5b8a22b8..b87b434fe4 100644
--- a/Zend/tests/multibyte/multibyte_encoding_006.phpt
+++ b/Zend/tests/multibyte/multibyte_encoding_006.phpt
Binary files differ
diff --git a/Zend/tests/nowdoc_013.phpt b/Zend/tests/nowdoc_013.phpt
index f4ee251749..3e7d41fe07 100644
--- a/Zend/tests/nowdoc_013.phpt
+++ b/Zend/tests/nowdoc_013.phpt
@@ -4,7 +4,6 @@ Test whitespace following end of nowdoc
highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
-highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
--FILE--
diff --git a/Zend/tests/nowdoc_014.phpt b/Zend/tests/nowdoc_014.phpt
index b8948699f8..694490b17d 100644
--- a/Zend/tests/nowdoc_014.phpt
+++ b/Zend/tests/nowdoc_014.phpt
@@ -4,7 +4,6 @@ Highlighting empty nowdoc
highlight.string = #DD0000
highlight.comment = #FF8000
highlight.keyword = #007700
-highlight.bg = #FFFFFF
highlight.default = #0000BB
highlight.html = #000000
--FILE--
diff --git a/Zend/tests/ns_071.phpt b/Zend/tests/ns_071.phpt
index 1fdaec9db3..604e649836 100644
--- a/Zend/tests/ns_071.phpt
+++ b/Zend/tests/ns_071.phpt
@@ -18,4 +18,4 @@ new bar(new \stdclass);
--EXPECTF--
NULL
-Catchable fatal error: Argument 1 passed to foo\bar::__construct() must be an array, object given, called in %s on line %d and defined in %s on line %d
+Catchable fatal error: Argument 1 passed to foo\bar::__construct() must be of the type array, object given, called in %s on line %d and defined in %s on line %d
diff --git a/Zend/tests/ns_086.phpt b/Zend/tests/ns_086.phpt
index ce3e2a6476..00657f6bde 100644
--- a/Zend/tests/ns_086.phpt
+++ b/Zend/tests/ns_086.phpt
@@ -1,5 +1,13 @@
--TEST--
086: bracketed namespace with encoding
+--SKIPIF--
+<?php
+if (!extension_loaded("mbstring")) {
+ die("skip Requires mbstring extension");
+}
+?>
+--INI--
+zend.multibyte=1
--FILE--
<?php
declare(encoding='utf-8');
diff --git a/Zend/tests/objects_002.phpt b/Zend/tests/objects_002.phpt
index 87ba0fdc3b..e2db140b18 100644
--- a/Zend/tests/objects_002.phpt
+++ b/Zend/tests/objects_002.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo() in %s on line %d
Done
diff --git a/Zend/tests/objects_003.phpt b/Zend/tests/objects_003.phpt
index 1c254290f7..7e0f083267 100644
--- a/Zend/tests/objects_003.phpt
+++ b/Zend/tests/objects_003.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo($arg) in %s on line %d
Done
diff --git a/Zend/tests/objects_004.phpt b/Zend/tests/objects_004.phpt
index 35ab4775b1..eb04124474 100644
--- a/Zend/tests/objects_004.phpt
+++ b/Zend/tests/objects_004.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo($arg) in %s on line %d
Done
diff --git a/Zend/tests/objects_005.phpt b/Zend/tests/objects_005.phpt
index d583c9be90..908e797243 100644
--- a/Zend/tests/objects_005.phpt
+++ b/Zend/tests/objects_005.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with & test::foo() in %s on line %d
Done
diff --git a/Zend/tests/objects_006.phpt b/Zend/tests/objects_006.phpt
index fb2e28b3af..f84a3053e9 100644
--- a/Zend/tests/objects_006.phpt
+++ b/Zend/tests/objects_006.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo($arg, $arg2 = NULL) in %s on line %d
Done
diff --git a/Zend/tests/objects_007.phpt b/Zend/tests/objects_007.phpt
index 2fce04a17d..75e0817589 100644
--- a/Zend/tests/objects_007.phpt
+++ b/Zend/tests/objects_007.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo($arg, &$arg2 = NULL) in %s on line %d
Done
diff --git a/Zend/tests/objects_008.phpt b/Zend/tests/objects_008.phpt
index b61d16786c..f6d5826eb8 100644
--- a/Zend/tests/objects_008.phpt
+++ b/Zend/tests/objects_008.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo(Test $arg) in %s on line %d
Done
diff --git a/Zend/tests/objects_009.phpt b/Zend/tests/objects_009.phpt
index 5fad0046a8..04b1118e09 100644
--- a/Zend/tests/objects_009.phpt
+++ b/Zend/tests/objects_009.phpt
@@ -20,5 +20,5 @@ class test3 extends test {
echo "Done\n";
?>
--EXPECTF--
-Strict Standards: Declaration of test3::foo() should be compatible with that of test::foo() in %s on line %d
+Strict Standards: Declaration of test3::foo() should be compatible with test::foo(Test $arg) in %s on line %d
Done
diff --git a/Zend/tests/offset_assign.phpt b/Zend/tests/offset_assign.phpt
index eebf63c4f3..6a00591095 100644
--- a/Zend/tests/offset_assign.phpt
+++ b/Zend/tests/offset_assign.phpt
@@ -3,9 +3,11 @@ Crash on $x['x']['y'] += 1 when $x is string
--FILE--
<?php
$x = "a";
-$x['x']['y'] += 1;
+$x['x']['y'] += 1;
echo "Done\n";
?>
---EXPECTF--
-Fatal error: Cannot use string offset as an array in %s on line %d
+--EXPECTF--
+Warning: Illegal string offset 'x' in %soffset_assign.php on line %d
+
+Fatal error: Cannot use string offset as an array in %soffset_assign.php on line %d
diff --git a/Zend/tests/offset_string.phpt b/Zend/tests/offset_string.phpt
index 63d8abe8dd..f7cb81bb20 100644
--- a/Zend/tests/offset_string.phpt
+++ b/Zend/tests/offset_string.phpt
@@ -9,6 +9,9 @@ var_dump($str[1]);
var_dump($str[0.0836]);
var_dump($str[NULL]);
var_dump($str["run away"]);
+var_dump($str["13"]);
+var_dump($str["14.5"]);
+var_dump($str["15 and then some"]);
var_dump($str[TRUE]);
var_dump($str[FALSE]);
@@ -24,12 +27,29 @@ var_dump($str[$arr]);
echo "Done\n";
?>
---EXPECTF--
+--EXPECTF--
string(1) "i"
+
+Notice: String offset cast occurred in %s on line %d
string(1) "S"
+
+Notice: String offset cast occurred in %s on line %d
string(1) "S"
+
+Warning: Illegal string offset 'run away' in %s on line %d
string(1) "S"
+string(1) "c"
+
+Warning: Illegal string offset '14.5' in %s on line %d
+string(1) "o"
+
+Notice: A non well formed numeric value encountered in %s on line %d
+string(1) "r"
+
+Notice: String offset cast occurred in %s on line %d
string(1) "i"
+
+Notice: String offset cast occurred in %s on line %d
string(1) "S"
Warning: Illegal offset type in %s on line %d
@@ -42,4 +62,4 @@ string(1) "%s"
Warning: Illegal offset type in %s on line %d
string(1) "i"
-Done
+Done \ No newline at end of file
diff --git a/Zend/tests/result_unused.phpt b/Zend/tests/result_unused.phpt
new file mode 100644
index 0000000000..0db744d089
--- /dev/null
+++ b/Zend/tests/result_unused.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Unused result of fetch operations
+--FILE--
+<?php
+$x = array(1);
+$a = "x";
+$$a;
+
+$x = array(array(2));
+$x[0];
+
+$x = "str";
+$x[0];
+$x[3];
+
+class Foo {
+ public $prop = array(3);
+ function __get($name) {
+ return array(4);
+ }
+}
+$x = new Foo();
+$x->prop;
+$x->y;
+echo "ok\n";
+--EXPECTF--
+Notice: Uninitialized string offset: 3 in %sresult_unused.php on line %d
+ok
+
diff --git a/Zend/tests/str_offset_001.phpt b/Zend/tests/str_offset_001.phpt
new file mode 100644
index 0000000000..8a6b91b49a
--- /dev/null
+++ b/Zend/tests/str_offset_001.phpt
@@ -0,0 +1,51 @@
+--TEST--
+string offset 001
+--FILE--
+<?php
+function foo($x) {
+ var_dump($x);
+}
+
+$str = "abc";
+var_dump($str[-1]);
+var_dump($str[0]);
+var_dump($str[1]);
+var_dump($str[2]);
+var_dump($str[3]);
+var_dump($str[1][0]);
+var_dump($str[2][1]);
+
+foo($str[-1]);
+foo($str[0]);
+foo($str[1]);
+foo($str[2]);
+foo($str[3]);
+foo($str[1][0]);
+foo($str[2][1]);
+?>
+--EXPECTF--
+Notice: Uninitialized string offset: -1 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "a"
+string(1) "b"
+string(1) "c"
+
+Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "b"
+
+Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d
+string(0) ""
+
+Notice: Uninitialized string offset: -1 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "a"
+string(1) "b"
+string(1) "c"
+
+Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "b"
+
+Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d
+string(0) ""
diff --git a/Zend/tests/str_offset_002.phpt b/Zend/tests/str_offset_002.phpt
new file mode 100644
index 0000000000..1c465e5bae
--- /dev/null
+++ b/Zend/tests/str_offset_002.phpt
@@ -0,0 +1,9 @@
+--TEST--
+string offset 002
+--FILE--
+<?php
+$a = "aaa";
+$x = array(&$a[1]);
+?>
+--EXPECTF--
+Fatal error: Cannot create references to/from string offsets in %sstr_offset_002.php on line 3
diff --git a/Zend/tests/trait_exists_001.phpt b/Zend/tests/trait_exists_001.phpt
new file mode 100644
index 0000000000..10ce3fa0cb
--- /dev/null
+++ b/Zend/tests/trait_exists_001.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Testing trait_exists()
+--FILE--
+<?php
+
+trait foo {
+}
+
+var_dump(trait_exists('foo'));
+var_dump(trait_exists(1));
+var_dump(trait_exists(NULL));
+var_dump(trait_exists(new stdClass));
+
+?>
+--EXPECTF--
+bool(true)
+bool(false)
+bool(false)
+
+Warning: trait_exists() expects parameter 1 to be string, object given in %s on line %d
+NULL
diff --git a/Zend/tests/trait_exists_002.phpt b/Zend/tests/trait_exists_002.phpt
new file mode 100644
index 0000000000..7b5c899806
--- /dev/null
+++ b/Zend/tests/trait_exists_002.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Testing trait_exists() inside a namespace
+--FILE--
+<?php
+
+namespace foo;
+
+trait IFoo { }
+
+trait ITest { }
+
+
+var_dump(trait_exists('IFoo'));
+var_dump(trait_exists('foo\\IFoo'));
+var_dump(trait_exists('FOO\\ITEST'));
+
+?>
+--EXPECT--
+bool(false)
+bool(true)
+bool(true)
diff --git a/Zend/tests/trait_exists_003.phpt b/Zend/tests/trait_exists_003.phpt
new file mode 100644
index 0000000000..2d57d86486
--- /dev/null
+++ b/Zend/tests/trait_exists_003.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Checking trait_exists(): interface, trait, abstract and final class
+--FILE--
+<?php
+
+interface a { }
+
+abstract class b { }
+
+final class c { }
+
+trait d {}
+
+var_dump(trait_exists('a'));
+var_dump(trait_exists('b'));
+var_dump(trait_exists('c'));
+var_dump(trait_exists('d'));
+
+?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
+bool(true)
diff --git a/Zend/tests/traits/bug54441.phpt b/Zend/tests/traits/bug54441.phpt
new file mode 100644
index 0000000000..84139f326b
--- /dev/null
+++ b/Zend/tests/traits/bug54441.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #54441 (Changing trait static method visibility)
+--FILE--
+<?php
+
+trait Foo {
+ public function bar() {}
+}
+
+class Boo {
+ use Foo {
+ bar as dontKnow;
+ dontKnow as protected;
+ }
+}
+
+?>
+--EXPECTF--
+Fatal error: The modifiers for the trait alias dontKnow() need to be changed in the same statment in which the alias is defined. Error in %s on line %d
diff --git a/Zend/tests/traits/bug55137.phpt b/Zend/tests/traits/bug55137.phpt
new file mode 100644
index 0000000000..4a4e6e61a2
--- /dev/null
+++ b/Zend/tests/traits/bug55137.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #55137 (Changing trait static method visibility)
+--FILE--
+<?php
+
+trait A {
+ protected static function foo() { echo "abc\n"; }
+ private static function bar() { echo "def\n"; }
+}
+
+
+class B {
+ use A {
+ A::foo as public;
+ A::bar as public baz;
+ }
+}
+
+B::foo();
+B::baz();
+
+
+?>
+--EXPECT--
+abc
+def
diff --git a/Zend/tests/traits/bug55214.phpt b/Zend/tests/traits/bug55214.phpt
new file mode 100644
index 0000000000..890fc3792c
--- /dev/null
+++ b/Zend/tests/traits/bug55214.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Bug #55214 (Use of __CLASS__ within trait returns trait name not class name)
+--FILE--
+<?php
+
+trait ATrait {
+ public static $static_var = __CLASS__;
+ public $var = __CLASS__;
+
+ public static function get_class_name() {
+ return __CLASS__;
+ }
+
+ public function get_class_name_obj() {
+ return __CLASS__;
+ }
+
+ public static function get_class_name2() {
+ return self::$static_var;
+ }
+
+ public function get_class_name_obj2() {
+ return $this->var;
+ }
+}
+
+trait Indirect {
+ use ATrait;
+}
+
+class SomeClass {
+ use ATrait;
+}
+
+class UsingIndirect {
+ use Indirect;
+}
+
+$r = SomeClass::get_class_name();
+var_dump($r);
+$r = SomeClass::get_class_name2();
+var_dump($r);
+
+$o = new SomeClass();
+$r = $o->get_class_name_obj();
+var_dump($r);
+$r = $o->get_class_name_obj2();
+var_dump($r);
+
+$r = UsingIndirect::get_class_name();
+var_dump($r);
+$r = UsingIndirect::get_class_name2();
+var_dump($r);
+
+$o = new UsingIndirect();
+$r = $o->get_class_name_obj();
+var_dump($r);
+$r = $o->get_class_name_obj2();
+var_dump($r);
+
+
+?>
+--EXPECT--
+string(9) "SomeClass"
+string(9) "SomeClass"
+string(9) "SomeClass"
+string(9) "SomeClass"
+string(13) "UsingIndirect"
+string(13) "UsingIndirect"
+string(13) "UsingIndirect"
+string(13) "UsingIndirect"
diff --git a/Zend/tests/traits/bug55355.phpt b/Zend/tests/traits/bug55355.phpt
new file mode 100644
index 0000000000..301ceeeb09
--- /dev/null
+++ b/Zend/tests/traits/bug55355.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #55355 (Abstract functions required by a trait are not correctly found when implemented in an ancestor class)
+--FILE--
+<?php
+
+// A trait that has a abstract function
+trait ATrait {
+ function bar() {
+ $this->foo();
+ }
+ abstract function foo();
+}
+
+// A class on the second level in the
+// inheritance chain
+class Level2Impl {
+ function foo() {}
+}
+
+class Level1Indirect extends Level2Impl {}
+
+// A class on the first level in the
+// inheritance chain
+class Level1Direct {
+ function foo() {}
+}
+
+// Trait Uses
+
+class Direct {
+ use ATrait;
+ function foo() {}
+}
+
+class BaseL2 extends Level1Indirect {
+ use ATrait;
+}
+
+class BaseL1 extends Level1Direct {
+ use ATrait;
+}
+
+echo 'DONE';
+?>
+--EXPECT--
+DONE
diff --git a/Zend/tests/traits/bug55372.phpt b/Zend/tests/traits/bug55372.phpt
new file mode 100644
index 0000000000..e215d968ab
--- /dev/null
+++ b/Zend/tests/traits/bug55372.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #55372 (Literal handling in methods is inconsistent, causing memory corruption)
+--FILE--
+<?php
+
+trait testTrait {
+ public function testMethod() {
+ if (1) {
+ $letters1 = range('a', 'z', 1);
+ $letters2 = range('A', 'Z', 1);
+ $letters1 = 'foo';
+ $letters2 = 'baarr';
+ var_dump($letters1);
+ var_dump($letters2);
+ }
+ }
+}
+
+class foo {
+ use testTrait;
+}
+
+$x = new foo;
+$x->testMethod();
+?>
+--EXPECT--
+string(3) "foo"
+string(5) "baarr"
diff --git a/Zend/tests/traits/bug55424.phpt b/Zend/tests/traits/bug55424.phpt
new file mode 100644
index 0000000000..b6c3b54515
--- /dev/null
+++ b/Zend/tests/traits/bug55424.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #55424 (Method got missing from class when a trait defined an abstract method to express a requirement)
+--FILE--
+<?php
+
+ trait ATrait
+ {
+ function setRequired()
+ {
+ $this->setAttribute();
+ }
+
+ abstract function setAttribute();
+ }
+
+ class Base
+ {
+ function setAttribute() { }
+ }
+
+ class MyClass extends Base
+ {
+ use ATrait;
+ }
+
+ $i = new Base();
+ $i->setAttribute();
+
+ $t = new MyClass();
+ /* setAttribute used to disappear for no good reason. */
+ $t->setRequired();
+ echo 'DONE';
+?>
+--EXPECT--
+DONE
diff --git a/Zend/tests/traits/bug55524.phpt b/Zend/tests/traits/bug55524.phpt
new file mode 100644
index 0000000000..137975980d
--- /dev/null
+++ b/Zend/tests/traits/bug55524.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #55524 Traits should not be able to extend a class
+--FILE--
+<?php
+
+class Base {}
+
+trait Foo extends Base {
+ function bar() {}
+}
+
+echo 'DONE';
+?>
+--EXPECTF--
+Fatal error: A trait (Foo) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error in %s on line %d
diff --git a/Zend/tests/traits/bug55554a.phpt b/Zend/tests/traits/bug55554a.phpt
new file mode 100644
index 0000000000..b92a81f54f
--- /dev/null
+++ b/Zend/tests/traits/bug55554a.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+// All constructors should be registered as such
+
+trait TConstructor {
+ public function constructor() {
+ echo "ctor executed\n";
+ }
+}
+
+class NewConstructor {
+ use TConstructor {
+ constructor as __construct;
+ }
+}
+
+class LegacyConstructor {
+ use TConstructor {
+ constructor as LegacyConstructor;
+ }
+}
+
+echo "New constructor: ";
+$o = new NewConstructor;
+
+echo "Legacy constructor: ";
+$o = new LegacyConstructor;
+
+--EXPECT--
+New constructor: ctor executed
+Legacy constructor: ctor executed
diff --git a/Zend/tests/traits/bug55554b.phpt b/Zend/tests/traits/bug55554b.phpt
new file mode 100644
index 0000000000..bf40e89a08
--- /dev/null
+++ b/Zend/tests/traits/bug55554b.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+trait TConstructor {
+ public function foo() {
+ echo "foo executed\n";
+ }
+ public function bar() {
+ echo "bar executed\n";
+ }
+}
+
+class OverridingIsSilent1 {
+ use TConstructor {
+ foo as __construct;
+ }
+
+ public function __construct() {
+ echo "OverridingIsSilent1 __construct\n";
+ }
+}
+
+$o = new OverridingIsSilent1;
+
+class OverridingIsSilent2 {
+ use TConstructor {
+ foo as OverridingIsSilent2;
+ }
+
+ public function OverridingIsSilent2() {
+ echo "OverridingIsSilent2 OverridingIsSilent2\n";
+ }
+}
+
+$o = new OverridingIsSilent2;
+
+class ReportCollision {
+ use TConstructor {
+ bar as ReportCollision;
+ foo as __construct;
+ }
+}
+
+
+echo "ReportCollision: ";
+$o = new ReportCollision;
+
+
+--EXPECTF--
+OverridingIsSilent1 __construct
+OverridingIsSilent2 OverridingIsSilent2
+
+Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d
+
diff --git a/Zend/tests/traits/bug55554c.phpt b/Zend/tests/traits/bug55554c.phpt
new file mode 100644
index 0000000000..466b3f1c08
--- /dev/null
+++ b/Zend/tests/traits/bug55554c.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+// Test that the behavior is consistent with the existing handling of new
+// and legacy constructors.
+// Here, the traits conflicts are overridden by local definitions,
+// and the two constructor definitions do not directly collide in that case.
+
+trait TC1 {
+ public function __construct() {
+ echo "TC1 executed\n";
+ }
+ public function ReportCollision() {
+ echo "TC1 executed\n";
+ }
+}
+
+trait TC2 {
+ public function __construct() {
+ echo "TC2 executed\n";
+ }
+ public function ReportCollision() {
+ echo "TC1 executed\n";
+ }
+}
+
+class ReportCollision {
+ use TC1, TC2;
+
+ public function __construct() {
+ echo "New constructor executed\n";
+ }
+ public function ReportCollision() {
+ echo "Legacy constructor executed\n";
+ }
+}
+
+
+echo "ReportCollision: ";
+$o = new ReportCollision;
+
+
+--EXPECTF--
+ReportCollision: New constructor executed
diff --git a/Zend/tests/traits/bug55554d.phpt b/Zend/tests/traits/bug55554d.phpt
new file mode 100644
index 0000000000..10f2e2952d
--- /dev/null
+++ b/Zend/tests/traits/bug55554d.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+// Test mixed constructors from different traits, we are more strict about
+// these cases, since that can lead to un-expected behavior.
+// It is not consistent with the normal constructor handling, but
+// here we have a chance to be more strict for the new traits.
+
+trait TNew {
+ public function __construct() {
+ echo "TNew executed\n";
+ }
+}
+
+trait TLegacy {
+ public function ReportCollision() {
+ echo "ReportCollision executed\n";
+ }
+}
+
+class ReportCollision {
+ use TNew, TLegacy;
+}
+
+$o = new ReportCollision;
+
+--EXPECTF--
+
+Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d
+
diff --git a/Zend/tests/traits/bug55554e.phpt b/Zend/tests/traits/bug55554e.phpt
new file mode 100644
index 0000000000..5db508fc85
--- /dev/null
+++ b/Zend/tests/traits/bug55554e.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+// Ensuring that the collision still occurs as expected.
+
+trait TC1 {
+ public function ReportCollision() {
+ echo "TC1 executed\n";
+ }
+}
+
+trait TC2 {
+ public function ReportCollision() {
+ echo "TC1 executed\n";
+ }
+}
+
+class ReportCollision {
+ use TC1, TC2;
+}
+
+
+echo "ReportCollision: ";
+$o = new ReportCollision;
+
+
+--EXPECTF--
+Fatal error: Trait method ReportCollision has not been applied, because there are collisions with other trait methods on ReportCollision in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bug55554f.phpt b/Zend/tests/traits/bug55554f.phpt
new file mode 100644
index 0000000000..34b327d305
--- /dev/null
+++ b/Zend/tests/traits/bug55554f.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+// Ensuring that inconsistent constructor use results in an error to avoid
+// problems creeping in.
+
+trait TNew {
+ public function __construct() {
+ echo "TNew executed\n";
+ }
+}
+
+class ReportCollision {
+ use TNew;
+
+ public function ReportCollision() {
+ echo "ReportCollision executed\n";
+ }
+}
+
+
+echo "ReportCollision: ";
+$o = new ReportCollision;
+
+
+--EXPECTF--
+Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bug55554g.phpt b/Zend/tests/traits/bug55554g.phpt
new file mode 100644
index 0000000000..22d269603e
--- /dev/null
+++ b/Zend/tests/traits/bug55554g.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #55137 (Legacy constructor not registered for class)
+--FILE--
+<?php
+
+// Ensuring that inconsistent constructor use results in an error to avoid
+// problems creeping in.
+
+trait TLegacy {
+ public function ReportCollision() {
+ echo "TLegacy executed\n";
+ }
+}
+
+class ReportCollision {
+ use TLegacy;
+
+ public function __construct() {
+ echo "ReportCollision executed\n";
+ }
+}
+
+
+echo "ReportCollision: ";
+$o = new ReportCollision;
+
+
+--EXPECTF--
+Fatal error: ReportCollision has colliding constructor definitions coming from traits in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bug60145.phpt b/Zend/tests/traits/bug60145.phpt
new file mode 100644
index 0000000000..fcd0cfa5f2
--- /dev/null
+++ b/Zend/tests/traits/bug60145.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #60145 (Usage of trait's use statement inside interfaces not properly checked.)
+--FILE--
+<?php
+
+trait foo {
+
+}
+
+interface MyInterface {
+ use foo;
+
+ public function b();
+
+}
+--EXPECTF--
+Fatal error: Cannot use traits inside of interfaces. foo is used in MyInterface in %s on line %d
diff --git a/Zend/tests/traits/bug60153.phpt b/Zend/tests/traits/bug60153.phpt
new file mode 100644
index 0000000000..8f01e72c2d
--- /dev/null
+++ b/Zend/tests/traits/bug60153.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #60153 (Interface method prototypes not enforced when implementd via traits.)
+--FILE--
+<?php
+
+interface IFoo {
+ public function oneArgument($a);
+}
+
+trait TFoo {
+ public function oneArgument() {}
+}
+
+class C implements IFoo {
+ use TFoo;
+}
+
+--EXPECTF--
+Fatal error: Declaration of C::oneArgument() must be compatible with IFoo::oneArgument($a) in %s on line %d
diff --git a/Zend/tests/traits/bug60165a.phpt b/Zend/tests/traits/bug60165a.phpt
new file mode 100644
index 0000000000..245bb94e97
--- /dev/null
+++ b/Zend/tests/traits/bug60165a.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #60165 (Aliasing unexisting trait should throw/trigger the exception/error)
+--FILE--
+<?php
+
+trait A {
+ public function bar() {}
+}
+
+class MyClass {
+ use A {
+ nonExistent as barA;
+ }
+}
+
+--EXPECTF--
+Fatal error: An alias (barA) was defined for method nonExistent(), but this method does not exist in %s on line %d
diff --git a/Zend/tests/traits/bug60165b.phpt b/Zend/tests/traits/bug60165b.phpt
new file mode 100644
index 0000000000..7b4855a646
--- /dev/null
+++ b/Zend/tests/traits/bug60165b.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #60165 (Aliasing unexisting trait should throw/trigger the exception/error)
+--FILE--
+<?php
+
+trait A {
+ public function bar() {}
+}
+
+class MyClass {
+ use A {
+ A::nonExistent as barA;
+ }
+}
+
+--EXPECTF--
+Fatal error: An alias was defined for A::nonExistent but this method does not exist in %s on line %d
diff --git a/Zend/tests/traits/bug60165c.phpt b/Zend/tests/traits/bug60165c.phpt
new file mode 100644
index 0000000000..d72491f030
--- /dev/null
+++ b/Zend/tests/traits/bug60165c.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #60165 (Aliasing unexisting trait should throw/trigger the exception/error)
+--FILE--
+<?php
+
+trait A {
+ public function bar() {}
+}
+
+trait B {
+ public function foo() {}
+}
+
+class MyClass {
+ use A, B {
+ foo as fooB;
+ baz as foobar;
+ }
+}
+
+--EXPECTF--
+Fatal error: An alias (foobar) was defined for method baz(), but this method does not exist in %s on line %d
diff --git a/Zend/tests/traits/bug60165d.phpt b/Zend/tests/traits/bug60165d.phpt
new file mode 100644
index 0000000000..26ac927a81
--- /dev/null
+++ b/Zend/tests/traits/bug60165d.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #60165 (Aliasing unexisting trait should throw/trigger the exception/error)
+--FILE--
+<?php
+
+// The same is true for the insteadof operator to resolve conflicts
+
+trait A {}
+
+trait B {
+ public function bar() {}
+}
+
+class MyClass {
+ use A, B {
+ A::bar insteadof B;
+ }
+}
+
+--EXPECTF--
+Fatal error: A precedence rule was defined for A::bar but this method does not exist in %s on line %d
diff --git a/Zend/tests/traits/bug60173.phpt b/Zend/tests/traits/bug60173.phpt
new file mode 100644
index 0000000000..a28a1033a0
--- /dev/null
+++ b/Zend/tests/traits/bug60173.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #60173 (Wrong error message on reflective trait instantiation)
+--FILE--
+<?php
+
+trait foo { }
+
+$rc = new ReflectionClass('foo');
+$rc->newInstance();
+
+--EXPECTF--
+Fatal error: Cannot instantiate trait foo in %s on line %d
diff --git a/Zend/tests/traits/bug60217a.phpt b/Zend/tests/traits/bug60217a.phpt
new file mode 100644
index 0000000000..62a3515955
--- /dev/null
+++ b/Zend/tests/traits/bug60217a.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #60217 (Requiring the same method from different traits.)
+--FILE--
+<?php
+
+trait T1 {
+ public abstract function foo();
+}
+
+trait T2 {
+ public abstract function foo();
+}
+
+class C {
+ use T1, T2;
+
+ public function foo() {
+ echo "C::foo() works.\n";
+ }
+}
+
+$o = new C;
+$o->foo();
+
+--EXPECTF--
+C::foo() works.
diff --git a/Zend/tests/traits/bug60217b.phpt b/Zend/tests/traits/bug60217b.phpt
new file mode 100644
index 0000000000..f03955020e
--- /dev/null
+++ b/Zend/tests/traits/bug60217b.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #60217 (Requiring the same method from different traits and abstract methods have to be compatible)
+--FILE--
+<?php
+
+trait TBroken1 {
+ public abstract function foo($a);
+}
+
+trait TBroken2 {
+ public abstract function foo($a, $b = 0);
+}
+
+class CBroken {
+ use TBroken1, TBroken2;
+
+ public function foo($a) {
+ echo 'FOO';
+ }
+}
+
+$o = new CBroken;
+$o->foo(1);
+
+--EXPECTF--
+Fatal error: Declaration of TBroken1::foo($a) must be compatible with TBroken2::foo($a, $b = 0) in %s on line %d
diff --git a/Zend/tests/traits/bug60217c.phpt b/Zend/tests/traits/bug60217c.phpt
new file mode 100644
index 0000000000..ce8980775f
--- /dev/null
+++ b/Zend/tests/traits/bug60217c.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #60217 (Requiring the same method from different traits and abstract methods have to be compatible, in both directions.)
+--FILE--
+<?php
+
+trait TBroken1 {
+ public abstract function foo($a, $b = 0);
+}
+
+trait TBroken2 {
+ public abstract function foo($a);
+}
+
+class CBroken {
+ use TBroken1, TBroken2;
+
+ public function foo($a) {
+ echo 'FOO';
+ }
+}
+
+$o = new CBroken;
+$o->foo(1);
+
+--EXPECTF--
+Fatal error: Declaration of TBroken1::foo($a, $b = 0) must be compatible with TBroken2::foo($a) in %s on line %d
diff --git a/Zend/tests/traits/bug60369.phpt b/Zend/tests/traits/bug60369.phpt
new file mode 100644
index 0000000000..bfc1ee303f
--- /dev/null
+++ b/Zend/tests/traits/bug60369.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #60369 (Crash with static property in trait)
+--FILE--
+<?php
+
+trait PropertiesTrait {
+ static $same = true;
+}
+
+class Properties {
+ use PropertiesTrait;
+ public $same = true;
+}
+
+?>
+--EXPECTF--
+Fatal error: Properties and PropertiesTrait define the same property ($same) in the composition of Properties. However, the definition differs and is considered incompatible. Class was composed in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bug60717.phpt b/Zend/tests/traits/bug60717.phpt
new file mode 100644
index 0000000000..bf3adb1c88
--- /dev/null
+++ b/Zend/tests/traits/bug60717.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Bug #60717 (Order of traits in use statement can cause unexpected unresolved abstract method)
+--FILE--
+<?php
+
+namespace HTML
+{
+ interface Helper
+ {
+ function text($text);
+ function attributes(array $attributes = null);
+ function textArea(array $attributes = null, $value);
+ }
+
+ trait TextUTF8
+ {
+ function text($text) {}
+ }
+
+ trait TextArea
+ {
+ function textArea(array $attributes = null, $value) {}
+ abstract function attributes(array $attributes = null);
+ abstract function text($text);
+ }
+
+ trait HTMLAttributes
+ {
+ function attributes(array $attributes = null) { }
+ abstract function text($text);
+ }
+
+ class HTMLHelper implements Helper
+ {
+ use TextArea, HTMLAttributes, TextUTF8;
+ }
+
+ class HTMLHelper2 implements Helper
+ {
+ use TextArea, TextUTF8, HTMLAttributes;
+ }
+
+ class HTMLHelper3 implements Helper
+ {
+ use HTMLAttributes, TextArea, TextUTF8;
+ }
+
+ class HTMLHelper4 implements Helper
+ {
+ use HTMLAttributes, TextUTF8, TextArea;
+ }
+
+ class HTMLHelper5 implements Helper
+ {
+ use TextUTF8, TextArea, HTMLAttributes;
+ }
+
+ class HTMLHelper6 implements Helper
+ {
+ use TextUTF8, HTMLAttributes, TextArea;
+ }
+
+ $o = new HTMLHelper;
+ $o = new HTMLHelper2;
+ $o = new HTMLHelper3;
+ $o = new HTMLHelper4;
+ $o = new HTMLHelper5;
+ $o = new HTMLHelper6;
+ echo 'Done';
+}
+
+--EXPECT--
+Done
diff --git a/Zend/tests/traits/bug60809.phpt b/Zend/tests/traits/bug60809.phpt
new file mode 100644
index 0000000000..78e7898461
--- /dev/null
+++ b/Zend/tests/traits/bug60809.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #60809 (TRAITS - PHPDoc Comment Style Bug)
+--FILE--
+<?php
+class ExampleParent {
+ private $hello_world = "hello foo\n";
+ public function foo() {
+ echo $this->hello_world;
+ }
+}
+
+class Example extends ExampleParent {
+ use ExampleTrait;
+}
+
+trait ExampleTrait {
+ /**
+ *
+ */
+ private $hello_world = "hello bar\n";
+ /**
+ *
+ */
+ public $prop = "ops";
+ public function bar() {
+ echo $this->hello_world;
+ }
+}
+
+$x = new Example();
+$x->foo();
+$x->bar();
+?>
+--EXPECT--
+hello foo
+hello bar
diff --git a/Zend/tests/traits/bug61052.phpt b/Zend/tests/traits/bug61052.phpt
new file mode 100644
index 0000000000..421e9074e5
--- /dev/null
+++ b/Zend/tests/traits/bug61052.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #61052 (missing error check in trait 'insteadof' clause)
+--FILE--
+<?php
+trait T1 {
+ function foo(){ echo "T1\n"; }
+}
+trait T2 {
+ function foo(){ echo "T2\n"; }
+}
+class C {
+ use T1, T2 {
+ T1::foo insteadof T1;
+ }
+}
+C::foo();
+--EXPECTF--
+Fatal error: Inconsistent insteadof definition. The method foo is to be used from T1, but T1 is also on the exclude list in %s on line %d
diff --git a/Zend/tests/traits/bug61998.phpt b/Zend/tests/traits/bug61998.phpt
new file mode 100644
index 0000000000..612caa0662
--- /dev/null
+++ b/Zend/tests/traits/bug61998.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Bug #61998 (Using traits with method aliases appears to result in crash during execution)
+--FILE--
+<?php
+class Foo {
+ use T1 {
+ func as newFunc;
+ }
+
+ public function func() {
+ echo "From Foo\n";
+ }
+}
+
+trait T1 {
+ public function func() {
+ echo "From T1\n";
+ }
+}
+
+class Bar {
+ public function func() {
+ echo "From Bar\n";
+ }
+ public function func2() {
+ echo "From Bar\n";
+ }
+ public function func3() {
+ echo "From Bar\n";
+ }
+ use T1 {
+ func as newFunc;
+ func as func2;
+ }
+ use T2 {
+ func2 as newFunc2;
+ func2 as newFunc3;
+ func2 as func3;
+ }
+}
+
+trait T2 {
+ public function func2() {
+ echo "From T2\n";
+ }
+}
+
+$f = new Foo();
+
+$f->newFunc(); //from T1
+$f->func(); //from Foo
+
+$b = new Bar();
+$b->newFunc(); //from T1
+$b->func(); //from Bar
+$b->func2(); //from Bar
+$b->newFunc2(); //from T2
+$b->newFunc3(); //from T2
+$b->func3(); //from Bar
+--EXPECTF--
+From T1
+From Foo
+From T1
+From Bar
+From Bar
+From T2
+From T2
+From Bar
diff --git a/Zend/tests/traits/bugs/abstract-methods01.phpt b/Zend/tests/traits/bugs/abstract-methods01.phpt
new file mode 100644
index 0000000000..6275caa193
--- /dev/null
+++ b/Zend/tests/traits/bugs/abstract-methods01.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Abstract Trait Methods should behave like common abstract methods.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public abstract function hello();
+}
+
+class TraitsTest {
+ use THello;
+}
+
+$test = new TraitsTest();
+$test->hello();
+?>
+--EXPECTF--
+Fatal error: Class %s contains %d abstract method and must therefore be declared abstract or implement the remaining methods (%s) in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/abstract-methods02.phpt b/Zend/tests/traits/bugs/abstract-methods02.phpt
new file mode 100644
index 0000000000..78abe7d1bc
--- /dev/null
+++ b/Zend/tests/traits/bugs/abstract-methods02.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Abstract Trait Methods should behave like common abstract methods.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public abstract function hello();
+}
+
+trait THelloImpl {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+class TraitsTest {
+ use THello;
+ use THelloImpl;
+}
+
+$test = new TraitsTest();
+$test->hello();
+?>
+--EXPECTF--
+Hello \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/abstract-methods03.phpt b/Zend/tests/traits/bugs/abstract-methods03.phpt
new file mode 100644
index 0000000000..605b1d8e9e
--- /dev/null
+++ b/Zend/tests/traits/bugs/abstract-methods03.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Abstract Trait Methods should behave like common abstract methods.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public abstract function hello();
+}
+
+class TraitsTest {
+ use THello;
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+$test = new TraitsTest();
+$test->hello();
+?>
+--EXPECTF--
+Hello \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/abstract-methods04.phpt b/Zend/tests/traits/bugs/abstract-methods04.phpt
new file mode 100644
index 0000000000..56a3464067
--- /dev/null
+++ b/Zend/tests/traits/bugs/abstract-methods04.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Abstract Trait Methods should behave like common abstract methods and
+implementstion may be provided by other traits. Sorting order shouldn't influence result.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public abstract function hello();
+}
+
+trait THelloImpl {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+class TraitsTest1 {
+ use THello;
+ use THelloImpl;
+}
+
+$test = new TraitsTest1();
+$test->hello();
+
+class TraitsTest2 {
+ use THelloImpl;
+ use THello;
+}
+
+$test = new TraitsTest2();
+$test->hello();
+
+?>
+--EXPECTF--
+HelloHello \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/abstract-methods05.phpt b/Zend/tests/traits/bugs/abstract-methods05.phpt
new file mode 100644
index 0000000000..e90ce39a32
--- /dev/null
+++ b/Zend/tests/traits/bugs/abstract-methods05.phpt
@@ -0,0 +1,25 @@
+--TEST--
+The compatibility with the signature of abstract methods should be checked.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THelloB {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+trait THelloA {
+ public abstract function hello($a);
+}
+
+class TraitsTest1 {
+ use THelloB;
+ use THelloA;
+}
+
+
+?>
+--EXPECTF--
+Fatal error: Declaration of THelloB::hello() must be compatible with THelloA::hello($a) in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/abstract-methods06.phpt b/Zend/tests/traits/bugs/abstract-methods06.phpt
new file mode 100644
index 0000000000..28ed672725
--- /dev/null
+++ b/Zend/tests/traits/bugs/abstract-methods06.phpt
@@ -0,0 +1,26 @@
+--TEST--
+The compatibility with the signature of abstract methods should be checked. (also checking the second possible implementation branch)
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THelloB {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+trait THelloA {
+ public abstract function hello($a);
+}
+
+class TraitsTest1 {
+ use THelloA;
+ use THelloB;
+}
+
+
+
+?>
+--EXPECTF--
+Fatal error: Declaration of THelloA::hello($a) must be compatible with THelloB::hello() in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/alias-semantics.phpt b/Zend/tests/traits/bugs/alias-semantics.phpt
new file mode 100644
index 0000000000..ac86692880
--- /dev/null
+++ b/Zend/tests/traits/bugs/alias-semantics.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Semantic of alias operation is to provide an additional identifier for the method body of the original method.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public function a() {
+ echo 'A';
+ }
+}
+
+class TraitsTest {
+ use THello { a as b; }
+}
+
+$test = new TraitsTest();
+$test->a();
+$test->b();
+
+?>
+--EXPECTF--
+AA \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/alias-semantics02.phpt b/Zend/tests/traits/bugs/alias-semantics02.phpt
new file mode 100644
index 0000000000..e0b5286e4f
--- /dev/null
+++ b/Zend/tests/traits/bugs/alias-semantics02.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Semantic of alias operation is to provide an additional identifier for the
+method body of the original method.
+It should also work incase the method is fully qualified.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public function a() {
+ echo 'A';
+ }
+}
+
+class TraitsTest {
+ use THello { THello::a as b; }
+}
+
+$test = new TraitsTest();
+$test->a();
+$test->b();
+
+?>
+--EXPECTF--
+AA \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/alias01.phpt b/Zend/tests/traits/bugs/alias01.phpt
new file mode 100644
index 0000000000..b60261efac
--- /dev/null
+++ b/Zend/tests/traits/bugs/alias01.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Aliases are applied to the correct methods, and only to them.
+--FILE--
+<?php
+trait T1 {
+ function m1() { echo "T:m1\n"; }
+ function m2() { echo "T:m2\n"; }
+}
+
+class C1 {
+ use T1 { m1 as a1; }
+}
+
+$o = new C1;
+$o->m1();
+$o->a1();
+$o->m2();
+$o->a2();
+
+?>
+--EXPECTF--
+T:m1
+T:m1
+T:m2
+
+Fatal error: Call to undefined method C1::a2() in %s on line %d
diff --git a/Zend/tests/traits/bugs/case-sensitive.phpt b/Zend/tests/traits/bugs/case-sensitive.phpt
new file mode 100644
index 0000000000..13d4188f2f
--- /dev/null
+++ b/Zend/tests/traits/bugs/case-sensitive.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Check for problems with case sensitivity in compositions
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait A {
+ public function M1() {}
+ public function M2() {}
+}
+
+trait B {
+ public function M1() {}
+ public function M2() {}
+}
+
+class MyClass {
+ use A;
+ use B;
+}
+?>
+--EXPECTF--
+Fatal error: Trait method M1 has not been applied, because there are collisions with other trait methods on MyClass in %s on line %d
diff --git a/Zend/tests/traits/bugs/interfaces.phpt b/Zend/tests/traits/bugs/interfaces.phpt
new file mode 100644
index 0000000000..486bda7efb
--- /dev/null
+++ b/Zend/tests/traits/bugs/interfaces.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Make sure trait does not implement an interface.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+interface MyInterface {
+ public function a();
+}
+
+trait THello implements MyInterface {
+ public function a() {
+ echo 'A';
+ }
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use 'MyInterface' as interface on 'THello' since it is a Trait in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/missing-trait.phpt b/Zend/tests/traits/bugs/missing-trait.phpt
new file mode 100644
index 0000000000..ce4fa5c69a
--- /dev/null
+++ b/Zend/tests/traits/bugs/missing-trait.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Check error message for missing traits
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+class TraitsTest {
+ use THello;
+}
+
+$test = new TraitsTest();
+
+?>
+--EXPECTF--
+Fatal error: Trait 'THello' not found in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/overridding-conflicting-methods.phpt b/Zend/tests/traits/bugs/overridding-conflicting-methods.phpt
new file mode 100644
index 0000000000..fc09a367bd
--- /dev/null
+++ b/Zend/tests/traits/bugs/overridding-conflicting-methods.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Overridding Conflicting Methods should not result in a notice/warning about collisions
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello1 {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+trait THello2 {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+class TraitsTest {
+ use THello1;
+ use THello2;
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+$test = new TraitsTest();
+$test->hello();
+?>
+--EXPECTF--
+Hello \ No newline at end of file
diff --git a/Zend/tests/traits/bugs/overridding-conflicting-property-initializer.phpt b/Zend/tests/traits/bugs/overridding-conflicting-property-initializer.phpt
new file mode 100644
index 0000000000..1b9d98dac0
--- /dev/null
+++ b/Zend/tests/traits/bugs/overridding-conflicting-property-initializer.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Properties are considered incompatible if they are different in any of their
+defined characteristics. Thus, initialization values have to be equal, too.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait foo
+{
+ public $zoo = 'foo::zoo';
+}
+
+class baz
+{
+ use foo;
+ public $zoo = 'baz::zoo';
+}
+
+$obj = new baz();
+echo $obj->zoo, "\n";
+?>
+--EXPECTF--
+Fatal error: baz and foo define the same property ($zoo) in the composition of baz. However, the definition differs and is considered incompatible. Class was composed in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/conflict001.phpt b/Zend/tests/traits/conflict001.phpt
new file mode 100644
index 0000000000..32346b3d92
--- /dev/null
+++ b/Zend/tests/traits/conflict001.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Method conflict in traits
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello1 {
+ private function hello() {
+ echo 'Hello';
+ }
+}
+
+trait THello2 {
+ private function hello() {
+ echo 'Hello';
+ }
+}
+
+class TraitsTest {
+ use THello1;
+ use THello2;
+}
+?>
+--EXPECTF--
+Fatal error: Trait method hello has not been applied, because there are collisions with other trait methods on TraitsTest in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/conflict002.phpt b/Zend/tests/traits/conflict002.phpt
new file mode 100644
index 0000000000..64712d40a4
--- /dev/null
+++ b/Zend/tests/traits/conflict002.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Overwridden methods do not cause a conflict.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait HelloWorld {
+ public function sayHello() {
+ echo 'Hello World!';
+ }
+}
+
+trait HelloWorld2 {
+ public function sayHello() {
+ echo 'Hello World2!';
+ }
+}
+
+
+class TheWorldIsNotEnough {
+ use HelloWorld;
+ use HelloWorld2;
+ public function sayHello() {
+ echo 'Hello Universe!';
+ }
+}
+
+$o = new TheWorldIsNotEnough();
+$o->sayHello(); // echos Hello Universe!
+?>
+--EXPECTF--
+Hello Universe! \ No newline at end of file
diff --git a/Zend/tests/traits/conflict003.phpt b/Zend/tests/traits/conflict003.phpt
new file mode 100644
index 0000000000..0e71063f19
--- /dev/null
+++ b/Zend/tests/traits/conflict003.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Two methods resulting in a conflict, should be reported both.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait A {
+ public function smallTalk() {
+ echo 'a';
+ }
+ public function bigTalk() {
+ echo 'A';
+ }
+}
+
+trait B {
+ public function smallTalk() {
+ echo 'b';
+ }
+ public function bigTalk() {
+ echo 'B';
+ }
+}
+
+class Talker {
+ use A, B;
+}
+
+?>
+--EXPECTF--
+Fatal error: Trait method smallTalk has not been applied, because there are collisions with other trait methods on Talker in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/error_001.phpt b/Zend/tests/traits/error_001.phpt
new file mode 100644
index 0000000000..307e5c128a
--- /dev/null
+++ b/Zend/tests/traits/error_001.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Trying to use instanceof for a method twice
+--FILE--
+<?php
+
+trait foo {
+ public function foo() {
+ return 1;
+ }
+}
+
+trait foo2 {
+ public function foo() {
+ return 2;
+ }
+}
+
+
+class A extends foo {
+ use foo {
+ foo2::foo insteadof foo;
+ foo2::foo insteadof foo;
+ }
+}
+
+?>
+--EXPECTF--
+Fatal error: Class A cannot extend from trait foo in %s on line %d
diff --git a/Zend/tests/traits/error_002.phpt b/Zend/tests/traits/error_002.phpt
new file mode 100644
index 0000000000..ac98769f47
--- /dev/null
+++ b/Zend/tests/traits/error_002.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Trying to use an undefined trait
+--FILE--
+<?php
+
+class A {
+ use abc;
+}
+
+?>
+--EXPECTF--
+Fatal error: Trait 'abc' not found in %s on line %d
diff --git a/Zend/tests/traits/error_003.phpt b/Zend/tests/traits/error_003.phpt
new file mode 100644
index 0000000000..5122155bb3
--- /dev/null
+++ b/Zend/tests/traits/error_003.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Trying to use an interface as trait
+--FILE--
+<?php
+
+interface abc {
+}
+
+class A {
+ use abc;
+}
+
+?>
+--EXPECTF--
+Fatal error: A cannot use abc - it is not a trait in %s on line %d
diff --git a/Zend/tests/traits/error_004.phpt b/Zend/tests/traits/error_004.phpt
new file mode 100644
index 0000000000..c7ac916116
--- /dev/null
+++ b/Zend/tests/traits/error_004.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Trying to use a class as trait
+--FILE--
+<?php
+
+class abc {
+}
+
+class A {
+ use abc;
+}
+
+?>
+--EXPECTF--
+Fatal error: A cannot use abc - it is not a trait in %s on line %d
diff --git a/Zend/tests/traits/error_005.phpt b/Zend/tests/traits/error_005.phpt
new file mode 100644
index 0000000000..5aa5e10d95
--- /dev/null
+++ b/Zend/tests/traits/error_005.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Trying to use a final class as trait
+--FILE--
+<?php
+
+final class abc {
+}
+
+class A {
+ use abc;
+}
+
+?>
+--EXPECTF--
+Fatal error: A cannot use abc - it is not a trait in %s on line %d
diff --git a/Zend/tests/traits/error_006.phpt b/Zend/tests/traits/error_006.phpt
new file mode 100644
index 0000000000..0169321936
--- /dev/null
+++ b/Zend/tests/traits/error_006.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Trying to use an abstract class as trait
+--FILE--
+<?php
+
+abstract class abc {
+}
+
+class A {
+ use abc;
+}
+
+?>
+--EXPECTF--
+Fatal error: A cannot use abc - it is not a trait in %s on line %d
diff --git a/Zend/tests/traits/error_007.phpt b/Zend/tests/traits/error_007.phpt
new file mode 100644
index 0000000000..82a6a2e941
--- /dev/null
+++ b/Zend/tests/traits/error_007.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Trying to instantiate a trait
+--FILE--
+<?php
+
+trait abc {
+}
+
+new abc;
+
+?>
+--EXPECTF--
+Fatal error: Cannot instantiate trait abc in %s on line %d
diff --git a/Zend/tests/traits/error_008.phpt b/Zend/tests/traits/error_008.phpt
new file mode 100644
index 0000000000..ee97d756d3
--- /dev/null
+++ b/Zend/tests/traits/error_008.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Trying to implement a trait
+--FILE--
+<?php
+
+trait abc { }
+
+class foo implements abc { }
+
+?>
+--EXPECTF--
+Fatal error: foo cannot implement abc - it is not an interface in %s on line %d
diff --git a/Zend/tests/traits/error_009.phpt b/Zend/tests/traits/error_009.phpt
new file mode 100644
index 0000000000..a1eb6b4134
--- /dev/null
+++ b/Zend/tests/traits/error_009.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Trying to extend a trait
+--FILE--
+<?php
+
+trait abc { }
+
+class foo extends abc { }
+
+?>
+--EXPECTF--
+Fatal error: Class foo cannot extend from trait abc in %s on line %d
diff --git a/Zend/tests/traits/error_010.phpt b/Zend/tests/traits/error_010.phpt
new file mode 100644
index 0000000000..8f3f7dddfd
--- /dev/null
+++ b/Zend/tests/traits/error_010.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Trying to exclude trait method multiple times
+--FILE--
+<?php
+
+trait foo {
+ public function test() { return 3; }
+}
+trait c {
+ public function test() { return 2; }
+}
+
+trait b {
+ public function test() { return 1; }
+}
+
+class bar {
+ use foo, c { c::test insteadof foo, b; }
+ use foo, c { c::test insteadof foo, b; }
+}
+
+$x = new bar;
+var_dump($x->test());
+
+?>
+--EXPECTF--
+Fatal error: Failed to evaluate a trait precedence (test). Method of trait foo was defined to be excluded multiple times in %s on line %d
diff --git a/Zend/tests/traits/error_011.phpt b/Zend/tests/traits/error_011.phpt
new file mode 100644
index 0000000000..2d266dd1ec
--- /dev/null
+++ b/Zend/tests/traits/error_011.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Testing trait collisions
+--FILE--
+<?php
+
+trait foo {
+ public function test() { return 3; }
+}
+trait c {
+ public function test() { return 2; }
+}
+
+trait b {
+ public function test() { return 1; }
+}
+
+class bar {
+ use foo, c, b;
+}
+
+$x = new bar;
+var_dump($x->test());
+
+?>
+--EXPECTF--
+Fatal error: Trait method test has not been applied, because there are collisions with other trait methods on bar in %s on line %d
diff --git a/Zend/tests/traits/error_012.phpt b/Zend/tests/traits/error_012.phpt
new file mode 100644
index 0000000000..b90e32ac84
--- /dev/null
+++ b/Zend/tests/traits/error_012.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Trying to access a protected trait method
+--FILE--
+<?php
+
+trait foo {
+ public function test() { return 3; }
+}
+
+class bar {
+ use foo { test as protected; }
+}
+
+$x = new bar;
+var_dump($x->test());
+
+?>
+--EXPECTF--
+Fatal error: Call to protected method bar::test() from context '' in %s on line %d
diff --git a/Zend/tests/traits/error_013.phpt b/Zend/tests/traits/error_013.phpt
new file mode 100644
index 0000000000..d9fda2d005
--- /dev/null
+++ b/Zend/tests/traits/error_013.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Trying to use static as method modifier
+--FILE--
+<?php
+
+trait foo {
+ public function test() { return 3; }
+}
+
+class bar {
+ use foo { test as static; }
+}
+
+$x = new bar;
+var_dump($x->test());
+
+?>
+--EXPECTF--
+Fatal error: Cannot use 'static' as method modifier in %s on line %d
diff --git a/Zend/tests/traits/error_014.phpt b/Zend/tests/traits/error_014.phpt
new file mode 100644
index 0000000000..be1c91977c
--- /dev/null
+++ b/Zend/tests/traits/error_014.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Trying to override final method
+--FILE--
+<?php
+
+trait foo {
+ public function test() { return 3; }
+}
+
+class baz {
+ final public function test() { return 4; }
+}
+
+class bar extends baz {
+ use foo { test as public; }
+}
+
+$x = new bar;
+var_dump($x->test());
+
+?>
+--EXPECTF--
+Fatal error: Cannot override final method baz::test() in %s on line %d
diff --git a/Zend/tests/traits/error_015.phpt b/Zend/tests/traits/error_015.phpt
new file mode 100644
index 0000000000..efcffea5f3
--- /dev/null
+++ b/Zend/tests/traits/error_015.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Trying to add an alias to a trait method where there is another with same name.
+Should warn about the conflict.
+--FILE--
+<?php
+
+trait foo {
+ public function test() { return 3; }
+}
+
+trait baz {
+ public function test() { return 4; }
+}
+
+class bar {
+ use foo, baz {
+ baz::test as zzz;
+ }
+}
+
+$x = new bar;
+var_dump($x->test());
+
+?>
+--EXPECTF--
+Fatal error: Trait method test has not been applied, because there are collisions with other trait methods on bar in %s on line %d
diff --git a/Zend/tests/traits/error_016.phpt b/Zend/tests/traits/error_016.phpt
new file mode 100644
index 0000000000..65a3a83485
--- /dev/null
+++ b/Zend/tests/traits/error_016.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Trying to create a constant on Trait
+--FILE--
+<?php
+
+trait foo {
+ const a = 1;
+}
+
+?>
+--EXPECTF--
+Fatal error: Traits cannot have constants in %s on line %d
diff --git a/Zend/tests/traits/flattening001.phpt b/Zend/tests/traits/flattening001.phpt
new file mode 100644
index 0000000000..aa7f03dcb8
--- /dev/null
+++ b/Zend/tests/traits/flattening001.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Methods using object properties
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait T1 {
+ public function getText() {
+ return $this->text;
+ }
+}
+
+trait T2 {
+ public function setTextT2($val) {
+ $this->text = $val;
+ }
+}
+
+class TraitsTest {
+ use T1;
+ use T2;
+ private $text = 'test';
+ public function setText($val) {
+ $this->text = $val;
+ }
+}
+
+$o = new TraitsTest();
+var_dump($o->getText());
+
+$o->setText('foo');
+
+var_dump($o->getText());
+
+$o->setText('bar');
+
+var_dump($o->getText());
+?>
+--EXPECTF--
+string(4) "test"
+string(3) "foo"
+string(3) "bar" \ No newline at end of file
diff --git a/Zend/tests/traits/flattening002.phpt b/Zend/tests/traits/flattening002.phpt
new file mode 100644
index 0000000000..251af29711
--- /dev/null
+++ b/Zend/tests/traits/flattening002.phpt
@@ -0,0 +1,28 @@
+--TEST--
+parent:: works like in a method defined without traits.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+class Base {
+ public function sayHello() {
+ echo 'Hello ';
+ }
+}
+
+trait SayWorld {
+ public function sayHello() {
+ parent::sayHello();
+ echo 'World!';
+ }
+}
+
+class MyHelloWorld extends Base {
+ use SayWorld;
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+?>
+--EXPECTF--
+Hello World! \ No newline at end of file
diff --git a/Zend/tests/traits/flattening003.phpt b/Zend/tests/traits/flattening003.phpt
new file mode 100644
index 0000000000..d189ca70c1
--- /dev/null
+++ b/Zend/tests/traits/flattening003.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Traits are flattened recurivly.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function sayHello() {
+ echo 'Hello ';
+ }
+}
+
+trait World {
+ public function sayWorld() {
+ echo 'World!';
+ }
+}
+
+trait HelloWorld {
+ use Hello, World;
+}
+
+class MyHelloWorld {
+ use HelloWorld;
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+$o->sayWorld();
+?>
+--EXPECTF--
+Hello World! \ No newline at end of file
diff --git a/Zend/tests/traits/get_declared_traits_001.phpt b/Zend/tests/traits/get_declared_traits_001.phpt
new file mode 100644
index 0000000000..91f6b3d20a
--- /dev/null
+++ b/Zend/tests/traits/get_declared_traits_001.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Testing get_declared_traits()
+--FILE--
+<?php
+
+class a { }
+interface b { }
+trait c { }
+abstract class d { }
+final class e { }
+
+var_dump(get_declared_traits());
+
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ string(1) "c"
+}
diff --git a/Zend/tests/traits/get_declared_traits_002.phpt b/Zend/tests/traits/get_declared_traits_002.phpt
new file mode 100644
index 0000000000..74fdcc4082
--- /dev/null
+++ b/Zend/tests/traits/get_declared_traits_002.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Testing get_declared_traits() inside namespace
+--FILE--
+<?php
+
+namespace test {
+ class a { }
+ interface b { }
+ trait c { }
+ abstract class d { }
+ final class e { }
+ var_dump(get_declared_traits());
+}
+
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ string(6) "test\c"
+}
diff --git a/Zend/tests/traits/get_declared_traits_003.phpt b/Zend/tests/traits/get_declared_traits_003.phpt
new file mode 100644
index 0000000000..4a687467f2
--- /dev/null
+++ b/Zend/tests/traits/get_declared_traits_003.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Testing get_declared_classes() and get_declared_traits()
+--FILE--
+<?php
+
+class a { }
+interface b { }
+trait c { }
+abstract class d { }
+final class e { }
+var_dump(get_declared_classes());
+var_dump(get_declared_traits());
+
+?>
+--EXPECTF--
+%astring(1) "a"
+ [%d]=>
+ string(1) "d"
+ [%d]=>
+ string(1) "e"
+}
+array(1) {
+ [0]=>
+ string(1) "c"
+}
diff --git a/Zend/tests/traits/inheritance001.phpt b/Zend/tests/traits/inheritance001.phpt
new file mode 100644
index 0000000000..e8195c4749
--- /dev/null
+++ b/Zend/tests/traits/inheritance001.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Trait method overwridden by a method defined in the class.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait HelloWorld {
+ public function sayHello() {
+ echo 'Hello World!';
+ }
+}
+
+class TheWorldIsNotEnough {
+ use HelloWorld;
+ public function sayHello() {
+ echo 'Hello Universe!';
+ }
+}
+
+$o = new TheWorldIsNotEnough();
+$o->sayHello(); // echos Hello Universe!
+?>
+--EXPECTF--
+Hello Universe! \ No newline at end of file
diff --git a/Zend/tests/traits/inheritance002.phpt b/Zend/tests/traits/inheritance002.phpt
new file mode 100644
index 0000000000..51badc5a4c
--- /dev/null
+++ b/Zend/tests/traits/inheritance002.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Trait method overriddes base class method
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+class Base {
+ public function sayHello() {
+ echo 'Hello ';
+ }
+}
+
+trait SayWorld {
+ public function sayHello() {
+ echo 'World!';
+ }
+}
+
+class MyHelloWorld extends Base {
+ use SayWorld;
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+?>
+--EXPECTF--
+World! \ No newline at end of file
diff --git a/Zend/tests/traits/inheritance003.phpt b/Zend/tests/traits/inheritance003.phpt
new file mode 100644
index 0000000000..a41c4e484a
--- /dev/null
+++ b/Zend/tests/traits/inheritance003.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Trait method overrides base class method and satisfies prototype
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+abstract class Base {
+ public abstract function sayHello(array $a);
+}
+
+class SubClass extends Base {
+ public function sayHello(array $a) {
+ echo "World!\n";
+ }
+}
+
+$s = new SubClass();
+$s->sayHello(array());
+
+
+trait SayWorld {
+ public function sayHello(Base $d) {
+ echo 'World!';
+ }
+}
+
+class MyHelloWorld extends Base {
+ use SayWorld;
+}
+
+$o = new MyHelloWorld();
+$o->sayHello(array());
+
+?>
+--EXPECTF--
+World!
+
+Fatal error: Declaration of MyHelloWorld::sayHello() must be compatible with Base::sayHello(array $a) in %s on line %d
diff --git a/Zend/tests/traits/interface_001.phpt b/Zend/tests/traits/interface_001.phpt
new file mode 100644
index 0000000000..a14f78efc8
--- /dev/null
+++ b/Zend/tests/traits/interface_001.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Using traits to implement interface
+--FILE--
+<?php
+
+trait foo {
+ public function abc() {
+ }
+}
+
+interface baz {
+ public function abc();
+}
+
+class bar implements baz {
+ use foo;
+
+}
+
+new bar;
+print "OK\n";
+
+?>
+--EXPECT--
+OK
diff --git a/Zend/tests/traits/interface_002.phpt b/Zend/tests/traits/interface_002.phpt
new file mode 100644
index 0000000000..462d73fbd6
--- /dev/null
+++ b/Zend/tests/traits/interface_002.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Checking error message when the trait doesn't implements the interface
+--FILE--
+<?php
+
+trait foo {
+ public function a() {
+ }
+}
+
+interface baz {
+ public function abc();
+}
+
+class bar implements baz {
+ use foo;
+
+}
+
+new bar;
+
+?>
+--EXPECTF--
+Fatal error: Class bar contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (baz::abc) in %s on line %d
diff --git a/Zend/tests/traits/interface_003.phpt b/Zend/tests/traits/interface_003.phpt
new file mode 100644
index 0000000000..aa13bd8b59
--- /dev/null
+++ b/Zend/tests/traits/interface_003.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Testing to implement Serializable interface by traits
+--FILE--
+<?php
+
+trait foo {
+ public function serialize() {
+ return 'foobar';
+ }
+ public function unserialize($x) {
+ var_dump($x);
+ }
+}
+
+class bar implements Serializable {
+ use foo;
+}
+
+var_dump($o = serialize(new bar));
+var_dump(unserialize($o));
+
+?>
+--EXPECTF--
+string(20) "C:3:"bar":6:{foobar}"
+string(6) "foobar"
+object(bar)#%d (0) {
+}
diff --git a/Zend/tests/traits/language001.phpt b/Zend/tests/traits/language001.phpt
new file mode 100644
index 0000000000..d892112416
--- /dev/null
+++ b/Zend/tests/traits/language001.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Single Trait with simple trait method
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+class TraitsTest {
+ use THello;
+}
+
+$test = new TraitsTest();
+$test->hello();
+?>
+--EXPECTF--
+Hello
diff --git a/Zend/tests/traits/language002.phpt b/Zend/tests/traits/language002.phpt
new file mode 100644
index 0000000000..d093f2952d
--- /dev/null
+++ b/Zend/tests/traits/language002.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Use multiple traits.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function sayHello() {
+ echo 'Hello ';
+ }
+}
+
+trait World {
+ public function sayWorld() {
+ echo 'World';
+ }
+}
+
+class MyHelloWorld {
+ use Hello, World;
+ public function sayExclamationMark() {
+ echo '!';
+ }
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+$o->sayWorld();
+$o->sayExclamationMark();
+?>
+--EXPECTF--
+Hello World! \ No newline at end of file
diff --git a/Zend/tests/traits/language003.phpt b/Zend/tests/traits/language003.phpt
new file mode 100644
index 0000000000..77d4429f43
--- /dev/null
+++ b/Zend/tests/traits/language003.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Use instead to solve a conflict.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function saySomething() {
+ echo 'Hello';
+ }
+}
+
+trait World {
+ public function saySomething() {
+ echo 'World';
+ }
+}
+
+class MyHelloWorld {
+ use Hello, World {
+ Hello::saySomething insteadof World;
+ }
+}
+
+$o = new MyHelloWorld();
+$o->saySomething();
+?>
+--EXPECTF--
+Hello \ No newline at end of file
diff --git a/Zend/tests/traits/language004.phpt b/Zend/tests/traits/language004.phpt
new file mode 100644
index 0000000000..4df307ab8d
--- /dev/null
+++ b/Zend/tests/traits/language004.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Use instead to solve a conflict and as to access the method.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function saySomething() {
+ echo 'Hello';
+ }
+}
+
+trait World {
+ public function saySomething() {
+ echo ' World';
+ }
+}
+
+class MyHelloWorld {
+ use Hello, World {
+ Hello::saySomething insteadof World;
+ World::saySomething as sayWorld;
+ }
+}
+
+$o = new MyHelloWorld();
+$o->saySomething();
+$o->sayWorld();
+?>
+--EXPECTF--
+Hello World \ No newline at end of file
diff --git a/Zend/tests/traits/language005.phpt b/Zend/tests/traits/language005.phpt
new file mode 100644
index 0000000000..20eaeb35c2
--- /dev/null
+++ b/Zend/tests/traits/language005.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Use instead to solve a conflict and as to access the method.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait A {
+ public function smallTalk() {
+ echo 'a';
+ }
+ public function bigTalk() {
+ echo 'A';
+ }
+}
+
+trait B {
+ public function smallTalk() {
+ echo 'b';
+ }
+ public function bigTalk() {
+ echo 'B';
+ }
+}
+
+class Talker {
+ use A, B {
+ B::smallTalk insteadof A;
+ A::bigTalk insteadof B;
+ B::bigTalk as talk;
+ }
+}
+
+$t = new Talker;
+$t->smallTalk();
+$t->bigTalk();
+$t->talk();
+
+?>
+--EXPECTF--
+bAB \ No newline at end of file
diff --git a/Zend/tests/traits/language006.phpt b/Zend/tests/traits/language006.phpt
new file mode 100644
index 0000000000..5a32359bb5
--- /dev/null
+++ b/Zend/tests/traits/language006.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Express requirements of a trait by abstract methods.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function sayHelloWorld() {
+ echo 'Hello'.$this->getWorld();
+ }
+ abstract public function getWorld();
+ }
+
+class MyHelloWorld {
+ private $world;
+ use Hello;
+ public function getWorld() {
+ return $this->world;
+ }
+ public function setWorld($val) {
+ $this->world = $val;
+ }
+}
+
+$o = new MyHelloWorld();
+$o->setWorld(' World!');
+$o->sayHelloWorld();
+
+?>
+--EXPECTF--
+Hello World! \ No newline at end of file
diff --git a/Zend/tests/traits/language007.phpt b/Zend/tests/traits/language007.phpt
new file mode 100644
index 0000000000..3b65d0123a
--- /dev/null
+++ b/Zend/tests/traits/language007.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Traits can fulfill the requirements of abstract base classes.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+abstract class Base {
+ abstract function sayWorld();
+}
+
+trait Hello {
+ public function sayHello() {
+ echo 'Hello';
+ }
+ public function sayWorld() {
+ echo ' World!';
+ }
+ }
+
+class MyHelloWorld extends Base {
+ use Hello;
+}
+
+$o = new MyHelloWorld();
+$o->sayHello();
+$o->sayWorld();
+
+?>
+--EXPECTF--
+Hello World! \ No newline at end of file
diff --git a/Zend/tests/traits/language008a.phpt b/Zend/tests/traits/language008a.phpt
new file mode 100644
index 0000000000..5a12a4e74b
--- /dev/null
+++ b/Zend/tests/traits/language008a.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Visibility can be changed with the as aliasing construct as well.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait HelloWorld {
+ public function sayHello() {
+ echo 'Hello World!';
+ }
+}
+
+class MyClass {
+ use HelloWorld { sayHello as protected; }
+}
+
+
+$o = new MyClass;
+$o->sayHello();
+
+?>
+--EXPECTF--
+Fatal error: Call to protected method MyClass::sayHello() from context '' in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/language008b.phpt b/Zend/tests/traits/language008b.phpt
new file mode 100644
index 0000000000..9abbdbeb0d
--- /dev/null
+++ b/Zend/tests/traits/language008b.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Visibility can be changed with the as aliasing construct as well.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait HelloWorld {
+ public function sayHello() {
+ echo 'Hello World!';
+ }
+}
+
+class MyClass {
+ use HelloWorld { sayHello as private sayHelloWorld; }
+
+ public function callPrivateAlias() {
+ $this->sayHelloWorld();
+ }
+}
+
+$o = new MyClass();
+$o->sayHello();
+$o->callPrivateAlias();
+$o->sayHelloWorld();
+
+
+?>
+--EXPECTF--
+Hello World!Hello World!
+Fatal error: Call to private method MyClass::sayHelloWorld() from context '' in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/language009.phpt b/Zend/tests/traits/language009.phpt
new file mode 100644
index 0000000000..e55c8d84aa
--- /dev/null
+++ b/Zend/tests/traits/language009.phpt
@@ -0,0 +1,36 @@
+--TEST--
+In instead definitions all trait whose methods are meant to be hidden can be listed.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait A {
+ public function foo() {
+ echo 'a';
+ }
+}
+
+trait B {
+ public function foo() {
+ echo 'b';
+ }
+}
+
+trait C {
+ public function foo() {
+ echo 'c';
+ }
+}
+
+class MyClass {
+ use C, A, B {
+ B::foo insteadof A, C;
+ }
+}
+
+$t = new MyClass;
+$t->foo();
+
+?>
+--EXPECTF--
+b \ No newline at end of file
diff --git a/Zend/tests/traits/language010.phpt b/Zend/tests/traits/language010.phpt
new file mode 100644
index 0000000000..e550abb7bc
--- /dev/null
+++ b/Zend/tests/traits/language010.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Aliasing leading to conflict should result in error message
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function hello() {
+ echo 'Hello';
+ }
+}
+
+trait World {
+ public function world() {
+ echo ' World!';
+ }
+}
+
+
+class MyClass {
+ use Hello, World { hello as world; }
+}
+
+$o = new MyClass();
+$o->hello();
+$o->world();
+
+?>
+--EXPECTF--
+Fatal error: Trait method world has not been applied, because there are collisions with other trait methods on MyClass in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/language011.phpt b/Zend/tests/traits/language011.phpt
new file mode 100644
index 0000000000..585699da55
--- /dev/null
+++ b/Zend/tests/traits/language011.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Aliasing on conflicting method should not cover up conflict.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Hello {
+ public function sayHello() {
+ echo 'Hello';
+ }
+}
+
+trait World {
+ public function sayHello() {
+ echo ' World!';
+ }
+}
+
+
+class MyClass {
+ use Hello, World { sayHello as sayWorld; }
+}
+
+$o = new MyClass();
+$o->sayHello();
+$o->sayWorld();
+
+?>
+--EXPECTF--
+Fatal error: Trait method sayHello has not been applied, because there are collisions with other trait methods on MyClass in %s on line %d
diff --git a/Zend/tests/traits/language012.phpt b/Zend/tests/traits/language012.phpt
new file mode 100644
index 0000000000..481dd64ec7
--- /dev/null
+++ b/Zend/tests/traits/language012.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Statics should work in traits, too.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Counter {
+ public function inc() {
+ static $c = 0;
+ $c = $c + 1;
+ echo "$c\n";
+ }
+}
+
+
+class C1 {
+ use Counter;
+}
+
+$o = new C1();
+$o->inc();
+$o->inc();
+
+?>
+--EXPECTF--
+1
+2
diff --git a/Zend/tests/traits/language013.phpt b/Zend/tests/traits/language013.phpt
new file mode 100644
index 0000000000..a55cbbed34
--- /dev/null
+++ b/Zend/tests/traits/language013.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Statics work like expected for language-based copy'n'paste. No link between methods from the same trait.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Counter {
+ public function inc() {
+ static $c = 0;
+ $c = $c + 1;
+ echo "$c\n";
+ }
+}
+
+
+class C1 {
+ use Counter;
+}
+
+class C2 {
+ use Counter;
+}
+
+$o = new C1();
+$o->inc();
+$o->inc();
+
+$p = new C2();
+$p->inc();
+$p->inc();
+
+?>
+--EXPECTF--
+1
+2
+1
+2
diff --git a/Zend/tests/traits/methods_001.phpt b/Zend/tests/traits/methods_001.phpt
new file mode 100644
index 0000000000..e1ee8152a6
--- /dev/null
+++ b/Zend/tests/traits/methods_001.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Testing magic method on trait
+--FILE--
+<?php
+
+trait foo {
+ public function __toString() {
+ return '123';
+ }
+
+ public function __get($x) {
+ var_dump($x);
+ }
+
+ public function __set($attr, $val) {
+ var_dump($attr .'==='. $val);
+ }
+
+ public function __clone() {
+ var_dump(__FUNCTION__);
+ }
+}
+
+class bar {
+ use foo;
+}
+
+$o = new bar;
+echo $o, PHP_EOL;
+$o->xyz;
+$o->xyz = 2;
+clone $o;
+
+?>
+--EXPECT--
+123
+string(3) "xyz"
+string(7) "xyz===2"
+string(7) "__clone"
diff --git a/Zend/tests/traits/methods_002.phpt b/Zend/tests/traits/methods_002.phpt
new file mode 100644
index 0000000000..4ed64c1a55
--- /dev/null
+++ b/Zend/tests/traits/methods_002.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Testing collision with magic methods
+--FILE--
+<?php
+
+trait foo {
+ public function __clone() {
+ var_dump(__FUNCTION__);
+ }
+}
+
+trait baz {
+ public function __clone() {
+ var_dump(__FUNCTION__);
+ }
+}
+
+class bar {
+ use foo;
+ use baz;
+}
+
+$o = new bar;
+var_dump(clone $o);
+
+?>
+--EXPECTF--
+Fatal error: Trait method __clone has not been applied, because there are collisions with other trait methods on bar in %s on line %d
diff --git a/Zend/tests/traits/methods_003.phpt b/Zend/tests/traits/methods_003.phpt
new file mode 100644
index 0000000000..1c1218ae3a
--- /dev/null
+++ b/Zend/tests/traits/methods_003.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Testing __construct and __destruct with Trait
+--FILE--
+<?php
+
+trait foo {
+ public function __construct() {
+ var_dump(__FUNCTION__);
+ }
+ public function __destruct() {
+ var_dump(__FUNCTION__);
+ }
+}
+
+class bar {
+ use foo;
+}
+
+new bar;
+
+?>
+--EXPECT--
+string(11) "__construct"
+string(10) "__destruct"
diff --git a/Zend/tests/traits/noctor001.phpt b/Zend/tests/traits/noctor001.phpt
new file mode 100644
index 0000000000..d15acff87a
--- /dev/null
+++ b/Zend/tests/traits/noctor001.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Don't mark trait methods as constructor
+--FILE--
+<?php
+trait Foo {
+ public function Foo() {
+ }
+}
+
+class Bar {
+ use Foo;
+ public function Bar() {
+ }
+}
+
+$rfoofoo = new ReflectionMethod('Foo::Foo');
+var_dump($rfoofoo->isConstructor());
+
+$rbarfoo = new ReflectionMethod('Bar::Foo');
+var_dump($rbarfoo->isConstructor());
+
+$rbarbar = new ReflectionMethod('Bar::Bar');
+var_dump($rbarbar->isConstructor());
+?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(true)
diff --git a/Zend/tests/traits/property001.phpt b/Zend/tests/traits/property001.phpt
new file mode 100644
index 0000000000..d5e4ddc617
--- /dev/null
+++ b/Zend/tests/traits/property001.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Potentially conflicting properties should result in a strict notice. Property use is discorage for traits that are supposed to enable maintainable code reuse. Accessor methods are the language supported idiom for this.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello1 {
+ private $foo;
+}
+
+trait THello2 {
+ private $foo;
+}
+
+echo "PRE-CLASS-GUARD-TraitsTest\n";
+error_reporting(E_ALL & ~E_STRICT); // ensuring that it is only for E_STRICT
+
+class TraitsTest {
+ use THello1;
+ use THello2;
+}
+
+error_reporting(E_ALL | E_STRICT);
+
+echo "PRE-CLASS-GUARD-TraitsTest2\n";
+
+class TraitsTest2 {
+ use THello1;
+ use THello2;
+}
+
+var_dump(property_exists('TraitsTest', 'foo'));
+var_dump(property_exists('TraitsTest2', 'foo'));
+?>
+--EXPECTF--
+PRE-CLASS-GUARD-TraitsTest
+PRE-CLASS-GUARD-TraitsTest2
+
+Strict Standards: THello1 and THello2 define the same property ($foo) in the composition of TraitsTest2. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+bool(true)
+bool(true) \ No newline at end of file
diff --git a/Zend/tests/traits/property002.phpt b/Zend/tests/traits/property002.phpt
new file mode 100644
index 0000000000..27361e04d2
--- /dev/null
+++ b/Zend/tests/traits/property002.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Non-conflicting properties should work just fine.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello1 {
+ public $hello = "hello";
+}
+
+trait THello2 {
+ private $world = "World!";
+}
+
+class TraitsTest {
+ use THello1;
+ use THello2;
+ function test() {
+ echo $this->hello . ' ' . $this->world;
+ }
+}
+
+var_dump(property_exists('TraitsTest', 'hello'));
+var_dump(property_exists('TraitsTest', 'world'));
+
+$t = new TraitsTest;
+$t->test();
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+hello World! \ No newline at end of file
diff --git a/Zend/tests/traits/property003.phpt b/Zend/tests/traits/property003.phpt
new file mode 100644
index 0000000000..b4f0105d20
--- /dev/null
+++ b/Zend/tests/traits/property003.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Conflicting properties with different visibility modifiers should result in a fatal error, since this indicates that the code is incompatible.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello1 {
+ public $hello;
+}
+
+trait THello2 {
+ private $hello;
+}
+
+echo "PRE-CLASS-GUARD\n";
+
+class TraitsTest {
+ use THello1;
+ use THello2;
+}
+
+echo "POST-CLASS-GUARD\n";
+
+$t = new TraitsTest;
+$t->hello = "foo";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Fatal error: THello1 and THello2 define the same property ($hello) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/property004.phpt b/Zend/tests/traits/property004.phpt
new file mode 100644
index 0000000000..393b492b7f
--- /dev/null
+++ b/Zend/tests/traits/property004.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Conflicting properties with different initial values are considered incompatible.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait THello1 {
+ public $hello = "foo";
+}
+
+trait THello2 {
+ private $hello = "bar";
+}
+
+echo "PRE-CLASS-GUARD\n";
+
+class TraitsTest {
+ use THello1;
+ use THello2;
+ public function getHello() {
+ return $this->hello;
+ }
+}
+
+$t = new TraitsTest;
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Fatal error: THello1 and THello2 define the same property ($hello) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d \ No newline at end of file
diff --git a/Zend/tests/traits/property005.phpt b/Zend/tests/traits/property005.phpt
new file mode 100644
index 0000000000..899a332acc
--- /dev/null
+++ b/Zend/tests/traits/property005.phpt
@@ -0,0 +1,40 @@
+--TEST--
+The same rules are applied for properties that are defined in the class hierarchy. Thus, if the properties are compatible, a notice is issued, if not a fatal error occures.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+ private $hello;
+}
+
+trait THello1 {
+ private $hello;
+}
+
+echo "PRE-CLASS-GUARD\n";
+class Notice extends Base {
+ use THello1;
+ private $hello;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now we do the test for a fatal error
+
+class TraitsTest {
+ use THello1;
+ public $hello;
+}
+
+echo "POST-CLASS-GUARD2\n";
+
+$t = new TraitsTest;
+$t->hello = "foo";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD
+
+Fatal error: TraitsTest and THello1 define the same property ($hello) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d
diff --git a/Zend/tests/traits/property006.phpt b/Zend/tests/traits/property006.phpt
new file mode 100644
index 0000000000..1a709199a9
--- /dev/null
+++ b/Zend/tests/traits/property006.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+ private $hello;
+}
+
+trait THello1 {
+ private $hello;
+}
+
+// Now we use the trait, which happens to introduce another private variable
+// but they are distinct, and not related to each other, so no warning.
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassNoNotice extends Base {
+ use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself,
+// that should give the expected strict warning.
+
+class Notice extends Base {
+ use THello1;
+ private $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2
diff --git a/Zend/tests/traits/property007.phpt b/Zend/tests/traits/property007.phpt
new file mode 100644
index 0000000000..0f7c3b3948
--- /dev/null
+++ b/Zend/tests/traits/property007.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Introducing new private variables of the same name in a subclass is ok, and does not lead to any output. That is consitent with normal inheritance handling.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class Base {
+ protected $hello;
+}
+
+trait THello1 {
+ protected $hello;
+}
+
+// Protected and public are handle more strict with a warning then what is
+// expected from normal inheritance since they can have easier coliding semantics
+echo "PRE-CLASS-GUARD\n";
+class SameNameInSubClassProducesNotice extends Base {
+ use THello1;
+}
+echo "POST-CLASS-GUARD\n";
+
+// now the same with a class that defines the property itself, too.
+
+class Notice extends Base {
+ use THello1;
+ protected $hello;
+}
+echo "POST-CLASS-GUARD2\n";
+?>
+--EXPECTF--
+PRE-CLASS-GUARD
+
+Strict Standards: Base and THello1 define the same property ($hello) in the composition of SameNameInSubClassProducesNotice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD
+
+Strict Standards: Notice and THello1 define the same property ($hello) in the composition of Notice. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+POST-CLASS-GUARD2
diff --git a/Zend/tests/traits/property008.phpt b/Zend/tests/traits/property008.phpt
new file mode 100644
index 0000000000..e263692d60
--- /dev/null
+++ b/Zend/tests/traits/property008.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Handling of private fields with traits needs to have same semantics as with normal inheritance.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+ private $hello = 0;
+}
+
+// This is how privates are handled in normal inheritance
+class SubclassClassicInheritance extends BaseWithPropA {
+ private $hello = 0;
+}
+
+// And here, we need to make sure, that the traits behave the same
+
+trait AHelloProperty {
+ private $hello = 0;
+}
+
+class BaseWithTPropB {
+ use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+ use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+ use AHelloProperty;
+}
+
+$classic = new SubclassClassicInheritance;
+var_dump($classic);
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+object(SubclassClassicInheritance)#1 (2) {
+ ["hello":"SubclassClassicInheritance":private]=>
+ int(0)
+ ["hello":"BaseWithPropA":private]=>
+ int(0)
+}
+object(SubclassA)#2 (2) {
+ ["hello":"SubclassA":private]=>
+ int(0)
+ ["hello":"BaseWithPropA":private]=>
+ int(0)
+}
+object(SubclassB)#3 (2) {
+ ["hello":"SubclassB":private]=>
+ int(0)
+ ["hello":"BaseWithTPropB":private]=>
+ int(0)
+} \ No newline at end of file
diff --git a/Zend/tests/traits/property009.phpt b/Zend/tests/traits/property009.phpt
new file mode 100644
index 0000000000..135129d31f
--- /dev/null
+++ b/Zend/tests/traits/property009.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Handling of public fields with traits needs to have same semantics as with normal inheritance, however, we do add strict warnings since it is easier to run into something unexpeted with changing traits.
+--FILE--
+<?php
+error_reporting(E_ALL | E_STRICT);
+
+class BaseWithPropA {
+ public $hello = 0;
+}
+
+// This is how publics are handled in normal inheritance
+class SubclassClassicInheritance extends BaseWithPropA {
+ public $hello = 0;
+}
+
+// And here, we need to make sure, that the traits behave the same
+
+trait AHelloProperty {
+ public $hello = 0;
+}
+
+class BaseWithTPropB {
+ use AHelloProperty;
+}
+
+class SubclassA extends BaseWithPropA {
+ use AHelloProperty;
+}
+
+class SubclassB extends BaseWithTPropB {
+ use AHelloProperty;
+}
+
+$classic = new SubclassClassicInheritance;
+var_dump($classic);
+
+$a = new SubclassA;
+var_dump($a);
+
+$b = new SubclassB;
+var_dump($b);
+
+?>
+--EXPECTF--
+Strict Standards: BaseWithPropA and AHelloProperty define the same property ($hello) in the composition of SubclassA. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+
+Strict Standards: BaseWithTPropB and AHelloProperty define the same property ($hello) in the composition of SubclassB. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed in %s on line %d
+object(SubclassClassicInheritance)#1 (1) {
+ ["hello"]=>
+ int(0)
+}
+object(SubclassA)#2 (1) {
+ ["hello"]=>
+ int(0)
+}
+object(SubclassB)#3 (1) {
+ ["hello"]=>
+ int(0)
+} \ No newline at end of file
diff --git a/Zend/tests/traits/static_001.phpt b/Zend/tests/traits/static_001.phpt
new file mode 100644
index 0000000000..d86cb851b9
--- /dev/null
+++ b/Zend/tests/traits/static_001.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Traits with static methods.
+--CREDITS--
+Simas Toleikis simast@gmail.com
+--FILE--
+<?php
+
+ trait TestTrait {
+ public static function test() {
+ return 'Test';
+ }
+ }
+
+ class A {
+ use TestTrait;
+ }
+
+ echo A::test();
+
+?>
+--EXPECT--
+Test \ No newline at end of file
diff --git a/Zend/tests/traits/static_002.phpt b/Zend/tests/traits/static_002.phpt
new file mode 100644
index 0000000000..c076085519
--- /dev/null
+++ b/Zend/tests/traits/static_002.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Traits with static methods referenced using variable.
+--CREDITS--
+Simas Toleikis simast@gmail.com
+--FILE--
+<?php
+
+ trait TestTrait {
+ public static function test() {
+ return 'Test';
+ }
+ }
+
+ class A {
+ use TestTrait;
+ }
+
+ $class = "A";
+ echo $class::test();
+
+?>
+--EXPECT--
+Test \ No newline at end of file
diff --git a/Zend/tests/traits/static_003.phpt b/Zend/tests/traits/static_003.phpt
new file mode 100644
index 0000000000..fbe5421c71
--- /dev/null
+++ b/Zend/tests/traits/static_003.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Traits with late static bindings.
+--CREDITS--
+Simas Toleikis simast@gmail.com
+--FILE--
+<?php
+
+ trait TestTrait {
+ public static function test() {
+ return static::$test;
+ }
+ }
+
+ class A {
+ use TestTrait;
+ protected static $test = "Test A";
+ }
+
+ class B extends A {
+ protected static $test = "Test B";
+ }
+
+ echo B::test();
+
+?>
+--EXPECT--
+Test B \ No newline at end of file
diff --git a/Zend/tests/traits/static_004.phpt b/Zend/tests/traits/static_004.phpt
new file mode 100644
index 0000000000..c360f457f0
--- /dev/null
+++ b/Zend/tests/traits/static_004.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Traits with __callStatic magic method.
+--CREDITS--
+Simas Toleikis simast@gmail.com
+--FILE--
+<?php
+
+ trait TestTrait {
+ public static function __callStatic($name, $arguments) {
+ return $name;
+ }
+ }
+
+ class A {
+ use TestTrait;
+ }
+
+ echo A::Test();
+
+?>
+--EXPECT--
+Test \ No newline at end of file
diff --git a/Zend/tests/traits/static_forward_static_call.phpt b/Zend/tests/traits/static_forward_static_call.phpt
new file mode 100644
index 0000000000..878cf1fcc1
--- /dev/null
+++ b/Zend/tests/traits/static_forward_static_call.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Traits and forward_static_call().
+--CREDITS--
+Simas Toleikis simast@gmail.com
+--FILE--
+<?php
+
+ trait TestTrait {
+ public static function test() {
+ return 'Forwarded '.forward_static_call(array('A', 'test'));
+ }
+ }
+
+ class A {
+ public static function test() {
+ return "Test A";
+ }
+ }
+
+ class B extends A {
+ use TestTrait;
+ }
+
+ echo B::test();
+
+?>
+--EXPECT--
+Forwarded Test A \ No newline at end of file
diff --git a/Zend/tests/traits/static_get_called_class.phpt b/Zend/tests/traits/static_get_called_class.phpt
new file mode 100644
index 0000000000..dc29ecefa2
--- /dev/null
+++ b/Zend/tests/traits/static_get_called_class.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Traits and get_called_class().
+--CREDITS--
+Simas Toleikis simast@gmail.com
+--FILE--
+<?php
+
+ trait TestTrait {
+ public static function test() {
+ return get_called_class();
+ }
+ }
+
+ class A {
+ use TestTrait;
+ }
+
+ class B extends A { }
+
+ echo B::test();
+
+?>
+--EXPECT--
+B \ No newline at end of file
diff --git a/Zend/tests/traits/trait_constant_001.phpt b/Zend/tests/traits/trait_constant_001.phpt
new file mode 100644
index 0000000000..0fd8ff921b
--- /dev/null
+++ b/Zend/tests/traits/trait_constant_001.phpt
@@ -0,0 +1,36 @@
+--TEST--
+__TRAIT__: Basics, a constant denoiting the trait of definition.
+--FILE--
+<?php
+
+trait TestTrait {
+ public static function test() {
+ return __TRAIT__;
+ }
+}
+
+class Direct {
+ use TestTrait;
+}
+
+class IndirectInheritance extends Direct {
+
+}
+
+trait TestTraitIndirect {
+ use TestTrait;
+}
+
+class Indirect {
+ use TestTraitIndirect;
+}
+
+echo Direct::test()."\n";
+echo IndirectInheritance::test()."\n";
+echo Indirect::test()."\n";
+
+?>
+--EXPECT--
+TestTrait
+TestTrait
+TestTrait
diff --git a/Zend/tests/traits/trait_constant_002.phpt b/Zend/tests/traits/trait_constant_002.phpt
new file mode 100644
index 0000000000..327dd44a64
--- /dev/null
+++ b/Zend/tests/traits/trait_constant_002.phpt
@@ -0,0 +1,27 @@
+--TEST--
+__TRAIT__: Use outside of traits.
+--FILE--
+<?php
+
+ class MyClass {
+ static function test() {
+ return __TRAIT__;
+ }
+ }
+
+ function someFun() {
+ return __TRAIT__;
+ }
+
+
+ $t = __TRAIT__;
+ var_dump($t);
+ $t = MyClass::test();
+ var_dump($t);
+ $t = someFun();
+ var_dump($t);
+?>
+--EXPECT--
+string(0) ""
+string(0) ""
+string(0) "" \ No newline at end of file
diff --git a/Zend/tests/unset_cv05.phpt b/Zend/tests/unset_cv05.phpt
index 90ebc6ba34..36fea3bc40 100644
--- a/Zend/tests/unset_cv05.phpt
+++ b/Zend/tests/unset_cv05.phpt
@@ -1,7 +1,6 @@
--TEST--
unset() CV 5 (indirect unset() of global variable in session_start())
--INI--
-register_long_arrays=1
session.auto_start=0
session.save_handler=files
--SKIPIF--
@@ -12,18 +11,19 @@ include(dirname(__FILE__).'/../../ext/session/tests/skipif.inc');
?>
--FILE--
<?php
-$HTTP_SESSION_VARS = "ok\n";
-echo $HTTP_SESSION_VARS;
+$_SESSION = "ok\n";
+echo $_SESSION;
session_start();
-echo $HTTP_SESSION_VARS;
+echo $_SESSION;
echo "\nok\n";
?>
--EXPECTF--
-Deprecated: Directive 'register_long_arrays' is deprecated in PHP %d.%d and greater in Unknown on line 0
ok
Warning: session_start(): Cannot send session cookie - headers already sent by (output started at %sunset_cv05.php on line %d
Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at %sunset_cv05.php:%d) in %sunset_cv05.php on line %d
+
+Notice: Array to string conversion in %sunset_cv05.php on line %d
Array
ok
diff --git a/Zend/tests/unset_cv06.phpt b/Zend/tests/unset_cv06.phpt
index ba21cf430d..dd788158e4 100644
--- a/Zend/tests/unset_cv06.phpt
+++ b/Zend/tests/unset_cv06.phpt
@@ -3,27 +3,20 @@ unset() CV 6 (indirect unset() of global variable in session_unset())
--SKIPIF--
<?php include(dirname(__FILE__).'/../../ext/session/tests/skipif.inc'); ?>
--INI--
-register_globals=1
session.auto_start=0
session.save_handler=files
--FILE--
<?php
-$x = "1\n";
session_start();
-echo $x;
-session_register('x');
-$_SESSION['x'] = "2\n";
-echo $x;
+$_SESSION['x'] = "1\n";
+echo $_SESSION['x'];
+
session_unset();
-echo $x;
+echo $_SESSION['x'];
echo "ok\n";
?>
--EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP %d.%d and greater in Unknown on line 0
1
-Deprecated: Function session_register() is deprecated in %s on line %d
-2
-
-Notice: Undefined variable: x in %sunset_cv06.php on line %d
+Notice: Undefined index: x in %sunset_cv06.php on line %d
ok
diff --git a/Zend/tests/unset_cv07.phpt b/Zend/tests/unset_cv07.phpt
index b7bdb7db5c..3f893ca235 100644
--- a/Zend/tests/unset_cv07.phpt
+++ b/Zend/tests/unset_cv07.phpt
@@ -1,5 +1,7 @@
--TEST--
unset() CV 7 (indirect unset() of global variable in import_request_variables())
+--SKIPIF--
+<?php if(PHP_VERSION_ID >= 50399){ die('skip not needed anymore without register_globals'); } ?>
--GET--
x=2
--FILE--
diff --git a/Zend/tests/unset_cv08.phpt b/Zend/tests/unset_cv08.phpt
index 1c4015ab38..9b8ab1520f 100644
--- a/Zend/tests/unset_cv08.phpt
+++ b/Zend/tests/unset_cv08.phpt
@@ -4,7 +4,7 @@ unset() CV 8 (unset() of global variable in array_unique($GLOBALS))
<?php
$a = "ok\n";
$b = "ok\n";
-array_unique($GLOBALS);
+@array_unique($GLOBALS);
echo $a;
echo $b;
echo "ok\n";
diff --git a/Zend/zend.c b/Zend/zend.c
index bd53d55183..9ab879a2a4 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -29,6 +29,7 @@
#include "zend_builtin_functions.h"
#include "zend_ini.h"
#include "zend_vm.h"
+#include "zend_dtrace.h"
#ifdef ZTS
# define GLOBAL_FUNCTION_TABLE global_function_table
@@ -62,7 +63,7 @@ ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRML
void (*zend_on_timeout)(int seconds TSRMLS_DC);
-static void (*zend_message_dispatcher_p)(long message, void *data TSRMLS_DC);
+static void (*zend_message_dispatcher_p)(long message, const void *data TSRMLS_DC);
static int (*zend_get_configuration_directive_p)(const char *name, uint name_length, zval *contents);
static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */
@@ -88,11 +89,27 @@ static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */
}
/* }}} */
+static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */
+{
+ if (!CG(multibyte)) {
+ return FAILURE;
+ }
+ if (!zend_multibyte_get_functions(TSRMLS_C)) {
+ return SUCCESS;
+ }
+ return zend_multibyte_set_script_encoding_by_string(new_value, new_value_length TSRMLS_CC);
+}
+/* }}} */
+
+
ZEND_INI_BEGIN()
ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)
-#ifdef ZEND_MULTIBYTE
- STD_ZEND_INI_BOOLEAN("detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals)
+ STD_ZEND_INI_BOOLEAN("zend.multibyte", "0", ZEND_INI_PERDIR, OnUpdateBool, multibyte, zend_compiler_globals, compiler_globals)
+ ZEND_INI_ENTRY("zend.script_encoding", NULL, ZEND_INI_ALL, OnUpdateScriptEncoding)
+ STD_ZEND_INI_BOOLEAN("zend.detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals)
+#ifdef ZEND_SIGNALS
+ STD_ZEND_INI_BOOLEAN("zend.signal_check", "0", ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals)
#endif
ZEND_INI_END()
@@ -140,7 +157,7 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
case HASH_KEY_IS_STRING:
if (is_object) {
- char *prop_name, *class_name;
+ const char *prop_name, *class_name;
int mangled = zend_unmangle_property_name(string_key, str_len - 1, &class_name, &prop_name);
ZEND_PUTS_EX(prop_name);
@@ -230,9 +247,10 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
break;
case IS_RESOURCE:
Z_STRVAL_P(expr_copy) = (char *) emalloc(sizeof("Resource id #") - 1 + MAX_LENGTH_OF_LONG);
- Z_STRLEN_P(expr_copy) = sprintf(Z_STRVAL_P(expr_copy), "Resource id #%ld", Z_LVAL_P(expr));
+ Z_STRLEN_P(expr_copy) = snprintf(Z_STRVAL_P(expr_copy), sizeof("Resource id #") - 1 + MAX_LENGTH_OF_LONG, "Resource id #%ld", Z_LVAL_P(expr));
break;
case IS_ARRAY:
+ zend_error(E_NOTICE, "Array to string conversion");
Z_STRLEN_P(expr_copy) = sizeof("Array") - 1;
Z_STRVAL_P(expr_copy) = estrndup("Array", Z_STRLEN_P(expr_copy));
break;
@@ -240,14 +258,20 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
{
TSRMLS_FETCH();
- if (Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
+ if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
break;
}
- /* Standard PHP objects */
- if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HANDLER_P(expr, cast_object)) {
- if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_P(expr, cast_object)) {
+ zval *val;
+
+ ALLOC_ZVAL(val);
+ INIT_PZVAL_COPY(val, expr);
+ zval_copy_ctor(val);
+ if (Z_OBJ_HANDLER_P(expr, cast_object)(val, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
+ zval_ptr_dtor(&val);
break;
}
+ zval_ptr_dtor(&val);
}
if (!Z_OBJ_HANDLER_P(expr, cast_object) && Z_OBJ_HANDLER_P(expr, get)) {
zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
@@ -332,7 +356,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */
case IS_OBJECT:
{
HashTable *properties = NULL;
- char *class_name = NULL;
+ const char *class_name = NULL;
zend_uint clen;
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
@@ -344,7 +368,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) /* {{{ */
zend_printf("%s Object (", "Unknown Class");
}
if (class_name) {
- efree(class_name);
+ efree((char*)class_name);
}
if (Z_OBJ_HANDLER_P(expr, get_properties)) {
properties = Z_OBJPROP_P(expr);
@@ -390,7 +414,7 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
case IS_OBJECT:
{
HashTable *properties;
- char *class_name = NULL;
+ const char *class_name = NULL;
zend_uint clen;
int is_temp;
@@ -404,7 +428,7 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
}
ZEND_PUTS_EX(" Object\n");
if (class_name) {
- efree(class_name);
+ efree((char*)class_name);
}
if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
break;
@@ -441,12 +465,10 @@ static FILE *zend_fopen_wrapper(const char *filename, char **opened_path TSRMLS_
#ifdef ZTS
static zend_bool asp_tags_default = 0;
static zend_bool short_tags_default = 1;
-static zend_bool ct_pass_ref_default = 1;
static zend_uint compiler_options_default = ZEND_COMPILE_DEFAULT;
#else
# define asp_tags_default 0
# define short_tags_default 1
-# define ct_pass_ref_default 1
# define compiler_options_default ZEND_COMPILE_DEFAULT
#endif
@@ -455,7 +477,6 @@ static void zend_set_default_compile_time_values(TSRMLS_D) /* {{{ */
/* default compile-time values */
CG(asp_tags) = asp_tags_default;
CG(short_tags) = short_tags_default;
- CG(allow_call_time_pass_reference) = ct_pass_ref_default;
CG(compiler_options) = compiler_options_default;
}
/* }}} */
@@ -464,19 +485,19 @@ static void zend_init_exception_op(TSRMLS_D) /* {{{ */
{
memset(EG(exception_op), 0, sizeof(EG(exception_op)));
EG(exception_op)[0].opcode = ZEND_HANDLE_EXCEPTION;
- EG(exception_op)[0].op1.op_type = IS_UNUSED;
- EG(exception_op)[0].op2.op_type = IS_UNUSED;
- EG(exception_op)[0].result.op_type = IS_UNUSED;
+ EG(exception_op)[0].op1_type = IS_UNUSED;
+ EG(exception_op)[0].op2_type = IS_UNUSED;
+ EG(exception_op)[0].result_type = IS_UNUSED;
ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op));
EG(exception_op)[1].opcode = ZEND_HANDLE_EXCEPTION;
- EG(exception_op)[1].op1.op_type = IS_UNUSED;
- EG(exception_op)[1].op2.op_type = IS_UNUSED;
- EG(exception_op)[1].result.op_type = IS_UNUSED;
+ EG(exception_op)[1].op1_type = IS_UNUSED;
+ EG(exception_op)[1].op2_type = IS_UNUSED;
+ EG(exception_op)[1].result_type = IS_UNUSED;
ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+1);
EG(exception_op)[2].opcode = ZEND_HANDLE_EXCEPTION;
- EG(exception_op)[2].op1.op_type = IS_UNUSED;
- EG(exception_op)[2].op2.op_type = IS_UNUSED;
- EG(exception_op)[2].result.op_type = IS_UNUSED;
+ EG(exception_op)[2].op1_type = IS_UNUSED;
+ EG(exception_op)[2].op2_type = IS_UNUSED;
+ EG(exception_op)[2].result_type = IS_UNUSED;
ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+2);
}
/* }}} */
@@ -507,10 +528,11 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS
compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table);
if (compiler_globals->last_static_member) {
- compiler_globals->static_members = (HashTable**)calloc(compiler_globals->last_static_member, sizeof(HashTable*));
+ compiler_globals->static_members_table = calloc(compiler_globals->last_static_member, sizeof(zval**));
} else {
- compiler_globals->static_members = NULL;
+ compiler_globals->static_members_table = NULL;
}
+ compiler_globals->script_encoding_list = NULL;
}
/* }}} */
@@ -528,8 +550,11 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS
zend_hash_destroy(compiler_globals->auto_globals);
free(compiler_globals->auto_globals);
}
- if (compiler_globals->static_members) {
- free(compiler_globals->static_members);
+ if (compiler_globals->static_members_table) {
+ free(compiler_globals->static_members_table);
+ }
+ if (compiler_globals->script_encoding_list) {
+ pefree(compiler_globals->script_encoding_list, 1);
}
compiler_globals->last_static_member = 0;
}
@@ -549,7 +574,10 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS
EG(current_execute_data) = NULL;
EG(current_module) = NULL;
EG(exit_status) = 0;
- EG(saved_fpu_cw) = NULL;
+#if XPFPA_HAVE_CW
+ EG(saved_fpu_cw) = 0;
+#endif
+ EG(saved_fpu_cw_ptr) = NULL;
EG(active) = 0;
}
/* }}} */
@@ -595,6 +623,20 @@ static void php_scanner_globals_ctor(zend_php_scanner_globals *scanner_globals_p
void zend_init_opcodes_handlers(void);
+static zend_bool php_auto_globals_create_globals(const char *name, uint name_len TSRMLS_DC) /* {{{ */
+{
+ zval *globals;
+
+ ALLOC_ZVAL(globals);
+ Z_SET_REFCOUNT_P(globals, 1);
+ Z_SET_ISREF_P(globals);
+ Z_TYPE_P(globals) = IS_ARRAY;
+ Z_ARRVAL_P(globals) = &EG(symbol_table);
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &globals, sizeof(zval *), NULL);
+ return 0;
+}
+/* }}} */
+
int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC) /* {{{ */
{
#ifdef ZTS
@@ -627,8 +669,10 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
}
zend_stream_open_function = utility_functions->stream_open_function;
zend_message_dispatcher_p = utility_functions->message_handler;
+#ifndef ZEND_SIGNALS
zend_block_interruptions = utility_functions->block_interruptions;
zend_unblock_interruptions = utility_functions->unblock_interruptions;
+#endif
zend_get_configuration_directive_p = utility_functions->get_configuration_directive;
zend_ticks_function = utility_functions->ticks_function;
zend_on_timeout = utility_functions->on_timeout;
@@ -636,10 +680,17 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
zend_getenv = utility_functions->getenv_function;
zend_resolve_path = utility_functions->resolve_path_function;
+#if HAVE_DTRACE
+/* build with dtrace support */
+ zend_compile_file = dtrace_compile_file;
+ zend_execute = dtrace_execute;
+ zend_execute_internal = dtrace_execute_internal;
+#else
zend_compile_file = compile_file;
- zend_compile_string = compile_string;
zend_execute = execute;
zend_execute_internal = NULL;
+#endif /* HAVE_SYS_SDT_H */
+ zend_compile_string = compile_string;
zend_throw_exception_hook = NULL;
zend_init_opcodes_handlers();
@@ -655,7 +706,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
- zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
+ zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0);
zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0);
zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
@@ -693,9 +744,10 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
EG(user_exception_handler) = NULL;
#endif
+ zend_interned_strings_init(TSRMLS_C);
zend_startup_builtin_functions(TSRMLS_C);
zend_register_standard_constants(TSRMLS_C);
- zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, NULL TSRMLS_CC);
+ zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, 1, php_auto_globals_create_globals TSRMLS_CC);
#ifndef ZTS
zend_init_rsrc_plist(TSRMLS_C);
@@ -726,6 +778,8 @@ void zend_register_standard_ini_entries(TSRMLS_D) /* {{{ */
void zend_post_startup(TSRMLS_D) /* {{{ */
{
#ifdef ZTS
+ zend_encoding **script_encoding_list;
+
zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
@@ -735,13 +789,17 @@ void zend_post_startup(TSRMLS_D) /* {{{ */
asp_tags_default = CG(asp_tags);
short_tags_default = CG(short_tags);
- ct_pass_ref_default = CG(allow_call_time_pass_reference);
compiler_options_default = CG(compiler_options);
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
free(compiler_globals->function_table);
free(compiler_globals->class_table);
- compiler_globals_ctor(compiler_globals, tsrm_ls);
+ if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) {
+ compiler_globals_ctor(compiler_globals, tsrm_ls);
+ compiler_globals->script_encoding_list = (const zend_encoding **)script_encoding_list;
+ } else {
+ compiler_globals_ctor(compiler_globals, tsrm_ls);
+ }
free(EG(zend_constants));
executor_globals_ctor(executor_globals, tsrm_ls);
global_persistent_list = &EG(persistent_list);
@@ -752,11 +810,14 @@ void zend_post_startup(TSRMLS_D) /* {{{ */
void zend_shutdown(TSRMLS_D) /* {{{ */
{
+#ifdef ZEND_SIGNALS
+ zend_signal_shutdown(TSRMLS_C);
+#endif
#ifdef ZEND_WIN32
zend_shutdown_timeout_thread();
#endif
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
- zend_hash_graceful_reverse_destroy(&module_registry);
+ zend_destroy_modules();
zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
zend_hash_destroy(GLOBAL_CLASS_TABLE);
@@ -781,6 +842,8 @@ void zend_shutdown(TSRMLS_D) /* {{{ */
GLOBAL_CONSTANTS_TABLE = NULL;
#endif
zend_destroy_rsrc_list_dtors();
+
+ zend_interned_strings_dtor(TSRMLS_C);
}
/* }}} */
@@ -853,22 +916,6 @@ void zend_activate(TSRMLS_D) /* {{{ */
}
/* }}} */
-void zend_activate_modules(TSRMLS_D) /* {{{ */
-{
- zend_hash_apply(&module_registry, (apply_func_t) module_registry_request_startup TSRMLS_CC);
-}
-/* }}} */
-
-void zend_deactivate_modules(TSRMLS_D) /* {{{ */
-{
- EG(opline_ptr) = NULL; /* we're no longer executing anything */
-
- zend_try {
- zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC);
- } zend_end_try();
-}
-/* }}} */
-
void zend_call_destructors(TSRMLS_D) /* {{{ */
{
zend_try {
@@ -922,24 +969,8 @@ void zend_deactivate(TSRMLS_D) /* {{{ */
}
/* }}} */
-static int exec_done_cb(zend_module_entry *module TSRMLS_DC) /* {{{ */
-{
- if (module->post_deactivate_func) {
- module->post_deactivate_func();
- }
- return 0;
-}
-/* }}} */
-
-void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */
-{
- zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC);
- zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_unload_temp TSRMLS_CC);
-}
-/* }}} */
-
BEGIN_EXTERN_C()
-ZEND_API void zend_message_dispatcher(long message, void *data TSRMLS_DC) /* {{{ */
+ZEND_API void zend_message_dispatcher(long message, const void *data TSRMLS_DC) /* {{{ */
{
if (zend_message_dispatcher_p) {
zend_message_dispatcher_p(message, data TSRMLS_CC);
@@ -982,7 +1013,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
zval ***params;
zval *retval;
zval *z_error_type, *z_error_message, *z_error_filename, *z_error_lineno, *z_context;
- char *error_filename;
+ const char *error_filename;
uint error_lineno;
zval *orig_user_error_handler;
zend_bool in_compilation;
@@ -994,7 +1025,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
zend_stack object_stack;
zend_stack declare_stack;
zend_stack list_stack;
- zend_stack labels_stack;
+ zend_stack context_stack;
TSRMLS_FETCH();
/* Report about uncaught exception in case of fatal errors */
@@ -1062,6 +1093,15 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
va_start(args, format);
+#ifdef HAVE_DTRACE
+ if(DTRACE_ERROR_ENABLED()) {
+ char *dtrace_error_buffer;
+ zend_vspprintf(&dtrace_error_buffer, 0, format, args);
+ DTRACE_ERROR(dtrace_error_buffer, error_filename, error_lineno);
+ efree(dtrace_error_buffer);
+ }
+#endif /* HAVE_DTRACE */
+
/* if we don't have a user defined error handler */
if (!EG(user_error_handler)
|| !(EG(user_error_handler_error_reporting) & type)
@@ -1152,7 +1192,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
SAVE_STACK(object_stack);
SAVE_STACK(declare_stack);
SAVE_STACK(list_stack);
- SAVE_STACK(labels_stack);
+ SAVE_STACK(context_stack);
}
if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC) == SUCCESS) {
@@ -1176,7 +1216,7 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
RESTORE_STACK(object_stack);
RESTORE_STACK(declare_stack);
RESTORE_STACK(list_stack);
- RESTORE_STACK(labels_stack);
+ RESTORE_STACK(context_stack);
}
if (!EG(user_error_handler)) {
@@ -1241,6 +1281,7 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
zend_file_handle *file_handle;
zend_op_array *orig_op_array = EG(active_op_array);
zval **orig_retval_ptr_ptr = EG(return_value_ptr_ptr);
+ long orig_interactive = CG(interactive);
va_start(files, file_count);
for (i = 0; i < file_count; i++) {
@@ -1248,6 +1289,15 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
if (!file_handle) {
continue;
}
+
+ if (orig_interactive) {
+ if (file_handle->filename[0] != '-' || file_handle->filename[1]) {
+ CG(interactive) = 0;
+ } else {
+ CG(interactive) = 1;
+ }
+ }
+
EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC);
if (file_handle->opened_path) {
int dummy = 1;
@@ -1289,12 +1339,14 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
va_end(files);
EG(active_op_array) = orig_op_array;
EG(return_value_ptr_ptr) = orig_retval_ptr_ptr;
+ CG(interactive) = orig_interactive;
return FAILURE;
}
}
va_end(files);
EG(active_op_array) = orig_op_array;
EG(return_value_ptr_ptr) = orig_retval_ptr_ptr;
+ CG(interactive) = orig_interactive;
return SUCCESS;
}
@@ -1304,7 +1356,7 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
ZEND_API char *zend_make_compiled_string_description(const char *name TSRMLS_DC) /* {{{ */
{
- char *cur_filename;
+ const char *cur_filename;
int cur_lineno;
char *compiled_string_description;
diff --git a/Zend/zend.h b/Zend/zend.h
index 4958c1492e..3226f8ce03 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -22,7 +22,7 @@
#ifndef ZEND_H
#define ZEND_H
-#define ZEND_VERSION "2.3.0"
+#define ZEND_VERSION "2.4.0"
#define ZEND_ENGINE_2
@@ -200,9 +200,9 @@ char *alloca ();
#endif
#if ZEND_DEBUG
-#define ZEND_FILE_LINE_D char *__zend_filename, uint __zend_lineno
+#define ZEND_FILE_LINE_D const char *__zend_filename, const uint __zend_lineno
#define ZEND_FILE_LINE_DC , ZEND_FILE_LINE_D
-#define ZEND_FILE_LINE_ORIG_D char *__zend_orig_filename, uint __zend_orig_lineno
+#define ZEND_FILE_LINE_ORIG_D const char *__zend_orig_filename, const uint __zend_orig_lineno
#define ZEND_FILE_LINE_ORIG_DC , ZEND_FILE_LINE_ORIG_D
#define ZEND_FILE_LINE_RELAY_C __zend_filename, __zend_lineno
#define ZEND_FILE_LINE_RELAY_CC , ZEND_FILE_LINE_RELAY_C
@@ -237,6 +237,7 @@ char *alloca ();
#include "zend_alloc.h"
#include "zend_types.h"
+#include "zend_string.h"
#ifdef HAVE_LIMITS_H
# include <limits.h>
@@ -297,6 +298,7 @@ typedef struct _zend_guard {
typedef struct _zend_object {
zend_class_entry *ce;
HashTable *properties;
+ zval **properties_table;
HashTable *guards; /* protects from __get/__set ... recursion */
} zend_object;
@@ -351,17 +353,21 @@ struct _zval_struct {
#if defined(__GNUC__)
#if __GNUC__ >= 3
#define zend_always_inline inline __attribute__((always_inline))
+#define zend_never_inline __attribute__((noinline))
#else
#define zend_always_inline inline
+#define zend_never_inline
#endif
#elif defined(_MSC_VER)
#define zend_always_inline __forceinline
+#define zend_never_inline
#else
#define zend_always_inline inline
+#define zend_never_inline
#endif
-#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
+#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
# define EXPECTED(condition) __builtin_expect(condition, 1)
# define UNEXPECTED(condition) __builtin_expect(condition, 0)
#else
@@ -415,22 +421,60 @@ struct _zend_unserialize_data;
typedef struct _zend_serialize_data zend_serialize_data;
typedef struct _zend_unserialize_data zend_unserialize_data;
+struct _zend_trait_method_reference {
+ const char* method_name;
+ unsigned int mname_len;
+
+ zend_class_entry *ce;
+
+ const char* class_name;
+ unsigned int cname_len;
+};
+typedef struct _zend_trait_method_reference zend_trait_method_reference;
+
+struct _zend_trait_precedence {
+ zend_trait_method_reference *trait_method;
+
+ zend_class_entry** exclude_from_classes;
+
+ union _zend_function* function;
+};
+typedef struct _zend_trait_precedence zend_trait_precedence;
+
+struct _zend_trait_alias {
+ zend_trait_method_reference *trait_method;
+
+ /**
+ * name for method to be added
+ */
+ const char* alias;
+ unsigned int alias_len;
+
+ /**
+ * modifiers to be set on trait method
+ */
+ zend_uint modifiers;
+
+ union _zend_function* function;
+};
+typedef struct _zend_trait_alias zend_trait_alias;
+
struct _zend_class_entry {
char type;
- char *name;
+ const char *name;
zend_uint name_length;
struct _zend_class_entry *parent;
int refcount;
- zend_bool constants_updated;
zend_uint ce_flags;
HashTable function_table;
- HashTable default_properties;
HashTable properties_info;
- HashTable default_static_members;
- HashTable *static_members;
+ zval **default_properties_table;
+ zval **default_static_members_table;
+ zval **static_members_table;
HashTable constants_table;
- const struct _zend_function_entry *builtin_functions;
+ int default_properties_count;
+ int default_static_members_count;
union _zend_function *constructor;
union _zend_function *destructor;
@@ -459,14 +503,25 @@ struct _zend_class_entry {
zend_class_entry **interfaces;
zend_uint num_interfaces;
-
- char *filename;
- zend_uint line_start;
- zend_uint line_end;
- char *doc_comment;
- zend_uint doc_comment_len;
-
- struct _zend_module_entry *module;
+
+ zend_class_entry **traits;
+ zend_uint num_traits;
+ zend_trait_alias **trait_aliases;
+ zend_trait_precedence **trait_precedences;
+
+ union {
+ struct {
+ const char *filename;
+ zend_uint line_start;
+ zend_uint line_end;
+ const char *doc_comment;
+ zend_uint doc_comment_len;
+ } user;
+ struct {
+ const struct _zend_function_entry *builtin_functions;
+ struct _zend_module_entry *module;
+ } internal;
+ } info;
};
#include "zend_stream.h"
@@ -475,7 +530,7 @@ typedef struct _zend_utility_functions {
int (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
int (*write_function)(const char *str, uint str_length);
FILE *(*fopen_function)(const char *filename, char **opened_path TSRMLS_DC);
- void (*message_handler)(long message, void *data TSRMLS_DC);
+ void (*message_handler)(long message, const void *data TSRMLS_DC);
void (*block_interruptions)(void);
void (*unblock_interruptions)(void);
int (*get_configuration_directive)(const char *name, uint name_length, zval *contents);
@@ -518,13 +573,15 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
+#define IS_CALLABLE 10
/* Ugly hack to support constants as static array indices */
-#define IS_CONSTANT_TYPE_MASK 0x0f
-#define IS_CONSTANT_UNQUALIFIED 0x10
-#define IS_CONSTANT_INDEX 0x80
-#define IS_LEXICAL_VAR 0x20
-#define IS_LEXICAL_REF 0x40
+#define IS_CONSTANT_TYPE_MASK 0x00f
+#define IS_CONSTANT_UNQUALIFIED 0x010
+#define IS_CONSTANT_INDEX 0x080
+#define IS_LEXICAL_VAR 0x020
+#define IS_LEXICAL_REF 0x040
+#define IS_CONSTANT_IN_NAMESPACE 0x100
/* overloaded elements data types */
#define OE_IS_ARRAY (1<<0)
@@ -599,8 +656,8 @@ END_EXTERN_C()
/* FIXME: Check if we can save if (ptr) too */
-#define STR_FREE(ptr) if (ptr) { efree(ptr); }
-#define STR_FREE_REL(ptr) if (ptr) { efree_rel(ptr); }
+#define STR_FREE(ptr) if (ptr && !IS_INTERNED(ptr)) { efree(ptr); }
+#define STR_FREE_REL(ptr) if (ptr && !IS_INTERNED(ptr)) { efree_rel(ptr); }
#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1)
@@ -622,7 +679,7 @@ extern ZEND_API void (*zend_block_interruptions)(void);
extern ZEND_API void (*zend_unblock_interruptions)(void);
extern ZEND_API void (*zend_ticks_function)(int ticks);
extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
-extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
+extern ZEND_API void (*zend_on_timeout)(int seconds TSRMLS_DC);
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
@@ -642,11 +699,18 @@ END_EXTERN_C()
#define ZEND_UV(name) (zend_uv.name)
+#ifndef ZEND_SIGNALS
#define HANDLE_BLOCK_INTERRUPTIONS() if (zend_block_interruptions) { zend_block_interruptions(); }
#define HANDLE_UNBLOCK_INTERRUPTIONS() if (zend_unblock_interruptions) { zend_unblock_interruptions(); }
+#else
+#include "zend_signal.h"
+
+#define HANDLE_BLOCK_INTERRUPTIONS() ZEND_SIGNAL_BLOCK_INTERRUPUTIONS()
+#define HANDLE_UNBLOCK_INTERRUPTIONS() ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS()
+#endif
BEGIN_EXTERN_C()
-ZEND_API void zend_message_dispatcher(long message, void *data TSRMLS_DC);
+ZEND_API void zend_message_dispatcher(long message, const void *data TSRMLS_DC);
ZEND_API int zend_get_configuration_directive(const char *name, uint name_length, zval *contents);
END_EXTERN_C()
@@ -676,19 +740,30 @@ END_EXTERN_C()
#define PZVAL_IS_REF(z) Z_ISREF_P(z)
-#define SEPARATE_ZVAL(ppzv) \
- { \
- zval *orig_ptr = *(ppzv); \
- \
- if (Z_REFCOUNT_P(orig_ptr) > 1) { \
- Z_DELREF_P(orig_ptr); \
- ALLOC_ZVAL(*(ppzv)); \
- **(ppzv) = *orig_ptr; \
- zval_copy_ctor(*(ppzv)); \
- Z_SET_REFCOUNT_PP(ppzv, 1); \
- Z_UNSET_ISREF_PP((ppzv)); \
- } \
- }
+#define ZVAL_COPY_VALUE(z, v) \
+ do { \
+ (z)->value = (v)->value; \
+ Z_TYPE_P(z) = Z_TYPE_P(v); \
+ } while (0)
+
+#define INIT_PZVAL_COPY(z, v) \
+ do { \
+ ZVAL_COPY_VALUE(z, v); \
+ Z_SET_REFCOUNT_P(z, 1); \
+ Z_UNSET_ISREF_P(z); \
+ } while (0)
+
+#define SEPARATE_ZVAL(ppzv) \
+ do { \
+ if (Z_REFCOUNT_PP((ppzv)) > 1) { \
+ zval *new_zv; \
+ Z_DELREF_PP(ppzv); \
+ ALLOC_ZVAL(new_zv); \
+ INIT_PZVAL_COPY(new_zv, *(ppzv)); \
+ *(ppzv) = new_zv; \
+ zval_copy_ctor(new_zv); \
+ } \
+ } while (0)
#define SEPARATE_ZVAL_IF_NOT_REF(ppzv) \
if (!PZVAL_IS_REF(*ppzv)) { \
@@ -711,10 +786,9 @@ END_EXTERN_C()
} \
INIT_PZVAL(&(zv));
-#define MAKE_COPY_ZVAL(ppzv, pzv) \
- *(pzv) = **(ppzv); \
- zval_copy_ctor((pzv)); \
- INIT_PZVAL((pzv));
+#define MAKE_COPY_ZVAL(ppzv, pzv) \
+ INIT_PZVAL_COPY(pzv, *(ppzv)); \
+ zval_copy_ctor((pzv));
#define REPLACE_ZVAL_VALUE(ppzv_dest, pzv_src, copy) { \
int is_ref, refcount; \
@@ -723,7 +797,7 @@ END_EXTERN_C()
is_ref = Z_ISREF_PP(ppzv_dest); \
refcount = Z_REFCOUNT_PP(ppzv_dest); \
zval_dtor(*ppzv_dest); \
- **ppzv_dest = *pzv_src; \
+ ZVAL_COPY_VALUE(*ppzv_dest, pzv_src); \
if (copy) { \
zval_copy_ctor(*ppzv_dest); \
} \
@@ -735,10 +809,7 @@ END_EXTERN_C()
if (PZVAL_IS_REF(varptr)) { \
zval *original_var = varptr; \
ALLOC_ZVAL(varptr); \
- varptr->value = original_var->value; \
- Z_TYPE_P(varptr) = Z_TYPE_P(original_var); \
- Z_UNSET_ISREF_P(varptr); \
- Z_SET_REFCOUNT_P(varptr, 1); \
+ INIT_PZVAL_COPY(varptr, original_var); \
zval_copy_ctor(varptr); \
} else { \
Z_ADDREF_P(varptr); \
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index d529775764..45abcf61e8 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -35,6 +35,12 @@
/* these variables are true statics/globals, and have to be mutex'ed on every access */
ZEND_API HashTable module_registry;
+static zend_module_entry **module_request_startup_handlers;
+static zend_module_entry **module_request_shutdown_handlers;
+static zend_module_entry **module_post_deactivate_handlers;
+
+static zend_class_entry **class_cleanup_handlers;
+
/* this function doesn't check for too many parameters */
ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
{
@@ -185,8 +191,8 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS
ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */
{
- char *space;
- char *class_name = get_active_class_name(&space TSRMLS_CC);
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
}
@@ -210,6 +216,8 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
return "resource";
case IS_NULL:
return "null";
+ case IS_CALLABLE:
+ return "callable";
case IS_ARRAY:
return "array";
default:
@@ -236,7 +244,7 @@ ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) /
/* }}} */
/* returns 1 if you need to copy result, 0 if it's already a copy */
-ZEND_API int zend_get_object_classname(const zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */
+ZEND_API int zend_get_object_classname(const zval *object, const char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */
{
if (Z_OBJ_HT_P(object)->get_class_name == NULL ||
Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) {
@@ -250,14 +258,16 @@ ZEND_API int zend_get_object_classname(const zval *object, char **class_name, ze
}
/* }}} */
-static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
+static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TSRMLS_DC) /* {{{ */
{
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
zval *obj;
MAKE_STD_ZVAL(obj);
- if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, IS_STRING TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, type TSRMLS_CC) == SUCCESS) {
zval_ptr_dtor(arg);
*arg = obj;
+ *pl = Z_STRLEN_PP(arg);
+ *p = Z_STRVAL_PP(arg);
return SUCCESS;
}
efree(obj);
@@ -265,7 +275,9 @@ static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
/* Standard PHP objects */
if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
- if (zend_std_cast_object_tostring(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
+ if (zend_std_cast_object_tostring(*arg, *arg, type TSRMLS_CC) == SUCCESS) {
+ *pl = Z_STRLEN_PP(arg);
+ *p = Z_STRVAL_PP(arg);
return SUCCESS;
}
}
@@ -280,6 +292,8 @@ static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
if (!use_copy) {
ZVAL_ZVAL(*arg, z, 1, 1);
}
+ *pl = Z_STRLEN_PP(arg);
+ *p = Z_STRVAL_PP(arg);
return SUCCESS;
}
zval_ptr_dtor(&z);
@@ -288,9 +302,9 @@ static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
}
/* }}} */
-static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
+static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, const char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
{
- char *spec_walk = *spec;
+ const char *spec_walk = *spec;
char c = *spec_walk++;
int return_null = 0;
@@ -397,6 +411,7 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp
}
break;
+ case 'p':
case 's':
{
char **p = va_arg(*va, char **);
@@ -423,13 +438,23 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp
}
*p = Z_STRVAL_PP(arg);
*pl = Z_STRLEN_PP(arg);
+ if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
+ return "a valid path";
+ }
break;
case IS_OBJECT:
+ if (parse_arg_object_to_string(arg, p, pl, IS_STRING TSRMLS_CC) == SUCCESS) {
+ if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
+ return "a valid path";
+ }
+ break;
+ }
+
case IS_ARRAY:
case IS_RESOURCE:
default:
- return "string";
+ return c == 's' ? "string" : "a valid path";
}
}
break;
@@ -641,16 +666,17 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp
}
/* }}} */
-static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */
+static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spec, int quiet TSRMLS_DC) /* {{{ */
{
- char *expected_type = NULL, *error = NULL;
+ const char *expected_type = NULL;
+ char *error = NULL;
int severity = E_WARNING;
expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
if (expected_type) {
if (!quiet && (*expected_type || error)) {
- char *space;
- char *class_name = get_active_class_name(&space TSRMLS_CC);
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
if (error) {
zend_error(severity, "%s%s%s() expects parameter %d %s",
@@ -671,15 +697,15 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int
}
/* }}} */
-static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
+static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
{
- char *spec_walk;
+ const char *spec_walk;
int c, i;
int min_num_args = -1;
int max_num_args = 0;
int post_varargs = 0;
zval **arg;
- int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
+ int arg_count;
int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
zend_bool have_varargs = 0;
zval ****varargs = NULL;
@@ -688,21 +714,14 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
for (spec_walk = type_spec; *spec_walk; spec_walk++) {
c = *spec_walk;
switch (c) {
- case 's':
- if (max_num_args < arg_count) {
- arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - max_num_args));
- if (Z_TYPE_PP(arg) == IS_OBJECT) {
- parse_arg_object_to_string(arg TSRMLS_CC);
- }
- }
- /* break missing intentionally */
case 'l': case 'd':
- case 'H': case 'b':
+ case 's': case 'b':
case 'r': case 'a':
case 'o': case 'O':
case 'z': case 'Z':
case 'C': case 'h':
case 'f': case 'A':
+ case 'H': case 'p':
max_num_args++;
break;
@@ -720,7 +739,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
if (have_varargs) {
if (!quiet) {
zend_function *active_function = EG(current_execute_data)->function_state.function;
- char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+ const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
class_name,
class_name[0] ? "::" : "",
@@ -740,7 +759,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
default:
if (!quiet) {
zend_function *active_function = EG(current_execute_data)->function_state.function;
- char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+ const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
class_name,
class_name[0] ? "::" : "",
@@ -763,7 +782,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
if (!quiet) {
zend_function *active_function = EG(current_execute_data)->function_state.function;
- char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+ const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
class_name,
class_name[0] ? "::" : "",
@@ -776,6 +795,8 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
return FAILURE;
}
+ arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
+
if (num_args > arg_count) {
zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
get_active_function_name(TSRMLS_C));
@@ -839,8 +860,8 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
int __num_args = (num_args); \
\
if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
- char *__space; \
- char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
+ const char *__space; \
+ const char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
__class_name, __space, \
get_active_function_name(TSRMLS_C), __num_args); \
@@ -848,7 +869,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
}\
}
-ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
+ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, const char *type_spec, ...) /* {{{ */
{
va_list va;
int retval;
@@ -863,7 +884,7 @@ ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *t
}
/* }}} */
-ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
+ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...) /* {{{ */
{
va_list va;
int retval;
@@ -878,11 +899,11 @@ ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...)
}
/* }}} */
-ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
+ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
{
va_list va;
int retval;
- char *p = type_spec;
+ const char *p = type_spec;
zval **object;
zend_class_entry *ce;
@@ -914,11 +935,11 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr
}
/* }}} */
-ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
+ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
{
va_list va;
int retval;
- char *p = type_spec;
+ const char *p = type_spec;
zval **object;
zend_class_entry *ce;
int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
@@ -976,7 +997,7 @@ static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list arg
MAKE_STD_ZVAL(member);
ZVAL_STRINGL(member, hash_key->arKey, hash_key->nKeyLength-1, 1);
- obj_ht->write_property(obj, member, *value TSRMLS_CC);
+ obj_ht->write_property(obj, member, *value, 0 TSRMLS_CC);
zval_ptr_dtor(&member);
}
return ZEND_HASH_APPLY_KEEP;
@@ -987,7 +1008,7 @@ static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list arg
* because it may call __set from the uninitialized object otherwise. */
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */
{
- zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
+ const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
zend_class_entry *old_scope = EG(scope);
EG(scope) = Z_OBJCE_P(obj);
@@ -1003,45 +1024,44 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) {
+ if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
zend_class_entry *old_scope = *scope;
+ int i;
*scope = class_type;
zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
- zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
- if (!CE_STATIC_MEMBERS(class_type)) {
- HashPosition pos;
+ for (i = 0; i < class_type->default_properties_count; i++) {
+ if (class_type->default_properties_table[i]) {
+ zval_update_constant(&class_type->default_properties_table[i], (void**)1 TSRMLS_CC);
+ }
+ }
+
+ if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
zval **p;
if (class_type->parent) {
zend_update_class_constants(class_type->parent TSRMLS_CC);
}
#if ZTS
- ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]);
+ CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
#else
- ALLOC_HASHTABLE(class_type->static_members);
+ class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
#endif
- zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0);
-
- zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
- while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
- char *str_index;
- uint str_length;
- ulong num_index;
- zval **q;
-
- zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
+ for (i = 0; i < class_type->default_static_members_count; i++) {
+ p = &class_type->default_static_members_table[i];
if (Z_ISREF_PP(p) &&
class_type->parent &&
- zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
- *p == *q &&
- zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS
+ i < class_type->parent->default_static_members_count &&
+ *p == class_type->parent->default_static_members_table[i] &&
+ CE_STATIC_MEMBERS(class_type->parent)[i]
) {
- Z_ADDREF_PP(q);
- Z_SET_ISREF_PP(q);
- zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL);
+ zval *q = CE_STATIC_MEMBERS(class_type->parent)[i];
+
+ Z_ADDREF_P(q);
+ Z_SET_ISREF_P(q);
+ CE_STATIC_MEMBERS(class_type)[i] = q;
} else {
zval *r;
@@ -1049,15 +1069,39 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
*r = **p;
INIT_PZVAL(r);
zval_copy_ctor(r);
- zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL);
+ CE_STATIC_MEMBERS(class_type)[i] = r;
}
- zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
}
}
- zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
+
+ for (i = 0; i < class_type->default_static_members_count; i++) {
+ zval_update_constant(&CE_STATIC_MEMBERS(class_type)[i], (void**)1 TSRMLS_CC);
+ }
*scope = old_scope;
- class_type->constants_updated = 1;
+ class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
+ }
+}
+/* }}} */
+
+ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
+{
+ int i;
+
+ if (class_type->default_properties_count) {
+ object->properties_table = emalloc(sizeof(zval*) * class_type->default_properties_count);
+ for (i = 0; i < class_type->default_properties_count; i++) {
+ object->properties_table[i] = class_type->default_properties_table[i];
+ if (class_type->default_properties_table[i]) {
+#if ZTS
+ ALLOC_ZVAL( object->properties_table[i]);
+ MAKE_COPY_ZVAL(&class_type->default_properties_table[i], object->properties_table[i]);
+#else
+ Z_ADDREF_P(object->properties_table[i]);
+#endif
+ }
+ }
+ object->properties = NULL;
}
}
/* }}} */
@@ -1068,11 +1112,12 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
* calling zend_merge_properties(). */
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
{
- zval *tmp;
zend_object *object;
if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
- char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class";
+ char *what = (class_type->ce_flags & ZEND_ACC_INTERFACE) ? "interface"
+ :((class_type->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) ? "trait"
+ : "abstract class";
zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
}
@@ -1083,10 +1128,9 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
if (properties) {
object->properties = properties;
+ object->properties_table = NULL;
} else {
- ALLOC_HASHTABLE_REL(object->properties);
- zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void *) &tmp, sizeof(zval *));
+ object_properties_init(object, class_type);
}
} else {
Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
@@ -1440,7 +1484,7 @@ ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
@@ -1458,7 +1502,7 @@ ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
@@ -1476,7 +1520,7 @@ ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRML
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
@@ -1494,7 +1538,7 @@ ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len,
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
@@ -1512,14 +1556,14 @@ ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, do
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
}
/* }}} */
-ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate TSRMLS_DC) /* {{{ */
+ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str, int duplicate TSRMLS_DC) /* {{{ */
{
zval *tmp;
zval *z_key;
@@ -1530,14 +1574,14 @@ ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, ch
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
}
/* }}} */
-ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */
+ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */
{
zval *tmp;
zval *z_key;
@@ -1548,7 +1592,7 @@ ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, c
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
zval_ptr_dtor(&z_key);
return SUCCESS;
@@ -1562,7 +1606,7 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval
MAKE_STD_ZVAL(z_key);
ZVAL_STRINGL(z_key, key, key_len-1, 1);
- Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value TSRMLS_CC);
+ Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value, 0 TSRMLS_CC);
zval_ptr_dtor(&z_key);
return SUCCESS;
}
@@ -1660,6 +1704,84 @@ try_again:
}
/* }}} */
+ZEND_API void zend_collect_module_handlers(TSRMLS_D) /* {{{ */
+{
+ HashPosition pos;
+ zend_module_entry *module;
+ int startup_count = 0;
+ int shutdown_count = 0;
+ int post_deactivate_count = 0;
+ zend_class_entry **pce;
+ int class_count = 0;
+
+ /* Collect extensions with request startup/shutdown handlers */
+ for (zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
+ zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(&module_registry, &pos)) {
+ if (module->request_startup_func) {
+ startup_count++;
+ }
+ if (module->request_shutdown_func) {
+ shutdown_count++;
+ }
+ if (module->post_deactivate_func) {
+ post_deactivate_count++;
+ }
+ }
+ module_request_startup_handlers = (zend_module_entry**)malloc(
+ sizeof(zend_module_entry*) *
+ (startup_count + 1 +
+ shutdown_count + 1 +
+ post_deactivate_count + 1));
+ module_request_startup_handlers[startup_count] = NULL;
+ module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
+ module_request_shutdown_handlers[shutdown_count] = NULL;
+ module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
+ module_post_deactivate_handlers[post_deactivate_count] = NULL;
+ startup_count = 0;
+
+ for (zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
+ zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(&module_registry, &pos)) {
+ if (module->request_startup_func) {
+ module_request_startup_handlers[startup_count++] = module;
+ }
+ if (module->request_shutdown_func) {
+ module_request_shutdown_handlers[--shutdown_count] = module;
+ }
+ if (module->post_deactivate_func) {
+ module_post_deactivate_handlers[--post_deactivate_count] = module;
+ }
+ }
+
+ /* Collect internal classes with static members */
+ for (zend_hash_internal_pointer_reset_ex(CG(class_table), &pos);
+ zend_hash_get_current_data_ex(CG(class_table), (void *) &pce, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(CG(class_table), &pos)) {
+ if ((*pce)->type == ZEND_INTERNAL_CLASS &&
+ (*pce)->default_static_members_count > 0) {
+ class_count++;
+ }
+ }
+
+ class_cleanup_handlers = (zend_class_entry**)malloc(
+ sizeof(zend_class_entry*) *
+ (class_count + 1));
+ class_cleanup_handlers[class_count] = NULL;
+
+ if (class_count) {
+ for (zend_hash_internal_pointer_reset_ex(CG(class_table), &pos);
+ zend_hash_get_current_data_ex(CG(class_table), (void *) &pce, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(CG(class_table), &pos)) {
+ if ((*pce)->type == ZEND_INTERNAL_CLASS &&
+ (*pce)->default_static_members_count > 0) {
+ class_cleanup_handlers[--class_count] = *pce;
+ }
+ }
+ }
+}
+/* }}} */
+
ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
{
zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC);
@@ -1668,6 +1790,14 @@ ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
}
/* }}} */
+ZEND_API void zend_destroy_modules(void) /* {{{ */
+{
+ free(class_cleanup_handlers);
+ free(module_request_startup_handlers);
+ zend_hash_graceful_reverse_destroy(&module_registry);
+}
+/* }}} */
+
ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
{
int name_len;
@@ -1801,13 +1931,13 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
const zend_function_entry *ptr = functions;
zend_function function, *reg_function;
zend_internal_function *internal_function = (zend_internal_function *)&function;
- int count=0, unload=0;
+ int count=0, unload=0, result=0;
HashTable *target_function_table = function_table;
int error_type;
zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL;
- char *lowercase_name;
+ const char *lowercase_name;
int fname_len;
- char *lc_class_name = NULL;
+ const char *lc_class_name = NULL;
int class_name_len = 0;
if (type==MODULE_PERSISTENT) {
@@ -1838,24 +1968,6 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
internal_function->function_name = (char*)ptr->fname;
internal_function->scope = scope;
internal_function->prototype = NULL;
- if (ptr->arg_info) {
- internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
- internal_function->num_args = ptr->num_args;
- /* Currently you cannot denote that the function can accept less arguments than num_args */
- if (ptr->arg_info[0].required_num_args == -1) {
- internal_function->required_num_args = ptr->num_args;
- } else {
- internal_function->required_num_args = ptr->arg_info[0].required_num_args;
- }
- internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
- internal_function->return_reference = ptr->arg_info[0].return_reference;
- } else {
- internal_function->arg_info = NULL;
- internal_function->num_args = 0;
- internal_function->required_num_args = 0;
- internal_function->pass_rest_by_reference = 0;
- internal_function->return_reference = 0;
- }
if (ptr->flags) {
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
@@ -1868,6 +1980,32 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
} else {
internal_function->fn_flags = ZEND_ACC_PUBLIC;
}
+ if (ptr->arg_info) {
+ zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
+
+ internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
+ internal_function->num_args = ptr->num_args;
+ /* Currently you cannot denote that the function can accept less arguments than num_args */
+ if (info->required_num_args == -1) {
+ internal_function->required_num_args = ptr->num_args;
+ } else {
+ internal_function->required_num_args = info->required_num_args;
+ }
+ if (info->pass_rest_by_reference) {
+ if (info->pass_rest_by_reference == ZEND_SEND_PREFER_REF) {
+ internal_function->fn_flags |= ZEND_ACC_PASS_REST_PREFER_REF;
+ } else {
+ internal_function->fn_flags |= ZEND_ACC_PASS_REST_BY_REFERENCE;
+ }
+ }
+ if (info->return_reference) {
+ internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
+ }
+ } else {
+ internal_function->arg_info = NULL;
+ internal_function->num_args = 0;
+ internal_function->required_num_args = 0;
+ }
if (ptr->flags & ZEND_ACC_ABSTRACT) {
if (scope) {
/* This is a class that must be abstract itself. Here we set the check info. */
@@ -1884,13 +2022,13 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
} else {
if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
- efree(lc_class_name);
+ efree((char*)lc_class_name);
zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
return FAILURE;
}
if (!internal_function->handler) {
if (scope) {
- efree(lc_class_name);
+ efree((char*)lc_class_name);
}
zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
@@ -1898,10 +2036,15 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
}
fname_len = strlen(ptr->fname);
- lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
- if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
+ lowercase_name = zend_new_interned_string(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC);
+ if (IS_INTERNED(lowercase_name)) {
+ result = zend_hash_quick_add(target_function_table, lowercase_name, fname_len+1, INTERNED_HASH(lowercase_name), &function, sizeof(zend_function), (void**)&reg_function);
+ } else {
+ result = zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function);
+ }
+ if (result == FAILURE) {
unload=1;
- efree(lowercase_name);
+ str_efree(lowercase_name);
break;
}
if (scope) {
@@ -1909,7 +2052,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
* If it's an old-style constructor, store it only if we don't have
* a constructor already.
*/
- if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {
+ if ((fname_len == class_name_len) && !ctor && !memcmp(lowercase_name, lc_class_name, class_name_len+1)) {
ctor = reg_function;
} else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
ctor = reg_function;
@@ -1943,11 +2086,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
ptr++;
count++;
- efree(lowercase_name);
+ str_efree(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) {
- efree(lc_class_name);
+ efree((char*)lc_class_name);
}
while (ptr->fname) {
fname_len = strlen(ptr->fname);
@@ -1955,7 +2098,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) {
zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
}
- efree(lowercase_name);
+ efree((char*)lowercase_name);
ptr++;
}
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
@@ -2035,7 +2178,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
}
__isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
}
- efree(lc_class_name);
+ efree((char*)lc_class_name);
}
return SUCCESS;
}
@@ -2088,7 +2231,7 @@ ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
static int clean_module_class(const zend_class_entry **ce, int *module_number TSRMLS_DC) /* {{{ */
{
- if ((*ce)->type == ZEND_INTERNAL_CLASS && (*ce)->module->module_number == *module_number) {
+ if ((*ce)->type == ZEND_INTERNAL_CLASS && (*ce)->info.internal.module->module_number == *module_number) {
return ZEND_HASH_APPLY_REMOVE;
} else {
return ZEND_HASH_APPLY_KEEP;
@@ -2147,19 +2290,19 @@ void module_destructor(zend_module_entry *module) /* {{{ */
}
/* }}} */
-/* call request startup for all modules */
-int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) /* {{{ */
+void zend_activate_modules(TSRMLS_D) /* {{{ */
{
- if (module->request_startup_func) {
-#if 0
- zend_printf("%s: Request startup\n", module->name);
-#endif
+ zend_module_entry **p = module_request_startup_handlers;
+
+ while (*p) {
+ zend_module_entry *module = *p;
+
if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
exit(1);
}
+ p++;
}
- return 0;
}
/* }}} */
@@ -2176,12 +2319,71 @@ int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
}
/* }}} */
+void zend_deactivate_modules(TSRMLS_D) /* {{{ */
+{
+ EG(opline_ptr) = NULL; /* we're no longer executing anything */
+
+ zend_try {
+ if (EG(full_tables_cleanup)) {
+ zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC);
+ } else {
+ zend_module_entry **p = module_request_shutdown_handlers;
+
+ while (*p) {
+ zend_module_entry *module = *p;
+
+ module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
+ p++;
+ }
+ }
+ } zend_end_try();
+}
+/* }}} */
+
+ZEND_API void zend_cleanup_internal_classes(TSRMLS_D) /* {{{ */
+{
+ zend_class_entry **p = class_cleanup_handlers;
+
+ while (*p) {
+ zend_cleanup_internal_class_data(*p TSRMLS_CC);
+ p++;
+ }
+}
+/* }}} */
+
int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */
{
return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
}
/* }}} */
+static int exec_done_cb(zend_module_entry *module TSRMLS_DC) /* {{{ */
+{
+ if (module->post_deactivate_func) {
+ module->post_deactivate_func();
+ }
+ return 0;
+}
+/* }}} */
+
+void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */
+{
+ if (EG(full_tables_cleanup)) {
+ zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC);
+ zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_unload_temp TSRMLS_CC);
+ } else {
+ zend_module_entry **p = module_post_deactivate_handlers;
+
+ while (*p) {
+ zend_module_entry *module = *p;
+
+ module->post_deactivate_func();
+ p++;
+ }
+ }
+}
+/* }}} */
+
/* return the next free module number */
int zend_next_free_module(void) /* {{{ */
{
@@ -2192,21 +2394,26 @@ int zend_next_free_module(void) /* {{{ */
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
{
zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
- char *lowercase_name = malloc(orig_class_entry->name_length + 1);
+ char *lowercase_name = emalloc(orig_class_entry->name_length + 1);
*class_entry = *orig_class_entry;
class_entry->type = ZEND_INTERNAL_CLASS;
zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
class_entry->ce_flags = ce_flags;
- class_entry->module = EG(current_module);
+ class_entry->info.internal.module = EG(current_module);
- if (class_entry->builtin_functions) {
- zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
+ if (class_entry->info.internal.builtin_functions) {
+ zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
}
zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
- zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
- free(lowercase_name);
+ lowercase_name = (char*)zend_new_interned_string(lowercase_name, class_entry->name_length + 1, 1 TSRMLS_CC);
+ if (IS_INTERNED(lowercase_name)) {
+ zend_hash_quick_update(CG(class_table), lowercase_name, class_entry->name_length+1, INTERNED_HASH(lowercase_name), &class_entry, sizeof(zend_class_entry *), NULL);
+ } else {
+ zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
+ }
+ str_efree(lowercase_name);
return class_entry;
}
/* }}} */
@@ -2326,16 +2533,20 @@ ZEND_API int zend_disable_function(char *function_name, uint function_name_lengt
}
/* }}} */
+#ifdef ZEND_WIN32
+#pragma optimize("", off)
+#endif
static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
zend_object_value retval;
zend_object *intern;
retval = zend_objects_new(&intern, class_type TSRMLS_CC);
- ALLOC_HASHTABLE(intern->properties);
- zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
return retval;
}
+#ifdef ZEND_WIN32
+#pragma optimize("", on)
+#endif
/* }}} */
static const zend_function_entry disabled_class_new[] = {
@@ -2404,7 +2615,7 @@ static int zend_is_callable_check_class(const char *name, int name_len, zend_fca
*strict_class = 1;
ret = 1;
}
- } else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
+ } else if (zend_lookup_class_ex(name, name_len, NULL, 1, &pce TSRMLS_CC) == SUCCESS) {
zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
fcc->calling_scope = *pce;
@@ -2430,7 +2641,8 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
{
zend_class_entry *ce_org = fcc->calling_scope;
int retval = 0;
- char *mname, *lmname, *colon;
+ char *mname, *lmname;
+ const char *colon;
int clen, mlen;
zend_class_entry *last_scope;
HashTable *ftable;
@@ -2554,26 +2766,24 @@ get_function_via_handler:
if (strict_class && ce_org->__call) {
fcc->function_handler = emalloc(sizeof(zend_internal_function));
fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
- fcc->function_handler->internal_function.module = ce_org->module;
+ fcc->function_handler->internal_function.module = (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL;
fcc->function_handler->internal_function.handler = zend_std_call_user_call;
fcc->function_handler->internal_function.arg_info = NULL;
fcc->function_handler->internal_function.num_args = 0;
fcc->function_handler->internal_function.scope = ce_org;
fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
- fcc->function_handler->internal_function.pass_rest_by_reference = 0;
- fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
call_via_handler = 1;
retval = 1;
} else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
- fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen TSRMLS_CC);
+ fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen, NULL TSRMLS_CC);
if (fcc->function_handler) {
if (strict_class &&
(!fcc->function_handler->common.scope ||
!instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fcc->function_handler->common.function_name);
+ efree((char*)fcc->function_handler->common.function_name);
}
efree(fcc->function_handler);
}
@@ -2587,7 +2797,7 @@ get_function_via_handler:
if (fcc->calling_scope->get_static_method) {
fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
} else {
- fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
+ fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen, NULL TSRMLS_CC);
}
if (fcc->function_handler) {
retval = 1;
@@ -2756,7 +2966,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fcc->function_handler->common.function_name);
+ efree((char*)fcc->function_handler->common.function_name);
}
efree(fcc->function_handler);
}
@@ -2834,7 +3044,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fcc->function_handler->common.function_name);
+ efree((char*)fcc->function_handler->common.function_name);
}
efree(fcc->function_handler);
}
@@ -2912,7 +3122,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fcc.function_handler->common.function_name);
+ efree((char*)fcc.function_handler->common.function_name);
}
efree(fcc.function_handler);
}
@@ -3098,18 +3308,40 @@ ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
}
/* }}} */
-ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
{
- zend_property_info property_info;
- HashTable *target_symbol_table;
+ zend_property_info property_info, *property_info_ptr;
+ const char *interned_name;
+ ulong h = zend_get_hash_value(name, name_length+1);
if (!(access_type & ZEND_ACC_PPP_MASK)) {
access_type |= ZEND_ACC_PUBLIC;
}
if (access_type & ZEND_ACC_STATIC) {
- target_symbol_table = &ce->default_static_members;
+ if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
+ (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
+ property_info.offset = property_info_ptr->offset;
+ zval_ptr_dtor(&ce->default_static_members_table[property_info.offset]);
+ zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
+ } else {
+ property_info.offset = ce->default_static_members_count++;
+ ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
+ }
+ ce->default_static_members_table[property_info.offset] = property;
+ if (ce->type == ZEND_USER_CLASS) {
+ ce->static_members_table = ce->default_static_members_table;
+ }
} else {
- target_symbol_table = &ce->default_properties;
+ if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
+ (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
+ property_info.offset = property_info_ptr->offset;
+ zval_ptr_dtor(&ce->default_properties_table[property_info.offset]);
+ zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
+ } else {
+ property_info.offset = ce->default_properties_count++;
+ ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
+ }
+ ce->default_properties_table[property_info.offset] = property;
}
if (ce->type & ZEND_INTERNAL_CLASS) {
switch(Z_TYPE_P(property)) {
@@ -3129,7 +3361,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
int priv_name_length;
zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
property_info.name = priv_name;
property_info.name_length = priv_name_length;
}
@@ -3139,46 +3370,51 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
int prot_name_length;
zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
property_info.name = prot_name;
property_info.name_length = prot_name_length;
}
break;
case ZEND_ACC_PUBLIC:
- if (ce->parent) {
- char *prot_name;
- int prot_name_length;
-
- zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
- pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
+ if (IS_INTERNED(name)) {
+ property_info.name = (char*)name;
+ } else {
+ property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
}
- zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
- property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
property_info.name_length = name_length;
break;
}
+
+ interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
+ if (interned_name != property_info.name) {
+ if (ce->type == ZEND_USER_CLASS) {
+ efree((char*)property_info.name);
+ } else {
+ free((char*)property_info.name);
+ }
+ property_info.name = interned_name;
+ }
+
property_info.flags = access_type;
- property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
+ property_info.h = (access_type & ZEND_ACC_PUBLIC) ? h : zend_get_hash_value(property_info.name, property_info.name_length+1);
property_info.doc_comment = doc_comment;
property_info.doc_comment_len = doc_comment_len;
property_info.ce = ce;
- zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
+ zend_hash_quick_update(&ce->properties_info, name, name_length+1, h, &property_info, sizeof(zend_property_info), NULL);
return SUCCESS;
}
/* }}} */
-ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
{
return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
}
/* }}} */
-ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
{
zval *property;
@@ -3192,7 +3428,7 @@ ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int na
}
/* }}} */
-ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
{
zval *property;
@@ -3207,7 +3443,7 @@ ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int na
}
/* }}} */
-ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
{
zval *property;
@@ -3222,7 +3458,7 @@ ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int na
}
/* }}} */
-ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
{
zval *property;
@@ -3237,7 +3473,7 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int
}
/* }}} */
-ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC) /* {{{ */
{
zval *property;
int len = strlen(value);
@@ -3254,7 +3490,7 @@ ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int
}
/* }}} */
-ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
+ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
{
zval *property;
@@ -3358,7 +3594,7 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char
}
/* }}} */
-ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
{
zval *property;
zend_class_entry *old_scope = EG(scope);
@@ -3366,7 +3602,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *
EG(scope) = scope;
if (!Z_OBJ_HT_P(object)->write_property) {
- char *class_name;
+ const char *class_name;
zend_uint class_name_len;
zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
@@ -3375,14 +3611,14 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *
}
MAKE_STD_ZVAL(property);
ZVAL_STRINGL(property, name, name_length, 1);
- Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, value, 0 TSRMLS_CC);
zval_ptr_dtor(&property);
EG(scope) = old_scope;
}
/* }}} */
-ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3394,7 +3630,7 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, c
}
/* }}} */
-ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3406,7 +3642,7 @@ ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, c
}
/* }}} */
-ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3418,7 +3654,7 @@ ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, c
}
/* }}} */
-ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3430,7 +3666,7 @@ ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object,
}
/* }}} */
-ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3442,7 +3678,7 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object,
}
/* }}} */
-ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
+ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3454,13 +3690,13 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object
}
/* }}} */
-ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
{
zval **property;
zend_class_entry *old_scope = EG(scope);
EG(scope) = scope;
- property = zend_std_get_static_property(scope, name, name_length, 0 TSRMLS_CC);
+ property = zend_std_get_static_property(scope, name, name_length, 0, NULL TSRMLS_CC);
EG(scope) = old_scope;
if (!property) {
return FAILURE;
@@ -3489,7 +3725,7 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, in
}
/* }}} */
-ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3501,7 +3737,7 @@ ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *nam
}
/* }}} */
-ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3513,7 +3749,7 @@ ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *nam
}
/* }}} */
-ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3525,7 +3761,7 @@ ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *nam
}
/* }}} */
-ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3537,7 +3773,7 @@ ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *n
}
/* }}} */
-ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3549,7 +3785,7 @@ ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *n
}
/* }}} */
-ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -3561,7 +3797,7 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *
}
/* }}} */
-ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
+ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
{
zval *property, *value;
zend_class_entry *old_scope = EG(scope);
@@ -3569,7 +3805,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
EG(scope) = scope;
if (!Z_OBJ_HT_P(object)->read_property) {
- char *class_name;
+ const char *class_name;
zend_uint class_name_len;
zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
@@ -3578,7 +3814,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
MAKE_STD_ZVAL(property);
ZVAL_STRINGL(property, name, name_length, 1);
- value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R TSRMLS_CC);
+ value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R, 0 TSRMLS_CC);
zval_ptr_dtor(&property);
EG(scope) = old_scope;
@@ -3586,13 +3822,13 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
}
/* }}} */
-ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
+ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
{
zval **property;
zend_class_entry *old_scope = EG(scope);
EG(scope) = scope;
- property = zend_std_get_static_property(scope, name, name_length, silent TSRMLS_CC);
+ property = zend_std_get_static_property(scope, name, name_length, silent, NULL TSRMLS_CC);
EG(scope) = old_scope;
return property?*property:NULL;
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index ddd84fa584..d7fbc3c3af 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -98,13 +98,14 @@ typedef struct _zend_fcall_info_cache {
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
-#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
-#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
-#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, 0, allow_null, pass_by_ref, 0, 0 },
-#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, 1, allow_null, pass_by_ref, 0, 0 },
+#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref},
+#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, 0, pass_by_ref},
+#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_OBJECT, allow_null, pass_by_ref},
+#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref},
+#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, allow_null, pass_by_ref},
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
static const zend_arg_info name[] = { \
- { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
+ { NULL, 0, NULL, required_num_args, 0, return_reference, pass_rest_by_reference},
#define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \
ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1)
#define ZEND_END_ARG_INFO() };
@@ -167,15 +168,18 @@ typedef struct _zend_fcall_info_cache {
#define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
{ \
+ const char *cl_name = class_name; \
int _len = class_name_len; \
- class_container.name = zend_strndup(class_name, _len); \
+ class_container.name = zend_new_interned_string(cl_name, _len+1, 0 TSRMLS_CC); \
+ if (class_container.name == cl_name) { \
+ class_container.name = zend_strndup(cl_name, _len); \
+ } \
class_container.name_length = _len; \
INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
}
#define INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
{ \
- class_container.builtin_functions = functions; \
class_container.constructor = NULL; \
class_container.destructor = NULL; \
class_container.clone = NULL; \
@@ -197,10 +201,15 @@ typedef struct _zend_fcall_info_cache {
class_container.unserialize = NULL; \
class_container.parent = NULL; \
class_container.num_interfaces = 0; \
+ class_container.traits = NULL; \
+ class_container.num_traits = 0; \
+ class_container.trait_aliases = NULL; \
+ class_container.trait_precedences = NULL; \
class_container.interfaces = NULL; \
class_container.get_iterator = NULL; \
class_container.iterator_funcs.funcs = NULL; \
- class_container.module = NULL; \
+ class_container.info.internal.module = NULL; \
+ class_container.info.internal.builtin_functions = functions; \
}
#define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \
@@ -214,9 +223,9 @@ typedef struct _zend_fcall_info_cache {
INIT_OVERLOADED_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions, handle_fcall, handle_propget, handle_propset)
#ifdef ZTS
-# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members)[(zend_intptr_t)(ce)->static_members])
+# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members_table:CG(static_members_table)[(zend_intptr_t)(ce)->static_members_table])
#else
-# define CE_STATIC_MEMBERS(ce) ((ce)->static_members)
+# define CE_STATIC_MEMBERS(ce) ((ce)->static_members_table)
#endif
#define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)
@@ -242,12 +251,12 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TS
/* Parameter parsing API -- andrei */
#define ZEND_PARSE_PARAMS_QUIET 1<<1
-ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
-ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);
+ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...);
+ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, const char *type_spec, ...);
ZEND_API char *zend_zval_type_name(const zval *arg);
-ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...);
-ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...);
+ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
+ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...);
/* End of parameter parsing API -- andrei */
@@ -258,6 +267,8 @@ ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *mod
ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC);
ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC);
ZEND_API int zend_startup_modules(TSRMLS_D);
+ZEND_API void zend_collect_module_handlers(TSRMLS_D);
+ZEND_API void zend_destroy_modules(void);
ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC);
ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *class_entry TSRMLS_DC);
@@ -289,14 +300,14 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC);
ZEND_API const char *zend_get_module_version(const char *module_name);
ZEND_API int zend_get_module_started(const char *module_name);
-ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC);
-ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC);
-ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC);
+ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC);
+ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC);
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC);
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC);
@@ -307,28 +318,28 @@ ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const cha
ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC);
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
-ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC);
-ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC);
-ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);
-ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);
-ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC);
-ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC);
-ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_length TSRMLS_DC);
-
-ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC);
-ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC);
-ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);
-ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);
-ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC);
-ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC);
-ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_length TSRMLS_DC);
-
-ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC);
-
-ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC);
+ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC);
+ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC);
+ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
+ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC);
+ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC);
+ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC);
+ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
+
+ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC);
+ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_length TSRMLS_DC);
+
+ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC);
+
+ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC);
ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC);
-ZEND_API int zend_get_object_classname(const zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC);
+ZEND_API int zend_get_object_classname(const zval *object, const char **class_name, zend_uint *class_name_len TSRMLS_DC);
ZEND_API char *zend_get_type_by_const(int type);
#define getThis() (this_ptr)
@@ -353,6 +364,7 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC);
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC);
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC);
+ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type);
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC);
@@ -417,8 +429,8 @@ ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRML
ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC);
ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long r TSRMLS_DC);
ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC);
-ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate TSRMLS_DC);
-ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC);
+ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str, int duplicate TSRMLS_DC);
+ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, int duplicate TSRMLS_DC);
ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC);
#define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key)+1, __n TSRMLS_CC)
@@ -495,7 +507,11 @@ ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci
ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...);
-ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC);
+ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC);
+
+ZEND_API int zend_delete_global_variable(const char *name, int name_len TSRMLS_DC);
+
+ZEND_API int zend_delete_global_variable_ex(const char *name, int name_len, ulong hash_value TSRMLS_DC);
ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC);
@@ -517,54 +533,64 @@ END_EXTERN_C()
#define CHECK_ZVAL_STRING_REL(z)
#endif
-#define ZVAL_RESOURCE(z, l) { \
- Z_TYPE_P(z) = IS_RESOURCE; \
- Z_LVAL_P(z) = l; \
- }
+#define CHECK_ZVAL_NULL_PATH(p) (Z_STRLEN_P(p) != strlen(Z_STRVAL_P(p)))
+#define CHECK_NULL_PATH(p, l) (strlen(p) != l)
-#define ZVAL_BOOL(z, b) { \
- Z_TYPE_P(z) = IS_BOOL; \
- Z_LVAL_P(z) = ((b) != 0); \
- }
+#define ZVAL_RESOURCE(z, l) do { \
+ zval *__z = (z); \
+ Z_LVAL_P(__z) = l; \
+ Z_TYPE_P(__z) = IS_RESOURCE;\
+ } while (0)
+
+#define ZVAL_BOOL(z, b) do { \
+ zval *__z = (z); \
+ Z_LVAL_P(__z) = ((b) != 0); \
+ Z_TYPE_P(__z) = IS_BOOL; \
+ } while (0)
#define ZVAL_NULL(z) { \
Z_TYPE_P(z) = IS_NULL; \
}
#define ZVAL_LONG(z, l) { \
- Z_TYPE_P(z) = IS_LONG; \
- Z_LVAL_P(z) = l; \
+ zval *__z = (z); \
+ Z_LVAL_P(__z) = l; \
+ Z_TYPE_P(__z) = IS_LONG; \
}
#define ZVAL_DOUBLE(z, d) { \
- Z_TYPE_P(z) = IS_DOUBLE; \
- Z_DVAL_P(z) = d; \
+ zval *__z = (z); \
+ Z_DVAL_P(__z) = d; \
+ Z_TYPE_P(__z) = IS_DOUBLE; \
}
-#define ZVAL_STRING(z, s, duplicate) { \
- const char *__s=(s); \
- Z_STRLEN_P(z) = strlen(__s); \
- Z_STRVAL_P(z) = (duplicate?estrndup(__s, Z_STRLEN_P(z)):(char*)__s);\
- Z_TYPE_P(z) = IS_STRING; \
- }
-
-#define ZVAL_STRINGL(z, s, l, duplicate) { \
- const char *__s=(s); int __l=l; \
- Z_STRLEN_P(z) = __l; \
- Z_STRVAL_P(z) = (duplicate?estrndup(__s, __l):(char*)__s);\
- Z_TYPE_P(z) = IS_STRING; \
- }
-
-#define ZVAL_EMPTY_STRING(z) { \
- Z_STRLEN_P(z) = 0; \
- Z_STRVAL_P(z) = STR_EMPTY_ALLOC();\
- Z_TYPE_P(z) = IS_STRING; \
- }
+#define ZVAL_STRING(z, s, duplicate) do { \
+ const char *__s=(s); \
+ zval *__z = (z); \
+ Z_STRLEN_P(__z) = strlen(__s); \
+ Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\
+ Z_TYPE_P(__z) = IS_STRING; \
+ } while (0)
+
+#define ZVAL_STRINGL(z, s, l, duplicate) do { \
+ const char *__s=(s); int __l=l; \
+ zval *__z = (z); \
+ Z_STRLEN_P(__z) = __l; \
+ Z_STRVAL_P(__z) = (duplicate?estrndup(__s, __l):(char*)__s);\
+ Z_TYPE_P(__z) = IS_STRING; \
+ } while (0)
+
+#define ZVAL_EMPTY_STRING(z) do { \
+ zval *__z = (z); \
+ Z_STRLEN_P(__z) = 0; \
+ Z_STRVAL_P(__z) = STR_EMPTY_ALLOC();\
+ Z_TYPE_P(__z) = IS_STRING; \
+ } while (0)
#define ZVAL_ZVAL(z, zv, copy, dtor) { \
zend_uchar is_ref = Z_ISREF_P(z); \
zend_uint refcount = Z_REFCOUNT_P(z); \
- *(z) = *(zv); \
+ ZVAL_COPY_VALUE(z, zv); \
if (copy) { \
zval_copy_ctor(z); \
} \
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 00ac438280..0b0e8632c1 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -344,9 +344,9 @@ typedef struct _zend_mm_block_info {
#if ZEND_DEBUG
typedef struct _zend_mm_debug_info {
- char *filename;
+ const char *filename;
uint lineno;
- char *orig_filename;
+ const char *orig_filename;
uint orig_lineno;
size_t size;
#if ZEND_MM_HEAP_PROTECTION
@@ -439,6 +439,7 @@ struct _zend_mm_heap {
zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2];
zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS];
zend_mm_free_block *rest_buckets[2];
+ int rest_count;
#if ZEND_MM_CACHE_STAT
struct {
int count;
@@ -459,6 +460,10 @@ struct _zend_mm_heap {
sizeof(zend_mm_free_block*) * 2 - \
sizeof(zend_mm_small_free_block))
+#define ZEND_MM_REST_BLOCK ((zend_mm_free_block**)(zend_uintptr_t)(1))
+
+#define ZEND_MM_MAX_REST_BLOCKS 16
+
#if ZEND_MM_COOKIES
static unsigned int _zend_mm_cookie = 0;
@@ -659,7 +664,7 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
static inline unsigned int zend_mm_high_bit(size_t _size)
{
-#if defined(__GNUC__) && defined(i386)
+#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
unsigned int n;
__asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size));
@@ -685,7 +690,7 @@ static inline unsigned int zend_mm_high_bit(size_t _size)
static inline unsigned int zend_mm_low_bit(size_t _size)
{
-#if defined(__GNUC__) && defined(i386)
+#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
unsigned int n;
__asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size));
@@ -715,23 +720,6 @@ static inline unsigned int zend_mm_low_bit(size_t _size)
#endif
}
-static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
-{
- zend_mm_free_block *prev, *next;
-
- ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
-
- if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
- mm_block->parent = NULL;
- }
-
- prev = heap->rest_buckets[0];
- next = prev->next_free_block;
- mm_block->prev_free_block = prev;
- mm_block->next_free_block = next;
- prev->next_free_block = next->prev_free_block = mm_block;
-}
-
static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
{
size_t size;
@@ -858,12 +846,45 @@ subst_block:
heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
}
}
+ } else if (UNEXPECTED(mm_block->parent == ZEND_MM_REST_BLOCK)) {
+ heap->rest_count--;
} else if (UNEXPECTED(mm_block->parent != NULL)) {
goto subst_block;
}
}
}
+static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
+{
+ zend_mm_free_block *prev, *next;
+
+ while (heap->rest_count >= ZEND_MM_MAX_REST_BLOCKS) {
+ zend_mm_free_block *p = heap->rest_buckets[1];
+
+ if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(p))) {
+ heap->rest_count--;
+ }
+ prev = p->prev_free_block;
+ next = p->next_free_block;
+ prev->next_free_block = next;
+ next->prev_free_block = prev;
+ zend_mm_add_to_free_list(heap, p);
+ }
+
+ if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
+ mm_block->parent = ZEND_MM_REST_BLOCK;
+ heap->rest_count++;
+ }
+
+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
+
+ prev = heap->rest_buckets[0];
+ next = prev->next_free_block;
+ mm_block->prev_free_block = prev;
+ mm_block->next_free_block = next;
+ prev->next_free_block = next->prev_free_block = mm_block;
+}
+
static inline void zend_mm_init(zend_mm_heap *heap)
{
zend_mm_free_block* p;
@@ -888,6 +909,7 @@ static inline void zend_mm_init(zend_mm_heap *heap)
heap->large_free_buckets[i] = NULL;
}
heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
+ heap->rest_count = 0;
}
static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment)
@@ -1126,6 +1148,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers,
}
}
mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap);
+ mm_heap->rest_count = 0;
free(heap);
heap = mm_heap;
@@ -1578,6 +1601,13 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent
zend_mm_segment *prev;
int internal;
+ if (!heap->use_zend_alloc) {
+ if (full_shutdown) {
+ free(heap);
+ }
+ return;
+ }
+
if (heap->reserve) {
#if ZEND_DEBUG
if (!silent) {
@@ -1642,27 +1672,63 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent
internal = heap->internal;
storage = heap->storage;
segment = heap->segments_list;
- while (segment) {
- prev = segment;
- segment = segment->next_segment;
- ZEND_MM_STORAGE_FREE(prev);
- }
if (full_shutdown) {
+ while (segment) {
+ prev = segment;
+ segment = segment->next_segment;
+ ZEND_MM_STORAGE_FREE(prev);
+ }
+ heap->segments_list = NULL;
storage->handlers->dtor(storage);
if (!internal) {
free(heap);
}
} else {
+ if (segment) {
+#ifndef ZEND_WIN32
+ if (heap->reserve_size) {
+ while (segment->next_segment) {
+ prev = segment;
+ segment = segment->next_segment;
+ ZEND_MM_STORAGE_FREE(prev);
+ }
+ heap->segments_list = segment;
+ } else {
+#endif
+ do {
+ prev = segment;
+ segment = segment->next_segment;
+ ZEND_MM_STORAGE_FREE(prev);
+ } while (segment);
+ heap->segments_list = NULL;
+#ifndef ZEND_WIN32
+ }
+#endif
+ }
if (heap->compact_size &&
heap->real_peak > heap->compact_size) {
storage->handlers->compact(storage);
}
- heap->segments_list = NULL;
zend_mm_init(heap);
- heap->real_size = 0;
- heap->real_peak = 0;
+ if (heap->segments_list) {
+ heap->real_size = heap->segments_list->size;
+ heap->real_peak = heap->segments_list->size;
+ } else {
+ heap->real_size = 0;
+ heap->real_peak = 0;
+ }
heap->size = 0;
heap->peak = 0;
+ if (heap->segments_list) {
+ /* mark segment as a free block */
+ zend_mm_free_block *b = (zend_mm_free_block*)((char*)heap->segments_list + ZEND_MM_ALIGNED_SEGMENT_SIZE);
+ size_t block_size = heap->segments_list->size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
+
+ ZEND_MM_MARK_FIRST_BLOCK(b);
+ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(b, block_size));
+ ZEND_MM_BLOCK(b, ZEND_MM_FREE_BLOCK, block_size);
+ zend_mm_add_to_free_list(heap, b);
+ }
if (heap->reserve_size) {
heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
}
@@ -1684,7 +1750,7 @@ static void zend_mm_safe_error(zend_mm_heap *heap,
heap->reserve = NULL;
}
if (heap->overflow == 0) {
- char *error_filename;
+ const char *error_filename;
uint error_lineno;
TSRMLS_FETCH();
if (zend_is_compiling(TSRMLS_C)) {
@@ -1816,6 +1882,11 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
size_t segment_size;
zend_mm_segment *segment;
int keep_rest = 0;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
+
+ HANDLE_BLOCK_INTERRUPTIONS();
if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
size_t index = ZEND_MM_BUCKET_INDEX(true_size);
@@ -1836,6 +1907,7 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
heap->cached -= true_size;
ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return ZEND_MM_DATA_OF(best_fit);
}
#if ZEND_MM_CACHE_STAT
@@ -1889,8 +1961,6 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
segment_size = heap->block_size;
}
- HANDLE_BLOCK_INTERRUPTIONS();
-
if (segment_size < true_size ||
heap->real_size + segment_size > heap->limit) {
/* Memory limit overflow */
@@ -1912,8 +1982,8 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
#if ZEND_MM_CACHE
zend_mm_free_cache(heap);
#endif
- HANDLE_UNBLOCK_INTERRUPTIONS();
out_of_memory:
+ HANDLE_UNBLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
#else
@@ -1941,7 +2011,6 @@ out_of_memory:
} else {
zend_mm_finished_searching_for_block:
/* remove from free list */
- HANDLE_BLOCK_INTERRUPTIONS();
ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
ZEND_MM_CHECK_COOKIE(best_fit);
ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
@@ -1989,11 +2058,15 @@ static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND
zend_mm_block *mm_block;
zend_mm_block *next_block;
size_t size;
-
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
if (!ZEND_MM_VALID_PTR(p)) {
return;
}
+ HANDLE_BLOCK_INTERRUPTIONS();
+
mm_block = ZEND_MM_HEADER_OF(p);
size = ZEND_MM_BLOCK_SIZE(mm_block);
ZEND_MM_CHECK_PROTECTION(mm_block);
@@ -2016,12 +2089,11 @@ static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND
heap->cache_stat[index].max_count = heap->cache_stat[index].count;
}
#endif
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return;
}
#endif
- HANDLE_BLOCK_INTERRUPTIONS();
-
heap->size -= size;
next_block = ZEND_MM_BLOCK_AT(mm_block, size);
@@ -2051,10 +2123,15 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
size_t true_size;
size_t orig_size;
void *ptr;
-
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
+
+ HANDLE_BLOCK_INTERRUPTIONS();
+
mm_block = ZEND_MM_HEADER_OF(p);
true_size = ZEND_MM_TRUE_SIZE(size);
orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
@@ -2070,7 +2147,6 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
zend_mm_free_block *new_free_block;
- HANDLE_BLOCK_INTERRUPTIONS();
next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
@@ -2086,9 +2162,9 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
/* add the new free block to the free list */
zend_mm_add_to_free_list(heap, new_free_block);
heap->size += (true_size - orig_size);
- HANDLE_UNBLOCK_INTERRUPTIONS();
}
ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
@@ -2131,6 +2207,7 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
}
#endif
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return ptr;
}
}
@@ -2145,7 +2222,6 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
size_t remaining_size = block_size - true_size;
- HANDLE_BLOCK_INTERRUPTIONS();
zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
@@ -2176,7 +2252,6 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
return p;
} else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
- HANDLE_BLOCK_INTERRUPTIONS();
zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
goto realloc_segment;
}
@@ -2187,7 +2262,6 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
size_t block_size;
size_t remaining_size;
- HANDLE_BLOCK_INTERRUPTIONS();
realloc_segment:
/* segment size, size of block and size of guard block */
if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
@@ -2220,8 +2294,8 @@ realloc_segment:
#if ZEND_MM_CACHE
zend_mm_free_cache(heap);
#endif
- HANDLE_UNBLOCK_INTERRUPTIONS();
out_of_memory:
+ HANDLE_UNBLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
#else
@@ -2285,6 +2359,7 @@ out_of_memory:
memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
#endif
_zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return ptr;
}
@@ -2379,7 +2454,7 @@ ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_
return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
}
-#if defined(__GNUC__) && defined(i386)
+#if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
{
@@ -2473,12 +2548,18 @@ ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset
ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
void *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
+ HANDLE_BLOCK_INTERRUPTIONS();
p = _safe_emalloc(nmemb, size, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
memset(p, 0, size * nmemb);
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
@@ -2486,26 +2567,40 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
int length;
char *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
+
+ HANDLE_BLOCK_INTERRUPTIONS();
length = strlen(s)+1;
p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
memcpy(p, s, length);
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
+
+ HANDLE_BLOCK_INTERRUPTIONS();
p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
if (UNEXPECTED(p == NULL)) {
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
memcpy(p, s, length);
p[length] = 0;
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
@@ -2513,15 +2608,22 @@ ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_
ZEND_API char *zend_strndup(const char *s, uint length)
{
char *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
+
+ HANDLE_BLOCK_INTERRUPTIONS();
p = (char *) malloc(length+1);
if (UNEXPECTED(p == NULL)) {
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
if (length) {
memcpy(p, s, length);
}
p[length] = 0;
+ HANDLE_UNBLOCK_INTERRUPTIONS();
return p;
}
@@ -2564,17 +2666,17 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC)
static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC)
{
- char *tmp;
- alloc_globals->mm_heap = zend_mm_startup();
+ char *tmp = getenv("USE_ZEND_ALLOC");
- tmp = getenv("USE_ZEND_ALLOC");
- if (tmp) {
- alloc_globals->mm_heap->use_zend_alloc = zend_atoi(tmp, 0);
- if (!alloc_globals->mm_heap->use_zend_alloc) {
- alloc_globals->mm_heap->_malloc = malloc;
- alloc_globals->mm_heap->_free = free;
- alloc_globals->mm_heap->_realloc = realloc;
- }
+ if (tmp && !zend_atoi(tmp, 0)) {
+ alloc_globals->mm_heap = malloc(sizeof(struct _zend_mm_heap));
+ memset(alloc_globals->mm_heap, 0, sizeof(struct _zend_mm_heap));
+ alloc_globals->mm_heap->use_zend_alloc = 0;
+ alloc_globals->mm_heap->_malloc = malloc;
+ alloc_globals->mm_heap->_free = free;
+ alloc_globals->mm_heap->_realloc = realloc;
+ } else {
+ alloc_globals->mm_heap = zend_mm_startup();
}
}
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index c4ba0d5d80..b8b800e0d9 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -44,9 +44,9 @@
typedef struct _zend_leak_info {
void *addr;
size_t size;
- char *filename;
+ const char *filename;
uint lineno;
- char *orig_filename;
+ const char *orig_filename;
uint orig_lineno;
} zend_leak_info;
@@ -161,45 +161,31 @@ ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC);
END_EXTERN_C()
-/* Macroses for zend_fast_cache.h compatibility */
-
-#define ZEND_FAST_ALLOC(p, type, fc_type) \
- (p) = (type *) emalloc(sizeof(type))
-
-#define ZEND_FAST_FREE(p, fc_type) \
- efree(p)
-
-#define ZEND_FAST_ALLOC_REL(p, type, fc_type) \
- (p) = (type *) emalloc_rel(sizeof(type))
-
-#define ZEND_FAST_FREE_REL(p, fc_type) \
- efree_rel(p)
-
/* fast cache for zval's */
#define ALLOC_ZVAL(z) \
- ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)
+ (z) = (zval *) emalloc(sizeof(zval))
#define FREE_ZVAL(z) \
- ZEND_FAST_FREE(z, ZVAL_CACHE_LIST)
+ efree_rel(z)
#define ALLOC_ZVAL_REL(z) \
- ZEND_FAST_ALLOC_REL(z, zval, ZVAL_CACHE_LIST)
+ (z) = (zval *) emalloc_rel(sizeof(zval))
#define FREE_ZVAL_REL(z) \
- ZEND_FAST_FREE_REL(z, ZVAL_CACHE_LIST)
+ efree_rel(z)
/* fast cache for HashTables */
#define ALLOC_HASHTABLE(ht) \
- ZEND_FAST_ALLOC(ht, HashTable, HASHTABLE_CACHE_LIST)
+ (ht) = (HashTable *) emalloc(sizeof(HashTable))
#define FREE_HASHTABLE(ht) \
- ZEND_FAST_FREE(ht, HASHTABLE_CACHE_LIST)
+ efree(ht)
#define ALLOC_HASHTABLE_REL(ht) \
- ZEND_FAST_ALLOC_REL(ht, HashTable, HASHTABLE_CACHE_LIST)
+ (ht) = (HashTable *) emalloc_rel(sizeof(HashTable))
#define FREE_HASHTABLE_REL(ht) \
- ZEND_FAST_FREE_REL(ht, HASHTABLE_CACHE_LIST)
+ efree_rel(ht)
/* Heap functions */
typedef struct _zend_mm_heap zend_mm_heap;
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 8d39a31ad0..eab98ed944 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -50,10 +50,12 @@ static ZEND_FUNCTION(method_exists);
static ZEND_FUNCTION(property_exists);
static ZEND_FUNCTION(class_exists);
static ZEND_FUNCTION(interface_exists);
+static ZEND_FUNCTION(trait_exists);
static ZEND_FUNCTION(function_exists);
static ZEND_FUNCTION(class_alias);
#if ZEND_DEBUG
static ZEND_FUNCTION(leak);
+static ZEND_FUNCTION(leak_variable);
#ifdef ZEND_TEST_EXCEPTIONS
static ZEND_FUNCTION(crash);
#endif
@@ -70,6 +72,7 @@ static ZEND_FUNCTION(restore_error_handler);
static ZEND_FUNCTION(set_exception_handler);
static ZEND_FUNCTION(restore_exception_handler);
static ZEND_FUNCTION(get_declared_classes);
+static ZEND_FUNCTION(get_declared_traits);
static ZEND_FUNCTION(get_declared_interfaces);
static ZEND_FUNCTION(get_defined_functions);
static ZEND_FUNCTION(get_defined_vars);
@@ -140,6 +143,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2)
ZEND_ARG_INFO(0, object)
ZEND_ARG_INFO(0, class_name)
+ ZEND_ARG_INFO(0, allow_string)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1)
@@ -169,6 +173,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1)
ZEND_ARG_INFO(0, autoload)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1)
+ ZEND_ARG_INFO(0, traitname)
+ ZEND_ARG_INFO(0, autoload)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1)
ZEND_ARG_INFO(0, function_name)
ZEND_END_ARG_INFO()
@@ -179,6 +188,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
ZEND_ARG_INFO(0, autoload)
ZEND_END_ARG_INFO()
+#if ZEND_DEBUG
+ZEND_BEGIN_ARG_INFO_EX(arginfo_leak_variable, 0, 0, 1)
+ ZEND_ARG_INFO(0, variable)
+ ZEND_ARG_INFO(0, leak_data)
+ZEND_END_ARG_INFO()
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
ZEND_ARG_INFO(0, message)
ZEND_ARG_INFO(0, error_type)
@@ -212,6 +228,11 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
ZEND_ARG_INFO(0, options)
+ ZEND_ARG_INFO(0, limit)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0)
+ ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
@@ -240,10 +261,12 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
ZEND_FE(property_exists, arginfo_property_exists)
ZEND_FE(class_exists, arginfo_class_exists)
ZEND_FE(interface_exists, arginfo_class_exists)
+ ZEND_FE(trait_exists, arginfo_trait_exists)
ZEND_FE(function_exists, arginfo_function_exists)
ZEND_FE(class_alias, arginfo_class_alias)
#if ZEND_DEBUG
ZEND_FE(leak, NULL)
+ ZEND_FE(leak_variable, arginfo_leak_variable)
#ifdef ZEND_TEST_EXCEPTIONS
ZEND_FE(crash, NULL)
#endif
@@ -262,6 +285,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
ZEND_FE(set_exception_handler, arginfo_set_exception_handler)
ZEND_FE(restore_exception_handler, arginfo_zend__void)
ZEND_FE(get_declared_classes, arginfo_zend__void)
+ ZEND_FE(get_declared_traits, arginfo_zend__void)
ZEND_FE(get_declared_interfaces, arginfo_zend__void)
ZEND_FE(get_defined_functions, arginfo_zend__void)
ZEND_FE(get_defined_vars, arginfo_zend__void)
@@ -272,7 +296,7 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
ZEND_FE(get_extension_funcs, arginfo_extension_loaded)
ZEND_FE(get_defined_constants, arginfo_get_defined_constants)
ZEND_FE(debug_backtrace, arginfo_debug_backtrace)
- ZEND_FE(debug_print_backtrace, arginfo_debug_backtrace)
+ ZEND_FE(debug_print_backtrace, arginfo_debug_print_backtrace)
#if ZEND_DEBUG
ZEND_FE(zend_test_func, NULL)
#ifdef ZTS
@@ -682,7 +706,10 @@ repeat:
zval_ptr_dtor(&val_free);
}
c.flags = case_sensitive; /* non persistent */
- c.name = zend_strndup(name, name_len);
+ c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len);
+ if(c.name == NULL) {
+ RETURN_FALSE;
+ }
c.name_len = name_len+1;
c.module_number = PHP_USER_CONSTANT;
if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
@@ -721,7 +748,7 @@ ZEND_FUNCTION(defined)
ZEND_FUNCTION(get_class)
{
zval *obj = NULL;
- char *name = "";
+ const char *name = "";
zend_uint name_len = 0;
int dup;
@@ -769,7 +796,7 @@ ZEND_FUNCTION(get_parent_class)
{
zval *arg;
zend_class_entry *ce = NULL;
- char *name;
+ const char *name;
zend_uint name_length;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) {
@@ -823,10 +850,11 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
return;
}
/*
- allow_string - is_a default is no, is_subclass_of is yes.
- if it's allowed, then the autoloader will be called if the class does not exist.
- default behaviour is different, as 'is_a' usage is normally to test mixed return values
- */
+ * allow_string - is_a default is no, is_subclass_of is yes.
+ * if it's allowed, then the autoloader will be called if the class does not exist.
+ * default behaviour is different, as 'is_a' used to be used to test mixed return values
+ * and there is no easy way to deprecate this.
+ */
if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
zend_class_entry **the_ce;
@@ -840,12 +868,12 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
RETURN_FALSE;
}
- if (zend_lookup_class_ex(class_name, class_name_len, 0, &ce TSRMLS_CC) == FAILURE) {
+ if (zend_lookup_class_ex(class_name, class_name_len, NULL, 0, &ce TSRMLS_CC) == FAILURE) {
retval = 0;
} else {
if (only_subclass && instance_ce == *ce) {
retval = 0;
- } else {
+ } else {
retval = instanceof_function(instance_ce, *ce TSRMLS_CC);
}
}
@@ -873,49 +901,53 @@ ZEND_FUNCTION(is_a)
/* {{{ add_class_vars */
-static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC)
+static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
{
- if (zend_hash_num_elements(properties) > 0) {
- HashPosition pos;
- zval **prop;
-
- zend_hash_internal_pointer_reset_ex(properties, &pos);
- while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
- char *key, *class_name, *prop_name;
- uint key_len;
- ulong num_index;
- int prop_name_len = 0;
- zval *prop_copy;
- zend_property_info *property_info;
- zval zprop_name;
-
- zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
- zend_hash_move_forward_ex(properties, &pos);
-
- zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
- prop_name_len = strlen(prop_name);
-
- ZVAL_STRINGL(&zprop_name, prop_name, prop_name_len, 0);
- property_info = zend_get_property_info(ce, &zprop_name, 1 TSRMLS_CC);
-
- if (!property_info || property_info == &EG(std_property_info)) {
- continue;
- }
+ HashPosition pos;
+ zend_property_info *prop_info;
+ zval *prop, *prop_copy;
+ char *key;
+ uint key_len;
+ ulong num_index;
- /* copy: enforce read only access */
- ALLOC_ZVAL(prop_copy);
- *prop_copy = **prop;
- zval_copy_ctor(prop_copy);
- INIT_PZVAL(prop_copy);
+ zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+ while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
+ zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
+ zend_hash_move_forward_ex(&ce->properties_info, &pos);
+ if (((prop_info->flags & ZEND_ACC_SHADOW) &&
+ prop_info->ce != EG(scope)) ||
+ ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+ !zend_check_protected(prop_info->ce, EG(scope))) ||
+ ((prop_info->flags & ZEND_ACC_PRIVATE) &&
+ ce != EG(scope) &&
+ prop_info->ce != EG(scope))) {
+ continue;
+ }
+ prop = NULL;
+ if (prop_info->offset >= 0) {
+ if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
+ prop = ce->default_static_members_table[prop_info->offset];
+ } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
+ prop = ce->default_properties_table[prop_info->offset];
+ }
+ }
+ if (!prop) {
+ continue;
+ }
- /* this is necessary to make it able to work with default array
- * properties, returned to user */
- if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
- zval_update_constant(&prop_copy, 0 TSRMLS_CC);
- }
+ /* copy: enforce read only access */
+ ALLOC_ZVAL(prop_copy);
+ *prop_copy = *prop;
+ zval_copy_ctor(prop_copy);
+ INIT_PZVAL(prop_copy);
- add_assoc_zval(return_value, prop_name, prop_copy);
+ /* this is necessary to make it able to work with default array
+ * properties, returned to user */
+ if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+ zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
+
+ add_assoc_zval(return_value, key, prop_copy);
}
}
/* }}} */
@@ -938,8 +970,8 @@ ZEND_FUNCTION(get_class_vars)
} else {
array_init(return_value);
zend_update_class_constants(*pce TSRMLS_CC);
- add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC);
- add_class_vars(*pce, CE_STATIC_MEMBERS(*pce), return_value TSRMLS_CC);
+ add_class_vars(*pce, 0, return_value TSRMLS_CC);
+ add_class_vars(*pce, 1, return_value TSRMLS_CC);
}
}
/* }}} */
@@ -953,7 +985,8 @@ ZEND_FUNCTION(get_object_vars)
zval **value;
HashTable *properties;
HashPosition pos;
- char *key, *prop_name, *class_name;
+ char *key;
+ const char *prop_name, *class_name;
uint key_len;
ulong num_index;
zend_object *zobj;
@@ -1088,7 +1121,7 @@ ZEND_FUNCTION(method_exists)
if (Z_TYPE_P(klass) == IS_OBJECT
&& Z_OBJ_HT_P(klass)->get_method != NULL
- && (func = Z_OBJ_HT_P(klass)->get_method(&klass, method_name, method_len TSRMLS_CC)) != NULL
+ && (func = Z_OBJ_HT_P(klass)->get_method(&klass, method_name, method_len, NULL TSRMLS_CC)) != NULL
) {
if (func->type == ZEND_INTERNAL_FUNCTION
&& (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0
@@ -1097,9 +1130,9 @@ ZEND_FUNCTION(method_exists)
RETVAL_BOOL((func->common.scope == zend_ce_closure
&& (method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) ? 1 : 0);
-
+
efree(lcname);
- efree(((zend_internal_function*)func)->function_name);
+ efree((char*)((zend_internal_function*)func)->function_name);
efree(func);
return;
}
@@ -1154,7 +1187,7 @@ ZEND_FUNCTION(property_exists)
if (Z_TYPE_P(object) == IS_OBJECT &&
Z_OBJ_HANDLER_P(object, has_property) &&
- Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2 TSRMLS_CC)) {
+ Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, 0 TSRMLS_CC)) {
RETURN_TRUE;
}
RETURN_FALSE;
@@ -1194,11 +1227,11 @@ ZEND_FUNCTION(class_exists)
found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
free_alloca(lc_name, use_heap);
- RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
+ RETURN_BOOL(found == SUCCESS && !(((*ce)->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
}
if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
- RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0);
+ RETURN_BOOL(((*ce)->ce_flags & (ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT - ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) == 0);
} else {
RETURN_FALSE;
}
@@ -1248,6 +1281,49 @@ ZEND_FUNCTION(interface_exists)
}
/* }}} */
+/* {{{ proto bool trait_exists(string traitname [, bool autoload])
+ Checks if the trait exists */
+ZEND_FUNCTION(trait_exists)
+{
+ char *trait_name, *lc_name;
+ zend_class_entry **ce;
+ int trait_name_len;
+ int found;
+ zend_bool autoload = 1;
+ ALLOCA_FLAG(use_heap)
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &trait_name, &trait_name_len, &autoload) == FAILURE) {
+ return;
+ }
+
+ if (!autoload) {
+ char *name;
+ int len;
+
+ lc_name = do_alloca(trait_name_len + 1, use_heap);
+ zend_str_tolower_copy(lc_name, trait_name, trait_name_len);
+
+ /* Ignore leading "\" */
+ name = lc_name;
+ len = trait_name_len;
+ if (lc_name[0] == '\\') {
+ name = &lc_name[1];
+ len--;
+ }
+
+ found = zend_hash_find(EG(class_table), name, len+1, (void **) &ce);
+ free_alloca(lc_name, use_heap);
+ RETURN_BOOL(found == SUCCESS && (((*ce)->ce_flags & ZEND_ACC_TRAIT) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS));
+ }
+
+ if (zend_lookup_class(trait_name, trait_name_len, &ce TSRMLS_CC) == SUCCESS) {
+ RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_TRAIT) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
/* {{{ proto bool function_exists(string function_name)
Checks if the function exists */
@@ -1347,6 +1423,28 @@ ZEND_FUNCTION(leak)
}
/* }}} */
+/* {{{ proto leak_variable(mixed variable [, bool leak_data]) */
+ZEND_FUNCTION(leak_variable)
+{
+ zval *zv;
+ zend_bool leak_data = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &zv, &leak_data) == FAILURE) {
+ return;
+ }
+
+ if (!leak_data) {
+ zval_add_ref(&zv);
+ } else if (Z_TYPE_P(zv) == IS_RESOURCE) {
+ zend_list_addref(Z_RESVAL_P(zv));
+ } else if (Z_TYPE_P(zv) == IS_OBJECT) {
+ Z_OBJ_HANDLER_P(zv, add_ref)(zv TSRMLS_CC);
+ } else {
+ zend_error(E_WARNING, "Leaking non-zval data is only applicable to resources and objects");
+ }
+}
+/* }}} */
+
#ifdef ZEND_TEST_EXCEPTIONS
ZEND_FUNCTION(crash)
@@ -1364,6 +1462,7 @@ ZEND_FUNCTION(crash)
ZEND_FUNCTION(get_included_files)
{
char *entry;
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -1415,7 +1514,7 @@ ZEND_FUNCTION(set_error_handler)
zval *error_handler;
zend_bool had_orig_error_handler=0;
char *error_handler_name = NULL;
- long error_type = E_ALL | E_STRICT;
+ long error_type = E_ALL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &error_handler, &error_type) == FAILURE) {
return;
@@ -1557,12 +1656,28 @@ static int copy_class_or_interface_name(zend_class_entry **pce TSRMLS_DC, int nu
return ZEND_HASH_APPLY_KEEP;
}
+/* {{{ proto array get_declared_traits()
+ Returns an array of all declared traits. */
+ZEND_FUNCTION(get_declared_traits)
+{
+ zend_uint mask = ZEND_ACC_TRAIT;
+ zend_uint comply = 1;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ array_init(return_value);
+ zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, return_value, mask, comply);
+}
+/* }}} */
+
/* {{{ proto array get_declared_classes()
Returns an array of all declared classes. */
ZEND_FUNCTION(get_declared_classes)
{
- zend_uint mask = ZEND_ACC_INTERFACE;
+ zend_uint mask = ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT & ~ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
zend_uint comply = 0;
if (zend_parse_parameters_none() == FAILURE) {
@@ -1751,7 +1866,7 @@ ZEND_FUNCTION(zend_thread_id)
Get the resource type name for a given resource */
ZEND_FUNCTION(get_resource_type)
{
- char *resource_type;
+ const char *resource_type;
zval *z_resource_type;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_resource_type) == FAILURE) {
@@ -1929,21 +2044,22 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
}
}
-/* {{{ proto void debug_print_backtrace([int options]) */
+/* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
ZEND_FUNCTION(debug_print_backtrace)
{
zend_execute_data *ptr, *skip;
- int lineno;
- char *function_name;
- char *filename;
- char *class_name = NULL;
+ int lineno, frameno = 0;
+ const char *function_name;
+ const char *filename;
+ const char *class_name = NULL;
char *call_type;
- char *include_filename = NULL;
+ const char *include_filename = NULL;
zval *arg_array = NULL;
int indent = 0;
long options = 0;
+ long limit = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &options, &limit) == FAILURE) {
return;
}
@@ -1952,9 +2068,10 @@ ZEND_FUNCTION(debug_print_backtrace)
/* skip debug_backtrace() */
ptr = ptr->prev_execute_data;
- while (ptr) {
- char *free_class_name = NULL;
+ while (ptr && (limit == 0 || frameno < limit)) {
+ const char *free_class_name = NULL;
+ frameno++;
class_name = call_type = NULL;
arg_array = NULL;
@@ -2015,7 +2132,7 @@ ZEND_FUNCTION(debug_print_backtrace)
function_name = "unknown";
build_filename_arg = 0;
} else
- switch (Z_LVAL(ptr->opline->op2.u.constant)) {
+ switch (ptr->opline->extended_value) {
case ZEND_EVAL:
function_name = "eval";
build_filename_arg = 0;
@@ -2043,7 +2160,7 @@ ZEND_FUNCTION(debug_print_backtrace)
if (build_filename_arg && include_filename) {
MAKE_STD_ZVAL(arg_array);
array_init(arg_array);
- add_next_index_string(arg_array, include_filename, 1);
+ add_next_index_string(arg_array, (char*)include_filename, 1);
}
call_type = NULL;
}
@@ -2082,21 +2199,21 @@ ZEND_FUNCTION(debug_print_backtrace)
ptr = skip->prev_execute_data;
++indent;
if (free_class_name) {
- efree(free_class_name);
+ efree((char*)free_class_name);
}
}
}
/* }}} */
-ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options TSRMLS_DC)
+ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC)
{
zend_execute_data *ptr, *skip;
- int lineno;
- char *function_name;
- char *filename;
- char *class_name;
- char *include_filename = NULL;
+ int lineno, frameno = 0;
+ const char *function_name;
+ const char *filename;
+ const char *class_name;
+ const char *include_filename = NULL;
zval *stack_frame;
ptr = EG(current_execute_data);
@@ -2113,7 +2230,8 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
array_init(return_value);
- while (ptr) {
+ while (ptr && (limit == 0 || frameno < limit)) {
+ frameno++;
MAKE_STD_ZVAL(stack_frame);
array_init(stack_frame);
@@ -2131,7 +2249,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
if (skip->op_array) {
filename = skip->op_array->filename;
lineno = skip->opline->lineno;
- add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1);
+ add_assoc_string_ex(stack_frame, "file", sizeof("file"), (char*)filename, 1);
add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno);
/* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
@@ -2148,7 +2266,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
break;
}
if (prev->op_array) {
- add_assoc_string_ex(stack_frame, "file", sizeof("file"), prev->op_array->filename, 1);
+ add_assoc_string_ex(stack_frame, "file", sizeof("file"), (char*)prev->op_array->filename, 1);
add_assoc_long_ex(stack_frame, "line", sizeof("line"), prev->opline->lineno);
break;
}
@@ -2160,17 +2278,17 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
function_name = ptr->function_state.function->common.function_name;
if (function_name) {
- add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
+ add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);
if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
if (ptr->function_state.function->common.scope) {
- add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ add_assoc_string_ex(stack_frame, "class", sizeof("class"), (char*)ptr->function_state.function->common.scope->name, 1);
} else {
zend_uint class_name_len;
int dup;
dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
- add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
+ add_assoc_string_ex(stack_frame, "class", sizeof("class"), (char*)class_name, dup);
}
if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
@@ -2180,7 +2298,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
} else if (ptr->function_state.function->common.scope) {
- add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ add_assoc_string_ex(stack_frame, "class", sizeof("class"), (char*)ptr->function_state.function->common.scope->name, 1);
add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
}
@@ -2199,7 +2317,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
function_name = "unknown";
build_filename_arg = 0;
} else
- switch (ptr->opline->op2.u.constant.value.lval) {
+ switch (ptr->opline->extended_value) {
case ZEND_EVAL:
function_name = "eval";
build_filename_arg = 0;
@@ -2234,11 +2352,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
if we have called include in the frame above - this is the file we have included.
*/
- add_next_index_string(arg_array, include_filename, 1);
+ add_next_index_string(arg_array, (char*)include_filename, 1);
add_assoc_zval_ex(stack_frame, "args", sizeof("args"), arg_array);
}
- add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
+ add_assoc_string_ex(stack_frame, "function", sizeof("function"), (char*)function_name, 1);
}
add_next_index_zval(return_value, stack_frame);
@@ -2251,17 +2369,18 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
/* }}} */
-/* {{{ proto array debug_backtrace([int options])
+/* {{{ proto array debug_backtrace([int options[, int limit]])
Return backtrace as array */
ZEND_FUNCTION(debug_backtrace)
{
long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
+ long limit = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &options) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &options, &limit) == FAILURE) {
return;
}
- zend_fetch_debug_backtrace(return_value, 1, options TSRMLS_CC);
+ zend_fetch_debug_backtrace(return_value, 1, options, limit TSRMLS_CC);
}
/* }}} */
diff --git a/Zend/zend_builtin_functions.h b/Zend/zend_builtin_functions.h
index 2508bd725d..a53bfb65a1 100644
--- a/Zend/zend_builtin_functions.h
+++ b/Zend/zend_builtin_functions.h
@@ -25,7 +25,7 @@
int zend_startup_builtin_functions(TSRMLS_D);
BEGIN_EXTERN_C()
-ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options TSRMLS_DC);
+ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC);
END_EXTERN_C()
#endif /* ZEND_BUILTIN_FUNCTIONS_H */
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index dbaade4c52..c7527b4ff9 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -37,6 +37,7 @@
typedef struct _zend_closure {
zend_object std;
zend_function func;
+ zval *this_ptr;
HashTable *debug_info;
} zend_closure;
@@ -70,11 +71,72 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */
efree(arguments);
/* destruct the function also, then - we have allocated it in get_method */
- efree(func->internal_function.function_name);
+ efree((char*)func->internal_function.function_name);
efree(func);
}
/* }}} */
+/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] )
+ Create a closure from another one and bind to another object and scope */
+ZEND_METHOD(Closure, bind)
+{
+ zval *newthis, *zclosure, *scope_arg = NULL;
+ zend_closure *closure;
+ zend_class_entry *ce, **ce_p;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) {
+ RETURN_NULL();
+ }
+
+ closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC);
+
+ if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) {
+ zend_error(E_WARNING, "Cannot bind an instance to a static closure");
+ }
+
+ if (scope_arg != NULL) { /* scope argument was given */
+ if (IS_ZEND_STD_OBJECT(*scope_arg)) {
+ ce = Z_OBJCE_P(scope_arg);
+ } else if (Z_TYPE_P(scope_arg) == IS_NULL) {
+ ce = NULL;
+ } else {
+ char *class_name;
+ int class_name_len;
+ zval tmp_zval;
+ INIT_ZVAL(tmp_zval);
+
+ if (Z_TYPE_P(scope_arg) == IS_STRING) {
+ class_name = Z_STRVAL_P(scope_arg);
+ class_name_len = Z_STRLEN_P(scope_arg);
+ } else {
+ tmp_zval = *scope_arg;
+ zval_copy_ctor(&tmp_zval);
+ convert_to_string(&tmp_zval);
+ class_name = Z_STRVAL(tmp_zval);
+ class_name_len = Z_STRLEN(tmp_zval);
+ }
+
+ if ((class_name_len == sizeof("static") - 1) &&
+ (memcmp("static", class_name, sizeof("static") - 1) == 0)) {
+ ce = closure->func.common.scope;
+ }
+ else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) {
+ zend_error(E_WARNING, "Class '%s' not found", class_name);
+ zval_dtor(&tmp_zval);
+ RETURN_NULL();
+ } else {
+ ce = *ce_p;
+ }
+ zval_dtor(&tmp_zval);
+ }
+ } else { /* scope argument not given; do not change the scope by default */
+ ce = closure->func.common.scope;
+ }
+
+ zend_create_closure(return_value, &closure->func, ce, newthis TSRMLS_CC);
+}
+/* }}} */
+
static zend_function *zend_closure_get_constructor(zval *object TSRMLS_DC) /* {{{ */
{
zend_error(E_RECOVERABLE_ERROR, "Instantiation of 'Closure' is not allowed");
@@ -95,7 +157,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC) /* {
invoke->common = closure->func.common;
invoke->type = ZEND_INTERNAL_FUNCTION;
- invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
+ invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & ZEND_ACC_RETURN_REFERENCE);
invoke->internal_function.handler = ZEND_MN(Closure___invoke);
invoke->internal_function.module = 0;
invoke->internal_function.scope = zend_ce_closure;
@@ -111,7 +173,14 @@ ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC) /
}
/* }}} */
-static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */
+ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC) /* {{{ */
+{
+ zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
+ return closure->this_ptr;
+}
+/* }}} */
+
+static zend_function *zend_closure_get_method(zval **object_ptr, char *method_name, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */
{
char *lc_name;
ALLOCA_FLAG(use_heap)
@@ -125,11 +194,11 @@ static zend_function *zend_closure_get_method(zval **object_ptr, char *method_na
return zend_get_closure_invoke_method(*object_ptr TSRMLS_CC);
}
free_alloca(lc_name, use_heap);
- return NULL;
+ return std_object_handlers.get_method(object_ptr, method_name, method_len, key TSRMLS_CC);
}
/* }}} */
-static zval *zend_closure_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
+static zval *zend_closure_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ZEND_CLOSURE_PROPERTY_ERROR();
Z_ADDREF(EG(uninitialized_zval));
@@ -137,20 +206,20 @@ static zval *zend_closure_read_property(zval *object, zval *member, int type TSR
}
/* }}} */
-static void zend_closure_write_property(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */
+static void zend_closure_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ZEND_CLOSURE_PROPERTY_ERROR();
}
/* }}} */
-static zval **zend_closure_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval **zend_closure_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ZEND_CLOSURE_PROPERTY_ERROR();
return NULL;
}
/* }}} */
-static int zend_closure_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */
+static int zend_closure_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
{
if (has_set_exists != 2) {
ZEND_CLOSURE_PROPERTY_ERROR();
@@ -159,7 +228,7 @@ static int zend_closure_has_property(zval *object, zval *member, int has_set_exi
}
/* }}} */
-static void zend_closure_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static void zend_closure_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ZEND_CLOSURE_PROPERTY_ERROR();
}
@@ -187,6 +256,10 @@ static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
efree(closure->debug_info);
}
+ if (closure->this_ptr) {
+ zval_ptr_dtor(&closure->this_ptr);
+ }
+
efree(closure);
}
/* }}} */
@@ -208,6 +281,17 @@ static zend_object_value zend_closure_new(zend_class_entry *class_type TSRMLS_DC
}
/* }}} */
+static zend_object_value zend_closure_clone(zval *zobject TSRMLS_DC) /* {{{ */
+{
+ zend_closure *closure = (zend_closure *)zend_object_store_get_object(zobject TSRMLS_CC);
+ zval result;
+
+ zend_create_closure(&result, &closure->func, closure->func.common.scope, closure->this_ptr TSRMLS_CC);
+ return Z_OBJVAL(result);
+}
+/* }}} */
+
+
int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */
{
zend_closure *closure;
@@ -219,10 +303,17 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function
closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
*fptr_ptr = &closure->func;
- if (zobj_ptr) {
- *zobj_ptr = NULL;
+ if (closure->this_ptr) {
+ if (zobj_ptr) {
+ *zobj_ptr = closure->this_ptr;
+ }
+ *ce_ptr = Z_OBJCE_P(closure->this_ptr);
+ } else {
+ if (zobj_ptr) {
+ *zobj_ptr = NULL;
+ }
+ *ce_ptr = closure->func.common.scope;
}
- *ce_ptr = NULL;
return SUCCESS;
}
/* }}} */
@@ -245,7 +336,12 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
MAKE_STD_ZVAL(val);
array_init(val);
zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*));
- zend_symtable_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL);
+ zend_hash_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL);
+ }
+
+ if (closure->this_ptr) {
+ Z_ADDREF_P(closure->this_ptr);
+ zend_symtable_update(closure->debug_info, "this", sizeof("this"), (void *) &closure->this_ptr, sizeof(zval *), NULL);
}
if (arg_info) {
@@ -272,7 +368,7 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
efree(name);
arg_info++;
}
- zend_symtable_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL);
+ zend_hash_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL);
}
}
@@ -280,15 +376,14 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
}
/* }}} */
-static HashTable *zend_closure_get_properties(zval *obj TSRMLS_DC) /* {{{ */
+static HashTable *zend_closure_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
{
zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj TSRMLS_CC);
- if (GC_G(gc_active)) {
- return (closure->func.type == ZEND_USER_FUNCTION) ? closure->func.op_array.static_variables : NULL;
- }
-
- return closure->std.properties;
+ *table = closure->this_ptr ? &closure->this_ptr : NULL;
+ *n = closure->this_ptr ? 1 : 0;
+ return (closure->func.type == ZEND_USER_FUNCTION) ?
+ closure->func.op_array.static_variables : NULL;
}
/* }}} */
@@ -300,8 +395,21 @@ ZEND_METHOD(Closure, __construct)
}
/* }}} */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bindto, 0, 0, 1)
+ ZEND_ARG_INFO(0, newthis)
+ ZEND_ARG_INFO(0, newscope)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_closure_bind, 0, 0, 2)
+ ZEND_ARG_INFO(0, closure)
+ ZEND_ARG_INFO(0, newthis)
+ ZEND_ARG_INFO(0, newscope)
+ZEND_END_ARG_INFO()
+
static const zend_function_entry closure_functions[] = {
ZEND_ME(Closure, __construct, NULL, ZEND_ACC_PRIVATE)
+ ZEND_ME(Closure, bind, arginfo_closure_bind, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ ZEND_MALIAS(Closure, bindTo, bind, arginfo_closure_bindto, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
@@ -325,59 +433,14 @@ void zend_register_closure_ce(TSRMLS_D) /* {{{ */
closure_handlers.has_property = zend_closure_has_property;
closure_handlers.unset_property = zend_closure_unset_property;
closure_handlers.compare_objects = zend_closure_compare_objects;
- closure_handlers.clone_obj = NULL;
+ closure_handlers.clone_obj = zend_closure_clone;
closure_handlers.get_debug_info = zend_closure_get_debug_info;
closure_handlers.get_closure = zend_closure_get_closure;
- closure_handlers.get_properties = zend_closure_get_properties;
+ closure_handlers.get_gc = zend_closure_get_gc;
}
/* }}} */
-static int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
-{
- HashTable *target = va_arg(args, HashTable*);
- zend_bool is_ref;
- zval *tmp;
-
- if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
- is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF;
-
- if (!EG(active_symbol_table)) {
- zend_rebuild_symbol_table(TSRMLS_C);
- }
- if (zend_hash_quick_find(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) {
- if (is_ref) {
- ALLOC_INIT_ZVAL(tmp);
- Z_SET_ISREF_P(tmp);
- zend_hash_quick_add(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), (void**)&p);
- } else {
- tmp = EG(uninitialized_zval_ptr);
- zend_error(E_NOTICE,"Undefined variable: %s", key->arKey);
- }
- } else {
- if (is_ref) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
- tmp = *p;
- } else if (Z_ISREF_PP(p)) {
- ALLOC_INIT_ZVAL(tmp);
- *tmp = **p;
- zval_copy_ctor(tmp);
- Z_SET_REFCOUNT_P(tmp, 0);
- Z_UNSET_ISREF_P(tmp);
- } else {
- tmp = *p;
- }
- }
- } else {
- tmp = *p;
- }
- if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), NULL) == SUCCESS) {
- Z_ADDREF_P(tmp);
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-ZEND_API void zend_create_closure(zval *res, zend_function *func TSRMLS_DC) /* {{{ */
+ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zval *this_ptr TSRMLS_DC) /* {{{ */
{
zend_closure *closure;
@@ -388,6 +451,12 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func TSRMLS_DC) /* {
closure->func = *func;
closure->func.common.prototype = NULL;
+ if ((scope == NULL) && (this_ptr != NULL)) {
+ /* use dummy scope if we're binding an object without specifying a scope */
+ /* maybe it would be better to create one for this purpose */
+ scope = zend_ce_closure;
+ }
+
if (closure->func.type == ZEND_USER_FUNCTION) {
if (closure->func.op_array.static_variables) {
HashTable *static_variables = closure->func.op_array.static_variables;
@@ -396,10 +465,44 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func TSRMLS_DC) /* {
zend_hash_init(closure->func.op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_apply_with_arguments(static_variables TSRMLS_CC, (apply_func_args_t)zval_copy_static_var, 1, closure->func.op_array.static_variables);
}
+ closure->func.op_array.run_time_cache = NULL;
(*closure->func.op_array.refcount)++;
+ } else {
+ /* verify that we aren't binding internal function to a wrong scope */
+ if(func->common.scope != NULL) {
+ if(scope && !instanceof_function(scope, func->common.scope TSRMLS_CC)) {
+ zend_error(E_WARNING, "Cannot bind function %s::%s to scope class %s", func->common.scope->name, func->common.function_name, scope->name);
+ scope = NULL;
+ }
+ if(scope && this_ptr && (func->common.fn_flags & ZEND_ACC_STATIC) == 0 &&
+ !instanceof_function(Z_OBJCE_P(this_ptr), closure->func.common.scope TSRMLS_CC)) {
+ zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", func->common.scope->name, func->common.function_name, Z_OBJCE_P(this_ptr)->name);
+ scope = NULL;
+ this_ptr = NULL;
+ }
+ } else {
+ /* if it's a free function, we won't set scope & this since they're meaningless */
+ this_ptr = NULL;
+ scope = NULL;
+ }
}
- closure->func.common.scope = NULL;
+ /* Invariants:
+ * If the closure is unscoped, it has no bound object.
+ * The the closure is scoped, it's either static or it's bound */
+ closure->func.common.scope = scope;
+ if (scope) {
+ closure->func.common.fn_flags |= ZEND_ACC_PUBLIC;
+ if (this_ptr && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) {
+ closure->this_ptr = this_ptr;
+ Z_ADDREF_P(this_ptr);
+ } else {
+ closure->func.common.fn_flags |= ZEND_ACC_STATIC;
+ closure->this_ptr = NULL;
+ }
+ } else {
+ closure->this_ptr = NULL;
+ }
}
/* }}} */
diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h
index 12d5b3400e..c540b554c9 100644
--- a/Zend/zend_closures.h
+++ b/Zend/zend_closures.h
@@ -30,9 +30,10 @@ void zend_register_closure_ce(TSRMLS_D);
extern ZEND_API zend_class_entry *zend_ce_closure;
-ZEND_API void zend_create_closure(zval *res, zend_function *op_array TSRMLS_DC);
+ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zval *this_ptr TSRMLS_DC);
ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC);
ZEND_API const zend_function *zend_get_closure_method_def(zval *obj TSRMLS_DC);
+ZEND_API zval* zend_get_closure_this_ptr(zval *obj TSRMLS_DC);
END_EXTERN_C()
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 4c31f7c368..4dd3eaf1ed 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -27,10 +27,75 @@
#include "zend_API.h"
#include "zend_exceptions.h"
#include "tsrm_virtual_cwd.h"
-
-#ifdef ZEND_MULTIBYTE
#include "zend_multibyte.h"
-#endif /* ZEND_MULTIBYTE */
+#include "zend_language_scanner.h"
+
+#define CONSTANT_EX(op_array, op) \
+ (op_array)->literals[op].constant
+
+#define CONSTANT(op) \
+ CONSTANT_EX(CG(active_op_array), op)
+
+#define SET_NODE(target, src) do { \
+ target ## _type = (src)->op_type; \
+ if ((src)->op_type == IS_CONST) { \
+ target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant TSRMLS_CC); \
+ } else { \
+ target = (src)->u.op; \
+ } \
+ } while (0)
+
+#define GET_NODE(target, src) do { \
+ (target)->op_type = src ## _type; \
+ if ((target)->op_type == IS_CONST) { \
+ (target)->u.constant = CONSTANT(src.constant); \
+ } else { \
+ (target)->u.op = src; \
+ (target)->EA = 0; \
+ } \
+ } while (0)
+
+#define COPY_NODE(target, src) do { \
+ target ## _type = src ## _type; \
+ target = src; \
+ } while (0)
+
+#define CALCULATE_LITERAL_HASH(num) do { \
+ if (IS_INTERNED(Z_STRVAL(CONSTANT(num)))) { \
+ Z_HASH_P(&CONSTANT(num)) = INTERNED_HASH(Z_STRVAL(CONSTANT(num))); \
+ } else { \
+ Z_HASH_P(&CONSTANT(num)) = zend_hash_func(Z_STRVAL(CONSTANT(num)), Z_STRLEN(CONSTANT(num))+1); \
+ } \
+ } while (0)
+
+#define GET_CACHE_SLOT(literal) do { \
+ CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
+ if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
+ CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
+ CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
+ } \
+ } while (0)
+
+#define POLYMORPHIC_CACHE_SLOT_SIZE 2
+
+#define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
+ CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
+ CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
+ if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
+ CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
+ CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
+ CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 2] = NULL; \
+ } \
+ } while (0)
+
+#define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
+ if (CG(active_op_array)->literals[literal].cache_slot != -1 && \
+ CG(active_op_array)->literals[literal].cache_slot == \
+ CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
+ CG(active_op_array)->literals[literal].cache_slot = -1; \
+ CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
+ } \
+ } while (0)
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
@@ -42,34 +107,35 @@ ZEND_API zend_executor_globals executor_globals;
static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
{
- property_info->name = estrndup(property_info->name, property_info->name_length);
+ if (!IS_INTERNED(property_info->name)) {
+ property_info->name = estrndup(property_info->name, property_info->name_length);
+ }
if (property_info->doc_comment) {
property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
}
}
/* }}} */
-
static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
{
- property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ if (!IS_INTERNED(property_info->name)) {
+ property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ }
}
/* }}} */
-
static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
{
- efree(property_info->name);
+ str_efree(property_info->name);
if (property_info->doc_comment) {
- efree(property_info->doc_comment);
+ efree((char*)property_info->doc_comment);
}
}
/* }}} */
-
static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
{
- free(property_info->name);
+ str_free((char*)property_info->name);
}
/* }}} */
@@ -77,7 +143,7 @@ static void build_runtime_defined_function_key(zval *result, const char *name, i
{
char char_pos_buf[32];
uint char_pos_len;
- char *filename;
+ const char *filename;
char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
if (CG(active_op_array)->filename) {
@@ -88,41 +154,17 @@ static void build_runtime_defined_function_key(zval *result, const char *name, i
/* NULL, name length, filename length, last accepting char position length */
result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
-#ifdef ZEND_MULTIBYTE
+
/* must be binary safe */
result->value.str.val = (char *) safe_emalloc(result->value.str.len, 1, 1);
result->value.str.val[0] = '\0';
sprintf(result->value.str.val+1, "%s%s%s", name, filename, char_pos_buf);
-#else
- zend_spprintf(&result->value.str.val, 0, "%c%s%s%s", '\0', name, filename, char_pos_buf);
-#endif /* ZEND_MULTIBYTE */
+
result->type = IS_STRING;
Z_SET_REFCOUNT_P(result, 1);
}
/* }}} */
-
-int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
-{
- auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
- return 0;
-}
-/* }}} */
-
-
-ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */
-{
- zend_auto_global *auto_global;
-
- if (zend_hash_find(CG(auto_globals), varname, varname_length+1, (void **) &auto_global)==FAILURE) {
- return FAILURE;
- }
- auto_global->armed = 0;
- return SUCCESS;
-}
-/* }}} */
-
-
static void init_compiler_declarables(TSRMLS_D) /* {{{ */
{
Z_TYPE(CG(declarables).ticks) = IS_LONG;
@@ -130,6 +172,16 @@ static void init_compiler_declarables(TSRMLS_D) /* {{{ */
}
/* }}} */
+void zend_init_compiler_context(TSRMLS_D) /* {{{ */
+{
+ CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
+ CG(context).vars_size = 0;
+ CG(context).literals_size = 0;
+ CG(context).current_brk_cont = -1;
+ CG(context).backpatch_count = 0;
+ CG(context).labels = NULL;
+}
+/* }}} */
void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
{
@@ -150,23 +202,12 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
CG(has_bracketed_namespaces) = 0;
CG(current_import) = NULL;
init_compiler_declarables(TSRMLS_C);
- zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
- zend_stack_init(&CG(labels_stack));
- CG(labels) = NULL;
-
-#ifdef ZEND_MULTIBYTE
- CG(script_encoding_list) = NULL;
- CG(script_encoding_list_size) = 0;
- CG(internal_encoding) = NULL;
- CG(encoding_detector) = NULL;
- CG(encoding_converter) = NULL;
- CG(encoding_oddlen) = NULL;
+ zend_stack_init(&CG(context_stack));
+
CG(encoding_declared) = 0;
-#endif /* ZEND_MULTIBYTE */
}
/* }}} */
-
ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
{
TSRMLS_FETCH();
@@ -175,7 +216,6 @@ ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
}
/* }}} */
-
void init_compiler(TSRMLS_D) /* {{{ */
{
CG(active_op_array) = NULL;
@@ -187,7 +227,6 @@ void init_compiler(TSRMLS_D) /* {{{ */
}
/* }}} */
-
void shutdown_compiler(TSRMLS_D) /* {{{ */
{
zend_stack_destroy(&CG(bp_stack));
@@ -199,17 +238,10 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */
zend_stack_destroy(&CG(list_stack));
zend_hash_destroy(&CG(filenames_table));
zend_llist_destroy(&CG(open_files));
- zend_stack_destroy(&CG(labels_stack));
-
-#ifdef ZEND_MULTIBYTE
- if (CG(script_encoding_list)) {
- efree(CG(script_encoding_list));
- }
-#endif /* ZEND_MULTIBYTE */
+ zend_stack_destroy(&CG(context_stack));
}
/* }}} */
-
ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
{
char **pp, *p;
@@ -226,79 +258,327 @@ ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRM
}
/* }}} */
-
ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
{
CG(compiled_filename) = original_compiled_filename;
}
/* }}} */
-
ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
{
return CG(compiled_filename);
}
/* }}} */
-
ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
{
return CG(zend_lineno);
}
/* }}} */
-
ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
{
return CG(in_compilation);
}
/* }}} */
-
static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
{
return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
}
/* }}} */
-static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ */
+static int lookup_cv(zend_op_array *op_array, char* name, int name_len, ulong hash TSRMLS_DC) /* {{{ */
{
int i = 0;
- ulong hash_value = zend_inline_hash_func(name, name_len+1);
+ ulong hash_value = hash ? hash : zend_inline_hash_func(name, name_len+1);
while (i < op_array->last_var) {
- if (op_array->vars[i].hash_value == hash_value &&
- op_array->vars[i].name_len == name_len &&
- strcmp(op_array->vars[i].name, name) == 0) {
- efree(name);
- return i;
+ if (op_array->vars[i].name == name ||
+ (op_array->vars[i].hash_value == hash_value &&
+ op_array->vars[i].name_len == name_len &&
+ memcmp(op_array->vars[i].name, name, name_len) == 0)) {
+ str_efree(name);
+ return i;
}
i++;
}
i = op_array->last_var;
op_array->last_var++;
- if (op_array->last_var > op_array->size_var) {
- op_array->size_var += 16; /* FIXME */
- op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
+ if (op_array->last_var > CG(context).vars_size) {
+ CG(context).vars_size += 16; /* FIXME */
+ op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_compiled_variable));
}
- op_array->vars[i].name = name; /* estrndup(name, name_len); */
+ op_array->vars[i].name = zend_new_interned_string(name, name_len + 1, 1 TSRMLS_CC);
op_array->vars[i].name_len = name_len;
op_array->vars[i].hash_value = hash_value;
return i;
}
/* }}} */
+void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
+{
+ zval_dtor(&CONSTANT_EX(op_array, n));
+ if (n + 1 == op_array->last_literal) {
+ op_array->last_literal--;
+ } else {
+ Z_TYPE(CONSTANT_EX(op_array, n)) = IS_NULL;
+ }
+}
+/* }}} */
+
+/* Common part of zend_add_literal and zend_append_individual_literal */
+static inline void zend_insert_literal(zend_op_array *op_array, const zval *zv, int literal_position TSRMLS_DC) /* {{{ */
+{
+ if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
+ zval *z = (zval*)zv;
+ Z_STRVAL_P(z) = (char*)zend_new_interned_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC);
+ }
+ CONSTANT_EX(op_array, literal_position) = *zv;
+ Z_SET_REFCOUNT(CONSTANT_EX(op_array, literal_position), 2);
+ Z_SET_ISREF(CONSTANT_EX(op_array, literal_position));
+ op_array->literals[literal_position].hash_value = 0;
+ op_array->literals[literal_position].cache_slot = -1;
+}
+/* }}} */
+
+/* Is used while compiling a function, using the context to keep track
+ of an approximate size to avoid to relocate to often.
+ Literals are truncated to actual size in the second compiler pass (pass_two()). */
+int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
+{
+ int i = op_array->last_literal;
+ op_array->last_literal++;
+ if (i >= CG(context).literals_size) {
+ while (i >= CG(context).literals_size) {
+ CG(context).literals_size += 16; /* FIXME */
+ }
+ op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
+ }
+ zend_insert_literal(op_array, zv, i TSRMLS_CC);
+ return i;
+}
+/* }}} */
+
+/* Is used after normal compilation to append an additional literal.
+ Allocation is done precisely here. */
+int zend_append_individual_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
+{
+ int i = op_array->last_literal;
+ op_array->last_literal++;
+ op_array->literals = (zend_literal*)erealloc(op_array->literals, (i + 1) * sizeof(zend_literal));
+ zend_insert_literal(op_array, zv, i TSRMLS_CC);
+ return i;
+}
+/* }}} */
+
+int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
+{
+ int ret;
+ char *lc_name;
+ zval c;
+ int lc_literal;
+
+ if (op_array->last_literal > 0 &&
+ &op_array->literals[op_array->last_literal - 1].constant == zv &&
+ op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
+ /* we already have function name as last literal (do nothing) */
+ ret = op_array->last_literal - 1;
+ } else {
+ ret = zend_add_literal(op_array, zv TSRMLS_CC);
+ }
+
+ lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
+ ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
+ lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(lc_literal);
+
+ return ret;
+}
+/* }}} */
+
+int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
+{
+ int ret;
+ char *lc_name;
+ const char *ns_separator;
+ int lc_len;
+ zval c;
+ int lc_literal;
+
+ if (op_array->last_literal > 0 &&
+ &op_array->literals[op_array->last_literal - 1].constant == zv &&
+ op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
+ /* we already have function name as last literal (do nothing) */
+ ret = op_array->last_literal - 1;
+ } else {
+ ret = zend_add_literal(op_array, zv TSRMLS_CC);
+ }
+
+ lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
+ ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
+ lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(lc_literal);
+
+ ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv)) + 1;
+ lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
+ lc_name = zend_str_tolower_dup(ns_separator, lc_len);
+ ZVAL_STRINGL(&c, lc_name, lc_len, 0);
+ lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(lc_literal);
+
+ return ret;
+}
+/* }}} */
+
+int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
+{
+ int ret;
+ char *lc_name;
+ int lc_len;
+ zval c;
+ int lc_literal;
+
+ if (op_array->last_literal > 0 &&
+ &op_array->literals[op_array->last_literal - 1].constant == zv &&
+ op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
+ /* we already have function name as last literal (do nothing) */
+ ret = op_array->last_literal - 1;
+ } else {
+ ret = zend_add_literal(op_array, zv TSRMLS_CC);
+ }
+
+ if (Z_STRVAL_P(zv)[0] == '\\') {
+ lc_len = Z_STRLEN_P(zv) - 1;
+ lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv) + 1, lc_len);
+ } else {
+ lc_len = Z_STRLEN_P(zv);
+ lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), lc_len);
+ }
+ ZVAL_STRINGL(&c, lc_name, lc_len, 0);
+ lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(lc_literal);
+
+ GET_CACHE_SLOT(ret);
+
+ return ret;
+}
+/* }}} */
+
+int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unqualified TSRMLS_DC) /* {{{ */
+{
+ int ret, tmp_literal;
+ char *name, *tmp_name;
+ const char *ns_separator;
+ int name_len, ns_len;
+ zval c;
+
+ if (op_array->last_literal > 0 &&
+ &op_array->literals[op_array->last_literal - 1].constant == zv &&
+ op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
+ /* we already have function name as last literal (do nothing) */
+ ret = op_array->last_literal - 1;
+ } else {
+ ret = zend_add_literal(op_array, zv TSRMLS_CC);
+ }
+
+ /* skip leading '\\' */
+ if (Z_STRVAL_P(zv)[0] == '\\') {
+ name_len = Z_STRLEN_P(zv) - 1;
+ name = Z_STRVAL_P(zv) + 1;
+ } else {
+ name_len = Z_STRLEN_P(zv);
+ name = Z_STRVAL_P(zv);
+ }
+ ns_separator = zend_memrchr(name, '\\', name_len);
+ if (ns_separator) {
+ ns_len = ns_separator - name;
+ } else {
+ ns_len = 0;
+ }
+
+ if (ns_len) {
+ /* lowercased namespace name & original constant name */
+ tmp_name = estrndup(name, name_len);
+ zend_str_tolower(tmp_name, ns_len);
+ ZVAL_STRINGL(&c, tmp_name, name_len, 0);
+ tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(tmp_literal);
+
+ /* lowercased namespace name & lowercased constant name */
+ tmp_name = zend_str_tolower_dup(name, name_len);
+ ZVAL_STRINGL(&c, tmp_name, name_len, 0);
+ tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(tmp_literal);
+ }
+
+ if (ns_len) {
+ if (!unqualified) {
+ return ret;
+ }
+ ns_len++;
+ name += ns_len;
+ name_len -= ns_len;
+ }
+
+ /* original constant name */
+ tmp_name = estrndup(name, name_len);
+ ZVAL_STRINGL(&c, tmp_name, name_len, 0);
+ tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(tmp_literal);
+
+ /* lowercased constant name */
+ tmp_name = zend_str_tolower_dup(name, name_len);
+ ZVAL_STRINGL(&c, tmp_name, name_len, 0);
+ tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
+ CALCULATE_LITERAL_HASH(tmp_literal);
+
+ return ret;
+}
+/* }}} */
+
+#define LITERAL_STRINGL(op, str, len, copy) do { \
+ zval _c; \
+ ZVAL_STRINGL(&_c, str, len, copy); \
+ op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
+ } while (0)
+
+#define LITERAL_LONG(op, val) do { \
+ zval _c; \
+ ZVAL_LONG(&_c, val); \
+ op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
+ } while (0)
+
+#define LITERAL_LONG_EX(op_array, op, val) do { \
+ zval _c; \
+ ZVAL_LONG(&_c, val); \
+ op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
+ } while (0)
+
+#define LITERAL_NULL(op) do { \
+ zval _c; \
+ INIT_ZVAL( _c); \
+ op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
+ } while (0)
+
+static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
+{
+ zend_uint type = variable->EA;
+
+ return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
+}
+/* }}} */
void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = op;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *op1;
- opline->op2 = *op2;
- *result = opline->result;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, op1);
+ SET_NODE(opline->op2, op2);
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -307,21 +587,20 @@ void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC)
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = op;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *op1;
- *result = opline->result;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, op1);
+ GET_NODE(result, opline->result);
SET_UNUSED(opline->op2);
}
/* }}} */
-#define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; }
-
+#define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; }
static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
{
data_op->opcode = ZEND_OP_DATA;
- data_op->op1 = *value;
+ SET_NODE(data_op->op1, value);
SET_UNUSED(data_op->op2);
}
/* }}} */
@@ -341,18 +620,17 @@ void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, co
zend_do_op_data(opline, op2 TSRMLS_CC);
SET_UNUSED(opline->result);
- *result = last_op->result;
+ GET_NODE(result, last_op->result);
return;
case ZEND_FETCH_DIM_RW:
last_op->opcode = op;
last_op->extended_value = ZEND_ASSIGN_DIM;
zend_do_op_data(opline, op2 TSRMLS_CC);
- opline->op2.u.var = get_temporary_variable(CG(active_op_array));
- opline->op2.u.EA.type = 0;
- opline->op2.op_type = IS_VAR;
+ opline->op2.var = get_temporary_variable(CG(active_op_array));
+ opline->op2_type = IS_VAR;
SET_UNUSED(opline->result);
- *result = last_op->result;
+ GET_NODE(result,last_op->result);
return;
default:
break;
@@ -360,12 +638,11 @@ void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, co
}
opline->opcode = op;
- opline->op1 = *op1;
- opline->op2 = *op2;
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
+ SET_NODE(opline->op1, op1);
+ SET_NODE(opline->op2, op2);
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -376,18 +653,22 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
zend_llist *fetch_list_ptr;
if (varname->op_type == IS_CONST) {
+ ulong hash = 0;
+
if (Z_TYPE(varname->u.constant) != IS_STRING) {
convert_to_string(&varname->u.constant);
+ } else if (IS_INTERNED(Z_STRVAL(varname->u.constant))) {
+ hash = INTERNED_HASH(Z_STRVAL(varname->u.constant));
}
- if (!zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC) &&
+ if (!zend_is_auto_global_quick(varname->u.constant.value.str.val, varname->u.constant.value.str.len, hash TSRMLS_CC) &&
!(varname->u.constant.value.str.len == (sizeof("this")-1) &&
!memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
(CG(active_op_array)->last == 0 ||
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
result->op_type = IS_CV;
- result->u.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
- result->u.EA.type = 0;
- varname->u.constant.value.str.val = CG(active_op_array)->vars[result->u.var].name;
+ result->u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len, hash TSRMLS_CC);
+ varname->u.constant.value.str.val = (char*)CG(active_op_array)->vars[result->u.op.var].name;
+ result->EA = 0;
return;
}
}
@@ -400,17 +681,17 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
}
opline_ptr->opcode = op;
- opline_ptr->result.op_type = IS_VAR;
- opline_ptr->result.u.EA.type = 0;
- opline_ptr->result.u.var = get_temporary_variable(CG(active_op_array));
- opline_ptr->op1 = *varname;
- *result = opline_ptr->result;
+ opline_ptr->result_type = IS_VAR;
+ opline_ptr->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline_ptr->op1, varname);
+ GET_NODE(result, opline_ptr->result);
SET_UNUSED(opline_ptr->op2);
+ opline_ptr->extended_value = ZEND_FETCH_LOCAL;
- opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
- if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
- if (zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC)) {
- opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
+ if (varname->op_type == IS_CONST) {
+ CALCULATE_LITERAL_HASH(opline_ptr->op1.constant);
+ if (zend_is_auto_global_quick(varname->u.constant.value.str.val, varname->u.constant.value.str.len, Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC)) {
+ opline_ptr->extended_value = ZEND_FETCH_GLOBAL;
}
}
@@ -436,48 +717,72 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
zend_op *opline_ptr;
zend_op opline;
- zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+ if (class_name->op_type == IS_CONST &&
+ ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
+ zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
+ class_node = *class_name;
+ } else {
+ zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+ }
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
if (result->op_type == IS_CV) {
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_W;
- opline.result.op_type = IS_VAR;
- opline.result.u.EA.type = 0;
- opline.result.u.var = get_temporary_variable(CG(active_op_array));
- opline.op1.op_type = IS_CONST;
- opline.op1.u.constant.type = IS_STRING;
- opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
- opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
- SET_UNUSED(opline.op2);
- opline.op2 = class_node;
- opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
- *result = opline.result;
+ opline.result_type = IS_VAR;
+ opline.result.var = get_temporary_variable(CG(active_op_array));
+ opline.op1_type = IS_CONST;
+ LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
+ CALCULATE_LITERAL_HASH(opline.op1.constant);
+ GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
+ if (class_node.op_type == IS_CONST) {
+ opline.op2_type = IS_CONST;
+ opline.op2.constant =
+ zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline.op2, &class_node);
+ }
+ GET_NODE(result,opline.result);
+ opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
+ opline_ptr = &opline;
zend_llist_add_element(fetch_list_ptr, &opline);
} else {
le = fetch_list_ptr->head;
opline_ptr = (zend_op *)le->data;
- if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1.op_type == IS_CV) {
+ if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_W;
- opline.result.op_type = IS_VAR;
- opline.result.u.EA.type = 0;
- opline.result.u.var = get_temporary_variable(CG(active_op_array));
- opline.op1.op_type = IS_CONST;
- opline.op1.u.constant.type = IS_STRING;
- opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
- opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
- SET_UNUSED(opline.op2);
- opline.op2 = class_node;
- opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
- opline_ptr->op1 = opline.result;
+ opline.result_type = IS_VAR;
+ opline.result.var = get_temporary_variable(CG(active_op_array));
+ opline.op1_type = IS_CONST;
+ LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
+ CALCULATE_LITERAL_HASH(opline.op1.constant);
+ GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
+ if (class_node.op_type == IS_CONST) {
+ opline.op2_type = IS_CONST;
+ opline.op2.constant =
+ zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline.op2, &class_node);
+ }
+ opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
+ COPY_NODE(opline_ptr->op1, opline.result);
zend_llist_prepend_element(fetch_list_ptr, &opline);
} else {
- opline_ptr->op2 = class_node;
- opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
+ if (opline_ptr->op1_type == IS_CONST) {
+ GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
+ }
+ if (class_node.op_type == IS_CONST) {
+ opline_ptr->op2_type = IS_CONST;
+ opline_ptr->op2.constant =
+ zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline_ptr->op2, &class_node);
+ }
+ opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
}
}
}
@@ -496,17 +801,39 @@ void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS
zend_op opline;
zend_llist *fetch_list_ptr;
+ zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
+
+ if (zend_is_function_or_method_call(parent)) {
+ init_op(&opline TSRMLS_CC);
+ opline.opcode = ZEND_SEPARATE;
+ SET_NODE(opline.op1, parent);
+ SET_UNUSED(opline.op2);
+ opline.result_type = IS_VAR;
+ opline.result.var = opline.op1.var;
+ zend_llist_add_element(fetch_list_ptr, &opline);
+ }
+
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */
- opline.result.op_type = IS_VAR;
- opline.result.u.EA.type = 0;
- opline.result.u.var = get_temporary_variable(CG(active_op_array));
- opline.op1 = *parent;
- opline.op2 = *dim;
- opline.extended_value = ZEND_FETCH_STANDARD;
- *result = opline.result;
+ opline.result_type = IS_VAR;
+ opline.result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline.op1, parent);
+ SET_NODE(opline.op2, dim);
+ if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
+ ulong index;
+ int numeric = 0;
+
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline.op2.constant)), Z_STRLEN(CONSTANT(opline.op2.constant))+1, index, numeric = 1);
+ if (numeric) {
+ zval_dtor(&CONSTANT(opline.op2.constant));
+ ZVAL_LONG(&CONSTANT(opline.op2.constant), index);
+ } else {
+ CALCULATE_LITERAL_HASH(opline.op2.constant);
+ }
+ }
+
+ GET_NODE(result, opline.result);
- zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
zend_llist_add_element(fetch_list_ptr, &opline);
}
/* }}} */
@@ -521,12 +848,12 @@ void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
opline->opcode = ZEND_PRINT;
- opline->op1 = *arg;
+ SET_NODE(opline->op1, arg);
SET_UNUSED(opline->op2);
- *result = opline->result;
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -535,7 +862,7 @@ void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ECHO;
- opline->op1 = *arg;
+ SET_NODE(opline->op1, arg);
SET_UNUSED(opline->op2);
}
/* }}} */
@@ -575,10 +902,11 @@ void zend_do_abstract_method(const znode *function_name, znode *modifiers, const
static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
{
- if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
- && (opline->op1.u.constant.type == IS_STRING)
- && (opline->op1.u.constant.value.str.len == (sizeof("this")-1))
- && !memcmp(opline->op1.u.constant.value.str.val, "this", sizeof("this"))) {
+ if ((opline->opcode == ZEND_FETCH_W) && (opline->op1_type == IS_CONST)
+ && (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING)
+ && (Z_HASH_P(&CONSTANT(opline->op1.constant)) == THIS_HASHVAL)
+ && (Z_STRLEN(CONSTANT(opline->op1.constant)) == (sizeof("this")-1))
+ && !memcmp(Z_STRVAL(CONSTANT(opline->op1.constant)), "this", sizeof("this"))) {
return 1;
} else {
return 0;
@@ -586,7 +914,7 @@ static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
}
/* }}} */
-void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC) /* {{{ */
+void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {{{ */
{
int last_op_number;
zend_op *opline;
@@ -599,21 +927,21 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
opline = (zend_op *)fetch_list_ptr->head->data;
if (opline->opcode == ZEND_FETCH_DIM_W &&
- opline->op1.op_type == IS_CV &&
- opline->op1.u.var == value->u.var) {
+ opline->op1_type == IS_CV &&
+ opline->op1.var == value->u.op.var) {
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_R;
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1.op_type = IS_CONST;
- ZVAL_STRINGL(&opline->op1.u.constant,
- CG(active_op_array)->vars[value->u.var].name,
- CG(active_op_array)->vars[value->u.var].name_len, 1);
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->op1_type = IS_CONST;
+ LITERAL_STRINGL(opline->op1,
+ CG(active_op_array)->vars[value->u.op.var].name,
+ CG(active_op_array)->vars[value->u.op.var].name_len, 1);
+ CALCULATE_LITERAL_HASH(opline->op1.constant);
SET_UNUSED(opline->op2);
- opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
- value = &opline->result;
+ opline->extended_value = ZEND_FETCH_LOCAL;
+ GET_NODE(value, opline->result);
}
}
}
@@ -624,7 +952,7 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
if (variable->op_type == IS_CV) {
- if (variable->u.var == CG(active_op_array)->this_var) {
+ if (variable->u.op.var == CG(active_op_array)->this_var) {
zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
}
} else if (variable->op_type == IS_VAR) {
@@ -635,8 +963,8 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
- if (last_op->result.op_type == IS_VAR &&
- last_op->result.u.var == variable->u.var) {
+ if (last_op->result_type == IS_VAR &&
+ last_op->result.var == variable->u.op.var) {
if (last_op->opcode == ZEND_FETCH_OBJ_W) {
if (n > 0) {
int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
@@ -650,7 +978,7 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
last_op->opcode = ZEND_ASSIGN_OBJ;
zend_do_op_data(opline, value TSRMLS_CC);
SET_UNUSED(opline->result);
- *result = last_op->result;
+ GET_NODE(result, last_op->result);
return;
} else if (last_op->opcode == ZEND_FETCH_DIM_W) {
if (n > 0) {
@@ -665,11 +993,10 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
}
last_op->opcode = ZEND_ASSIGN_DIM;
zend_do_op_data(opline, value TSRMLS_CC);
- opline->op2.u.var = get_temporary_variable(CG(active_op_array));
- opline->op2.u.EA.type = 0;
- opline->op2.op_type = IS_VAR;
+ opline->op2.var = get_temporary_variable(CG(active_op_array));
+ opline->op2_type = IS_VAR;
SET_UNUSED(opline->result);
- *result = last_op->result;
+ GET_NODE(result, last_op->result);
return;
} else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
@@ -682,20 +1009,11 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
}
opline->opcode = ZEND_ASSIGN;
- opline->op1 = *variable;
- opline->op2 = *value;
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
-}
-/* }}} */
-
-static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
-{
- zend_uint type = variable->u.EA.type;
-
- return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
+ SET_NODE(opline->op1, variable);
+ SET_NODE(opline->op2, value);
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -704,7 +1022,7 @@ void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRM
zend_op *opline;
if (lvar->op_type == IS_CV) {
- if (lvar->u.var == CG(active_op_array)->this_var) {
+ if (lvar->u.op.var == CG(active_op_array)->this_var) {
zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
}
} else if (lvar->op_type == IS_VAR) {
@@ -722,22 +1040,20 @@ void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRM
opline->opcode = ZEND_ASSIGN_REF;
if (zend_is_function_or_method_call(rvar)) {
opline->extended_value = ZEND_RETURNS_FUNCTION;
- } else if (rvar->u.EA.type & ZEND_PARSED_NEW) {
+ } else if (rvar->EA & ZEND_PARSED_NEW) {
opline->extended_value = ZEND_RETURNS_NEW;
} else {
opline->extended_value = 0;
}
if (result) {
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
} else {
- /* SET_UNUSED(opline->result); */
- opline->result.u.EA.type |= EXT_TYPE_UNUSED;
+ opline->result_type = IS_UNUSED | EXT_TYPE_UNUSED;
}
- opline->op1 = *lvar;
- opline->op2 = *rvar;
+ SET_NODE(opline->op1, lvar);
+ SET_NODE(opline->op2, rvar);
}
/* }}} */
@@ -746,8 +1062,8 @@ static inline void do_begin_loop(TSRMLS_D) /* {{{ */
zend_brk_cont_element *brk_cont_element;
int parent;
- parent = CG(active_op_array)->current_brk_cont;
- CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
+ parent = CG(context).current_brk_cont;
+ CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
brk_cont_element->start = get_next_op_number(CG(active_op_array));
brk_cont_element->parent = parent;
@@ -760,11 +1076,11 @@ static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{
/* The start fileld is used to free temporary variables in case of exceptions.
* We won't try to free something of we don't have loop variable.
*/
- CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
+ CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
}
- CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
- CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
+ CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
+ CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
+ CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
}
/* }}} */
@@ -774,8 +1090,8 @@ void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC)
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMPZ;
- opline->op1 = *expr;
- close_bracket_token->u.opline_num = while_cond_op_number;
+ SET_NODE(opline->op1, expr);
+ close_bracket_token->u.op.opline_num = while_cond_op_number;
SET_UNUSED(opline->op2);
do_begin_loop(TSRMLS_C);
@@ -789,14 +1105,14 @@ void zend_do_while_end(const znode *while_token, const znode *close_bracket_toke
/* add unconditional jump */
opline->opcode = ZEND_JMP;
- opline->op1.u.opline_num = while_token->u.opline_num;
+ opline->op1.opline_num = while_token->u.op.opline_num;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
/* update while's conditional jmp */
- CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
- do_end_loop(while_token->u.opline_num, 0 TSRMLS_CC);
+ do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
DEC_BPC(CG(active_op_array));
}
@@ -808,8 +1124,8 @@ void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMPZNZ;
- opline->op1 = *expr; /* the conditional expression */
- second_semicolon_token->u.opline_num = for_cond_op_number;
+ SET_NODE(opline->op1, expr); /* the conditional expression */
+ second_semicolon_token->u.op.opline_num = for_cond_op_number;
SET_UNUSED(opline->op2);
}
/* }}} */
@@ -819,8 +1135,8 @@ void zend_do_for_before_statement(const znode *cond_start, const znode *second_s
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMP;
- opline->op1.u.opline_num = cond_start->u.opline_num;
- CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
+ opline->op1.opline_num = cond_start->u.op.opline_num;
+ CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
@@ -835,12 +1151,12 @@ void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMP;
- opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1;
- CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
+ CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- do_end_loop(second_semicolon_token->u.opline_num+1, 0 TSRMLS_CC);
+ do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
DEC_BPC(CG(active_op_array));
}
@@ -856,22 +1172,20 @@ void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC
if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
- last_op->result.op_type = IS_VAR;
- last_op->result.u.EA.type = 0;
- last_op->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = last_op->result;
+ last_op->result_type = IS_VAR;
+ last_op->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, last_op->result);
return;
}
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = op;
- opline->op1 = *op1;
+ SET_NODE(opline->op1, op1);
SET_UNUSED(opline->op2);
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -885,20 +1199,20 @@ void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_D
if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
- last_op->result.op_type = IS_TMP_VAR;
- last_op->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = last_op->result;
+ last_op->result_type = IS_TMP_VAR;
+ last_op->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, last_op->result);
return;
}
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = op;
- opline->op1 = *op1;
+ SET_NODE(opline->op1, op1);
SET_UNUSED(opline->op2);
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -908,8 +1222,8 @@ void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC)
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMPZ;
- opline->op1 = *cond;
- closing_bracket_token->u.opline_num = if_cond_op_number;
+ SET_NODE(opline->op1, cond);
+ closing_bracket_token->u.op.opline_num = if_cond_op_number;
SET_UNUSED(opline->op2);
INC_BPC(CG(active_op_array));
}
@@ -932,7 +1246,7 @@ void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned cha
zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
- CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1;
+ CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
}
@@ -946,7 +1260,7 @@ void zend_do_if_end(TSRMLS_D) /* {{{ */
zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
for (le=jmp_list_ptr->head; le; le = le->next) {
- CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number;
+ CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
}
zend_llist_destroy(jmp_list_ptr);
zend_stack_del_top(&CG(bp_stack));
@@ -956,7 +1270,7 @@ void zend_do_if_end(TSRMLS_D) /* {{{ */
void zend_check_writable_variable(const znode *variable) /* {{{ */
{
- zend_uint type = variable->u.EA.type;
+ zend_uint type = variable->EA;
if (type & ZEND_PARSED_METHOD_CALL) {
zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
@@ -997,35 +1311,44 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
if (CG(active_op_array)->last == 0 ||
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
- this_var = opline_ptr->result.u.var;
+ this_var = opline_ptr->result.var;
if (CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(opline_ptr->op1.u.constant), Z_STRLEN(opline_ptr->op1.u.constant));
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
+ Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL;
} else {
- efree(Z_STRVAL(opline_ptr->op1.u.constant));
+ zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
}
le = le->next;
if (variable->op_type == IS_VAR &&
- variable->u.var == this_var) {
+ variable->u.op.var == this_var) {
variable->op_type = IS_CV;
- variable->u.var = CG(active_op_array)->this_var;
+ variable->u.op.var = CG(active_op_array)->this_var;
}
} else if (CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
}
}
while (le) {
opline_ptr = (zend_op *)le->data;
+ if (opline_ptr->opcode == ZEND_SEPARATE) {
+ if (type != BP_VAR_R && type != BP_VAR_IS) {
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ memcpy(opline, opline_ptr, sizeof(zend_op));
+ }
+ le = le->next;
+ continue;
+ }
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
memcpy(opline, opline_ptr, sizeof(zend_op));
- if (opline->op1.op_type == IS_VAR &&
- opline->op1.u.var == this_var) {
- opline->op1.op_type = IS_CV;
- opline->op1.u.var = CG(active_op_array)->this_var;
+ if (opline->op1_type == IS_VAR &&
+ opline->op1.var == this_var) {
+ opline->op1_type = IS_CV;
+ opline->op1.var = CG(active_op_array)->this_var;
}
switch (type) {
case BP_VAR_R:
- if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
+ if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
}
opline->opcode -= 3;
@@ -1036,17 +1359,17 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
opline->opcode += 3;
break;
case BP_VAR_IS:
- if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
+ if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
}
opline->opcode += 6; /* 3+3 */
break;
case BP_VAR_FUNC_ARG:
opline->opcode += 9; /* 3+3+3 */
- opline->extended_value = arg_offset;
+ opline->extended_value |= arg_offset;
break;
case BP_VAR_UNSET:
- if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
+ if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
}
opline->opcode += 12; /* 3+3+3+3 */
@@ -1055,7 +1378,7 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
le = le->next;
}
if (opline && type == BP_VAR_W && arg_offset) {
- opline->extended_value = ZEND_FETCH_MAKE_REF;
+ opline->extended_value |= ZEND_FETCH_MAKE_REF;
}
}
zend_llist_destroy(fetch_list_ptr);
@@ -1084,15 +1407,15 @@ void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /
}
if (op1) {
- opline->op1 = *op1;
- opline->result = *op1;
+ SET_NODE(opline->op1, op1);
+ SET_NODE(opline->result, op1);
} else {
SET_UNUSED(opline->op1);
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
}
- opline->op2 = *op2;
- *result = opline->result;
+ SET_NODE(opline->op2, op2);
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -1103,15 +1426,15 @@ void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRM
opline->opcode = ZEND_ADD_VAR;
if (op1) {
- opline->op1 = *op1;
- opline->result = *op1;
+ SET_NODE(opline->op1, op1);
+ SET_NODE(opline->result, op1);
} else {
SET_UNUSED(opline->op1);
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
}
- opline->op2 = *op2;
- *result = opline->result;
+ SET_NODE(opline->op2, op2);
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -1121,7 +1444,7 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FREE;
- opline->op1 = *op1;
+ SET_NODE(opline->op1, op1);
SET_UNUSED(opline->op2);
} else if (op1->op_type==IS_VAR) {
zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
@@ -1129,23 +1452,36 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
opline--;
}
- if (opline->result.op_type == IS_VAR
- && opline->result.u.var == op1->u.var) {
- opline->result.u.EA.type |= EXT_TYPE_UNUSED;
+ if (opline->result_type == IS_VAR
+ && opline->result.var == op1->u.op.var) {
+ if (opline->opcode == ZEND_FETCH_R ||
+ opline->opcode == ZEND_FETCH_DIM_R ||
+ opline->opcode == ZEND_FETCH_OBJ_R ||
+ opline->opcode == ZEND_QM_ASSIGN_VAR) {
+ /* It's very rare and useless case. It's better to use
+ additional FREE opcode and simplify the FETCH handlers
+ their selves */
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_FREE;
+ SET_NODE(opline->op1, op1);
+ SET_UNUSED(opline->op2);
+ } else {
+ opline->result_type |= EXT_TYPE_UNUSED;
+ }
} else {
while (opline>CG(active_op_array)->opcodes) {
if (opline->opcode == ZEND_FETCH_DIM_R
- && opline->op1.op_type == IS_VAR
- && opline->op1.u.var == op1->u.var) {
+ && opline->op1_type == IS_VAR
+ && opline->op1.var == op1->u.op.var) {
/* This should the end of a list() construct
* Mark its result as unused
*/
opline->extended_value = ZEND_FETCH_STANDARD;
break;
- } else if (opline->result.op_type==IS_VAR
- && opline->result.u.var == op1->u.var) {
+ } else if (opline->result_type==IS_VAR
+ && opline->result.var == op1->u.op.var) {
if (opline->opcode == ZEND_NEW) {
- opline->result.u.EA.type |= EXT_TYPE_UNUSED;
+ opline->result_type |= EXT_TYPE_UNUSED;
}
break;
}
@@ -1188,9 +1524,9 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
zend_op_array op_array;
char *name = function_name->u.constant.value.str.val;
int name_len = function_name->u.constant.value.str.len;
- int function_begin_line = function_token->u.opline_num;
+ int function_begin_line = function_token->u.op.opline_num;
zend_uint fn_flags;
- char *lcname;
+ const char *lcname;
zend_bool orig_interactive;
ALLOCA_FLAG(use_heap)
@@ -1210,7 +1546,6 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
}
function_token->u.op_array = CG(active_op_array);
- lcname = zend_str_tolower_dup(name, name_len);
orig_interactive = CG(interactive);
CG(interactive) = 0;
@@ -1218,9 +1553,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
CG(interactive) = orig_interactive;
op_array.function_name = name;
- op_array.return_reference = return_reference;
+ if (return_reference) {
+ op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
+ }
op_array.fn_flags |= fn_flags;
- op_array.pass_rest_by_reference = 0;
op_array.scope = is_method?CG(active_class_entry):NULL;
op_array.prototype = NULL;
@@ -1228,10 +1564,22 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
if (is_method) {
- if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
+ int result;
+
+ lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
+
+ if (IS_INTERNED(lcname)) {
+ result = zend_hash_quick_add(&CG(active_class_entry)->function_table, lcname, name_len+1, INTERNED_HASH(lcname), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ } else {
+ result = zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ }
+ if (result == FAILURE) {
zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
}
+ zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
+ zend_init_compiler_context(TSRMLS_C);
+
if (fn_flags & ZEND_ACC_ABSTRACT) {
CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
}
@@ -1277,7 +1625,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
/* Improve after RC: cache the lowercase class name */
- if ((CG(active_class_entry)->name_length == name_len) && (!memcmp(class_lcname, lcname, name_len))) {
+ if ((CG(active_class_entry)->name_length == name_len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname, name_len))) {
if (!CG(active_class_entry)->constructor) {
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
}
@@ -1331,9 +1679,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
free_alloca(class_lcname, use_heap);
}
- efree(lcname);
+ str_efree(lcname);
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ zval key;
if (CG(current_namespace)) {
/* Prefix function name with current namespace name */
@@ -1343,21 +1692,24 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
zval_copy_ctor(&tmp.u.constant);
zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
op_array.function_name = Z_STRVAL(tmp.u.constant);
- efree(lcname);
name_len = Z_STRLEN(tmp.u.constant);
lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
+ } else {
+ lcname = zend_str_tolower_dup(name, name_len);
}
opline->opcode = ZEND_DECLARE_FUNCTION;
- opline->op1.op_type = IS_CONST;
- build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
- opline->op2.op_type = IS_CONST;
- opline->op2.u.constant.type = IS_STRING;
- opline->op2.u.constant.value.str.val = lcname;
- opline->op2.u.constant.value.str.len = name_len;
- Z_SET_REFCOUNT(opline->op2.u.constant, 1);
+ opline->op1_type = IS_CONST;
+ build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
+ opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
+ Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
+ opline->op2_type = IS_CONST;
+ LITERAL_STRINGL(opline->op2, lcname, name_len, 0);
+ CALCULATE_LITERAL_HASH(opline->op2.constant);
opline->extended_value = ZEND_DECLARE_FUNCTION;
- zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
+ zend_init_compiler_context(TSRMLS_C);
}
if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
@@ -1383,8 +1735,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
/* Foreach stack separator */
zend_op dummy_opline;
- dummy_opline.result.op_type = IS_UNUSED;
- dummy_opline.op1.op_type = IS_UNUSED;
+ dummy_opline.result_type = IS_UNUSED;
+ dummy_opline.op1_type = IS_UNUSED;
zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
}
@@ -1396,13 +1748,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
CG(doc_comment) = NULL;
CG(doc_comment_len) = 0;
}
-
- zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
- CG(labels) = NULL;
}
/* }}} */
-void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC) /* {{{ */
+void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) /* {{{ */
{
znode function_name;
zend_op_array *current_op_array = CG(active_op_array);
@@ -1415,13 +1764,16 @@ void zend_do_begin_lambda_function_declaration(znode *result, znode *function_to
zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
result->op_type = IS_TMP_VAR;
- result->u.var = get_temporary_variable(current_op_array);
+ result->u.op.var = get_temporary_variable(current_op_array);
current_op = &current_op_array->opcodes[current_op_number];
current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
- zval_dtor(&current_op->op2.u.constant);
- ZVAL_LONG(&current_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant)));
- current_op->result = *result;
+ zend_del_literal(current_op_array, current_op->op2.constant);
+ SET_UNUSED(current_op->op2);
+ SET_NODE(current_op->result, result);
+ if (is_static) {
+ CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
+ }
CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
}
/* }}} */
@@ -1470,10 +1822,11 @@ void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /*
}
/* }}} */
-void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, const znode *initialization, znode *class_type, const znode *varname, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
+void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, const znode *initialization, znode *class_type, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
{
zend_op *opline;
zend_arg_info *cur_arg_info;
+ znode var;
if (class_type->op_type == IS_CONST &&
Z_TYPE(class_type->u.constant) == IS_STRING &&
@@ -1484,35 +1837,40 @@ void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, c
return;
}
- if (var->op_type == IS_CV &&
- var->u.var == CG(active_op_array)->this_var &&
- (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
- } else if (var->op_type == IS_VAR &&
- CG(active_op_array)->scope &&
- ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
- (Z_TYPE(varname->u.constant) == IS_STRING) &&
- (Z_STRLEN(varname->u.constant) == sizeof("this")-1) &&
- (memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")) == 0)) {
- zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+ if (zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0 TSRMLS_CC)) {
+ zend_error(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
+ } else {
+ var.op_type = IS_CV;
+ var.u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len, 0 TSRMLS_CC);
+ Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
+ var.EA = 0;
+ if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
+ Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
+ !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
+ if (CG(active_op_array)->scope &&
+ (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
+ zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+ }
+ CG(active_op_array)->this_var = var.u.op.var;
+ }
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
CG(active_op_array)->num_args++;
opline->opcode = op;
- opline->result = *var;
- opline->op1 = *offset;
+ SET_NODE(opline->result, &var);
+ SET_NODE(opline->op1, offset);
if (op == ZEND_RECV_INIT) {
- opline->op2 = *initialization;
+ SET_NODE(opline->op2, initialization);
} else {
CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
SET_UNUSED(opline->op2);
}
CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
- cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len);
+ cur_arg_info->name = zend_new_interned_string(estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len), varname->u.constant.value.str.len + 1, 1 TSRMLS_CC);
cur_arg_info->name_len = varname->u.constant.value.str.len;
- cur_arg_info->array_type_hint = 0;
+ cur_arg_info->type_hint = 0;
cur_arg_info->allow_null = 1;
cur_arg_info->pass_by_reference = pass_by_reference;
cur_arg_info->class_name = NULL;
@@ -1520,33 +1878,44 @@ void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, c
if (class_type->op_type != IS_UNUSED) {
cur_arg_info->allow_null = 0;
- if (class_type->u.constant.type == IS_STRING) {
- if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
- zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
- }
- cur_arg_info->class_name = class_type->u.constant.value.str.val;
- cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
- cur_arg_info->allow_null = 1;
- } else {
- zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
+
+ if (class_type->u.constant.type != IS_NULL) {
+ if (class_type->u.constant.type == IS_ARRAY) {
+ cur_arg_info->type_hint = IS_ARRAY;
+ if (op == ZEND_RECV_INIT) {
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
+ cur_arg_info->allow_null = 1;
+ } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
+ }
}
- }
- } else {
- cur_arg_info->array_type_hint = 1;
- cur_arg_info->class_name = NULL;
- cur_arg_info->class_name_len = 0;
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
- cur_arg_info->allow_null = 1;
- } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
- zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
+ } else if (class_type->u.constant.type == IS_CALLABLE) {
+ cur_arg_info->type_hint = IS_CALLABLE;
+ if (op == ZEND_RECV_INIT) {
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
+ cur_arg_info->allow_null = 1;
+ } else {
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
+ }
+ }
+ } else {
+ cur_arg_info->type_hint = IS_OBJECT;
+ if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
+ zend_resolve_class_name(class_type, opline->extended_value, 1 TSRMLS_CC);
+ }
+ Z_STRVAL(class_type->u.constant) = (char*)zend_new_interned_string(class_type->u.constant.value.str.val, class_type->u.constant.value.str.len + 1, 1 TSRMLS_CC);
+ cur_arg_info->class_name = class_type->u.constant.value.str.val;
+ cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
+ if (op == ZEND_RECV_INIT) {
+ if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
+ cur_arg_info->allow_null = 1;
+ } else {
+ zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
+ }
}
}
}
}
- opline->result.u.EA.type |= EXT_TYPE_UNUSED;
}
/* }}} */
@@ -1597,28 +1966,39 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
last_op_number = get_next_op_number(CG(active_op_array))-1;
last_op = &CG(active_op_array)->opcodes[last_op_number];
- if ((last_op->op2.op_type == IS_CONST) && (last_op->op2.u.constant.type == IS_STRING) && (last_op->op2.u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1)
- && !zend_binary_strcasecmp(last_op->op2.u.constant.value.str.val, last_op->op2.u.constant.value.str.len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
+ if ((last_op->op2_type == IS_CONST) && (Z_TYPE(CONSTANT(last_op->op2.constant)) == IS_STRING) && (Z_STRLEN(CONSTANT(last_op->op2.constant)) == sizeof(ZEND_CLONE_FUNC_NAME)-1)
+ && !zend_binary_strcasecmp(Z_STRVAL(CONSTANT(last_op->op2.constant)), Z_STRLEN(CONSTANT(last_op->op2.constant)), ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
zend_error(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
}
if (last_op->opcode == ZEND_FETCH_OBJ_R) {
+ if (last_op->op2_type == IS_CONST) {
+ zval name;
+ name = CONSTANT(last_op->op2.constant);
+ if (Z_TYPE(name) != IS_STRING) {
+ zend_error(E_COMPILE_ERROR, "Method name must be a string");
+ }
+ if (!IS_INTERNED(Z_STRVAL(name))) {
+ Z_STRVAL(name) = estrndup(Z_STRVAL(name), Z_STRLEN(name));
+ }
+ FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
+ last_op->op2.constant =
+ zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
+ GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
+ }
last_op->opcode = ZEND_INIT_METHOD_CALL;
SET_UNUSED(last_op->result);
Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
} else {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
- opline->op2 = *left_bracket;
- if (opline->op2.op_type == IS_CONST) {
- opline->op1.op_type = IS_CONST;
- Z_TYPE(opline->op1.u.constant) = IS_STRING;
- Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
- Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
- opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
+ SET_UNUSED(opline->op1);
+ if (left_bracket->op_type == IS_CONST) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
+ GET_CACHE_SLOT(opline->op2.constant);
} else {
- opline->extended_value = 0;
- SET_UNUSED(opline->op1);
+ SET_NODE(opline->op2, left_bracket);
}
}
@@ -1632,60 +2012,37 @@ void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_CLONE;
- opline->op1 = *expr;
+ SET_NODE(opline->op1, expr);
SET_UNUSED(opline->op2);
- opline->result.op_type = IS_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
}
/* }}} */
void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
{
unsigned char *ptr = NULL;
- zend_op *opline, *opline2;
+ zend_op *opline;
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
if (ns_call) {
- char *slash;
- int prefix_len, name_len;
/* In run-time PHP will check for function with full name and
internal function with short name */
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
- opline->op2 = *function_name;
- opline->extended_value = 0;
- opline->op1.op_type = IS_CONST;
- Z_TYPE(opline->op1.u.constant) = IS_STRING;
- Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
- Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
- opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
- slash = zend_memrchr(Z_STRVAL(opline->op1.u.constant), '\\', Z_STRLEN(opline->op1.u.constant));
- prefix_len = slash-Z_STRVAL(opline->op1.u.constant)+1;
- name_len = Z_STRLEN(opline->op1.u.constant)-prefix_len;
- opline2 = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline2->opcode = ZEND_OP_DATA;
- opline2->op1.op_type = IS_CONST;
- Z_TYPE(opline2->op1.u.constant) = IS_LONG;
- if(!slash) {
- zend_error(E_CORE_ERROR, "Namespaced name %s should contain slash", Z_STRVAL(opline->op1.u.constant));
- }
- /* this is the length of namespace prefix */
- Z_LVAL(opline2->op1.u.constant) = prefix_len;
- /* this is the hash of the non-prefixed part, lowercased */
- opline2->extended_value = zend_hash_func(slash+1, name_len+1);
- SET_UNUSED(opline2->op2);
+ SET_UNUSED(opline->op1);
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
+ GET_CACHE_SLOT(opline->op2.constant);
} else {
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
- opline->op2 = *function_name;
- if (opline->op2.op_type == IS_CONST) {
- opline->op1.op_type = IS_CONST;
- Z_TYPE(opline->op1.u.constant) = IS_STRING;
- Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
- Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
- opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
+ SET_UNUSED(opline->op1);
+ if (function_name->op_type == IS_CONST) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
+ GET_CACHE_SLOT(opline->op2.constant);
} else {
- opline->extended_value = 0;
- SET_UNUSED(opline->op1);
+ SET_NODE(opline->op2, function_name);
}
}
@@ -1745,7 +2102,7 @@ void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace
}
/* }}} */
-void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC) /* {{{ */
+void zend_resolve_class_name(znode *class_name, ulong fetch_type, int check_ns_name TSRMLS_DC) /* {{{ */
{
char *compound;
char *lcname;
@@ -1757,12 +2114,12 @@ void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_
if (compound) {
/* This is a compound class name that contains namespace prefix */
if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
- /* The STRING name has "\" prefix */
- Z_STRLEN(class_name->u.constant) -= 1;
- memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
+ /* The STRING name has "\" prefix */
+ Z_STRLEN(class_name->u.constant) -= 1;
+ memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
Z_STRVAL(class_name->u.constant) = erealloc(
- Z_STRVAL(class_name->u.constant),
- Z_STRLEN(class_name->u.constant) + 1);
+ Z_STRVAL(class_name->u.constant),
+ Z_STRLEN(class_name->u.constant) + 1);
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
zend_error(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
@@ -1853,34 +2210,35 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
zval_dtor(&class_name->u.constant);
break;
default:
- zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
- opline->op2 = *class_name;
+ zend_resolve_class_name(class_name, opline->extended_value, 0 TSRMLS_CC);
+ opline->op2_type = IS_CONST;
+ opline->op2.constant =
+ zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
break;
}
} else {
- opline->op2 = *class_name;
+ SET_NODE(opline->op2, class_name);
}
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.u.EA.type = opline->extended_value;
- opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
- *result = opline->result;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
+ GET_NODE(result, opline->result);
+ result->EA = opline->extended_value;
}
/* }}} */
void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
{
- zend_op_array *oparray = CG(active_op_array);
zend_label dest;
- if (!CG(labels)) {
- ALLOC_HASHTABLE(CG(labels));
- zend_hash_init(CG(labels), 4, NULL, NULL, 0);
+ if (!CG(context).labels) {
+ ALLOC_HASHTABLE(CG(context).labels);
+ zend_hash_init(CG(context).labels, 4, NULL, NULL, 0);
}
- dest.brk_cont = oparray->current_brk_cont;
- dest.opline_num = get_next_op_number(oparray);
+ dest.brk_cont = CG(context).current_brk_cont;
+ dest.opline_num = get_next_op_number(CG(active_op_array));
- if (zend_hash_add(CG(labels), Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
+ if (zend_hash_add(CG(context).labels, Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
zend_error(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
}
@@ -1893,15 +2251,21 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
{
zend_label *dest;
long current, distance;
+ zval *label;
- if (CG(labels) == NULL ||
- zend_hash_find(CG(labels), Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void**)&dest) == FAILURE) {
+ if (pass2) {
+ label = opline->op2.zv;
+ } else {
+ label = &CONSTANT_EX(op_array, opline->op2.constant);
+ }
+ if (CG(context).labels == NULL ||
+ zend_hash_find(CG(context).labels, Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
if (pass2) {
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
CG(zend_lineno) = opline->lineno;
- zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL(opline->op2.u.constant));
+ zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
} else {
/* Label is not defined. Delay to pass 2. */
INC_BPC(op_array);
@@ -1909,8 +2273,9 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
}
}
- opline->op1.u.opline_num = dest->opline_num;
- zval_dtor(&opline->op2.u.constant);
+ opline->op1.opline_num = dest->opline_num;
+ zval_dtor(label);
+ Z_TYPE_P(label) = IS_NULL;
/* Check that we are not moving into loop or switch */
current = opline->extended_value;
@@ -1933,7 +2298,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
SET_UNUSED(opline->op2);
} else {
/* Set real break distance */
- ZVAL_LONG(&opline->op2.u.constant, distance);
+ ZVAL_LONG(label, distance);
}
if (pass2) {
@@ -1947,27 +2312,25 @@ void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_GOTO;
- opline->extended_value = CG(active_op_array)->current_brk_cont;
+ opline->extended_value = CG(context).current_brk_cont;
SET_UNUSED(opline->op1);
- opline->op2 = *label;
+ SET_NODE(opline->op2, label);
zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
}
/* }}} */
void zend_release_labels(TSRMLS_D) /* {{{ */
{
- if (CG(labels)) {
- zend_hash_destroy(CG(labels));
- FREE_HASHTABLE(CG(labels));
+ if (CG(context).labels) {
+ zend_hash_destroy(CG(context).labels);
+ FREE_HASHTABLE(CG(context).labels);
}
- if (!zend_stack_is_empty(&CG(labels_stack))) {
- HashTable **pht;
+ if (!zend_stack_is_empty(&CG(context_stack))) {
+ zend_compiler_context *ctx;
- zend_stack_top(&CG(labels_stack), (void**)&pht);
- CG(labels) = *pht;
- zend_stack_del_top(&CG(labels_stack));
- } else {
- CG(labels) = NULL;
+ zend_stack_top(&CG(context_stack), (void**)&ctx);
+ CG(context) = *ctx;
+ zend_stack_del_top(&CG(context_stack));
}
}
/* }}} */
@@ -2005,30 +2368,51 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
znode class_node;
unsigned char *ptr = NULL;
zend_op *opline;
- ulong fetch_type = 0;
if (method_name->op_type == IS_CONST) {
- char *lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
+ char *lcname;
+ if (Z_TYPE(method_name->u.constant) != IS_STRING) {
+ zend_error(E_COMPILE_ERROR, "Method name must be a string");
+ }
+ lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
- memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
+ memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
zval_dtor(&method_name->u.constant);
- SET_UNUSED(*method_name);
+ method_name->op_type = IS_UNUSED;
}
efree(lcname);
}
if (class_name->op_type == IS_CONST &&
- ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
- fetch_type = ZEND_FETCH_CLASS_GLOBAL;
- zend_resolve_class_name(class_name, &fetch_type, 1 TSRMLS_CC);
+ ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
+ zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
class_node = *class_name;
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
} else {
zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->extended_value = class_node.EA ;
}
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
- opline->op1 = class_node;
- opline->op2 = *method_name;
+ if (class_node.op_type == IS_CONST) {
+ opline->op1_type = IS_CONST;
+ opline->op1.constant =
+ zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline->op1, &class_node);
+ }
+ if (method_name->op_type == IS_CONST) {
+ opline->op2_type = IS_CONST;
+ opline->op2.constant =
+ zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
+ if (opline->op1_type == IS_CONST) {
+ GET_CACHE_SLOT(opline->op2.constant);
+ } else {
+ GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
+ }
+ } else {
+ SET_NODE(opline->op2, method_name);
+ }
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
zend_do_extended_fcall_begin(TSRMLS_C);
@@ -2050,17 +2434,18 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
opline->opcode = ZEND_DO_FCALL;
- opline->op1 = *function_name;
- ZVAL_LONG(&opline->op2.u.constant, zend_hash_func(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant) + 1));
+ SET_NODE(opline->op1, function_name);
+ CALCULATE_LITERAL_HASH(opline->op1.constant);
+ GET_CACHE_SLOT(opline->op1.constant);
} else {
opline->opcode = ZEND_DO_FCALL_BY_NAME;
SET_UNUSED(opline->op1);
}
}
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.op_type = IS_VAR;
- *result = opline->result;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_VAR;
+ GET_NODE(result, opline->result) ;
SET_UNUSED(opline->op2);
zend_stack_del_top(&CG(function_call_stack));
@@ -2079,24 +2464,24 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
function_ptr = *function_ptr_ptr;
- if (original_op == ZEND_SEND_REF && !CG(allow_call_time_pass_reference)) {
+ if (original_op == ZEND_SEND_REF) {
if (function_ptr &&
- function_ptr->common.function_name &&
- function_ptr->common.type == ZEND_USER_FUNCTION &&
- !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
- zend_error(E_DEPRECATED,
- "Call-time pass-by-reference has been deprecated; "
- "If you would like to pass it by reference, modify the declaration of %s(). "
- "If you would like to enable call-time pass-by-reference, you can set "
- "allow_call_time_pass_reference to true in your INI file", function_ptr->common.function_name);
+ function_ptr->common.function_name &&
+ function_ptr->common.type == ZEND_USER_FUNCTION &&
+ !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+ zend_error(E_COMPILE_ERROR,
+ "Call-time pass-by-reference has been removed; "
+ "If you would like to pass argument by reference, modify the declaration of %s().",
+ function_ptr->common.function_name);
} else {
- zend_error(E_DEPRECATED, "Call-time pass-by-reference has been deprecated");
+ zend_error(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed");
}
- }
-
+ return;
+ }
+
if (function_ptr) {
if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
- if (param->op_type & (IS_VAR|IS_CV)) {
+ if (param->op_type & (IS_VAR|IS_CV) && original_op != ZEND_SEND_VAL) {
send_by_reference = 1;
if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
/* Method call */
@@ -2169,8 +2554,8 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
}
}
opline->opcode = op;
- opline->op1 = *param;
- opline->op2.u.opline_num = offset;
+ SET_NODE(opline->op1, param);
+ opline->op2.opline_num = offset;
SET_UNUSED(opline->op2);
}
/* }}} */
@@ -2186,7 +2571,7 @@ static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRML
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- opline->op1 = switch_entry->cond;
+ SET_NODE(opline->op1, &switch_entry->cond);
SET_UNUSED(opline->op2);
opline->extended_value = 0;
return 0;
@@ -2198,22 +2583,22 @@ static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /*
zend_op *opline;
/* If we reach the seperator then stop applying the stack */
- if (foreach_copy->result.op_type == IS_UNUSED && foreach_copy->op1.op_type == IS_UNUSED) {
+ if (foreach_copy->result_type == IS_UNUSED && foreach_copy->op1_type == IS_UNUSED) {
return 1;
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = (foreach_copy->result.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- opline->op1 = foreach_copy->result;
+ opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
+ COPY_NODE(opline->op1, foreach_copy->result);
SET_UNUSED(opline->op2);
opline->extended_value = 1;
- if (foreach_copy->op1.op_type != IS_UNUSED) {
+ if (foreach_copy->op1_type != IS_UNUSED) {
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = (foreach_copy->op1.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- opline->op1 = foreach_copy->op1;
+ opline->opcode = (foreach_copy->op1_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
+ COPY_NODE(opline->op1, foreach_copy->op1);
SET_UNUSED(opline->op2);
opline->extended_value = 0;
}
@@ -2228,7 +2613,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
int start_op_number, end_op_number;
if (do_end_vparse) {
- if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
+ if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(expr)) {
zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
} else {
zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
@@ -2247,23 +2632,23 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
end_op_number = get_next_op_number(CG(active_op_array));
while (start_op_number < end_op_number) {
- CG(active_op_array)->opcodes[start_op_number].op1.u.EA.type = EXT_TYPE_FREE_ON_RETURN;
+ CG(active_op_array)->opcodes[start_op_number].extended_value |= EXT_TYPE_FREE_ON_RETURN;
start_op_number++;
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_RETURN;
+ opline->opcode = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) ? ZEND_RETURN_BY_REF : ZEND_RETURN;
if (expr) {
- opline->op1 = *expr;
+ SET_NODE(opline->op1, expr);
if (do_end_vparse && zend_is_function_or_method_call(expr)) {
opline->extended_value = ZEND_RETURNS_FUNCTION;
}
} else {
- opline->op1.op_type = IS_CONST;
- INIT_ZVAL(opline->op1.u.constant);
+ opline->op1_type = IS_CONST;
+ LITERAL_NULL(opline->op1);
}
SET_UNUSED(opline->op2);
@@ -2288,7 +2673,7 @@ static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /*
void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
{
- open_parentheses->u.opline_num = get_next_op_number(CG(active_op_array));
+ open_parentheses->u.op.opline_num = get_next_op_number(CG(active_op_array));
}
/* }}} */
@@ -2309,7 +2694,7 @@ void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{
zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
- zend_add_catch_element(try_token->u.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
+ zend_add_catch_element(try_token->u.op.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
}
/* }}} */
@@ -2317,12 +2702,12 @@ void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additio
{
CG(active_op_array)->last--;
zend_do_if_end(TSRMLS_C);
- if (last_additional_catch->u.opline_num == -1) {
- CG(active_op_array)->opcodes[first_catch->u.opline_num].op1.u.EA.type = 1;
- CG(active_op_array)->opcodes[first_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
+ if (last_additional_catch->u.op.opline_num == -1) {
+ CG(active_op_array)->opcodes[first_catch->u.op.opline_num].result.num = 1;
+ CG(active_op_array)->opcodes[first_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
} else {
- CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].op1.u.EA.type = 1;
- CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].result.num = 1;
+ CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
}
DEC_BPC(CG(active_op_array));
}
@@ -2330,41 +2715,40 @@ void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additio
void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
{
- try_token->u.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
+ try_token->u.op.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
INC_BPC(CG(active_op_array));
}
/* }}} */
-void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
+void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
{
long catch_op_number;
zend_op *opline;
znode catch_class;
- zend_do_fetch_class(&catch_class, class_name TSRMLS_CC);
-
- catch_op_number = get_next_op_number(CG(active_op_array));
- if (catch_op_number > 0) {
- opline = &CG(active_op_array)->opcodes[catch_op_number-1];
- if (opline->opcode == ZEND_FETCH_CLASS) {
- opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
- }
+ if (class_name->op_type == IS_CONST &&
+ ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
+ zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
+ catch_class = *class_name;
+ } else {
+ zend_error(E_COMPILE_ERROR, "Bad class name in the catch statement");
}
+ catch_op_number = get_next_op_number(CG(active_op_array));
if (first_catch) {
- first_catch->u.opline_num = catch_op_number;
+ first_catch->u.op.opline_num = catch_op_number;
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_CATCH;
- opline->op1 = catch_class;
-/* SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */
- opline->op2.op_type = IS_CV;
- opline->op2.u.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len);
- opline->op2.u.EA.type = 0;
- opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */
+ opline->op1_type = IS_CONST;
+ opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &catch_class.u.constant TSRMLS_CC);
+ opline->op2_type = IS_CV;
+ opline->op2.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len, 0 TSRMLS_CC);
+ Z_STRVAL(catch_var->u.constant) = (char*)CG(active_op_array)->vars[opline->op2.var].name;
+ opline->result.num = 0; /* 1 means it's the last catch in the block */
- try_token->u.opline_num = catch_op_number;
+ try_token->u.op.opline_num = catch_op_number;
}
/* }}} */
@@ -2382,7 +2766,7 @@ void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */
zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
- CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[try_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
}
/* }}} */
@@ -2392,7 +2776,7 @@ void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_THROW;
- opline->op1 = *expr;
+ SET_NODE(opline->op1, expr);
SET_UNUSED(opline->op2);
}
/* }}} */
@@ -2411,13 +2795,14 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
}
+ op_array->run_time_cache = NULL;
}
}
/* }}} */
static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
{
- zend_function *function;
+ zend_function *function, *new_function;
if (!ce->parent) {
return;
@@ -2478,8 +2863,8 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
/* inherit parent's constructor */
- zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL);
- function_add_ref(function);
+ zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), (void**)&new_function);
+ function_add_ref(new_function);
} else {
/* Don't inherit the old style constructor if we already have the new style constructor */
char *lc_class_name;
@@ -2492,8 +2877,8 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
if (function->common.fn_flags & ZEND_ACC_CTOR) {
/* inherit parent's constructor */
- zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), NULL);
- function_add_ref(function);
+ zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), (void**)&new_function);
+ function_add_ref(new_function);
}
}
efree(lc_parent_class_name);
@@ -2541,8 +2926,17 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
return 1;
}
- /* Checks for constructors only if they are declared in an interface */
- if ((fe->common.fn_flags & ZEND_ACC_CTOR) && (proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
+ /* Checks for constructors only if they are declared in an interface,
+ * or explicitly marked as abstract
+ */
+ if ((fe->common.fn_flags & ZEND_ACC_CTOR)
+ && ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
+ && (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) {
+ return 1;
+ }
+
+ /* If both methods are private do not enforce a signature */
+ if ((fe->common.fn_flags & ZEND_ACC_PRIVATE) && (proto->common.fn_flags & ZEND_ACC_PRIVATE)) {
return 1;
}
@@ -2553,13 +2947,14 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
}
if (fe->common.type != ZEND_USER_FUNCTION
- && proto->common.pass_rest_by_reference
- && !fe->common.pass_rest_by_reference) {
+ && (proto->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) != 0
+ && (fe->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) == 0) {
return 0;
}
/* by-ref constraints on return values are covariant */
- if (proto->common.return_reference && !fe->common.return_reference) {
+ if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+ && !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
return 0;
}
@@ -2568,32 +2963,59 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
/* Only one has a type hint and the other one doesn't */
return 0;
}
- if (fe->common.arg_info[i].class_name
- && strcasecmp(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)!=0) {
- char *colon;
- if (fe->common.type != ZEND_USER_FUNCTION) {
- return 0;
- } else if (strchr(proto->common.arg_info[i].class_name, '\\') != NULL ||
- (colon = zend_memrchr(fe->common.arg_info[i].class_name, '\\', fe->common.arg_info[i].class_name_len)) == NULL ||
- strcasecmp(colon+1, proto->common.arg_info[i].class_name) != 0) {
- zend_class_entry **fe_ce, **proto_ce;
- int found, found2;
-
- found = zend_lookup_class(fe->common.arg_info[i].class_name, fe->common.arg_info[i].class_name_len, &fe_ce TSRMLS_CC);
- found2 = zend_lookup_class(proto->common.arg_info[i].class_name, proto->common.arg_info[i].class_name_len, &proto_ce TSRMLS_CC);
-
- /* Check for class alias */
- if (found != SUCCESS || found2 != SUCCESS ||
- (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
- (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
- *fe_ce != *proto_ce) {
+ if (fe->common.arg_info[i].class_name) {
+ const char *fe_class_name, *proto_class_name;
+ zend_uint fe_class_name_len, proto_class_name_len;
+
+ if (!strcasecmp(fe->common.arg_info[i].class_name, "parent") && proto->common.scope) {
+ fe_class_name = proto->common.scope->name;
+ fe_class_name_len = proto->common.scope->name_length;
+ } else if (!strcasecmp(fe->common.arg_info[i].class_name, "self") && fe->common.scope) {
+ fe_class_name = fe->common.scope->name;
+ fe_class_name_len = fe->common.scope->name_length;
+ } else {
+ fe_class_name = fe->common.arg_info[i].class_name;
+ fe_class_name_len = fe->common.arg_info[i].class_name_len;
+ }
+
+ if (!strcasecmp(proto->common.arg_info[i].class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
+ proto_class_name = proto->common.scope->parent->name;
+ proto_class_name_len = proto->common.scope->parent->name_length;
+ } else if (!strcasecmp(proto->common.arg_info[i].class_name, "self") && proto->common.scope) {
+ proto_class_name = proto->common.scope->name;
+ proto_class_name_len = proto->common.scope->name_length;
+ } else {
+ proto_class_name = proto->common.arg_info[i].class_name;
+ proto_class_name_len = proto->common.arg_info[i].class_name_len;
+ }
+
+ if (strcasecmp(fe_class_name, proto_class_name)!=0) {
+ const char *colon;
+
+ if (fe->common.type != ZEND_USER_FUNCTION) {
return 0;
+ } else if (strchr(proto_class_name, '\\') != NULL ||
+ (colon = zend_memrchr(fe_class_name, '\\', fe_class_name_len)) == NULL ||
+ strcasecmp(colon+1, proto_class_name) != 0) {
+ zend_class_entry **fe_ce, **proto_ce;
+ int found, found2;
+
+ found = zend_lookup_class(fe_class_name, fe_class_name_len, &fe_ce TSRMLS_CC);
+ found2 = zend_lookup_class(proto_class_name, proto_class_name_len, &proto_ce TSRMLS_CC);
+
+ /* Check for class alias */
+ if (found != SUCCESS || found2 != SUCCESS ||
+ (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
+ (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
+ *fe_ce != *proto_ce) {
+ return 0;
+ }
}
- }
- }
- if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) {
- /* Only one has an array type hint and the other one doesn't */
+ }
+ }
+ if (fe->common.arg_info[i].type_hint != proto->common.arg_info[i].type_hint) {
+ /* Incompatible type hint */
return 0;
}
@@ -2603,7 +3025,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
}
}
- if (proto->common.pass_rest_by_reference) {
+ if (proto->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) {
for (i=proto->common.num_args; i < fe->common.num_args; i++) {
if (!fe->common.arg_info[i].pass_by_reference) {
return 0;
@@ -2614,19 +3036,179 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
}
/* }}} */
-static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
+#define REALLOC_BUF_IF_EXCEED(buf, offset, length, size) \
+ if (UNEXPECTED(offset - buf + size >= length)) { \
+ length += size + 1; \
+ buf = erealloc(buf, length); \
+ }
+
+static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
{
- zend_uint child_flags;
- zend_uint parent_flags = parent->common.fn_flags;
- zend_function *child;
- TSRMLS_FETCH();
+ char *offset, *buf;
+ zend_uint length = 1024;
- if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
- if (parent_flags & (ZEND_ACC_ABSTRACT)) {
- child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+ offset = buf = (char *)emalloc(length * sizeof(char));
+ if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ *(offset++) = '&';
+ *(offset++) = ' ';
+ }
+
+ if (fptr->common.scope) {
+ memcpy(offset, fptr->common.scope->name, fptr->common.scope->name_length);
+ offset += fptr->common.scope->name_length;
+ *(offset++) = ':';
+ *(offset++) = ':';
+ }
+
+ {
+ size_t name_len = strlen(fptr->common.function_name);
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, name_len);
+ memcpy(offset, fptr->common.function_name, name_len);
+ offset += name_len;
+ }
+
+ *(offset++) = '(';
+ if (fptr->common.arg_info) {
+ zend_uint i, required;
+ zend_arg_info *arg_info = fptr->common.arg_info;
+
+ required = fptr->common.required_num_args;
+ for (i = 0; i < fptr->common.num_args;) {
+ if (arg_info->class_name) {
+ const char *class_name;
+ zend_uint class_name_len;
+ if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope ) {
+ class_name = fptr->common.scope->name;
+ class_name_len = fptr->common.scope->name_length;
+ } else if (!strcasecmp(arg_info->class_name, "parent") && fptr->common.scope->parent) {
+ class_name = fptr->common.scope->parent->name;
+ class_name_len = fptr->common.scope->parent->name_length;
+ } else {
+ class_name = arg_info->class_name;
+ class_name_len = arg_info->class_name_len;
+ }
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, class_name_len);
+ memcpy(offset, class_name, class_name_len);
+ offset += class_name_len;
+ *(offset++) = ' ';
+ } else if (arg_info->type_hint) {
+ zend_uint type_name_len;
+ char *type_name = zend_get_type_by_const(arg_info->type_hint);
+ type_name_len = strlen(type_name);
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len);
+ memcpy(offset, type_name, type_name_len);
+ offset += type_name_len;
+ *(offset++) = ' ';
+ }
+
+ if (arg_info->pass_by_reference) {
+ *(offset++) = '&';
+ }
+ *(offset++) = '$';
+
+ if (arg_info->name) {
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, arg_info->name_len);
+ memcpy(offset, arg_info->name, arg_info->name_len);
+ offset += arg_info->name_len;
+ } else {
+ zend_uint idx = i;
+ memcpy(offset, "param", 5);
+ offset += 5;
+ do {
+ *(offset++) = (char) (idx % 10) + '0';
+ idx /= 10;
+ } while (idx > 0);
+ }
+ if (i >= required) {
+ *(offset++) = ' ';
+ *(offset++) = '=';
+ *(offset++) = ' ';
+ if (fptr->type == ZEND_USER_FUNCTION) {
+ zend_op *precv = NULL;
+ {
+ zend_uint idx = i;
+ zend_op *op = ((zend_op_array *)fptr)->opcodes;
+ zend_op *end = op + ((zend_op_array *)fptr)->last;
+
+ ++idx;
+ while (op < end) {
+ if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
+ && op->op1.num == (long)idx)
+ {
+ precv = op;
+ }
+ ++op;
+ }
+ }
+ if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
+ zval *zv, zv_copy;
+ int use_copy;
+ ALLOC_ZVAL(zv);
+ *zv = *precv->op2.zv;
+ zval_copy_ctor(zv);
+ INIT_PZVAL(zv);
+ zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
+ if (Z_TYPE_P(zv) == IS_BOOL) {
+ if (Z_LVAL_P(zv)) {
+ memcpy(offset, "true", 4);
+ offset += 4;
+ } else {
+ memcpy(offset, "false", 5);
+ offset += 5;
+ }
+ } else if (Z_TYPE_P(zv) == IS_NULL) {
+ memcpy(offset, "NULL", 4);
+ offset += 4;
+ } else if (Z_TYPE_P(zv) == IS_STRING) {
+ *(offset++) = '\'';
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
+ memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
+ offset += MIN(Z_STRLEN_P(zv), 10);
+ if (Z_STRLEN_P(zv) > 10) {
+ *(offset++) = '.';
+ *(offset++) = '.';
+ *(offset++) = '.';
+ }
+ *(offset++) = '\'';
+ } else if (Z_TYPE_P(zv) == IS_ARRAY) {
+ memcpy(offset, "Array", 5);
+ offset += 5;
+ } else {
+ zend_make_printable_zval(zv, &zv_copy, &use_copy);
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN(zv_copy));
+ memcpy(offset, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
+ offset += Z_STRLEN(zv_copy);
+ if (use_copy) {
+ zval_dtor(&zv_copy);
+ }
+ }
+ zval_ptr_dtor(&zv);
+ }
+ } else {
+ memcpy(offset, "NULL", 4);
+ offset += 4;
+ }
+ }
+
+ if (++i < fptr->common.num_args) {
+ *(offset++) = ',';
+ *(offset++) = ' ';
+ }
+ arg_info++;
+ REALLOC_BUF_IF_EXCEED(buf, offset, length, 32);
}
- return 1; /* method doesn't exist in child, copy from parent */
}
+ *(offset++) = ')';
+ *offset = '\0';
+
+ return buf;
+}
+/* }}} */
+
+static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */
+{
+ zend_uint child_flags;
+ zend_uint parent_flags = parent->common.fn_flags;
if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
&& parent->common.fn_flags & ZEND_ACC_ABSTRACT
@@ -2683,14 +3265,33 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
- zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_get_function_declaration(child->common.prototype? child->common.prototype : parent TSRMLS_CC));
}
} else if (EG(error_reporting) & E_STRICT || EG(user_error_handler)) { /* Check E_STRICT (or custom error handler) before the check so that we save some time */
if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
- zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
+ char *method_prototype = zend_get_function_declaration(child->common.prototype? child->common.prototype : parent TSRMLS_CC);
+ zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, method_prototype);
+ efree(method_prototype);
}
}
+}
+/* }}} */
+
+static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
+{
+ zend_uint parent_flags = parent->common.fn_flags;
+ zend_function *child;
+ TSRMLS_FETCH();
+ if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
+ if (parent_flags & (ZEND_ACC_ABSTRACT)) {
+ child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+ }
+ return 1; /* method doesn't exist in child, copy from parent */
+ }
+
+ do_inheritance_check_on_method(child, parent TSRMLS_CC);
+
return 0;
}
/* }}} */
@@ -2730,42 +3331,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
- } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
- if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
- /* Explicitly copy the default value from the parent (if it has one) */
- zval **pvalue;
-
- if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
- Z_ADDREF_PP(pvalue);
- zend_hash_quick_del(&ce->default_properties, child_info->name, child_info->name_length+1, parent_info->h);
- zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
- }
- }
- return 1; /* Inherit from the parent */
- } else if ((child_info->flags & ZEND_ACC_PUBLIC) && (parent_info->flags & ZEND_ACC_PROTECTED)) {
- char *prot_name;
- int prot_name_length;
-
- zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
- if (child_info->flags & ZEND_ACC_STATIC) {
- zval **prop;
- HashTable *ht;
-
- if (parent_ce->type != ce->type) {
- /* User class extends internal class */
- TSRMLS_FETCH();
-
- ht = CE_STATIC_MEMBERS(parent_ce);
- } else {
- ht = &parent_ce->default_static_members;
- }
- if (zend_hash_find(ht, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
- zend_hash_del(&ce->default_static_members, prot_name, prot_name_length+1);
- }
- } else {
- zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
- }
- pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
+ } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
+ Z_DELREF_P(ce->default_properties_table[parent_info->offset]);
+ ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
+ ce->default_properties_table[child_info->offset] = NULL;
+ child_info->offset = parent_info->offset;
}
return 0; /* Don't copy from parent */
} else {
@@ -2822,25 +3392,27 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
}
/* }}} */
-static int inherit_static_prop(zval **p TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
+#ifdef ZTS
+static void zval_internal_ctor(zval **p) /* {{{ */
{
- HashTable *target = va_arg(args, HashTable*);
+ zval *orig_ptr = *p;
- if (!zend_hash_quick_exists(target, key->arKey, key->nKeyLength, key->h)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
- if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) {
- Z_ADDREF_PP(p);
- }
- }
- return ZEND_HASH_APPLY_KEEP;
+ ALLOC_ZVAL(*p);
+ MAKE_COPY_ZVAL(&orig_ptr, *p);
}
/* }}} */
-#define zval_property_ctor(parent_ce, ce) \
- ((copy_ctor_func_t) (((parent_ce)->type != (ce)->type) ? zval_shared_property_ctor : zval_add_ref))
+# define zval_property_ctor(parent_ce, ce) \
+ ((void (*)(void *)) (((parent_ce)->type != (ce)->type) ? zval_internal_ctor : zval_add_ref))
+#else
+# define zval_property_ctor(parent_ce, ce) \
+ ((void (*)(void *)) zval_add_ref)
+#endif
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
{
+ zend_property_info *property_info;
+
if ((ce->ce_flags & ZEND_ACC_INTERFACE)
&& !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
@@ -2862,14 +3434,90 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
/* Inherit properties */
- zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
+ if (parent_ce->default_properties_count) {
+ int i = ce->default_properties_count + parent_ce->default_properties_count;
+
+ ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
+ if (ce->default_properties_count) {
+ while (i-- > parent_ce->default_properties_count) {
+ ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
+ }
+ }
+ for (i = 0; i < parent_ce->default_properties_count; i++) {
+ ce->default_properties_table[i] = parent_ce->default_properties_table[i];
+ if (ce->default_properties_table[i]) {
+#ifdef ZTS
+ if (parent_ce->type != ce->type) {
+ zval *p;
+
+ ALLOC_ZVAL(p);
+ MAKE_COPY_ZVAL(&ce->default_properties_table[i], p);
+ ce->default_properties_table[i] = p;
+ } else {
+ Z_ADDREF_P(ce->default_properties_table[i]);
+ }
+#else
+ Z_ADDREF_P(ce->default_properties_table[i]);
+#endif
+ }
+ }
+ ce->default_properties_count += parent_ce->default_properties_count;
+ }
+
if (parent_ce->type != ce->type) {
/* User class extends internal class */
zend_update_class_constants(parent_ce TSRMLS_CC);
- zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
+ if (parent_ce->default_static_members_count) {
+ int i = ce->default_static_members_count + parent_ce->default_static_members_count;
+
+ ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
+ if (ce->default_static_members_count) {
+ while (i-- > parent_ce->default_static_members_count) {
+ ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
+ }
+ }
+ for (i = 0; i < parent_ce->default_static_members_count; i++) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
+ ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
+ Z_ADDREF_P(ce->default_static_members_table[i]);
+ }
+ ce->default_static_members_count += parent_ce->default_static_members_count;
+ ce->static_members_table = ce->default_static_members_table;
+ }
} else {
- zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
+ if (parent_ce->default_static_members_count) {
+ int i = ce->default_static_members_count + parent_ce->default_static_members_count;
+
+ ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
+ if (ce->default_static_members_count) {
+ while (i-- > parent_ce->default_static_members_count) {
+ ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
+ }
+ }
+ for (i = 0; i < parent_ce->default_static_members_count; i++) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
+ ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
+ Z_ADDREF_P(ce->default_static_members_table[i]);
+ }
+ ce->default_static_members_count += parent_ce->default_static_members_count;
+ if (ce->type == ZEND_USER_CLASS) {
+ ce->static_members_table = ce->default_static_members_table;
+ }
+ }
}
+
+ for (zend_hash_internal_pointer_reset(&ce->properties_info);
+ zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
+ zend_hash_move_forward(&ce->properties_info)) {
+ if (property_info->ce == ce) {
+ if (property_info->flags & ZEND_ACC_STATIC) {
+ property_info->offset += parent_ce->default_static_members_count;
+ } else {
+ property_info->offset += parent_ce->default_properties_count;
+ }
+ }
+ }
+
zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
@@ -2878,10 +3526,12 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
- } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {
+ } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)
+ && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
/* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
zend_verify_abstract_class(ce TSRMLS_CC);
}
+ ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
}
/* }}} */
@@ -2949,16 +3599,821 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
}
/* }}} */
-ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
+ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
+{
+ zend_uint i, ignore = 0;
+ zend_uint current_trait_num = ce->num_traits;
+ zend_uint parent_trait_num = ce->parent ? ce->parent->num_traits : 0;
+
+ for (i = 0; i < ce->num_traits; i++) {
+ if (ce->traits[i] == NULL) {
+ memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
+ i--;
+ } else if (ce->traits[i] == trait) {
+ if (i < parent_trait_num) {
+ ignore = 1;
+ }
+ }
+ }
+ if (!ignore) {
+ if (ce->num_traits >= current_trait_num) {
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
+ } else {
+ ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
+ }
+ }
+ ce->traits[ce->num_traits++] = trait;
+ trait->refcount++;
+ }
+}
+/* }}} */
+
+static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC) /* {{{ */
+{
+ zend_uint fn_flags = fn->common.scope->ce_flags;
+ zend_uint other_flags = other_fn->common.scope->ce_flags;
+
+ return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
+ && zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC)
+ && ((fn_flags & ZEND_ACC_FINAL) == (other_flags & ZEND_ACC_FINAL)) /* equal final qualifier */
+ && ((fn_flags & ZEND_ACC_STATIC)== (other_flags & ZEND_ACC_STATIC)); /* equal static qualifier */
+}
+/* }}} */
+
+static int zend_traits_merge_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ size_t current;
+ size_t i;
+ size_t count;
+ HashTable* resulting_table;
+ HashTable** function_tables;
+ zend_class_entry *ce;
+ size_t collision = 0;
+ size_t abstract_solved = 0;
+ zend_function* other_trait_fn;
+
+ current = va_arg(args, size_t); /* index of current trait */
+ count = va_arg(args, size_t);
+ resulting_table = va_arg(args, HashTable*);
+ function_tables = va_arg(args, HashTable**);
+ ce = va_arg(args, zend_class_entry*);
+
+ for (i = 0; i < count; i++) {
+ if (i == current) {
+ continue; /* just skip this, cause its the table this function is applied on */
+ }
+
+ if (zend_hash_quick_find(function_tables[i], hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **)&other_trait_fn) == SUCCESS) {
+ /* if it is an abstract method, there is no collision */
+ if (other_trait_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ /* Make sure they are compatible */
+ /* In case both are abstract, just check prototype, but need to do that in both directions */
+ if (!zend_traits_method_compatibility_check(fn, other_trait_fn TSRMLS_CC)) {
+ zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
+ zend_get_function_declaration(fn TSRMLS_CC),
+ zend_get_function_declaration(other_trait_fn TSRMLS_CC));
+ }
+
+ /* we can savely free and remove it from other table */
+ zend_function_dtor(other_trait_fn);
+ zend_hash_quick_del(function_tables[i], hash_key->arKey, hash_key->nKeyLength, hash_key->h);
+ } else {
+ /* if it is not an abstract method, there is still no collision */
+ /* if fn is an abstract method */
+ if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ /* Make sure they are compatible.
+ Here, we already know other_trait_fn cannot be abstract, full check ok. */
+ if (!zend_traits_method_compatibility_check(fn, other_trait_fn TSRMLS_CC)) {
+ zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
+ zend_get_function_declaration(fn TSRMLS_CC),
+ zend_get_function_declaration(other_trait_fn TSRMLS_CC));
+ }
+
+ /* just mark as solved, will be added if its own trait is processed */
+ abstract_solved = 1;
+ } else {
+ /* but else, we have a collision of non-abstract methods */
+ collision++;
+ zend_function_dtor(other_trait_fn);
+ zend_hash_quick_del(function_tables[i], hash_key->arKey, hash_key->nKeyLength, hash_key->h);
+ }
+ }
+ }
+ }
+
+ if (collision) {
+ zend_function* class_fn;
+
+ /* make sure method is not already overridden in class */
+ if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **)&class_fn) == FAILURE
+ || class_fn->common.scope != ce) {
+ zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s", fn->common.function_name, ce->name);
+ }
+
+ zend_function_dtor(fn);
+ } else if (abstract_solved) {
+ zend_function_dtor(fn);
+ } else {
+ /* Add it to result function table */
+ if (zend_hash_quick_add(resulting_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, fn, sizeof(zend_function), NULL)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because failure occurred during updating resulting trait method table", fn->common.function_name);
+ }
+ }
+
+ return ZEND_HASH_APPLY_REMOVE;
+}
+/* }}} */
+
+static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint mname_len, zend_function* fe TSRMLS_DC) /* {{{ */
+{
+ if (!strncmp(mname, ZEND_CLONE_FUNC_NAME, mname_len)) {
+ ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
+ } else if (!strncmp(mname, ZEND_CONSTRUCTOR_FUNC_NAME, mname_len)) {
+ if (ce->constructor) {
+ zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
+ }
+ ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
+ } else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME, mname_len)) {
+ ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
+ } else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) {
+ ce->__get = fe;
+ } else if (!strncmp(mname, ZEND_SET_FUNC_NAME, mname_len)) {
+ ce->__set = fe;
+ } else if (!strncmp(mname, ZEND_CALL_FUNC_NAME, mname_len)) {
+ ce->__call = fe;
+ } else if (!strncmp(mname, ZEND_UNSET_FUNC_NAME, mname_len)) {
+ ce->__unset = fe;
+ } else if (!strncmp(mname, ZEND_ISSET_FUNC_NAME, mname_len)) {
+ ce->__isset = fe;
+ } else if (!strncmp(mname, ZEND_CALLSTATIC_FUNC_NAME, mname_len)) {
+ ce->__callstatic = fe;
+ } else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) {
+ ce->__tostring = fe;
+ } else if (ce->name_length + 1 == mname_len) {
+ char *lowercase_name = emalloc(ce->name_length + 1);
+ zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length);
+ lowercase_name = (char*)zend_new_interned_string(lowercase_name, ce->name_length + 1, 1 TSRMLS_CC);
+ if (!memcmp(mname, lowercase_name, mname_len)) {
+ if (ce->constructor) {
+ zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
+ }
+ ce->constructor = fe;
+ fe->common.fn_flags |= ZEND_ACC_CTOR;
+ }
+ str_efree(lowercase_name);
+ }
+}
+/* }}} */
+
+static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ zend_class_entry *ce = va_arg(args, zend_class_entry*);
+ zend_function* existing_fn = NULL;
+ zend_function fn_copy, *fn_copy_p;
+ zend_function* prototype = NULL; /* is used to determine the prototype according to the inheritance chain */
+
+ if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE ||
+ existing_fn->common.scope != ce) {
+ /* not found or inherited from other class or interface */
+ zend_function* parent_function;
+
+ if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) {
+ prototype = parent_function; /* ->common.fn_flags |= ZEND_ACC_ABSTRACT; */
+
+ /* we got that method in the parent class, and are going to override it,
+ except, if the trait is just asking to have an abstract method implemented. */
+ if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ /* then we clean up an skip this method */
+ zend_function_dtor(fn);
+ return ZEND_HASH_APPLY_REMOVE;
+ }
+ }
+
+ fn->common.scope = ce;
+ fn->common.prototype = prototype;
+
+ if (prototype
+ && (prototype->common.fn_flags & ZEND_ACC_IMPLEMENTED_ABSTRACT
+ || prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+ fn->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
+ } else if (fn->common.fn_flags & ZEND_ACC_IMPLEMENTED_ABSTRACT) {
+ /* remove ZEND_ACC_IMPLEMENTED_ABSTRACT flag, think it shouldn't be copied to class */
+ fn->common.fn_flags = fn->common.fn_flags - ZEND_ACC_IMPLEMENTED_ABSTRACT;
+ }
+
+ /* check whether the trait method fullfills the inheritance requirements */
+ if (prototype) {
+ do_inheritance_check_on_method(fn, prototype TSRMLS_CC);
+ }
+
+ /* one more thing: make sure we properly implement an abstract method */
+ if (existing_fn && existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ prototype = fn->common.prototype;
+ do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
+ fn->common.prototype = prototype;
+ }
+
+ /* delete inherited fn if the function to be added is not abstract */
+ if (existing_fn
+ && existing_fn->common.scope != ce
+ && (fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) {
+ /* it is just a reference which was added to the subclass while doing
+ the inheritance, so we can deleted now, and will add the overriding
+ method afterwards.
+ Except, if we try to add an abstract function, then we should not
+ delete the inherited one */
+ zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
+ }
+
+
+ if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+ }
+ if (fn->op_array.static_variables) {
+ ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
+ }
+ fn_copy = *fn;
+ function_add_ref(&fn_copy);
+
+ if (zend_hash_quick_update(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, &fn_copy, sizeof(zend_function), (void**)&fn_copy_p)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because failure occurred during updating class method table", hash_key->arKey);
+ }
+
+ zend_add_magic_methods(ce, hash_key->arKey, hash_key->nKeyLength, fn_copy_p TSRMLS_CC);
+
+ zend_function_dtor(fn);
+ } else {
+ zend_function_dtor(fn);
+ }
+
+ return ZEND_HASH_APPLY_REMOVE;
+}
+/* }}} */
+
+static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ HashTable* target;
+ zend_trait_alias** aliases;
+ HashTable* exclude_table;
+ char* lcname;
+ unsigned int fnname_len;
+ zend_function fn_copy;
+ void* dummy;
+ size_t i = 0;
+
+ target = va_arg(args, HashTable*);
+ aliases = va_arg(args, zend_trait_alias**);
+ exclude_table = va_arg(args, HashTable*);
+
+ fnname_len = strlen(fn->common.function_name);
+
+ /* apply aliases which are qualified with a class name, there should not be any ambiguity */
+ if (aliases) {
+ while (aliases[i]) {
+ /* Scope unset or equal to the function we compare to, and the alias applies to fn */
+ if (aliases[i]->alias != NULL
+ && (!aliases[i]->trait_method->ce || fn->common.scope == aliases[i]->trait_method->ce)
+ && aliases[i]->trait_method->mname_len == fnname_len
+ && (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) {
+ fn_copy = *fn;
+ function_add_ref(&fn_copy);
+ /* this function_name is never destroyed, because ZEND_ACC_ALIAS
+ flag is set */
+ fn_copy.common.function_name = aliases[i]->alias;
+ fn_copy.common.fn_flags |= ZEND_ACC_ALIAS;
+
+ /* if it is 0, no modifieres has been changed */
+ if (aliases[i]->modifiers) {
+ fn_copy.common.fn_flags = aliases[i]->modifiers | ZEND_ACC_ALIAS;
+ if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
+ fn_copy.common.fn_flags |= ZEND_ACC_PUBLIC;
+ }
+ fn_copy.common.fn_flags |= fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK);
+ }
+
+ lcname = zend_str_tolower_dup(aliases[i]->alias, aliases[i]->alias_len);
+
+ if (zend_hash_add(target, lcname, aliases[i]->alias_len+1, &fn_copy, sizeof(zend_function), NULL)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Failed to add aliased trait method (%s) to the trait table. There is probably already a trait method with the same name", fn_copy.common.function_name);
+ }
+ efree(lcname);
+
+ /** Record the trait from which this alias was resolved. */
+ if (!aliases[i]->trait_method->ce) {
+ aliases[i]->trait_method->ce = fn->common.scope;
+ }
+ }
+ i++;
+ }
+ }
+
+ lcname = zend_str_tolower_dup(fn->common.function_name, fnname_len);
+
+ if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
+ /* is not in hashtable, thus, function is not to be excluded */
+ fn_copy = *fn;
+ function_add_ref(&fn_copy);
+ fn_copy.common.fn_flags |= ZEND_ACC_ALIAS;
+
+ /* apply aliases which are not qualified by a class name, or which have not
+ * alias name, just setting visibility */
+ if (aliases) {
+ i = 0;
+ while (aliases[i]) {
+ /* Scope unset or equal to the function we compare to, and the alias applies to fn */
+ if (aliases[i]->alias == NULL && aliases[i]->modifiers != 0
+ && (!aliases[i]->trait_method->ce || fn->common.scope == aliases[i]->trait_method->ce)
+ && (aliases[i]->trait_method->mname_len == fnname_len)
+ && (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) {
+ fn_copy.common.fn_flags = aliases[i]->modifiers | ZEND_ACC_ALIAS;
+
+ if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
+ fn_copy.common.fn_flags |= ZEND_ACC_PUBLIC;
+ }
+ fn_copy.common.fn_flags |= fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK);
+
+ /** Record the trait from which this alias was resolved. */
+ if (!aliases[i]->trait_method->ce) {
+ aliases[i]->trait_method->ce = fn->common.scope;
+ }
+ }
+ i++;
+ }
+ }
+
+ if (zend_hash_add(target, lcname, fnname_len+1, &fn_copy, sizeof(zend_function), NULL)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Failed to add trait method (%s) to the trait table. There is probably already a trait method with the same name", fn_copy.common.function_name);
+ }
+ }
+
+ efree(lcname);
+
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+/* Copies function table entries to target function table with applied aliasing */
+static void zend_traits_copy_trait_function_table(HashTable *target, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
+{
+ zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, target, aliases, exclude_table);
+}
+/* }}} */
+
+static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+ size_t i, j = 0;
+ zend_trait_precedence *cur_precedence;
+ zend_trait_method_reference *cur_method_ref;
+ char *lcname;
+ zend_bool method_exists;
+
+ /* resolve class references */
+ if (ce->trait_precedences) {
+ i = 0;
+ while ((cur_precedence = ce->trait_precedences[i])) {
+ /** Resolve classes for all precedence operations. */
+ if (cur_precedence->exclude_from_classes) {
+ cur_method_ref = cur_precedence->trait_method;
+ if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len,
+ ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
+ zend_error(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
+ }
+
+ /** Ensure that the prefered method is actually available. */
+ lcname = zend_str_tolower_dup(cur_method_ref->method_name,
+ cur_method_ref->mname_len);
+ method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
+ lcname,
+ cur_method_ref->mname_len + 1);
+ efree(lcname);
+ if (!method_exists) {
+ zend_error(E_COMPILE_ERROR,
+ "A precedence rule was defined for %s::%s but this method does not exist",
+ cur_method_ref->ce->name,
+ cur_method_ref->method_name);
+ }
+
+ /** With the other traits, we are more permissive.
+ We do not give errors for those. This allows to be more
+ defensive in such definitions.
+ However, we want to make sure that the insteadof declartion
+ is consistent in itself.
+ */
+ j = 0;
+ while (cur_precedence->exclude_from_classes[j]) {
+ char* class_name = (char*)cur_precedence->exclude_from_classes[j];
+ zend_uint name_length = strlen(class_name);
+
+ if (!(cur_precedence->exclude_from_classes[j] = zend_fetch_class(class_name, name_length, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
+ zend_error(E_COMPILE_ERROR, "Could not find trait %s", class_name);
+ }
+
+ /* make sure that the trait method is not from a class mentioned in
+ exclude_from_classes, for consistency */
+ if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[i]) {
+ zend_error(E_COMPILE_ERROR,
+ "Inconsistent insteadof definition. "
+ "The method %s is to be used from %s, but %s is also on the exclude list",
+ cur_method_ref->method_name,
+ cur_precedence->trait_method->ce->name,
+ cur_precedence->trait_method->ce->name);
+ }
+
+ efree(class_name);
+ j++;
+ }
+ }
+ i++;
+ }
+ }
+
+ if (ce->trait_aliases) {
+ i = 0;
+ while (ce->trait_aliases[i]) {
+ /** For all aliases with an explicit class name, resolve the class now. */
+ if (ce->trait_aliases[i]->trait_method->class_name) {
+ cur_method_ref = ce->trait_aliases[i]->trait_method;
+ if (!(cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
+ zend_error(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
+ }
+
+ /** And, ensure that the referenced method is resolvable, too. */
+ lcname = zend_str_tolower_dup(cur_method_ref->method_name,
+ cur_method_ref->mname_len);
+ method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
+ lcname, cur_method_ref->mname_len + 1);
+ efree(lcname);
+
+ if (!method_exists) {
+ zend_error(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", cur_method_ref->ce->name, cur_method_ref->method_name);
+ }
+ }
+ i++;
+ }
+ }
+}
+/* }}} */
+
+static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */
+{
+ size_t i = 0, j;
+
+ if (!precedences) {
+ return;
+ }
+ while (precedences[i]) {
+ if (precedences[i]->exclude_from_classes) {
+ j = 0;
+ while (precedences[i]->exclude_from_classes[j]) {
+ if (precedences[i]->exclude_from_classes[j] == trait) {
+ zend_uint lcname_len = precedences[i]->trait_method->mname_len;
+ char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len);
+
+ if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) {
+ efree(lcname);
+ zend_error(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name, trait->name);
+ }
+ efree(lcname);
+ }
+ ++j;
+ }
+ }
+ ++i;
+ }
+}
+/* }}} */
+
+static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+ HashTable** function_tables;
+ HashTable* resulting_table;
+ HashTable exclude_table;
+ size_t i;
+
+ /* prepare copies of trait function tables for combination */
+ function_tables = emalloc(sizeof(HashTable*) * ce->num_traits);
+ resulting_table = (HashTable *)emalloc(sizeof(HashTable));
+
+ /* TODO: revisit this start size, may be its not optimal */
+ zend_hash_init_ex(resulting_table, 10, NULL, NULL, 0, 0);
+
+ for (i = 0; i < ce->num_traits; i++) {
+ function_tables[i] = (HashTable *)emalloc(sizeof(HashTable));
+ zend_hash_init_ex(function_tables[i], ce->traits[i]->function_table.nNumOfElements, NULL, NULL, 1, 0);
+
+ if (ce->trait_precedences) {
+ /* TODO: revisit this start size, may be its not optimal */
+ zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
+
+ zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
+
+ /* copies functions, applies defined aliasing, and excludes unused trait methods */
+ zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
+ zend_hash_destroy(&exclude_table);
+ } else {
+ zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
+ }
+ }
+
+ /* now merge trait methods */
+ for (i = 0; i < ce->num_traits; i++) {
+ zend_hash_apply_with_arguments(function_tables[i] TSRMLS_CC, (apply_func_args_t)zend_traits_merge_functions, 5, i, ce->num_traits, resulting_table, function_tables, ce);
+ }
+
+ /* Now the resulting_table contains all trait methods we would have to
+ * add to the class in the following step the methods are inserted into the method table
+ * if there is already a method with the same name it is replaced iff ce != fn.scope
+ * --> all inherited methods are overridden, methods defined in the class are left untouched
+ */
+ zend_hash_apply_with_arguments(resulting_table TSRMLS_CC, (apply_func_args_t)zend_traits_merge_functions_to_class, 1, ce);
+
+ /* free temporary function tables */
+ for (i = 0; i < ce->num_traits; i++) {
+ /* zend_hash_destroy(function_tables[i]); */
+ zend_hash_graceful_destroy(function_tables[i]);
+ efree(function_tables[i]);
+ }
+ efree(function_tables);
+
+ /* free temporary resulting table */
+ /* zend_hash_destroy(resulting_table); */
+ zend_hash_graceful_destroy(resulting_table);
+ efree(resulting_table);
+}
+/* }}} */
+
+static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t current_trait, const char* prop_name, int prop_name_length, ulong prop_hash, zend_class_entry *coliding_ce) /* {{{ */
+{
+ size_t i;
+ zend_property_info *coliding_prop;
+ for (i = 0; (i < current_trait) && (i < ce->num_traits); i++) {
+ if (zend_hash_quick_find(&ce->traits[i]->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
+ return ce->traits[i];
+ }
+ }
+
+ return coliding_ce;
+}
+/* }}} */
+
+static void zend_traits_register_private_property(zend_class_entry *ce, const char *name, int name_len, zend_property_info *old_info, zval *property TSRMLS_DC) /* {{{ */
+{
+ char *priv_name;
+ int priv_name_length;
+ const char *interned_name;
+ zend_property_info property_info;
+ ulong h = zend_get_hash_value(name, name_len+1);
+ property_info = *old_info;
+
+ if (old_info->flags & ZEND_ACC_STATIC) {
+ property_info.offset = ce->default_static_members_count++;
+ ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
+ ce->default_static_members_table[property_info.offset] = property;
+ if (ce->type == ZEND_USER_CLASS) {
+ ce->static_members_table = ce->default_static_members_table;
+ }
+ } else {
+ property_info.offset = ce->default_properties_count++;
+ ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
+ ce->default_properties_table[property_info.offset] = property;
+ }
+
+ zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_len, ce->type & ZEND_INTERNAL_CLASS);
+ property_info.name = priv_name;
+ property_info.name_length = priv_name_length;
+
+ interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
+ if (interned_name != property_info.name) {
+ if (ce->type == ZEND_USER_CLASS) {
+ efree((char*)property_info.name);
+ } else {
+ free((char*)property_info.name);
+ }
+ property_info.name = interned_name;
+ }
+
+ property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
+
+ property_info.ce = ce;
+
+ if (property_info.doc_comment) {
+ property_info.doc_comment = estrndup(property_info.doc_comment, property_info.doc_comment_len);
+ }
+
+ zend_hash_quick_update(&ce->properties_info, name, name_len+1, h, &property_info, sizeof(zend_property_info), NULL);
+}
+/* }}} */
+
+static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+ size_t i;
+ zend_property_info *property_info;
+ zend_property_info *coliding_prop;
+ zval compare_result;
+ const char* prop_name;
+ int prop_name_length;
+ ulong prop_hash;
+ const char* class_name_unused;
+ zend_bool not_compatible;
+ zval* prop_value;
+ char* doc_comment;
+
+ /* In the following steps the properties are inserted into the property table
+ * for that, a very strict approach is applied:
+ * - check for compatibility, if not compatible with any property in class -> fatal
+ * - if compatible, then strict notice
+ */
+ for (i = 0; i < ce->num_traits; i++) {
+ for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info);
+ zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS;
+ zend_hash_move_forward(&ce->traits[i]->properties_info)) {
+ /* first get the unmangeld name if necessary,
+ * then check whether the property is already there
+ */
+ if ((property_info->flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
+ prop_hash = property_info->h;
+ prop_name = property_info->name;
+ prop_name_length = property_info->name_length;
+ } else {
+ /* for private and protected we need to unmangle the names */
+ zend_unmangle_property_name(property_info->name, property_info->name_length,
+ &class_name_unused, &prop_name);
+ prop_name_length = strlen(prop_name);
+ prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
+ }
+
+ /* next: check for conflicts with current class */
+ if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
+ if (coliding_prop->flags & ZEND_ACC_SHADOW) {
+ /* this one is inherited, lets look it up in its own class */
+ zend_hash_quick_find(&coliding_prop->ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop);
+ if (coliding_prop->flags & ZEND_ACC_PRIVATE) {
+ /* private property, make the property_info.offset indenpended */
+ if (property_info->flags & ZEND_ACC_STATIC) {
+ prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
+ } else {
+ prop_value = ce->traits[i]->default_properties_table[property_info->offset];
+ }
+ Z_ADDREF_P(prop_value);
+
+ zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
+ continue;
+ }
+ }
+
+ if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
+ == (property_info->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
+ /* flags are identical, now the value needs to be checked */
+ if (property_info->flags & ZEND_ACC_STATIC) {
+ not_compatible = (FAILURE == compare_function(&compare_result,
+ ce->default_static_members_table[coliding_prop->offset],
+ ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
+ || (Z_LVAL(compare_result) != 0);
+ } else {
+ not_compatible = (FAILURE == compare_function(&compare_result,
+ ce->default_properties_table[coliding_prop->offset],
+ ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
+ || (Z_LVAL(compare_result) != 0);
+ }
+ } else {
+ /* the flags are not identical, thus, we assume properties are not compatible */
+ not_compatible = 1;
+ }
+
+ if (not_compatible) {
+ zend_error(E_COMPILE_ERROR,
+ "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
+ find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
+ property_info->ce->name,
+ prop_name,
+ ce->name);
+ } else {
+ zend_error(E_STRICT,
+ "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
+ find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
+ property_info->ce->name,
+ prop_name,
+ ce->name);
+ }
+ }
+
+ /* property not found, so lets add it */
+ if (property_info->flags & ZEND_ACC_STATIC) {
+ prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
+ } else {
+ prop_value = ce->traits[i]->default_properties_table[property_info->offset];
+ }
+ Z_ADDREF_P(prop_value);
+
+ doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
+ zend_declare_property_ex(ce, prop_name, prop_name_length,
+ prop_value, property_info->flags,
+ doc_comment, property_info->doc_comment_len TSRMLS_CC);
+ }
+ }
+}
+/* }}} */
+
+static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+ int i = 0;
+ zend_trait_alias* cur_alias;
+ char* lc_method_name;
+
+ if (ce->trait_aliases) {
+ while (ce->trait_aliases[i]) {
+ cur_alias = ce->trait_aliases[i];
+ /** The trait for this alias has not been resolved, this means, this
+ alias was not applied. Abort with an error. */
+ if (!cur_alias->trait_method->ce) {
+ if (cur_alias->alias) {
+ /** Plain old inconsistency/typo/bug */
+ zend_error(E_COMPILE_ERROR,
+ "An alias (%s) was defined for method %s(), but this method does not exist",
+ cur_alias->alias,
+ cur_alias->trait_method->method_name);
+ } else {
+ /** Here are two possible cases:
+ 1) this is an attempt to modifiy the visibility
+ of a method introduce as part of another alias.
+ Since that seems to violate the DRY principle,
+ we check against it and abort.
+ 2) it is just a plain old inconsitency/typo/bug
+ as in the case where alias is set. */
+
+ lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name,
+ cur_alias->trait_method->mname_len);
+ if (zend_hash_exists(&ce->function_table,
+ lc_method_name,
+ cur_alias->trait_method->mname_len+1)) {
+ efree(lc_method_name);
+ zend_error(E_COMPILE_ERROR,
+ "The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
+ cur_alias->trait_method->method_name);
+ } else {
+ efree(lc_method_name);
+ zend_error(E_COMPILE_ERROR,
+ "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
+ cur_alias->trait_method->method_name);
+
+ }
+ }
+ }
+ i++;
+ }
+ }
+}
+/* }}} */
+
+ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+
+ if (ce->num_traits <= 0) {
+ return;
+ }
+
+ /* complete initialization of trait strutures in ce */
+ zend_traits_init_trait_structures(ce TSRMLS_CC);
+
+ /* first care about all methods to be flattened into the class */
+ zend_do_traits_method_binding(ce TSRMLS_CC);
+
+ /* Aliases which have not been applied indicate typos/bugs. */
+ zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC);
+
+ /* then flatten the properties into it, to, mostly to notfiy developer about problems */
+ zend_do_traits_property_binding(ce TSRMLS_CC);
+
+ /* verify that all abstract methods from traits have been implemented */
+ zend_verify_abstract_class(ce TSRMLS_CC);
+
+ /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
+ if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
+ ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+ }
+}
+/* }}} */
+
+ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
{
zend_function *function;
+ zval *op1, *op2;
+
+ if (compile_time) {
+ op1 = &CONSTANT_EX(op_array, opline->op1.constant);
+ op2 = &CONSTANT_EX(op_array, opline->op2.constant);
+ } else {
+ op1 = opline->op1.zv;
+ op2 = opline->op2.zv;
+ }
- zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
- if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) {
+ zend_hash_quick_find(function_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void *) &function);
+ if (zend_hash_quick_add(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), function, sizeof(zend_function), NULL)==FAILURE) {
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
zend_function *old_function;
- if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &old_function)==SUCCESS
+ if (zend_hash_quick_find(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), (void *) &old_function)==SUCCESS
&& old_function->type == ZEND_USER_FUNCTION
&& old_function->op_array.last > 0) {
zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
@@ -2977,18 +4432,101 @@ ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_b
}
/* }}} */
-ZEND_API zend_class_entry *do_bind_class(const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
+void zend_add_trait_precedence(znode *precedence_znode TSRMLS_DC) /* {{{ */
+{
+ zend_class_entry *ce = CG(active_class_entry);
+ zend_add_to_list(&ce->trait_precedences, precedence_znode->u.op.ptr TSRMLS_CC);
+}
+/* }}} */
+
+void zend_add_trait_alias(znode *alias_znode TSRMLS_DC) /* {{{ */
+{
+ zend_class_entry *ce = CG(active_class_entry);
+ zend_add_to_list(&ce->trait_aliases, alias_znode->u.op.ptr TSRMLS_CC);
+}
+/* }}} */
+
+void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
+{
+ zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
+ method_ref->ce = NULL;
+
+ /* REM: There should not be a need for copying,
+ zend_do_begin_class_declaration is also just using that string */
+ if (class_name) {
+ zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
+ method_ref->class_name = Z_STRVAL(class_name->u.constant);
+ method_ref->cname_len = Z_STRLEN(class_name->u.constant);
+ } else {
+ method_ref->class_name = NULL;
+ method_ref->cname_len = 0;
+ }
+
+ method_ref->method_name = Z_STRVAL(method_name->u.constant);
+ method_ref->mname_len = Z_STRLEN(method_name->u.constant);
+
+ result->u.op.ptr = method_ref;
+ result->op_type = IS_TMP_VAR;
+}
+/* }}} */
+
+void zend_prepare_trait_alias(znode *result, znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
+{
+ zend_trait_alias *trait_alias = emalloc(sizeof(zend_trait_alias));
+
+ trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
+ trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
+
+ if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
+ zend_error(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
+ return;
+ }
+
+ if (alias) {
+ trait_alias->alias = Z_STRVAL(alias->u.constant);
+ trait_alias->alias_len = Z_STRLEN(alias->u.constant);
+ } else {
+ trait_alias->alias = NULL;
+ }
+ trait_alias->function = NULL;
+
+ result->u.op.ptr = trait_alias;
+}
+/* }}} */
+
+void zend_prepare_trait_precedence(znode *result, znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
+{
+ zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
+
+ trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
+ trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
+
+ trait_precedence->function = NULL;
+
+ result->u.op.ptr = trait_precedence;
+}
+/* }}} */
+
+ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce, **pce;
+ zval *op1, *op2;
- if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
+ if (compile_time) {
+ op1 = &CONSTANT_EX(op_array, opline->op1.constant);
+ op2 = &CONSTANT_EX(op_array, opline->op2.constant);
+ } else {
+ op1 = opline->op1.zv;
+ op2 = opline->op2.zv;
+ }
+ if (zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
return NULL;
} else {
ce = *pce;
}
ce->refcount++;
- if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
+ if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
ce->refcount--;
if (!compile_time) {
/* If we're in compile time, in practice, it's quite possible
@@ -3008,12 +4546,21 @@ ZEND_API zend_class_entry *do_bind_class(const zend_op *opline, HashTable *class
}
/* }}} */
-ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) /* {{{ */
+ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) /* {{{ */
{
zend_class_entry *ce, **pce;
int found_ce;
+ zval *op1, *op2;
+
+ if (compile_time) {
+ op1 = &CONSTANT_EX(op_array, opline->op1.constant);
+ op2 = &CONSTANT_EX(op_array, opline->op2.constant);
+ } else {
+ op1 = opline->op1.zv;
+ op2 = opline->op2.zv;
+ }
- found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
+ found_ce = zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce);
if (found_ce == FAILURE) {
if (!compile_time) {
@@ -3022,7 +4569,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTa
* so we shut up about it. This allows the if (!defined('FOO')) { return; }
* approach to work.
*/
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", Z_STRVAL_P(op2));
}
return NULL;
} else {
@@ -3031,6 +4578,8 @@ ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTa
if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
+ } else if ((parent_ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ce->name, parent_ce->name);
}
zend_do_inheritance(ce, parent_ce TSRMLS_CC);
@@ -3038,7 +4587,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTa
ce->refcount++;
/* Register the derived class */
- if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
+ if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
}
return ce;
@@ -3056,13 +4605,13 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
switch (opline->opcode) {
case ZEND_DECLARE_FUNCTION:
- if (do_bind_function(opline, CG(function_table), 1) == FAILURE) {
+ if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
return;
}
table = CG(function_table);
break;
case ZEND_DECLARE_CLASS:
- if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
+ if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
return;
}
table = CG(class_table);
@@ -3070,30 +4619,31 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
case ZEND_DECLARE_INHERITED_CLASS:
{
zend_op *fetch_class_opline = opline-1;
- zval *parent_name = &fetch_class_opline->op2.u.constant;
+ zval *parent_name;
zend_class_entry **pce;
+ parent_name = &CONSTANT(fetch_class_opline->op2.constant);
if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
- ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
- ((*pce)->type == ZEND_INTERNAL_CLASS))) {
- if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
+ ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
+ ((*pce)->type == ZEND_INTERNAL_CLASS))) {
+ if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
zend_uint *opline_num = &CG(active_op_array)->early_binding;
while (*opline_num != -1) {
- opline_num = &CG(active_op_array)->opcodes[*opline_num].result.u.opline_num;
+ opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
}
*opline_num = opline - CG(active_op_array)->opcodes;
opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
- opline->result.op_type = IS_UNUSED;
- opline->result.u.opline_num = -1;
+ opline->result_type = IS_UNUSED;
+ opline->result.opline_num = -1;
}
return;
}
- if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
+ if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
return;
}
/* clear unnecessary ZEND_FETCH_CLASS opcode */
- zval_dtor(&fetch_class_opline->op2.u.constant);
+ zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
MAKE_NOP(fetch_class_opline);
table = CG(class_table);
@@ -3101,16 +4651,19 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
}
case ZEND_VERIFY_ABSTRACT_CLASS:
case ZEND_ADD_INTERFACE:
+ case ZEND_ADD_TRAIT:
+ case ZEND_BIND_TRAITS:
/* We currently don't early-bind classes that implement interfaces */
+ /* Classes with traits are handled exactly the same, no early-bind here */
return;
default:
zend_error(E_COMPILE_ERROR, "Invalid binding type");
return;
}
- zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
- zval_dtor(&opline->op1.u.constant);
- zval_dtor(&opline->op2.u.constant);
+ zend_hash_quick_del(table, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)), Z_HASH_P(&CONSTANT(opline->op1.constant)));
+ zend_del_literal(CG(active_op_array), opline->op1.constant);
+ zend_del_literal(CG(active_op_array), opline->op2.constant);
MAKE_NOP(opline);
}
/* }}} */
@@ -3124,10 +4677,10 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS
CG(in_compilation) = 1;
while (opline_num != -1) {
- if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num-1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num-1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) {
- do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
+ if (zend_lookup_class(Z_STRVAL_P(op_array->opcodes[opline_num-1].op2.zv), Z_STRLEN_P(op_array->opcodes[opline_num-1].op2.zv), &pce TSRMLS_CC) == SUCCESS) {
+ do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), *pce, 0 TSRMLS_CC);
}
- opline_num = op_array->opcodes[opline_num].result.u.opline_num;
+ opline_num = op_array->opcodes[opline_num].result.opline_num;
}
CG(in_compilation) = orig_in_compilation;
}
@@ -3141,17 +4694,17 @@ void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
opline->opcode = ZEND_JMPNZ_EX;
if (expr1->op_type == IS_TMP_VAR) {
- opline->result = *expr1;
+ SET_NODE(opline->result, expr1);
} else {
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.op_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
}
- opline->op1 = *expr1;
+ SET_NODE(opline->op1, expr1);
SET_UNUSED(opline->op2);
- op_token->u.opline_num = next_op_number;
+ op_token->u.op.opline_num = next_op_number;
- *expr1 = opline->result;
+ GET_NODE(expr1, opline->result);
}
/* }}} */
@@ -3161,11 +4714,11 @@ void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr
*result = *expr1; /* we saved the original result in expr1 */
opline->opcode = ZEND_BOOL;
- opline->result = *result;
- opline->op1 = *expr2;
+ SET_NODE(opline->result, result);
+ SET_NODE(opline->op1, expr2);
SET_UNUSED(opline->op2);
- CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
}
/* }}} */
@@ -3176,17 +4729,17 @@ void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ *
opline->opcode = ZEND_JMPZ_EX;
if (expr1->op_type == IS_TMP_VAR) {
- opline->result = *expr1;
+ SET_NODE(opline->result, expr1);
} else {
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.op_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
}
- opline->op1 = *expr1;
+ SET_NODE(opline->op1, expr1);
SET_UNUSED(opline->op2);
- op_token->u.opline_num = next_op_number;
+ op_token->u.op.opline_num = next_op_number;
- *expr1 = opline->result;
+ GET_NODE(expr1, opline->result);
}
/* }}} */
@@ -3196,11 +4749,11 @@ void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *exp
*result = *expr1; /* we saved the original result in expr1 */
opline->opcode = ZEND_BOOL;
- opline->result = *result;
- opline->op1 = *expr2;
+ SET_NODE(opline->result, result);
+ SET_NODE(opline->op1, expr2);
SET_UNUSED(opline->op2);
- CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
}
/* }}} */
@@ -3216,11 +4769,11 @@ void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket,
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMPNZ;
- opline->op1 = *expr;
- opline->op2.u.opline_num = do_token->u.opline_num;
+ SET_NODE(opline->op1, expr);
+ opline->op2.opline_num = do_token->u.op.opline_num;
SET_UNUSED(opline->op2);
- do_end_loop(expr_open_bracket->u.opline_num, 0 TSRMLS_CC);
+ do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
DEC_BPC(CG(active_op_array));
}
@@ -3231,15 +4784,18 @@ void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = op;
- opline->op1.u.opline_num = CG(active_op_array)->current_brk_cont;
+ opline->op1.opline_num = CG(context).current_brk_cont;
SET_UNUSED(opline->op1);
if (expr) {
- opline->op2 = *expr;
+ if (expr->op_type != IS_CONST) {
+ zend_error(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
+ } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
+ zend_error(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
+ }
+ SET_NODE(opline->op2, expr);
} else {
- Z_TYPE(opline->op2.u.constant) = IS_LONG;
- Z_LVAL(opline->op2.u.constant) = 1;
- INIT_PZVAL(&opline->op2.u.constant);
- opline->op2.op_type = IS_CONST;
+ LITERAL_LONG(opline->op2, 1);
+ opline->op2_type = IS_CONST;
}
}
/* }}} */
@@ -3272,24 +4828,24 @@ void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
opline->opcode = ZEND_JMP;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- opline->op1.u.opline_num = switch_entry_ptr->default_case;
+ opline->op1.opline_num = switch_entry_ptr->default_case;
}
if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
int next_op_number = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
+ CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
}
/* remember break/continue loop information */
- CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
+ CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
+ CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
/* emit free for the switch condition*/
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- opline->op1 = switch_entry_ptr->cond;
+ SET_NODE(opline->op1, &switch_entry_ptr->cond);
SET_UNUSED(opline->op2);
}
if (switch_entry_ptr->cond.op_type == IS_CONST) {
@@ -3315,27 +4871,27 @@ void zend_do_case_before_statement(const znode *case_list, znode *case_token, co
switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
}
opline->opcode = ZEND_CASE;
- opline->result.u.var = switch_entry_ptr->control_var;
- opline->result.op_type = IS_TMP_VAR;
- opline->op1 = switch_entry_ptr->cond;
- opline->op2 = *case_expr;
- if (opline->op1.op_type == IS_CONST) {
- zval_copy_ctor(&opline->op1.u.constant);
+ opline->result.var = switch_entry_ptr->control_var;
+ opline->result_type = IS_TMP_VAR;
+ SET_NODE(opline->op1, &switch_entry_ptr->cond);
+ SET_NODE(opline->op2, case_expr);
+ if (opline->op1_type == IS_CONST) {
+ zval_copy_ctor(&CONSTANT(opline->op1.constant));
}
- result = opline->result;
+ GET_NODE(&result, opline->result);
next_op_number = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMPZ;
- opline->op1 = result;
+ SET_NODE(opline->op1, &result);
SET_UNUSED(opline->op2);
- case_token->u.opline_num = next_op_number;
+ case_token->u.op.opline_num = next_op_number;
if (case_list->op_type==IS_UNUSED) {
return;
}
next_op_number = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
+ CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
}
/* }}} */
@@ -3347,14 +4903,14 @@ void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_
opline->opcode = ZEND_JMP;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- result->u.opline_num = next_op_number;
+ result->u.op.opline_num = next_op_number;
- switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) {
+ switch (CG(active_op_array)->opcodes[case_token->u.op.opline_num].opcode) {
case ZEND_JMP:
- CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[case_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
break;
case ZEND_JMPZ:
- CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[case_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
break;
}
}
@@ -3371,7 +4927,7 @@ void zend_do_default_before_statement(const znode *case_list, znode *default_tok
opline->opcode = ZEND_JMP;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- default_token->u.opline_num = next_op_number;
+ default_token->u.op.opline_num = next_op_number;
next_op_number = get_next_op_number(CG(active_op_array));
switch_entry_ptr->default_case = next_op_number;
@@ -3379,7 +4935,7 @@ void zend_do_default_before_statement(const znode *case_list, znode *default_tok
if (case_list->op_type==IS_UNUSED) {
return;
}
- CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
+ CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
}
/* }}} */
@@ -3390,7 +4946,7 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
zend_class_entry *new_class_entry;
char *lcname;
int error = 0;
- zval **ns_name;
+ zval **ns_name, key;
if (CG(active_class_entry)) {
zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
@@ -3401,12 +4957,12 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
efree(lcname);
- zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant));
}
/* Class name must not conflict with import names */
if (CG(current_import) &&
- zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
+ zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
error = 1;
}
@@ -3434,16 +4990,16 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
new_class_entry = emalloc(sizeof(zend_class_entry));
new_class_entry->type = ZEND_USER_CLASS;
- new_class_entry->name = class_name->u.constant.value.str.val;
- new_class_entry->name_length = class_name->u.constant.value.str.len;
+ new_class_entry->name = zend_new_interned_string(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant) + 1, 1 TSRMLS_CC);
+ new_class_entry->name_length = Z_STRLEN(class_name->u.constant);
zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
- new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
- new_class_entry->line_start = class_token->u.opline_num;
- new_class_entry->ce_flags |= class_token->u.EA.type;
+ new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
+ new_class_entry->info.user.line_start = class_token->u.op.opline_num;
+ new_class_entry->ce_flags |= class_token->EA;
if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
- switch (parent_class_name->u.EA.type) {
+ switch (parent_class_name->EA) {
case ZEND_FETCH_CLASS_SELF:
zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
break;
@@ -3460,33 +5016,38 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->op1.op_type = IS_CONST;
- build_runtime_defined_function_key(&opline->op1.u.constant, lcname, new_class_entry->name_length TSRMLS_CC);
+ opline->op1_type = IS_CONST;
+ build_runtime_defined_function_key(&key, lcname, new_class_entry->name_length TSRMLS_CC);
+ opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
+ Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
- opline->op2.op_type = IS_CONST;
- opline->op2.u.constant.type = IS_STRING;
- Z_SET_REFCOUNT(opline->op2.u.constant, 1);
+ opline->op2_type = IS_CONST;
if (doing_inheritance) {
- opline->extended_value = parent_class_name->u.var;
+ /* Make sure a trait does not try to extend a class */
+ if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name);
+ }
+
+ opline->extended_value = parent_class_name->u.op.var;
opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
} else {
opline->opcode = ZEND_DECLARE_CLASS;
}
- opline->op2.u.constant.value.str.val = lcname;
- opline->op2.u.constant.value.str.len = new_class_entry->name_length;
+ LITERAL_STRINGL(opline->op2, lcname, new_class_entry->name_length, 0);
+ CALCULATE_LITERAL_HASH(opline->op2.constant);
- zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL);
+ zend_hash_quick_update(CG(class_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &new_class_entry, sizeof(zend_class_entry *), NULL);
CG(active_class_entry) = new_class_entry;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.op_type = IS_VAR;
- CG(implementing_class) = opline->result;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_VAR;
+ GET_NODE(&CG(implementing_class), opline->result);
if (CG(doc_comment)) {
- CG(active_class_entry)->doc_comment = CG(doc_comment);
- CG(active_class_entry)->doc_comment_len = CG(doc_comment_len);
+ CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
+ CG(active_class_entry)->info.user.doc_comment_len = CG(doc_comment_len);
CG(doc_comment) = NULL;
CG(doc_comment_len) = 0;
}
@@ -3498,7 +5059,7 @@ static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
- opline->op1 = CG(implementing_class);
+ SET_NODE(opline->op1, &CG(implementing_class));
SET_UNUSED(opline->op2);
}
/* }}} */
@@ -3526,7 +5087,23 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent
}
}
- ce->line_end = zend_get_compiled_lineno(TSRMLS_C);
+ ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
+
+ /* Check for traits and proceed like with interfaces.
+ * The only difference will be a combined handling of them in the end.
+ * Thus, we need another opcode here. */
+ if (ce->num_traits > 0) {
+ zend_op *opline;
+
+ ce->traits = NULL;
+ ce->num_traits = 0;
+ ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
+
+ /* opcode generation: */
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_BIND_TRAITS;
+ SET_NODE(opline->op1, &CG(implementing_class));
+ }
if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
&& ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) {
@@ -3544,6 +5121,7 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent
ce->num_interfaces = 0;
ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
}
+
CG(active_class_entry) = NULL;
}
/* }}} */
@@ -3552,6 +5130,13 @@ void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
{
zend_op *opline;
+ /* Traits can not implement interfaces */
+ if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
+ Z_STRVAL(interface_name->u.constant),
+ CG(active_class_entry)->name);
+ }
+
switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
case ZEND_FETCH_CLASS_SELF:
case ZEND_FETCH_CLASS_PARENT:
@@ -3564,14 +5149,46 @@ void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ADD_INTERFACE;
- opline->op1 = CG(implementing_class);
- zend_resolve_class_name(interface_name, &opline->extended_value, 0 TSRMLS_CC);
+ SET_NODE(opline->op1, &CG(implementing_class));
+ zend_resolve_class_name(interface_name, opline->extended_value, 0 TSRMLS_CC);
opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
- opline->op2 = *interface_name;
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC);
CG(active_class_entry)->num_interfaces++;
}
/* }}} */
+void zend_do_implements_trait(znode *trait_name TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline;
+ if ((CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
+ zend_error(E_COMPILE_ERROR,
+ "Cannot use traits inside of interfaces. %s is used in %s",
+ Z_STRVAL(trait_name->u.constant), CG(active_class_entry)->name);
+ }
+
+
+ switch (zend_get_class_fetch_type(Z_STRVAL(trait_name->u.constant), Z_STRLEN(trait_name->u.constant))) {
+ case ZEND_FETCH_CLASS_SELF:
+ case ZEND_FETCH_CLASS_PARENT:
+ case ZEND_FETCH_CLASS_STATIC:
+ zend_error(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", Z_STRVAL(trait_name->u.constant));
+ break;
+ default:
+ break;
+ }
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_ADD_TRAIT;
+ SET_NODE(opline->op1, &CG(implementing_class));
+ zend_resolve_class_name(trait_name, opline->extended_value, 0 TSRMLS_CC);
+ opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC);
+ CG(active_class_entry)->num_traits++;
+}
+/* }}} */
+
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
{
char *prop_name;
@@ -3596,7 +5213,7 @@ static int zend_strnlen(const char* s, int maxlen) /* {{{ */
}
/* }}} */
-ZEND_API int zend_unmangle_property_name(char *mangled_property, int len, char **class_name, char **prop_name) /* {{{ */
+ZEND_API int zend_unmangle_property_name(const char *mangled_property, int len, const char **class_name, const char **prop_name) /* {{{ */
{
int class_name_len;
@@ -3641,13 +5258,11 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui
if (access_type & ZEND_ACC_FINAL) {
zend_error(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
- CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ CG(active_class_entry)->name, var_name->u.constant.value.str.val);
}
if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
- if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
- }
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
}
ALLOC_ZVAL(property);
@@ -3665,7 +5280,7 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui
CG(doc_comment_len) = 0;
}
- zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value.str.val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
+ zend_declare_property_ex(CG(active_class_entry), zend_new_interned_string(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len + 1, 0 TSRMLS_CC), var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
efree(var_name->u.constant.value.str.val);
}
/* }}} */
@@ -3673,15 +5288,29 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui
void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC) /* {{{ */
{
zval *property;
+ const char *cname = NULL;
+ int result;
if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
zend_error(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
+ return;
+ }
+ if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error(E_COMPILE_ERROR, "Traits cannot have constants");
+ return;
}
ALLOC_ZVAL(property);
*property = value->u.constant;
+
+ cname = zend_new_interned_string(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, 0 TSRMLS_CC);
- if (zend_hash_add(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) {
+ if (IS_INTERNED(cname)) {
+ result = zend_hash_quick_add(&CG(active_class_entry)->constants_table, cname, var_name->u.constant.value.str.len+1, INTERNED_HASH(cname), &property, sizeof(zval *), NULL);
+ } else {
+ result = zend_hash_add(&CG(active_class_entry)->constants_table, cname, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
+ }
+ if (result == FAILURE) {
FREE_ZVAL(property);
zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
}
@@ -3703,17 +5332,17 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
if (object->op_type == IS_CV) {
- if (object->u.var == CG(active_op_array)->this_var) {
- SET_UNUSED(*object); /* this means $this for objects */
+ if (object->u.op.var == CG(active_op_array)->this_var) {
+ object->op_type = IS_UNUSED; /* this means $this for objects */
}
} else if (fetch_list_ptr->count == 1) {
zend_llist_element *le = fetch_list_ptr->head;
zend_op *opline_ptr = (zend_op *) le->data;
if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
- efree(Z_STRVAL(opline_ptr->op1.u.constant));
+ zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
- opline_ptr->op2 = *property;
+ SET_NODE(opline_ptr->op2, property);
/* if it was usual fetch, we change it to object fetch */
switch (opline_ptr->opcode) {
case ZEND_FETCH_W:
@@ -3735,19 +5364,36 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
break;
}
- *result = opline_ptr->result;
+ if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
+ CALCULATE_LITERAL_HASH(opline_ptr->op2.constant);
+ GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
+ }
+ GET_NODE(result, opline_ptr->result);
return;
}
}
+ if (zend_is_function_or_method_call(object)) {
+ init_op(&opline TSRMLS_CC);
+ opline.opcode = ZEND_SEPARATE;
+ SET_NODE(opline.op1, object);
+ SET_UNUSED(opline.op2);
+ opline.result_type = IS_VAR;
+ opline.result.var = opline.op1.var;
+ zend_llist_add_element(fetch_list_ptr, &opline);
+ }
+
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_OBJ_W; /* the backpatching routine assumes W */
- opline.result.op_type = IS_VAR;
- opline.result.u.EA.type = 0;
- opline.result.u.var = get_temporary_variable(CG(active_op_array));
- opline.op1 = *object;
- opline.op2 = *property;
- *result = opline.result;
+ opline.result_type = IS_VAR;
+ opline.result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline.op1, object);
+ SET_NODE(opline.op2, property);
+ if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
+ CALCULATE_LITERAL_HASH(opline.op2.constant);
+ GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
+ }
+ GET_NODE(result, opline.result);
zend_llist_add_element(fetch_list_ptr, &opline);
}
@@ -3775,40 +5421,6 @@ void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
}
/* }}} */
-void zend_do_declare_implicit_property(TSRMLS_D) /* {{{ */
-{
-/* Fixes bug #26182. Not sure why we needed to do this in the first place.
- Has to be checked with Zeev.
-*/
-#if ANDI_0
- zend_op *opline_ptr;
- zend_llist_element *le;
- zend_llist *fetch_list_ptr;
-
-
- zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
-
- if (fetch_list_ptr->count != 1) {
- return;
- }
-
- le = fetch_list_ptr->head;
- opline_ptr = (zend_op *) le->data;
-
- if (opline_ptr->op1.op_type == IS_UNUSED
- && CG(active_class_entry)
- && opline_ptr->op2.op_type == IS_CONST
- && !zend_hash_exists(&CG(active_class_entry)->properties_info, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
- znode property;
-
- property = opline_ptr->op2;
- property.u.constant.value.str.val = estrndup(opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
- zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);
- }
-#endif
-}
-/* }}} */
-
void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
{
zend_stack_push(&CG(object_stack), object, sizeof(znode));
@@ -3832,12 +5444,12 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
zend_op *opline;
unsigned char *ptr = NULL;
- new_token->u.opline_num = get_next_op_number(CG(active_op_array));
+ new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_NEW;
- opline->result.op_type = IS_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *class_type;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, class_type);
SET_UNUSED(opline->op2);
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
@@ -3851,8 +5463,8 @@ void zend_do_end_new_object(znode *result, const znode *new_token, const znode *
zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
zend_do_free(&ctor_result TSRMLS_CC);
- CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
- *result = CG(active_op_array)->opcodes[new_token->u.opline_num].result;
+ CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
+ GET_NODE(result, CG(active_op_array)->opcodes[new_token->u.op.opline_num].result);
}
/* }}} */
@@ -3889,10 +5501,10 @@ static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal
return c;
}
if (all_internal_constants_substitution &&
- (c->flags & CONST_PERSISTENT) &&
- !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
- Z_TYPE(c->value) != IS_CONSTANT &&
- Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
+ (c->flags & CONST_PERSISTENT) &&
+ !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
+ Z_TYPE(c->value) != IS_CONSTANT &&
+ Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
return c;
}
return NULL;
@@ -3932,7 +5544,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
if (ZEND_FETCH_CLASS_STATIC == type) {
zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
} else if (ZEND_FETCH_CLASS_DEFAULT == type) {
- zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
+ zend_resolve_class_name(constant_container, fetch_type, 1 TSRMLS_CC);
}
zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
*result = *constant_container;
@@ -3941,18 +5553,29 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
case ZEND_RT:
if (constant_container->op_type == IS_CONST &&
ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
- zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
+ zend_resolve_class_name(constant_container, fetch_type, 1 TSRMLS_CC);
} else {
zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
constant_container = &tmp;
}
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_CONSTANT;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *constant_container;
- opline->op2 = *constant_name;
- *result = opline->result;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ if (constant_container->op_type == IS_CONST) {
+ opline->op1_type = IS_CONST;
+ opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &constant_container->u.constant TSRMLS_CC);
+ } else {
+ SET_NODE(opline->op1, constant_container);
+ }
+ SET_NODE(opline->op2, constant_name);
+ CALCULATE_LITERAL_HASH(opline->op2.constant);
+ if (opline->op1_type == IS_CONST) {
+ GET_CACHE_SLOT(opline->op2.constant);
+ } else {
+ GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
+ }
+ GET_NODE(result, opline->result);
break;
}
return;
@@ -3988,17 +5611,25 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_CONSTANT;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- *result = opline->result;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ GET_NODE(result, opline->result);
SET_UNUSED(opline->op1);
- if(compound) {
+ opline->op2_type = IS_CONST;
+ if (compound) {
/* the name is unambiguous */
opline->extended_value = 0;
- } else {
+ opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
+ } else {
opline->extended_value = IS_CONSTANT_UNQUALIFIED;
+ if (CG(current_namespace)) {
+ opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
+ opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 1 TSRMLS_CC);
+ } else {
+ opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
+ }
}
- opline->op2 = *constant_name;
+ GET_CACHE_SLOT(opline->op2.constant);
break;
}
}
@@ -4017,25 +5648,23 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
opline->opcode = ZEND_SEND_VAR;
break;
}
- opline->op1 = *cmd;
- opline->op2.u.opline_num = 0;
+ SET_NODE(opline->op1, cmd);
+ opline->op2.opline_num = 0;
opline->extended_value = ZEND_DO_FCALL;
SET_UNUSED(opline->op2);
/* FIXME: exception support not added to this op2 */
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_DO_FCALL;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.op_type = IS_VAR;
- Z_STRVAL(opline->op1.u.constant) = estrndup("shell_exec", sizeof("shell_exec")-1);
- Z_STRLEN(opline->op1.u.constant) = sizeof("shell_exec")-1;
- INIT_PZVAL(&opline->op1.u.constant);
- Z_TYPE(opline->op1.u.constant) = IS_STRING;
- opline->op1.op_type = IS_CONST;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_VAR;
+ LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0);
+ CALCULATE_LITERAL_HASH(opline->op1.constant);
+ opline->op1_type = IS_CONST;
+ GET_CACHE_SLOT(opline->op1.constant);
opline->extended_value = 1;
SET_UNUSED(opline->op2);
- ZVAL_LONG(&opline->op2.u.constant, zend_hash_func("shell_exec", sizeof("shell_exec")));
- *result = opline->result;
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -4044,13 +5673,25 @@ void zend_do_init_array(znode *result, const znode *expr, const znode *offset, z
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INIT_ARRAY;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->result.op_type = IS_TMP_VAR;
- *result = opline->result;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
+ GET_NODE(result, opline->result);
if (expr) {
- opline->op1 = *expr;
+ SET_NODE(opline->op1, expr);
if (offset) {
- opline->op2 = *offset;
+ SET_NODE(opline->op2, offset);
+ if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
+ ulong index;
+ int numeric = 0;
+
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
+ if (numeric) {
+ zval_dtor(&CONSTANT(opline->op2.constant));
+ ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
+ } else {
+ CALCULATE_LITERAL_HASH(opline->op2.constant);
+ }
+ }
} else {
SET_UNUSED(opline->op2);
}
@@ -4067,10 +5708,22 @@ void zend_do_add_array_element(znode *result, const znode *expr, const znode *of
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
- opline->result = *result;
- opline->op1 = *expr;
+ SET_NODE(opline->result, result);
+ SET_NODE(opline->op1, expr);
if (offset) {
- opline->op2 = *offset;
+ SET_NODE(opline->op2, offset);
+ if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
+ ulong index;
+ int numeric = 0;
+
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
+ if (numeric) {
+ zval_dtor(&CONSTANT(opline->op2.constant));
+ ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
+ } else {
+ CALCULATE_LITERAL_HASH(opline->op2.constant);
+ }
+ }
} else {
SET_UNUSED(opline->op2);
}
@@ -4186,19 +5839,16 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
break;
}
- opline->extended_value = ZEND_FETCH_ADD_LOCK;
+ opline->extended_value |= ZEND_FETCH_ADD_LOCK;
} else {
opline->opcode = ZEND_FETCH_DIM_R;
}
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = last_container;
- opline->op2.op_type = IS_CONST;
- Z_TYPE(opline->op2.u.constant) = IS_LONG;
- Z_LVAL(opline->op2.u.constant) = *((int *) dimension->data);
- INIT_PZVAL(&opline->op2.u.constant);
- last_container = opline->result;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, &last_container);
+ opline->op2_type = IS_CONST;
+ LITERAL_LONG(opline->op2, *((int *) dimension->data));
+ GET_NODE(&last_container, opline->result);
dimension = dimension->next;
}
((list_llist_element *) le->data)->value = last_container;
@@ -4224,6 +5874,33 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
}
/* }}} */
+void zend_init_list(void *result, void *item TSRMLS_DC) /* {{{ */
+{
+ void** list = emalloc(sizeof(void*) * 2);
+
+ list[0] = item;
+ list[1] = NULL;
+
+ *(void**)result = list;
+}
+/* }}} */
+
+void zend_add_to_list(void *result, void *item TSRMLS_DC) /* {{{ */
+{
+ void** list = *(void**)result;
+ size_t n = 0;
+
+ while (list && list[n]) { n++; }
+
+ list = erealloc(list, sizeof(void*) * (n+2));
+
+ list[n] = item;
+ list[n+1] = NULL;
+
+ *(void**)result = list;
+}
+/* }}} */
+
void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
{
zval *tmp;
@@ -4239,6 +5916,9 @@ void zend_do_fetch_static_variable(znode *varname, const znode *static_assignmen
INIT_ZVAL(*tmp);
}
if (!CG(active_op_array)->static_variables) {
+ if (CG(active_op_array)->scope) {
+ CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
+ }
ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
}
@@ -4252,13 +5932,15 @@ void zend_do_fetch_static_variable(znode *varname, const znode *static_assignmen
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R : ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *varname;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, varname);
+ if (opline->op1_type == IS_CONST) {
+ CALCULATE_LITERAL_HASH(opline->op1.constant);
+ }
SET_UNUSED(opline->op2);
- opline->op2.u.EA.type = ZEND_FETCH_STATIC;
- result = opline->result;
+ opline->extended_value = ZEND_FETCH_STATIC;
+ GET_NODE(&result, opline->result);
if (varname->op_type == IS_CONST) {
zval_copy_ctor(&varname->u.constant);
@@ -4274,9 +5956,7 @@ void zend_do_fetch_static_variable(znode *varname, const znode *static_assignmen
} else {
zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
}
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
-
-/* zval_dtor(&varname->u.constant); */
+ CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
}
/* }}} */
@@ -4285,7 +5965,7 @@ void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC)
znode value;
if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
- memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
+ memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
zend_error(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
return;
}
@@ -4314,13 +5994,15 @@ void zend_do_fetch_global_variable(znode *varname, const znode *static_assignmen
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *varname;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, varname);
+ if (opline->op1_type == IS_CONST) {
+ CALCULATE_LITERAL_HASH(opline->op1.constant);
+ }
SET_UNUSED(opline->op2);
- opline->op2.u.EA.type = fetch_type;
- result = opline->result;
+ opline->extended_value = fetch_type;
+ GET_NODE(&result, opline->result);
if (varname->op_type == IS_CONST) {
zval_copy_ctor(&varname->u.constant);
@@ -4328,7 +6010,7 @@ void zend_do_fetch_global_variable(znode *varname, const znode *static_assignmen
fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
+ CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
}
/* }}} */
@@ -4337,12 +6019,12 @@ void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC) /* {{{ *
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_CAST;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *expr;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, expr);
SET_UNUSED(opline->op2);
opline->extended_value = type;
- *result = opline->result;
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -4353,12 +6035,12 @@ void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INCLUDE_OR_EVAL;
- opline->result.op_type = IS_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *op1;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, op1);
SET_UNUSED(opline->op2);
- Z_LVAL(opline->op2.u.constant) = type;
- *result = opline->result;
+ opline->extended_value = type;
+ GET_NODE(result, opline->result);
}
zend_do_extended_fcall_end(TSRMLS_C);
}
@@ -4377,7 +6059,7 @@ void zend_do_indirect_references(znode *result, const znode *num_references, zno
fetch_simple_variable(result, variable, 1 TSRMLS_CC);
/* there is a chance someone is accessing $this */
if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
}
}
/* }}} */
@@ -4391,23 +6073,25 @@ void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
if (variable->op_type == IS_CV) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_UNSET_VAR;
- opline->op1 = *variable;
+ SET_NODE(opline->op1, variable);
SET_UNUSED(opline->op2);
- opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
SET_UNUSED(opline->result);
- opline->extended_value = ZEND_QUICK_SET;
+ opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {
last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
switch (last_op->opcode) {
case ZEND_FETCH_UNSET:
last_op->opcode = ZEND_UNSET_VAR;
+ SET_UNUSED(last_op->result);
break;
case ZEND_FETCH_DIM_UNSET:
last_op->opcode = ZEND_UNSET_DIM;
+ SET_UNUSED(last_op->result);
break;
case ZEND_FETCH_OBJ_UNSET:
last_op->opcode = ZEND_UNSET_OBJ;
+ SET_UNUSED(last_op->result);
break;
}
@@ -4426,11 +6110,10 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
if (variable->op_type == IS_CV) {
last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
- last_op->op1 = *variable;
+ SET_NODE(last_op->op1, variable);
SET_UNUSED(last_op->op2);
- last_op->op2.u.EA.type = ZEND_FETCH_LOCAL;
- last_op->result.u.var = get_temporary_variable(CG(active_op_array));
- last_op->extended_value = ZEND_QUICK_SET;
+ last_op->result.var = get_temporary_variable(CG(active_op_array));
+ last_op->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {
last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
@@ -4445,12 +6128,11 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
break;
}
- last_op->extended_value = 0;
}
- last_op->result.op_type = IS_TMP_VAR;
+ last_op->result_type = IS_TMP_VAR;
last_op->extended_value |= type;
- *result = last_op->result;
+ GET_NODE(result, last_op->result);
}
/* }}} */
@@ -4472,13 +6154,13 @@ void zend_do_instanceof(znode *result, const znode *expr, const znode *class_zno
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_INSTANCEOF;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *expr;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, expr);
- opline->op2 = *class_znode;
+ SET_NODE(opline->op2, class_znode);
- *result = opline->result;
+ GET_NODE(result, opline->result);
}
/* }}} */
@@ -4496,53 +6178,50 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
is_variable = 1;
}
/* save the location of FETCH_W instruction(s) */
- open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
+ open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
if (CG(active_op_array)->last > 0 &&
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
+ CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
/* Only lock the container if we are fetching from a real container and not $this */
- if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1.op_type == IS_VAR) {
+ if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1_type == IS_VAR) {
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
push_container = 1;
}
}
} else {
is_variable = 0;
- open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
+ open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
}
/* save the location of FE_RESET */
- foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
+ foreach_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
/* Preform array reset */
opline->opcode = ZEND_FE_RESET;
- opline->result.op_type = IS_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *array;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, array);
SET_UNUSED(opline->op2);
opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
- dummy_opline.result = opline->result;
+ COPY_NODE(dummy_opline.result, opline->result);
if (push_container) {
- dummy_opline.op1 = CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1;
+ COPY_NODE(dummy_opline.op1, CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1);
} else {
- znode tmp;
-
- tmp.op_type = IS_UNUSED;
- dummy_opline.op1 = tmp;
+ dummy_opline.op1_type = IS_UNUSED;
}
zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
/* save the location of FE_FETCH */
- as_token->u.opline_num = get_next_op_number(CG(active_op_array));
+ as_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FE_FETCH;
- opline->result.op_type = IS_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = dummy_opline.result;
+ opline->result_type = IS_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ COPY_NODE(opline->op1, dummy_opline.result);
opline->extended_value = 0;
SET_UNUSED(opline->op2);
@@ -4560,7 +6239,7 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
znode dummy, value_node;
zend_bool assign_by_ref=0;
- opline = &CG(active_op_array)->opcodes[as_token->u.opline_num];
+ opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num];
if (key->op_type != IS_UNUSED) {
znode *tmp;
@@ -4573,38 +6252,42 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
}
- if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) {
+ if ((key->op_type != IS_UNUSED) && (key->EA & ZEND_PARSED_REFERENCE_VARIABLE)) {
zend_error(E_COMPILE_ERROR, "Key element cannot be a reference");
}
- if (value->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE) {
+ if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
assign_by_ref = 1;
if (!(opline-1)->extended_value) {
zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
}
/* Mark extended_value for assign-by-reference */
opline->extended_value |= ZEND_FE_FETCH_BYREF;
- CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
+ CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
} else {
zend_op *foreach_copy;
- zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.opline_num];
- zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.opline_num];
+ zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
+ zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
/* Change "write context" into "read context" */
fetch->extended_value = 0; /* reset ZEND_FE_RESET_VARIABLE */
while (fetch != end) {
--fetch;
- if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2.op_type == IS_UNUSED) {
+ if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
}
- fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
+ if (fetch->opcode == ZEND_SEPARATE) {
+ MAKE_NOP(fetch);
+ } else {
+ fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
+ }
}
/* prevent double SWITCH_FREE */
zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
- foreach_copy->op1.op_type = IS_UNUSED;
+ foreach_copy->op1_type = IS_UNUSED;
}
- value_node = opline->result;
+ GET_NODE(&value_node, opline->result);
if (assign_by_ref) {
zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
@@ -4618,11 +6301,10 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
if (key->op_type != IS_UNUSED) {
znode key_node;
- opline = &CG(active_op_array)->opcodes[as_token->u.opline_num+1];
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
- key_node = opline->result;
+ opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num+1];
+ opline->result_type = IS_TMP_VAR;
+ opline->result.opline_num = get_temporary_variable(CG(active_op_array));
+ GET_NODE(&key_node, opline->result);
zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
zend_do_free(&dummy TSRMLS_CC);
@@ -4639,14 +6321,14 @@ void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRML
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMP;
- opline->op1.u.opline_num = as_token->u.opline_num;
+ opline->op1.opline_num = as_token->u.op.opline_num;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
- CG(active_op_array)->opcodes[as_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
+ CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
+ CG(active_op_array)->opcodes[as_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
- do_end_loop(as_token->u.opline_num, 1 TSRMLS_CC);
+ do_end_loop(as_token->u.op.opline_num, 1 TSRMLS_CC);
zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
generate_free_foreach_copy(container_ptr TSRMLS_CC);
@@ -4667,11 +6349,7 @@ void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
convert_to_long(&val->u.constant);
CG(declarables).ticks = val->u.constant;
-#ifdef ZEND_MULTIBYTE
} else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
- zend_encoding *new_encoding, *old_encoding;
- zend_encoding_filter old_input_filter;
-
if ((Z_TYPE(val->u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_error(E_COMPILE_ERROR, "Cannot use constants as encoding");
}
@@ -4686,8 +6364,8 @@ void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
int num = CG(active_op_array)->last;
/* ignore ZEND_EXT_STMT and ZEND_TICKS */
while (num > 0 &&
- (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
- CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
+ (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
+ CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
--num;
}
@@ -4695,31 +6373,32 @@ void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
zend_error(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
}
}
- CG(encoding_declared) = 1;
- convert_to_string(&val->u.constant);
- new_encoding = zend_multibyte_fetch_encoding(val->u.constant.value.str.val);
- if (!new_encoding) {
- zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", val->u.constant.value.str.val);
- } else {
- old_input_filter = LANG_SCNG(input_filter);
- old_encoding = LANG_SCNG(script_encoding);
- zend_multibyte_set_filter(new_encoding TSRMLS_CC);
-
- /* need to re-scan if input filter changed */
- if (old_input_filter != LANG_SCNG(input_filter) ||
- ((old_input_filter == zend_multibyte_script_encoding_filter) &&
- (new_encoding != old_encoding))) {
- zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
+ if (CG(multibyte)) {
+ const zend_encoding *new_encoding, *old_encoding;
+ zend_encoding_filter old_input_filter;
+
+ CG(encoding_declared) = 1;
+
+ convert_to_string(&val->u.constant);
+ new_encoding = zend_multibyte_fetch_encoding(val->u.constant.value.str.val TSRMLS_CC);
+ if (!new_encoding) {
+ zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", val->u.constant.value.str.val);
+ } else {
+ old_input_filter = LANG_SCNG(input_filter);
+ old_encoding = LANG_SCNG(script_encoding);
+ zend_multibyte_set_filter(new_encoding TSRMLS_CC);
+
+ /* need to re-scan if input filter changed */
+ if (old_input_filter != LANG_SCNG(input_filter) ||
+ (old_input_filter && new_encoding != old_encoding)) {
+ zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
+ }
}
+ } else {
+ zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because Zend multibyte feature is turned off by settings");
}
- efree(val->u.constant.value.str.val);
-#else /* !ZEND_MULTIBYTE */
- } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
- /* Do not generate any kind of warning for encoding declares */
- /* zend_error(E_COMPILE_WARNING, "Declare encoding [%s] not supported", val->u.constant.value.str.val); */
zval_dtor(&val->u.constant);
-#endif /* ZEND_MULTIBYTE */
} else {
zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", var->u.constant.value.str.val);
zval_dtor(&val->u.constant);
@@ -4734,7 +6413,7 @@ void zend_do_declare_end(const znode *declare_token TSRMLS_DC) /* {{{ */
zend_stack_top(&CG(declare_stack), (void **) &declarables);
/* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
- if ((get_next_op_number(CG(active_op_array)) - declare_token->u.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
+ if ((get_next_op_number(CG(active_op_array)) - declare_token->u.op.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
CG(declarables) = *declarables;
}
}
@@ -4745,7 +6424,7 @@ void zend_do_exit(znode *result, const znode *message TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_EXIT;
- opline->op1 = *message;
+ SET_NODE(opline->op1, message);
SET_UNUSED(opline->op2);
result->op_type = IS_CONST;
@@ -4759,11 +6438,11 @@ void zend_do_begin_silence(znode *strudel_token TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_BEGIN_SILENCE;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = get_temporary_variable(CG(active_op_array));
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- *strudel_token = opline->result;
+ GET_NODE(strudel_token, opline->result);
}
/* }}} */
@@ -4772,7 +6451,7 @@ void zend_do_end_silence(const znode *strudel_token TSRMLS_DC) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_END_SILENCE;
- opline->op1 = *strudel_token;
+ SET_NODE(opline->op1, strudel_token);
SET_UNUSED(opline->op2);
}
/* }}} */
@@ -4782,15 +6461,20 @@ void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TS
int op_number = get_next_op_number(CG(active_op_array));
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMP_SET;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *value;
+ if (value->op_type == IS_VAR || value->op_type == IS_CV) {
+ opline->opcode = ZEND_JMP_SET_VAR;
+ opline->result_type = IS_VAR;
+ } else {
+ opline->opcode = ZEND_JMP_SET;
+ opline->result_type = IS_TMP_VAR;
+ }
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, value);
SET_UNUSED(opline->op2);
- *colon_token = opline->result;
+ GET_NODE(colon_token, opline->result);
- jmp_token->u.opline_num = op_number;
+ jmp_token->u.op.opline_num = op_number;
INC_BPC(CG(active_op_array));
}
@@ -4800,15 +6484,26 @@ void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_QM_ASSIGN;
+ SET_NODE(opline->result, colon_token);
+ if (colon_token->op_type == IS_TMP_VAR) {
+ if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
+ CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
+ CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
+ opline->opcode = ZEND_QM_ASSIGN_VAR;
+ opline->result_type = IS_VAR;
+ } else {
+ opline->opcode = ZEND_QM_ASSIGN;
+ }
+ } else {
+ opline->opcode = ZEND_QM_ASSIGN_VAR;
+ }
opline->extended_value = 0;
- opline->result = *colon_token;
- opline->op1 = *false_value;
+ SET_NODE(opline->op1, false_value);
SET_UNUSED(opline->op2);
- *result = opline->result;
+ GET_NODE(result, opline->result);
- CG(active_op_array)->opcodes[jmp_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
DEC_BPC(CG(active_op_array));
}
@@ -4822,10 +6517,10 @@ void zend_do_begin_qm_op(const znode *cond, znode *qm_token TSRMLS_DC) /* {{{ */
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMPZ;
- opline->op1 = *cond;
+ SET_NODE(opline->op1, cond);
SET_UNUSED(opline->op2);
- opline->op2.u.opline_num = jmpz_op_number;
- *qm_token = opline->op2;
+ opline->op2.opline_num = jmpz_op_number;
+ GET_NODE(qm_token, opline->op2);
INC_BPC(CG(active_op_array));
}
@@ -4835,16 +6530,21 @@ void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_toke
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- CG(active_op_array)->opcodes[qm_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
+ CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
- opline->opcode = ZEND_QM_ASSIGN;
- opline->result.op_type = IS_TMP_VAR;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *true_value;
+ if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
+ opline->opcode = ZEND_QM_ASSIGN_VAR;
+ opline->result_type = IS_VAR;
+ } else {
+ opline->opcode = ZEND_QM_ASSIGN;
+ opline->result_type = IS_TMP_VAR;
+ }
+ opline->result.var = get_temporary_variable(CG(active_op_array));
+ SET_NODE(opline->op1, true_value);
SET_UNUSED(opline->op2);
- *qm_token = opline->result;
- colon_token->u.opline_num = get_next_op_number(CG(active_op_array));
+ GET_NODE(qm_token, opline->result);
+ colon_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMP;
@@ -4857,14 +6557,25 @@ void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_t
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_QM_ASSIGN;
- opline->result = *qm_token;
- opline->op1 = *false_value;
+ SET_NODE(opline->result, qm_token);
+ if (qm_token->op_type == IS_TMP_VAR) {
+ if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
+ CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
+ CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
+ opline->opcode = ZEND_QM_ASSIGN_VAR;
+ opline->result_type = IS_VAR;
+ } else {
+ opline->opcode = ZEND_QM_ASSIGN;
+ }
+ } else {
+ opline->opcode = ZEND_QM_ASSIGN_VAR;
+ }
+ SET_NODE(opline->op1, false_value);
SET_UNUSED(opline->op2);
- CG(active_op_array)->opcodes[colon_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
+ CG(active_op_array)->opcodes[colon_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
- *result = opline->result;
+ GET_NODE(result, opline->result);
DEC_BPC(CG(active_op_array));
}
@@ -4923,23 +6634,18 @@ void zend_do_ticks(TSRMLS_D) /* {{{ */
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_TICKS;
- opline->op1.u.constant = CG(declarables).ticks;
- opline->op1.op_type = IS_CONST;
+ SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
+ opline->extended_value = Z_LVAL(CG(declarables).ticks);
}
/* }}} */
-void zend_auto_global_dtor(zend_auto_global *auto_global) /* {{{ */
-{
- free(auto_global->name);
-}
-/* }}} */
-
-zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */
+zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hashval TSRMLS_DC) /* {{{ */
{
zend_auto_global *auto_global;
+ ulong hash = hashval ? hashval : zend_hash_func(name, name_len+1);
- if (zend_hash_find(CG(auto_globals), name, name_len+1, (void **) &auto_global)==SUCCESS) {
+ if (zend_hash_quick_find(CG(auto_globals), name, name_len+1, hash, (void **) &auto_global)==SUCCESS) {
if (auto_global->armed) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
}
@@ -4949,18 +6655,44 @@ zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{
}
/* }}} */
-int zend_register_auto_global(const char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
+zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */
+{
+ return zend_is_auto_global_quick(name, name_len, 0 TSRMLS_CC);
+}
+/* }}} */
+
+int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
{
zend_auto_global auto_global;
- auto_global.name = zend_strndup(name, name_len);
+ auto_global.name = zend_new_interned_string((char*)name, name_len + 1, 0 TSRMLS_CC);
auto_global.name_len = name_len;
auto_global.auto_global_callback = auto_global_callback;
+ auto_global.jit = jit;
return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL);
}
/* }}} */
+static int zend_auto_global_init(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
+{
+ if (auto_global->jit) {
+ auto_global->armed = 1;
+ } else if (auto_global->auto_global_callback) {
+ auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
+ } else {
+ auto_global->armed = 0;
+ }
+ return 0;
+}
+/* }}} */
+
+ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */
+{
+ zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_init TSRMLS_CC);
+}
+/* }}} */
+
int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */
{
int retval;
@@ -5009,15 +6741,11 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
ce->refcount = 1;
- ce->constants_updated = 0;
ce->ce_flags = 0;
- ce->doc_comment = NULL;
- ce->doc_comment_len = 0;
-
- zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
+ ce->default_properties_table = NULL;
+ ce->default_static_members_table = NULL;
zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
- zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
@@ -5025,20 +6753,25 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
#ifdef ZTS
int n = zend_hash_num_elements(CG(class_table));
- if (CG(static_members) && n >= CG(last_static_member)) {
+ if (CG(static_members_table) && n >= CG(last_static_member)) {
/* Support for run-time declaration: dl() */
CG(last_static_member) = n+1;
- CG(static_members) = realloc(CG(static_members), (n+1)*sizeof(HashTable*));
- CG(static_members)[n] = NULL;
+ CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval**));
+ CG(static_members_table)[n] = NULL;
}
- ce->static_members = (HashTable*)(zend_intptr_t)n;
+ ce->static_members_table = (zval**)(zend_intptr_t)n;
#else
- ce->static_members = NULL;
+ ce->static_members_table = NULL;
#endif
} else {
- ce->static_members = &ce->default_static_members;
+ ce->static_members_table = ce->default_static_members_table;
+ ce->info.user.doc_comment = NULL;
+ ce->info.user.doc_comment_len = 0;
}
+ ce->default_properties_count = 0;
+ ce->default_static_members_count = 0;
+
if (nullify_handlers) {
ce->constructor = NULL;
ce->destructor = NULL;
@@ -5058,12 +6791,18 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ce->parent = NULL;
ce->num_interfaces = 0;
ce->interfaces = NULL;
- ce->module = NULL;
+ ce->num_traits = 0;
+ ce->traits = NULL;
+ ce->trait_aliases = NULL;
+ ce->trait_precedences = NULL;
ce->serialize = NULL;
ce->unserialize = NULL;
ce->serialize_func = NULL;
ce->unserialize_func = NULL;
- ce->builtin_functions = NULL;
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ce->info.internal.module = NULL;
+ ce->info.internal.builtin_functions = NULL;
+ }
}
}
/* }}} */
@@ -5085,7 +6824,7 @@ int zend_get_class_fetch_type(const char *class_name, uint class_name_len) /* {{
}
/* }}} */
-ZEND_API char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len) /* {{{ */
+ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len) /* {{{ */
{
if (name_len) {
*name_len = op_array->vars[var].name_len;
@@ -5099,7 +6838,7 @@ void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRM
if (prefix) {
*result = *prefix;
if (Z_TYPE(result->u.constant) == IS_STRING &&
- Z_STRLEN(result->u.constant) == 0) {
+ Z_STRLEN(result->u.constant) == 0) {
/* namespace\ */
if (CG(current_namespace)) {
znode tmp;
@@ -5147,8 +6886,8 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC
/* ignore ZEND_EXT_STMT and ZEND_TICKS */
int num = CG(active_op_array)->last;
while (num > 0 &&
- (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
- CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
+ (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
+ CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
--num;
}
if (num > 0) {
@@ -5164,9 +6903,9 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC
if (name) {
lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
- !memcmp(lcname, "self", sizeof("self")-1)) ||
- ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
- !memcmp(lcname, "parent", sizeof("parent")-1))) {
+ !memcmp(lcname, "self", sizeof("self")-1)) ||
+ ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
+ !memcmp(lcname, "parent", sizeof("parent")-1))) {
zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
}
efree(lcname);
@@ -5190,7 +6929,7 @@ void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC
efree(CG(current_import));
CG(current_import) = NULL;
}
-
+
if (CG(doc_comment)) {
efree(CG(doc_comment));
CG(doc_comment) = NULL;
@@ -5216,7 +6955,7 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
if (new_name) {
name = &new_name->u.constant;
} else {
- char *p;
+ const char *p;
/* The form "use A\B" is eqivalent to "use A\B as B".
So we extract the last part of compound name to use as a new_name */
@@ -5236,7 +6975,7 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
!memcmp(lcname, "self", sizeof("self")-1)) ||
((Z_STRLEN_P(name) == sizeof("parent")-1) &&
- !memcmp(lcname, "parent", sizeof("parent")-1))) {
+ !memcmp(lcname, "parent", sizeof("parent")-1))) {
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
}
@@ -5259,7 +6998,7 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
efree(c_ns_name);
} else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
(*pce)->type == ZEND_USER_CLASS &&
- (*pce)->filename == CG(compiled_filename)) {
+ (*pce)->info.user.filename == CG(compiled_filename)) {
char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
@@ -5273,6 +7012,9 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
}
if (warn) {
+ if (!strcmp(Z_STRVAL_P(name), "strict")) {
+ zend_error(E_COMPILE_ERROR, "You seem to be trying to use a different language...");
+ }
zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
}
efree(lcname);
@@ -5306,8 +7048,8 @@ void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_DECLARE_CONST;
SET_UNUSED(opline->result);
- opline->op1 = *name;
- opline->op2 = *value;
+ SET_NODE(opline->op1, name);
+ SET_NODE(opline->op2, value);
}
/* }}} */
@@ -5332,12 +7074,6 @@ void zend_do_end_namespace(TSRMLS_D) /* {{{ */
efree(CG(current_import));
CG(current_import) = NULL;
}
-
- if (CG(doc_comment)) {
- efree(CG(doc_comment));
- CG(doc_comment) = NULL;
- CG(doc_comment_len) = 0;
- }
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index de589846c0..79ace0c3c3 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -34,10 +34,10 @@
#define FREE_PNODE(znode) zval_dtor(&znode->u.constant);
-#define SET_UNUSED(op) (op).op_type = IS_UNUSED
+#define SET_UNUSED(op) op ## _type = IS_UNUSED
-#define INC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { ((op_array)->backpatch_count++); }
-#define DEC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { ((op_array)->backpatch_count--); }
+#define INC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count++); }
+#define DEC_BPC(op_array) if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count--); }
#define HANDLE_INTERACTIVE() if (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) { execute_new_code(TSRMLS_C); }
#define DO_TICKS() if (Z_LVAL(CG(declarables).ticks)) { zend_do_ticks(TSRMLS_C); }
@@ -53,20 +53,44 @@
typedef struct _zend_op_array zend_op_array;
typedef struct _zend_op zend_op;
-typedef struct _znode {
+typedef struct _zend_compiler_context {
+ zend_uint opcodes_size;
+ int vars_size;
+ int literals_size;
+ int current_brk_cont;
+ int backpatch_count;
+ HashTable *labels;
+} zend_compiler_context;
+
+typedef struct _zend_literal {
+ zval constant;
+ zend_ulong hash_value;
+ zend_uint cache_slot;
+} zend_literal;
+
+#define Z_HASH_P(zv) \
+ (((zend_literal*)(zv))->hash_value)
+
+typedef union _znode_op {
+ zend_uint constant;
+ zend_uint var;
+ zend_uint num;
+ zend_ulong hash;
+ zend_uint opline_num; /* Needs to be signed */
+ zend_op *jmp_addr;
+ zval *zv;
+ zend_literal *literal;
+ void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */
+} znode_op;
+
+typedef struct _znode { /* used only during compilation */
int op_type;
union {
- zval constant;
-
- zend_uint var;
- zend_uint opline_num; /* Needs to be signed */
+ znode_op op;
+ zval constant; /* replaced by literal/zv */
zend_op_array *op_array;
- zend_op *jmp_addr;
- struct {
- zend_uint var; /* dummy */
- zend_uint type;
- } EA;
} u;
+ zend_uint EA; /* extended attributes */
} znode;
typedef struct _zend_execute_data zend_execute_data;
@@ -81,12 +105,15 @@ extern ZEND_API opcode_handler_t *zend_opcode_handlers;
struct _zend_op {
opcode_handler_t handler;
- znode result;
- znode op1;
- znode op2;
+ znode_op op1;
+ znode_op op2;
+ znode_op result;
ulong extended_value;
uint lineno;
zend_uchar opcode;
+ zend_uchar op1_type;
+ zend_uchar op2_type;
+ zend_uchar result_type;
};
@@ -107,6 +134,11 @@ typedef struct _zend_try_catch_element {
zend_uint catch_op; /* ketchup! */
} zend_try_catch_element;
+#if SIZEOF_LONG == 8
+#define THIS_HASHVAL 210728972157UL
+#else
+#define THIS_HASHVAL 275574653UL
+#endif
/* method flags (types) */
#define ZEND_ACC_STATIC 0x01
@@ -121,6 +153,7 @@ typedef struct _zend_try_catch_element {
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20
#define ZEND_ACC_FINAL_CLASS 0x40
#define ZEND_ACC_INTERFACE 0x80
+#define ZEND_ACC_TRAIT 0x120
/* op_array flags */
#define ZEND_ACC_INTERACTIVE 0x10
@@ -151,21 +184,41 @@ typedef struct _zend_try_catch_element {
/* class implement interface(s) flag */
#define ZEND_ACC_IMPLEMENT_INTERFACES 0x80000
+#define ZEND_ACC_IMPLEMENT_TRAITS 0x400000
+
+/* class constants updated */
+#define ZEND_ACC_CONSTANTS_UPDATED 0x100000
+
+/* user class has methods with static variables */
+#define ZEND_HAS_STATIC_IN_METHODS 0x800000
+
#define ZEND_ACC_CLOSURE 0x100000
/* function flag for internal user call handlers __call, __callstatic */
#define ZEND_ACC_CALL_VIA_HANDLER 0x200000
+/* disable inline caching */
+#define ZEND_ACC_NEVER_CACHE 0x400000
+
+#define ZEND_ACC_PASS_REST_BY_REFERENCE 0x1000000
+#define ZEND_ACC_PASS_REST_PREFER_REF 0x2000000
+
+#define ZEND_ACC_RETURN_REFERENCE 0x4000000
+#define ZEND_ACC_DONE_PASS_TWO 0x8000000
+
+#define ZEND_ACC_ALIAS 0x10000000
+
char *zend_visibility_string(zend_uint fn_flags);
typedef struct _zend_property_info {
zend_uint flags;
- char *name;
+ const char *name;
int name_length;
ulong h;
- char *doc_comment;
+ int offset;
+ const char *doc_comment;
int doc_comment_len;
zend_class_entry *ce;
} zend_property_info;
@@ -176,15 +229,27 @@ typedef struct _zend_arg_info {
zend_uint name_len;
const char *class_name;
zend_uint class_name_len;
- zend_bool array_type_hint;
+ zend_uchar type_hint;
zend_bool allow_null;
zend_bool pass_by_reference;
- zend_bool return_reference;
- int required_num_args;
} zend_arg_info;
+/* the following structure repeats the layout of zend_arg_info,
+ * but its fields have different meaning. It's used as the first element of
+ * arg_info array to define properties of internal functions.
+ */
+typedef struct _zend_internal_function_info {
+ const char *_name;
+ zend_uint _name_len;
+ const char *_class_name;
+ zend_uint required_num_args;
+ zend_uchar _type_hint;
+ zend_bool return_reference;
+ zend_bool pass_rest_by_reference;
+} zend_internal_function_info;
+
typedef struct _zend_compiled_variable {
- char *name;
+ const char *name;
int name_len;
ulong hash_value;
} zend_compiled_variable;
@@ -192,32 +257,27 @@ typedef struct _zend_compiled_variable {
struct _zend_op_array {
/* Common elements */
zend_uchar type;
- char *function_name;
+ const char *function_name;
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
zend_uint num_args;
zend_uint required_num_args;
zend_arg_info *arg_info;
- zend_bool pass_rest_by_reference;
- unsigned char return_reference;
/* END of common elements */
- zend_bool done_pass_two;
-
zend_uint *refcount;
zend_op *opcodes;
- zend_uint last, size;
+ zend_uint last;
zend_compiled_variable *vars;
- int last_var, size_var;
+ int last_var;
zend_uint T;
zend_brk_cont_element *brk_cont_array;
int last_brk_cont;
- int current_brk_cont;
zend_try_catch_element *try_catch_array;
int last_try_catch;
@@ -225,18 +285,21 @@ struct _zend_op_array {
/* static variables support */
HashTable *static_variables;
- zend_op *start_op;
- int backpatch_count;
-
zend_uint this_var;
- char *filename;
+ const char *filename;
zend_uint line_start;
zend_uint line_end;
- char *doc_comment;
+ const char *doc_comment;
zend_uint doc_comment_len;
zend_uint early_binding; /* the linked list of delayed declarations */
+ zend_literal *literals;
+ int last_literal;
+
+ void **run_time_cache;
+ int last_cache_slot;
+
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
@@ -247,15 +310,13 @@ struct _zend_op_array {
typedef struct _zend_internal_function {
/* Common elements */
zend_uchar type;
- char * function_name;
+ const char * function_name;
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
zend_uint num_args;
zend_uint required_num_args;
zend_arg_info *arg_info;
- zend_bool pass_rest_by_reference;
- unsigned char return_reference;
/* END of common elements */
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
@@ -269,15 +330,13 @@ typedef union _zend_function {
struct {
zend_uchar type; /* never used */
- char *function_name;
+ const char *function_name;
zend_class_entry *scope;
zend_uint fn_flags;
union _zend_function *prototype;
zend_uint num_args;
zend_uint required_num_args;
zend_arg_info *arg_info;
- zend_bool pass_rest_by_reference;
- unsigned char return_reference;
} common;
zend_op_array op_array;
@@ -324,7 +383,6 @@ struct _zend_execute_data {
zend_class_entry *current_called_scope;
zval *current_this;
zval *current_object;
- struct _zend_op *call_opline;
};
#define EX(element) execute_data.element
@@ -336,8 +394,7 @@ struct _zend_execute_data {
#define IS_UNUSED (1<<3) /* Unused variable */
#define IS_CV (1<<4) /* Compiled variable */
-#define EXT_TYPE_UNUSED (1<<0)
-#define EXT_TYPE_FREE_ON_RETURN (2<<0)
+#define EXT_TYPE_UNUSED (1<<5)
#include "zend_globals.h"
@@ -346,6 +403,7 @@ BEGIN_EXTERN_C()
void init_compiler(TSRMLS_D);
void shutdown_compiler(TSRMLS_D);
void zend_init_compiler_data_structures(TSRMLS_D);
+void zend_init_compiler_context(TSRMLS_D);
extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
@@ -361,8 +419,8 @@ ZEND_API int zend_get_compiled_lineno(TSRMLS_D);
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D);
void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC);
-void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC);
-ZEND_API char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len);
+void zend_resolve_class_name(znode *class_name, ulong fetch_type, int check_ns_name TSRMLS_DC);
+ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len);
#ifdef ZTS
const char *zend_get_zendtext(TSRMLS_D);
@@ -374,7 +432,7 @@ int zend_get_zendleng(TSRMLS_D);
void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC);
void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC);
void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC);
-void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC);
+void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC);
void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC);
void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC);
void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC);
@@ -423,7 +481,7 @@ void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRM
int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier);
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC);
-void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, const znode *initialization, znode *class_type, const znode *varname, zend_bool pass_by_reference TSRMLS_DC);
+void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, const znode *initialization, znode *class_type, zend_bool pass_by_reference TSRMLS_DC);
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC);
void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC);
void zend_do_clone(znode *result, const znode *expr TSRMLS_DC);
@@ -435,21 +493,33 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
void zend_do_handle_exception(TSRMLS_D);
-void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC);
+void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC);
void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC);
void zend_do_try(znode *try_token TSRMLS_DC);
-void zend_do_begin_catch(znode *try_token, znode *catch_class, const znode *catch_var, znode *first_catch TSRMLS_DC);
+void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC);
void zend_do_end_catch(const znode *try_token TSRMLS_DC);
void zend_do_throw(const znode *expr TSRMLS_DC);
-ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time);
-ZEND_API zend_class_entry *do_bind_class(const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC);
-ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC);
+ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time);
+ZEND_API zend_class_entry *do_bind_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC);
+ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC);
ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC);
ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC);
void zend_do_implements_interface(znode *interface_znode TSRMLS_DC);
+/* Trait related functions */
+void zend_add_trait_precedence(znode *precedence_znode TSRMLS_DC);
+void zend_add_trait_alias(znode *alias_znode TSRMLS_DC);
+
+
+void zend_do_implements_trait(znode *interface_znode /*, znode* aliases */ TSRMLS_DC);
+ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC);
+ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC);
+void zend_prepare_trait_precedence(znode *result, znode *method_reference, znode *trait_list TSRMLS_DC);
+void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC);
+void zend_prepare_trait_alias(znode *result, znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC);
+
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC);
void zend_do_early_binding(TSRMLS_D);
ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC);
@@ -473,7 +543,6 @@ void zend_do_default_before_statement(const znode *case_list, znode *default_tok
void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC);
void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC);
void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC);
-void zend_do_declare_implicit_property(TSRMLS_D);
void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC);
void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC);
@@ -500,6 +569,11 @@ void zend_do_add_list_element(const znode *element TSRMLS_DC);
void zend_do_new_list_begin(TSRMLS_D);
void zend_do_new_list_end(TSRMLS_D);
+/* Functions for a null terminated pointer list, used for traits parsing and compilation */
+void zend_init_list(void *result, void *item TSRMLS_DC);
+void zend_add_to_list(void *result, void *item TSRMLS_DC);
+
+
void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC);
void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC);
@@ -552,6 +626,7 @@ void zend_release_labels(TSRMLS_D);
ZEND_API void function_add_ref(zend_function *function);
#define INITIAL_OP_ARRAY_SIZE 64
+#define INITIAL_INTERACTIVE_OP_ARRAY_SIZE 8192
/* helper functions in zend_language_scanner.l */
@@ -564,6 +639,9 @@ ZEND_API void init_op_array(zend_op_array *op_array, zend_uchar type, int initia
ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC);
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC);
ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC);
+ZEND_API int zend_cleanup_user_class_data(zend_class_entry **pce TSRMLS_DC);
+ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC);
+ZEND_API void zend_cleanup_internal_classes(TSRMLS_D);
ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC);
ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC);
@@ -573,7 +651,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce);
void zend_class_add_ref(zend_class_entry **ce);
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal);
-ZEND_API int zend_unmangle_property_name(char *mangled_property, int mangled_property_len, char **prop_name, char **class_name);
+ZEND_API int zend_unmangle_property_name(const char *mangled_property, int mangled_property_len, const char **class_name, const char **prop_name);
#define ZEND_FUNCTION_DTOR (void (*)(void *)) zend_function_dtor
#define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class
@@ -593,22 +671,25 @@ ZEND_API char *zend_make_compiled_string_description(const char *name TSRMLS_DC)
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC);
int zend_get_class_fetch_type(const char *class_name, uint class_name_len);
-typedef zend_bool (*zend_auto_global_callback)(char *name, uint name_len TSRMLS_DC);
+typedef zend_bool (*zend_auto_global_callback)(const char *name, uint name_len TSRMLS_DC);
typedef struct _zend_auto_global {
- char *name;
+ const char *name;
uint name_len;
zend_auto_global_callback auto_global_callback;
+ zend_bool jit;
zend_bool armed;
} zend_auto_global;
-void zend_auto_global_dtor(zend_auto_global *auto_global);
-ZEND_API int zend_register_auto_global(const char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC);
+ZEND_API int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC);
+ZEND_API void zend_activate_auto_globals(TSRMLS_D);
ZEND_API zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC);
-ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC);
+ZEND_API zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hashval TSRMLS_DC);
ZEND_API size_t zend_dirname(char *path, size_t len);
int zendlex(znode *zendlval TSRMLS_DC);
+int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
+
/* BEGIN: OPCODES */
#include "zend_vm_opcodes.h"
@@ -617,18 +698,6 @@ int zendlex(znode *zendlval TSRMLS_DC);
/* END: OPCODES */
-
-
-
-/* global/local fetches */
-#define ZEND_FETCH_GLOBAL 0
-#define ZEND_FETCH_LOCAL 1
-#define ZEND_FETCH_STATIC 2
-#define ZEND_FETCH_STATIC_MEMBER 3
-#define ZEND_FETCH_GLOBAL_LOCK 4
-#define ZEND_FETCH_LEXICAL 5
-
-
/* class fetches */
#define ZEND_FETCH_CLASS_DEFAULT 0
#define ZEND_FETCH_CLASS_SELF 1
@@ -638,6 +707,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_FETCH_CLASS_AUTO 5
#define ZEND_FETCH_CLASS_INTERFACE 6
#define ZEND_FETCH_CLASS_STATIC 7
+#define ZEND_FETCH_CLASS_TRAIT 14
#define ZEND_FETCH_CLASS_MASK 0x0f
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
#define ZEND_FETCH_CLASS_SILENT 0x0100
@@ -680,23 +750,36 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_REQUIRE (1<<3)
#define ZEND_REQUIRE_ONCE (1<<4)
-#define ZEND_ISSET (1<<0)
-#define ZEND_ISEMPTY (1<<1)
-#define ZEND_ISSET_ISEMPTY_MASK (ZEND_ISSET | ZEND_ISEMPTY)
-#define ZEND_QUICK_SET (1<<2)
-
#define ZEND_CT (1<<0)
#define ZEND_RT (1<<1)
-#define ZEND_FETCH_STANDARD 0x00000000
-#define ZEND_FETCH_ADD_LOCK 0x08000000
-#define ZEND_FETCH_MAKE_REF 0x04000000
+/* global/local fetches */
+#define ZEND_FETCH_GLOBAL 0x00000000
+#define ZEND_FETCH_LOCAL 0x10000000
+#define ZEND_FETCH_STATIC 0x20000000
+#define ZEND_FETCH_STATIC_MEMBER 0x30000000
+#define ZEND_FETCH_GLOBAL_LOCK 0x40000000
+#define ZEND_FETCH_LEXICAL 0x50000000
+
+#define ZEND_FETCH_TYPE_MASK 0x70000000
+
+#define ZEND_FETCH_STANDARD 0x00000000
+#define ZEND_FETCH_ADD_LOCK 0x08000000
+#define ZEND_FETCH_MAKE_REF 0x04000000
+
+#define ZEND_ISSET 0x02000000
+#define ZEND_ISEMPTY 0x01000000
+#define ZEND_ISSET_ISEMPTY_MASK (ZEND_ISSET | ZEND_ISEMPTY)
+#define ZEND_QUICK_SET 0x00800000
+
+#define ZEND_FETCH_ARG_MASK 0x000fffff
#define ZEND_FE_FETCH_BYREF 1
#define ZEND_FE_FETCH_WITH_KEY 2
-#define ZEND_FE_RESET_VARIABLE 1
-#define ZEND_FE_RESET_REFERENCE 2
+#define ZEND_FE_RESET_VARIABLE (1<<0)
+#define ZEND_FE_RESET_REFERENCE (1<<1)
+#define EXT_TYPE_FREE_ON_RETURN (1<<2)
#define ZEND_MEMBER_FUNC_CALL 1<<0
@@ -709,22 +792,21 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_SEND_BY_REF 1
#define ZEND_SEND_PREFER_REF 2
-#define ARG_SEND_TYPE(zf, arg_num) \
- ((zf) ? \
- ((((zend_function*)(zf))->common.arg_info && \
- arg_num<=((zend_function*)(zf))->common.num_args) ? \
- ((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference : \
- ((zend_function *)(zf))->common.pass_rest_by_reference) : \
- ZEND_SEND_BY_VAL)
+#define CHECK_ARG_SEND_TYPE(zf, arg_num, m1, m2) \
+ ((zf) && \
+ ((((zend_function*)(zf))->common.arg_info && \
+ arg_num <= ((zend_function*)(zf))->common.num_args) ? \
+ (((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference & (m1)) : \
+ (((zend_function *)(zf))->common.fn_flags & (m2))))
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
- (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_BY_REF)
+ CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF, ZEND_ACC_PASS_REST_BY_REFERENCE)
#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
- (ARG_SEND_TYPE(zf, arg_num) & (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF))
+ CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF, ZEND_ACC_PASS_REST_BY_REFERENCE|ZEND_ACC_PASS_REST_PREFER_REF)
#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
- (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_PREFER_REF)
+ CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_PREFER_REF, ZEND_ACC_PASS_REST_PREFER_REF)
#define ZEND_RETURN_VAL 0
#define ZEND_RETURN_REF 1
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 94c3b4cf02..03b6309cc3 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -32,13 +32,15 @@ void free_zend_constant(zend_constant *c)
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
- free(c->name);
+ str_free(c->name);
}
void copy_zend_constant(zend_constant *c)
{
- c->name = zend_strndup(c->name, c->name_len - 1);
+ if (!IS_INTERNED(c->name)) {
+ c->name = zend_strndup(c->name, c->name_len - 1);
+ }
if (!(c->flags & CONST_PERSISTENT)) {
zval_copy_ctor(&c->value);
}
@@ -139,7 +141,7 @@ void zend_register_standard_constants(TSRMLS_D)
c.value.type = IS_NULL;
zend_register_constant(&c TSRMLS_CC);
- c.flags = CONST_PERSISTENT;
+ c.flags = CONST_PERSISTENT | CONST_CS;
c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
c.name_len = sizeof("ZEND_THREAD_SAFE");
@@ -222,6 +224,64 @@ ZEND_API void zend_register_string_constant(const char *name, uint name_len, cha
zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
}
+static int zend_get_special_constant(const char *name, uint name_len, zend_constant **c TSRMLS_DC)
+{
+ int ret;
+ static char haltoff[] = "__COMPILER_HALT_OFFSET__";
+
+ if (!EG(in_execution)) {
+ return 0;
+ } else if (name_len == sizeof("__CLASS__")-1 &&
+ !memcmp(name, "__CLASS__", sizeof("__CLASS__")-1)) {
+ zend_constant tmp;
+
+ /* Returned constants may be cached, so they have to be stored */
+ if (EG(scope) && EG(scope)->name) {
+ int const_name_len;
+ char *const_name;
+ ALLOCA_FLAG(use_heap)
+
+ const_name_len = sizeof("\0__CLASS__") + EG(scope)->name_length;
+ const_name = do_alloca(const_name_len, use_heap);
+ memcpy(const_name, "\0__CLASS__", sizeof("\0__CLASS__")-1);
+ zend_str_tolower_copy(const_name + sizeof("\0__CLASS__")-1, EG(scope)->name, EG(scope)->name_length);
+ if (zend_hash_find(EG(zend_constants), const_name, const_name_len, (void**)c) == FAILURE) {
+ zend_hash_add(EG(zend_constants), const_name, const_name_len, (void*)&tmp, sizeof(zend_constant), (void**)c);
+ memset(*c, 0, sizeof(zend_constant));
+ Z_STRVAL((**c).value) = estrndup(EG(scope)->name, EG(scope)->name_length);
+ Z_STRLEN((**c).value) = EG(scope)->name_length;
+ Z_TYPE((**c).value) = IS_STRING;
+ }
+ free_alloca(const_name, use_heap);
+ } else {
+ if (zend_hash_find(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void**)c) == FAILURE) {
+ zend_hash_add(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void*)&tmp, sizeof(zend_constant), (void**)c);
+ memset(*c, 0, sizeof(zend_constant));
+ Z_STRVAL((**c).value) = estrndup("", 0);
+ Z_STRLEN((**c).value) = 0;
+ Z_TYPE((**c).value) = IS_STRING;
+ }
+ }
+ return 1;
+ } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
+ !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
+ const char *cfilename;
+ char *haltname;
+ int len, clen;
+
+ cfilename = zend_get_executed_filename(TSRMLS_C);
+ clen = strlen(cfilename);
+ /* check for __COMPILER_HALT_OFFSET__ */
+ zend_mangle_property_name(&haltname, &len, haltoff,
+ sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
+ ret = zend_hash_find(EG(zend_constants), haltname, len+1, (void **) c);
+ efree(haltname);
+ return (ret == SUCCESS);
+ } else {
+ return 0;
+ }
+}
+
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC)
{
@@ -237,29 +297,7 @@ ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSR
retval=0;
}
} else {
- static char haltoff[] = "__COMPILER_HALT_OFFSET__";
-
- if (!EG(in_execution)) {
- retval = 0;
- } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
- !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
- char *cfilename, *haltname;
- int len, clen;
-
- cfilename = zend_get_executed_filename(TSRMLS_C);
- clen = strlen(cfilename);
- /* check for __COMPILER_HALT_OFFSET__ */
- zend_mangle_property_name(&haltname, &len, haltoff,
- sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
- if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
- retval = 1;
- } else {
- retval=0;
- }
- pefree(haltname, 0);
- } else {
- retval=0;
- }
+ retval = zend_get_special_constant(name, name_len, &c TSRMLS_CC);
}
efree(lookup_name);
}
@@ -278,7 +316,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
{
zend_constant *c;
int retval = 1;
- char *colon;
+ const char *colon;
zend_class_entry *ce = NULL;
char *class_name;
zval **ret_constant;
@@ -294,7 +332,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
colon > name && (*(colon - 1) == ':')) {
int class_name_len = colon - name - 1;
int const_name_len = name_len - class_name_len - 2;
- char *constant_name = colon + 1;
+ const char *constant_name = colon + 1;
char *lcname;
class_name = estrndup(name, class_name_len);
@@ -357,7 +395,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
/* compound constant name */
int prefix_len = colon - name;
int const_name_len = name_len - prefix_len - 1;
- char *constant_name = colon + 1;
+ const char *constant_name = colon + 1;
char *lcname;
int found_const = 0;
@@ -410,11 +448,44 @@ finish:
return zend_get_constant(name, name_len, result TSRMLS_CC);
}
+zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRMLS_DC)
+{
+ zend_constant *c;
+
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) {
+ key++;
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE ||
+ (c->flags & CONST_CS) != 0) {
+ if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
+ key++;
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) {
+ key++;
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE ||
+ (c->flags & CONST_CS) != 0) {
+
+ key--;
+ if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) {
+ return NULL;
+ }
+ }
+ }
+ } else {
+ key--;
+ if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) {
+ return NULL;
+ }
+ }
+ }
+ }
+ return c;
+}
+
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
{
char *lowercase_name = NULL;
char *name;
int ret = SUCCESS;
+ ulong chash = 0;
#if 0
printf("Registering constant for module %d\n", c->module_number);
@@ -424,22 +495,30 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
/* keep in mind that c->name_len already contains the '\0' */
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, c->name_len-1);
+ lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
+ chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
} else {
char *slash = strrchr(c->name, '\\');
if(slash) {
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, slash-c->name);
+ lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
+
+ chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
} else {
name = c->name;
}
}
+ if (chash == 0) {
+ chash = zend_hash_func(name, c->name_len);
+ }
/* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
&& !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
- || zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
+ || zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
/* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
@@ -447,13 +526,13 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
name++;
}
zend_error(E_NOTICE,"Constant %s already defined", name);
- free(c->name);
+ str_free(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
ret = FAILURE;
}
- if (lowercase_name) {
+ if (lowercase_name && !IS_INTERNED(lowercase_name)) {
efree(lowercase_name);
}
return ret;
diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h
index e079b4b2d2..af8ec56e81 100644
--- a/Zend/zend_constants.h
+++ b/Zend/zend_constants.h
@@ -69,6 +69,7 @@ ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, ch
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC);
void zend_copy_constants(HashTable *target, HashTable *sourc);
void copy_zend_constant(zend_constant *c);
+zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRMLS_DC);
END_EXTERN_C()
#define ZEND_CONSTANT_DTOR (void (*)(void *)) free_zend_constant
diff --git a/Zend/zend_dtrace.c b/Zend/zend_dtrace.c
new file mode 100644
index 0000000000..5b2d0d2dfe
--- /dev/null
+++ b/Zend/zend_dtrace.c
@@ -0,0 +1,108 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: David Soria Parra <david.soriaparra@sun.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#include "zend.h"
+#include "zend_API.h"
+#include "zend_dtrace.h"
+
+#ifdef HAVE_DTRACE
+/* PHP DTrace probes {{{ */
+static inline char *dtrace_get_executed_filename(TSRMLS_D)
+{
+ if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
+ return EG(current_execute_data)->op_array->filename;
+ } else {
+ return zend_get_executed_filename(TSRMLS_C);
+ }
+}
+
+ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
+{
+ zend_op_array *res;
+ DTRACE_COMPILE_FILE_ENTRY(file_handle->opened_path, file_handle->filename);
+ res = compile_file(file_handle, type TSRMLS_CC);
+ DTRACE_COMPILE_FILE_RETURN(file_handle->opened_path, file_handle->filename);
+
+ return res;
+}
+
+/* We wrap the execute function to have fire the execute-entry/return and function-entry/return probes */
+ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC)
+{
+ int lineno;
+ char *scope, *filename, *funcname, *classname;
+ scope = filename = funcname = classname = NULL;
+
+ /* we need filename and lineno for both execute and function probes */
+ if (DTRACE_EXECUTE_ENTRY_ENABLED() || DTRACE_EXECUTE_RETURN_ENABLED()
+ || DTRACE_FUNCTION_ENTRY_ENABLED() || DTRACE_FUNCTION_RETURN_ENABLED()) {
+ filename = dtrace_get_executed_filename(TSRMLS_C);
+ lineno = zend_get_executed_lineno(TSRMLS_C);
+ }
+
+ if (DTRACE_FUNCTION_ENTRY_ENABLED() || DTRACE_FUNCTION_RETURN_ENABLED()) {
+ filename = dtrace_get_executed_filename(TSRMLS_C);
+ classname = get_active_class_name(&scope TSRMLS_CC);
+ funcname = get_active_function_name(TSRMLS_C);
+ lineno = zend_get_executed_lineno(TSRMLS_C);
+ }
+
+ if (DTRACE_EXECUTE_ENTRY_ENABLED()) {
+ DTRACE_EXECUTE_ENTRY(filename, lineno);
+ }
+
+ if (DTRACE_FUNCTION_ENTRY_ENABLED() && funcname != NULL) {
+ DTRACE_FUNCTION_ENTRY(funcname, filename, lineno, classname, scope);
+ }
+
+ execute(op_array TSRMLS_CC);
+
+ if (DTRACE_FUNCTION_RETURN_ENABLED() && funcname != NULL) {
+ DTRACE_FUNCTION_RETURN(funcname, filename, lineno, classname, scope);
+ }
+
+ if (DTRACE_EXECUTE_RETURN_ENABLED()) {
+ DTRACE_EXECUTE_RETURN(filename, lineno);
+ }
+}
+
+ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
+{
+ int lineno;
+ char *filename;
+ if (DTRACE_EXECUTE_ENTRY_ENABLED() || DTRACE_EXECUTE_RETURN_ENABLED()) {
+ filename = dtrace_get_executed_filename(TSRMLS_C);
+ lineno = zend_get_executed_lineno(TSRMLS_C);
+ }
+
+ if (DTRACE_EXECUTE_ENTRY_ENABLED()) {
+ DTRACE_EXECUTE_ENTRY(filename, lineno);
+ }
+
+ execute_internal(execute_data_ptr, return_value_used TSRMLS_CC);
+
+ if (DTRACE_EXECUTE_RETURN_ENABLED()) {
+ DTRACE_EXECUTE_RETURN(filename, lineno);
+ }
+}
+
+/* }}} */
+#endif /* HAVE_DTRACE */
+
diff --git a/Zend/zend_dtrace.d b/Zend/zend_dtrace.d
new file mode 100644
index 0000000000..609663f4b1
--- /dev/null
+++ b/Zend/zend_dtrace.d
@@ -0,0 +1,37 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: David Soria Parra <david.soriaparra@sun.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+provider php {
+ probe exception__caught(char *classname);
+ probe exception__thrown(char* classname);
+ probe request__startup(char* request_file, char* request_uri, char* request_method);
+ probe request__shutdown(char* request_file, char* request_uri, char* request_method);
+ probe compile__file__entry(char * compile_file, char *compile_file_translated);
+ probe compile__file__return(char *compile_file, char *compile_file_translated);
+ probe error(char *errormsg, char *request_file, int lineno);
+ probe execute__entry(char* request_file, int lineno);
+ probe execute__return(char* request_file, int lineno);
+ probe function__entry(char* function_name, char* request_file, int lineno, char* classname, char* scope);
+ probe function__return(char* function_name, char* request_file, int lineno, char* classname, char* scope);
+};
+
+/*#pragma D attributes Private/Private/Unknown provider php module
+#pragma D attributes Private/Private/Unknown provider php function
+#pragma D attributes Evolving/Evolving/Common provider php provider */
diff --git a/Zend/zend_dtrace.h b/Zend/zend_dtrace.h
new file mode 100644
index 0000000000..65d19ef346
--- /dev/null
+++ b/Zend/zend_dtrace.h
@@ -0,0 +1,48 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: David Soria Parra <david.soriaparra@sun.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#ifndef _ZEND_DTRACE_H
+#define _ZEND_DTRACE_H
+
+#ifndef ZEND_WIN32
+# include <unistd.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_DTRACE
+ZEND_API zend_op_array *(*zend_dtrace_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
+ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC);
+ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
+
+ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
+ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC);
+ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
+#include <zend_dtrace_gen.h>
+
+#endif /* HAVE_DTRACE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZEND_DTRACE_H */
diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h
index 02c5375264..1774a353b1 100644
--- a/Zend/zend_errors.h
+++ b/Zend/zend_errors.h
@@ -38,7 +38,7 @@
#define E_DEPRECATED (1<<13L)
#define E_USER_DEPRECATED (1<<14L)
-#define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED)
+#define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)
#define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
#endif /* ZEND_ERRORS_H */
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index a83053e120..787e66bfe9 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -27,9 +27,10 @@
#include "zend_interfaces.h"
#include "zend_exceptions.h"
#include "zend_vm.h"
+#include "zend_dtrace.h"
-zend_class_entry *default_exception_ce;
-zend_class_entry *error_exception_ce;
+static zend_class_entry *default_exception_ce;
+static zend_class_entry *error_exception_ce;
static zend_object_handlers default_exception_handlers;
ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
@@ -82,6 +83,20 @@ void zend_exception_restore(TSRMLS_D) /* {{{ */
void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
{
+#ifdef HAVE_DTRACE
+ if (DTRACE_EXCEPTION_THROWN_ENABLED()) {
+ char *classname;
+ int name_len;
+
+ if (exception != NULL) {
+ zend_get_object_classname(exception, &classname, &name_len TSRMLS_CC);
+ DTRACE_EXCEPTION_THROWN(classname);
+ } else {
+ DTRACE_EXCEPTION_THROWN(NULL);
+ }
+ }
+#endif /* HAVE_DTRACE */
+
if (exception != NULL) {
zval *previous = EG(exception);
zend_exception_set_previous(exception, EG(exception) TSRMLS_CC);
@@ -131,21 +146,19 @@ ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */
{
- zval tmp, obj;
+ zval obj;
zend_object *object;
zval *trace;
Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC);
Z_OBJ_HT(obj) = &default_exception_handlers;
- ALLOC_HASHTABLE(object->properties);
- zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void *) &tmp, sizeof(zval *));
+ object_properties_init(object, class_type);
ALLOC_ZVAL(trace);
Z_UNSET_ISREF_P(trace);
Z_SET_REFCOUNT_P(trace, 0);
- zend_fetch_debug_backtrace(trace, skip_top_traces, 0 TSRMLS_CC);
+ zend_fetch_debug_backtrace(trace, skip_top_traces, 0, 0 TSRMLS_CC);
zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC);
zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
@@ -417,7 +430,7 @@ static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, z
TRACE_APPEND_STR("Array, ");
break;
case IS_OBJECT: {
- char *class_name;
+ const char *class_name;
zend_uint class_name_len;
int dup;
@@ -427,7 +440,7 @@ static int _build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, z
TRACE_APPEND_STRL(class_name, class_name_len);
if(!dup) {
- efree(class_name);
+ efree((char*)class_name);
}
TRACE_APPEND_STR("), ");
@@ -600,6 +613,7 @@ ZEND_METHOD(exception, __toString)
if (trace) {
zval_ptr_dtor(&trace);
}
+
}
zval_dtor(&fname);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 4423921649..fbc73258c7 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -36,6 +36,7 @@
#include "zend_interfaces.h"
#include "zend_closures.h"
#include "zend_vm.h"
+#include "zend_dtrace.h"
/* Virtual current working directory support */
#include "tsrm_virtual_cwd.h"
@@ -48,20 +49,20 @@
typedef int (*incdec_t)(zval *);
-#define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
-#define get_zval_ptr_ptr(node, Ts, should_free, type) _get_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
-#define get_obj_zval_ptr(node, Ts, should_free, type) _get_obj_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
-#define get_obj_zval_ptr_ptr(node, Ts, should_free, type) _get_obj_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
+#define get_zval_ptr(op_type, node, Ts, should_free, type) _get_zval_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
+#define get_zval_ptr_ptr(op_type, node, Ts, should_free, type) _get_zval_ptr_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
+#define get_obj_zval_ptr(op_type, node, Ts, should_free, type) _get_obj_zval_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
+#define get_obj_zval_ptr_ptr(op_type, node, Ts, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
/* Prototypes */
static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
-#define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
+#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
-#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
#define T(offset) (*(temp_variable *)((char *) Ts + offset))
+#define CV(var) CVs[var]
#define TEMP_VAR_STACK_LIMIT 2000
@@ -92,24 +93,32 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
}
}
+#undef zval_ptr_dtor
+#define zval_ptr_dtor(pzv) i_zval_ptr_dtor(*(pzv) ZEND_FILE_LINE_CC)
+
#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
#define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
#define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC)
#define PZVAL_LOCK(z) Z_ADDREF_P((z))
-#define RETURN_VALUE_UNUSED(pzn) (((pzn)->u.EA.type & EXT_TYPE_UNUSED))
-#define SELECTIVE_PZVAL_LOCK(pzv, pzn) if (!RETURN_VALUE_UNUSED(pzn)) { PZVAL_LOCK(pzv); }
-
-#define AI_USE_PTR(ai) \
- if ((ai).ptr_ptr) { \
- (ai).ptr = *((ai).ptr_ptr); \
- (ai).ptr_ptr = &((ai).ptr); \
- } else { \
- (ai).ptr = NULL; \
- }
+#define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
+
+#define EXTRACT_ZVAL_PTR(t) do { \
+ temp_variable *__t = (t); \
+ if (__t->var.ptr_ptr) { \
+ __t->var.ptr = *__t->var.ptr_ptr; \
+ __t->var.ptr_ptr = &__t->var.ptr; \
+ if (!PZVAL_IS_REF(__t->var.ptr) && \
+ Z_REFCOUNT_P(__t->var.ptr) > 2) { \
+ SEPARATE_ZVAL(__t->var.ptr_ptr); \
+ } \
+ } \
+ } while (0)
-#define AI_SET_PTR(ai, val) \
- (ai).ptr = (val); \
- (ai).ptr_ptr = &((ai).ptr);
+#define AI_SET_PTR(t, val) do { \
+ temp_variable *__t = (t); \
+ __t->var.ptr = (val); \
+ __t->var.ptr_ptr = &__t->var.ptr; \
+ } while (0)
#define FREE_OP(should_free) \
if (should_free.var) { \
@@ -134,21 +143,12 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
#define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
-#define INIT_PZVAL_COPY(z,v) \
- (z)->value = (v)->value; \
- Z_TYPE_P(z) = Z_TYPE_P(v); \
- Z_SET_REFCOUNT_P(z, 1); \
- Z_UNSET_ISREF_P(z);
-
#define MAKE_REAL_ZVAL_PTR(val) \
do { \
zval *_tmp; \
ALLOC_ZVAL(_tmp); \
- _tmp->value = (val)->value; \
- Z_TYPE_P(_tmp) = Z_TYPE_P(val); \
- Z_SET_REFCOUNT_P(_tmp, 1); \
- Z_UNSET_ISREF_P(_tmp); \
- val = _tmp; \
+ INIT_PZVAL_COPY(_tmp, (val)); \
+ (val) = _tmp; \
} while (0)
/* End of zend_execute_locks.h */
@@ -172,50 +172,20 @@ ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execut
return execute_data_ptr->CVs[var];
}
-static zend_always_inline zval *_get_zval_ptr_tmp(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
{
- return should_free->var = &T(node->u.var).tmp_var;
+ return should_free->var = &T(var).tmp_var;
}
-static zval *_get_zval_ptr_var_string_offset(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
{
- temp_variable *T = &T(node->u.var);
- zval *str = T->str_offset.str;
- zval *ptr;
-
- /* string offset */
- ALLOC_ZVAL(ptr);
- T->str_offset.ptr = ptr;
- should_free->var = ptr;
-
- if (T->str_offset.str->type != IS_STRING
- || ((int)T->str_offset.offset < 0)
- || (T->str_offset.str->value.str.len <= (int)T->str_offset.offset)) {
- ptr->value.str.val = STR_EMPTY_ALLOC();
- ptr->value.str.len = 0;
- } else {
- ptr->value.str.val = estrndup(str->value.str.val + T->str_offset.offset, 1);
- ptr->value.str.len = 1;
- }
- PZVAL_UNLOCK_FREE(str);
- Z_SET_REFCOUNT_P(ptr, 1);
- Z_SET_ISREF_P(ptr);
- ptr->type = IS_STRING;
- return ptr;
-}
+ zval *ptr = T(var).var.ptr;
-static zend_always_inline zval *_get_zval_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
-{
- zval *ptr = T(node->u.var).var.ptr;
- if (EXPECTED(ptr != NULL)) {
- PZVAL_UNLOCK(ptr, should_free);
- return ptr;
- } else {
- return _get_zval_ptr_var_string_offset(node, Ts, should_free TSRMLS_CC);
- }
+ PZVAL_UNLOCK(ptr, should_free);
+ return ptr;
}
-static zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
+static zend_never_inline zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
{
zend_compiled_variable *cv = &CV_DEF_OF(var);
@@ -246,30 +216,147 @@ static zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC
return *ptr;
}
-static zend_always_inline zval *_get_zval_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
+static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_R(zval ***ptr, zend_uint var TSRMLS_DC)
{
- zval ***ptr = &CV_OF(node->u.var);
+ zend_compiled_variable *cv = &CV_DEF_OF(var);
+
+ if (!EG(active_symbol_table) ||
+ zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ return &EG(uninitialized_zval_ptr);
+ }
+ return *ptr;
+}
+
+static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_UNSET(zval ***ptr, zend_uint var TSRMLS_DC)
+{
+ zend_compiled_variable *cv = &CV_DEF_OF(var);
+
+ if (!EG(active_symbol_table) ||
+ zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ return &EG(uninitialized_zval_ptr);
+ }
+ return *ptr;
+}
+
+static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_IS(zval ***ptr, zend_uint var TSRMLS_DC)
+{
+ zend_compiled_variable *cv = &CV_DEF_OF(var);
+
+ if (!EG(active_symbol_table) ||
+ zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ return &EG(uninitialized_zval_ptr);
+ }
+ return *ptr;
+}
+
+static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_RW(zval ***ptr, zend_uint var TSRMLS_DC)
+{
+ zend_compiled_variable *cv = &CV_DEF_OF(var);
+
+ if (!EG(active_symbol_table)) {
+ Z_ADDREF(EG(uninitialized_zval));
+ *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
+ **ptr = &EG(uninitialized_zval);
+ zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ } else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ Z_ADDREF(EG(uninitialized_zval));
+ zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
+ zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ }
+ return *ptr;
+}
+
+static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_W(zval ***ptr, zend_uint var TSRMLS_DC)
+{
+ zend_compiled_variable *cv = &CV_DEF_OF(var);
+
+ if (!EG(active_symbol_table)) {
+ Z_ADDREF(EG(uninitialized_zval));
+ *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
+ **ptr = &EG(uninitialized_zval);
+ } else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ Z_ADDREF(EG(uninitialized_zval));
+ zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
+ }
+ return *ptr;
+}
+
+static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_DC)
+{
+ zval ***ptr = &CV_OF(var);
if (UNEXPECTED(*ptr == NULL)) {
- return *_get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
+ return *_get_zval_cv_lookup(ptr, var, type TSRMLS_CC);
}
return **ptr;
}
-static inline zval *_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return *_get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
+ }
+ return **ptr;
+}
+
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return *_get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC);
+ }
+ return **ptr;
+}
+
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return *_get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC);
+ }
+ return **ptr;
+}
+
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return *_get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC);
+ }
+ return **ptr;
+}
+
+static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return *_get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC);
+ }
+ return **ptr;
+}
+
+static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
{
/* should_free->is_var = 0; */
- switch (node->op_type) {
+ switch (op_type) {
case IS_CONST:
should_free->var = 0;
- return &node->u.constant;
+ return node->zv;
break;
case IS_TMP_VAR:
- should_free->var = TMP_FREE(&T(node->u.var).tmp_var);
- return &T(node->u.var).tmp_var;
+ should_free->var = TMP_FREE(&T(node->var).tmp_var);
+ return &T(node->var).tmp_var;
break;
case IS_VAR:
- return _get_zval_ptr_var(node, Ts, should_free TSRMLS_CC);
+ return _get_zval_ptr_var(node->var, Ts, should_free TSRMLS_CC);
break;
case IS_UNUSED:
should_free->var = 0;
@@ -277,43 +364,93 @@ static inline zval *_get_zval_ptr(znode *node, const temp_variable *Ts, zend_fre
break;
case IS_CV:
should_free->var = 0;
- return _get_zval_ptr_cv(node, Ts, type TSRMLS_CC);
+ return _get_zval_ptr_cv(node->var, type TSRMLS_CC);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
return NULL;
}
-static zend_always_inline zval **_get_zval_ptr_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
+static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
{
- zval** ptr_ptr = T(node->u.var).var.ptr_ptr;
+ zval** ptr_ptr = T(var).var.ptr_ptr;
if (EXPECTED(ptr_ptr != NULL)) {
PZVAL_UNLOCK(*ptr_ptr, should_free);
} else {
/* string offset */
- PZVAL_UNLOCK(T(node->u.var).str_offset.str, should_free);
+ PZVAL_UNLOCK(T(var).str_offset.str, should_free);
}
return ptr_ptr;
}
-static zend_always_inline zval **_get_zval_ptr_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
+static zend_always_inline zval **_get_zval_ptr_ptr_cv(zend_uint var, int type TSRMLS_DC)
{
- zval ***ptr = &CV_OF(node->u.var);
+ zval ***ptr = &CV_OF(var);
if (UNEXPECTED(*ptr == NULL)) {
- return _get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
+ return _get_zval_cv_lookup(ptr, var, type TSRMLS_CC);
}
return *ptr;
}
-static inline zval **_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
+static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC)
{
- if (node->op_type == IS_CV) {
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return _get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
+ }
+ return *ptr;
+}
+
+static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return _get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC);
+ }
+ return *ptr;
+}
+
+static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return _get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC);
+ }
+ return *ptr;
+}
+
+static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return _get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC);
+ }
+ return *ptr;
+}
+
+static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint var TSRMLS_DC)
+{
+ zval ***ptr = &CV(var);
+
+ if (UNEXPECTED(*ptr == NULL)) {
+ return _get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC);
+ }
+ return *ptr;
+}
+
+static inline zval **_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
+{
+ if (op_type == IS_CV) {
should_free->var = 0;
- return _get_zval_ptr_ptr_cv(node, Ts, type TSRMLS_CC);
- } else if (node->op_type == IS_VAR) {
- return _get_zval_ptr_ptr_var(node, Ts, should_free TSRMLS_CC);
+ return _get_zval_ptr_ptr_cv(node->var, type TSRMLS_CC);
+ } else if (op_type == IS_VAR) {
+ return _get_zval_ptr_ptr_var(node->var, Ts, should_free TSRMLS_CC);
} else {
should_free->var = 0;
return NULL;
@@ -330,9 +467,9 @@ static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
}
}
-static inline zval **_get_obj_zval_ptr_ptr(const znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
+static inline zval **_get_obj_zval_ptr_ptr(int op_type, const znode_op *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
{
- if (op->op_type == IS_UNUSED) {
+ if (op_type == IS_UNUSED) {
if (EXPECTED(EG(This) != NULL)) {
/* this should actually never be modified, _ptr_ptr is modified only when
the object is empty */
@@ -342,7 +479,7 @@ static inline zval **_get_obj_zval_ptr_ptr(const znode *op, const temp_variable
zend_error_noreturn(E_ERROR, "Using $this when not in object context");
}
}
- return get_zval_ptr_ptr(op, Ts, should_free, type);
+ return get_zval_ptr_ptr(op_type, op, Ts, should_free, type);
}
static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
@@ -355,9 +492,9 @@ static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
}
}
-static inline zval *_get_obj_zval_ptr(znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
+static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
{
- if (op->op_type == IS_UNUSED) {
+ if (op_type == IS_UNUSED) {
if (EXPECTED(EG(This) != NULL)) {
should_free->var = 0;
return EG(This);
@@ -365,22 +502,7 @@ static inline zval *_get_obj_zval_ptr(znode *op, const temp_variable *Ts, zend_f
zend_error_noreturn(E_ERROR, "Using $this when not in object context");
}
}
- return get_zval_ptr(op, Ts, should_free, type);
-}
-
-static inline void zend_switch_free(temp_variable *T, int extended_value TSRMLS_DC)
-{
- if (T->var.ptr) {
- if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */
- Z_DELREF_P(T->var.ptr);
- }
- zval_ptr_dtor(&T->var.ptr);
- } else if (!T->var.ptr_ptr) {
- /* perform the equivalent of equivalent of a
- * quick & silent get_zval_ptr, and FREE_OP
- */
- PZVAL_UNLOCK_FREE(T->str_offset.str);
- }
+ return get_zval_ptr(op_type, op, Ts, should_free, type);
}
static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC)
@@ -388,7 +510,7 @@ static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **va
zval *variable_ptr = *variable_ptr_ptr;
zval *value_ptr = *value_ptr_ptr;
- if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) {
+ if (variable_ptr == &EG(error_zval) || value_ptr == &EG(error_zval)) {
variable_ptr_ptr = &EG(uninitialized_zval_ptr);
} else if (variable_ptr != value_ptr) {
if (!PZVAL_IS_REF(value_ptr)) {
@@ -396,7 +518,7 @@ static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **va
Z_DELREF_P(value_ptr);
if (Z_REFCOUNT_P(value_ptr)>0) {
ALLOC_ZVAL(*value_ptr_ptr);
- **value_ptr_ptr = *value_ptr;
+ ZVAL_COPY_VALUE(*value_ptr_ptr, value_ptr);
value_ptr = *value_ptr_ptr;
zendi_zval_copy_ctor(*value_ptr);
}
@@ -411,12 +533,12 @@ static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **va
} else if (!Z_ISREF_P(variable_ptr)) {
if (variable_ptr_ptr == value_ptr_ptr) {
SEPARATE_ZVAL(variable_ptr_ptr);
- } else if (variable_ptr==EG(uninitialized_zval_ptr)
+ } else if (variable_ptr==&EG(uninitialized_zval)
|| Z_REFCOUNT_P(variable_ptr)>2) {
/* we need to separate */
Z_SET_REFCOUNT_P(variable_ptr, Z_REFCOUNT_P(variable_ptr) - 2);
ALLOC_ZVAL(*variable_ptr_ptr);
- **variable_ptr_ptr = *variable_ptr;
+ ZVAL_COPY_VALUE(*variable_ptr_ptr, variable_ptr);
zval_copy_ctor(*variable_ptr_ptr);
*value_ptr_ptr = *variable_ptr_ptr;
Z_SET_REFCOUNT_PP(variable_ptr_ptr, 2);
@@ -435,11 +557,11 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC)
SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
zval_dtor(*object_ptr);
object_init(*object_ptr);
- zend_error(E_STRICT, "Creating default object from empty value");
+ zend_error(E_WARNING, "Creating default object from empty value");
}
}
-static inline char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC)
+ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC)
{
*pce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
@@ -451,12 +573,12 @@ static inline char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_inf
}
}
-static inline int zend_verify_arg_error(const zend_function *zf, zend_uint arg_num, const zend_arg_info *cur_arg_info, const char *need_msg, const char *need_kind, const char *given_msg, char *given_kind TSRMLS_DC)
+ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
{
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
- char *fname = zf->common.function_name;
+ const char *fname = zf->common.function_name;
char *fsep;
- char *fclass;
+ const char *fclass;
if (zf->common.scope) {
fsep = "::";
@@ -467,9 +589,9 @@ static inline int zend_verify_arg_error(const zend_function *zf, zend_uint arg_n
}
if (ptr && ptr->op_array) {
- zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->op_array->filename, ptr->opline->lineno);
+ zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
+ zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
}
return 0;
}
@@ -492,40 +614,55 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
if (!arg) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
- return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "none", "" TSRMLS_CC);
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
}
if (Z_TYPE_P(arg) == IS_OBJECT) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
- return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
}
} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
- return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
}
- } else if (cur_arg_info->array_type_hint) {
- if (!arg) {
- return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC);
- }
- if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ } else if (cur_arg_info->type_hint) {
+ switch(cur_arg_info->type_hint) {
+ case IS_ARRAY:
+ if (!arg) {
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
+ }
+
+ if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ }
+ break;
+
+ case IS_CALLABLE:
+ if (!arg) {
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
+ }
+ if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
+ return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ }
+ break;
+
+ default:
+ zend_error(E_ERROR, "Unknown typehint");
}
}
return 1;
}
-static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval *property_name, znode *value_op, const temp_variable *Ts, int opcode TSRMLS_DC)
-
+static inline void zend_assign_to_object(zval **retval, zval **object_ptr, zval *property_name, int value_type, znode_op *value_op, const temp_variable *Ts, int opcode, const zend_literal *key TSRMLS_DC)
{
zval *object = *object_ptr;
zend_free_op free_value;
- zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R);
- zval **retval = &T(result->u.var).var.ptr;
+ zval *value = get_zval_ptr(value_type, value_op, Ts, &free_value, BP_VAR_R);
if (Z_TYPE_P(object) != IS_OBJECT) {
- if (object == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(result)) {
- *retval = EG(uninitialized_zval_ptr);
+ if (object == &EG(error_zval)) {
+ if (retval) {
+ *retval = &EG(uninitialized_zval);
PZVAL_LOCK(*retval);
}
FREE_OP(free_value);
@@ -537,7 +674,7 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval
SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
object = *object_ptr;
Z_ADDREF_P(object);
- zend_error(E_STRICT, "Creating default object from empty value");
+ zend_error(E_WARNING, "Creating default object from empty value");
if (Z_REFCOUNT_P(object) == 1) {
/* object was removed by error handler, nothing to assign to */
zval_ptr_dtor(&object);
@@ -553,28 +690,28 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval
object_init(object);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- *retval = EG(uninitialized_zval_ptr);
+ if (retval) {
+ *retval = &EG(uninitialized_zval);
PZVAL_LOCK(*retval);
}
FREE_OP(free_value);
return;
}
}
-
+
/* separate our value if necessary */
- if (value_op->op_type == IS_TMP_VAR) {
+ if (value_type == IS_TMP_VAR) {
zval *orig_value = value;
ALLOC_ZVAL(value);
- *value = *orig_value;
+ ZVAL_COPY_VALUE(value, orig_value);
Z_UNSET_ISREF_P(value);
Z_SET_REFCOUNT_P(value, 0);
- } else if (value_op->op_type == IS_CONST) {
+ } else if (value_type == IS_CONST) {
zval *orig_value = value;
ALLOC_ZVAL(value);
- *value = *orig_value;
+ ZVAL_COPY_VALUE(value, orig_value);
Z_UNSET_ISREF_P(value);
Z_SET_REFCOUNT_P(value, 0);
zval_copy_ctor(value);
@@ -585,19 +722,19 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval
if (opcode == ZEND_ASSIGN_OBJ) {
if (!Z_OBJ_HT_P(object)->write_property) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (retval) {
+ *retval = &EG(uninitialized_zval);
+ PZVAL_LOCK(&EG(uninitialized_zval));
}
- if (value_op->op_type == IS_TMP_VAR) {
+ if (value_type == IS_TMP_VAR) {
FREE_ZVAL(value);
- } else if (value_op->op_type == IS_CONST) {
+ } else if (value_type == IS_CONST) {
zval_ptr_dtor(&value);
}
FREE_OP(free_value);
return;
}
- Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property_name, value, key TSRMLS_CC);
} else {
/* Note: property_name in this case is really the array index! */
if (!Z_OBJ_HT_P(object)->write_dimension) {
@@ -606,8 +743,8 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval
Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result) && !EG(exception)) {
- AI_SET_PTR(T(result->u.var).var, value);
+ if (retval && !EG(exception)) {
+ *retval = value;
PZVAL_LOCK(value);
}
zval_ptr_dtor(&value);
@@ -624,17 +761,30 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva
}
if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
- Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
+ if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
+ char *tmp = (char *) emalloc(T->str_offset.offset+1+1);
+
+ memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str)+1);
+ Z_STRVAL_P(T->str_offset.str) = tmp;
+ } else {
+ Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
+ }
memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
' ',
T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
+ } else if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
+ char *tmp = (char *) emalloc(Z_STRLEN_P(T->str_offset.str) + 1);
+
+ memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str) + 1);
+ Z_STRVAL_P(T->str_offset.str) = tmp;
}
if (Z_TYPE_P(value) != IS_STRING) {
- zval tmp = *value;
+ zval tmp;
+ ZVAL_COPY_VALUE(&tmp, value);
if (value_type != IS_TMP_VAR) {
zval_copy_ctor(&tmp);
}
@@ -658,92 +808,139 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva
return 1;
}
-static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC)
+
+static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
{
zval *variable_ptr = *variable_ptr_ptr;
zval garbage;
- if (variable_ptr == EG(error_zval_ptr)) {
- if (is_tmp_var) {
- zval_dtor(value);
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
+ Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
+ return variable_ptr;
+ }
+
+ if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
+ EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
+ /* we need to split */
+ Z_DELREF_P(variable_ptr);
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ ALLOC_ZVAL(variable_ptr);
+ INIT_PZVAL_COPY(variable_ptr, value);
+ *variable_ptr_ptr = variable_ptr;
+ return variable_ptr;
+ } else {
+ if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
+ /* nothing to destroy */
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ } else {
+ ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
}
- return EG(uninitialized_zval_ptr);
+ return variable_ptr;
}
+}
- if (Z_TYPE_P(variable_ptr) == IS_OBJECT && Z_OBJ_HANDLER_P(variable_ptr, set)) {
+static inline zval* zend_assign_const_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
+{
+ zval *variable_ptr = *variable_ptr_ptr;
+ zval garbage;
+
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
return variable_ptr;
}
- if (PZVAL_IS_REF(variable_ptr)) {
- if (variable_ptr!=value) {
- zend_uint refcount = Z_REFCOUNT_P(variable_ptr);
-
- garbage = *variable_ptr;
- *variable_ptr = *value;
- Z_SET_REFCOUNT_P(variable_ptr, refcount);
- Z_SET_ISREF_P(variable_ptr);
- if (!is_tmp_var) {
- zendi_zval_copy_ctor(*variable_ptr);
- }
- zendi_zval_dtor(garbage);
- return variable_ptr;
+ if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
+ EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
+ /* we need to split */
+ Z_DELREF_P(variable_ptr);
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ ALLOC_ZVAL(variable_ptr);
+ INIT_PZVAL_COPY(variable_ptr, value);
+ zval_copy_ctor(variable_ptr);
+ *variable_ptr_ptr = variable_ptr;
+ return variable_ptr;
+ } else {
+ if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
+ /* nothing to destroy */
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ } else {
+ ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
}
- } else {
- if (Z_DELREF_P(variable_ptr)==0) {
- if (!is_tmp_var) {
- if (variable_ptr==value) {
- Z_ADDREF_P(variable_ptr);
- } else if (PZVAL_IS_REF(value)) {
- garbage = *variable_ptr;
- *variable_ptr = *value;
- INIT_PZVAL(variable_ptr);
- zval_copy_ctor(variable_ptr);
- zendi_zval_dtor(garbage);
- return variable_ptr;
+ return variable_ptr;
+ }
+}
+
+static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
+{
+ zval *variable_ptr = *variable_ptr_ptr;
+ zval garbage;
+
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
+ Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
+ return variable_ptr;
+ }
+
+ if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
+ if (Z_REFCOUNT_P(variable_ptr)==1) {
+ if (UNEXPECTED(variable_ptr == value)) {
+ return variable_ptr;
+ } else if (EXPECTED(!PZVAL_IS_REF(value))) {
+ Z_ADDREF_P(value);
+ *variable_ptr_ptr = value;
+ if (EXPECTED(variable_ptr != &EG(uninitialized_zval))) {
+ GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
+ zval_dtor(variable_ptr);
+ efree(variable_ptr);
} else {
- Z_ADDREF_P(value);
- *variable_ptr_ptr = value;
- if (variable_ptr != &EG(uninitialized_zval)) {
- GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
- zval_dtor(variable_ptr);
- efree(variable_ptr);
- }
- return value;
+ Z_DELREF_P(variable_ptr);
}
+ return value;
} else {
- garbage = *variable_ptr;
- *variable_ptr = *value;
- INIT_PZVAL(variable_ptr);
- zendi_zval_dtor(garbage);
- return variable_ptr;
+ goto copy_value;
}
} else { /* we need to split */
- GC_ZVAL_CHECK_POSSIBLE_ROOT(*variable_ptr_ptr);
- if (!is_tmp_var) {
- if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
- ALLOC_ZVAL(variable_ptr);
- *variable_ptr_ptr = variable_ptr;
- *variable_ptr = *value;
- Z_SET_REFCOUNT_P(variable_ptr, 1);
- zval_copy_ctor(variable_ptr);
- } else {
- *variable_ptr_ptr = value;
- Z_ADDREF_P(value);
- }
+ Z_DELREF_P(variable_ptr);
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
+ ALLOC_ZVAL(variable_ptr);
+ *variable_ptr_ptr = variable_ptr;
+ INIT_PZVAL_COPY(variable_ptr, value);
+ zval_copy_ctor(variable_ptr);
+ return variable_ptr;
} else {
- ALLOC_ZVAL(*variable_ptr_ptr);
- Z_SET_REFCOUNT_P(value, 1);
- **variable_ptr_ptr = *value;
+ *variable_ptr_ptr = value;
+ Z_ADDREF_P(value);
+ Z_UNSET_ISREF_P(value);
+ return value;
}
}
- Z_UNSET_ISREF_PP(variable_ptr_ptr);
+ } else {
+ if (EXPECTED(variable_ptr != value)) {
+copy_value:
+ if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
+ /* nothing to destroy */
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ } else {
+ ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ ZVAL_COPY_VALUE(variable_ptr, value);
+ zendi_zval_copy_ctor(*variable_ptr);
+ _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
+ }
+ }
+ return variable_ptr;
}
-
- return *variable_ptr_ptr;
}
-
/* Utility Functions for Extensions */
static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
{
@@ -769,9 +966,9 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze
}
-static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, const temp_variable *Ts, int type, const zval *variable TSRMLS_DC)
+static inline HashTable *zend_get_target_symbol_table(int fetch_type TSRMLS_DC)
{
- switch (opline->op2.u.EA.type) {
+ switch (fetch_type) {
case ZEND_FETCH_LOCAL:
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
@@ -794,26 +991,37 @@ static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, con
return NULL;
}
-static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int type TSRMLS_DC)
+static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type TSRMLS_DC)
{
zval **retval;
char *offset_key;
int offset_key_length;
- long index;
+ ulong hval;
switch (dim->type) {
case IS_NULL:
offset_key = "";
offset_key_length = 0;
+ hval = zend_inline_hash_func("", 1);
goto fetch_string_dim;
case IS_STRING:
-
+
offset_key = dim->value.str.val;
offset_key_length = dim->value.str.len;
-
+
+ if (dim_type == IS_CONST) {
+ hval = Z_HASH_P(dim);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(offset_key, offset_key_length+1, hval, goto num_index);
+ if (IS_INTERNED(offset_key)) {
+ hval = INTERNED_HASH(offset_key);
+ } else {
+ hval = zend_hash_func(offset_key, offset_key_length+1);
+ }
+ }
fetch_string_dim:
- if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
+ if (zend_hash_quick_find(ht, offset_key, offset_key_length+1, hval, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
zend_error(E_NOTICE, "Undefined index: %s", offset_key);
@@ -829,39 +1037,39 @@ fetch_string_dim:
zval *new_zval = &EG(uninitialized_zval);
Z_ADDREF_P(new_zval);
- zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_hash_quick_update(ht, offset_key, offset_key_length+1, hval, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
}
}
break;
case IS_DOUBLE:
- index = zend_dval_to_lval(Z_DVAL_P(dim));
+ hval = zend_dval_to_lval(Z_DVAL_P(dim));
goto num_index;
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim));
/* Fall Through */
case IS_BOOL:
case IS_LONG:
- index = Z_LVAL_P(dim);
+ hval = Z_LVAL_P(dim);
num_index:
- if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
+ if (zend_hash_index_find(ht, hval, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE,"Undefined offset: %ld", index);
+ zend_error(E_NOTICE,"Undefined offset: %ld", hval);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined offset: %ld", index);
+ zend_error(E_NOTICE,"Undefined offset: %ld", hval);
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
Z_ADDREF_P(new_zval);
- zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_hash_index_update(ht, hval, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
}
@@ -876,7 +1084,7 @@ num_index:
return retval;
}
-static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
+static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_type, int type TSRMLS_DC)
{
zval *container = *container_ptr;
zval **retval;
@@ -899,7 +1107,7 @@ fetch_from_array:
Z_DELREF_P(new_zval);
}
} else {
- retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
+ retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
}
result->var.ptr_ptr = retval;
PZVAL_LOCK(*retval);
@@ -907,7 +1115,7 @@ fetch_from_array:
break;
case IS_NULL:
- if (container == EG(error_zval_ptr)) {
+ if (container == &EG(error_zval)) {
result->var.ptr_ptr = &EG(error_zval_ptr);
PZVAL_LOCK(EG(error_zval_ptr));
} else if (type != BP_VAR_UNSET) {
@@ -938,13 +1146,22 @@ convert_to_array:
}
if (Z_TYPE_P(dim) != IS_LONG) {
+
switch(Z_TYPE_P(dim)) {
/* case IS_LONG: */
case IS_STRING:
+ if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
+ break;
+ }
+ if (type != BP_VAR_UNSET) {
+ zend_error(E_WARNING, "Illegal string offset '%s'", dim->value.str.val);
+ }
+
+ break;
case IS_DOUBLE:
case IS_NULL:
case IS_BOOL:
- /* do nothing */
+ zend_error(E_NOTICE, "String offset cast occurred");
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -963,8 +1180,7 @@ convert_to_array:
result->str_offset.str = container;
PZVAL_LOCK(container);
result->str_offset.offset = Z_LVAL_P(dim);
- result->var.ptr_ptr = NULL;
- result->var.ptr = NULL;
+ result->str_offset.ptr_ptr = NULL;
return;
}
break;
@@ -975,7 +1191,7 @@ convert_to_array:
} else {
zval *overloaded_result;
- if (dim_is_tmp_var) {
+ if (dim_type == IS_TMP_VAR) {
zval *orig = dim;
MAKE_REAL_ZVAL_PTR(dim);
ZVAL_NULL(orig);
@@ -988,7 +1204,7 @@ convert_to_array:
zval *tmp = overloaded_result;
ALLOC_ZVAL(overloaded_result);
- *overloaded_result = *tmp;
+ ZVAL_COPY_VALUE(overloaded_result, tmp);
zval_copy_ctor(overloaded_result);
Z_UNSET_ISREF_P(overloaded_result);
Z_SET_REFCOUNT_P(overloaded_result, 0);
@@ -1002,9 +1218,9 @@ convert_to_array:
} else {
retval = &EG(error_zval_ptr);
}
- AI_SET_PTR(result->var, *retval);
+ AI_SET_PTR(result, *retval);
PZVAL_LOCK(*retval);
- if (dim_is_tmp_var) {
+ if (dim_type == IS_TMP_VAR) {
zval_ptr_dtor(&dim);
}
}
@@ -1020,8 +1236,8 @@ convert_to_array:
default:
if (type == BP_VAR_UNSET) {
zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
- AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ AI_SET_PTR(result, &EG(uninitialized_zval));
+ PZVAL_LOCK(&EG(uninitialized_zval));
} else {
zend_error(E_WARNING, "Cannot use a scalar value as an array");
result->var.ptr_ptr = &EG(error_zval_ptr);
@@ -1031,7 +1247,7 @@ convert_to_array:
}
}
-static void zend_fetch_dimension_address_read(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
+static void zend_fetch_dimension_address_read(temp_variable *result, zval **container_ptr, zval *dim, int dim_type, int type TSRMLS_DC)
{
zval *container = *container_ptr;
zval **retval;
@@ -1039,54 +1255,66 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
switch (Z_TYPE_P(container)) {
case IS_ARRAY:
- retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
- if (result) {
- AI_SET_PTR(result->var, *retval);
- PZVAL_LOCK(*retval);
- }
+ retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
+ AI_SET_PTR(result, *retval);
+ PZVAL_LOCK(*retval);
return;
- break;
case IS_NULL:
- if (result) {
- AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ AI_SET_PTR(result, &EG(uninitialized_zval));
+ PZVAL_LOCK(&EG(uninitialized_zval));
return;
- break;
case IS_STRING: {
zval tmp;
+ zval *ptr;
if (Z_TYPE_P(dim) != IS_LONG) {
switch(Z_TYPE_P(dim)) {
/* case IS_LONG: */
case IS_STRING:
+ if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
+ break;
+ }
+ if (type != BP_VAR_IS) {
+ zend_error(E_WARNING, "Illegal string offset '%s'", dim->value.str.val);
+ }
+ break;
case IS_DOUBLE:
case IS_NULL:
case IS_BOOL:
- /* do nothing */
+ if (type != BP_VAR_IS) {
+ zend_error(E_NOTICE, "String offset cast occurred");
+ }
break;
default:
zend_error(E_WARNING, "Illegal offset type");
break;
}
- tmp = *dim;
+ ZVAL_COPY_VALUE(&tmp, dim);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
dim = &tmp;
}
- if (result) {
- if ((Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) && type != BP_VAR_IS) {
+
+ ALLOC_ZVAL(ptr);
+ INIT_PZVAL(ptr);
+ Z_TYPE_P(ptr) = IS_STRING;
+
+ if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) {
+ if (type != BP_VAR_IS) {
zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
}
- result->str_offset.str = container;
- PZVAL_LOCK(container);
- result->str_offset.offset = Z_LVAL_P(dim);
- result->var.ptr_ptr = NULL;
- result->var.ptr = NULL;
+ Z_STRVAL_P(ptr) = STR_EMPTY_ALLOC();
+ Z_STRLEN_P(ptr) = 0;
+ } else {
+ Z_STRVAL_P(ptr) = (char*)emalloc(2);
+ Z_STRVAL_P(ptr)[0] = Z_STRVAL_P(container)[Z_LVAL_P(dim)];
+ Z_STRVAL_P(ptr)[1] = 0;
+ Z_STRLEN_P(ptr) = 1;
}
+ AI_SET_PTR(result, ptr);
return;
}
break;
@@ -1097,7 +1325,7 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
} else {
zval *overloaded_result;
- if (dim_is_tmp_var) {
+ if (dim_type == IS_TMP_VAR) {
zval *orig = dim;
MAKE_REAL_ZVAL_PTR(dim);
ZVAL_NULL(orig);
@@ -1105,43 +1333,33 @@ static void zend_fetch_dimension_address_read(temp_variable *result, zval **cont
overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
if (overloaded_result) {
- if (result) {
- AI_SET_PTR(result->var, overloaded_result);
- PZVAL_LOCK(overloaded_result);
- } else if (Z_REFCOUNT_P(overloaded_result) == 0) {
- /* Destroy unused result from offsetGet() magic method */
- Z_SET_REFCOUNT_P(overloaded_result, 1);
- zval_ptr_dtor(&overloaded_result);
- }
+ AI_SET_PTR(result, overloaded_result);
+ PZVAL_LOCK(overloaded_result);
} else if (result) {
- AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ AI_SET_PTR(result, &EG(uninitialized_zval));
+ PZVAL_LOCK(&EG(uninitialized_zval));
}
- if (dim_is_tmp_var) {
+ if (dim_type == IS_TMP_VAR) {
zval_ptr_dtor(&dim);
}
}
return;
- break;
default:
- if (result) {
- AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ AI_SET_PTR(result, &EG(uninitialized_zval));
+ PZVAL_LOCK(&EG(uninitialized_zval));
return;
- break;
}
}
-static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, int type TSRMLS_DC)
+static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, const zend_literal *key, int type TSRMLS_DC)
{
zval *container = *container_ptr;;
if (Z_TYPE_P(container) != IS_OBJECT) {
- if (container == EG(error_zval_ptr)) {
+ if (container == &EG(error_zval)) {
result->var.ptr_ptr = &EG(error_zval_ptr);
- PZVAL_LOCK(*result->var.ptr_ptr);
+ PZVAL_LOCK(EG(error_zval_ptr));
return;
}
@@ -1164,13 +1382,13 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_
}
if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
- zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr TSRMLS_CC);
+ zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, key TSRMLS_CC);
if (NULL == ptr_ptr) {
zval *ptr;
if (Z_OBJ_HT_P(container)->read_property &&
- (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC)) != NULL) {
- AI_SET_PTR(result->var, ptr);
+ (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, key TSRMLS_CC)) != NULL) {
+ AI_SET_PTR(result, ptr);
PZVAL_LOCK(ptr);
} else {
zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
@@ -1180,9 +1398,9 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_
PZVAL_LOCK(*ptr_ptr);
}
} else if (Z_OBJ_HT_P(container)->read_property) {
- zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC);
+ zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, key TSRMLS_CC);
- AI_SET_PTR(result->var, ptr);
+ AI_SET_PTR(result, ptr);
PZVAL_LOCK(ptr);
} else {
zend_error(E_WARNING, "This object doesn't support property references");
@@ -1191,21 +1409,11 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_
}
}
-static inline zend_brk_cont_element* zend_brk_cont(const zval *nest_levels_zval, int array_offset, const zend_op_array *op_array, const temp_variable *Ts TSRMLS_DC)
+static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const temp_variable *Ts TSRMLS_DC)
{
- zval tmp;
- int nest_levels, original_nest_levels;
+ int original_nest_levels = nest_levels;
zend_brk_cont_element *jmp_to;
- if (nest_levels_zval->type != IS_LONG) {
- tmp = *nest_levels_zval;
- zval_copy_ctor(&tmp);
- convert_to_long(&tmp);
- nest_levels = tmp.value.lval;
- } else {
- nest_levels = nest_levels_zval->value.lval;
- }
- original_nest_levels = nest_levels;
do {
if (array_offset==-1) {
zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
@@ -1216,13 +1424,13 @@ static inline zend_brk_cont_element* zend_brk_cont(const zval *nest_levels_zval,
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor(&T(brk_opline->op1.var).var.ptr);
}
break;
case ZEND_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zendi_zval_dtor(T(brk_opline->op1.var).tmp_var);
}
break;
}
@@ -1268,35 +1476,47 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
{
- zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr;
- ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, execute_data_ptr->function_state.function->common.return_reference?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
+ zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr;
+ ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
}
#define ZEND_VM_NEXT_OPCODE() \
CHECK_SYMBOL_TABLES() \
- EX(opline)++; \
+ ZEND_VM_INC_OPCODE(); \
ZEND_VM_CONTINUE()
#define ZEND_VM_SET_OPCODE(new_op) \
CHECK_SYMBOL_TABLES() \
- EX(opline) = new_op
+ OPLINE = new_op
#define ZEND_VM_JMP(new_op) \
- CHECK_SYMBOL_TABLES() \
if (EXPECTED(!EG(exception))) { \
- EX(opline) = new_op; \
+ ZEND_VM_SET_OPCODE(new_op); \
+ } else { \
+ LOAD_OPLINE(); \
} \
ZEND_VM_CONTINUE()
#define ZEND_VM_INC_OPCODE() \
- EX(opline)++
+ OPLINE++
+
+#ifdef __GNUC__
+# define ZEND_VM_GUARD(name) __asm__("#" #name)
+#else
+# define ZEND_VM_GUARD(name)
+#endif
#include "zend_vm_execute.h"
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
{
if (opcode != ZEND_USER_OPCODE) {
- zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
+ if (handler == NULL) {
+ /* restore the original handler */
+ zend_user_opcodes[opcode] = opcode;
+ } else {
+ zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
+ }
zend_user_opcode_handlers[opcode] = handler;
return SUCCESS;
}
@@ -1308,12 +1528,12 @@ ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
return zend_user_opcode_handlers[opcode];
}
-ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
- return get_zval_ptr(node, Ts, should_free, type);
+ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
+ return get_zval_ptr(op_type, node, Ts, should_free, type);
}
-ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
- return get_zval_ptr_ptr(node, Ts, should_free, type);
+ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
+ return get_zval_ptr_ptr(op_type, node, Ts, should_free, type);
}
/*
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index ec82aca3f4..7d427388bd 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -35,16 +35,13 @@ typedef union _temp_variable {
zend_bool fcall_returned_reference;
} var;
struct {
- zval **ptr_ptr;
- zval *ptr;
- zend_bool fcall_returned_reference;
+ zval **ptr_ptr; /* shared with var.ptr_ptr */
zval *str;
zend_uint offset;
} str_offset;
struct {
- zval **ptr_ptr;
- zval *ptr;
- zend_bool fcall_returned_reference;
+ zval **ptr_ptr; /* shared with var.ptr_ptr */
+ zval *ptr; /* shared with var.ptr */
HashPointer fe_pos;
} fe;
zend_class_entry *class_entry;
@@ -62,7 +59,7 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC);
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
ZEND_API int zend_is_true(zval *op);
#define safe_free_zval_ptr(p) safe_free_zval_ptr_rel(p ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
-static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+static zend_always_inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
TSRMLS_FETCH();
@@ -71,13 +68,37 @@ static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LI
}
}
ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
-ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
+ZEND_API int zend_lookup_class_ex(const char *name, int name_length, const zend_literal *key, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
-static inline int i_zend_is_true(zval *op)
+ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC);
+ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
+
+static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC)
+{
+ if (!Z_DELREF_P(zval_ptr)) {
+ TSRMLS_FETCH();
+
+ if (zval_ptr != &EG(uninitialized_zval)) {
+ GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
+ zval_dtor(zval_ptr);
+ efree_rel(zval_ptr);
+ }
+ } else {
+ TSRMLS_FETCH();
+
+ if (Z_REFCOUNT_P(zval_ptr) == 1) {
+ Z_UNSET_ISREF_P(zval_ptr);
+ }
+
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(zval_ptr);
+ }
+}
+
+static zend_always_inline int i_zend_is_true(zval *op)
{
int result;
@@ -140,7 +161,7 @@ ZEND_API int zval_update_constant_no_inline_change(zval **pp, void *arg TSRMLS_D
ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC);
/* dedicated Zend executor functions - do not use! */
-#define ZEND_VM_STACK_PAGE_SIZE ((64 * 1024) - 64)
+#define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
struct _zend_vm_stack {
void **top;
@@ -159,7 +180,7 @@ struct _zend_vm_stack {
} \
} while (0)
-static inline zend_vm_stack zend_vm_stack_new_page(int count) {
+static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(void*) * count);
page->top = ZEND_VM_STACK_ELEMETS(page);
@@ -168,12 +189,12 @@ static inline zend_vm_stack zend_vm_stack_new_page(int count) {
return page;
}
-static inline void zend_vm_stack_init(TSRMLS_D)
+static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
{
EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
}
-static inline void zend_vm_stack_destroy(TSRMLS_D)
+static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
{
zend_vm_stack stack = EG(argument_stack);
@@ -184,30 +205,30 @@ static inline void zend_vm_stack_destroy(TSRMLS_D)
}
}
-static inline void zend_vm_stack_extend(int count TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
{
zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
p->prev = EG(argument_stack);
EG(argument_stack) = p;
}
-static inline void **zend_vm_stack_top(TSRMLS_D)
+static zend_always_inline void **zend_vm_stack_top(TSRMLS_D)
{
return EG(argument_stack)->top;
}
-static inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
{
ZEND_VM_STACK_GROW_IF_NEEDED(1);
*(EG(argument_stack)->top++) = ptr;
}
-static inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC)
{
*(EG(argument_stack)->top++) = ptr;
}
-static inline void *zend_vm_stack_pop(TSRMLS_D)
+static zend_always_inline void *zend_vm_stack_pop(TSRMLS_D)
{
void *el = *(--EG(argument_stack)->top);
@@ -219,7 +240,7 @@ static inline void *zend_vm_stack_pop(TSRMLS_D)
return el;
}
-static inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
+static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
{
void *ret;
@@ -248,7 +269,7 @@ static inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
return ret;
}
-static inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
{
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
zend_vm_stack p = EG(argument_stack);
@@ -260,7 +281,7 @@ static inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC)
}
}
-static inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
{
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) {
zend_vm_stack p = EG(argument_stack);
@@ -278,7 +299,7 @@ static inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
}
}
-static inline void** zend_vm_stack_push_args(int count TSRMLS_DC)
+static zend_always_inline void** zend_vm_stack_push_args(int count TSRMLS_DC)
{
if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count) ||
@@ -307,7 +328,7 @@ static inline void** zend_vm_stack_push_args(int count TSRMLS_DC)
return EG(argument_stack)->top++;
}
-static inline void zend_vm_stack_clear_multiple(TSRMLS_D)
+static zend_always_inline void zend_vm_stack_clear_multiple(TSRMLS_D)
{
void **p = EG(argument_stack)->top - 1;
int delete_count = (int)(zend_uintptr_t) *p;
@@ -315,12 +336,12 @@ static inline void zend_vm_stack_clear_multiple(TSRMLS_D)
while (--delete_count>=0) {
zval *q = *(zval **)(--p);
*p = NULL;
- zval_ptr_dtor(&q);
+ i_zval_ptr_dtor(q ZEND_FILE_LINE_CC);
}
zend_vm_stack_free_int(p TSRMLS_CC);
}
-static inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
+static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
{
void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments;
int arg_count = (int)(zend_uintptr_t) *p;
@@ -331,7 +352,7 @@ static inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
return (zval**)p - arg_count + requested_arg - 1;
}
-static inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **object, zend_function **fbc)
+static zend_always_inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **object, zend_function **fbc)
{
void *a, *b;
@@ -341,7 +362,7 @@ static inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **obje
*fbc = (zend_function *) b;
}
-static inline void zend_arg_types_stack_3_pop(zend_ptr_stack *stack, zend_class_entry **called_scope, zval **object, zend_function **fbc)
+static zend_always_inline void zend_arg_types_stack_3_pop(zend_ptr_stack *stack, zend_class_entry **called_scope, zval **object, zend_function **fbc)
{
void *a, *b, *c;
@@ -356,9 +377,9 @@ void execute_new_code(TSRMLS_D);
/* services */
-ZEND_API char *get_active_class_name(char **space TSRMLS_DC);
-ZEND_API char *get_active_function_name(TSRMLS_D);
-ZEND_API char *zend_get_executed_filename(TSRMLS_D);
+ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC);
+ZEND_API const char *get_active_function_name(TSRMLS_D);
+ZEND_API const char *zend_get_executed_filename(TSRMLS_D);
ZEND_API uint zend_get_executed_lineno(TSRMLS_D);
ZEND_API zend_bool zend_is_executing(TSRMLS_D);
@@ -366,6 +387,7 @@ ZEND_API void zend_set_timeout(long seconds, int reset_signals);
ZEND_API void zend_unset_timeout(TSRMLS_D);
ZEND_API void zend_timeout(int dummy);
ZEND_API zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
+ZEND_API zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC);
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
#ifdef ZEND_WIN32
@@ -404,11 +426,28 @@ typedef struct _zend_free_op {
/* int is_var; */
} zend_free_op;
-ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
-ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
+ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
+ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC);
ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
+#define CACHED_PTR(num) \
+ EG(active_op_array)->run_time_cache[(num)]
+
+#define CACHE_PTR(num, ptr) do { \
+ EG(active_op_array)->run_time_cache[(num)] = (ptr); \
+ } while (0)
+
+#define CACHED_POLYMORPHIC_PTR(num, ce) \
+ ((EG(active_op_array)->run_time_cache[(num)] == (ce)) ? \
+ EG(active_op_array)->run_time_cache[(num) + 1] : \
+ NULL)
+
+#define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
+ EG(active_op_array)->run_time_cache[(num)] = (ce); \
+ EG(active_op_array)->run_time_cache[(num) + 1] = (ptr); \
+ } while (0)
+
END_EXTERN_C()
#endif /* ZEND_EXECUTE_H */
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 47a37d8b9a..1deee2a86c 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -110,7 +110,7 @@ static int clean_non_persistent_function(zend_function *function TSRMLS_DC) /* {
static int clean_non_persistent_function_full(zend_function *function TSRMLS_DC) /* {{{ */
{
- return (function->type != ZEND_INTERNAL_FUNCTION);
+ return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
}
/* }}} */
@@ -122,7 +122,7 @@ static int clean_non_persistent_class(zend_class_entry **ce TSRMLS_DC) /* {{{ */
static int clean_non_persistent_class_full(zend_class_entry **ce TSRMLS_DC) /* {{{ */
{
- return ((*ce)->type != ZEND_INTERNAL_CLASS);
+ return ((*ce)->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
}
/* }}} */
@@ -159,16 +159,6 @@ void init_executor(TSRMLS_D) /* {{{ */
zend_vm_stack_push((void *) NULL TSRMLS_CC);
zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
- {
- zval *globals;
-
- ALLOC_ZVAL(globals);
- Z_SET_REFCOUNT_P(globals, 1);
- Z_SET_ISREF_P(globals);
- Z_TYPE_P(globals) = IS_ARRAY;
- Z_ARRVAL_P(globals) = &EG(symbol_table);
- zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL);
- }
EG(active_symbol_table) = &EG(symbol_table);
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
@@ -204,6 +194,7 @@ void init_executor(TSRMLS_D) /* {{{ */
EG(active_op_array) = NULL;
EG(active) = 1;
+ EG(start_op) = NULL;
}
/* }}} */
@@ -292,10 +283,12 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
* not contain objects and thus are not probelmatic */
if (EG(full_tables_cleanup)) {
zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
+ zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
} else {
zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
+ zend_hash_reverse_apply(EG(class_table), (apply_func_t) zend_cleanup_user_class_data TSRMLS_CC);
+ zend_cleanup_internal_classes(TSRMLS_C);
}
- zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
} zend_end_try();
zend_try {
@@ -305,8 +298,8 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
/* Destroy all op arrays */
if (EG(full_tables_cleanup)) {
- zend_hash_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC);
- zend_hash_apply(EG(class_table), (apply_func_t) clean_non_persistent_class_full TSRMLS_CC);
+ zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC);
+ zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class_full TSRMLS_CC);
} else {
zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function TSRMLS_CC);
zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class TSRMLS_CC);
@@ -348,7 +341,7 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
/* }}} */
/* return class name and "::" or "". */
-ZEND_API char *get_active_class_name(char **space TSRMLS_DC) /* {{{ */
+ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */
{
if (!zend_is_executing(TSRMLS_C)) {
if (space) {
@@ -376,14 +369,14 @@ ZEND_API char *get_active_class_name(char **space TSRMLS_DC) /* {{{ */
}
/* }}} */
-ZEND_API char *get_active_function_name(TSRMLS_D) /* {{{ */
+ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
{
if (!zend_is_executing(TSRMLS_C)) {
return NULL;
}
switch (EG(current_execute_data)->function_state.function->type) {
case ZEND_USER_FUNCTION: {
- char *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
+ const char *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
if (function_name) {
return function_name;
@@ -401,7 +394,7 @@ ZEND_API char *get_active_function_name(TSRMLS_D) /* {{{ */
}
/* }}} */
-ZEND_API char *zend_get_executed_filename(TSRMLS_D) /* {{{ */
+ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */
{
if (EG(active_op_array)) {
return EG(active_op_array)->filename;
@@ -433,28 +426,26 @@ ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */
ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
{
- zval *zv = *zval_ptr;
-
#if DEBUG_ZEND>=2
printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1);
#endif
- Z_DELREF_P(zv);
- if (Z_REFCOUNT_P(zv) == 0) {
+ Z_DELREF_PP(zval_ptr);
+ if (Z_REFCOUNT_PP(zval_ptr) == 0) {
TSRMLS_FETCH();
- if (zv != &EG(uninitialized_zval)) {
- GC_REMOVE_ZVAL_FROM_BUFFER(zv);
- zval_dtor(zv);
- efree_rel(zv);
+ if (*zval_ptr != &EG(uninitialized_zval)) {
+ GC_REMOVE_ZVAL_FROM_BUFFER(*zval_ptr);
+ zval_dtor(*zval_ptr);
+ efree_rel(*zval_ptr);
}
} else {
TSRMLS_FETCH();
- if (Z_REFCOUNT_P(zv) == 1) {
- Z_UNSET_ISREF_P(zv);
+ if (Z_REFCOUNT_PP(zval_ptr) == 1) {
+ Z_UNSET_ISREF_PP(zval_ptr);
}
- GC_ZVAL_CHECK_POSSIBLE_ROOT(zv);
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(*zval_ptr);
}
}
/* }}} */
@@ -524,12 +515,12 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
char *actual = Z_STRVAL_P(p);
- if ((colon = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
+ if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
if (inline_change) {
colon = estrndup(colon, Z_STRLEN_P(p));
- efree(Z_STRVAL_P(p));
+ str_efree(Z_STRVAL_P(p));
Z_STRVAL_P(p) = colon;
} else {
Z_STRVAL_P(p) = colon + 1;
@@ -565,12 +556,12 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
if (fix_save) {
save--;
}
- if (inline_change) {
+ if (inline_change && !IS_INTERNED(save)) {
efree(save);
}
save = NULL;
}
- if (inline_change && save && save != actual) {
+ if (inline_change && save && save != actual && !IS_INTERNED(save)) {
efree(save);
}
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
@@ -624,8 +615,9 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
continue;
}
if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
- char *actual, *save = str_index;
- if ((colon = zend_memrchr(str_index, ':', str_index_len - 3))) {
+ char *actual;
+ const char *save = str_index;
+ if ((colon = (char*)zend_memrchr(str_index, ':', str_index_len - 3))) {
zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
str_index_len -= ((colon - str_index) + 1);
str_index = colon;
@@ -772,6 +764,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_class_entry *called_scope = NULL;
zval *current_this;
zend_execute_data execute_data;
+ zend_fcall_info_cache fci_cache_local;
*fci->retval_ptr_ptr = NULL;
@@ -806,7 +799,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}
if (!fci_cache || !fci_cache->initialized) {
- zend_fcall_info_cache fci_cache_local;
char *callable_name;
char *error = NULL;
@@ -861,23 +853,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
for (i=0; i<fci->param_count; i++) {
zval *param;
- if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION
- && (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0
- && !ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)
- && PZVAL_IS_REF(*fci->params[i])) {
- ALLOC_ZVAL(param);
- *param = **(fci->params[i]);
- INIT_PZVAL(param);
- zval_copy_ctor(param);
- } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)
- && !PZVAL_IS_REF(*fci->params[i])) {
-
- if (Z_REFCOUNT_PP(fci->params[i]) > 1) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
+ if (!PZVAL_IS_REF(*fci->params[i]) && Z_REFCOUNT_PP(fci->params[i]) > 1) {
zval *new_zval;
if (fci->no_separation &&
!ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
- if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == EG(argument_stack)->top)) {
+ if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
/* hack to clean up the stack */
zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC);
zend_vm_stack_clear_multiple(TSRMLS_C);
@@ -901,6 +883,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
Z_ADDREF_PP(fci->params[i]);
Z_SET_ISREF_PP(fci->params[i]);
param = *fci->params[i];
+ } else if (PZVAL_IS_REF(*fci->params[i]) &&
+ /* don't separate references for __call */
+ (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
+ ALLOC_ZVAL(param);
+ *param = **(fci->params[i]);
+ INIT_PZVAL(param);
+ zval_copy_ctor(param);
} else if (*fci->params[i] != &EG(uninitialized_zval)) {
Z_ADDREF_PP(fci->params[i]);
param = *fci->params[i];
@@ -1015,7 +1004,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}
if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- efree(EX(function_state).function->common.function_name);
+ efree((char*)EX(function_state).function->common.function_name);
}
efree(EX(function_state).function);
@@ -1041,7 +1030,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}
/* }}} */
-ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
+ZEND_API int zend_lookup_class_ex(const char *name, int name_length, const zend_literal *key, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
{
zval **args[1];
zval autoload_function;
@@ -1056,23 +1045,31 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
ulong hash;
ALLOCA_FLAG(use_heap)
- if (name == NULL || !name_length) {
- return FAILURE;
- }
+ if (key) {
+ lc_name = Z_STRVAL(key->constant);
+ lc_length = Z_STRLEN(key->constant) + 1;
+ hash = key->hash_value;
+ } else {
+ if (name == NULL || !name_length) {
+ return FAILURE;
+ }
- lc_free = lc_name = do_alloca(name_length + 1, use_heap);
- zend_str_tolower_copy(lc_name, name, name_length);
- lc_length = name_length + 1;
+ lc_free = lc_name = do_alloca(name_length + 1, use_heap);
+ zend_str_tolower_copy(lc_name, name, name_length);
+ lc_length = name_length + 1;
- if (lc_name[0] == '\\') {
- lc_name += 1;
- lc_length -= 1;
- }
+ if (lc_name[0] == '\\') {
+ lc_name += 1;
+ lc_length -= 1;
+ }
- hash = zend_inline_hash_func(lc_name, lc_length);
+ hash = zend_inline_hash_func(lc_name, lc_length);
+ }
if (zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce) == SUCCESS) {
- free_alloca(lc_free, use_heap);
+ if (!key) {
+ free_alloca(lc_free, use_heap);
+ }
return SUCCESS;
}
@@ -1080,7 +1077,9 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
* (doesn't impact fuctionality of __autoload()
*/
if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
- free_alloca(lc_free, use_heap);
+ if (!key) {
+ free_alloca(lc_free, use_heap);
+ }
return FAILURE;
}
@@ -1090,7 +1089,9 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
}
if (zend_hash_quick_add(EG(in_autoload), lc_name, lc_length, hash, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
- free_alloca(lc_free, use_heap);
+ if (!key) {
+ free_alloca(lc_free, use_heap);
+ }
return FAILURE;
}
@@ -1136,20 +1137,19 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
zval_ptr_dtor(&retval_ptr);
}
- if (retval == FAILURE) {
+ if (retval == SUCCESS) {
+ retval = zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce);
+ }
+ if (!key) {
free_alloca(lc_free, use_heap);
- return FAILURE;
}
-
- retval = zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce);
- free_alloca(lc_free, use_heap);
return retval;
}
/* }}} */
ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
{
- return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC);
+ return zend_lookup_class_ex(name, name_length, NULL, 1, ce TSRMLS_CC);
}
/* }}} */
@@ -1195,7 +1195,13 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
}
CG(interactive) = 0;
- zend_execute(new_op_array TSRMLS_CC);
+ zend_try {
+ zend_execute(new_op_array TSRMLS_CC);
+ } zend_catch {
+ destroy_op_array(new_op_array TSRMLS_CC);
+ efree(new_op_array);
+ zend_bailout();
+ } zend_end_try();
CG(interactive) = orig_interactive;
if (local_retval_ptr) {
@@ -1259,7 +1265,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
int orig_interactive;
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
- || CG(active_op_array)->backpatch_count>0
+ || CG(context).backpatch_count>0
|| CG(active_op_array)->function_name
|| CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
return;
@@ -1267,41 +1273,40 @@ void execute_new_code(TSRMLS_D) /* {{{ */
ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC);
ret_opline->opcode = ZEND_RETURN;
- ret_opline->op1.op_type = IS_CONST;
- INIT_ZVAL(ret_opline->op1.u.constant);
+ ret_opline->op1_type = IS_CONST;
+ ret_opline->op1.constant = zend_add_literal(CG(active_op_array), &EG(uninitialized_zval) TSRMLS_CC);
SET_UNUSED(ret_opline->op2);
- if (!CG(active_op_array)->start_op) {
- CG(active_op_array)->start_op = CG(active_op_array)->opcodes;
+ if (!EG(start_op)) {
+ EG(start_op) = CG(active_op_array)->opcodes;
}
- opline=CG(active_op_array)->start_op;
+ opline=EG(start_op);
end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
while (opline<end) {
- if (opline->op1.op_type == IS_CONST) {
- Z_SET_ISREF(opline->op1.u.constant);
- Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */
+ if (opline->op1_type == IS_CONST) {
+ opline->op1.zv = &CG(active_op_array)->literals[opline->op1.constant].constant;
}
- if (opline->op2.op_type == IS_CONST) {
- Z_SET_ISREF(opline->op2.u.constant);
- Z_SET_REFCOUNT(opline->op2.u.constant, 2);
+ if (opline->op2_type == IS_CONST) {
+ opline->op2.zv = &CG(active_op_array)->literals[opline->op2.constant].constant;
}
switch (opline->opcode) {
case ZEND_GOTO:
- if (Z_TYPE(opline->op2.u.constant) != IS_LONG) {
+ if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
zend_resolve_goto_label(CG(active_op_array), opline, 1 TSRMLS_CC);
}
/* break omitted intentionally */
case ZEND_JMP:
- opline->op1.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.u.opline_num];
+ opline->op1.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.opline_num];
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
- opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num];
+ case ZEND_JMP_SET_VAR:
+ opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num];
break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline);
@@ -1322,7 +1327,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
}
CG(active_op_array)->last -= 1; /* get rid of that ZEND_RETURN */
- CG(active_op_array)->start_op = CG(active_op_array)->opcodes+CG(active_op_array)->last;
+ EG(start_op) = CG(active_op_array)->opcodes+CG(active_op_array)->last;
}
/* }}} */
@@ -1331,6 +1336,15 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */
TSRMLS_FETCH();
if (zend_on_timeout) {
+#ifdef ZEND_SIGNALS
+ /*
+ We got here because we got a timeout signal, so we are in a signal handler
+ at this point. However, we want to be able to timeout any user-supplied
+ shutdown functions, so pretend we are not in a signal handler while we are
+ calling these
+ */
+ SIGG(running) = 0;
+#endif
zend_on_timeout(EG(timeout_seconds) TSRMLS_CC);
}
@@ -1472,7 +1486,7 @@ void zend_set_timeout(long seconds, int reset_signals) /* {{{ */
# ifdef HAVE_SETITIMER
{
struct itimerval t_r; /* timeout requested */
- sigset_t sigset;
+ int signo;
if(seconds) {
t_r.it_value.tv_sec = seconds;
@@ -1481,25 +1495,27 @@ void zend_set_timeout(long seconds, int reset_signals) /* {{{ */
# ifdef __CYGWIN__
setitimer(ITIMER_REAL, &t_r, NULL);
}
- if(reset_signals) {
- signal(SIGALRM, zend_timeout);
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGALRM);
- }
+ signo = SIGALRM;
# else
setitimer(ITIMER_PROF, &t_r, NULL);
}
- if(reset_signals) {
- signal(SIGPROF, zend_timeout);
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGPROF);
- }
+ signo = SIGPROF;
# endif
- if(reset_signals) {
+
+ if (reset_signals) {
+# ifdef ZEND_SIGNALS
+ zend_signal(signo, zend_timeout TSRMLS_CC);
+# else
+ sigset_t sigset;
+
+ signal(signo, zend_timeout);
+ sigemptyset(&sigset);
+ sigaddset(&sigset, signo);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+# endif
}
}
-# endif
+# endif /* HAVE_SETITIMER */
#endif
}
/* }}} */
@@ -1565,11 +1581,36 @@ check_fetch_type:
break;
}
- if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) {
+ if (zend_lookup_class_ex(class_name, class_name_len, NULL, use_autoload, &pce TSRMLS_CC) == FAILURE) {
if (use_autoload) {
if (!silent && !EG(exception)) {
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
zend_error(E_ERROR, "Interface '%s' not found", class_name);
+ } else if (fetch_type == ZEND_FETCH_CLASS_TRAIT) {
+ zend_error(E_ERROR, "Trait '%s' not found", class_name);
+ } else {
+ zend_error(E_ERROR, "Class '%s' not found", class_name);
+ }
+ }
+ }
+ return NULL;
+ }
+ return *pce;
+}
+/* }}} */
+
+zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_name_len, const zend_literal *key, int fetch_type TSRMLS_DC) /* {{{ */
+{
+ zend_class_entry **pce;
+ int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
+
+ if (zend_lookup_class_ex(class_name, class_name_len, key, use_autoload, &pce TSRMLS_CC) == FAILURE) {
+ if (use_autoload) {
+ if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) {
+ if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
+ zend_error(E_ERROR, "Interface '%s' not found", class_name);
+ } else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
+ zend_error(E_ERROR, "Trait '%s' not found", class_name);
} else {
zend_error(E_ERROR, "Class '%s' not found", class_name);
}
@@ -1653,10 +1694,32 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */
}
/* }}} */
-ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /* {{{ */
+ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */
+{
+ if (zend_hash_quick_del(ht, name, name_len, hash_value) == SUCCESS) {
+ name_len--;
+ while (ex && ex->symbol_table == ht) {
+ int i;
+
+ if (ex->op_array) {
+ for (i = 0; i < ex->op_array->last_var; i++) {
+ if (ex->op_array->vars[i].hash_value == hash_value &&
+ ex->op_array->vars[i].name_len == name_len &&
+ !memcmp(ex->op_array->vars[i].name, name, name_len)) {
+ ex->CVs[i] = NULL;
+ break;
+ }
+ }
+ }
+ ex = ex->prev_execute_data;
+ }
+ }
+}
+/* }}} */
+
+ZEND_API int zend_delete_global_variable_ex(const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */
{
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(name, name_len + 1);
if (zend_hash_quick_exists(&EG(symbol_table), name, name_len + 1, hash_value)) {
for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
@@ -1679,6 +1742,12 @@ ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /*
}
/* }}} */
+ZEND_API int zend_delete_global_variable(const char *name, int name_len TSRMLS_DC) /* {{{ */
+{
+ return zend_delete_global_variable_ex(name, name_len, zend_inline_hash_func(name, name_len + 1) TSRMLS_CC);
+}
+/* }}} */
+
ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
{
zend_uint i;
@@ -1702,7 +1771,7 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EG(active_symbol_table));
- zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_init(EG(active_symbol_table), ex->op_array->last_var, NULL, ZVAL_PTR_DTOR, 0);
/*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
}
ex->symbol_table = EG(active_symbol_table);
diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h
index 46137133fd..b3f510ac12 100644
--- a/Zend/zend_extensions.h
+++ b/Zend/zend_extensions.h
@@ -28,7 +28,7 @@
/* The first number is the engine version and the rest is the date.
* This way engine 2/3 API no. is always greater than engine 1 API no..
*/
-#define ZEND_EXTENSION_API_NO 220090626
+#define ZEND_EXTENSION_API_NO 220100525
typedef struct _zend_extension_version_info {
int zend_extension_api_no;
diff --git a/Zend/zend_fast_cache.h b/Zend/zend_fast_cache.h
deleted file mode 100644
index 51f70296ca..0000000000
--- a/Zend/zend_fast_cache.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | Zend Engine |
- +----------------------------------------------------------------------+
- | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.zend.com/license/2_00.txt. |
- | If you did not receive a copy of the Zend license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@zend.com so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Andi Gutmans <andi@zend.com> |
- | Zeev Suraski <zeev@zend.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-#if 0
-#ifndef ZEND_FAST_CACHE_H
-#define ZEND_FAST_CACHE_H
-
-#ifndef ZEND_ENABLE_FAST_CACHE
-# if ZEND_DEBUG
-# define ZEND_ENABLE_FAST_CACHE 0
-# else
-# define ZEND_ENABLE_FAST_CACHE 0
-# endif
-#endif
-
-typedef struct _zend_fast_cache_list_entry {
- struct _zend_fast_cache_list_entry *next;
-} zend_fast_cache_list_entry;
-
-#define MAX_FAST_CACHE_TYPES 4
-
-
-#define ZVAL_CACHE_LIST 0
-#define HASHTABLE_CACHE_LIST 1
-
-#if ZEND_ENABLE_FAST_CACHE
-
-
-#include "zend_globals.h"
-#include "zend_globals_macros.h"
-#include "zend_alloc.h"
-
-
-#if ZEND_DEBUG
-# define RECORD_ZVAL_CACHE_HIT(fc_type) AG(fast_cache_stats)[fc_type][1]++;
-# define RECORD_ZVAL_CACHE_MISS(fc_type) AG(fast_cache_stats)[fc_type][0]++;
-#else
-# define RECORD_ZVAL_CACHE_HIT(fc_type)
-# define RECORD_ZVAL_CACHE_MISS(fc_type)
-#endif
-
-
-#define ZEND_FAST_ALLOC(p, type, fc_type) \
- { \
- TSRMLS_FETCH(); \
- \
- if (((p) = (type *) AG(fast_cache_list_head)[fc_type])) { \
- AG(fast_cache_list_head)[fc_type] = ((zend_fast_cache_list_entry *) AG(fast_cache_list_head)[fc_type])->next; \
- RECORD_ZVAL_CACHE_HIT(fc_type); \
- } else { \
- (p) = (type *) emalloc(sizeof(type)); \
- RECORD_ZVAL_CACHE_MISS(fc_type); \
- } \
- }
-
-
-#define ZEND_FAST_FREE(p, fc_type) \
- { \
- TSRMLS_FETCH(); \
- \
- ((zend_fast_cache_list_entry *) (p))->next = (zend_fast_cache_list_entry *) AG(fast_cache_list_head)[fc_type]; \
- AG(fast_cache_list_head)[fc_type] = (zend_fast_cache_list_entry *) (p); \
- }
-
-#define ZEND_FAST_ALLOC_REL(p, type, fc_type) \
- ZEND_FAST_ALLOC(p, type, fc_type)
-
-#define ZEND_FAST_FREE_REL(p, fc_type) \
- ZEND_FAST_FREE(p, fc_type)
-
-
-#else /* !ZEND_ENABLE_FAST_CACHE */
-
-#define ZEND_FAST_ALLOC(p, type, fc_type) \
- (p) = (type *) emalloc(sizeof(type))
-
-#define ZEND_FAST_FREE(p, fc_type) \
- efree(p)
-
-#define ZEND_FAST_ALLOC_REL(p, type, fc_type) \
- (p) = (type *) emalloc_rel(sizeof(type))
-
-#define ZEND_FAST_FREE_REL(p, fc_type) \
- efree_rel(p)
-
-#endif /* ZEND_ENABLE_FAST_CACHE */
-
-
-
-/* fast cache for zval's */
-#define ALLOC_ZVAL(z) \
- ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)
-
-#define FREE_ZVAL(z) \
- ZEND_FAST_FREE(z, ZVAL_CACHE_LIST)
-
-#define ALLOC_ZVAL_REL(z) \
- ZEND_FAST_ALLOC_REL(z, zval, ZVAL_CACHE_LIST)
-
-#define FREE_ZVAL_REL(z) \
- ZEND_FAST_FREE_REL(z, ZVAL_CACHE_LIST)
-
-/* fast cache for HashTables */
-#define ALLOC_HASHTABLE(ht) \
- ZEND_FAST_ALLOC(ht, HashTable, HASHTABLE_CACHE_LIST)
-
-#define FREE_HASHTABLE(ht) \
- ZEND_FAST_FREE(ht, HASHTABLE_CACHE_LIST)
-
-#define ALLOC_HASHTABLE_REL(ht) \
- ZEND_FAST_ALLOC_REL(ht, HashTable, HASHTABLE_CACHE_LIST)
-
-#define FREE_HASHTABLE_REL(ht) \
- ZEND_FAST_FREE_REL(ht, HASHTABLE_CACHE_LIST)
-
-#endif /* ZEND_FAST_CACHE_H */
-#endif
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- */
diff --git a/Zend/zend_float.c b/Zend/zend_float.c
index b7791fb7f2..75e42efd60 100644
--- a/Zend/zend_float.c
+++ b/Zend/zend_float.c
@@ -27,16 +27,13 @@ ZEND_API void zend_init_fpu(TSRMLS_D) /* {{{ */
#if XPFPA_HAVE_CW
XPFPA_DECLARE
- if (!EG(saved_fpu_cw)) {
- EG(saved_fpu_cw) = emalloc(sizeof(XPFPA_CW_DATATYPE));
+ if (!EG(saved_fpu_cw_ptr)) {
+ EG(saved_fpu_cw_ptr) = (void*)&EG(saved_fpu_cw);
}
- XPFPA_STORE_CW(EG(saved_fpu_cw));
+ XPFPA_STORE_CW(EG(saved_fpu_cw_ptr));
XPFPA_SWITCH_DOUBLE();
#else
- if (EG(saved_fpu_cw)) {
- efree(EG(saved_fpu_cw));
- }
- EG(saved_fpu_cw) = NULL;
+ EG(saved_fpu_cw_ptr) = NULL;
#endif
}
/* }}} */
@@ -44,14 +41,11 @@ ZEND_API void zend_init_fpu(TSRMLS_D) /* {{{ */
ZEND_API void zend_shutdown_fpu(TSRMLS_D) /* {{{ */
{
#if XPFPA_HAVE_CW
- if (EG(saved_fpu_cw)) {
- XPFPA_RESTORE_CW(EG(saved_fpu_cw));
+ if (EG(saved_fpu_cw_ptr)) {
+ XPFPA_RESTORE_CW(EG(saved_fpu_cw_ptr));
}
#endif
- if (EG(saved_fpu_cw)) {
- efree(EG(saved_fpu_cw));
- EG(saved_fpu_cw) = NULL;
- }
+ EG(saved_fpu_cw_ptr) = NULL;
}
/* }}} */
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 07031f066a..84a99c169a 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -194,7 +194,7 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
{
struct _store_object *obj;
- if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_properties == NULL ||
+ if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_gc == NULL ||
EG(objects_store).object_buckets == NULL)) {
return;
}
@@ -275,15 +275,35 @@ tail_call:
GC_ZVAL_SET_BLACK(pz);
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ zend_object_get_gc_t get_gc;
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
obj->refcount++;
if (GC_GET_COLOR(obj->buffered) != GC_BLACK) {
GC_SET_BLACK(obj->buffered);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ while (n > 0 && !table[n-1]) n--;
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+ pz->refcount__gc++;
+ }
+ if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ zval_scan_black(pz TSRMLS_CC);
+ }
+ }
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
@@ -313,12 +333,27 @@ tail_call:
static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC)
{
Bucket *p;
+ zend_object_get_gc_t get_gc;
GC_SET_BLACK(obj->buffered);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+ pz->refcount__gc++;
+ }
+ if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+ zval_scan_black(pz TSRMLS_CC);
+ }
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
@@ -346,6 +381,7 @@ tail_call:
GC_ZVAL_SET_COLOR(pz, GC_GREY);
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ zend_object_get_gc_t get_gc;
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
obj->refcount--;
@@ -353,9 +389,26 @@ tail_call:
GC_BENCH_INC(zobj_marked_grey);
GC_SET_COLOR(obj->buffered, GC_GREY);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ while (n > 0 && !table[n-1]) n--;
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+ pz->refcount__gc--;
+ }
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ zval_mark_grey(pz TSRMLS_CC);
+ }
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
@@ -386,14 +439,27 @@ tail_call:
static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC)
{
Bucket *p;
+ zend_object_get_gc_t get_gc;
if (GC_GET_COLOR(obj->buffered) != GC_GREY) {
GC_BENCH_INC(zobj_marked_grey);
GC_SET_COLOR(obj->buffered, GC_GREY);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+ pz->refcount__gc--;
+ }
+ zval_mark_grey(pz TSRMLS_CC);
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
@@ -442,7 +508,7 @@ static void gc_mark_roots(TSRMLS_D)
}
}
-static int zval_scan(zval *pz TSRMLS_DC)
+static void zval_scan(zval *pz TSRMLS_DC)
{
Bucket *p;
@@ -454,6 +520,7 @@ tail_call:
} else {
GC_ZVAL_SET_COLOR(pz, GC_WHITE);
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ zend_object_get_gc_t get_gc;
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
@@ -462,10 +529,24 @@ tail_call:
} else {
GC_SET_COLOR(obj->buffered, GC_WHITE);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
- return 0;
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ while (n > 0 && !table[n-1]) n--;
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ zval_scan(pz TSRMLS_CC);
+ }
+ }
+ }
+ if (!props) {
+ return;
}
p = props->pListHead;
}
@@ -489,12 +570,12 @@ tail_call:
p = p->pListNext;
}
}
- return 0;
}
static void zobj_scan(zval *pz TSRMLS_DC)
{
Bucket *p;
+ zend_object_get_gc_t get_gc;
if (EG(objects_store).object_buckets) {
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
@@ -505,9 +586,18 @@ static void zobj_scan(zval *pz TSRMLS_DC)
} else {
GC_SET_COLOR(obj->buffered, GC_WHITE);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ zval_scan(pz TSRMLS_CC);
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
@@ -550,15 +640,41 @@ tail_call:
GC_ZVAL_SET_BLACK(pz);
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ zend_object_get_gc_t get_gc;
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
GC_SET_BLACK(obj->buffered);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table, *zv;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ if (!props) {
+ /* restore refcount and put into list to free */
+ pz->refcount__gc++;
+ ((zval_gc_info*)pz)->u.next = GC_G(zval_to_free);
+ GC_G(zval_to_free) = (zval_gc_info*)pz;
+ }
+
+ while (n > 0 && !table[n-1]) n--;
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ zv = table[i];
+ if (Z_TYPE_P(zv) != IS_ARRAY || Z_ARRVAL_P(zv) != &EG(symbol_table)) {
+ zv->refcount__gc++;
+ }
+ if (!props && i == n - 1) {
+ pz = zv;
+ goto tail_call;
+ } else {
+ zval_collect_white(zv TSRMLS_CC);
+ }
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
@@ -595,15 +711,28 @@ static void zobj_collect_white(zval *pz TSRMLS_DC)
Bucket *p;
if (EG(objects_store).object_buckets) {
+ zend_object_get_gc_t get_gc;
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
GC_SET_BLACK(obj->buffered);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
- HashTable *props = Z_OBJPROP_P(pz);
- if(!props) {
+ (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
+ int i, n;
+ zval **table;
+ HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+
+ for (i = 0; i < n; i++) {
+ if (table[i]) {
+ pz = table[i];
+ if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
+ pz->refcount__gc++;
+ }
+ zval_collect_white(pz TSRMLS_CC);
+ }
+ }
+ if (!props) {
return;
}
p = props->pListHead;
diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h
index 5effa5a148..ba30b3aa3b 100644
--- a/Zend/zend_gc.h
+++ b/Zend/zend_gc.h
@@ -84,7 +84,7 @@ typedef struct _gc_root_buffer {
zend_object_handle handle; /* must be 0 for zval */
union {
zval *pz;
- zend_object_handlers *handlers;
+ const zend_object_handlers *handlers;
} u;
} gc_root_buffer;
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 59be87b8d3..dbbcf972a4 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -34,10 +34,8 @@
#include "zend_objects.h"
#include "zend_objects_API.h"
#include "zend_modules.h"
-
-#ifdef ZEND_MULTIBYTE
+#include "zend_float.h"
#include "zend_multibyte.h"
-#endif /* ZEND_MULTIBYTE */
/* Define ZTS if you want a thread-safe Zend */
/*#undef ZTS*/
@@ -68,6 +66,8 @@ typedef struct _zend_declarables {
} zend_declarables;
typedef struct _zend_vm_stack *zend_vm_stack;
+typedef struct _zend_ini_entry zend_ini_entry;
+
struct _zend_compiler_globals {
zend_stack bp_stack;
@@ -101,10 +101,10 @@ struct _zend_compiler_globals {
HashTable *auto_globals;
+ zend_bool parse_error;
zend_bool in_compilation;
zend_bool short_tags;
zend_bool asp_tags;
- zend_bool allow_call_time_pass_reference;
zend_declarables declarables;
@@ -137,25 +137,25 @@ struct _zend_compiler_globals {
zend_bool in_namespace;
zend_bool has_bracketed_namespaces;
- HashTable *labels;
- zend_stack labels_stack;
+ zend_compiler_context context;
+ zend_stack context_stack;
+
+ /* interned strings */
+ char *interned_strings_start;
+ char *interned_strings_end;
+ char *interned_strings_top;
+ char *interned_strings_snapshot_top;
+
+ HashTable interned_strings;
-#ifdef ZEND_MULTIBYTE
- zend_encoding **script_encoding_list;
+ const zend_encoding **script_encoding_list;
size_t script_encoding_list_size;
+ zend_bool multibyte;
zend_bool detect_unicode;
zend_bool encoding_declared;
- zend_encoding *internal_encoding;
-
- /* multibyte utility functions */
- zend_encoding_detector encoding_detector;
- zend_encoding_converter encoding_converter;
- zend_encoding_oddlen encoding_oddlen;
-#endif /* ZEND_MULTIBYTE */
-
#ifdef ZTS
- HashTable **static_members;
+ zval ***static_members_table;
int last_static_member;
#endif
};
@@ -240,6 +240,7 @@ struct _zend_executor_globals {
HashTable *ini_directives;
HashTable *modified_ini_directives;
+ zend_ini_entry *error_reporting_ini_entry;
zend_objects_store objects_store;
zval *exception, *prev_exception;
@@ -254,7 +255,12 @@ struct _zend_executor_globals {
zend_bool active;
- void *saved_fpu_cw;
+ zend_op *start_op;
+
+ void *saved_fpu_cw_ptr;
+#if XPFPA_HAVE_CW
+ XPFPA_CW_DATATYPE saved_fpu_cw;
+#endif
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
@@ -292,7 +298,6 @@ struct _zend_php_scanner_globals {
int yy_state;
zend_stack state_stack;
-#ifdef ZEND_MULTIBYTE
/* original (unfiltered) script */
unsigned char *script_org;
size_t script_org_size;
@@ -304,9 +309,7 @@ struct _zend_php_scanner_globals {
/* input/ouput filters */
zend_encoding_filter input_filter;
zend_encoding_filter output_filter;
- zend_encoding *script_encoding;
- zend_encoding *internal_encoding;
-#endif /* ZEND_MULTIBYTE */
+ const zend_encoding *script_encoding;
};
#endif /* ZEND_GLOBALS_H */
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 481173157d..2087d57296 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -20,6 +20,7 @@
/* $Id$ */
#include "zend.h"
+#include "zend_globals.h"
#define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
(element)->pNext = (list_head); \
@@ -135,12 +136,18 @@ ZEND_API ulong zend_hash_func(const char *arKey, uint nKeyLength)
(p)->pDataPtr=NULL; \
}
-
+#define CHECK_INIT(ht) do { \
+ if (UNEXPECTED((ht)->nTableMask == 0)) { \
+ (ht)->arBuckets = (Bucket **) pecalloc((ht)->nTableSize, sizeof(Bucket *), (ht)->persistent); \
+ (ht)->nTableMask = (ht)->nTableSize - 1; \
+ } \
+} while (0)
+
+static const Bucket *uninitialized_bucket = NULL;
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
{
uint i = 3;
- Bucket **tmp;
SET_INCONSISTENT(HT_OK);
@@ -154,9 +161,9 @@ ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunctio
ht->nTableSize = 1 << i;
}
- ht->nTableMask = ht->nTableSize - 1;
+ ht->nTableMask = 0; /* 0 means that ht->arBuckets is uninitialized */
ht->pDestructor = pDestructor;
- ht->arBuckets = NULL;
+ ht->arBuckets = (Bucket**)&uninitialized_bucket;
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
@@ -165,21 +172,6 @@ ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunctio
ht->persistent = persistent;
ht->nApplyCount = 0;
ht->bApplyProtection = 1;
-
- /* Uses ecalloc() so that Bucket* == NULL */
- if (persistent) {
- tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));
- if (!tmp) {
- return FAILURE;
- }
- ht->arBuckets = tmp;
- } else {
- tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *));
- if (tmp) {
- ht->arBuckets = tmp;
- }
- }
-
return SUCCESS;
}
@@ -205,6 +197,9 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe
ulong h;
uint nIndex;
Bucket *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
IS_CONSISTENT(ht);
@@ -215,13 +210,15 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe
return FAILURE;
}
+ CHECK_INIT(ht);
+
h = zend_inline_hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
if (flag & HASH_ADD) {
return FAILURE;
}
@@ -242,16 +239,24 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe
}
HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
- }
}
p = p->pNext;
}
- p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
- if (!p) {
- return FAILURE;
+ if (IS_INTERNED(arKey)) {
+ p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = arKey;
+ } else {
+ p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = (const char*)(p + 1);
+ memcpy((char*)p->arKey, arKey, nKeyLength);
}
- memcpy(p->arKey, arKey, nKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
@@ -274,6 +279,9 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui
{
uint nIndex;
Bucket *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
IS_CONSISTENT(ht);
@@ -281,12 +289,13 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui
return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
}
+ CHECK_INIT(ht);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
if (flag & HASH_ADD) {
return FAILURE;
}
@@ -307,17 +316,25 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui
}
HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
- }
}
p = p->pNext;
}
- p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
- if (!p) {
- return FAILURE;
+ if (IS_INTERNED(arKey)) {
+ p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = arKey;
+ } else {
+ p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
+ if (!p) {
+ return FAILURE;
+ }
+ p->arKey = (const char*)(p + 1);
+ memcpy((char*)p->arKey, arKey, nKeyLength);
}
- memcpy(p->arKey, arKey, nKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
@@ -351,8 +368,12 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
{
uint nIndex;
Bucket *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
IS_CONSISTENT(ht);
+ CHECK_INIT(ht);
if (flag & HASH_NEXT_INSERT) {
h = ht->nNextFreeElement;
@@ -388,10 +409,11 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
}
p = p->pNext;
}
- p = (Bucket *) pemalloc_rel(sizeof(Bucket) - 1, ht->persistent);
+ p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent);
if (!p) {
return FAILURE;
}
+ p->arKey = NULL;
p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
p->h = h;
INIT_DATA(ht, p, pData, nDataSize);
@@ -418,6 +440,9 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
static int zend_hash_do_resize(HashTable *ht)
{
Bucket **t;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
IS_CONSISTENT(ht);
@@ -443,6 +468,9 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
uint nIndex;
IS_CONSISTENT(ht);
+ if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ return SUCCESS;
+ }
memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
p = ht->pListHead;
@@ -459,6 +487,9 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n
{
uint nIndex;
Bucket *p;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
IS_CONSISTENT(ht);
@@ -533,7 +564,9 @@ ZEND_API void zend_hash_destroy(HashTable *ht)
}
pefree(q, ht->persistent);
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
@@ -547,7 +580,9 @@ ZEND_API void zend_hash_clean(HashTable *ht)
p = ht->pListHead;
- memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+ if (ht->nTableMask) {
+ memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+ }
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->nNumOfElements = 0;
@@ -575,6 +610,9 @@ ZEND_API void zend_hash_clean(HashTable *ht)
static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
{
Bucket *retval;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
HANDLE_BLOCK_INTERRUPTIONS();
if (p->pLast) {
@@ -631,7 +669,9 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
while (p != NULL) {
p = zend_hash_apply_deleter(ht, p);
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
@@ -648,7 +688,9 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
p = ht->pListTail;
}
- pefree(ht->arBuckets, ht->persistent);
+ if (ht->nTableMask) {
+ pefree(ht->arBuckets, ht->persistent);
+ }
SET_INCONSISTENT(HT_DESTROYED);
}
@@ -881,11 +923,10 @@ ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLen
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
*pData = p->pData;
return SUCCESS;
- }
}
p = p->pNext;
}
@@ -908,11 +949,10 @@ ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint n
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
*pData = p->pData;
return SUCCESS;
- }
}
p = p->pNext;
}
@@ -933,10 +973,9 @@ ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyL
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
return 1;
- }
}
p = p->pNext;
}
@@ -959,10 +998,9 @@ ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (p->arKey == arKey ||
+ ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
return 1;
- }
}
p = p->pNext;
}
@@ -1119,7 +1157,7 @@ ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index,
if (duplicate) {
*str_index = estrndup(p->arKey, p->nKeyLength - 1);
} else {
- *str_index = p->arKey;
+ *str_index = (char*)p->arKey;
}
if (str_length) {
*str_length = p->nKeyLength;
@@ -1175,6 +1213,10 @@ ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosi
ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos)
{
Bucket *p, *q;
+ ulong h;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
p = pos ? (*pos) : ht->pInternalPointer;
@@ -1195,19 +1237,25 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
q = q->pNext;
}
} else if (key_type == HASH_KEY_IS_STRING) {
- ulong h;
+ if (IS_INTERNED(str_index)) {
+ h = INTERNED_HASH(str_index);
+ } else {
+ h = zend_inline_hash_func(str_index, str_length);
+ }
- if (p->nKeyLength == str_length &&
- memcmp(p->arKey, str_index, str_length) == 0) {
+ if (p->arKey == str_index ||
+ (p->nKeyLength == str_length &&
+ p->h == h &&
+ memcmp(p->arKey, str_index, str_length) == 0)) {
return SUCCESS;
}
- h = zend_inline_hash_func(str_index, str_length);
q = ht->arBuckets[h & ht->nTableMask];
while (q != NULL) {
- if (q->h == h && q->nKeyLength == str_length &&
- memcmp(q->arKey, str_index, str_length) == 0) {
+ if (q->arKey == str_index ||
+ (q->h == h && q->nKeyLength == str_length &&
+ memcmp(q->arKey, str_index, str_length) == 0)) {
break;
}
q = q->pNext;
@@ -1222,7 +1270,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
if (mode != HASH_UPDATE_KEY_ANYWAY) {
Bucket *r = p->pListLast;
int found = HASH_UPDATE_KEY_IF_BEFORE;
-
+
while (r) {
if (r == q) {
found = HASH_UPDATE_KEY_IF_AFTER;
@@ -1242,7 +1290,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
- } else {
+ } else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
@@ -1277,7 +1325,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
}
if (q->pListLast != NULL) {
q->pListLast->pListNext = q->pListNext;
- } else {
+ } else {
/* Deleting the head of the list */
ht->pListHead = q->pListNext;
}
@@ -1308,8 +1356,15 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
}
- if (p->nKeyLength != str_length) {
- Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + str_length, ht->persistent);
+ if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) ||
+ (!IS_INTERNED(p->arKey) && p->nKeyLength != str_length)) {
+ Bucket *q;
+
+ if (IS_INTERNED(str_index)) {
+ q = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
+ } else {
+ q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent);
+ }
q->nKeyLength = str_length;
if (p->pData == &p->pDataPtr) {
@@ -1343,8 +1398,14 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
if (key_type == HASH_KEY_IS_LONG) {
p->h = num_index;
} else {
- memcpy(p->arKey, str_index, str_length);
- p->h = zend_inline_hash_func(str_index, str_length);
+ p->h = h;
+ p->nKeyLength = str_length;
+ if (IS_INTERNED(str_index)) {
+ p->arKey = str_index;
+ } else {
+ p->arKey = (const char*)(p+1);
+ memcpy((char*)p->arKey, str_index, str_length);
+ }
}
CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
@@ -1559,6 +1620,10 @@ void zend_hash_display(const HashTable *ht)
Bucket *p;
uint i;
+ if (UNEXPECTED(ht->nNumOfElements == 0)) {
+ zend_output_debug_string(0, "The hash is empty");
+ return;
+ }
for (i = 0; i < ht->nTableSize; i++) {
p = ht->arBuckets[i];
while (p != NULL) {
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 81146e9dd0..1bd64394ac 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -60,7 +60,7 @@ typedef struct bucket {
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
- char arKey[1]; /* Must be last element */
+ const char *arKey;
} Bucket;
typedef struct _hashtable {
@@ -83,7 +83,7 @@ typedef struct _hashtable {
typedef struct _zend_hash_key {
- char *arKey;
+ const char *arKey;
uint nKeyLength;
ulong h;
} zend_hash_key;
@@ -304,7 +304,7 @@ END_EXTERN_C()
#define ZEND_INIT_SYMTABLE_EX(ht, n, persistent) \
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
-#define ZEND_HANDLE_NUMERIC(key, length, func) do { \
+#define ZEND_HANDLE_NUMERIC_EX(key, length, idx, func) do { \
register const char *tmp = key; \
\
if (*tmp == '-') { \
@@ -312,7 +312,6 @@ END_EXTERN_C()
} \
if (*tmp >= '0' && *tmp <= '9') { /* possibly a numeric index */ \
const char *end = key + length - 1; \
- ulong idx; \
\
if ((*end != '\0') /* not a null terminated string */ \
|| (*tmp == '0' && length > 2) /* numbers with leading zeros */ \
@@ -335,11 +334,17 @@ END_EXTERN_C()
} else if (idx > LONG_MAX) { /* overflow */ \
break; \
} \
- return func; \
+ func; \
} \
} \
} while (0)
+#define ZEND_HANDLE_NUMERIC(key, length, func) do { \
+ ulong idx; \
+ \
+ ZEND_HANDLE_NUMERIC_EX(key, length, idx, return func); \
+} while (0)
+
static inline int zend_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) \
{
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c
index 4110f13c89..e9fd850e6b 100644
--- a/Zend/zend_highlight.c
+++ b/Zend/zend_highlight.c
@@ -56,18 +56,15 @@ ZEND_API void zend_html_putc(char c)
ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC)
{
- const char *ptr=s, *end=s+len;
-
-#ifdef ZEND_MULTIBYTE
- char *filtered;
- int filtered_len;
+ const unsigned char *ptr = (const unsigned char*)s, *end = ptr + len;
+ unsigned char *filtered;
+ size_t filtered_len;
if (LANG_SCNG(output_filter)) {
- LANG_SCNG(output_filter)(&filtered, &filtered_len, s, len TSRMLS_CC);
+ LANG_SCNG(output_filter)(&filtered, &filtered_len, ptr, len TSRMLS_CC);
ptr = filtered;
end = filtered + filtered_len;
}
-#endif /* ZEND_MULTIBYTE */
while (ptr<end) {
if (*ptr==' ') {
@@ -79,11 +76,9 @@ ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC)
}
}
-#ifdef ZEND_MULTIBYTE
if (LANG_SCNG(output_filter)) {
efree(filtered);
}
-#endif /* ZEND_MULTIBYTE */
}
@@ -120,7 +115,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
next_color = syntax_highlighter_ini->highlight_string;
break;
case T_WHITESPACE:
- zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); /* no color needed */
+ zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); /* no color needed */
token.type = 0;
continue;
break;
@@ -143,7 +138,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
}
}
- zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);
+ zend_html_puts((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);
if (token.type == IS_STRING) {
switch (token_type) {
@@ -192,11 +187,11 @@ ZEND_API void zend_strip(TSRMLS_D)
continue;
case T_END_HEREDOC:
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
efree(token.value.str.val);
/* read the following character, either newline or ; */
if (lex_scan(&token TSRMLS_CC) != T_WHITESPACE) {
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
}
zend_write("\n", sizeof("\n") - 1);
prev_space = 1;
@@ -204,7 +199,7 @@ ZEND_API void zend_strip(TSRMLS_D)
continue;
default:
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
break;
}
diff --git a/Zend/zend_highlight.h b/Zend/zend_highlight.h
index fea4a4bcc7..7923d35bec 100644
--- a/Zend/zend_highlight.h
+++ b/Zend/zend_highlight.h
@@ -26,7 +26,6 @@
#define HL_DEFAULT_COLOR "#0000BB" /* blue */
#define HL_HTML_COLOR "#000000" /* black */
#define HL_STRING_COLOR "#DD0000" /* red */
-#define HL_BG_COLOR "#FFFFFF" /* white */
#define HL_KEYWORD_COLOR "#007700" /* green */
diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c
index 96092f465c..f2cf6d9133 100644
--- a/Zend/zend_indent.c
+++ b/Zend/zend_indent.c
@@ -64,7 +64,7 @@ ZEND_API void zend_indent()
while ((token_type=lex_scan(&token TSRMLS_CC))) {
switch (token_type) {
case T_INLINE_HTML:
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
break;
case T_WHITESPACE: {
token.type = 0;
@@ -118,16 +118,16 @@ dflt_printout:
} else {
handle_whitespace(emit_whitespace);
}
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
break;
}
} else {
handle_whitespace(emit_whitespace);
if (in_string) {
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
/* a part of a string */
} else {
- zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
}
}
break;
diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c
index 62665d63c1..b8f65b7cf2 100644
--- a/Zend/zend_ini.c
+++ b/Zend/zend_ini.c
@@ -92,6 +92,7 @@ ZEND_API int zend_ini_startup(TSRMLS_D) /* {{{ */
EG(ini_directives) = registered_zend_ini_directives;
EG(modified_ini_directives) = NULL;
+ EG(error_reporting_ini_entry) = NULL;
if (zend_hash_init_ex(registered_zend_ini_directives, 100, NULL, NULL, 1, 0) == FAILURE) {
return FAILURE;
}
@@ -133,6 +134,7 @@ ZEND_API int zend_copy_ini_directives(TSRMLS_D) /* {{{ */
zend_ini_entry ini_entry;
EG(modified_ini_directives) = NULL;
+ EG(error_reporting_ini_entry) = NULL;
EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
if (zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0) == FAILURE) {
return FAILURE;
@@ -145,11 +147,11 @@ ZEND_API int zend_copy_ini_directives(TSRMLS_D) /* {{{ */
static int ini_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
{
- Bucket *f;
- Bucket *s;
+ const Bucket *f;
+ const Bucket *s;
- f = *((Bucket **) a);
- s = *((Bucket **) b);
+ f = *((const Bucket **) a);
+ s = *((const Bucket **) b);
if (f->nKeyLength == 0 && s->nKeyLength == 0) { /* both numeric */
return ZEND_NORMALIZE_BOOL(f->nKeyLength - s->nKeyLength);
diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index e34fd34046..0f3eeb524b 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -57,8 +57,6 @@
#endif
-typedef struct _zend_ini_entry zend_ini_entry;
-
#define ZEND_INI_MH(name) int name(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC)
#define ZEND_INI_DISP(name) void name(zend_ini_entry *ini_entry, int type)
diff --git a/Zend/zend_ini_scanner.c b/Zend/zend_ini_scanner.c
index 26f98748eb..94c48c8977 100644
--- a/Zend/zend_ini_scanner.c
+++ b/Zend/zend_ini_scanner.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Thu Jun 7 17:37:03 2012 */
+/* Generated by re2c 0.13.5 on Thu Jun 7 17:48:25 2012 */
#line 1 "Zend/zend_ini_scanner.l"
/*
+----------------------------------------------------------------------+
diff --git a/Zend/zend_ini_scanner_defs.h b/Zend/zend_ini_scanner_defs.h
index f5a158aa6b..0c0471373c 100644
--- a/Zend/zend_ini_scanner_defs.h
+++ b/Zend/zend_ini_scanner_defs.h
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Thu Jun 7 17:37:03 2012 */
+/* Generated by re2c 0.13.5 on Thu Jun 7 17:48:25 2012 */
#line 3 "Zend/zend_ini_scanner_defs.h"
enum YYCONDTYPE {
diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c
index 47dbe0b052..aee0d612db 100644
--- a/Zend/zend_interfaces.c
+++ b/Zend/zend_interfaces.c
@@ -31,7 +31,7 @@ ZEND_API zend_class_entry *zend_ce_serializable;
/* {{{ zend_call_method
Only returns the returned zval if retval_ptr != NULL */
-ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
+ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC)
{
int result;
zend_fcall_info fci;
diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h
index 2b05bbd5a1..e3e3629c5b 100644
--- a/Zend/zend_interfaces.h
+++ b/Zend/zend_interfaces.h
@@ -38,7 +38,7 @@ typedef struct _zend_user_iterator {
zval *value;
} zend_user_iterator;
-ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC);
+ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, int function_name_len, zval **retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC);
#define zend_call_method_with_0_params(obj, obj_ce, fn_proxy, function_name, retval) \
zend_call_method(obj, obj_ce, fn_proxy, function_name, sizeof(function_name)-1, retval, 0, NULL, NULL TSRMLS_CC)
diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c
index 1c5ba321de..d0572b25c6 100644
--- a/Zend/zend_iterators.c
+++ b/Zend/zend_iterators.c
@@ -51,7 +51,7 @@ static zend_object_handlers iterator_object_handlers = {
ZEND_API void zend_register_iterator_wrapper(TSRMLS_D)
{
INIT_CLASS_ENTRY(zend_iterator_class_entry, "__iterator_wrapper", NULL);
- free(zend_iterator_class_entry.name);
+ str_free(zend_iterator_class_entry.name);
zend_iterator_class_entry.name = "__iterator_wrapper";
}
@@ -82,13 +82,13 @@ ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(
*iter = (zend_object_iterator *)zend_object_store_get_object(array_ptr TSRMLS_CC);
return ZEND_ITER_OBJECT;
}
- if (HASH_OF(array_ptr)) {
+ if (Z_OBJPROP_P(array_ptr)) {
return ZEND_ITER_PLAIN_OBJECT;
}
return ZEND_ITER_INVALID;
case IS_ARRAY:
- if (HASH_OF(array_ptr)) {
+ if (Z_ARRVAL_P(array_ptr)) {
return ZEND_ITER_PLAIN_ARRAY;
}
return ZEND_ITER_INVALID;
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 83d90cd1c2..9a0b3209e5 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -35,6 +35,9 @@
#include "zend_API.h"
#include "zend_constants.h"
+#define YYSIZE_T size_t
+#define yytnamerr zend_yytnamerr
+static YYSIZE_T zend_yytnamerr(char*, const char*);
#define YYERROR_VERBOSE
#define YYSTYPE znode
@@ -47,107 +50,163 @@
%}
%pure_parser
-%expect 2
+%expect 3
+%token END 0 "end of file"
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
+%token T_INCLUDE "include (T_INCLUDE)"
+%token T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)"
+%token T_EVAL "eval (T_EVAL)"
+%token T_REQUIRE "require (T_REQUIRE)"
+%token T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)"
%left ','
%left T_LOGICAL_OR
+%token T_LOGICAL_OR "or (T_LOGICAL_OR)"
%left T_LOGICAL_XOR
+%token T_LOGICAL_XOR "xor (T_LOGICAL_XOR)"
%left T_LOGICAL_AND
+%token T_LOGICAL_AND "and (T_LOGICAL_AND)"
%right T_PRINT
+%token T_PRINT "print (T_PRINT)"
%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL
+%token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
+%token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
+%token T_MUL_EQUAL "*= (T_MUL_EQUAL)"
+%token T_DIV_EQUAL "/= (T_DIV_EQUAL)"
+%token T_CONCAT_EQUAL ".= (T_CONCAT_EQUAL)"
+%token T_MOD_EQUAL "%= (T_MOD_EQUAL)"
+%token T_AND_EQUAL "&= (T_AND_EQUAL)"
+%token T_OR_EQUAL "|= (T_OR_EQUAL)"
+%token T_XOR_EQUAL "^= (T_XOR_EQUAL)"
+%token T_SL_EQUAL "<<= (T_SL_EQUAL)"
+%token T_SR_EQUAL ">>= (T_SR_EQUAL)"
%left '?' ':'
%left T_BOOLEAN_OR
-%left T_BOOLEAN_AND
+%token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)"
+%left T_BOOLEAN_AND
+%token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)"
%left '|'
%left '^'
%left '&'
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
+%token T_IS_EQUAL "== (T_IS_EQUAL)"
+%token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)"
+%token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)"
+%token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)"
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
+%token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)"
+%token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)"
%left T_SL T_SR
+%token T_SL "<< (T_SL)"
+%token T_SR ">> (T_SR)"
%left '+' '-' '.'
%left '*' '/' '%'
%right '!'
%nonassoc T_INSTANCEOF
+%token T_INSTANCEOF "instanceof (T_INSTANCEOF)"
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
+%token T_INC "++ (T_INC)"
+%token T_DEC "-- (T_DEC)"
+%token T_INT_CAST "(int) (T_INT_CAST)"
+%token T_DOUBLE_CAST "(double) (T_DOUBLE_CAST)"
+%token T_STRING_CAST "(string) (T_STRING_CAST)"
+%token T_ARRAY_CAST "(array) (T_ARRAY_CAST)"
+%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)"
+%token T_BOOL_CAST "(bool) (T_BOOL_CAST)"
+%token T_UNSET_CAST "(unset) (T_UNSET_CAST)"
%right '['
%nonassoc T_NEW T_CLONE
-%token T_EXIT
-%token T_IF
+%token T_NEW "new (T_NEW)"
+%token T_CLONE "clone (T_CLONE)"
+%token T_EXIT "exit (T_EXIT)"
+%token T_IF "if (T_IF)"
%left T_ELSEIF
-%left T_ELSE
-%left T_ENDIF
-%token T_LNUMBER
-%token T_DNUMBER
-%token T_STRING
-%token T_STRING_VARNAME
-%token T_VARIABLE
-%token T_NUM_STRING
+%token T_ELSEIF "elseif (T_ELSEIF)"
+%left T_ELSE
+%token T_ELSE "else (T_ELSE)"
+%left T_ENDIF
+%token T_ENDIF "endif (T_ENDIF)"
+%token T_LNUMBER "integer number (T_LNUMBER)"
+%token T_DNUMBER "floating-point number (T_DNUMBER)"
+%token T_STRING "identifier (T_STRING)"
+%token T_STRING_VARNAME "variable name (T_STRING_VARNAME)"
+%token T_VARIABLE "variable (T_VARIABLE)"
+%token T_NUM_STRING "number (T_NUM_STRING)"
%token T_INLINE_HTML
%token T_CHARACTER
%token T_BAD_CHARACTER
-%token T_ENCAPSED_AND_WHITESPACE
-%token T_CONSTANT_ENCAPSED_STRING
-%token T_ECHO
-%token T_DO
-%token T_WHILE
-%token T_ENDWHILE
-%token T_FOR
-%token T_ENDFOR
-%token T_FOREACH
-%token T_ENDFOREACH
-%token T_DECLARE
-%token T_ENDDECLARE
-%token T_AS
-%token T_SWITCH
-%token T_ENDSWITCH
-%token T_CASE
-%token T_DEFAULT
-%token T_BREAK
-%token T_CONTINUE
-%token T_GOTO
-%token T_FUNCTION
-%token T_CONST
-%token T_RETURN
-%token T_TRY
-%token T_CATCH
-%token T_THROW
-%token T_USE
-%token T_GLOBAL
+%token T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)"
+%token T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)"
+%token T_ECHO "echo (T_ECHO)"
+%token T_DO "do (T_DO)"
+%token T_WHILE "while (T_WHILE)"
+%token T_ENDWHILE "endwhile (T_ENDWHILE)"
+%token T_FOR "for (T_FOR)"
+%token T_ENDFOR "endfor (T_ENDFOR)"
+%token T_FOREACH "foreach (T_FOREACH)"
+%token T_ENDFOREACH "endforeach (T_ENDFOREACH)"
+%token T_DECLARE "declare (T_DECLARE)"
+%token T_ENDDECLARE "enddeclare (T_ENDDECLARE)"
+%token T_AS "as (T_AS)"
+%token T_SWITCH "switch (T_SWITCH)"
+%token T_ENDSWITCH "endswitch (T_ENDSWITCH)"
+%token T_CASE "case (T_CASE)"
+%token T_DEFAULT "default (T_DEFAULT)"
+%token T_BREAK "break (T_BREAK)"
+%token T_CONTINUE "continue (T_CONTINUE)"
+%token T_GOTO "goto (T_GOTO)"
+%token T_FUNCTION "function (T_FUNCTION)"
+%token T_CONST "const (T_CONST)"
+%token T_RETURN "return (T_RETURN)"
+%token T_TRY "try (T_TRY)"
+%token T_CATCH "catch (T_CATCH)"
+%token T_THROW "throw (T_THROW)"
+%token T_USE "use (T_USE)"
+%token T_INSTEADOF "insteadof (T_INSTEADOF)"
+%token T_GLOBAL "global (T_GLOBAL)"
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
-%token T_VAR
-%token T_UNSET
-%token T_ISSET
-%token T_EMPTY
-%token T_HALT_COMPILER
-%token T_CLASS
-%token T_INTERFACE
-%token T_EXTENDS
-%token T_IMPLEMENTS
-%token T_OBJECT_OPERATOR
-%token T_DOUBLE_ARROW
-%token T_LIST
-%token T_ARRAY
-%token T_CLASS_C
-%token T_METHOD_C
-%token T_FUNC_C
-%token T_LINE
-%token T_FILE
-%token T_COMMENT
-%token T_DOC_COMMENT
-%token T_OPEN_TAG
-%token T_OPEN_TAG_WITH_ECHO
-%token T_CLOSE_TAG
-%token T_WHITESPACE
-%token T_START_HEREDOC
-%token T_END_HEREDOC
-%token T_DOLLAR_OPEN_CURLY_BRACES
-%token T_CURLY_OPEN
-%token T_PAAMAYIM_NEKUDOTAYIM
-%token T_NAMESPACE
-%token T_NS_C
-%token T_DIR
-%token T_NS_SEPARATOR
+%token T_STATIC "static (T_STATIC)"
+%token T_ABSTRACT "abstract (T_ABSTRACT)"
+%token T_FINAL "final (T_FINAL)"
+%token T_PRIVATE "private (T_PRIVATE)"
+%token T_PROTECTED "protected (T_PROTECTED)"
+%token T_PUBLIC "public (T_PUBLIC)"
+%token T_VAR "var (T_VAR)"
+%token T_UNSET "unset (T_UNSET)"
+%token T_ISSET "isset (T_ISSET)"
+%token T_EMPTY "empty (T_EMPTY)"
+%token T_HALT_COMPILER "__halt_compiler (T_HALT_COMPILER)"
+%token T_CLASS "class (T_CLASS)"
+%token T_TRAIT "trait (T_TRAIT)"
+%token T_INTERFACE "interface (T_INTERFACE)"
+%token T_EXTENDS "extends (T_EXTENDS)"
+%token T_IMPLEMENTS "implements (T_IMPLEMENTS)"
+%token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)"
+%token T_DOUBLE_ARROW "=> (T_DOUBLE_ARROW)"
+%token T_LIST "list (T_LIST)"
+%token T_ARRAY "array (T_ARRAY)"
+%token T_CALLABLE "callable (T_CALLABLE)"
+%token T_CLASS_C "__CLASS__ (T_CLASS_C)"
+%token T_TRAIT_C "__TRAIT__ (T_TRAIT_C)"
+%token T_METHOD_C "__METHOD__ (T_METHOD_C)"
+%token T_FUNC_C "__FUNCTION__ (T_FUNC_C)"
+%token T_LINE "__LINE__ (T_LINE)"
+%token T_FILE "__FILE__ (T_FILE)"
+%token T_COMMENT "comment (T_COMMENT)"
+%token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)"
+%token T_OPEN_TAG "open tag (T_OPEN_TAG)"
+%token T_OPEN_TAG_WITH_ECHO "open tag with echo (T_OPEN_TAG_WITH_ECHO)"
+%token T_CLOSE_TAG "close tag (T_CLOSE_TAG)"
+%token T_WHITESPACE "whitespace (T_WHITESPACE)"
+%token T_START_HEREDOC "heredoc start (T_START_HEREDOC)"
+%token T_END_HEREDOC "heredoc end (T_END_HEREDOC)"
+%token T_DOLLAR_OPEN_CURLY_BRACES "${ (T_DOLLAR_OPEN_CURLY_BRACES)"
+%token T_CURLY_OPEN "{$ (T_CURLY_OPEN)"
+%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)"
+%token T_NAMESPACE "namespace (T_NAMESPACE)"
+%token T_NS_C "__NAMESPACE__ (T_NS_C)"
+%token T_DIR "__DIR__ (T_DIR)"
+%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)"
%% /* Rules */
@@ -219,12 +278,12 @@ unticked_statement:
'{' inner_statement_list '}'
| T_IF '(' expr ')' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } statement { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); }
| T_IF '(' expr ')' ':' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); }
- | T_WHILE '(' { $1.u.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' { zend_do_while_cond(&$4, &$5 TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$5 TSRMLS_CC); }
- | T_DO { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE '(' { $5.u.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' ';' { zend_do_do_while_end(&$1, &$5, &$7 TSRMLS_CC); }
+ | T_WHILE '(' { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' { zend_do_while_cond(&$4, &$5 TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$5 TSRMLS_CC); }
+ | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE '(' { $5.u.op.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' ';' { zend_do_do_while_end(&$1, &$5, &$7 TSRMLS_CC); }
| T_FOR
'('
for_expr
- ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.opline_num = get_next_op_number(CG(active_op_array)); }
+ ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); }
for_expr
';' { zend_do_extended_info(TSRMLS_C); zend_do_for_cond(&$6, &$7 TSRMLS_CC); }
for_expr
@@ -252,7 +311,7 @@ unticked_statement:
{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
- | T_DECLARE { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
+ | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
| ';' /* empty statement */
| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); }
@@ -267,7 +326,7 @@ unticked_statement:
additional_catches:
non_empty_additional_catches { $$ = $1; }
- | /* empty */ { $$.u.opline_num = -1; }
+ | /* empty */ { $$.u.op.opline_num = -1; }
;
non_empty_additional_catches:
@@ -277,7 +336,7 @@ non_empty_additional_catches:
additional_catch:
- T_CATCH '(' fully_qualified_class_name { $$.u.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+ T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
;
@@ -327,9 +386,10 @@ unticked_class_declaration_statement:
class_entry_type:
- T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = 0; }
- | T_ABSTRACT T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
- | T_FINAL T_CLASS { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_FINAL_CLASS; }
+ T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = 0; }
+ | T_ABSTRACT T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
+ | T_TRAIT { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_TRAIT; }
+ | T_FINAL T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_FINAL_CLASS; }
;
extends_from:
@@ -338,7 +398,7 @@ extends_from:
;
interface_entry:
- T_INTERFACE { $$.u.opline_num = CG(zend_lineno); $$.u.EA.type = ZEND_ACC_INTERFACE; }
+ T_INTERFACE { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_INTERFACE; }
;
interface_extends_list:
@@ -364,7 +424,7 @@ foreach_optional_arg:
foreach_variable:
variable { zend_check_writable_variable(&$1); $$ = $1; }
- | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.u.EA.type |= ZEND_PARSED_REFERENCE_VARIABLE; }
+ | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; }
;
for_statement:
@@ -450,21 +510,22 @@ parameter_list:
non_empty_parameter_list:
- optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; Z_LVAL($$.u.constant)=1; Z_TYPE($$.u.constant)=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, &$2, 0 TSRMLS_CC); }
- | optional_class_type '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; Z_LVAL($$.u.constant)=1; Z_TYPE($$.u.constant)=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$1, &$3, 1 TSRMLS_CC); }
- | optional_class_type '&' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$3, 0 TSRMLS_CC); $$.op_type = IS_CONST; Z_LVAL($$.u.constant)=1; Z_TYPE($$.u.constant)=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, &$1, &$3, 1 TSRMLS_CC); }
- | optional_class_type T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$2, 0 TSRMLS_CC); $$.op_type = IS_CONST; Z_LVAL($$.u.constant)=1; Z_TYPE($$.u.constant)=IS_LONG; INIT_PZVAL(&$$.u.constant); zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$4, &$1, &$2, 0 TSRMLS_CC); }
- | non_empty_parameter_list ',' optional_class_type T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; Z_LVAL($$.u.constant)++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, &$4, 0 TSRMLS_CC); }
- | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; Z_LVAL($$.u.constant)++; zend_do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, &$3, &$5, 1 TSRMLS_CC); }
- | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$5, 0 TSRMLS_CC); $$=$1; Z_LVAL($$.u.constant)++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$7, &$3, &$5, 1 TSRMLS_CC); }
- | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$4, 0 TSRMLS_CC); $$=$1; Z_LVAL($$.u.constant)++; zend_do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$6, &$3, &$4, 0 TSRMLS_CC); }
+ optional_class_type T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$2, &$$, NULL, &$1, 0 TSRMLS_CC); }
+ | optional_class_type '&' T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$3, &$$, NULL, &$1, 1 TSRMLS_CC); }
+ | optional_class_type '&' T_VARIABLE '=' static_scalar { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$3, &$$, &$5, &$1, 1 TSRMLS_CC); }
+ | optional_class_type T_VARIABLE '=' static_scalar { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$2, &$$, &$4, &$1, 0 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type T_VARIABLE { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$4, &$$, NULL, &$3, 0 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$5, &$$, NULL, &$3, 1 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$5, &$$, &$7, &$3, 1 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$4, &$$, &$6, &$3, 0 TSRMLS_CC); }
;
optional_class_type:
/* empty */ { $$.op_type = IS_UNUSED; }
- | fully_qualified_class_name { $$ = $1; }
- | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NULL;}
+ | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; }
+ | T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; }
+ | fully_qualified_class_name { $$ = $1; }
;
@@ -514,10 +575,67 @@ class_statement_list:
class_statement:
variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
| class_constant_declaration ';'
+ | trait_use_statement
| method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } '('
parameter_list ')' method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
;
+trait_use_statement:
+ T_USE trait_list trait_adaptations
+;
+
+trait_list:
+ fully_qualified_class_name { zend_do_implements_trait(&$1 TSRMLS_CC); }
+ | trait_list ',' fully_qualified_class_name { zend_do_implements_trait(&$3 TSRMLS_CC); }
+;
+
+trait_adaptations:
+ ';'
+ | '{' trait_adaptation_list '}'
+;
+
+trait_adaptation_list:
+ /* empty */
+ | non_empty_trait_adaptation_list
+;
+
+non_empty_trait_adaptation_list:
+ trait_adaptation_statement
+ | non_empty_trait_adaptation_list trait_adaptation_statement
+;
+
+trait_adaptation_statement:
+ trait_precedence ';' { zend_add_trait_precedence(&$1 TSRMLS_CC); }
+ | trait_alias ';' { zend_add_trait_alias(&$1 TSRMLS_CC); }
+;
+
+trait_precedence:
+ trait_method_reference_fully_qualified T_INSTEADOF trait_reference_list { zend_prepare_trait_precedence(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+trait_reference_list:
+ fully_qualified_class_name { zend_resolve_class_name(&$1, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STRVAL($1.u.constant) TSRMLS_CC); }
+ | trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STRVAL($3.u.constant) TSRMLS_CC); $$ = $1; }
+;
+
+trait_method_reference:
+ T_STRING { zend_prepare_reference(&$$, NULL, &$1 TSRMLS_CC); }
+ | trait_method_reference_fully_qualified { $$ = $1; }
+;
+
+trait_method_reference_fully_qualified:
+ fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_prepare_reference(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+trait_alias:
+ trait_method_reference T_AS trait_modifiers T_STRING { zend_prepare_trait_alias(&$$, &$1, &$3, &$4 TSRMLS_CC); }
+ | trait_method_reference T_AS member_modifier { zend_prepare_trait_alias(&$$, &$1, &$3, NULL TSRMLS_CC); }
+;
+
+trait_modifiers:
+ /* empty */ { Z_LVAL($$.u.constant) = 0x0; } /* No change of methods visibility */
+ | member_modifier { $$ = $1; } /* REM: Keep in mind, there are not only visibility modifiers */
+;
method_body:
';' /* abstract method */ { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
@@ -576,12 +694,37 @@ non_empty_for_expr:
| expr { $$ = $1; }
;
+chaining_method_or_property:
+ chaining_method_or_property variable_property { $$.EA = $2.EA; }
+ | variable_property { $$.EA = $1.EA; }
+;
+
+chaining_dereference:
+ chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
+;
+
+chaining_instance_call:
+ chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
+ | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
+ | chaining_method_or_property { $$ = $1; }
+;
+
+instance_call:
+ /* empty */ { $$ = $0; }
+ | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
+ chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
+;
+
+new_expr:
+ T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+;
+
expr_without_variable:
T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
| variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
| variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
- | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.u.EA.type = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
- | T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
| T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
| variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
| variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
@@ -628,6 +771,8 @@ expr_without_variable:
| expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
| expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
| '(' expr ')' { $$ = $2; }
+ | new_expr { $$ = $1; }
+ | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
@@ -645,14 +790,17 @@ expr_without_variable:
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
| scalar { $$ = $1; }
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
+ | '[' array_pair_list ']' { $$ = $2; }
| '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
- | function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type TSRMLS_CC); }
+ | function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
+ | T_STATIC function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); }
+ parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $5; }
;
function:
- T_FUNCTION { $$.u.opline_num = CG(zend_lineno); }
+ T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); }
;
lexical_vars:
@@ -668,22 +816,22 @@ lexical_var_list:
;
function_call:
- namespace_name '(' { $2.u.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
+ namespace_name '(' { $2.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
function_call_parameter_list
- ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
- | T_NAMESPACE T_NS_SEPARATOR namespace_name '(' { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $4.u.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); }
+ ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name '(' { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $4.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); }
function_call_parameter_list
- ')' { zend_do_end_function_call(&$1, &$$, &$6, 0, $4.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
- | T_NS_SEPARATOR namespace_name '(' { $3.u.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
+ ')' { zend_do_end_function_call(&$1, &$$, &$6, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+ | T_NS_SEPARATOR namespace_name '(' { $3.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
function_call_parameter_list
- ')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
- | class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $4.u.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ ')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+ | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name '(' { $4.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
- ')' { zend_do_end_function_call($4.u.opline_num?NULL:&$3, &$$, &$6, $4.u.opline_num, $4.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ ')' { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, &$6, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
@@ -717,8 +865,8 @@ class_name_reference:
dynamic_class_name_reference:
base_variable T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
- object_property { zend_do_push_object(&$4 TSRMLS_CC); zend_do_declare_implicit_property(TSRMLS_C); } dynamic_class_name_variable_properties
- { zend_do_pop_object(&$$ TSRMLS_CC); $$.u.EA.type = ZEND_PARSED_MEMBER; }
+ object_property { zend_do_push_object(&$4 TSRMLS_CC); } dynamic_class_name_variable_properties
+ { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; }
| base_variable { $$ = $1; }
;
@@ -730,7 +878,7 @@ dynamic_class_name_variable_properties:
dynamic_class_name_variable_property:
- T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); zend_do_declare_implicit_property(TSRMLS_C); }
+ T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); }
;
exit_expr:
@@ -759,7 +907,7 @@ common_scalar:
| T_LINE { $$ = $1; }
| T_FILE { $$ = $1; }
| T_DIR { $$ = $1; }
- | T_CLASS_C { $$ = $1; }
+ | T_TRAIT_C { $$ = $1; }
| T_METHOD_C { $$ = $1; }
| T_FUNC_C { $$ = $1; }
| T_NS_C { $$ = $1; }
@@ -776,7 +924,9 @@ static_scalar: /* compile-time evaluated scalars */
| '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
| '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
| T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
+ | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
| static_class_constant { $$ = $1; }
+ | T_CLASS_C { $$ = $1; }
;
static_class_constant:
@@ -792,6 +942,7 @@ scalar:
| common_scalar { $$ = $1; }
| '"' encaps_list '"' { $$ = $2; }
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); }
+ | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} }
;
@@ -836,26 +987,35 @@ rw_variable:
variable:
base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties
- { zend_do_pop_object(&$$ TSRMLS_CC); $$.u.EA.type = $1.u.EA.type | ($7.u.EA.type ? $7.u.EA.type : $6.u.EA.type); }
+ { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); }
| base_variable_with_function_calls { $$ = $1; }
;
variable_properties:
- variable_properties variable_property { $$.u.EA.type = $2.u.EA.type; }
- | /* empty */ { $$.u.EA.type = 0; }
+ variable_properties variable_property { $$.EA = $2.EA; }
+ | /* empty */ { $$.EA = 0; }
;
variable_property:
- T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.u.EA.type = $4.u.EA.type; }
+ T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.EA = $4.EA; }
;
-method_or_not:
+array_method_dereference:
+ array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+method:
'(' { zend_do_pop_object(&$1 TSRMLS_CC); zend_do_begin_method_call(&$1 TSRMLS_CC); }
function_call_parameter_list ')'
- { zend_do_end_function_call(&$1, &$$, &$3, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);
- zend_do_push_object(&$$ TSRMLS_CC); $$.u.EA.type = ZEND_PARSED_METHOD_CALL; }
- | /* empty */ { zend_do_declare_implicit_property(TSRMLS_C); $$.u.EA.type = ZEND_PARSED_MEMBER; }
+ { zend_do_end_function_call(&$1, &$$, &$3, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+;
+
+method_or_not:
+ method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); }
+ | array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); }
+ | /* empty */ { $$.EA = ZEND_PARSED_MEMBER; }
;
variable_without_objects:
@@ -873,16 +1033,23 @@ variable_class_name:
reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
;
+array_function_dereference:
+ array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; }
+ '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); }
+;
+
base_variable_with_function_calls:
- base_variable { $$ = $1; }
- | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.u.EA.type = ZEND_PARSED_FUNCTION_CALL; }
+ base_variable { $$ = $1; }
+ | array_function_dereference { $$ = $1; }
+ | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; }
;
base_variable:
- reference_variable { $$ = $1; $$.u.EA.type = ZEND_PARSED_VARIABLE; }
- | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.u.EA.type = ZEND_PARSED_VARIABLE; }
- | static_member { $$ = $1; $$.u.EA.type = ZEND_PARSED_STATIC_MEMBER; }
+ reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; }
+ | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; }
+ | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; }
;
reference_variable:
@@ -1001,6 +1168,74 @@ class_constant:
%%
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr)
+{
+ if (!yyres) {
+ return yystrlen(yystr);
+ }
+ {
+ TSRMLS_FETCH();
+ if (CG(parse_error) == 0) {
+ char buffer[120];
+ const unsigned char *end, *str, *tok1 = NULL, *tok2 = NULL;
+ unsigned int len = 0, toklen = 0, yystr_len;
+
+ CG(parse_error) = 1;
+
+ if (LANG_SCNG(yy_text)[0] == 0 &&
+ LANG_SCNG(yy_leng) == 1 &&
+ memcmp(yystr, "\"end of file\"", sizeof("\"end of file\"") - 1) == 0) {
+ yystpcpy(yyres, "end of file");
+ return sizeof("end of file")-1;
+ }
+
+ str = LANG_SCNG(yy_text);
+ end = memchr(str, '\n', LANG_SCNG(yy_leng));
+ yystr_len = yystrlen(yystr);
+
+ if ((tok1 = memchr(yystr, '(', yystr_len)) != NULL
+ && (tok2 = zend_memrchr(yystr, ')', yystr_len)) != NULL) {
+ toklen = (tok2 - tok1) + 1;
+ } else {
+ tok1 = tok2 = NULL;
+ toklen = 0;
+ }
+
+ if (end == NULL) {
+ len = LANG_SCNG(yy_leng) > 30 ? 30 : LANG_SCNG(yy_leng);
+ } else {
+ len = (end - str) > 30 ? 30 : (end - str);
+ }
+ if (toklen) {
+ snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1);
+ } else {
+ snprintf(buffer, sizeof(buffer), "'%.*s'", len, str);
+ }
+ yystpcpy(yyres, buffer);
+ return len + (toklen ? toklen + 1 : 0) + 2;
+ }
+ }
+ if (*yystr == '"') {
+ YYSIZE_T yyn = 0;
+ const char *yyp = yystr;
+
+ for (; *++yyp != '"'; ++yyn) {
+ yyres[yyn] = *yyp;
+ }
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ yystpcpy(yyres, yystr);
+ return strlen(yystr);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c
index 15a48fad8c..e3d3de2836 100644
--- a/Zend/zend_language_scanner.c
+++ b/Zend/zend_language_scanner.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Sat Jul 28 16:59:07 2012 */
+/* Generated by re2c 0.13.5 on Mon Apr 30 15:55:05 2012 */
#line 1 "Zend/zend_language_scanner.l"
/*
+----------------------------------------------------------------------+
@@ -35,6 +35,9 @@
#include <errno.h>
#include "zend.h"
+#ifdef PHP_WIN32
+# include <Winuser.h>
+#endif
#include "zend_alloc.h"
#include <zend_language_parser.h>
#include "zend_compile.h"
@@ -122,6 +125,33 @@ do { \
BEGIN_EXTERN_C()
+static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC);
+}
+
+static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding) TSRMLS_CC);
+}
+
+static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length,
+LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC);
+}
+
+static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length,
+internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
+}
+
+
static void _yy_push_state(int new_state TSRMLS_DC)
{
zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
@@ -149,6 +179,7 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
void startup_scanner(TSRMLS_D)
{
+ CG(parse_error) = 0;
CG(heredoc) = NULL;
CG(heredoc_len) = 0;
CG(doc_comment) = NULL;
@@ -162,6 +193,7 @@ void shutdown_scanner(TSRMLS_D)
efree(CG(heredoc));
CG(heredoc_len)=0;
}
+ CG(parse_error) = 0;
zend_stack_destroy(&SCNG(state_stack));
RESET_DOC_COMMENT();
}
@@ -183,7 +215,6 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
lex_state->lineno = CG(zend_lineno);
-#ifdef ZEND_MULTIBYTE
lex_state->script_org = SCNG(script_org);
lex_state->script_org_size = SCNG(script_org_size);
lex_state->script_filtered = SCNG(script_filtered);
@@ -191,8 +222,6 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
lex_state->input_filter = SCNG(input_filter);
lex_state->output_filter = SCNG(output_filter);
lex_state->script_encoding = SCNG(script_encoding);
- lex_state->internal_encoding = SCNG(internal_encoding);
-#endif /* ZEND_MULTIBYTE */
}
ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
@@ -211,11 +240,7 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
YYSETCONDITION(lex_state->yy_state);
CG(zend_lineno) = lex_state->lineno;
zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
+
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
@@ -227,8 +252,6 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
SCNG(input_filter) = lex_state->input_filter;
SCNG(output_filter) = lex_state->output_filter;
SCNG(script_encoding) = lex_state->script_encoding;
- SCNG(internal_encoding) = lex_state->internal_encoding;
-#endif /* ZEND_MULTIBYTE */
if (CG(heredoc)) {
efree(CG(heredoc));
@@ -247,12 +270,214 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
}
}
+#define BOM_UTF32_BE "\x00\x00\xfe\xff"
+#define BOM_UTF32_LE "\xff\xfe\x00\x00"
+#define BOM_UTF16_BE "\xfe\xff"
+#define BOM_UTF16_LE "\xff\xfe"
+#define BOM_UTF8 "\xef\xbb\xbf"
+
+static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC)
+{
+ const unsigned char *p;
+ int wchar_size = 2;
+ int le = 0;
+
+ /* utf-16 or utf-32? */
+ p = script;
+ while ((p-script) < script_size) {
+ p = memchr(p, 0, script_size-(p-script)-2);
+ if (!p) {
+ break;
+ }
+ if (*(p+1) == '\0' && *(p+2) == '\0') {
+ wchar_size = 4;
+ break;
+ }
+
+ /* searching for UTF-32 specific byte orders, so this will do */
+ p += 4;
+ }
+
+ /* BE or LE? */
+ p = script;
+ while ((p-script) < script_size) {
+ if (*p == '\0' && *(p+wchar_size-1) != '\0') {
+ /* BE */
+ le = 0;
+ break;
+ } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
+ /* LE* */
+ le = 1;
+ break;
+ }
+ p += wchar_size;
+ }
+
+ if (wchar_size == 2) {
+ return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be;
+ } else {
+ return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be;
+ }
+
+ return NULL;
+}
+
+static const zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D)
+{
+ const zend_encoding *script_encoding = NULL;
+ int bom_size;
+ unsigned char *pos1, *pos2;
+
+ if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
+ return NULL;
+ }
+
+ /* check out BOM */
+ if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf32be;
+ bom_size = sizeof(BOM_UTF32_BE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf32le;
+ bom_size = sizeof(BOM_UTF32_LE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf16be;
+ bom_size = sizeof(BOM_UTF16_BE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf16le;
+ bom_size = sizeof(BOM_UTF16_LE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
+ script_encoding = zend_multibyte_encoding_utf8;
+ bom_size = sizeof(BOM_UTF8)-1;
+ }
+
+ if (script_encoding) {
+ /* remove BOM */
+ LANG_SCNG(script_org) += bom_size;
+ LANG_SCNG(script_org_size) -= bom_size;
+
+ return script_encoding;
+ }
+
+ /* script contains NULL bytes -> auto-detection */
+ if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) {
+ /* check if the NULL byte is after the __HALT_COMPILER(); */
+ pos2 = LANG_SCNG(script_org);
+
+ while (pos1 - pos2 >= sizeof("__HALT_COMPILER();")-1) {
+ pos2 = memchr(pos2, '_', pos1 - pos2);
+ if (!pos2) break;
+ pos2++;
+ if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) {
+ pos2 += sizeof("_HALT_COMPILER")-1;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == '(') {
+ pos2++;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == ')') {
+ pos2++;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == ';') {
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+ /* make best effort if BOM is missing */
+ return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC);
+ }
+
+ return NULL;
+}
+
+static const zend_encoding* zend_multibyte_find_script_encoding(TSRMLS_D)
+{
+ const zend_encoding *script_encoding;
+
+ if (CG(detect_unicode)) {
+ /* check out bom(byte order mark) and see if containing wchars */
+ script_encoding = zend_multibyte_detect_unicode(TSRMLS_C);
+ if (script_encoding != NULL) {
+ /* bom or wchar detection is prior to 'script_encoding' option */
+ return script_encoding;
+ }
+ }
+
+ /* if no script_encoding specified, just leave alone */
+ if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
+ return NULL;
+ }
+
+ /* if multiple encodings specified, detect automagically */
+ if (CG(script_encoding_list_size) > 1) {
+ return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size) TSRMLS_CC);
+ }
+
+ return CG(script_encoding_list)[0];
+}
+
+ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding(TSRMLS_C);
+
+ if (!script_encoding) {
+ return FAILURE;
+ }
+
+ /* judge input/output filter */
+ LANG_SCNG(script_encoding) = script_encoding;
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = NULL;
+
+ if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) {
+ if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
+ /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
+ LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
+ LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script;
+ } else {
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = NULL;
+ }
+ return SUCCESS;
+ }
+
+ if (zend_multibyte_check_lexer_compatibility(internal_encoding)) {
+ LANG_SCNG(input_filter) = encoding_filter_script_to_internal;
+ LANG_SCNG(output_filter) = NULL;
+ } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = encoding_filter_script_to_internal;
+ } else {
+ /* both script and internal encodings are incompatible w/ flex */
+ LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
+ LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal;
+ }
+
+ return 0;
+}
ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
{
- char *file_path = NULL, *buf;
+ const char *file_path = NULL;
+ char *buf;
size_t size, offset = 0;
-
+
/* The shebang line was read, get the current position to obtain the buffer start */
if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
if ((offset = ftell(file_handle->handle.fp)) == -1) {
@@ -277,32 +502,24 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
SCNG(yy_start) = NULL;
if (size != -1) {
-#ifdef ZEND_MULTIBYTE
- if (zend_multibyte_read_script((unsigned char *)buf, size TSRMLS_CC) != 0) {
- return FAILURE;
- }
-
- SCNG(yy_in) = NULL;
+ if (CG(multibyte)) {
+ SCNG(script_org) = (unsigned char*)buf;
+ SCNG(script_org_size) = size;
+ SCNG(script_filtered) = NULL;
- zend_multibyte_set_filter(NULL TSRMLS_CC);
+ zend_multibyte_set_filter(NULL TSRMLS_CC);
- if (!SCNG(input_filter)) {
- SCNG(script_filtered) = (unsigned char*)emalloc(SCNG(script_org_size)+2);
- memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
- SCNG(script_filtered_size) = SCNG(script_org_size);
- } else {
- SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
- if (SCNG(script_filtered) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
- "encoding \"%s\" to a compatible encoding", LANG_SCNG(script_encoding)->name);
+ if (SCNG(input_filter)) {
+ if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ buf = (char*)SCNG(script_filtered);
+ size = SCNG(script_filtered_size);
}
}
- SCNG(yy_start) = SCNG(script_filtered) - offset;
- yy_scan_buffer((char *)SCNG(script_filtered), SCNG(script_filtered_size) TSRMLS_CC);
-#else /* !ZEND_MULTIBYTE */
- SCNG(yy_start) = buf - offset;
+ SCNG(yy_start) = (unsigned char *)buf - offset;
yy_scan_buffer(buf, size TSRMLS_CC);
-#endif /* ZEND_MULTIBYTE */
} else {
zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
}
@@ -363,6 +580,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
compiler_result = zendparse(TSRMLS_C);
zend_do_return(&retval_znode, 0 TSRMLS_CC);
CG(in_compilation) = original_in_compilation;
@@ -430,32 +648,44 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
{
+ char *buf;
+ size_t size;
+
/* enforce two trailing NULLs for flex... */
- str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ if (IS_INTERNED(str->value.str.val)) {
+ char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD);
+ memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD);
+ str->value.str.val = tmp;
+ } else {
+ str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ }
memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD);
- SCNG(yy_in)=NULL;
+ SCNG(yy_in) = NULL;
SCNG(yy_start) = NULL;
-#ifdef ZEND_MULTIBYTE
- SCNG(script_org) = (unsigned char *)estrdup(str->value.str.val);
- SCNG(script_org_size) = str->value.str.len;
+ buf = str->value.str.val;
+ size = str->value.str.len;
- zend_multibyte_set_filter(CG(internal_encoding) TSRMLS_CC);
+ if (CG(multibyte)) {
+ SCNG(script_org) = (unsigned char*)buf;
+ SCNG(script_org_size) = size;
+ SCNG(script_filtered) = NULL;
- if (!SCNG(input_filter)) {
- SCNG(script_filtered) = (unsigned char*)emalloc(SCNG(script_org_size)+2);
- memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
- SCNG(script_filtered_size) = SCNG(script_org_size);
- } else {
- SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
+ zend_multibyte_set_filter(zend_multibyte_get_internal_encoding(TSRMLS_C) TSRMLS_CC);
+
+ if (SCNG(input_filter)) {
+ if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ buf = (char*)SCNG(script_filtered);
+ size = SCNG(script_filtered_size);
+ }
}
- yy_scan_buffer((char *)SCNG(script_filtered), SCNG(script_filtered_size) TSRMLS_CC);
-#else /* !ZEND_MULTIBYTE */
- yy_scan_buffer(str->value.str.val, str->value.str.len TSRMLS_CC);
-#endif /* ZEND_MULTIBYTE */
+ yy_scan_buffer(buf, size TSRMLS_CC);
zend_set_compiled_filename(filename TSRMLS_CC);
CG(zend_lineno) = 1;
@@ -467,13 +697,12 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
{
size_t offset = SCNG(yy_cursor) - SCNG(yy_start);
-#ifdef ZEND_MULTIBYTE
if (SCNG(input_filter)) {
- size_t original_offset = offset, length = 0; do {
+ size_t original_offset = offset, length = 0;
+ do {
unsigned char *p = NULL;
- SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC);
- if (!p) {
- break;
+ if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC)) {
+ return (size_t)-1;
}
efree(p);
if (length > original_offset) {
@@ -483,7 +712,6 @@ ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
}
} while (original_offset != length);
}
-#endif
return offset;
}
@@ -521,19 +749,14 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
CG(interactive) = orig_interactive;
CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
BEGIN(ST_IN_SCRIPTING);
compiler_result = zendparse(TSRMLS_C);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
}
-#endif /* ZEND_MULTIBYTE */
if (compiler_result==1) {
CG(active_op_array) = original_active_op_array;
@@ -573,16 +796,10 @@ int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlight
return FAILURE;
}
zend_highlight(syntax_highlighter_ini TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
}
-#endif /* ZEND_MULTIBYTE */
zend_destroy_file_handle(&file_handle TSRMLS_CC);
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
return SUCCESS;
@@ -602,122 +819,44 @@ int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_
}
BEGIN(INITIAL);
zend_highlight(syntax_highlighter_ini TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
}
-#endif /* ZEND_MULTIBYTE */
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
zval_dtor(str);
return SUCCESS;
}
-END_EXTERN_C()
-#ifdef ZEND_MULTIBYTE
-
-BEGIN_EXTERN_C()
-ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, zend_encoding *old_encoding TSRMLS_DC)
+ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC)
{
- size_t original_offset, offset, free_flag, new_len, length;
- unsigned char *p;
-
- /* calculate current position */
- offset = original_offset = YYCURSOR - SCNG(yy_start);
- if (old_input_filter && offset > 0) {
- zend_encoding *new_encoding = SCNG(script_encoding);
- zend_encoding_filter new_filter = SCNG(input_filter);
- SCNG(script_encoding) = old_encoding;
- SCNG(input_filter) = old_input_filter;
- offset = zend_get_scanned_file_offset(TSRMLS_C);
- SCNG(script_encoding) = new_encoding;
- SCNG(input_filter) = new_filter;
- }
+ size_t length;
+ unsigned char *new_yy_start;
/* convert and set */
if (!SCNG(input_filter)) {
- length = SCNG(script_org_size) - offset;
- p = SCNG(script_org) + offset;
- free_flag = 0;
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+ SCNG(script_filtered_size) = 0;
+ length = SCNG(script_org_size);
+ new_yy_start = SCNG(script_org);
} else {
- SCNG(input_filter)(&p, &length, SCNG(script_org) + offset, SCNG(script_org_size) - offset TSRMLS_CC);
- free_flag = 1;
- }
-
- new_len = original_offset + length;
-
- if (new_len > YYLIMIT - SCNG(yy_start)) {
- unsigned char *new_yy_start = erealloc(SCNG(yy_start), new_len);
- SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
- SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
- SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
- SCNG(yy_start) = new_yy_start;
- SCNG(script_filtered) = new_yy_start;
- SCNG(script_filtered_size) = new_len;
- }
-
- SCNG(yy_limit) = SCNG(yy_start) + new_len;
- memmove(SCNG(yy_start) + original_offset, p, length);
-
- if (free_flag) {
- efree(p);
- }
-}
-
-
-ZEND_API int zend_multibyte_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
-{
- size_t n;
-
- if (CG(interactive) == 0) {
- if (zend_stream_fixup(file_handle, &buf, &len TSRMLS_CC) == FAILURE) {
- return FAILURE;
+ if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
}
- n = len;
- return n;
- }
-
- /* interactive */
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- }
- SCNG(script_org) = NULL;
- SCNG(script_org_size) = 0;
-
- /* TODO: support widechars */
- if (zend_stream_fixup(file_handle, &buf, &len TSRMLS_CC) == FAILURE) {
- return FAILURE;
+ SCNG(script_filtered) = new_yy_start;
+ SCNG(script_filtered_size) = length;
}
- n = len;
-
- SCNG(script_org_size) = n;
- SCNG(script_org) = (unsigned char*)emalloc(SCNG(script_org_size) + 1);
- memcpy(SCNG(script_org), buf, n);
-
- return n;
-}
+ SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
+ SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
+ SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
+ SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start));
-ZEND_API int zend_multibyte_read_script(unsigned char *buf, size_t n TSRMLS_DC)
-{
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
- SCNG(script_org_size) = n;
-
- SCNG(script_org) = (unsigned char*)emalloc(SCNG(script_org_size) + 1);
- memcpy(SCNG(script_org), buf, n);
- *(SCNG(script_org)+SCNG(script_org_size)) = '\0';
-
- return 0;
+ SCNG(yy_start) = new_yy_start;
}
@@ -730,11 +869,6 @@ ZEND_API int zend_multibyte_read_script(unsigned char *buf, size_t n TSRMLS_DC)
zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
zendlval->value.str.len = yyleng; \
}
-#else /* ZEND_MULTIBYTE */
-# define zend_copy_value(zendlval, yytext, yyleng) \
- zendlval->value.str.val = (char *)estrndup(yytext, yyleng); \
- zendlval->value.str.len = yyleng;
-#endif /* ZEND_MULTIBYTE */
static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
{
@@ -775,6 +909,14 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
*t++ = '\v';
zendlval->value.str.len--;
break;
+ case 'e':
+#ifdef PHP_WIN32
+ *t++ = VK_ESCAPE;
+#else
+ *t++ = '\e';
+#endif
+ zendlval->value.str.len--;
+ break;
case '"':
case '`':
if (*s != quote_type) {
@@ -838,7 +980,6 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
s++;
}
*t = 0;
-#ifdef ZEND_MULTIBYTE
if (SCNG(output_filter)) {
size_t sz = 0;
s = zendlval->value.str.val;
@@ -846,7 +987,6 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
zendlval->value.str.len = sz;
efree(s);
}
-#endif /* ZEND_MULTIBYTE */
}
@@ -858,7 +998,7 @@ restart:
yymore_restart:
-#line 862 "Zend/zend_language_scanner.c"
+#line 1002 "Zend/zend_language_scanner.c"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@@ -957,7 +1097,7 @@ yyc_INITIAL:
yy3:
YYDEBUG(3, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1590 "Zend/zend_language_scanner.l"
+#line 1790 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -973,7 +1113,7 @@ inline_char_handler:
if (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR) {
case '?':
- if (CG(short_tags) || !strncasecmp(YYCURSOR + 1, "php", 3)) { /* Assume [ \t\n\r] follows "php" */
+ if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */
break;
}
continue;
@@ -1001,7 +1141,6 @@ inline_char_handler:
inline_html:
yyleng = YYCURSOR - SCNG(yy_text);
-#ifdef ZEND_MULTIBYTE
if (SCNG(output_filter)) {
int readsize;
size_t sz = 0;
@@ -1014,15 +1153,11 @@ inline_html:
zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
}
-#else /* !ZEND_MULTIBYTE */
- zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
-#endif
zendlval->type = IS_STRING;
HANDLE_NEWLINES(yytext, yyleng);
return T_INLINE_HTML;
}
-#line 1026 "Zend/zend_language_scanner.c"
+#line 1161 "Zend/zend_language_scanner.c"
yy4:
YYDEBUG(4, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1040,7 +1175,7 @@ yy5:
yy6:
YYDEBUG(6, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1578 "Zend/zend_language_scanner.l"
+#line 1778 "Zend/zend_language_scanner.l"
{
if (CG(short_tags)) {
zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1052,14 +1187,14 @@ yy6:
goto inline_char_handler;
}
}
-#line 1056 "Zend/zend_language_scanner.c"
+#line 1191 "Zend/zend_language_scanner.c"
yy7:
YYDEBUG(7, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy43;
YYDEBUG(8, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1555 "Zend/zend_language_scanner.l"
+#line 1755 "Zend/zend_language_scanner.l"
{
if (CG(asp_tags)) {
zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1071,7 +1206,7 @@ yy7:
goto inline_char_handler;
}
}
-#line 1075 "Zend/zend_language_scanner.c"
+#line 1210 "Zend/zend_language_scanner.c"
yy9:
YYDEBUG(9, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1257,9 +1392,9 @@ yy35:
++YYCURSOR;
YYDEBUG(38, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1511 "Zend/zend_language_scanner.l"
+#line 1715 "Zend/zend_language_scanner.l"
{
- YYCTYPE *bracket = zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
+ YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
if (bracket != SCNG(yy_text)) {
/* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */
@@ -1274,7 +1409,7 @@ yy35:
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
}
-#line 1278 "Zend/zend_language_scanner.c"
+#line 1413 "Zend/zend_language_scanner.c"
yy39:
YYDEBUG(39, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1301,7 +1436,7 @@ yy43:
++YYCURSOR;
YYDEBUG(44, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1529 "Zend/zend_language_scanner.l"
+#line 1733 "Zend/zend_language_scanner.l"
{
if (CG(asp_tags)) {
zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1313,25 +1448,21 @@ yy43:
goto inline_char_handler;
}
}
-#line 1317 "Zend/zend_language_scanner.c"
+#line 1452 "Zend/zend_language_scanner.c"
yy45:
YYDEBUG(45, *YYCURSOR);
++YYCURSOR;
YYDEBUG(46, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1542 "Zend/zend_language_scanner.l"
+#line 1746 "Zend/zend_language_scanner.l"
{
- if (CG(short_tags)) {
- zendlval->value.str.val = yytext; /* no copying - intentional */
- zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
- BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG_WITH_ECHO;
- } else {
- goto inline_char_handler;
- }
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG_WITH_ECHO;
}
-#line 1335 "Zend/zend_language_scanner.c"
+#line 1466 "Zend/zend_language_scanner.c"
yy47:
YYDEBUG(47, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1358,7 +1489,7 @@ yy50:
yy51:
YYDEBUG(51, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1568 "Zend/zend_language_scanner.l"
+#line 1768 "Zend/zend_language_scanner.l"
{
zendlval->value.str.val = yytext; /* no copying - intentional */
zendlval->value.str.len = yyleng;
@@ -1367,7 +1498,7 @@ yy51:
BEGIN(ST_IN_SCRIPTING);
return T_OPEN_TAG;
}
-#line 1371 "Zend/zend_language_scanner.c"
+#line 1502 "Zend/zend_language_scanner.c"
yy52:
YYDEBUG(52, *YYCURSOR);
++YYCURSOR;
@@ -1438,7 +1569,7 @@ yyc_ST_BACKQUOTE:
yy56:
YYDEBUG(56, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2048 "Zend/zend_language_scanner.l"
+#line 2241 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -1479,7 +1610,7 @@ yy56:
zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 1483 "Zend/zend_language_scanner.c"
+#line 1614 "Zend/zend_language_scanner.c"
yy57:
YYDEBUG(57, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1490,12 +1621,12 @@ yy58:
++YYCURSOR;
YYDEBUG(59, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1992 "Zend/zend_language_scanner.l"
+#line 2185 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
return '`';
}
-#line 1499 "Zend/zend_language_scanner.c"
+#line 1630 "Zend/zend_language_scanner.c"
yy60:
YYDEBUG(60, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1505,14 +1636,14 @@ yy61:
++YYCURSOR;
YYDEBUG(62, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1979 "Zend/zend_language_scanner.l"
+#line 2172 "Zend/zend_language_scanner.l"
{
zendlval->value.lval = (long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
}
-#line 1516 "Zend/zend_language_scanner.c"
+#line 1647 "Zend/zend_language_scanner.c"
yy63:
YYDEBUG(63, *YYCURSOR);
yyaccept = 0;
@@ -1528,24 +1659,24 @@ yy63:
yy65:
YYDEBUG(65, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1677 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 1538 "Zend/zend_language_scanner.c"
+#line 1669 "Zend/zend_language_scanner.c"
yy66:
YYDEBUG(66, *YYCURSOR);
++YYCURSOR;
YYDEBUG(67, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1300 "Zend/zend_language_scanner.l"
+#line 1449 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
return T_DOLLAR_OPEN_CURLY_BRACES;
}
-#line 1549 "Zend/zend_language_scanner.c"
+#line 1680 "Zend/zend_language_scanner.c"
yy68:
YYDEBUG(68, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1559,7 +1690,7 @@ yy70:
++YYCURSOR;
YYDEBUG(71, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1669 "Zend/zend_language_scanner.l"
+#line 1864 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
@@ -1567,7 +1698,7 @@ yy70:
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 1571 "Zend/zend_language_scanner.c"
+#line 1702 "Zend/zend_language_scanner.c"
yy72:
YYDEBUG(72, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1585,7 +1716,7 @@ yy73:
++YYCURSOR;
YYDEBUG(74, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1659 "Zend/zend_language_scanner.l"
+#line 1854 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
@@ -1593,7 +1724,7 @@ yy73:
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 1597 "Zend/zend_language_scanner.c"
+#line 1728 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_DOUBLE_QUOTES:
@@ -1661,7 +1792,7 @@ yy77:
yy78:
YYDEBUG(78, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1998 "Zend/zend_language_scanner.l"
+#line 2191 "Zend/zend_language_scanner.l"
{
if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
@@ -1710,7 +1841,7 @@ double_quotes_scan_done:
zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 1714 "Zend/zend_language_scanner.c"
+#line 1845 "Zend/zend_language_scanner.c"
yy79:
YYDEBUG(79, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1721,12 +1852,12 @@ yy80:
++YYCURSOR;
YYDEBUG(81, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1987 "Zend/zend_language_scanner.l"
+#line 2180 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
return '"';
}
-#line 1730 "Zend/zend_language_scanner.c"
+#line 1861 "Zend/zend_language_scanner.c"
yy82:
YYDEBUG(82, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1736,14 +1867,14 @@ yy83:
++YYCURSOR;
YYDEBUG(84, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1979 "Zend/zend_language_scanner.l"
+#line 2172 "Zend/zend_language_scanner.l"
{
zendlval->value.lval = (long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
}
-#line 1747 "Zend/zend_language_scanner.c"
+#line 1878 "Zend/zend_language_scanner.c"
yy85:
YYDEBUG(85, *YYCURSOR);
yyaccept = 0;
@@ -1759,24 +1890,24 @@ yy85:
yy87:
YYDEBUG(87, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1677 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 1769 "Zend/zend_language_scanner.c"
+#line 1900 "Zend/zend_language_scanner.c"
yy88:
YYDEBUG(88, *YYCURSOR);
++YYCURSOR;
YYDEBUG(89, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1300 "Zend/zend_language_scanner.l"
+#line 1449 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
return T_DOLLAR_OPEN_CURLY_BRACES;
}
-#line 1780 "Zend/zend_language_scanner.c"
+#line 1911 "Zend/zend_language_scanner.c"
yy90:
YYDEBUG(90, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1790,7 +1921,7 @@ yy92:
++YYCURSOR;
YYDEBUG(93, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1669 "Zend/zend_language_scanner.l"
+#line 1864 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
@@ -1798,7 +1929,7 @@ yy92:
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 1802 "Zend/zend_language_scanner.c"
+#line 1933 "Zend/zend_language_scanner.c"
yy94:
YYDEBUG(94, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1816,7 +1947,7 @@ yy95:
++YYCURSOR;
YYDEBUG(96, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1659 "Zend/zend_language_scanner.l"
+#line 1854 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
@@ -1824,7 +1955,7 @@ yy95:
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 1828 "Zend/zend_language_scanner.c"
+#line 1959 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_END_HEREDOC:
@@ -1835,7 +1966,7 @@ yyc_ST_END_HEREDOC:
++YYCURSOR;
YYDEBUG(100, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1966 "Zend/zend_language_scanner.l"
+#line 2159 "Zend/zend_language_scanner.l"
{
YYCURSOR += CG(heredoc_len) - 1;
yyleng = CG(heredoc_len);
@@ -1847,7 +1978,7 @@ yyc_ST_END_HEREDOC:
BEGIN(ST_IN_SCRIPTING);
return T_END_HEREDOC;
}
-#line 1851 "Zend/zend_language_scanner.c"
+#line 1982 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_HEREDOC:
{
@@ -1909,7 +2040,7 @@ yy103:
yy104:
YYDEBUG(104, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2090 "Zend/zend_language_scanner.l"
+#line 2283 "Zend/zend_language_scanner.l"
{
int newline = 0;
@@ -1980,7 +2111,7 @@ heredoc_scan_done:
zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 1984 "Zend/zend_language_scanner.c"
+#line 2115 "Zend/zend_language_scanner.c"
yy105:
YYDEBUG(105, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1995,14 +2126,14 @@ yy107:
++YYCURSOR;
YYDEBUG(108, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1979 "Zend/zend_language_scanner.l"
+#line 2172 "Zend/zend_language_scanner.l"
{
zendlval->value.lval = (long) '{';
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
yyless(1);
return T_CURLY_OPEN;
}
-#line 2006 "Zend/zend_language_scanner.c"
+#line 2137 "Zend/zend_language_scanner.c"
yy109:
YYDEBUG(109, *YYCURSOR);
yyaccept = 0;
@@ -2018,24 +2149,24 @@ yy109:
yy111:
YYDEBUG(111, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1677 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 2028 "Zend/zend_language_scanner.c"
+#line 2159 "Zend/zend_language_scanner.c"
yy112:
YYDEBUG(112, *YYCURSOR);
++YYCURSOR;
YYDEBUG(113, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1300 "Zend/zend_language_scanner.l"
+#line 1449 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
return T_DOLLAR_OPEN_CURLY_BRACES;
}
-#line 2039 "Zend/zend_language_scanner.c"
+#line 2170 "Zend/zend_language_scanner.c"
yy114:
YYDEBUG(114, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2049,7 +2180,7 @@ yy116:
++YYCURSOR;
YYDEBUG(117, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1669 "Zend/zend_language_scanner.l"
+#line 1864 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
@@ -2057,7 +2188,7 @@ yy116:
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 2061 "Zend/zend_language_scanner.c"
+#line 2192 "Zend/zend_language_scanner.c"
yy118:
YYDEBUG(118, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2075,7 +2206,7 @@ yy119:
++YYCURSOR;
YYDEBUG(120, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1659 "Zend/zend_language_scanner.l"
+#line 1854 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
@@ -2083,7 +2214,7 @@ yy119:
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 2087 "Zend/zend_language_scanner.c"
+#line 2218 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_IN_SCRIPTING:
@@ -2095,32 +2226,32 @@ yyc_ST_IN_SCRIPTING:
0, 0, 0, 0, 0, 0, 0, 0,
192, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 0, 0, 0, 0, 0, 0,
- 0, 40, 40, 40, 40, 40, 40, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 0, 0, 0, 0, 8,
- 0, 40, 40, 40, 40, 40, 40, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 0, 0, 0, 0, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
+ 60, 60, 44, 44, 44, 44, 44, 44,
+ 44, 44, 0, 0, 0, 0, 0, 0,
+ 0, 36, 36, 36, 36, 36, 36, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 0, 0, 0, 0, 4,
+ 0, 36, 36, 36, 36, 36, 36, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 0, 0, 0, 0, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
};
YYDEBUG(121, *YYCURSOR);
YYFILL(16);
@@ -2248,48 +2379,48 @@ yy123:
YYDEBUG(-1, yych);
switch ((yych = *YYCURSOR)) {
case 'C':
- case 'c': goto yy701;
+ case 'c': goto yy726;
case 'L':
- case 'l': goto yy702;
+ case 'l': goto yy727;
case 'M':
- case 'm': goto yy703;
+ case 'm': goto yy728;
case 'N':
- case 'n': goto yy704;
+ case 'n': goto yy729;
case 'V':
- case 'v': goto yy705;
+ case 'v': goto yy730;
case 'X':
- case 'x': goto yy706;
+ case 'x': goto yy731;
default: goto yy186;
}
yy124:
YYDEBUG(124, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1700 "Zend/zend_language_scanner.l"
+#line 1895 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
zendlval->type = IS_STRING;
return T_STRING;
}
-#line 2274 "Zend/zend_language_scanner.c"
+#line 2405 "Zend/zend_language_scanner.c"
yy125:
YYDEBUG(125, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'O') {
if (yych <= 'H') {
- if (yych == 'E') goto yy683;
+ if (yych == 'E') goto yy708;
goto yy186;
} else {
- if (yych <= 'I') goto yy684;
+ if (yych <= 'I') goto yy709;
if (yych <= 'N') goto yy186;
- goto yy685;
+ goto yy710;
}
} else {
if (yych <= 'h') {
- if (yych == 'e') goto yy683;
+ if (yych == 'e') goto yy708;
goto yy186;
} else {
- if (yych <= 'i') goto yy684;
- if (yych == 'o') goto yy685;
+ if (yych <= 'i') goto yy709;
+ if (yych == 'o') goto yy710;
goto yy186;
}
}
@@ -2298,20 +2429,20 @@ yy126:
yych = *++YYCURSOR;
if (yych <= 'U') {
if (yych <= 'N') {
- if (yych == 'I') goto yy662;
+ if (yych == 'I') goto yy687;
goto yy186;
} else {
- if (yych <= 'O') goto yy663;
+ if (yych <= 'O') goto yy688;
if (yych <= 'T') goto yy186;
- goto yy664;
+ goto yy689;
}
} else {
if (yych <= 'n') {
- if (yych == 'i') goto yy662;
+ if (yych == 'i') goto yy687;
goto yy186;
} else {
- if (yych <= 'o') goto yy663;
- if (yych == 'u') goto yy664;
+ if (yych <= 'o') goto yy688;
+ if (yych == 'u') goto yy689;
goto yy186;
}
}
@@ -2320,42 +2451,42 @@ yy127:
yych = *++YYCURSOR;
if (yych <= 'O') {
if (yych <= 'K') {
- if (yych == 'A') goto yy634;
+ if (yych == 'A') goto yy652;
goto yy186;
} else {
- if (yych <= 'L') goto yy635;
+ if (yych <= 'L') goto yy653;
if (yych <= 'N') goto yy186;
- goto yy636;
+ goto yy654;
}
} else {
if (yych <= 'k') {
- if (yych == 'a') goto yy634;
+ if (yych == 'a') goto yy652;
goto yy186;
} else {
- if (yych <= 'l') goto yy635;
- if (yych == 'o') goto yy636;
+ if (yych <= 'l') goto yy653;
+ if (yych == 'o') goto yy654;
goto yy186;
}
}
yy128:
YYDEBUG(128, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy616;
- if (yych == 'e') goto yy616;
+ if (yych == 'E') goto yy634;
+ if (yych == 'e') goto yy634;
goto yy186;
yy129:
YYDEBUG(129, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'R') {
- if (yych == 'H') goto yy608;
+ if (yych == 'H') goto yy622;
if (yych <= 'Q') goto yy186;
- goto yy609;
+ goto yy623;
} else {
if (yych <= 'h') {
if (yych <= 'g') goto yy186;
- goto yy608;
+ goto yy622;
} else {
- if (yych == 'r') goto yy609;
+ if (yych == 'r') goto yy623;
goto yy186;
}
}
@@ -2364,53 +2495,53 @@ yy130:
yych = *++YYCURSOR;
if (yych <= 'S') {
if (yych <= 'L') {
- if (yych == 'F') goto yy561;
+ if (yych == 'F') goto yy569;
goto yy186;
} else {
- if (yych <= 'M') goto yy563;
- if (yych <= 'N') goto yy564;
+ if (yych <= 'M') goto yy571;
+ if (yych <= 'N') goto yy572;
if (yych <= 'R') goto yy186;
- goto yy565;
+ goto yy573;
}
} else {
if (yych <= 'm') {
- if (yych == 'f') goto yy561;
+ if (yych == 'f') goto yy569;
if (yych <= 'l') goto yy186;
- goto yy563;
+ goto yy571;
} else {
- if (yych <= 'n') goto yy564;
- if (yych == 's') goto yy565;
+ if (yych <= 'n') goto yy572;
+ if (yych == 's') goto yy573;
goto yy186;
}
}
yy131:
YYDEBUG(131, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy556;
- if (yych == 'h') goto yy556;
+ if (yych == 'H') goto yy564;
+ if (yych == 'h') goto yy564;
goto yy186;
yy132:
YYDEBUG(132, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'S') {
if (yych <= 'M') {
- if (yych == 'B') goto yy538;
+ if (yych == 'B') goto yy546;
goto yy186;
} else {
- if (yych <= 'N') goto yy539;
+ if (yych <= 'N') goto yy547;
if (yych <= 'Q') goto yy186;
- if (yych <= 'R') goto yy540;
- goto yy541;
+ if (yych <= 'R') goto yy548;
+ goto yy549;
}
} else {
if (yych <= 'n') {
- if (yych == 'b') goto yy538;
+ if (yych == 'b') goto yy546;
if (yych <= 'm') goto yy186;
- goto yy539;
+ goto yy547;
} else {
if (yych <= 'q') goto yy186;
- if (yych <= 'r') goto yy540;
- if (yych <= 's') goto yy541;
+ if (yych <= 'r') goto yy548;
+ if (yych <= 's') goto yy549;
goto yy186;
}
}
@@ -2418,15 +2549,15 @@ yy133:
YYDEBUG(133, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'W') {
- if (yych == 'T') goto yy526;
+ if (yych == 'T') goto yy534;
if (yych <= 'V') goto yy186;
- goto yy527;
+ goto yy535;
} else {
if (yych <= 't') {
if (yych <= 's') goto yy186;
- goto yy526;
+ goto yy534;
} else {
- if (yych == 'w') goto yy527;
+ if (yych == 'w') goto yy535;
goto yy186;
}
}
@@ -2437,18 +2568,18 @@ yy134:
if (yych <= ';') {
if (yych <= '"') {
if (yych <= '!') goto yy186;
- goto yy518;
+ goto yy526;
} else {
- if (yych == '\'') goto yy519;
+ if (yych == '\'') goto yy527;
goto yy186;
}
} else {
if (yych <= 'R') {
- if (yych <= '<') goto yy517;
+ if (yych <= '<') goto yy525;
if (yych <= 'Q') goto yy186;
- goto yy520;
+ goto yy528;
} else {
- if (yych == 'r') goto yy520;
+ if (yych == 'r') goto yy528;
goto yy186;
}
}
@@ -2456,15 +2587,15 @@ yy135:
YYDEBUG(135, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'O') {
- if (yych == 'L') goto yy507;
+ if (yych == 'L') goto yy515;
if (yych <= 'N') goto yy186;
- goto yy508;
+ goto yy516;
} else {
if (yych <= 'l') {
if (yych <= 'k') goto yy186;
- goto yy507;
+ goto yy515;
} else {
- if (yych == 'o') goto yy508;
+ if (yych == 'o') goto yy516;
goto yy186;
}
}
@@ -2472,15 +2603,15 @@ yy136:
YYDEBUG(136, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'U') {
- if (yych == 'R') goto yy483;
+ if (yych == 'R') goto yy491;
if (yych <= 'T') goto yy186;
- goto yy484;
+ goto yy492;
} else {
if (yych <= 'r') {
if (yych <= 'q') goto yy186;
- goto yy483;
+ goto yy491;
} else {
- if (yych == 'u') goto yy484;
+ if (yych == 'u') goto yy492;
goto yy186;
}
}
@@ -2488,28 +2619,28 @@ yy137:
YYDEBUG(137, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '<') {
- if (yych == '-') goto yy479;
+ if (yych == '-') goto yy487;
} else {
- if (yych <= '=') goto yy477;
- if (yych <= '>') goto yy481;
+ if (yych <= '=') goto yy485;
+ if (yych <= '>') goto yy489;
}
yy138:
YYDEBUG(138, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1289 "Zend/zend_language_scanner.l"
+#line 1438 "Zend/zend_language_scanner.l"
{
return yytext[0];
}
-#line 2504 "Zend/zend_language_scanner.c"
+#line 2635 "Zend/zend_language_scanner.c"
yy139:
YYDEBUG(139, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy476;
+ goto yy484;
yy140:
YYDEBUG(140, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1024 "Zend/zend_language_scanner.l"
+#line 1169 "Zend/zend_language_scanner.l"
{
zendlval->value.str.val = yytext; /* no copying - intentional */
zendlval->value.str.len = yyleng;
@@ -2517,43 +2648,43 @@ yy140:
HANDLE_NEWLINES(yytext, yyleng);
return T_WHITESPACE;
}
-#line 2521 "Zend/zend_language_scanner.c"
+#line 2652 "Zend/zend_language_scanner.c"
yy141:
YYDEBUG(141, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == ':') goto yy473;
+ if (yych == ':') goto yy481;
goto yy138;
yy142:
YYDEBUG(142, *YYCURSOR);
++YYCURSOR;
YYDEBUG(143, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1053 "Zend/zend_language_scanner.l"
+#line 1198 "Zend/zend_language_scanner.l"
{
return T_NS_SEPARATOR;
}
-#line 2536 "Zend/zend_language_scanner.c"
+#line 2667 "Zend/zend_language_scanner.c"
yy144:
YYDEBUG(144, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'E') {
- if (yych == 'A') goto yy461;
+ if (yych == 'A') goto yy469;
if (yych <= 'D') goto yy186;
- goto yy462;
+ goto yy470;
} else {
if (yych <= 'a') {
if (yych <= '`') goto yy186;
- goto yy461;
+ goto yy469;
} else {
- if (yych == 'e') goto yy462;
+ if (yych == 'e') goto yy470;
goto yy186;
}
}
yy145:
YYDEBUG(145, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy458;
- if (yych == 'a') goto yy458;
+ if (yych == 'A') goto yy466;
+ if (yych == 'a') goto yy466;
goto yy186;
yy146:
YYDEBUG(146, *YYCURSOR);
@@ -2562,47 +2693,47 @@ yy146:
if (yych <= 'S') {
if (yych <= 'D') {
if (yych <= ' ') {
- if (yych == '\t') goto yy379;
+ if (yych == '\t') goto yy391;
if (yych <= 0x1F) goto yy138;
- goto yy379;
+ goto yy391;
} else {
if (yych <= '@') goto yy138;
if (yych == 'C') goto yy138;
- goto yy379;
+ goto yy391;
}
} else {
if (yych <= 'I') {
- if (yych == 'F') goto yy379;
+ if (yych == 'F') goto yy391;
if (yych <= 'H') goto yy138;
- goto yy379;
+ goto yy391;
} else {
- if (yych == 'O') goto yy379;
+ if (yych == 'O') goto yy391;
if (yych <= 'Q') goto yy138;
- goto yy379;
+ goto yy391;
}
}
} else {
if (yych <= 'f') {
if (yych <= 'b') {
- if (yych == 'U') goto yy379;
+ if (yych == 'U') goto yy391;
if (yych <= '`') goto yy138;
- goto yy379;
+ goto yy391;
} else {
- if (yych == 'd') goto yy379;
+ if (yych == 'd') goto yy391;
if (yych <= 'e') goto yy138;
- goto yy379;
+ goto yy391;
}
} else {
if (yych <= 'o') {
- if (yych == 'i') goto yy379;
+ if (yych == 'i') goto yy391;
if (yych <= 'n') goto yy138;
- goto yy379;
+ goto yy391;
} else {
if (yych <= 's') {
if (yych <= 'q') goto yy138;
- goto yy379;
+ goto yy391;
} else {
- if (yych == 'u') goto yy379;
+ if (yych == 'u') goto yy391;
goto yy138;
}
}
@@ -2612,139 +2743,139 @@ yy147:
YYDEBUG(147, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'S') {
- if (yych == 'N') goto yy370;
+ if (yych == 'N') goto yy382;
if (yych <= 'R') goto yy186;
- goto yy371;
+ goto yy383;
} else {
if (yych <= 'n') {
if (yych <= 'm') goto yy186;
- goto yy370;
+ goto yy382;
} else {
- if (yych == 's') goto yy371;
+ if (yych == 's') goto yy383;
goto yy186;
}
}
yy148:
YYDEBUG(148, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '_') goto yy296;
+ if (yych == '_') goto yy300;
goto yy186;
yy149:
YYDEBUG(149, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '<') goto yy138;
- if (yych <= '=') goto yy290;
- if (yych <= '>') goto yy292;
+ if (yych <= '=') goto yy294;
+ if (yych <= '>') goto yy296;
goto yy138;
yy150:
YYDEBUG(150, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy286;
- if (yych == 'i') goto yy286;
+ if (yych == 'I') goto yy290;
+ if (yych == 'i') goto yy290;
goto yy186;
yy151:
YYDEBUG(151, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '+') goto yy284;
- if (yych == '=') goto yy282;
+ if (yych == '+') goto yy288;
+ if (yych == '=') goto yy286;
goto yy138;
yy152:
YYDEBUG(152, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '=') goto yy279;
+ if (yych == '=') goto yy283;
goto yy138;
yy153:
YYDEBUG(153, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= ';') {
- if (yych == '/') goto yy251;
+ if (yych == '/') goto yy255;
goto yy138;
} else {
- if (yych <= '<') goto yy249;
- if (yych <= '=') goto yy252;
- if (yych <= '>') goto yy254;
+ if (yych <= '<') goto yy253;
+ if (yych <= '=') goto yy256;
+ if (yych <= '>') goto yy258;
goto yy138;
}
yy154:
YYDEBUG(154, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '<') goto yy138;
- if (yych <= '=') goto yy245;
- if (yych <= '>') goto yy243;
+ if (yych <= '=') goto yy249;
+ if (yych <= '>') goto yy247;
goto yy138;
yy155:
YYDEBUG(155, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '=') goto yy241;
+ if (yych == '=') goto yy245;
goto yy138;
yy156:
YYDEBUG(156, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '.') {
- if (yych == '*') goto yy233;
+ if (yych == '*') goto yy237;
goto yy138;
} else {
- if (yych <= '/') goto yy235;
- if (yych == '=') goto yy236;
+ if (yych <= '/') goto yy239;
+ if (yych == '=') goto yy240;
goto yy138;
}
yy157:
YYDEBUG(157, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '/') goto yy138;
- if (yych <= '9') goto yy229;
- if (yych == '=') goto yy231;
+ if (yych <= '9') goto yy233;
+ if (yych == '=') goto yy235;
goto yy138;
yy158:
YYDEBUG(158, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '<') goto yy138;
- if (yych <= '=') goto yy225;
- if (yych <= '>') goto yy223;
+ if (yych <= '=') goto yy229;
+ if (yych <= '>') goto yy227;
goto yy138;
yy159:
YYDEBUG(159, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '&') goto yy219;
- if (yych == '=') goto yy221;
+ if (yych == '&') goto yy223;
+ if (yych == '=') goto yy225;
goto yy138;
yy160:
YYDEBUG(160, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '=') goto yy217;
- if (yych == '|') goto yy215;
+ if (yych == '=') goto yy221;
+ if (yych == '|') goto yy219;
goto yy138;
yy161:
YYDEBUG(161, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '=') goto yy213;
+ if (yych == '=') goto yy217;
goto yy138;
yy162:
YYDEBUG(162, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy211;
- if (yych == 'r') goto yy211;
+ if (yych == 'R') goto yy215;
+ if (yych == 'r') goto yy215;
goto yy186;
yy163:
YYDEBUG(163, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy208;
- if (yych == 'o') goto yy208;
+ if (yych == 'O') goto yy212;
+ if (yych == 'o') goto yy212;
goto yy186;
yy164:
YYDEBUG(164, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= '_') {
if (yych <= '@') goto yy138;
- if (yych <= 'Z') goto yy205;
+ if (yych <= 'Z') goto yy209;
if (yych <= '^') goto yy138;
- goto yy205;
+ goto yy209;
} else {
if (yych <= '`') goto yy138;
- if (yych <= 'z') goto yy205;
+ if (yych <= 'z') goto yy209;
if (yych <= '~') goto yy138;
- goto yy205;
+ goto yy209;
}
yy165:
YYDEBUG(165, *YYCURSOR);
@@ -2753,25 +2884,25 @@ yy165:
yy166:
YYDEBUG(166, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '>') goto yy201;
+ if (yych == '>') goto yy205;
goto yy138;
yy167:
YYDEBUG(167, *YYCURSOR);
++YYCURSOR;
YYDEBUG(168, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1294 "Zend/zend_language_scanner.l"
+#line 1443 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return '{';
}
-#line 2769 "Zend/zend_language_scanner.c"
+#line 2900 "Zend/zend_language_scanner.c"
yy169:
YYDEBUG(169, *YYCURSOR);
++YYCURSOR;
YYDEBUG(170, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1306 "Zend/zend_language_scanner.l"
+#line 1455 "Zend/zend_language_scanner.l"
{
RESET_DOC_COMMENT();
if (!zend_stack_is_empty(&SCNG(state_stack))) {
@@ -2779,30 +2910,35 @@ yy169:
}
return '}';
}
-#line 2783 "Zend/zend_language_scanner.c"
+#line 2914 "Zend/zend_language_scanner.c"
yy171:
YYDEBUG(171, *YYCURSOR);
yyaccept = 2;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= 'E') {
- if (yych <= '/') {
+ if (yych <= '9') {
if (yych == '.') goto yy187;
+ if (yych >= '0') goto yy190;
} else {
- if (yych <= '9') goto yy190;
+ if (yych == 'B') goto yy198;
if (yych >= 'E') goto yy192;
}
} else {
- if (yych <= 'd') {
+ if (yych <= 'b') {
if (yych == 'X') goto yy197;
+ if (yych >= 'b') goto yy198;
} else {
- if (yych <= 'e') goto yy192;
- if (yych == 'x') goto yy197;
+ if (yych <= 'e') {
+ if (yych >= 'e') goto yy192;
+ } else {
+ if (yych == 'x') goto yy197;
+ }
}
}
yy172:
YYDEBUG(172, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1332 "Zend/zend_language_scanner.l"
+#line 1505 "Zend/zend_language_scanner.l"
{
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
zendlval->value.lval = strtol(yytext, NULL, 0);
@@ -2823,7 +2959,7 @@ yy172:
zendlval->type = IS_LONG;
return T_LNUMBER;
}
-#line 2827 "Zend/zend_language_scanner.c"
+#line 2963 "Zend/zend_language_scanner.c"
yy173:
YYDEBUG(173, *YYCURSOR);
yyaccept = 2;
@@ -2851,7 +2987,7 @@ yy175:
yy176:
YYDEBUG(176, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1707 "Zend/zend_language_scanner.l"
+#line 1902 "Zend/zend_language_scanner.l"
{
while (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR++) {
@@ -2885,14 +3021,14 @@ yy176:
return T_COMMENT;
}
-#line 2889 "Zend/zend_language_scanner.c"
+#line 3025 "Zend/zend_language_scanner.c"
yy177:
YYDEBUG(177, *YYCURSOR);
++YYCURSOR;
yy178:
YYDEBUG(178, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1798 "Zend/zend_language_scanner.l"
+#line 1993 "Zend/zend_language_scanner.l"
{
register char *s, *t;
char *end;
@@ -2951,7 +3087,6 @@ yy178:
}
*t = 0;
-#ifdef ZEND_MULTIBYTE
if (SCNG(output_filter)) {
size_t sz = 0;
s = zendlval->value.str.val;
@@ -2959,17 +3094,16 @@ yy178:
zendlval->value.str.len = sz;
efree(s);
}
-#endif /* ZEND_MULTIBYTE */
return T_CONSTANT_ENCAPSED_STRING;
}
-#line 2966 "Zend/zend_language_scanner.c"
+#line 3100 "Zend/zend_language_scanner.c"
yy179:
YYDEBUG(179, *YYCURSOR);
++YYCURSOR;
yy180:
YYDEBUG(180, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1869 "Zend/zend_language_scanner.l"
+#line 2062 "Zend/zend_language_scanner.l"
{
int bprefix = (yytext[0] != '"') ? 1 : 0;
@@ -3010,24 +3144,24 @@ yy180:
BEGIN(ST_DOUBLE_QUOTES);
return '"';
}
-#line 3014 "Zend/zend_language_scanner.c"
+#line 3148 "Zend/zend_language_scanner.c"
yy181:
YYDEBUG(181, *YYCURSOR);
++YYCURSOR;
YYDEBUG(182, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1960 "Zend/zend_language_scanner.l"
+#line 2153 "Zend/zend_language_scanner.l"
{
BEGIN(ST_BACKQUOTE);
return '`';
}
-#line 3025 "Zend/zend_language_scanner.c"
+#line 3159 "Zend/zend_language_scanner.c"
yy183:
YYDEBUG(183, *YYCURSOR);
++YYCURSOR;
YYDEBUG(184, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2218 "Zend/zend_language_scanner.l"
+#line 2411 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -3036,7 +3170,7 @@ yy183:
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 3040 "Zend/zend_language_scanner.c"
+#line 3174 "Zend/zend_language_scanner.c"
yy185:
YYDEBUG(185, *YYCURSOR);
++YYCURSOR;
@@ -3044,7 +3178,7 @@ yy185:
yych = *YYCURSOR;
yy186:
YYDEBUG(186, *YYCURSOR);
- if (yybm[0+yych] & 8) {
+ if (yybm[0+yych] & 4) {
goto yy185;
}
goto yy124;
@@ -3055,7 +3189,7 @@ yy187:
YYFILL(3);
yych = *YYCURSOR;
YYDEBUG(188, *YYCURSOR);
- if (yybm[0+yych] & 16) {
+ if (yybm[0+yych] & 8) {
goto yy187;
}
if (yych == 'E') goto yy192;
@@ -3063,13 +3197,13 @@ yy187:
yy189:
YYDEBUG(189, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1397 "Zend/zend_language_scanner.l"
+#line 1570 "Zend/zend_language_scanner.l"
{
zendlval->value.dval = zend_strtod(yytext, NULL);
zendlval->type = IS_DOUBLE;
return T_DNUMBER;
}
-#line 3073 "Zend/zend_language_scanner.c"
+#line 3207 "Zend/zend_language_scanner.c"
yy190:
YYDEBUG(190, *YYCURSOR);
yyaccept = 2;
@@ -3116,10 +3250,10 @@ yy193:
if (yyaccept <= 3) {
goto yy189;
} else {
- goto yy234;
+ goto yy238;
}
} else {
- goto yy250;
+ goto yy254;
}
}
yy194:
@@ -3140,21 +3274,65 @@ yy197:
YYDEBUG(197, *YYCURSOR);
yych = *++YYCURSOR;
if (yybm[0+yych] & 32) {
- goto yy198;
+ goto yy202;
}
goto yy193;
yy198:
YYDEBUG(198, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yybm[0+yych] & 16) {
+ goto yy199;
+ }
+ goto yy193;
+yy199:
+ YYDEBUG(199, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(199, *YYCURSOR);
+ YYDEBUG(200, *YYCURSOR);
+ if (yybm[0+yych] & 16) {
+ goto yy199;
+ }
+ YYDEBUG(201, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1480 "Zend/zend_language_scanner.l"
+ {
+ char *bin = yytext + 2; /* Skip "0b" */
+ int len = yyleng - 2;
+
+ /* Skip any leading 0s */
+ while (*bin == '0') {
+ ++bin;
+ --len;
+ }
+
+ if (len < SIZEOF_LONG * 8) {
+ if (len == 0) {
+ zendlval->value.lval = 0;
+ } else {
+ zendlval->value.lval = strtol(bin, NULL, 2);
+ }
+ zendlval->type = IS_LONG;
+ return T_LNUMBER;
+ } else {
+ zendlval->value.dval = zend_bin_strtod(bin, NULL);
+ zendlval->type = IS_DOUBLE;
+ return T_DNUMBER;
+ }
+}
+#line 3324 "Zend/zend_language_scanner.c"
+yy202:
+ YYDEBUG(202, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(203, *YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy198;
+ goto yy202;
}
- YYDEBUG(200, *YYCURSOR);
+ YYDEBUG(204, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1353 "Zend/zend_language_scanner.l"
+#line 1526 "Zend/zend_language_scanner.l"
{
char *hex = yytext + 2; /* Skip "0x" */
int len = yyleng - 2;
@@ -3179,16 +3357,16 @@ yy198:
return T_DNUMBER;
}
}
-#line 3183 "Zend/zend_language_scanner.c"
-yy201:
- YYDEBUG(201, *YYCURSOR);
+#line 3361 "Zend/zend_language_scanner.c"
+yy205:
+ YYDEBUG(205, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '\n') goto yy203;
- if (yych == '\r') goto yy204;
-yy202:
- YYDEBUG(202, *YYCURSOR);
+ if ((yych = *YYCURSOR) == '\n') goto yy207;
+ if (yych == '\r') goto yy208;
+yy206:
+ YYDEBUG(206, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1775 "Zend/zend_language_scanner.l"
+#line 1970 "Zend/zend_language_scanner.l"
{
zendlval->value.str.val = yytext; /* no copying - intentional */
zendlval->value.str.len = yyleng;
@@ -3196,137 +3374,137 @@ yy202:
BEGIN(INITIAL);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
}
-#line 3200 "Zend/zend_language_scanner.c"
-yy203:
- YYDEBUG(203, *YYCURSOR);
+#line 3378 "Zend/zend_language_scanner.c"
+yy207:
+ YYDEBUG(207, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy202;
-yy204:
- YYDEBUG(204, *YYCURSOR);
+ goto yy206;
+yy208:
+ YYDEBUG(208, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy203;
- goto yy202;
-yy205:
- YYDEBUG(205, *YYCURSOR);
+ if (yych == '\n') goto yy207;
+ goto yy206;
+yy209:
+ YYDEBUG(209, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(206, *YYCURSOR);
+ YYDEBUG(210, *YYCURSOR);
if (yych <= '^') {
if (yych <= '9') {
- if (yych >= '0') goto yy205;
+ if (yych >= '0') goto yy209;
} else {
- if (yych <= '@') goto yy207;
- if (yych <= 'Z') goto yy205;
+ if (yych <= '@') goto yy211;
+ if (yych <= 'Z') goto yy209;
}
} else {
if (yych <= '`') {
- if (yych <= '_') goto yy205;
+ if (yych <= '_') goto yy209;
} else {
- if (yych <= 'z') goto yy205;
- if (yych >= 0x7F) goto yy205;
+ if (yych <= 'z') goto yy209;
+ if (yych >= 0x7F) goto yy209;
}
}
-yy207:
- YYDEBUG(207, *YYCURSOR);
+yy211:
+ YYDEBUG(211, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1677 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 3240 "Zend/zend_language_scanner.c"
-yy208:
- YYDEBUG(208, *YYCURSOR);
+#line 3418 "Zend/zend_language_scanner.c"
+yy212:
+ YYDEBUG(212, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy209;
+ if (yych == 'R') goto yy213;
if (yych != 'r') goto yy186;
-yy209:
- YYDEBUG(209, *YYCURSOR);
+yy213:
+ YYDEBUG(213, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(210, *YYCURSOR);
+ YYDEBUG(214, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1277 "Zend/zend_language_scanner.l"
+#line 1426 "Zend/zend_language_scanner.l"
{
return T_LOGICAL_XOR;
}
-#line 3258 "Zend/zend_language_scanner.c"
-yy211:
- YYDEBUG(211, *YYCURSOR);
+#line 3436 "Zend/zend_language_scanner.c"
+yy215:
+ YYDEBUG(215, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(212, *YYCURSOR);
+ YYDEBUG(216, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1269 "Zend/zend_language_scanner.l"
+#line 1418 "Zend/zend_language_scanner.l"
{
return T_LOGICAL_OR;
}
-#line 3271 "Zend/zend_language_scanner.c"
-yy213:
- YYDEBUG(213, *YYCURSOR);
+#line 3449 "Zend/zend_language_scanner.c"
+yy217:
+ YYDEBUG(217, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(214, *YYCURSOR);
+ YYDEBUG(218, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1257 "Zend/zend_language_scanner.l"
+#line 1406 "Zend/zend_language_scanner.l"
{
return T_XOR_EQUAL;
}
-#line 3281 "Zend/zend_language_scanner.c"
-yy215:
- YYDEBUG(215, *YYCURSOR);
+#line 3459 "Zend/zend_language_scanner.c"
+yy219:
+ YYDEBUG(219, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(216, *YYCURSOR);
+ YYDEBUG(220, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1261 "Zend/zend_language_scanner.l"
+#line 1410 "Zend/zend_language_scanner.l"
{
return T_BOOLEAN_OR;
}
-#line 3291 "Zend/zend_language_scanner.c"
-yy217:
- YYDEBUG(217, *YYCURSOR);
+#line 3469 "Zend/zend_language_scanner.c"
+yy221:
+ YYDEBUG(221, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(218, *YYCURSOR);
+ YYDEBUG(222, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1253 "Zend/zend_language_scanner.l"
+#line 1402 "Zend/zend_language_scanner.l"
{
return T_OR_EQUAL;
}
-#line 3301 "Zend/zend_language_scanner.c"
-yy219:
- YYDEBUG(219, *YYCURSOR);
+#line 3479 "Zend/zend_language_scanner.c"
+yy223:
+ YYDEBUG(223, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(220, *YYCURSOR);
+ YYDEBUG(224, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1265 "Zend/zend_language_scanner.l"
+#line 1414 "Zend/zend_language_scanner.l"
{
return T_BOOLEAN_AND;
}
-#line 3311 "Zend/zend_language_scanner.c"
-yy221:
- YYDEBUG(221, *YYCURSOR);
+#line 3489 "Zend/zend_language_scanner.c"
+yy225:
+ YYDEBUG(225, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(222, *YYCURSOR);
+ YYDEBUG(226, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1249 "Zend/zend_language_scanner.l"
+#line 1398 "Zend/zend_language_scanner.l"
{
return T_AND_EQUAL;
}
-#line 3321 "Zend/zend_language_scanner.c"
-yy223:
- YYDEBUG(223, *YYCURSOR);
+#line 3499 "Zend/zend_language_scanner.c"
+yy227:
+ YYDEBUG(227, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '\n') goto yy227;
- if (yych == '\r') goto yy228;
-yy224:
- YYDEBUG(224, *YYCURSOR);
+ if ((yych = *YYCURSOR) == '\n') goto yy231;
+ if (yych == '\r') goto yy232;
+yy228:
+ YYDEBUG(228, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1784 "Zend/zend_language_scanner.l"
+#line 1979 "Zend/zend_language_scanner.l"
{
if (CG(asp_tags)) {
BEGIN(INITIAL);
@@ -3339,61 +3517,61 @@ yy224:
return yytext[0];
}
}
-#line 3343 "Zend/zend_language_scanner.c"
-yy225:
- YYDEBUG(225, *YYCURSOR);
+#line 3521 "Zend/zend_language_scanner.c"
+yy229:
+ YYDEBUG(229, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(226, *YYCURSOR);
+ YYDEBUG(230, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1237 "Zend/zend_language_scanner.l"
+#line 1386 "Zend/zend_language_scanner.l"
{
return T_MOD_EQUAL;
}
-#line 3353 "Zend/zend_language_scanner.c"
-yy227:
- YYDEBUG(227, *YYCURSOR);
+#line 3531 "Zend/zend_language_scanner.c"
+yy231:
+ YYDEBUG(231, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy224;
-yy228:
- YYDEBUG(228, *YYCURSOR);
+ goto yy228;
+yy232:
+ YYDEBUG(232, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy227;
- goto yy224;
-yy229:
- YYDEBUG(229, *YYCURSOR);
+ if (yych == '\n') goto yy231;
+ goto yy228;
+yy233:
+ YYDEBUG(233, *YYCURSOR);
yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
- YYDEBUG(230, *YYCURSOR);
+ YYDEBUG(234, *YYCURSOR);
if (yych <= 'D') {
if (yych <= '/') goto yy189;
- if (yych <= '9') goto yy229;
+ if (yych <= '9') goto yy233;
goto yy189;
} else {
if (yych <= 'E') goto yy192;
if (yych == 'e') goto yy192;
goto yy189;
}
-yy231:
- YYDEBUG(231, *YYCURSOR);
+yy235:
+ YYDEBUG(235, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(232, *YYCURSOR);
+ YYDEBUG(236, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1233 "Zend/zend_language_scanner.l"
+#line 1382 "Zend/zend_language_scanner.l"
{
return T_CONCAT_EQUAL;
}
-#line 3388 "Zend/zend_language_scanner.c"
-yy233:
- YYDEBUG(233, *YYCURSOR);
+#line 3566 "Zend/zend_language_scanner.c"
+yy237:
+ YYDEBUG(237, *YYCURSOR);
yyaccept = 4;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == '*') goto yy238;
-yy234:
- YYDEBUG(234, *YYCURSOR);
+ if (yych == '*') goto yy242;
+yy238:
+ YYDEBUG(238, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1741 "Zend/zend_language_scanner.l"
+#line 1936 "Zend/zend_language_scanner.l"
{
int doc_com;
@@ -3427,281 +3605,281 @@ yy234:
return T_COMMENT;
}
-#line 3431 "Zend/zend_language_scanner.c"
-yy235:
- YYDEBUG(235, *YYCURSOR);
+#line 3609 "Zend/zend_language_scanner.c"
+yy239:
+ YYDEBUG(239, *YYCURSOR);
yych = *++YYCURSOR;
goto yy176;
-yy236:
- YYDEBUG(236, *YYCURSOR);
+yy240:
+ YYDEBUG(240, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(237, *YYCURSOR);
+ YYDEBUG(241, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1229 "Zend/zend_language_scanner.l"
+#line 1378 "Zend/zend_language_scanner.l"
{
return T_DIV_EQUAL;
}
-#line 3445 "Zend/zend_language_scanner.c"
-yy238:
- YYDEBUG(238, *YYCURSOR);
+#line 3623 "Zend/zend_language_scanner.c"
+yy242:
+ YYDEBUG(242, *YYCURSOR);
yych = *++YYCURSOR;
if (yybm[0+yych] & 64) {
- goto yy239;
+ goto yy243;
}
goto yy193;
-yy239:
- YYDEBUG(239, *YYCURSOR);
+yy243:
+ YYDEBUG(243, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(240, *YYCURSOR);
+ YYDEBUG(244, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy239;
+ goto yy243;
}
- goto yy234;
-yy241:
- YYDEBUG(241, *YYCURSOR);
+ goto yy238;
+yy245:
+ YYDEBUG(245, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(242, *YYCURSOR);
+ YYDEBUG(246, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1225 "Zend/zend_language_scanner.l"
+#line 1374 "Zend/zend_language_scanner.l"
{
return T_MUL_EQUAL;
}
-#line 3472 "Zend/zend_language_scanner.c"
-yy243:
- YYDEBUG(243, *YYCURSOR);
+#line 3650 "Zend/zend_language_scanner.c"
+yy247:
+ YYDEBUG(247, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '=') goto yy247;
- YYDEBUG(244, *YYCURSOR);
+ if ((yych = *YYCURSOR) == '=') goto yy251;
+ YYDEBUG(248, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1285 "Zend/zend_language_scanner.l"
+#line 1434 "Zend/zend_language_scanner.l"
{
return T_SR;
}
-#line 3483 "Zend/zend_language_scanner.c"
-yy245:
- YYDEBUG(245, *YYCURSOR);
+#line 3661 "Zend/zend_language_scanner.c"
+yy249:
+ YYDEBUG(249, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(246, *YYCURSOR);
+ YYDEBUG(250, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1213 "Zend/zend_language_scanner.l"
+#line 1362 "Zend/zend_language_scanner.l"
{
return T_IS_GREATER_OR_EQUAL;
}
-#line 3493 "Zend/zend_language_scanner.c"
-yy247:
- YYDEBUG(247, *YYCURSOR);
+#line 3671 "Zend/zend_language_scanner.c"
+yy251:
+ YYDEBUG(251, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(248, *YYCURSOR);
+ YYDEBUG(252, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1245 "Zend/zend_language_scanner.l"
+#line 1394 "Zend/zend_language_scanner.l"
{
return T_SR_EQUAL;
}
-#line 3503 "Zend/zend_language_scanner.c"
-yy249:
- YYDEBUG(249, *YYCURSOR);
+#line 3681 "Zend/zend_language_scanner.c"
+yy253:
+ YYDEBUG(253, *YYCURSOR);
yyaccept = 5;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= ';') goto yy250;
- if (yych <= '<') goto yy265;
- if (yych <= '=') goto yy263;
-yy250:
- YYDEBUG(250, *YYCURSOR);
+ if (yych <= ';') goto yy254;
+ if (yych <= '<') goto yy269;
+ if (yych <= '=') goto yy267;
+yy254:
+ YYDEBUG(254, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1281 "Zend/zend_language_scanner.l"
+#line 1430 "Zend/zend_language_scanner.l"
{
return T_SL;
}
-#line 3518 "Zend/zend_language_scanner.c"
-yy251:
- YYDEBUG(251, *YYCURSOR);
+#line 3696 "Zend/zend_language_scanner.c"
+yy255:
+ YYDEBUG(255, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy256;
- if (yych == 's') goto yy256;
+ if (yych == 'S') goto yy260;
+ if (yych == 's') goto yy260;
goto yy193;
-yy252:
- YYDEBUG(252, *YYCURSOR);
+yy256:
+ YYDEBUG(256, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(253, *YYCURSOR);
+ YYDEBUG(257, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1209 "Zend/zend_language_scanner.l"
+#line 1358 "Zend/zend_language_scanner.l"
{
return T_IS_SMALLER_OR_EQUAL;
}
-#line 3534 "Zend/zend_language_scanner.c"
-yy254:
- YYDEBUG(254, *YYCURSOR);
+#line 3712 "Zend/zend_language_scanner.c"
+yy258:
+ YYDEBUG(258, *YYCURSOR);
++YYCURSOR;
-yy255:
- YYDEBUG(255, *YYCURSOR);
+yy259:
+ YYDEBUG(259, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1205 "Zend/zend_language_scanner.l"
+#line 1354 "Zend/zend_language_scanner.l"
{
return T_IS_NOT_EQUAL;
}
-#line 3545 "Zend/zend_language_scanner.c"
-yy256:
- YYDEBUG(256, *YYCURSOR);
+#line 3723 "Zend/zend_language_scanner.c"
+yy260:
+ YYDEBUG(260, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy257;
+ if (yych == 'C') goto yy261;
if (yych != 'c') goto yy193;
-yy257:
- YYDEBUG(257, *YYCURSOR);
+yy261:
+ YYDEBUG(261, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy258;
+ if (yych == 'R') goto yy262;
if (yych != 'r') goto yy193;
-yy258:
- YYDEBUG(258, *YYCURSOR);
+yy262:
+ YYDEBUG(262, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy259;
+ if (yych == 'I') goto yy263;
if (yych != 'i') goto yy193;
-yy259:
- YYDEBUG(259, *YYCURSOR);
+yy263:
+ YYDEBUG(263, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'P') goto yy260;
+ if (yych == 'P') goto yy264;
if (yych != 'p') goto yy193;
-yy260:
- YYDEBUG(260, *YYCURSOR);
+yy264:
+ YYDEBUG(264, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy261;
+ if (yych == 'T') goto yy265;
if (yych != 't') goto yy193;
-yy261:
- YYDEBUG(261, *YYCURSOR);
+yy265:
+ YYDEBUG(265, *YYCURSOR);
++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
- YYDEBUG(262, *YYCURSOR);
+ YYDEBUG(266, *YYCURSOR);
if (yych <= '\r') {
if (yych <= 0x08) goto yy193;
- if (yych <= '\n') goto yy261;
+ if (yych <= '\n') goto yy265;
if (yych <= '\f') goto yy193;
- goto yy261;
+ goto yy265;
} else {
if (yych <= ' ') {
if (yych <= 0x1F) goto yy193;
- goto yy261;
+ goto yy265;
} else {
- if (yych == '>') goto yy201;
+ if (yych == '>') goto yy205;
goto yy193;
}
}
-yy263:
- YYDEBUG(263, *YYCURSOR);
+yy267:
+ YYDEBUG(267, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(264, *YYCURSOR);
+ YYDEBUG(268, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1241 "Zend/zend_language_scanner.l"
+#line 1390 "Zend/zend_language_scanner.l"
{
return T_SL_EQUAL;
}
-#line 3600 "Zend/zend_language_scanner.c"
-yy265:
- YYDEBUG(265, *YYCURSOR);
+#line 3778 "Zend/zend_language_scanner.c"
+yy269:
+ YYDEBUG(269, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
- YYDEBUG(266, *YYCURSOR);
+ YYDEBUG(270, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy265;
+ goto yy269;
}
if (yych <= 'Z') {
if (yych <= '&') {
- if (yych == '"') goto yy270;
+ if (yych == '"') goto yy274;
goto yy193;
} else {
- if (yych <= '\'') goto yy269;
+ if (yych <= '\'') goto yy273;
if (yych <= '@') goto yy193;
}
} else {
if (yych <= '`') {
if (yych != '_') goto yy193;
} else {
- if (yych <= 'z') goto yy267;
+ if (yych <= 'z') goto yy271;
if (yych <= '~') goto yy193;
}
}
-yy267:
- YYDEBUG(267, *YYCURSOR);
+yy271:
+ YYDEBUG(271, *YYCURSOR);
++YYCURSOR;
YYFILL(2);
yych = *YYCURSOR;
- YYDEBUG(268, *YYCURSOR);
+ YYDEBUG(272, *YYCURSOR);
if (yych <= '@') {
if (yych <= '\f') {
- if (yych == '\n') goto yy274;
+ if (yych == '\n') goto yy278;
goto yy193;
} else {
- if (yych <= '\r') goto yy276;
+ if (yych <= '\r') goto yy280;
if (yych <= '/') goto yy193;
- if (yych <= '9') goto yy267;
+ if (yych <= '9') goto yy271;
goto yy193;
}
} else {
if (yych <= '_') {
- if (yych <= 'Z') goto yy267;
+ if (yych <= 'Z') goto yy271;
if (yych <= '^') goto yy193;
- goto yy267;
+ goto yy271;
} else {
if (yych <= '`') goto yy193;
- if (yych <= 'z') goto yy267;
+ if (yych <= 'z') goto yy271;
if (yych <= '~') goto yy193;
- goto yy267;
+ goto yy271;
}
}
-yy269:
- YYDEBUG(269, *YYCURSOR);
+yy273:
+ YYDEBUG(273, *YYCURSOR);
yych = *++YYCURSOR;
if (yych == '\'') goto yy193;
- if (yych <= '/') goto yy278;
+ if (yych <= '/') goto yy282;
if (yych <= '9') goto yy193;
- goto yy278;
-yy270:
- YYDEBUG(270, *YYCURSOR);
+ goto yy282;
+yy274:
+ YYDEBUG(274, *YYCURSOR);
yych = *++YYCURSOR;
if (yych == '"') goto yy193;
- if (yych <= '/') goto yy272;
+ if (yych <= '/') goto yy276;
if (yych <= '9') goto yy193;
- goto yy272;
-yy271:
- YYDEBUG(271, *YYCURSOR);
+ goto yy276;
+yy275:
+ YYDEBUG(275, *YYCURSOR);
++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
-yy272:
- YYDEBUG(272, *YYCURSOR);
+yy276:
+ YYDEBUG(276, *YYCURSOR);
if (yych <= 'Z') {
if (yych <= '/') {
if (yych != '"') goto yy193;
} else {
- if (yych <= '9') goto yy271;
+ if (yych <= '9') goto yy275;
if (yych <= '@') goto yy193;
- goto yy271;
+ goto yy275;
}
} else {
if (yych <= '`') {
- if (yych == '_') goto yy271;
+ if (yych == '_') goto yy275;
goto yy193;
} else {
- if (yych <= 'z') goto yy271;
+ if (yych <= 'z') goto yy275;
if (yych <= '~') goto yy193;
- goto yy271;
+ goto yy275;
}
}
-yy273:
- YYDEBUG(273, *YYCURSOR);
+yy277:
+ YYDEBUG(277, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy274;
- if (yych == '\r') goto yy276;
+ if (yych == '\n') goto yy278;
+ if (yych == '\r') goto yy280;
goto yy193;
-yy274:
- YYDEBUG(274, *YYCURSOR);
+yy278:
+ YYDEBUG(278, *YYCURSOR);
++YYCURSOR;
-yy275:
- YYDEBUG(275, *YYCURSOR);
+yy279:
+ YYDEBUG(279, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1911 "Zend/zend_language_scanner.l"
+#line 2104 "Zend/zend_language_scanner.l"
{
char *s;
int bprefix = (yytext[0] != '<') ? 1 : 0;
@@ -3749,217 +3927,200 @@ yy275:
return T_START_HEREDOC;
}
-#line 3753 "Zend/zend_language_scanner.c"
-yy276:
- YYDEBUG(276, *YYCURSOR);
+#line 3931 "Zend/zend_language_scanner.c"
+yy280:
+ YYDEBUG(280, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '\n') goto yy274;
- goto yy275;
-yy277:
- YYDEBUG(277, *YYCURSOR);
+ if (yych == '\n') goto yy278;
+ goto yy279;
+yy281:
+ YYDEBUG(281, *YYCURSOR);
++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
-yy278:
- YYDEBUG(278, *YYCURSOR);
+yy282:
+ YYDEBUG(282, *YYCURSOR);
if (yych <= 'Z') {
if (yych <= '/') {
- if (yych == '\'') goto yy273;
+ if (yych == '\'') goto yy277;
goto yy193;
} else {
- if (yych <= '9') goto yy277;
+ if (yych <= '9') goto yy281;
if (yych <= '@') goto yy193;
- goto yy277;
+ goto yy281;
}
} else {
if (yych <= '`') {
- if (yych == '_') goto yy277;
+ if (yych == '_') goto yy281;
goto yy193;
} else {
- if (yych <= 'z') goto yy277;
+ if (yych <= 'z') goto yy281;
if (yych <= '~') goto yy193;
- goto yy277;
+ goto yy281;
}
}
-yy279:
- YYDEBUG(279, *YYCURSOR);
+yy283:
+ YYDEBUG(283, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych != '=') goto yy255;
- YYDEBUG(280, *YYCURSOR);
+ if (yych != '=') goto yy259;
+ YYDEBUG(284, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(281, *YYCURSOR);
+ YYDEBUG(285, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1197 "Zend/zend_language_scanner.l"
+#line 1346 "Zend/zend_language_scanner.l"
{
return T_IS_NOT_IDENTICAL;
}
-#line 3797 "Zend/zend_language_scanner.c"
-yy282:
- YYDEBUG(282, *YYCURSOR);
+#line 3975 "Zend/zend_language_scanner.c"
+yy286:
+ YYDEBUG(286, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(283, *YYCURSOR);
+ YYDEBUG(287, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1217 "Zend/zend_language_scanner.l"
+#line 1366 "Zend/zend_language_scanner.l"
{
return T_PLUS_EQUAL;
}
-#line 3807 "Zend/zend_language_scanner.c"
-yy284:
- YYDEBUG(284, *YYCURSOR);
+#line 3985 "Zend/zend_language_scanner.c"
+yy288:
+ YYDEBUG(288, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(285, *YYCURSOR);
+ YYDEBUG(289, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1185 "Zend/zend_language_scanner.l"
+#line 1334 "Zend/zend_language_scanner.l"
{
return T_INC;
}
-#line 3817 "Zend/zend_language_scanner.c"
-yy286:
- YYDEBUG(286, *YYCURSOR);
+#line 3995 "Zend/zend_language_scanner.c"
+yy290:
+ YYDEBUG(290, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy287;
+ if (yych == 'S') goto yy291;
if (yych != 's') goto yy186;
-yy287:
- YYDEBUG(287, *YYCURSOR);
+yy291:
+ YYDEBUG(291, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy288;
+ if (yych == 'T') goto yy292;
if (yych != 't') goto yy186;
-yy288:
- YYDEBUG(288, *YYCURSOR);
+yy292:
+ YYDEBUG(292, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(289, *YYCURSOR);
+ YYDEBUG(293, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1177 "Zend/zend_language_scanner.l"
+#line 1322 "Zend/zend_language_scanner.l"
{
return T_LIST;
}
-#line 3840 "Zend/zend_language_scanner.c"
-yy290:
- YYDEBUG(290, *YYCURSOR);
+#line 4018 "Zend/zend_language_scanner.c"
+yy294:
+ YYDEBUG(294, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '=') goto yy294;
- YYDEBUG(291, *YYCURSOR);
+ if ((yych = *YYCURSOR) == '=') goto yy298;
+ YYDEBUG(295, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1201 "Zend/zend_language_scanner.l"
+#line 1350 "Zend/zend_language_scanner.l"
{
return T_IS_EQUAL;
}
-#line 3851 "Zend/zend_language_scanner.c"
-yy292:
- YYDEBUG(292, *YYCURSOR);
+#line 4029 "Zend/zend_language_scanner.c"
+yy296:
+ YYDEBUG(296, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(293, *YYCURSOR);
+ YYDEBUG(297, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1173 "Zend/zend_language_scanner.l"
+#line 1318 "Zend/zend_language_scanner.l"
{
return T_DOUBLE_ARROW;
}
-#line 3861 "Zend/zend_language_scanner.c"
-yy294:
- YYDEBUG(294, *YYCURSOR);
+#line 4039 "Zend/zend_language_scanner.c"
+yy298:
+ YYDEBUG(298, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(295, *YYCURSOR);
+ YYDEBUG(299, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1193 "Zend/zend_language_scanner.l"
+#line 1342 "Zend/zend_language_scanner.l"
{
return T_IS_IDENTICAL;
}
-#line 3871 "Zend/zend_language_scanner.c"
-yy296:
- YYDEBUG(296, *YYCURSOR);
+#line 4049 "Zend/zend_language_scanner.c"
+yy300:
+ YYDEBUG(300, *YYCURSOR);
yych = *++YYCURSOR;
YYDEBUG(-1, yych);
switch (yych) {
case 'C':
- case 'c': goto yy298;
+ case 'c': goto yy302;
case 'D':
- case 'd': goto yy302;
+ case 'd': goto yy307;
case 'F':
- case 'f': goto yy299;
+ case 'f': goto yy304;
case 'H':
- case 'h': goto yy297;
+ case 'h': goto yy301;
case 'L':
- case 'l': goto yy301;
+ case 'l': goto yy306;
case 'M':
- case 'm': goto yy300;
+ case 'm': goto yy305;
case 'N':
- case 'n': goto yy303;
+ case 'n': goto yy308;
+ case 'T':
+ case 't': goto yy303;
default: goto yy186;
}
-yy297:
- YYDEBUG(297, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'A') goto yy357;
- if (yych == 'a') goto yy357;
- goto yy186;
-yy298:
- YYDEBUG(298, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'L') goto yy350;
- if (yych == 'l') goto yy350;
- goto yy186;
-yy299:
- YYDEBUG(299, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych <= 'U') {
- if (yych == 'I') goto yy334;
- if (yych <= 'T') goto yy186;
- goto yy335;
- } else {
- if (yych <= 'i') {
- if (yych <= 'h') goto yy186;
- goto yy334;
- } else {
- if (yych == 'u') goto yy335;
- goto yy186;
- }
- }
-yy300:
- YYDEBUG(300, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'E') goto yy326;
- if (yych == 'e') goto yy326;
- goto yy186;
yy301:
YYDEBUG(301, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy320;
- if (yych == 'i') goto yy320;
+ if (yych == 'A') goto yy369;
+ if (yych == 'a') goto yy369;
goto yy186;
yy302:
YYDEBUG(302, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy315;
- if (yych == 'i') goto yy315;
+ if (yych == 'L') goto yy362;
+ if (yych == 'l') goto yy362;
goto yy186;
yy303:
YYDEBUG(303, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy304;
- if (yych != 'a') goto yy186;
+ if (yych == 'R') goto yy355;
+ if (yych == 'r') goto yy355;
+ goto yy186;
yy304:
YYDEBUG(304, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'M') goto yy305;
- if (yych != 'm') goto yy186;
+ if (yych <= 'U') {
+ if (yych == 'I') goto yy339;
+ if (yych <= 'T') goto yy186;
+ goto yy340;
+ } else {
+ if (yych <= 'i') {
+ if (yych <= 'h') goto yy186;
+ goto yy339;
+ } else {
+ if (yych == 'u') goto yy340;
+ goto yy186;
+ }
+ }
yy305:
YYDEBUG(305, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy306;
- if (yych != 'e') goto yy186;
+ if (yych == 'E') goto yy331;
+ if (yych == 'e') goto yy331;
+ goto yy186;
yy306:
YYDEBUG(306, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy307;
- if (yych != 's') goto yy186;
+ if (yych == 'I') goto yy325;
+ if (yych == 'i') goto yy325;
+ goto yy186;
yy307:
YYDEBUG(307, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'P') goto yy308;
- if (yych != 'p') goto yy186;
+ if (yych == 'I') goto yy320;
+ if (yych == 'i') goto yy320;
+ goto yy186;
yy308:
YYDEBUG(308, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3968,8 +4129,8 @@ yy308:
yy309:
YYDEBUG(309, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy310;
- if (yych != 'c') goto yy186;
+ if (yych == 'M') goto yy310;
+ if (yych != 'm') goto yy186;
yy310:
YYDEBUG(310, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3978,18 +4139,43 @@ yy310:
yy311:
YYDEBUG(311, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych != '_') goto yy186;
+ if (yych == 'S') goto yy312;
+ if (yych != 's') goto yy186;
+yy312:
YYDEBUG(312, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych != '_') goto yy186;
+ if (yych == 'P') goto yy313;
+ if (yych != 'p') goto yy186;
+yy313:
YYDEBUG(313, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'A') goto yy314;
+ if (yych != 'a') goto yy186;
+yy314:
+ YYDEBUG(314, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'C') goto yy315;
+ if (yych != 'c') goto yy186;
+yy315:
+ YYDEBUG(315, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy316;
+ if (yych != 'e') goto yy186;
+yy316:
+ YYDEBUG(316, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych != '_') goto yy186;
+ YYDEBUG(317, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych != '_') goto yy186;
+ YYDEBUG(318, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(314, *YYCURSOR);
+ YYDEBUG(319, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1501 "Zend/zend_language_scanner.l"
+#line 1705 "Zend/zend_language_scanner.l"
{
if (CG(current_namespace)) {
*zendlval = *CG(current_namespace);
@@ -3999,27 +4185,27 @@ yy311:
}
return T_NS_C;
}
-#line 4003 "Zend/zend_language_scanner.c"
-yy315:
- YYDEBUG(315, *YYCURSOR);
+#line 4189 "Zend/zend_language_scanner.c"
+yy320:
+ YYDEBUG(320, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy316;
+ if (yych == 'R') goto yy321;
if (yych != 'r') goto yy186;
-yy316:
- YYDEBUG(316, *YYCURSOR);
+yy321:
+ YYDEBUG(321, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(317, *YYCURSOR);
+ YYDEBUG(322, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(318, *YYCURSOR);
+ YYDEBUG(323, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(319, *YYCURSOR);
+ YYDEBUG(324, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1474 "Zend/zend_language_scanner.l"
+#line 1678 "Zend/zend_language_scanner.l"
{
char *filename = zend_get_compiled_filename(TSRMLS_C);
const size_t filename_len = strlen(filename);
@@ -4046,76 +4232,76 @@ yy316:
zendlval->type = IS_STRING;
return T_DIR;
}
-#line 4050 "Zend/zend_language_scanner.c"
-yy320:
- YYDEBUG(320, *YYCURSOR);
+#line 4236 "Zend/zend_language_scanner.c"
+yy325:
+ YYDEBUG(325, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy321;
+ if (yych == 'N') goto yy326;
if (yych != 'n') goto yy186;
-yy321:
- YYDEBUG(321, *YYCURSOR);
+yy326:
+ YYDEBUG(326, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy322;
+ if (yych == 'E') goto yy327;
if (yych != 'e') goto yy186;
-yy322:
- YYDEBUG(322, *YYCURSOR);
+yy327:
+ YYDEBUG(327, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(323, *YYCURSOR);
+ YYDEBUG(328, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(324, *YYCURSOR);
+ YYDEBUG(329, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(325, *YYCURSOR);
+ YYDEBUG(330, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1456 "Zend/zend_language_scanner.l"
+#line 1660 "Zend/zend_language_scanner.l"
{
zendlval->value.lval = CG(zend_lineno);
zendlval->type = IS_LONG;
return T_LINE;
}
-#line 4081 "Zend/zend_language_scanner.c"
-yy326:
- YYDEBUG(326, *YYCURSOR);
+#line 4267 "Zend/zend_language_scanner.c"
+yy331:
+ YYDEBUG(331, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy327;
+ if (yych == 'T') goto yy332;
if (yych != 't') goto yy186;
-yy327:
- YYDEBUG(327, *YYCURSOR);
+yy332:
+ YYDEBUG(332, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy328;
+ if (yych == 'H') goto yy333;
if (yych != 'h') goto yy186;
-yy328:
- YYDEBUG(328, *YYCURSOR);
+yy333:
+ YYDEBUG(333, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy329;
+ if (yych == 'O') goto yy334;
if (yych != 'o') goto yy186;
-yy329:
- YYDEBUG(329, *YYCURSOR);
+yy334:
+ YYDEBUG(334, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'D') goto yy330;
+ if (yych == 'D') goto yy335;
if (yych != 'd') goto yy186;
-yy330:
- YYDEBUG(330, *YYCURSOR);
+yy335:
+ YYDEBUG(335, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(331, *YYCURSOR);
+ YYDEBUG(336, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(332, *YYCURSOR);
+ YYDEBUG(337, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(333, *YYCURSOR);
+ YYDEBUG(338, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1435 "Zend/zend_language_scanner.l"
+#line 1639 "Zend/zend_language_scanner.l"
{
- char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
- char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
+ const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
+ const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
size_t len = 0;
if (class_name) {
@@ -4125,7 +4311,7 @@ yy330:
len += strlen(func_name);
}
- zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
+ zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
class_name ? class_name : "",
class_name && func_name ? "::" : "",
func_name ? func_name : ""
@@ -4133,60 +4319,60 @@ yy330:
zendlval->type = IS_STRING;
return T_METHOD_C;
}
-#line 4137 "Zend/zend_language_scanner.c"
-yy334:
- YYDEBUG(334, *YYCURSOR);
+#line 4323 "Zend/zend_language_scanner.c"
+yy339:
+ YYDEBUG(339, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy345;
- if (yych == 'l') goto yy345;
+ if (yych == 'L') goto yy350;
+ if (yych == 'l') goto yy350;
goto yy186;
-yy335:
- YYDEBUG(335, *YYCURSOR);
+yy340:
+ YYDEBUG(340, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy336;
+ if (yych == 'N') goto yy341;
if (yych != 'n') goto yy186;
-yy336:
- YYDEBUG(336, *YYCURSOR);
+yy341:
+ YYDEBUG(341, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy337;
+ if (yych == 'C') goto yy342;
if (yych != 'c') goto yy186;
-yy337:
- YYDEBUG(337, *YYCURSOR);
+yy342:
+ YYDEBUG(342, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy338;
+ if (yych == 'T') goto yy343;
if (yych != 't') goto yy186;
-yy338:
- YYDEBUG(338, *YYCURSOR);
+yy343:
+ YYDEBUG(343, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy339;
+ if (yych == 'I') goto yy344;
if (yych != 'i') goto yy186;
-yy339:
- YYDEBUG(339, *YYCURSOR);
+yy344:
+ YYDEBUG(344, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy340;
+ if (yych == 'O') goto yy345;
if (yych != 'o') goto yy186;
-yy340:
- YYDEBUG(340, *YYCURSOR);
+yy345:
+ YYDEBUG(345, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy341;
+ if (yych == 'N') goto yy346;
if (yych != 'n') goto yy186;
-yy341:
- YYDEBUG(341, *YYCURSOR);
+yy346:
+ YYDEBUG(346, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(342, *YYCURSOR);
+ YYDEBUG(347, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(343, *YYCURSOR);
+ YYDEBUG(348, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(344, *YYCURSOR);
+ YYDEBUG(349, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1419 "Zend/zend_language_scanner.l"
+#line 1623 "Zend/zend_language_scanner.l"
{
- char *func_name = NULL;
+ const char *func_name = NULL;
if (CG(active_op_array)) {
func_name = CG(active_op_array)->function_name;
@@ -4200,27 +4386,27 @@ yy341:
zendlval->type = IS_STRING;
return T_FUNC_C;
}
-#line 4204 "Zend/zend_language_scanner.c"
-yy345:
- YYDEBUG(345, *YYCURSOR);
+#line 4390 "Zend/zend_language_scanner.c"
+yy350:
+ YYDEBUG(350, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy346;
+ if (yych == 'E') goto yy351;
if (yych != 'e') goto yy186;
-yy346:
- YYDEBUG(346, *YYCURSOR);
+yy351:
+ YYDEBUG(351, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(347, *YYCURSOR);
+ YYDEBUG(352, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(348, *YYCURSOR);
+ YYDEBUG(353, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(349, *YYCURSOR);
+ YYDEBUG(354, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1462 "Zend/zend_language_scanner.l"
+#line 1666 "Zend/zend_language_scanner.l"
{
char *filename = zend_get_compiled_filename(TSRMLS_C);
@@ -4232,1045 +4418,1044 @@ yy346:
zendlval->type = IS_STRING;
return T_FILE;
}
-#line 4236 "Zend/zend_language_scanner.c"
-yy350:
- YYDEBUG(350, *YYCURSOR);
+#line 4422 "Zend/zend_language_scanner.c"
+yy355:
+ YYDEBUG(355, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy351;
+ if (yych == 'A') goto yy356;
if (yych != 'a') goto yy186;
-yy351:
- YYDEBUG(351, *YYCURSOR);
+yy356:
+ YYDEBUG(356, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy352;
- if (yych != 's') goto yy186;
-yy352:
- YYDEBUG(352, *YYCURSOR);
+ if (yych == 'I') goto yy357;
+ if (yych != 'i') goto yy186;
+yy357:
+ YYDEBUG(357, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy353;
- if (yych != 's') goto yy186;
-yy353:
- YYDEBUG(353, *YYCURSOR);
+ if (yych == 'T') goto yy358;
+ if (yych != 't') goto yy186;
+yy358:
+ YYDEBUG(358, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(354, *YYCURSOR);
+ YYDEBUG(359, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(355, *YYCURSOR);
+ YYDEBUG(360, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(356, *YYCURSOR);
+ YYDEBUG(361, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1403 "Zend/zend_language_scanner.l"
+#line 1603 "Zend/zend_language_scanner.l"
{
- char *class_name = NULL;
-
- if (CG(active_class_entry)) {
- class_name = CG(active_class_entry)->name;
+ const char *trait_name = NULL;
+
+ if (CG(active_class_entry)
+ && (ZEND_ACC_TRAIT ==
+ (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
+ trait_name = CG(active_class_entry)->name;
}
-
- if (!class_name) {
- class_name = "";
+
+ if (!trait_name) {
+ trait_name = "";
}
- zendlval->value.str.len = strlen(class_name);
- zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+
+ zendlval->value.str.len = strlen(trait_name);
+ zendlval->value.str.val = estrndup(trait_name, zendlval->value.str.len);
zendlval->type = IS_STRING;
+
+ return T_TRAIT_C;
+}
+#line 4472 "Zend/zend_language_scanner.c"
+yy362:
+ YYDEBUG(362, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'A') goto yy363;
+ if (yych != 'a') goto yy186;
+yy363:
+ YYDEBUG(363, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'S') goto yy364;
+ if (yych != 's') goto yy186;
+yy364:
+ YYDEBUG(364, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'S') goto yy365;
+ if (yych != 's') goto yy186;
+yy365:
+ YYDEBUG(365, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych != '_') goto yy186;
+ YYDEBUG(366, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych != '_') goto yy186;
+ YYDEBUG(367, *YYCURSOR);
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
+ YYDEBUG(368, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1576 "Zend/zend_language_scanner.l"
+ {
+ const char *class_name = NULL;
+
+ if (CG(active_class_entry)
+ && (ZEND_ACC_TRAIT ==
+ (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
+ /* We create a special __CLASS__ constant that is going to be resolved
+ at run-time */
+ zendlval->value.str.len = sizeof("__CLASS__")-1;
+ zendlval->value.str.val = estrndup("__CLASS__", zendlval->value.str.len);
+ zendlval->type = IS_CONSTANT;
+ } else {
+ if (CG(active_class_entry)) {
+ class_name = CG(active_class_entry)->name;
+ }
+
+ if (!class_name) {
+ class_name = "";
+ }
+
+ zendlval->value.str.len = strlen(class_name);
+ zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
+ }
return T_CLASS_C;
}
-#line 4282 "Zend/zend_language_scanner.c"
-yy357:
- YYDEBUG(357, *YYCURSOR);
+#line 4529 "Zend/zend_language_scanner.c"
+yy369:
+ YYDEBUG(369, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy358;
+ if (yych == 'L') goto yy370;
if (yych != 'l') goto yy186;
-yy358:
- YYDEBUG(358, *YYCURSOR);
+yy370:
+ YYDEBUG(370, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy359;
+ if (yych == 'T') goto yy371;
if (yych != 't') goto yy186;
-yy359:
- YYDEBUG(359, *YYCURSOR);
+yy371:
+ YYDEBUG(371, *YYCURSOR);
yych = *++YYCURSOR;
if (yych != '_') goto yy186;
- YYDEBUG(360, *YYCURSOR);
+ YYDEBUG(372, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy361;
+ if (yych == 'C') goto yy373;
if (yych != 'c') goto yy186;
-yy361:
- YYDEBUG(361, *YYCURSOR);
+yy373:
+ YYDEBUG(373, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy362;
+ if (yych == 'O') goto yy374;
if (yych != 'o') goto yy186;
-yy362:
- YYDEBUG(362, *YYCURSOR);
+yy374:
+ YYDEBUG(374, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'M') goto yy363;
+ if (yych == 'M') goto yy375;
if (yych != 'm') goto yy186;
-yy363:
- YYDEBUG(363, *YYCURSOR);
+yy375:
+ YYDEBUG(375, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'P') goto yy364;
+ if (yych == 'P') goto yy376;
if (yych != 'p') goto yy186;
-yy364:
- YYDEBUG(364, *YYCURSOR);
+yy376:
+ YYDEBUG(376, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy365;
+ if (yych == 'I') goto yy377;
if (yych != 'i') goto yy186;
-yy365:
- YYDEBUG(365, *YYCURSOR);
+yy377:
+ YYDEBUG(377, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy366;
+ if (yych == 'L') goto yy378;
if (yych != 'l') goto yy186;
-yy366:
- YYDEBUG(366, *YYCURSOR);
+yy378:
+ YYDEBUG(378, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy367;
+ if (yych == 'E') goto yy379;
if (yych != 'e') goto yy186;
-yy367:
- YYDEBUG(367, *YYCURSOR);
+yy379:
+ YYDEBUG(379, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy368;
+ if (yych == 'R') goto yy380;
if (yych != 'r') goto yy186;
-yy368:
- YYDEBUG(368, *YYCURSOR);
+yy380:
+ YYDEBUG(380, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(369, *YYCURSOR);
+ YYDEBUG(381, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1141 "Zend/zend_language_scanner.l"
+#line 1286 "Zend/zend_language_scanner.l"
{
return T_HALT_COMPILER;
}
-#line 4348 "Zend/zend_language_scanner.c"
-yy370:
- YYDEBUG(370, *YYCURSOR);
+#line 4595 "Zend/zend_language_scanner.c"
+yy382:
+ YYDEBUG(382, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy374;
- if (yych == 's') goto yy374;
+ if (yych == 'S') goto yy386;
+ if (yych == 's') goto yy386;
goto yy186;
-yy371:
- YYDEBUG(371, *YYCURSOR);
+yy383:
+ YYDEBUG(383, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy372;
+ if (yych == 'E') goto yy384;
if (yych != 'e') goto yy186;
-yy372:
- YYDEBUG(372, *YYCURSOR);
+yy384:
+ YYDEBUG(384, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(373, *YYCURSOR);
+ YYDEBUG(385, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1125 "Zend/zend_language_scanner.l"
+#line 1266 "Zend/zend_language_scanner.l"
{
return T_USE;
}
-#line 4372 "Zend/zend_language_scanner.c"
-yy374:
- YYDEBUG(374, *YYCURSOR);
+#line 4619 "Zend/zend_language_scanner.c"
+yy386:
+ YYDEBUG(386, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy375;
+ if (yych == 'E') goto yy387;
if (yych != 'e') goto yy186;
-yy375:
- YYDEBUG(375, *YYCURSOR);
+yy387:
+ YYDEBUG(387, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy376;
+ if (yych == 'T') goto yy388;
if (yych != 't') goto yy186;
-yy376:
- YYDEBUG(376, *YYCURSOR);
+yy388:
+ YYDEBUG(388, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(377, *YYCURSOR);
+ YYDEBUG(389, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1169 "Zend/zend_language_scanner.l"
+#line 1314 "Zend/zend_language_scanner.l"
{
return T_UNSET;
}
-#line 4395 "Zend/zend_language_scanner.c"
-yy378:
- YYDEBUG(378, *YYCURSOR);
+#line 4642 "Zend/zend_language_scanner.c"
+yy390:
+ YYDEBUG(390, *YYCURSOR);
++YYCURSOR;
YYFILL(7);
yych = *YYCURSOR;
-yy379:
- YYDEBUG(379, *YYCURSOR);
+yy391:
+ YYDEBUG(391, *YYCURSOR);
if (yych <= 'S') {
if (yych <= 'D') {
if (yych <= ' ') {
- if (yych == '\t') goto yy378;
+ if (yych == '\t') goto yy390;
if (yych <= 0x1F) goto yy193;
- goto yy378;
+ goto yy390;
} else {
if (yych <= 'A') {
if (yych <= '@') goto yy193;
- goto yy383;
+ goto yy395;
} else {
- if (yych <= 'B') goto yy381;
+ if (yych <= 'B') goto yy393;
if (yych <= 'C') goto yy193;
- goto yy386;
+ goto yy398;
}
}
} else {
if (yych <= 'I') {
- if (yych == 'F') goto yy387;
+ if (yych == 'F') goto yy399;
if (yych <= 'H') goto yy193;
- goto yy388;
+ goto yy400;
} else {
if (yych <= 'O') {
if (yych <= 'N') goto yy193;
- goto yy382;
+ goto yy394;
} else {
if (yych <= 'Q') goto yy193;
- if (yych <= 'R') goto yy385;
- goto yy384;
+ if (yych <= 'R') goto yy397;
+ goto yy396;
}
}
}
} else {
if (yych <= 'f') {
if (yych <= 'a') {
- if (yych == 'U') goto yy380;
+ if (yych == 'U') goto yy392;
if (yych <= '`') goto yy193;
- goto yy383;
+ goto yy395;
} else {
if (yych <= 'c') {
- if (yych <= 'b') goto yy381;
+ if (yych <= 'b') goto yy393;
goto yy193;
} else {
- if (yych <= 'd') goto yy386;
+ if (yych <= 'd') goto yy398;
if (yych <= 'e') goto yy193;
- goto yy387;
+ goto yy399;
}
}
} else {
if (yych <= 'q') {
if (yych <= 'i') {
if (yych <= 'h') goto yy193;
- goto yy388;
+ goto yy400;
} else {
- if (yych == 'o') goto yy382;
+ if (yych == 'o') goto yy394;
goto yy193;
}
} else {
if (yych <= 's') {
- if (yych <= 'r') goto yy385;
- goto yy384;
+ if (yych <= 'r') goto yy397;
+ goto yy396;
} else {
if (yych != 'u') goto yy193;
}
}
}
}
-yy380:
- YYDEBUG(380, *YYCURSOR);
+yy392:
+ YYDEBUG(392, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy451;
- if (yych == 'n') goto yy451;
+ if (yych == 'N') goto yy459;
+ if (yych == 'n') goto yy459;
goto yy193;
-yy381:
- YYDEBUG(381, *YYCURSOR);
+yy393:
+ YYDEBUG(393, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'O') {
- if (yych == 'I') goto yy434;
+ if (yych == 'I') goto yy446;
if (yych <= 'N') goto yy193;
- goto yy435;
+ goto yy447;
} else {
if (yych <= 'i') {
if (yych <= 'h') goto yy193;
- goto yy434;
+ goto yy446;
} else {
- if (yych == 'o') goto yy435;
+ if (yych == 'o') goto yy447;
goto yy193;
}
}
-yy382:
- YYDEBUG(382, *YYCURSOR);
+yy394:
+ YYDEBUG(394, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'B') goto yy426;
- if (yych == 'b') goto yy426;
+ if (yych == 'B') goto yy438;
+ if (yych == 'b') goto yy438;
goto yy193;
-yy383:
- YYDEBUG(383, *YYCURSOR);
+yy395:
+ YYDEBUG(395, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy419;
- if (yych == 'r') goto yy419;
+ if (yych == 'R') goto yy431;
+ if (yych == 'r') goto yy431;
goto yy193;
-yy384:
- YYDEBUG(384, *YYCURSOR);
+yy396:
+ YYDEBUG(396, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy411;
- if (yych == 't') goto yy411;
+ if (yych == 'T') goto yy423;
+ if (yych == 't') goto yy423;
goto yy193;
-yy385:
- YYDEBUG(385, *YYCURSOR);
+yy397:
+ YYDEBUG(397, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy409;
- if (yych == 'e') goto yy409;
+ if (yych == 'E') goto yy421;
+ if (yych == 'e') goto yy421;
goto yy193;
-yy386:
- YYDEBUG(386, *YYCURSOR);
+yy398:
+ YYDEBUG(398, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy405;
- if (yych == 'o') goto yy405;
+ if (yych == 'O') goto yy417;
+ if (yych == 'o') goto yy417;
goto yy193;
-yy387:
- YYDEBUG(387, *YYCURSOR);
+yy399:
+ YYDEBUG(399, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy398;
- if (yych == 'l') goto yy398;
+ if (yych == 'L') goto yy410;
+ if (yych == 'l') goto yy410;
goto yy193;
-yy388:
- YYDEBUG(388, *YYCURSOR);
+yy400:
+ YYDEBUG(400, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy389;
+ if (yych == 'N') goto yy401;
if (yych != 'n') goto yy193;
-yy389:
- YYDEBUG(389, *YYCURSOR);
+yy401:
+ YYDEBUG(401, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy390;
+ if (yych == 'T') goto yy402;
if (yych != 't') goto yy193;
-yy390:
- YYDEBUG(390, *YYCURSOR);
+yy402:
+ YYDEBUG(402, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy391;
- if (yych != 'e') goto yy393;
-yy391:
- YYDEBUG(391, *YYCURSOR);
+ if (yych == 'E') goto yy403;
+ if (yych != 'e') goto yy405;
+yy403:
+ YYDEBUG(403, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'G') goto yy396;
- if (yych == 'g') goto yy396;
+ if (yych == 'G') goto yy408;
+ if (yych == 'g') goto yy408;
goto yy193;
-yy392:
- YYDEBUG(392, *YYCURSOR);
+yy404:
+ YYDEBUG(404, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy393:
- YYDEBUG(393, *YYCURSOR);
+yy405:
+ YYDEBUG(405, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy392;
+ if (yych == '\t') goto yy404;
goto yy193;
} else {
- if (yych <= ' ') goto yy392;
+ if (yych <= ' ') goto yy404;
if (yych != ')') goto yy193;
}
- YYDEBUG(394, *YYCURSOR);
+ YYDEBUG(406, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(395, *YYCURSOR);
+ YYDEBUG(407, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1069 "Zend/zend_language_scanner.l"
+#line 1214 "Zend/zend_language_scanner.l"
{
return T_INT_CAST;
}
-#line 4571 "Zend/zend_language_scanner.c"
-yy396:
- YYDEBUG(396, *YYCURSOR);
+#line 4818 "Zend/zend_language_scanner.c"
+yy408:
+ YYDEBUG(408, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy397;
+ if (yych == 'E') goto yy409;
if (yych != 'e') goto yy193;
-yy397:
- YYDEBUG(397, *YYCURSOR);
+yy409:
+ YYDEBUG(409, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy392;
- if (yych == 'r') goto yy392;
+ if (yych == 'R') goto yy404;
+ if (yych == 'r') goto yy404;
goto yy193;
-yy398:
- YYDEBUG(398, *YYCURSOR);
+yy410:
+ YYDEBUG(410, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy399;
+ if (yych == 'O') goto yy411;
if (yych != 'o') goto yy193;
-yy399:
- YYDEBUG(399, *YYCURSOR);
+yy411:
+ YYDEBUG(411, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy400;
+ if (yych == 'A') goto yy412;
if (yych != 'a') goto yy193;
-yy400:
- YYDEBUG(400, *YYCURSOR);
+yy412:
+ YYDEBUG(412, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy401;
+ if (yych == 'T') goto yy413;
if (yych != 't') goto yy193;
-yy401:
- YYDEBUG(401, *YYCURSOR);
+yy413:
+ YYDEBUG(413, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(402, *YYCURSOR);
+ YYDEBUG(414, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy401;
+ if (yych == '\t') goto yy413;
goto yy193;
} else {
- if (yych <= ' ') goto yy401;
+ if (yych <= ' ') goto yy413;
if (yych != ')') goto yy193;
}
- YYDEBUG(403, *YYCURSOR);
+ YYDEBUG(415, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(404, *YYCURSOR);
+ YYDEBUG(416, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1073 "Zend/zend_language_scanner.l"
+#line 1218 "Zend/zend_language_scanner.l"
{
return T_DOUBLE_CAST;
}
-#line 4619 "Zend/zend_language_scanner.c"
-yy405:
- YYDEBUG(405, *YYCURSOR);
+#line 4866 "Zend/zend_language_scanner.c"
+yy417:
+ YYDEBUG(417, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'U') goto yy406;
+ if (yych == 'U') goto yy418;
if (yych != 'u') goto yy193;
-yy406:
- YYDEBUG(406, *YYCURSOR);
+yy418:
+ YYDEBUG(418, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'B') goto yy407;
+ if (yych == 'B') goto yy419;
if (yych != 'b') goto yy193;
-yy407:
- YYDEBUG(407, *YYCURSOR);
+yy419:
+ YYDEBUG(419, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy408;
+ if (yych == 'L') goto yy420;
if (yych != 'l') goto yy193;
-yy408:
- YYDEBUG(408, *YYCURSOR);
+yy420:
+ YYDEBUG(420, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy401;
- if (yych == 'e') goto yy401;
+ if (yych == 'E') goto yy413;
+ if (yych == 'e') goto yy413;
goto yy193;
-yy409:
- YYDEBUG(409, *YYCURSOR);
+yy421:
+ YYDEBUG(421, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy410;
+ if (yych == 'A') goto yy422;
if (yych != 'a') goto yy193;
-yy410:
- YYDEBUG(410, *YYCURSOR);
+yy422:
+ YYDEBUG(422, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy401;
- if (yych == 'l') goto yy401;
+ if (yych == 'L') goto yy413;
+ if (yych == 'l') goto yy413;
goto yy193;
-yy411:
- YYDEBUG(411, *YYCURSOR);
+yy423:
+ YYDEBUG(423, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy412;
+ if (yych == 'R') goto yy424;
if (yych != 'r') goto yy193;
-yy412:
- YYDEBUG(412, *YYCURSOR);
+yy424:
+ YYDEBUG(424, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy413;
+ if (yych == 'I') goto yy425;
if (yych != 'i') goto yy193;
-yy413:
- YYDEBUG(413, *YYCURSOR);
+yy425:
+ YYDEBUG(425, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy414;
+ if (yych == 'N') goto yy426;
if (yych != 'n') goto yy193;
-yy414:
- YYDEBUG(414, *YYCURSOR);
+yy426:
+ YYDEBUG(426, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'G') goto yy415;
+ if (yych == 'G') goto yy427;
if (yych != 'g') goto yy193;
-yy415:
- YYDEBUG(415, *YYCURSOR);
+yy427:
+ YYDEBUG(427, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(416, *YYCURSOR);
+ YYDEBUG(428, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy415;
+ if (yych == '\t') goto yy427;
goto yy193;
} else {
- if (yych <= ' ') goto yy415;
+ if (yych <= ' ') goto yy427;
if (yych != ')') goto yy193;
}
- YYDEBUG(417, *YYCURSOR);
+ YYDEBUG(429, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(418, *YYCURSOR);
+ YYDEBUG(430, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1077 "Zend/zend_language_scanner.l"
+#line 1222 "Zend/zend_language_scanner.l"
{
return T_STRING_CAST;
}
-#line 4693 "Zend/zend_language_scanner.c"
-yy419:
- YYDEBUG(419, *YYCURSOR);
+#line 4940 "Zend/zend_language_scanner.c"
+yy431:
+ YYDEBUG(431, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy420;
+ if (yych == 'R') goto yy432;
if (yych != 'r') goto yy193;
-yy420:
- YYDEBUG(420, *YYCURSOR);
+yy432:
+ YYDEBUG(432, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy421;
+ if (yych == 'A') goto yy433;
if (yych != 'a') goto yy193;
-yy421:
- YYDEBUG(421, *YYCURSOR);
+yy433:
+ YYDEBUG(433, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'Y') goto yy422;
+ if (yych == 'Y') goto yy434;
if (yych != 'y') goto yy193;
-yy422:
- YYDEBUG(422, *YYCURSOR);
+yy434:
+ YYDEBUG(434, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(423, *YYCURSOR);
+ YYDEBUG(435, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy422;
+ if (yych == '\t') goto yy434;
goto yy193;
} else {
- if (yych <= ' ') goto yy422;
+ if (yych <= ' ') goto yy434;
if (yych != ')') goto yy193;
}
- YYDEBUG(424, *YYCURSOR);
+ YYDEBUG(436, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(425, *YYCURSOR);
+ YYDEBUG(437, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1085 "Zend/zend_language_scanner.l"
+#line 1226 "Zend/zend_language_scanner.l"
{
return T_ARRAY_CAST;
}
-#line 4730 "Zend/zend_language_scanner.c"
-yy426:
- YYDEBUG(426, *YYCURSOR);
+#line 4977 "Zend/zend_language_scanner.c"
+yy438:
+ YYDEBUG(438, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'J') goto yy427;
+ if (yych == 'J') goto yy439;
if (yych != 'j') goto yy193;
-yy427:
- YYDEBUG(427, *YYCURSOR);
+yy439:
+ YYDEBUG(439, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy428;
+ if (yych == 'E') goto yy440;
if (yych != 'e') goto yy193;
-yy428:
- YYDEBUG(428, *YYCURSOR);
+yy440:
+ YYDEBUG(440, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy429;
+ if (yych == 'C') goto yy441;
if (yych != 'c') goto yy193;
-yy429:
- YYDEBUG(429, *YYCURSOR);
+yy441:
+ YYDEBUG(441, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy430;
+ if (yych == 'T') goto yy442;
if (yych != 't') goto yy193;
-yy430:
- YYDEBUG(430, *YYCURSOR);
+yy442:
+ YYDEBUG(442, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(431, *YYCURSOR);
+ YYDEBUG(443, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy430;
+ if (yych == '\t') goto yy442;
goto yy193;
} else {
- if (yych <= ' ') goto yy430;
+ if (yych <= ' ') goto yy442;
if (yych != ')') goto yy193;
}
- YYDEBUG(432, *YYCURSOR);
+ YYDEBUG(444, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(433, *YYCURSOR);
+ YYDEBUG(445, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1089 "Zend/zend_language_scanner.l"
+#line 1230 "Zend/zend_language_scanner.l"
{
return T_OBJECT_CAST;
}
-#line 4772 "Zend/zend_language_scanner.c"
-yy434:
- YYDEBUG(434, *YYCURSOR);
+#line 5019 "Zend/zend_language_scanner.c"
+yy446:
+ YYDEBUG(446, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy444;
- if (yych == 'n') goto yy444;
+ if (yych == 'N') goto yy456;
+ if (yych == 'n') goto yy456;
goto yy193;
-yy435:
- YYDEBUG(435, *YYCURSOR);
+yy447:
+ YYDEBUG(447, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy436;
+ if (yych == 'O') goto yy448;
if (yych != 'o') goto yy193;
-yy436:
- YYDEBUG(436, *YYCURSOR);
+yy448:
+ YYDEBUG(448, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy437;
+ if (yych == 'L') goto yy449;
if (yych != 'l') goto yy193;
-yy437:
- YYDEBUG(437, *YYCURSOR);
+yy449:
+ YYDEBUG(449, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy442;
- if (yych == 'e') goto yy442;
- goto yy439;
-yy438:
- YYDEBUG(438, *YYCURSOR);
+ if (yych == 'E') goto yy454;
+ if (yych == 'e') goto yy454;
+ goto yy451;
+yy450:
+ YYDEBUG(450, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy439:
- YYDEBUG(439, *YYCURSOR);
+yy451:
+ YYDEBUG(451, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy438;
+ if (yych == '\t') goto yy450;
goto yy193;
} else {
- if (yych <= ' ') goto yy438;
+ if (yych <= ' ') goto yy450;
if (yych != ')') goto yy193;
}
- YYDEBUG(440, *YYCURSOR);
+ YYDEBUG(452, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(441, *YYCURSOR);
+ YYDEBUG(453, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1093 "Zend/zend_language_scanner.l"
+#line 1234 "Zend/zend_language_scanner.l"
{
return T_BOOL_CAST;
}
-#line 4817 "Zend/zend_language_scanner.c"
-yy442:
- YYDEBUG(442, *YYCURSOR);
+#line 5064 "Zend/zend_language_scanner.c"
+yy454:
+ YYDEBUG(454, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy443;
+ if (yych == 'A') goto yy455;
if (yych != 'a') goto yy193;
-yy443:
- YYDEBUG(443, *YYCURSOR);
+yy455:
+ YYDEBUG(455, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy438;
- if (yych == 'n') goto yy438;
+ if (yych == 'N') goto yy450;
+ if (yych == 'n') goto yy450;
goto yy193;
-yy444:
- YYDEBUG(444, *YYCURSOR);
+yy456:
+ YYDEBUG(456, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy445;
+ if (yych == 'A') goto yy457;
if (yych != 'a') goto yy193;
-yy445:
- YYDEBUG(445, *YYCURSOR);
+yy457:
+ YYDEBUG(457, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy446;
+ if (yych == 'R') goto yy458;
if (yych != 'r') goto yy193;
-yy446:
- YYDEBUG(446, *YYCURSOR);
+yy458:
+ YYDEBUG(458, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'Y') goto yy447;
- if (yych != 'y') goto yy193;
-yy447:
- YYDEBUG(447, *YYCURSOR);
- ++YYCURSOR;
- YYFILL(1);
- yych = *YYCURSOR;
- YYDEBUG(448, *YYCURSOR);
- if (yych <= 0x1F) {
- if (yych == '\t') goto yy447;
- goto yy193;
- } else {
- if (yych <= ' ') goto yy447;
- if (yych != ')') goto yy193;
- }
- YYDEBUG(449, *YYCURSOR);
- ++YYCURSOR;
- YYDEBUG(450, *YYCURSOR);
- yyleng = YYCURSOR - SCNG(yy_text);
-#line 1081 "Zend/zend_language_scanner.l"
- {
- return T_STRING_CAST;
-}
-#line 4865 "Zend/zend_language_scanner.c"
-yy451:
- YYDEBUG(451, *YYCURSOR);
+ if (yych == 'Y') goto yy427;
+ if (yych == 'y') goto yy427;
+ goto yy193;
+yy459:
+ YYDEBUG(459, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy452;
+ if (yych == 'S') goto yy460;
if (yych != 's') goto yy193;
-yy452:
- YYDEBUG(452, *YYCURSOR);
+yy460:
+ YYDEBUG(460, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy453;
+ if (yych == 'E') goto yy461;
if (yych != 'e') goto yy193;
-yy453:
- YYDEBUG(453, *YYCURSOR);
+yy461:
+ YYDEBUG(461, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy454;
+ if (yych == 'T') goto yy462;
if (yych != 't') goto yy193;
-yy454:
- YYDEBUG(454, *YYCURSOR);
+yy462:
+ YYDEBUG(462, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(455, *YYCURSOR);
+ YYDEBUG(463, *YYCURSOR);
if (yych <= 0x1F) {
- if (yych == '\t') goto yy454;
+ if (yych == '\t') goto yy462;
goto yy193;
} else {
- if (yych <= ' ') goto yy454;
+ if (yych <= ' ') goto yy462;
if (yych != ')') goto yy193;
}
- YYDEBUG(456, *YYCURSOR);
+ YYDEBUG(464, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(457, *YYCURSOR);
+ YYDEBUG(465, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1097 "Zend/zend_language_scanner.l"
+#line 1238 "Zend/zend_language_scanner.l"
{
return T_UNSET_CAST;
}
-#line 4902 "Zend/zend_language_scanner.c"
-yy458:
- YYDEBUG(458, *YYCURSOR);
+#line 5128 "Zend/zend_language_scanner.c"
+yy466:
+ YYDEBUG(466, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy459;
+ if (yych == 'R') goto yy467;
if (yych != 'r') goto yy186;
-yy459:
- YYDEBUG(459, *YYCURSOR);
+yy467:
+ YYDEBUG(467, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(460, *YYCURSOR);
+ YYDEBUG(468, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1065 "Zend/zend_language_scanner.l"
+#line 1210 "Zend/zend_language_scanner.l"
{
return T_VAR;
}
-#line 4920 "Zend/zend_language_scanner.c"
-yy461:
- YYDEBUG(461, *YYCURSOR);
+#line 5146 "Zend/zend_language_scanner.c"
+yy469:
+ YYDEBUG(469, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'M') goto yy465;
- if (yych == 'm') goto yy465;
+ if (yych == 'M') goto yy473;
+ if (yych == 'm') goto yy473;
goto yy186;
-yy462:
- YYDEBUG(462, *YYCURSOR);
+yy470:
+ YYDEBUG(470, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'W') goto yy463;
+ if (yych == 'W') goto yy471;
if (yych != 'w') goto yy186;
-yy463:
- YYDEBUG(463, *YYCURSOR);
+yy471:
+ YYDEBUG(471, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(464, *YYCURSOR);
+ YYDEBUG(472, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1057 "Zend/zend_language_scanner.l"
+#line 1202 "Zend/zend_language_scanner.l"
{
return T_NEW;
}
-#line 4944 "Zend/zend_language_scanner.c"
-yy465:
- YYDEBUG(465, *YYCURSOR);
+#line 5170 "Zend/zend_language_scanner.c"
+yy473:
+ YYDEBUG(473, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy466;
+ if (yych == 'E') goto yy474;
if (yych != 'e') goto yy186;
-yy466:
- YYDEBUG(466, *YYCURSOR);
+yy474:
+ YYDEBUG(474, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy467;
+ if (yych == 'S') goto yy475;
if (yych != 's') goto yy186;
-yy467:
- YYDEBUG(467, *YYCURSOR);
+yy475:
+ YYDEBUG(475, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'P') goto yy468;
+ if (yych == 'P') goto yy476;
if (yych != 'p') goto yy186;
-yy468:
- YYDEBUG(468, *YYCURSOR);
+yy476:
+ YYDEBUG(476, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy469;
+ if (yych == 'A') goto yy477;
if (yych != 'a') goto yy186;
-yy469:
- YYDEBUG(469, *YYCURSOR);
+yy477:
+ YYDEBUG(477, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy470;
+ if (yych == 'C') goto yy478;
if (yych != 'c') goto yy186;
-yy470:
- YYDEBUG(470, *YYCURSOR);
+yy478:
+ YYDEBUG(478, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy471;
+ if (yych == 'E') goto yy479;
if (yych != 'e') goto yy186;
-yy471:
- YYDEBUG(471, *YYCURSOR);
+yy479:
+ YYDEBUG(479, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(472, *YYCURSOR);
+ YYDEBUG(480, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1121 "Zend/zend_language_scanner.l"
+#line 1262 "Zend/zend_language_scanner.l"
{
return T_NAMESPACE;
}
-#line 4987 "Zend/zend_language_scanner.c"
-yy473:
- YYDEBUG(473, *YYCURSOR);
+#line 5213 "Zend/zend_language_scanner.c"
+yy481:
+ YYDEBUG(481, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(474, *YYCURSOR);
+ YYDEBUG(482, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1049 "Zend/zend_language_scanner.l"
+#line 1194 "Zend/zend_language_scanner.l"
{
return T_PAAMAYIM_NEKUDOTAYIM;
}
-#line 4997 "Zend/zend_language_scanner.c"
-yy475:
- YYDEBUG(475, *YYCURSOR);
+#line 5223 "Zend/zend_language_scanner.c"
+yy483:
+ YYDEBUG(483, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy476:
- YYDEBUG(476, *YYCURSOR);
+yy484:
+ YYDEBUG(484, *YYCURSOR);
if (yych <= '\f') {
if (yych <= 0x08) goto yy140;
- if (yych <= '\n') goto yy475;
+ if (yych <= '\n') goto yy483;
goto yy140;
} else {
- if (yych <= '\r') goto yy475;
- if (yych == ' ') goto yy475;
+ if (yych <= '\r') goto yy483;
+ if (yych == ' ') goto yy483;
goto yy140;
}
-yy477:
- YYDEBUG(477, *YYCURSOR);
+yy485:
+ YYDEBUG(485, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(478, *YYCURSOR);
+ YYDEBUG(486, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1221 "Zend/zend_language_scanner.l"
+#line 1370 "Zend/zend_language_scanner.l"
{
return T_MINUS_EQUAL;
}
-#line 5023 "Zend/zend_language_scanner.c"
-yy479:
- YYDEBUG(479, *YYCURSOR);
+#line 5249 "Zend/zend_language_scanner.c"
+yy487:
+ YYDEBUG(487, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(480, *YYCURSOR);
+ YYDEBUG(488, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1189 "Zend/zend_language_scanner.l"
+#line 1338 "Zend/zend_language_scanner.l"
{
return T_DEC;
}
-#line 5033 "Zend/zend_language_scanner.c"
-yy481:
- YYDEBUG(481, *YYCURSOR);
+#line 5259 "Zend/zend_language_scanner.c"
+yy489:
+ YYDEBUG(489, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(482, *YYCURSOR);
+ YYDEBUG(490, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1019 "Zend/zend_language_scanner.l"
+#line 1164 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
return T_OBJECT_OPERATOR;
}
-#line 5044 "Zend/zend_language_scanner.c"
-yy483:
- YYDEBUG(483, *YYCURSOR);
+#line 5270 "Zend/zend_language_scanner.c"
+yy491:
+ YYDEBUG(491, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'O') {
- if (yych == 'I') goto yy490;
+ if (yych == 'I') goto yy498;
if (yych <= 'N') goto yy186;
- goto yy491;
+ goto yy499;
} else {
if (yych <= 'i') {
if (yych <= 'h') goto yy186;
- goto yy490;
+ goto yy498;
} else {
- if (yych == 'o') goto yy491;
+ if (yych == 'o') goto yy499;
goto yy186;
}
}
-yy484:
- YYDEBUG(484, *YYCURSOR);
+yy492:
+ YYDEBUG(492, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'B') goto yy485;
+ if (yych == 'B') goto yy493;
if (yych != 'b') goto yy186;
-yy485:
- YYDEBUG(485, *YYCURSOR);
+yy493:
+ YYDEBUG(493, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy486;
+ if (yych == 'L') goto yy494;
if (yych != 'l') goto yy186;
-yy486:
- YYDEBUG(486, *YYCURSOR);
+yy494:
+ YYDEBUG(494, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy487;
+ if (yych == 'I') goto yy495;
if (yych != 'i') goto yy186;
-yy487:
- YYDEBUG(487, *YYCURSOR);
+yy495:
+ YYDEBUG(495, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy488;
+ if (yych == 'C') goto yy496;
if (yych != 'c') goto yy186;
-yy488:
- YYDEBUG(488, *YYCURSOR);
+yy496:
+ YYDEBUG(496, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(489, *YYCURSOR);
+ YYDEBUG(497, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1165 "Zend/zend_language_scanner.l"
+#line 1310 "Zend/zend_language_scanner.l"
{
return T_PUBLIC;
}
-#line 5093 "Zend/zend_language_scanner.c"
-yy490:
- YYDEBUG(490, *YYCURSOR);
+#line 5319 "Zend/zend_language_scanner.c"
+yy498:
+ YYDEBUG(498, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'V') {
- if (yych == 'N') goto yy499;
+ if (yych == 'N') goto yy507;
if (yych <= 'U') goto yy186;
- goto yy500;
+ goto yy508;
} else {
if (yych <= 'n') {
if (yych <= 'm') goto yy186;
- goto yy499;
+ goto yy507;
} else {
- if (yych == 'v') goto yy500;
+ if (yych == 'v') goto yy508;
goto yy186;
}
}
-yy491:
- YYDEBUG(491, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'T') goto yy492;
- if (yych != 't') goto yy186;
-yy492:
- YYDEBUG(492, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'E') goto yy493;
- if (yych != 'e') goto yy186;
-yy493:
- YYDEBUG(493, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'C') goto yy494;
- if (yych != 'c') goto yy186;
-yy494:
- YYDEBUG(494, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'T') goto yy495;
- if (yych != 't') goto yy186;
-yy495:
- YYDEBUG(495, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'E') goto yy496;
- if (yych != 'e') goto yy186;
-yy496:
- YYDEBUG(496, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'D') goto yy497;
- if (yych != 'd') goto yy186;
-yy497:
- YYDEBUG(497, *YYCURSOR);
- ++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
- goto yy185;
- }
- YYDEBUG(498, *YYCURSOR);
- yyleng = YYCURSOR - SCNG(yy_text);
-#line 1161 "Zend/zend_language_scanner.l"
- {
- return T_PROTECTED;
-}
-#line 5152 "Zend/zend_language_scanner.c"
yy499:
YYDEBUG(499, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy505;
- if (yych == 't') goto yy505;
- goto yy186;
+ if (yych == 'T') goto yy500;
+ if (yych != 't') goto yy186;
yy500:
YYDEBUG(500, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy501;
- if (yych != 'a') goto yy186;
+ if (yych == 'E') goto yy501;
+ if (yych != 'e') goto yy186;
yy501:
YYDEBUG(501, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy502;
- if (yych != 't') goto yy186;
+ if (yych == 'C') goto yy502;
+ if (yych != 'c') goto yy186;
yy502:
YYDEBUG(502, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy503;
- if (yych != 'e') goto yy186;
+ if (yych == 'T') goto yy503;
+ if (yych != 't') goto yy186;
yy503:
YYDEBUG(503, *YYCURSOR);
- ++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
- goto yy185;
- }
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy504;
+ if (yych != 'e') goto yy186;
+yy504:
YYDEBUG(504, *YYCURSOR);
- yyleng = YYCURSOR - SCNG(yy_text);
-#line 1157 "Zend/zend_language_scanner.l"
- {
- return T_PRIVATE;
-}
-#line 5186 "Zend/zend_language_scanner.c"
+ yych = *++YYCURSOR;
+ if (yych == 'D') goto yy505;
+ if (yych != 'd') goto yy186;
yy505:
YYDEBUG(505, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
YYDEBUG(506, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 999 "Zend/zend_language_scanner.l"
+#line 1306 "Zend/zend_language_scanner.l"
{
- return T_PRINT;
+ return T_PROTECTED;
}
-#line 5199 "Zend/zend_language_scanner.c"
+#line 5378 "Zend/zend_language_scanner.c"
yy507:
YYDEBUG(507, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy512;
- if (yych == 'o') goto yy512;
+ if (yych == 'T') goto yy513;
+ if (yych == 't') goto yy513;
goto yy186;
yy508:
YYDEBUG(508, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy509;
- if (yych != 't') goto yy186;
+ if (yych == 'A') goto yy509;
+ if (yych != 'a') goto yy186;
yy509:
YYDEBUG(509, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy510;
- if (yych != 'o') goto yy186;
+ if (yych == 'T') goto yy510;
+ if (yych != 't') goto yy186;
yy510:
YYDEBUG(510, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy511;
+ if (yych != 'e') goto yy186;
+yy511:
+ YYDEBUG(511, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(511, *YYCURSOR);
+ YYDEBUG(512, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 991 "Zend/zend_language_scanner.l"
+#line 1302 "Zend/zend_language_scanner.l"
{
- return T_GOTO;
+ return T_PRIVATE;
}
-#line 5228 "Zend/zend_language_scanner.c"
-yy512:
- YYDEBUG(512, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'B') goto yy513;
- if (yych != 'b') goto yy186;
+#line 5412 "Zend/zend_language_scanner.c"
yy513:
YYDEBUG(513, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'A') goto yy514;
- if (yych != 'a') goto yy186;
-yy514:
- YYDEBUG(514, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'L') goto yy515;
- if (yych != 'l') goto yy186;
-yy515:
- YYDEBUG(515, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(516, *YYCURSOR);
+ YYDEBUG(514, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1129 "Zend/zend_language_scanner.l"
+#line 1140 "Zend/zend_language_scanner.l"
{
- return T_GLOBAL;
+ return T_PRINT;
}
-#line 5256 "Zend/zend_language_scanner.c"
+#line 5425 "Zend/zend_language_scanner.c"
+yy515:
+ YYDEBUG(515, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'O') goto yy520;
+ if (yych == 'o') goto yy520;
+ goto yy186;
+yy516:
+ YYDEBUG(516, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'T') goto yy517;
+ if (yych != 't') goto yy186;
yy517:
YYDEBUG(517, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '<') goto yy525;
- goto yy193;
+ if (yych == 'O') goto yy518;
+ if (yych != 'o') goto yy186;
yy518:
YYDEBUG(518, *YYCURSOR);
- yych = *++YYCURSOR;
- goto yy180;
-yy519:
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
YYDEBUG(519, *YYCURSOR);
- yych = *++YYCURSOR;
- goto yy178;
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1132 "Zend/zend_language_scanner.l"
+ {
+ return T_GOTO;
+}
+#line 5454 "Zend/zend_language_scanner.c"
yy520:
YYDEBUG(520, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy521;
- if (yych != 'e') goto yy186;
+ if (yych == 'B') goto yy521;
+ if (yych != 'b') goto yy186;
yy521:
YYDEBUG(521, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5279,1545 +5464,1709 @@ yy521:
yy522:
YYDEBUG(522, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'K') goto yy523;
- if (yych != 'k') goto yy186;
+ if (yych == 'L') goto yy523;
+ if (yych != 'l') goto yy186;
yy523:
YYDEBUG(523, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
YYDEBUG(524, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 983 "Zend/zend_language_scanner.l"
+#line 1274 "Zend/zend_language_scanner.l"
{
- return T_BREAK;
+ return T_GLOBAL;
}
-#line 5297 "Zend/zend_language_scanner.c"
+#line 5482 "Zend/zend_language_scanner.c"
yy525:
YYDEBUG(525, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '<') goto yy265;
+ if (yych == '<') goto yy533;
goto yy193;
yy526:
YYDEBUG(526, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy533;
- if (yych == 'a') goto yy533;
- goto yy186;
+ goto yy180;
yy527:
YYDEBUG(527, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy528;
- if (yych != 'i') goto yy186;
+ goto yy178;
yy528:
YYDEBUG(528, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy529;
- if (yych != 't') goto yy186;
+ if (yych == 'E') goto yy529;
+ if (yych != 'e') goto yy186;
yy529:
YYDEBUG(529, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy530;
- if (yych != 'c') goto yy186;
+ if (yych == 'A') goto yy530;
+ if (yych != 'a') goto yy186;
yy530:
YYDEBUG(530, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy531;
- if (yych != 'h') goto yy186;
+ if (yych == 'K') goto yy531;
+ if (yych != 'k') goto yy186;
yy531:
YYDEBUG(531, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
YYDEBUG(532, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 967 "Zend/zend_language_scanner.l"
+#line 1124 "Zend/zend_language_scanner.l"
{
- return T_SWITCH;
+ return T_BREAK;
}
-#line 5341 "Zend/zend_language_scanner.c"
+#line 5523 "Zend/zend_language_scanner.c"
yy533:
YYDEBUG(533, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy534;
- if (yych != 't') goto yy186;
+ if (yych == '<') goto yy269;
+ goto yy193;
yy534:
YYDEBUG(534, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy535;
- if (yych != 'i') goto yy186;
+ if (yych == 'A') goto yy541;
+ if (yych == 'a') goto yy541;
+ goto yy186;
yy535:
YYDEBUG(535, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy536;
- if (yych != 'c') goto yy186;
+ if (yych == 'I') goto yy536;
+ if (yych != 'i') goto yy186;
yy536:
YYDEBUG(536, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'T') goto yy537;
+ if (yych != 't') goto yy186;
+yy537:
+ YYDEBUG(537, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'C') goto yy538;
+ if (yych != 'c') goto yy186;
+yy538:
+ YYDEBUG(538, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'H') goto yy539;
+ if (yych != 'h') goto yy186;
+yy539:
+ YYDEBUG(539, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(537, *YYCURSOR);
+ YYDEBUG(540, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1145 "Zend/zend_language_scanner.l"
+#line 1108 "Zend/zend_language_scanner.l"
+ {
+ return T_SWITCH;
+}
+#line 5567 "Zend/zend_language_scanner.c"
+yy541:
+ YYDEBUG(541, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'T') goto yy542;
+ if (yych != 't') goto yy186;
+yy542:
+ YYDEBUG(542, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'I') goto yy543;
+ if (yych != 'i') goto yy186;
+yy543:
+ YYDEBUG(543, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'C') goto yy544;
+ if (yych != 'c') goto yy186;
+yy544:
+ YYDEBUG(544, *YYCURSOR);
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
+ YYDEBUG(545, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1290 "Zend/zend_language_scanner.l"
{
return T_STATIC;
}
-#line 5369 "Zend/zend_language_scanner.c"
-yy538:
- YYDEBUG(538, *YYCURSOR);
+#line 5595 "Zend/zend_language_scanner.c"
+yy546:
+ YYDEBUG(546, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy549;
- if (yych == 's') goto yy549;
+ if (yych == 'S') goto yy557;
+ if (yych == 's') goto yy557;
goto yy186;
-yy539:
- YYDEBUG(539, *YYCURSOR);
+yy547:
+ YYDEBUG(547, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'D') goto yy547;
- if (yych == 'd') goto yy547;
+ if (yych == 'D') goto yy555;
+ if (yych == 'd') goto yy555;
goto yy186;
-yy540:
- YYDEBUG(540, *YYCURSOR);
+yy548:
+ YYDEBUG(548, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy543;
- if (yych == 'r') goto yy543;
+ if (yych == 'R') goto yy551;
+ if (yych == 'r') goto yy551;
goto yy186;
-yy541:
- YYDEBUG(541, *YYCURSOR);
+yy549:
+ YYDEBUG(549, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(542, *YYCURSOR);
+ YYDEBUG(550, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 963 "Zend/zend_language_scanner.l"
+#line 1104 "Zend/zend_language_scanner.l"
{
return T_AS;
}
-#line 5400 "Zend/zend_language_scanner.c"
-yy543:
- YYDEBUG(543, *YYCURSOR);
+#line 5626 "Zend/zend_language_scanner.c"
+yy551:
+ YYDEBUG(551, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy544;
+ if (yych == 'A') goto yy552;
if (yych != 'a') goto yy186;
-yy544:
- YYDEBUG(544, *YYCURSOR);
+yy552:
+ YYDEBUG(552, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'Y') goto yy545;
+ if (yych == 'Y') goto yy553;
if (yych != 'y') goto yy186;
-yy545:
- YYDEBUG(545, *YYCURSOR);
+yy553:
+ YYDEBUG(553, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(546, *YYCURSOR);
+ YYDEBUG(554, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1181 "Zend/zend_language_scanner.l"
+#line 1326 "Zend/zend_language_scanner.l"
{
return T_ARRAY;
}
-#line 5423 "Zend/zend_language_scanner.c"
-yy547:
- YYDEBUG(547, *YYCURSOR);
+#line 5649 "Zend/zend_language_scanner.c"
+yy555:
+ YYDEBUG(555, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(548, *YYCURSOR);
+ YYDEBUG(556, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1273 "Zend/zend_language_scanner.l"
+#line 1422 "Zend/zend_language_scanner.l"
{
return T_LOGICAL_AND;
}
-#line 5436 "Zend/zend_language_scanner.c"
-yy549:
- YYDEBUG(549, *YYCURSOR);
+#line 5662 "Zend/zend_language_scanner.c"
+yy557:
+ YYDEBUG(557, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy550;
+ if (yych == 'T') goto yy558;
if (yych != 't') goto yy186;
-yy550:
- YYDEBUG(550, *YYCURSOR);
+yy558:
+ YYDEBUG(558, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy551;
+ if (yych == 'R') goto yy559;
if (yych != 'r') goto yy186;
-yy551:
- YYDEBUG(551, *YYCURSOR);
+yy559:
+ YYDEBUG(559, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy552;
+ if (yych == 'A') goto yy560;
if (yych != 'a') goto yy186;
-yy552:
- YYDEBUG(552, *YYCURSOR);
+yy560:
+ YYDEBUG(560, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy553;
+ if (yych == 'C') goto yy561;
if (yych != 'c') goto yy186;
-yy553:
- YYDEBUG(553, *YYCURSOR);
+yy561:
+ YYDEBUG(561, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy554;
+ if (yych == 'T') goto yy562;
if (yych != 't') goto yy186;
-yy554:
- YYDEBUG(554, *YYCURSOR);
+yy562:
+ YYDEBUG(562, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(555, *YYCURSOR);
+ YYDEBUG(563, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1149 "Zend/zend_language_scanner.l"
+#line 1294 "Zend/zend_language_scanner.l"
{
return T_ABSTRACT;
}
-#line 5474 "Zend/zend_language_scanner.c"
-yy556:
- YYDEBUG(556, *YYCURSOR);
+#line 5700 "Zend/zend_language_scanner.c"
+yy564:
+ YYDEBUG(564, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy557;
+ if (yych == 'I') goto yy565;
if (yych != 'i') goto yy186;
-yy557:
- YYDEBUG(557, *YYCURSOR);
+yy565:
+ YYDEBUG(565, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy558;
+ if (yych == 'L') goto yy566;
if (yych != 'l') goto yy186;
-yy558:
- YYDEBUG(558, *YYCURSOR);
+yy566:
+ YYDEBUG(566, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy559;
+ if (yych == 'E') goto yy567;
if (yych != 'e') goto yy186;
-yy559:
- YYDEBUG(559, *YYCURSOR);
+yy567:
+ YYDEBUG(567, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(560, *YYCURSOR);
+ YYDEBUG(568, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 923 "Zend/zend_language_scanner.l"
+#line 1064 "Zend/zend_language_scanner.l"
{
return T_WHILE;
}
-#line 5502 "Zend/zend_language_scanner.c"
-yy561:
- YYDEBUG(561, *YYCURSOR);
+#line 5728 "Zend/zend_language_scanner.c"
+yy569:
+ YYDEBUG(569, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(562, *YYCURSOR);
+ YYDEBUG(570, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 907 "Zend/zend_language_scanner.l"
+#line 1048 "Zend/zend_language_scanner.l"
{
return T_IF;
}
-#line 5515 "Zend/zend_language_scanner.c"
-yy563:
- YYDEBUG(563, *YYCURSOR);
+#line 5741 "Zend/zend_language_scanner.c"
+yy571:
+ YYDEBUG(571, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'P') goto yy599;
- if (yych == 'p') goto yy599;
+ if (yych == 'P') goto yy613;
+ if (yych == 'p') goto yy613;
goto yy186;
-yy564:
- YYDEBUG(564, *YYCURSOR);
+yy572:
+ YYDEBUG(572, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'T') {
if (yych <= 'C') {
if (yych <= 'B') goto yy186;
- goto yy572;
+ goto yy580;
} else {
if (yych <= 'R') goto yy186;
- if (yych <= 'S') goto yy570;
- goto yy571;
+ if (yych <= 'S') goto yy578;
+ goto yy579;
}
} else {
if (yych <= 'r') {
- if (yych == 'c') goto yy572;
+ if (yych == 'c') goto yy580;
goto yy186;
} else {
- if (yych <= 's') goto yy570;
- if (yych <= 't') goto yy571;
+ if (yych <= 's') goto yy578;
+ if (yych <= 't') goto yy579;
goto yy186;
}
}
-yy565:
- YYDEBUG(565, *YYCURSOR);
+yy573:
+ YYDEBUG(573, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy566;
+ if (yych == 'S') goto yy574;
if (yych != 's') goto yy186;
-yy566:
- YYDEBUG(566, *YYCURSOR);
+yy574:
+ YYDEBUG(574, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy567;
+ if (yych == 'E') goto yy575;
if (yych != 'e') goto yy186;
-yy567:
- YYDEBUG(567, *YYCURSOR);
+yy575:
+ YYDEBUG(575, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy568;
+ if (yych == 'T') goto yy576;
if (yych != 't') goto yy186;
-yy568:
- YYDEBUG(568, *YYCURSOR);
+yy576:
+ YYDEBUG(576, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(569, *YYCURSOR);
+ YYDEBUG(577, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1133 "Zend/zend_language_scanner.l"
+#line 1278 "Zend/zend_language_scanner.l"
{
return T_ISSET;
}
-#line 5571 "Zend/zend_language_scanner.c"
-yy570:
- YYDEBUG(570, *YYCURSOR);
+#line 5797 "Zend/zend_language_scanner.c"
+yy578:
+ YYDEBUG(578, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy591;
- if (yych == 't') goto yy591;
+ if (yych == 'T') goto yy599;
+ if (yych == 't') goto yy599;
goto yy186;
-yy571:
- YYDEBUG(571, *YYCURSOR);
+yy579:
+ YYDEBUG(579, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy584;
- if (yych == 'e') goto yy584;
+ if (yych == 'E') goto yy592;
+ if (yych == 'e') goto yy592;
goto yy186;
-yy572:
- YYDEBUG(572, *YYCURSOR);
+yy580:
+ YYDEBUG(580, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy573;
+ if (yych == 'L') goto yy581;
if (yych != 'l') goto yy186;
-yy573:
- YYDEBUG(573, *YYCURSOR);
+yy581:
+ YYDEBUG(581, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'U') goto yy574;
+ if (yych == 'U') goto yy582;
if (yych != 'u') goto yy186;
-yy574:
- YYDEBUG(574, *YYCURSOR);
+yy582:
+ YYDEBUG(582, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'D') goto yy575;
+ if (yych == 'D') goto yy583;
if (yych != 'd') goto yy186;
-yy575:
- YYDEBUG(575, *YYCURSOR);
+yy583:
+ YYDEBUG(583, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy576;
+ if (yych == 'E') goto yy584;
if (yych != 'e') goto yy186;
-yy576:
- YYDEBUG(576, *YYCURSOR);
+yy584:
+ YYDEBUG(584, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '^') {
if (yych <= '9') {
if (yych >= '0') goto yy185;
} else {
- if (yych <= '@') goto yy577;
+ if (yych <= '@') goto yy585;
if (yych <= 'Z') goto yy185;
}
} else {
if (yych <= '`') {
- if (yych <= '_') goto yy578;
+ if (yych <= '_') goto yy586;
} else {
if (yych <= 'z') goto yy185;
if (yych >= 0x7F) goto yy185;
}
}
-yy577:
- YYDEBUG(577, *YYCURSOR);
+yy585:
+ YYDEBUG(585, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1105 "Zend/zend_language_scanner.l"
+#line 1246 "Zend/zend_language_scanner.l"
{
return T_INCLUDE;
}
-#line 5629 "Zend/zend_language_scanner.c"
-yy578:
- YYDEBUG(578, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'O') goto yy579;
- if (yych != 'o') goto yy186;
-yy579:
- YYDEBUG(579, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'N') goto yy580;
- if (yych != 'n') goto yy186;
-yy580:
- YYDEBUG(580, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'C') goto yy581;
- if (yych != 'c') goto yy186;
-yy581:
- YYDEBUG(581, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'E') goto yy582;
- if (yych != 'e') goto yy186;
-yy582:
- YYDEBUG(582, *YYCURSOR);
- ++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
- goto yy185;
- }
- YYDEBUG(583, *YYCURSOR);
- yyleng = YYCURSOR - SCNG(yy_text);
-#line 1109 "Zend/zend_language_scanner.l"
- {
- return T_INCLUDE_ONCE;
-}
-#line 5662 "Zend/zend_language_scanner.c"
-yy584:
- YYDEBUG(584, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'R') goto yy585;
- if (yych != 'r') goto yy186;
-yy585:
- YYDEBUG(585, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'F') goto yy586;
- if (yych != 'f') goto yy186;
+#line 5855 "Zend/zend_language_scanner.c"
yy586:
YYDEBUG(586, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy587;
- if (yych != 'a') goto yy186;
+ if (yych == 'O') goto yy587;
+ if (yych != 'o') goto yy186;
yy587:
YYDEBUG(587, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy588;
- if (yych != 'c') goto yy186;
+ if (yych == 'N') goto yy588;
+ if (yych != 'n') goto yy186;
yy588:
YYDEBUG(588, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy589;
- if (yych != 'e') goto yy186;
+ if (yych == 'C') goto yy589;
+ if (yych != 'c') goto yy186;
yy589:
YYDEBUG(589, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy590;
+ if (yych != 'e') goto yy186;
+yy590:
+ YYDEBUG(590, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(590, *YYCURSOR);
+ YYDEBUG(591, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1007 "Zend/zend_language_scanner.l"
+#line 1250 "Zend/zend_language_scanner.l"
{
- return T_INTERFACE;
+ return T_INCLUDE_ONCE;
}
-#line 5700 "Zend/zend_language_scanner.c"
-yy591:
- YYDEBUG(591, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'A') goto yy592;
- if (yych != 'a') goto yy186;
+#line 5888 "Zend/zend_language_scanner.c"
yy592:
YYDEBUG(592, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy593;
- if (yych != 'n') goto yy186;
+ if (yych == 'R') goto yy593;
+ if (yych != 'r') goto yy186;
yy593:
YYDEBUG(593, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy594;
- if (yych != 'c') goto yy186;
+ if (yych == 'F') goto yy594;
+ if (yych != 'f') goto yy186;
yy594:
YYDEBUG(594, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy595;
- if (yych != 'e') goto yy186;
+ if (yych == 'A') goto yy595;
+ if (yych != 'a') goto yy186;
yy595:
YYDEBUG(595, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy596;
- if (yych != 'o') goto yy186;
+ if (yych == 'C') goto yy596;
+ if (yych != 'c') goto yy186;
yy596:
YYDEBUG(596, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'F') goto yy597;
- if (yych != 'f') goto yy186;
+ if (yych == 'E') goto yy597;
+ if (yych != 'e') goto yy186;
yy597:
YYDEBUG(597, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
YYDEBUG(598, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 959 "Zend/zend_language_scanner.l"
+#line 1148 "Zend/zend_language_scanner.l"
{
- return T_INSTANCEOF;
+ return T_INTERFACE;
}
-#line 5743 "Zend/zend_language_scanner.c"
+#line 5926 "Zend/zend_language_scanner.c"
yy599:
YYDEBUG(599, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy600;
- if (yych != 'l') goto yy186;
+ if (yych <= 'E') {
+ if (yych == 'A') goto yy600;
+ if (yych <= 'D') goto yy186;
+ goto yy601;
+ } else {
+ if (yych <= 'a') {
+ if (yych <= '`') goto yy186;
+ } else {
+ if (yych == 'e') goto yy601;
+ goto yy186;
+ }
+ }
yy600:
YYDEBUG(600, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy601;
- if (yych != 'e') goto yy186;
+ if (yych == 'N') goto yy607;
+ if (yych == 'n') goto yy607;
+ goto yy186;
yy601:
YYDEBUG(601, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'M') goto yy602;
- if (yych != 'm') goto yy186;
+ if (yych == 'A') goto yy602;
+ if (yych != 'a') goto yy186;
yy602:
YYDEBUG(602, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy603;
- if (yych != 'e') goto yy186;
+ if (yych == 'D') goto yy603;
+ if (yych != 'd') goto yy186;
yy603:
YYDEBUG(603, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy604;
- if (yych != 'n') goto yy186;
+ if (yych == 'O') goto yy604;
+ if (yych != 'o') goto yy186;
yy604:
YYDEBUG(604, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy605;
- if (yych != 't') goto yy186;
+ if (yych == 'F') goto yy605;
+ if (yych != 'f') goto yy186;
yy605:
YYDEBUG(605, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'S') goto yy606;
- if (yych != 's') goto yy186;
-yy606:
- YYDEBUG(606, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(607, *YYCURSOR);
+ YYDEBUG(606, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1015 "Zend/zend_language_scanner.l"
+#line 1270 "Zend/zend_language_scanner.l"
{
- return T_IMPLEMENTS;
+ return T_INSTEADOF;
}
-#line 5791 "Zend/zend_language_scanner.c"
+#line 5980 "Zend/zend_language_scanner.c"
+yy607:
+ YYDEBUG(607, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'C') goto yy608;
+ if (yych != 'c') goto yy186;
yy608:
YYDEBUG(608, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy612;
- if (yych == 'r') goto yy612;
- goto yy186;
+ if (yych == 'E') goto yy609;
+ if (yych != 'e') goto yy186;
yy609:
YYDEBUG(609, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'Y') goto yy610;
- if (yych != 'y') goto yy186;
+ if (yych == 'O') goto yy610;
+ if (yych != 'o') goto yy186;
yy610:
YYDEBUG(610, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'F') goto yy611;
+ if (yych != 'f') goto yy186;
+yy611:
+ YYDEBUG(611, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(611, *YYCURSOR);
+ YYDEBUG(612, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 895 "Zend/zend_language_scanner.l"
+#line 1100 "Zend/zend_language_scanner.l"
{
- return T_TRY;
+ return T_INSTANCEOF;
}
-#line 5815 "Zend/zend_language_scanner.c"
-yy612:
- YYDEBUG(612, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'O') goto yy613;
- if (yych != 'o') goto yy186;
+#line 6013 "Zend/zend_language_scanner.c"
yy613:
YYDEBUG(613, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'W') goto yy614;
- if (yych != 'w') goto yy186;
+ if (yych == 'L') goto yy614;
+ if (yych != 'l') goto yy186;
yy614:
YYDEBUG(614, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy615;
+ if (yych != 'e') goto yy186;
+yy615:
+ YYDEBUG(615, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'M') goto yy616;
+ if (yych != 'm') goto yy186;
+yy616:
+ YYDEBUG(616, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy617;
+ if (yych != 'e') goto yy186;
+yy617:
+ YYDEBUG(617, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'N') goto yy618;
+ if (yych != 'n') goto yy186;
+yy618:
+ YYDEBUG(618, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'T') goto yy619;
+ if (yych != 't') goto yy186;
+yy619:
+ YYDEBUG(619, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'S') goto yy620;
+ if (yych != 's') goto yy186;
+yy620:
+ YYDEBUG(620, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(615, *YYCURSOR);
+ YYDEBUG(621, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1160 "Zend/zend_language_scanner.l"
+ {
+ return T_IMPLEMENTS;
+}
+#line 6061 "Zend/zend_language_scanner.c"
+yy622:
+ YYDEBUG(622, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'R') goto yy630;
+ if (yych == 'r') goto yy630;
+ goto yy186;
+yy623:
+ YYDEBUG(623, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych <= 'Y') {
+ if (yych == 'A') goto yy626;
+ if (yych <= 'X') goto yy186;
+ } else {
+ if (yych <= 'a') {
+ if (yych <= '`') goto yy186;
+ goto yy626;
+ } else {
+ if (yych != 'y') goto yy186;
+ }
+ }
+ YYDEBUG(624, *YYCURSOR);
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
+ YYDEBUG(625, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1036 "Zend/zend_language_scanner.l"
+ {
+ return T_TRY;
+}
+#line 6093 "Zend/zend_language_scanner.c"
+yy626:
+ YYDEBUG(626, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'I') goto yy627;
+ if (yych != 'i') goto yy186;
+yy627:
+ YYDEBUG(627, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'T') goto yy628;
+ if (yych != 't') goto yy186;
+yy628:
+ YYDEBUG(628, *YYCURSOR);
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
+ YYDEBUG(629, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 903 "Zend/zend_language_scanner.l"
+#line 1152 "Zend/zend_language_scanner.l"
+ {
+ return T_TRAIT;
+}
+#line 6116 "Zend/zend_language_scanner.c"
+yy630:
+ YYDEBUG(630, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'O') goto yy631;
+ if (yych != 'o') goto yy186;
+yy631:
+ YYDEBUG(631, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'W') goto yy632;
+ if (yych != 'w') goto yy186;
+yy632:
+ YYDEBUG(632, *YYCURSOR);
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
+ YYDEBUG(633, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1044 "Zend/zend_language_scanner.l"
{
return T_THROW;
}
-#line 5838 "Zend/zend_language_scanner.c"
-yy616:
- YYDEBUG(616, *YYCURSOR);
+#line 6139 "Zend/zend_language_scanner.c"
+yy634:
+ YYDEBUG(634, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'T') {
- if (yych == 'Q') goto yy618;
+ if (yych == 'Q') goto yy636;
if (yych <= 'S') goto yy186;
} else {
if (yych <= 'q') {
if (yych <= 'p') goto yy186;
- goto yy618;
+ goto yy636;
} else {
if (yych != 't') goto yy186;
}
}
- YYDEBUG(617, *YYCURSOR);
+ YYDEBUG(635, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'U') goto yy630;
- if (yych == 'u') goto yy630;
+ if (yych == 'U') goto yy648;
+ if (yych == 'u') goto yy648;
goto yy186;
-yy618:
- YYDEBUG(618, *YYCURSOR);
+yy636:
+ YYDEBUG(636, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'U') goto yy619;
+ if (yych == 'U') goto yy637;
if (yych != 'u') goto yy186;
-yy619:
- YYDEBUG(619, *YYCURSOR);
+yy637:
+ YYDEBUG(637, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy620;
+ if (yych == 'I') goto yy638;
if (yych != 'i') goto yy186;
-yy620:
- YYDEBUG(620, *YYCURSOR);
+yy638:
+ YYDEBUG(638, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy621;
+ if (yych == 'R') goto yy639;
if (yych != 'r') goto yy186;
-yy621:
- YYDEBUG(621, *YYCURSOR);
+yy639:
+ YYDEBUG(639, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy622;
+ if (yych == 'E') goto yy640;
if (yych != 'e') goto yy186;
-yy622:
- YYDEBUG(622, *YYCURSOR);
+yy640:
+ YYDEBUG(640, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '^') {
if (yych <= '9') {
if (yych >= '0') goto yy185;
} else {
- if (yych <= '@') goto yy623;
+ if (yych <= '@') goto yy641;
if (yych <= 'Z') goto yy185;
}
} else {
if (yych <= '`') {
- if (yych <= '_') goto yy624;
+ if (yych <= '_') goto yy642;
} else {
if (yych <= 'z') goto yy185;
if (yych >= 0x7F) goto yy185;
}
}
-yy623:
- YYDEBUG(623, *YYCURSOR);
+yy641:
+ YYDEBUG(641, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1113 "Zend/zend_language_scanner.l"
+#line 1254 "Zend/zend_language_scanner.l"
{
return T_REQUIRE;
}
-#line 5903 "Zend/zend_language_scanner.c"
-yy624:
- YYDEBUG(624, *YYCURSOR);
+#line 6204 "Zend/zend_language_scanner.c"
+yy642:
+ YYDEBUG(642, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy625;
+ if (yych == 'O') goto yy643;
if (yych != 'o') goto yy186;
-yy625:
- YYDEBUG(625, *YYCURSOR);
+yy643:
+ YYDEBUG(643, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy626;
+ if (yych == 'N') goto yy644;
if (yych != 'n') goto yy186;
-yy626:
- YYDEBUG(626, *YYCURSOR);
+yy644:
+ YYDEBUG(644, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy627;
+ if (yych == 'C') goto yy645;
if (yych != 'c') goto yy186;
-yy627:
- YYDEBUG(627, *YYCURSOR);
+yy645:
+ YYDEBUG(645, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy628;
+ if (yych == 'E') goto yy646;
if (yych != 'e') goto yy186;
-yy628:
- YYDEBUG(628, *YYCURSOR);
+yy646:
+ YYDEBUG(646, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(629, *YYCURSOR);
+ YYDEBUG(647, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1117 "Zend/zend_language_scanner.l"
+#line 1258 "Zend/zend_language_scanner.l"
{
return T_REQUIRE_ONCE;
}
-#line 5936 "Zend/zend_language_scanner.c"
-yy630:
- YYDEBUG(630, *YYCURSOR);
+#line 6237 "Zend/zend_language_scanner.c"
+yy648:
+ YYDEBUG(648, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy631;
+ if (yych == 'R') goto yy649;
if (yych != 'r') goto yy186;
-yy631:
- YYDEBUG(631, *YYCURSOR);
+yy649:
+ YYDEBUG(649, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy632;
+ if (yych == 'N') goto yy650;
if (yych != 'n') goto yy186;
-yy632:
- YYDEBUG(632, *YYCURSOR);
+yy650:
+ YYDEBUG(650, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(633, *YYCURSOR);
+ YYDEBUG(651, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 891 "Zend/zend_language_scanner.l"
+#line 1032 "Zend/zend_language_scanner.l"
{
return T_RETURN;
}
-#line 5959 "Zend/zend_language_scanner.c"
-yy634:
- YYDEBUG(634, *YYCURSOR);
+#line 6260 "Zend/zend_language_scanner.c"
+yy652:
+ YYDEBUG(652, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'T') {
- if (yych <= 'R') goto yy186;
- if (yych <= 'S') goto yy656;
- goto yy655;
+ if (yych <= 'L') {
+ if (yych <= 'K') goto yy186;
+ goto yy675;
+ } else {
+ if (yych <= 'R') goto yy186;
+ if (yych <= 'S') goto yy674;
+ goto yy673;
+ }
} else {
- if (yych <= 'r') goto yy186;
- if (yych <= 's') goto yy656;
- if (yych <= 't') goto yy655;
- goto yy186;
+ if (yych <= 'r') {
+ if (yych == 'l') goto yy675;
+ goto yy186;
+ } else {
+ if (yych <= 's') goto yy674;
+ if (yych <= 't') goto yy673;
+ goto yy186;
+ }
}
-yy635:
- YYDEBUG(635, *YYCURSOR);
+yy653:
+ YYDEBUG(653, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'O') {
- if (yych == 'A') goto yy647;
+ if (yych == 'A') goto yy665;
if (yych <= 'N') goto yy186;
- goto yy648;
+ goto yy666;
} else {
if (yych <= 'a') {
if (yych <= '`') goto yy186;
- goto yy647;
+ goto yy665;
} else {
- if (yych == 'o') goto yy648;
+ if (yych == 'o') goto yy666;
goto yy186;
}
}
-yy636:
- YYDEBUG(636, *YYCURSOR);
+yy654:
+ YYDEBUG(654, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy637;
+ if (yych == 'N') goto yy655;
if (yych != 'n') goto yy186;
-yy637:
- YYDEBUG(637, *YYCURSOR);
+yy655:
+ YYDEBUG(655, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'T') {
if (yych <= 'R') goto yy186;
- if (yych >= 'T') goto yy639;
+ if (yych >= 'T') goto yy657;
} else {
if (yych <= 'r') goto yy186;
- if (yych <= 's') goto yy638;
- if (yych <= 't') goto yy639;
+ if (yych <= 's') goto yy656;
+ if (yych <= 't') goto yy657;
goto yy186;
}
-yy638:
- YYDEBUG(638, *YYCURSOR);
+yy656:
+ YYDEBUG(656, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy645;
- if (yych == 't') goto yy645;
+ if (yych == 'T') goto yy663;
+ if (yych == 't') goto yy663;
goto yy186;
-yy639:
- YYDEBUG(639, *YYCURSOR);
+yy657:
+ YYDEBUG(657, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy640;
+ if (yych == 'I') goto yy658;
if (yych != 'i') goto yy186;
-yy640:
- YYDEBUG(640, *YYCURSOR);
+yy658:
+ YYDEBUG(658, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy641;
+ if (yych == 'N') goto yy659;
if (yych != 'n') goto yy186;
-yy641:
- YYDEBUG(641, *YYCURSOR);
+yy659:
+ YYDEBUG(659, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'U') goto yy642;
+ if (yych == 'U') goto yy660;
if (yych != 'u') goto yy186;
-yy642:
- YYDEBUG(642, *YYCURSOR);
+yy660:
+ YYDEBUG(660, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy643;
+ if (yych == 'E') goto yy661;
if (yych != 'e') goto yy186;
-yy643:
- YYDEBUG(643, *YYCURSOR);
+yy661:
+ YYDEBUG(661, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(644, *YYCURSOR);
+ YYDEBUG(662, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 987 "Zend/zend_language_scanner.l"
+#line 1128 "Zend/zend_language_scanner.l"
{
return T_CONTINUE;
}
-#line 6044 "Zend/zend_language_scanner.c"
-yy645:
- YYDEBUG(645, *YYCURSOR);
+#line 6354 "Zend/zend_language_scanner.c"
+yy663:
+ YYDEBUG(663, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(646, *YYCURSOR);
+ YYDEBUG(664, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 887 "Zend/zend_language_scanner.l"
+#line 1028 "Zend/zend_language_scanner.l"
{
return T_CONST;
}
-#line 6057 "Zend/zend_language_scanner.c"
-yy647:
- YYDEBUG(647, *YYCURSOR);
+#line 6367 "Zend/zend_language_scanner.c"
+yy665:
+ YYDEBUG(665, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy652;
- if (yych == 's') goto yy652;
+ if (yych == 'S') goto yy670;
+ if (yych == 's') goto yy670;
goto yy186;
-yy648:
- YYDEBUG(648, *YYCURSOR);
+yy666:
+ YYDEBUG(666, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy649;
+ if (yych == 'N') goto yy667;
if (yych != 'n') goto yy186;
-yy649:
- YYDEBUG(649, *YYCURSOR);
+yy667:
+ YYDEBUG(667, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy650;
+ if (yych == 'E') goto yy668;
if (yych != 'e') goto yy186;
-yy650:
- YYDEBUG(650, *YYCURSOR);
+yy668:
+ YYDEBUG(668, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(651, *YYCURSOR);
+ YYDEBUG(669, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1061 "Zend/zend_language_scanner.l"
+#line 1206 "Zend/zend_language_scanner.l"
{
return T_CLONE;
}
-#line 6086 "Zend/zend_language_scanner.c"
-yy652:
- YYDEBUG(652, *YYCURSOR);
+#line 6396 "Zend/zend_language_scanner.c"
+yy670:
+ YYDEBUG(670, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy653;
+ if (yych == 'S') goto yy671;
if (yych != 's') goto yy186;
-yy653:
- YYDEBUG(653, *YYCURSOR);
+yy671:
+ YYDEBUG(671, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(654, *YYCURSOR);
+ YYDEBUG(672, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1003 "Zend/zend_language_scanner.l"
+#line 1144 "Zend/zend_language_scanner.l"
{
return T_CLASS;
}
-#line 6104 "Zend/zend_language_scanner.c"
-yy655:
- YYDEBUG(655, *YYCURSOR);
+#line 6414 "Zend/zend_language_scanner.c"
+yy673:
+ YYDEBUG(673, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy659;
- if (yych == 'c') goto yy659;
+ if (yych == 'C') goto yy684;
+ if (yych == 'c') goto yy684;
goto yy186;
-yy656:
- YYDEBUG(656, *YYCURSOR);
+yy674:
+ YYDEBUG(674, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy657;
+ if (yych == 'E') goto yy682;
+ if (yych == 'e') goto yy682;
+ goto yy186;
+yy675:
+ YYDEBUG(675, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'L') goto yy676;
+ if (yych != 'l') goto yy186;
+yy676:
+ YYDEBUG(676, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'A') goto yy677;
+ if (yych != 'a') goto yy186;
+yy677:
+ YYDEBUG(677, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'B') goto yy678;
+ if (yych != 'b') goto yy186;
+yy678:
+ YYDEBUG(678, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'L') goto yy679;
+ if (yych != 'l') goto yy186;
+yy679:
+ YYDEBUG(679, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych == 'E') goto yy680;
if (yych != 'e') goto yy186;
-yy657:
- YYDEBUG(657, *YYCURSOR);
+yy680:
+ YYDEBUG(680, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(658, *YYCURSOR);
+ YYDEBUG(681, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 975 "Zend/zend_language_scanner.l"
+#line 1330 "Zend/zend_language_scanner.l"
+ {
+ return T_CALLABLE;
+}
+#line 6464 "Zend/zend_language_scanner.c"
+yy682:
+ YYDEBUG(682, *YYCURSOR);
+ ++YYCURSOR;
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
+ goto yy185;
+ }
+ YYDEBUG(683, *YYCURSOR);
+ yyleng = YYCURSOR - SCNG(yy_text);
+#line 1116 "Zend/zend_language_scanner.l"
{
return T_CASE;
}
-#line 6128 "Zend/zend_language_scanner.c"
-yy659:
- YYDEBUG(659, *YYCURSOR);
+#line 6477 "Zend/zend_language_scanner.c"
+yy684:
+ YYDEBUG(684, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy660;
+ if (yych == 'H') goto yy685;
if (yych != 'h') goto yy186;
-yy660:
- YYDEBUG(660, *YYCURSOR);
+yy685:
+ YYDEBUG(685, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(661, *YYCURSOR);
+ YYDEBUG(686, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 899 "Zend/zend_language_scanner.l"
+#line 1040 "Zend/zend_language_scanner.l"
{
return T_CATCH;
}
-#line 6146 "Zend/zend_language_scanner.c"
-yy662:
- YYDEBUG(662, *YYCURSOR);
+#line 6495 "Zend/zend_language_scanner.c"
+yy687:
+ YYDEBUG(687, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy679;
- if (yych == 'n') goto yy679;
+ if (yych == 'N') goto yy704;
+ if (yych == 'n') goto yy704;
goto yy186;
-yy663:
- YYDEBUG(663, *YYCURSOR);
+yy688:
+ YYDEBUG(688, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy672;
- if (yych == 'r') goto yy672;
+ if (yych == 'R') goto yy697;
+ if (yych == 'r') goto yy697;
goto yy186;
-yy664:
- YYDEBUG(664, *YYCURSOR);
+yy689:
+ YYDEBUG(689, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy665;
+ if (yych == 'N') goto yy690;
if (yych != 'n') goto yy186;
-yy665:
- YYDEBUG(665, *YYCURSOR);
+yy690:
+ YYDEBUG(690, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy666;
+ if (yych == 'C') goto yy691;
if (yych != 'c') goto yy186;
-yy666:
- YYDEBUG(666, *YYCURSOR);
+yy691:
+ YYDEBUG(691, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy667;
+ if (yych == 'T') goto yy692;
if (yych != 't') goto yy186;
-yy667:
- YYDEBUG(667, *YYCURSOR);
+yy692:
+ YYDEBUG(692, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy668;
+ if (yych == 'I') goto yy693;
if (yych != 'i') goto yy186;
-yy668:
- YYDEBUG(668, *YYCURSOR);
+yy693:
+ YYDEBUG(693, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy669;
+ if (yych == 'O') goto yy694;
if (yych != 'o') goto yy186;
-yy669:
- YYDEBUG(669, *YYCURSOR);
+yy694:
+ YYDEBUG(694, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy670;
+ if (yych == 'N') goto yy695;
if (yych != 'n') goto yy186;
-yy670:
- YYDEBUG(670, *YYCURSOR);
+yy695:
+ YYDEBUG(695, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(671, *YYCURSOR);
+ YYDEBUG(696, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 883 "Zend/zend_language_scanner.l"
+#line 1024 "Zend/zend_language_scanner.l"
{
return T_FUNCTION;
}
-#line 6201 "Zend/zend_language_scanner.c"
-yy672:
- YYDEBUG(672, *YYCURSOR);
+#line 6550 "Zend/zend_language_scanner.c"
+yy697:
+ YYDEBUG(697, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '^') {
if (yych <= '@') {
- if (yych <= '/') goto yy673;
+ if (yych <= '/') goto yy698;
if (yych <= '9') goto yy185;
} else {
- if (yych == 'E') goto yy674;
+ if (yych == 'E') goto yy699;
if (yych <= 'Z') goto yy185;
}
} else {
if (yych <= 'd') {
if (yych != '`') goto yy185;
} else {
- if (yych <= 'e') goto yy674;
+ if (yych <= 'e') goto yy699;
if (yych <= 'z') goto yy185;
if (yych >= 0x7F) goto yy185;
}
}
-yy673:
- YYDEBUG(673, *YYCURSOR);
+yy698:
+ YYDEBUG(698, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 935 "Zend/zend_language_scanner.l"
+#line 1076 "Zend/zend_language_scanner.l"
{
return T_FOR;
}
-#line 6229 "Zend/zend_language_scanner.c"
-yy674:
- YYDEBUG(674, *YYCURSOR);
+#line 6578 "Zend/zend_language_scanner.c"
+yy699:
+ YYDEBUG(699, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy675;
+ if (yych == 'A') goto yy700;
if (yych != 'a') goto yy186;
-yy675:
- YYDEBUG(675, *YYCURSOR);
+yy700:
+ YYDEBUG(700, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy676;
+ if (yych == 'C') goto yy701;
if (yych != 'c') goto yy186;
-yy676:
- YYDEBUG(676, *YYCURSOR);
+yy701:
+ YYDEBUG(701, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy677;
+ if (yych == 'H') goto yy702;
if (yych != 'h') goto yy186;
-yy677:
- YYDEBUG(677, *YYCURSOR);
+yy702:
+ YYDEBUG(702, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(678, *YYCURSOR);
+ YYDEBUG(703, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 943 "Zend/zend_language_scanner.l"
+#line 1084 "Zend/zend_language_scanner.l"
{
return T_FOREACH;
}
-#line 6257 "Zend/zend_language_scanner.c"
-yy679:
- YYDEBUG(679, *YYCURSOR);
+#line 6606 "Zend/zend_language_scanner.c"
+yy704:
+ YYDEBUG(704, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy680;
+ if (yych == 'A') goto yy705;
if (yych != 'a') goto yy186;
-yy680:
- YYDEBUG(680, *YYCURSOR);
+yy705:
+ YYDEBUG(705, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy681;
+ if (yych == 'L') goto yy706;
if (yych != 'l') goto yy186;
-yy681:
- YYDEBUG(681, *YYCURSOR);
+yy706:
+ YYDEBUG(706, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(682, *YYCURSOR);
+ YYDEBUG(707, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1153 "Zend/zend_language_scanner.l"
+#line 1298 "Zend/zend_language_scanner.l"
{
return T_FINAL;
}
-#line 6280 "Zend/zend_language_scanner.c"
-yy683:
- YYDEBUG(683, *YYCURSOR);
+#line 6629 "Zend/zend_language_scanner.c"
+yy708:
+ YYDEBUG(708, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'F') {
- if (yych == 'C') goto yy689;
+ if (yych == 'C') goto yy714;
if (yych <= 'E') goto yy186;
- goto yy690;
+ goto yy715;
} else {
if (yych <= 'c') {
if (yych <= 'b') goto yy186;
- goto yy689;
+ goto yy714;
} else {
- if (yych == 'f') goto yy690;
+ if (yych == 'f') goto yy715;
goto yy186;
}
}
-yy684:
- YYDEBUG(684, *YYCURSOR);
+yy709:
+ YYDEBUG(709, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy687;
- if (yych == 'e') goto yy687;
+ if (yych == 'E') goto yy712;
+ if (yych == 'e') goto yy712;
goto yy186;
-yy685:
- YYDEBUG(685, *YYCURSOR);
+yy710:
+ YYDEBUG(710, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(686, *YYCURSOR);
+ YYDEBUG(711, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 931 "Zend/zend_language_scanner.l"
+#line 1072 "Zend/zend_language_scanner.l"
{
return T_DO;
}
-#line 6315 "Zend/zend_language_scanner.c"
-yy687:
- YYDEBUG(687, *YYCURSOR);
+#line 6664 "Zend/zend_language_scanner.c"
+yy712:
+ YYDEBUG(712, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(688, *YYCURSOR);
+ YYDEBUG(713, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 879 "Zend/zend_language_scanner.l"
+#line 1020 "Zend/zend_language_scanner.l"
{
return T_EXIT;
}
-#line 6328 "Zend/zend_language_scanner.c"
-yy689:
- YYDEBUG(689, *YYCURSOR);
+#line 6677 "Zend/zend_language_scanner.c"
+yy714:
+ YYDEBUG(714, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy696;
- if (yych == 'l') goto yy696;
+ if (yych == 'L') goto yy721;
+ if (yych == 'l') goto yy721;
goto yy186;
-yy690:
- YYDEBUG(690, *YYCURSOR);
+yy715:
+ YYDEBUG(715, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy691;
+ if (yych == 'A') goto yy716;
if (yych != 'a') goto yy186;
-yy691:
- YYDEBUG(691, *YYCURSOR);
+yy716:
+ YYDEBUG(716, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'U') goto yy692;
+ if (yych == 'U') goto yy717;
if (yych != 'u') goto yy186;
-yy692:
- YYDEBUG(692, *YYCURSOR);
+yy717:
+ YYDEBUG(717, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy693;
+ if (yych == 'L') goto yy718;
if (yych != 'l') goto yy186;
-yy693:
- YYDEBUG(693, *YYCURSOR);
+yy718:
+ YYDEBUG(718, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy694;
+ if (yych == 'T') goto yy719;
if (yych != 't') goto yy186;
-yy694:
- YYDEBUG(694, *YYCURSOR);
+yy719:
+ YYDEBUG(719, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(695, *YYCURSOR);
+ YYDEBUG(720, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 979 "Zend/zend_language_scanner.l"
+#line 1120 "Zend/zend_language_scanner.l"
{
return T_DEFAULT;
}
-#line 6367 "Zend/zend_language_scanner.c"
-yy696:
- YYDEBUG(696, *YYCURSOR);
+#line 6716 "Zend/zend_language_scanner.c"
+yy721:
+ YYDEBUG(721, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy697;
+ if (yych == 'A') goto yy722;
if (yych != 'a') goto yy186;
-yy697:
- YYDEBUG(697, *YYCURSOR);
+yy722:
+ YYDEBUG(722, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy698;
+ if (yych == 'R') goto yy723;
if (yych != 'r') goto yy186;
-yy698:
- YYDEBUG(698, *YYCURSOR);
+yy723:
+ YYDEBUG(723, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy699;
+ if (yych == 'E') goto yy724;
if (yych != 'e') goto yy186;
-yy699:
- YYDEBUG(699, *YYCURSOR);
+yy724:
+ YYDEBUG(724, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(700, *YYCURSOR);
+ YYDEBUG(725, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 951 "Zend/zend_language_scanner.l"
+#line 1092 "Zend/zend_language_scanner.l"
{
return T_DECLARE;
}
-#line 6395 "Zend/zend_language_scanner.c"
-yy701:
- YYDEBUG(701, *YYCURSOR);
+#line 6744 "Zend/zend_language_scanner.c"
+yy726:
+ YYDEBUG(726, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy763;
- if (yych == 'h') goto yy763;
+ if (yych == 'H') goto yy788;
+ if (yych == 'h') goto yy788;
goto yy186;
-yy702:
- YYDEBUG(702, *YYCURSOR);
+yy727:
+ YYDEBUG(727, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy757;
- if (yych == 's') goto yy757;
+ if (yych == 'S') goto yy782;
+ if (yych == 's') goto yy782;
goto yy186;
-yy703:
- YYDEBUG(703, *YYCURSOR);
+yy728:
+ YYDEBUG(728, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'P') goto yy753;
- if (yych == 'p') goto yy753;
+ if (yych == 'P') goto yy778;
+ if (yych == 'p') goto yy778;
goto yy186;
-yy704:
- YYDEBUG(704, *YYCURSOR);
+yy729:
+ YYDEBUG(729, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'D') goto yy719;
- if (yych == 'd') goto yy719;
+ if (yych == 'D') goto yy744;
+ if (yych == 'd') goto yy744;
goto yy186;
-yy705:
- YYDEBUG(705, *YYCURSOR);
+yy730:
+ YYDEBUG(730, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy716;
- if (yych == 'a') goto yy716;
+ if (yych == 'A') goto yy741;
+ if (yych == 'a') goto yy741;
goto yy186;
-yy706:
- YYDEBUG(706, *YYCURSOR);
+yy731:
+ YYDEBUG(731, *YYCURSOR);
yych = *++YYCURSOR;
if (yych <= 'T') {
- if (yych == 'I') goto yy707;
+ if (yych == 'I') goto yy732;
if (yych <= 'S') goto yy186;
- goto yy708;
+ goto yy733;
} else {
if (yych <= 'i') {
if (yych <= 'h') goto yy186;
} else {
- if (yych == 't') goto yy708;
+ if (yych == 't') goto yy733;
goto yy186;
}
}
-yy707:
- YYDEBUG(707, *YYCURSOR);
+yy732:
+ YYDEBUG(732, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy714;
- if (yych == 't') goto yy714;
+ if (yych == 'T') goto yy739;
+ if (yych == 't') goto yy739;
goto yy186;
-yy708:
- YYDEBUG(708, *YYCURSOR);
+yy733:
+ YYDEBUG(733, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy709;
+ if (yych == 'E') goto yy734;
if (yych != 'e') goto yy186;
-yy709:
- YYDEBUG(709, *YYCURSOR);
+yy734:
+ YYDEBUG(734, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'N') goto yy710;
+ if (yych == 'N') goto yy735;
if (yych != 'n') goto yy186;
-yy710:
- YYDEBUG(710, *YYCURSOR);
+yy735:
+ YYDEBUG(735, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'D') goto yy711;
+ if (yych == 'D') goto yy736;
if (yych != 'd') goto yy186;
-yy711:
- YYDEBUG(711, *YYCURSOR);
+yy736:
+ YYDEBUG(736, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'S') goto yy712;
+ if (yych == 'S') goto yy737;
if (yych != 's') goto yy186;
-yy712:
- YYDEBUG(712, *YYCURSOR);
+yy737:
+ YYDEBUG(737, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(713, *YYCURSOR);
+ YYDEBUG(738, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1011 "Zend/zend_language_scanner.l"
+#line 1156 "Zend/zend_language_scanner.l"
{
return T_EXTENDS;
}
-#line 6479 "Zend/zend_language_scanner.c"
-yy714:
- YYDEBUG(714, *YYCURSOR);
+#line 6828 "Zend/zend_language_scanner.c"
+yy739:
+ YYDEBUG(739, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(715, *YYCURSOR);
+ YYDEBUG(740, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 875 "Zend/zend_language_scanner.l"
+#line 1016 "Zend/zend_language_scanner.l"
{
return T_EXIT;
}
-#line 6492 "Zend/zend_language_scanner.c"
-yy716:
- YYDEBUG(716, *YYCURSOR);
+#line 6841 "Zend/zend_language_scanner.c"
+yy741:
+ YYDEBUG(741, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy717;
+ if (yych == 'L') goto yy742;
if (yych != 'l') goto yy186;
-yy717:
- YYDEBUG(717, *YYCURSOR);
+yy742:
+ YYDEBUG(742, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(718, *YYCURSOR);
+ YYDEBUG(743, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1101 "Zend/zend_language_scanner.l"
+#line 1242 "Zend/zend_language_scanner.l"
{
return T_EVAL;
}
-#line 6510 "Zend/zend_language_scanner.c"
-yy719:
- YYDEBUG(719, *YYCURSOR);
+#line 6859 "Zend/zend_language_scanner.c"
+yy744:
+ YYDEBUG(744, *YYCURSOR);
yych = *++YYCURSOR;
YYDEBUG(-1, yych);
switch (yych) {
case 'D':
- case 'd': goto yy720;
+ case 'd': goto yy745;
case 'F':
- case 'f': goto yy721;
+ case 'f': goto yy746;
case 'I':
- case 'i': goto yy722;
+ case 'i': goto yy747;
case 'S':
- case 's': goto yy723;
+ case 's': goto yy748;
case 'W':
- case 'w': goto yy724;
+ case 'w': goto yy749;
default: goto yy186;
}
-yy720:
- YYDEBUG(720, *YYCURSOR);
+yy745:
+ YYDEBUG(745, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy746;
- if (yych == 'e') goto yy746;
+ if (yych == 'E') goto yy771;
+ if (yych == 'e') goto yy771;
goto yy186;
-yy721:
- YYDEBUG(721, *YYCURSOR);
+yy746:
+ YYDEBUG(746, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy738;
- if (yych == 'o') goto yy738;
+ if (yych == 'O') goto yy763;
+ if (yych == 'o') goto yy763;
goto yy186;
-yy722:
- YYDEBUG(722, *YYCURSOR);
+yy747:
+ YYDEBUG(747, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'F') goto yy736;
- if (yych == 'f') goto yy736;
+ if (yych == 'F') goto yy761;
+ if (yych == 'f') goto yy761;
goto yy186;
-yy723:
- YYDEBUG(723, *YYCURSOR);
+yy748:
+ YYDEBUG(748, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'W') goto yy730;
- if (yych == 'w') goto yy730;
+ if (yych == 'W') goto yy755;
+ if (yych == 'w') goto yy755;
goto yy186;
-yy724:
- YYDEBUG(724, *YYCURSOR);
+yy749:
+ YYDEBUG(749, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy725;
+ if (yych == 'H') goto yy750;
if (yych != 'h') goto yy186;
-yy725:
- YYDEBUG(725, *YYCURSOR);
+yy750:
+ YYDEBUG(750, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy726;
+ if (yych == 'I') goto yy751;
if (yych != 'i') goto yy186;
-yy726:
- YYDEBUG(726, *YYCURSOR);
+yy751:
+ YYDEBUG(751, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy727;
+ if (yych == 'L') goto yy752;
if (yych != 'l') goto yy186;
-yy727:
- YYDEBUG(727, *YYCURSOR);
+yy752:
+ YYDEBUG(752, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy728;
+ if (yych == 'E') goto yy753;
if (yych != 'e') goto yy186;
-yy728:
- YYDEBUG(728, *YYCURSOR);
+yy753:
+ YYDEBUG(753, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(729, *YYCURSOR);
+ YYDEBUG(754, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 927 "Zend/zend_language_scanner.l"
+#line 1068 "Zend/zend_language_scanner.l"
{
return T_ENDWHILE;
}
-#line 6584 "Zend/zend_language_scanner.c"
-yy730:
- YYDEBUG(730, *YYCURSOR);
+#line 6933 "Zend/zend_language_scanner.c"
+yy755:
+ YYDEBUG(755, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'I') goto yy731;
+ if (yych == 'I') goto yy756;
if (yych != 'i') goto yy186;
-yy731:
- YYDEBUG(731, *YYCURSOR);
+yy756:
+ YYDEBUG(756, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy732;
+ if (yych == 'T') goto yy757;
if (yych != 't') goto yy186;
-yy732:
- YYDEBUG(732, *YYCURSOR);
+yy757:
+ YYDEBUG(757, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy733;
+ if (yych == 'C') goto yy758;
if (yych != 'c') goto yy186;
-yy733:
- YYDEBUG(733, *YYCURSOR);
+yy758:
+ YYDEBUG(758, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy734;
+ if (yych == 'H') goto yy759;
if (yych != 'h') goto yy186;
-yy734:
- YYDEBUG(734, *YYCURSOR);
+yy759:
+ YYDEBUG(759, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(735, *YYCURSOR);
+ YYDEBUG(760, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 971 "Zend/zend_language_scanner.l"
+#line 1112 "Zend/zend_language_scanner.l"
{
return T_ENDSWITCH;
}
-#line 6617 "Zend/zend_language_scanner.c"
-yy736:
- YYDEBUG(736, *YYCURSOR);
+#line 6966 "Zend/zend_language_scanner.c"
+yy761:
+ YYDEBUG(761, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(737, *YYCURSOR);
+ YYDEBUG(762, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 915 "Zend/zend_language_scanner.l"
+#line 1056 "Zend/zend_language_scanner.l"
{
return T_ENDIF;
}
-#line 6630 "Zend/zend_language_scanner.c"
-yy738:
- YYDEBUG(738, *YYCURSOR);
+#line 6979 "Zend/zend_language_scanner.c"
+yy763:
+ YYDEBUG(763, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy739;
+ if (yych == 'R') goto yy764;
if (yych != 'r') goto yy186;
-yy739:
- YYDEBUG(739, *YYCURSOR);
+yy764:
+ YYDEBUG(764, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '^') {
if (yych <= '@') {
- if (yych <= '/') goto yy740;
+ if (yych <= '/') goto yy765;
if (yych <= '9') goto yy185;
} else {
- if (yych == 'E') goto yy741;
+ if (yych == 'E') goto yy766;
if (yych <= 'Z') goto yy185;
}
} else {
if (yych <= 'd') {
if (yych != '`') goto yy185;
} else {
- if (yych <= 'e') goto yy741;
+ if (yych <= 'e') goto yy766;
if (yych <= 'z') goto yy185;
if (yych >= 0x7F) goto yy185;
}
}
-yy740:
- YYDEBUG(740, *YYCURSOR);
+yy765:
+ YYDEBUG(765, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 939 "Zend/zend_language_scanner.l"
+#line 1080 "Zend/zend_language_scanner.l"
{
return T_ENDFOR;
}
-#line 6663 "Zend/zend_language_scanner.c"
-yy741:
- YYDEBUG(741, *YYCURSOR);
+#line 7012 "Zend/zend_language_scanner.c"
+yy766:
+ YYDEBUG(766, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy742;
+ if (yych == 'A') goto yy767;
if (yych != 'a') goto yy186;
-yy742:
- YYDEBUG(742, *YYCURSOR);
+yy767:
+ YYDEBUG(767, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy743;
+ if (yych == 'C') goto yy768;
if (yych != 'c') goto yy186;
-yy743:
- YYDEBUG(743, *YYCURSOR);
+yy768:
+ YYDEBUG(768, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'H') goto yy744;
+ if (yych == 'H') goto yy769;
if (yych != 'h') goto yy186;
-yy744:
- YYDEBUG(744, *YYCURSOR);
+yy769:
+ YYDEBUG(769, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(745, *YYCURSOR);
+ YYDEBUG(770, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 947 "Zend/zend_language_scanner.l"
+#line 1088 "Zend/zend_language_scanner.l"
{
return T_ENDFOREACH;
}
-#line 6691 "Zend/zend_language_scanner.c"
-yy746:
- YYDEBUG(746, *YYCURSOR);
+#line 7040 "Zend/zend_language_scanner.c"
+yy771:
+ YYDEBUG(771, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'C') goto yy747;
+ if (yych == 'C') goto yy772;
if (yych != 'c') goto yy186;
-yy747:
- YYDEBUG(747, *YYCURSOR);
+yy772:
+ YYDEBUG(772, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'L') goto yy748;
+ if (yych == 'L') goto yy773;
if (yych != 'l') goto yy186;
-yy748:
- YYDEBUG(748, *YYCURSOR);
+yy773:
+ YYDEBUG(773, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'A') goto yy749;
+ if (yych == 'A') goto yy774;
if (yych != 'a') goto yy186;
-yy749:
- YYDEBUG(749, *YYCURSOR);
+yy774:
+ YYDEBUG(774, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'R') goto yy750;
+ if (yych == 'R') goto yy775;
if (yych != 'r') goto yy186;
-yy750:
- YYDEBUG(750, *YYCURSOR);
+yy775:
+ YYDEBUG(775, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy751;
+ if (yych == 'E') goto yy776;
if (yych != 'e') goto yy186;
-yy751:
- YYDEBUG(751, *YYCURSOR);
+yy776:
+ YYDEBUG(776, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(752, *YYCURSOR);
+ YYDEBUG(777, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 955 "Zend/zend_language_scanner.l"
+#line 1096 "Zend/zend_language_scanner.l"
{
return T_ENDDECLARE;
}
-#line 6729 "Zend/zend_language_scanner.c"
-yy753:
- YYDEBUG(753, *YYCURSOR);
+#line 7078 "Zend/zend_language_scanner.c"
+yy778:
+ YYDEBUG(778, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'T') goto yy754;
+ if (yych == 'T') goto yy779;
if (yych != 't') goto yy186;
-yy754:
- YYDEBUG(754, *YYCURSOR);
+yy779:
+ YYDEBUG(779, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'Y') goto yy755;
+ if (yych == 'Y') goto yy780;
if (yych != 'y') goto yy186;
-yy755:
- YYDEBUG(755, *YYCURSOR);
+yy780:
+ YYDEBUG(780, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(756, *YYCURSOR);
+ YYDEBUG(781, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1137 "Zend/zend_language_scanner.l"
+#line 1282 "Zend/zend_language_scanner.l"
{
return T_EMPTY;
}
-#line 6752 "Zend/zend_language_scanner.c"
-yy757:
- YYDEBUG(757, *YYCURSOR);
+#line 7101 "Zend/zend_language_scanner.c"
+yy782:
+ YYDEBUG(782, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'E') goto yy758;
+ if (yych == 'E') goto yy783;
if (yych != 'e') goto yy186;
-yy758:
- YYDEBUG(758, *YYCURSOR);
+yy783:
+ YYDEBUG(783, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '^') {
if (yych <= '@') {
- if (yych <= '/') goto yy759;
+ if (yych <= '/') goto yy784;
if (yych <= '9') goto yy185;
} else {
- if (yych == 'I') goto yy760;
+ if (yych == 'I') goto yy785;
if (yych <= 'Z') goto yy185;
}
} else {
if (yych <= 'h') {
if (yych != '`') goto yy185;
} else {
- if (yych <= 'i') goto yy760;
+ if (yych <= 'i') goto yy785;
if (yych <= 'z') goto yy185;
if (yych >= 0x7F) goto yy185;
}
}
-yy759:
- YYDEBUG(759, *YYCURSOR);
+yy784:
+ YYDEBUG(784, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 919 "Zend/zend_language_scanner.l"
+#line 1060 "Zend/zend_language_scanner.l"
{
return T_ELSE;
}
-#line 6785 "Zend/zend_language_scanner.c"
-yy760:
- YYDEBUG(760, *YYCURSOR);
+#line 7134 "Zend/zend_language_scanner.c"
+yy785:
+ YYDEBUG(785, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'F') goto yy761;
+ if (yych == 'F') goto yy786;
if (yych != 'f') goto yy186;
-yy761:
- YYDEBUG(761, *YYCURSOR);
+yy786:
+ YYDEBUG(786, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(762, *YYCURSOR);
+ YYDEBUG(787, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 911 "Zend/zend_language_scanner.l"
+#line 1052 "Zend/zend_language_scanner.l"
{
return T_ELSEIF;
}
-#line 6803 "Zend/zend_language_scanner.c"
-yy763:
- YYDEBUG(763, *YYCURSOR);
+#line 7152 "Zend/zend_language_scanner.c"
+yy788:
+ YYDEBUG(788, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == 'O') goto yy764;
+ if (yych == 'O') goto yy789;
if (yych != 'o') goto yy186;
-yy764:
- YYDEBUG(764, *YYCURSOR);
+yy789:
+ YYDEBUG(789, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 8) {
+ if (yybm[0+(yych = *YYCURSOR)] & 4) {
goto yy185;
}
- YYDEBUG(765, *YYCURSOR);
+ YYDEBUG(790, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 995 "Zend/zend_language_scanner.l"
+#line 1136 "Zend/zend_language_scanner.l"
{
return T_ECHO;
}
-#line 6821 "Zend/zend_language_scanner.c"
+#line 7170 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_LOOKING_FOR_PROPERTY:
@@ -6856,41 +7205,41 @@ yyc_ST_LOOKING_FOR_PROPERTY:
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
};
- YYDEBUG(766, *YYCURSOR);
+ YYDEBUG(791, *YYCURSOR);
YYFILL(2);
yych = *YYCURSOR;
if (yych <= '-') {
if (yych <= '\r') {
- if (yych <= 0x08) goto yy774;
- if (yych <= '\n') goto yy768;
- if (yych <= '\f') goto yy774;
+ if (yych <= 0x08) goto yy799;
+ if (yych <= '\n') goto yy793;
+ if (yych <= '\f') goto yy799;
} else {
- if (yych == ' ') goto yy768;
- if (yych <= ',') goto yy774;
- goto yy770;
+ if (yych == ' ') goto yy793;
+ if (yych <= ',') goto yy799;
+ goto yy795;
}
} else {
if (yych <= '_') {
- if (yych <= '@') goto yy774;
- if (yych <= 'Z') goto yy772;
- if (yych <= '^') goto yy774;
- goto yy772;
+ if (yych <= '@') goto yy799;
+ if (yych <= 'Z') goto yy797;
+ if (yych <= '^') goto yy799;
+ goto yy797;
} else {
- if (yych <= '`') goto yy774;
- if (yych <= 'z') goto yy772;
- if (yych <= '~') goto yy774;
- goto yy772;
+ if (yych <= '`') goto yy799;
+ if (yych <= 'z') goto yy797;
+ if (yych <= '~') goto yy799;
+ goto yy797;
}
}
-yy768:
- YYDEBUG(768, *YYCURSOR);
+yy793:
+ YYDEBUG(793, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy780;
-yy769:
- YYDEBUG(769, *YYCURSOR);
+ goto yy805;
+yy794:
+ YYDEBUG(794, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1024 "Zend/zend_language_scanner.l"
+#line 1169 "Zend/zend_language_scanner.l"
{
zendlval->value.str.val = yytext; /* no copying - intentional */
zendlval->value.str.len = yyleng;
@@ -6898,73 +7247,73 @@ yy769:
HANDLE_NEWLINES(yytext, yyleng);
return T_WHITESPACE;
}
-#line 6902 "Zend/zend_language_scanner.c"
-yy770:
- YYDEBUG(770, *YYCURSOR);
+#line 7251 "Zend/zend_language_scanner.c"
+yy795:
+ YYDEBUG(795, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == '>') goto yy777;
-yy771:
- YYDEBUG(771, *YYCURSOR);
+ if ((yych = *YYCURSOR) == '>') goto yy802;
+yy796:
+ YYDEBUG(796, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1043 "Zend/zend_language_scanner.l"
+#line 1188 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state(TSRMLS_C);
goto restart;
}
-#line 6916 "Zend/zend_language_scanner.c"
-yy772:
- YYDEBUG(772, *YYCURSOR);
+#line 7265 "Zend/zend_language_scanner.c"
+yy797:
+ YYDEBUG(797, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy776;
-yy773:
- YYDEBUG(773, *YYCURSOR);
+ goto yy801;
+yy798:
+ YYDEBUG(798, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1036 "Zend/zend_language_scanner.l"
+#line 1181 "Zend/zend_language_scanner.l"
{
yy_pop_state(TSRMLS_C);
zend_copy_value(zendlval, yytext, yyleng);
zendlval->type = IS_STRING;
return T_STRING;
}
-#line 6932 "Zend/zend_language_scanner.c"
-yy774:
- YYDEBUG(774, *YYCURSOR);
+#line 7281 "Zend/zend_language_scanner.c"
+yy799:
+ YYDEBUG(799, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy771;
-yy775:
- YYDEBUG(775, *YYCURSOR);
+ goto yy796;
+yy800:
+ YYDEBUG(800, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy776:
- YYDEBUG(776, *YYCURSOR);
+yy801:
+ YYDEBUG(801, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy775;
+ goto yy800;
}
- goto yy773;
-yy777:
- YYDEBUG(777, *YYCURSOR);
+ goto yy798;
+yy802:
+ YYDEBUG(802, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(778, *YYCURSOR);
+ YYDEBUG(803, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1032 "Zend/zend_language_scanner.l"
+#line 1177 "Zend/zend_language_scanner.l"
{
return T_OBJECT_OPERATOR;
}
-#line 6957 "Zend/zend_language_scanner.c"
-yy779:
- YYDEBUG(779, *YYCURSOR);
+#line 7306 "Zend/zend_language_scanner.c"
+yy804:
+ YYDEBUG(804, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy780:
- YYDEBUG(780, *YYCURSOR);
+yy805:
+ YYDEBUG(805, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy779;
+ goto yy804;
}
- goto yy769;
+ goto yy794;
}
/* *********************************** */
yyc_ST_LOOKING_FOR_VARNAME:
@@ -7003,27 +7352,27 @@ yyc_ST_LOOKING_FOR_VARNAME:
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
};
- YYDEBUG(781, *YYCURSOR);
+ YYDEBUG(806, *YYCURSOR);
YYFILL(2);
yych = *YYCURSOR;
if (yych <= '_') {
- if (yych <= '@') goto yy785;
- if (yych <= 'Z') goto yy783;
- if (yych <= '^') goto yy785;
+ if (yych <= '@') goto yy810;
+ if (yych <= 'Z') goto yy808;
+ if (yych <= '^') goto yy810;
} else {
- if (yych <= '`') goto yy785;
- if (yych <= 'z') goto yy783;
- if (yych <= '~') goto yy785;
+ if (yych <= '`') goto yy810;
+ if (yych <= 'z') goto yy808;
+ if (yych <= '~') goto yy810;
}
-yy783:
- YYDEBUG(783, *YYCURSOR);
+yy808:
+ YYDEBUG(808, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy788;
-yy784:
- YYDEBUG(784, *YYCURSOR);
+ goto yy813;
+yy809:
+ YYDEBUG(809, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1315 "Zend/zend_language_scanner.l"
+#line 1464 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
zendlval->type = IS_STRING;
@@ -7031,42 +7380,42 @@ yy784:
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return T_STRING_VARNAME;
}
-#line 7035 "Zend/zend_language_scanner.c"
-yy785:
- YYDEBUG(785, *YYCURSOR);
+#line 7384 "Zend/zend_language_scanner.c"
+yy810:
+ YYDEBUG(810, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(786, *YYCURSOR);
+ YYDEBUG(811, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1324 "Zend/zend_language_scanner.l"
+#line 1473 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state(TSRMLS_C);
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
goto restart;
}
-#line 7048 "Zend/zend_language_scanner.c"
-yy787:
- YYDEBUG(787, *YYCURSOR);
+#line 7397 "Zend/zend_language_scanner.c"
+yy812:
+ YYDEBUG(812, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy788:
- YYDEBUG(788, *YYCURSOR);
+yy813:
+ YYDEBUG(813, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy787;
+ goto yy812;
}
- goto yy784;
+ goto yy809;
}
/* *********************************** */
yyc_ST_NOWDOC:
- YYDEBUG(789, *YYCURSOR);
+ YYDEBUG(814, *YYCURSOR);
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(791, *YYCURSOR);
+ YYDEBUG(816, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(792, *YYCURSOR);
+ YYDEBUG(817, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2162 "Zend/zend_language_scanner.l"
+#line 2355 "Zend/zend_language_scanner.l"
{
int newline = 0;
@@ -7121,7 +7470,7 @@ nowdoc_scan_done:
HANDLE_NEWLINES(yytext, yyleng - newline);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 7125 "Zend/zend_language_scanner.c"
+#line 7474 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_VAR_OFFSET:
{
@@ -7132,96 +7481,103 @@ yyc_ST_VAR_OFFSET:
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 224, 224, 224, 224, 224, 224, 224, 224,
- 224, 224, 0, 0, 0, 0, 0, 0,
- 0, 160, 160, 160, 160, 160, 160, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 0, 0, 0, 0, 32,
- 0, 160, 160, 160, 160, 160, 160, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 0, 0, 0, 0, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32,
+ 240, 240, 112, 112, 112, 112, 112, 112,
+ 112, 112, 0, 0, 0, 0, 0, 0,
+ 0, 80, 80, 80, 80, 80, 80, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 0, 0, 0, 0, 16,
+ 0, 80, 80, 80, 80, 80, 80, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 0, 0, 0, 0, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
};
- YYDEBUG(793, *YYCURSOR);
+ YYDEBUG(818, *YYCURSOR);
YYFILL(3);
yych = *YYCURSOR;
if (yych <= '/') {
if (yych <= ' ') {
if (yych <= '\f') {
- if (yych <= 0x08) goto yy807;
- if (yych <= '\n') goto yy803;
- goto yy807;
+ if (yych <= 0x08) goto yy832;
+ if (yych <= '\n') goto yy828;
+ goto yy832;
} else {
- if (yych <= '\r') goto yy803;
- if (yych <= 0x1F) goto yy807;
- goto yy803;
+ if (yych <= '\r') goto yy828;
+ if (yych <= 0x1F) goto yy832;
+ goto yy828;
}
} else {
if (yych <= '$') {
- if (yych <= '"') goto yy802;
- if (yych <= '#') goto yy803;
- goto yy798;
+ if (yych <= '"') goto yy827;
+ if (yych <= '#') goto yy828;
+ goto yy823;
} else {
- if (yych == '\'') goto yy803;
- goto yy802;
+ if (yych == '\'') goto yy828;
+ goto yy827;
}
}
} else {
if (yych <= '\\') {
if (yych <= '@') {
- if (yych <= '0') goto yy795;
- if (yych <= '9') goto yy797;
- goto yy802;
+ if (yych <= '0') goto yy820;
+ if (yych <= '9') goto yy822;
+ goto yy827;
} else {
- if (yych <= 'Z') goto yy805;
- if (yych <= '[') goto yy802;
- goto yy803;
+ if (yych <= 'Z') goto yy830;
+ if (yych <= '[') goto yy827;
+ goto yy828;
}
} else {
if (yych <= '_') {
- if (yych <= ']') goto yy800;
- if (yych <= '^') goto yy802;
- goto yy805;
+ if (yych <= ']') goto yy825;
+ if (yych <= '^') goto yy827;
+ goto yy830;
} else {
- if (yych <= '`') goto yy802;
- if (yych <= 'z') goto yy805;
- if (yych <= '~') goto yy802;
- goto yy805;
+ if (yych <= '`') goto yy827;
+ if (yych <= 'z') goto yy830;
+ if (yych <= '~') goto yy827;
+ goto yy830;
}
}
}
-yy795:
- YYDEBUG(795, *YYCURSOR);
+yy820:
+ YYDEBUG(820, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
if (yych <= 'W') {
- if (yych <= '/') goto yy796;
- if (yych <= '9') goto yy818;
+ if (yych <= '9') {
+ if (yych >= '0') goto yy844;
+ } else {
+ if (yych == 'B') goto yy841;
+ }
} else {
- if (yych <= 'X') goto yy816;
- if (yych == 'x') goto yy816;
+ if (yych <= 'b') {
+ if (yych <= 'X') goto yy843;
+ if (yych >= 'b') goto yy841;
+ } else {
+ if (yych == 'x') goto yy843;
+ }
}
-yy796:
- YYDEBUG(796, *YYCURSOR);
+yy821:
+ YYDEBUG(821, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1378 "Zend/zend_language_scanner.l"
+#line 1551 "Zend/zend_language_scanner.l"
{ /* Offset could be treated as a long */
if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
zendlval->value.lval = strtol(yytext, NULL, 10);
@@ -7233,81 +7589,81 @@ yy796:
}
return T_NUM_STRING;
}
-#line 7237 "Zend/zend_language_scanner.c"
-yy797:
- YYDEBUG(797, *YYCURSOR);
+#line 7593 "Zend/zend_language_scanner.c"
+yy822:
+ YYDEBUG(822, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy815;
-yy798:
- YYDEBUG(798, *YYCURSOR);
+ goto yy840;
+yy823:
+ YYDEBUG(823, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) <= '_') {
- if (yych <= '@') goto yy799;
- if (yych <= 'Z') goto yy811;
- if (yych >= '_') goto yy811;
+ if (yych <= '@') goto yy824;
+ if (yych <= 'Z') goto yy836;
+ if (yych >= '_') goto yy836;
} else {
- if (yych <= '`') goto yy799;
- if (yych <= 'z') goto yy811;
- if (yych >= 0x7F) goto yy811;
+ if (yych <= '`') goto yy824;
+ if (yych <= 'z') goto yy836;
+ if (yych >= 0x7F) goto yy836;
}
-yy799:
- YYDEBUG(799, *YYCURSOR);
+yy824:
+ YYDEBUG(824, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1688 "Zend/zend_language_scanner.l"
+#line 1883 "Zend/zend_language_scanner.l"
{
/* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
return yytext[0];
}
-#line 7262 "Zend/zend_language_scanner.c"
-yy800:
- YYDEBUG(800, *YYCURSOR);
+#line 7618 "Zend/zend_language_scanner.c"
+yy825:
+ YYDEBUG(825, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(801, *YYCURSOR);
+ YYDEBUG(826, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1683 "Zend/zend_language_scanner.l"
+#line 1878 "Zend/zend_language_scanner.l"
{
yy_pop_state(TSRMLS_C);
return ']';
}
-#line 7273 "Zend/zend_language_scanner.c"
-yy802:
- YYDEBUG(802, *YYCURSOR);
+#line 7629 "Zend/zend_language_scanner.c"
+yy827:
+ YYDEBUG(827, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy799;
-yy803:
- YYDEBUG(803, *YYCURSOR);
+ goto yy824;
+yy828:
+ YYDEBUG(828, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(804, *YYCURSOR);
+ YYDEBUG(829, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1693 "Zend/zend_language_scanner.l"
+#line 1888 "Zend/zend_language_scanner.l"
{
/* Invalid rule to return a more explicit parse error with proper line number */
yyless(0);
yy_pop_state(TSRMLS_C);
return T_ENCAPSED_AND_WHITESPACE;
}
-#line 7290 "Zend/zend_language_scanner.c"
-yy805:
- YYDEBUG(805, *YYCURSOR);
+#line 7646 "Zend/zend_language_scanner.c"
+yy830:
+ YYDEBUG(830, *YYCURSOR);
++YYCURSOR;
yych = *YYCURSOR;
- goto yy810;
-yy806:
- YYDEBUG(806, *YYCURSOR);
+ goto yy835;
+yy831:
+ YYDEBUG(831, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1700 "Zend/zend_language_scanner.l"
+#line 1895 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
zendlval->type = IS_STRING;
return T_STRING;
}
-#line 7305 "Zend/zend_language_scanner.c"
-yy807:
- YYDEBUG(807, *YYCURSOR);
+#line 7661 "Zend/zend_language_scanner.c"
+yy832:
+ YYDEBUG(832, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(808, *YYCURSOR);
+ YYDEBUG(833, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2218 "Zend/zend_language_scanner.l"
+#line 2411 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
return 0;
@@ -7316,100 +7672,118 @@ yy807:
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 7320 "Zend/zend_language_scanner.c"
-yy809:
- YYDEBUG(809, *YYCURSOR);
+#line 7676 "Zend/zend_language_scanner.c"
+yy834:
+ YYDEBUG(834, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy810:
- YYDEBUG(810, *YYCURSOR);
- if (yybm[0+yych] & 32) {
- goto yy809;
+yy835:
+ YYDEBUG(835, *YYCURSOR);
+ if (yybm[0+yych] & 16) {
+ goto yy834;
}
- goto yy806;
-yy811:
- YYDEBUG(811, *YYCURSOR);
+ goto yy831;
+yy836:
+ YYDEBUG(836, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(812, *YYCURSOR);
+ YYDEBUG(837, *YYCURSOR);
if (yych <= '^') {
if (yych <= '9') {
- if (yych >= '0') goto yy811;
+ if (yych >= '0') goto yy836;
} else {
- if (yych <= '@') goto yy813;
- if (yych <= 'Z') goto yy811;
+ if (yych <= '@') goto yy838;
+ if (yych <= 'Z') goto yy836;
}
} else {
if (yych <= '`') {
- if (yych <= '_') goto yy811;
+ if (yych <= '_') goto yy836;
} else {
- if (yych <= 'z') goto yy811;
- if (yych >= 0x7F) goto yy811;
+ if (yych <= 'z') goto yy836;
+ if (yych >= 0x7F) goto yy836;
}
}
-yy813:
- YYDEBUG(813, *YYCURSOR);
+yy838:
+ YYDEBUG(838, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1677 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
-#line 7362 "Zend/zend_language_scanner.c"
-yy814:
- YYDEBUG(814, *YYCURSOR);
+#line 7718 "Zend/zend_language_scanner.c"
+yy839:
+ YYDEBUG(839, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
-yy815:
- YYDEBUG(815, *YYCURSOR);
- if (yybm[0+yych] & 64) {
- goto yy814;
+yy840:
+ YYDEBUG(840, *YYCURSOR);
+ if (yybm[0+yych] & 32) {
+ goto yy839;
}
- goto yy796;
-yy816:
- YYDEBUG(816, *YYCURSOR);
+ goto yy821;
+yy841:
+ YYDEBUG(841, *YYCURSOR);
yych = *++YYCURSOR;
if (yybm[0+yych] & 128) {
- goto yy821;
+ goto yy849;
}
- YYDEBUG(817, *YYCURSOR);
+yy842:
+ YYDEBUG(842, *YYCURSOR);
YYCURSOR = YYMARKER;
- goto yy796;
-yy818:
- YYDEBUG(818, *YYCURSOR);
+ goto yy821;
+yy843:
+ YYDEBUG(843, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yybm[0+yych] & 64) {
+ goto yy847;
+ }
+ goto yy842;
+yy844:
+ YYDEBUG(844, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(819, *YYCURSOR);
- if (yych <= '/') goto yy820;
- if (yych <= '9') goto yy818;
-yy820:
- YYDEBUG(820, *YYCURSOR);
+ YYDEBUG(845, *YYCURSOR);
+ if (yych <= '/') goto yy846;
+ if (yych <= '9') goto yy844;
+yy846:
+ YYDEBUG(846, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1390 "Zend/zend_language_scanner.l"
+#line 1563 "Zend/zend_language_scanner.l"
{ /* Offset must be treated as a string */
zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
zendlval->type = IS_STRING;
return T_NUM_STRING;
}
-#line 7401 "Zend/zend_language_scanner.c"
-yy821:
- YYDEBUG(821, *YYCURSOR);
+#line 7765 "Zend/zend_language_scanner.c"
+yy847:
+ YYDEBUG(847, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(822, *YYCURSOR);
+ YYDEBUG(848, *YYCURSOR);
+ if (yybm[0+yych] & 64) {
+ goto yy847;
+ }
+ goto yy846;
+yy849:
+ YYDEBUG(849, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(850, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy821;
+ goto yy849;
}
- goto yy820;
+ goto yy846;
}
}
-#line 2227 "Zend/zend_language_scanner.l"
+#line 2420 "Zend/zend_language_scanner.l"
}
diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h
index ca6420aa10..a1a84b3bc9 100644
--- a/Zend/zend_language_scanner.h
+++ b/Zend/zend_language_scanner.h
@@ -36,7 +36,6 @@ typedef struct _zend_lex_state {
uint lineno;
char *filename;
-#ifdef ZEND_MULTIBYTE
/* original (unfiltered) script */
unsigned char *script_org;
size_t script_org_size;
@@ -48,9 +47,7 @@ typedef struct _zend_lex_state {
/* input/ouput filters */
zend_encoding_filter input_filter;
zend_encoding_filter output_filter;
- zend_encoding *script_encoding;
- zend_encoding *internal_encoding;
-#endif /* ZEND_MULTIBYTE */
+ const zend_encoding *script_encoding;
} zend_lex_state;
@@ -59,6 +56,8 @@ int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2);
ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC);
ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC);
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC);
+ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC);
+ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC);
END_EXTERN_C()
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index c92bf2b107..703ca968ea 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -33,6 +33,9 @@
#include <errno.h>
#include "zend.h"
+#ifdef PHP_WIN32
+# include <Winuser.h>
+#endif
#include "zend_alloc.h"
#include <zend_language_parser.h>
#include "zend_compile.h"
@@ -120,6 +123,33 @@ do { \
BEGIN_EXTERN_C()
+static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC);
+}
+
+static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding) TSRMLS_CC);
+}
+
+static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length,
+LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC);
+}
+
+static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length,
+internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
+}
+
+
static void _yy_push_state(int new_state TSRMLS_DC)
{
zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
@@ -147,6 +177,7 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
void startup_scanner(TSRMLS_D)
{
+ CG(parse_error) = 0;
CG(heredoc) = NULL;
CG(heredoc_len) = 0;
CG(doc_comment) = NULL;
@@ -160,6 +191,7 @@ void shutdown_scanner(TSRMLS_D)
efree(CG(heredoc));
CG(heredoc_len)=0;
}
+ CG(parse_error) = 0;
zend_stack_destroy(&SCNG(state_stack));
RESET_DOC_COMMENT();
}
@@ -181,7 +213,6 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
lex_state->lineno = CG(zend_lineno);
-#ifdef ZEND_MULTIBYTE
lex_state->script_org = SCNG(script_org);
lex_state->script_org_size = SCNG(script_org_size);
lex_state->script_filtered = SCNG(script_filtered);
@@ -189,8 +220,6 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
lex_state->input_filter = SCNG(input_filter);
lex_state->output_filter = SCNG(output_filter);
lex_state->script_encoding = SCNG(script_encoding);
- lex_state->internal_encoding = SCNG(internal_encoding);
-#endif /* ZEND_MULTIBYTE */
}
ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
@@ -209,11 +238,7 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
YYSETCONDITION(lex_state->yy_state);
CG(zend_lineno) = lex_state->lineno;
zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
+
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
@@ -225,8 +250,6 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
SCNG(input_filter) = lex_state->input_filter;
SCNG(output_filter) = lex_state->output_filter;
SCNG(script_encoding) = lex_state->script_encoding;
- SCNG(internal_encoding) = lex_state->internal_encoding;
-#endif /* ZEND_MULTIBYTE */
if (CG(heredoc)) {
efree(CG(heredoc));
@@ -245,12 +268,214 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
}
}
+#define BOM_UTF32_BE "\x00\x00\xfe\xff"
+#define BOM_UTF32_LE "\xff\xfe\x00\x00"
+#define BOM_UTF16_BE "\xfe\xff"
+#define BOM_UTF16_LE "\xff\xfe"
+#define BOM_UTF8 "\xef\xbb\xbf"
+
+static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC)
+{
+ const unsigned char *p;
+ int wchar_size = 2;
+ int le = 0;
+
+ /* utf-16 or utf-32? */
+ p = script;
+ while ((p-script) < script_size) {
+ p = memchr(p, 0, script_size-(p-script)-2);
+ if (!p) {
+ break;
+ }
+ if (*(p+1) == '\0' && *(p+2) == '\0') {
+ wchar_size = 4;
+ break;
+ }
+
+ /* searching for UTF-32 specific byte orders, so this will do */
+ p += 4;
+ }
+
+ /* BE or LE? */
+ p = script;
+ while ((p-script) < script_size) {
+ if (*p == '\0' && *(p+wchar_size-1) != '\0') {
+ /* BE */
+ le = 0;
+ break;
+ } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
+ /* LE* */
+ le = 1;
+ break;
+ }
+ p += wchar_size;
+ }
+
+ if (wchar_size == 2) {
+ return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be;
+ } else {
+ return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be;
+ }
+
+ return NULL;
+}
+
+static const zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D)
+{
+ const zend_encoding *script_encoding = NULL;
+ int bom_size;
+ unsigned char *pos1, *pos2;
+
+ if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
+ return NULL;
+ }
+
+ /* check out BOM */
+ if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf32be;
+ bom_size = sizeof(BOM_UTF32_BE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf32le;
+ bom_size = sizeof(BOM_UTF32_LE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf16be;
+ bom_size = sizeof(BOM_UTF16_BE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf16le;
+ bom_size = sizeof(BOM_UTF16_LE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
+ script_encoding = zend_multibyte_encoding_utf8;
+ bom_size = sizeof(BOM_UTF8)-1;
+ }
+
+ if (script_encoding) {
+ /* remove BOM */
+ LANG_SCNG(script_org) += bom_size;
+ LANG_SCNG(script_org_size) -= bom_size;
+
+ return script_encoding;
+ }
+
+ /* script contains NULL bytes -> auto-detection */
+ if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) {
+ /* check if the NULL byte is after the __HALT_COMPILER(); */
+ pos2 = LANG_SCNG(script_org);
+
+ while (pos1 - pos2 >= sizeof("__HALT_COMPILER();")-1) {
+ pos2 = memchr(pos2, '_', pos1 - pos2);
+ if (!pos2) break;
+ pos2++;
+ if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) {
+ pos2 += sizeof("_HALT_COMPILER")-1;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == '(') {
+ pos2++;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == ')') {
+ pos2++;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == ';') {
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+ /* make best effort if BOM is missing */
+ return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC);
+ }
+
+ return NULL;
+}
+
+static const zend_encoding* zend_multibyte_find_script_encoding(TSRMLS_D)
+{
+ const zend_encoding *script_encoding;
+
+ if (CG(detect_unicode)) {
+ /* check out bom(byte order mark) and see if containing wchars */
+ script_encoding = zend_multibyte_detect_unicode(TSRMLS_C);
+ if (script_encoding != NULL) {
+ /* bom or wchar detection is prior to 'script_encoding' option */
+ return script_encoding;
+ }
+ }
+
+ /* if no script_encoding specified, just leave alone */
+ if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
+ return NULL;
+ }
+
+ /* if multiple encodings specified, detect automagically */
+ if (CG(script_encoding_list_size) > 1) {
+ return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size) TSRMLS_CC);
+ }
+
+ return CG(script_encoding_list)[0];
+}
+
+ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding(TSRMLS_C);
+
+ if (!script_encoding) {
+ return FAILURE;
+ }
+
+ /* judge input/output filter */
+ LANG_SCNG(script_encoding) = script_encoding;
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = NULL;
+
+ if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) {
+ if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
+ /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
+ LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
+ LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script;
+ } else {
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = NULL;
+ }
+ return SUCCESS;
+ }
+
+ if (zend_multibyte_check_lexer_compatibility(internal_encoding)) {
+ LANG_SCNG(input_filter) = encoding_filter_script_to_internal;
+ LANG_SCNG(output_filter) = NULL;
+ } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = encoding_filter_script_to_internal;
+ } else {
+ /* both script and internal encodings are incompatible w/ flex */
+ LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
+ LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal;
+ }
+
+ return 0;
+}
ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
{
- char *file_path = NULL, *buf;
+ const char *file_path = NULL;
+ char *buf;
size_t size, offset = 0;
-
+
/* The shebang line was read, get the current position to obtain the buffer start */
if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
if ((offset = ftell(file_handle->handle.fp)) == -1) {
@@ -275,32 +500,24 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
SCNG(yy_start) = NULL;
if (size != -1) {
-#ifdef ZEND_MULTIBYTE
- if (zend_multibyte_read_script((unsigned char *)buf, size TSRMLS_CC) != 0) {
- return FAILURE;
- }
-
- SCNG(yy_in) = NULL;
+ if (CG(multibyte)) {
+ SCNG(script_org) = (unsigned char*)buf;
+ SCNG(script_org_size) = size;
+ SCNG(script_filtered) = NULL;
- zend_multibyte_set_filter(NULL TSRMLS_CC);
+ zend_multibyte_set_filter(NULL TSRMLS_CC);
- if (!SCNG(input_filter)) {
- SCNG(script_filtered) = (unsigned char*)emalloc(SCNG(script_org_size)+2);
- memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
- SCNG(script_filtered_size) = SCNG(script_org_size);
- } else {
- SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
- if (SCNG(script_filtered) == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
- "encoding \"%s\" to a compatible encoding", LANG_SCNG(script_encoding)->name);
+ if (SCNG(input_filter)) {
+ if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ buf = (char*)SCNG(script_filtered);
+ size = SCNG(script_filtered_size);
}
}
- SCNG(yy_start) = SCNG(script_filtered) - offset;
- yy_scan_buffer((char *)SCNG(script_filtered), SCNG(script_filtered_size) TSRMLS_CC);
-#else /* !ZEND_MULTIBYTE */
- SCNG(yy_start) = buf - offset;
+ SCNG(yy_start) = (unsigned char *)buf - offset;
yy_scan_buffer(buf, size TSRMLS_CC);
-#endif /* ZEND_MULTIBYTE */
} else {
zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
}
@@ -361,6 +578,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
compiler_result = zendparse(TSRMLS_C);
zend_do_return(&retval_znode, 0 TSRMLS_CC);
CG(in_compilation) = original_in_compilation;
@@ -428,32 +646,44 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
{
+ char *buf;
+ size_t size;
+
/* enforce two trailing NULLs for flex... */
- str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ if (IS_INTERNED(str->value.str.val)) {
+ char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD);
+ memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD);
+ str->value.str.val = tmp;
+ } else {
+ str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ }
memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD);
- SCNG(yy_in)=NULL;
+ SCNG(yy_in) = NULL;
SCNG(yy_start) = NULL;
-#ifdef ZEND_MULTIBYTE
- SCNG(script_org) = (unsigned char *)estrdup(str->value.str.val);
- SCNG(script_org_size) = str->value.str.len;
+ buf = str->value.str.val;
+ size = str->value.str.len;
- zend_multibyte_set_filter(CG(internal_encoding) TSRMLS_CC);
+ if (CG(multibyte)) {
+ SCNG(script_org) = (unsigned char*)buf;
+ SCNG(script_org_size) = size;
+ SCNG(script_filtered) = NULL;
- if (!SCNG(input_filter)) {
- SCNG(script_filtered) = (unsigned char*)emalloc(SCNG(script_org_size)+2);
- memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
- SCNG(script_filtered_size) = SCNG(script_org_size);
- } else {
- SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
+ zend_multibyte_set_filter(zend_multibyte_get_internal_encoding(TSRMLS_C) TSRMLS_CC);
+
+ if (SCNG(input_filter)) {
+ if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ buf = (char*)SCNG(script_filtered);
+ size = SCNG(script_filtered_size);
+ }
}
- yy_scan_buffer((char *)SCNG(script_filtered), SCNG(script_filtered_size) TSRMLS_CC);
-#else /* !ZEND_MULTIBYTE */
- yy_scan_buffer(str->value.str.val, str->value.str.len TSRMLS_CC);
-#endif /* ZEND_MULTIBYTE */
+ yy_scan_buffer(buf, size TSRMLS_CC);
zend_set_compiled_filename(filename TSRMLS_CC);
CG(zend_lineno) = 1;
@@ -465,13 +695,12 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
{
size_t offset = SCNG(yy_cursor) - SCNG(yy_start);
-#ifdef ZEND_MULTIBYTE
if (SCNG(input_filter)) {
- size_t original_offset = offset, length = 0; do {
+ size_t original_offset = offset, length = 0;
+ do {
unsigned char *p = NULL;
- SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC);
- if (!p) {
- break;
+ if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC)) {
+ return (size_t)-1;
}
efree(p);
if (length > original_offset) {
@@ -481,7 +710,6 @@ ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
}
} while (original_offset != length);
}
-#endif
return offset;
}
@@ -519,19 +747,14 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
CG(interactive) = orig_interactive;
CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
BEGIN(ST_IN_SCRIPTING);
compiler_result = zendparse(TSRMLS_C);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
}
-#endif /* ZEND_MULTIBYTE */
if (compiler_result==1) {
CG(active_op_array) = original_active_op_array;
@@ -571,16 +794,10 @@ int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlight
return FAILURE;
}
zend_highlight(syntax_highlighter_ini TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
}
-#endif /* ZEND_MULTIBYTE */
zend_destroy_file_handle(&file_handle TSRMLS_CC);
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
return SUCCESS;
@@ -600,122 +817,44 @@ int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_
}
BEGIN(INITIAL);
zend_highlight(syntax_highlighter_ini TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
if (SCNG(script_filtered)) {
efree(SCNG(script_filtered));
SCNG(script_filtered) = NULL;
}
-#endif /* ZEND_MULTIBYTE */
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
zval_dtor(str);
return SUCCESS;
}
-END_EXTERN_C()
-#ifdef ZEND_MULTIBYTE
-
-BEGIN_EXTERN_C()
-ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, zend_encoding *old_encoding TSRMLS_DC)
+ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC)
{
- size_t original_offset, offset, free_flag, new_len, length;
- unsigned char *p;
-
- /* calculate current position */
- offset = original_offset = YYCURSOR - SCNG(yy_start);
- if (old_input_filter && offset > 0) {
- zend_encoding *new_encoding = SCNG(script_encoding);
- zend_encoding_filter new_filter = SCNG(input_filter);
- SCNG(script_encoding) = old_encoding;
- SCNG(input_filter) = old_input_filter;
- offset = zend_get_scanned_file_offset(TSRMLS_C);
- SCNG(script_encoding) = new_encoding;
- SCNG(input_filter) = new_filter;
- }
+ size_t length;
+ unsigned char *new_yy_start;
/* convert and set */
if (!SCNG(input_filter)) {
- length = SCNG(script_org_size) - offset;
- p = SCNG(script_org) + offset;
- free_flag = 0;
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+ SCNG(script_filtered_size) = 0;
+ length = SCNG(script_org_size);
+ new_yy_start = SCNG(script_org);
} else {
- SCNG(input_filter)(&p, &length, SCNG(script_org) + offset, SCNG(script_org_size) - offset TSRMLS_CC);
- free_flag = 1;
- }
-
- new_len = original_offset + length;
-
- if (new_len > YYLIMIT - SCNG(yy_start)) {
- unsigned char *new_yy_start = erealloc(SCNG(yy_start), new_len);
- SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
- SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
- SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
- SCNG(yy_start) = new_yy_start;
- SCNG(script_filtered) = new_yy_start;
- SCNG(script_filtered_size) = new_len;
- }
-
- SCNG(yy_limit) = SCNG(yy_start) + new_len;
- memmove(SCNG(yy_start) + original_offset, p, length);
-
- if (free_flag) {
- efree(p);
- }
-}
-
-
-ZEND_API int zend_multibyte_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
-{
- size_t n;
-
- if (CG(interactive) == 0) {
- if (zend_stream_fixup(file_handle, &buf, &len TSRMLS_CC) == FAILURE) {
- return FAILURE;
+ if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
}
- n = len;
- return n;
- }
-
- /* interactive */
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- }
- SCNG(script_org) = NULL;
- SCNG(script_org_size) = 0;
-
- /* TODO: support widechars */
- if (zend_stream_fixup(file_handle, &buf, &len TSRMLS_CC) == FAILURE) {
- return FAILURE;
+ SCNG(script_filtered) = new_yy_start;
+ SCNG(script_filtered_size) = length;
}
- n = len;
- SCNG(script_org_size) = n;
- SCNG(script_org) = (unsigned char*)emalloc(SCNG(script_org_size) + 1);
- memcpy(SCNG(script_org), buf, n);
+ SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
+ SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
+ SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
+ SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start));
- return n;
-}
-
-
-ZEND_API int zend_multibyte_read_script(unsigned char *buf, size_t n TSRMLS_DC)
-{
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
- SCNG(script_org_size) = n;
-
- SCNG(script_org) = (unsigned char*)emalloc(SCNG(script_org_size) + 1);
- memcpy(SCNG(script_org), buf, n);
- *(SCNG(script_org)+SCNG(script_org_size)) = '\0';
-
- return 0;
+ SCNG(yy_start) = new_yy_start;
}
@@ -728,11 +867,6 @@ ZEND_API int zend_multibyte_read_script(unsigned char *buf, size_t n TSRMLS_DC)
zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
zendlval->value.str.len = yyleng; \
}
-#else /* ZEND_MULTIBYTE */
-# define zend_copy_value(zendlval, yytext, yyleng) \
- zendlval->value.str.val = (char *)estrndup(yytext, yyleng); \
- zendlval->value.str.len = yyleng;
-#endif /* ZEND_MULTIBYTE */
static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
{
@@ -773,6 +907,14 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
*t++ = '\v';
zendlval->value.str.len--;
break;
+ case 'e':
+#ifdef PHP_WIN32
+ *t++ = VK_ESCAPE;
+#else
+ *t++ = '\e';
+#endif
+ zendlval->value.str.len--;
+ break;
case '"':
case '`':
if (*s != quote_type) {
@@ -836,7 +978,6 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
s++;
}
*t = 0;
-#ifdef ZEND_MULTIBYTE
if (SCNG(output_filter)) {
size_t sz = 0;
s = zendlval->value.str.val;
@@ -844,7 +985,6 @@ static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quo
zendlval->value.str.len = sz;
efree(s);
}
-#endif /* ZEND_MULTIBYTE */
}
@@ -861,6 +1001,7 @@ LNUM [0-9]+
DNUM ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})
HNUM "0x"[0-9a-fA-F]+
+BNUM "0b"[01]+
LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
WHITESPACE [ \n\r\t]+
TABS_AND_SPACES [ \t]*
@@ -1008,6 +1149,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_INTERFACE;
}
+<ST_IN_SCRIPTING>"trait" {
+ return T_TRAIT;
+}
+
<ST_IN_SCRIPTING>"extends" {
return T_EXTENDS;
}
@@ -1074,11 +1219,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_DOUBLE_CAST;
}
-<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"string"{TABS_AND_SPACES}")" {
- return T_STRING_CAST;
-}
-
-<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"binary"{TABS_AND_SPACES}")" {
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" {
return T_STRING_CAST;
}
@@ -1126,6 +1267,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_USE;
}
+<ST_IN_SCRIPTING>"insteadof" {
+ return T_INSTEADOF;
+}
+
<ST_IN_SCRIPTING>"global" {
return T_GLOBAL;
}
@@ -1182,6 +1327,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_ARRAY;
}
+<ST_IN_SCRIPTING>"callable" {
+ return T_CALLABLE;
+}
+
<ST_IN_SCRIPTING>"++" {
return T_INC;
}
@@ -1328,6 +1477,30 @@ NEWLINE ("\r"|"\n"|"\r\n")
goto restart;
}
+<ST_IN_SCRIPTING>{BNUM} {
+ char *bin = yytext + 2; /* Skip "0b" */
+ int len = yyleng - 2;
+
+ /* Skip any leading 0s */
+ while (*bin == '0') {
+ ++bin;
+ --len;
+ }
+
+ if (len < SIZEOF_LONG * 8) {
+ if (len == 0) {
+ zendlval->value.lval = 0;
+ } else {
+ zendlval->value.lval = strtol(bin, NULL, 2);
+ }
+ zendlval->type = IS_LONG;
+ return T_LNUMBER;
+ } else {
+ zendlval->value.dval = zend_bin_strtod(bin, NULL);
+ zendlval->type = IS_DOUBLE;
+ return T_DNUMBER;
+ }
+}
<ST_IN_SCRIPTING>{LNUM} {
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
@@ -1387,7 +1560,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_NUM_STRING;
}
-<ST_VAR_OFFSET>{LNUM}|{HNUM} { /* Offset must be treated as a string */
+<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
zendlval->type = IS_STRING;
@@ -1401,23 +1574,54 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_IN_SCRIPTING>"__CLASS__" {
- char *class_name = NULL;
-
- if (CG(active_class_entry)) {
- class_name = CG(active_class_entry)->name;
+ const char *class_name = NULL;
+
+ if (CG(active_class_entry)
+ && (ZEND_ACC_TRAIT ==
+ (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
+ /* We create a special __CLASS__ constant that is going to be resolved
+ at run-time */
+ zendlval->value.str.len = sizeof("__CLASS__")-1;
+ zendlval->value.str.val = estrndup("__CLASS__", zendlval->value.str.len);
+ zendlval->type = IS_CONSTANT;
+ } else {
+ if (CG(active_class_entry)) {
+ class_name = CG(active_class_entry)->name;
+ }
+
+ if (!class_name) {
+ class_name = "";
+ }
+
+ zendlval->value.str.len = strlen(class_name);
+ zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
}
+ return T_CLASS_C;
+}
- if (!class_name) {
- class_name = "";
+<ST_IN_SCRIPTING>"__TRAIT__" {
+ const char *trait_name = NULL;
+
+ if (CG(active_class_entry)
+ && (ZEND_ACC_TRAIT ==
+ (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
+ trait_name = CG(active_class_entry)->name;
+ }
+
+ if (!trait_name) {
+ trait_name = "";
}
- zendlval->value.str.len = strlen(class_name);
- zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+
+ zendlval->value.str.len = strlen(trait_name);
+ zendlval->value.str.val = estrndup(trait_name, zendlval->value.str.len);
zendlval->type = IS_STRING;
- return T_CLASS_C;
+
+ return T_TRAIT_C;
}
<ST_IN_SCRIPTING>"__FUNCTION__" {
- char *func_name = NULL;
+ const char *func_name = NULL;
if (CG(active_op_array)) {
func_name = CG(active_op_array)->function_name;
@@ -1433,8 +1637,8 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_IN_SCRIPTING>"__METHOD__" {
- char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
- char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
+ const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
+ const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
size_t len = 0;
if (class_name) {
@@ -1444,7 +1648,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
len += strlen(func_name);
}
- zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
+ zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
class_name ? class_name : "",
class_name && func_name ? "::" : "",
func_name ? func_name : ""
@@ -1509,7 +1713,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<INITIAL>"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"'php'"){WHITESPACE}*">" {
- YYCTYPE *bracket = zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
+ YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
if (bracket != SCNG(yy_text)) {
/* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */
@@ -1540,15 +1744,11 @@ NEWLINE ("\r"|"\n"|"\r\n")
<INITIAL>"<?=" {
- if (CG(short_tags)) {
- zendlval->value.str.val = yytext; /* no copying - intentional */
- zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
- BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG_WITH_ECHO;
- } else {
- goto inline_char_handler;
- }
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG_WITH_ECHO;
}
@@ -1602,7 +1802,7 @@ inline_char_handler:
if (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR) {
case '?':
- if (CG(short_tags) || !strncasecmp(YYCURSOR + 1, "php", 3)) { /* Assume [ \t\n\r] follows "php" */
+ if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */
break;
}
continue;
@@ -1630,7 +1830,6 @@ inline_char_handler:
inline_html:
yyleng = YYCURSOR - SCNG(yy_text);
-#ifdef ZEND_MULTIBYTE
if (SCNG(output_filter)) {
int readsize;
size_t sz = 0;
@@ -1643,10 +1842,6 @@ inline_html:
zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
}
-#else /* !ZEND_MULTIBYTE */
- zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
-#endif
zendlval->type = IS_STRING;
HANDLE_NEWLINES(yytext, yyleng);
return T_INLINE_HTML;
@@ -1853,7 +2048,6 @@ inline_html:
}
*t = 0;
-#ifdef ZEND_MULTIBYTE
if (SCNG(output_filter)) {
size_t sz = 0;
s = zendlval->value.str.val;
@@ -1861,7 +2055,6 @@ inline_html:
zendlval->value.str.len = sz;
efree(s);
}
-#endif /* ZEND_MULTIBYTE */
return T_CONSTANT_ENCAPSED_STRING;
}
diff --git a/Zend/zend_language_scanner_defs.h b/Zend/zend_language_scanner_defs.h
index 02a2a39500..dbf8674042 100644
--- a/Zend/zend_language_scanner_defs.h
+++ b/Zend/zend_language_scanner_defs.h
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Sat Jul 28 16:59:07 2012 */
+/* Generated by re2c 0.13.5 on Mon Apr 30 15:55:05 2012 */
#line 3 "Zend/zend_language_scanner_defs.h"
enum YYCONDTYPE {
diff --git a/Zend/zend_list.c b/Zend/zend_list.c
index 08df2117ab..a75d6846d8 100644
--- a/Zend/zend_list.c
+++ b/Zend/zend_list.c
@@ -32,11 +32,10 @@ ZEND_API int le_index_ptr;
static HashTable list_destructors;
-ZEND_API int zend_list_insert(void *ptr, int type)
+ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC)
{
int index;
zend_rsrc_list_entry le;
- TSRMLS_FETCH();
le.ptr=ptr;
le.type=type;
@@ -92,11 +91,11 @@ ZEND_API int _zend_list_addref(int id TSRMLS_DC)
}
-ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type)
+ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
{
int rsrc_id;
- rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type);
+ rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type TSRMLS_CC);
if (rsrc_result) {
rsrc_result->value.lval = rsrc_id;
@@ -107,15 +106,15 @@ ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int r
}
-ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
+ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
{
int id;
int actual_resource_type;
void *resource;
va_list resource_types;
int i;
- char *space;
- char *class_name;
+ const char *space;
+ const char *class_name;
if (default_id==-1) { /* use id */
if (!passed_id) {
@@ -290,7 +289,7 @@ ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void
}
-ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number)
+ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
{
zend_rsrc_list_dtors_entry lde;
@@ -349,7 +348,7 @@ void zend_destroy_rsrc_list_dtors(void)
}
-char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC)
+const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC)
{
zend_rsrc_list_dtors_entry *lde;
int rsrc_type;
diff --git a/Zend/zend_list.h b/Zend/zend_list.h
index de9fd78c5a..b33c09da86 100644
--- a/Zend/zend_list.h
+++ b/Zend/zend_list.h
@@ -48,7 +48,7 @@ typedef struct _zend_rsrc_list_dtors_entry {
rsrc_dtor_func_t list_dtor_ex;
rsrc_dtor_func_t plist_dtor_ex;
- char *type_name;
+ const char *type_name;
int module_number;
int resource_id;
@@ -58,7 +58,7 @@ typedef struct _zend_rsrc_list_dtors_entry {
#define register_list_destructors(ld, pld) zend_register_list_destructors((void (*)(void *))ld, (void (*)(void *))pld, module_number);
ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number);
-ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number);
+ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number);
void list_entry_destructor(void *ptr);
void plist_entry_destructor(void *ptr);
@@ -70,7 +70,7 @@ void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC);
int zend_init_rsrc_list_dtors(void);
void zend_destroy_rsrc_list_dtors(void);
-ZEND_API int zend_list_insert(void *ptr, int type);
+ZEND_API int zend_list_insert(void *ptr, int type TSRMLS_DC);
ZEND_API int _zend_list_addref(int id TSRMLS_DC);
ZEND_API int _zend_list_delete(int id TSRMLS_DC);
ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC);
@@ -79,10 +79,10 @@ ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC);
#define zend_list_delete(id) _zend_list_delete(id TSRMLS_CC)
#define zend_list_find(id, type) _zend_list_find(id, type TSRMLS_CC)
-ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type);
-ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, char *resource_type_name, int *found_resource_type, int num_resource_types, ...);
+ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC);
+ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...);
-ZEND_API char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC);
+ZEND_API const char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC);
ZEND_API int zend_fetch_list_dtor_id(char *type_name);
extern ZEND_API int le_index_ptr; /* list entry type for index pointers */
@@ -107,7 +107,7 @@ extern ZEND_API int le_index_ptr; /* list entry type for index pointers */
(rsrc = (rsrc_type) zend_fetch_resource(passed_id TSRMLS_CC, default_id, resource_type_name, NULL, 2, resource_type1, resource_type2))
#define ZEND_REGISTER_RESOURCE(rsrc_result, rsrc_pointer, rsrc_type) \
- zend_register_resource(rsrc_result, rsrc_pointer, rsrc_type);
+ zend_register_resource(rsrc_result, rsrc_pointer, rsrc_type TSRMLS_CC);
#define ZEND_GET_RESOURCE_TYPE_ID(le_id, le_type_name) \
if (le_id == 0) { \
diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h
index 6a43e276f5..ad15a96624 100644
--- a/Zend/zend_modules.h
+++ b/Zend/zend_modules.h
@@ -33,7 +33,7 @@
#define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC
#define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC
-#define ZEND_MODULE_API_NO 20090626
+#define ZEND_MODULE_API_NO 20100525
#ifdef ZTS
#define USING_ZTS 1
#else
@@ -98,7 +98,7 @@ struct _zend_module_entry {
unsigned char type;
void *handle;
int module_number;
- char *build_id;
+ const char *build_id;
};
#define MODULE_DEP_REQUIRED 1
diff --git a/Zend/zend_multibyte.c b/Zend/zend_multibyte.c
index 092083b65c..379f50b01f 100644
--- a/Zend/zend_multibyte.c
+++ b/Zend/zend_multibyte.c
@@ -23,1152 +23,188 @@
#include "zend_compile.h"
#include "zend_operators.h"
#include "zend_multibyte.h"
+#include "zend_ini.h"
-#ifdef ZEND_MULTIBYTE
-static size_t zend_multibyte_encoding_filter(unsigned char **to, size_t *to_length, const char *to_encoding, const unsigned char *from, size_t from_length, const char *from_encoding TSRMLS_DC);
-size_t sjis_input_filter(unsigned char **buf, size_t *length, const unsigned char *sjis, size_t sjis_length TSRMLS_DC);
-size_t sjis_output_filter(unsigned char **buf, size_t *length, const unsigned char *sjis, size_t sjis_length TSRMLS_DC);
-static char* zend_multibyte_assemble_encoding_list(zend_encoding **encoding_list, size_t encoding_list_size);
-static int zend_multibyte_parse_encoding_list(const char *encoding_list,
-size_t encoding_list_size, zend_encoding ***result, size_t *result_size);
-static zend_encoding *zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC);
-static zend_encoding *zend_multibyte_detect_unicode(TSRMLS_D);
-static zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC);
-
-/*
- * encodings
- */
-static const char *ucs2_aliases[] = {"ISO-10646-UCS-2", "UCS2" , "UNICODE", NULL};
-static zend_encoding encoding_ucs2 = {
- NULL,
- NULL,
- "UCS-2",
- (const char *(*)[])&ucs2_aliases,
- 0
-};
-
-static zend_encoding encoding_ucs2be = {
- NULL,
- NULL,
- "UCS-2BE",
- NULL,
- 0
-};
-
-static zend_encoding encoding_ucs2le = {
- NULL,
- NULL,
- "UCS-2LE",
- NULL,
- 0
-};
-
-static const char *ucs4_aliases[] = {"ISO-10646-UCS-4", "UCS4", NULL};
-static zend_encoding encoding_ucs4 = {
- NULL,
- NULL,
- "UCS-4",
- (const char *(*)[])&ucs4_aliases,
- 0
-};
-
-static zend_encoding encoding_ucs4be = {
- NULL,
- NULL,
- "UCS-4BE",
- NULL,
- 0
-};
-
-static zend_encoding encoding_ucs4le = {
- NULL,
- NULL,
- "UCS-4LE",
- NULL,
- 0
-};
-
-static const char *utf32_aliases[] = {"utf32", NULL};
-static zend_encoding encoding_utf32 = {
- NULL,
- NULL,
- "UTF-32",
- (const char *(*)[])&utf32_aliases,
- 0
-};
-
-static zend_encoding encoding_utf32be = {
- NULL,
- NULL,
- "UTF-32BE",
- NULL,
- 0
-};
-
-static zend_encoding encoding_utf32le = {
- NULL,
- NULL,
- "UTF-32LE",
- NULL,
- 0
-};
-
-static const char *utf16_aliases[] = {"utf16", NULL};
-static zend_encoding encoding_utf16 = {
- NULL,
- NULL,
- "UTF-16",
- (const char *(*)[])&utf16_aliases,
- 0
-};
-
-static zend_encoding encoding_utf16be = {
- NULL,
- NULL,
- "UTF-16BE",
- NULL,
- 0
-};
-
-static zend_encoding encoding_utf16le = {
- NULL,
- NULL,
- "UTF-16LE",
- NULL,
- 0
-};
-
-static const char *utf8_aliases[] = {"utf8", NULL};
-static zend_encoding encoding_utf8 = {
- NULL,
- NULL,
- "UTF-8",
- (const char *(*)[])&utf8_aliases,
- 1
-};
-
-static const char *ascii_aliases[] = {"ANSI_X3.4-1968", "iso-ir-6", "ANSI_X3.4-1986", "ISO_646.irv:1991", "US-ASCII", "ISO646-US", "us", "IBM367", "cp367", "csASCII", NULL};
-static zend_encoding encoding_ascii = {
- NULL,
- NULL,
- "ASCII",
- (const char *(*)[])&ascii_aliases,
- 1
-};
-
-static const char *euc_jp_aliases[] = {"EUC", "EUC_JP", "eucJP", "x-euc-jp", NULL};
-static zend_encoding encoding_euc_jp = {
- NULL,
- NULL,
- "EUC-JP",
- (const char *(*)[])&euc_jp_aliases,
- 1
-};
-
-static const char *sjis_aliases[] = {"x-sjis", "SJIS", "SHIFT-JIS", NULL};
-static zend_encoding encoding_sjis = {
- sjis_input_filter,
- sjis_output_filter,
- "Shift_JIS",
- (const char *(*)[])&sjis_aliases,
- 0
-};
-
-static const char *eucjp_win_aliases[] = {"eucJP-open", NULL};
-static zend_encoding encoding_eucjp_win = {
- NULL,
- NULL,
- "eucJP-win",
- (const char *(*)[])&eucjp_win_aliases,
- 1
-};
-
-static const char *sjis_win_aliases[] = {"SJIS-open", "MS_Kanji", "Windows-31J", "CP932", NULL};
-static zend_encoding encoding_sjis_win = {
- /* sjis-filters does not care about diffs of Shift_JIS and CP932 */
- sjis_input_filter,
- sjis_output_filter,
- "SJIS-win",
- (const char *(*)[])&sjis_win_aliases,
- 0
-};
-
-static const char *jis_aliases[] = {"ISO-2022-JP", NULL};
-static zend_encoding encoding_jis = {
- NULL,
- NULL,
- "JIS",
- (const char *(*)[])&jis_aliases,
- 0
-};
-
-static const char *euc_cn_aliases[] = {"CN-GB", "EUC_CN", "eucCN", "x-euc-cn", "gb2312", NULL};
-static zend_encoding encoding_euc_cn = {
- NULL,
- NULL,
- "EUC-CN",
- (const char *(*)[])&euc_cn_aliases,
- 1
-};
-
-static const char *cp936_aliases[] = {"CP-936", NULL};
-static zend_encoding encoding_cp936 = {
- NULL,
- NULL,
- "CP936",
- (const char *(*)[])&cp936_aliases,
- 0
-};
-
-static const char *hz_aliases[] = {"HZ-GB-2312", NULL};
-static zend_encoding encoding_hz = {
- NULL,
- NULL,
- "HZ",
- (const char *(*)[])&hz_aliases,
- 0
-};
-
-static const char *euc_tw_aliases[] = {"EUC_TW", "eucTW", "x-euc-tw", NULL};
-static zend_encoding encoding_euc_tw = {
- NULL,
- NULL,
- "EUC-TW",
- (const char *(*)[])&euc_tw_aliases,
- 1
-};
-
-static const char *big5_aliases[] = {"BIG5", "CN-BIG5", "BIG-FIVE", "BIGFIVE", "CP950", NULL};
-static zend_encoding encoding_big5 = {
- NULL,
- NULL,
- "BIG-5",
- (const char *(*)[])&big5_aliases,
- 0
-};
-
-static const char *euc_kr_aliases[] = {"EUC_KR", "eucKR", "x-euc-kr", NULL};
-static zend_encoding encoding_euc_kr = {
- NULL,
- NULL,
- "EUC-KR",
- (const char *(*)[])&euc_kr_aliases,
- 1
-};
-
-static const char *uhc_aliases[] = {"CP949", NULL};
-static zend_encoding encoding_uhc = {
- NULL,
- NULL,
- "UHC",
- (const char *(*)[])&uhc_aliases,
- 1
-};
-
-static zend_encoding encoding_2022kr = {
- NULL,
- NULL,
- "ISO-2022-KR",
- NULL,
- 0
-};
-
-static const char *cp1252_aliases[] = {"cp1252", NULL};
-static zend_encoding encoding_cp1252 = {
- NULL,
- NULL,
- "Windows-1252",
- (const char *(*)[])&cp1252_aliases,
- 1
-};
-
-static const char *iso_8859_1_aliases[] = {"ISO_8859-1", "latin1", NULL};
-static zend_encoding encoding_8859_1 = {
- NULL,
- NULL,
- "ISO-8859-1",
- (const char *(*)[])&iso_8859_1_aliases,
- 1
-};
-
-static const char *iso_8859_2_aliases[] = {"ISO_8859-2", "latin2", NULL};
-static zend_encoding encoding_8859_2 = {
- NULL,
- NULL,
- "ISO-8859-2",
- (const char *(*)[])&iso_8859_2_aliases,
- 1
-};
-
-static const char *iso_8859_3_aliases[] = {"ISO_8859-3", "latin3", NULL};
-static zend_encoding encoding_8859_3 = {
- NULL,
- NULL,
- "ISO-8859-3",
- (const char *(*)[])&iso_8859_3_aliases,
- 1
-};
-
-static const char *iso_8859_4_aliases[] = {"ISO_8859-4", "latin4", NULL};
-static zend_encoding encoding_8859_4 = {
- NULL,
- NULL,
- "ISO-8859-4",
- (const char *(*)[])&iso_8859_4_aliases,
- 1
-};
-
-static const char *iso_8859_5_aliases[] = {"ISO_8859-5", "cyrillic", NULL};
-static zend_encoding encoding_8859_5 = {
- NULL,
- NULL,
- "ISO-8859-5",
- (const char *(*)[])&iso_8859_5_aliases,
- 1
-};
-
-static const char *iso_8859_6_aliases[] = {"ISO_8859-6", "arabic", NULL};
-static zend_encoding encoding_8859_6 = {
- NULL,
- NULL,
- "ISO-8859-6",
- (const char *(*)[])&iso_8859_6_aliases,
- 1
-};
-
-static const char *iso_8859_7_aliases[] = {"ISO_8859-7", "greek", NULL};
-static zend_encoding encoding_8859_7 = {
- NULL,
- NULL,
- "ISO-8859-7",
- (const char *(*)[])&iso_8859_7_aliases,
- 1
-};
-
-static const char *iso_8859_8_aliases[] = {"ISO_8859-8", "hebrew", NULL};
-static zend_encoding encoding_8859_8 = {
- NULL,
- NULL,
- "ISO-8859-8",
- (const char *(*)[])&iso_8859_8_aliases,
- 1
-};
-
-static const char *iso_8859_9_aliases[] = {"ISO_8859-9", "latin5", NULL};
-static zend_encoding encoding_8859_9 = {
- NULL,
- NULL,
- "ISO-8859-9",
- (const char *(*)[])&iso_8859_9_aliases,
- 1
-};
-
-static const char *iso_8859_10_aliases[] = {"ISO_8859-10", "latin6", NULL};
-static zend_encoding encoding_8859_10 = {
- NULL,
- NULL,
- "ISO-8859-10",
- (const char *(*)[])&iso_8859_10_aliases,
- 1
-};
-
-static const char *iso_8859_13_aliases[] = {"ISO_8859-13", NULL};
-static zend_encoding encoding_8859_13 = {
- NULL,
- NULL,
- "ISO-8859-13",
- (const char *(*)[])&iso_8859_13_aliases,
- 1
-};
-
-static const char *iso_8859_14_aliases[] = {"ISO_8859-14", "latin8", NULL};
-static zend_encoding encoding_8859_14 = {
- NULL,
- NULL,
- "ISO-8859-14",
- (const char *(*)[])&iso_8859_14_aliases,
- 1
-};
-
-static const char *iso_8859_15_aliases[] = {"ISO_8859-15", NULL};
-static zend_encoding encoding_8859_15 = {
- NULL,
- NULL,
- "ISO-8859-15",
- (const char *(*)[])&iso_8859_15_aliases,
- 1
-};
-
-static const char *cp1251_aliases[] = {"CP1251", "CP-1251", "WINDOWS-1251", NULL};
-static zend_encoding encoding_cp1251 = {
- NULL,
- NULL,
- "Windows-1251",
- (const char *(*)[])&cp1251_aliases,
- 1
-};
-
-static const char *cp866_aliases[] = {"CP866", "CP-866", "IBM-866", NULL};
-static zend_encoding encoding_cp866 = {
- NULL,
- NULL,
- "CP866",
- (const char *(*)[])&cp866_aliases,
- 1
-};
-
-static const char *koi8r_aliases[] = {"KOI8-R", "KOI8R", NULL};
-static zend_encoding encoding_koi8r = {
- NULL,
- NULL,
- "KOI8-R",
- (const char *(*)[])&koi8r_aliases,
- 1
-};
-
-static const char *koi8u_aliases[] = {"KOI8-U", "KOI8U", NULL};
-static zend_encoding encoding_koi8u = {
- NULL,
- NULL,
- "KOI8-U",
- (const char *(*)[])&koi8u_aliases,
- 1
-};
-
-static const char *cp1254_aliases[] = {"cp1254", NULL};
-static zend_encoding encoding_cp1254 = {
- NULL,
- NULL,
- "Windows-1254",
- (const char *(*)[])&cp1254_aliases,
- 1
-};
-
-static const char *armscii8_aliases[] = { "ArmSCII8", "ARMSCII-8", "ARMSCII8", NULL};
-static zend_encoding encoding_armscii8 = {
- NULL,
- NULL,
- "ArmSCII-8",
- (const char *(*)[])&armscii8_aliases,
- 1
-};
-
-static const char *cp850_aliases[] = {"IBM850", NULL};
-static zend_encoding encoding_cp850 = {
- NULL,
- NULL,
- "CP850",
- (const char *(*)[])&cp850_aliases,
- 1
-};
-
-static zend_encoding *zend_encoding_table[] = {
- &encoding_ucs4,
- &encoding_ucs4be,
- &encoding_ucs4le,
- &encoding_ucs2,
- &encoding_ucs2be,
- &encoding_ucs2le,
- &encoding_utf32,
- &encoding_utf32be,
- &encoding_utf32le,
- &encoding_utf16,
- &encoding_utf16be,
- &encoding_utf16le,
- &encoding_utf8,
- &encoding_ascii,
- &encoding_euc_jp,
- &encoding_sjis,
- &encoding_eucjp_win,
- &encoding_sjis_win,
- &encoding_jis,
- &encoding_cp1252,
- &encoding_8859_1,
- &encoding_8859_2,
- &encoding_8859_3,
- &encoding_8859_4,
- &encoding_8859_5,
- &encoding_8859_6,
- &encoding_8859_7,
- &encoding_8859_8,
- &encoding_8859_9,
- &encoding_8859_10,
- &encoding_8859_13,
- &encoding_8859_14,
- &encoding_8859_15,
- &encoding_euc_cn,
- &encoding_cp936,
- &encoding_hz,
- &encoding_euc_tw,
- &encoding_big5,
- &encoding_euc_kr,
- &encoding_uhc,
- &encoding_2022kr,
- &encoding_cp1251,
- &encoding_cp866,
- &encoding_koi8r,
- &encoding_koi8u,
- &encoding_armscii8,
- &encoding_cp1254,
- &encoding_cp850,
- NULL
-};
-
-
-
-ZEND_API int zend_multibyte_set_script_encoding(const char *encoding_list,
-size_t encoding_list_size TSRMLS_DC)
-{
- if (CG(script_encoding_list)) {
- efree(CG(script_encoding_list));
- CG(script_encoding_list) = NULL;
- }
- CG(script_encoding_list_size) = 0;
-
- if (!encoding_list) {
- return 0;
- }
-
- zend_multibyte_parse_encoding_list(encoding_list, encoding_list_size, &(CG(script_encoding_list)), &(CG(script_encoding_list_size)));
-
- return 0;
-}
-
-
-ZEND_API int zend_multibyte_set_internal_encoding(const char *encoding_name TSRMLS_DC)
+static const zend_encoding *dummy_encoding_fetcher(const char *encoding_name TSRMLS_DC)
{
- CG(internal_encoding) = zend_multibyte_fetch_encoding(encoding_name);
- return 0;
+ return NULL;
}
-ZEND_API int zend_multibyte_set_functions(zend_encoding_detector encoding_detector, zend_encoding_converter encoding_converter, zend_encoding_oddlen encoding_oddlen TSRMLS_DC)
+static const char *dummy_encoding_name_getter(const zend_encoding *encoding)
{
- CG(encoding_detector) = encoding_detector;
- CG(encoding_converter) = encoding_converter;
- CG(encoding_oddlen) = encoding_oddlen;
- return 0;
+ return (const char*)encoding;
}
-
-ZEND_API int zend_multibyte_set_filter(zend_encoding *onetime_encoding TSRMLS_DC)
+static int dummy_encoding_lexer_compatibility_checker(const zend_encoding *encoding)
{
- LANG_SCNG(script_encoding) = zend_multibyte_find_script_encoding(onetime_encoding TSRMLS_CC);
- LANG_SCNG(internal_encoding) = CG(internal_encoding);
-
- /* judge input/output filter */
- LANG_SCNG(input_filter) = NULL;
- LANG_SCNG(output_filter) = NULL;
-
- if (!LANG_SCNG(script_encoding)) {
- return 0;
- }
-
- if (!LANG_SCNG(internal_encoding) || LANG_SCNG(script_encoding) == LANG_SCNG(internal_encoding)) {
- /* if encoding specfic filters exist, use them */
- if (LANG_SCNG(script_encoding)->input_filter && LANG_SCNG(script_encoding)->output_filter) {
- LANG_SCNG(input_filter) = LANG_SCNG(script_encoding)->input_filter;
- LANG_SCNG(output_filter) = LANG_SCNG(script_encoding)->output_filter;
- return 0;
- }
-
- if (!LANG_SCNG(script_encoding)->compatible) {
- /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
- LANG_SCNG(internal_encoding) = LANG_SCNG(script_encoding);
- LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
- LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
- return 0;
- } else {
- /* nothing to do in this case */
- return 0;
- }
- }
-
- /* LANG_SCNG(internal_encoding) cannot be NULL here */
- if (LANG_SCNG(internal_encoding)->compatible) {
- LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
- return 0;
- } else if (LANG_SCNG(script_encoding)->compatible) {
- LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
- return 0;
- }
-
- /* both script and internal encodings are incompatible w/ flex */
- LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
- LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
-
return 0;
}
-
-ZEND_API zend_encoding* zend_multibyte_fetch_encoding(const char *encoding_name)
+static const zend_encoding *dummy_encoding_detector(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size TSRMLS_DC)
{
- int i, j;
- zend_encoding *encoding;
-
- if (!encoding_name) {
- return NULL;
- }
-
- for (i = 0; (encoding = zend_encoding_table[i]) != NULL; i++) {
- if (zend_binary_strcasecmp(encoding->name, strlen(encoding->name), encoding_name, strlen(encoding_name)) == 0) {
- return encoding;
- }
- }
-
- for (i = 0; (encoding = zend_encoding_table[i]) != NULL; i++) {
- if (encoding->aliases != NULL) {
- for (j = 0; (*encoding->aliases)[j] != NULL; j++) {
- if (zend_binary_strcasecmp((*encoding->aliases)[j], strlen((*encoding->aliases)[j]), encoding_name, strlen(encoding_name)) == 0) {
- return encoding;
- }
- }
- }
- }
-
return NULL;
}
-
-ZEND_API size_t zend_multibyte_script_encoding_filter(unsigned char **to, size_t
-*to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+static size_t dummy_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from TSRMLS_DC)
{
- const char *name;
-
- if (LANG_SCNG(internal_encoding) == NULL || LANG_SCNG(internal_encoding)->compatible == 0) {
- name = "UTF-8";
- } else {
- name = LANG_SCNG(internal_encoding)->name;
- }
-
- return zend_multibyte_encoding_filter(to, to_length, name, from, from_length, LANG_SCNG(script_encoding)->name TSRMLS_CC);
+ return (size_t)-1;
}
-ZEND_API size_t zend_multibyte_internal_encoding_filter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+static int dummy_encoding_list_parser(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
{
- const char *name;
-
- if (LANG_SCNG(script_encoding)->compatible == 0) {
- name = "UTF-8";
- } else {
- name = LANG_SCNG(script_encoding)->name;
- }
-
- return zend_multibyte_encoding_filter(to, to_length, LANG_SCNG(internal_encoding)->name, from, from_length, name TSRMLS_CC);
+ *return_list = pemalloc(0, persistent);
+ return_size = 0;
+ return SUCCESS;
}
-static size_t zend_multibyte_encoding_filter(unsigned char **to, size_t *to_length, const char *to_encoding, const unsigned char *from, size_t from_length, const char *from_encoding TSRMLS_DC)
+static const zend_encoding *dummy_internal_encoding_getter(TSRMLS_D)
{
- size_t oddlen;
-
- if (!CG(encoding_converter)) {
- return 0;
- }
-
- if (CG(encoding_oddlen)) {
- oddlen = CG(encoding_oddlen)(from, from_length, from_encoding TSRMLS_CC);
- if (oddlen > 0) {
- from_length -= oddlen;
- }
- }
-
- if (CG(encoding_converter)(to, to_length, from, from_length, to_encoding, from_encoding TSRMLS_CC) != 0) {
- return 0;
- }
-
- return from_length;
+ return NULL;
}
-
-/*
- * Shift_JIS Input/Output Filter
- */
-static const unsigned char table_sjis[] = { /* 0x80-0x9f,0xE0-0xEF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 0, 0, 0
-};
-
-size_t sjis_input_filter(unsigned char **buf, size_t *length, const unsigned char *sjis, size_t sjis_length TSRMLS_DC)
+static int dummy_internal_encoding_setter(const zend_encoding *encoding TSRMLS_DC)
{
- const unsigned char *p;
- unsigned char *q;
- unsigned char c1, c2;
-
- *buf = (unsigned char*)emalloc(sjis_length * 3 / 2 + 1);
- if (!*buf)
- return 0;
- *length = 0;
-
- p = sjis;
- q = *buf;
-
- /* convert [SJIS -> EUC-JP] (for lex scan) -- some other better ways? */
- while (*p && (p - sjis) < sjis_length) {
- if (!(*p & 0x80)) {
- *q++ = *p++;
- continue;
- }
-
- /* handling 8 bit code */
- if (table_sjis[*p] == 1) {
- /* 1 byte kana */
- *q++ = 0x8e;
- *q++ = *p++;
- continue;
- }
-
- if (!*(p+1)) {
- *q++ = *p++;
- break;
- }
-
- if (table_sjis[*p] == 2) {
- /* 2 byte kanji code */
- c1 = *p++;
- if (!*p || (p - sjis) >= sjis_length) {
- break;
- }
- c2 = *p++;
- c1 -= (c1 <= 0x9f) ? 0x71 : 0xb1;
- c1 = (c1 << 1) + 1;
- if (c2 >= 0x9e) {
- c2 -= 0x7e;
- c1++;
- } else if (c2 > 0x7f) {
- c2 -= 0x20;
- } else {
- c2 -= 0x1f;
- }
-
- c1 |= 0x80;
- c2 |= 0x80;
-
- *q++ = c1;
- *q++ = c2;
- } else {
- /*
- * for user defined chars (ATTENTION)
- *
- * THESE ARE NOT CODE FOR CONVERSION! :-P
- * (using *ILLEGALLY* 3byte EUC-JP space)
- *
- * we cannot perfectly (== 1 to 1) convert these chars to EUC-JP.
- * so, these code are for perfect RESTORING in sjis_output_filter()
- */
- c1 = *p++;
- if (!*p || (p - sjis) >= sjis_length) {
- break;
- }
- c2 = *p++;
- *q++ = 0x8f;
- /*
- * MAP TO (EUC-JP):
- * type A: 0xeba1 - 0xf4fe
- * type B: 0xf5a1 - 0xfefe
- * type C: 0xa1a1 - 0xa6fe
- */
- c1 -= (c1 > 0xf9) ? (0x79+0x71) : (0x0a+0xb1);
- c1 = (c1 << 1) + 1;
- if (c2 >= 0x9e) {
- c2 -= 0x7e;
- c1++;
- } else if (c2 > 0x7f) {
- c2 -= 0x20;
- } else {
- c2 -= 0x1f;
- }
-
- c1 |= 0x80;
- c2 |= 0x80;
-
- *q++ = c1;
- *q++ = c2;
- }
- }
- *q = '\0';
- *length = q - *buf;
-
- return *length;
+ return FAILURE;
}
-static const unsigned char table_eucjp[] = { /* 0xA1-0xFE */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1
+static zend_multibyte_functions multibyte_functions = {
+ NULL,
+ dummy_encoding_fetcher,
+ dummy_encoding_name_getter,
+ dummy_encoding_lexer_compatibility_checker,
+ dummy_encoding_detector,
+ dummy_encoding_converter,
+ dummy_encoding_list_parser,
+ dummy_internal_encoding_getter,
+ dummy_internal_encoding_setter
};
-size_t sjis_output_filter(unsigned char **sjis, size_t *sjis_length, const unsigned char *buf, size_t length TSRMLS_DC)
-{
- unsigned char c1, c2;
- unsigned char *p;
- const unsigned char *q;
+ZEND_API const zend_encoding *zend_multibyte_encoding_utf32be = (const zend_encoding*)"UTF-32BE";
+ZEND_API const zend_encoding *zend_multibyte_encoding_utf32le = (const zend_encoding*)"UTF-32LE";
+ZEND_API const zend_encoding *zend_multibyte_encoding_utf16be = (const zend_encoding*)"UTF-16BE";
+ZEND_API const zend_encoding *zend_multibyte_encoding_utf16le = (const zend_encoding*)"UTF-32LE";
+ZEND_API const zend_encoding *zend_multibyte_encoding_utf8 = (const zend_encoding*)"UTF-8";
- if (!sjis || !sjis_length) {
- return 0;
+ZEND_API int zend_multibyte_set_functions(const zend_multibyte_functions *functions TSRMLS_DC)
+{
+ zend_multibyte_encoding_utf32be = functions->encoding_fetcher("UTF-32BE" TSRMLS_CC);
+ if (!zend_multibyte_encoding_utf32be) {
+ return FAILURE;
}
-
- /* always Shift_JIS <= EUC-JP */
- *sjis = (unsigned char*)emalloc(length+1);
- if (!sjis) {
- return 0;
+ zend_multibyte_encoding_utf32le = functions->encoding_fetcher("UTF-32LE" TSRMLS_CC);
+ if (!zend_multibyte_encoding_utf32le) {
+ return FAILURE;
+ }
+ zend_multibyte_encoding_utf16be = functions->encoding_fetcher("UTF-16BE" TSRMLS_CC);
+ if (!zend_multibyte_encoding_utf16be) {
+ return FAILURE;
+ }
+ zend_multibyte_encoding_utf16le = functions->encoding_fetcher("UTF-16LE" TSRMLS_CC);
+ if (!zend_multibyte_encoding_utf16le) {
+ return FAILURE;
+ }
+ zend_multibyte_encoding_utf8 = functions->encoding_fetcher("UTF-8" TSRMLS_CC);
+ if (!zend_multibyte_encoding_utf8) {
+ return FAILURE;
}
- p = *sjis;
- q = buf;
-
- /* restore converted strings [EUC-JP -> Shift_JIS] */
- while (*q && (q - buf) < length) {
- if (!(*q & 0x80)) {
- *p++ = *q++;
- continue;
- }
-
- /* hankaku kana */
- if (*q == 0x8e) {
- q++;
- if (*q) {
- *p++ = *q++;
- }
- continue;
- }
-
- /* 2 byte kanji code */
- if (table_eucjp[*q] == 2) {
- c1 = (*q++ & ~0x80) & 0xff;
- if (*q) {
- c2 = (*q++ & ~0x80) & 0xff;
- } else {
- q--;
- break;
- }
-
- c2 += (c1 & 0x01) ? 0x1f : 0x7d;
- if (c2 >= 0x7f) {
- c2++;
- }
- c1 = ((c1 - 0x21) >> 1) + 0x81;
- if (c1 > 0x9f) {
- c1 += 0x40;
- }
-
- *p++ = c1;
- *p++ = c2;
- continue;
- }
- if (*q == 0x8f) {
- q++;
- if (*q) {
- c1 = (*q++ & ~0x80) & 0xff;
- } else {
- q--;
- break;
- }
- if (*q) {
- c2 = (*q++ & ~0x80) & 0xff;
- } else {
- q -= 2;
- break;
- }
-
- c2 += (c1 & 0x01) ? 0x1f : 0x7d;
- if (c2 >= 0x7f) {
- c2++;
- }
- c1 = ((c1 - 0x21) >> 1) + 0x81;
- if (c1 > 0x9f) {
- c1 += 0x40;
- }
-
- if (c1 >= 0x81 && c1 <= 0x9f) {
- c1 += 0x79;
- } else {
- c1 += 0x0a;
- }
-
- *p++ = c1;
- *p++ = c2;
- continue;
- }
+ multibyte_functions = *functions;
- /* some other chars (may not happen) */
- *p++ = *q++;
+ /* As zend_multibyte_set_functions() gets called after ini settings were
+ * populated, we need to reinitialize script_encoding here.
+ */
+ {
+ const char *value = zend_ini_string("zend.script_encoding", sizeof("zend.script_encoding"), 0);
+ zend_multibyte_set_script_encoding_by_string(value, strlen(value) TSRMLS_CC);
}
- *p = '\0';
- *sjis_length = p - *sjis;
-
- return q-buf; /* return length we actually read */
+ return SUCCESS;
}
-
-static char *zend_multibyte_assemble_encoding_list(zend_encoding **encoding_list, size_t encoding_list_size)
+ZEND_API const zend_multibyte_functions *zend_multibyte_get_functions(TSRMLS_D)
{
- int i, list_size = 0;
- const char *name;
- char *list = NULL;
-
- if (!encoding_list || !encoding_list_size) {
- return NULL;
- }
-
- for (i = 0; i < encoding_list_size; i++) {
- name = (*(encoding_list+i))->name;
- if (name) {
- list_size += strlen(name) + 1;
- if (!list) {
- list = (char*)emalloc(list_size);
- if (!list) {
- return NULL;
- }
- *list = '\0';
- } else {
- list = (char*)erealloc(list, list_size);
- if (!list) {
- return NULL;
- }
- strcat(list, ",");
- }
- strcat(list, name);
- }
- }
- return list;
+ return multibyte_functions.provider_name ? &multibyte_functions: NULL;
}
-
-static int zend_multibyte_parse_encoding_list(const char *encoding_list,
-size_t encoding_list_size, zend_encoding ***result, size_t *result_size)
+ZEND_API const zend_encoding *zend_multibyte_fetch_encoding(const char *name TSRMLS_DC)
{
- int n, size;
- char *p, *p1, *p2, *endp, *tmpstr;
- zend_encoding **list, **entry, *encoding;
-
- list = NULL;
- if (encoding_list == NULL || encoding_list_size <= 0) {
- return -1;
- } else {
- /* copy the encoding_list string for work */
- tmpstr = (char *)estrndup(encoding_list, encoding_list_size);
- if (tmpstr == NULL) {
- return -1;
- }
- /* count the number of listed encoding names */
- endp = tmpstr + encoding_list_size;
- n = 1;
- p1 = tmpstr;
- while ((p2 = zend_memnstr(p1, ",", 1, endp)) != NULL) {
- p1 = p2 + 1;
- n++;
- }
- size = n;
- /* make list */
- list = (zend_encoding**)ecalloc(size, sizeof(zend_encoding*));
- if (list != NULL) {
- entry = list;
- n = 0;
- p1 = tmpstr;
- do {
- p2 = p = zend_memnstr(p1, ",", 1, endp);
- if (p == NULL) {
- p = endp;
- }
- *p = '\0';
- /* trim spaces */
- while (p1 < p && (*p1 == ' ' || *p1 == '\t')) {
- p1++;
- }
- p--;
- while (p > p1 && (*p == ' ' || *p == '\t')) {
- *p = '\0';
- p--;
- }
- /* convert to the encoding number and check encoding */
- encoding = zend_multibyte_fetch_encoding(p1);
- if (encoding)
- {
- *entry++ = encoding;
- n++;
- }
- p1 = p2 + 1;
- } while (n < size && p2 != NULL);
- *result = list;
- *result_size = n;
- }
- efree(tmpstr);
- }
-
- if (list == NULL) {
- return -1;
- }
-
- return 0;
+ return multibyte_functions.encoding_fetcher(name TSRMLS_CC);
}
-
-static zend_encoding* zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC)
+ZEND_API const char *zend_multibyte_get_encoding_name(const zend_encoding *encoding)
{
- zend_encoding *script_encoding;
- char *name, *list;
-
- /* onetime_encoding is prior to everything */
- if (onetime_encoding != NULL) {
- return onetime_encoding;
- }
-
- if (CG(detect_unicode)) {
- /* check out bom(byte order mark) and see if containing wchars */
- script_encoding = zend_multibyte_detect_unicode(TSRMLS_C);
- if (script_encoding != NULL) {
- /* bom or wchar detection is prior to 'script_encoding' option */
- return script_encoding;
- }
- }
-
- /* if no script_encoding specified, just leave alone */
- if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
- return NULL;
- }
-
- /* if multiple encodings specified, detect automagically */
- if (CG(script_encoding_list_size) > 1 && CG(encoding_detector)) {
- list = zend_multibyte_assemble_encoding_list(CG(script_encoding_list),
- CG(script_encoding_list_size));
- name = CG(encoding_detector)(LANG_SCNG(script_org),
- LANG_SCNG(script_org_size), list TSRMLS_CC);
- if (list) {
- efree(list);
- }
- if (name) {
- script_encoding = zend_multibyte_fetch_encoding(name);
- efree(name);
- } else {
- script_encoding = NULL;
- }
- return script_encoding;
- }
-
- return *(CG(script_encoding_list));
+ return multibyte_functions.encoding_name_getter(encoding);
}
+ZEND_API int zend_multibyte_check_lexer_compatibility(const zend_encoding *encoding)
+{
+ return multibyte_functions.lexer_compatibility_checker(encoding);
+}
-static zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D)
+ZEND_API const zend_encoding *zend_multibyte_encoding_detector(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size TSRMLS_DC)
{
- zend_encoding *script_encoding = NULL;
- int bom_size;
- unsigned char *script;
+ return multibyte_functions.encoding_detector(string, length, list, list_size TSRMLS_CC);
+}
- if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
- return NULL;
- }
+ZEND_API size_t zend_multibyte_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from TSRMLS_DC)
+{
+ return multibyte_functions.encoding_converter(to, to_length, from, from_length, encoding_to, encoding_from TSRMLS_CC);
+}
- /* check out BOM */
- if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
- script_encoding = &encoding_utf32be;
- bom_size = sizeof(BOM_UTF32_BE)-1;
- } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
- script_encoding = &encoding_utf32le;
- bom_size = sizeof(BOM_UTF32_LE)-1;
- } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
- script_encoding = &encoding_utf16be;
- bom_size = sizeof(BOM_UTF16_BE)-1;
- } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
- script_encoding = &encoding_utf16le;
- bom_size = sizeof(BOM_UTF16_LE)-1;
- } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
- script_encoding = &encoding_utf8;
- bom_size = sizeof(BOM_UTF8)-1;
- }
+ZEND_API int zend_multibyte_parse_encoding_list(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
+{
+ return multibyte_functions.encoding_list_parser(encoding_list, encoding_list_len, return_list, return_size, persistent TSRMLS_CC);
+}
- if (script_encoding) {
- /* remove BOM */
- script = (unsigned char*)emalloc(LANG_SCNG(script_org_size)+1-bom_size);
- memcpy(script, LANG_SCNG(script_org)+bom_size, LANG_SCNG(script_org_size)+1-bom_size);
- efree(LANG_SCNG(script_org));
- LANG_SCNG(script_org) = script;
- LANG_SCNG(script_org_size) -= bom_size;
+ZEND_API const zend_encoding *zend_multibyte_get_internal_encoding(TSRMLS_D)
+{
+ return multibyte_functions.internal_encoding_getter(TSRMLS_C);
+}
- return script_encoding;
- }
+ZEND_API const zend_encoding *zend_multibyte_get_script_encoding(TSRMLS_D)
+{
+ return LANG_SCNG(script_encoding);
+}
- /* script contains NULL bytes -> auto-detection */
- if (memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size))) {
- /* make best effort if BOM is missing */
- return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC);
+ZEND_API int zend_multibyte_set_script_encoding(const zend_encoding **encoding_list, size_t encoding_list_size TSRMLS_DC)
+{
+ if (CG(script_encoding_list)) {
+ free(CG(script_encoding_list));
}
+ CG(script_encoding_list) = encoding_list;
+ CG(script_encoding_list_size) = encoding_list_size;
+ return SUCCESS;
+}
- return NULL;
+ZEND_API int zend_multibyte_set_internal_encoding(const zend_encoding *encoding TSRMLS_DC)
+{
+ return multibyte_functions.internal_encoding_setter(encoding TSRMLS_CC);
}
-static zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC)
+ZEND_API int zend_multibyte_set_script_encoding_by_string(const char *new_value, size_t new_value_length TSRMLS_DC)
{
- const unsigned char *p;
- int wchar_size = 2;
- int le = 0;
+ const zend_encoding **list = 0;
+ size_t size = 0;
- /* utf-16 or utf-32? */
- p = script;
- while ((p-script) < script_size) {
- p = memchr(p, 0, script_size-(p-script)-2);
- if (!p) {
- break;
- }
- if (*(p+1) == '\0' && *(p+2) == '\0') {
- wchar_size = 4;
- break;
- }
+ if (!new_value) {
+ zend_multibyte_set_script_encoding(NULL, 0 TSRMLS_CC);
+ return SUCCESS;
+ }
- /* searching for UTF-32 specific byte orders, so this will do */
- p += 4;
+ if (FAILURE == zend_multibyte_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
+ return FAILURE;
}
- /* BE or LE? */
- p = script;
- while ((p-script) < script_size) {
- if (*p == '\0' && *(p+wchar_size-1) != '\0') {
- /* BE */
- le = 0;
- break;
- } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
- /* LE* */
- le = 1;
- break;
- }
- p += wchar_size;
+ if (size == 0) {
+ pefree(list, 1);
+ return FAILURE;
}
- if (wchar_size == 2) {
- return le ? &encoding_utf16le : &encoding_utf16be;
- } else {
- return le ? &encoding_utf32le : &encoding_utf32be;
+ if (FAILURE == zend_multibyte_set_script_encoding(list, size TSRMLS_CC)) {
+ return FAILURE;
}
- return NULL;
+ return SUCCESS;
}
-#endif /* ZEND_MULTIBYTE */
/*
* Local variables:
diff --git a/Zend/zend_multibyte.h b/Zend/zend_multibyte.h
index 802008bb37..38b13c2d16 100644
--- a/Zend/zend_multibyte.h
+++ b/Zend/zend_multibyte.h
@@ -22,52 +22,60 @@
#ifndef ZEND_MULTIBYTE_H
#define ZEND_MULTIBYTE_H
-#ifdef ZEND_MULTIBYTE
-
-#define BOM_UTF32_BE "\x00\x00\xfe\xff"
-#define BOM_UTF32_LE "\xff\xfe\x00\x00"
-#define BOM_UTF16_BE "\xfe\xff"
-#define BOM_UTF16_LE "\xff\xfe"
-#define BOM_UTF8 "\xef\xbb\xbf"
+typedef struct _zend_encoding zend_encoding;
typedef size_t (*zend_encoding_filter)(unsigned char **str, size_t *str_length, const unsigned char *buf, size_t length TSRMLS_DC);
-typedef char* (*zend_encoding_detector)(const unsigned char *string, size_t length, char *list TSRMLS_DC);
-
-typedef int (*zend_encoding_converter)(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const char *encoding_to, const char *encoding_from TSRMLS_DC);
-
-typedef size_t (*zend_encoding_oddlen)(const unsigned char *string, size_t length, const char *encoding TSRMLS_DC);
-
-typedef struct _zend_encoding {
- zend_encoding_filter input_filter; /* escape input filter */
- zend_encoding_filter output_filter; /* escape output filter */
- const char *name; /* encoding name */
- const char *(*aliases)[]; /* encoding name aliases */
- zend_bool compatible; /* flex compatible or not */
-} zend_encoding;
+typedef const zend_encoding* (*zend_encoding_fetcher)(const char *encoding_name TSRMLS_DC);
+typedef const char* (*zend_encoding_name_getter)(const zend_encoding *encoding);
+typedef int (*zend_encoding_lexer_compatibility_checker)(const zend_encoding *encoding);
+typedef const zend_encoding *(*zend_encoding_detector)(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size TSRMLS_DC);
+typedef size_t (*zend_encoding_converter)(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from TSRMLS_DC);
+typedef int (*zend_encoding_list_parser)(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC);
+typedef const zend_encoding *(*zend_encoding_internal_encoding_getter)(TSRMLS_D);
+typedef int (*zend_encoding_internal_encoding_setter)(const zend_encoding *encoding TSRMLS_DC);
+typedef struct _zend_multibyte_functions {
+ const char *provider_name;
+ zend_encoding_fetcher encoding_fetcher;
+ zend_encoding_name_getter encoding_name_getter;
+ zend_encoding_lexer_compatibility_checker lexer_compatibility_checker;
+ zend_encoding_detector encoding_detector;
+ zend_encoding_converter encoding_converter;
+ zend_encoding_list_parser encoding_list_parser;
+ zend_encoding_internal_encoding_getter internal_encoding_getter;
+ zend_encoding_internal_encoding_setter internal_encoding_setter;
+} zend_multibyte_functions;
/*
* zend multibyte APIs
*/
BEGIN_EXTERN_C()
-ZEND_API int zend_multibyte_set_script_encoding(const char *encoding_list,
-size_t encoding_list_size TSRMLS_DC);
-ZEND_API int zend_multibyte_set_internal_encoding(const char *encoding_name TSRMLS_DC);
-ZEND_API int zend_multibyte_set_functions(zend_encoding_detector encoding_detector, zend_encoding_converter encoding_converter, zend_encoding_oddlen encoding_oddlen TSRMLS_DC);
-ZEND_API int zend_multibyte_set_filter(zend_encoding *onetime_encoding TSRMLS_DC);
-ZEND_API zend_encoding* zend_multibyte_fetch_encoding(const char *encoding_name);
-ZEND_API size_t zend_multibyte_script_encoding_filter(unsigned char **to, size_t
-*to_length, const unsigned char *from, size_t from_length TSRMLS_DC);
-ZEND_API size_t zend_multibyte_internal_encoding_filter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC);
-/* in zend_language_scanner.l */
-ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, zend_encoding *old_encoding TSRMLS_DC);
-ZEND_API int zend_multibyte_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC);
-ZEND_API int zend_multibyte_read_script(unsigned char *buf, size_t n TSRMLS_DC);
-END_EXTERN_C()
+ZEND_API extern const zend_encoding *zend_multibyte_encoding_utf32be;
+ZEND_API extern const zend_encoding *zend_multibyte_encoding_utf32le;
+ZEND_API extern const zend_encoding *zend_multibyte_encoding_utf16be;
+ZEND_API extern const zend_encoding *zend_multibyte_encoding_utf16le;
+ZEND_API extern const zend_encoding *zend_multibyte_encoding_utf8;
-#endif /* ZEND_MULTIBYTE */
+/* multibyte utility functions */
+ZEND_API int zend_multibyte_set_functions(const zend_multibyte_functions *functions TSRMLS_DC);
+ZEND_API const zend_multibyte_functions *zend_multibyte_get_functions(TSRMLS_D);
+
+ZEND_API const zend_encoding *zend_multibyte_fetch_encoding(const char *name TSRMLS_DC);
+ZEND_API const char *zend_multibyte_get_encoding_name(const zend_encoding *encoding);
+ZEND_API int zend_multibyte_check_lexer_compatibility(const zend_encoding *encoding);
+ZEND_API const zend_encoding *zend_multibyte_encoding_detector(const unsigned char *string, size_t length, const zend_encoding **list, size_t list_size TSRMLS_DC);
+ZEND_API size_t zend_multibyte_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from TSRMLS_DC);
+ZEND_API int zend_multibyte_parse_encoding_list(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC);
+
+ZEND_API const zend_encoding *zend_multibyte_get_internal_encoding(TSRMLS_D);
+ZEND_API const zend_encoding *zend_multibyte_get_script_encoding(TSRMLS_D);
+ZEND_API int zend_multibyte_set_script_encoding(const zend_encoding **encoding_list, size_t encoding_list_size TSRMLS_DC);
+ZEND_API int zend_multibyte_set_internal_encoding(const zend_encoding *encoding TSRMLS_DC);
+ZEND_API int zend_multibyte_set_script_encoding_by_string(const char *new_value, size_t new_value_length TSRMLS_DC);
+
+END_EXTERN_C()
#endif /* ZEND_MULTIBYTE_H */
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 49a5d1d1b7..33a86d7dd8 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -31,6 +31,18 @@
else (lval) = __tmpvar; \
} while (0)
+#elif defined(__x86_64__) && defined(__GNUC__)
+
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+ long __tmpvar; \
+ __asm__ ("imulq %3,%0\n" \
+ "adcq $0,%1" \
+ : "=r"(__tmpvar),"=r"(usedval) \
+ : "0"(a), "r"(b), "1"(0)); \
+ if (usedval) (dval) = (double) (a) * (double) (b); \
+ else (lval) = __tmpvar; \
+} while (0)
+
#elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64)
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index eae47d9c5a..d82493aeaf 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -32,7 +32,8 @@
#define DEBUG_OBJECT_HANDLERS 0
-#define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p TSRMLS_CC)
+#define Z_OBJ_P(zval_p) \
+ ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object))
/*
__X accessors explanation:
@@ -51,14 +52,78 @@
called, we cal __call handler.
*/
+ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
+{
+ if (!zobj->properties) {
+ HashPosition pos;
+ zend_property_info *prop_info;
+ zend_class_entry *ce = zobj->ce;
+
+ ALLOC_HASHTABLE(zobj->properties);
+ zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ if (ce->default_properties_count) {
+ for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+ zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
+ if (/*prop_info->ce == ce &&*/
+ (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
+ prop_info->offset >= 0 &&
+ zobj->properties_table[prop_info->offset]) {
+ zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
+ }
+ }
+ while (ce->parent && ce->parent->default_properties_count) {
+ ce = ce->parent;
+ for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+ zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
+ if (prop_info->ce == ce &&
+ (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
+ (prop_info->flags & ZEND_ACC_PRIVATE) != 0 &&
+ prop_info->offset >= 0 &&
+ zobj->properties_table[prop_info->offset]) {
+ zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
+ }
+ }
+ }
+ }
+ }
+}
+/* }}} */
+
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zobj = Z_OBJ_P(object);
+ if (!zobj->properties) {
+ rebuild_object_properties(zobj);
+ }
return zobj->properties;
}
/* }}} */
+ZEND_API HashTable *zend_std_get_gc(zval *object, zval ***table, int *n TSRMLS_DC) /* {{{ */
+{
+ if (Z_OBJ_HANDLER_P(object, get_properties) != zend_std_get_properties) {
+ *table = NULL;
+ *n = 0;
+ return Z_OBJ_HANDLER_P(object, get_properties)(object TSRMLS_CC);
+ } else {
+ zend_object *zobj = Z_OBJ_P(object);
+
+ if (zobj->properties) {
+ *table = NULL;
+ *n = 0;
+ return zobj->properties;
+ } else {
+ *table = zobj->properties_table;
+ *n = zobj->ce->default_properties_count;
+ return NULL;
+ }
+ }
+}
+/* }}} */
+
ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
{
*is_temp = 0;
@@ -158,7 +223,7 @@ static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{
}
/* }}} */
-static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */
+static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */
{
switch (property_info->flags & ZEND_ACC_PPP_MASK) {
case ZEND_ACC_PUBLIC:
@@ -177,7 +242,7 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c
}
/* }}} */
-static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
+static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
{
child_class = child_class->parent;
while (child_class) {
@@ -191,40 +256,48 @@ static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_cla
}
/* }}} */
-ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) /* {{{ */
+static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */
{
- zend_property_info *property_info = NULL;
+ zend_property_info *property_info;
zend_property_info *scope_property_info;
zend_bool denied_access = 0;
ulong h;
- if (Z_STRVAL_P(member)[0] == '\0') {
+ if (key && (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) != NULL) {
+ return property_info;
+ }
+
+ if (UNEXPECTED(Z_STRVAL_P(member)[0] == '\0')) {
if (!silent) {
if (Z_STRLEN_P(member) == 0) {
- zend_error(E_ERROR, "Cannot access empty property");
+ zend_error_noreturn(E_ERROR, "Cannot access empty property");
} else {
- zend_error(E_ERROR, "Cannot access property started with '\\0'");
+ zend_error_noreturn(E_ERROR, "Cannot access property started with '\\0'");
}
}
return NULL;
}
- h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
+ property_info = NULL;
+ h = key ? key->hash_value : zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
if (zend_hash_quick_find(&ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) {
- if(property_info->flags & ZEND_ACC_SHADOW) {
+ if (UNEXPECTED((property_info->flags & ZEND_ACC_SHADOW) != 0)) {
/* if it's a shadow - go to access it's private */
property_info = NULL;
} else {
- if (zend_verify_property_access(property_info, ce TSRMLS_CC)) {
- if (property_info->flags & ZEND_ACC_CHANGED
- && !(property_info->flags & ZEND_ACC_PRIVATE)) {
+ if (EXPECTED(zend_verify_property_access(property_info, ce TSRMLS_CC) != 0)) {
+ if (EXPECTED((property_info->flags & ZEND_ACC_CHANGED) != 0)
+ && EXPECTED(!(property_info->flags & ZEND_ACC_PRIVATE))) {
/* We still need to make sure that we're not in a context
* where the right property is a different 'statically linked' private
* continue checking below...
*/
} else {
- if (!silent && (property_info->flags & ZEND_ACC_STATIC)) {
+ if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0) && !silent) {
zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
}
+ if (key) {
+ CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
+ }
return property_info;
}
} else {
@@ -234,20 +307,26 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
}
}
if (EG(scope) != ce
- && is_derived_class(ce, EG(scope))
&& EG(scope)
+ && is_derived_class(ce, EG(scope))
&& zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
&& scope_property_info->flags & ZEND_ACC_PRIVATE) {
+ if (key) {
+ CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, scope_property_info);
+ }
return scope_property_info;
} else if (property_info) {
- if (denied_access) {
+ if (UNEXPECTED(denied_access != 0)) {
/* Information was available, but we were denied access. Error out. */
- if (silent) {
- return NULL;
+ if (!silent) {
+ zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
}
- zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
+ return NULL;
} else {
/* fall through, return property_info... */
+ if (key) {
+ CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
+ }
}
} else {
EG(std_property_info).flags = ZEND_ACC_PUBLIC;
@@ -255,21 +334,28 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
EG(std_property_info).name_length = Z_STRLEN_P(member);
EG(std_property_info).h = h;
EG(std_property_info).ce = ce;
+ EG(std_property_info).offset = -1;
property_info = &EG(std_property_info);
}
return property_info;
}
/* }}} */
-ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, int prop_info_name_len TSRMLS_DC) /* {{{ */
+ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC) /* {{{ */
+{
+ return zend_get_property_info_quick(ce, member, silent, NULL TSRMLS_CC);
+}
+/* }}} */
+
+ZEND_API int zend_check_property_access(zend_object *zobj, const char *prop_info_name, int prop_info_name_len TSRMLS_DC) /* {{{ */
{
zend_property_info *property_info;
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
zval member;
zend_unmangle_property_name(prop_info_name, prop_info_name_len, &class_name, &prop_name);
ZVAL_STRING(&member, prop_name, 0);
- property_info = zend_get_property_info(zobj->ce, &member, 1 TSRMLS_CC);
+ property_info = zend_get_property_info_quick(zobj->ce, &member, 1, NULL TSRMLS_CC);
if (!property_info) {
return FAILURE;
}
@@ -311,7 +397,7 @@ static int zend_get_property_guard(zend_object *zobj, zend_property_info *proper
}
/* }}} */
-zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
+zval *zend_std_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zval *tmp_member = NULL;
@@ -323,13 +409,14 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /*
silent = (type == BP_VAR_IS);
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
- ALLOC_ZVAL(tmp_member);
+ if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
+ ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
member = tmp_member;
+ key = NULL;
}
#if DEBUG_OBJECT_HANDLERS
@@ -337,9 +424,16 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /*
#endif
/* make zend_get_property_info silent if we have getter - we may want to use it */
- property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC);
-
- if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
+ property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
+
+ if (UNEXPECTED(!property_info) ||
+ ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) ?
+ (zobj->properties ?
+ ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
+ (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
+ (UNEXPECTED(!zobj->properties) ||
+ UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
zend_guard *guard = NULL;
if (zobj->ce->__get &&
@@ -367,7 +461,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /*
Z_UNSET_ISREF_P(rv);
Z_SET_REFCOUNT_P(rv, 0);
}
- if (Z_TYPE_P(rv) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(rv) != IS_OBJECT)) {
zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member));
}
}
@@ -395,7 +489,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /*
retval = &EG(uninitialized_zval_ptr);
}
}
- if (tmp_member) {
+ if (UNEXPECTED(tmp_member != NULL)) {
Z_ADDREF_PP(retval);
zval_ptr_dtor(&tmp_member);
Z_DELREF_PP(retval);
@@ -404,7 +498,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /*
}
/* }}} */
-static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */
+ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zval *tmp_member = NULL;
@@ -413,20 +507,28 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
member = tmp_member;
+ key = NULL;
}
- property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__set != NULL) TSRMLS_CC);
+ property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__set != NULL), key TSRMLS_CC);
- if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
+ if (EXPECTED(property_info != NULL) &&
+ ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) ?
+ (zobj->properties ?
+ ((variable_ptr = (zval**)zobj->properties_table[property_info->offset]) != NULL) :
+ (*(variable_ptr = &zobj->properties_table[property_info->offset]) != NULL)) :
+ (EXPECTED(zobj->properties != NULL) &&
+ EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)))) {
/* if we already have this value there, we don't actually need to do anything */
- if (*variable_ptr != value) {
+ if (EXPECTED(*variable_ptr != value)) {
/* if we are assigning reference, we shouldn't move it, but instead assign variable
to the same pointer */
if (PZVAL_IS_REF(*variable_ptr)) {
@@ -467,15 +569,27 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
}
guard->in_set = 0;
zval_ptr_dtor(&object);
- } else if (property_info) {
- zval **foo;
-
+ } else if (EXPECTED(property_info != NULL)) {
/* if we assign referenced variable, we should separate it */
Z_ADDREF_P(value);
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
- zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
+ if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) {
+ if (!zobj->properties) {
+ zobj->properties_table[property_info->offset] = value;
+ } else if (zobj->properties_table[property_info->offset]) {
+ *(zval**)zobj->properties_table[property_info->offset] = value;
+ } else {
+ zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
+ }
+ } else {
+ if (!zobj->properties) {
+ rebuild_object_properties(zobj);
+ }
+ zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), NULL);
+ }
} else if (zobj->ce->__set && guard && guard->in_set == 1) {
if (Z_STRVAL_P(member)[0] == '\0') {
if (Z_STRLEN_P(member) == 0) {
@@ -487,7 +601,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
}
}
- if (tmp_member) {
+ if (UNEXPECTED(tmp_member != NULL)) {
zval_ptr_dtor(&tmp_member);
}
}
@@ -498,7 +612,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /*
zend_class_entry *ce = Z_OBJCE_P(object);
zval *retval;
- if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+ if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) {
if(offset == NULL) {
/* [] construct */
ALLOC_INIT_ZVAL(offset);
@@ -509,9 +623,9 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /*
zval_ptr_dtor(&offset);
- if (!retval) {
- if (!EG(exception)) {
- zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
+ if (UNEXPECTED(!retval)) {
+ if (UNEXPECTED(!EG(exception))) {
+ zend_error_noreturn(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
}
return 0;
}
@@ -521,7 +635,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /*
return retval;
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
return 0;
}
}
@@ -531,7 +645,7 @@ static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSR
{
zend_class_entry *ce = Z_OBJCE_P(object);
- if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+ if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) {
if (!offset) {
ALLOC_INIT_ZVAL(offset);
} else {
@@ -540,7 +654,7 @@ static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSR
zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value);
zval_ptr_dtor(&offset);
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
}
}
/* }}} */
@@ -551,13 +665,13 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
zval *retval;
int result;
- if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+ if (EXPECTED(instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC) != 0)) {
SEPARATE_ARG_IF_REF(offset);
zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset);
- if (retval) {
+ if (EXPECTED(retval != NULL)) {
result = i_zend_is_true(retval);
zval_ptr_dtor(&retval);
- if (check_empty && result && !EG(exception)) {
+ if (check_empty && result && EXPECTED(!EG(exception))) {
zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
if (retval) {
result = i_zend_is_true(retval);
@@ -569,14 +683,14 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
}
zval_ptr_dtor(&offset);
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
return 0;
}
return result;
}
/* }}} */
-static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zval tmp_member;
@@ -585,20 +699,28 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
tmp_member = *member;
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
member = &tmp_member;
+ key = NULL;
}
#if DEBUG_OBJECT_HANDLERS
fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
#endif
- property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__get != NULL) TSRMLS_CC);
+ property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
- if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
+ if (UNEXPECTED(!property_info) ||
+ ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) ?
+ (zobj->properties ?
+ ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
+ (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
+ (UNEXPECTED(!zobj->properties) ||
+ UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
zval *new_zval;
zend_guard *guard;
@@ -610,20 +732,37 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
/* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */
Z_ADDREF_P(new_zval);
- zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
+ if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) {
+ if (!zobj->properties) {
+ zobj->properties_table[property_info->offset] = new_zval;
+ retval = &zobj->properties_table[property_info->offset];
+ } else if (zobj->properties_table[property_info->offset]) {
+ *(zval**)zobj->properties_table[property_info->offset] = new_zval;
+ retval = (zval**)zobj->properties_table[property_info->offset];
+ } else {
+ zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
+ retval = (zval**)zobj->properties_table[property_info->offset];
+ }
+ } else {
+ if (!zobj->properties) {
+ rebuild_object_properties(zobj);
+ }
+ zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
+ }
} else {
/* we do have getter - fail and let it try again with usual get/set */
retval = NULL;
}
}
- if (member == &tmp_member) {
+ if (UNEXPECTED(member == &tmp_member)) {
zval_dtor(member);
}
return retval;
}
/* }}} */
-static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static void zend_std_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zval *tmp_member = NULL;
@@ -631,18 +770,28 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
member = tmp_member;
+ key = NULL;
}
- property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__unset != NULL) TSRMLS_CC);
-
- if (!property_info || zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE) {
+ property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC);
+
+ if (EXPECTED(property_info != NULL) &&
+ EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ !zobj->properties &&
+ property_info->offset >= 0 &&
+ EXPECTED(zobj->properties_table[property_info->offset] != NULL)) {
+ zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
+ zobj->properties_table[property_info->offset] = NULL;
+ } else if (UNEXPECTED(!property_info) ||
+ !zobj->properties ||
+ UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) {
zend_guard *guard = NULL;
if (zobj->ce->__unset &&
@@ -666,9 +815,13 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{
}
}
}
+ } else if (EXPECTED(property_info != NULL) &&
+ EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) {
+ zobj->properties_table[property_info->offset] = NULL;
}
- if (tmp_member) {
+ if (UNEXPECTED(tmp_member != NULL)) {
zval_ptr_dtor(&tmp_member);
}
}
@@ -683,7 +836,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{
zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
zval_ptr_dtor(&offset);
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot use object of type %s as array", ce->name);
}
}
/* }}} */
@@ -699,9 +852,9 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
INIT_PZVAL(method_args_ptr);
array_init_size(method_args_ptr, ZEND_NUM_ARGS());
- if (zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE) {
+ if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE)) {
zval_dtor(method_args_ptr);
- zend_error(E_ERROR, "Cannot get arguments for __call");
+ zend_error_noreturn(E_ERROR, "Cannot get arguments for __call");
RETURN_FALSE;
}
@@ -737,7 +890,7 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
* Returns the function address that should be called, or NULL
* if no such function exists.
*/
-static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */
+static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen, ulong hash_value TSRMLS_DC) /* {{{ */
{
if (!ce) {
return 0;
@@ -759,7 +912,7 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla
ce = ce->parent;
while (ce) {
if (ce == EG(scope)) {
- if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS
+ if (zend_hash_quick_find(&ce->function_table, function_name_strval, function_name_strlen+1, hash_value, (void **) &fbc)==SUCCESS
&& fbc->op_array.fn_flags & ZEND_ACC_PRIVATE
&& fbc->common.scope == EG(scope)) {
return fbc;
@@ -774,7 +927,7 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla
ZEND_API int zend_check_private(zend_function *fbc, zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */
{
- return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen TSRMLS_CC) != NULL;
+ return zend_check_private_int(fbc, ce, function_name_strval, function_name_strlen, zend_hash_func(function_name_strval, function_name_strlen+1) TSRMLS_CC) != NULL;
}
/* }}} */
@@ -807,45 +960,45 @@ ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope)
}
/* }}} */
-static inline zend_class_entry * zend_get_function_root_class(zend_function *fbc) /* {{{ */
-{
- return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope;
-}
-/* }}} */
-
static inline union _zend_function *zend_get_user_call_function(zend_class_entry *ce, const char *method_name, int method_len) /* {{{ */
{
zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
call_user_call->type = ZEND_INTERNAL_FUNCTION;
- call_user_call->module = ce->module;
+ call_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
call_user_call->handler = zend_std_call_user_call;
call_user_call->arg_info = NULL;
call_user_call->num_args = 0;
call_user_call->scope = ce;
call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
call_user_call->function_name = estrndup(method_name, method_len);
- call_user_call->pass_rest_by_reference = 0;
- call_user_call->return_reference = ZEND_RETURN_VALUE;
return (union _zend_function *)call_user_call;
}
/* }}} */
-static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len TSRMLS_DC) /* {{{ */
+static union _zend_function *zend_std_get_method(zval **object_ptr, char *method_name, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */
{
- zend_object *zobj;
zend_function *fbc;
- char *lc_method_name;
zval *object = *object_ptr;
+ zend_object *zobj = Z_OBJ_P(object);
+ ulong hash_value;
+ char *lc_method_name;
ALLOCA_FLAG(use_heap)
- lc_method_name = do_alloca(method_len+1, use_heap);
- /* Create a zend_copy_str_tolower(dest, src, src_length); */
- zend_str_tolower_copy(lc_method_name, method_name, method_len);
+ if (EXPECTED(key != NULL)) {
+ lc_method_name = Z_STRVAL(key->constant);
+ hash_value = key->hash_value;
+ } else {
+ lc_method_name = do_alloca(method_len+1, use_heap);
+ /* Create a zend_copy_str_tolower(dest, src, src_length); */
+ zend_str_tolower_copy(lc_method_name, method_name, method_len);
+ hash_value = zend_hash_func(lc_method_name, method_len+1);
+ }
- zobj = Z_OBJ_P(object);
- if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
- free_alloca(lc_method_name, use_heap);
+ if (UNEXPECTED(zend_hash_quick_find(&zobj->ce->function_table, lc_method_name, method_len+1, hash_value, (void **)&fbc) == FAILURE)) {
+ if (UNEXPECTED(!key)) {
+ free_alloca(lc_method_name, use_heap);
+ }
if (zobj->ce->__call) {
return zend_get_user_call_function(zobj->ce, method_name, method_len);
} else {
@@ -860,14 +1013,14 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
/* Ensure that if we're calling a private function, we're allowed to do so.
* If we're not and __call() handler exists, invoke it, otherwise error out.
*/
- updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
- if (updated_fbc) {
+ updated_fbc = zend_check_private_int(fbc, Z_OBJ_HANDLER_P(object, get_class_entry)(object TSRMLS_CC), lc_method_name, method_len, hash_value TSRMLS_CC);
+ if (EXPECTED(updated_fbc != NULL)) {
fbc = updated_fbc;
} else {
if (zobj->ce->__call) {
fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
} else {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
}
}
} else {
@@ -879,7 +1032,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
zend_function *priv_fbc;
- if (zend_hash_find(&EG(scope)->function_table, lc_method_name, method_len+1, (void **) &priv_fbc)==SUCCESS
+ if (zend_hash_quick_find(&EG(scope)->function_table, lc_method_name, method_len+1, hash_value, (void **) &priv_fbc)==SUCCESS
&& priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
&& priv_fbc->common.scope == EG(scope)) {
fbc = priv_fbc;
@@ -889,17 +1042,19 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
/* Ensure that if we're calling a protected function, we're allowed to do so.
* If we're not and __call() handler exists, invoke it, otherwise error out.
*/
- if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) {
if (zobj->ce->__call) {
fbc = zend_get_user_call_function(zobj->ce, method_name, method_len);
} else {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
}
}
}
}
- free_alloca(lc_method_name, use_heap);
+ if (UNEXPECTED(!key)) {
+ free_alloca(lc_method_name, use_heap);
+ }
return fbc;
}
/* }}} */
@@ -915,9 +1070,9 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
INIT_PZVAL(method_args_ptr);
array_init_size(method_args_ptr, ZEND_NUM_ARGS());
- if (zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE) {
+ if (UNEXPECTED(zend_copy_parameters_array(ZEND_NUM_ARGS(), method_args_ptr TSRMLS_CC) == FAILURE)) {
zval_dtor(method_args_ptr);
- zend_error(E_ERROR, "Cannot get arguments for " ZEND_CALLSTATIC_FUNC_NAME);
+ zend_error_noreturn(E_ERROR, "Cannot get arguments for " ZEND_CALLSTATIC_FUNC_NAME);
RETURN_FALSE;
}
@@ -952,15 +1107,13 @@ static inline union _zend_function *zend_get_user_callstatic_function(zend_class
{
zend_internal_function *callstatic_user_call = emalloc(sizeof(zend_internal_function));
callstatic_user_call->type = ZEND_INTERNAL_FUNCTION;
- callstatic_user_call->module = ce->module;
+ callstatic_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
callstatic_user_call->handler = zend_std_callstatic_user_call;
callstatic_user_call->arg_info = NULL;
callstatic_user_call->num_args = 0;
callstatic_user_call->scope = ce;
callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
callstatic_user_call->function_name = estrndup(method_name, method_len);
- callstatic_user_call->pass_rest_by_reference = 0;
- callstatic_user_call->return_reference = ZEND_RETURN_VALUE;
return (zend_function *)callstatic_user_call;
}
@@ -968,12 +1121,22 @@ static inline union _zend_function *zend_get_user_callstatic_function(zend_class
/* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */
-ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) /* {{{ */
+ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, const char *function_name_strval, int function_name_strlen, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_function *fbc = NULL;
char *lc_class_name, *lc_function_name = NULL;
-
- lc_function_name = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+ ulong hash_value;
+ ALLOCA_FLAG(use_heap)
+
+ if (EXPECTED(key != NULL)) {
+ lc_function_name = Z_STRVAL(key->constant);
+ hash_value = key->hash_value;
+ } else {
+ lc_function_name = do_alloca(function_name_strlen+1, use_heap);
+ /* Create a zend_copy_str_tolower(dest, src, src_length); */
+ zend_str_tolower_copy(lc_function_name, function_name_strval, function_name_strlen);
+ hash_value = zend_hash_func(lc_function_name, function_name_strlen+1);
+ }
if (function_name_strlen == ce->name_length && ce->constructor) {
lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
@@ -985,8 +1148,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
}
efree(lc_class_name);
}
- if (!fbc && zend_hash_find(&ce->function_table, lc_function_name, function_name_strlen+1, (void **) &fbc)==FAILURE) {
- efree(lc_function_name);
+ if (EXPECTED(!fbc) &&
+ UNEXPECTED(zend_hash_quick_find(&ce->function_table, lc_function_name, function_name_strlen+1, hash_value, (void **) &fbc)==FAILURE)) {
+ if (UNEXPECTED(!key)) {
+ free_alloca(lc_function_name, use_heap);
+ }
if (ce->__call &&
EG(This) &&
@@ -999,15 +1165,14 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
return NULL;
}
}
- efree(lc_function_name);
#if MBO_0
/* right now this function is used for non static method lookup too */
/* Is the function static */
- if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
- zend_error(E_ERROR, "Cannot call non static method %s::%s() without object", ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name);
+ if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
+ zend_error_noreturn(E_ERROR, "Cannot call non static method %s::%s() without object", ZEND_FN_SCOPE_NAME(fbc), fbc->common.function_name);
}
-#endif
+#endif
if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
/* No further checks necessary, most common case */
} else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
@@ -1015,76 +1180,88 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC);
- if (updated_fbc) {
+ updated_fbc = zend_check_private_int(fbc, EG(scope), lc_function_name, function_name_strlen, hash_value TSRMLS_CC);
+ if (EXPECTED(updated_fbc != NULL)) {
fbc = updated_fbc;
} else {
if (ce->__callstatic) {
- return zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
+ fbc = zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
+ } else {
+ zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
}
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
}
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(zend_get_function_root_class(fbc), EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) {
if (ce->__callstatic) {
- return zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
+ fbc = zend_get_user_callstatic_function(ce, function_name_strval, function_name_strlen);
+ } else {
+ zend_error_noreturn(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
}
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
}
}
+ if (UNEXPECTED(!key)) {
+ free_alloca(lc_function_name, use_heap);
+ }
+
return fbc;
}
/* }}} */
-ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC) /* {{{ */
+ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */
{
- zval **retval = NULL;
- zend_class_entry *tmp_ce = ce;
zend_property_info *property_info;
- zend_property_info std_property_info;
-
- if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) {
- std_property_info.flags = ZEND_ACC_PUBLIC;
- std_property_info.name = property_name;
- std_property_info.name_length = property_name_len;
- std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1);
- std_property_info.ce = ce;
- property_info = &std_property_info;
- }
+ ulong hash_value;
+
+ if (UNEXPECTED(!key) ||
+ (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) == NULL) {
+ if (EXPECTED(key != NULL)) {
+ hash_value = key->hash_value;
+ } else {
+ hash_value = zend_hash_func(property_name, property_name_len+1);
+ }
+
+ if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) {
+ if (!silent) {
+ zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+ }
+ return NULL;
+ }
#if DEBUG_OBJECT_HANDLERS
- zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
+ zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
#endif
- if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
- if (!silent) {
- zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
+ if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) {
+ if (!silent) {
+ zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
+ }
+ return NULL;
}
- return NULL;
- }
- zend_update_class_constants(tmp_ce TSRMLS_CC);
+ if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
+ if (!silent) {
+ zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+ }
+ return NULL;
+ }
- zend_hash_quick_find(CE_STATIC_MEMBERS(tmp_ce), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
+ zend_update_class_constants(ce TSRMLS_CC);
- if (!retval) {
- if (silent) {
- return NULL;
- } else {
- zend_error(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+ if (EXPECTED(key != NULL)) {
+ CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
}
}
- return retval;
+ return &CE_STATIC_MEMBERS(ce)[property_info->offset];
}
/* }}} */
-ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC) /* {{{ */
+ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, const zend_literal *key TSRMLS_DC) /* {{{ */
{
- zend_error(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
+ zend_error_noreturn(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
return 0;
}
/* }}} */
@@ -1100,11 +1277,11 @@ ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
} else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (constructor->common.scope != EG(scope)) {
+ if (UNEXPECTED(constructor->common.scope != EG(scope))) {
if (EG(scope)) {
- zend_error(E_ERROR, "Call to private %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
+ zend_error_noreturn(E_ERROR, "Call to private %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
} else {
- zend_error(E_ERROR, "Call to private %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
+ zend_error_noreturn(E_ERROR, "Call to private %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
}
}
} else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
@@ -1112,11 +1289,11 @@ ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
* Constructors only have prototype if they are defined by an interface but
* it is the compilers responsibility to take care of the prototype.
*/
- if (!zend_check_protected(zend_get_function_root_class(constructor), EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), EG(scope)))) {
if (EG(scope)) {
- zend_error(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
+ zend_error_noreturn(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope)->name);
} else {
- zend_error(E_ERROR, "Call to protected %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
+ zend_error_noreturn(E_ERROR, "Call to protected %s::%s() from invalid context", constructor->common.scope->name, constructor->common.function_name);
}
}
}
@@ -1138,36 +1315,77 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
if (zobj1->ce != zobj2->ce) {
return 1; /* different classes */
}
- return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
+ if (!zobj1->properties && !zobj2->properties) {
+ int i;
+ for (i = 0; i < zobj1->ce->default_properties_count; i++) {
+ if (zobj1->properties_table[i]) {
+ if (zobj2->properties_table[i]) {
+ zval result;
+
+ if (compare_function(&result, zobj1->properties_table[i], zobj2->properties_table[i] TSRMLS_CC)==FAILURE) {
+ return 1;
+ }
+ if (Z_LVAL(result) != 0) {
+ return Z_LVAL(result);
+ }
+ } else {
+ return 1;
+ }
+ } else {
+ if (zobj2->properties_table[i]) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+ return 0;
+ } else {
+ if (!zobj1->properties) {
+ rebuild_object_properties(zobj1);
+ }
+ if (!zobj2->properties) {
+ rebuild_object_properties(zobj2);
+ }
+ return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
+ }
}
/* }}} */
-static int zend_std_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */
+static int zend_std_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
int result;
- zval **value;
+ zval **value = NULL;
zval *tmp_member = NULL;
zend_property_info *property_info;
zobj = Z_OBJ_P(object);
- if (Z_TYPE_P(member) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(member) != IS_STRING)) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
convert_to_string(tmp_member);
member = tmp_member;
+ key = NULL;
}
#if DEBUG_OBJECT_HANDLERS
fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
#endif
- property_info = zend_get_property_info(zobj->ce, member, 1 TSRMLS_CC);
+ property_info = zend_get_property_info_quick(zobj->ce, member, 1, key TSRMLS_CC);
- if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
+ if (UNEXPECTED(!property_info) ||
+ ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+ property_info->offset >= 0) ?
+ (zobj->properties ?
+ ((value = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
+ (*(value = &zobj->properties_table[property_info->offset]) == NULL)) :
+ (UNEXPECTED(!zobj->properties) ||
+ UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE)))) {
zend_guard *guard;
result = 0;
@@ -1188,7 +1406,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
result = zend_is_true(rv);
zval_ptr_dtor(&rv);
if (has_set_exists && result) {
- if (!EG(exception) && zobj->ce->__get && !guard->in_get) {
+ if (EXPECTED(!EG(exception)) && zobj->ce->__get && !guard->in_get) {
guard->in_get = 1;
rv = zend_std_call_getter(object, member TSRMLS_CC);
guard->in_get = 0;
@@ -1221,7 +1439,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
}
}
- if (tmp_member) {
+ if (UNEXPECTED(tmp_member != NULL)) {
zval_ptr_dtor(&tmp_member);
}
return result;
@@ -1237,7 +1455,7 @@ zend_class_entry *zend_std_object_get_class(const zval *object TSRMLS_DC) /* {{{
}
/* }}} */
-int zend_std_object_get_class_name(const zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) /* {{{ */
+int zend_std_object_get_class_name(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) /* {{{ */
{
zend_object *zobj;
zend_class_entry *ce;
@@ -1268,15 +1486,15 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
ce = Z_OBJCE_P(readobj);
if (ce->__tostring &&
(zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) {
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
if (retval) {
zval_ptr_dtor(&retval);
}
EG(exception) = NULL;
- zend_error(E_ERROR, "Method %s::__toString() must not throw an exception", ce->name);
+ zend_error_noreturn(E_ERROR, "Method %s::__toString() must not throw an exception", ce->name);
return FAILURE;
}
- if (Z_TYPE_P(retval) == IS_STRING) {
+ if (EXPECTED(Z_TYPE_P(retval) == IS_STRING)) {
INIT_PZVAL(writeobj);
if (readobj == writeobj) {
zval_dtor(readobj);
@@ -1383,6 +1601,7 @@ ZEND_API zend_object_handlers std_object_handlers = {
NULL, /* count_elements */
NULL, /* get_debug_info */
zend_std_get_closure, /* get_closure */
+ zend_std_get_gc, /* get_gc */
};
/*
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index 0ee6fc0bd2..d0d7a7b847 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -24,13 +24,14 @@
union _zend_function;
struct _zend_property_info;
+struct _zend_literal;
/* The following rule applies to read_property() and read_dimension() implementations:
If you return a zval which is not otherwise referenced by the extension or the engine's
symbol table, its reference count should be 0.
*/
/* Used to fetch property from the object, read-only */
-typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type TSRMLS_DC);
+typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type, const struct _zend_literal *key TSRMLS_DC);
/* Used to fetch dimension from the object, read-only */
typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int type TSRMLS_DC);
@@ -42,14 +43,14 @@ typedef zval *(*zend_object_read_dimension_t)(zval *object, zval *offset, int ty
any changes. You should NOT modify the reference count of the value passed to you.
*/
/* Used to set property of the object */
-typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value TSRMLS_DC);
+typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC);
/* Used to set dimension of the object */
typedef void (*zend_object_write_dimension_t)(zval *object, zval *offset, zval *value TSRMLS_DC);
/* Used to create pointer to the property of the object, for future direct r/w access */
-typedef zval **(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member TSRMLS_DC);
+typedef zval **(*zend_object_get_property_ptr_ptr_t)(zval *object, zval *member, const struct _zend_literal *key TSRMLS_DC);
/* Used to set object value. Can be used to override assignments and scalar
write ops (like ++, +=) on the object */
@@ -66,13 +67,13 @@ typedef zval* (*zend_object_get_t)(zval *object TSRMLS_DC);
* 1 (set) whether property exists and is true
* 2 (exists) whether property exists
*/
-typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists TSRMLS_DC);
+typedef int (*zend_object_has_property_t)(zval *object, zval *member, int has_set_exists, const struct _zend_literal *key TSRMLS_DC);
/* Used to check if a dimension of the object exists */
typedef int (*zend_object_has_dimension_t)(zval *object, zval *member, int check_empty TSRMLS_DC);
/* Used to remove a property of the object */
-typedef void (*zend_object_unset_property_t)(zval *object, zval *member TSRMLS_DC);
+typedef void (*zend_object_unset_property_t)(zval *object, zval *member, const struct _zend_literal *key TSRMLS_DC);
/* Used to remove a dimension of the object */
typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
@@ -86,8 +87,8 @@ typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp TS
/* args on stack! */
/* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this.
*/
-typedef int (*zend_object_call_method_t)(char *method, INTERNAL_FUNCTION_PARAMETERS);
-typedef union _zend_function *(*zend_object_get_method_t)(zval **object_ptr, char *method, int method_len TSRMLS_DC);
+typedef int (*zend_object_call_method_t)(const char *method, INTERNAL_FUNCTION_PARAMETERS);
+typedef union _zend_function *(*zend_object_get_method_t)(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC);
typedef union _zend_function *(*zend_object_get_constructor_t)(zval *object TSRMLS_DC);
/* Object maintenance/destruction */
@@ -97,7 +98,7 @@ typedef void (*zend_object_delete_obj_t)(zval *object TSRMLS_DC);
typedef zend_object_value (*zend_object_clone_obj_t)(zval *object TSRMLS_DC);
typedef zend_class_entry *(*zend_object_get_class_entry_t)(const zval *object TSRMLS_DC);
-typedef int (*zend_object_get_class_name_t)(const zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC);
+typedef int (*zend_object_get_class_name_t)(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC);
typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC);
/* Cast an object to some other type
@@ -110,6 +111,8 @@ typedef int (*zend_object_count_elements_t)(zval *object, long *count TSRMLS_DC)
typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
+typedef HashTable *(*zend_object_get_gc_t)(zval *object, zval ***table, int *n TSRMLS_DC);
+
struct _zend_object_handlers {
/* general object functions */
zend_object_add_ref_t add_ref;
@@ -138,19 +141,25 @@ struct _zend_object_handlers {
zend_object_count_elements_t count_elements;
zend_object_get_debug_info_t get_debug_info;
zend_object_get_closure_t get_closure;
+ zend_object_get_gc_t get_gc;
};
extern ZEND_API zend_object_handlers std_object_handlers;
+#define zend_get_function_root_class(fbc) \
+ ((fbc)->common.prototype ? (fbc)->common.prototype->common.scope : (fbc)->common.scope)
+
BEGIN_EXTERN_C()
-ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC);
-ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent TSRMLS_DC);
-ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC);
+ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry *ce, const char *function_name_strval, int function_name_strlen, const struct _zend_literal *key TSRMLS_DC);
+ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, const struct _zend_literal *key TSRMLS_DC);
+ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, const struct _zend_literal *key TSRMLS_DC);
ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC);
ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC);
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC);
ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
+ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC);
+ZEND_API void rebuild_object_properties(zend_object *zobj);
#define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL))
@@ -160,7 +169,7 @@ ZEND_API int zend_check_private(union _zend_function *fbc, zend_class_entry *ce,
ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope);
-ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name, int prop_info_name_len TSRMLS_DC);
+ZEND_API int zend_check_property_access(zend_object *zobj, const char *prop_info_name, int prop_info_name_len TSRMLS_DC);
ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS);
END_EXTERN_C()
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index fbee312d38..f7470fa578 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -28,10 +28,9 @@
ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC)
{
- ALLOC_HASHTABLE(object->properties);
- zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-
- object->ce = ce;
+ object->ce = ce;
+ object->properties = NULL;
+ object->properties_table = NULL;
object->guards = NULL;
}
@@ -39,11 +38,23 @@ ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
{
if (object->guards) {
zend_hash_destroy(object->guards);
- FREE_HASHTABLE(object->guards);
+ FREE_HASHTABLE(object->guards);
}
if (object->properties) {
zend_hash_destroy(object->properties);
FREE_HASHTABLE(object->properties);
+ if (object->properties_table) {
+ efree(object->properties_table);
+ }
+ } else if (object->properties_table) {
+ int i;
+
+ for (i = 0; i < object->ce->default_properties_count; i++) {
+ if (object->properties_table[i]) {
+ zval_ptr_dtor(&object->properties_table[i]);
+ }
+ }
+ efree(object->properties_table);
}
}
@@ -63,23 +74,23 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
if (object->ce != EG(scope)) {
zend_class_entry *ce = object->ce;
- zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
- "Call to private %s::__destruct() from context '%s'%s",
- ce->name,
- EG(scope) ? EG(scope)->name : "",
+ zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
+ "Call to private %s::__destruct() from context '%s'%s",
+ ce->name,
+ EG(scope) ? EG(scope)->name : "",
EG(in_execution) ? "" : " during shutdown ignored");
return;
}
} else {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(destructor->common.scope, EG(scope))) {
+ if (!zend_check_protected(zend_get_function_root_class(destructor), EG(scope))) {
zend_class_entry *ce = object->ce;
- zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
- "Call to protected %s::__destruct() from context '%s'%s",
- ce->name,
- EG(scope) ? EG(scope)->name : "",
+ zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
+ "Call to protected %s::__destruct() from context '%s'%s",
+ ce->name,
+ EG(scope) ? EG(scope)->name : "",
EG(in_execution) ? "" : " during shutdown ignored");
return;
}
@@ -128,14 +139,16 @@ ZEND_API void zend_objects_free_object_storage(zend_object *object TSRMLS_DC)
}
ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type TSRMLS_DC)
-{
+{
zend_object_value retval;
*object = emalloc(sizeof(zend_object));
(*object)->ce = class_type;
+ (*object)->properties = NULL;
+ (*object)->properties_table = NULL;
+ (*object)->guards = NULL;
retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
retval.handlers = &std_object_handlers;
- (*object)->guards = NULL;
return retval;
}
@@ -146,7 +159,47 @@ ZEND_API zend_object *zend_objects_get_address(const zval *zobject TSRMLS_DC)
ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC)
{
- zend_hash_copy(new_object->properties, old_object->properties, zval_copy_property_ctor(old_object->ce), (void *) NULL /* Not used anymore */, sizeof(zval *));
+ int i;
+
+ if (old_object->properties_table) {
+ if (!new_object->properties_table) {
+ new_object->properties_table = emalloc(sizeof(zval*) * old_object->ce->default_properties_count);
+ memset(new_object->properties_table, 0, sizeof(zval*) * old_object->ce->default_properties_count);
+ }
+ for (i = 0; i < old_object->ce->default_properties_count; i++) {
+ if (!new_object->properties) {
+ if (new_object->properties_table[i]) {
+ zval_ptr_dtor(&new_object->properties_table[i]);
+ }
+ }
+ if (!old_object->properties) {
+ new_object->properties_table[i] = old_object->properties_table[i];
+ if (new_object->properties_table[i]) {
+ Z_ADDREF_P(new_object->properties_table[i]);
+ }
+ }
+ }
+ }
+ if (old_object->properties) {
+ if (!new_object->properties) {
+ ALLOC_HASHTABLE(new_object->properties);
+ zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+ zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
+ if (old_object->properties_table) {
+ HashPosition pos;
+ zend_property_info *prop_info;
+ for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos);
+ zend_hash_get_current_data_ex(&old_object->ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) {
+ if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
+ if (zend_hash_quick_find(new_object->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&new_object->properties_table[prop_info->offset]) == FAILURE) {
+ new_object->properties_table[prop_info->offset] = NULL;
+ }
+ }
+ }
+ }
+ }
if (old_object->ce->clone) {
zval *new_obj;
@@ -169,14 +222,11 @@ ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
zend_object *new_object;
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
- /* assume that create isn't overwritten, so when clone depends on the
+ /* assume that create isn't overwritten, so when clone depends on the
* overwritten one then it must itself be overwritten */
old_object = zend_objects_get_address(zobject TSRMLS_CC);
new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
- ALLOC_HASHTABLE(new_object->properties);
- zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-
zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
return new_obj_val;
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index 7f68fdc50e..91b7676574 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -314,6 +314,10 @@ typedef struct _zend_proxy_object {
static zend_object_handlers zend_object_proxy_handlers;
+ZEND_API void zend_objects_proxy_destroy(zend_object *object, zend_object_handle handle TSRMLS_DC)
+{
+}
+
ZEND_API void zend_objects_proxy_free_storage(zend_proxy_object *object TSRMLS_DC)
{
zval_ptr_dtor(&object->object);
@@ -336,13 +340,14 @@ ZEND_API zval *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC)
zval *retval;
pobj->object = object;
- pobj->property = member;
- zval_add_ref(&pobj->property);
zval_add_ref(&pobj->object);
+ ALLOC_ZVAL(pobj->property);
+ INIT_PZVAL_COPY(pobj->property, member);
+ zval_copy_ctor(pobj->property);
MAKE_STD_ZVAL(retval);
Z_TYPE_P(retval) = IS_OBJECT;
- Z_OBJ_HANDLE_P(retval) = zend_objects_store_put(pobj, NULL, (zend_objects_free_object_storage_t) zend_objects_proxy_free_storage, (zend_objects_store_clone_t) zend_objects_proxy_clone TSRMLS_CC);
+ Z_OBJ_HANDLE_P(retval) = zend_objects_store_put(pobj, (zend_objects_store_dtor_t)zend_objects_proxy_destroy, (zend_objects_free_object_storage_t) zend_objects_proxy_free_storage, (zend_objects_store_clone_t) zend_objects_proxy_clone TSRMLS_CC);
Z_OBJ_HT_P(retval) = &zend_object_proxy_handlers;
return retval;
@@ -353,7 +358,7 @@ ZEND_API void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC)
zend_proxy_object *probj = zend_object_store_get_object(*property TSRMLS_CC);
if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->write_property) {
- Z_OBJ_HT_P(probj->object)->write_property(probj->object, probj->property, value TSRMLS_CC);
+ Z_OBJ_HT_P(probj->object)->write_property(probj->object, probj->property, value, 0 TSRMLS_CC);
} else {
zend_error(E_WARNING, "Cannot write property of object - no write handler defined");
}
@@ -364,7 +369,7 @@ ZEND_API zval* zend_object_proxy_get(zval *property TSRMLS_DC)
zend_proxy_object *probj = zend_object_store_get_object(property TSRMLS_CC);
if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->read_property) {
- return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property, BP_VAR_R TSRMLS_CC);
+ return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property, BP_VAR_R, 0 TSRMLS_CC);
} else {
zend_error(E_WARNING, "Cannot read property of object - no read handler defined");
}
diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h
index b0b17e5675..12f1c06842 100644
--- a/Zend/zend_objects_API.h
+++ b/Zend/zend_objects_API.h
@@ -68,7 +68,7 @@ ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC);
ZEND_API void zend_objects_store_del_ref(zval *object TSRMLS_DC);
ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC);
ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC);
-static inline void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) {
+static zend_always_inline void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) {
zend_objects_store_del_ref_by_handle_ex(handle, NULL TSRMLS_CC);
}
ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC);
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 982bfcbf04..4c6a784a88 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -43,31 +43,28 @@ static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend
}
}
-static void op_array_alloc_ops(zend_op_array *op_array)
+static void op_array_alloc_ops(zend_op_array *op_array, zend_uint size)
{
- op_array->opcodes = erealloc(op_array->opcodes, (op_array->size)*sizeof(zend_op));
+ op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
}
void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size TSRMLS_DC)
{
op_array->type = type;
- op_array->backpatch_count = 0;
if (CG(interactive)) {
/* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants
* will become invalid
*/
- initial_ops_size = 8192;
+ initial_ops_size = INITIAL_INTERACTIVE_OP_ARRAY_SIZE;
}
op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint));
*op_array->refcount = 1;
- op_array->size = initial_ops_size;
op_array->last = 0;
op_array->opcodes = NULL;
- op_array_alloc_ops(op_array);
+ op_array_alloc_ops(op_array, initial_ops_size);
- op_array->size_var = 0; /* FIXME:??? */
op_array->last_var = 0;
op_array->vars = NULL;
@@ -87,22 +84,22 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->brk_cont_array = NULL;
op_array->try_catch_array = NULL;
op_array->last_brk_cont = 0;
- op_array->current_brk_cont = -1;
op_array->static_variables = NULL;
op_array->last_try_catch = 0;
- op_array->return_reference = 0;
- op_array->done_pass_two = 0;
-
op_array->this_var = -1;
- op_array->start_op = NULL;
-
op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0;
op_array->early_binding = -1;
+ op_array->last_literal = 0;
+ op_array->literals = NULL;
+
+ op_array->run_time_cache = NULL;
+ op_array->last_cache_slot = 0;
+
memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
@@ -152,26 +149,130 @@ ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC)
return 0;
}
-ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
+static inline void cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC)
{
- if ((*pce)->type == ZEND_USER_CLASS) {
- /* Clean all parts that can contain run-time data */
- /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
- not contain objects and thus are not probelmatic */
- zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
- if ((*pce)->static_members) {
- zend_hash_clean((*pce)->static_members);
- (*pce)->static_members = NULL;
+ /* Clean all parts that can contain run-time data */
+ /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
+ not contain objects and thus are not probelmatic */
+ if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
+ zend_hash_apply(&ce->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
+ }
+ if (ce->static_members_table) {
+ int i;
+
+ for (i = 0; i < ce->default_static_members_count; i++) {
+ if (ce->static_members_table[i]) {
+ zval_ptr_dtor(&ce->static_members_table[i]);
+ ce->static_members_table[i] = NULL;
+ }
}
- } else if (CE_STATIC_MEMBERS(*pce)) {
- zend_hash_destroy(CE_STATIC_MEMBERS(*pce));
- FREE_HASHTABLE(CE_STATIC_MEMBERS(*pce));
+ ce->static_members_table = NULL;
+ }
+}
+
+static inline void cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC)
+{
+ if (CE_STATIC_MEMBERS(ce)) {
+ int i;
+
+ for (i = 0; i < ce->default_static_members_count; i++) {
+ zval_ptr_dtor(&CE_STATIC_MEMBERS(ce)[i]);
+ }
+ efree(CE_STATIC_MEMBERS(ce));
#ifdef ZTS
- CG(static_members)[(zend_intptr_t)((*pce)->static_members)] = NULL;
+ CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL;
#else
- (*pce)->static_members = NULL;
+ ce->static_members_table = NULL;
#endif
}
+}
+
+ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC)
+{
+ cleanup_internal_class_data(ce TSRMLS_CC);
+}
+
+ZEND_API int zend_cleanup_user_class_data(zend_class_entry **pce TSRMLS_DC)
+{
+ if ((*pce)->type == ZEND_USER_CLASS) {
+ cleanup_user_class_data(*pce TSRMLS_CC);
+ return ZEND_HASH_APPLY_KEEP;
+ } else {
+ return ZEND_HASH_APPLY_STOP;
+ }
+}
+
+ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
+{
+ if ((*pce)->type == ZEND_USER_CLASS) {
+ cleanup_user_class_data(*pce TSRMLS_CC);
+ } else {
+ cleanup_internal_class_data(*pce TSRMLS_CC);
+ }
+ return 0;
+}
+
+void _destroy_zend_class_traits_info(zend_class_entry *ce)
+{
+ if (ce->num_traits > 0 && ce->traits) {
+ size_t i;
+ for (i = 0; i < ce->num_traits; i++) {
+ if (ce->traits[i]) {
+ destroy_zend_class(&ce->traits[i]);
+ }
+ }
+ efree(ce->traits);
+ }
+
+ if (ce->trait_aliases) {
+ size_t i = 0;
+ while (ce->trait_aliases[i]) {
+ if (ce->trait_aliases[i]->trait_method) {
+ if (ce->trait_aliases[i]->trait_method->method_name) {
+ efree((char*)ce->trait_aliases[i]->trait_method->method_name);
+ }
+ if (ce->trait_aliases[i]->trait_method->class_name) {
+ efree((char*)ce->trait_aliases[i]->trait_method->class_name);
+ }
+ efree(ce->trait_aliases[i]->trait_method);
+ }
+
+ if (ce->trait_aliases[i]->alias) {
+ efree((char*)ce->trait_aliases[i]->alias);
+ }
+
+ efree(ce->trait_aliases[i]);
+ i++;
+ }
+
+ efree(ce->trait_aliases);
+ }
+
+ if (ce->trait_precedences) {
+ size_t i = 0;
+
+ while (ce->trait_precedences[i]) {
+ efree((char*)ce->trait_precedences[i]->trait_method->method_name);
+ efree((char*)ce->trait_precedences[i]->trait_method->class_name);
+ efree(ce->trait_precedences[i]->trait_method);
+
+ if (ce->trait_precedences[i]->exclude_from_classes) {
+ efree(ce->trait_precedences[i]->exclude_from_classes);
+ }
+
+ efree(ce->trait_precedences[i]);
+ i++;
+ }
+ efree(ce->trait_precedences);
+ }
+}
+
+static int zend_clear_trait_method_name(zend_op_array *op_array TSRMLS_DC)
+{
+ if (op_array->function_name && (op_array->fn_flags & ZEND_ACC_ALIAS) == 0) {
+ efree(op_array->function_name);
+ op_array->function_name = NULL;
+ }
return 0;
}
@@ -184,33 +285,71 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
}
switch (ce->type) {
case ZEND_USER_CLASS:
- zend_hash_destroy(&ce->default_properties);
+ if (ce->default_properties_table) {
+ int i;
+
+ for (i = 0; i < ce->default_properties_count; i++) {
+ if (ce->default_properties_table[i]) {
+ zval_ptr_dtor(&ce->default_properties_table[i]);
+ }
+ }
+ efree(ce->default_properties_table);
+ }
+ if (ce->default_static_members_table) {
+ int i;
+
+ for (i = 0; i < ce->default_static_members_count; i++) {
+ if (ce->default_static_members_table[i]) {
+ zval_ptr_dtor(&ce->default_static_members_table[i]);
+ }
+ }
+ efree(ce->default_static_members_table);
+ }
zend_hash_destroy(&ce->properties_info);
- zend_hash_destroy(&ce->default_static_members);
- efree(ce->name);
+ str_efree(ce->name);
+ if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ TSRMLS_FETCH();
+ zend_hash_apply(&ce->function_table, (apply_func_t)zend_clear_trait_method_name TSRMLS_CC);
+ }
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->constants_table);
if (ce->num_interfaces > 0 && ce->interfaces) {
efree(ce->interfaces);
}
- if (ce->doc_comment) {
- efree(ce->doc_comment);
+ if (ce->info.user.doc_comment) {
+ efree((char*)ce->info.user.doc_comment);
}
+
+ _destroy_zend_class_traits_info(ce);
+
efree(ce);
break;
case ZEND_INTERNAL_CLASS:
- zend_hash_destroy(&ce->default_properties);
+ if (ce->default_properties_table) {
+ int i;
+
+ for (i = 0; i < ce->default_properties_count; i++) {
+ if (ce->default_properties_table[i]) {
+ zval_internal_ptr_dtor(&ce->default_properties_table[i]);
+ }
+ }
+ free(ce->default_properties_table);
+ }
+ if (ce->default_static_members_table) {
+ int i;
+
+ for (i = 0; i < ce->default_static_members_count; i++) {
+ zval_internal_ptr_dtor(&ce->default_static_members_table[i]);
+ }
+ free(ce->default_static_members_table);
+ }
zend_hash_destroy(&ce->properties_info);
- zend_hash_destroy(&ce->default_static_members);
- free(ce->name);
+ str_free(ce->name);
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->constants_table);
if (ce->num_interfaces > 0) {
free(ce->interfaces);
}
- if (ce->doc_comment) {
- free(ce->doc_comment);
- }
free(ce);
break;
}
@@ -223,8 +362,8 @@ void zend_class_add_ref(zend_class_entry **ce)
ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
{
- zend_op *opline = op_array->opcodes;
- zend_op *end = op_array->opcodes+op_array->last;
+ zend_literal *literal = op_array->literals;
+ zend_literal *end;
zend_uint i;
if (op_array->static_variables) {
@@ -232,6 +371,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
FREE_HASHTABLE(op_array->static_variables);
}
+ if (op_array->run_time_cache) {
+ efree(op_array->run_time_cache);
+ }
+
if (--(*op_array->refcount)>0) {
return;
}
@@ -242,33 +385,26 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
i = op_array->last_var;
while (i > 0) {
i--;
- efree(op_array->vars[i].name);
+ str_efree(op_array->vars[i].name);
}
efree(op_array->vars);
}
- while (opline<end) {
- if (opline->op1.op_type==IS_CONST) {
-#if DEBUG_ZEND>2
- printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op1.u.constant);
-#endif
- zval_dtor(&opline->op1.u.constant);
+ if (literal) {
+ end = literal + op_array->last_literal;
+ while (literal < end) {
+ zval_dtor(&literal->constant);
+ literal++;
}
- if (opline->op2.op_type==IS_CONST) {
-#if DEBUG_ZEND>2
- printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op2.u.constant);
-#endif
- zval_dtor(&opline->op2.u.constant);
- }
- opline++;
+ efree(op_array->literals);
}
efree(op_array->opcodes);
- if (op_array->function_name) {
- efree(op_array->function_name);
+ if (op_array->function_name && (op_array->fn_flags & ZEND_ACC_ALIAS) == 0) {
+ efree((char*)op_array->function_name);
}
if (op_array->doc_comment) {
- efree(op_array->doc_comment);
+ efree((char*)op_array->doc_comment);
}
if (op_array->brk_cont_array) {
efree(op_array->brk_cont_array);
@@ -276,14 +412,14 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
if (op_array->try_catch_array) {
efree(op_array->try_catch_array);
}
- if (op_array->done_pass_two) {
+ if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC);
}
if (op_array->arg_info) {
for (i=0; i<op_array->num_args; i++) {
- efree((char*)op_array->arg_info[i].name);
+ str_efree(op_array->arg_info[i].name);
if (op_array->arg_info[i].class_name) {
- efree((char*)op_array->arg_info[i].class_name);
+ str_efree(op_array->arg_info[i].class_name);
}
}
efree(op_array->arg_info);
@@ -302,15 +438,15 @@ zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC)
zend_uint next_op_num = op_array->last++;
zend_op *next_op;
- if (next_op_num >= op_array->size) {
+ if (next_op_num >= CG(context).opcodes_size) {
if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) {
/* we messed up */
zend_printf("Ran out of opcode space!\n"
"You should probably consider writing this huge script into a file!\n");
zend_bailout();
}
- op_array->size *= 4;
- op_array_alloc_ops(op_array);
+ CG(context).opcodes_size *= 4;
+ op_array_alloc_ops(op_array, CG(context).opcodes_size);
}
next_op = &(op_array->opcodes[next_op_num]);
@@ -376,44 +512,51 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC);
}
- if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && op_array->size != op_array->last) {
+ if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) {
+ op_array->vars = (zend_compiled_variable *) erealloc(op_array->vars, sizeof(zend_compiled_variable)*op_array->last_var);
+ CG(context).vars_size = op_array->last_var;
+ }
+ if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) {
op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
- op_array->size = op_array->last;
+ CG(context).opcodes_size = op_array->last;
+ }
+ if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) {
+ op_array->literals = (zend_literal*)erealloc(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
+ CG(context).literals_size = op_array->last_literal;
}
opline = op_array->opcodes;
end = opline + op_array->last;
while (opline < end) {
- if (opline->op1.op_type == IS_CONST) {
- Z_SET_ISREF(opline->op1.u.constant);
- Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */
+ if (opline->op1_type == IS_CONST) {
+ opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
}
- if (opline->op2.op_type == IS_CONST) {
- Z_SET_ISREF(opline->op2.u.constant);
- Z_SET_REFCOUNT(opline->op2.u.constant, 2);
+ if (opline->op2_type == IS_CONST) {
+ opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
}
switch (opline->opcode) {
case ZEND_GOTO:
- if (Z_TYPE(opline->op2.u.constant) != IS_LONG) {
+ if (Z_TYPE_P(opline->op2.zv) != IS_LONG) {
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
}
/* break omitted intentionally */
case ZEND_JMP:
- opline->op1.u.jmp_addr = &op_array->opcodes[opline->op1.u.opline_num];
+ opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
- opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num];
+ case ZEND_JMP_SET_VAR:
+ opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
break;
}
ZEND_VM_SET_OPCODE_HANDLER(opline);
opline++;
}
-
- op_array->done_pass_two = 1;
+
+ op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return 0;
}
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index aea63faedd..9b01e5fbcb 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -27,13 +27,10 @@
#include "zend_globals.h"
#include "zend_list.h"
#include "zend_API.h"
-#include "zend_multiply.h"
#include "zend_strtod.h"
#include "zend_exceptions.h"
#include "zend_closures.h"
-#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
-
#if ZEND_USE_TOLOWER_L
#include <locale.h>
static _locale_t current_locale = NULL;
@@ -1199,11 +1196,18 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
/* must support result==op1 */
ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
- Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1;
- Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1);
- Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2);
- Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
- Z_TYPE_P(result) = IS_STRING;
+ int length = Z_STRLEN_P(op1) + 1;
+ char *buf;
+
+ if (IS_INTERNED(Z_STRVAL_P(op1))) {
+ buf = (char *) emalloc(length + 1);
+ memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
+ } else {
+ buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1);
+ }
+ buf[length - 1] = (char) Z_LVAL_P(op2);
+ buf[length] = 0;
+ ZVAL_STRINGL(result, buf, length, 0);
return SUCCESS;
}
/* }}} */
@@ -1212,12 +1216,17 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
{
int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
+ char *buf;
- Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1);
- memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
- Z_STRVAL_P(result)[length] = 0;
- Z_STRLEN_P(result) = length;
- Z_TYPE_P(result) = IS_STRING;
+ if (IS_INTERNED(Z_STRVAL_P(op1))) {
+ buf = (char *) emalloc(length+1);
+ memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
+ } else {
+ buf = (char *) erealloc(Z_STRVAL_P(op1), length+1);
+ }
+ memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
+ buf[length] = 0;
+ ZVAL_STRINGL(result, buf, length, 0);
return SUCCESS;
}
/* }}} */
@@ -1246,7 +1255,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
if (use_copy2) {
op2 = &op2_copy;
}
- if (result==op1) { /* special case, perform operations on result */
+ if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) { /* special case, perform operations on result */
uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
@@ -1261,12 +1270,13 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
Z_STRVAL_P(result)[res_len]=0;
Z_STRLEN_P(result) = res_len;
} else {
- Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
- Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1);
- memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1));
- memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
- Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
- Z_TYPE_P(result) = IS_STRING;
+ int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
+ char *buf = (char *) emalloc(length + 1);
+
+ memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
+ memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
+ buf[length] = 0;
+ ZVAL_STRINGL(result, buf, length, 0);
}
if (use_copy1) {
zval_dtor(op1);
@@ -1278,7 +1288,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
}
/* }}} */
-ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */
{
zval op1_copy, op2_copy;
int use_copy1 = 0, use_copy2 = 0;
@@ -1297,7 +1307,11 @@ ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_D
op2 = &op2_copy;
}
- ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
+ if (case_insensitive) {
+ ZVAL_LONG(result, zend_binary_zval_strcasecmp(op1, op2));
+ } else {
+ ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
+ }
if (use_copy1) {
zval_dtor(op1);
@@ -1309,6 +1323,18 @@ ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_D
}
/* }}} */
+ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC);
+}
+/* }}} */
+
+ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC);
+}
+/* }}} */
+
#if HAVE_STRCOLL
ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
@@ -1397,8 +1423,12 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {
return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
- Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
+ if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
+ ZVAL_LONG(result, 0);
+ } else {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
+ ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
+ }
return SUCCESS;
case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
@@ -1694,6 +1724,12 @@ static void increment_string(zval *str) /* {{{ */
return;
}
+ if (IS_INTERNED(s)) {
+ s = (char*) emalloc(Z_STRLEN_P(str) + 1);
+ memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1);
+ Z_STRVAL_P(str) = s;
+ }
+
while (pos >= 0) {
ch = s[pos];
if (ch >= 'a' && ch <= 'z') {
@@ -1779,7 +1815,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */
switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
case IS_LONG:
- efree(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
if (lval == LONG_MAX) {
/* switch to double */
double d = (double)lval;
@@ -1789,7 +1825,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */
}
break;
case IS_DOUBLE:
- efree(Z_STRVAL_P(op1));
+ str_efree(Z_STRVAL_P(op1));
ZVAL_DOUBLE(op1, dval+1);
break;
default:
@@ -1905,6 +1941,9 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint
{
int retval;
+ if (s1 == s2) {
+ return 0;
+ }
retval = memcmp(s1, s2, MIN(len1, len2));
if (!retval) {
return (len1 - len2);
@@ -1918,6 +1957,9 @@ ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint
{
int retval;
+ if (s1 == s2) {
+ return 0;
+ }
retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
if (!retval) {
return (MIN(length, len1) - MIN(length, len2));
@@ -1932,8 +1974,11 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, u
int len;
int c1, c2;
- len = MIN(len1, len2);
+ if (s1 == s2) {
+ return 0;
+ }
+ len = MIN(len1, len2);
while (len--) {
c1 = zend_tolower((int)*(unsigned char *)s1++);
c2 = zend_tolower((int)*(unsigned char *)s2++);
@@ -1951,8 +1996,10 @@ ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2,
int len;
int c1, c2;
+ if (s1 == s2) {
+ return 0;
+ }
len = MIN(length, MIN(len1, len2));
-
while (len--) {
c1 = zend_tolower((int)*(unsigned char *)s1++);
c2 = zend_tolower((int)*(unsigned char *)s2++);
@@ -1992,15 +2039,36 @@ ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ *
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
{
int ret1, ret2;
+ int oflow1, oflow2;
long lval1, lval2;
double dval1, dval2;
- if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
- (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
+ if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
+ (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) {
+#if ULONG_MAX == 0xFFFFFFFF
+ if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
+ ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
+ || (oflow1 == -1 && dval1 < -9007199254740991.))) {
+#else
+ if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
+#endif
+ /* both values are integers overflown to the same side, and the
+ * double comparison may have resulted in crucial accuracy lost */
+ goto string_cmp;
+ }
if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
if (ret1!=IS_DOUBLE) {
+ if (oflow2) {
+ /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
+ ZVAL_LONG(result, -1 * oflow2);
+ return;
+ }
dval1 = (double) lval1;
} else if (ret2!=IS_DOUBLE) {
+ if (oflow1) {
+ ZVAL_LONG(result, oflow1);
+ return;
+ }
dval2 = (double) lval2;
} else if (dval1 == dval2 && !zend_finite(dval1)) {
/* Both values overflowed and have the same sign,
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 1beae0bb4e..d28140e9e5 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -31,11 +31,14 @@
#endif
#include "zend_strtod.h"
+#include "zend_multiply.h"
#if 0&&HAVE_BCMATH
#include "ext/bcmath/libbcmath/src/bcmath.h"
#endif
+#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
+
BEGIN_EXTERN_C()
ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
@@ -97,9 +100,12 @@ static zend_always_inline long zend_dval_to_lval(double d)
* if the number was out of long range or contained a decimal point/exponent.
* The number's value is returned into the respective pointer, *lval or *dval,
* if that pointer is not NULL.
+ *
+ * This variant also gives information if a string that represents an integer
+ * could not be represented as such due to overflow. It writes 1 to oflow_info
+ * if the integer is larger than LONG_MAX and -1 if it's smaller than LONG_MIN.
*/
-
-static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors)
+static inline zend_uchar is_numeric_string_ex(const char *str, int length, long *lval, double *dval, int allow_errors, int *oflow_info)
{
const char *ptr;
int base = 10, digits = 0, dp_or_e = 0;
@@ -110,6 +116,10 @@ static inline zend_uchar is_numeric_string(const char *str, int length, long *lv
return 0;
}
+ if (oflow_info != NULL) {
+ *oflow_info = 0;
+ }
+
/* Skip any whitespace
* This is much faster than the isspace() function */
while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
@@ -162,12 +172,18 @@ check_digits:
if (base == 10) {
if (digits >= MAX_LENGTH_OF_LONG) {
+ if (oflow_info != NULL) {
+ *oflow_info = *str == '-' ? -1 : 1;
+ }
dp_or_e = -1;
goto process_double;
}
} else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) {
if (dval) {
- local_dval = zend_hex_strtod(str, (char **)&ptr);
+ local_dval = zend_hex_strtod(str, &ptr);
+ }
+ if (oflow_info != NULL) {
+ *oflow_info = 1;
}
type = IS_DOUBLE;
}
@@ -178,7 +194,7 @@ process_double:
/* If there's a dval, do the conversion; else continue checking
* the digits if we need to check for a full match */
if (dval) {
- local_dval = zend_strtod(str, (char **)&ptr);
+ local_dval = zend_strtod(str, &ptr);
} else if (allow_errors != 1 && dp_or_e != -1) {
dp_or_e = (*ptr++ == '.') ? 1 : 2;
goto check_digits;
@@ -204,6 +220,9 @@ process_double:
if (dval) {
*dval = zend_strtod(str, NULL);
}
+ if (oflow_info != NULL) {
+ *oflow_info = *str == '-' ? -1 : 1;
+ }
return IS_DOUBLE;
}
@@ -223,6 +242,10 @@ process_double:
}
}
+static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors) {
+ return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
+}
+
static inline char *
zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
{
@@ -256,17 +279,17 @@ zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
return NULL;
}
-static inline void *zend_memrchr(const void *s, int c, size_t n)
+static inline const void *zend_memrchr(const void *s, int c, size_t n)
{
- register unsigned char *e;
+ register const unsigned char *e;
if (n <= 0) {
return NULL;
}
- for (e = (unsigned char *)s + n - 1; e >= (unsigned char *)s; e--) {
- if (*e == (unsigned char)c) {
- return (void *)e;
+ for (e = (const unsigned char *)s + n - 1; e >= (const unsigned char *)s; e--) {
+ if (*e == (const unsigned char)c) {
+ return (const void *)e;
}
}
@@ -298,7 +321,9 @@ ZEND_API double zend_string_to_double(const char *number, zend_uint length);
ZEND_API int zval_is_true(zval *op);
ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC);
ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
#if HAVE_STRCOLL
ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
#endif
@@ -448,6 +473,424 @@ ZEND_API void zend_update_current_locale(void);
#define zend_update_current_locale()
#endif
+static zend_always_inline int fast_increment_function(zval *op1)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+#if defined(__GNUC__) && defined(__i386__)
+ __asm__(
+ "incl (%0)\n\t"
+ "jno 0f\n\t"
+ "movl $0x0, (%0)\n\t"
+ "movl $0x41e00000, 0x4(%0)\n\t"
+ "movb $0x2,0xc(%0)\n"
+ "0:"
+ :
+ : "r"(op1));
+#elif defined(__GNUC__) && defined(__x86_64__)
+ __asm__(
+ "incq (%0)\n\t"
+ "jno 0f\n\t"
+ "movl $0x0, (%0)\n\t"
+ "movl $0x43e00000, 0x4(%0)\n\t"
+ "movb $0x2,0x14(%0)\n"
+ "0:"
+ :
+ : "r"(op1));
+#else
+ if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
+ /* switch to double */
+ Z_DVAL_P(op1) = (double)LONG_MAX + 1.0;
+ Z_TYPE_P(op1) = IS_DOUBLE;
+ } else {
+ Z_LVAL_P(op1)++;
+ }
+#endif
+ return SUCCESS;
+ }
+ return increment_function(op1);
+}
+
+static zend_always_inline int fast_decrement_function(zval *op1)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+#if defined(__GNUC__) && defined(__i386__)
+ __asm__(
+ "decl (%0)\n\t"
+ "jno 0f\n\t"
+ "movl $0x00200000, (%0)\n\t"
+ "movl $0xc1e00000, 0x4(%0)\n\t"
+ "movb $0x2,0xc(%0)\n"
+ "0:"
+ :
+ : "r"(op1));
+#elif defined(__GNUC__) && defined(__x86_64__)
+ __asm__(
+ "decq (%0)\n\t"
+ "jno 0f\n\t"
+ "movl $0x00000000, (%0)\n\t"
+ "movl $0xc3e00000, 0x4(%0)\n\t"
+ "movb $0x2,0x14(%0)\n"
+ "0:"
+ :
+ : "r"(op1));
+#else
+ if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
+ /* switch to double */
+ Z_DVAL_P(op1) = (double)LONG_MIN - 1.0;
+ Z_TYPE_P(op1) = IS_DOUBLE;
+ } else {
+ Z_LVAL_P(op1)--;
+ }
+#endif
+ return SUCCESS;
+ }
+ return decrement_function(op1);
+}
+
+static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+#if defined(__GNUC__) && defined(__i386__)
+ __asm__(
+ "movl (%1), %%eax\n\t"
+ "addl (%2), %%eax\n\t"
+ "jo 0f\n\t"
+ "movl %%eax, (%0)\n\t"
+ "movb $0x1,0xc(%0)\n\t"
+ "jmp 1f\n"
+ "0:\n\t"
+ "fildl (%1)\n\t"
+ "fildl (%2)\n\t"
+ "faddp %%st, %%st(1)\n\t"
+ "movb $0x2,0xc(%0)\n\t"
+ "fstpl (%0)\n"
+ "1:"
+ :
+ : "r"(result),
+ "r"(op1),
+ "r"(op2)
+ : "eax");
+#elif defined(__GNUC__) && defined(__x86_64__)
+ __asm__(
+ "movq (%1), %%rax\n\t"
+ "addq (%2), %%rax\n\t"
+ "jo 0f\n\t"
+ "movq %%rax, (%0)\n\t"
+ "movb $0x1,0x14(%0)\n\t"
+ "jmp 1f\n"
+ "0:\n\t"
+ "fildq (%1)\n\t"
+ "fildq (%2)\n\t"
+ "faddp %%st, %%st(1)\n\t"
+ "movb $0x2,0x14(%0)\n\t"
+ "fstpl (%0)\n"
+ "1:"
+ :
+ : "r"(result),
+ "r"(op1),
+ "r"(op2)
+ : "rax");
+#else
+ Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
+
+ if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
+ && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
+ Z_DVAL_P(result) = (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ } else {
+ Z_TYPE_P(result) = IS_LONG;
+ }
+#endif
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) + Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2));
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ }
+ return add_function(result, op1, op2 TSRMLS_CC);
+}
+
+static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+#if defined(__GNUC__) && defined(__i386__)
+ __asm__(
+ "movl (%1), %%eax\n\t"
+ "subl (%2), %%eax\n\t"
+ "jo 0f\n\t"
+ "movl %%eax, (%0)\n\t"
+ "movb $0x1,0xc(%0)\n\t"
+ "jmp 1f\n"
+ "0:\n\t"
+ "fildl (%2)\n\t"
+ "fildl (%1)\n\t"
+#if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
+ "fsubp %%st(1), %%st\n\t" /* LLVM bug #9164 */
+#else
+ "fsubp %%st, %%st(1)\n\t"
+#endif
+ "movb $0x2,0xc(%0)\n\t"
+ "fstpl (%0)\n"
+ "1:"
+ :
+ : "r"(result),
+ "r"(op1),
+ "r"(op2)
+ : "eax");
+#elif defined(__GNUC__) && defined(__x86_64__)
+ __asm__(
+ "movq (%1), %%rax\n\t"
+ "subq (%2), %%rax\n\t"
+ "jo 0f\n\t"
+ "movq %%rax, (%0)\n\t"
+ "movb $0x1,0x14(%0)\n\t"
+ "jmp 1f\n"
+ "0:\n\t"
+ "fildq (%2)\n\t"
+ "fildq (%1)\n\t"
+#if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
+ "fsubp %%st(1), %%st\n\t" /* LLVM bug #9164 */
+#else
+ "fsubp %%st, %%st(1)\n\t"
+#endif
+ "movb $0x2,0x14(%0)\n\t"
+ "fstpl (%0)\n"
+ "1:"
+ :
+ : "r"(result),
+ "r"(op1),
+ "r"(op2)
+ : "rax");
+#else
+ Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);
+
+ if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
+ && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
+ Z_DVAL_P(result) = (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ } else {
+ Z_TYPE_P(result) = IS_LONG;
+ }
+#endif
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2));
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ }
+ return sub_function(result, op1, op2 TSRMLS_CC);
+}
+
+static zend_always_inline int fast_mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ long overflow;
+
+ ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
+ Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) * Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ Z_DVAL_P(result) = Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2));
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ }
+ return mul_function(result, op1, op2 TSRMLS_CC);
+}
+
+static zend_always_inline int fast_div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && 0) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
+ zend_error(E_WARNING, "Division by zero");
+ Z_LVAL_P(result) = 0;
+ Z_TYPE_P(result) = IS_BOOL;
+ return FAILURE;
+ } else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN)) {
+ /* Prevent overflow error/crash */
+ Z_DVAL_P(result) = (double) LONG_MIN / -1;
+ Z_TYPE_P(result) = IS_DOUBLE;
+ } else if (EXPECTED(Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0)) {
+ /* integer */
+ Z_LVAL_P(result) = Z_LVAL_P(op1) / Z_LVAL_P(op2);
+ Z_TYPE_P(result) = IS_LONG;
+ } else {
+ Z_DVAL_P(result) = ((double) Z_LVAL_P(op1)) / ((double)Z_LVAL_P(op2));
+ Z_TYPE_P(result) = IS_DOUBLE;
+ }
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
+ zend_error(E_WARNING, "Division by zero");
+ Z_LVAL_P(result) = 0;
+ Z_TYPE_P(result) = IS_BOOL;
+ return FAILURE;
+ }
+ Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) / Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE) && 0) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
+ zend_error(E_WARNING, "Division by zero");
+ Z_LVAL_P(result) = 0;
+ Z_TYPE_P(result) = IS_BOOL;
+ return FAILURE;
+ }
+ Z_DVAL_P(result) = Z_DVAL_P(op1) / Z_DVAL_P(op2);
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
+ zend_error(E_WARNING, "Division by zero");
+ Z_LVAL_P(result) = 0;
+ Z_TYPE_P(result) = IS_BOOL;
+ return FAILURE;
+ }
+ Z_DVAL_P(result) = Z_DVAL_P(op1) / ((double)Z_LVAL_P(op2));
+ Z_TYPE_P(result) = IS_DOUBLE;
+ return SUCCESS;
+ }
+ }
+ return div_function(result, op1, op2 TSRMLS_CC);
+}
+
+static zend_always_inline int fast_mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
+ zend_error(E_WARNING, "Division by zero");
+ Z_LVAL_P(result) = 0;
+ Z_TYPE_P(result) = IS_BOOL;
+ return FAILURE;
+ } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
+ /* Prevent overflow error/crash if op1==LONG_MIN */
+ Z_LVAL_P(result) = 0;
+ Z_TYPE_P(result) = IS_LONG;
+ return SUCCESS;
+ }
+ Z_LVAL_P(result) = Z_LVAL_P(op1) % Z_LVAL_P(op2);
+ Z_TYPE_P(result) = IS_LONG;
+ return SUCCESS;
+ }
+ }
+ return mod_function(result, op1, op2 TSRMLS_CC);
+}
+
+static zend_always_inline int fast_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_LVAL_P(op1) == Z_LVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return ((double)Z_LVAL_P(op1)) == Z_DVAL_P(op2);
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return Z_DVAL_P(op1) == Z_DVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2));
+ }
+ }
+ compare_function(result, op1, op2 TSRMLS_CC);
+ return Z_LVAL_P(result) == 0;
+}
+
+static zend_always_inline int fast_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_LVAL_P(op1) != Z_LVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return ((double)Z_LVAL_P(op1)) != Z_DVAL_P(op2);
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return Z_DVAL_P(op1) != Z_DVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2));
+ }
+ }
+ compare_function(result, op1, op2 TSRMLS_CC);
+ return Z_LVAL_P(result) != 0;
+}
+
+static zend_always_inline int fast_is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_LVAL_P(op1) < Z_LVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return ((double)Z_LVAL_P(op1)) < Z_DVAL_P(op2);
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return Z_DVAL_P(op1) < Z_DVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_DVAL_P(op1) < ((double)Z_LVAL_P(op2));
+ }
+ }
+ compare_function(result, op1, op2 TSRMLS_CC);
+ return Z_LVAL_P(result) < 0;
+}
+
+static zend_always_inline int fast_is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
+{
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_LVAL_P(op1) <= Z_LVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return ((double)Z_LVAL_P(op1)) <= Z_DVAL_P(op2);
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ return Z_DVAL_P(op1) <= Z_DVAL_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_DVAL_P(op1) <= ((double)Z_LVAL_P(op2));
+ }
+ }
+ compare_function(result, op1, op2 TSRMLS_CC);
+ return Z_LVAL_P(result) <= 0;
+}
+
#endif
/*
diff --git a/Zend/zend_ptr_stack.c b/Zend/zend_ptr_stack.c
index 993b4b82ad..aefa91f73d 100644
--- a/Zend/zend_ptr_stack.c
+++ b/Zend/zend_ptr_stack.c
@@ -27,9 +27,8 @@
ZEND_API void zend_ptr_stack_init_ex(zend_ptr_stack *stack, zend_bool persistent)
{
- stack->top_element = stack->elements = (void **) pemalloc(sizeof(void *)*PTR_STACK_BLOCK_SIZE, persistent);
- stack->max = PTR_STACK_BLOCK_SIZE;
- stack->top = 0;
+ stack->top_element = stack->elements = NULL;
+ stack->top = stack->max = 0;
stack->persistent = persistent;
}
diff --git a/Zend/zend_ptr_stack.h b/Zend/zend_ptr_stack.h
index cf31d992d7..cc062de872 100644
--- a/Zend/zend_ptr_stack.h
+++ b/Zend/zend_ptr_stack.h
@@ -46,15 +46,16 @@ END_EXTERN_C()
#define ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, count) \
if (stack->top+count > stack->max) { \
/* we need to allocate more memory */ \
- stack->max *= 2; \
- stack->max += count; \
+ do { \
+ stack->max += PTR_STACK_BLOCK_SIZE; \
+ } while (stack->top+count > stack->max); \
stack->elements = (void **) perealloc(stack->elements, (sizeof(void *) * (stack->max)), stack->persistent); \
stack->top_element = stack->elements+stack->top; \
}
/* Not doing this with a macro because of the loop unrolling in the element assignment.
Just using a macro for 3 in the body for readability sake. */
-static inline void zend_ptr_stack_3_push(zend_ptr_stack *stack, void *a, void *b, void *c)
+static zend_always_inline void zend_ptr_stack_3_push(zend_ptr_stack *stack, void *a, void *b, void *c)
{
#define ZEND_PTR_STACK_NUM_ARGS 3
@@ -68,7 +69,7 @@ static inline void zend_ptr_stack_3_push(zend_ptr_stack *stack, void *a, void *b
#undef ZEND_PTR_STACK_NUM_ARGS
}
-static inline void zend_ptr_stack_2_push(zend_ptr_stack *stack, void *a, void *b)
+static zend_always_inline void zend_ptr_stack_2_push(zend_ptr_stack *stack, void *a, void *b)
{
#define ZEND_PTR_STACK_NUM_ARGS 2
@@ -81,7 +82,7 @@ static inline void zend_ptr_stack_2_push(zend_ptr_stack *stack, void *a, void *b
#undef ZEND_PTR_STACK_NUM_ARGS
}
-static inline void zend_ptr_stack_3_pop(zend_ptr_stack *stack, void **a, void **b, void **c)
+static zend_always_inline void zend_ptr_stack_3_pop(zend_ptr_stack *stack, void **a, void **b, void **c)
{
*a = *(--stack->top_element);
*b = *(--stack->top_element);
@@ -89,14 +90,14 @@ static inline void zend_ptr_stack_3_pop(zend_ptr_stack *stack, void **a, void **
stack->top -= 3;
}
-static inline void zend_ptr_stack_2_pop(zend_ptr_stack *stack, void **a, void **b)
+static zend_always_inline void zend_ptr_stack_2_pop(zend_ptr_stack *stack, void **a, void **b)
{
*a = *(--stack->top_element);
*b = *(--stack->top_element);
stack->top -= 2;
}
-static inline void zend_ptr_stack_push(zend_ptr_stack *stack, void *ptr)
+static zend_always_inline void zend_ptr_stack_push(zend_ptr_stack *stack, void *ptr)
{
ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, 1)
@@ -104,7 +105,7 @@ static inline void zend_ptr_stack_push(zend_ptr_stack *stack, void *ptr)
*(stack->top_element++) = ptr;
}
-static inline void *zend_ptr_stack_pop(zend_ptr_stack *stack)
+static zend_always_inline void *zend_ptr_stack_pop(zend_ptr_stack *stack)
{
stack->top--;
return *(--stack->top_element);
diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c
new file mode 100644
index 0000000000..f61ae0b176
--- /dev/null
+++ b/Zend/zend_signal.c
@@ -0,0 +1,414 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Signal Handling |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2008 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Lucas Nealan <lucas@php.net> |
+ | Arnaud Le Blanc <lbarnaud@php.net> |
+ +----------------------------------------------------------------------+
+
+ This software was contributed to PHP by Facebook Inc. in 2008.
+
+ Future revisions and derivatives of this source code must acknowledge
+ Facebook Inc. as the original contributor of this module by leaving
+ this note intact in the source code.
+
+ All other licensing and usage conditions are those of the PHP Group.
+*/
+
+ /* $Id$ */
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include "zend.h"
+#include "zend_globals.h"
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef ZEND_SIGNALS
+
+#include "zend_signal.h"
+
+#ifdef ZTS
+ZEND_API int zend_signal_globals_id;
+#else
+zend_signal_globals_t zend_signal_globals;
+#endif
+
+static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context TSRMLS_DC);
+static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC);
+
+#ifdef __CYGWIN__
+#define TIMEOUT_SIG SIGALRM
+#else
+#define TIMEOUT_SIG SIGPROF
+#endif
+
+static int zend_sigs[] = { TIMEOUT_SIG, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2 };
+
+#define SA_FLAGS_MASK ~(SA_NODEFER | SA_RESETHAND)
+
+/* True globals, written only at process startup */
+static zend_signal_entry_t global_orig_handlers[NSIG];
+static sigset_t global_sigmask;
+
+/* {{{ zend_signal_handler_defer
+ * Blocks signals if in critical section */
+void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
+{
+ int errno_save = errno;
+ zend_signal_queue_t *queue, *qtmp;
+ TSRMLS_FETCH();
+
+ if (SIGG(active)) {
+ if (SIGG(depth) == 0) { /* try to handle signal */
+ if (SIGG(blocked) != -1) { /* inverse */
+ SIGG(blocked) = -1; /* signal is not blocked */
+ }
+ if (SIGG(running) == 0) {
+ SIGG(running) = 1;
+ zend_signal_handler(signo, siginfo, context TSRMLS_CC);
+
+ queue = SIGG(phead);
+ SIGG(phead) = NULL;
+
+ while (queue) {
+ zend_signal_handler(queue->zend_signal.signo, queue->zend_signal.siginfo, queue->zend_signal.context TSRMLS_CC);
+ qtmp = queue->next;
+ queue->next = SIGG(pavail);
+ queue->zend_signal.signo = 0;
+ SIGG(pavail) = queue;
+ queue = qtmp;
+ }
+ SIGG(running) = 0;
+ }
+ } else { /* delay signal handling */
+ SIGG(blocked) = 0; /* signal is blocked */
+
+ if ((queue = SIGG(pavail))) { /* if none available it's simply forgotton */
+ SIGG(pavail) = queue->next;
+ queue->zend_signal.signo = signo;
+ queue->zend_signal.siginfo = siginfo;
+ queue->zend_signal.context = context;
+ queue->next = NULL;
+
+ if (SIGG(phead) && SIGG(ptail)) {
+ SIGG(ptail)->next = queue;
+ } else {
+ SIGG(phead) = queue;
+ }
+ SIGG(ptail) = queue;
+ }
+#if ZEND_DEBUG
+ else { /* this may not be safe to do, but could work and be useful */
+ zend_output_debug_string(0, "zend_signal: not enough queue storage, lost signal (%d)", signo);
+ }
+#endif
+ }
+ } else {
+ /* need to just run handler if we're inactive and getting a signal */
+ zend_signal_handler(signo, siginfo, context TSRMLS_CC);
+ }
+
+ errno = errno_save;
+} /* }}} */
+
+/* {{{ zend_signal_handler_unblock
+ * Handle deferred signal from HANDLE_UNBLOCK_ALARMS */
+ZEND_API void zend_signal_handler_unblock(TSRMLS_D)
+{
+ zend_signal_queue_t *queue;
+ zend_signal_t zend_signal;
+
+ if (SIGG(active)) {
+ SIGNAL_BEGIN_CRITICAL(); /* procmask to protect handler_defer as if it were called by the kernel */
+ queue = SIGG(phead);
+ SIGG(phead) = queue->next;
+ zend_signal = queue->zend_signal;
+ queue->next = SIGG(pavail);
+ queue->zend_signal.signo = 0;
+ SIGG(pavail) = queue;
+
+ zend_signal_handler_defer(zend_signal.signo, zend_signal.siginfo, zend_signal.context);
+ SIGNAL_END_CRITICAL();
+ }
+}
+/* }}} */
+
+/* {{{ zend_signal_handler
+ * Call the previously registered handler for a signal
+ */
+static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context TSRMLS_DC)
+{
+ int errno_save = errno;
+ struct sigaction sa = {{0}};
+ sigset_t sigset;
+ zend_signal_entry_t p_sig = SIGG(handlers)[signo-1];
+
+ if (p_sig.handler == SIG_DFL) { /* raise default handler */
+ if (sigaction(signo, NULL, &sa) == 0) {
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, signo);
+
+ if (sigaction(signo, &sa, NULL) == 0) {
+ /* throw away any blocked signals */
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ raise(signo);
+ }
+ }
+ } else if (p_sig.handler != SIG_IGN) { /* ignore SIG_IGN */
+ if (p_sig.flags & SA_SIGINFO) {
+ if (p_sig.flags & SA_RESETHAND) {
+ SIGG(handlers)[signo-1].flags = 0;
+ SIGG(handlers)[signo-1].handler = SIG_DFL;
+ }
+ (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
+ } else {
+ (*(void (*)(int))p_sig.handler)(signo);
+ }
+ }
+
+ errno = errno_save;
+} /* }}} */
+
+/* {{{ zend_sigaction
+ * Register a signal handler that will be deferred in critical sections */
+ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact TSRMLS_DC)
+{
+ struct sigaction sa = {{0}};
+ sigset_t sigset;
+
+ if (oldact != NULL) {
+ oldact->sa_flags = SIGG(handlers)[signo-1].flags;
+ oldact->sa_handler = (void *) SIGG(handlers)[signo-1].handler;
+ oldact->sa_mask = global_sigmask;
+ }
+ if (act != NULL) {
+ SIGG(handlers)[signo-1].flags = act->sa_flags;
+ if (act->sa_flags & SA_SIGINFO) {
+ SIGG(handlers)[signo-1].handler = (void *) act->sa_sigaction;
+ } else {
+ SIGG(handlers)[signo-1].handler = (void *) act->sa_handler;
+ }
+
+ sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK);
+ sa.sa_sigaction = zend_signal_handler_defer;
+ sa.sa_mask = global_sigmask;
+
+ if (sigaction(signo, &sa, NULL) < 0) {
+ zend_error(E_WARNING, "Error installing signal handler for %d", signo);
+ }
+
+ /* unsure this signal is not blocked */
+ sigemptyset(&sigset);
+ sigaddset(&sigset, signo);
+ zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ zend_signal
+ * Register a signal handler that will be deferred in critical sections */
+ZEND_API int zend_signal(int signo, void (*handler)(int) TSRMLS_DC)
+{
+ struct sigaction sa = {{0}};
+
+ sa.sa_flags = 0;
+ sa.sa_handler = handler;
+ sa.sa_mask = global_sigmask;
+
+ return zend_sigaction(signo, &sa, NULL TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ zend_signal_register
+ * Set a handler for a signal we want to defer.
+ * Previously set handler must have been saved before.
+ */
+static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC)
+{
+ struct sigaction sa = {{0}};
+
+ if (sigaction(signo, NULL, &sa) == 0) {
+ if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction == handler) {
+ return FAILURE;
+ }
+
+ SIGG(handlers)[signo-1].flags = sa.sa_flags;
+ if (sa.sa_flags & SA_SIGINFO) {
+ SIGG(handlers)[signo-1].handler = (void *)sa.sa_sigaction;
+ } else {
+ SIGG(handlers)[signo-1].handler = (void *)sa.sa_handler;
+ }
+
+ sa.sa_flags = SA_SIGINFO; /* we'll use a siginfo handler */
+ sa.sa_sigaction = handler;
+ sa.sa_mask = global_sigmask;
+
+ if (sigaction(signo, &sa, NULL) < 0) {
+ zend_error(E_WARNING, "Error installing signal handler for %d", signo);
+ }
+
+ return SUCCESS;
+ }
+ return FAILURE;
+} /* }}} */
+
+/* {{{ zend_signal_activate
+ * Install our signal handlers, per request */
+void zend_signal_activate(TSRMLS_D)
+{
+ int x;
+
+ memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers));
+
+ for (x=0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
+ zend_signal_register(zend_sigs[x], zend_signal_handler_defer TSRMLS_CC);
+ }
+
+ SIGG(active) = 1;
+ SIGG(depth) = 0;
+} /* }}} */
+
+/* {{{ zend_signal_deactivate
+ * */
+void zend_signal_deactivate(TSRMLS_D)
+{
+ int x;
+ struct sigaction sa = {{0}};
+
+ if (SIGG(check)) {
+ if (SIGG(depth) != 0) {
+ zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
+ }
+ /* did anyone steal our installed handler */
+ for (x=0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
+ sigaction(zend_sigs[x], NULL, &sa);
+ if (sa.sa_sigaction != zend_signal_handler_defer) {
+ zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
+ }
+ }
+ }
+
+ SIGNAL_BEGIN_CRITICAL();
+ SIGG(active) = 0;
+ SIGG(running) = 0;
+ SIGG(blocked) = -1;
+ SIGG(depth) = 0;
+ SIGNAL_END_CRITICAL();
+}
+/* }}} */
+
+static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals TSRMLS_DC)
+{
+ size_t x;
+
+ memset(zend_signal_globals, 0, sizeof(*zend_signal_globals));
+ zend_signal_globals->blocked = -1;
+
+ for (x = 0; x < sizeof(zend_signal_globals->pstorage) / sizeof(*zend_signal_globals->pstorage); ++x) {
+ zend_signal_queue_t *queue = &zend_signal_globals->pstorage[x];
+ queue->zend_signal.signo = 0;
+ queue->next = zend_signal_globals->pavail;
+ zend_signal_globals->pavail = queue;
+ }
+}
+
+static void zend_signal_globals_dtor(zend_signal_globals_t *zend_signal_globals TSRMLS_DC)
+{
+ zend_signal_globals->blocked = -1;
+}
+
+/* {{{ zend_signal_startup
+ * alloc zend signal globals */
+void zend_signal_startup()
+{
+ int signo;
+ struct sigaction sa = {{0}};
+
+#ifdef ZTS
+ ts_allocate_id(&zend_signal_globals_id, sizeof(zend_signal_globals_t), (ts_allocate_ctor) zend_signal_globals_ctor, (ts_allocate_dtor) zend_signal_globals_dtor);
+#else
+ zend_signal_globals_ctor(&zend_signal_globals);
+#endif
+
+ /* Used to block signals during execution of signal handlers */
+ sigfillset(&global_sigmask);
+ sigdelset(&global_sigmask, SIGILL);
+ sigdelset(&global_sigmask, SIGABRT);
+ sigdelset(&global_sigmask, SIGFPE);
+ sigdelset(&global_sigmask, SIGKILL);
+ sigdelset(&global_sigmask, SIGSEGV);
+ sigdelset(&global_sigmask, SIGCONT);
+ sigdelset(&global_sigmask, SIGSTOP);
+ sigdelset(&global_sigmask, SIGTSTP);
+ sigdelset(&global_sigmask, SIGTTIN);
+ sigdelset(&global_sigmask, SIGTTOU);
+#ifdef SIGBUS
+ sigdelset(&global_sigmask, SIGBUS);
+#endif
+#ifdef SIGSYS
+ sigdelset(&global_sigmask, SIGSYS);
+#endif
+#ifdef SIGTRAP
+ sigdelset(&global_sigmask, SIGTRAP);
+#endif
+
+ /* Save previously registered signal handlers into orig_handlers */
+ memset(&global_orig_handlers, 0, sizeof(global_orig_handlers));
+ for (signo = 1; signo < NSIG; ++signo) {
+ if (sigaction(signo, NULL, &sa) == 0) {
+ global_orig_handlers[signo-1].flags = sa.sa_flags;
+ if (sa.sa_flags & SA_SIGINFO) {
+ global_orig_handlers[signo-1].handler = (void *) sa.sa_sigaction;
+ } else {
+ global_orig_handlers[signo-1].handler = (void *) sa.sa_handler;
+ }
+ }
+ }
+}
+/* }}} */
+
+/* {{{ zend_signal_shutdown
+ * called by zend_shutdown */
+void zend_signal_shutdown(TSRMLS_D)
+{
+#ifndef ZTS
+ zend_signal_globals_dtor(&zend_signal_globals);
+#endif
+}
+/* }}} */
+
+
+#endif /* ZEND_SIGNALS */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ * vim600: fdm=marker
+ * vim: noet sw=4 ts=4
+ */
diff --git a/Zend/zend_signal.h b/Zend/zend_signal.h
new file mode 100644
index 0000000000..02d6495437
--- /dev/null
+++ b/Zend/zend_signal.h
@@ -0,0 +1,108 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Signal Handling |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2008 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Lucas Nealan <lucas@php.net> |
+ | Arnaud Le Blanc <lbarnaud@php.net> |
+ +----------------------------------------------------------------------+
+
+ */
+
+/* $Id$ */
+
+#ifndef ZEND_SIGNAL_H
+#define ZEND_SIGNAL_H
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifndef NSIG
+#define NSIG 65
+#endif
+
+#ifndef ZEND_SIGNAL_QUEUE_SIZE
+#define ZEND_SIGNAL_QUEUE_SIZE 32
+#endif
+
+/* Signal structs */
+typedef struct _zend_signal_entry_t {
+ int flags; /* sigaction style flags */
+ void* handler; /* signal handler or context */
+} zend_signal_entry_t;
+
+typedef struct _zend_signal_t {
+ int signo;
+ siginfo_t *siginfo;
+ void* context;
+} zend_signal_t;
+
+typedef struct _zend_signal_queue_t {
+ zend_signal_t zend_signal;
+ struct _zend_signal_queue_t *next;
+} zend_signal_queue_t;
+
+/* Signal Globals */
+typedef struct _zend_signal_globals_t {
+ int depth;
+ int blocked; /* 0==TRUE, -1==FALSE */
+ int running; /* in signal handler execution */
+ int active; /* internal signal handling is enabled */
+ int initialized; /* memory initialized */
+ zend_bool check; /* check for replaced handlers on shutdown */
+ zend_signal_entry_t handlers[NSIG];
+ zend_signal_queue_t pstorage[ZEND_SIGNAL_QUEUE_SIZE], *phead, *ptail, *pavail; /* pending queue */
+} zend_signal_globals_t;
+
+#ifdef ZTS
+# define SIGG(v) TSRMG(zend_signal_globals_id, zend_signal_globals_t *, v)
+BEGIN_EXTERN_C()
+ZEND_API extern int zend_signal_globals_id;
+END_EXTERN_C()
+# define ZEND_SIGNAL_BLOCK_INTERRUPUTIONS() if (EXPECTED(zend_signal_globals_id)) { SIGG(depth)++; }
+# define ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() if (EXPECTED(zend_signal_globals_id) && UNEXPECTED((--SIGG(depth))==SIGG(blocked))) { zend_signal_handler_unblock(TSRMLS_C); }
+#else /* ZTS */
+# define SIGG(v) (zend_signal_globals.v)
+extern ZEND_API zend_signal_globals_t zend_signal_globals;
+# define ZEND_SIGNAL_BLOCK_INTERRUPUTIONS() SIGG(depth)++;
+# define ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS() if (UNEXPECTED((--SIGG(depth))==SIGG(blocked))) { zend_signal_handler_unblock(TSRMLS_C); }
+#endif /* not ZTS */
+
+# define SIGNAL_BEGIN_CRITICAL() sigset_t oldmask; \
+ zend_sigprocmask(SIG_BLOCK, &global_sigmask, &oldmask);
+# define SIGNAL_END_CRITICAL() zend_sigprocmask(SIG_SETMASK, &oldmask, NULL);
+
+void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context);
+ZEND_API void zend_signal_handler_unblock();
+void zend_signal_activate(TSRMLS_D);
+void zend_signal_deactivate(TSRMLS_D);
+void zend_signal_startup();
+void zend_signal_shutdown(TSRMLS_D);
+ZEND_API int zend_signal(int signo, void (*handler)(int) TSRMLS_DC);
+ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact TSRMLS_DC);
+
+#ifdef ZTS
+#define zend_sigprocmask(signo, set, oldset) tsrm_sigmask((signo), (set), (oldset))
+#else
+#define zend_sigprocmask(signo, set, oldset) sigprocmask((signo), (set), (oldset))
+#endif
+
+#endif /* ZEND_SIGNAL_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/Zend/zend_stack.c b/Zend/zend_stack.c
index 926e9511fd..cbc8a0043d 100644
--- a/Zend/zend_stack.c
+++ b/Zend/zend_stack.c
@@ -25,13 +25,9 @@
ZEND_API int zend_stack_init(zend_stack *stack)
{
stack->top = 0;
- stack->elements = (void **) emalloc(sizeof(void **) * STACK_BLOCK_SIZE);
- if (!stack->elements) {
- return FAILURE;
- } else {
- stack->max = STACK_BLOCK_SIZE;
- return SUCCESS;
- }
+ stack->max = 0;
+ stack->elements = NULL;
+ return SUCCESS;
}
ZEND_API int zend_stack_push(zend_stack *stack, const void *element, int size)
@@ -100,8 +96,8 @@ ZEND_API int zend_stack_destroy(zend_stack *stack)
for (i = 0; i < stack->top; i++) {
efree(stack->elements[i]);
}
-
efree(stack->elements);
+ stack->elements = NULL;
}
return SUCCESS;
diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c
index bc5206c12c..30cc3a5ba4 100644
--- a/Zend/zend_stream.c
+++ b/Zend/zend_stream.c
@@ -134,7 +134,7 @@ ZEND_API int zend_stream_open(const char *filename, zend_file_handle *handle TSR
handle->type = ZEND_HANDLE_FP;
handle->opened_path = NULL;
handle->handle.fp = zend_fopen(filename, &handle->opened_path TSRMLS_CC);
- handle->filename = (char *)filename;
+ handle->filename = filename;
handle->free_filename = 0;
memset(&handle->handle.stream.mmap, 0, sizeof(zend_mmap));
@@ -284,7 +284,6 @@ ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t
if (ZEND_MMAP_AHEAD) {
memset(file_handle->handle.stream.mmap.buf + file_handle->handle.stream.mmap.len, 0, ZEND_MMAP_AHEAD);
}
-
#if HAVE_MMAP
return_mapped:
#endif
@@ -328,7 +327,7 @@ ZEND_API void zend_file_handle_dtor(zend_file_handle *fh TSRMLS_DC) /* {{{ */
fh->opened_path = NULL;
}
if (fh->free_filename && fh->filename) {
- efree(fh->filename);
+ efree((char*)fh->filename);
fh->filename = NULL;
}
}
diff --git a/Zend/zend_stream.h b/Zend/zend_stream.h
index bf05240293..aff87eb6d1 100644
--- a/Zend/zend_stream.h
+++ b/Zend/zend_stream.h
@@ -61,7 +61,7 @@ typedef struct _zend_stream {
typedef struct _zend_file_handle {
zend_stream_type type;
- char *filename;
+ const char *filename;
char *opened_path;
union {
int fd;
diff --git a/Zend/zend_string.c b/Zend/zend_string.c
new file mode 100644
index 0000000000..8e9009f9fd
--- /dev/null
+++ b/Zend/zend_string.c
@@ -0,0 +1,233 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#include "zend.h"
+#include "zend_globals.h"
+
+#ifndef ZEND_DEBUG_INTERNED_STRINGS
+# define ZEND_DEBUG_INTERNED_STRINGS 0
+#endif
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+# include <sys/mman.h>
+#endif
+
+ZEND_API const char *(*zend_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
+ZEND_API void (*zend_interned_strings_snapshot)(TSRMLS_D);
+ZEND_API void (*zend_interned_strings_restore)(TSRMLS_D);
+
+static const char *zend_new_interned_string_int(const char *str, int len, int free_src TSRMLS_DC);
+static void zend_interned_strings_snapshot_int(TSRMLS_D);
+static void zend_interned_strings_restore_int(TSRMLS_D);
+
+void zend_interned_strings_init(TSRMLS_D)
+{
+#ifndef ZTS
+ size_t size = 1024 * 1024;
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ CG(interned_strings_start) = valloc(size);
+#else
+ CG(interned_strings_start) = malloc(size);
+#endif
+
+ CG(interned_strings_top) = CG(interned_strings_start);
+ CG(interned_strings_snapshot_top) = CG(interned_strings_start);
+ CG(interned_strings_end) = CG(interned_strings_start) + size;
+
+ zend_hash_init(&CG(interned_strings), 0, NULL, NULL, 1);
+
+ CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
+ CG(interned_strings).arBuckets = (Bucket **) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket *), CG(interned_strings).persistent);
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
+#endif
+
+#endif
+
+ zend_new_interned_string = zend_new_interned_string_int;
+ zend_interned_strings_snapshot = zend_interned_strings_snapshot_int;
+ zend_interned_strings_restore = zend_interned_strings_restore_int;
+}
+
+void zend_interned_strings_dtor(TSRMLS_D)
+{
+#ifndef ZTS
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
+#endif
+ free(CG(interned_strings).arBuckets);
+ free(CG(interned_strings_start));
+#endif
+}
+
+static const char *zend_new_interned_string_int(const char *arKey, int nKeyLength, int free_src TSRMLS_DC)
+{
+#ifndef ZTS
+ ulong h;
+ uint nIndex;
+ Bucket *p;
+
+ if (IS_INTERNED(arKey)) {
+ return arKey;
+ }
+
+ h = zend_inline_hash_func(arKey, nKeyLength);
+ nIndex = h & CG(interned_strings).nTableMask;
+ p = CG(interned_strings).arBuckets[nIndex];
+ while (p != NULL) {
+ if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
+ if (!memcmp(p->arKey, arKey, nKeyLength)) {
+ if (free_src) {
+ efree((void *)arKey);
+ }
+ return p->arKey;
+ }
+ }
+ p = p->pNext;
+ }
+
+ if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >=
+ CG(interned_strings_end)) {
+ /* no memory */
+ return arKey;
+ }
+
+ p = (Bucket *) CG(interned_strings_top);
+ CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength);
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE);
+#endif
+
+ p->arKey = (char*)(p+1);
+ memcpy((char*)p->arKey, arKey, nKeyLength);
+ if (free_src) {
+ efree((void *)arKey);
+ }
+ p->nKeyLength = nKeyLength;
+ p->h = h;
+ p->pData = &p->pDataPtr;
+ p->pDataPtr = p;
+
+ p->pNext = CG(interned_strings).arBuckets[nIndex];
+ p->pLast = NULL;
+ if (p->pNext) {
+ p->pNext->pLast = p;
+ }
+
+ HANDLE_BLOCK_INTERRUPTIONS();
+
+ p->pListLast = CG(interned_strings).pListTail;
+ CG(interned_strings).pListTail = p;
+ p->pListNext = NULL;
+ if (p->pListLast != NULL) {
+ p->pListLast->pListNext = p;
+ }
+ if (!CG(interned_strings).pListHead) {
+ CG(interned_strings).pListHead = p;
+ }
+
+ CG(interned_strings).arBuckets[nIndex] = p;
+
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+
+ CG(interned_strings).nNumOfElements++;
+
+ if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) {
+ if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */
+ Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent);
+
+ if (t) {
+ HANDLE_BLOCK_INTERRUPTIONS();
+ CG(interned_strings).arBuckets = t;
+ CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1);
+ CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1;
+ zend_hash_rehash(&CG(interned_strings));
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ }
+ }
+ }
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
+#endif
+
+ return p->arKey;
+#else
+ return arKey;
+#endif
+}
+
+static void zend_interned_strings_snapshot_int(TSRMLS_D)
+{
+ CG(interned_strings_snapshot_top) = CG(interned_strings_top);
+}
+
+static void zend_interned_strings_restore_int(TSRMLS_D)
+{
+#ifndef ZTS
+ Bucket *p;
+ int i;
+#endif
+
+ CG(interned_strings_top) = CG(interned_strings_snapshot_top);
+
+#ifndef ZTS
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ);
+#endif
+
+ for (i = 0; i < CG(interned_strings).nTableSize; i++) {
+ p = CG(interned_strings).arBuckets[i];
+ while (p && p->arKey > CG(interned_strings_top)) {
+ CG(interned_strings).nNumOfElements--;
+ if (p->pListLast != NULL) {
+ p->pListLast->pListNext = p->pListNext;
+ } else {
+ CG(interned_strings).pListHead = p->pListNext;
+ }
+ if (p->pListNext != NULL) {
+ p->pListNext->pListLast = p->pListLast;
+ } else {
+ CG(interned_strings).pListTail = p->pListLast;
+ }
+ p = p->pNext;
+ }
+ if (p) {
+ p->pLast = NULL;
+ }
+ CG(interned_strings).arBuckets[i] = p;
+ }
+
+#if ZEND_DEBUG_INTERNED_STRINGS
+ mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ);
+#endif
+#endif
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
new file mode 100644
index 0000000000..0a4738466d
--- /dev/null
+++ b/Zend/zend_string.h
@@ -0,0 +1,73 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: $ */
+
+#ifndef ZEND_STRING_H
+#define ZEND_STRING_H
+
+#include "zend.h"
+
+BEGIN_EXTERN_C()
+ZEND_API extern const char *(*zend_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC);
+ZEND_API extern void (*zend_interned_strings_snapshot)(TSRMLS_D);
+ZEND_API extern void (*zend_interned_strings_restore)(TSRMLS_D);
+
+void zend_interned_strings_init(TSRMLS_D);
+void zend_interned_strings_dtor(TSRMLS_D);
+END_EXTERN_C()
+
+#ifndef ZTS
+
+#define IS_INTERNED(s) \
+ (((s) >= CG(interned_strings_start)) && ((s) < CG(interned_strings_end)))
+
+#else
+
+#define IS_INTERNED(s) \
+ (0)
+
+#endif
+
+#define INTERNED_LEN(s) \
+ (((Bucket*)(((char*)(s))-sizeof(Bucket)))->nKeyLength)
+
+#define INTERNED_HASH(s) \
+ (((Bucket*)(((char*)(s))-sizeof(Bucket)))->h)
+
+#define str_efree(s) do { \
+ if (!IS_INTERNED(s)) { \
+ efree((char*)s); \
+ } \
+ } while (0)
+
+#define str_free(s) do { \
+ if (!IS_INTERNED(s)) { \
+ free((char*)s); \
+ } \
+ } while (0)
+
+#endif /* ZEND_STRING_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 3d133bfecd..d6e5ccf960 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -2037,11 +2037,7 @@ ret1:
return s0;
}
-/* F* VC6 */
-#if _MSC_VER <= 1300
-# pragma optimize( "", off )
-#endif
-ZEND_API double zend_strtod (CONST char *s00, char **se)
+ZEND_API double zend_strtod (CONST char *s00, CONST char **se)
{
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
@@ -2574,7 +2570,7 @@ retfree:
Bfree(delta);
ret:
if (se)
- *se = (char *)s;
+ *se = s;
result = sign ? -value(rv) : value(rv);
_THREAD_PRIVATE_MUTEX_LOCK(pow5mult_mutex);
@@ -2588,13 +2584,18 @@ ret:
return result;
}
-ZEND_API double zend_hex_strtod(const char *str, char **endptr)
+ZEND_API double zend_hex_strtod(const char *str, const char **endptr)
{
const char *s = str;
char c;
int any = 0;
double value = 0;
+ if (strlen(str) < 2) {
+ *endptr = str;
+ return 0.0;
+ }
+
if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) {
s += 2;
}
@@ -2615,19 +2616,24 @@ ZEND_API double zend_hex_strtod(const char *str, char **endptr)
}
if (endptr != NULL) {
- *endptr = (char *)(any ? s - 1 : str);
+ *endptr = any ? s - 1 : str;
}
return value;
}
-ZEND_API double zend_oct_strtod(const char *str, char **endptr)
+ZEND_API double zend_oct_strtod(const char *str, const char **endptr)
{
const char *s = str;
char c;
double value = 0;
int any = 0;
+ if (strlen(str) < 1) {
+ *endptr = str;
+ return 0.0;
+ }
+
/* skip leading zero */
s++;
@@ -2643,6 +2649,49 @@ ZEND_API double zend_oct_strtod(const char *str, char **endptr)
}
if (endptr != NULL) {
+ *endptr = any ? s - 1 : str;
+ }
+
+ return value;
+}
+
+ZEND_API double zend_bin_strtod(const char *str, const char **endptr)
+{
+ const char *s = str;
+ char c;
+ double value = 0;
+ int any = 0;
+
+ if (strlen(str) < 2) {
+ *endptr = str;
+ return 0.0;
+ }
+
+ if ('0' == *s && ('b' == s[1] || 'B' == s[1])) {
+ s += 2;
+ }
+
+ while ((c = *s++)) {
+ /*
+ * Verify the validity of the current character as a base-2 digit. In
+ * the event that an invalid digit is found, halt the conversion and
+ * return the portion which has been converted thus far.
+ */
+ if ('0' == c || '1' == c)
+ value = value * 2 + c - '0';
+ else
+ break;
+
+ any = 1;
+ }
+
+ /*
+ * As with many strtoX implementations, should the subject sequence be
+ * empty or not well-formed, no conversion is performed and the original
+ * value of str is stored in *endptr, provided that endptr is not a null
+ * pointer.
+ */
+ if (NULL != endptr) {
*endptr = (char *)(any ? s - 1 : str);
}
diff --git a/Zend/zend_strtod.h b/Zend/zend_strtod.h
index d6a5ca98f0..4516d203d5 100644
--- a/Zend/zend_strtod.h
+++ b/Zend/zend_strtod.h
@@ -27,9 +27,10 @@
BEGIN_EXTERN_C()
ZEND_API void zend_freedtoa(char *s);
ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve);
-ZEND_API double zend_strtod(const char *s00, char **se);
-ZEND_API double zend_hex_strtod(const char *str, char **endptr);
-ZEND_API double zend_oct_strtod(const char *str, char **endptr);
+ZEND_API double zend_strtod(const char *s00, const char **se);
+ZEND_API double zend_hex_strtod(const char *str, const char **endptr);
+ZEND_API double zend_oct_strtod(const char *str, const char **endptr);
+ZEND_API double zend_bin_strtod(const char *str, const char **endptr);
ZEND_API int zend_startup_strtod(void);
ZEND_API int zend_shutdown_strtod(void);
END_EXTERN_C()
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 89d91a518a..f33138aaae 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -55,7 +55,7 @@ typedef struct _zend_object_handlers zend_object_handlers;
typedef struct _zend_object_value {
zend_object_handle handle;
- zend_object_handlers *handlers;
+ const zend_object_handlers *handlers;
} zend_object_value;
#endif /* ZEND_TYPES_H */
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 2b2ca0f2d1..25a66a197c 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -79,7 +79,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
case IS_STRING:
case IS_CONSTANT:
CHECK_ZVAL_STRING_REL(zvalue);
- free(zvalue->value.str.val);
+ str_free(zvalue->value.str.val);
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
@@ -119,7 +119,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
case IS_CONSTANT:
case IS_STRING:
CHECK_ZVAL_STRING_REL(zvalue);
- zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
+ if (!IS_INTERNED(zvalue->value.str.val)) {
+ zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
+ }
break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
@@ -161,17 +163,6 @@ ZEND_API void _zval_dtor_wrapper(zval *zvalue)
zval_dtor(zvalue);
}
-ZEND_API void zval_property_ctor(zval **p) /* {{{ */
-{
- zval *orig_ptr = *p;
-
- ALLOC_ZVAL(*p);
- **p = *orig_ptr;
- zval_copy_ctor(*p);
- Z_SET_REFCOUNT_PP(p, 1);
- Z_UNSET_ISREF_PP(p);
-}
-/* }}} */
#if ZEND_DEBUG
ZEND_API void _zval_copy_ctor_wrapper(zval *zvalue)
@@ -198,6 +189,51 @@ ZEND_API void _zval_internal_ptr_dtor_wrapper(zval **zval_ptr)
}
#endif
+ZEND_API int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
+{
+ HashTable *target = va_arg(args, HashTable*);
+ zend_bool is_ref;
+ zval *tmp;
+
+ if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
+ is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF;
+
+ if (!EG(active_symbol_table)) {
+ zend_rebuild_symbol_table(TSRMLS_C);
+ }
+ if (zend_hash_quick_find(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) {
+ if (is_ref) {
+ ALLOC_INIT_ZVAL(tmp);
+ Z_SET_ISREF_P(tmp);
+ zend_hash_quick_add(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), (void**)&p);
+ } else {
+ tmp = EG(uninitialized_zval_ptr);
+ zend_error(E_NOTICE,"Undefined variable: %s", key->arKey);
+ }
+ } else {
+ if (is_ref) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
+ tmp = *p;
+ } else if (Z_ISREF_PP(p)) {
+ ALLOC_INIT_ZVAL(tmp);
+ ZVAL_COPY_VALUE(tmp, *p);
+ zval_copy_ctor(tmp);
+ Z_SET_REFCOUNT_P(tmp, 0);
+ Z_UNSET_ISREF_P(tmp);
+ } else {
+ tmp = *p;
+ }
+ }
+ } else {
+ tmp = *p;
+ }
+ if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), NULL) == SUCCESS) {
+ Z_ADDREF_P(tmp);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h
index 3159ae9ed0..eb9f0d22c7 100644
--- a/Zend/zend_variables.h
+++ b/Zend/zend_variables.h
@@ -27,7 +27,7 @@ BEGIN_EXTERN_C()
ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC);
-static inline void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
+static zend_always_inline void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
{
if (zvalue->type <= IS_BOOL) {
return;
@@ -37,7 +37,7 @@ static inline void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC);
-static inline void _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
+static zend_always_inline void _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
{
if (zvalue->type <= IS_BOOL) {
return;
@@ -45,6 +45,7 @@ static inline void _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
_zval_copy_ctor_func(zvalue ZEND_FILE_LINE_RELAY_CC);
}
+ZEND_API int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key);
ZEND_API int zend_print_variable(zval *var);
ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC);
@@ -76,17 +77,6 @@ ZEND_API void _zval_internal_ptr_dtor_wrapper(zval **zvalue);
ZEND_API void zval_add_ref(zval **p);
-ZEND_API void zval_property_ctor(zval **);
-
-#ifdef ZTS
-# define zval_shared_property_ctor zval_property_ctor
-#else
-# define zval_shared_property_ctor zval_add_ref
-#endif
-
-#define zval_copy_property_ctor(ce) ((copy_ctor_func_t) (((ce)->type == ZEND_INTERNAL_CLASS) ? zval_shared_property_ctor : zval_add_ref))
-
-
END_EXTERN_C()
#define ZVAL_DESTRUCTOR (void (*)(void *)) zval_dtor_wrapper
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 22d77dd79f..9d475a688c 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -27,299 +27,332 @@
ZEND_VM_HANDLER(1, ZEND_ADD, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(2, ZEND_SUB, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(3, ZEND_MUL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(4, ZEND_DIV, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(5, ZEND_MOD, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(6, ZEND_SL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(7, ZEND_SR, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(15, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(16, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC));
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC));
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(19, ZEND_IS_SMALLER, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC));
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(20, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC));
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(9, ZEND_BW_OR, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(10, ZEND_BW_AND, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(11, ZEND_BW_XOR, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(14, ZEND_BOOL_XOR, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(12, ZEND_BW_NOT, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_not_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ bitwise_not_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(13, ZEND_BOOL_NOT, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_not_function(&EX_T(opline->result.u.var).tmp_var,
+ SAVE_OPLINE();
+ boolean_not_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC))
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data1;
- zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
+ zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
zval *object;
zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (OP1_TYPE == IS_VAR && !object_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP2();
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -330,16 +363,16 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -349,7 +382,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -371,22 +404,22 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -401,17 +434,19 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
FREE_OP1_VAR_PTR();
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC))
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, binary_op);
@@ -419,21 +454,19 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
case ZEND_ASSIGN_DIM: {
zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (OP1_TYPE == IS_VAR && !OP1_FREE) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, binary_op);
} else {
- zend_op *op_data = opline+1;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, OP2_TYPE, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
@@ -444,23 +477,28 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
FREE_OP2();
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -472,17 +510,22 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
FREE_OP2();
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
+ FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+ FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
}
- FREE_OP1_VAR_PTR();
ZEND_VM_NEXT_OPCODE();
}
@@ -543,29 +586,35 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV)
ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV, incdec_t incdec_op)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
+ zval **object_ptr;
zval *object;
- zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (OP1_TYPE == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
FREE_OP2();
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -576,13 +625,13 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -591,9 +640,9 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -607,14 +656,14 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -625,6 +674,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
FREE_OP2();
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -640,26 +690,32 @@ ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV, incdec_t incdec_op)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
+ zval **object_ptr;
zval *object;
- zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (OP1_TYPE == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
FREE_OP2();
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -670,12 +726,12 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -685,10 +741,10 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -698,20 +754,19 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -721,6 +776,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
FREE_OP2();
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -736,171 +792,197 @@ ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ zval **var_ptr;
- if (OP1_TYPE == IS_VAR && !var_ptr) {
+ SAVE_OPLINE();
+ var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- increment_function(val);
+ fast_increment_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- increment_function(*var_ptr);
+ fast_increment_function(*var_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ zval **var_ptr;
+
+ SAVE_OPLINE();
+ var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && !var_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- decrement_function(val);
+ fast_decrement_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- decrement_function(*var_ptr);
+ fast_decrement_function(*var_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ zval **var_ptr, *retval;
- if (OP1_TYPE == IS_VAR && !var_ptr) {
+ SAVE_OPLINE();
+ var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr);
- }
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ ZVAL_NULL(&EX_T(opline->result.var).tmp_var);
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- EX_T(opline->result.u.var).tmp_var = **var_ptr;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, *var_ptr);
+ zendi_zval_copy_ctor(*retval);
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- increment_function(val);
+ fast_increment_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- increment_function(*var_ptr);
+ fast_increment_function(*var_ptr);
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ zval **var_ptr, *retval;
+
+ SAVE_OPLINE();
+ var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && !var_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (OP1_TYPE == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr);
- }
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ ZVAL_NULL(&EX_T(opline->result.var).tmp_var);
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- EX_T(opline->result.u.var).tmp_var = **var_ptr;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, *var_ptr);
+ zendi_zval_copy_ctor(*retval);
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- decrement_function(val);
+ fast_decrement_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- decrement_function(*var_ptr);
+ fast_decrement_function(*var_ptr);
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval z_copy;
- zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *z;
+
+ SAVE_OPLINE();
+ z = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE != IS_CONST &&
- Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
+ UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) &&
+ Z_OBJ_HT_P(z)->get_method != NULL) {
if (OP1_TYPE == IS_TMP_VAR) {
INIT_PZVAL(z);
}
@@ -915,46 +997,80 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
}
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(41, ZEND_PRINT, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
-
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG;
+ USE_OPLINE
+ ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ECHO);
}
-ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type)
+ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|VAR, int type)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *varname;
zval **retval;
zval tmp_varname;
HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- tmp_varname = *varname;
+ if (OP1_TYPE != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
convert_to_string(&tmp_varname);
varname = &tmp_varname;
}
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- retval = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0 TSRMLS_CC);
+ if (OP2_TYPE != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (OP2_TYPE == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (OP1_TYPE != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ FREE_OP1();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((OP1_TYPE == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
FREE_OP1();
} else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
/*
if (!target_symbol_table) {
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (OP1_TYPE == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@@ -966,17 +1082,14 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
/* break missing intentionally */
- case BP_VAR_W: {
- zval *new_zval = &EG(uninitialized_zval);
-
- Z_ADDREF_P(new_zval);
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
- }
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
- switch (opline->op2.u.EA.type) {
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
case ZEND_FETCH_GLOBAL:
if (OP1_TYPE != IS_TMP_VAR) {
FREE_OP1();
@@ -990,7 +1103,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
break;
case ZEND_FETCH_GLOBAL_LOCK:
if (OP1_TYPE == IS_VAR && !free_op1.var) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
break;
}
@@ -998,261 +1111,248 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
if (OP1_TYPE != IS_CONST && varname == &tmp_varname) {
- zval_dtor(varname);
+ zval_dtor(&tmp_varname);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- }
- PZVAL_LOCK(*retval);
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_IS:
- AI_SET_PTR(EX_T(opline->result.u.var).var, *retval);
- break;
- case BP_VAR_UNSET: {
- zend_free_op free_res;
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- }
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
- FREE_OP_VAR_PTR(free_res);
- break;
- default:
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- break;
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
}
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
}
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
}
-ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
}
-ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_RW);
}
-ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
+ USE_OPLINE
+
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type,
- ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)?BP_VAR_W:BP_VAR_R);
+ ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R);
}
-ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
}
-ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS);
}
ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
OP1_TYPE != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_W TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_RW TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS);
+ zval **container;
- if (OP1_TYPE == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_IS TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_W TSRMLS_CC);
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (OP2_TYPE == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
}
FREE_OP2();
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (OP1_TYPE == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, IS_OP2_TMP_FREE(), BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_UNSET TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HELPER_EX(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV, int type)
+ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = GET_OP1_OBJ_ZVAL_PTR(type);
+ zval *container;
zend_free_op free_op2;
- zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
+ offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
FREE_OP2();
} else {
zval *retval;
@@ -1262,18 +1362,10 @@ ZEND_VM_HELPER_EX(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&offset);
@@ -1283,138 +1375,184 @@ ZEND_VM_HELPER_EX(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|
}
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_property_address_read_helper, type, BP_VAR_R);
+ ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper);
}
ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+
if (OP1_TYPE == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
FREE_OP2();
}
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
-
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
FREE_OP2();
}
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_property_address_read_helper, type, BP_VAR_IS);
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
+ offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ FREE_OP2();
+ } else {
+ zval *retval;
+
+ if (IS_OP2_TMP_FREE()) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (IS_OP2_TMP_FREE()) {
+ zval_ptr_dtor(&offset);
+ } else {
+ FREE_OP2();
+ }
+ }
+
+ FREE_OP1();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
FREE_OP2();
}
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_property_address_read_helper, type, BP_VAR_R);
+ ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper);
}
}
ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_R);
- zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
+ property = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -1424,71 +1562,72 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (OP1_TYPE == IS_VAR && !container) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
FREE_OP2();
}
- if (OP1_TYPE == IS_VAR && OP1_FREE &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
FREE_OP1_VAR_PTR();
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(98, ZEND_FETCH_DIM_TMP_VAR, CONST|TMP, CONST)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *container;
- if (Z_TYPE_P(container) != IS_ARRAY) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zend_free_op free_op2;
- zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *value = *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
- AI_SET_PTR(EX_T(opline->result.u.var).var, *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC));
- SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr, &opline->result);
+ PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
FREE_OP2();
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
- zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W);
+ property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (OP1_TYPE == IS_VAR && !object_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property_name);
} else {
@@ -1496,18 +1635,21 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
}
FREE_OP1_VAR_PTR();
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
+ zval **object_ptr;
+
+ SAVE_OPLINE();
+ object_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && !object_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
@@ -1517,7 +1659,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property_name);
} else {
@@ -1529,28 +1671,44 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, OP2_TYPE, BP_VAR_W TSRMLS_CC);
FREE_OP2();
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -1558,34 +1716,55 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
}
FREE_OP1_VAR_PTR();
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *value = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zval **variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
-
- if (OP1_TYPE == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, OP2_TYPE TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ zval *value;
+ zval **variable_ptr_ptr;
+
+ SAVE_OPLINE();
+ value = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
+
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, OP2_TYPE TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (OP1_TYPE == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_OP2_TMP_FREE()) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_OP2_TMP_FREE() TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (OP2_TYPE == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (OP2_TYPE == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
@@ -1594,40 +1773,44 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
/* zend_assign_to_variable() always takes care of op2, never free it! */
FREE_OP2_IF_VAR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
zval **variable_ptr_ptr;
- zval **value_ptr_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
+ zval **value_ptr_ptr;
+
+ SAVE_OPLINE();
+ value_ptr_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
if (OP2_TYPE == IS_VAR &&
value_ptr_ptr &&
!Z_ISREF_PP(value_ptr_ptr) &&
opline->extended_value == ZEND_RETURNS_FUNCTION &&
- !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+ !EX_T(opline->op2.var).var.fcall_returned_reference) {
if (free_op2.var == NULL) {
PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
}
zend_error(E_STRICT, "Only variables should be assigned by reference");
if (UNEXPECTED(EG(exception) != NULL)) {
FREE_OP2_VAR_PTR();
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ASSIGN);
} else if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
PZVAL_LOCK(*value_ptr_ptr);
}
- if (OP1_TYPE == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr)) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if ((OP2_TYPE == IS_VAR && !value_ptr_ptr) ||
- (OP1_TYPE == IS_VAR && !variable_ptr_ptr)) {
+ if ((OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
+ (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
@@ -1636,47 +1819,53 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
Z_DELREF_PP(variable_ptr_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*variable_ptr_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *variable_ptr_ptr);
}
FREE_OP1_VAR_PTR();
FREE_OP2_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
{
+ USE_OPLINE
+
#if DEBUG_ZEND>=2
- printf("Jumping to %d\n", EX(opline)->op1.u.opline_num);
+ printf("Jumping to %d\n", opline->op1.opline_num);
#endif
- ZEND_VM_SET_OPCODE(EX(opline)->op1.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *val;
int ret;
- if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (!ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -1685,25 +1874,28 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY)
ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *val;
int ret;
- if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -1712,18 +1904,21 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMP|VAR|CV, ANY)
ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *val;
int retval;
- if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (EXPECTED(retval != 0)) {
@@ -1734,36 +1929,39 @@ ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY)
ZEND_VM_CONTINUE(); /* CHECK_ME */
} else {
#if DEBUG_ZEND>=2
- printf("Conditional jmp on false to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.u.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *val;
int retval;
- if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (!retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -1771,55 +1969,71 @@ ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|VAR|CV, ANY)
ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *val;
int retval;
- if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(70, ZEND_FREE, TMP, ANY)
+ZEND_VM_HANDLER(70, ZEND_FREE, TMP|VAR, ANY)
{
- zendi_zval_dtor(EX_T(EX(opline)->op1.u.var).tmp_var);
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ if (OP1_TYPE == IS_TMP_VAR) {
+ zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
+ } else {
+ zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+ }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
{
- zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *tmp = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
tmp->value.str.val = emalloc(1);
tmp->value.str.val[0] = 0;
tmp->value.str.len = 0;
Z_SET_REFCOUNT_P(tmp, 1);
tmp->type = IS_STRING;
Z_UNSET_ISREF_P(tmp);
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
{
- zend_op *opline = EX(opline);
- zval *str = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
if (OP1_TYPE == IS_UNUSED) {
/* Initialize for erealloc in add_char_to_string */
@@ -1830,16 +2044,19 @@ ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
INIT_PZVAL(str);
}
- add_char_to_string(str, str, &opline->op2.u.constant);
+ add_char_to_string(str, str, opline->op2.zv);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
{
- zend_op *opline = EX(opline);
- zval *str = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
if (OP1_TYPE == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
@@ -1850,21 +2067,25 @@ ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
INIT_PZVAL(str);
}
- add_string_to_string(str, str, &opline->op2.u.constant);
+ add_string_to_string(str, str, opline->op2.zv);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = GET_OP2_ZVAL_PTR(BP_VAR_R);
+
if (OP1_TYPE == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -1894,47 +2115,60 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV)
*/
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
+ SAVE_OPLINE();
+ EG(exception) = NULL;
if (OP2_TYPE == IS_UNUSED) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
zend_free_op free_op2;
zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP2_TYPE != IS_CONST && Z_TYPE_P(class_name) == IS_OBJECT) {
- EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+ if (OP2_TYPE == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+ }
+ } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
+ EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
}
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (OP2_TYPE != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
@@ -1943,25 +2177,37 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
EX(object) = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
+
+ if (OP2_TYPE != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
+
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (OP2_TYPE == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
}
-
- EX(called_scope) = Z_OBJCE_P(EX(object));
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
-
+
if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
EX(object) = NULL;
- } else {
+ } else {
if (!PZVAL_IS_REF(EX(object))) {
Z_ADDREF_P(EX(object)); /* For $this pointer */
} else {
@@ -1976,48 +2222,62 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
FREE_OP2();
FREE_OP1_IF_VAR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (OP1_TYPE == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
-
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ ce = EX_T(opline->op1.var).class_entry;
+
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(OP2_TYPE != IS_UNUSED) {
+
+ if (OP1_TYPE == IS_CONST &&
+ OP2_TYPE == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (OP1_TYPE != IS_CONST &&
+ OP2_TYPE == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (OP2_TYPE != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
zend_free_op free_op2;
if (OP2_TYPE == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -2029,22 +2289,30 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (OP2_TYPE == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (OP1_TYPE == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (OP2_TYPE != IS_CONST) {
FREE_OP2();
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -2057,18 +2325,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -2076,28 +2338,56 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
- char *function_name_strval, *lcname;
- int function_name_strlen;
- zend_free_op free_op2;
-
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (OP2_TYPE == IS_CONST) {
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ function_name = (zval*)(opline->op2.literal+1);
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ EX(object) = NULL;
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
} else {
+ char *function_name_strval, *lcname;
+ int function_name_strlen;
+ zend_free_op free_op2;
+
+ SAVE_OPLINE();
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
- Z_TYPE_P(function_name) == IS_OBJECT &&
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ function_name_strval = Z_STRVAL_P(function_name);
+ function_name_strlen = Z_STRLEN_P(function_name);
+ if (function_name_strval[0] == '\\') {
+ function_name_strlen -= 1;
+ lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ } else {
+ lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+ }
+ if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ }
+ efree(lcname);
+ FREE_OP2();
+ EX(object) = NULL;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
@@ -2110,46 +2400,101 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
} else {
FREE_OP2();
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
- }
+ } else if (OP2_TYPE != IS_CONST &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
+ zend_class_entry *ce;
+ zval **method = NULL;
+ zval **obj = NULL;
+
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
+
+ if (!obj || !method) {
+ zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
+ }
- if (Z_TYPE_P(function_name) != IS_STRING) {
- zend_error_noreturn(E_ERROR, "Function name must be a string");
- }
- function_name_strval = Z_STRVAL_P(function_name);
- function_name_strlen = Z_STRLEN_P(function_name);
- if (function_name_strval[0] == '\\') {
+ if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
+ }
+
+ if (Z_TYPE_PP(method) != IS_STRING) {
+ zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
+ }
+
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ EX(called_scope) = ce;
+ EX(object) = NULL;
+
+ if (ce->get_static_method) {
+ EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
+ } else {
+ EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ }
+ } else {
+ EX(object) = *obj;
+ ce = EX(called_scope) = Z_OBJCE_PP(obj);
+
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
+ }
+
+ if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ EX(object) = NULL;
+ } else {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
+ }
+ }
- function_name_strlen -= 1;
- lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
+ }
+ FREE_OP2();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
} else {
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- }
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- efree(lcname);
- FREE_OP2();
}
-
- EX(object) = NULL;
- ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline + 1;
+ USE_OPLINE
+ zend_literal *func_name;
- ZEND_VM_INC_OPCODE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc))==FAILURE) {
- char *short_name = Z_STRVAL(opline->op1.u.constant)+Z_LVAL(op_data->op1.u.constant);
- if (zend_hash_quick_find(EG(function_table), short_name, Z_STRLEN(opline->op1.u.constant)-Z_LVAL(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ func_name = opline->op2.literal + 1;
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
+ func_name++;
+ if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
EX(object) = NULL;
@@ -2164,8 +2509,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
EG(current_execute_data) = EX(prev_execute_data);
EG(opline_ptr) = NULL;
if (!EG(active_symbol_table)) {
- zval ***cv = EX(CVs);
- zval ***end = cv + EX(op_array)->last_var;
+ zval ***cv = EX_CVs();
+ zval ***end = cv + op_array->last_var;
while (cv != end) {
if (*cv) {
zval_ptr_dtor(*cv);
@@ -2173,43 +2518,49 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
cv++;
}
}
-
+
if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
zval_ptr_dtor((zval**)&op_array->prototype);
}
nested = EX(nested);
-
+
zend_vm_stack_free(execute_data TSRMLS_CC);
if (nested) {
execute_data = EG(current_execute_data);
+ }
+ if (nested) {
+ USE_OPLINE
- if (EX(call_opline)->opcode == ZEND_INCLUDE_OR_EVAL) {
+ LOAD_REGS();
+ LOAD_OPLINE();
+ if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
EX(object) = EX(current_object);
- if (RETURN_VALUE_USED(EX(call_opline))) {
- if (!EX_T(EX(call_opline)->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(EX(call_opline)->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(EX(call_opline)->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(EX(call_opline)->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(EX(call_opline)->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(op_array TSRMLS_CC);
efree(op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION_LEAVE();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
+ }
}
- EX(opline)++;
+ ZEND_VM_INC_OPCODE();
ZEND_VM_LEAVE();
} else {
@@ -2233,7 +2584,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
EX(function_state).arguments = NULL;
if (EG(This)) {
- if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) {
+ if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
if (IS_CTOR_USED(EX(called_scope))) {
Z_DELREF_P(EG(This));
}
@@ -2252,14 +2603,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
zend_vm_stack_clear_multiple(TSRMLS_C);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(EX(call_opline)) && EX_T(EX(call_opline)->result.u.var).var.ptr) {
- zval_ptr_dtor(&EX_T(EX(call_opline)->result.u.var).var.ptr);
+ if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
}
+ HANDLE_EXCEPTION_LEAVE();
}
- EX(opline)++;
+ ZEND_VM_INC_OPCODE();
ZEND_VM_LEAVE();
}
}
@@ -2268,89 +2620,99 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_bool should_change_scope = 0;
+ zend_function *fbc = EX(function_state).function;
- if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ SAVE_OPLINE();
+ if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
- EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
- EX(function_state).function->common.scope ? "::" : "",
- EX(function_state).function->common.function_name);
+ fbc->common.scope ? fbc->common.scope->name : "",
+ fbc->common.scope ? "::" : "",
+ fbc->common.function_name);
}
}
- if (EX(function_state).function->common.scope &&
- !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) &&
+ if (fbc->common.scope &&
+ !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
!EX(object)) {
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
- zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name);
} else {
/* FIXME: output identifiers properly */
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name);
}
}
- if (EX(function_state).function->type == ZEND_USER_FUNCTION ||
- EX(function_state).function->common.scope) {
+ if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
should_change_scope = 1;
EX(current_this) = EG(This);
EX(current_scope) = EG(scope);
EX(current_called_scope) = EG(called_scope);
EG(This) = EX(object);
- EG(scope) = (EX(function_state).function->type == ZEND_USER_FUNCTION || !EX(object)) ? EX(function_state).function->common.scope : NULL;
+ EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
EG(called_scope) = EX(called_scope);
}
zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc));
EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC);
+ LOAD_OPLINE();
+
+ if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+ temp_variable *ret = &EX_T(opline->result.var);
- if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
- ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr);
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference;
+ MAKE_STD_ZVAL(ret->var.ptr);
+ ZVAL_NULL(ret->var.ptr);
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
- if (EX(function_state).function->common.arg_info) {
+ if (fbc->common.arg_info) {
zend_uint i=0;
zval **p = (zval**)EX(function_state).arguments;
ulong arg_count = opline->extended_value;
while (arg_count>0) {
- zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count), 0 TSRMLS_CC);
+ zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC);
arg_count--;
}
}
+
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
- ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common.return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(EXECUTE_DATA, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ zval_ptr_dtor(&ret->var.ptr);
}
- } else if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
+ } else if (fbc->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
EG(active_symbol_table) = NULL;
- EG(active_op_array) = &EX(function_state).function->op_array;
+ EG(active_op_array) = &fbc->op_array;
EG(return_value_ptr_ptr) = NULL;
- if (RETURN_VALUE_USED(opline)) {
- EG(return_value_ptr_ptr) = &EX_T(opline->result.u.var).var.ptr;
- EX_T(opline->result.u.var).var.ptr = NULL;
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference;
+ if (RETURN_VALUE_USED(opline)) {
+ temp_variable *ret = &EX_T(opline->result.var);
+
+ ret->var.ptr = NULL;
+ EG(return_value_ptr_ptr) = &ret->var.ptr;
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
}
- if (zend_execute == execute && !EG(exception)) {
- EX(call_opline) = opline;
- ZEND_VM_ENTER();
+ if (EXPECTED(zend_execute == execute)) {
+ if (EXPECTED(EG(exception) == NULL)) {
+ ZEND_VM_ENTER();
+ }
} else {
zend_execute(EG(active_op_array) TSRMLS_CC);
}
@@ -2371,27 +2733,28 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
- ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr);
+ MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
+ ZVAL_NULL(EX_T(opline->result.var).var.ptr);
/* Not sure what should be done here if it's a static method */
- if (EX(object)) {
- Z_OBJ_HT_P(EX(object))->call_method(EX(function_state).function->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ if (EXPECTED(EX(object) != NULL)) {
+ Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
- if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- efree(EX(function_state).function->common.function_name);
+ if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+ efree((char*)fbc->common.function_name);
}
- efree(EX(function_state).function);
+ efree(fbc);
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
} else {
- Z_UNSET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
+ Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
+ Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
+ EX_T(opline->result.var).var.fcall_returned_reference = 0;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
}
@@ -2400,7 +2763,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (should_change_scope) {
if (EG(This)) {
- if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) {
+ if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
if (IS_CTOR_USED(EX(called_scope))) {
Z_DELREF_P(EG(This));
}
@@ -2420,11 +2783,12 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
zend_vm_stack_clear_multiple(TSRMLS_C);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline) && EX_T(opline->result.u.var).var.ptr) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
}
+ HANDLE_EXCEPTION();
}
ZEND_VM_NEXT_OPCODE();
@@ -2438,14 +2802,19 @@ ZEND_VM_HANDLER(61, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- if (zend_hash_quick_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, Z_LVAL(opline->op2.u.constant), (void **) &EX(function_state).function)==FAILURE) {
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
+ SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
+ } else {
+ CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function);
}
EX(object) = NULL;
@@ -2456,34 +2825,100 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval *retval_ptr;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (!EG(return_value_ptr_ptr)) {
+ if (OP1_TYPE == IS_TMP_VAR) {
+ FREE_OP1();
+ }
+ } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
+ if (OP1_TYPE == IS_CONST ||
+ (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
+ retval_ptr == &EG(uninitialized_zval)) {
+ zval *ret;
+
+ ALLOC_INIT_ZVAL(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ } else {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
+ FREE_OP1_IF_VAR();
+ ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
+}
+
+ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
+{
+ USE_OPLINE
zval *retval_ptr;
zval **retval_ptr_ptr;
zend_free_op free_op1;
- if (EG(active_op_array)->return_reference == ZEND_RETURN_REF) {
+ SAVE_OPLINE();
+ do {
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
- ZEND_VM_C_GOTO(return_by_value);
+
+ retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ if (!EG(return_value_ptr_ptr)) {
+ if (OP1_TYPE == IS_TMP_VAR) {
+ FREE_OP1();
+ }
+ } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
+ break;
}
retval_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && !retval_ptr_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
if (OP1_TYPE == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference) {
- } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
- if (OP1_TYPE == IS_VAR && !OP1_FREE) {
- PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
- }
+ EX_T(opline->op1.var).var.fcall_returned_reference) {
+ } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
zend_error(E_NOTICE, "Only variable references should be returned by reference");
- ZEND_VM_C_GOTO(return_by_value);
+ if (EG(return_value_ptr_ptr)) {
+ retval_ptr = *retval_ptr_ptr;
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ break;
}
}
@@ -2491,59 +2926,25 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
Z_ADDREF_PP(retval_ptr_ptr);
- (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+ *EG(return_value_ptr_ptr) = *retval_ptr_ptr;
}
- } else {
-ZEND_VM_C_LABEL(return_by_value):
-
- retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
-
- if (!EG(return_value_ptr_ptr)) {
- if (OP1_TYPE == IS_TMP_VAR) {
- FREE_OP1();
- }
- } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
- if (OP1_TYPE == IS_CONST ||
- EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
- (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
- zval *ret;
-
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- zval_copy_ctor(ret);
- *EG(return_value_ptr_ptr) = ret;
- } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
- retval_ptr == &EG(uninitialized_zval)) {
- zval *ret;
+ } while (0);
- ALLOC_INIT_ZVAL(ret);
- *EG(return_value_ptr_ptr) = ret;
- } else {
- *EG(return_value_ptr_ptr) = retval_ptr;
- Z_ADDREF_P(retval_ptr);
- }
- } else {
- zval *ret;
-
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- *EG(return_value_ptr_ptr) = ret;
- }
- }
FREE_OP1_IF_VAR();
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *value;
zval *exception;
zend_free_op free_op1;
+ SAVE_OPLINE();
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_CONST || Z_TYPE_P(value) != IS_OBJECT) {
+ if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
zend_exception_save(TSRMLS_C);
@@ -2557,53 +2958,77 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
zend_throw_exception_object(exception TSRMLS_CC);
zend_exception_restore(TSRMLS_C);
FREE_OP1_IF_VAR();
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
-ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, CV)
+ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
{
- zend_op *opline = EX(opline);
- zend_class_entry *ce;
+ USE_OPLINE
+ zend_class_entry *ce, *catch_ce;
+ zval *exception;
+ SAVE_OPLINE();
/* Check whether an exception has been thrown, if not, jump over code */
zend_exception_restore(TSRMLS_C);
if (EG(exception) == NULL) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ catch_ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
+
+ CACHE_PTR(opline->op1.literal->cache_slot, catch_ce);
+ }
ce = Z_OBJCE_P(EG(exception));
- if (ce != EX_T(opline->op1.u.var).class_entry) {
- if (!instanceof_function(ce, EX_T(opline->op1.u.var).class_entry TSRMLS_CC)) {
- if (opline->op1.u.EA.type) {
+
+#ifdef HAVE_DTRACE
+ if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
+ DTRACE_EXCEPTION_CAUGHT(ce->name);
+ }
+#endif /* HAVE_DTRACE */
+
+ if (ce != catch_ce) {
+ if (!instanceof_function(ce, catch_ce TSRMLS_CC)) {
+ if (opline->result.num) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
+ exception = EG(exception);
if (!EG(active_symbol_table)) {
- if (EX(CVs)[opline->op2.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op2.u.var]);
+ if (EX_CV(opline->op2.var)) {
+ zval_ptr_dtor(EX_CV(opline->op2.var));
}
- EX(CVs)[opline->op2.u.var] = (zval**)EX(CVs) + (EX(op_array)->last_var + opline->op2.u.var);
- *EX(CVs)[opline->op2.u.var] = EG(exception);
+ EX_CV(opline->op2.var) = (zval**)EX_CVs() + (EX(op_array)->last_var + opline->op2.var);
+ *EX_CV(opline->op2.var) = EG(exception);
} else {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.var);
zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value,
- &EG(exception), sizeof(zval *), (void**)&EX(CVs)[opline->op2.u.var]);
+ &EG(exception), sizeof(zval *), (void**)&EX_CV(opline->op2.var));
+ }
+ if (UNEXPECTED(EG(exception) != exception)) {
+ Z_ADDREF_P(EG(exception));
+ HANDLE_EXCEPTION();
+ } else {
+ EG(exception) = NULL;
+ ZEND_VM_NEXT_OPCODE();
}
- EG(exception) = NULL;
- ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
- && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
- zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
+ && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
+ zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num);
}
{
zval *valptr;
@@ -2620,12 +3045,13 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP|VAR|CV, ANY)
zend_vm_stack_push(valptr TSRMLS_CC);
FREE_OP1_IF_VAR();
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *varptr;
zend_free_op free_op1;
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
@@ -2638,7 +3064,7 @@ ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
zval *original_var = varptr;
ALLOC_ZVAL(varptr);
- *varptr = *original_var;
+ ZVAL_COPY_VALUE(varptr, original_var);
Z_UNSET_ISREF_P(varptr);
Z_SET_REFCOUNT_P(varptr, 0);
zval_copy_ctor(varptr);
@@ -2647,34 +3073,36 @@ ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
zend_vm_stack_push(varptr TSRMLS_CC);
FREE_OP1(); /* for string offsets */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *varptr;
+ SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
- } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
if (OP1_TYPE == IS_VAR &&
(opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference &&
- EX_T(opline->op1.u.var).var.ptr) {
- varptr = EX_T(opline->op1.u.var).var.ptr;
+ EX_T(opline->op1.var).var.fcall_returned_reference &&
+ EX_T(opline->op1.var).var.ptr) {
+ varptr = EX_T(opline->op1.var).var.ptr;
PZVAL_UNLOCK_EX(varptr, &free_op1, 0);
} else {
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
}
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
- EX_T(opline->op1.u.var).var.fcall_returned_reference) &&
+ EX_T(opline->op1.var).var.fcall_returned_reference) &&
varptr != &EG(uninitialized_zval) &&
(PZVAL_IS_REF(varptr) ||
(Z_REFCOUNT_P(varptr) == 1 && (OP1_TYPE == IS_CV || free_op1.var)))) {
@@ -2686,7 +3114,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
- !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
ALLOC_ZVAL(valptr);
@@ -2697,28 +3125,32 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
zend_vm_stack_push(valptr TSRMLS_CC);
}
FREE_OP1_IF_VAR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval **varptr_ptr;
zval *varptr;
+
+ SAVE_OPLINE();
varptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (OP1_TYPE == IS_VAR && !varptr_ptr) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
- if (OP1_TYPE == IS_VAR && *varptr_ptr == EG(error_zval_ptr)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(*varptr_ptr == &EG(error_zval))) {
ALLOC_INIT_ZVAL(varptr);
zend_vm_stack_push(varptr TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
@@ -2728,68 +3160,77 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
zend_vm_stack_push(varptr TSRMLS_CC);
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME)
- && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
}
+ SAVE_OPLINE();
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
{
- zend_op *opline = EX(opline);
- zend_uint arg_num = Z_LVAL(opline->op1.u.constant);
+ USE_OPLINE
+ zend_uint arg_num = opline->op1.num;
zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
- if (param == NULL) {
- char *space;
- char *class_name = get_active_class_name(&space TSRMLS_CC);
- zend_execute_data *ptr = EX(prev_execute_data);
-
+ SAVE_OPLINE();
+ if (UNEXPECTED(param == NULL)) {
if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
+ const char *space;
+ const char *class_name;
+ zend_execute_data *ptr;
+
+ if (EG(active_op_array)->scope) {
+ class_name = EG(active_op_array)->scope->name;
+ space = "::";
+ } else {
+ class_name = space = "";
+ }
+ ptr = EX(prev_execute_data);
+
if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s()", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C));
}
}
- if (opline->result.op_type == IS_VAR) {
- PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
- }
} else {
- zend_free_op free_res;
zval **var_ptr;
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
- var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
*var_ptr = *param;
Z_ADDREF_PP(var_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *assignment_value;
- zend_uint arg_num = Z_LVAL(opline->op1.u.constant);
- zend_free_op free_res;
+ zend_uint arg_num = opline->op1.num;
zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
zval **var_ptr;
+ SAVE_OPLINE();
if (param == NULL) {
ALLOC_ZVAL(assignment_value);
- *assignment_value = opline->op2.u.constant;
- if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
+ *assignment_value = *opline->op2.zv;
+ if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
+ Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
} else {
@@ -2802,46 +3243,49 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
}
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
- var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
*var_ptr = assignment_value;
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
+ zval *retval = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
/* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = i_zend_is_true(GET_OP1_ZVAL_PTR(BP_VAR_R));
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ ZVAL_BOOL(retval, i_zend_is_true(GET_OP1_ZVAL_PTR(BP_VAR_R)));
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
+ USE_OPLINE
zend_brk_cont_element *el;
- el = zend_brk_cont(GET_OP2_ZVAL_PTR(BP_VAR_R), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
+ SAVE_OPLINE();
+ el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
+ EX(op_array), EX_Ts() TSRMLS_CC);
FREE_OP2();
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
-ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
+ USE_OPLINE
zend_brk_cont_element *el;
- el = zend_brk_cont(GET_OP2_ZVAL_PTR(BP_VAR_R), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
+ SAVE_OPLINE();
+ el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
+ EX(op_array), EX_Ts() TSRMLS_CC);
FREE_OP2();
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
@@ -2849,102 +3293,91 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST|TMP|VAR|CV)
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
{
zend_op *brk_opline;
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_brk_cont_element *el;
- el = zend_brk_cont(&opline->op2.u.constant, opline->extended_value,
- EX(op_array), EX(Ts) TSRMLS_CC);
+ SAVE_OPLINE();
+ el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
+ EX(op_array), EX_Ts() TSRMLS_CC);
brk_opline = EX(op_array)->opcodes + el->brk;
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
}
break;
case ZEND_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
}
break;
}
- ZEND_VM_JMP(opline->op1.u.jmp_addr);
+ ZEND_VM_JMP(opline->op1.jmp_addr);
}
ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
if (OP1_TYPE==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
FREE_OP2();
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- FREE_OP1();
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(49, ZEND_SWITCH_FREE, VAR, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zend_switch_free(&EX_T(opline->op1.u.var), opline->extended_value TSRMLS_CC);
+ SAVE_OPLINE();
+ zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *object_zval;
zend_function *constructor;
- if (EX_T(opline->op1.u.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
- char *class_type;
-
- if (EX_T(opline->op1.u.var).class_entry->ce_flags & ZEND_ACC_INTERFACE) {
- class_type = "interface";
+ SAVE_OPLINE();
+ if (UNEXPECTED((EX_T(opline->op1.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+ if (EX_T(opline->op1.var).class_entry->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", EX_T(opline->op1.var).class_entry->name);
+ } else if ((EX_T(opline->op1.var).class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", EX_T(opline->op1.var).class_entry->name);
} else {
- class_type = "abstract class";
+ zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", EX_T(opline->op1.var).class_entry->name);
}
- zend_error_noreturn(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(opline->op1.u.var).class_entry->name);
}
ALLOC_ZVAL(object_zval);
- object_init_ex(object_zval, EX_T(opline->op1.u.var).class_entry);
+ object_init_ex(object_zval, EX_T(opline->op1.var).class_entry);
INIT_PZVAL(object_zval);
constructor = Z_OBJ_HT_P(object_zval)->get_constructor(object_zval TSRMLS_CC);
if (constructor == NULL) {
if (RETURN_VALUE_USED(opline)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval);
+ AI_SET_PTR(&EX_T(opline->result.var), object_zval);
} else {
zval_ptr_dtor(&object_zval);
}
- ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num);
} else {
if (RETURN_VALUE_USED(opline)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval);
PZVAL_LOCK(object_zval);
+ AI_SET_PTR(&EX_T(opline->result.var), object_zval);
}
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline)));
@@ -2952,31 +3385,34 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
/* We are not handling overloaded classes right now */
EX(object) = object_zval;
EX(fbc) = constructor;
- EX(called_scope) = EX_T(opline->op1.u.var).class_entry;
+ EX(called_scope) = EX_T(opline->op1.var).class_entry;
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *obj = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
+ zval *obj;
zend_class_entry *ce;
zend_function *clone;
zend_object_clone_obj_t clone_call;
+ SAVE_OPLINE();
+ obj = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
+
if (OP1_TYPE == IS_CONST ||
- (OP1_TYPE == IS_VAR && !obj) ||
- Z_TYPE_P(obj) != IS_OBJECT) {
+ UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
}
ce = Z_OBJCE_P(obj);
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
- if (!clone_call) {
+ if (UNEXPECTED(clone_call == NULL)) {
if (ce) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
} else {
@@ -2988,55 +3424,71 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (ce != EG(scope)) {
+ if (UNEXPECTED(ce != EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(clone->common.scope, EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
}
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (!EG(exception)) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_OBJVAL_P(EX_T(opline->result.u.var).var.ptr) = clone_call(obj TSRMLS_CC);
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT;
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- Z_SET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- if (!RETURN_VALUE_USED(opline) || EG(exception)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (EXPECTED(EG(exception) == NULL)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ Z_OBJVAL_P(retval) = clone_call(obj TSRMLS_CC);
+ Z_TYPE_P(retval) = IS_OBJECT;
+ Z_SET_REFCOUNT_P(retval, 1);
+ Z_SET_ISREF_P(retval);
+ if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor(&retval);
+ } else {
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
}
FREE_OP1_IF_VAR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ SAVE_OPLINE();
if (OP1_TYPE == IS_UNUSED) {
- /* namespaced constant */
- if (!zend_get_constant_ex(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) {
+ zend_constant *c;
+ zval *retval;
+
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ c = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL(opline->op2.u.constant), '\\', Z_STRLEN(opline->op2.u.constant));
+ char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
if(!actual) {
- actual = Z_STRVAL(opline->op2.u.constant);
+ actual = Z_STRVAL_P(opline->op2.zv);
} else {
actual++;
}
/* non-qualified constant - allow text substitution */
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- ZVAL_STRINGL(&EX_T(opline->result.u.var).tmp_var, actual, Z_STRLEN(opline->op2.u.constant)-(actual - Z_STRVAL(opline->op2.u.constant)), 1);
+ ZVAL_STRINGL(&EX_T(opline->result.var).tmp_var, actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv)), 1);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
} else {
- zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
- Z_STRVAL(opline->op2.u.constant), Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, c);
}
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, &c->value);
+ zval_copy_ctor(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
@@ -3044,19 +3496,33 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zval **value;
if (OP1_TYPE == IS_CONST) {
-
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ value = CACHED_PTR(opline->op2.literal->cache_slot);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
+ if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
}
- if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+ if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
@@ -3065,52 +3531,47 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
- EX_T(opline->result.u.var).tmp_var = **value;
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ if (OP1_TYPE == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, value);
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+ }
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1, free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zend_free_op free_op1;
zval *expr_ptr;
- zval *offset=GET_OP2_ZVAL_PTR(BP_VAR_R);
-#if !defined(ZEND_VM_SPEC) || OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
- if (opline->extended_value) {
- expr_ptr_ptr=GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
expr_ptr=GET_OP1_ZVAL_PTR(BP_VAR_R);
- }
-#else
- expr_ptr=GET_OP1_ZVAL_PTR(BP_VAR_R);
-#endif
-
- if (IS_OP1_TMP_FREE()) { /* temporary variable */
- zval *new_expr;
+ if (IS_OP1_TMP_FREE()) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if !defined(ZEND_VM_SPEC) || OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (OP1_TYPE == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (OP1_TYPE == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -3121,20 +3582,37 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (OP2_TYPE != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ ZEND_VM_C_GOTO(num_index);
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+ZEND_VM_C_LABEL(num_index):
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (OP2_TYPE == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, ZEND_VM_C_GOTO(num_index));
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -3144,21 +3622,22 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
}
FREE_OP2();
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && opline->extended_value) {
FREE_OP1_VAR_PTR();
} else {
FREE_OP1_IF_VAR();
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (OP1_TYPE == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if !defined(ZEND_VM_SPEC) || OP1_TYPE != IS_UNUSED
@@ -3170,13 +3649,16 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|UNUS
ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *expr;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
+ expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (opline->extended_value != IS_STRING) {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!IS_OP1_TMP_FREE()) {
zendi_zval_copy_ctor(*result);
}
@@ -3200,12 +3682,12 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
zend_make_printable_zval(expr, &var_copy, &use_copy);
if (use_copy) {
- *result = var_copy;
+ ZVAL_COPY_VALUE(result, &var_copy);
if (IS_OP1_TMP_FREE()) {
FREE_OP1();
}
} else {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!IS_OP1_TMP_FREE()) {
zendi_zval_copy_ctor(*result);
}
@@ -3220,37 +3702,38 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
break;
}
FREE_OP1_IF_VAR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_op_array *new_op_array=NULL;
- int return_value_used;
zend_free_op free_op1;
- zval *inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R);
- zval *tmp_inc_filename = NULL;
+ zval *inc_filename;
+ zval *tmp_inc_filename = NULL;
zend_bool failure_retval=0;
+ SAVE_OPLINE();
+ inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
if (inc_filename->type!=IS_STRING) {
MAKE_STD_ZVAL(tmp_inc_filename);
- *tmp_inc_filename = *inc_filename;
+ ZVAL_COPY_VALUE(tmp_inc_filename, inc_filename);
zval_copy_ctor(tmp_inc_filename);
convert_to_string(tmp_inc_filename);
inc_filename = tmp_inc_filename;
}
- return_value_used = RETURN_VALUE_USED(opline);
-
- if (Z_LVAL(opline->op2.u.constant) != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE || Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE) {
+ if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
} else {
- switch (Z_LVAL(opline->op2.u.constant)) {
+ switch (opline->extended_value) {
case ZEND_INCLUDE_ONCE:
case ZEND_REQUIRE_ONCE: {
zend_file_handle file_handle;
@@ -3272,14 +3755,14 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
}
if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1)==SUCCESS) {
- new_op_array = zend_compile_file(&file_handle, (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
+ new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
zend_file_handle_dtor(&file_handle TSRMLS_CC);
failure_retval=1;
}
} else {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
@@ -3292,7 +3775,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
- new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -3308,12 +3791,18 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
zval_ptr_dtor(&tmp_inc_filename);
}
FREE_OP1();
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (new_op_array && !EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ } else if (EXPECTED(new_op_array != NULL)) {
EX(original_return_value) = EG(return_value_ptr_ptr);
- EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
EG(active_op_array) = new_op_array;
- EX_T(opline->result.u.var).var.ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.var).var.ptr = NULL;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ EG(return_value_ptr_ptr) = EX_T(opline->result.var).var.ptr_ptr;
+ } else {
+ EG(return_value_ptr_ptr) = NULL;
+ }
EX(current_object) = EX(object);
@@ -3324,8 +3813,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
zend_rebuild_symbol_table(TSRMLS_C);
}
- if (zend_execute == execute) {
- EX(call_opline) = opline;
+ if (EXPECTED(zend_execute == execute)) {
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array TSRMLS_CC);
@@ -3334,75 +3822,64 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
EX(function_state).function = (zend_function *) EX(op_array);
EX(object) = EX(current_object);
- if (return_value_used) {
- if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
+ }
}
- } else {
- if (return_value_used) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_ZVAL(*EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = failure_retval;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
+
+ } else if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, failure_retval);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval tmp, *varname;
HashTable *target_symbol_table;
zend_free_op free_op1;
- if (OP1_TYPE == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
+ SAVE_OPLINE();
+ if (OP1_TYPE == IS_CV &&
+ OP2_TYPE == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
if (EG(active_symbol_table)) {
- zend_execute_data *ex = EX(prev_execute_data);
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_del(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) {
- while (ex && ex->symbol_table == EG(active_symbol_table)) {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == cv->hash_value &&
- ex->op_array->vars[i].name_len == cv->name_len &&
- !memcmp(ex->op_array->vars[i].name, cv->name, cv->name_len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- }
- }
- EX(CVs)[opline->op1.u.var] = NULL;
- } else if (EX(CVs)[opline->op1.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op1.u.var]);
- EX(CVs)[opline->op1.u.var] = NULL;
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
+ if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
varname = &tmp;
@@ -3410,49 +3887,57 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY)
Z_ADDREF_P(varname);
}
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
- } else {
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
-
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_quick_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value) == SUCCESS) {
- zend_execute_data *ex = EXECUTE_DATA;
+ if (OP2_TYPE != IS_UNUSED) {
+ zend_class_entry *ce;
- do {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
+ if (OP2_TYPE == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (OP1_TYPE != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+ zval_ptr_dtor(&varname);
}
+ FREE_OP1();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ex = ex->prev_execute_data;
- } while (ex && ex->symbol_table == target_symbol_table);
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
}
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((OP1_TYPE == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(EXECUTE_DATA, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
}
- if (varname == &tmp) {
+ if (OP1_TYPE != IS_CONST && varname == &tmp) {
zval_dtor(&tmp);
} else if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
zval_ptr_dtor(&varname);
}
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
if (OP1_TYPE == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
@@ -3465,37 +3950,40 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = EXECUTE_DATA; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (OP2_TYPE == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, ZEND_VM_C_GOTO(num_index_dim));
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+ZEND_VM_C_LABEL(num_index_dim):
+ zend_hash_index_del(ht, hval);
if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -3511,7 +3999,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (IS_OP2_TMP_FREE()) {
@@ -3536,15 +4024,20 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
- zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
+ offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE != IS_VAR || container) {
if (OP1_TYPE == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -3555,7 +4048,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -3572,12 +4065,13 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
@@ -3585,14 +4079,18 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
zend_class_entry *ce = NULL;
zend_bool is_empty = 0;
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ SAVE_OPLINE();
+
+ if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
+ (opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
array_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) {
- ALLOC_INIT_ZVAL(array_ptr);
+ MAKE_STD_ZVAL(array_ptr);
+ ZVAL_NULL(array_ptr);
} else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) {
if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) {
zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
ce = Z_OBJCE_PP(array_ptr_ptr);
@@ -3630,7 +4128,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
if (!ce || !ce->get_iterator) {
Z_ADDREF_P(array_ptr);
}
- } else if (OP1_TYPE == IS_CONST ||
+ } else if (OP1_TYPE == IS_CONST ||
((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
!Z_ISREF_P(array_ptr) &&
Z_REFCOUNT_P(array_ptr) > 1)) {
@@ -3648,50 +4146,35 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
if (ce && ce->get_iterator) {
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_RESET_REFERENCE TSRMLS_CC);
- if (iter && !EG(exception)) {
+ if (iter && EXPECTED(EG(exception) == NULL)) {
array_ptr = zend_iterator_wrap(iter TSRMLS_CC);
} else {
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- FREE_OP1_VAR_PTR();
- } else {
- FREE_OP1_IF_VAR();
- }
+ FREE_OP1_IF_VAR();
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
- AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr);
- PZVAL_LOCK(array_ptr);
+ EX_T(opline->result.var).fe.ptr = array_ptr;
if (iter) {
iter->index = 0;
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- FREE_OP1_VAR_PTR();
- } else {
- FREE_OP1_IF_VAR();
- }
- ZEND_VM_NEXT_OPCODE();
+ FREE_OP1_IF_VAR();
+ HANDLE_EXCEPTION();
}
}
is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- FREE_OP1_VAR_PTR();
- } else {
- FREE_OP1_IF_VAR();
- }
- ZEND_VM_NEXT_OPCODE();
+ FREE_OP1_IF_VAR();
+ HANDLE_EXCEPTION();
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
@@ -3714,29 +4197,26 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
}
}
is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->result.var).fe.fe_pos);
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- FREE_OP1_VAR_PTR();
- } else {
- FREE_OP1_IF_VAR();
- }
+ FREE_OP1_IF_VAR();
if (is_empty) {
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
} else {
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *array = EX_T(opline->op1.u.var).var.ptr;
+ zval *array = EX_T(opline->op1.var).fe.ptr;
zval **value;
char *str_key;
uint str_key_len;
@@ -3746,22 +4226,24 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
int key_type = 0;
zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY);
+ SAVE_OPLINE();
+
switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
default:
case ZEND_ITER_INVALID:
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
case ZEND_ITER_PLAIN_OBJECT: {
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
- fe_ht = HASH_OF(array);
- zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ fe_ht = Z_OBJPROP_P(array);
+ zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
do {
if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
/* reached end of iteration */
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
@@ -3769,7 +4251,7 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
} while (key_type == HASH_KEY_NON_EXISTANT ||
(key_type != HASH_KEY_IS_LONG &&
zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
- zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
if (use_key && key_type != HASH_KEY_IS_LONG) {
zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
str_key_len = strlen(prop_name);
@@ -3780,17 +4262,17 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
}
case ZEND_ITER_PLAIN_ARRAY:
- fe_ht = HASH_OF(array);
- zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ fe_ht = Z_ARRVAL_P(array);
+ zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
/* reached end of iteration */
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
}
zend_hash_move_forward(fe_ht);
- zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
break;
case ZEND_ITER_OBJECT:
@@ -3799,39 +4281,35 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
/* This could cause an endless loop if index becomes zero again.
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
/* If index is zero we come from FE_RESET and checked valid() already. */
if (!iter || (iter->index > 0 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) {
/* reached end of iteration */
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
iter->funcs->get_current_data(iter, &value TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
if (!value) {
/* failure in get_current_data */
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
if (iter->funcs->get_current_key) {
key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
} else {
key_type = HASH_KEY_IS_LONG;
@@ -3844,20 +4322,19 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
SEPARATE_ZVAL_IF_NOT_REF(value);
Z_SET_ISREF_PP(value);
- EX_T(opline->result.u.var).var.ptr_ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = value;
Z_ADDREF_PP(value);
} else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *value);
PZVAL_LOCK(*value);
+ AI_SET_PTR(&EX_T(opline->result.var), *value);
}
if (use_key) {
- zend_op *op_data = opline+1;
- zval *key = &EX_T(op_data->result.u.var).tmp_var;
+ zval *key = &EX_T((opline+1)->result.var).tmp_var;
switch (key_type) {
case HASH_KEY_IS_STRING:
- Z_STRVAL_P(key) = str_key;
+ Z_STRVAL_P(key) = (char*)str_key;
Z_STRLEN_P(key) = str_key_len-1;
Z_TYPE_P(key) = IS_STRING;
break;
@@ -3872,26 +4349,30 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
}
}
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval **value;
zend_bool isset = 1;
- if (OP1_TYPE == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EX(CVs)[opline->op1.u.var]) {
- value = EX(CVs)[opline->op1.u.var];
+ SAVE_OPLINE();
+ if (OP1_TYPE == IS_CV &&
+ OP2_TYPE == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
} else if (EG(active_symbol_table)) {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
isset = 0;
}
- } else {
+ } else {
isset = 0;
}
} else {
@@ -3899,183 +4380,206 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY)
zend_free_op free_op1;
zval tmp, *varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
+ if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
varname = &tmp;
}
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1 TSRMLS_CC);
+ if (OP2_TYPE != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (OP2_TYPE == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((OP1_TYPE == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
if (!value) {
isset = 0;
}
} else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
- if (varname == &tmp) {
+ if (OP1_TYPE != IS_CONST && varname == &tmp) {
zval_dtor(&tmp);
}
FREE_OP1();
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value & ZEND_ISSET_ISEMPTY_MASK) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|TMP|VAR|CV, int prop_dim)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval **container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_IS);
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (OP1_TYPE != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
-
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ SAVE_OPLINE();
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_IS);
- ht = Z_ARRVAL_PP(container);
+ offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- break;
- }
+ ht = Z_ARRVAL_PP(container);
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ ZEND_VM_C_GOTO(num_index_prop);
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+ZEND_VM_C_LABEL(num_index_prop):
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (OP2_TYPE == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, ZEND_VM_C_GOTO(num_index_prop));
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- FREE_OP2();
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (IS_OP2_TMP_FREE()) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ FREE_OP2();
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (IS_OP2_TMP_FREE()) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (IS_OP2_TMP_FREE()) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- FREE_OP2();
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (IS_OP2_TMP_FREE()) {
+ zval_ptr_dtor(&offset);
+ } else {
+ FREE_OP2();
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- FREE_OP2();
- } else {
- FREE_OP2();
}
+ FREE_OP2();
+ } else {
+ FREE_OP2();
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
FREE_OP1_VAR_PTR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -4092,7 +4596,9 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|C
ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP|VAR|UNUSED|CV, ANY)
{
#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (OP1_TYPE != IS_UNUSED) {
zend_free_op free_op1;
zval *ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
@@ -4106,169 +4612,301 @@ ZEND_VM_HANDLER(79, ZEND_EXIT, CONST|TMP|VAR|UNUSED|CV, ANY)
}
#endif
zend_bailout();
- ZEND_VM_NEXT_OPCODE();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = EG(error_reporting);
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG; /* shouldn't be necessary */
+ SAVE_OPLINE();
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = EG(error_reporting);
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_LONG; /* shouldn't be necessary */
if (EX(old_error_reporting) == NULL) {
- EX(old_error_reporting) = &EX_T(opline->result.u.var).tmp_var;
+ EX(old_error_reporting) = &EX_T(opline->result.var).tmp_var;
}
if (EG(error_reporting)) {
- zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC);
+ do {
+ EG(error_reporting) = 0;
+ if (!EG(error_reporting_ini_entry)) {
+ if (UNEXPECTED(zend_hash_find(EG(ini_directives), "error_reporting", sizeof("error_reporting"), (void **) &EG(error_reporting_ini_entry)) == FAILURE)) {
+ break;
+ }
+ }
+ if (!EG(error_reporting_ini_entry)->modified) {
+ if (!EG(modified_ini_directives)) {
+ ALLOC_HASHTABLE(EG(modified_ini_directives));
+ zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
+ }
+ if (EXPECTED(zend_hash_add(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting"), &EG(error_reporting_ini_entry), sizeof(zend_ini_entry*), NULL) == SUCCESS)) {
+ EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
+ EG(error_reporting_ini_entry)->orig_value_length = EG(error_reporting_ini_entry)->value_length;
+ EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
+ EG(error_reporting_ini_entry)->modified = 1;
+ }
+ } else if (EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value) {
+ efree(EG(error_reporting_ini_entry)->value);
+ }
+ EG(error_reporting_ini_entry)->value = estrndup("0", sizeof("0")-1);
+ EG(error_reporting_ini_entry)->value_length = sizeof("0")-1;
+ } while (0);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
{
+ SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, EX(op_array)->function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval restored_error_reporting;
- if (!EG(error_reporting) && Z_LVAL(EX_T(opline->op1.u.var).tmp_var) != 0) {
+ SAVE_OPLINE();
+ if (!EG(error_reporting) && Z_LVAL(EX_T(opline->op1.var).tmp_var) != 0) {
Z_TYPE(restored_error_reporting) = IS_LONG;
- Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.u.var).tmp_var);
+ Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.var).tmp_var);
+ EG(error_reporting) = Z_LVAL(restored_error_reporting);
convert_to_string(&restored_error_reporting);
- zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC);
- zendi_zval_dtor(restored_error_reporting);
+ if (EXPECTED(EG(error_reporting_ini_entry) != NULL)) {
+ if (EXPECTED(EG(error_reporting_ini_entry)->modified &&
+ EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value)) {
+ efree(EG(error_reporting_ini_entry)->value);
+ }
+ EG(error_reporting_ini_entry)->value = Z_STRVAL(restored_error_reporting);
+ EG(error_reporting_ini_entry)->value_length = Z_STRLEN(restored_error_reporting);
+ } else {
+ zendi_zval_dtor(restored_error_reporting);
+ }
}
- if (EX(old_error_reporting) == &EX_T(opline->op1.u.var).tmp_var) {
+ if (EX(old_error_reporting) == &EX_T(opline->op1.var).tmp_var) {
EX(old_error_reporting) = NULL;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *value;
+
+ SAVE_OPLINE();
+ value = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (i_zend_is_true(value)) {
- EX_T(opline->result.u.var).tmp_var = *value;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
- FREE_OP1();
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
+ if (!IS_OP1_TMP_FREE()) {
+ zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+ }
+ FREE_OP1_IF_VAR();
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_JMP(opline->op2.u.jmp_addr);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
FREE_OP1();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (i_zend_is_true(value)) {
+ if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!IS_OP1_TMP_FREE()) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
+ }
+ FREE_OP1_IF_VAR();
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+
+ FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *value;
- EX_T(opline->result.u.var).tmp_var = *value;
+ SAVE_OPLINE();
+ value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
if (!IS_OP1_TMP_FREE()) {
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
}
FREE_OP1_IF_VAR();
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!IS_OP1_TMP_FREE()) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
+ }
+
+ FREE_OP1_IF_VAR();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
{
+ SAVE_OPLINE();
if (!EG(no_extensions)) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(102, ZEND_EXT_FCALL_BEGIN, ANY, ANY)
{
+ SAVE_OPLINE();
if (!EG(no_extensions)) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
{
+ SAVE_OPLINE();
if (!EG(no_extensions)) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- EX_T(opline->result.u.var).class_entry = do_bind_class(opline, EG(class_table), 0 TSRMLS_CC);
+ SAVE_OPLINE();
+ EX_T(opline->result.var).class_entry = do_bind_class(EX(op_array), opline, EG(class_table), 0 TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- EX_T(opline->result.u.var).class_entry = do_bind_inherited_class(opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ SAVE_OPLINE();
+ EX_T(opline->result.var).class_entry = do_bind_inherited_class(EX(op_array), opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_class_entry **pce, **pce_orig;
- if (zend_hash_find(EG(class_table), Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void**)&pce) == FAILURE ||
- (zend_hash_find(EG(class_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), (void**)&pce_orig) == SUCCESS &&
+ SAVE_OPLINE();
+ if (zend_hash_quick_find(EG(class_table), Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void**)&pce) == FAILURE ||
+ (zend_hash_quick_find(EG(class_table), Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), Z_HASH_P(opline->op1.zv), (void**)&pce_orig) == SUCCESS &&
*pce != *pce_orig)) {
- do_bind_inherited_class(opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ do_bind_inherited_class(EX(op_array), opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
{
- do_bind_function(EX(opline), EG(function_table), 0);
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ do_bind_function(EX(op_array), opline, EG(function_table), 0);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(105, ZEND_TICKS, CONST, ANY)
+ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (++EG(ticks_count)>=Z_LVAL(opline->op1.u.constant)) {
+ SAVE_OPLINE();
+ if (++EG(ticks_count)>=opline->extended_value) {
EG(ticks_count)=0;
if (zend_ticks_function) {
- zend_ticks_function(Z_LVAL(opline->op1.u.constant));
+ zend_ticks_function(opline->extended_value);
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMP|VAR|CV, ANY)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *expr;
zend_bool result;
+ SAVE_OPLINE();
+ expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) {
- result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.u.var).class_entry TSRMLS_CC);
+ result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC);
} else {
result = 0;
}
- ZVAL_BOOL(&EX_T(opline->result.u.var).tmp_var, result);
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, result);
FREE_OP1();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -4284,17 +4922,69 @@ ZEND_VM_HANDLER(0, ZEND_NOP, ANY, ANY)
ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST)
{
- zend_op *opline = EX(opline);
- zend_class_entry *ce = EX_T(opline->op1.u.var).class_entry;
- zend_class_entry *iface = zend_fetch_class(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), opline->extended_value TSRMLS_CC);
+ USE_OPLINE
+ zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+ zend_class_entry *iface;
- if (iface) {
- if (!(iface->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+ SAVE_OPLINE();
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ iface = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(iface == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+
+ if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
+ zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+ }
+ zend_do_implement_interface(ce, iface TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
+{
+ USE_OPLINE
+ zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+ zend_class_entry *trait;
+
+ SAVE_OPLINE();
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ trait = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
+ Z_STRLEN_P(opline->op2.zv),
+ opline->op2.literal + 1,
+ opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(trait == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- zend_do_implement_interface(ce, iface TSRMLS_CC);
+ if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
+ zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, trait);
}
+ zend_do_implement_trait(ce, trait TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
+{
+ USE_OPLINE
+ zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+
+ SAVE_OPLINE();
+ zend_do_bind_traits(ce TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -4302,11 +4992,11 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
{
zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
int i;
- zend_uint catch_op_num;
+ zend_uint catch_op_num = 0;
int catched = 0;
zval restored_error_reporting;
-
- void **stack_frame = (void**)(((char*)EX(Ts)) +
+
+ void **stack_frame = (void**)(((char*)EX_Ts()) +
(ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T));
while (zend_vm_stack_top(TSRMLS_C) != stack_frame) {
@@ -4318,9 +5008,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
/* further blocks will not be relevant... */
break;
- }
- if (op_num >= EG(active_op_array)->try_catch_array[i].try_op
- && op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
+ } else if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
catched = 1;
}
@@ -4356,13 +5044,13 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
}
break;
case ZEND_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
}
break;
}
@@ -4390,13 +5078,22 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
ZEND_VM_HANDLER(146, ZEND_VERIFY_ABSTRACT_CLASS, ANY, ANY)
{
- zend_verify_abstract_class(EX_T(EX(opline)->op1.u.var).class_entry TSRMLS_CC);
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ zend_verify_abstract_class(EX_T(opline->op1.var).class_entry TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
{
- int ret = zend_user_opcode_handlers[EX(opline)->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL);
+ USE_OPLINE
+ int ret;
+
+ SAVE_OPLINE();
+ ret = zend_user_opcode_handlers[opline->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL);
+ LOAD_OPLINE();
switch (ret) {
case ZEND_USER_OPCODE_CONTINUE:
@@ -4408,24 +5105,29 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
case ZEND_USER_OPCODE_LEAVE:
ZEND_VM_LEAVE();
case ZEND_USER_OPCODE_DISPATCH:
- ZEND_VM_DISPATCH(EX(opline)->opcode, EX(opline));
+ ZEND_VM_DISPATCH(opline->opcode, opline);
default:
- ZEND_VM_DISPATCH((zend_uchar)(ret & 0xff), EX(opline));
+ ZEND_VM_DISPATCH((zend_uchar)(ret & 0xff), opline);
}
}
ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *name = GET_OP1_ZVAL_PTR(BP_VAR_R);
- zval *val = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *name;
+ zval *val;
zend_constant c;
+ SAVE_OPLINE();
+ name = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ val = GET_OP2_ZVAL_PTR(BP_VAR_R);
+
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
- zval tmp = *val;
+ zval tmp;
zval *tmp_ptr = &tmp;
+ ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
}
@@ -4433,11 +5135,11 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
c.value = *tmp_ptr;
} else {
- c.value = *val;
+ INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
c.flags = CONST_CS; /* non persistent, case sensetive */
- c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
c.module_number = PHP_USER_CONSTANT;
@@ -4446,21 +5148,46 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
FREE_OP1();
FREE_OP2();
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, CONST)
+ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_function *op_array;
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), Z_LVAL(opline->op2.u.constant), (void *) &op_array) == FAILURE ||
- op_array->type != ZEND_USER_FUNCTION) {
+ SAVE_OPLINE();
+
+ if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), Z_HASH_P(opline->op1.zv), (void *) &op_array) == FAILURE) ||
+ UNEXPECTED(op_array->type != ZEND_USER_FUNCTION)) {
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
}
- zend_create_closure(&EX_T(opline->result.u.var).tmp_var, op_array TSRMLS_CC);
+ zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
+{
+ USE_OPLINE
+ zval *var_ptr, *new_zv;
+ SAVE_OPLINE();
+ var_ptr = EX_T(opline->op1.var).var.ptr;
+ if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
+ !PZVAL_IS_REF(var_ptr) &&
+ Z_REFCOUNT_P(var_ptr) > 1) {
+
+ Z_DELREF_P(var_ptr);
+ ALLOC_ZVAL(new_zv);
+ INIT_PZVAL_COPY(new_zv, var_ptr);
+ var_ptr = new_zv;
+ zval_copy_ctor(var_ptr);
+ EX_T(opline->op1.var).var.ptr = var_ptr;
+ }
ZEND_VM_NEXT_OPCODE();
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 1481602040..4abe6503cd 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -21,26 +21,327 @@
#ifdef ZEND_WIN32
# pragma warning(once : 4101)
#endif
-static user_opcode_handler_t zend_user_opcode_handlers[256] = {(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL,(user_opcode_handler_t)NULL};
-
-static zend_uchar zend_user_opcodes[256] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};
+static user_opcode_handler_t zend_user_opcode_handlers[256] = {
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL,
+ (user_opcode_handler_t)NULL
+};
+
+static zend_uchar zend_user_opcodes[256] = {0,
+ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
+ 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
+ 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
+ 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
+ 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
+ 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,
+ 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
+ 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
+ 129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,
+ 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,
+ 161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
+ 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
+ 193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,
+ 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
+ 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
+ 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op);
-#define ZEND_VM_CONTINUE() return 0
-#define ZEND_VM_RETURN() return 1
-#define ZEND_VM_ENTER() return 2
-#define ZEND_VM_LEAVE() return 3
+#undef OPLINE
+#undef DCL_OPLINE
+#undef USE_OPLINE
+#undef LOAD_OPLINE
+#undef SAVE_OPLINE
+#define OPLINE EX(opline)
+#define DCL_OPLINE
+#define USE_OPLINE zend_op *opline = EX(opline);
+#define LOAD_OPLINE()
+#define SAVE_OPLINE()
+#undef CHECK_EXCEPTION
+#undef HANDLE_EXCEPTION
+#undef HANDLE_EXCEPTION_LEAVE
+#define CHECK_EXCEPTION() LOAD_OPLINE()
+#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()
+#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()
+#define LOAD_REGS()
+#define ZEND_VM_CONTINUE() return 0
+#define ZEND_VM_RETURN() return 1
+#define ZEND_VM_ENTER() return 2
+#define ZEND_VM_LEAVE() return 3
#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC
#undef EX
#define EX(element) execute_data->element
+#undef EX_CV
+#define EX_CV(var) EX(CVs)[var]
+#undef EX_CVs
+#define EX_CVs() EX(CVs)
+#undef EX_T
+#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
+#undef EX_Ts
+#define EX_Ts() EX(Ts)
+
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
{
+ DCL_OPLINE
zend_execute_data *execute_data;
zend_bool nested = 0;
zend_bool original_in_execution = EG(in_execution);
@@ -73,29 +374,31 @@ zend_vm_enter:
EX(nested) = nested;
nested = 1;
- if (op_array->start_op) {
- ZEND_VM_SET_OPCODE(op_array->start_op);
- } else {
- ZEND_VM_SET_OPCODE(op_array->opcodes);
+ LOAD_REGS();
+
+ if (!op_array->run_time_cache && op_array->last_cache_slot) {
+ op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
if (op_array->this_var != -1 && EG(This)) {
Z_ADDREF_P(EG(This)); /* For $this pointer */
if (!EG(active_symbol_table)) {
- EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
- *EX(CVs)[op_array->this_var] = EG(This);
+ EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var);
+ *EX_CV(op_array->this_var) = EG(This);
} else {
- if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
+ if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) {
Z_DELREF_P(EG(This));
}
}
}
+ EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
EG(opline_ptr) = &EX(opline);
+ LOAD_OPLINE();
EX(function_state).function = (zend_function *) op_array;
EX(function_state).arguments = NULL;
-
+
while (1) {
int ret;
#ifdef ZEND_WIN32
@@ -104,7 +407,7 @@ zend_vm_enter:
}
#endif
- if ((ret = EX(opline)->handler(execute_data TSRMLS_CC)) > 0) {
+ if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0) {
switch (ret) {
case 1:
EG(in_execution) = original_in_execution;
@@ -125,23 +428,28 @@ zend_vm_enter:
static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ USE_OPLINE
+
#if DEBUG_ZEND>=2
- printf("Jumping to %d\n", EX(opline)->op1.u.opline_num);
+ printf("Jumping to %d\n", opline->op1.opline_num);
#endif
- ZEND_VM_SET_OPCODE(EX(opline)->op1.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *tmp = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
tmp->value.str.val = emalloc(1);
tmp->value.str.val[0] = 0;
tmp->value.str.len = 0;
Z_SET_REFCOUNT_P(tmp, 1);
tmp->type = IS_STRING;
Z_UNSET_ISREF_P(tmp);
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
@@ -153,8 +461,8 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EG(current_execute_data) = EX(prev_execute_data);
EG(opline_ptr) = NULL;
if (!EG(active_symbol_table)) {
- zval ***cv = EX(CVs);
- zval ***end = cv + EX(op_array)->last_var;
+ zval ***cv = EX_CVs();
+ zval ***end = cv + op_array->last_var;
while (cv != end) {
if (*cv) {
zval_ptr_dtor(*cv);
@@ -173,32 +481,38 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
if (nested) {
execute_data = EG(current_execute_data);
+ }
+ if (nested) {
+ USE_OPLINE
- if (EX(call_opline)->opcode == ZEND_INCLUDE_OR_EVAL) {
+ LOAD_REGS();
+ LOAD_OPLINE();
+ if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
EX(function_state).function = (zend_function *) EX(op_array);
EX(function_state).arguments = NULL;
EX(object) = EX(current_object);
- if (RETURN_VALUE_USED(EX(call_opline))) {
- if (!EX_T(EX(call_opline)->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(EX(call_opline)->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(EX(call_opline)->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(EX(call_opline)->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(EX(call_opline)->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(op_array TSRMLS_CC);
efree(op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION_LEAVE();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
+ }
}
- EX(opline)++;
+ ZEND_VM_INC_OPCODE();
ZEND_VM_LEAVE();
} else {
@@ -222,7 +536,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EX(function_state).arguments = NULL;
if (EG(This)) {
- if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) {
+ if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
if (IS_CTOR_USED(EX(called_scope))) {
Z_DELREF_P(EG(This));
}
@@ -241,14 +555,15 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_vm_stack_clear_multiple(TSRMLS_C);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(EX(call_opline)) && EX_T(EX(call_opline)->result.u.var).var.ptr) {
- zval_ptr_dtor(&EX_T(EX(call_opline)->result.u.var).var.ptr);
+ if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
}
+ HANDLE_EXCEPTION_LEAVE();
}
- EX(opline)++;
+ ZEND_VM_INC_OPCODE();
ZEND_VM_LEAVE();
}
}
@@ -257,89 +572,99 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_bool should_change_scope = 0;
+ zend_function *fbc = EX(function_state).function;
- if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ SAVE_OPLINE();
+ if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
- EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
- EX(function_state).function->common.scope ? "::" : "",
- EX(function_state).function->common.function_name);
+ fbc->common.scope ? fbc->common.scope->name : "",
+ fbc->common.scope ? "::" : "",
+ fbc->common.function_name);
}
}
- if (EX(function_state).function->common.scope &&
- !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) &&
+ if (fbc->common.scope &&
+ !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
!EX(object)) {
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
- zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name);
} else {
/* FIXME: output identifiers properly */
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name);
}
}
- if (EX(function_state).function->type == ZEND_USER_FUNCTION ||
- EX(function_state).function->common.scope) {
+ if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
should_change_scope = 1;
EX(current_this) = EG(This);
EX(current_scope) = EG(scope);
EX(current_called_scope) = EG(called_scope);
EG(This) = EX(object);
- EG(scope) = (EX(function_state).function->type == ZEND_USER_FUNCTION || !EX(object)) ? EX(function_state).function->common.scope : NULL;
+ EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
EG(called_scope) = EX(called_scope);
}
zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc));
EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC);
+ LOAD_OPLINE();
- if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
- ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr);
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference;
+ if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+ temp_variable *ret = &EX_T(opline->result.var);
- if (EX(function_state).function->common.arg_info) {
+ MAKE_STD_ZVAL(ret->var.ptr);
+ ZVAL_NULL(ret->var.ptr);
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+
+ if (fbc->common.arg_info) {
zend_uint i=0;
zval **p = (zval**)EX(function_state).arguments;
ulong arg_count = opline->extended_value;
while (arg_count>0) {
- zend_verify_arg_type(EX(function_state).function, ++i, *(p-arg_count), 0 TSRMLS_CC);
+ zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC);
arg_count--;
}
}
+
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
- ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common.return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ zval_ptr_dtor(&ret->var.ptr);
}
- } else if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
+ } else if (fbc->type == ZEND_USER_FUNCTION) {
EX(original_return_value) = EG(return_value_ptr_ptr);
EG(active_symbol_table) = NULL;
- EG(active_op_array) = &EX(function_state).function->op_array;
+ EG(active_op_array) = &fbc->op_array;
EG(return_value_ptr_ptr) = NULL;
if (RETURN_VALUE_USED(opline)) {
- EG(return_value_ptr_ptr) = &EX_T(opline->result.u.var).var.ptr;
- EX_T(opline->result.u.var).var.ptr = NULL;
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference;
+ temp_variable *ret = &EX_T(opline->result.var);
+
+ ret->var.ptr = NULL;
+ EG(return_value_ptr_ptr) = &ret->var.ptr;
+ ret->var.ptr_ptr = &ret->var.ptr;
+ ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
}
- if (zend_execute == execute && !EG(exception)) {
- EX(call_opline) = opline;
- ZEND_VM_ENTER();
+ if (EXPECTED(zend_execute == execute)) {
+ if (EXPECTED(EG(exception) == NULL)) {
+ ZEND_VM_ENTER();
+ }
} else {
zend_execute(EG(active_op_array) TSRMLS_CC);
}
@@ -360,27 +685,28 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
- ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr);
+ MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr);
+ ZVAL_NULL(EX_T(opline->result.var).var.ptr);
/* Not sure what should be done here if it's a static method */
- if (EX(object)) {
- Z_OBJ_HT_P(EX(object))->call_method(EX(function_state).function->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ if (EXPECTED(EX(object) != NULL)) {
+ Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
- if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- efree(EX(function_state).function->common.function_name);
+ if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+ efree((char*)fbc->common.function_name);
}
- efree(EX(function_state).function);
+ efree(fbc);
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
} else {
- Z_UNSET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
+ Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
+ Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
+ EX_T(opline->result.var).var.fcall_returned_reference = 0;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
}
@@ -389,7 +715,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
if (should_change_scope) {
if (EG(This)) {
- if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) {
+ if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) {
if (IS_CTOR_USED(EX(called_scope))) {
Z_DELREF_P(EG(This));
}
@@ -409,11 +735,12 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
zend_vm_stack_clear_multiple(TSRMLS_C);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline) && EX_T(opline->result.u.var).var.ptr) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) {
+ zval_ptr_dtor(&EX_T(opline->result.var).var.ptr);
}
+ HANDLE_EXCEPTION();
}
ZEND_VM_NEXT_OPCODE();
@@ -427,72 +754,78 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER
static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_uint arg_num = Z_LVAL(opline->op1.u.constant);
+ USE_OPLINE
+ zend_uint arg_num = opline->op1.num;
zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
- if (param == NULL) {
- char *space;
- char *class_name = get_active_class_name(&space TSRMLS_CC);
- zend_execute_data *ptr = EX(prev_execute_data);
-
+ SAVE_OPLINE();
+ if (UNEXPECTED(param == NULL)) {
if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
+ const char *space;
+ const char *class_name;
+ zend_execute_data *ptr;
+
+ if (EG(active_op_array)->scope) {
+ class_name = EG(active_op_array)->scope->name;
+ space = "::";
+ } else {
+ class_name = space = "";
+ }
+ ptr = EX(prev_execute_data);
+
if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s()", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C));
}
}
- if (opline->result.op_type == IS_VAR) {
- PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
- }
} else {
- zend_free_op free_res;
zval **var_ptr;
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
- var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
*var_ptr = *param;
Z_ADDREF_PP(var_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *object_zval;
zend_function *constructor;
- if (EX_T(opline->op1.u.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
- char *class_type;
-
- if (EX_T(opline->op1.u.var).class_entry->ce_flags & ZEND_ACC_INTERFACE) {
- class_type = "interface";
+ SAVE_OPLINE();
+ if (UNEXPECTED((EX_T(opline->op1.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
+ if (EX_T(opline->op1.var).class_entry->ce_flags & ZEND_ACC_INTERFACE) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", EX_T(opline->op1.var).class_entry->name);
+ } else if ((EX_T(opline->op1.var).class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", EX_T(opline->op1.var).class_entry->name);
} else {
- class_type = "abstract class";
+ zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", EX_T(opline->op1.var).class_entry->name);
}
- zend_error_noreturn(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(opline->op1.u.var).class_entry->name);
}
ALLOC_ZVAL(object_zval);
- object_init_ex(object_zval, EX_T(opline->op1.u.var).class_entry);
+ object_init_ex(object_zval, EX_T(opline->op1.var).class_entry);
INIT_PZVAL(object_zval);
constructor = Z_OBJ_HT_P(object_zval)->get_constructor(object_zval TSRMLS_CC);
if (constructor == NULL) {
if (RETURN_VALUE_USED(opline)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval);
+ AI_SET_PTR(&EX_T(opline->result.var), object_zval);
} else {
zval_ptr_dtor(&object_zval);
}
- ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num);
} else {
if (RETURN_VALUE_USED(opline)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, object_zval);
PZVAL_LOCK(object_zval);
+ AI_SET_PTR(&EX_T(opline->result.var), object_zval);
}
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline)));
@@ -500,90 +833,148 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* We are not handling overloaded classes right now */
EX(object) = object_zval;
EX(fbc) = constructor;
- EX(called_scope) = EX_T(opline->op1.u.var).class_entry;
+ EX(called_scope) = EX_T(opline->op1.var).class_entry;
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = EG(error_reporting);
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG; /* shouldn't be necessary */
+ SAVE_OPLINE();
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = EG(error_reporting);
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_LONG; /* shouldn't be necessary */
if (EX(old_error_reporting) == NULL) {
- EX(old_error_reporting) = &EX_T(opline->result.u.var).tmp_var;
+ EX(old_error_reporting) = &EX_T(opline->result.var).tmp_var;
}
if (EG(error_reporting)) {
- zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC);
+ do {
+ EG(error_reporting) = 0;
+ if (!EG(error_reporting_ini_entry)) {
+ if (UNEXPECTED(zend_hash_find(EG(ini_directives), "error_reporting", sizeof("error_reporting"), (void **) &EG(error_reporting_ini_entry)) == FAILURE)) {
+ break;
+ }
+ }
+ if (!EG(error_reporting_ini_entry)->modified) {
+ if (!EG(modified_ini_directives)) {
+ ALLOC_HASHTABLE(EG(modified_ini_directives));
+ zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
+ }
+ if (EXPECTED(zend_hash_add(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting"), &EG(error_reporting_ini_entry), sizeof(zend_ini_entry*), NULL) == SUCCESS)) {
+ EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
+ EG(error_reporting_ini_entry)->orig_value_length = EG(error_reporting_ini_entry)->value_length;
+ EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
+ EG(error_reporting_ini_entry)->modified = 1;
+ }
+ } else if (EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value) {
+ efree(EG(error_reporting_ini_entry)->value);
+ }
+ EG(error_reporting_ini_entry)->value = estrndup("0", sizeof("0")-1);
+ EG(error_reporting_ini_entry)->value_length = sizeof("0")-1;
+ } while (0);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, EX(op_array)->function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
static int ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ SAVE_OPLINE();
if (!EG(no_extensions)) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ SAVE_OPLINE();
if (!EG(no_extensions)) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ SAVE_OPLINE();
if (!EG(no_extensions)) {
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- EX_T(opline->result.u.var).class_entry = do_bind_class(opline, EG(class_table), 0 TSRMLS_CC);
+ SAVE_OPLINE();
+ EX_T(opline->result.var).class_entry = do_bind_class(EX(op_array), opline, EG(class_table), 0 TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- EX_T(opline->result.u.var).class_entry = do_bind_inherited_class(opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ SAVE_OPLINE();
+ EX_T(opline->result.var).class_entry = do_bind_inherited_class(EX(op_array), opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_class_entry **pce, **pce_orig;
- if (zend_hash_find(EG(class_table), Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void**)&pce) == FAILURE ||
- (zend_hash_find(EG(class_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), (void**)&pce_orig) == SUCCESS &&
+ SAVE_OPLINE();
+ if (zend_hash_quick_find(EG(class_table), Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void**)&pce) == FAILURE ||
+ (zend_hash_quick_find(EG(class_table), Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), Z_HASH_P(opline->op1.zv), (void**)&pce_orig) == SUCCESS &&
*pce != *pce_orig)) {
- do_bind_inherited_class(opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ do_bind_inherited_class(EX(op_array), opline, EG(class_table), EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- do_bind_function(EX(opline), EG(function_table), 0);
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ do_bind_function(EX(op_array), opline, EG(function_table), 0);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_TICKS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ if (++EG(ticks_count)>=opline->extended_value) {
+ EG(ticks_count)=0;
+ if (zend_ticks_function) {
+ zend_ticks_function(opline->extended_value);
+ }
+ }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -597,15 +988,56 @@ static int ZEND_FASTCALL ZEND_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+ zend_class_entry *trait;
+
+ SAVE_OPLINE();
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ trait = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
+ Z_STRLEN_P(opline->op2.zv),
+ opline->op2.literal + 1,
+ opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(trait == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
+ zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, trait);
+ }
+
+ zend_do_implement_trait(ce, trait TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+
+ SAVE_OPLINE();
+ zend_do_bind_traits(ce TSRMLS_CC);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
int i;
- zend_uint catch_op_num;
+ zend_uint catch_op_num = 0;
int catched = 0;
zval restored_error_reporting;
- void **stack_frame = (void**)(((char*)EX(Ts)) +
+ void **stack_frame = (void**)(((char*)EX_Ts()) +
(ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T));
while (zend_vm_stack_top(TSRMLS_C) != stack_frame) {
@@ -617,9 +1049,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
/* further blocks will not be relevant... */
break;
- }
- if (op_num >= EG(active_op_array)->try_catch_array[i].try_op
- && op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
+ } else if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
catched = 1;
}
@@ -655,13 +1085,13 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
}
break;
case ZEND_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
}
break;
}
@@ -689,13 +1119,22 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
static int ZEND_FASTCALL ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_verify_abstract_class(EX_T(EX(opline)->op1.u.var).class_entry TSRMLS_CC);
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ zend_verify_abstract_class(EX_T(opline->op1.var).class_entry TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- int ret = zend_user_opcode_handlers[EX(opline)->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL);
+ USE_OPLINE
+ int ret;
+
+ SAVE_OPLINE();
+ ret = zend_user_opcode_handlers[opline->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL);
+ LOAD_OPLINE();
switch (ret) {
case ZEND_USER_OPCODE_CONTINUE:
@@ -707,55 +1146,92 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
case ZEND_USER_OPCODE_LEAVE:
ZEND_VM_LEAVE();
case ZEND_USER_OPCODE_DISPATCH:
- ZEND_VM_DISPATCH(EX(opline)->opcode, EX(opline));
+ ZEND_VM_DISPATCH(opline->opcode, opline);
default:
- ZEND_VM_DISPATCH((zend_uchar)(ret & 0xff), EX(opline));
+ ZEND_VM_DISPATCH((zend_uchar)(ret & 0xff), opline);
}
}
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
+ SAVE_OPLINE();
+ EG(exception) = NULL;
if (IS_CONST == IS_UNUSED) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- zval *class_name = &opline->op2.u.constant;
+ zval *class_name = opline->op2.zv;
- if (IS_CONST != IS_CONST && Z_TYPE_P(class_name) == IS_OBJECT) {
- EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+ }
+ } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
+ EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
- char *function_name_strval, *lcname;
- int function_name_strlen;
-
-
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ function_name = (zval*)(opline->op2.literal+1);
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ EX(object) = NULL;
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
} else {
- function_name = &opline->op2.u.constant;
+ char *function_name_strval, *lcname;
+ int function_name_strlen;
+
- if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
- Z_TYPE_P(function_name) == IS_OBJECT &&
+ SAVE_OPLINE();
+ function_name = opline->op2.zv;
+
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ function_name_strval = Z_STRVAL_P(function_name);
+ function_name_strlen = Z_STRLEN_P(function_name);
+ if (function_name_strval[0] == '\\') {
+ function_name_strlen -= 1;
+ lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ } else {
+ lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+ }
+ if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ }
+ efree(lcname);
+
+ EX(object) = NULL;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
@@ -768,46 +1244,101 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
- }
+ } else if (IS_CONST != IS_CONST &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
+ zend_class_entry *ce;
+ zval **method = NULL;
+ zval **obj = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
- zend_error_noreturn(E_ERROR, "Function name must be a string");
- }
- function_name_strval = Z_STRVAL_P(function_name);
- function_name_strlen = Z_STRLEN_P(function_name);
- if (function_name_strval[0] == '\\') {
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
+
+ if (!obj || !method) {
+ zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
+ }
+
+ if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
+ }
+
+ if (Z_TYPE_PP(method) != IS_STRING) {
+ zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
+ }
+
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ EX(called_scope) = ce;
+ EX(object) = NULL;
+
+ if (ce->get_static_method) {
+ EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
+ } else {
+ EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ }
+ } else {
+ EX(object) = *obj;
+ ce = EX(called_scope) = Z_OBJCE_PP(obj);
- function_name_strlen -= 1;
- lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
+ }
+
+ if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ EX(object) = NULL;
+ } else {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
+ }
+ }
+
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
} else {
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- }
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- efree(lcname);
-
}
-
- EX(object) = NULL;
- ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline + 1;
+ USE_OPLINE
+ zend_literal *func_name;
- ZEND_VM_INC_OPCODE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc))==FAILURE) {
- char *short_name = Z_STRVAL(opline->op1.u.constant)+Z_LVAL(op_data->op1.u.constant);
- if (zend_hash_quick_find(EG(function_table), short_name, Z_STRLEN(opline->op1.u.constant)-Z_LVAL(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &EX(fbc))==FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ func_name = opline->op2.literal + 1;
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
+ func_name++;
+ if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
EX(object) = NULL;
@@ -816,17 +1347,18 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC
static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *assignment_value;
- zend_uint arg_num = Z_LVAL(opline->op1.u.constant);
- zend_free_op free_res;
+ zend_uint arg_num = opline->op1.num;
zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
zval **var_ptr;
+ SAVE_OPLINE();
if (param == NULL) {
ALLOC_ZVAL(assignment_value);
- *assignment_value = opline->op2.u.constant;
- if ((Z_TYPE(opline->op2.u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE(opline->op2.u.constant)==IS_CONSTANT_ARRAY) {
+ *assignment_value = *opline->op2.zv;
+ if ((Z_TYPE_P(assignment_value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT ||
+ Z_TYPE_P(assignment_value)==IS_CONSTANT_ARRAY) {
Z_SET_REFCOUNT_P(assignment_value, 1);
zval_update_constant(&assignment_value, 0 TSRMLS_CC);
} else {
@@ -839,33 +1371,34 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
}
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC);
- var_ptr = get_zval_ptr_ptr(&opline->result, EX(Ts), &free_res, BP_VAR_W);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC);
Z_DELREF_PP(var_ptr);
*var_ptr = assignment_value;
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
zend_brk_cont_element *el;
- el = zend_brk_cont(&opline->op2.u.constant, opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
+ SAVE_OPLINE();
+ el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
+ EX(op_array), EX_Ts() TSRMLS_CC);
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
zend_brk_cont_element *el;
- el = zend_brk_cont(&opline->op2.u.constant, opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
+ SAVE_OPLINE();
+ el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
+ EX(op_array), EX_Ts() TSRMLS_CC);
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
@@ -873,89 +1406,138 @@ static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *brk_opline;
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_brk_cont_element *el;
- el = zend_brk_cont(&opline->op2.u.constant, opline->extended_value,
- EX(op_array), EX(Ts) TSRMLS_CC);
+ SAVE_OPLINE();
+ el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
+ EX(op_array), EX_Ts() TSRMLS_CC);
brk_opline = EX(op_array)->opcodes + el->brk;
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
}
break;
case ZEND_FREE:
- if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
- zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
}
break;
}
- ZEND_VM_JMP(opline->op1.u.jmp_addr);
+ ZEND_VM_JMP(opline->op1.jmp_addr);
}
static int ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_class_entry *ce = EX_T(opline->op1.u.var).class_entry;
- zend_class_entry *iface = zend_fetch_class(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), opline->extended_value TSRMLS_CC);
+ USE_OPLINE
+ zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+ zend_class_entry *iface;
- if (iface) {
- if (!(iface->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+ SAVE_OPLINE();
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ iface = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(iface == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- zend_do_implement_interface(ce, iface TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+
+ if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
+ zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
}
+ zend_do_implement_interface(ce, iface TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
+ SAVE_OPLINE();
+ EG(exception) = NULL;
if (IS_TMP_VAR == IS_UNUSED) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
zend_free_op free_op2;
- zval *class_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *class_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(class_name) == IS_OBJECT) {
- EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+ if (IS_TMP_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+ }
+ } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
+ EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
}
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
- char *function_name_strval, *lcname;
- int function_name_strlen;
- zend_free_op free_op2;
-
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_TMP_VAR == IS_CONST) {
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ function_name = (zval*)(opline->op2.literal+1);
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ EX(object) = NULL;
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
} else {
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ char *function_name_strval, *lcname;
+ int function_name_strlen;
+ zend_free_op free_op2;
- if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
- Z_TYPE_P(function_name) == IS_OBJECT &&
+ SAVE_OPLINE();
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ function_name_strval = Z_STRVAL_P(function_name);
+ function_name_strlen = Z_STRLEN_P(function_name);
+ if (function_name_strval[0] == '\\') {
+ function_name_strlen -= 1;
+ lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ } else {
+ lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+ }
+ if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ }
+ efree(lcname);
+ zval_dtor(free_op2.var);
+ EX(object) = NULL;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
@@ -968,101 +1550,162 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
} else {
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
- }
+ } else if (IS_TMP_VAR != IS_CONST &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
+ zend_class_entry *ce;
+ zval **method = NULL;
+ zval **obj = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
- zend_error_noreturn(E_ERROR, "Function name must be a string");
- }
- function_name_strval = Z_STRVAL_P(function_name);
- function_name_strlen = Z_STRLEN_P(function_name);
- if (function_name_strval[0] == '\\') {
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
- function_name_strlen -= 1;
- lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
- } else {
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- }
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
- }
- efree(lcname);
- zval_dtor(free_op2.var);
- }
+ if (!obj || !method) {
+ zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
+ }
- EX(object) = NULL;
- ZEND_VM_NEXT_OPCODE();
-}
+ if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
+ }
+ if (Z_TYPE_PP(method) != IS_STRING) {
+ zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
+ }
-static int ZEND_FASTCALL ZEND_BRK_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zend_brk_cont_element *el;
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ EX(called_scope) = ce;
+ EX(object) = NULL;
- el = zend_brk_cont(_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
- zval_dtor(free_op2.var);
- ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
-}
+ if (ce->get_static_method) {
+ EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
+ } else {
+ EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ }
+ } else {
+ EX(object) = *obj;
+ ce = EX(called_scope) = Z_OBJCE_PP(obj);
-static int ZEND_FASTCALL ZEND_CONT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zend_brk_cont_element *el;
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
+ }
- el = zend_brk_cont(_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
- zval_dtor(free_op2.var);
- ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
+ if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ EX(object) = NULL;
+ } else {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
+ }
+ }
+
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
+ }
+ zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ zend_error_noreturn(E_ERROR, "Function name must be a string");
+ }
+ }
}
+
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
+ SAVE_OPLINE();
+ EG(exception) = NULL;
if (IS_VAR == IS_UNUSED) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
zend_free_op free_op2;
- zval *class_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *class_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (IS_VAR != IS_CONST && Z_TYPE_P(class_name) == IS_OBJECT) {
- EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+ }
+ } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
+ EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
- char *function_name_strval, *lcname;
- int function_name_strlen;
- zend_free_op free_op2;
-
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ function_name = (zval*)(opline->op2.literal+1);
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ EX(object) = NULL;
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
} else {
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ char *function_name_strval, *lcname;
+ int function_name_strlen;
+ zend_free_op free_op2;
- if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
- Z_TYPE_P(function_name) == IS_OBJECT &&
+ SAVE_OPLINE();
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ function_name_strval = Z_STRVAL_P(function_name);
+ function_name_strlen = Z_STRLEN_P(function_name);
+ if (function_name_strval[0] == '\\') {
+ function_name_strlen -= 1;
+ lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ } else {
+ lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+ }
+ if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ }
+ efree(lcname);
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ EX(object) = NULL;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
@@ -1075,124 +1718,195 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
- }
+ } else if (IS_VAR != IS_CONST &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
+ zend_class_entry *ce;
+ zval **method = NULL;
+ zval **obj = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
- zend_error_noreturn(E_ERROR, "Function name must be a string");
- }
- function_name_strval = Z_STRVAL_P(function_name);
- function_name_strlen = Z_STRLEN_P(function_name);
- if (function_name_strval[0] == '\\') {
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
- function_name_strlen -= 1;
- lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
- } else {
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- }
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
- }
- efree(lcname);
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- }
+ if (!obj || !method) {
+ zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
+ }
- EX(object) = NULL;
- ZEND_VM_NEXT_OPCODE();
-}
+ if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
+ }
+ if (Z_TYPE_PP(method) != IS_STRING) {
+ zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
+ }
-static int ZEND_FASTCALL ZEND_BRK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zend_brk_cont_element *el;
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ EX(called_scope) = ce;
+ EX(object) = NULL;
- el = zend_brk_cont(_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
-}
+ if (ce->get_static_method) {
+ EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
+ } else {
+ EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ }
+ } else {
+ EX(object) = *obj;
+ ce = EX(called_scope) = Z_OBJCE_PP(obj);
-static int ZEND_FASTCALL ZEND_CONT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zend_brk_cont_element *el;
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
+ }
- el = zend_brk_cont(_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
+ if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ EX(object) = NULL;
+ } else {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
+ }
+ }
+
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
+ }
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ zend_error_noreturn(E_ERROR, "Function name must be a string");
+ }
+ }
}
+
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
+ SAVE_OPLINE();
+ EG(exception) = NULL;
if (IS_UNUSED == IS_UNUSED) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
zval *class_name = NULL;
- if (IS_UNUSED != IS_CONST && Z_TYPE_P(class_name) == IS_OBJECT) {
- EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+ }
+ } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
+ EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
+ USE_OPLINE
+ SAVE_OPLINE();
+ EG(exception) = NULL;
if (IS_CV == IS_UNUSED) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- zval *class_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *class_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (IS_CV != IS_CONST && Z_TYPE_P(class_name) == IS_OBJECT) {
- EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
+ if (IS_CV == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+ CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+ }
+ } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
+ EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
} else if (Z_TYPE_P(class_name) == IS_STRING) {
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ EX_T(opline->result.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
- char *function_name_strval, *lcname;
- int function_name_strlen;
-
-
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CV == IS_CONST) {
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, opline->extended_value, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
+ function_name = (zval*)(opline->op2.literal+1);
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
}
+ EX(object) = NULL;
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
} else {
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ char *function_name_strval, *lcname;
+ int function_name_strlen;
+
+
+ SAVE_OPLINE();
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
- Z_TYPE_P(function_name) == IS_OBJECT &&
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ function_name_strval = Z_STRVAL_P(function_name);
+ function_name_strlen = Z_STRLEN_P(function_name);
+ if (function_name_strval[0] == '\\') {
+ function_name_strlen -= 1;
+ lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
+ } else {
+ lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+ }
+ if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ }
+ efree(lcname);
+
+ EX(object) = NULL;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) {
if (EX(object)) {
@@ -1205,126 +1919,120 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
- }
+ } else if (IS_CV != IS_CONST &&
+ EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
+ zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
+ zend_class_entry *ce;
+ zval **method = NULL;
+ zval **obj = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
- zend_error_noreturn(E_ERROR, "Function name must be a string");
- }
- function_name_strval = Z_STRVAL_P(function_name);
- function_name_strlen = Z_STRLEN_P(function_name);
- if (function_name_strval[0] == '\\') {
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 0, (void **) &obj);
+ zend_hash_index_find(Z_ARRVAL_P(function_name), 1, (void **) &method);
- function_name_strlen -= 1;
- lcname = zend_str_tolower_dup(function_name_strval + 1, function_name_strlen);
- } else {
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- }
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
- }
- efree(lcname);
+ if (!obj || !method) {
+ zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
+ }
- }
+ if (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
+ }
- EX(object) = NULL;
- ZEND_VM_NEXT_OPCODE();
-}
+ if (Z_TYPE_PP(method) != IS_STRING) {
+ zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
+ }
+ if (Z_TYPE_PP(obj) == IS_STRING) {
+ ce = zend_fetch_class_by_name(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ EX(called_scope) = ce;
+ EX(object) = NULL;
-static int ZEND_FASTCALL ZEND_CATCH_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_class_entry *ce;
+ if (ce->get_static_method) {
+ EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC);
+ } else {
+ EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ }
+ } else {
+ EX(object) = *obj;
+ ce = EX(called_scope) = Z_OBJCE_PP(obj);
- /* Check whether an exception has been thrown, if not, jump over code */
- zend_exception_restore(TSRMLS_C);
- if (EG(exception) == NULL) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
- }
- ce = Z_OBJCE_P(EG(exception));
- if (ce != EX_T(opline->op1.u.var).class_entry) {
- if (!instanceof_function(ce, EX_T(opline->op1.u.var).class_entry TSRMLS_CC)) {
- if (opline->op1.u.EA.type) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method));
+ }
+
+ if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ EX(object) = NULL;
+ } else {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
+ }
}
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
- }
- }
- if (!EG(active_symbol_table)) {
- if (EX(CVs)[opline->op2.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op2.u.var]);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method));
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- EX(CVs)[opline->op2.u.var] = (zval**)EX(CVs) + (EX(op_array)->last_var + opline->op2.u.var);
- *EX(CVs)[opline->op2.u.var] = EG(exception);
- } else {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
- zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value,
- &EG(exception), sizeof(zval *), (void**)&EX(CVs)[opline->op2.u.var]);
}
- EG(exception) = NULL;
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_BRK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
-
- zend_brk_cont_element *el;
-
- el = zend_brk_cont(_get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
-
- ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
-}
-
-static int ZEND_FASTCALL ZEND_CONT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
-
- zend_brk_cont_element *el;
-
- el = zend_brk_cont(_get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC), opline->op1.u.opline_num,
- EX(op_array), EX(Ts) TSRMLS_CC);
-
- ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
-}
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_not_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_not_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- boolean_not_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_not_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval z_copy;
- zval *z = &opline->op1.u.constant;
+ zval *z;
+
+ SAVE_OPLINE();
+ z = opline->op1.zv;
if (IS_CONST != IS_CONST &&
- Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
+ UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) &&
+ Z_OBJ_HT_P(z)->get_method != NULL) {
if (IS_CONST == IS_TMP_VAR) {
INIT_PZVAL(z);
}
@@ -1338,172 +2046,42 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_print_variable(z);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRINT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG;
+ USE_OPLINE
+ ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
return ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval *varname = &opline->op1.u.constant;
- zval **retval;
- zval tmp_varname;
- HashTable *target_symbol_table;
-
- if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- tmp_varname = *varname;
- zval_copy_ctor(&tmp_varname);
- convert_to_string(&tmp_varname);
- varname = &tmp_varname;
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- retval = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0 TSRMLS_CC);
-
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);
-/*
- if (!target_symbol_table) {
- ZEND_VM_NEXT_OPCODE();
- }
-*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval_ptr);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_W: {
- zval *new_zval = &EG(uninitialized_zval);
-
- Z_ADDREF_P(new_zval);
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
- }
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
- switch (opline->op2.u.EA.type) {
- case ZEND_FETCH_GLOBAL:
- if (IS_CONST != IS_TMP_VAR) {
-
- }
- break;
- case ZEND_FETCH_LOCAL:
-
- break;
- case ZEND_FETCH_STATIC:
- zval_update_constant(retval, (void*) 1 TSRMLS_CC);
- break;
- case ZEND_FETCH_GLOBAL_LOCK:
- if (IS_CONST == IS_VAR && !free_op1.var) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- break;
- }
- }
-
-
- if (IS_CONST != IS_CONST && varname == &tmp_varname) {
- zval_dtor(varname);
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- }
- PZVAL_LOCK(*retval);
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_IS:
- AI_SET_PTR(EX_T(opline->result.u.var).var, *retval);
- break;
- case BP_VAR_UNSET: {
- zend_free_op free_res;
-
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- }
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
- FREE_OP_VAR_PTR(free_res);
- break;
- default:
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- break;
- }
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = &opline->op1.u.constant;
+ zval *val;
int ret;
- if (IS_CONST == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = opline->op1.zv;
+
+ if (IS_CONST == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (!ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -1512,25 +2090,28 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = &opline->op1.u.constant;
+ zval *val;
int ret;
- if (IS_CONST == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = opline->op1.zv;
+
+ if (IS_CONST == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -1539,18 +2120,21 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = &opline->op1.u.constant;
+ zval *val;
int retval;
- if (IS_CONST == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = opline->op1.zv;
+
+ if (IS_CONST == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (EXPECTED(retval != 0)) {
@@ -1561,36 +2145,39 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZEND_VM_CONTINUE(); /* CHECK_ME */
} else {
#if DEBUG_ZEND>=2
- printf("Conditional jmp on false to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.u.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = &opline->op1.u.constant;
+ zval *val;
int retval;
- if (IS_CONST == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = opline->op1.zv;
+
+ if (IS_CONST == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (!retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -1598,27 +2185,30 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = &opline->op1.u.constant;
+ zval *val;
int retval;
- if (IS_CONST == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = opline->op1.zv;
+
+ if (IS_CONST == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -1626,14 +2216,19 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *fname = &opline->op1.u.constant;
+ zval *fname = opline->op1.zv;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- if (zend_hash_quick_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, Z_LVAL(opline->op2.u.constant), (void **) &EX(function_state).function)==FAILURE) {
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
+ SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
+ } else {
+ CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function);
}
EX(object) = NULL;
@@ -1642,94 +2237,125 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *retval_ptr;
- zval **retval_ptr_ptr;
- if (EG(active_op_array)->return_reference == ZEND_RETURN_REF) {
+ SAVE_OPLINE();
+ retval_ptr = opline->op1.zv;
+
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_CONST == IS_TMP_VAR) {
- if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
- /* Not supposed to happen, but we'll allow it */
- zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
}
+ } else if (!0) { /* Not a temp var */
+ if (IS_CONST == IS_CONST ||
+ (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ zval *ret;
- retval_ptr_ptr = NULL;
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) &&
+ retval_ptr == &EG(uninitialized_zval)) {
+ zval *ret;
- if (IS_CONST == IS_VAR && !retval_ptr_ptr) {
- zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
+ ALLOC_INIT_ZVAL(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
}
+ } else {
+ zval *ret;
- if (IS_CONST == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
- if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference) {
- } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
- if (IS_CONST == IS_VAR && !0) {
- PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
- }
- zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
- }
- }
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
- if (EG(return_value_ptr_ptr)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
- Z_ADDREF_PP(retval_ptr_ptr);
+ return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
- (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
- }
- } else {
-return_by_value:
+static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *retval_ptr;
+ zval **retval_ptr_ptr;
- retval_ptr = &opline->op1.u.constant;
- if (!EG(return_value_ptr_ptr)) {
- if (IS_CONST == IS_TMP_VAR) {
+ SAVE_OPLINE();
- }
- } else if (!0) { /* Not a temp var */
- if (IS_CONST == IS_CONST ||
- EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
- (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ do {
+ if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
+ /* Not supposed to happen, but we'll allow it */
+ zend_error(E_NOTICE, "Only variable references should be returned by reference");
+
+ retval_ptr = opline->op1.zv;
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_CONST == IS_TMP_VAR) {
+
+ }
+ } else if (!0) { /* Not a temp var */
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
*EG(return_value_ptr_ptr) = ret;
- } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) &&
- retval_ptr == &EG(uninitialized_zval)) {
+ } else {
zval *ret;
- ALLOC_INIT_ZVAL(ret);
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
- } else {
- *EG(return_value_ptr_ptr) = retval_ptr;
- Z_ADDREF_P(retval_ptr);
}
- } else {
- zval *ret;
+ break;
+ }
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- *EG(return_value_ptr_ptr) = ret;
+ retval_ptr_ptr = NULL;
+
+ if (IS_CONST == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
- }
+
+ if (IS_CONST == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
+ if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
+ EX_T(opline->op1.var).var.fcall_returned_reference) {
+ } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be returned by reference");
+ if (EG(return_value_ptr_ptr)) {
+ retval_ptr = *retval_ptr_ptr;
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ break;
+ }
+ }
+
+ if (EG(return_value_ptr_ptr)) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+ Z_ADDREF_PP(retval_ptr_ptr);
+
+ *EG(return_value_ptr_ptr) = *retval_ptr_ptr;
+ }
+ } while (0);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *value;
zval *exception;
- value = &opline->op1.u.constant;
+ SAVE_OPLINE();
+ value = opline->op1.zv;
- if (IS_CONST == IS_CONST || Z_TYPE_P(value) != IS_OBJECT) {
+ if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
zend_exception_save(TSRMLS_C);
@@ -1743,22 +2369,24 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_throw_exception_object(exception TSRMLS_CC);
zend_exception_restore(TSRMLS_C);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
- && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
- zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
+ && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
+ zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num);
}
{
zval *valptr;
zval *value;
- value = &opline->op1.u.constant;
+ value = opline->op1.zv;
ALLOC_ZVAL(valptr);
INIT_PZVAL_COPY(valptr, value);
@@ -1768,40 +2396,45 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
zend_vm_stack_push(valptr TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval *retval = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
/* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = i_zend_is_true(&opline->op1.u.constant);
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ ZVAL_BOOL(retval, i_zend_is_true(opline->op1.zv));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *obj = &opline->op1.u.constant;
+ zval *obj;
zend_class_entry *ce;
zend_function *clone;
zend_object_clone_obj_t clone_call;
+ SAVE_OPLINE();
+ obj = opline->op1.zv;
+
if (IS_CONST == IS_CONST ||
- (IS_CONST == IS_VAR && !obj) ||
- Z_TYPE_P(obj) != IS_OBJECT) {
+ UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
}
ce = Z_OBJCE_P(obj);
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
- if (!clone_call) {
+ if (UNEXPECTED(clone_call == NULL)) {
if (ce) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
} else {
@@ -1813,42 +2446,49 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (ce != EG(scope)) {
+ if (UNEXPECTED(ce != EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(clone->common.scope, EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
}
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (!EG(exception)) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_OBJVAL_P(EX_T(opline->result.u.var).var.ptr) = clone_call(obj TSRMLS_CC);
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT;
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- Z_SET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- if (!RETURN_VALUE_USED(opline) || EG(exception)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (EXPECTED(EG(exception) == NULL)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ Z_OBJVAL_P(retval) = clone_call(obj TSRMLS_CC);
+ Z_TYPE_P(retval) = IS_OBJECT;
+ Z_SET_REFCOUNT_P(retval, 1);
+ Z_SET_ISREF_P(retval);
+ if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor(&retval);
+ } else {
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *expr = &opline->op1.u.constant;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *expr;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
+ expr = opline->op1.zv;
if (opline->extended_value != IS_STRING) {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!0) {
zendi_zval_copy_ctor(*result);
}
@@ -1872,12 +2512,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_make_printable_zval(expr, &var_copy, &use_copy);
if (use_copy) {
- *result = var_copy;
+ ZVAL_COPY_VALUE(result, &var_copy);
if (0) {
}
} else {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!0) {
zendi_zval_copy_ctor(*result);
}
@@ -1892,37 +2532,38 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
break;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_op_array *new_op_array=NULL;
- int return_value_used;
- zval *inc_filename = &opline->op1.u.constant;
- zval *tmp_inc_filename = NULL;
+ zval *inc_filename;
+ zval *tmp_inc_filename = NULL;
zend_bool failure_retval=0;
+ SAVE_OPLINE();
+ inc_filename = opline->op1.zv;
+
if (inc_filename->type!=IS_STRING) {
MAKE_STD_ZVAL(tmp_inc_filename);
- *tmp_inc_filename = *inc_filename;
+ ZVAL_COPY_VALUE(tmp_inc_filename, inc_filename);
zval_copy_ctor(tmp_inc_filename);
convert_to_string(tmp_inc_filename);
inc_filename = tmp_inc_filename;
}
- return_value_used = RETURN_VALUE_USED(opline);
-
- if (Z_LVAL(opline->op2.u.constant) != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE || Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE) {
+ if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
} else {
- switch (Z_LVAL(opline->op2.u.constant)) {
+ switch (opline->extended_value) {
case ZEND_INCLUDE_ONCE:
case ZEND_REQUIRE_ONCE: {
zend_file_handle file_handle;
@@ -1944,14 +2585,14 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
}
if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1)==SUCCESS) {
- new_op_array = zend_compile_file(&file_handle, (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
+ new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
zend_file_handle_dtor(&file_handle TSRMLS_CC);
failure_retval=1;
}
} else {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
@@ -1964,7 +2605,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
- new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -1980,12 +2621,18 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
zval_ptr_dtor(&tmp_inc_filename);
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (new_op_array && !EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ } else if (EXPECTED(new_op_array != NULL)) {
EX(original_return_value) = EG(return_value_ptr_ptr);
- EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
EG(active_op_array) = new_op_array;
- EX_T(opline->result.u.var).var.ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.var).var.ptr = NULL;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ EG(return_value_ptr_ptr) = EX_T(opline->result.var).var.ptr_ptr;
+ } else {
+ EG(return_value_ptr_ptr) = NULL;
+ }
EX(current_object) = EX(object);
@@ -1996,8 +2643,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
zend_rebuild_symbol_table(TSRMLS_C);
}
- if (zend_execute == execute) {
- EX(call_opline) = opline;
+ if (EXPECTED(zend_execute == execute)) {
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array TSRMLS_CC);
@@ -2006,121 +2652,39 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
EX(function_state).function = (zend_function *) EX(op_array);
EX(object) = EX(current_object);
- if (return_value_used) {
- if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- }
- } else {
- if (return_value_used) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_ZVAL(*EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = failure_retval;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zval tmp, *varname;
- HashTable *target_symbol_table;
+ HANDLE_EXCEPTION();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
-
- if (IS_CONST == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EG(active_symbol_table)) {
- zend_execute_data *ex = EX(prev_execute_data);
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_del(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) {
- while (ex && ex->symbol_table == EG(active_symbol_table)) {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == cv->hash_value &&
- ex->op_array->vars[i].name_len == cv->name_len &&
- !memcmp(ex->op_array->vars[i].name, cv->name, cv->name_len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
}
- EX(CVs)[opline->op1.u.var] = NULL;
- } else if (EX(CVs)[opline->op1.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op1.u.var]);
- EX(CVs)[opline->op1.u.var] = NULL;
}
- ZEND_VM_NEXT_OPCODE();
- }
-
- varname = &opline->op1.u.constant;
-
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- Z_ADDREF_P(varname);
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
- } else {
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_quick_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value) == SUCCESS) {
- zend_execute_data *ex = execute_data;
+ } else if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- do {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- } while (ex && ex->symbol_table == target_symbol_table);
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, failure_retval);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
-
- if (varname == &tmp) {
- zval_dtor(&tmp);
- } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- zval_ptr_dtor(&varname);
- }
-
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
@@ -2128,14 +2692,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
zend_class_entry *ce = NULL;
zend_bool is_empty = 0;
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ SAVE_OPLINE();
+
+ if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) &&
+ (opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
array_ptr_ptr = NULL;
if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) {
- ALLOC_INIT_ZVAL(array_ptr);
+ MAKE_STD_ZVAL(array_ptr);
+ ZVAL_NULL(array_ptr);
} else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) {
if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) {
zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
ce = Z_OBJCE_PP(array_ptr_ptr);
@@ -2155,7 +2723,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
Z_ADDREF_P(array_ptr);
}
} else {
- array_ptr = &opline->op1.u.constant;
+ array_ptr = opline->op1.zv;
if (0) { /* IS_TMP_VAR */
zval *tmp;
@@ -2191,50 +2759,35 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
if (ce && ce->get_iterator) {
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_RESET_REFERENCE TSRMLS_CC);
- if (iter && !EG(exception)) {
+ if (iter && EXPECTED(EG(exception) == NULL)) {
array_ptr = zend_iterator_wrap(iter TSRMLS_CC);
} else {
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- } else {
-
- }
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
- AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr);
- PZVAL_LOCK(array_ptr);
+ EX_T(opline->result.var).fe.ptr = array_ptr;
if (iter) {
iter->index = 0;
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- } else {
-
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
@@ -2257,465 +2810,662 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
}
}
is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->result.var).fe.fe_pos);
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
-
- }
if (is_empty) {
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
} else {
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
-static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_EXIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zval **value;
- zend_bool isset = 1;
-
- if (IS_CONST == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EX(CVs)[opline->op1.u.var]) {
- value = EX(CVs)[opline->op1.u.var];
- } else if (EG(active_symbol_table)) {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
- isset = 0;
- }
- } else {
- isset = 0;
- }
- } else {
- HashTable *target_symbol_table;
+#if 0 || (IS_CONST != IS_UNUSED)
+ USE_OPLINE
- zval tmp, *varname = &opline->op1.u.constant;
+ SAVE_OPLINE();
+ if (IS_CONST != IS_UNUSED) {
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- }
+ zval *ptr = opline->op1.zv;
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1 TSRMLS_CC);
- if (!value) {
- isset = 0;
- }
+ if (Z_TYPE_P(ptr) == IS_LONG) {
+ EG(exit_status) = Z_LVAL_P(ptr);
} else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
- isset = 0;
- }
- }
-
- if (varname == &tmp) {
- zval_dtor(&tmp);
+ zend_print_variable(ptr);
}
}
-
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value & ZEND_ISSET_ISEMPTY_MASK) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- }
- break;
- }
-
- ZEND_VM_NEXT_OPCODE();
+#endif
+ zend_bailout();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
-static int ZEND_FASTCALL ZEND_EXIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
-#if 0 || (IS_CONST != IS_UNUSED)
- zend_op *opline = EX(opline);
- if (IS_CONST != IS_UNUSED) {
+ USE_OPLINE
- zval *ptr = &opline->op1.u.constant;
+ zval *value;
- if (Z_TYPE_P(ptr) == IS_LONG) {
- EG(exit_status) = Z_LVAL_P(ptr);
- } else {
- zend_print_variable(ptr);
+ SAVE_OPLINE();
+ value = opline->op1.zv;
+
+ if (i_zend_is_true(value)) {
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
+ if (!0) {
+ zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
}
- }
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- zend_bailout();
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *value = &opline->op1.u.constant;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = opline->op1.zv;
if (i_zend_is_true(value)) {
- EX_T(opline->result.u.var).tmp_var = *value;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!0) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
+ }
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_JMP(opline->op2.u.jmp_addr);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ zval *value;
- zval *value = &opline->op1.u.constant;
+ SAVE_OPLINE();
+ value = opline->op1.zv;
- EX_T(opline->result.u.var).tmp_var = *value;
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
if (!0) {
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_TICKS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (++EG(ticks_count)>=Z_LVAL(opline->op1.u.constant)) {
- EG(ticks_count)=0;
- if (zend_ticks_function) {
- zend_ticks_function(Z_LVAL(opline->op1.u.constant));
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = opline->op1.zv;
+
+ if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!0) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
}
}
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- add_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- div_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_CONST == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_CONST != IS_TMP_VAR) {
+
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_CONST == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
- zval *container = &opline->op1.u.constant;
- if (Z_TYPE_P(container) != IS_ARRAY) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (IS_CONST != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
}
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_CONST_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *container;
+
+ SAVE_OPLINE();
+ container = opline->op1.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
- zval *dim = &opline->op2.u.constant;
+ zval *value = *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC);
- AI_SET_PTR(EX_T(opline->result.u.var).var, *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC));
- SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr, &opline->result);
+ PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_CONST != IS_UNUSED) {
+
+ if (IS_CONST == IS_CONST &&
+ IS_CONST == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_CONST != IS_CONST &&
+ IS_CONST == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_CONST != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
if (IS_CONST == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = &opline->op2.u.constant;
+ function_name = opline->op2.zv;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -2727,22 +3477,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_CONST != IS_CONST) {
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -2755,18 +3513,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -2774,62 +3526,61 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
+ SAVE_OPLINE();
if (IS_CONST==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- &opline->op2.u.constant TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ opline->op2.zv TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
-
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ SAVE_OPLINE();
if (IS_CONST == IS_UNUSED) {
- /* namespaced constant */
- if (!zend_get_constant_ex(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) {
+ zend_constant *c;
+ zval *retval;
+
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ c = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL(opline->op2.u.constant), '\\', Z_STRLEN(opline->op2.u.constant));
+ char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
if(!actual) {
- actual = Z_STRVAL(opline->op2.u.constant);
+ actual = Z_STRVAL_P(opline->op2.zv);
} else {
actual++;
}
/* non-qualified constant - allow text substitution */
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- ZVAL_STRINGL(&EX_T(opline->result.u.var).tmp_var, actual, Z_STRLEN(opline->op2.u.constant)-(actual - Z_STRVAL(opline->op2.u.constant)), 1);
+ ZVAL_STRINGL(&EX_T(opline->result.var).tmp_var, actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv)), 1);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
} else {
- zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
- Z_STRVAL(opline->op2.u.constant), Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, c);
}
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, &c->value);
+ zval_copy_ctor(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
@@ -2837,19 +3588,33 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
zval **value;
if (IS_CONST == IS_CONST) {
-
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ value = CACHED_PTR(opline->op2.literal->cache_slot);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
+ if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
}
- if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+ if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
@@ -2858,52 +3623,47 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
- EX_T(opline->result.u.var).tmp_var = **value;
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, value);
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+ }
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=&opline->op2.u.constant;
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=&opline->op1.u.constant;
- }
-#else
- expr_ptr=&opline->op1.u.constant;
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=opline->op1.zv;
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -2914,20 +3674,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *offset = opline->op2.zv;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -2937,21 +3714,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CONST == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CONST != IS_UNUSED
@@ -2961,18 +3739,184 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_H
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+
+ zval tmp, *varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *name = &opline->op1.u.constant;
- zval *val = &opline->op2.u.constant;
+ zval *name;
+ zval *val;
zend_constant c;
+ SAVE_OPLINE();
+ name = opline->op1.zv;
+ val = opline->op2.zv;
+
if ((Z_TYPE_P(val) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT || Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
- zval tmp = *val;
+ zval tmp;
zval *tmp_ptr = &tmp;
+ ZVAL_COPY_VALUE(&tmp, val);
if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) {
zval_copy_ctor(&tmp);
}
@@ -2980,11 +3924,11 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
zval_update_constant(&tmp_ptr, NULL TSRMLS_CC);
c.value = *tmp_ptr;
} else {
- c.value = *val;
+ INIT_PZVAL_COPY(&c.value, val);
zval_copy_ctor(&c.value);
}
c.flags = CONST_CS; /* non persistent, case sensetive */
- c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
c.name_len = Z_STRLEN_P(name)+1;
c.module_number = PHP_USER_CONSTANT;
@@ -2992,307 +3936,338 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
}
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_function *op_array;
-
- if (zend_hash_quick_find(EG(function_table), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), Z_LVAL(opline->op2.u.constant), (void *) &op_array) == FAILURE ||
- op_array->type != ZEND_USER_FUNCTION) {
- zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
- }
-
- zend_create_closure(&EX_T(opline->result.u.var).tmp_var, op_array TSRMLS_CC);
-
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_TMP_VAR != IS_UNUSED) {
+
+ if (IS_CONST == IS_CONST &&
+ IS_TMP_VAR == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_CONST != IS_CONST &&
+ IS_TMP_VAR == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_TMP_VAR != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
zend_free_op free_op2;
if (IS_TMP_VAR == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -3304,22 +4279,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_TMP_VAR != IS_CONST) {
zval_dtor(free_op2.var);
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -3332,18 +4315,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -3351,77 +4328,53 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op2;
+ SAVE_OPLINE();
if (IS_CONST==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
-
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+
zval *expr_ptr;
- zval *offset=_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=&opline->op1.u.constant;
- }
-#else
- expr_ptr=&opline->op1.u.constant;
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=opline->op1.zv;
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -3432,20 +4385,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -3455,21 +4425,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
}
zval_dtor(free_op2.var);
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CONST == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CONST != IS_UNUSED
@@ -3481,287 +4452,496 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_CONST == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_CONST != IS_TMP_VAR) {
+
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_CONST == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_CONST != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_CONST_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_VAR != IS_UNUSED) {
+
+ if (IS_CONST == IS_CONST &&
+ IS_VAR == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_CONST != IS_CONST &&
+ IS_VAR == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_VAR != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
zend_free_op free_op2;
if (IS_VAR == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -3773,22 +4953,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_VAR != IS_CONST) {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -3801,18 +4989,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -3820,77 +5002,53 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op2;
+ SAVE_OPLINE();
if (IS_CONST==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
-
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+
zval *expr_ptr;
- zval *offset=_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=&opline->op1.u.constant;
- }
-#else
- expr_ptr=&opline->op1.u.constant;
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=opline->op1.zv;
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -3901,20 +5059,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -3924,21 +5099,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CONST == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CONST != IS_UNUSED
@@ -3948,45 +5124,383 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAN
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+
+ zval tmp, *varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_CONST == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_CONST != IS_TMP_VAR) {
+
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_CONST == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_CONST != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_UNUSED != IS_UNUSED) {
+
+ if (IS_CONST == IS_CONST &&
+ IS_UNUSED == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_CONST != IS_CONST &&
+ IS_UNUSED == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_UNUSED != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
if (IS_UNUSED == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
function_name = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -3998,22 +5512,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_UNUSED == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_UNUSED != IS_CONST) {
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -4026,18 +5548,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -4045,45 +5561,35 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=NULL;
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=&opline->op1.u.constant;
- }
-#else
- expr_ptr=&opline->op1.u.constant;
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=opline->op1.zv;
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -4094,20 +5600,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *offset = NULL;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_UNUSED == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -4117,21 +5640,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CONST == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CONST != IS_UNUSED
@@ -4141,289 +5665,513 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+
+ zval tmp, *varname = opline->op1.zv;
+
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_CONST != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_function *op_array;
+
+ SAVE_OPLINE();
+
+ if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), Z_HASH_P(opline->op1.zv), (void *) &op_array) == FAILURE) ||
+ UNEXPECTED(op_array->type != ZEND_USER_FUNCTION)) {
+ zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+ }
+
+ zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- add_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- div_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_CV != IS_UNUSED) {
+
+ if (IS_CONST == IS_CONST &&
+ IS_CV == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_CONST != IS_CONST &&
+ IS_CV == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_CV != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
if (IS_CV == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -4435,22 +6183,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_CV == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_CV != IS_CONST) {
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -4463,18 +6219,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -4482,76 +6232,112 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
+ zend_class_entry *ce, *catch_ce;
+ zval *exception;
+ SAVE_OPLINE();
+ /* Check whether an exception has been thrown, if not, jump over code */
+ zend_exception_restore(TSRMLS_C);
+ if (EG(exception) == NULL) {
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_CONTINUE(); /* CHECK_ME */
+ }
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ catch_ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
- if (IS_CONST==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
+ CACHE_PTR(opline->op1.literal->cache_slot, catch_ce);
+ }
+ ce = Z_OBJCE_P(EG(exception));
+
+#ifdef HAVE_DTRACE
+ if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
+ DTRACE_EXCEPTION_CAUGHT(ce->name);
+ }
+#endif /* HAVE_DTRACE */
+
+ if (ce != catch_ce) {
+ if (!instanceof_function(ce, catch_ce TSRMLS_CC)) {
+ if (opline->result.num) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ HANDLE_EXCEPTION();
+ }
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- &opline->op1.u.constant,
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
+ exception = EG(exception);
+ if (!EG(active_symbol_table)) {
+ if (EX_CV(opline->op2.var)) {
+ zval_ptr_dtor(EX_CV(opline->op2.var));
+ }
+ EX_CV(opline->op2.var) = (zval**)EX_CVs() + (EX(op_array)->last_var + opline->op2.var);
+ *EX_CV(opline->op2.var) = EG(exception);
+ } else {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.var);
+ zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value,
+ &EG(exception), sizeof(zval *), (void**)&EX_CV(opline->op2.var));
+ }
+ if (UNEXPECTED(EG(exception) != exception)) {
+ Z_ADDREF_P(EG(exception));
+ HANDLE_EXCEPTION();
+ } else {
+ EG(exception) = NULL;
+ ZEND_VM_NEXT_OPCODE();
+ }
+}
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
+static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+
+ SAVE_OPLINE();
+ if (IS_CONST==IS_VAR) {
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ opline->op1.zv,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=&opline->op1.u.constant;
- }
-#else
- expr_ptr=&opline->op1.u.constant;
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=opline->op1.zv;
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CONST == IS_VAR || IS_CONST == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CONST == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -4562,20 +6348,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CV != IS_UNUSED) {
+
+ zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -4585,21 +6388,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CONST == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CONST != IS_UNUSED
@@ -4611,35 +6415,43 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_not_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_not_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_not_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_not_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval z_copy;
- zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *z;
+
+ SAVE_OPLINE();
+ z = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (IS_TMP_VAR != IS_CONST &&
- Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
+ UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) &&
+ Z_OBJ_HT_P(z)->get_method != NULL) {
if (IS_TMP_VAR == IS_TMP_VAR) {
INIT_PZVAL(z);
}
@@ -4654,172 +6466,42 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRINT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG;
+ USE_OPLINE
+ ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
return ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval *varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval **retval;
- zval tmp_varname;
- HashTable *target_symbol_table;
-
- if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- tmp_varname = *varname;
- zval_copy_ctor(&tmp_varname);
- convert_to_string(&tmp_varname);
- varname = &tmp_varname;
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- retval = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0 TSRMLS_CC);
- zval_dtor(free_op1.var);
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);
-/*
- if (!target_symbol_table) {
- ZEND_VM_NEXT_OPCODE();
- }
-*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval_ptr);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_W: {
- zval *new_zval = &EG(uninitialized_zval);
-
- Z_ADDREF_P(new_zval);
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
- }
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
- switch (opline->op2.u.EA.type) {
- case ZEND_FETCH_GLOBAL:
- if (IS_TMP_VAR != IS_TMP_VAR) {
- zval_dtor(free_op1.var);
- }
- break;
- case ZEND_FETCH_LOCAL:
- zval_dtor(free_op1.var);
- break;
- case ZEND_FETCH_STATIC:
- zval_update_constant(retval, (void*) 1 TSRMLS_CC);
- break;
- case ZEND_FETCH_GLOBAL_LOCK:
- if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- break;
- }
- }
-
-
- if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
- zval_dtor(varname);
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- }
- PZVAL_LOCK(*retval);
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_IS:
- AI_SET_PTR(EX_T(opline->result.u.var).var, *retval);
- break;
- case BP_VAR_UNSET: {
- zend_free_op free_res;
-
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- }
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
- FREE_OP_VAR_PTR(free_res);
- break;
- default:
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- break;
- }
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_TMP(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_TMP(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_TMP(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_TMP(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_TMP(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int ret;
- if (IS_TMP_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
zval_dtor(free_op1.var);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (!ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -4828,25 +6510,28 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int ret;
- if (IS_TMP_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
zval_dtor(free_op1.var);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -4855,18 +6540,21 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_TMP_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
zval_dtor(free_op1.var);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (EXPECTED(retval != 0)) {
@@ -4877,36 +6565,39 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_CONTINUE(); /* CHECK_ME */
} else {
#if DEBUG_ZEND>=2
- printf("Conditional jmp on false to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.u.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_TMP_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
zval_dtor(free_op1.var);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (!retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -4914,27 +6605,30 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_TMP_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
zval_dtor(free_op1.var);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -4942,40 +6636,114 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
static int ZEND_FASTCALL ZEND_FREE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zendi_zval_dtor(EX_T(EX(opline)->op1.u.var).tmp_var);
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_TMP_VAR) {
+ zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
+ } else {
+ zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+ }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval *retval_ptr;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_TMP_VAR == IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ } else if (!1) { /* Not a temp var */
+ if (IS_TMP_VAR == IS_CONST ||
+ (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) &&
+ retval_ptr == &EG(uninitialized_zval)) {
+ zval *ret;
+
+ ALLOC_INIT_ZVAL(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ } else {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
+
+ return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
zval *retval_ptr;
zval **retval_ptr_ptr;
zend_free_op free_op1;
- if (EG(active_op_array)->return_reference == ZEND_RETURN_REF) {
+ SAVE_OPLINE();
+ do {
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
+
+ retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_TMP_VAR == IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ } else if (!1) { /* Not a temp var */
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
+ break;
}
retval_ptr_ptr = NULL;
- if (IS_TMP_VAR == IS_VAR && !retval_ptr_ptr) {
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference) {
- } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
- if (IS_TMP_VAR == IS_VAR && !1) {
- PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
- }
+ EX_T(opline->op1.var).var.fcall_returned_reference) {
+ } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
+ if (EG(return_value_ptr_ptr)) {
+ retval_ptr = *retval_ptr_ptr;
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ break;
}
}
@@ -4983,59 +6751,24 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
Z_ADDREF_PP(retval_ptr_ptr);
- (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
- }
- } else {
-return_by_value:
-
- retval_ptr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
- if (!EG(return_value_ptr_ptr)) {
- if (IS_TMP_VAR == IS_TMP_VAR) {
- zval_dtor(free_op1.var);
- }
- } else if (!1) { /* Not a temp var */
- if (IS_TMP_VAR == IS_CONST ||
- EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
- (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
- zval *ret;
-
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- zval_copy_ctor(ret);
- *EG(return_value_ptr_ptr) = ret;
- } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) &&
- retval_ptr == &EG(uninitialized_zval)) {
- zval *ret;
-
- ALLOC_INIT_ZVAL(ret);
- *EG(return_value_ptr_ptr) = ret;
- } else {
- *EG(return_value_ptr_ptr) = retval_ptr;
- Z_ADDREF_P(retval_ptr);
- }
- } else {
- zval *ret;
-
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- *EG(return_value_ptr_ptr) = ret;
+ *EG(return_value_ptr_ptr) = *retval_ptr_ptr;
}
- }
+ } while (0);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *value;
zval *exception;
zend_free_op free_op1;
- value = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_TMP_VAR == IS_CONST || Z_TYPE_P(value) != IS_OBJECT) {
+ if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
zend_exception_save(TSRMLS_C);
@@ -5049,22 +6782,24 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_throw_exception_object(exception TSRMLS_CC);
zend_exception_restore(TSRMLS_C);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
- && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
- zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
+ && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
+ zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num);
}
{
zval *valptr;
zval *value;
zend_free_op free_op1;
- value = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
ALLOC_ZVAL(valptr);
INIT_PZVAL_COPY(valptr, value);
@@ -5074,41 +6809,46 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_vm_stack_push(valptr TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
+ zval *retval = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
/* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = i_zend_is_true(_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC));
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *obj = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *obj;
zend_class_entry *ce;
zend_function *clone;
zend_object_clone_obj_t clone_call;
+ SAVE_OPLINE();
+ obj = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
if (IS_TMP_VAR == IS_CONST ||
- (IS_TMP_VAR == IS_VAR && !obj) ||
- Z_TYPE_P(obj) != IS_OBJECT) {
+ UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
}
ce = Z_OBJCE_P(obj);
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
- if (!clone_call) {
+ if (UNEXPECTED(clone_call == NULL)) {
if (ce) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
} else {
@@ -5120,42 +6860,49 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (ce != EG(scope)) {
+ if (UNEXPECTED(ce != EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(clone->common.scope, EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
}
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (!EG(exception)) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_OBJVAL_P(EX_T(opline->result.u.var).var.ptr) = clone_call(obj TSRMLS_CC);
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT;
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- Z_SET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- if (!RETURN_VALUE_USED(opline) || EG(exception)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (EXPECTED(EG(exception) == NULL)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ Z_OBJVAL_P(retval) = clone_call(obj TSRMLS_CC);
+ Z_TYPE_P(retval) = IS_OBJECT;
+ Z_SET_REFCOUNT_P(retval, 1);
+ Z_SET_ISREF_P(retval);
+ if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor(&retval);
+ } else {
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *expr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *expr;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (opline->extended_value != IS_STRING) {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!1) {
zendi_zval_copy_ctor(*result);
}
@@ -5179,12 +6926,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_make_printable_zval(expr, &var_copy, &use_copy);
if (use_copy) {
- *result = var_copy;
+ ZVAL_COPY_VALUE(result, &var_copy);
if (1) {
zval_dtor(free_op1.var);
}
} else {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!1) {
zendi_zval_copy_ctor(*result);
}
@@ -5199,37 +6946,38 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
break;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_op_array *new_op_array=NULL;
- int return_value_used;
zend_free_op free_op1;
- zval *inc_filename = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *tmp_inc_filename = NULL;
+ zval *inc_filename;
+ zval *tmp_inc_filename = NULL;
zend_bool failure_retval=0;
+ SAVE_OPLINE();
+ inc_filename = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
if (inc_filename->type!=IS_STRING) {
MAKE_STD_ZVAL(tmp_inc_filename);
- *tmp_inc_filename = *inc_filename;
+ ZVAL_COPY_VALUE(tmp_inc_filename, inc_filename);
zval_copy_ctor(tmp_inc_filename);
convert_to_string(tmp_inc_filename);
inc_filename = tmp_inc_filename;
}
- return_value_used = RETURN_VALUE_USED(opline);
-
- if (Z_LVAL(opline->op2.u.constant) != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE || Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE) {
+ if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
} else {
- switch (Z_LVAL(opline->op2.u.constant)) {
+ switch (opline->extended_value) {
case ZEND_INCLUDE_ONCE:
case ZEND_REQUIRE_ONCE: {
zend_file_handle file_handle;
@@ -5251,14 +6999,14 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
}
if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1)==SUCCESS) {
- new_op_array = zend_compile_file(&file_handle, (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
+ new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
zend_file_handle_dtor(&file_handle TSRMLS_CC);
failure_retval=1;
}
} else {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
@@ -5271,7 +7019,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
- new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -5287,12 +7035,18 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
zval_ptr_dtor(&tmp_inc_filename);
}
zval_dtor(free_op1.var);
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (new_op_array && !EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ } else if (EXPECTED(new_op_array != NULL)) {
EX(original_return_value) = EG(return_value_ptr_ptr);
- EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
EG(active_op_array) = new_op_array;
- EX_T(opline->result.u.var).var.ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.var).var.ptr = NULL;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ EG(return_value_ptr_ptr) = EX_T(opline->result.var).var.ptr_ptr;
+ } else {
+ EG(return_value_ptr_ptr) = NULL;
+ }
EX(current_object) = EX(object);
@@ -5303,8 +7057,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
zend_rebuild_symbol_table(TSRMLS_C);
}
- if (zend_execute == execute) {
- EX(call_opline) = opline;
+ if (EXPECTED(zend_execute == execute)) {
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array TSRMLS_CC);
@@ -5313,121 +7066,39 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
EX(function_state).function = (zend_function *) EX(op_array);
EX(object) = EX(current_object);
- if (return_value_used) {
- if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- }
- } else {
- if (return_value_used) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_ZVAL(*EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = failure_retval;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zval tmp, *varname;
- HashTable *target_symbol_table;
- zend_free_op free_op1;
+ HANDLE_EXCEPTION();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
- if (IS_TMP_VAR == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EG(active_symbol_table)) {
- zend_execute_data *ex = EX(prev_execute_data);
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_del(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) {
- while (ex && ex->symbol_table == EG(active_symbol_table)) {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == cv->hash_value &&
- ex->op_array->vars[i].name_len == cv->name_len &&
- !memcmp(ex->op_array->vars[i].name, cv->name, cv->name_len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
}
- EX(CVs)[opline->op1.u.var] = NULL;
- } else if (EX(CVs)[opline->op1.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op1.u.var]);
- EX(CVs)[opline->op1.u.var] = NULL;
}
- ZEND_VM_NEXT_OPCODE();
- }
- varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- Z_ADDREF_P(varname);
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
- } else {
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
-
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_quick_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value) == SUCCESS) {
- zend_execute_data *ex = execute_data;
+ } else if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- do {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- } while (ex && ex->symbol_table == target_symbol_table);
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, failure_retval);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
-
- if (varname == &tmp) {
- zval_dtor(&tmp);
- } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- zval_ptr_dtor(&varname);
- }
- zval_dtor(free_op1.var);
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
@@ -5435,14 +7106,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_class_entry *ce = NULL;
zend_bool is_empty = 0;
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ SAVE_OPLINE();
+
+ if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) &&
+ (opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
array_ptr_ptr = NULL;
if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) {
- ALLOC_INIT_ZVAL(array_ptr);
+ MAKE_STD_ZVAL(array_ptr);
+ ZVAL_NULL(array_ptr);
} else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) {
if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) {
zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
ce = Z_OBJCE_PP(array_ptr_ptr);
@@ -5462,7 +7137,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
Z_ADDREF_P(array_ptr);
}
} else {
- array_ptr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ array_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (1) { /* IS_TMP_VAR */
zval *tmp;
@@ -5498,50 +7173,35 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (ce && ce->get_iterator) {
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_RESET_REFERENCE TSRMLS_CC);
- if (iter && !EG(exception)) {
+ if (iter && EXPECTED(EG(exception) == NULL)) {
array_ptr = zend_iterator_wrap(iter TSRMLS_CC);
} else {
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
- }
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
- AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr);
- PZVAL_LOCK(array_ptr);
+ EX_T(opline->result.var).fe.ptr = array_ptr;
if (iter) {
iter->index = 0;
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- } else {
-
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
@@ -5564,101 +7224,29 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
}
is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->result.var).fe.fe_pos);
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
-
- }
if (is_empty) {
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
} else {
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
-static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zval **value;
- zend_bool isset = 1;
-
- if (IS_TMP_VAR == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EX(CVs)[opline->op1.u.var]) {
- value = EX(CVs)[opline->op1.u.var];
- } else if (EG(active_symbol_table)) {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
- isset = 0;
- }
- } else {
- isset = 0;
- }
- } else {
- HashTable *target_symbol_table;
- zend_free_op free_op1;
- zval tmp, *varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1 TSRMLS_CC);
- if (!value) {
- isset = 0;
- }
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
- isset = 0;
- }
- }
-
- if (varname == &tmp) {
- zval_dtor(&tmp);
- }
- zval_dtor(free_op1.var);
- }
-
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value & ZEND_ISSET_ISEMPTY_MASK) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- }
- break;
- }
-
- ZEND_VM_NEXT_OPCODE();
-}
-
static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
#if 0 || (IS_TMP_VAR != IS_UNUSED)
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- zval *ptr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
@@ -5669,348 +7257,635 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
#endif
zend_bailout();
- ZEND_VM_NEXT_OPCODE();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval restored_error_reporting;
- if (!EG(error_reporting) && Z_LVAL(EX_T(opline->op1.u.var).tmp_var) != 0) {
+ SAVE_OPLINE();
+ if (!EG(error_reporting) && Z_LVAL(EX_T(opline->op1.var).tmp_var) != 0) {
Z_TYPE(restored_error_reporting) = IS_LONG;
- Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.u.var).tmp_var);
+ Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.var).tmp_var);
+ EG(error_reporting) = Z_LVAL(restored_error_reporting);
convert_to_string(&restored_error_reporting);
- zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC);
- zendi_zval_dtor(restored_error_reporting);
+ if (EXPECTED(EG(error_reporting_ini_entry) != NULL)) {
+ if (EXPECTED(EG(error_reporting_ini_entry)->modified &&
+ EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value)) {
+ efree(EG(error_reporting_ini_entry)->value);
+ }
+ EG(error_reporting_ini_entry)->value = Z_STRVAL(restored_error_reporting);
+ EG(error_reporting_ini_entry)->value_length = Z_STRLEN(restored_error_reporting);
+ } else {
+ zendi_zval_dtor(restored_error_reporting);
+ }
}
- if (EX(old_error_reporting) == &EX_T(opline->op1.u.var).tmp_var) {
+ if (EX(old_error_reporting) == &EX_T(opline->op1.var).tmp_var) {
EX(old_error_reporting) = NULL;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (i_zend_is_true(value)) {
- EX_T(opline->result.u.var).tmp_var = *value;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
- zval_dtor(free_op1.var);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
+ if (!1) {
+ zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+ }
+
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_JMP(opline->op2.u.jmp_addr);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (i_zend_is_true(value)) {
+ if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!1) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
+ }
+
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
- EX_T(opline->result.u.var).tmp_var = *value;
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
if (!1) {
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!1) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *expr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *expr;
zend_bool result;
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) {
- result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.u.var).class_entry TSRMLS_CC);
+ result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC);
} else {
result = 0;
}
- ZVAL_BOOL(&EX_T(opline->result.u.var).tmp_var, result);
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, result);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ zval_dtor(free_op1.var);
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_TMP_VAR == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_TMP_VAR != IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+ zval_dtor(free_op1.var);
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
- if (Z_TYPE_P(container) != IS_ARRAY) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
}
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_TMP_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
- zval *dim = &opline->op2.u.constant;
+ zval *value = *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC);
- AI_SET_PTR(EX_T(opline->result.u.var).var, *zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, BP_VAR_R TSRMLS_CC));
- SELECTIVE_PZVAL_LOCK(EX_T(opline->result.u.var).var.ptr, &opline->result);
+ PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zval *str = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
if (IS_TMP_VAR == IS_UNUSED) {
/* Initialize for erealloc in add_char_to_string */
@@ -6021,16 +7896,19 @@ static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL
INIT_PZVAL(str);
}
- add_char_to_string(str, str, &opline->op2.u.constant);
+ add_char_to_string(str, str, opline->op2.zv);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zval *str = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
if (IS_TMP_VAR == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
@@ -6041,45 +7919,60 @@ static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAN
INIT_PZVAL(str);
}
- add_string_to_string(str, str, &opline->op2.u.constant);
+ add_string_to_string(str, str, opline->op2.zv);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = &opline->op2.u.constant;
+ function_name = opline->op2.zv;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CONST != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CONST != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -6099,76 +7992,52 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1;
+ SAVE_OPLINE();
if (IS_TMP_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- zval_dtor(free_op1.var);
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=&opline->op2.u.constant;
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (1) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (1) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -6179,20 +8048,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *offset = opline->op2.zv;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -6202,21 +8088,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_TMP_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_TMP_VAR != IS_UNUSED
@@ -6226,259 +8113,455 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAN
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+ zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+ zval_dtor(free_op1.var);
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_TMP_VAR == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -6508,42 +8591,57 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_
*/
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_TMP_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_TMP_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -6564,77 +8662,53 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
if (IS_TMP_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- zval_dtor(free_op1.var);
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1, free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zend_free_op free_op1;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (1) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (1) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -6645,20 +8719,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -6668,21 +8759,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
}
zval_dtor(free_op2.var);
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_TMP_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_TMP_VAR != IS_UNUSED
@@ -6694,257 +8786,456 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ zval_dtor(free_op1.var);
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_TMP_VAR == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_TMP_VAR != IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+ zval_dtor(free_op1.var);
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_TMP_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_TMP_VAR == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -6974,42 +9265,57 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_
*/
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -7030,77 +9336,53 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
if (IS_TMP_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- zval_dtor(free_op1.var);
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1, free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zend_free_op free_op1;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (1) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (1) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -7111,20 +9393,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -7134,21 +9433,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_TMP_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_TMP_VAR != IS_UNUSED
@@ -7158,42 +9458,356 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDL
}
}
-static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
zend_free_op free_op1;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
- zval *expr_ptr;
- zval *offset=NULL;
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
- expr_ptr = *expr_ptr_ptr;
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
} else {
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
}
-#else
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
- if (1) { /* temporary variable */
- zval *new_expr;
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+ zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+ zval_dtor(free_op1.var);
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ zval_dtor(free_op1.var);
} else {
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_TMP_VAR == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_TMP_VAR != IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+ zval_dtor(free_op1.var);
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_TMP_VAR == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *expr_ptr;
+
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
+
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
+ expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
+ } else {
+ expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (1) { /* temporary variable */
+ zval *new_expr;
+
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -7204,20 +9818,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *offset = NULL;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_UNUSED == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -7227,21 +9858,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_TMP_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_TMP_VAR != IS_UNUSED
@@ -7251,259 +9883,455 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HA
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_TMP_VAR == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+ zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+ zval_dtor(free_op1.var);
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op1.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
if (IS_TMP_VAR == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -7532,42 +10360,57 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_A
* string offsets or overloaded objects
*/
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CV != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CV != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -7587,76 +10430,52 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1;
+ SAVE_OPLINE();
if (IS_TMP_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- zval_dtor(free_op1.var);
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = NULL;
- if (opline->extended_value) {
- expr_ptr_ptr=NULL;
+ if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (1) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (1) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_TMP_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -7667,20 +10486,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CV != IS_UNUSED) {
+
+ zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -7690,21 +10526,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_TMP_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_TMP_VAR != IS_UNUSED
@@ -7716,193 +10553,223 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_not_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_not_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_not_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_not_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **var_ptr;
+
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !var_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (IS_VAR == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- increment_function(val);
+ fast_increment_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- increment_function(*var_ptr);
+ fast_increment_function(*var_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **var_ptr;
+
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !var_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (IS_VAR == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- decrement_function(val);
+ fast_decrement_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- decrement_function(*var_ptr);
+ fast_decrement_function(*var_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **var_ptr, *retval;
+
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !var_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr);
- }
+ if (IS_VAR == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ ZVAL_NULL(&EX_T(opline->result.var).tmp_var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- EX_T(opline->result.u.var).tmp_var = **var_ptr;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, *var_ptr);
+ zendi_zval_copy_ctor(*retval);
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- increment_function(val);
+ fast_increment_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- increment_function(*var_ptr);
+ fast_increment_function(*var_ptr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **var_ptr, *retval;
+
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !var_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_VAR == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr);
- }
+ if (IS_VAR == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ ZVAL_NULL(&EX_T(opline->result.var).tmp_var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- EX_T(opline->result.u.var).tmp_var = **var_ptr;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, *var_ptr);
+ zendi_zval_copy_ctor(*retval);
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- decrement_function(val);
+ fast_decrement_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- decrement_function(*var_ptr);
+ fast_decrement_function(*var_ptr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval z_copy;
- zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *z;
+
+ SAVE_OPLINE();
+ z = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (IS_VAR != IS_CONST &&
- Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
+ UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) &&
+ Z_OBJ_HT_P(z)->get_method != NULL) {
if (IS_VAR == IS_TMP_VAR) {
INIT_PZVAL(z);
}
@@ -7917,172 +10784,42 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRINT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG;
+ USE_OPLINE
+ ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
return ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval *varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval **retval;
- zval tmp_varname;
- HashTable *target_symbol_table;
-
- if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- tmp_varname = *varname;
- zval_copy_ctor(&tmp_varname);
- convert_to_string(&tmp_varname);
- varname = &tmp_varname;
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- retval = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0 TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);
-/*
- if (!target_symbol_table) {
- ZEND_VM_NEXT_OPCODE();
- }
-*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval_ptr);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_W: {
- zval *new_zval = &EG(uninitialized_zval);
-
- Z_ADDREF_P(new_zval);
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
- }
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
- switch (opline->op2.u.EA.type) {
- case ZEND_FETCH_GLOBAL:
- if (IS_VAR != IS_TMP_VAR) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
- break;
- case ZEND_FETCH_LOCAL:
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- break;
- case ZEND_FETCH_STATIC:
- zval_update_constant(retval, (void*) 1 TSRMLS_CC);
- break;
- case ZEND_FETCH_GLOBAL_LOCK:
- if (IS_VAR == IS_VAR && !free_op1.var) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- break;
- }
- }
-
-
- if (IS_VAR != IS_CONST && varname == &tmp_varname) {
- zval_dtor(varname);
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- }
- PZVAL_LOCK(*retval);
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_IS:
- AI_SET_PTR(EX_T(opline->result.u.var).var, *retval);
- break;
- case BP_VAR_UNSET: {
- zend_free_op free_res;
-
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- }
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
- FREE_OP_VAR_PTR(free_res);
- break;
- default:
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- break;
- }
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int ret;
- if (IS_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (!ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -8091,25 +10828,28 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int ret;
- if (IS_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -8118,18 +10858,21 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (EXPECTED(retval != 0)) {
@@ -8140,36 +10883,39 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_CONTINUE(); /* CHECK_ME */
} else {
#if DEBUG_ZEND>=2
- printf("Conditional jmp on false to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.u.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (!retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -8177,62 +10923,145 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *val = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_VAR == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_FASTCALL ZEND_FREE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_TMP_VAR) {
+ zendi_zval_dtor(EX_T(opline->op1.var).tmp_var);
+ } else {
+ zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval *retval_ptr;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_VAR == IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ } else if (!0) { /* Not a temp var */
+ if (IS_VAR == IS_CONST ||
+ (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) &&
+ retval_ptr == &EG(uninitialized_zval)) {
+ zval *ret;
+
+ ALLOC_INIT_ZVAL(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ } else {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
zval *retval_ptr;
zval **retval_ptr_ptr;
zend_free_op free_op1;
- if (EG(active_op_array)->return_reference == ZEND_RETURN_REF) {
+ SAVE_OPLINE();
+ do {
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
/* Not supposed to happen, but we'll allow it */
zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
+
+ retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_VAR == IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ } else if (!0) { /* Not a temp var */
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ zval *ret;
+
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
+ break;
}
- retval_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ retval_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !retval_ptr_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
}
if (IS_VAR == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference) {
- } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
- if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
- PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
- }
+ EX_T(opline->op1.var).var.fcall_returned_reference) {
+ } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
+ if (EG(return_value_ptr_ptr)) {
+ retval_ptr = *retval_ptr_ptr;
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ break;
}
}
@@ -8240,59 +11069,25 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
Z_ADDREF_PP(retval_ptr_ptr);
- (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+ *EG(return_value_ptr_ptr) = *retval_ptr_ptr;
}
- } else {
-return_by_value:
-
- retval_ptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ } while (0);
- if (!EG(return_value_ptr_ptr)) {
- if (IS_VAR == IS_TMP_VAR) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
- } else if (!0) { /* Not a temp var */
- if (IS_VAR == IS_CONST ||
- EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
- (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
- zval *ret;
-
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- zval_copy_ctor(ret);
- *EG(return_value_ptr_ptr) = ret;
- } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) &&
- retval_ptr == &EG(uninitialized_zval)) {
- zval *ret;
-
- ALLOC_INIT_ZVAL(ret);
- *EG(return_value_ptr_ptr) = ret;
- } else {
- *EG(return_value_ptr_ptr) = retval_ptr;
- Z_ADDREF_P(retval_ptr);
- }
- } else {
- zval *ret;
-
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- *EG(return_value_ptr_ptr) = ret;
- }
- }
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *value;
zval *exception;
zend_free_op free_op1;
- value = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_CONST || Z_TYPE_P(value) != IS_OBJECT) {
+ if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
zend_exception_save(TSRMLS_C);
@@ -8306,40 +11101,15 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_throw_exception_object(exception TSRMLS_CC);
zend_exception_restore(TSRMLS_C);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
- && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
- zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
- }
- {
- zval *valptr;
- zval *value;
- zend_free_op free_op1;
-
- value = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
- ALLOC_ZVAL(valptr);
- INIT_PZVAL_COPY(valptr, value);
- if (!0) {
- zval_copy_ctor(valptr);
- }
- zend_vm_stack_push(valptr TSRMLS_CC);
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *varptr;
zend_free_op free_op1;
- varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ varptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (varptr == &EG(uninitialized_zval)) {
ALLOC_ZVAL(varptr);
@@ -8349,7 +11119,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_AR
zval *original_var = varptr;
ALLOC_ZVAL(varptr);
- *varptr = *original_var;
+ ZVAL_COPY_VALUE(varptr, original_var);
Z_UNSET_ISREF_P(varptr);
Z_SET_REFCOUNT_P(varptr, 0);
zval_copy_ctor(varptr);
@@ -8358,34 +11128,36 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_AR
zend_vm_stack_push(varptr TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; /* for string offsets */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *varptr;
+ SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
- } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (IS_VAR == IS_VAR &&
(opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference &&
- EX_T(opline->op1.u.var).var.ptr) {
- varptr = EX_T(opline->op1.u.var).var.ptr;
+ EX_T(opline->op1.var).var.fcall_returned_reference &&
+ EX_T(opline->op1.var).var.ptr) {
+ varptr = EX_T(opline->op1.var).var.ptr;
PZVAL_UNLOCK_EX(varptr, &free_op1, 0);
} else {
- varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ varptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
}
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
- EX_T(opline->op1.u.var).var.fcall_returned_reference) &&
+ EX_T(opline->op1.var).var.fcall_returned_reference) &&
varptr != &EG(uninitialized_zval) &&
(PZVAL_IS_REF(varptr) ||
(Z_REFCOUNT_P(varptr) == 1 && (IS_VAR == IS_CV || free_op1.var)))) {
@@ -8397,7 +11169,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
- !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
ALLOC_ZVAL(valptr);
@@ -8408,28 +11180,32 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
zend_vm_stack_push(valptr TSRMLS_CC);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval **varptr_ptr;
zval *varptr;
- varptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !varptr_ptr) {
+ SAVE_OPLINE();
+ varptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
- if (IS_VAR == IS_VAR && *varptr_ptr == EG(error_zval_ptr)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(*varptr_ptr == &EG(error_zval))) {
ALLOC_INIT_ZVAL(varptr);
zend_vm_stack_push(varptr TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@@ -8439,60 +11215,68 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_vm_stack_push(varptr TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME)
- && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+ SAVE_OPLINE();
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
+ zval *retval = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
/* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = i_zend_is_true(_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC));
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SWITCH_FREE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zend_switch_free(&EX_T(opline->op1.u.var), opline->extended_value TSRMLS_CC);
+ SAVE_OPLINE();
+ zval_ptr_dtor(&EX_T(opline->op1.var).var.ptr);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *obj = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *obj;
zend_class_entry *ce;
zend_function *clone;
zend_object_clone_obj_t clone_call;
+ SAVE_OPLINE();
+ obj = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
if (IS_VAR == IS_CONST ||
- (IS_VAR == IS_VAR && !obj) ||
- Z_TYPE_P(obj) != IS_OBJECT) {
+ UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
}
ce = Z_OBJCE_P(obj);
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
- if (!clone_call) {
+ if (UNEXPECTED(clone_call == NULL)) {
if (ce) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
} else {
@@ -8504,42 +11288,49 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (ce != EG(scope)) {
+ if (UNEXPECTED(ce != EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(clone->common.scope, EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
}
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (!EG(exception)) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_OBJVAL_P(EX_T(opline->result.u.var).var.ptr) = clone_call(obj TSRMLS_CC);
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT;
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- Z_SET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- if (!RETURN_VALUE_USED(opline) || EG(exception)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (EXPECTED(EG(exception) == NULL)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ Z_OBJVAL_P(retval) = clone_call(obj TSRMLS_CC);
+ Z_TYPE_P(retval) = IS_OBJECT;
+ Z_SET_REFCOUNT_P(retval, 1);
+ Z_SET_ISREF_P(retval);
+ if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor(&retval);
+ } else {
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *expr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *expr;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (opline->extended_value != IS_STRING) {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!0) {
zendi_zval_copy_ctor(*result);
}
@@ -8563,12 +11354,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_make_printable_zval(expr, &var_copy, &use_copy);
if (use_copy) {
- *result = var_copy;
+ ZVAL_COPY_VALUE(result, &var_copy);
if (0) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
} else {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!0) {
zendi_zval_copy_ctor(*result);
}
@@ -8583,37 +11374,38 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
break;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_op_array *new_op_array=NULL;
- int return_value_used;
zend_free_op free_op1;
- zval *inc_filename = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *tmp_inc_filename = NULL;
+ zval *inc_filename;
+ zval *tmp_inc_filename = NULL;
zend_bool failure_retval=0;
+ SAVE_OPLINE();
+ inc_filename = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
if (inc_filename->type!=IS_STRING) {
MAKE_STD_ZVAL(tmp_inc_filename);
- *tmp_inc_filename = *inc_filename;
+ ZVAL_COPY_VALUE(tmp_inc_filename, inc_filename);
zval_copy_ctor(tmp_inc_filename);
convert_to_string(tmp_inc_filename);
inc_filename = tmp_inc_filename;
}
- return_value_used = RETURN_VALUE_USED(opline);
-
- if (Z_LVAL(opline->op2.u.constant) != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE || Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE) {
+ if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
} else {
- switch (Z_LVAL(opline->op2.u.constant)) {
+ switch (opline->extended_value) {
case ZEND_INCLUDE_ONCE:
case ZEND_REQUIRE_ONCE: {
zend_file_handle file_handle;
@@ -8635,14 +11427,14 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
}
if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1)==SUCCESS) {
- new_op_array = zend_compile_file(&file_handle, (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
+ new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
zend_file_handle_dtor(&file_handle TSRMLS_CC);
failure_retval=1;
}
} else {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
@@ -8655,7 +11447,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
- new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -8671,12 +11463,18 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
zval_ptr_dtor(&tmp_inc_filename);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (new_op_array && !EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ } else if (EXPECTED(new_op_array != NULL)) {
EX(original_return_value) = EG(return_value_ptr_ptr);
- EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
EG(active_op_array) = new_op_array;
- EX_T(opline->result.u.var).var.ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.var).var.ptr = NULL;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ EG(return_value_ptr_ptr) = EX_T(opline->result.var).var.ptr_ptr;
+ } else {
+ EG(return_value_ptr_ptr) = NULL;
+ }
EX(current_object) = EX(object);
@@ -8687,8 +11485,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
zend_rebuild_symbol_table(TSRMLS_C);
}
- if (zend_execute == execute) {
- EX(call_opline) = opline;
+ if (EXPECTED(zend_execute == execute)) {
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array TSRMLS_CC);
@@ -8697,121 +11494,39 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
EX(function_state).function = (zend_function *) EX(op_array);
EX(object) = EX(current_object);
- if (return_value_used) {
- if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- }
- } else {
- if (return_value_used) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_ZVAL(*EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = failure_retval;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
+ HANDLE_EXCEPTION();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
-static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zval tmp, *varname;
- HashTable *target_symbol_table;
- zend_free_op free_op1;
-
- if (IS_VAR == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EG(active_symbol_table)) {
- zend_execute_data *ex = EX(prev_execute_data);
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_del(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) {
- while (ex && ex->symbol_table == EG(active_symbol_table)) {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == cv->hash_value &&
- ex->op_array->vars[i].name_len == cv->name_len &&
- !memcmp(ex->op_array->vars[i].name, cv->name, cv->name_len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
}
- EX(CVs)[opline->op1.u.var] = NULL;
- } else if (EX(CVs)[opline->op1.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op1.u.var]);
- EX(CVs)[opline->op1.u.var] = NULL;
}
- ZEND_VM_NEXT_OPCODE();
- }
-
- varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- Z_ADDREF_P(varname);
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
- } else {
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
-
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_quick_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value) == SUCCESS) {
- zend_execute_data *ex = execute_data;
- do {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- } while (ex && ex->symbol_table == target_symbol_table);
- }
- }
+ } else if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- if (varname == &tmp) {
- zval_dtor(&tmp);
- } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- zval_ptr_dtor(&varname);
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, failure_retval);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
@@ -8819,14 +11534,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_class_entry *ce = NULL;
zend_bool is_empty = 0;
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- array_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ SAVE_OPLINE();
+
+ if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) &&
+ (opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
+ array_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) {
- ALLOC_INIT_ZVAL(array_ptr);
+ MAKE_STD_ZVAL(array_ptr);
+ ZVAL_NULL(array_ptr);
} else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) {
if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) {
zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
ce = Z_OBJCE_PP(array_ptr_ptr);
@@ -8846,7 +11565,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
Z_ADDREF_P(array_ptr);
}
} else {
- array_ptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ array_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) { /* IS_TMP_VAR */
zval *tmp;
@@ -8882,50 +11601,35 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (ce && ce->get_iterator) {
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_RESET_REFERENCE TSRMLS_CC);
- if (iter && !EG(exception)) {
+ if (iter && EXPECTED(EG(exception) == NULL)) {
array_ptr = zend_iterator_wrap(iter TSRMLS_CC);
} else {
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
- AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr);
- PZVAL_LOCK(array_ptr);
+ EX_T(opline->result.var).fe.ptr = array_ptr;
if (iter) {
iter->index = 0;
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
- ZEND_VM_NEXT_OPCODE();
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ HANDLE_EXCEPTION();
}
}
is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
- ZEND_VM_NEXT_OPCODE();
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ HANDLE_EXCEPTION();
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
@@ -8948,29 +11652,26 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
}
is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->result.var).fe.fe_pos);
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- } else {
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (is_empty) {
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
} else {
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array = EX_T(opline->op1.u.var).var.ptr;
+ zval *array = EX_T(opline->op1.var).fe.ptr;
zval **value;
char *str_key;
uint str_key_len;
@@ -8980,22 +11681,24 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
int key_type = 0;
zend_bool use_key = (zend_bool)(opline->extended_value & ZEND_FE_FETCH_WITH_KEY);
+ SAVE_OPLINE();
+
switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
default:
case ZEND_ITER_INVALID:
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
case ZEND_ITER_PLAIN_OBJECT: {
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
zend_object *zobj = zend_objects_get_address(array TSRMLS_CC);
- fe_ht = HASH_OF(array);
- zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ fe_ht = Z_OBJPROP_P(array);
+ zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
do {
if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
/* reached end of iteration */
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
@@ -9003,7 +11706,7 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
} while (key_type == HASH_KEY_NON_EXISTANT ||
(key_type != HASH_KEY_IS_LONG &&
zend_check_property_access(zobj, str_key, str_key_len-1 TSRMLS_CC) != SUCCESS));
- zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
if (use_key && key_type != HASH_KEY_IS_LONG) {
zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
str_key_len = strlen(prop_name);
@@ -9014,17 +11717,17 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
case ZEND_ITER_PLAIN_ARRAY:
- fe_ht = HASH_OF(array);
- zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ fe_ht = Z_ARRVAL_P(array);
+ zend_hash_set_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) {
/* reached end of iteration */
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL);
}
zend_hash_move_forward(fe_ht);
- zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->op1.var).fe.fe_pos);
break;
case ZEND_ITER_OBJECT:
@@ -9033,39 +11736,35 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* This could cause an endless loop if index becomes zero again.
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
/* If index is zero we come from FE_RESET and checked valid() already. */
if (!iter || (iter->index > 0 && iter->funcs->valid(iter TSRMLS_CC) == FAILURE)) {
/* reached end of iteration */
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
iter->funcs->get_current_data(iter, &value TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
if (!value) {
/* failure in get_current_data */
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
if (use_key) {
if (iter->funcs->get_current_key) {
key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
} else {
key_type = HASH_KEY_IS_LONG;
@@ -9078,20 +11777,19 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
SEPARATE_ZVAL_IF_NOT_REF(value);
Z_SET_ISREF_PP(value);
- EX_T(opline->result.u.var).var.ptr_ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = value;
Z_ADDREF_PP(value);
} else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *value);
PZVAL_LOCK(*value);
+ AI_SET_PTR(&EX_T(opline->result.var), *value);
}
if (use_key) {
- zend_op *op_data = opline+1;
- zval *key = &EX_T(op_data->result.u.var).tmp_var;
+ zval *key = &EX_T((opline+1)->result.var).tmp_var;
switch (key_type) {
case HASH_KEY_IS_STRING:
- Z_STRVAL_P(key) = str_key;
+ Z_STRVAL_P(key) = (char*)str_key;
Z_STRLEN_P(key) = str_key_len-1;
Z_TYPE_P(key) = IS_STRING;
break;
@@ -9106,87 +11804,20 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
}
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zval **value;
- zend_bool isset = 1;
-
- if (IS_VAR == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EX(CVs)[opline->op1.u.var]) {
- value = EX(CVs)[opline->op1.u.var];
- } else if (EG(active_symbol_table)) {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
- isset = 0;
- }
- } else {
- isset = 0;
- }
- } else {
- HashTable *target_symbol_table;
- zend_free_op free_op1;
- zval tmp, *varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1 TSRMLS_CC);
- if (!value) {
- isset = 0;
- }
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
- isset = 0;
- }
- }
-
- if (varname == &tmp) {
- zval_dtor(&tmp);
- }
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- }
-
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value & ZEND_ISSET_ISEMPTY_MASK) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- }
- break;
- }
-
- ZEND_VM_NEXT_OPCODE();
-}
-
static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
#if 0 || (IS_VAR != IS_UNUSED)
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- zval *ptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (Z_TYPE_P(ptr) == IS_LONG) {
EG(exit_status) = Z_LVAL_P(ptr);
@@ -9197,333 +11828,439 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
#endif
zend_bailout();
- ZEND_VM_NEXT_OPCODE();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (i_zend_is_true(value)) {
- EX_T(opline->result.u.var).tmp_var = *value;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
+ if (!0) {
+ zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+ }
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_JMP(opline->op2.u.jmp_addr);
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (i_zend_is_true(value)) {
+ if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!0) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
- EX_T(opline->result.u.var).tmp_var = *value;
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
if (!0) {
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value, *ret;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!0) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
}
+
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *expr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *expr;
zend_bool result;
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) {
- result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.u.var).class_entry TSRMLS_CC);
+ result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC);
} else {
result = 0;
}
- ZVAL_BOOL(&EX_T(opline->result.u.var).tmp_var, result);
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, result);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
zval *object;
- zval *property = &opline->op2.u.constant;
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = opline->op2.zv;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -9534,16 +12271,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -9553,7 +12290,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -9575,22 +12312,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -9605,66 +12342,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = &opline->op2.u.constant;
+ zval *dim = opline->op2.zv;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = &opline->op2.u.constant;
- var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ value = opline->op2.zv;
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -9676,16 +12418,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
}
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
@@ -9746,29 +12493,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = &opline->op2.u.constant;
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = opline->op2.zv;
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -9779,13 +12532,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -9794,9 +12547,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -9810,14 +12563,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -9828,6 +12581,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -9843,26 +12597,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = &opline->op2.u.constant;
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = opline->op2.zv;
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -9873,12 +12633,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -9888,10 +12648,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -9901,20 +12661,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -9924,6 +12683,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -9937,198 +12697,349 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H
return zend_post_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_VAR == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_VAR != IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_VAR == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_VAR_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_VAR != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_RW TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_W TSRMLS_CC);
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_CONST == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *dim = &opline->op2.u.constant;
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_UNSET TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *container;
- zval *offset = &opline->op2.u.constant;
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zval *retval;
@@ -10138,18 +13049,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST(
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -10159,138 +13062,184 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST(
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_res;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property = &opline->op2.u.constant;
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = opline->op2.zv;
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -10300,49 +13249,48 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property_name = &opline->op2.u.constant;
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property_name = opline->op2.zv;
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -10350,28 +13298,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
- zval *property_name = &opline->op2.u.constant;
+ zval *property_name = opline->op2.zv;
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -10380,30 +13331,46 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
} else {
zend_free_op free_op_data1, free_op_data2;
zval *value;
- zval *dim = &opline->op2.u.constant;
+ zval *dim = opline->op2.zv;
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CONST, BP_VAR_W TSRMLS_CC);
+
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -10411,34 +13378,55 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = &opline->op2.u.constant;
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
+
+ SAVE_OPLINE();
+ value = opline->op2.zv;
+ variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CONST TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- if (IS_VAR == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CONST TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_VAR == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (0) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_CONST == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CONST == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
@@ -10446,42 +13434,57 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER
/* zend_assign_to_variable() always takes care of op2, never free it! */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = &opline->op2.u.constant;
+ function_name = opline->op2.zv;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CONST != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CONST != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -10502,48 +13505,62 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_CONST != IS_UNUSED) {
+
+ if (IS_VAR == IS_CONST &&
+ IS_CONST == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_VAR != IS_CONST &&
+ IS_CONST == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_CONST != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
if (IS_CONST == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = &opline->op2.u.constant;
+ function_name = opline->op2.zv;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -10555,22 +13572,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_CONST != IS_CONST) {
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -10583,18 +13608,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -10602,62 +13621,61 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1;
+ SAVE_OPLINE();
if (IS_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ SAVE_OPLINE();
if (IS_VAR == IS_UNUSED) {
- /* namespaced constant */
- if (!zend_get_constant_ex(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) {
+ zend_constant *c;
+ zval *retval;
+
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ c = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL(opline->op2.u.constant), '\\', Z_STRLEN(opline->op2.u.constant));
+ char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
if(!actual) {
- actual = Z_STRVAL(opline->op2.u.constant);
+ actual = Z_STRVAL_P(opline->op2.zv);
} else {
actual++;
}
/* non-qualified constant - allow text substitution */
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- ZVAL_STRINGL(&EX_T(opline->result.u.var).tmp_var, actual, Z_STRLEN(opline->op2.u.constant)-(actual - Z_STRVAL(opline->op2.u.constant)), 1);
+ ZVAL_STRINGL(&EX_T(opline->result.var).tmp_var, actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv)), 1);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
} else {
- zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
- Z_STRVAL(opline->op2.u.constant), Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, c);
}
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, &c->value);
+ zval_copy_ctor(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
@@ -10665,19 +13683,33 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
zval **value;
if (IS_VAR == IS_CONST) {
-
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ value = CACHED_PTR(opline->op2.literal->cache_slot);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
+ if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
}
- if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+ if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
@@ -10686,52 +13718,47 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
- EX_T(opline->result.u.var).tmp_var = **value;
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, value);
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+ }
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=&opline->op2.u.constant;
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -10742,20 +13769,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *offset = opline->op2.zv;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -10765,21 +13809,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
} else {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_VAR != IS_UNUSED
@@ -10789,17 +13834,96 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = &opline->op2.u.constant;
+ offset = opline->op2.zv;
if (IS_VAR != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -10808,37 +13932,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -10854,7 +13981,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -10879,15 +14006,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *offset = &opline->op2.u.constant;
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = opline->op2.zv;
if (IS_VAR != IS_VAR || container) {
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -10898,7 +14030,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -10915,139 +14047,236 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+ zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_VAR != IS_VAR || container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- zval *offset = &opline->op2.u.constant;
+ offset = opline->op2.zv;
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- ht = Z_ARRVAL_PP(container);
+ ht = Z_ARRVAL_PP(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
- } else {
- result = 1;
- }
- break;
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
+ }
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
- }
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
-
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
+ }
- } else {
+ } else {
- }
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -11063,277 +14292,306 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
zval_dtor(free_op2.var);
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -11344,16 +14602,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -11363,7 +14621,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -11385,22 +14643,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -11415,66 +14673,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
zval_dtor(free_op2.var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -11486,17 +14749,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
zval_dtor(free_op2.var);
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
}
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
@@ -11557,29 +14825,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HA
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
zval_dtor(free_op2.var);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -11590,13 +14864,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -11605,9 +14879,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -11621,14 +14895,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -11639,6 +14913,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i
zval_dtor(free_op2.var);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -11654,26 +14929,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
zval_dtor(free_op2.var);
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -11684,12 +14965,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -11699,10 +14980,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -11712,20 +14993,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -11735,6 +15015,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t
zval_dtor(free_op2.var);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -11750,196 +15031,183 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_VAR != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC);
zval_dtor(free_op2.var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC);
zval_dtor(free_op2.var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC);
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_TMP_VAR == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC);
}
zval_dtor(free_op2.var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *container;
zend_free_op free_op2;
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
zval_dtor(free_op2.var);
} else {
zval *retval;
@@ -11949,18 +15217,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(in
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (1) {
zval_ptr_dtor(&offset);
@@ -11970,138 +15230,184 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(in
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ zval_dtor(free_op2.var);
+ } else {
+ zval *retval;
+
+ if (1) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (1) {
+ zval_ptr_dtor(&offset);
+ } else {
+ zval_dtor(free_op2.var);
+ }
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -12111,49 +15417,48 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property_name);
} else {
@@ -12161,28 +15466,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
zend_free_op free_op2;
- zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property_name);
} else {
@@ -12191,31 +15499,47 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
} else {
zend_free_op free_op2, free_op_data1, free_op_data2;
zval *value;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 1, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR, BP_VAR_W TSRMLS_CC);
zval_dtor(free_op2.var);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -12223,34 +15547,55 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_TMP_VAR TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_VAR == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (1) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 1 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_TMP_VAR == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_TMP_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
@@ -12258,42 +15603,57 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
/* zend_assign_to_variable() always takes care of op2, never free it! */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_TMP_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_TMP_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -12315,48 +15675,62 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
zval_dtor(free_op2.var);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_TMP_VAR != IS_UNUSED) {
+
+ if (IS_VAR == IS_CONST &&
+ IS_TMP_VAR == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_VAR != IS_CONST &&
+ IS_TMP_VAR == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_TMP_VAR != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
zend_free_op free_op2;
if (IS_TMP_VAR == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -12368,22 +15742,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_TMP_VAR != IS_CONST) {
zval_dtor(free_op2.var);
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -12396,18 +15778,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -12415,77 +15791,53 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
if (IS_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1, free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zend_free_op free_op1;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -12496,20 +15848,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -12519,21 +15888,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
}
zval_dtor(free_op2.var);
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
} else {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_VAR != IS_UNUSED
@@ -12545,15 +15915,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -12562,37 +15935,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -12608,7 +15984,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (1) {
@@ -12633,15 +16009,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR != IS_VAR || container) {
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -12652,7 +16033,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -12669,139 +16050,151 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_VAR != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- ht = Z_ARRVAL_PP(container);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- break;
- }
+ ht = Z_ARRVAL_PP(container);
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- zval_dtor(free_op2.var);
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (1) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ zval_dtor(free_op2.var);
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (1) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (1) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- zval_dtor(free_op2.var);
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (1) {
+ zval_ptr_dtor(&offset);
+ } else {
+ zval_dtor(free_op2.var);
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- zval_dtor(free_op2.var);
- } else {
- zval_dtor(free_op2.var);
}
+ zval_dtor(free_op2.var);
+ } else {
+ zval_dtor(free_op2.var);
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -12817,277 +16210,306 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -13098,16 +16520,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -13117,7 +16539,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -13139,22 +16561,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -13169,66 +16591,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -13240,17 +16667,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
}
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
@@ -13311,29 +16743,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HA
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -13344,13 +16782,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -13359,9 +16797,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -13375,14 +16813,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -13393,6 +16831,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -13408,26 +16847,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -13438,12 +16883,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -13453,10 +16898,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -13466,20 +16911,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -13489,6 +16933,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -13502,198 +16947,349 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN
return zend_post_incdec_property_helper_SPEC_VAR_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_VAR == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_VAR != IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_VAR == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_VAR_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_VAR != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC);
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_VAR == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC);
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *container;
zend_free_op free_op2;
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
zval *retval;
@@ -13703,18 +17299,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(in
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -13724,138 +17312,184 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(in
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ }
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -13865,49 +17499,48 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -13915,28 +17548,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
zend_free_op free_op2;
- zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -13945,31 +17581,47 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
} else {
zend_free_op free_op2, free_op_data1, free_op_data2;
zval *value;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_VAR, BP_VAR_W TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -13977,34 +17629,55 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
- if (IS_VAR == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_VAR TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_VAR TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_VAR == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (0) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_VAR == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
@@ -14013,40 +17686,44 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
/* zend_assign_to_variable() always takes care of op2, never free it! */
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
zval **variable_ptr_ptr;
- zval **value_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **value_ptr_ptr;
+
+ SAVE_OPLINE();
+ value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR == IS_VAR &&
value_ptr_ptr &&
!Z_ISREF_PP(value_ptr_ptr) &&
opline->extended_value == ZEND_RETURNS_FUNCTION &&
- !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+ !EX_T(opline->op2.var).var.fcall_returned_reference) {
if (free_op2.var == NULL) {
PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
}
zend_error(E_STRICT, "Only variables should be assigned by reference");
if (UNEXPECTED(EG(exception) != NULL)) {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
PZVAL_LOCK(*value_ptr_ptr);
}
- if (IS_VAR == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr)) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if ((IS_VAR == IS_VAR && !value_ptr_ptr) ||
- (IS_VAR == IS_VAR && !variable_ptr_ptr)) {
+ variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
+ (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
@@ -14055,50 +17732,65 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
Z_DELREF_PP(variable_ptr_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*variable_ptr_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *variable_ptr_ptr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -14120,48 +17812,62 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_VAR != IS_UNUSED) {
+
+ if (IS_VAR == IS_CONST &&
+ IS_VAR == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_VAR != IS_CONST &&
+ IS_VAR == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_VAR != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
zend_free_op free_op2;
if (IS_VAR == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -14173,22 +17879,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_VAR != IS_CONST) {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -14201,18 +17915,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -14220,77 +17928,53 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1, free_op2;
+ SAVE_OPLINE();
if (IS_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1, free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zend_free_op free_op1;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -14301,20 +17985,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -14324,21 +18025,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
} else {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_VAR != IS_UNUSED
@@ -14348,17 +18050,96 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -14367,37 +18148,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -14413,7 +18197,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -14438,15 +18222,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR != IS_VAR || container) {
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -14457,7 +18246,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -14474,139 +18263,236 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+ zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ USE_OPLINE
+ zend_free_op free_op1, free_op2;
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_VAR != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- ht = Z_ARRVAL_PP(container);
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ ht = Z_ARRVAL_PP(container);
- break;
- }
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- } else {
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -14622,33 +18508,30 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
zval *object;
zval *property = NULL;
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -14659,16 +18542,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -14678,7 +18561,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -14700,22 +18583,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -14730,66 +18613,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
zval *dim = NULL;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
value = NULL;
- var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -14801,16 +18689,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
}
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
@@ -14869,106 +18762,266 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_VAR == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_VAR != IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_VAR == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_VAR != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = NULL;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = NULL;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_RW TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = NULL;
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_W TSRMLS_CC);
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_UNUSED == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_R TSRMLS_CC);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
@@ -14978,7 +19031,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -14990,27 +19043,43 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
zval *dim = NULL;
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_UNUSED, BP_VAR_W TSRMLS_CC);
+
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -15018,49 +19087,63 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_UNUSED != IS_UNUSED) {
+
+ if (IS_VAR == IS_CONST &&
+ IS_UNUSED == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_VAR != IS_CONST &&
+ IS_UNUSED == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_UNUSED != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
if (IS_UNUSED == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
function_name = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -15072,22 +19155,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_UNUSED == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_UNUSED != IS_CONST) {
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -15100,18 +19191,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -15119,45 +19204,35 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=NULL;
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -15168,20 +19243,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *offset = NULL;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_UNUSED == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -15191,21 +19283,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
} else {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_VAR != IS_UNUSED
@@ -15215,279 +19308,490 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_VAR == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+ zend_free_op free_op1;
+ zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_VAR != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *var_ptr, *new_zv;
+
+ SAVE_OPLINE();
+ var_ptr = EX_T(opline->op1.var).var.ptr;
+ if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
+ !PZVAL_IS_REF(var_ptr) &&
+ Z_REFCOUNT_P(var_ptr) > 1) {
+
+ Z_DELREF_P(var_ptr);
+ ALLOC_ZVAL(new_zv);
+ INIT_PZVAL_COPY(new_zv, var_ptr);
+ var_ptr = new_zv;
+ zval_copy_ctor(var_ptr);
+ EX_T(opline->op1.var).var.ptr = var_ptr;
+ }
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -15498,16 +19802,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -15517,7 +19821,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -15539,22 +19843,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -15569,66 +19873,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- var_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -15640,16 +19949,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
}
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
@@ -15710,29 +20024,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -15743,13 +20063,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -15758,9 +20078,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -15774,14 +20094,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -15792,6 +20112,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -15807,26 +20128,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -15837,12 +20164,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -15852,10 +20179,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -15865,20 +20192,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -15888,6 +20214,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -15903,196 +20230,183 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_VAR != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC);
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_CV == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC);
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *container = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *container;
+
+ zval *offset;
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zval *retval;
@@ -16102,18 +20416,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(int
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -16123,138 +20429,184 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(int
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_VAR_CV(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ }
+
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_VAR_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_res;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_VAR == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -16264,49 +20616,48 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_VAR == IS_VAR && !container) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_VAR == IS_VAR && (free_op1.var != NULL) &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_VAR == IS_VAR && !object_ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -16314,28 +20665,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op1;
- zval **object_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **object_ptr;
- if (IS_VAR == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
- zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -16344,30 +20698,46 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
} else {
zend_free_op free_op_data1, free_op_data2;
zval *value;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CV, BP_VAR_W TSRMLS_CC);
+
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -16375,34 +20745,55 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CV TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CV TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_VAR == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (0) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_CV == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CV == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
@@ -16410,40 +20801,44 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
/* zend_assign_to_variable() always takes care of op2, never free it! */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
zval **variable_ptr_ptr;
- zval **value_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **value_ptr_ptr;
+
+ SAVE_OPLINE();
+ value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_CV == IS_VAR &&
value_ptr_ptr &&
!Z_ISREF_PP(value_ptr_ptr) &&
opline->extended_value == ZEND_RETURNS_FUNCTION &&
- !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+ !EX_T(opline->op2.var).var.fcall_returned_reference) {
if (free_op2.var == NULL) {
PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
}
zend_error(E_STRICT, "Only variables should be assigned by reference");
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
PZVAL_LOCK(*value_ptr_ptr);
}
- if (IS_VAR == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr)) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if ((IS_CV == IS_VAR && !value_ptr_ptr) ||
- (IS_VAR == IS_VAR && !variable_ptr_ptr)) {
+ variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
+ (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
@@ -16452,49 +20847,64 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
Z_DELREF_PP(variable_ptr_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*variable_ptr_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *variable_ptr_ptr);
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CV != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CV != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -16515,48 +20925,62 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
zend_class_entry *ce;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
/* no function found. try a static method in class */
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL(opline->op1.u.constant));
+ if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
EX(called_scope) = ce;
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
- if (opline->op1.u.EA.type == ZEND_FETCH_CLASS_PARENT || opline->op1.u.EA.type == ZEND_FETCH_CLASS_SELF) {
+ if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
EX(called_scope) = EG(called_scope);
} else {
EX(called_scope) = ce;
}
}
- if(IS_CV != IS_UNUSED) {
+
+ if (IS_VAR == IS_CONST &&
+ IS_CV == IS_CONST &&
+ CACHED_PTR(opline->op2.literal->cache_slot)) {
+ EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if (IS_VAR != IS_CONST &&
+ IS_CV == IS_CONST &&
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+ /* do nothing */
+ } else if (IS_CV != IS_UNUSED) {
char *function_name_strval = NULL;
int function_name_strlen = 0;
if (IS_CV == IS_CONST) {
- function_name_strval = Z_STRVAL(opline->op2.u.constant);
- function_name_strlen = Z_STRLEN(opline->op2.u.constant);
+ function_name_strval = Z_STRVAL_P(opline->op2.zv);
+ function_name_strlen = Z_STRLEN_P(opline->op2.zv);
} else {
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
} else {
function_name_strval = Z_STRVAL_P(function_name);
@@ -16568,22 +20992,30 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
if (ce->get_static_method) {
EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
} else {
- EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
+ EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
}
- if (!EX(fbc)) {
+ if (UNEXPECTED(EX(fbc) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
}
+ if (IS_CV == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+ }
+ }
}
-
if (IS_CV != IS_CONST) {
}
} else {
- if(!ce->constructor) {
+ if (UNEXPECTED(ce->constructor == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot call constructor");
}
if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
- zend_error(E_COMPILE_ERROR, "Cannot call private %s::__construct()", ce->name);
+ zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name);
}
EX(fbc) = ce->constructor;
}
@@ -16596,18 +21028,12 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
!instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
- int severity;
- char *verb;
if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- severity = E_STRICT;
- verb = "should not";
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- severity = E_ERROR;
- verb = "cannot";
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name);
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name, verb);
-
}
if ((EX(object) = EG(This))) {
Z_ADDREF_P(EX(object));
@@ -16615,76 +21041,52 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op1;
+ SAVE_OPLINE();
if (IS_VAR==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
- if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_VAR == IS_VAR || IS_VAR == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_VAR == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -16695,20 +21097,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CV != IS_UNUSED) {
+
+ zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -16718,21 +21137,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
} else {
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_VAR == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_VAR != IS_UNUSED
@@ -16744,15 +21164,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_VAR != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -16761,37 +21184,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -16807,7 +21233,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -16832,15 +21258,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_VAR != IS_VAR || container) {
if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -16851,7 +21282,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -16868,139 +21299,151 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_VAR != IS_VAR || container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- ht = Z_ARRVAL_PP(container);
+ ht = Z_ARRVAL_PP(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
- } else {
- result = 1;
- }
- break;
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
+ }
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
- }
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
-
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
+ }
- } else {
+ } else {
- }
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -17016,23 +21459,25 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O
static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *obj = _get_obj_zval_ptr_unused(TSRMLS_C);
+ zval *obj;
zend_class_entry *ce;
zend_function *clone;
zend_object_clone_obj_t clone_call;
+ SAVE_OPLINE();
+ obj = _get_obj_zval_ptr_unused(TSRMLS_C);
+
if (IS_UNUSED == IS_CONST ||
- (IS_UNUSED == IS_VAR && !obj) ||
- Z_TYPE_P(obj) != IS_OBJECT) {
+ UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
}
ce = Z_OBJCE_P(obj);
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
- if (!clone_call) {
+ if (UNEXPECTED(clone_call == NULL)) {
if (ce) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
} else {
@@ -17044,37 +21489,43 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (ce != EG(scope)) {
+ if (UNEXPECTED(ce != EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(clone->common.scope, EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
}
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (!EG(exception)) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_OBJVAL_P(EX_T(opline->result.u.var).var.ptr) = clone_call(obj TSRMLS_CC);
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT;
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- Z_SET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- if (!RETURN_VALUE_USED(opline) || EG(exception)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (EXPECTED(EG(exception) == NULL)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ Z_OBJVAL_P(retval) = clone_call(obj TSRMLS_CC);
+ Z_TYPE_P(retval) = IS_OBJECT;
+ Z_SET_REFCOUNT_P(retval, 1);
+ Z_SET_ISREF_P(retval);
+ if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor(&retval);
+ } else {
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
#if 0 || (IS_UNUSED != IS_UNUSED)
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ SAVE_OPLINE();
if (IS_UNUSED != IS_UNUSED) {
zval *ptr = NULL;
@@ -17088,38 +21539,35 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
#endif
zend_bailout();
- ZEND_VM_NEXT_OPCODE();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op_data1;
zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
zval *object;
- zval *property = &opline->op2.u.constant;
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = opline->op2.zv;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -17130,16 +21578,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -17149,7 +21597,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -17171,22 +21619,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -17200,17 +21648,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -17218,48 +21668,51 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi
case ZEND_ASSIGN_DIM: {
zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = &opline->op2.u.constant;
+ zval *dim = opline->op2.zv;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = &opline->op2.u.constant;
+ value = opline->op2.zv;
var_ptr = NULL;
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -17271,16 +21724,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -17341,29 +21799,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCO
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = &opline->op2.u.constant;
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = opline->op2.zv;
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -17374,13 +21838,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -17389,9 +21853,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -17405,14 +21869,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -17423,6 +21887,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -17438,26 +21903,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = &opline->op2.u.constant;
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = opline->op2.zv;
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -17468,12 +21939,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -17483,10 +21954,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -17496,20 +21967,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -17519,6 +21989,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -17532,22 +22003,23 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCOD
return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ zval *container;
- zval *offset = &opline->op2.u.constant;
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zval *retval;
@@ -17557,18 +22029,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CON
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -17577,137 +22041,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CON
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_res;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property = &opline->op2.u.constant;
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = opline->op2.zv;
if (IS_UNUSED == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -17717,48 +22226,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OP
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property_name = &opline->op2.u.constant;
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property_name = opline->op2.zv;
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -17766,14 +22274,17 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zval *str = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
if (IS_UNUSED == IS_UNUSED) {
/* Initialize for erealloc in add_char_to_string */
@@ -17784,16 +22295,19 @@ static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HA
INIT_PZVAL(str);
}
- add_char_to_string(str, str, &opline->op2.u.constant);
+ add_char_to_string(str, str, opline->op2.zv);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zval *str = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+ zval *str = &EX_T(opline->result.var).tmp_var;
+
+ SAVE_OPLINE();
if (IS_UNUSED == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
@@ -17804,25 +22318,28 @@ static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_
INIT_PZVAL(str);
}
- add_string_to_string(str, str, &opline->op2.u.constant);
+ add_string_to_string(str, str, opline->op2.zv);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
+ /*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = &opline->op2.u.constant;
+ function_name = opline->op2.zv;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CONST != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
@@ -17831,18 +22348,30 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CONST != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -17862,31 +22391,44 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ SAVE_OPLINE();
if (IS_UNUSED == IS_UNUSED) {
- /* namespaced constant */
- if (!zend_get_constant_ex(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) {
+ zend_constant *c;
+ zval *retval;
+
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ c = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL(opline->op2.u.constant), '\\', Z_STRLEN(opline->op2.u.constant));
+ char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
if(!actual) {
- actual = Z_STRVAL(opline->op2.u.constant);
+ actual = Z_STRVAL_P(opline->op2.zv);
} else {
actual++;
}
/* non-qualified constant - allow text substitution */
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
- ZVAL_STRINGL(&EX_T(opline->result.u.var).tmp_var, actual, Z_STRLEN(opline->op2.u.constant)-(actual - Z_STRVAL(opline->op2.u.constant)), 1);
+ ZVAL_STRINGL(&EX_T(opline->result.var).tmp_var, actual, Z_STRLEN_P(opline->op2.zv)-(actual - Z_STRVAL_P(opline->op2.zv)), 1);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
} else {
- zend_error_noreturn(E_ERROR, "Undefined constant '%s'",
- Z_STRVAL(opline->op2.u.constant), Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ } else {
+ CACHE_PTR(opline->op2.literal->cache_slot, c);
}
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, &c->value);
+ zval_copy_ctor(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
/* class constant */
@@ -17894,19 +22436,33 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
zval **value;
if (IS_UNUSED == IS_CONST) {
-
- ce = zend_fetch_class(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
- if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
- }
- if (!ce) {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ value = CACHED_PTR(opline->op2.literal->cache_slot);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op1.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op1.literal->cache_slot, ce);
}
} else {
- ce = EX_T(opline->op1.u.var).class_entry;
+ ce = EX_T(opline->op1.var).class_entry;
+ if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
}
- if (zend_hash_find(&ce->constants_table, Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+ if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
(Z_TYPE_PP(value) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
zend_class_entry *old_scope = EG(scope);
@@ -17915,21 +22471,27 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EG(scope) = old_scope;
}
- EX_T(opline->result.u.var).tmp_var = **value;
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ if (IS_UNUSED == IS_CONST) {
+ CACHE_PTR(opline->op2.literal->cache_slot, value);
+ } else {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+ }
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL(opline->op2.u.constant));
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_UNUSED == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_UNUSED != IS_UNUSED
@@ -17941,15 +22503,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = &opline->op2.u.constant;
+ offset = opline->op2.zv;
if (IS_UNUSED != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -17958,37 +22523,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -18004,7 +22572,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -18028,15 +22596,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *offset = &opline->op2.u.constant;
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ offset = opline->op2.zv;
if (IS_UNUSED != IS_VAR || container) {
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -18047,7 +22620,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -18063,137 +22636,149 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_UNUSED != IS_VAR || container) {
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *offset = &opline->op2.u.constant;
+ offset = opline->op2.zv;
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- ht = Z_ARRVAL_PP(container);
+ ht = Z_ARRVAL_PP(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
- } else {
- result = 1;
- }
- break;
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
+ }
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
- }
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
-
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
+
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
+ }
- } else {
+ } else {
- }
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -18209,33 +22794,30 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2, free_op_data1;
zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
zval_dtor(free_op2.var);
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -18246,16 +22828,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -18265,7 +22847,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -18287,22 +22869,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -18316,17 +22898,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -18334,48 +22918,51 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina
case ZEND_ASSIGN_DIM: {
zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
var_ptr = NULL;
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -18387,17 +22974,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
zval_dtor(free_op2.var);
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -18458,29 +23050,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
zval_dtor(free_op2.var);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -18491,13 +23089,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -18506,9 +23104,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -18522,14 +23120,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -18540,6 +23138,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -18555,26 +23154,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
zval_dtor(free_op2.var);
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -18585,12 +23190,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -18600,10 +23205,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -18613,20 +23218,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -18636,6 +23240,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -18649,22 +23254,23 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_
return zend_post_incdec_property_helper_SPEC_UNUSED_TMP(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ zval *container;
zend_free_op free_op2;
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
zval_dtor(free_op2.var);
} else {
zval *retval;
@@ -18674,18 +23280,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (1) {
zval_ptr_dtor(&offset);
@@ -18694,137 +23292,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ zval_dtor(free_op2.var);
+ } else {
+ zval *retval;
+
+ if (1) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (1) {
+ zval_ptr_dtor(&offset);
+ } else {
+ zval_dtor(free_op2.var);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_UNUSED == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -18834,48 +23477,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property_name);
} else {
@@ -18883,19 +23525,23 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_UNUSED == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -18925,22 +23571,25 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDL
*/
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_TMP_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
@@ -18949,18 +23598,30 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_TMP_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -18981,14 +23642,15 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_UNUSED == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_UNUSED != IS_UNUSED
@@ -19000,15 +23662,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_UNUSED != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -19017,37 +23682,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -19063,7 +23731,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (1) {
@@ -19087,15 +23755,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_UNUSED != IS_VAR || container) {
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -19106,7 +23779,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -19122,137 +23795,149 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_UNUSED != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- ht = Z_ARRVAL_PP(container);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- break;
- }
+ ht = Z_ARRVAL_PP(container);
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- zval_dtor(free_op2.var);
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (1) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ zval_dtor(free_op2.var);
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (1) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (1) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- zval_dtor(free_op2.var);
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (1) {
+ zval_ptr_dtor(&offset);
+ } else {
+ zval_dtor(free_op2.var);
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- zval_dtor(free_op2.var);
- } else {
- zval_dtor(free_op2.var);
}
+ zval_dtor(free_op2.var);
+ } else {
+ zval_dtor(free_op2.var);
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -19268,33 +23953,30 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2, free_op_data1;
zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -19305,16 +23987,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -19324,7 +24006,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -19346,22 +24028,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -19375,17 +24057,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -19393,48 +24077,51 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina
case ZEND_ASSIGN_DIM: {
zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
var_ptr = NULL;
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -19446,17 +24133,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -19517,29 +24209,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -19550,13 +24248,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -19565,9 +24263,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -19581,14 +24279,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -19599,6 +24297,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -19614,26 +24313,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -19644,12 +24349,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -19659,10 +24364,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -19672,20 +24377,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -19695,6 +24399,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -19708,22 +24413,23 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_
return zend_post_incdec_property_helper_SPEC_UNUSED_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ zval *container;
zend_free_op free_op2;
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
zval *retval;
@@ -19733,18 +24439,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -19753,137 +24451,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_UNUSED == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -19893,48 +24636,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -19942,19 +24684,23 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_UNUSED == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -19984,22 +24730,25 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDL
*/
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
@@ -20008,18 +24757,30 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -20040,14 +24801,15 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_UNUSED == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_UNUSED != IS_UNUSED
@@ -20059,15 +24821,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_UNUSED != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -20076,37 +24841,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -20122,7 +24890,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -20146,15 +24914,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_UNUSED != IS_VAR || container) {
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -20165,7 +24938,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -20181,137 +24954,149 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_UNUSED != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- ht = Z_ARRVAL_PP(container);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- break;
- }
+ ht = Z_ARRVAL_PP(container);
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- } else {
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -20327,33 +25112,30 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZE
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op_data1;
zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
zval *object;
zval *property = NULL;
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -20364,16 +25146,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -20383,7 +25165,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -20405,22 +25187,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -20434,17 +25216,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -20452,21 +25236,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b
case ZEND_ASSIGN_DIM: {
zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
zval *dim = NULL;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
@@ -20477,23 +25259,28 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -20505,16 +25292,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -20575,9 +25367,9 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPC
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_UNUSED == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_UNUSED != IS_UNUSED
@@ -20589,33 +25381,30 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op_data1;
zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -20626,16 +25415,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -20645,7 +25434,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -20667,22 +25456,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -20696,17 +25485,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -20714,48 +25505,51 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar
case ZEND_ASSIGN_DIM: {
zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_UNUSED == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
var_ptr = NULL;
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -20767,16 +25561,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -20837,29 +25636,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -20870,13 +25675,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -20885,9 +25690,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -20901,14 +25706,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -20919,6 +25724,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -20934,26 +25740,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -20964,12 +25776,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -20979,10 +25791,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -20992,20 +25804,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -21015,6 +25826,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -21028,22 +25840,23 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H
return zend_post_incdec_property_helper_SPEC_UNUSED_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ zval *container;
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zval *retval;
@@ -21053,18 +25866,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -21073,137 +25878,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_UNUSED_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_res;
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_UNUSED == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -21213,48 +26063,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_UNUSED == IS_VAR && !container) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_UNUSED == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_UNUSED == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
- zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_UNUSED == IS_VAR && !object_ptr) {
+ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -21262,19 +26111,23 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *str = &EX_T(opline->result.u.var).tmp_var;
- zval *var = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *str = &EX_T(opline->result.var).tmp_var;
+ zval *var;
zval var_copy;
int use_copy = 0;
+ SAVE_OPLINE();
+ var = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
if (IS_UNUSED == IS_UNUSED) {
/* Initialize for erealloc in add_string_to_string */
Z_STRVAL_P(str) = NULL;
@@ -21303,22 +26156,25 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLE
* string offsets or overloaded objects
*/
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CV != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
@@ -21327,18 +26183,30 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CV != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -21358,14 +26226,15 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_UNUSED == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_UNUSED != IS_UNUSED
@@ -21377,15 +26246,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_UNUSED != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -21394,37 +26266,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -21440,7 +26315,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -21464,15 +26339,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_UNUSED != IS_VAR || container) {
if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -21483,7 +26363,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -21499,137 +26379,149 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_UNUSED != IS_VAR || container) {
+ SAVE_OPLINE();
+ container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C);
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- ht = Z_ARRVAL_PP(container);
+ ht = Z_ARRVAL_PP(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
- } else {
- result = 1;
- }
- break;
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
+ }
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
- }
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
-
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
+
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
+ }
- } else {
+ } else {
- }
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -21645,189 +26537,219 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEN
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_not_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_not_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- boolean_not_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_not_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **var_ptr;
+
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !var_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (IS_CV == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- increment_function(val);
+ fast_increment_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- increment_function(*var_ptr);
+ fast_increment_function(*var_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ zval **var_ptr;
- zval **var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !var_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (IS_CV == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- decrement_function(val);
+ fast_decrement_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- decrement_function(*var_ptr);
+ fast_decrement_function(*var_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **var_ptr, *retval;
- if (IS_CV == IS_VAR && !var_ptr) {
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr);
- }
+ if (IS_CV == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ ZVAL_NULL(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- EX_T(opline->result.u.var).tmp_var = **var_ptr;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, *var_ptr);
+ zendi_zval_copy_ctor(*retval);
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- increment_function(val);
+ fast_increment_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- increment_function(*var_ptr);
+ fast_increment_function(*var_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **var_ptr, *retval;
- if (IS_CV == IS_VAR && !var_ptr) {
+ SAVE_OPLINE();
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
- if (IS_CV == IS_VAR && *var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).tmp_var = *EG(uninitialized_zval_ptr);
- }
+ if (IS_CV == IS_VAR && UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ ZVAL_NULL(&EX_T(opline->result.var).tmp_var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- EX_T(opline->result.u.var).tmp_var = **var_ptr;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ retval = &EX_T(opline->result.var).tmp_var;
+ ZVAL_COPY_VALUE(retval, *var_ptr);
+ zendi_zval_copy_ctor(*retval);
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *val = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
Z_ADDREF_P(val);
- decrement_function(val);
+ fast_decrement_function(val);
Z_OBJ_HANDLER_PP(var_ptr, set)(var_ptr, val TSRMLS_CC);
zval_ptr_dtor(&val);
} else {
- decrement_function(*var_ptr);
+ fast_decrement_function(*var_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval z_copy;
- zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *z;
+
+ SAVE_OPLINE();
+ z = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
if (IS_CV != IS_CONST &&
- Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
+ UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) &&
+ Z_OBJ_HT_P(z)->get_method != NULL) {
if (IS_CV == IS_TMP_VAR) {
INIT_PZVAL(z);
}
@@ -21841,172 +26763,42 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_print_variable(z);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_PRINT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG;
+ USE_OPLINE
+ ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
return ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
-static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zend_free_op free_op1;
- zval *varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **retval;
- zval tmp_varname;
- HashTable *target_symbol_table;
-
- if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- tmp_varname = *varname;
- zval_copy_ctor(&tmp_varname);
- convert_to_string(&tmp_varname);
- varname = &tmp_varname;
- }
-
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- retval = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0 TSRMLS_CC);
-
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC);
-/*
- if (!target_symbol_table) {
- ZEND_VM_NEXT_OPCODE();
- }
-*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval_ptr);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
- /* break missing intentionally */
- case BP_VAR_W: {
- zval *new_zval = &EG(uninitialized_zval);
-
- Z_ADDREF_P(new_zval);
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
- }
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
- switch (opline->op2.u.EA.type) {
- case ZEND_FETCH_GLOBAL:
- if (IS_CV != IS_TMP_VAR) {
-
- }
- break;
- case ZEND_FETCH_LOCAL:
-
- break;
- case ZEND_FETCH_STATIC:
- zval_update_constant(retval, (void*) 1 TSRMLS_CC);
- break;
- case ZEND_FETCH_GLOBAL_LOCK:
- if (IS_CV == IS_VAR && !free_op1.var) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- break;
- }
- }
-
-
- if (IS_CV != IS_CONST && varname == &tmp_varname) {
- zval_dtor(varname);
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- }
- PZVAL_LOCK(*retval);
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_IS:
- AI_SET_PTR(EX_T(opline->result.u.var).var, *retval);
- break;
- case BP_VAR_UNSET: {
- zend_free_op free_res;
-
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- }
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
- FREE_OP_VAR_PTR(free_res);
- break;
- default:
- EX_T(opline->result.u.var).var.ptr_ptr = retval;
- break;
- }
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CV(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), EX(opline)->extended_value)?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
-static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- return zend_fetch_var_address_helper_SPEC_CV(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *val;
int ret;
- if (IS_CV == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (!ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -22015,25 +26807,28 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *val;
int ret;
- if (IS_CV == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
ret = Z_LVAL_P(val);
} else {
ret = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (ret) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
@@ -22042,18 +26837,21 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_CV == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
if (EXPECTED(retval != 0)) {
@@ -22064,36 +26862,39 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_CONTINUE(); /* CHECK_ME */
} else {
#if DEBUG_ZEND>=2
- printf("Conditional jmp on false to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp on false to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.u.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_CV == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (!retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -22101,27 +26902,30 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *val = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *val;
int retval;
- if (IS_CV == IS_TMP_VAR && Z_TYPE_P(val) == IS_BOOL) {
+ SAVE_OPLINE();
+ val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) {
retval = Z_LVAL_P(val);
} else {
retval = i_zend_is_true(val);
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_CONTINUE();
+ HANDLE_EXCEPTION();
}
}
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = retval;
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = retval;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
if (retval) {
#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- ZEND_VM_SET_OPCODE(opline->op2.u.jmp_addr);
+ ZEND_VM_SET_OPCODE(opline->op2.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_NEXT_OPCODE();
@@ -22129,94 +26933,125 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *retval_ptr;
- zval **retval_ptr_ptr;
- if (EG(active_op_array)->return_reference == ZEND_RETURN_REF) {
+ SAVE_OPLINE();
+ retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_CV == IS_TMP_VAR) {
- if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
- /* Not supposed to happen, but we'll allow it */
- zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
}
+ } else if (!0) { /* Not a temp var */
+ if (IS_CV == IS_CONST ||
+ (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ zval *ret;
- retval_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ zval_copy_ctor(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) &&
+ retval_ptr == &EG(uninitialized_zval)) {
+ zval *ret;
- if (IS_CV == IS_VAR && !retval_ptr_ptr) {
- zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
+ ALLOC_INIT_ZVAL(ret);
+ *EG(return_value_ptr_ptr) = ret;
+ } else {
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
}
+ } else {
+ zval *ret;
- if (IS_CV == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
- if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference) {
- } else if (EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
- if (IS_CV == IS_VAR && !0) {
- PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
- }
- zend_error(E_NOTICE, "Only variable references should be returned by reference");
- goto return_by_value;
- }
- }
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
+ *EG(return_value_ptr_ptr) = ret;
+ }
- if (EG(return_value_ptr_ptr)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
- Z_ADDREF_PP(retval_ptr_ptr);
+ return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
- (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
- }
- } else {
-return_by_value:
+static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *retval_ptr;
+ zval **retval_ptr_ptr;
- retval_ptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (!EG(return_value_ptr_ptr)) {
- if (IS_CV == IS_TMP_VAR) {
+ SAVE_OPLINE();
- }
- } else if (!0) { /* Not a temp var */
- if (IS_CV == IS_CONST ||
- EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
- (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
+ do {
+ if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
+ /* Not supposed to happen, but we'll allow it */
+ zend_error(E_NOTICE, "Only variable references should be returned by reference");
+
+ retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (!EG(return_value_ptr_ptr)) {
+ if (IS_CV == IS_TMP_VAR) {
+
+ }
+ } else if (!0) { /* Not a temp var */
zval *ret;
ALLOC_ZVAL(ret);
INIT_PZVAL_COPY(ret, retval_ptr);
zval_copy_ctor(ret);
*EG(return_value_ptr_ptr) = ret;
- } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) &&
- retval_ptr == &EG(uninitialized_zval)) {
+ } else {
zval *ret;
- ALLOC_INIT_ZVAL(ret);
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, retval_ptr);
*EG(return_value_ptr_ptr) = ret;
- } else {
- *EG(return_value_ptr_ptr) = retval_ptr;
- Z_ADDREF_P(retval_ptr);
}
- } else {
- zval *ret;
+ break;
+ }
- ALLOC_ZVAL(ret);
- INIT_PZVAL_COPY(ret, retval_ptr);
- *EG(return_value_ptr_ptr) = ret;
+ retval_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
+ }
+
+ if (IS_CV == IS_VAR && !Z_ISREF_PP(retval_ptr_ptr)) {
+ if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
+ EX_T(opline->op1.var).var.fcall_returned_reference) {
+ } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
+ zend_error(E_NOTICE, "Only variable references should be returned by reference");
+ if (EG(return_value_ptr_ptr)) {
+ retval_ptr = *retval_ptr_ptr;
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ Z_ADDREF_P(retval_ptr);
+ }
+ break;
+ }
}
- }
+
+ if (EG(return_value_ptr_ptr)) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+ Z_ADDREF_PP(retval_ptr_ptr);
+
+ *EG(return_value_ptr_ptr) = *retval_ptr_ptr;
+ }
+ } while (0);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *value;
zval *exception;
- value = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_CONST || Z_TYPE_P(value) != IS_OBJECT) {
+ if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
zend_exception_save(TSRMLS_C);
@@ -22230,40 +27065,15 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_throw_exception_object(exception TSRMLS_CC);
zend_exception_restore(TSRMLS_C);
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
- && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
- zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num);
- }
- {
- zval *valptr;
- zval *value;
-
-
- value = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-
- ALLOC_ZVAL(valptr);
- INIT_PZVAL_COPY(valptr, value);
- if (!0) {
- zval_copy_ctor(valptr);
- }
- zend_vm_stack_push(valptr TSRMLS_CC);
-
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *varptr;
- varptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ varptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
if (varptr == &EG(uninitialized_zval)) {
ALLOC_ZVAL(varptr);
@@ -22273,7 +27083,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARG
zval *original_var = varptr;
ALLOC_ZVAL(varptr);
- *varptr = *original_var;
+ ZVAL_COPY_VALUE(varptr, original_var);
Z_UNSET_ISREF_P(varptr);
Z_SET_REFCOUNT_P(varptr, 0);
zval_copy_ctor(varptr);
@@ -22282,34 +27092,36 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARG
zend_vm_stack_push(varptr TSRMLS_CC);
; /* for string offsets */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
zval *varptr;
+ SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
- } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
if (IS_CV == IS_VAR &&
(opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
- EX_T(opline->op1.u.var).var.fcall_returned_reference &&
- EX_T(opline->op1.u.var).var.ptr) {
- varptr = EX_T(opline->op1.u.var).var.ptr;
+ EX_T(opline->op1.var).var.fcall_returned_reference &&
+ EX_T(opline->op1.var).var.ptr) {
+ varptr = EX_T(opline->op1.var).var.ptr;
PZVAL_UNLOCK_EX(varptr, &free_op1, 0);
} else {
- varptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ varptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
}
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
- EX_T(opline->op1.u.var).var.fcall_returned_reference) &&
+ EX_T(opline->op1.var).var.fcall_returned_reference) &&
varptr != &EG(uninitialized_zval) &&
(PZVAL_IS_REF(varptr) ||
(Z_REFCOUNT_P(varptr) == 1 && (IS_CV == IS_CV || free_op1.var)))) {
@@ -22321,7 +27133,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
- !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
ALLOC_ZVAL(valptr);
@@ -22332,28 +27144,32 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
zend_vm_stack_push(valptr TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval **varptr_ptr;
zval *varptr;
- varptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !varptr_ptr) {
+ SAVE_OPLINE();
+ varptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
- if (IS_CV == IS_VAR && *varptr_ptr == EG(error_zval_ptr)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(*varptr_ptr == &EG(error_zval))) {
ALLOC_INIT_ZVAL(varptr);
zend_vm_stack_push(varptr TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@@ -22362,51 +27178,57 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
Z_ADDREF_P(varptr);
zend_vm_stack_push(varptr TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME)
- && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) {
+ && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) {
return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+ SAVE_OPLINE();
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval *retval = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
/* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = i_zend_is_true(_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC));
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC)));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *obj = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *obj;
zend_class_entry *ce;
zend_function *clone;
zend_object_clone_obj_t clone_call;
+ SAVE_OPLINE();
+ obj = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
if (IS_CV == IS_CONST ||
- (IS_CV == IS_VAR && !obj) ||
- Z_TYPE_P(obj) != IS_OBJECT) {
+ UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
}
ce = Z_OBJCE_P(obj);
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
- if (!clone_call) {
+ if (UNEXPECTED(clone_call == NULL)) {
if (ce) {
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
} else {
@@ -22418,42 +27240,49 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
- if (ce != EG(scope)) {
+ if (UNEXPECTED(ce != EG(scope))) {
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
- if (!zend_check_protected(clone->common.scope, EG(scope))) {
+ if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
}
}
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (!EG(exception)) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_OBJVAL_P(EX_T(opline->result.u.var).var.ptr) = clone_call(obj TSRMLS_CC);
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT;
- Z_SET_REFCOUNT_P(EX_T(opline->result.u.var).var.ptr, 1);
- Z_SET_ISREF_P(EX_T(opline->result.u.var).var.ptr);
- if (!RETURN_VALUE_USED(opline) || EG(exception)) {
- zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
+ if (EXPECTED(EG(exception) == NULL)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ Z_OBJVAL_P(retval) = clone_call(obj TSRMLS_CC);
+ Z_TYPE_P(retval) = IS_OBJECT;
+ Z_SET_REFCOUNT_P(retval, 1);
+ Z_SET_ISREF_P(retval);
+ if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor(&retval);
+ } else {
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ zval *expr;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- zval *expr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
if (opline->extended_value != IS_STRING) {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!0) {
zendi_zval_copy_ctor(*result);
}
@@ -22477,12 +27306,12 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_make_printable_zval(expr, &var_copy, &use_copy);
if (use_copy) {
- *result = var_copy;
+ ZVAL_COPY_VALUE(result, &var_copy);
if (0) {
}
} else {
- *result = *expr;
+ ZVAL_COPY_VALUE(result, expr);
if (!0) {
zendi_zval_copy_ctor(*result);
}
@@ -22497,37 +27326,38 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
break;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_op_array *new_op_array=NULL;
- int return_value_used;
- zval *inc_filename = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *tmp_inc_filename = NULL;
+ zval *inc_filename;
+ zval *tmp_inc_filename = NULL;
zend_bool failure_retval=0;
+ SAVE_OPLINE();
+ inc_filename = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
if (inc_filename->type!=IS_STRING) {
MAKE_STD_ZVAL(tmp_inc_filename);
- *tmp_inc_filename = *inc_filename;
+ ZVAL_COPY_VALUE(tmp_inc_filename, inc_filename);
zval_copy_ctor(tmp_inc_filename);
convert_to_string(tmp_inc_filename);
inc_filename = tmp_inc_filename;
}
- return_value_used = RETURN_VALUE_USED(opline);
-
- if (Z_LVAL(opline->op2.u.constant) != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE || Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE) {
+ if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
}
} else {
- switch (Z_LVAL(opline->op2.u.constant)) {
+ switch (opline->extended_value) {
case ZEND_INCLUDE_ONCE:
case ZEND_REQUIRE_ONCE: {
zend_file_handle file_handle;
@@ -22549,14 +27379,14 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
}
if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1)==SUCCESS) {
- new_op_array = zend_compile_file(&file_handle, (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
+ new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
} else {
zend_file_handle_dtor(&file_handle TSRMLS_CC);
failure_retval=1;
}
} else {
- if (Z_LVAL(opline->op2.u.constant)==ZEND_INCLUDE_ONCE) {
+ if (opline->extended_value == ZEND_INCLUDE_ONCE) {
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
} else {
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename) TSRMLS_CC);
@@ -22569,7 +27399,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
- new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC);
+ new_op_array = compile_filename(opline->extended_value, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
@@ -22585,12 +27415,18 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
zval_ptr_dtor(&tmp_inc_filename);
}
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- if (new_op_array && !EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ } else if (EXPECTED(new_op_array != NULL)) {
EX(original_return_value) = EG(return_value_ptr_ptr);
- EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
EG(active_op_array) = new_op_array;
- EX_T(opline->result.u.var).var.ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
+ EX_T(opline->result.var).var.ptr = NULL;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ EG(return_value_ptr_ptr) = EX_T(opline->result.var).var.ptr_ptr;
+ } else {
+ EG(return_value_ptr_ptr) = NULL;
+ }
EX(current_object) = EX(object);
@@ -22601,8 +27437,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
zend_rebuild_symbol_table(TSRMLS_C);
}
- if (zend_execute == execute) {
- EX(call_opline) = opline;
+ if (EXPECTED(zend_execute == execute)) {
ZEND_VM_ENTER();
} else {
zend_execute(new_op_array TSRMLS_CC);
@@ -22611,121 +27446,39 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
EX(function_state).function = (zend_function *) EX(op_array);
EX(object) = EX(current_object);
- if (return_value_used) {
- if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = 1;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
-
EG(opline_ptr) = &EX(opline);
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr) = EX(original_return_value);
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
- if (EG(exception)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
- }
- } else {
- if (return_value_used) {
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_ZVAL(*EX_T(opline->result.u.var).var.ptr);
- Z_LVAL_P(EX_T(opline->result.u.var).var.ptr) = failure_retval;
- Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_BOOL;
- }
- }
- ZEND_VM_NEXT_OPCODE();
-}
+ HANDLE_EXCEPTION();
+ } else if (RETURN_VALUE_USED(opline)) {
+ if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */
+ zval *retval;
-static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- zend_op *opline = EX(opline);
- zval tmp, *varname;
- HashTable *target_symbol_table;
-
-
- if (IS_CV == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EG(active_symbol_table)) {
- zend_execute_data *ex = EX(prev_execute_data);
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
-
- if (zend_hash_quick_del(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) {
- while (ex && ex->symbol_table == EG(active_symbol_table)) {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == cv->hash_value &&
- ex->op_array->vars[i].name_len == cv->name_len &&
- !memcmp(ex->op_array->vars[i].name, cv->name, cv->name_len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- }
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, 1);
+ INIT_PZVAL(retval);
+ EX_T(opline->result.var).var.ptr = retval;
}
- EX(CVs)[opline->op1.u.var] = NULL;
- } else if (EX(CVs)[opline->op1.u.var]) {
- zval_ptr_dtor(EX(CVs)[opline->op1.u.var]);
- EX(CVs)[opline->op1.u.var] = NULL;
}
- ZEND_VM_NEXT_OPCODE();
- }
-
- varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- Z_ADDREF_P(varname);
- }
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
- } else {
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
-
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_quick_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value) == SUCCESS) {
- zend_execute_data *ex = execute_data;
-
- do {
- int i;
-
- if (ex->op_array) {
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
- ex = ex->prev_execute_data;
- } while (ex && ex->symbol_table == target_symbol_table);
- }
- }
+ } else if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- if (varname == &tmp) {
- zval_dtor(&tmp);
- } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- zval_ptr_dtor(&varname);
+ ALLOC_ZVAL(retval);
+ ZVAL_BOOL(retval, failure_retval);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
-
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *array_ptr, **array_ptr_ptr;
HashTable *fe_ht;
@@ -22733,14 +27486,18 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_class_entry *ce = NULL;
zend_bool is_empty = 0;
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- array_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ SAVE_OPLINE();
+
+ if ((IS_CV == IS_CV || IS_CV == IS_VAR) &&
+ (opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
+ array_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) {
- ALLOC_INIT_ZVAL(array_ptr);
+ MAKE_STD_ZVAL(array_ptr);
+ ZVAL_NULL(array_ptr);
} else if (Z_TYPE_PP(array_ptr_ptr) == IS_OBJECT) {
if(Z_OBJ_HT_PP(array_ptr_ptr)->get_class_entry == NULL) {
zend_error(E_WARNING, "foreach() cannot iterate over objects without PHP class");
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
}
ce = Z_OBJCE_PP(array_ptr_ptr);
@@ -22760,7 +27517,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
Z_ADDREF_P(array_ptr);
}
} else {
- array_ptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ array_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) { /* IS_TMP_VAR */
zval *tmp;
@@ -22796,50 +27553,35 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (ce && ce->get_iterator) {
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_RESET_REFERENCE TSRMLS_CC);
- if (iter && !EG(exception)) {
+ if (iter && EXPECTED(EG(exception) == NULL)) {
array_ptr = zend_iterator_wrap(iter TSRMLS_CC);
} else {
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
- } else {
-
- }
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
- AI_SET_PTR(EX_T(opline->result.u.var).var, array_ptr);
- PZVAL_LOCK(array_ptr);
+ EX_T(opline->result.var).fe.ptr = array_ptr;
if (iter) {
iter->index = 0;
if (iter->funcs->rewind) {
iter->funcs->rewind(iter TSRMLS_CC);
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
}
is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
- if (EG(exception)) {
- Z_DELREF_P(array_ptr);
+ if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
- }
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
iter->index = -1; /* will be set to 0 before using next handler */
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
@@ -22862,437 +27604,469 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
}
is_empty = zend_hash_has_more_elements(fe_ht) != SUCCESS;
- zend_hash_get_pointer(fe_ht, &EX_T(opline->result.u.var).fe.fe_pos);
+ zend_hash_get_pointer(fe_ht, &EX_T(opline->result.var).fe.fe_pos);
} else {
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
is_empty = 1;
}
- if (opline->extended_value & ZEND_FE_RESET_VARIABLE) {
-
- } else {
-
- }
if (is_empty) {
- ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.u.opline_num);
+ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
} else {
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
}
-static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zval **value;
- zend_bool isset = 1;
+#if 0 || (IS_CV != IS_UNUSED)
+ USE_OPLINE
- if (IS_CV == IS_CV && (opline->extended_value & ZEND_QUICK_SET)) {
- if (EX(CVs)[opline->op1.u.var]) {
- value = EX(CVs)[opline->op1.u.var];
- } else if (EG(active_symbol_table)) {
- zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var);
+ SAVE_OPLINE();
+ if (IS_CV != IS_UNUSED) {
- if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
- isset = 0;
- }
+ zval *ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (Z_TYPE_P(ptr) == IS_LONG) {
+ EG(exit_status) = Z_LVAL_P(ptr);
} else {
- isset = 0;
+ zend_print_variable(ptr);
}
- } else {
- HashTable *target_symbol_table;
-
- zval tmp, *varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
- if (Z_TYPE_P(varname) != IS_STRING) {
- tmp = *varname;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- varname = &tmp;
- }
+ }
+#endif
+ zend_bailout();
+ ZEND_VM_NEXT_OPCODE(); /* Never reached */
+}
- if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
- value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1 TSRMLS_CC);
- if (!value) {
- isset = 0;
- }
- } else {
- target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
- isset = 0;
- }
- }
+static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
- if (varname == &tmp) {
- zval_dtor(&tmp);
- }
+ zval *value;
- }
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
+ if (i_zend_is_true(value)) {
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
+ if (!0) {
+ zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+ }
- switch (opline->extended_value & ZEND_ISSET_ISEMPTY_MASK) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
- } else {
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 0;
- }
- break;
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+ ZEND_VM_JMP(opline->op2.jmp_addr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
-#if 0 || (IS_CV != IS_UNUSED)
- zend_op *opline = EX(opline);
- if (IS_CV != IS_UNUSED) {
+ USE_OPLINE
- zval *ptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *value, *ret;
- if (Z_TYPE_P(ptr) == IS_LONG) {
- EG(exit_status) = Z_LVAL_P(ptr);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (i_zend_is_true(value)) {
+ if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
} else {
- zend_print_variable(ptr);
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!0) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
}
- }
+#if DEBUG_ZEND>=2
+ printf("Conditional jmp to %d\n", opline->op2.opline_num);
#endif
- zend_bailout();
+ ZEND_VM_JMP(opline->op2.jmp_addr);
+ }
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *value = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *value;
- if (i_zend_is_true(value)) {
- EX_T(opline->result.u.var).tmp_var = *value;
- zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
-#if DEBUG_ZEND>=2
- printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
-#endif
- ZEND_VM_JMP(opline->op2.u.jmp_addr);
+ ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
+ if (!0) {
+ zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *value = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *value, *ret;
- EX_T(opline->result.u.var).tmp_var = *value;
- if (!0) {
- zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ Z_ADDREF_P(value);
+ EX_T(opline->result.var).var.ptr = value;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ } else {
+ ALLOC_ZVAL(ret);
+ INIT_PZVAL_COPY(ret, value);
+ EX_T(opline->result.var).var.ptr = ret;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
+ if (!0) {
+ zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *expr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *expr;
zend_bool result;
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) {
- result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.u.var).class_entry TSRMLS_CC);
+ result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC);
} else {
result = 0;
}
- ZVAL_BOOL(&EX_T(opline->result.u.var).tmp_var, result);
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, result);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
zval *object;
- zval *property = &opline->op2.u.constant;
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = opline->op2.zv;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -23303,16 +28077,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -23322,7 +28096,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -23344,22 +28118,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -23373,66 +28147,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = &opline->op2.u.constant;
+ zval *dim = opline->op2.zv;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = &opline->op2.u.constant;
- var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ value = opline->op2.zv;
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -23444,16 +28223,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -23514,29 +28298,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_H
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = &opline->op2.u.constant;
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = opline->op2.zv;
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -23547,13 +28337,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -23562,9 +28352,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -23578,14 +28368,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -23596,6 +28386,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -23611,26 +28402,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = &opline->op2.u.constant;
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = opline->op2.zv;
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -23641,12 +28438,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -23656,10 +28453,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -23669,20 +28466,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -23692,6 +28488,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -23705,197 +28502,348 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA
return zend_post_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_CV == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_CV != IS_TMP_VAR) {
+
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_CV == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_CV != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_CV_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *dim = &opline->op2.u.constant;
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_CV != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_RW TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *dim = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = &opline->op2.u.constant;
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_CONST == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *dim = &opline->op2.u.constant;
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_UNSET TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC);
+ zval *container;
- zval *offset = &opline->op2.u.constant;
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zval *retval;
@@ -23905,18 +28853,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(i
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -23925,137 +28865,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(i
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = opline->op2.zv;
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1;
- zval *property = &opline->op2.u.constant;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = opline->op2.zv;
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_res;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *property = &opline->op2.u.constant;
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = opline->op2.zv;
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -24065,48 +29050,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
+
+ zval **object_ptr;
+ zval *property_name;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- zval *property_name = &opline->op2.u.constant;
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property_name = opline->op2.zv;
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -24114,28 +29098,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
- zval *property_name = &opline->op2.u.constant;
+ zval *property_name = opline->op2.zv;
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -24144,30 +29131,46 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
} else {
zend_free_op free_op_data1, free_op_data2;
zval *value;
- zval *dim = &opline->op2.u.constant;
+ zval *dim = opline->op2.zv;
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CONST, BP_VAR_W TSRMLS_CC);
+
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -24175,75 +29178,111 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
}
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ zval *value;
+ zval **variable_ptr_ptr;
- zval *value = &opline->op2.u.constant;
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ SAVE_OPLINE();
+ value = opline->op2.zv;
+ variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CONST TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CONST TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_CV == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (0) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_CONST == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CONST == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
/* zend_assign_to_variable() always takes care of op2, never free it! */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = &opline->op2.u.constant;
+ function_name = opline->op2.zv;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CONST != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CONST != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -24263,76 +29302,52 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
+ SAVE_OPLINE();
if (IS_CV==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- &opline->op2.u.constant TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ opline->op2.zv TSRMLS_CC);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
-
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=&opline->op2.u.constant;
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -24343,20 +29358,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CONST != IS_UNUSED) {
+
+ zval *offset = opline->op2.zv;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -24366,21 +29398,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CV == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CV != IS_UNUSED
@@ -24390,17 +29423,96 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+
+
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = &opline->op2.u.constant;
+ offset = opline->op2.zv;
if (IS_CV != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -24409,37 +29521,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -24455,7 +29570,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -24479,15 +29594,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *offset = &opline->op2.u.constant;
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = opline->op2.zv;
if (IS_CV != IS_VAR || container) {
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -24498,7 +29618,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -24514,137 +29634,234 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
}
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV &&
+ IS_CONST == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+
+ zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_CONST != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_CONST == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_CV != IS_VAR || container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
- zval *offset = &opline->op2.u.constant;
+ offset = opline->op2.zv;
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- ht = Z_ARRVAL_PP(container);
+ ht = Z_ARRVAL_PP(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_CONST == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
- } else {
- result = 1;
- }
- break;
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
+ }
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
- }
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
-
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
+ }
- } else {
+ } else {
- }
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -24660,277 +29877,306 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
zval_dtor(free_op2.var);
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -24941,16 +30187,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -24960,7 +30206,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -24982,22 +30228,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -25011,66 +30257,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -25082,17 +30333,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
zval_dtor(free_op2.var);
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -25153,29 +30409,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
zval_dtor(free_op2.var);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -25186,13 +30448,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -25201,9 +30463,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -25217,14 +30479,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -25235,6 +30497,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -25250,26 +30513,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
zval_dtor(free_op2.var);
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -25280,12 +30549,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -25295,10 +30564,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -25308,20 +30577,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -25331,6 +30599,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -25346,195 +30615,182 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_CV != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC);
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_TMP_VAR == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC);
}
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 1, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC);
zval_dtor(free_op2.var);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC);
+ zval *container;
zend_free_op free_op2;
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
zval_dtor(free_op2.var);
} else {
zval *retval;
@@ -25544,18 +30800,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(int
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (1) {
zval_ptr_dtor(&offset);
@@ -25564,137 +30812,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(int
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_TMP(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ zval_dtor(free_op2.var);
+ } else {
+ zval *retval;
+
+ if (1) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (1) {
+ zval_ptr_dtor(&offset);
+ } else {
+ zval_dtor(free_op2.var);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_CV_TMP(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *property = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -25704,48 +30997,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H
if (1) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property);
} else {
zval_dtor(free_op2.var);
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property_name);
} else {
@@ -25753,28 +31045,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
+
+ zval **object_ptr;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
zend_free_op free_op2;
- zval *property_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (1) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (1) {
zval_ptr_dtor(&property_name);
} else {
@@ -25783,31 +31078,47 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
} else {
zend_free_op free_op2, free_op_data1, free_op_data2;
zval *value;
- zval *dim = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 1, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR, BP_VAR_W TSRMLS_CC);
zval_dtor(free_op2.var);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -25815,75 +31126,111 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *value = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
- if (IS_CV == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_TMP_VAR TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_CV == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (1) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 1 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_TMP_VAR == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_TMP_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
/* zend_assign_to_variable() always takes care of op2, never free it! */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_TMP_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_TMP_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -25904,77 +31251,53 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
zval_dtor(free_op2.var);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op2;
+ SAVE_OPLINE();
if (IS_CV==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
zval_dtor(free_op2.var);
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
-
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+
zval *expr_ptr;
- zval *offset=_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -25985,20 +31308,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_TMP_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -26008,21 +31348,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
}
zval_dtor(free_op2.var);
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CV == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CV != IS_UNUSED
@@ -26034,15 +31375,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_CV != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -26051,37 +31395,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -26097,7 +31444,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (1) {
@@ -26121,15 +31468,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_CV != IS_VAR || container) {
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -26140,7 +31492,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -26156,137 +31508,149 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
zval_dtor(free_op2.var);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
-
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_CV != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
- ht = Z_ARRVAL_PP(container);
+ offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- break;
- }
+ ht = Z_ARRVAL_PP(container);
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_TMP_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- zval_dtor(free_op2.var);
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (1) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ zval_dtor(free_op2.var);
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (1) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (1) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- zval_dtor(free_op2.var);
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (1) {
+ zval_ptr_dtor(&offset);
+ } else {
+ zval_dtor(free_op2.var);
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- zval_dtor(free_op2.var);
- } else {
- zval_dtor(free_op2.var);
}
+ zval_dtor(free_op2.var);
+ } else {
+ zval_dtor(free_op2.var);
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -26302,277 +31666,306 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2, free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -26583,16 +31976,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -26602,7 +31995,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -26624,22 +32017,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -26653,66 +32046,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2, free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -26724,17 +32122,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -26795,29 +32198,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAN
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -26828,13 +32237,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -26843,9 +32252,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -26859,14 +32268,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -26877,6 +32286,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -26892,26 +32302,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -26922,12 +32338,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -26937,10 +32353,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -26950,20 +32366,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -26973,6 +32388,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -26986,197 +32402,348 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND
return zend_post_incdec_property_helper_SPEC_CV_VAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_CV == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_CV != IS_TMP_VAR) {
+
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_CV == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_CV != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_CV_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_CV != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_VAR == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC);
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC);
+ zval *container;
zend_free_op free_op2;
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *offset;
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
zval *retval;
@@ -27186,18 +32753,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(int
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -27206,137 +32765,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(int
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+ zend_free_op free_op2;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1, free_op2;
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_op2, free_res;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *property = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -27346,48 +32950,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op2;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -27395,28 +32998,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
+
+ zval **object_ptr;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
zend_free_op free_op2;
- zval *property_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -27425,31 +33031,47 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
} else {
zend_free_op free_op2, free_op_data1, free_op_data2;
zval *value;
- zval *dim = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_VAR, BP_VAR_W TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -27457,74 +33079,99 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
}
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval *value = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
+
+ SAVE_OPLINE();
+ value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_VAR TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_VAR TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_CV == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (0) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_VAR == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_VAR == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
/* zend_assign_to_variable() always takes care of op2, never free it! */
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
zval **variable_ptr_ptr;
- zval **value_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **value_ptr_ptr;
+
+ SAVE_OPLINE();
+ value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_VAR == IS_VAR &&
value_ptr_ptr &&
!Z_ISREF_PP(value_ptr_ptr) &&
opline->extended_value == ZEND_RETURNS_FUNCTION &&
- !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+ !EX_T(opline->op2.var).var.fcall_returned_reference) {
if (free_op2.var == NULL) {
PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
}
zend_error(E_STRICT, "Only variables should be assigned by reference");
if (UNEXPECTED(EG(exception) != NULL)) {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
PZVAL_LOCK(*value_ptr_ptr);
}
- if (IS_CV == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr)) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if ((IS_VAR == IS_VAR && !value_ptr_ptr) ||
- (IS_CV == IS_VAR && !variable_ptr_ptr)) {
+ variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
+ (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
@@ -27533,49 +33180,64 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
Z_DELREF_PP(variable_ptr_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*variable_ptr_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *variable_ptr_ptr);
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_VAR != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_VAR != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -27596,77 +33258,53 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
zend_free_op free_op2;
+ SAVE_OPLINE();
if (IS_CV==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC) TSRMLS_CC);
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC);
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
-
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_free_op free_op2;
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
+ USE_OPLINE
+
zval *expr_ptr;
- zval *offset=_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -27677,20 +33315,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_free_op free_op2;
+ zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -27700,21 +33355,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
}
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CV == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CV != IS_UNUSED
@@ -27724,17 +33380,96 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+
+
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_CV != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -27743,37 +33478,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -27789,7 +33527,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -27813,15 +33551,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ zval **container;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
if (IS_CV != IS_VAR || container) {
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -27832,7 +33575,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -27848,137 +33591,234 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
- zval **value = NULL;
- int result = 0;
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV &&
+ IS_VAR == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
- if (IS_CV != IS_VAR || container) {
- zend_free_op free_op2;
- zval *offset = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
- ht = Z_ARRVAL_PP(container);
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ if (IS_VAR != IS_UNUSED) {
+ zend_class_entry *ce;
- break;
+ if (IS_VAR == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
}
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op2;
+ zval **container;
+ zval **value = NULL;
+ int result = 0;
+ ulong hval;
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
+
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
+
+ ht = Z_ARRVAL_PP(container);
+
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_VAR == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
} else {
- result = 1;
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ }
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
- } else {
- if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+ } else {
+ if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -27994,33 +33834,30 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
zval *object;
zval *property = NULL;
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -28031,16 +33868,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -28050,7 +33887,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -28072,22 +33909,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -28101,66 +33938,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
zval *dim = NULL;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
value = NULL;
- var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -28172,16 +34014,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -28240,105 +34087,265 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
+static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval **retval;
+ zval tmp_varname;
+ HashTable *target_symbol_table;
+ ulong hash_value;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) {
+ ZVAL_COPY_VALUE(&tmp_varname, varname);
+ zval_copy_ctor(&tmp_varname);
+ Z_SET_REFCOUNT(tmp_varname, 1);
+ Z_UNSET_ISREF(tmp_varname);
+ convert_to_string(&tmp_varname);
+ varname = &tmp_varname;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ retval = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 0, ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+/*
+ if (!target_symbol_table) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+*/
+ if (IS_CV == IS_CONST) {
+ hash_value = Z_HASH_P(varname);
+ } else if (IS_INTERNED(Z_STRVAL_P(varname))) {
+ hash_value = INTERNED_HASH(Z_STRVAL_P(varname));
+ } else {
+ hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1);
+ }
+
+ if (zend_hash_quick_find(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, (void **) &retval) == FAILURE) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval_ptr);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+ /* break missing intentionally */
+ case BP_VAR_W:
+ Z_ADDREF_P(&EG(uninitialized_zval));
+ zend_hash_quick_update(target_symbol_table, Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1, hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **) &retval);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+ }
+ switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
+ case ZEND_FETCH_GLOBAL:
+ if (IS_CV != IS_TMP_VAR) {
+
+ }
+ break;
+ case ZEND_FETCH_LOCAL:
+
+ break;
+ case ZEND_FETCH_STATIC:
+ zval_update_constant(retval, (void*) 1 TSRMLS_CC);
+ break;
+ case ZEND_FETCH_GLOBAL_LOCK:
+ if (IS_CV == IS_VAR && !free_op1.var) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ }
+ break;
+ }
+ }
+
+
+ if (IS_CV != IS_CONST && varname == &tmp_varname) {
+ zval_dtor(&tmp_varname);
+ }
+ if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_IS:
+ AI_SET_PTR(&EX_T(opline->result.var), *retval);
+ break;
+ case BP_VAR_UNSET: {
+ zend_free_op free_res;
+
+ PZVAL_UNLOCK(*retval, &free_res);
+ if (retval != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval);
+ }
+ PZVAL_LOCK(*retval);
+ FREE_OP_VAR_PTR(free_res);
+ }
+ /* break missing intentionally */
+ default:
+ EX_T(opline->result.var).var.ptr_ptr = retval;
+ break;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ return zend_fetch_var_address_helper_SPEC_CV_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
+static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = NULL;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = NULL;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_RW TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = NULL;
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_UNUSED == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_R TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
+
+ zval **object_ptr;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
@@ -28348,7 +34355,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -28360,27 +34367,43 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
zval *dim = NULL;
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_UNUSED, BP_VAR_W TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -28388,46 +34411,36 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
}
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=NULL;
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -28438,20 +34451,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_UNUSED != IS_UNUSED) {
+
+ zval *offset = NULL;
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_UNUSED == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -28461,21 +34491,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CV == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CV != IS_UNUSED
@@ -28485,279 +34516,469 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
}
}
+static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ HashTable *target_symbol_table;
+
+
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value TSRMLS_CC);
+ EX_CV(opline->op1.var) = NULL;
+ } else if (EX_CV(opline->op1.var)) {
+ zval_ptr_dtor(EX_CV(opline->op1.var));
+ EX_CV(opline->op1.var) = NULL;
+ }
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+
+ varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ Z_ADDREF_P(varname);
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ zend_std_unset_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ } else {
+ ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC);
+ }
+
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ } else if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+ zval_ptr_dtor(&varname);
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval **value;
+ zend_bool isset = 1;
+
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV &&
+ IS_UNUSED == IS_UNUSED &&
+ (opline->extended_value & ZEND_QUICK_SET)) {
+ if (EX_CV(opline->op1.var)) {
+ value = EX_CV(opline->op1.var);
+ } else if (EG(active_symbol_table)) {
+ zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var);
+
+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ } else {
+ isset = 0;
+ }
+ } else {
+ HashTable *target_symbol_table;
+
+ zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_COPY_VALUE(&tmp, varname);
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED != IS_UNUSED) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+ ce = CACHED_PTR(opline->op2.literal->cache_slot);
+ } else {
+ ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+ if (UNEXPECTED(ce == NULL)) {
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+ }
+ CACHE_PTR(opline->op2.literal->cache_slot, ce);
+ }
+ } else {
+ ce = EX_T(opline->op2.var).class_entry;
+ }
+ value = zend_std_get_static_property(ce, Z_STRVAL_P(varname), Z_STRLEN_P(varname), 1, ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
+ if (!value) {
+ isset = 0;
+ }
+ } else {
+ target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
+ if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ isset = 0;
+ }
+ }
+
+ if (IS_CV != IS_CONST && varname == &tmp) {
+ zval_dtor(&tmp);
+ }
+
+ }
+
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) != IS_NULL) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 1);
+ } else {
+ ZVAL_BOOL(&EX_T(opline->result.var).tmp_var, 0);
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- add_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_add_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- sub_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_sub_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mul_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mul_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- div_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_div_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- mod_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ fast_mod_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_left_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_left_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- shift_right_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ shift_right_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- concat_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ concat_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- is_identical_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ is_identical_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
+ SAVE_OPLINE();
is_identical_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
Z_LVAL_P(result) = !Z_LVAL_P(result);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_not_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *result = &EX_T(opline->result.u.var).tmp_var;
+ zval *result = &EX_T(opline->result.var).tmp_var;
- compare_function(result,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ SAVE_OPLINE();
+ ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC));
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_or_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_or_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_and_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_and_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- bitwise_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ bitwise_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- boolean_xor_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
+ SAVE_OPLINE();
+ boolean_xor_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
zend_free_op free_op_data1;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- znode *result = &opline->result;
+ zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- EX_T(result->u.var).var.ptr_ptr = NULL;
make_real_object(object_ptr TSRMLS_CC);
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
FREE_OP(free_op_data1);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
} else {
/* here we are sure we are dealing with an object */
@@ -28768,16 +34989,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
/* here property is a string */
if (opline->extended_value == ZEND_ASSIGN_OBJ
&& Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
binary_op(*zptr, *zptr, value TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = *zptr;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*zptr);
+ EX_T(opline->result.var).var.ptr = *zptr;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -28787,7 +35008,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
if (Z_OBJ_HT_P(object)->read_property) {
- z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
}
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
if (Z_OBJ_HT_P(object)->read_dimension) {
@@ -28809,22 +35030,22 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
SEPARATE_ZVAL_IF_NOT_REF(&z);
binary_op(z, z, value TSRMLS_CC);
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else /* if (opline->extended_value == ZEND_ASSIGN_DIM) */ {
Z_OBJ_HT_P(object)->write_dimension(object, property, z TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = z;
- EX_T(result->u.var).var.ptr_ptr = NULL;
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(z);
+ EX_T(opline->result.var).var.ptr = z;
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (!RETURN_VALUE_UNUSED(result)) {
- EX_T(result->u.var).var.ptr = EG(uninitialized_zval_ptr);
- EX_T(result->u.var).var.ptr_ptr = NULL;
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ EX_T(opline->result.var).var.ptr = &EG(uninitialized_zval);
+ EX_T(opline->result.var).var.ptr_ptr = NULL;
}
}
}
@@ -28838,66 +35059,71 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op_data2, free_op_data1;
zval **var_ptr;
zval *value;
+ SAVE_OPLINE();
switch (opline->extended_value) {
case ZEND_ASSIGN_OBJ:
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
case ZEND_ASSIGN_DIM: {
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ } else if (UNEXPECTED(Z_TYPE_PP(container) == IS_OBJECT)) {
if (IS_CV == IS_VAR && !0) {
Z_ADDREF_PP(container); /* undo the effect of get_obj_zval_ptr_ptr() */
}
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
- zend_op *op_data = opline+1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- var_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- ZEND_VM_INC_OPCODE();
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
}
}
break;
default:
- value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- var_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
/* do nothing */
break;
}
- if (!var_ptr) {
+ if (UNEXPECTED(var_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
- if (*var_ptr == EG(error_zval_ptr)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ if (UNEXPECTED(*var_ptr == &EG(error_zval))) {
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
+ CHECK_EXCEPTION();
+ if (opline->extended_value == ZEND_ASSIGN_DIM) {
+ ZEND_VM_INC_OPCODE();
+ }
ZEND_VM_NEXT_OPCODE();
}
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- if(Z_TYPE_PP(var_ptr) == IS_OBJECT && Z_OBJ_HANDLER_PP(var_ptr, get)
+ if (UNEXPECTED(Z_TYPE_PP(var_ptr) == IS_OBJECT)
+ && Z_OBJ_HANDLER_PP(var_ptr, get)
&& Z_OBJ_HANDLER_PP(var_ptr, set)) {
/* proxy object */
zval *objval = Z_OBJ_HANDLER_PP(var_ptr, get)(*var_ptr TSRMLS_CC);
@@ -28909,16 +35135,21 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op
binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *var_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*var_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *var_ptr);
}
if (opline->extended_value == ZEND_ASSIGN_DIM) {
FREE_OP(free_op_data1);
FREE_OP_VAR_PTR(free_op_data2);
- }
+ CHECK_EXCEPTION();
+ ZEND_VM_INC_OPCODE();
+ } else {
+
+ CHECK_EXCEPTION();
+ }
ZEND_VM_NEXT_OPCODE();
}
@@ -28979,29 +35210,35 @@ static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HAND
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **retval = &EX_T(opline->result.u.var).var.ptr;
+ zval *property;
+ zval **retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ retval = &EX_T(opline->result.var).var.ptr;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -29012,13 +35249,13 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
SEPARATE_ZVAL_IF_NOT_REF(zptr);
have_get_ptr = 1;
incdec_op(*zptr);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
+ if (RETURN_VALUE_USED(opline)) {
*retval = *zptr;
PZVAL_LOCK(*retval);
}
@@ -29027,9 +35264,9 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -29043,14 +35280,14 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc
SEPARATE_ZVAL_IF_NOT_REF(&z);
incdec_op(z);
*retval = z;
- Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC);
- SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
+ Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+ SELECTIVE_PZVAL_LOCK(*retval, opline);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- *retval = EG(uninitialized_zval_ptr);
- PZVAL_LOCK(*retval);
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ *retval = &EG(uninitialized_zval);
}
}
}
@@ -29061,6 +35298,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -29076,26 +35314,32 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **object_ptr;
zval *object;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *retval = &EX_T(opline->result.u.var).tmp_var;
+ zval *property;
+ zval *retval;
int have_get_ptr = 0;
- if (IS_CV == IS_VAR && !object_ptr) {
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ retval = &EX_T(opline->result.var).tmp_var;
+
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
}
make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */
object = *object_ptr;
- if (Z_TYPE_P(object) != IS_OBJECT) {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -29106,12 +35350,12 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in
}
if (Z_OBJ_HT_P(object)->get_property_ptr_ptr) {
- zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property TSRMLS_CC);
+ zval **zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (zptr != NULL) { /* NULL means no success in getting PTR */
have_get_ptr = 1;
SEPARATE_ZVAL_IF_NOT_REF(zptr);
- *retval = **zptr;
+ ZVAL_COPY_VALUE(retval, *zptr);
zendi_zval_copy_ctor(*retval);
incdec_op(*zptr);
@@ -29121,10 +35365,10 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in
if (!have_get_ptr) {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R TSRMLS_CC);
+ zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval *z_copy;
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
@@ -29134,20 +35378,19 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in
}
z = value;
}
- *retval = *z;
+ ZVAL_COPY_VALUE(retval, z);
zendi_zval_copy_ctor(*retval);
ALLOC_ZVAL(z_copy);
- *z_copy = *z;
+ INIT_PZVAL_COPY(z_copy, z);
zendi_zval_copy_ctor(*z_copy);
- INIT_PZVAL(z_copy);
incdec_op(z_copy);
Z_ADDREF_P(z);
- Z_OBJ_HT_P(object)->write_property(object, property, z_copy TSRMLS_CC);
+ Z_OBJ_HT_P(object)->write_property(object, property, z_copy, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(&z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- *retval = *EG(uninitialized_zval_ptr);
+ ZVAL_NULL(retval);
}
}
@@ -29157,6 +35400,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -29172,195 +35416,182 @@ static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
zval **container;
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK &&
+ SAVE_OPLINE();
+
+ if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
IS_CV != IS_CV &&
- EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
+ EX_T(opline->op1.var).var.ptr_ptr) {
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
}
- zend_fetch_dimension_address_read(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
- if (opline->extended_value && EX_T(opline->result.u.var).var.ptr_ptr) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ if (UNEXPECTED(opline->extended_value != 0)) {
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ if (retval_ptr) {
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ }
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ zval **container;
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_IS TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
zval **container;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ SAVE_OPLINE();
+
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
} else {
if (IS_CV == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
- zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
- }
- zend_fetch_dimension_address_read(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_R TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
- /* Not needed in DIM_UNSET
- if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- }
- */
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_fetch_dimension_address(&EX_T(opline->result.u.var), container, dim, 0, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC);
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- if (EX_T(opline->result.u.var).var.ptr_ptr == NULL) {
+ if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
} else {
zend_free_op free_res;
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*retval_ptr, &free_res);
+ if (retval_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(retval_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*retval_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(int type, ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ zval *container;
- zval *container = _get_zval_ptr_cv(&opline->op1, EX(Ts), type TSRMLS_CC);
+ zval *offset;
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(container) != IS_OBJECT || !Z_OBJ_HT_P(container)->read_property) {
- if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Trying to get property of non-object");
- }
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
- }
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ zend_error(E_NOTICE, "Trying to get property of non-object");
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
} else {
zval *retval;
@@ -29370,18 +35601,10 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(int
}
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC);
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
- if (RETURN_VALUE_UNUSED(&opline->result)) {
- if (Z_REFCOUNT_P(retval) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(retval);
- zval_dtor(retval);
- FREE_ZVAL(retval);
- }
- } else {
- AI_SET_PTR(EX_T(opline->result.u.var).var, retval);
- PZVAL_LOCK(retval);
- }
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
if (0) {
zval_ptr_dtor(&offset);
@@ -29390,137 +35613,182 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(int
}
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *property;
zval **container;
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
- PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
- EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
+ PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
+ EX_T(opline->op1.var).var.ptr = *EX_T(opline->op1.var).var.ptr_ptr;
}
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if (IS_CV == IS_VAR && !container) {
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
/* We are going to assign the result by reference */
if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
- Z_DELREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(EX_T(opline->result.u.var).var.ptr_ptr);
- Z_ADDREF_PP(EX_T(opline->result.u.var).var.ptr_ptr);
+ zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr;
+
+ Z_DELREF_PP(retval_ptr);
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
+ Z_ADDREF_PP(retval_ptr);
+ EX_T(opline->result.var).var.ptr = *EX_T(opline->result.var).var.ptr_ptr;
+ EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_RW TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_RW TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_fetch_property_address_read_helper_SPEC_CV_CV(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ USE_OPLINE
+
+ zval *container;
+
+ zval *offset;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+
+ if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+ UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+
+ } else {
+ zval *retval;
+
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+
+ /* here we are sure we are dealing with an object */
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
+
+ PZVAL_LOCK(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
+
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
+
+ }
+ }
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->extended_value)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
/* Behave like FETCH_OBJ_W */
zend_free_op free_op1;
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *property;
+ zval **container;
+
+ SAVE_OPLINE();
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_W TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
} else {
- return zend_fetch_property_address_read_helper_SPEC_CV_CV(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op1, free_res;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval *property = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **container;
+ zval *property;
+
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_CV == IS_CV) {
if (container != &EG(uninitialized_zval_ptr)) {
@@ -29530,48 +35798,47 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA
if (0) {
MAKE_REAL_ZVAL_PTR(property);
}
- if (IS_CV == IS_VAR && !container) {
+ if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(&EX_T(opline->result.u.var), container, property, BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(&EX_T(opline->result.var), container, property, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL), BP_VAR_UNSET TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property);
} else {
}
- if (IS_CV == IS_VAR && 0 &&
- READY_TO_DESTROY(free_op1.var)) {
- AI_USE_PTR(EX_T(opline->result.u.var).var);
- if (!PZVAL_IS_REF(*EX_T(opline->result.u.var).var.ptr_ptr) &&
- Z_REFCOUNT_PP(EX_T(opline->result.u.var).var.ptr_ptr) > 2) {
- SEPARATE_ZVAL(EX_T(opline->result.u.var).var.ptr_ptr);
- }
+ if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) {
+ EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
- PZVAL_UNLOCK(*EX_T(opline->result.u.var).var.ptr_ptr, &free_res);
- if (EX_T(opline->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
- SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_UNLOCK(*EX_T(opline->result.var).var.ptr_ptr, &free_res);
+ if (EX_T(opline->result.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) {
+ SEPARATE_ZVAL_IF_NOT_REF(EX_T(opline->result.var).var.ptr_ptr);
}
- PZVAL_LOCK(*EX_T(opline->result.u.var).var.ptr_ptr);
+ PZVAL_LOCK(*EX_T(opline->result.var).var.ptr_ptr);
FREE_OP_VAR_PTR(free_res);
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval **object_ptr;
+ zval *property_name;
+
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_OBJ TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -29579,28 +35846,31 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
}
/* assign_obj has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- zend_op *op_data = opline+1;
+ USE_OPLINE
+
+ zval **object_ptr;
- zval **object_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ SAVE_OPLINE();
+ object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR && !object_ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
if (Z_TYPE_PP(object_ptr) == IS_OBJECT) {
- zval *property_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (0) {
MAKE_REAL_ZVAL_PTR(property_name);
}
- zend_assign_to_object(&opline->result, object_ptr, property_name, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
if (0) {
zval_ptr_dtor(&property_name);
} else {
@@ -29609,30 +35879,46 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
} else {
zend_free_op free_op_data1, free_op_data2;
zval *value;
- zval *dim = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
zval **variable_ptr_ptr;
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var), object_ptr, dim, 0, BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CV, BP_VAR_W TSRMLS_CC);
- value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1, BP_VAR_R);
- variable_ptr_ptr = _get_zval_ptr_ptr_var(&op_data->op2, EX(Ts), &free_op_data2 TSRMLS_CC);
- if (!variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(op_data->op2.u.var), value, op_data->op1.op_type TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(op_data->op2.u.var).str_offset.str)+EX_T(op_data->op2.u.var).str_offset.offset, 1, 1);
+ value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R);
+ variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC);
+ if (UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T((opline+1)->op2.var).str_offset.str)+EX_T((opline+1)->op2.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (IS_TMP_FREE(free_op_data1)) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, IS_TMP_FREE(free_op_data1) TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if ((opline+1)->op1_type == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if ((opline+1)->op1_type == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
FREE_OP_VAR_PTR(free_op_data2);
@@ -29640,73 +35926,98 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
}
/* assign_dim has two opcodes! */
+ CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *value = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval *value;
+ zval **variable_ptr_ptr;
- if (IS_CV == IS_VAR && !variable_ptr_ptr) {
- if (zend_assign_to_string_offset(&EX_T(opline->op1.u.var), value, IS_CV TSRMLS_CC)) {
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
- ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
- INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
- ZVAL_STRINGL(EX_T(opline->result.u.var).var.ptr, Z_STRVAL_P(EX_T(opline->op1.u.var).str_offset.str)+EX_T(opline->op1.u.var).str_offset.offset, 1, 1);
+ SAVE_OPLINE();
+ value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+ if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) {
+ if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CV TSRMLS_CC)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zval *retval;
+
+ ALLOC_ZVAL(retval);
+ ZVAL_STRINGL(retval, Z_STRVAL_P(EX_T(opline->op1.var).str_offset.str)+EX_T(opline->op1.var).str_offset.offset, 1, 1);
+ INIT_PZVAL(retval);
+ AI_SET_PTR(&EX_T(opline->result.var), retval);
}
- } else if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, EG(uninitialized_zval_ptr));
- PZVAL_LOCK(EG(uninitialized_zval_ptr));
+ } else if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
+ }
+ } else if (IS_CV == IS_VAR && UNEXPECTED(*variable_ptr_ptr == &EG(error_zval))) {
+ if (0) {
+ zval_dtor(value);
+ }
+ if (RETURN_VALUE_USED(opline)) {
+ PZVAL_LOCK(&EG(uninitialized_zval));
+ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval));
}
} else {
- value = zend_assign_to_variable(variable_ptr_ptr, value, 0 TSRMLS_CC);
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, value);
+ if (IS_CV == IS_TMP_VAR) {
+ value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else if (IS_CV == IS_CONST) {
+ value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ } else {
+ value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC);
+ }
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(value);
+ AI_SET_PTR(&EX_T(opline->result.var), value);
}
}
/* zend_assign_to_variable() always takes care of op2, never free it! */
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zend_free_op free_op2;
zval **variable_ptr_ptr;
- zval **value_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC);
+ zval **value_ptr_ptr;
+
+ SAVE_OPLINE();
+ value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_CV == IS_VAR &&
value_ptr_ptr &&
!Z_ISREF_PP(value_ptr_ptr) &&
opline->extended_value == ZEND_RETURNS_FUNCTION &&
- !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+ !EX_T(opline->op2.var).var.fcall_returned_reference) {
if (free_op2.var == NULL) {
PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
}
zend_error(E_STRICT, "Only variables should be assigned by reference");
if (UNEXPECTED(EG(exception) != NULL)) {
- ZEND_VM_NEXT_OPCODE();
+ HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
PZVAL_LOCK(*value_ptr_ptr);
}
- if (IS_CV == IS_VAR && EX_T(opline->op1.u.var).var.ptr_ptr == &EX_T(opline->op1.u.var).var.ptr) {
+ if (IS_CV == IS_VAR && UNEXPECTED(EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr)) {
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
}
- variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
- if ((IS_CV == IS_VAR && !value_ptr_ptr) ||
- (IS_CV == IS_VAR && !variable_ptr_ptr)) {
+ variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) ||
+ (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
}
zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
@@ -29715,48 +36026,63 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
Z_DELREF_PP(variable_ptr_ptr);
}
- if (!RETURN_VALUE_UNUSED(&opline->result)) {
- AI_SET_PTR(EX_T(opline->result.u.var).var, *variable_ptr_ptr);
+ if (RETURN_VALUE_USED(opline)) {
PZVAL_LOCK(*variable_ptr_ptr);
+ AI_SET_PTR(&EX_T(opline->result.var), *variable_ptr_ptr);
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
zval *function_name;
char *function_name_strval;
int function_name_strlen;
+ SAVE_OPLINE();
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
- function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (IS_CV != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
function_name_strval = Z_STRVAL_P(function_name);
function_name_strlen = Z_STRLEN_P(function_name);
- EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (EXPECTED(EX(object) != NULL) &&
+ EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
+ EX(called_scope) = Z_OBJCE_P(EX(object));
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
- }
+ if (IS_CV != IS_CONST ||
+ (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+ zval *object = EX(object);
- EX(called_scope) = Z_OBJCE_P(EX(object));
+ if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(EX(fbc) == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(EX(object) == object)) {
+ CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+ }
+ }
} else {
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
@@ -29776,76 +36102,52 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
- int switch_expr_is_overloaded=0;
+ USE_OPLINE
+ SAVE_OPLINE();
if (IS_CV==IS_VAR) {
- if (EX_T(opline->op1.u.var).var.ptr_ptr) {
- PZVAL_LOCK(EX_T(opline->op1.u.var).var.ptr);
- } else {
- switch_expr_is_overloaded = 1;
- Z_ADDREF_P(EX_T(opline->op1.u.var).str_offset.str);
- }
+ PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
}
- is_equal_function(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC),
- _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC) TSRMLS_CC);
-
- if (switch_expr_is_overloaded) {
- /* We only free op1 if this is a string offset,
- * Since if it is a TMP_VAR, it'll be reused by
- * other CASE opcodes (whereas string offsets
- * are allocated at each get_zval_ptr())
- */
+ is_equal_function(&EX_T(opline->result.var).tmp_var,
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC),
+ _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC);
- EX_T(opline->op1.u.var).var.ptr_ptr = NULL;
- EX_T(opline->op1.u.var).var.ptr = NULL;
- }
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval *array_ptr = &EX_T(opline->result.u.var).tmp_var;
zval *expr_ptr;
- zval *offset=_get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- zval **expr_ptr_ptr = NULL;
+ SAVE_OPLINE();
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
+ zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
- if (opline->extended_value) {
- expr_ptr_ptr=_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+ if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) {
+ zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
+ }
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
expr_ptr = *expr_ptr_ptr;
+ Z_ADDREF_P(expr_ptr);
} else {
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- }
-#else
- expr_ptr=_get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
-#endif
-
- if (0) { /* temporary variable */
- zval *new_expr;
+ expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+ if (0) { /* temporary variable */
+ zval *new_expr;
- ALLOC_ZVAL(new_expr);
- INIT_PZVAL_COPY(new_expr, expr_ptr);
- expr_ptr = new_expr;
- } else {
-#if 0 || IS_CV == IS_VAR || IS_CV == IS_CV
- if (opline->extended_value) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr);
- expr_ptr = *expr_ptr_ptr;
- Z_ADDREF_P(expr_ptr);
- } else
-#endif
- if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
+ ALLOC_ZVAL(new_expr);
+ INIT_PZVAL_COPY(new_expr, expr_ptr);
+ expr_ptr = new_expr;
+ } else if (IS_CV == IS_CONST || PZVAL_IS_REF(expr_ptr)) {
zval *new_expr;
ALLOC_ZVAL(new_expr);
@@ -29856,20 +36158,37 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
Z_ADDREF_P(expr_ptr);
}
}
- if (offset) {
+
+ if (IS_CV != IS_UNUSED) {
+
+ zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
+ ulong hval;
+
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), zend_dval_to_lval(Z_DVAL_P(offset)), &expr_ptr, sizeof(zval *), NULL);
- break;
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
case IS_LONG:
case IS_BOOL:
- zend_hash_index_update(Z_ARRVAL_P(array_ptr), Z_LVAL_P(offset), &expr_ptr, sizeof(zval *), NULL);
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
+ }
+ }
+ zend_hash_quick_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(array_ptr), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL(EX_T(opline->result.var).tmp_var), "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
break;
default:
zend_error(E_WARNING, "Illegal offset type");
@@ -29879,21 +36198,22 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
}
} else {
- zend_hash_next_index_insert(Z_ARRVAL_P(array_ptr), &expr_ptr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(Z_ARRVAL(EX_T(opline->result.var).tmp_var), &expr_ptr, sizeof(zval *), NULL);
}
- if (opline->extended_value) {
+ if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) {
} else {
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- array_init(&EX_T(opline->result.u.var).tmp_var);
+ array_init(&EX_T(opline->result.var).tmp_var);
if (IS_CV == IS_UNUSED) {
ZEND_VM_NEXT_OPCODE();
#if 0 || IS_CV != IS_UNUSED
@@ -29905,15 +36225,18 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
+ zval **container;
zval *offset;
+ ulong hval;
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
SEPARATE_ZVAL_IF_NOT_REF(container);
}
- offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_CV != IS_VAR || container) {
switch (Z_TYPE_PP(container)) {
@@ -29922,37 +36245,40 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
switch (Z_TYPE_P(offset)) {
case IS_DOUBLE:
- zend_hash_index_del(ht, zend_dval_to_lval(Z_DVAL_P(offset)));
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ zend_hash_index_del(ht, hval);
break;
case IS_RESOURCE:
case IS_BOOL:
case IS_LONG:
- zend_hash_index_del(ht, Z_LVAL_P(offset));
+ hval = Z_LVAL_P(offset);
+ zend_hash_index_del(ht, hval);
break;
case IS_STRING:
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
Z_ADDREF_P(offset);
}
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
- zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
-
- for (ex = execute_data; ex; ex = ex->prev_execute_data) {
- if (ex->op_array && ex->symbol_table == ht) {
- int i;
-
- for (i = 0; i < ex->op_array->last_var; i++) {
- if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
- ex->CVs[i] = NULL;
- break;
- }
- }
- }
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_dim);
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
}
+ if (ht == &EG(symbol_table)) {
+ zend_delete_global_variable_ex(offset->value.str.val, offset->value.str.len, hval TSRMLS_CC);
+ } else {
+ zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval);
+ }
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ zval_ptr_dtor(&offset);
+ }
+ break;
+num_index_dim:
+ zend_hash_index_del(ht, hval);
if (IS_CV == IS_CV || IS_CV == IS_VAR) {
zval_ptr_dtor(&offset);
}
@@ -29968,7 +36294,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
break;
}
case IS_OBJECT:
- if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ if (UNEXPECTED(Z_OBJ_HT_P(*container)->unset_dimension == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
}
if (0) {
@@ -29992,15 +36318,20 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
+
+ zval **container;
+ zval *offset;
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_UNSET TSRMLS_CC);
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
if (IS_CV != IS_VAR || container) {
if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) {
@@ -30011,7 +36342,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
MAKE_REAL_ZVAL_PTR(offset);
}
if (Z_OBJ_HT_P(*container)->unset_property) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@@ -30027,137 +36358,149 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *opline = EX(opline);
+ USE_OPLINE
- zval **container = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC);
+ zval **container;
zval **value = NULL;
int result = 0;
+ ulong hval;
+ zval *offset;
- if (IS_CV != IS_VAR || container) {
+ SAVE_OPLINE();
+ container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC);
- zval *offset = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
+ offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
- if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
- HashTable *ht;
- int isset = 0;
+ if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) {
+ HashTable *ht;
+ int isset = 0;
- ht = Z_ARRVAL_PP(container);
+ ht = Z_ARRVAL_PP(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- if (zend_hash_index_find(ht, zend_dval_to_lval(Z_DVAL_P(offset)), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_RESOURCE:
- case IS_BOOL:
- case IS_LONG:
- if (zend_hash_index_find(ht, Z_LVAL_P(offset), (void **) &value) == SUCCESS) {
- isset = 1;
- }
- break;
- case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
- isset = 1;
+ switch (Z_TYPE_P(offset)) {
+ case IS_DOUBLE:
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ case IS_RESOURCE:
+ case IS_BOOL:
+ case IS_LONG:
+ hval = Z_LVAL_P(offset);
+num_index_prop:
+ if (zend_hash_index_find(ht, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_STRING:
+ if (IS_CV == IS_CONST) {
+ hval = Z_HASH_P(offset);
+ } else {
+ if (!prop_dim) {
+ ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
}
- break;
- case IS_NULL:
- if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
- isset = 1;
+ if (IS_INTERNED(Z_STRVAL_P(offset))) {
+ hval = INTERNED_HASH(Z_STRVAL_P(offset));
+ } else {
+ hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
}
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ }
+ if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ case IS_NULL:
+ if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
+ isset = 1;
+ }
+ break;
+ default:
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ break;
+ }
- break;
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_PP(value) == IS_NULL) {
+ result = 0;
+ } else {
+ result = isset;
}
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (isset && Z_TYPE_PP(value) == IS_NULL) {
- result = 0;
- } else {
- result = isset;
- }
- break;
- case ZEND_ISEMPTY:
- if (!isset || !i_zend_is_true(*value)) {
- result = 0;
- } else {
- result = 1;
- }
- break;
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (!isset || !i_zend_is_true(*value)) {
+ result = 0;
+ } else {
+ result = 1;
}
+ }
- } else if (Z_TYPE_PP(container) == IS_OBJECT) {
- if (0) {
- MAKE_REAL_ZVAL_PTR(offset);
- }
- if (prop_dim) {
- if (Z_OBJ_HT_P(*container)->has_property) {
- result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check property of non-object");
- result = 0;
- }
+ } else if (Z_TYPE_PP(container) == IS_OBJECT) {
+ if (0) {
+ MAKE_REAL_ZVAL_PTR(offset);
+ }
+ if (prop_dim) {
+ if (Z_OBJ_HT_P(*container)->has_property) {
+ result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC);
} else {
- if (Z_OBJ_HT_P(*container)->has_dimension) {
- result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value == ZEND_ISEMPTY) TSRMLS_CC);
- } else {
- zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
+ zend_error(E_NOTICE, "Trying to check property of non-object");
+ result = 0;
}
- if (0) {
- zval_ptr_dtor(&offset);
+ } else {
+ if (Z_OBJ_HT_P(*container)->has_dimension) {
+ result = Z_OBJ_HT_P(*container)->has_dimension(*container, offset, (opline->extended_value & ZEND_ISEMPTY) != 0 TSRMLS_CC);
} else {
-
+ zend_error(E_NOTICE, "Trying to check element of non-array");
+ result = 0;
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
- zval tmp;
+ }
+ if (0) {
+ zval_ptr_dtor(&offset);
+ } else {
- if (Z_TYPE_P(offset) != IS_LONG) {
- tmp = *offset;
+ }
+ } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ zval tmp;
+
+ if (Z_TYPE_P(offset) != IS_LONG) {
+ if (Z_TYPE_P(offset) <= IS_BOOL /* simple scalar types */
+ || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
+ && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
+ ZVAL_COPY_VALUE(&tmp, offset);
zval_copy_ctor(&tmp);
convert_to_long(&tmp);
offset = &tmp;
+ } else {
+ /* can not be converted to proper offset, return "not set" */
+ result = 0;
}
- if (Z_TYPE_P(offset) == IS_LONG) {
- switch (opline->extended_value) {
- case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
- result = 1;
- }
- break;
- case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
- result = 1;
- }
- break;
+ }
+ if (Z_TYPE_P(offset) == IS_LONG) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ result = 1;
+ }
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ result = 1;
}
}
+ }
- } else {
+ } else {
- }
}
- Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL;
-
- switch (opline->extended_value) {
- case ZEND_ISSET:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = result;
- break;
- case ZEND_ISEMPTY:
- Z_LVAL(EX_T(opline->result.u.var).tmp_var) = !result;
- break;
+ Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL;
+ if (opline->extended_value & ZEND_ISSET) {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = result;
+ } else {
+ Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
+ CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -30173,7 +36516,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OP
static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);
+ zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);
}
@@ -31431,55 +37774,55 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_BRK_SPEC_TMP_HANDLER,
- ZEND_BRK_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_BRK_SPEC_TMP_HANDLER,
- ZEND_BRK_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_BRK_SPEC_TMP_HANDLER,
- ZEND_BRK_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_BRK_SPEC_TMP_HANDLER,
- ZEND_BRK_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_BRK_SPEC_TMP_HANDLER,
- ZEND_BRK_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_CONT_SPEC_TMP_HANDLER,
- ZEND_CONT_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_CONT_SPEC_TMP_HANDLER,
- ZEND_CONT_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_CONT_SPEC_TMP_HANDLER,
- ZEND_CONT_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_CONT_SPEC_TMP_HANDLER,
- ZEND_CONT_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_CONT_SPEC_TMP_HANDLER,
- ZEND_CONT_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_BOOL_SPEC_CONST_HANDLER,
ZEND_BOOL_SPEC_CONST_HANDLER,
ZEND_BOOL_SPEC_CONST_HANDLER,
@@ -31815,21 +38158,21 @@ void zend_init_opcodes_handlers(void)
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
- ZEND_SEND_VAL_SPEC_VAR_HANDLER,
- ZEND_SEND_VAL_SPEC_VAR_HANDLER,
- ZEND_SEND_VAL_SPEC_VAR_HANDLER,
- ZEND_SEND_VAL_SPEC_VAR_HANDLER,
- ZEND_SEND_VAL_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_SEND_VAL_SPEC_CV_HANDLER,
- ZEND_SEND_VAL_SPEC_CV_HANDLER,
- ZEND_SEND_VAL_SPEC_CV_HANDLER,
- ZEND_SEND_VAL_SPEC_CV_HANDLER,
- ZEND_SEND_VAL_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -31940,11 +38283,11 @@ void zend_init_opcodes_handlers(void)
ZEND_FREE_SPEC_TMP_HANDLER,
ZEND_FREE_SPEC_TMP_HANDLER,
ZEND_FREE_SPEC_TMP_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_FREE_SPEC_VAR_HANDLER,
+ ZEND_FREE_SPEC_VAR_HANDLER,
+ ZEND_FREE_SPEC_VAR_HANDLER,
+ ZEND_FREE_SPEC_VAR_HANDLER,
+ ZEND_FREE_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32030,31 +38373,31 @@ void zend_init_opcodes_handlers(void)
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMP_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMP_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMP_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMP_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMP_HANDLER,
- ZEND_UNSET_VAR_SPEC_VAR_HANDLER,
- ZEND_UNSET_VAR_SPEC_VAR_HANDLER,
- ZEND_UNSET_VAR_SPEC_VAR_HANDLER,
- ZEND_UNSET_VAR_SPEC_VAR_HANDLER,
- ZEND_UNSET_VAR_SPEC_VAR_HANDLER,
+ ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER,
+ ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER,
+ ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER,
+ ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_HANDLER,
+ ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER,
+ ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32180,31 +38523,31 @@ void zend_init_opcodes_handlers(void)
ZEND_EXIT_SPEC_CV_HANDLER,
ZEND_EXIT_SPEC_CV_HANDLER,
ZEND_EXIT_SPEC_CV_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_HANDLER,
- ZEND_FETCH_R_SPEC_TMP_HANDLER,
- ZEND_FETCH_R_SPEC_TMP_HANDLER,
- ZEND_FETCH_R_SPEC_TMP_HANDLER,
- ZEND_FETCH_R_SPEC_TMP_HANDLER,
- ZEND_FETCH_R_SPEC_TMP_HANDLER,
- ZEND_FETCH_R_SPEC_VAR_HANDLER,
- ZEND_FETCH_R_SPEC_VAR_HANDLER,
- ZEND_FETCH_R_SPEC_VAR_HANDLER,
- ZEND_FETCH_R_SPEC_VAR_HANDLER,
- ZEND_FETCH_R_SPEC_VAR_HANDLER,
+ ZEND_FETCH_R_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_TMP_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_R_SPEC_TMP_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_VAR_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_VAR_VAR_HANDLER,
+ ZEND_FETCH_R_SPEC_VAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_CV_HANDLER,
- ZEND_FETCH_R_SPEC_CV_HANDLER,
- ZEND_FETCH_R_SPEC_CV_HANDLER,
- ZEND_FETCH_R_SPEC_CV_HANDLER,
- ZEND_FETCH_R_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_R_SPEC_CV_VAR_HANDLER,
+ ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32255,31 +38598,31 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_R_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_HANDLER,
- ZEND_FETCH_W_SPEC_TMP_HANDLER,
- ZEND_FETCH_W_SPEC_TMP_HANDLER,
- ZEND_FETCH_W_SPEC_TMP_HANDLER,
- ZEND_FETCH_W_SPEC_TMP_HANDLER,
- ZEND_FETCH_W_SPEC_TMP_HANDLER,
- ZEND_FETCH_W_SPEC_VAR_HANDLER,
- ZEND_FETCH_W_SPEC_VAR_HANDLER,
- ZEND_FETCH_W_SPEC_VAR_HANDLER,
- ZEND_FETCH_W_SPEC_VAR_HANDLER,
- ZEND_FETCH_W_SPEC_VAR_HANDLER,
+ ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_TMP_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_W_SPEC_TMP_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_VAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_VAR_VAR_HANDLER,
+ ZEND_FETCH_W_SPEC_VAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_CV_HANDLER,
- ZEND_FETCH_W_SPEC_CV_HANDLER,
- ZEND_FETCH_W_SPEC_CV_HANDLER,
- ZEND_FETCH_W_SPEC_CV_HANDLER,
- ZEND_FETCH_W_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_W_SPEC_CV_VAR_HANDLER,
+ ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32330,31 +38673,31 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_HANDLER,
- ZEND_FETCH_RW_SPEC_TMP_HANDLER,
- ZEND_FETCH_RW_SPEC_TMP_HANDLER,
- ZEND_FETCH_RW_SPEC_TMP_HANDLER,
- ZEND_FETCH_RW_SPEC_TMP_HANDLER,
- ZEND_FETCH_RW_SPEC_TMP_HANDLER,
- ZEND_FETCH_RW_SPEC_VAR_HANDLER,
- ZEND_FETCH_RW_SPEC_VAR_HANDLER,
- ZEND_FETCH_RW_SPEC_VAR_HANDLER,
- ZEND_FETCH_RW_SPEC_VAR_HANDLER,
- ZEND_FETCH_RW_SPEC_VAR_HANDLER,
+ ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_TMP_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_RW_SPEC_TMP_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_VAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_VAR_VAR_HANDLER,
+ ZEND_FETCH_RW_SPEC_VAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER,
+ ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32405,31 +38748,31 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_HANDLER,
- ZEND_FETCH_IS_SPEC_TMP_HANDLER,
- ZEND_FETCH_IS_SPEC_TMP_HANDLER,
- ZEND_FETCH_IS_SPEC_TMP_HANDLER,
- ZEND_FETCH_IS_SPEC_TMP_HANDLER,
- ZEND_FETCH_IS_SPEC_TMP_HANDLER,
- ZEND_FETCH_IS_SPEC_VAR_HANDLER,
- ZEND_FETCH_IS_SPEC_VAR_HANDLER,
- ZEND_FETCH_IS_SPEC_VAR_HANDLER,
- ZEND_FETCH_IS_SPEC_VAR_HANDLER,
- ZEND_FETCH_IS_SPEC_VAR_HANDLER,
+ ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_TMP_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_IS_SPEC_TMP_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_VAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_VAR_VAR_HANDLER,
+ ZEND_FETCH_IS_SPEC_VAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER,
+ ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32480,31 +38823,31 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMP_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMP_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMP_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMP_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMP_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_VAR_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_VAR_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_VAR_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_VAR_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_VAR_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER,
+ ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32555,31 +38898,31 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMP_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMP_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMP_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMP_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMP_HANDLER,
- ZEND_FETCH_UNSET_SPEC_VAR_HANDLER,
- ZEND_FETCH_UNSET_SPEC_VAR_HANDLER,
- ZEND_FETCH_UNSET_SPEC_VAR_HANDLER,
- ZEND_FETCH_UNSET_SPEC_VAR_HANDLER,
- ZEND_FETCH_UNSET_SPEC_VAR_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER,
+ ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32805,31 +39148,31 @@ void zend_init_opcodes_handlers(void)
ZEND_EXT_NOP_SPEC_HANDLER,
ZEND_EXT_NOP_SPEC_HANDLER,
ZEND_EXT_NOP_SPEC_HANDLER,
- ZEND_TICKS_SPEC_CONST_HANDLER,
- ZEND_TICKS_SPEC_CONST_HANDLER,
- ZEND_TICKS_SPEC_CONST_HANDLER,
- ZEND_TICKS_SPEC_CONST_HANDLER,
- ZEND_TICKS_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
+ ZEND_TICKS_SPEC_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -32859,27 +39202,27 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CATCH_SPEC_CV_HANDLER,
+ ZEND_CATCH_SPEC_CONST_CV_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CATCH_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CATCH_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CATCH_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CATCH_SPEC_CV_HANDLER,
ZEND_THROW_SPEC_CONST_HANDLER,
ZEND_THROW_SPEC_CONST_HANDLER,
ZEND_THROW_SPEC_CONST_HANDLER,
@@ -32955,31 +39298,31 @@ void zend_init_opcodes_handlers(void)
ZEND_CLONE_SPEC_CV_HANDLER,
ZEND_CLONE_SPEC_CV_HANDLER,
ZEND_CLONE_SPEC_CV_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
+ ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -33030,31 +39373,31 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -34005,10 +40348,95 @@ void zend_init_opcodes_handlers(void)
ZEND_JMP_SET_SPEC_CV_HANDLER,
ZEND_JMP_SET_SPEC_CV_HANDLER,
ZEND_JMP_SET_SPEC_CV_HANDLER,
- ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_ADD_TRAIT_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_BIND_TRAITS_SPEC_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -34020,16 +40448,56 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+ ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+ ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;
@@ -34055,7 +40523,7 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o
_UNUSED_CODE, /* 15 */
_CV_CODE /* 16 = IS_CV */
};
- return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]];
+ return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];
}
ZEND_API void zend_vm_set_opcode_handler(zend_op* op)
diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl
index e5a143eaa7..6d1b2e70e7 100644
--- a/Zend/zend_vm_execute.skl
+++ b/Zend/zend_vm_execute.skl
@@ -2,6 +2,7 @@
ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)
{
+ DCL_OPLINE
zend_execute_data *execute_data;
zend_bool nested = 0;
{%HELPER_VARS%}
@@ -36,29 +37,31 @@ zend_vm_enter:
EX(nested) = nested;
nested = 1;
- if (op_array->start_op) {
- ZEND_VM_SET_OPCODE(op_array->start_op);
- } else {
- ZEND_VM_SET_OPCODE(op_array->opcodes);
+ LOAD_REGS();
+
+ if (!op_array->run_time_cache && op_array->last_cache_slot) {
+ op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
}
if (op_array->this_var != -1 && EG(This)) {
Z_ADDREF_P(EG(This)); /* For $this pointer */
if (!EG(active_symbol_table)) {
- EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
- *EX(CVs)[op_array->this_var] = EG(This);
+ EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var);
+ *EX_CV(op_array->this_var) = EG(This);
} else {
- if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
+ if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) {
Z_DELREF_P(EG(This));
}
}
}
+ EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
EG(opline_ptr) = &EX(opline);
+ LOAD_OPLINE();
EX(function_state).function = (zend_function *) op_array;
EX(function_state).arguments = NULL;
-
+
while (1) {
{%ZEND_VM_CONTINUE_LABEL%}
#ifdef ZEND_WIN32
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php
index 2fff1a9c52..fde1baf90b 100644
--- a/Zend/zend_vm_gen.php
+++ b/Zend/zend_vm_gen.php
@@ -82,7 +82,7 @@ $typecode = array(
);
$op1_type = array(
- "ANY" => "opline->op1.op_type",
+ "ANY" => "opline->op1_type",
"TMP" => "IS_TMP_VAR",
"VAR" => "IS_VAR",
"CONST" => "IS_CONST",
@@ -91,7 +91,7 @@ $op1_type = array(
);
$op2_type = array(
- "ANY" => "opline->op2.op_type",
+ "ANY" => "opline->op2_type",
"TMP" => "IS_TMP_VAR",
"VAR" => "IS_VAR",
"CONST" => "IS_CONST",
@@ -118,75 +118,75 @@ $op2_free = array(
);
$op1_get_zval_ptr = array(
- "ANY" => "get_zval_ptr(&opline->op1, EX(Ts), &free_op1, \\1)",
- "TMP" => "_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC)",
- "VAR" => "_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC)",
- "CONST" => "&opline->op1.u.constant",
+ "ANY" => "get_zval_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)",
+ "TMP" => "_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)",
+ "CONST" => "opline->op1.zv",
"UNUSED" => "NULL",
- "CV" => "_get_zval_ptr_cv(&opline->op1, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)",
);
$op2_get_zval_ptr = array(
- "ANY" => "get_zval_ptr(&opline->op2, EX(Ts), &free_op2, \\1)",
- "TMP" => "_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC)",
- "VAR" => "_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC)",
- "CONST" => "&opline->op2.u.constant",
+ "ANY" => "get_zval_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)",
+ "TMP" => "_get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)",
+ "CONST" => "opline->op2.zv",
"UNUSED" => "NULL",
- "CV" => "_get_zval_ptr_cv(&opline->op2, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)",
);
$op1_get_zval_ptr_ptr = array(
- "ANY" => "get_zval_ptr_ptr(&opline->op1, EX(Ts), &free_op1, \\1)",
+ "ANY" => "get_zval_ptr_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)",
"TMP" => "NULL",
- "VAR" => "_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "NULL",
- "CV" => "_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)",
);
$op2_get_zval_ptr_ptr = array(
- "ANY" => "get_zval_ptr_ptr(&opline->op2, EX(Ts), &free_op2, \\1)",
+ "ANY" => "get_zval_ptr_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)",
"TMP" => "NULL",
- "VAR" => "_get_zval_ptr_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "NULL",
- "CV" => "_get_zval_ptr_ptr_cv(&opline->op2, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)",
);
$op1_get_obj_zval_ptr = array(
- "ANY" => "get_obj_zval_ptr(&opline->op1, EX(Ts), &free_op1, \\1)",
- "TMP" => "_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC)",
- "VAR" => "_get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC)",
- "CONST" => "&opline->op1.u.constant",
+ "ANY" => "get_obj_zval_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)",
+ "TMP" => "_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)",
+ "CONST" => "opline->op1.zv",
"UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)",
- "CV" => "_get_zval_ptr_cv(&opline->op1, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)",
);
$op2_get_obj_zval_ptr = array(
- "ANY" => "get_obj_zval_ptr(&opline->op2, EX(Ts), &free_op2, \\1)",
- "TMP" => "_get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC)",
- "VAR" => "_get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC)",
- "CONST" => "&opline->op2.u.constant",
+ "ANY" => "get_obj_zval_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)",
+ "TMP" => "_get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)",
+ "CONST" => "opline->op2.zv",
"UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)",
- "CV" => "_get_zval_ptr_cv(&opline->op2, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)",
);
$op1_get_obj_zval_ptr_ptr = array(
- "ANY" => "get_obj_zval_ptr_ptr(&opline->op1, EX(Ts), &free_op1, \\1)",
+ "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)",
"TMP" => "NULL",
- "VAR" => "_get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "_get_obj_zval_ptr_ptr_unused(TSRMLS_C)",
- "CV" => "_get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)",
);
$op2_get_obj_zval_ptr_ptr = array(
- "ANY" => "get_obj_zval_ptr_ptr(&opline->op2, EX(Ts), &free_op2, \\1)",
+ "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)",
"TMP" => "NULL",
- "VAR" => "_get_zval_ptr_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC)",
+ "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)",
"CONST" => "NULL",
"UNUSED" => "_get_obj_zval_ptr_ptr_unused(TSRMLS_C)",
- "CV" => "_get_zval_ptr_ptr_cv(&opline->op2, EX(Ts), \\1 TSRMLS_CC)",
+ "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)",
);
$op1_is_tmp_free = array(
@@ -504,7 +504,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno)
}
break;
case ZEND_VM_KIND_GOTO:
- out($f,$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER:\n");
+ out($f,$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER: ZEND_VM_GUARD(".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].");\n");
break;
}
@@ -694,7 +694,7 @@ function gen_null_handler($f) {
$done = 1;
out($f,"static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
out($f,"{\n");
- out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);\n");
+ out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
out($f,"}\n\n");
}
}
@@ -768,11 +768,11 @@ function gen_executor_code($f, $spec, $kind, $prolog) {
break;
case ZEND_VM_KIND_SWITCH:
out($f,"default:\n");
- out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);\n");
+ out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,"ZEND_NULL_HANDLER:\n");
- out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", EX(opline)->opcode, EX(opline)->op1.op_type, EX(opline)->op2.op_type);\n");
+ out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
break;
}
}
@@ -800,18 +800,60 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op);\n\n");
switch ($kind) {
case ZEND_VM_KIND_CALL:
- out($f,"\n");
- out($f,"#define ZEND_VM_CONTINUE() return 0\n");
- out($f,"#define ZEND_VM_RETURN() return 1\n");
- out($f,"#define ZEND_VM_ENTER() return 2\n");
- out($f,"#define ZEND_VM_LEAVE() return 3\n");
+ out($f,"\n");
+ out($f,"#undef OPLINE\n");
+ out($f,"#undef DCL_OPLINE\n");
+ out($f,"#undef USE_OPLINE\n");
+ out($f,"#undef LOAD_OPLINE\n");
+ out($f,"#undef SAVE_OPLINE\n");
+ out($f,"#define OPLINE EX(opline)\n");
+ out($f,"#define DCL_OPLINE\n");
+ out($f,"#define USE_OPLINE zend_op *opline = EX(opline);\n");
+ out($f,"#define LOAD_OPLINE()\n");
+ out($f,"#define SAVE_OPLINE()\n");
+ out($f,"#undef CHECK_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION_LEAVE\n");
+ out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n");
+ out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
+ out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
+ out($f,"#define LOAD_REGS()\n");
+ out($f,"#define ZEND_VM_CONTINUE() return 0\n");
+ out($f,"#define ZEND_VM_RETURN() return 1\n");
+ out($f,"#define ZEND_VM_ENTER() return 2\n");
+ out($f,"#define ZEND_VM_LEAVE() return 3\n");
out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n");
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
out($f,"#undef EX\n");
out($f,"#define EX(element) execute_data->element\n\n");
+ out($f,"#undef EX_CV\n");
+ out($f,"#define EX_CV(var) EX(CVs)[var]\n");
+ out($f,"#undef EX_CVs\n");
+ out($f,"#define EX_CVs() EX(CVs)\n");
+ out($f,"#undef EX_T\n");
+ out($f,"#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))\n");
+ out($f,"#undef EX_Ts\n");
+ out($f,"#define EX_Ts() EX(Ts)\n\n");
break;
case ZEND_VM_KIND_SWITCH:
out($f,"\n");
+ out($f,"#undef OPLINE\n");
+ out($f,"#undef DCL_OPLINE\n");
+ out($f,"#undef USE_OPLINE\n");
+ out($f,"#undef LOAD_OPLINE\n");
+ out($f,"#undef SAVE_OPLINE\n");
+ out($f,"#define OPLINE opline\n");
+ out($f,"#define DCL_OPLINE zend_op *opline;\n");
+ out($f,"#define USE_OPLINE\n");
+ out($f,"#define LOAD_OPLINE() opline = EX(opline)\n");
+ out($f,"#define SAVE_OPLINE() EX(opline) = opline\n");
+ out($f,"#undef CHECK_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION_LEAVE\n");
+ out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n");
+ out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
+ out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
+ out($f,"#define LOAD_REGS() do {Ts = EX(Ts); CVs = EX(CVs);} while (0)\n");
out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n");
out($f,"#define ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\n");
@@ -820,10 +862,35 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
out($f,"#undef EX\n");
out($f,"#define EX(element) execute_data->element\n\n");
+ out($f,"#undef EX_CV\n");
+ out($f,"#define EX_CV(var) CVs[var]\n");
+ out($f,"#undef EX_CVs\n");
+ out($f,"#define EX_CVs() CVs\n");
+ out($f,"#undef EX_T\n");
+ out($f,"#define EX_T(offset) T(offset)\n");
+ out($f,"#undef EX_Ts\n");
+ out($f,"#define EX_Ts() Ts\n\n");
break;
case ZEND_VM_KIND_GOTO:
out($f,"\n");
- out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(EX(opline)->handler)\n");
+ out($f,"#undef OPLINE\n");
+ out($f,"#undef DCL_OPLINE\n");
+ out($f,"#undef USE_OPLINE\n");
+ out($f,"#undef LOAD_OPLINE\n");
+ out($f,"#undef SAVE_OPLINE\n");
+ out($f,"#define OPLINE opline\n");
+ out($f,"#define DCL_OPLINE zend_op *opline;\n");
+ out($f,"#define USE_OPLINE\n");
+ out($f,"#define LOAD_OPLINE() opline = EX(opline)\n");
+ out($f,"#define SAVE_OPLINE() EX(opline) = opline\n");
+ out($f,"#undef CHECK_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION_LEAVE\n");
+ out($f,"#define CHECK_EXCEPTION() if (UNEXPECTED(EG(exception) != NULL)) goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
+ out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
+ out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n");
+ out($f,"#define LOAD_REGS() do {Ts = EX(Ts); CVs = EX(CVs);} while (0)\n");
+ out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n");
out($f,"#define ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\n");
out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
@@ -831,6 +898,14 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n");
out($f,"#undef EX\n");
out($f,"#define EX(element) execute_data->element\n\n");
+ out($f,"#undef EX_CV\n");
+ out($f,"#define EX_CV(var) CVs[var]\n");
+ out($f,"#undef EX_CVs\n");
+ out($f,"#define EX_CVs() CVs\n");
+ out($f,"#undef EX_T\n");
+ out($f,"#define EX_T(offset) T(offset)\n\n");
+ out($f,"#undef EX_Ts\n");
+ out($f,"#define EX_Ts() Ts\n\n");
break;
}
break;
@@ -839,6 +914,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
break;
case "HELPER_VARS":
if ($kind != ZEND_VM_KIND_CALL) {
+ out($f,$m[1]."temp_variable *Ts;\n");
+ out($f,$m[1]."zval ***CVs;\n");
if ($kind == ZEND_VM_KIND_SWITCH) {
out($f,$m[1]."opcode_handler_t dispatch_handler;\n");
}
@@ -888,13 +965,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
// Emit code that dispatches to opcode handler
switch ($kind) {
case ZEND_VM_KIND_CALL:
- out($f, $m[1]."if ((ret = EX(opline)->handler(execute_data TSRMLS_CC)) > 0)".$m[3]."\n");
+ out($f, $m[1]."if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0)".$m[3]."\n");
break;
case ZEND_VM_KIND_SWITCH:
- out($f, $m[1]."dispatch_handler = EX(opline)->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)dispatch_handler)".$m[3]."\n");
+ out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)dispatch_handler)".$m[3]."\n");
break;
case ZEND_VM_KIND_GOTO:
- out($f, $m[1]."goto *(void**)(EX(opline)->handler);".$m[3]."\n");
+ out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n");
break;
}
break;
@@ -1131,22 +1208,23 @@ function gen_vm($def, $skel) {
// Insert header
out($f, $GLOBALS['header_text']);
-
+
// Suppress free_op1 warnings on Windows
out($f, "#ifdef ZEND_WIN32\n# pragma warning(once : 4101)\n#endif\n");
-
+
// Support for ZEND_USER_OPCODE
- out($f, "static user_opcode_handler_t zend_user_opcode_handlers[256] = {");
+ out($f, "static user_opcode_handler_t zend_user_opcode_handlers[256] = {\n");
for ($i = 0; $i < 255; ++$i) {
- out($f, "(user_opcode_handler_t)NULL,");
+ out($f, "\t(user_opcode_handler_t)NULL,\n");
}
- out($f, "(user_opcode_handler_t)NULL};\n\n");
+ out($f, "\t(user_opcode_handler_t)NULL\n};\n\n");
out($f, "static zend_uchar zend_user_opcodes[256] = {");
for ($i = 0; $i < 255; ++$i) {
+ if ($i % 16 == 1) out($f, "\n\t");
out($f, "$i,");
}
- out($f, "255};\n\n");
+ out($f, "255\n};\n\n");
// Generate specialized executor
gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_KIND, "execute", "zend_init_opcodes_handlers", 0);
@@ -1156,6 +1234,12 @@ function gen_vm($def, $skel) {
out($f,"\n/* Old executor */\n\n");
out($f,"#undef EX\n");
out($f,"#define EX(element) execute_data.element\n\n");
+ out($f,"#undef EX_CV\n");
+ out($f,"#define EX_CV(var) EX(CVs)[var]\n");
+ out($f,"#undef EX_CVs\n");
+ out($f,"#define EX_CVs() EX(CVs)\n");
+ out($f,"#undef EX_T\n");
+ out($f,"#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))\n\n");
out($f,"#undef ZEND_VM_CONTINUE\n\n");
out($f,"#undef ZEND_VM_RETURN\n\n");
out($f,"#undef ZEND_VM_ENTER\n\n");
@@ -1195,7 +1279,7 @@ function gen_vm($def, $skel) {
out($f, "\t\t\t_UNUSED_CODE, /* 15 */\n");
out($f, "\t\t\t_CV_CODE /* 16 = IS_CV */\n");
out($f, "\t\t};\n");
- out($f, "\t\treturn zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]];\n");
+ out($f, "\t\treturn zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];\n");
if (ZEND_VM_OLD_EXECUTOR) {
out($f, "\t}\n");
}
@@ -1212,8 +1296,30 @@ function gen_vm($def, $skel) {
if (count($export) > 0 &&
!ZEND_VM_OLD_EXECUTOR &&
ZEND_VM_KIND != ZEND_VM_KIND_CALL) {
+ out($f,"#undef OPLINE\n");
+ out($f,"#undef DCL_OPLINE\n");
+ out($f,"#undef USE_OPLINE\n");
+ out($f,"#undef LOAD_OPLINE\n");
+ out($f,"#undef SAVE_OPLINE\n");
+ out($f,"#define OPLINE EX(opline)\n");
+ out($f,"#define DCL_OPLINE\n");
+ out($f,"#define USE_OPLINE zend_op *opline = EX(opline);\n");
+ out($f,"#define LOAD_OPLINE()\n");
+ out($f,"#define SAVE_OPLINE()\n");
+ out($f,"#undef CHECK_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION\n");
+ out($f,"#undef HANDLE_EXCEPTION_LEAVE\n");
+ out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n");
+ out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
+ out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
out($f,"#undef EX\n");
out($f,"#define EX(element) execute_data->element\n\n");
+ out($f,"#undef EX_CV\n");
+ out($f,"#define EX_CV(var) EX(CVs)[var]\n");
+ out($f,"#undef EX_CVs\n");
+ out($f,"#define EX_CVs() EX(CVs)\n");
+ out($f,"#undef EX_T\n");
+ out($f,"#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))\n\n");
out($f,"#undef ZEND_VM_CONTINUE\n");
out($f,"#undef ZEND_VM_RETURN\n");
out($f,"#undef ZEND_VM_ENTER\n");
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 5786fd7e24..680778c2a2 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -129,6 +129,7 @@
#define ZEND_THROW 108
#define ZEND_FETCH_CLASS 109
#define ZEND_CLONE 110
+#define ZEND_RETURN_BY_REF 111
#define ZEND_INIT_METHOD_CALL 112
#define ZEND_INIT_STATIC_METHOD_CALL 113
#define ZEND_ISSET_ISEMPTY_VAR 114
@@ -153,3 +154,8 @@
#define ZEND_USER_OPCODE 150
#define ZEND_JMP_SET 152
#define ZEND_DECLARE_LAMBDA_FUNCTION 153
+#define ZEND_ADD_TRAIT 154
+#define ZEND_BIND_TRAITS 155
+#define ZEND_SEPARATE 156
+#define ZEND_QM_ASSIGN_VAR 157
+#define ZEND_JMP_SET_VAR 158
diff --git a/acconfig.h.in b/acconfig.h.in
deleted file mode 100644
index f87979c2fd..0000000000
--- a/acconfig.h.in
+++ /dev/null
@@ -1 +0,0 @@
-/* Leave this file alone */
diff --git a/acinclude.m4 b/acinclude.m4
index ddf7285783..adb9599ce4 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -194,7 +194,7 @@ dnl the path is interpreted relative to the top build-directory.
dnl
dnl which array to append to?
AC_DEFUN([PHP_ADD_SOURCES],[
- PHP_ADD_SOURCES_X($1, $2, $3, ifelse($4,cli,PHP_CLI_OBJS,ifelse($4,sapi,PHP_SAPI_OBJS,PHP_GLOBAL_OBJS)))
+ PHP_ADD_SOURCES_X($1, $2, $3, ifelse($4,sapi,PHP_SAPI_OBJS,PHP_GLOBAL_OBJS))
])
dnl
@@ -762,6 +762,7 @@ AC_DEFUN([PHP_REQUIRE_CXX],[
if test -z "$php_cxx_done"; then
AC_PROG_CXX
AC_PROG_CXXCPP
+ PHP_ADD_LIBRARY(stdc++)
php_cxx_done=yes
fi
])
@@ -772,7 +773,7 @@ dnl
AC_DEFUN([PHP_BUILD_SHARED],[
PHP_BUILD_PROGRAM
OVERALL_TARGET=libphp[]$PHP_MAJOR_VERSION[.la]
- php_build_target=shared
+ php_sapi_module=shared
php_c_pre=$shared_c_pre
php_c_meta=$shared_c_meta
@@ -789,7 +790,7 @@ dnl
AC_DEFUN([PHP_BUILD_STATIC],[
PHP_BUILD_PROGRAM
OVERALL_TARGET=libphp[]$PHP_MAJOR_VERSION[.la]
- php_build_target=static
+ php_sapi_module=static
])
dnl
@@ -798,14 +799,13 @@ dnl
AC_DEFUN([PHP_BUILD_BUNDLE],[
PHP_BUILD_PROGRAM
OVERALL_TARGET=libs/libphp[]$PHP_MAJOR_VERSION[.bundle]
- php_build_target=static
+ php_sapi_module=static
])
dnl
dnl PHP_BUILD_PROGRAM
dnl
AC_DEFUN([PHP_BUILD_PROGRAM],[
- OVERALL_TARGET=[]ifelse($1,,php,$1)
php_c_pre='$(LIBTOOL) --mode=compile $(CC)'
php_c_meta='$(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS)'
php_c_post=
@@ -826,8 +826,6 @@ AC_DEFUN([PHP_BUILD_PROGRAM],[
shared_cxx_meta='$(COMMON_FLAGS) $(CXXFLAGS_CLEAN) $(EXTRA_CXXFLAGS) '$pic_setting
shared_cxx_post=
shared_lo=lo
-
- php_build_target=program
])
dnl
@@ -873,32 +871,45 @@ EOF
dnl
dnl PHP_SELECT_SAPI(name, type[, sources [, extra-cflags [, build-target]]])
dnl
-dnl Selects the SAPI name and type (static, shared, programm)
+dnl Selects the SAPI name and type (static, shared, bundle, program)
dnl and optionally also the source-files for the SAPI-specific
dnl objects.
dnl
AC_DEFUN([PHP_SELECT_SAPI],[
- if test "$PHP_SAPI" != "default"; then
-AC_MSG_ERROR([
+ if test "$2" = "program"; then
+ PHP_BINARIES="$PHP_BINARIES $1"
+ elif test "$PHP_SAPI" != "none"; then
+ AC_MSG_ERROR([
+--------------------------------------------------------------------+
| *** ATTENTION *** |
| |
| You've configured multiple SAPIs to be build. You can build only |
-| one SAPI module and CLI binary at the same time. |
+| one SAPI module plus CGI, CLI and FPM binaries at the same time. |
+--------------------------------------------------------------------+
])
- fi
+ else
+ PHP_SAPI=$1
+ fi
- PHP_SAPI=$1
-
- case "$2" in
- static[)] PHP_BUILD_STATIC;;
- shared[)] PHP_BUILD_SHARED;;
- bundle[)] PHP_BUILD_BUNDLE;;
- program[)] PHP_BUILD_PROGRAM($5);;
- esac
-
- ifelse($3,,,[PHP_ADD_SOURCES([sapi/$1],[$3],[$4],[sapi])])
+ PHP_ADD_BUILD_DIR([sapi/$1])
+
+ PHP_INSTALLED_SAPIS="$PHP_INSTALLED_SAPIS $1"
+
+ ifelse($2,program,[
+ PHP_BUILD_PROGRAM
+ install_binaries="install-binaries"
+ install_binary_targets="$install_binary_targets install-$1"
+ PHP_SUBST(PHP_[]translit($1,a-z0-9-,A-Z0-9_)[]_OBJS)
+ ifelse($3,,,[PHP_ADD_SOURCES_X([sapi/$1],[$3],[$4],PHP_[]translit($1,a-z0-9-,A-Z0-9_)[]_OBJS)])
+ ],[
+ case "$2" in
+ static[)] PHP_BUILD_STATIC;;
+ shared[)] PHP_BUILD_SHARED;;
+ bundle[)] PHP_BUILD_BUNDLE;;
+ esac
+ install_sapi="install-sapi"
+ ifelse($3,,,[PHP_ADD_SOURCES([sapi/$1],[$3],[$4],[sapi])])
+ ])
])
dnl deprecated
@@ -2672,19 +2683,19 @@ EOF
CONFIGURE_COMMAND="$CONFIGURE_COMMAND [$]0"
fi
for arg in $ac_configure_args; do
- if test `expr -- $arg : "'.*"` = 0; then
- if test `expr -- $arg : "--.*"` = 0; then
- break;
- fi
- echo "'[$]arg' \\" >> $1
- CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS '[$]arg'"
- else
- if test `expr -- $arg : "'--.*"` = 0; then
- break;
- fi
- echo "[$]arg \\" >> $1
- CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS [$]arg"
- fi
+ if test `expr -- $arg : "'.*"` = 0; then
+ if test `expr -- $arg : "--.*"` = 0; then
+ break;
+ fi
+ echo "'[$]arg' \\" >> $1
+ CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS '[$]arg'"
+ else
+ if test `expr -- $arg : "'--.*"` = 0; then
+ break;
+ fi
+ echo "[$]arg \\" >> $1
+ CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS [$]arg"
+ fi
done
echo '"[$]@"' >> $1
chmod +x $1
@@ -2752,17 +2763,17 @@ dnl
dnl PHP_CHECK_PDO_INCLUDES([found [, not-found]])
dnl
AC_DEFUN([PHP_CHECK_PDO_INCLUDES],[
- AC_CACHE_CHECK([for PDO includes], pdo_inc_path, [
+ AC_CACHE_CHECK([for PDO includes], pdo_cv_inc_path, [
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
fi
])
- if test -n "$pdo_inc_path"; then
+ if test -n "$pdo_cv_inc_path"; then
ifelse([$1],[],:,[$1])
else
ifelse([$2],[],[AC_MSG_ERROR([Cannot find php_pdo_driver.h.])],[$2])
@@ -2890,3 +2901,71 @@ main()
fi
])
+dnl
+dnl PHP_INIT_DTRACE(providerdesc, header-file, sources [, module])
+dnl
+AC_DEFUN([PHP_INIT_DTRACE],[
+dnl Set paths properly when called from extension
+ case "$4" in
+ ""[)] ac_srcdir="$abs_srcdir/"; unset ac_bdir;;
+ /*[)] ac_srcdir=`echo "$4"|cut -c 2-`"/"; ac_bdir=$ac_srcdir;;
+ *[)] ac_srcdir="$abs_srcdir/$1/"; ac_bdir="$4/";;
+ esac
+
+dnl providerdesc
+ ac_provsrc=$1
+ old_IFS=[$]IFS
+ IFS=.
+ set $ac_provsrc
+ ac_provobj=[$]1
+ IFS=$old_IFS
+
+dnl header-file
+ ac_hdrobj=$2
+
+dnl Add providerdesc.o into global objects when needed
+ case $host_alias in
+ *freebsd*)
+ PHP_GLOBAL_OBJS="[$]PHP_GLOBAL_OBJS [$]ac_bdir[$]ac_provsrc.o"
+ PHP_LDFLAGS="$PHP_LDFLAGS -lelf"
+ ;;
+ *solaris*)
+ PHP_GLOBAL_OBJS="[$]PHP_GLOBAL_OBJS [$]ac_bdir[$]ac_provsrc.o"
+ ;;
+ esac
+
+dnl DTrace objects
+ old_IFS=[$]IFS
+ for ac_src in $3; do
+ IFS=.
+ set $ac_src
+ ac_obj=[$]1
+ IFS=$old_IFS
+
+ PHP_DTRACE_OBJS="[$]PHP_DTRACE_OBJS [$]ac_bdir[$]ac_obj.lo"
+ done;
+
+ case [$]php_sapi_module in
+ shared[)]
+ for ac_lo in $PHP_DTRACE_OBJS; do
+ dtrace_objs="[$]dtrace_objs `echo $ac_lo | $SED -e 's,\.lo$,.o,' -e 's#\(.*\)\/#\1\/.libs\/#'`"
+ done;
+ ;;
+ *[)]
+ dtrace_objs='$(PHP_DTRACE_OBJS:.lo=.o)'
+ ;;
+ esac
+
+dnl Generate Makefile.objects entries
+ cat>>Makefile.objects<<EOF
+
+$ac_bdir[$]ac_hdrobj: $abs_srcdir/$ac_provsrc
+ dtrace -h -C -s $ac_srcdir[$]ac_provsrc -o \$[]@ && \$(SED) -ibak 's,PHP_,DTRACE_,g' \$[]@
+
+\$(PHP_DTRACE_OBJS): $ac_bdir[$]ac_hdrobj
+
+$ac_bdir[$]ac_provsrc.o: \$(PHP_DTRACE_OBJS)
+ dtrace -G -o \$[]@ -s $abs_srcdir/$ac_provsrc $dtrace_objs
+
+EOF
+])
diff --git a/build/build.mk b/build/build.mk
index 8cefd59aad..ac5dadb313 100644
--- a/build/build.mk
+++ b/build/build.mk
@@ -32,7 +32,6 @@ all: $(STAMP) $(ALWAYS)
generated_lists:
@echo makefile_am_files = Zend/Makefile.am TSRM/Makefile.am > $@
- @echo config_h_files = Zend/acconfig.h TSRM/acconfig.h >> $@
@echo config_m4_files = Zend/Zend.m4 TSRM/tsrm.m4 TSRM/threads.m4 \
Zend/acinclude.m4 ext/*/config*.m4 sapi/*/config.m4 >> $@
diff --git a/build/build2.mk b/build/build2.mk
index 30ee6b1a80..be103fc322 100644
--- a/build/build2.mk
+++ b/build/build2.mk
@@ -25,8 +25,6 @@ LT_TARGETS = ltmain.sh config.guess config.sub
config_h_in = main/php_config.h.in
-acconfig_h_SOURCES = acconfig.h.in $(config_h_files)
-
targets = $(TOUCH_FILES) configure $(config_h_in)
PHP_AUTOCONF ?= 'autoconf'
@@ -36,11 +34,7 @@ SUPPRESS_WARNINGS ?= 2>&1 | (egrep -v '(AC_TRY_RUN called without default to all
all: $(targets)
-acconfig.h: $(acconfig_h_SOURCES)
- @echo rebuilding $@
- cat $(acconfig_h_SOURCES) > $@
-
-$(config_h_in): configure acconfig.h
+$(config_h_in): configure
# explicitly remove target since autoheader does not seem to work
# correctly otherwise (timestamps are not updated)
@echo rebuilding $@
diff --git a/build/buildcheck.sh b/build/buildcheck.sh
index de16264429..8754e3a292 100755
--- a/build/buildcheck.sh
+++ b/build/buildcheck.sh
@@ -28,37 +28,22 @@ if test -z "$PHP_AUTOCONF"; then
PHP_AUTOCONF='autoconf'
fi
-# autoconf 2.13 or newer
+# autoconf 2.59 or newer
ac_version=`$PHP_AUTOCONF --version 2>/dev/null|head -n 1|sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
if test -z "$ac_version"; then
echo "buildconf: autoconf not found."
-echo " You need autoconf version 2.13 or newer installed"
+echo " You need autoconf version 2.59 or newer installed"
echo " to build PHP from SVN."
exit 1
fi
IFS=.; set $ac_version; IFS=' '
-if test "$1" = "2" -a "$2" -lt "13" || test "$1" -lt "2"; then
+if test "$1" = "2" -a "$2" -lt "59" || test "$1" -lt "2"; then
echo "buildconf: autoconf version $ac_version found."
-echo " You need autoconf version 2.13 or newer installed"
+echo " You need autoconf version 2.59 or newer installed"
echo " to build PHP from SVN."
exit 1
-fi
-
-if test "$1" = "2" -a "$2" -gt "59"; then
- echo "buildconf: You need autoconf 2.59 or lower to build this version of PHP."
- echo " You are currently trying to use $ac_version"
- echo " Most distros have separate autoconf 2.13 or 2.59 packages."
- echo " On Debian/Ubuntu both autoconf2.13 and autoconf2.59 packages exist."
- echo " Install autoconf2.13 and set the PHP_AUTOCONF env var to "
- echo " autoconf2.13 and try again."
- exit 1
else
- echo "buildconf: autoconf version $ac_version (ok)"
-fi
-
-if test "$1" = "2" -a "$2" -ge "50"; then
- ./vcsclean
- stamp=
+echo "buildconf: autoconf version $ac_version (ok)"
fi
test -n "$stamp" && touch $stamp
diff --git a/buildconf b/buildconf
index f1f2f778b8..9344b074ea 100755
--- a/buildconf
+++ b/buildconf
@@ -32,7 +32,12 @@ if test "$dev" = "0" -a "$devok" = "0"; then
echo "use buildconf --force to override this check."
exit 1
fi
-
+
+if test "$devok" = "1"; then
+ echo "Removing configure caches"
+ rm -rf autom4te.cache config.cache
+fi
+
rm -f generated_lists
if test "$debug" = "yes"; then
diff --git a/configure.in b/configure.in
index 050f8d40f1..afe470d30a 100644
--- a/configure.in
+++ b/configure.in
@@ -1,28 +1,6 @@
## $Id$ -*- autoconf -*-
dnl ## Process this file with autoconf to produce a configure script.
-divert(1)
-
-dnl ## Diversion 1 is the autoconf + automake setup phase. We also
-dnl ## set the PHP version, deal with platform-specific compile
-dnl ## options and check for the basic compile tools.
-
-dnl ## Diversion 2 is the initial checking of OS features, programs,
-dnl ## libraries and so on.
-
-dnl ## In diversion 3 we check for compile-time options to the PHP
-dnl ## core and how to deal with different system dependencies.
-dnl ## This includes whether debugging or short tags are enabled
-dnl ## and the default behaviour of php.ini options.
-dnl ## This is also where an SAPI interface is selected (choosing between
-dnl ## Apache module, CGI etc.)
-
-dnl ## In diversion 4 we check user-configurable general settings.
-
-dnl ## In diversion 5 we check which extensions should be compiled.
-dnl ## All of these are normally in the extension directories.
-dnl ## Diversion 5 is the last one. Here we generate files and clean up.
-
dnl include Zend specific macro definitions first
dnl -------------------------------------------------------------------------
sinclude(Zend/acinclude.m4)
@@ -30,18 +8,118 @@ sinclude(Zend/acinclude.m4)
dnl Basic autoconf + automake initialization, generation of config.nice.
dnl -------------------------------------------------------------------------
-AC_PREREQ(2.13)
+AC_PREREQ(2.59)
AC_INIT(README.GIT-RULES)
+ifdef([AC_PRESERVE_HELP_ORDER], [AC_PRESERVE_HELP_ORDER], [])
PHP_CONFIG_NICE(config.nice)
PHP_CANONICAL_HOST_TARGET
AC_CONFIG_HEADER(main/php_config.h)
+AH_TOP([
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ZEND_API __attribute__ ((visibility("default")))
+# define ZEND_DLEXPORT __attribute__ ((visibility("default")))
+#else
+# define ZEND_API
+# define ZEND_DLEXPORT
+#endif
+
+#define ZEND_DLIMPORT
+
+#undef uint
+#undef ulong
+
+/* Define if you want to enable memory limit support */
+#define MEMORY_LIMIT 0
+])
+AH_BOTTOM([
+#ifndef ZEND_ACCONFIG_H_NO_C_PROTOS
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if ZEND_BROKEN_SPRINTF
+int zend_sprintf(char *buffer, const char *format, ...);
+#else
+# define zend_sprintf sprintf
+#endif
+
+#include <math.h>
+
+/* To enable the is_nan, is_infinite and is_finite PHP functions */
+#ifdef NETWARE
+ #define HAVE_ISNAN 1
+ #define HAVE_ISINF 1
+ #define HAVE_ISFINITE 1
+#endif
+
+#ifndef zend_isnan
+#ifdef HAVE_ISNAN
+#define zend_isnan(a) isnan(a)
+#elif defined(HAVE_FPCLASS)
+#define zend_isnan(a) ((fpclass(a) == FP_SNAN) || (fpclass(a) == FP_QNAN))
+#else
+#define zend_isnan(a) 0
+#endif
+#endif
+
+#ifdef HAVE_ISINF
+#define zend_isinf(a) isinf(a)
+#elif defined(INFINITY)
+/* Might not work, but is required by ISO C99 */
+#define zend_isinf(a) (((a)==INFINITY)?1:0)
+#elif defined(HAVE_FPCLASS)
+#define zend_isinf(a) ((fpclass(a) == FP_PINF) || (fpclass(a) == FP_NINF))
+#else
+#define zend_isinf(a) 0
+#endif
+
+#ifdef HAVE_FINITE
+#define zend_finite(a) finite(a)
+#elif defined(HAVE_ISFINITE) || defined(isfinite)
+#define zend_finite(a) isfinite(a)
+#elif defined(fpclassify)
+#define zend_finite(a) ((fpclassify((a))!=FP_INFINITE&&fpclassify((a))!=FP_NAN)?1:0)
+#else
+#define zend_finite(a) (zend_isnan(a) ? 0 : zend_isinf(a) ? 0 : 1)
+#endif
+
+#endif /* ifndef ZEND_ACCONFIG_H_NO_C_PROTOS */
+
+#ifdef NETWARE
+#ifdef USE_WINSOCK
+#/*This detection against winsock is of no use*/ undef HAVE_SOCKLEN_T
+#/*This detection against winsock is of no use*/ undef HAVE_SYS_SOCKET_H
+#endif
+#endif
+
+#undef PTHREADS
+])
PHP_MAJOR_VERSION=5
-PHP_MINOR_VERSION=3
-PHP_RELEASE_VERSION=19
+PHP_MINOR_VERSION=4
+PHP_RELEASE_VERSION=9
PHP_EXTRA_VERSION="-dev"
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
@@ -289,23 +367,14 @@ sinclude(Zend/Zend.m4)
sinclude(TSRM/threads.m4)
sinclude(TSRM/tsrm.m4)
-
-divert(2)
-
-dnl ## Diversion 2 is where we set PHP-specific options and come up
-dnl ## with reasonable default values for them. We check for pthreads here
-dnl ## because the information is needed by the SAPI configuration.
-dnl ## This is also where an SAPI interface is selected (choosing between
-dnl ## Apache module, CGI etc.)
-
dnl .
dnl -------------------------------------------------------------------------
PTHREADS_CHECK
PHP_HELP_SEPARATOR([SAPI modules:])
PHP_SHLIB_SUFFIX_NAMES
-PHP_SAPI=default
PHP_BUILD_PROGRAM
+PHP_SAPI=none
dnl SAPI configuration.
@@ -324,18 +393,25 @@ dnl Show which main SAPI was selected
AC_MSG_CHECKING([for chosen SAPI module])
AC_MSG_RESULT([$PHP_SAPI])
+dnl Show which binaries were selected
+AC_MSG_CHECKING([for executable SAPI binaries])
+if test "$PHP_BINARIES"; then
+ AC_MSG_RESULT([$PHP_BINARIES])
+else
+ AC_MSG_RESULT([none])
+fi
+
+dnl Exit early
+if test -z "$PHP_INSTALLED_SAPIS"; then
+ AC_MSG_ERROR([Nothing to build.])
+fi
+
+dnl force ZTS
if test "$enable_maintainer_zts" = "yes"; then
PTHREADS_ASSIGN_VARS
PTHREADS_FLAGS
fi
-divert(3)
-
-dnl ## In diversion 3 we check for compile-time options to the PHP
-dnl ## core and how to deal with different system dependencies.
-dnl ## This includes whether debugging or short tags are enabled
-dnl ## and the default behaviour of php.ini options.
-
dnl Starting system checks.
dnl -------------------------------------------------------------------------
@@ -683,10 +759,6 @@ if test "x$php_crypt_r" = "x1"; then
PHP_CRYPT_R_STYLE
fi
-divert(4)
-
-dnl ## In diversion 4 we check user-configurable general settings.
-
dnl General settings.
dnl -------------------------------------------------------------------------
PHP_CONFIGURE_PART(General settings)
@@ -791,7 +863,7 @@ fi
PHP_ARG_WITH(layout, layout of installed files,
[ --with-layout=TYPE Set how installed files will be laid out. Type can
- be either PHP or GNU [PHP]], PHP, no)
+ be either PHP or GNU @<:@PHP@:>@], PHP, no)
case $PHP_LAYOUT in
GNU)
@@ -804,7 +876,7 @@ esac
PHP_ARG_WITH(config-file-path, path to configuration file,
[ --with-config-file-path=PATH
- Set the path in which to look for php.ini [PREFIX/lib]], DEFAULT, no)
+ Set the path in which to look for php.ini @<:@PREFIX/lib@:>@], DEFAULT, no)
if test "$PHP_CONFIG_FILE_PATH" = "DEFAULT"; then
case $PHP_LAYOUT in
@@ -828,28 +900,6 @@ AC_MSG_RESULT([$PHP_CONFIG_FILE_SCAN_DIR])
test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS"
-PHP_ARG_ENABLE(safe-mode, whether to enable safe mode by default,
-[ --enable-safe-mode Enable safe mode by default], no, no)
-
-if test "$PHP_SAFE_MODE" = "yes"; then
- AC_DEFINE(PHP_SAFE_MODE,1,[ ])
-else
- AC_DEFINE(PHP_SAFE_MODE,0,[ ])
-fi
-
-AC_MSG_CHECKING([for safe mode exec dir])
-PHP_ARG_WITH(exec-dir,,
-[ --with-exec-dir[=DIR] Only allow executables in DIR under safe-mode
- [/usr/local/php/bin]], no, no)
-
-if test "$PHP_EXEC_DIR" != "no" && test "$PHP_EXEC_DIR" != "yes" ; then
- AC_DEFINE_UNQUOTED(PHP_SAFE_MODE_EXEC_DIR, "$PHP_EXEC_DIR", [ ])
- AC_MSG_RESULT([$PHP_EXEC_DIR])
-else
- AC_DEFINE(PHP_SAFE_MODE_EXEC_DIR, "/usr/local/php/bin", [ ])
- AC_MSG_RESULT([/usr/local/php/bin])
-fi
-
PHP_ARG_ENABLE(sigchild, whether to enable PHP's own SIGCHLD handler,
[ --enable-sigchild Enable PHP's own SIGCHLD handler], no, no)
@@ -859,15 +909,6 @@ else
AC_DEFINE(PHP_SIGCHILD, 0, [ ])
fi
-PHP_ARG_ENABLE(magic-quotes, whether to enable magic quotes by default,
-[ --enable-magic-quotes Enable magic quotes by default.], no, no)
-
-if test "$PHP_MAGIC_QUOTES" = "yes"; then
- AC_DEFINE(MAGIC_QUOTES, 1, [ ])
-else
- AC_DEFINE(MAGIC_QUOTES, 0, [ ])
-fi
-
PHP_ARG_ENABLE(libgcc, whether to explicitly link against libgcc,
[ --enable-libgcc Enable explicitly linking against libgcc], no, no)
@@ -909,6 +950,25 @@ if test "$PHP_IPV6" != "no" && test "$ac_cv_ipv6_support" = yes; then
AC_DEFINE(HAVE_IPV6, 1, [Whether to enable IPv6 support])
fi
+dnl ##
+dnl ## DTRACE CHECKS
+dnl ## Note: this has to be done after SAPI configuration!
+dnl ##
+PHP_ARG_ENABLE(dtrace, whether to enable DTrace support,
+[ --enable-dtrace Enable DTrace support], no, no)
+
+if test "$PHP_DTRACE" = "yes"; then
+ AC_CHECK_HEADERS([sys/sdt.h], [
+ PHP_INIT_DTRACE([Zend/zend_dtrace.d],[Zend/zend_dtrace_gen.h],[main/main.c Zend/zend_API.c \
+ Zend/zend_execute.c Zend/zend_exceptions.c \
+ Zend/zend_dtrace.c Zend/zend.c])
+ AC_DEFINE(HAVE_DTRACE, 1, [Whether to enable DTrace support])
+ PHP_SUBST(PHP_DTRACE_OBJS)
+ ], [
+ AC_MSG_ERROR([Cannot find sys/sdt.h which is required for DTrace support])
+ ])
+fi
+
AC_MSG_CHECKING([how big to make fd sets])
PHP_ARG_ENABLE(fd-setsize,,
[ --enable-fd-setsize Set size of descriptor sets], no, no)
@@ -924,11 +984,6 @@ else
AC_MSG_RESULT([using system default])
fi
-divert(5)
-
-dnl ## In diversion 5 we check which extensions should be compiled.
-dnl ## All of these are normally in the extension directories.
-
dnl Extension configuration.
dnl -------------------------------------------------------------------------
@@ -965,14 +1020,8 @@ dnl -------------------------------------------------------------------------
enable_shared=yes
enable_static=yes
-case $php_build_target in
- program|static)
- standard_libtool_flag='-prefer-non-pic -static'
- if test -z "$PHP_MODULES" && test -z "$PHP_ZEND_EX"; then
- enable_shared=no
- fi
- ;;
- shared)
+case $php_sapi_module in
+ shared[)]
enable_static=no
case $with_pic in
yes)
@@ -984,6 +1033,12 @@ case $php_build_target in
esac
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -avoid-version -module"
;;
+ *[)]
+ standard_libtool_flag='-prefer-non-pic -static'
+ if test -z "$PHP_MODULES" && test -z "$PHP_ZEND_EX"; then
+ enable_shared=no
+ fi
+ ;;
esac
EXTRA_LIBS="$EXTRA_LIBS $DLIBS $LIBS"
@@ -1013,7 +1068,7 @@ if test "$PHP_CLI" = "no"; then
fi
PHP_ARG_WITH(pear, [whether to install PEAR],
-[ --with-pear=DIR Install PEAR in DIR [PREFIX/lib/php]
+[ --with-pear=DIR Install PEAR in DIR @<:@PREFIX/lib/php@:>@
--without-pear Do not install PEAR], DEFAULT, yes)
if test "$PHP_PEAR" != "no"; then
@@ -1221,24 +1276,15 @@ case $host_alias in
;;
esac
-if test "$PHP_CLI" != "no"; then
- PHP_CLI_TARGET="\$(SAPI_CLI_PATH)"
- PHP_INSTALL_CLI_TARGET="install-cli"
- PHP_ADD_SOURCES(sapi/cli, php_cli.c php_cli_readline.c,, cli)
- PHP_INSTALLED_SAPIS="cli $PHP_SAPI"
- PHP_EXECUTABLE="\$(top_builddir)/\$(SAPI_CLI_PATH)"
-else
- PHP_INSTALLED_SAPIS="$PHP_SAPI"
-fi
-
PHP_SUBST_OLD(PHP_INSTALLED_SAPIS)
PHP_SUBST(PHP_EXECUTABLE)
-PHP_SUBST(PHP_CLI_TARGET)
+
PHP_SUBST(PHP_SAPI_OBJS)
-PHP_SUBST(PHP_CLI_OBJS)
+PHP_SUBST(PHP_BINARY_OBJS)
PHP_SUBST(PHP_GLOBAL_OBJS)
+PHP_SUBST(PHP_BINARIES)
PHP_SUBST(PHP_MODULES)
PHP_SUBST(PHP_ZEND_EX)
@@ -1335,10 +1381,10 @@ PHP_CONFIGURE_PART(Configuring libtool)
LDFLAGS="$LDFLAGS $PHP_AIX_LDFLAGS"
-dnl Autoconf 2.13's libtool checks go slightly nuts on Mac OS X 10.5, 10.6, 10.7 and 10.8.
+dnl Autoconf 2.13's libtool checks go slightly nuts on Mac OS X 10.5 and 10.6.
dnl This hack works around it. Ugly.
case $host_alias in
-*darwin9*|*darwin10*|*darwin11*|*darwin12*)
+*darwin9*|*darwin10*)
ac_cv_exeext=
;;
esac
@@ -1382,27 +1428,19 @@ else
pharcmd_install=
fi;
-all_targets="$lcov_target \$(OVERALL_TARGET) \$(PHP_MODULES) \$(PHP_ZEND_EX) \$(PHP_CLI_TARGET) $pharcmd"
-install_targets="$install_modules install-build install-headers install-programs $install_pear $pharcmd_install"
-
-case $PHP_SAPI in
- cli)
- install_targets="$PHP_INSTALL_CLI_TARGET $install_targets"
- ;;
- *)
- install_targets="install-sapi $PHP_INSTALL_CLI_TARGET $install_targets"
- ;;
-esac
+all_targets="$lcov_target \$(OVERALL_TARGET) \$(PHP_MODULES) \$(PHP_ZEND_EX) \$(PHP_BINARIES) $pharcmd"
+install_targets="$install_sapi $install_modules $install_binaries install-build install-headers install-programs $install_pear $pharcmd_install"
PHP_SUBST(all_targets)
PHP_SUBST(install_targets)
+PHP_SUBST(install_binary_targets)
PHP_INSTALL_HEADERS([Zend/ TSRM/ include/ main/ main/streams/])
PHP_ADD_SOURCES(TSRM, TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c)
PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c php_sprintf.c \
- safe_mode.c fopen_wrappers.c alloca.c php_scandir.c \
+ fopen_wrappers.c alloca.c php_scandir.c \
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
network.c php_open_temporary_file.c php_logos.c \
@@ -1420,21 +1458,21 @@ case $host_alias in
PHP_ADD_BUILD_DIR(netware)
;;
*)
- PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli)
+ PHP_ADD_SOURCES_X(/main, internal_functions_cli.c,, PHP_BINARY_OBJS)
;;
esac
PHP_ADD_SOURCES(Zend, \
zend_language_parser.c zend_language_scanner.c \
zend_ini_parser.c zend_ini_scanner.c \
- zend_alloc.c zend_compile.c zend_constants.c zend_dynamic_array.c \
+ zend_alloc.c zend_compile.c zend_constants.c zend_dynamic_array.c zend_dtrace.c \
zend_execute_API.c zend_highlight.c zend_llist.c \
zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
- zend_closures.c zend_float.c)
+ zend_closures.c zend_float.c zend_string.c zend_signal.c)
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
@@ -1451,7 +1489,6 @@ fi
PHP_ADD_SOURCES_X(Zend, zend_execute.c,,PHP_GLOBAL_OBJS,,$flag)
PHP_ADD_BUILD_DIR(main main/streams)
-PHP_ADD_BUILD_DIR(sapi/$PHP_SAPI sapi/cli)
PHP_ADD_BUILD_DIR(TSRM)
PHP_ADD_BUILD_DIR(Zend)
diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c
index 0f9160a69f..c570a2dbf4 100644
--- a/ext/bz2/bz2.c
+++ b/ext/bz2/bz2.c
@@ -228,7 +228,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
path_copy = path;
#endif
- if ((PG(safe_mode) && (!php_checkuid(path_copy, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(path_copy TSRMLS_CC)) {
+ if (php_check_open_basedir(path_copy TSRMLS_CC)) {
return NULL;
}
@@ -242,7 +242,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper,
if (bz_file == NULL) {
/* that didn't work, so try and get something from the network/wrapper */
- stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST | ENFORCE_SAFE_MODE, opened_path);
+ stream = php_stream_open_wrapper(path, mode, options | STREAM_WILL_CAST, opened_path);
if (stream) {
int fd;
@@ -352,13 +352,6 @@ static PHP_FUNCTION(bzread)
}
Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
-
- if (PG(magic_quotes_runtime)) {
- Z_STRVAL_P(return_value) = php_addslashes( Z_STRVAL_P(return_value),
- Z_STRLEN_P(return_value),
- &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
- }
-
Z_TYPE_P(return_value) = IS_STRING;
}
/* }}} */
@@ -385,20 +378,19 @@ static PHP_FUNCTION(bzopen)
/* If it's not a resource its a string containing the filename to open */
if (Z_TYPE_PP(file) == IS_STRING) {
- convert_to_string_ex(file);
-
- if (strlen(Z_STRVAL_PP(file)) != Z_STRLEN_PP(file)) {
- RETURN_FALSE;
- }
if (Z_STRLEN_PP(file) == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "filename cannot be empty");
RETURN_FALSE;
}
+
+ if (CHECK_ZVAL_NULL_PATH(*file)) {
+ RETURN_FALSE;
+ }
stream = php_stream_bz2open(NULL,
Z_STRVAL_PP(file),
mode,
- ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ REPORT_ERRORS,
NULL);
} else if (Z_TYPE_PP(file) == IS_RESOURCE) {
/* If it is a resource, than its a stream resource */
diff --git a/ext/calendar/tests/jdtomonthname.phpt b/ext/calendar/tests/jdtomonthname.phpt
index 5dc3307428..5c552474bd 100644
--- a/ext/calendar/tests/jdtomonthname.phpt
+++ b/ext/calendar/tests/jdtomonthname.phpt
@@ -52,7 +52,9 @@ string(0) ""
string(0) ""
string(0) ""
-=== Array
+===
+Notice: Array to string conversion in %sjdtomonthname.php on line %d
+Array
Warning: jdmonthname() expects parameter 1 to be long, array given in %s on line %d
bool(false)
diff --git a/ext/com_dotnet/com_com.c b/ext/com_dotnet/com_com.c
index e84c767b74..15b9a6c508 100644
--- a/ext/com_dotnet/com_com.c
+++ b/ext/com_dotnet/com_com.c
@@ -224,7 +224,7 @@ PHP_FUNCTION(com_create_instance)
if (FAILED(res)) {
char *werr, *msg;
- werr = php_win_err(res);
+ werr = php_win32_error_to_msg(res);
spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr);
LocalFree(werr);
@@ -383,7 +383,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
case DISP_E_PARAMNOTFOUND:
case DISP_E_TYPEMISMATCH:
- desc = php_win_err(hr);
+ desc = php_win32_error_to_msg(hr);
spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc);
LocalFree(desc);
break;
@@ -399,7 +399,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
/* else fall through */
default:
- desc = php_win_err(hr);
+ desc = php_win32_error_to_msg(hr);
spprintf(&msg, 0, "Error [0x%08x] %s", hr, desc);
LocalFree(desc);
break;
@@ -481,7 +481,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen,
if (FAILED(hr)) {
char *winerr = NULL;
char *msg = NULL;
- winerr = php_win_err(hr);
+ winerr = php_win32_error_to_msg(hr);
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr);
LocalFree(winerr);
php_com_throw_exception(hr, msg TSRMLS_CC);
@@ -640,7 +640,7 @@ int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
hr = php_com_get_id_of_name(obj, name, namelen, &dispid TSRMLS_CC);
if (FAILED(hr)) {
- winerr = php_win_err(hr);
+ winerr = php_win32_error_to_msg(hr);
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr);
LocalFree(winerr);
php_com_throw_exception(hr, msg TSRMLS_CC);
diff --git a/ext/com_dotnet/com_dotnet.c b/ext/com_dotnet/com_dotnet.c
index 6b77a613e6..8e3bf31cc8 100644
--- a/ext/com_dotnet/com_dotnet.c
+++ b/ext/com_dotnet/com_dotnet.c
@@ -202,7 +202,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
hr = dotnet_init(&where TSRMLS_CC);
if (FAILED(hr)) {
char buf[1024];
- char *err = php_win_err(hr);
+ char *err = php_win32_error_to_msg(hr);
snprintf(buf, sizeof(buf), "Failed to init .Net runtime [%s] %s", where, err);
if (err)
LocalFree(err);
@@ -281,7 +281,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
if (ret == FAILURE) {
char buf[1024];
- char *err = php_win_err(hr);
+ char *err = php_win32_error_to_msg(hr);
snprintf(buf, sizeof(buf), "Failed to instantiate .Net object [%s] [0x%08x] %s", where, hr, err);
if (err && err[0]) {
LocalFree(err);
diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c
index a37ad5ffeb..a0824f2409 100644
--- a/ext/com_dotnet/com_handlers.c
+++ b/ext/com_dotnet/com_handlers.c
@@ -29,7 +29,7 @@
#include "php_com_dotnet_internal.h"
#include "Zend/zend_exceptions.h"
-static zval *com_property_read(zval *object, zval *member, int type TSRMLS_DC)
+static zval *com_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
zval *return_value;
php_com_dotnet_object *obj;
@@ -64,7 +64,7 @@ static zval *com_property_read(zval *object, zval *member, int type TSRMLS_DC)
return return_value;
}
-static void com_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
+static void com_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
php_com_dotnet_object *obj;
VARIANT v;
@@ -196,7 +196,7 @@ static zval *com_object_get(zval *property TSRMLS_DC)
}
#endif
-static int com_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+static int com_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
{
DISPID dispid;
php_com_dotnet_object *obj;
@@ -222,7 +222,7 @@ static int com_dimension_exists(zval *object, zval *member, int check_empty TSRM
return 0;
}
-static void com_property_delete(zval *object, zval *member TSRMLS_DC)
+static void com_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
}
@@ -246,7 +246,7 @@ static void function_dtor(void *pDest)
{
zend_internal_function *f = (zend_internal_function*)pDest;
- efree(f->function_name);
+ efree((char*)f->function_name);
if (f->arg_info) {
efree(f->arg_info);
}
@@ -259,7 +259,7 @@ static PHP_FUNCTION(com_method_handler)
INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
-static union _zend_function *com_method_get(zval **object_ptr, char *name, int len TSRMLS_DC)
+static union _zend_function *com_method_get(zval **object_ptr, char *name, int len, const zend_literal *key TSRMLS_DC)
{
zend_internal_function f, *fptr = NULL;
php_com_dotnet_object *obj;
@@ -283,7 +283,7 @@ static union _zend_function *com_method_get(zval **object_ptr, char *name, int l
f.num_args = 0;
f.arg_info = NULL;
f.scope = obj->ce;
- f.fn_flags = 0;
+ f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
f.function_name = estrndup(name, len);
f.handler = PHP_FN(com_method_handler);
@@ -364,7 +364,7 @@ static union _zend_function *com_method_get(zval **object_ptr, char *name, int l
return NULL;
}
-static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
+static int com_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
{
zval ***args = NULL;
php_com_dotnet_object *obj;
@@ -387,7 +387,7 @@ static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
VariantInit(&v);
- if (SUCCESS == php_com_do_invoke_byref(obj, method, -1, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) {
+ if (SUCCESS == php_com_do_invoke_byref(obj, (char*)method, -1, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) {
php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC);
ret = SUCCESS;
VariantClear(&v);
@@ -409,7 +409,7 @@ static union _zend_function *com_constructor_get(zval *object TSRMLS_DC)
#define POPULATE_CTOR(f, fn) \
f.type = ZEND_INTERNAL_FUNCTION; \
- f.function_name = obj->ce->name; \
+ f.function_name = (char *) obj->ce->name; \
f.scope = obj->ce; \
f.arg_info = NULL; \
f.num_args = 0; \
@@ -442,7 +442,7 @@ static zend_class_entry *com_class_entry_get(const zval *object TSRMLS_DC)
return obj->ce;
}
-static int com_class_name_get(const zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
+static int com_class_name_get(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
{
php_com_dotnet_object *obj;
obj = CDNO_FETCH(object);
@@ -580,7 +580,10 @@ zend_object_handlers php_com_object_handlers = {
com_class_name_get,
com_objects_compare,
com_object_cast,
- com_object_count
+ com_object_count,
+ NULL, /* get_debug_info */
+ NULL, /* get_closure */
+ NULL, /* get_gc */
};
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable TSRMLS_DC)
diff --git a/ext/com_dotnet/com_misc.c b/ext/com_dotnet/com_misc.c
index 86deca2969..33bd6380f3 100644
--- a/ext/com_dotnet/com_misc.c
+++ b/ext/com_dotnet/com_misc.c
@@ -33,7 +33,7 @@ void php_com_throw_exception(HRESULT code, char *message TSRMLS_DC)
{
int free_msg = 0;
if (message == NULL) {
- message = php_win_err(code);
+ message = php_win32_error_to_msg(code);
free_msg = 1;
}
zend_throw_exception(php_com_exception_class_entry, message, (long)code TSRMLS_CC);
diff --git a/ext/com_dotnet/com_olechar.c b/ext/com_dotnet/com_olechar.c
index 2cb1f03e50..e57c7343de 100644
--- a/ext/com_dotnet/com_olechar.c
+++ b/ext/com_dotnet/com_olechar.c
@@ -54,7 +54,7 @@ PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(char *string, uint strin
}
if (!ok) {
- char *msg = php_win_err(GetLastError());
+ char *msg = php_win32_error_to_msg(GetLastError());
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not convert string to unicode: `%s'", msg);
@@ -85,7 +85,7 @@ PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring, uint *s
}
if (!ok) {
- char *msg = php_win_err(GetLastError());
+ char *msg = php_win32_error_to_msg(GetLastError());
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not convert string from unicode: `%s'", msg);
diff --git a/ext/com_dotnet/com_persist.c b/ext/com_dotnet/com_persist.c
index fb940217e8..7c035f6c4a 100644
--- a/ext/com_dotnet/com_persist.c
+++ b/ext/com_dotnet/com_persist.c
@@ -45,32 +45,31 @@ typedef struct {
} php_istream;
static int le_istream;
-static void istream_destructor(php_istream *stm);
+static void istream_destructor(php_istream *stm TSRMLS_DC);
static void istream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
php_istream *stm = (php_istream *)rsrc->ptr;
- istream_destructor(stm);
+ istream_destructor(stm TSRMLS_CC);
}
-#ifdef ZTS
-# define TSRMLS_FIXED() TSRMLS_FETCH();
-#else
-# define TSRMLS_FIXED()
-#endif
-
#define FETCH_STM() \
- TSRMLS_FIXED() \
php_istream *stm = (php_istream*)This; \
+ TSRMLS_FETCH(); \
if (GetCurrentThreadId() != stm->engine_thread) \
return RPC_E_WRONG_THREAD;
+
+#define FETCH_STM_EX() \
+ php_istream *stm = (php_istream*)This; \
+ if (GetCurrentThreadId() != stm->engine_thread) \
+ return RPC_E_WRONG_THREAD;
static HRESULT STDMETHODCALLTYPE stm_queryinterface(
IStream *This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject)
{
- FETCH_STM();
+ FETCH_STM_EX();
if (IsEqualGUID(&IID_IUnknown, riid) ||
IsEqualGUID(&IID_IStream, riid)) {
@@ -85,7 +84,7 @@ static HRESULT STDMETHODCALLTYPE stm_queryinterface(
static ULONG STDMETHODCALLTYPE stm_addref(IStream *This)
{
- FETCH_STM();
+ FETCH_STM_EX();
return InterlockedIncrement(&stm->refcount);
}
@@ -190,7 +189,7 @@ static HRESULT STDMETHODCALLTYPE stm_set_size(IStream *This, ULARGE_INTEGER libN
static HRESULT STDMETHODCALLTYPE stm_copy_to(IStream *This, IStream *pstm, ULARGE_INTEGER cb,
ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
{
- FETCH_STM();
+ FETCH_STM_EX();
return E_NOTIMPL;
}
@@ -250,10 +249,8 @@ static struct IStreamVtbl php_istream_vtbl = {
stm_clone
};
-static void istream_destructor(php_istream *stm)
+static void istream_destructor(php_istream *stm TSRMLS_DC)
{
- TSRMLS_FETCH();
-
if (stm->id) {
int id = stm->id;
stm->id = 0;
@@ -285,7 +282,7 @@ PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream TSR
stm->stream = stream;
zend_list_addref(stream->rsrc_id);
- stm->id = zend_list_insert(stm, le_istream);
+ stm->id = zend_list_insert(stm, le_istream TSRMLS_CC);
return (IStream*)stm;
}
@@ -382,23 +379,19 @@ CPH_METHOD(SaveToFile)
res = get_persist_file(helper);
if (helper->ipf) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!|b",
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p!|b",
&filename, &filename_len, &remember)) {
php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
return;
}
if (filename) {
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
fullpath = expand_filepath(filename, NULL TSRMLS_CC);
if (!fullpath) {
RETURN_FALSE;
}
- if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
- php_check_open_basedir(fullpath TSRMLS_CC)) {
+ if (php_check_open_basedir(fullpath TSRMLS_CC)) {
efree(fullpath);
RETURN_FALSE;
}
@@ -450,22 +443,17 @@ CPH_METHOD(LoadFromFile)
res = get_persist_file(helper);
if (helper->ipf) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
&filename, &filename_len, &flags)) {
php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
return;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
RETURN_FALSE;
}
- if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
- php_check_open_basedir(fullpath TSRMLS_CC)) {
+ if (php_check_open_basedir(fullpath TSRMLS_CC)) {
efree(fullpath);
RETURN_FALSE;
}
diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c
index 071f6e20c0..1d851f0607 100644
--- a/ext/com_dotnet/com_saproxy.c
+++ b/ext/com_dotnet/com_saproxy.c
@@ -71,7 +71,7 @@ static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, in
}
}
-static zval *saproxy_property_read(zval *object, zval *member, int type TSRMLS_DC)
+static zval *saproxy_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
zval *return_value;
@@ -83,7 +83,7 @@ static zval *saproxy_property_read(zval *object, zval *member, int type TSRMLS_D
return return_value;
}
-static void saproxy_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
+static void saproxy_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
}
@@ -293,7 +293,7 @@ static zval *saproxy_object_get(zval *property TSRMLS_DC)
}
#endif
-static int saproxy_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+static int saproxy_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
{
/* no properties */
return 0;
@@ -305,7 +305,7 @@ static int saproxy_dimension_exists(zval *object, zval *member, int check_empty
return 0;
}
-static void saproxy_property_delete(zval *object, zval *member TSRMLS_DC)
+static void saproxy_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
}
@@ -321,13 +321,13 @@ static HashTable *saproxy_properties_get(zval *object TSRMLS_DC)
return NULL;
}
-static union _zend_function *saproxy_method_get(zval **object, char *name, int len TSRMLS_DC)
+static union _zend_function *saproxy_method_get(zval **object, const char *name, int len, const zend_literal *key TSRMLS_DC)
{
/* no methods */
return NULL;
}
-static int saproxy_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
+static int saproxy_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
{
return FAILURE;
}
@@ -343,7 +343,7 @@ static zend_class_entry *saproxy_class_entry_get(const zval *object TSRMLS_DC)
return php_com_saproxy_class_entry;
}
-static int saproxy_class_name_get(const zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
+static int saproxy_class_name_get(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
{
*class_name = estrndup(php_com_saproxy_class_entry->name, php_com_saproxy_class_entry->name_length);
*class_name_len = php_com_saproxy_class_entry->name_length;
diff --git a/ext/com_dotnet/com_typeinfo.c b/ext/com_dotnet/com_typeinfo.c
index e860872ebb..f57b97f0da 100644
--- a/ext/com_dotnet/com_typeinfo.c
+++ b/ext/com_dotnet/com_typeinfo.c
@@ -187,6 +187,10 @@ PHP_COM_DOTNET_API int php_com_import_typelib(ITypeLib *TL, int mode, int codepa
const_name = php_com_olestring_to_string(bstr_ids, &c.name_len, codepage TSRMLS_CC);
c.name = zend_strndup(const_name, c.name_len);
efree(const_name);
+ if(c.name == NULL) {
+ ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
+ continue;
+ }
c.name_len++; /* include NUL */
SysFreeString(bstr_ids);
diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c
index 16050d5077..2adccb5881 100644
--- a/ext/com_dotnet/com_variant.c
+++ b/ext/com_dotnet/com_variant.c
@@ -446,7 +446,7 @@ PHP_FUNCTION(com_variant_create_instance)
if (FAILED(res)) {
char *werr, *msg;
- werr = php_win_err(res);
+ werr = php_win32_error_to_msg(res);
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
LocalFree(werr);
@@ -1027,7 +1027,7 @@ PHP_FUNCTION(variant_set_type)
} else {
char *werr, *msg;
- werr = php_win_err(res);
+ werr = php_win32_error_to_msg(res);
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
LocalFree(werr);
@@ -1061,7 +1061,7 @@ PHP_FUNCTION(variant_cast)
} else {
char *werr, *msg;
- werr = php_win_err(res);
+ werr = php_win32_error_to_msg(res);
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
LocalFree(werr);
diff --git a/ext/com_dotnet/com_wrapper.c b/ext/com_dotnet/com_wrapper.c
index 27a5685863..c8e59f95cc 100644
--- a/ext/com_dotnet/com_wrapper.c
+++ b/ext/com_dotnet/com_wrapper.c
@@ -52,12 +52,12 @@ typedef struct {
static int le_dispatch;
-static void disp_destructor(php_dispatchex *disp);
+static void disp_destructor(php_dispatchex *disp TSRMLS_DC);
static void dispatch_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
php_dispatchex *disp = (php_dispatchex *)rsrc->ptr;
- disp_destructor(disp);
+ disp_destructor(disp TSRMLS_CC);
}
int php_com_wrapper_minit(INIT_FUNC_ARGS)
@@ -86,15 +86,9 @@ static inline void trace(char *fmt, ...)
}
/* }}} */
-#ifdef ZTS
-# define TSRMLS_FIXED() TSRMLS_FETCH();
-#else
-# define TSRMLS_FIXED()
-#endif
-
#define FETCH_DISP(methname) \
- TSRMLS_FIXED() \
php_dispatchex *disp = (php_dispatchex*)This; \
+ TSRMLS_FETCH(); \
if (COMG(rshutdown_started)) { \
trace(" PHP Object:%p (name:unknown) %s\n", disp->object, methname); \
} else { \
@@ -554,15 +548,13 @@ static php_dispatchex *disp_constructor(zval *object TSRMLS_DC)
Z_ADDREF_P(object);
disp->object = object;
- disp->id = zend_list_insert(disp, le_dispatch);
+ disp->id = zend_list_insert(disp, le_dispatch TSRMLS_CC);
return disp;
}
-static void disp_destructor(php_dispatchex *disp)
-{
- TSRMLS_FETCH();
-
+static void disp_destructor(php_dispatchex *disp TSRMLS_DC)
+{
/* Object store not available during request shutdown */
if (COMG(rshutdown_started)) {
trace("destroying COM wrapper for PHP object %p (name:unknown)\n", disp->object);
diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h
index 6f7f0305f8..f821bec976 100644
--- a/ext/com_dotnet/php_com_dotnet_internal.h
+++ b/ext/com_dotnet/php_com_dotnet_internal.h
@@ -29,9 +29,6 @@
#include <dispex.h>
#include "win32/winutil.h"
-/* brain-death in winutil.h defines the macro to hide the useful function... */
-#undef php_win_err
-
typedef struct _php_com_dotnet_object {
zend_object zo;
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index 7b72873038..00dbfd3d25 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -10,7 +10,7 @@
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | license@php.net so we can mail you 6 copy immediately. |
+----------------------------------------------------------------------+
| Author: Sterling Hughes <sterling@php.net> |
+----------------------------------------------------------------------+
@@ -164,16 +164,14 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
# define php_curl_ret(__ret) RETVAL_FALSE; return;
#endif
-static int php_curl_option_url(php_curl *ch, const char *url, const int len) /* {{{ */
+static int php_curl_option_url(php_curl *ch, const char *url, const int len TSRMLS_DC) /* {{{ */
{
CURLcode error = CURLE_OK;
#if LIBCURL_VERSION_NUM < 0x071100
char *copystr = NULL;
#endif
- TSRMLS_FETCH();
-
- /* Disable file:// if open_basedir or safe_mode are used */
- if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
+ /* Disable file:// if open_basedir are used */
+ if (PG(open_basedir) && *PG(open_basedir)) {
#if LIBCURL_VERSION_NUM >= 0x071304
error = curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
#else
@@ -715,6 +713,14 @@ PHP_MINIT_FUNCTION(curl)
#if LIBCURL_VERSION_NUM >= 0x071202
REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL);
#endif
+#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */
+ REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_IP);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */
+ REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_PORT);
+ REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_IP);
+ REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT);
+#endif
/* cURL protocol constants (curl_version) */
@@ -1547,8 +1553,6 @@ PHP_FUNCTION(curl_init)
MAKE_STD_ZVAL(clone);
ch->clone = clone;
-
-
curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str);
@@ -1572,7 +1576,7 @@ PHP_FUNCTION(curl_init)
#endif
if (url) {
- if (!php_curl_option_url(ch, url, url_len)) {
+ if (!php_curl_option_url(ch, url, url_len TSRMLS_CC)) {
_php_curl_close_ex(ch TSRMLS_CC);
RETURN_FALSE;
}
@@ -1679,6 +1683,11 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
CURLcode error=CURLE_OK;
switch (option) {
+ /* Long options */
+ case CURLOPT_SSL_VERIFYHOST:
+ if(Z_TYPE_PP(zvalue)==IS_BOOL && Z_BVAL_PP(zvalue)) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "CURLOPT_SSL_VERIFYHOST set to true which disables common name validation (setting CURLOPT_SSL_VERIFYHOST to 2 enables common name validation)");
+ }
case CURLOPT_INFILESIZE:
case CURLOPT_VERBOSE:
case CURLOPT_HEADER:
@@ -1717,7 +1726,6 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
#if LIBCURL_VERSION_NUM > 0x071002
case CURLOPT_CONNECTTIMEOUT_MS:
#endif
- case CURLOPT_SSL_VERIFYHOST:
case CURLOPT_SSL_VERIFYPEER:
case CURLOPT_DNS_USE_GLOBAL_CACHE:
case CURLOPT_NOSIGNAL:
@@ -1767,8 +1775,8 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
convert_to_long_ex(zvalue);
#if LIBCURL_VERSION_NUM >= 0x71304
if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
- ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when in safe_mode or an open_basedir is set");
+ (PG(open_basedir) && *PG(open_basedir)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set");
RETVAL_FALSE;
return 1;
}
@@ -1784,9 +1792,9 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
#endif
case CURLOPT_FOLLOWLOCATION:
convert_to_long_ex(zvalue);
- if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
if (Z_LVAL_PP(zvalue) != 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set");
RETVAL_FALSE;
return 1;
}
@@ -1838,14 +1846,14 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
option == CURLOPT_SSH_PUBLIC_KEYFILE || option == CURLOPT_SSH_PRIVATE_KEYFILE
) {
- if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) {
+ if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) {
RETVAL_FALSE;
return 1;
}
}
#endif
if (option == CURLOPT_URL) {
- if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue))) {
+ if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue) TSRMLS_CC)) {
RETVAL_FALSE;
return 1;
}
@@ -2027,10 +2035,6 @@ string_copy:
HashTable *postfields;
struct HttpPost *first = NULL;
struct HttpPost *last = NULL;
- char *postval;
- char *string_key = NULL;
- ulong num_key;
- uint string_key_len;
postfields = HASH_OF(*zvalue);
if (!postfields) {
@@ -2043,12 +2047,26 @@ string_copy:
zend_hash_get_current_data(postfields, (void **) &current) == SUCCESS;
zend_hash_move_forward(postfields)
) {
+ char *postval;
+ char *string_key = NULL;
+ uint string_key_len;
+ ulong num_key;
+ int numeric_key;
SEPARATE_ZVAL(current);
convert_to_string_ex(current);
zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL);
+ /* Pretend we have a string_key here */
+ if(!string_key) {
+ spprintf(&string_key, 0, "%ld", num_key);
+ string_key_len = strlen(string_key)+1;
+ numeric_key = 1;
+ } else {
+ numeric_key = 0;
+ }
+
postval = Z_STRVAL_PP(current);
/* The arguments after _NAMELENGTH and _CONTENTSLENGTH
@@ -2064,8 +2082,8 @@ string_copy:
if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) {
*filename = '\0';
}
- /* safe_mode / open_basedir check */
- if (php_check_open_basedir(postval TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(postval, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
+ /* open_basedir check */
+ if (php_check_open_basedir(postval TSRMLS_CC)) {
RETVAL_FALSE;
return 1;
}
@@ -2090,6 +2108,10 @@ string_copy:
CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current),
CURLFORM_END);
}
+
+ if (numeric_key) {
+ efree(string_key);
+ }
}
SAVE_CURL_ERROR(ch, error);
@@ -2154,8 +2176,8 @@ string_copy:
break;
}
- /* the following options deal with files, therefor safe_mode & open_basedir checks
- * are required.
+ /* the following options deal with files, therefore the open_basedir check
+ * is required.
*/
case CURLOPT_COOKIEJAR:
case CURLOPT_SSLCERT:
@@ -2167,7 +2189,7 @@ string_copy:
convert_to_string_ex(zvalue);
- if ((Z_STRLEN_PP(zvalue) && php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) || (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(zvalue), "rb+", CHECKUID_CHECK_MODE_PARAM))) {
+ if (Z_STRLEN_PP(zvalue) && php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) {
RETVAL_FALSE;
return 1;
}
@@ -2438,6 +2460,22 @@ PHP_FUNCTION(curl_getinfo)
CAAZ("certinfo", listcode);
}
#endif
+#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */
+ if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_IP, &s_code) == CURLE_OK) {
+ CAAS("primary_ip", s_code);
+ }
+#endif
+#if LIBCURL_VERSION_NUM > 0x071500
+ if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_PORT, &l_code) == CURLE_OK) {
+ CAAL("primary_port", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_IP, &s_code) == CURLE_OK) {
+ CAAS("local_ip", s_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_PORT, &l_code) == CURLE_OK) {
+ CAAL("local_port", l_code);
+ }
+#endif
#if LIBCURL_VERSION_NUM >= 0x071202
if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) {
CAAS("redirect_url", s_code);
@@ -2448,6 +2486,13 @@ PHP_FUNCTION(curl_getinfo)
}
} else {
switch (option) {
+ /* string variable types */
+#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */
+ case CURLINFO_PRIMARY_IP:
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */
+ case CURLINFO_LOCAL_IP:
+#endif
case CURLINFO_PRIVATE:
case CURLINFO_EFFECTIVE_URL:
case CURLINFO_CONTENT_TYPE:
@@ -2464,6 +2509,11 @@ PHP_FUNCTION(curl_getinfo)
}
break;
}
+ /* Long variable types */
+#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */
+ case CURLINFO_PRIMARY_PORT:
+ case CURLINFO_LOCAL_PORT:
+#endif
case CURLINFO_HTTP_CODE:
case CURLINFO_HEADER_SIZE:
case CURLINFO_REQUEST_SIZE:
@@ -2479,6 +2529,7 @@ PHP_FUNCTION(curl_getinfo)
}
break;
}
+ /* Double variable types */
case CURLINFO_TOTAL_TIME:
case CURLINFO_NAMELOOKUP_TIME:
case CURLINFO_CONNECT_TIME:
diff --git a/ext/curl/streams.c b/ext/curl/streams.c
index e317285c31..821c2ecad8 100644
--- a/ext/curl/streams.c
+++ b/ext/curl/streams.c
@@ -399,7 +399,7 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename,
}
}
if (mr > 1) {
- if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
} else {
curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
@@ -407,7 +407,7 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename,
curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, mr);
}
} else {
- if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
} else {
curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
diff --git a/ext/curl/tests/bug55767.phpt b/ext/curl/tests/bug55767.phpt
new file mode 100644
index 0000000000..321f67ba60
--- /dev/null
+++ b/ext/curl/tests/bug55767.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Test curl_opt() function with POST params from array with a numeric key
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl sending through GET an POST ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost&get_param=Hello%20World";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, array('Hello'=>'World','Foo'=>'Bar',100=>'John Doe'));
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl sending through GET an POST ***
+string(203) "array(2) {
+ ["test"]=>
+ string(7) "getpost"
+ ["get_param"]=>
+ string(11) "Hello World"
+}
+array(3) {
+ ["Hello"]=>
+ string(5) "World"
+ ["Foo"]=>
+ string(3) "Bar"
+ [100]=>
+ string(8) "John Doe"
+}
+"
+===DONE===
diff --git a/ext/curl/tests/bug63363.phpt b/ext/curl/tests/bug63363.phpt
new file mode 100644
index 0000000000..43deaa2346
--- /dev/null
+++ b/ext/curl/tests/bug63363.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #63363 (CURL silently accepts boolean value for SSL_VERIFYHOST)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+
+?>
+--FILE--
+<?php
+$ch = curl_init();
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false));
+/* Case that should throw an error */
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2));
+
+curl_close($ch);
+?>
+--EXPECTF--
+bool(true)
+
+Notice: curl_setopt(): CURLOPT_SSL_VERIFYHOST set to true which disables common name validation (setting CURLOPT_SSL_VERIFYHOST to 2 enables common name validation) in %s on line %d
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt
index c00e1d2080..7a778f3692 100644
--- a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt
+++ b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt
@@ -1,5 +1,5 @@
--TEST--
-CURLOPT_FOLLOWLOCATION case check safe_mode and open_basedir
+CURLOPT_FOLLOWLOCATION case check open_basedir
--CREDITS--
WHITE new media architects - Dennis
--INI--
@@ -17,6 +17,6 @@ curl_close($ch);
var_dump($succes);
?>
--EXPECTF--
-Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when %r(safe_mode is enabled or an )?%ropen_basedir is set in %s.php on line %d
+Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set in %s.php on line %d
bool(false)
diff --git a/ext/curl/tests/curl_setopt_basic001.phpt b/ext/curl/tests/curl_setopt_basic001.phpt
deleted file mode 100644
index 9c92785b0a..0000000000
--- a/ext/curl/tests/curl_setopt_basic001.phpt
+++ /dev/null
@@ -1,35 +0,0 @@
---TEST--
-curl_setopt basic tests.
---CREDITS--
-Paul Sohier
-#phptestfest utrecht
---INI--
-safe_mode=On
---SKIPIF--
-<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?>
---FILE--
-<?php
-
-$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
-
-// start testing
-echo "*** Testing curl_setopt with CURLOPT_FOLLOWLOCATION in safemode\n";
-
-$url = "{$host}/";
-$ch = curl_init();
-
-ob_start(); // start output buffering
-curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
-
-$curl_content = curl_exec($ch);
-curl_close($ch);
-
-var_dump( $curl_content );
-?>
---EXPECTF--
-Deprecated: Directive 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line 0
-*** Testing curl_setopt with CURLOPT_FOLLOWLOCATION in safemode
-
-Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set in %s on line %d
-bool(false)
-
diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c
index 0e21ecc00c..4829da6c91 100644
--- a/ext/date/lib/parse_date.c
+++ b/ext/date/lib/parse_date.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Mon Dec 5 22:02:41 2011 */
+/* Generated by re2c 0.13.5 on Sun Sep 30 20:14:42 2012 */
#line 1 "ext/date/lib/parse_date.re"
/*
+----------------------------------------------------------------------+
@@ -995,7 +995,7 @@ std:
}
yy2:
YYDEBUG(2, *YYCURSOR);
-#line 1082 "ext/date/lib/parse_date.re"
+#line 1083 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("firstdayof | lastdayof");
TIMELIB_INIT;
@@ -1034,7 +1034,7 @@ yy3:
}
yy4:
YYDEBUG(4, *YYCURSOR);
-#line 1676 "ext/date/lib/parse_date.re"
+#line 1677 "ext/date/lib/parse_date.re"
{
int tz_not_found;
DEBUG_OUTPUT("tzcorrection | tz");
@@ -1358,7 +1358,7 @@ yy12:
if (yych <= '9') goto yy1385;
yy13:
YYDEBUG(13, *YYCURSOR);
-#line 1771 "ext/date/lib/parse_date.re"
+#line 1772 "ext/date/lib/parse_date.re"
{
add_error(s, "Unexpected character");
goto std;
@@ -2420,7 +2420,7 @@ yy49:
if (yych <= '9') goto yy55;
yy50:
YYDEBUG(50, *YYCURSOR);
-#line 1760 "ext/date/lib/parse_date.re"
+#line 1761 "ext/date/lib/parse_date.re"
{
goto std;
}
@@ -2433,7 +2433,7 @@ yy52:
YYDEBUG(52, *YYCURSOR);
++YYCURSOR;
YYDEBUG(53, *YYCURSOR);
-#line 1765 "ext/date/lib/parse_date.re"
+#line 1766 "ext/date/lib/parse_date.re"
{
s->pos = cursor; s->line++;
goto std;
@@ -2825,7 +2825,7 @@ yy72:
if (yych == 's') goto yy74;
yy73:
YYDEBUG(73, *YYCURSOR);
-#line 1744 "ext/date/lib/parse_date.re"
+#line 1745 "ext/date/lib/parse_date.re"
{
timelib_ull i;
DEBUG_OUTPUT("relative");
@@ -3602,7 +3602,7 @@ yy166:
}
yy167:
YYDEBUG(167, *YYCURSOR);
-#line 1607 "ext/date/lib/parse_date.re"
+#line 1608 "ext/date/lib/parse_date.re"
{
const timelib_relunit* relunit;
DEBUG_OUTPUT("daytext");
@@ -4139,7 +4139,7 @@ yy193:
}
yy194:
YYDEBUG(194, *YYCURSOR);
-#line 1666 "ext/date/lib/parse_date.re"
+#line 1667 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("monthtext");
TIMELIB_INIT;
@@ -4199,7 +4199,7 @@ yy198:
}
yy199:
YYDEBUG(199, *YYCURSOR);
-#line 1412 "ext/date/lib/parse_date.re"
+#line 1413 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("datetextual | datenoyear");
@@ -4481,7 +4481,7 @@ yy222:
}
yy223:
YYDEBUG(223, *YYCURSOR);
-#line 1714 "ext/date/lib/parse_date.re"
+#line 1715 "ext/date/lib/parse_date.re"
{
int tz_not_found;
DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
@@ -5208,7 +5208,7 @@ yy278:
YYDEBUG(278, *YYCURSOR);
++YYCURSOR;
YYDEBUG(279, *YYCURSOR);
-#line 1690 "ext/date/lib/parse_date.re"
+#line 1691 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
TIMELIB_INIT;
@@ -5409,7 +5409,7 @@ yy294:
++YYCURSOR;
yy295:
YYDEBUG(295, *YYCURSOR);
-#line 1384 "ext/date/lib/parse_date.re"
+#line 1385 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("datenoday");
@@ -6642,7 +6642,7 @@ yy362:
if (yych <= '9') goto yy365;
yy364:
YYDEBUG(364, *YYCURSOR);
-#line 1528 "ext/date/lib/parse_date.re"
+#line 1529 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("pgtextshort");
@@ -7293,7 +7293,7 @@ yy392:
}
yy393:
YYDEBUG(393, *YYCURSOR);
-#line 1586 "ext/date/lib/parse_date.re"
+#line 1587 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("ago");
TIMELIB_INIT;
@@ -9063,7 +9063,7 @@ yy454:
++YYCURSOR;
yy455:
YYDEBUG(455, *YYCURSOR);
-#line 1289 "ext/date/lib/parse_date.re"
+#line 1290 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
TIMELIB_INIT;
@@ -9634,7 +9634,7 @@ yy475:
}
yy476:
YYDEBUG(476, *YYCURSOR);
-#line 1426 "ext/date/lib/parse_date.re"
+#line 1427 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("datenoyearrev");
TIMELIB_INIT;
@@ -9786,7 +9786,7 @@ yy488:
YYDEBUG(488, *YYCURSOR);
++YYCURSOR;
YYDEBUG(489, *YYCURSOR);
-#line 1144 "ext/date/lib/parse_date.re"
+#line 1145 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
TIMELIB_INIT;
@@ -9815,7 +9815,7 @@ yy490:
}
yy491:
YYDEBUG(491, *YYCURSOR);
-#line 1181 "ext/date/lib/parse_date.re"
+#line 1182 "ext/date/lib/parse_date.re"
{
int tz_not_found;
DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
@@ -10150,7 +10150,7 @@ yy523:
YYDEBUG(523, *YYCURSOR);
++YYCURSOR;
YYDEBUG(524, *YYCURSOR);
-#line 1161 "ext/date/lib/parse_date.re"
+#line 1162 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("mssqltime");
TIMELIB_INIT;
@@ -10275,7 +10275,7 @@ yy534:
if (yych <= '9') goto yy541;
yy535:
YYDEBUG(535, *YYCURSOR);
-#line 1343 "ext/date/lib/parse_date.re"
+#line 1344 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("datefull");
@@ -11026,7 +11026,7 @@ yy605:
YYDEBUG(606, *YYCURSOR);
++YYCURSOR;
YYDEBUG(607, *YYCURSOR);
-#line 1358 "ext/date/lib/parse_date.re"
+#line 1359 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("pointed date YYYY");
TIMELIB_INIT;
@@ -11073,7 +11073,7 @@ yy611:
if (yych <= '9') goto yy605;
yy612:
YYDEBUG(612, *YYCURSOR);
-#line 1370 "ext/date/lib/parse_date.re"
+#line 1371 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("pointed date YY");
@@ -11727,7 +11727,7 @@ yy656:
}
yy657:
YYDEBUG(657, *YYCURSOR);
-#line 1329 "ext/date/lib/parse_date.re"
+#line 1330 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("gnudateshort");
@@ -11846,7 +11846,7 @@ yy666:
}
yy667:
YYDEBUG(667, *YYCURSOR);
-#line 1273 "ext/date/lib/parse_date.re"
+#line 1274 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("americanshort | american");
@@ -12094,7 +12094,7 @@ yy700:
if (yych <= ':') goto yy704;
yy701:
YYDEBUG(701, *YYCURSOR);
-#line 1556 "ext/date/lib/parse_date.re"
+#line 1557 "ext/date/lib/parse_date.re"
{
int tz_not_found;
DEBUG_OUTPUT("clf");
@@ -12666,7 +12666,7 @@ yy763:
}
yy764:
YYDEBUG(764, *YYCURSOR);
-#line 1301 "ext/date/lib/parse_date.re"
+#line 1302 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("iso8601date2");
@@ -12718,7 +12718,7 @@ yy771:
YYDEBUG(771, *YYCURSOR);
++YYCURSOR;
YYDEBUG(772, *YYCURSOR);
-#line 1542 "ext/date/lib/parse_date.re"
+#line 1543 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("pgtextreverse");
@@ -12869,7 +12869,7 @@ yy783:
}
yy784:
YYDEBUG(784, *YYCURSOR);
-#line 1577 "ext/date/lib/parse_date.re"
+#line 1578 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("year4");
TIMELIB_INIT;
@@ -13028,7 +13028,7 @@ yy793:
}
yy794:
YYDEBUG(794, *YYCURSOR);
-#line 1398 "ext/date/lib/parse_date.re"
+#line 1399 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("datenodayrev");
@@ -13256,7 +13256,7 @@ yy814:
if (yych <= '7') goto yy817;
yy815:
YYDEBUG(815, *YYCURSOR);
-#line 1509 "ext/date/lib/parse_date.re"
+#line 1510 "ext/date/lib/parse_date.re"
{
timelib_sll w, d;
DEBUG_OUTPUT("isoweek");
@@ -13284,7 +13284,7 @@ yy817:
YYDEBUG(817, *YYCURSOR);
++YYCURSOR;
YYDEBUG(818, *YYCURSOR);
-#line 1490 "ext/date/lib/parse_date.re"
+#line 1491 "ext/date/lib/parse_date.re"
{
timelib_sll w, d;
DEBUG_OUTPUT("isoweekday");
@@ -13366,7 +13366,7 @@ yy821:
}
yy822:
YYDEBUG(822, *YYCURSOR);
-#line 1476 "ext/date/lib/parse_date.re"
+#line 1477 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("pgydotd");
@@ -13482,7 +13482,7 @@ yy842:
++YYCURSOR;
yy843:
YYDEBUG(843, *YYCURSOR);
-#line 1450 "ext/date/lib/parse_date.re"
+#line 1451 "ext/date/lib/parse_date.re"
{
int tz_not_found;
DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
@@ -13769,7 +13769,7 @@ yy848:
}
yy849:
YYDEBUG(849, *YYCURSOR);
-#line 1438 "ext/date/lib/parse_date.re"
+#line 1439 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("datenocolon");
TIMELIB_INIT;
@@ -14700,7 +14700,7 @@ yy973:
if (yych <= '9') goto yy996;
yy974:
YYDEBUG(974, *YYCURSOR);
-#line 1315 "ext/date/lib/parse_date.re"
+#line 1316 "ext/date/lib/parse_date.re"
{
int length = 0;
DEBUG_OUTPUT("gnudateshorter");
@@ -15722,7 +15722,7 @@ yy1066:
}
yy1068:
YYDEBUG(1068, *YYCURSOR);
-#line 1207 "ext/date/lib/parse_date.re"
+#line 1208 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("gnunocolon");
TIMELIB_INIT;
@@ -15836,7 +15836,7 @@ yy1075:
}
yy1076:
YYDEBUG(1076, *YYCURSOR);
-#line 1253 "ext/date/lib/parse_date.re"
+#line 1254 "ext/date/lib/parse_date.re"
{
int tz_not_found;
DEBUG_OUTPUT("iso8601nocolon");
@@ -16753,7 +16753,7 @@ yy1117:
}
yy1118:
YYDEBUG(1118, *YYCURSOR);
-#line 1649 "ext/date/lib/parse_date.re"
+#line 1650 "ext/date/lib/parse_date.re"
{
timelib_sll i;
int behavior = 0;
@@ -16820,7 +16820,7 @@ yy1126:
YYDEBUG(1126, *YYCURSOR);
++YYCURSOR;
YYDEBUG(1127, *YYCURSOR);
-#line 1122 "ext/date/lib/parse_date.re"
+#line 1123 "ext/date/lib/parse_date.re"
{
timelib_sll i;
int behavior = 0;
@@ -16949,7 +16949,7 @@ yy1141:
}
yy1142:
YYDEBUG(1142, *YYCURSOR);
-#line 1625 "ext/date/lib/parse_date.re"
+#line 1626 "ext/date/lib/parse_date.re"
{
timelib_sll i;
int behavior = 0;
@@ -19649,7 +19649,7 @@ yy1294:
goto yy1298;
yy1295:
YYDEBUG(1295, *YYCURSOR);
-#line 1099 "ext/date/lib/parse_date.re"
+#line 1100 "ext/date/lib/parse_date.re"
{
DEBUG_OUTPUT("backof | frontof");
TIMELIB_INIT;
@@ -21382,11 +21382,12 @@ yy1387:
s->time->is_localtime = 1;
s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
s->time->z = 0;
+ s->time->dst = 0;
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
}
-#line 21390 "ext/date/lib/parse_date.c"
+#line 21391 "ext/date/lib/parse_date.c"
yy1388:
YYDEBUG(1388, *YYCURSOR);
yych = *++YYCURSOR;
@@ -21833,7 +21834,7 @@ yy1417:
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
}
-#line 21837 "ext/date/lib/parse_date.c"
+#line 21838 "ext/date/lib/parse_date.c"
yy1418:
YYDEBUG(1418, *YYCURSOR);
yych = *++YYCURSOR;
@@ -21877,7 +21878,7 @@ yy1420:
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
}
-#line 21881 "ext/date/lib/parse_date.c"
+#line 21882 "ext/date/lib/parse_date.c"
yy1421:
YYDEBUG(1421, *YYCURSOR);
yych = *++YYCURSOR;
@@ -23897,7 +23898,7 @@ yy1500:
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
}
-#line 23901 "ext/date/lib/parse_date.c"
+#line 23902 "ext/date/lib/parse_date.c"
yy1501:
YYDEBUG(1501, *YYCURSOR);
yych = *++YYCURSOR;
@@ -24047,7 +24048,7 @@ yy1508:
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
}
-#line 24051 "ext/date/lib/parse_date.c"
+#line 24052 "ext/date/lib/parse_date.c"
yy1509:
YYDEBUG(1509, *YYCURSOR);
yyaccept = 0;
@@ -24591,7 +24592,7 @@ yy1531:
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
}
-#line 24595 "ext/date/lib/parse_date.c"
+#line 24596 "ext/date/lib/parse_date.c"
yy1532:
YYDEBUG(1532, *YYCURSOR);
yyaccept = 0;
@@ -24764,7 +24765,7 @@ yy1537:
goto yy1531;
}
}
-#line 1775 "ext/date/lib/parse_date.re"
+#line 1776 "ext/date/lib/parse_date.re"
}
@@ -25070,6 +25071,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, int len, tim
s->time->is_localtime = 1;
s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
s->time->z = 0;
+ s->time->dst = 0;
break;
case 'e': /* timezone */
diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re
index cca88580eb..5a8b6134b9 100644
--- a/ext/date/lib/parse_date.re
+++ b/ext/date/lib/parse_date.re
@@ -1073,6 +1073,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of
s->time->is_localtime = 1;
s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
s->time->z = 0;
+ s->time->dst = 0;
TIMELIB_DEINIT;
return TIMELIB_RELATIVE;
@@ -2077,6 +2078,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, int len, tim
s->time->is_localtime = 1;
s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
s->time->z = 0;
+ s->time->dst = 0;
break;
case 'e': /* timezone */
diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c
index 5f052221b8..d52c24d38f 100644
--- a/ext/date/lib/parse_iso_intervals.c
+++ b/ext/date/lib/parse_iso_intervals.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Mon Dec 5 22:02:31 2011 */
+/* Generated by re2c 0.13.5 on Mon Dec 5 22:02:27 2011 */
#line 1 "ext/date/lib/parse_iso_intervals.re"
/*
+----------------------------------------------------------------------+
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index e8a457052e..13e7b753d3 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -566,8 +566,8 @@ static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC);
static HashTable *date_object_get_properties(zval *object TSRMLS_DC);
static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC);
-zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC);
-void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC);
+zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC);
+void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC);
/* {{{ Module struct */
zend_module_entry date_module_entry = {
@@ -845,17 +845,10 @@ timelib_tzinfo *php_date_parse_tzfile_wrapper(char *formal_tzname, const timelib
/* {{{ Helper functions */
static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC)
{
- char *env;
-
/* Checking configure timezone */
if (DATEG(timezone) && (strlen(DATEG(timezone)) > 0)) {
return DATEG(timezone);
}
- /* Check environment variable */
- env = getenv("TZ");
- if (env && *env && timelib_timezone_id_is_valid(env, tzdb)) {
- return env;
- }
/* Check config setting for default timezone */
if (!DATEG(default_timezone)) {
/* Special case: ext/date wasn't initialized yet */
@@ -870,73 +863,8 @@ static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC)
} else if (*DATEG(default_timezone) && timelib_timezone_id_is_valid(DATEG(default_timezone), tzdb)) {
return DATEG(default_timezone);
}
-#if HAVE_TM_ZONE
- /* Try to guess timezone from system information */
- {
- struct tm *ta, tmbuf;
- time_t the_time;
- char *tzid = NULL;
-
- the_time = time(NULL);
- ta = php_localtime_r(&the_time, &tmbuf);
- if (ta) {
- tzid = timelib_timezone_id_from_abbr(ta->tm_zone, ta->tm_gmtoff, ta->tm_isdst);
- }
- if (! tzid) {
- tzid = "UTC";
- }
-
- php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%s/%.1f/%s' instead", tzid, ta ? ta->tm_zone : "Unknown", ta ? (float) (ta->tm_gmtoff / 3600) : 0, ta ? (ta->tm_isdst ? "DST" : "no DST") : "Unknown");
- return tzid;
- }
-#endif
-#ifdef PHP_WIN32
- {
- char *tzid;
- TIME_ZONE_INFORMATION tzi;
-
- switch (GetTimeZoneInformation(&tzi))
- {
- /* DST in effect */
- case TIME_ZONE_ID_DAYLIGHT:
- /* If user has disabled DST in the control panel, Windows returns 0 here */
- if (tzi.DaylightBias == 0) {
- goto php_win_std_time;
- }
-
- tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.DaylightBias) * -60, 1);
- if (! tzid) {
- tzid = "UTC";
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%.1f/DST' instead", tzid, ((tzi.Bias + tzi.DaylightBias) / -60.0));
- break;
-
- /* no DST or not in effect */
- case TIME_ZONE_ID_UNKNOWN:
- case TIME_ZONE_ID_STANDARD:
- default:
-php_win_std_time:
- tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.StandardBias) * -60, 0);
- if (! tzid) {
- tzid = "UTC";
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%.1f/no DST' instead", tzid, ((tzi.Bias + tzi.StandardBias) / -60.0));
- break;
-
- }
- return tzid;
- }
-#elif defined(NETWARE)
- /* Try to guess timezone from system information */
- {
- char *tzid = timelib_timezone_id_from_abbr("", ((_timezone * -1) + (daylightOffset * daylightOnOff)), daylightOnOff);
- if (tzid) {
- return tzid;
- }
- }
-#endif
/* Fallback to UTC */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We had to select 'UTC' because your platform doesn't provide functionality for the guessing algorithm");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone.");
return "UTC";
}
@@ -1213,14 +1141,13 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt
/* {{{ php_idate
*/
-PHPAPI int php_idate(char format, time_t ts, int localtime)
+PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC)
{
timelib_time *t;
timelib_tzinfo *tzi;
int retval = -1;
timelib_time_offset *offset = NULL;
timelib_sll isoweek, isoyear;
- TSRMLS_FETCH();
t = timelib_time_ctor();
@@ -1346,7 +1273,7 @@ PHP_FUNCTION(idate)
ts = time(NULL);
}
- ret = php_idate(format[0], ts, 0);
+ ret = php_idate(format[0], ts, 0 TSRMLS_CC);
if (ret == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized date format token.");
RETURN_FALSE;
@@ -2026,7 +1953,6 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
{
php_date_obj *intern;
zend_object_value retval;
- zval *tmp;
intern = emalloc(sizeof(php_date_obj));
memset(intern, 0, sizeof(php_date_obj));
@@ -2035,7 +1961,7 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
}
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_date;
@@ -2150,7 +2076,6 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
{
php_timezone_obj *intern;
zend_object_value retval;
- zval *tmp;
intern = emalloc(sizeof(php_timezone_obj));
memset(intern, 0, sizeof(php_timezone_obj));
@@ -2159,7 +2084,7 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
}
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_timezone;
@@ -2206,7 +2131,6 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
{
php_interval_obj *intern;
zend_object_value retval;
- zval *tmp;
intern = emalloc(sizeof(php_interval_obj));
memset(intern, 0, sizeof(php_interval_obj));
@@ -2215,7 +2139,7 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
}
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_interval;
@@ -2282,7 +2206,6 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
{
php_period_obj *intern;
zend_object_value retval;
- zval *tmp;
intern = emalloc(sizeof(php_period_obj));
memset(intern, 0, sizeof(php_period_obj));
@@ -2291,7 +2214,7 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
}
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC);
retval.handlers = &date_object_handlers_period;
@@ -3495,7 +3418,7 @@ static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *forma
}
/* {{{ date_interval_read_property */
-zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC)
+zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
php_interval_obj *obj;
zval *retval;
@@ -3507,12 +3430,13 @@ zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
member = &tmp_member;
+ key = NULL;
}
obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC);
if (!obj->initialized) {
- retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC);
+ retval = (zend_get_std_object_handlers())->read_property(object, member, type, key TSRMLS_CC);
if (member == &tmp_member) {
zval_dtor(member);
}
@@ -3534,7 +3458,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC
GET_VALUE_FROM_STRUCT(invert, "invert");
GET_VALUE_FROM_STRUCT(days, "days");
/* didn't find any */
- retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC);
+ retval = (zend_get_std_object_handlers())->read_property(object, member, type, key TSRMLS_CC);
if (member == &tmp_member) {
zval_dtor(member);
@@ -3557,7 +3481,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC
/* }}} */
/* {{{ date_interval_write_property */
-void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
php_interval_obj *obj;
zval tmp_member, tmp_value;
@@ -3567,12 +3491,13 @@ void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
member = &tmp_member;
+ key = NULL;
}
obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC);
if (!obj->initialized) {
- (zend_get_std_object_handlers())->write_property(object, member, value TSRMLS_CC);
+ (zend_get_std_object_handlers())->write_property(object, member, value, key TSRMLS_CC);
if (member == &tmp_member) {
zval_dtor(member);
}
@@ -3603,7 +3528,7 @@ void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS
SET_VALUE_FROM_STRUCT(s, "s");
SET_VALUE_FROM_STRUCT(invert, "invert");
/* didn't find any */
- (zend_get_std_object_handlers())->write_property(object, member, value TSRMLS_CC);
+ (zend_get_std_object_handlers())->write_property(object, member, value, key TSRMLS_CC);
} while(0);
if (member == &tmp_member) {
diff --git a/ext/date/php_date.h b/ext/date/php_date.h
index 77bb14014f..b2f4e9fd27 100644
--- a/ext/date/php_date.h
+++ b/ext/date/php_date.h
@@ -165,7 +165,7 @@ ZEND_END_MODULE_GLOBALS(date)
/* Backwards compability wrapper */
PHPAPI signed long php_parse_date(char *string, signed long *now);
PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt);
-PHPAPI int php_idate(char format, time_t ts, int localtime);
+PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC);
#if HAVE_STRFTIME
#define _php_strftime php_strftime
PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gm);
diff --git a/ext/date/tests/bug52062.phpt b/ext/date/tests/bug52062.phpt
index 81e767b0f0..1d814377c6 100644
--- a/ext/date/tests/bug52062.phpt
+++ b/ext/date/tests/bug52062.phpt
@@ -4,6 +4,8 @@ Bug #52062 (large timestamps with DateTime::getTimestamp and DateTime::setTimest
<?php
if (PHP_INT_SIZE == 8) die('skip 32-bit only');
?>
+--XFAIL--
+Waiting for resolution of the 32-bit case.
--INI--
date.timezone=UTC
--FILE--
diff --git a/ext/date/tests/bug62561.phpt b/ext/date/tests/bug62561.phpt
new file mode 100644
index 0000000000..0ed32c15a1
--- /dev/null
+++ b/ext/date/tests/bug62561.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #62561 Unixtimestamp may take on local times DST flag (this test will only be valid during EDT)
+--FILE--
+<?php
+$tz = new DateTimeZone('America/New_York');
+$ts = new DateTime('@1341115200', $tz);
+$int = new DateInterval('P1D');
+$dayFromTs = new DateTime('@1341115200', new DateTimeZone('America/New_York'));
+$dayFromTs->add($int);
+
+echo 'ts: '.$ts->format('Y-m-d H:i:s')."\n";
+echo 'day from ts: '.$dayFromTs->format('Y-m-d H:i:s')."\n";
+?>
+--EXPECT--
+ts: 2012-07-01 04:00:00
+day from ts: 2012-07-02 04:00:00
diff --git a/ext/date/tests/bug62896.phpt b/ext/date/tests/bug62896.phpt
new file mode 100644
index 0000000000..ccdcfb029c
--- /dev/null
+++ b/ext/date/tests/bug62896.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Bug #62896 Unixtimestamp may take on local times DST flag (this test will only be valid during CEST)
+--INI--
+date.timezone=Europe/Berlin
+--FILE--
+<?php
+ $tz = new DateTimeZone('Europe/Berlin');
+
+ echo "FROM TIMESTAMP, NO TZ:\n";
+
+ $date = new DateTime('@'.strtotime('2012-08-22 00:00:00 CEST'));
+ echo $date->format('Y-m-d H:i:s T').' (offset '.$date->getOffset().")\n";
+
+ $date->modify('+0 days');
+ echo $date->format('Y-m-d H:i:s T').' (offset '.$date->getOffset().")\n";
+
+ echo "FROM TIMESTAMP, WITH TZ:\n";
+
+ $date = new DateTime('@'.strtotime('2012-08-22 00:00:00 CEST'));
+ $date->setTimezone($tz);
+ echo $date->format('Y-m-d H:i:s T').' (offset '.$date->getOffset().")\n";
+
+ $date->modify('+0 days');
+ echo $date->format('Y-m-d H:i:s T').' (offset '.$date->getOffset().")\n";
+
+ echo "FROM STRING:\n";
+
+ $date = new DateTime('2012-08-22 00:00:00 CEST', $tz);
+ echo $date->format('Y-m-d H:i:s T').' (offset '.$date->getOffset().")\n";
+
+ $date->modify('+0 days');
+ echo $date->format('Y-m-d H:i:s T').' (offset '.$date->getOffset().")\n";
+--EXPECT--
+FROM TIMESTAMP, NO TZ:
+2012-08-21 22:00:00 GMT+0000 (offset 0)
+2012-08-21 22:00:00 GMT+0000 (offset 0)
+FROM TIMESTAMP, WITH TZ:
+2012-08-22 00:00:00 CEST (offset 7200)
+2012-08-22 00:00:00 CEST (offset 7200)
+FROM STRING:
+2012-08-22 00:00:00 CEST (offset 7200)
+2012-08-22 00:00:00 CEST (offset 7200)
diff --git a/ext/date/tests/date-lenient-create.phpt b/ext/date/tests/date-lenient-create.phpt
new file mode 100644
index 0000000000..49ee3c1371
--- /dev/null
+++ b/ext/date/tests/date-lenient-create.phpt
@@ -0,0 +1,149 @@
+--TEST--
+Test for + character in date format
+--FILE--
+<?php
+$tz = new DateTimeZone("UTC");
+$date = "06/08/04 12:00";
+echo "==\n";
+print_r( date_create_from_format( 'm/d/y', $date , $tz) );
+print_r( date_get_last_errors() );
+echo "==\n";
+print_r( date_create_from_format( 'm/d/y+', $date , $tz)->setTime(0, 0) );
+print_r( date_get_last_errors() );
+echo "==\n";
+print_r( date_create_from_format( '+m/d/y', $date , $tz)->setTime(0, 0) );
+print_r( date_get_last_errors() );
+echo "==\n";
+print_r( date_create_from_format( 'm/d/y++', $date , $tz)->setTime(0, 0) );
+print_r( date_get_last_errors() );
+echo "==\n";
+
+$date = "06/08/04";
+print_r( date_create_from_format( 'm/d/y+', $date , $tz)->setTime(0, 0) );
+print_r( date_get_last_errors() );
+echo "==\n";
+print_r( date_create_from_format( '+m/d/y', $date , $tz)->setTime(0, 0) );
+print_r( date_get_last_errors() );
+echo "==\n";
+
+?>
+--EXPECT--
+==
+Array
+(
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 1
+ [errors] => Array
+ (
+ [8] => Trailing data
+ )
+
+)
+==
+DateTime Object
+(
+ [date] => 2004-06-08 00:00:00
+ [timezone_type] => 3
+ [timezone] => UTC
+)
+Array
+(
+ [warning_count] => 1
+ [warnings] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+)
+==
+DateTime Object
+(
+ [date] => 2004-06-08 00:00:00
+ [timezone_type] => 3
+ [timezone] => UTC
+)
+Array
+(
+ [warning_count] => 1
+ [warnings] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+)
+==
+DateTime Object
+(
+ [date] => 2004-06-08 00:00:00
+ [timezone_type] => 3
+ [timezone] => UTC
+)
+Array
+(
+ [warning_count] => 1
+ [warnings] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+)
+==
+DateTime Object
+(
+ [date] => 2004-06-08 00:00:00
+ [timezone_type] => 3
+ [timezone] => UTC
+)
+Array
+(
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+)
+==
+DateTime Object
+(
+ [date] => 2004-06-08 00:00:00
+ [timezone_type] => 3
+ [timezone] => UTC
+)
+Array
+(
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+)
+==
diff --git a/ext/date/tests/date-lenient.phpt b/ext/date/tests/date-lenient.phpt
new file mode 100644
index 0000000000..e5862e191e
--- /dev/null
+++ b/ext/date/tests/date-lenient.phpt
@@ -0,0 +1,146 @@
+--TEST--
+Test for + character in date format
+--FILE--
+<?php
+$date = "06/08/04 12:00";
+print_r( date_parse_from_format( 'm/d/y', $date ) );
+print_r( date_parse_from_format( 'm/d/y+', $date ) );
+print_r( date_parse_from_format( '+m/d/y', $date ) );
+print_r( date_parse_from_format( 'm/d/y++', $date ) );
+
+$date = "06/08/04";
+print_r( date_parse_from_format( 'm/d/y+', $date ) );
+print_r( date_parse_from_format( '+m/d/y', $date ) );
+
+?>
+--EXPECT--
+Array
+(
+ [year] => 2004
+ [month] => 6
+ [day] => 8
+ [hour] =>
+ [minute] =>
+ [second] =>
+ [fraction] =>
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 1
+ [errors] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [is_localtime] =>
+)
+Array
+(
+ [year] => 2004
+ [month] => 6
+ [day] => 8
+ [hour] =>
+ [minute] =>
+ [second] =>
+ [fraction] =>
+ [warning_count] => 1
+ [warnings] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+ [is_localtime] =>
+)
+Array
+(
+ [year] => 2004
+ [month] => 6
+ [day] => 8
+ [hour] =>
+ [minute] =>
+ [second] =>
+ [fraction] =>
+ [warning_count] => 1
+ [warnings] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+ [is_localtime] =>
+)
+Array
+(
+ [year] => 2004
+ [month] => 6
+ [day] => 8
+ [hour] =>
+ [minute] =>
+ [second] =>
+ [fraction] =>
+ [warning_count] => 1
+ [warnings] => Array
+ (
+ [8] => Trailing data
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+ [is_localtime] =>
+)
+Array
+(
+ [year] => 2004
+ [month] => 6
+ [day] => 8
+ [hour] =>
+ [minute] =>
+ [second] =>
+ [fraction] =>
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+ [is_localtime] =>
+)
+Array
+(
+ [year] => 2004
+ [month] => 6
+ [day] => 8
+ [hour] =>
+ [minute] =>
+ [second] =>
+ [fraction] =>
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 0
+ [errors] => Array
+ (
+ )
+
+ [is_localtime] =>
+)
diff --git a/ext/date/tests/date_default_timezone_get-1-win32.phpt b/ext/date/tests/date_default_timezone_get-1-win32.phpt
index a12418f701..ed9ac1a478 100644
--- a/ext/date/tests/date_default_timezone_get-1-win32.phpt
+++ b/ext/date/tests/date_default_timezone_get-1-win32.phpt
@@ -17,8 +17,8 @@ date.timezone=
parametrized so there is no hardcoded timezone data.*/
?>
--EXPECTF--
-Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected '%s' for '%s' instead in %sdate_default_timezone_get-1-win32.php on line 3
+Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone '%s' for now, but please set date.timezone to select your timezone. in %s on line %d
%s
-Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected '%s' for '%s' instead in %sdate_default_timezone_get-1-win32.php on line 4
+Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone '%s' for now, but please set date.timezone to select your timezone. in %s on line %d
%s
diff --git a/ext/date/tests/date_default_timezone_get-1.phpt b/ext/date/tests/date_default_timezone_get-1.phpt
index 5d17a25caf..4bff31a783 100644
--- a/ext/date/tests/date_default_timezone_get-1.phpt
+++ b/ext/date/tests/date_default_timezone_get-1.phpt
@@ -13,8 +13,8 @@ date.timezone=
echo date('e'), "\n";
?>
--EXPECTF--
-Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for 'UTC/0.0/no DST' instead in %sdate_default_timezone_get-1.php on line 3
+Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in %sdate_default_timezone_get-1.php on line 3
UTC
-Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for 'UTC/0.0/no DST' instead in %sdate_default_timezone_get-1.php on line 4
+Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in %sdate_default_timezone_get-1.php on line 4
UTC
diff --git a/ext/date/tests/date_default_timezone_get-2-win32.phpt b/ext/date/tests/date_default_timezone_get-2-win32.phpt
deleted file mode 100644
index 34da0228b9..0000000000
--- a/ext/date/tests/date_default_timezone_get-2-win32.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-date_default_timezone_get() function [2]
---SKIPIF--
-<?php
- if(substr(PHP_OS, 0, 3) != 'WIN') die("skip on non windows");
-?>
---INI--
-date.timezone=
---FILE--
-<?php
- putenv('TZ=');
- echo date_default_timezone_get(), "\n";
- /* The behaviour on windows is to select an arbitrary timezone name from the current system settings.
- This gives no chance to hardcode the timezone name, for instance for UTC+1 it could choose
- from the multiple names like Europe/Berlin or Europe/Paris . For this reason the test is
- parametrized so there is no hardcoded timezone data.*/
-?>
---EXPECTF--
-Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected '%s' for '%s' instead in %sdate_default_timezone_get-2-win32.php on line 3
-%s
diff --git a/ext/date/tests/date_default_timezone_get-2.phpt b/ext/date/tests/date_default_timezone_get-2.phpt
index a72634ee75..f58938d35b 100644
--- a/ext/date/tests/date_default_timezone_get-2.phpt
+++ b/ext/date/tests/date_default_timezone_get-2.phpt
@@ -12,5 +12,5 @@ date.timezone=
echo date_default_timezone_get(), "\n";
?>
--EXPECTF--
-Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for 'UTC/0.0/no DST' instead in %sdate_default_timezone_get-2.php on line 3
+Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in %sdate_default_timezone_get-2.php on line 3
UTC
diff --git a/ext/date/tests/date_default_timezone_set-1.phpt b/ext/date/tests/date_default_timezone_set-1.phpt
index bca8789e78..7afa2b1a16 100644
--- a/ext/date/tests/date_default_timezone_set-1.phpt
+++ b/ext/date/tests/date_default_timezone_set-1.phpt
@@ -22,9 +22,9 @@ date.timezone=
echo date(DATE_ISO8601, $date4), "\n";
?>
--EXPECTF--
-Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for 'UTC/0.0/no DST' instead in %sdate_default_timezone_set-1.php on line 3
+Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in %sdate_default_timezone_set-1.php on line 3
-Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for 'UTC/0.0/no DST' instead in %sdate_default_timezone_set-1.php on line 4
+Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in %sdate_default_timezone_set-1.php on line 4
America/Indiana/Knox
2005-01-12T03:00:00-0500
2005-07-12T03:00:00-0500
diff --git a/ext/dba/config.m4 b/ext/dba/config.m4
index 4269b1cda7..4b123518b4 100644
--- a/ext/dba/config.m4
+++ b/ext/dba/config.m4
@@ -97,6 +97,10 @@ PHP_ARG_WITH(db1,,
PHP_ARG_WITH(dbm,,
[ --with-dbm[=DIR] DBA: DBM support], no, no)
+PHP_ARG_WITH(tcadb,,
+[ --with-tcadb[=DIR] DBA: Tokyo Cabinet abstract DB support], no, no)
+
+
dnl
dnl Library checks
dnl
@@ -193,6 +197,37 @@ if test "$PHP_NDBM" != "no"; then
fi
PHP_DBA_STD_RESULT(ndbm)
+dnl TCADB
+if test "$PHP_TCADB" != "no"; then
+ PHP_DBA_STD_BEGIN
+ for i in $PHP_TCADB /usr/local /usr; do
+ if test -f "$i/include/tcadb.h"; then
+ THIS_PREFIX=$i
+ PHP_ADD_INCLUDE($THIS_PREFIX/include)
+ THIS_INCLUDE=$i/include/tcadb.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ for LIB in tokyocabinet; do
+ PHP_CHECK_LIBRARY($LIB, tcadbopen, [
+ AC_DEFINE_UNQUOTED(TCADB_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_TCADB, 1, [ ])
+ THIS_LIBS=$LIB
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ if test -n "$THIS_LIBS"; then
+ break
+ fi
+ done
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(tcadb)
+
dnl Berkeley specific (library and version test)
dnl parameters(version, library list, function)
AC_DEFUN([PHP_DBA_DB_CHECK],[
@@ -590,7 +625,7 @@ if test "$HAVE_DBA" = "1"; then
AC_MSG_RESULT([yes])
fi
AC_DEFINE(HAVE_DBA, 1, [ ])
- PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db1.c dba_db2.c dba_db3.c dba_db4.c dba_flatfile.c dba_inifile.c dba_qdbm.c $cdb_sources $flat_sources $ini_sources, $ext_shared)
+ PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db1.c dba_db2.c dba_db3.c dba_db4.c dba_flatfile.c dba_inifile.c dba_qdbm.c dba_tcadb.c $cdb_sources $flat_sources $ini_sources, $ext_shared)
PHP_ADD_BUILD_DIR($ext_builddir/libinifile)
PHP_ADD_BUILD_DIR($ext_builddir/libcdb)
PHP_ADD_BUILD_DIR($ext_builddir/libflatfile)
diff --git a/ext/dba/dba.c b/ext/dba/dba.c
index 02339b8884..9bb05d2be6 100644
--- a/ext/dba/dba.c
+++ b/ext/dba/dba.c
@@ -50,6 +50,7 @@
#include "php_flatfile.h"
#include "php_inifile.h"
#include "php_qdbm.h"
+#include "php_tcadb.h"
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
@@ -337,6 +338,9 @@ static dba_handler handler[] = {
#if DBA_QDBM
DBA_HND(qdbm, DBA_LOCK_EXT)
#endif
+#if DBA_TCADB
+ DBA_HND(tcadb, DBA_LOCK_ALL)
+#endif
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -358,6 +362,8 @@ static dba_handler handler[] = {
#define DBA_DEFAULT "dbm"
#elif DBA_QDBM
#define DBA_DEFAULT "qdbm"
+#elif DBA_TCADB
+#define DBA_DEFAULT "tcadb"
#else
#define DBA_DEFAULT ""
#endif
@@ -554,20 +560,9 @@ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
DBA_WRITE_CHECK;
- if (PG(magic_quotes_runtime)) {
- v = estrndup(val, val_len);
- php_stripslashes(v, &val_len TSRMLS_CC);
- if (info->hnd->update(info, key_str, key_len, v, val_len, mode TSRMLS_CC) == SUCCESS) {
- efree(v);
- DBA_ID_DONE;
- RETURN_TRUE;
- }
- efree(v);
- } else {
- if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
- DBA_ID_DONE;
- RETURN_TRUE;
- }
+ if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
+ DBA_ID_DONE;
+ RETURN_TRUE;
}
DBA_ID_DONE;
@@ -832,7 +827,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
/* when in read only mode try to use existing .lck file first */
/* do not log errors for .lck file while in read ony mode on .lck file */
lock_file_mode = "rb";
- info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE|persistent_flag, &opened_path);
+ info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
}
if (!info->lock.fp) {
/* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
@@ -847,7 +842,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
}
if (!info->lock.fp) {
- info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE|persistent_flag, &opened_path);
+ info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
if (info->lock.fp) {
if (lock_dbf) {
/* replace the path info with the real path of the opened file */
@@ -885,7 +880,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
if (info->lock.fp && lock_dbf) {
info->fp = info->lock.fp; /* use the same stream for locking and database access */
} else {
- info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE|persistent_flag, NULL);
+ info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
}
if (!info->fp) {
dba_close(info TSRMLS_CC);
@@ -1023,9 +1018,6 @@ PHP_FUNCTION(dba_fetch)
skip = 0;
}
if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
- if (val && PG(magic_quotes_runtime)) {
- val = php_addslashes(val, len, &len, 1 TSRMLS_CC);
- }
DBA_ID_DONE;
RETURN_STRINGL(val, len, 0);
}
diff --git a/ext/dba/dba_db4.c b/ext/dba/dba_db4.c
index a75d438826..320015035a 100644
--- a/ext/dba/dba_db4.c
+++ b/ext/dba/dba_db4.c
@@ -48,7 +48,7 @@ static void php_dba_db4_errcall_fcn(
/* Bug 51086, Berkeley DB 4.8.26 */
/* This code suppresses a BDB 4.8+ error message, thus keeping PHP test compatibility */
{
- char *function = get_active_function_name(TSRMLS_C);
+ const char *function = get_active_function_name(TSRMLS_C);
if (function && (!strcmp(function,"dba_popen") || !strcmp(function,"dba_open"))
&& (!strncmp(msg, "fop_read_meta", sizeof("fop_read_meta")-1)
|| !strncmp(msg, "BDB0004 fop_read_meta", sizeof("BDB0004 fop_read_meta")-1))) {
diff --git a/ext/dba/dba_tcadb.c b/ext/dba/dba_tcadb.c
new file mode 100644
index 0000000000..e99fcbfd47
--- /dev/null
+++ b/ext/dba/dba_tcadb.c
@@ -0,0 +1,221 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Michael Maclean <mgdm@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_TCADB
+#include "php_tcadb.h"
+
+#ifdef TCADB_INCLUDE_FILE
+#include TCADB_INCLUDE_FILE
+#endif
+
+#define TCADB_DATA dba_tcadb_data *dba = info->dbf
+
+typedef struct {
+ TCADB *tcadb;
+} dba_tcadb_data;
+
+DBA_OPEN_FUNC(tcadb)
+{
+ char *path_string;
+ TCADB *tcadb = tcadbnew();
+
+ if (tcadb) {
+ switch(info->mode) {
+ case DBA_READER:
+ spprintf(&path_string, 0, "%s#mode=r", info->path);
+ break;
+ case DBA_WRITER:
+ spprintf(&path_string, 0, "%s#mode=w", info->path);
+ break;
+ case DBA_CREAT:
+ spprintf(&path_string, 0, "%s#mode=wc", info->path);
+ break;
+ case DBA_TRUNC:
+ spprintf(&path_string, 0, "%s#mode=wct", info->path);
+ break;
+ default:
+ tcadbdel(tcadb);
+ return FAILURE;
+ }
+
+ if (!tcadbopen(tcadb, path_string)) {
+ efree(path_string);
+ tcadbdel(tcadb);
+ return FAILURE;
+ }
+
+ efree(path_string);
+
+ info->dbf = pemalloc(sizeof(dba_tcadb_data), info->flags & DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(dba_tcadb_data));
+ ((dba_tcadb_data *) info->dbf)->tcadb = tcadb;
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+
+DBA_CLOSE_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+ tcadbclose(dba->tcadb);
+ pefree(dba, info->flags & DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(tcadb)
+{
+ TCADB_DATA;
+ char *value, *new = NULL;
+ int value_size;
+
+ value = tcadbget(dba->tcadb, key, keylen, &value_size);
+ if (value) {
+ if (newlen) {
+ *newlen = value_size;
+ }
+ new = estrndup(value, value_size);
+ tcfree(value);
+ }
+
+ return new;
+}
+
+DBA_UPDATE_FUNC(tcadb)
+{
+ TCADB_DATA;
+ int result;
+
+ if (mode == 1) {
+ /* Insert */
+ if (tcadbvsiz(dba->tcadb, key, keylen) > -1) {
+ return FAILURE;
+ }
+ }
+
+ result = tcadbput(dba->tcadb, key, keylen, val, vallen);
+
+ if (result) {
+ return SUCCESS;
+ }
+
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "Error updating data");
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(tcadb)
+{
+ TCADB_DATA;
+ char *value;
+ int value_len;
+
+ value = tcadbget(dba->tcadb, key, keylen, &value_len);
+ if (value) {
+ tcfree(value);
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+ return tcadbout(dba->tcadb, key, keylen) ? SUCCESS : FAILURE;
+}
+
+DBA_FIRSTKEY_FUNC(tcadb)
+{
+ TCADB_DATA;
+ int value_size;
+ char *value, *new = NULL;
+
+ tcadbiterinit(dba->tcadb);
+
+ value = tcadbiternext(dba->tcadb, &value_size);
+ if (value) {
+ if (newlen) {
+ *newlen = value_size;
+ }
+ new = estrndup(value, value_size);
+ tcfree(value);
+ }
+
+ return new;
+}
+
+DBA_NEXTKEY_FUNC(tcadb)
+{
+ TCADB_DATA;
+ int value_size;
+ char *value, *new = NULL;
+
+ value = tcadbiternext(dba->tcadb, &value_size);
+ if (value) {
+ if (newlen) {
+ *newlen = value_size;
+ }
+ new = estrndup(value, value_size);
+ tcfree(value);
+ }
+
+ return new;
+}
+
+DBA_OPTIMIZE_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+#if _TC_LIBVER >= 811
+ return tcadboptimize(dba->tcadb, NULL) ? SUCCESS : FAILURE;
+#else
+ return FAILURE;
+#endif
+}
+
+DBA_SYNC_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+ return tcadbsync(dba->tcadb) ? SUCCESS : FAILURE;
+}
+
+DBA_INFO_FUNC(tcadb)
+{
+ return estrdup(tcversion);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/libflatfile/flatfile.c b/ext/dba/libflatfile/flatfile.c
index 4d738af7b5..c17a295438 100644
--- a/ext/dba/libflatfile/flatfile.c
+++ b/ext/dba/libflatfile/flatfile.c
@@ -27,7 +27,6 @@
#include "php.h"
#include "php_globals.h"
-#include "safe_mode.h"
#include <stdlib.h>
#include <string.h>
diff --git a/ext/dba/libinifile/inifile.c b/ext/dba/libinifile/inifile.c
index 2d290e026e..cd53f4adf0 100644
--- a/ext/dba/libinifile/inifile.c
+++ b/ext/dba/libinifile/inifile.c
@@ -24,7 +24,6 @@
#include "php.h"
#include "php_globals.h"
-#include "safe_mode.h"
#include <stdlib.h>
#include <string.h>
diff --git a/sapi/cli/php_cli_readline.h b/ext/dba/php_tcadb.h
index 3b19584715..0a81146927 100644
--- a/sapi/cli/php_cli_readline.h
+++ b/ext/dba/php_tcadb.h
@@ -12,14 +12,30 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Marcus Boerger <helly@php.net> |
+ | Author: Michael Maclean <mgdm@php.net> |
+----------------------------------------------------------------------+
-*/
+ */
/* $Id$ */
-#include "php.h"
+#ifndef PHP_TCADB_H
+#define PHP_TCADB_H
-int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC);
+#if DBA_TCADB
-char **cli_code_completion(const char *text, int start, int end);
+#include "php_dba.h"
+
+DBA_FUNCS(tcadb);
+
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/tests/dba_cdb_make.phpt b/ext/dba/tests/dba_cdb_make.phpt
index e3ff9662a8..6a5f2dd9c3 100644
--- a/ext/dba/tests/dba_cdb_make.phpt
+++ b/ext/dba/tests/dba_cdb_make.phpt
@@ -1,7 +1,5 @@
--TEST--
DBA CDB_MAKE handler test
---INI--
-magic_quotes_runtime=1
--SKIPIF--
<?php
$handler = 'cdb_make';
@@ -37,7 +35,6 @@ magic_quotes_runtime=1
require(dirname(__FILE__) .'/clean.inc');
?>
--EXPECT--
-Deprecated: Directive 'magic_quotes_runtime' is deprecated in PHP 5.3 and greater in Unknown on line 0
database handler: cdb_make
string(32) "12fc5ba2b9dcfef2480e5324eeb5f3e5"
string(32) "12fc5ba2b9dcfef2480e5324eeb5f3e5"
diff --git a/ext/dba/tests/dba_tcadb.phpt b/ext/dba/tests/dba_tcadb.phpt
new file mode 100644
index 0000000000..52dd4de336
--- /dev/null
+++ b/ext/dba/tests/dba_tcadb.phpt
@@ -0,0 +1,50 @@
+--TEST--
+DBA TCADB handler test
+--SKIPIF--
+<?php
+ $handler = 'tcadb';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'tcadb';
+ require_once dirname(__FILE__) .'/skipif.inc';
+ $lock_flag = 'l';
+ $db_filename = $db_file = dirname(__FILE__) .'/test0.tch';
+ @unlink($db_filename);
+ @unlink($db_filename.'.lck');
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: tcadb
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dom/attr.c b/ext/dom/attr.c
index 5a1b30827e..98f645fc70 100644
--- a/ext/dom/attr.c
+++ b/ext/dom/attr.c
@@ -228,7 +228,7 @@ int dom_attr_owner_element_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object(nodeparent, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(nodeparent, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
diff --git a/ext/dom/document.c b/ext/dom/document.c
index 0161916f73..1d7f46a9bd 100644
--- a/ext/dom/document.c
+++ b/ext/dom/document.c
@@ -149,10 +149,12 @@ ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadhtml, 0, 0, 1)
ZEND_ARG_INFO(0, source)
+ ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadhtmlfile, 0, 0, 1)
ZEND_ARG_INFO(0, source)
+ ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savehtml, 0, 0, 0)
@@ -259,7 +261,7 @@ int dom_document_doctype_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object((xmlNodePtr) dtdptr, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object((xmlNodePtr) dtdptr, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -309,7 +311,7 @@ int dom_document_document_element_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object(root, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(root, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -899,7 +901,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_element)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp;
dom_object *intern;
@@ -922,7 +924,7 @@ PHP_FUNCTION(dom_document_create_element)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_document_create_element */
@@ -932,7 +934,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_document_fragment)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp;
dom_object *intern;
@@ -949,7 +951,7 @@ PHP_FUNCTION(dom_document_create_document_fragment)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_document_create_document_fragment */
@@ -959,7 +961,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_text_node)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp;
int ret, value_len;
@@ -977,7 +979,7 @@ PHP_FUNCTION(dom_document_create_text_node)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_document_create_text_node */
@@ -987,7 +989,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_comment)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp;
int ret, value_len;
@@ -1005,7 +1007,7 @@ PHP_FUNCTION(dom_document_create_comment)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_document_create_comment */
@@ -1015,7 +1017,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_cdatasection)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp;
int ret, value_len;
@@ -1033,7 +1035,7 @@ PHP_FUNCTION(dom_document_create_cdatasection)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_document_create_cdatasection */
@@ -1043,7 +1045,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_processing_instruction)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp;
int ret, value_len, name_len = 0;
@@ -1068,7 +1070,7 @@ PHP_FUNCTION(dom_document_create_processing_instruction)
node->doc = docp;
- DOM_RET_OBJ(rv, node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_document_create_processing_instruction */
@@ -1078,7 +1080,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_attribute)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlAttrPtr node;
xmlDocPtr docp;
int ret, name_len;
@@ -1101,7 +1103,7 @@ PHP_FUNCTION(dom_document_create_attribute)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, (xmlNodePtr) node, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
}
/* }}} end dom_document_create_attribute */
@@ -1112,7 +1114,7 @@ Since:
*/
PHP_FUNCTION(dom_document_create_entity_reference)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *node;
xmlDocPtr docp = NULL;
dom_object *intern;
@@ -1135,7 +1137,7 @@ PHP_FUNCTION(dom_document_create_entity_reference)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, (xmlNodePtr) node, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
}
/* }}} end dom_document_create_entity_reference */
@@ -1171,7 +1173,6 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_document_import_node)
{
- zval *rv = NULL;
zval *id, *node;
xmlDocPtr docp;
xmlNodePtr nodep, retnodep;
@@ -1211,13 +1212,13 @@ PHP_FUNCTION(dom_document_import_node)
nsptr = xmlSearchNsByHref (nodep->doc, root, nodep->ns->href);
if (nsptr == NULL) {
int errorcode;
- nsptr = dom_get_ns(root, nodep->ns->href, &errorcode, nodep->ns->prefix);
+ nsptr = dom_get_ns(root, (char *) nodep->ns->href, &errorcode, (char *) nodep->ns->prefix);
}
xmlSetNs(retnodep, nsptr);
}
}
- DOM_RET_OBJ(rv, (xmlNodePtr) retnodep, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) retnodep, &ret, intern);
}
/* }}} end dom_document_import_node */
@@ -1227,7 +1228,7 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_document_create_element_ns)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlDocPtr docp;
xmlNodePtr nodep = NULL;
xmlNsPtr nsptr = NULL;
@@ -1280,7 +1281,7 @@ PHP_FUNCTION(dom_document_create_element_ns)
nodep->ns = nsptr;
- DOM_RET_OBJ(rv, nodep, &ret, intern);
+ DOM_RET_OBJ(nodep, &ret, intern);
}
/* }}} end dom_document_create_element_ns */
@@ -1290,7 +1291,7 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_document_create_attribute_ns)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlDocPtr docp;
xmlNodePtr nodep = NULL, root;
xmlNsPtr nsptr;
@@ -1345,7 +1346,7 @@ PHP_FUNCTION(dom_document_create_attribute_ns)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, nodep, &ret, intern);
+ DOM_RET_OBJ(nodep, &ret, intern);
}
/* }}} end dom_document_create_attribute_ns */
@@ -1382,7 +1383,7 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_document_get_element_by_id)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlDocPtr docp;
xmlAttrPtr attrp;
int ret, idname_len;
@@ -1398,7 +1399,7 @@ PHP_FUNCTION(dom_document_get_element_by_id)
attrp = xmlGetID(docp, (xmlChar *) idname);
if (attrp && attrp->parent) {
- DOM_RET_OBJ(rv, (xmlNodePtr) attrp->parent, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) attrp->parent, &ret, intern);
} else {
RETVAL_NULL();
}
@@ -1660,7 +1661,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, int sourc
/* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */
static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
- zval *id, *rv = NULL;
+ zval *id;
xmlDoc *docp = NULL, *newdoc;
dom_doc_propsptr doc_prop;
dom_object *intern;
@@ -1712,7 +1713,7 @@ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
RETURN_TRUE;
} else {
- DOM_RET_OBJ(rv, (xmlNodePtr) newdoc, &ret, NULL);
+ DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
}
}
/* }}} end dom_parser_document */
@@ -1979,7 +1980,7 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
int is_valid;
char resolved_path[MAXPATHLEN + 1];
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
return;
}
@@ -2068,7 +2069,7 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ
int is_valid;
char resolved_path[MAXPATHLEN + 1];
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Op", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
return;
}
@@ -2150,17 +2151,18 @@ PHP_FUNCTION(dom_document_relaxNG_validate_xml)
static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
{
- zval *id, *rv = NULL;
+ zval *id;
xmlDoc *docp = NULL, *newdoc;
dom_object *intern;
dom_doc_propsptr doc_prop;
char *source;
int source_len, refcount, ret;
+ long options = 0;
htmlParserCtxtPtr ctxt;
id = getThis();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source, &source_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &source, &source_len, &options) == FAILURE) {
return;
}
@@ -2180,6 +2182,10 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
RETURN_FALSE;
}
+ if (options) {
+ htmlCtxtUseOptions(ctxt, options);
+ }
+
ctxt->vctxt.error = php_libxml_ctx_error;
ctxt->vctxt.warning = php_libxml_ctx_warning;
if (ctxt->sax != NULL) {
@@ -2218,7 +2224,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
RETURN_TRUE;
} else {
- DOM_RET_OBJ(rv, (xmlNodePtr) newdoc, &ret, NULL);
+ DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
}
}
/* }}} */
diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c
index 758181bc28..92302b1b4b 100644
--- a/ext/dom/dom_iterators.c
+++ b/ext/dom/dom_iterators.c
@@ -251,7 +251,7 @@ err:
zval_ptr_dtor((zval**)&curobj);
if (curnode) {
MAKE_STD_ZVAL(curattr);
- curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC);
+ curattr = php_dom_create_object(curnode, &ret, curattr, objmap->baseobj TSRMLS_CC);
}
iterator->curobj = curattr;
@@ -330,7 +330,7 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i
err:
if (curnode) {
MAKE_STD_ZVAL(curattr);
- curattr = php_dom_create_object(curnode, &ret, NULL, curattr, objmap->baseobj TSRMLS_CC);
+ curattr = php_dom_create_object(curnode, &ret, curattr, objmap->baseobj TSRMLS_CC);
}
iterator->curobj = curattr;
diff --git a/ext/dom/domerrorhandler.c b/ext/dom/domerrorhandler.c
index f1ab2871a8..e282f30146 100644
--- a/ext/dom/domerrorhandler.c
+++ b/ext/dom/domerrorhandler.c
@@ -29,7 +29,7 @@
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_domerrorhandler_handle_error, 0, 0, 1)
- ZEND_ARG_OBJ_INFO(0, error, DOMError, 0)
+ ZEND_ARG_OBJ_INFO(0, error, DOMDomError, 0)
ZEND_END_ARG_INFO();
/* }}} */
diff --git a/ext/dom/domimplementation.c b/ext/dom/domimplementation.c
index 2fa39ca49e..92715ce030 100644
--- a/ext/dom/domimplementation.c
+++ b/ext/dom/domimplementation.c
@@ -91,7 +91,6 @@ Since: DOM Level 2
*/
PHP_METHOD(domimplementation, createDocumentType)
{
- zval *rv = NULL;
xmlDtd *doctype;
int ret, name_len = 0, publicid_len = 0, systemid_len = 0;
char *name = NULL, *publicid = NULL, *systemid = NULL;
@@ -141,7 +140,7 @@ PHP_METHOD(domimplementation, createDocumentType)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, (xmlNodePtr) doctype, &ret, NULL);
+ DOM_RET_OBJ((xmlNodePtr) doctype, &ret, NULL);
}
/* }}} end dom_domimplementation_create_document_type */
@@ -151,7 +150,7 @@ Since: DOM Level 2
*/
PHP_METHOD(domimplementation, createDocument)
{
- zval *node = NULL, *rv = NULL;
+ zval *node = NULL;
xmlDoc *docp;
xmlNode *nodep;
xmlDtdPtr doctype = NULL;
@@ -238,7 +237,7 @@ PHP_METHOD(domimplementation, createDocument)
xmlFree(localname);
}
- DOM_RET_OBJ(rv, (xmlNodePtr) docp, &ret, NULL);
+ DOM_RET_OBJ((xmlNodePtr) docp, &ret, NULL);
if (doctobj != NULL) {
doctobj->document = ((dom_object *)((php_libxml_node_ptr *)docp->_private)->_private)->document;
diff --git a/ext/dom/element.c b/ext/dom/element.c
index 33002fa1ee..02fded9f1a 100644
--- a/ext/dom/element.c
+++ b/ext/dom/element.c
@@ -371,7 +371,7 @@ Since:
*/
PHP_FUNCTION(dom_element_set_attribute)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNode *nodep;
xmlNodePtr attr = NULL;
int ret, name_len, value_len, name_valid;
@@ -426,7 +426,7 @@ PHP_FUNCTION(dom_element_set_attribute)
RETURN_FALSE;
}
- DOM_RET_OBJ(rv, attr, &ret, intern);
+ DOM_RET_OBJ(attr, &ret, intern);
}
/* }}} end dom_element_set_attribute */
@@ -485,7 +485,7 @@ Since:
*/
PHP_FUNCTION(dom_element_get_attribute_node)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNodePtr nodep, attrp;
int name_len, ret;
dom_object *intern;
@@ -521,7 +521,7 @@ PHP_FUNCTION(dom_element_get_attribute_node)
attrp->ns = curns;
}
- DOM_RET_OBJ(rv, (xmlNodePtr) attrp, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
}
/* }}} end dom_element_get_attribute_node */
@@ -531,7 +531,7 @@ Since:
*/
PHP_FUNCTION(dom_element_set_attribute_node)
{
- zval *id, *node, *rv = NULL;
+ zval *id, *node;
xmlNode *nodep;
xmlAttr *attrp, *existattrp = NULL;
dom_object *intern, *attrobj, *oldobj;
@@ -583,7 +583,7 @@ PHP_FUNCTION(dom_element_set_attribute_node)
/* Returns old property if removed otherwise NULL */
if (existattrp != NULL) {
- DOM_RET_OBJ(rv, (xmlNodePtr) existattrp, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) existattrp, &ret, intern);
} else {
RETVAL_NULL();
}
@@ -597,7 +597,7 @@ Since:
*/
PHP_FUNCTION(dom_element_remove_attribute_node)
{
- zval *id, *node, *rv = NULL;
+ zval *id, *node;
xmlNode *nodep;
xmlAttr *attrp;
dom_object *intern, *attrobj;
@@ -623,7 +623,7 @@ PHP_FUNCTION(dom_element_remove_attribute_node)
xmlUnlinkNode((xmlNodePtr) attrp);
- DOM_RET_OBJ(rv, (xmlNodePtr) attrp, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
}
/* }}} end dom_element_remove_attribute_node */
@@ -925,7 +925,7 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_element_get_attribute_node_ns)
{
- zval *id, *rv = NULL;
+ zval *id;
xmlNodePtr elemp;
xmlAttrPtr attrp;
dom_object *intern;
@@ -944,7 +944,7 @@ PHP_FUNCTION(dom_element_get_attribute_node_ns)
RETURN_NULL();
}
- DOM_RET_OBJ(rv, (xmlNodePtr) attrp, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
}
/* }}} end dom_element_get_attribute_node_ns */
@@ -955,7 +955,7 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_element_set_attribute_node_ns)
{
- zval *id, *node, *rv = NULL;
+ zval *id, *node;
xmlNode *nodep;
xmlNs *nsp;
xmlAttr *attrp, *existattrp = NULL;
@@ -1014,7 +1014,7 @@ PHP_FUNCTION(dom_element_set_attribute_node_ns)
/* Returns old property if removed otherwise NULL */
if (existattrp != NULL) {
- DOM_RET_OBJ(rv, (xmlNodePtr) existattrp, &ret, intern);
+ DOM_RET_OBJ((xmlNodePtr) existattrp, &ret, intern);
} else {
RETVAL_NULL();
}
diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c
index 1935fcc03f..e6c8fffef4 100644
--- a/ext/dom/namednodemap.c
+++ b/ext/dom/namednodemap.c
@@ -126,7 +126,7 @@ Since:
*/
PHP_FUNCTION(dom_namednodemap_get_named_item)
{
- zval *id, *rv = NULL;
+ zval *id;
int ret, namedlen=0;
dom_object *intern;
xmlNodePtr itemnode = NULL;
@@ -166,7 +166,7 @@ PHP_FUNCTION(dom_namednodemap_get_named_item)
}
if (itemnode) {
- DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj);
+ DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
return;
} else {
RETVAL_NULL();
@@ -200,7 +200,7 @@ Since:
*/
PHP_FUNCTION(dom_namednodemap_item)
{
- zval *id, *rv = NULL;
+ zval *id;
long index;
int ret;
dom_object *intern;
@@ -243,7 +243,7 @@ PHP_FUNCTION(dom_namednodemap_item)
}
if (itemnode) {
- DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj);
+ DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
return;
}
}
@@ -258,7 +258,7 @@ Since: DOM Level 2
*/
PHP_FUNCTION(dom_namednodemap_get_named_item_ns)
{
- zval *id, *rv = NULL;
+ zval *id;
int ret, namedlen=0, urilen=0;
dom_object *intern;
xmlNodePtr itemnode = NULL;
@@ -298,7 +298,7 @@ PHP_FUNCTION(dom_namednodemap_get_named_item_ns)
}
if (itemnode) {
- DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj);
+ DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
return;
} else {
RETVAL_NULL();
diff --git a/ext/dom/node.c b/ext/dom/node.c
index 727d1bcef3..4dbce4d790 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -429,7 +429,7 @@ int dom_node_parent_node_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object(nodeparent, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(nodeparent, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -498,7 +498,7 @@ int dom_node_first_child_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object(first, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(first, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -535,7 +535,7 @@ int dom_node_last_child_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object(last, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(last, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -569,7 +569,7 @@ int dom_node_previous_sibling_read(dom_object *obj, zval **retval TSRMLS_DC)
return SUCCESS;
}
- if (NULL == (*retval = php_dom_create_object(prevsib, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(prevsib, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -602,7 +602,7 @@ int dom_node_next_sibling_read(dom_object *obj, zval **retval TSRMLS_DC)
ALLOC_ZVAL(*retval);
- if (NULL == (*retval = php_dom_create_object(nextsib, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object(nextsib, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -674,7 +674,7 @@ int dom_node_owner_document_read(dom_object *obj, zval **retval TSRMLS_DC)
ALLOC_ZVAL(*retval);
- if (NULL == (*retval = php_dom_create_object((xmlNodePtr) docp, &ret, NULL, *retval, obj TSRMLS_CC))) {
+ if (NULL == (*retval = php_dom_create_object((xmlNodePtr) docp, &ret, *retval, obj TSRMLS_CC))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
}
@@ -1087,7 +1087,7 @@ PHP_FUNCTION(dom_node_insert_before)
xmlUnlinkNode((xmlNodePtr) lastattr);
php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC);
} else {
- DOM_RET_OBJ_EX(child, &ret, intern);
+ DOM_RET_OBJ(child, &ret, intern);
return;
}
}
@@ -1129,7 +1129,7 @@ PHP_FUNCTION(dom_node_insert_before)
xmlUnlinkNode((xmlNodePtr) lastattr);
php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC);
} else {
- DOM_RET_OBJ_EX(child, &ret, intern);
+ DOM_RET_OBJ(child, &ret, intern);
return;
}
}
@@ -1148,7 +1148,7 @@ PHP_FUNCTION(dom_node_insert_before)
dom_reconcile_ns(parentp->doc, new_child);
- DOM_RET_OBJ_EX(new_child, &ret, intern);
+ DOM_RET_OBJ(new_child, &ret, intern);
}
/* }}} end dom_node_insert_before */
@@ -1232,7 +1232,7 @@ PHP_FUNCTION(dom_node_replace_child)
xmlReplaceNode(oldchild, newchild);
dom_reconcile_ns(nodep->doc, newchild);
}
- DOM_RET_OBJ_EX(oldchild, &ret, intern);
+ DOM_RET_OBJ(oldchild, &ret, intern);
return;
} else {
php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
@@ -1281,7 +1281,7 @@ PHP_FUNCTION(dom_node_remove_child)
while (children) {
if (children == child) {
xmlUnlinkNode(child);
- DOM_RET_OBJ_EX(child, &ret, intern);
+ DOM_RET_OBJ(child, &ret, intern);
return;
}
children = children->next;
@@ -1389,7 +1389,7 @@ PHP_FUNCTION(dom_node_append_child)
dom_reconcile_ns(nodep->doc, new_child);
- DOM_RET_OBJ_EX(new_child, &ret, intern);
+ DOM_RET_OBJ(new_child, &ret, intern);
}
/* }}} end dom_node_append_child */
@@ -1478,7 +1478,7 @@ PHP_FUNCTION(dom_node_clone_node)
intern = NULL;
}
- DOM_RET_OBJ_EX(node, &ret, intern);
+ DOM_RET_OBJ(node, &ret, intern);
}
/* }}} end dom_node_clone_node */
@@ -1825,7 +1825,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{
if (Z_TYPE_PP(tmpns) == IS_STRING) {
char *prefix;
ulong idx;
- int prefix_key_len;
+ uint prefix_key_len;
if (zend_hash_get_current_key_ex(Z_ARRVAL_PP(tmp),
&prefix, &prefix_key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c
index a179e1fbaa..21d23503af 100644
--- a/ext/dom/nodelist.c
+++ b/ext/dom/nodelist.c
@@ -104,7 +104,7 @@ Since:
*/
PHP_FUNCTION(dom_nodelist_item)
{
- zval *id, *rv = NULL;
+ zval *id;
long index;
int ret;
dom_object *intern;
@@ -163,7 +163,7 @@ PHP_FUNCTION(dom_nodelist_item)
}
if (itemnode) {
- DOM_RET_OBJ(rv, itemnode, &ret, objmap->baseobj);
+ DOM_RET_OBJ(itemnode, &ret, objmap->baseobj);
return;
}
}
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index df413e9b61..ec7ec1e848 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -303,7 +303,7 @@ static void dom_register_prop_handler(HashTable *prop_handler, char *name, dom_r
}
/* }}} */
-static zval **dom_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval **dom_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
dom_object *obj;
zval tmp_member;
@@ -326,7 +326,7 @@ static zval **dom_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /*
}
if (ret == FAILURE) {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->get_property_ptr_ptr(object, member TSRMLS_CC);
+ retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -337,7 +337,7 @@ static zval **dom_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /*
/* }}} */
/* {{{ dom_read_property */
-zval *dom_read_property(zval *object, zval *member, int type TSRMLS_DC)
+zval *dom_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
dom_object *obj;
zval tmp_member;
@@ -372,7 +372,7 @@ zval *dom_read_property(zval *object, zval *member, int type TSRMLS_DC)
}
} else {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->read_property(object, member, type TSRMLS_CC);
+ retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -383,7 +383,7 @@ zval *dom_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* }}} */
/* {{{ dom_write_property */
-void dom_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+void dom_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
dom_object *obj;
zval tmp_member;
@@ -408,7 +408,7 @@ void dom_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
hnd->write_func(obj, value TSRMLS_CC);
} else {
std_hnd = zend_get_std_object_handlers();
- std_hnd->write_property(object, member, value TSRMLS_CC);
+ std_hnd->write_property(object, member, value, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -418,7 +418,7 @@ void dom_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
/* }}} */
/* {{{ dom_property_exists */
-static int dom_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+static int dom_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
{
dom_object *obj;
zval tmp_member;
@@ -456,7 +456,7 @@ static int dom_property_exists(zval *object, zval *member, int check_empty TSRML
}
} else {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->has_property(object, member, check_empty TSRMLS_CC);
+ retval = std_hnd->has_property(object, member, check_empty, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -565,7 +565,6 @@ void *php_dom_export_node(zval *object TSRMLS_DC) /* {{{ */
Get a simplexml_element object from dom to allow for processing */
PHP_FUNCTION(dom_import_simplexml)
{
- zval *rv = NULL;
zval *node;
xmlNodePtr nodep = NULL;
php_libxml_node_object *nodeobj;
@@ -579,7 +578,7 @@ PHP_FUNCTION(dom_import_simplexml)
nodep = php_libxml_import_node(node TSRMLS_CC);
if (nodep && nodeobj && (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE)) {
- DOM_RET_OBJ(rv, (xmlNodePtr) nodep, &ret, (dom_object *)nodeobj);
+ DOM_RET_OBJ((xmlNodePtr) nodep, &ret, (dom_object *)nodeobj);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Nodetype to import");
RETURN_NULL();
@@ -1135,7 +1134,6 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml
static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool hash_copy TSRMLS_DC) /* {{{ */
{
zend_class_entry *base_class;
- zval *tmp;
dom_object *intern;
if (instanceof_function(class_type, dom_xpath_class_entry TSRMLS_CC)) {
@@ -1157,7 +1155,7 @@ static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
if (hash_copy) {
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
}
return intern;
@@ -1316,7 +1314,7 @@ void php_dom_create_interator(zval *return_value, int ce_type TSRMLS_DC) /* {{{
/* }}} */
/* {{{ php_dom_create_object */
-PHP_DOM_EXPORT zval *php_dom_create_object(xmlNodePtr obj, int *found, zval *wrapper_in, zval *return_value, dom_object *domobj TSRMLS_DC)
+PHP_DOM_EXPORT zval *php_dom_create_object(xmlNodePtr obj, int *found, zval *return_value, dom_object *domobj TSRMLS_DC)
{
zval *wrapper;
zend_class_entry *ce;
diff --git a/ext/dom/tests/DOMAttr_value_basic_001.phpt b/ext/dom/tests/DOMAttr_value_basic_001.phpt
index 40e00bcc4d..51c4ac954d 100644
--- a/ext/dom/tests/DOMAttr_value_basic_001.phpt
+++ b/ext/dom/tests/DOMAttr_value_basic_001.phpt
@@ -1,6 +1,6 @@
--TEST--
Read empty $value.
---CREDIT--
+--CREDITS--
Jason Bouffard <jbouffard1@yahoo.com>
# TestFest Atlanta 2009-05-14
--SKIPIF--
@@ -13,4 +13,4 @@ print $attr->value."\n";
===DONE===
--EXPECTF--
===DONE===
- \ No newline at end of file
+
diff --git a/ext/dom/tests/DOMAttr_value_basic_002.phpt b/ext/dom/tests/DOMAttr_value_basic_002.phpt
index cf71eebf39..384a9ca4af 100644
--- a/ext/dom/tests/DOMAttr_value_basic_002.phpt
+++ b/ext/dom/tests/DOMAttr_value_basic_002.phpt
@@ -1,6 +1,6 @@
--TEST--
Write non-string $value property
---CREDIT--
+--CREDITS--
Eric Berg <ehberg@gmail.com>
# TestFest Atlanta 2009-05-14
--SKIPIF--
@@ -12,4 +12,4 @@ $attr->value = 1;
print $attr->value;
?>
--EXPECTF--
-1 \ No newline at end of file
+1
diff --git a/ext/dom/tests/DOMCharacterData_data_error_002.phpt b/ext/dom/tests/DOMCharacterData_data_error_002.phpt
index 9dae096e6f..401e0f2f8c 100644
--- a/ext/dom/tests/DOMCharacterData_data_error_002.phpt
+++ b/ext/dom/tests/DOMCharacterData_data_error_002.phpt
@@ -1,6 +1,6 @@
--TEST--
Invalid State Error when getting data on DOMCharacterData out of content.
---CREDIT--
+--CREDITS--
Eric Berg <ehberg@gmail.com>
# TestFest Atlanta 2009-05-14
--SKIPIF--
@@ -11,4 +11,4 @@ $character_data = new DOMCharacterData();
print $character_data->data;
?>
--EXPECTF--
-Warning: main(): Invalid State Error in %s on line %d \ No newline at end of file
+Warning: main(): Invalid State Error in %s on line %d
diff --git a/ext/dom/tests/DOMCharacterData_length_error_001.phpt b/ext/dom/tests/DOMCharacterData_length_error_001.phpt
index 0dda492ad4..e8bf16ab98 100644
--- a/ext/dom/tests/DOMCharacterData_length_error_001.phpt
+++ b/ext/dom/tests/DOMCharacterData_length_error_001.phpt
@@ -1,6 +1,6 @@
--TEST--
Invalid State Error when getting length on DOMCharacterData out of content.
---CREDIT--
+--CREDITS--
Jason Bouffard <jbouffard1@yahoo.com>
# TestFest Atlanta 2009-05-14
--SKIPIF--
@@ -14,4 +14,4 @@ print $character_data->length;
--EXPECTF--
Warning: main(): Invalid State Error in %s
===DONE===
- \ No newline at end of file
+
diff --git a/ext/dom/tests/DOMDocument_loadHTML_error1.phpt b/ext/dom/tests/DOMDocument_loadHTML_error1.phpt
index c7b5e614d7..de8d349e9f 100644
--- a/ext/dom/tests/DOMDocument_loadHTML_error1.phpt
+++ b/ext/dom/tests/DOMDocument_loadHTML_error1.phpt
@@ -12,4 +12,4 @@ $doc = new DOMDocument();
$doc->loadHTML();
?>
--EXPECTF--
-Warning: DOMDocument::loadHTML() expects exactly 1 parameter, 0 given in %s on line %d
+Warning: DOMDocument::loadHTML() expects at least 1 parameter, 0 given in %s on line %d
diff --git a/ext/dom/tests/DOMDocument_saveHTML_variant2.phpt b/ext/dom/tests/DOMDocument_saveHTML_variant2.phpt
new file mode 100644
index 0000000000..54ccda1fa5
--- /dev/null
+++ b/ext/dom/tests/DOMDocument_saveHTML_variant2.phpt
@@ -0,0 +1,26 @@
+--TEST--
+DOMDocument::saveHTML() vs DOMDocumet::saveXML()
+--SKIPIF--
+<?php
+require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+$d = new DOMDocument();
+$str = <<<EOD
+<html>
+<head>
+</head>
+<body>
+<p>Hi.<br/>there</p>
+</body>
+</html>
+EOD;
+$d->loadHTML($str);
+$e = $d->getElementsByTagName("p");
+$e = $e->item(0);
+echo $d->saveXml($e),"\n";
+echo $d->saveHtml($e),"\n";
+--EXPECTF--
+<p>Hi.<br/>there</p>
+<p>Hi.<br>there</p>
diff --git a/ext/dom/tests/bug47430.phpt b/ext/dom/tests/bug47430.phpt
index d3ca435e5f..243fe8441c 100644
--- a/ext/dom/tests/bug47430.phpt
+++ b/ext/dom/tests/bug47430.phpt
@@ -21,9 +21,9 @@ print_r($arr);
?>
--EXPECTF--
-Strict Standards: Creating default object from empty value in %s on line %d
+Warning: Creating default object from empty value in %s on line %d
-Strict Standards: Creating default object from empty value in %s on line %d
+Warning: Creating default object from empty value in %s on line %d
Array
(
[0] => Value
diff --git a/ext/dom/text.c b/ext/dom/text.c
index 5ab716f389..4c129bf387 100644
--- a/ext/dom/text.c
+++ b/ext/dom/text.c
@@ -196,7 +196,7 @@ PHP_FUNCTION(dom_text_split_text)
nnode->type = XML_TEXT_NODE;
}
- return_value = php_dom_create_object(nnode, &ret, NULL, return_value, intern TSRMLS_CC);
+ return_value = php_dom_create_object(nnode, &ret, return_value, intern TSRMLS_CC);
}
/* }}} end dom_text_split_text */
diff --git a/ext/dom/xml_common.h b/ext/dom/xml_common.h
index 40a72d8ee0..ebe8a516ee 100644
--- a/ext/dom/xml_common.h
+++ b/ext/dom/xml_common.h
@@ -54,7 +54,7 @@ typedef struct _dom_object {
PHP_DOM_EXPORT extern zend_class_entry *dom_node_class_entry;
PHP_DOM_EXPORT dom_object *php_dom_object_get_data(xmlNodePtr obj);
-PHP_DOM_EXPORT zval *php_dom_create_object(xmlNodePtr obj, int *found, zval *in, zval* return_value, dom_object *domobj TSRMLS_DC);
+PHP_DOM_EXPORT zval *php_dom_create_object(xmlNodePtr obj, int *found, zval* return_value, dom_object *domobj TSRMLS_DC);
PHP_DOM_EXPORT xmlNodePtr dom_object_get_node(dom_object *obj);
#define DOM_XMLNS_NAMESPACE \
@@ -78,14 +78,12 @@ PHP_DOM_EXPORT xmlNodePtr dom_object_get_node(dom_object *obj);
} \
}
-#define DOM_RET_OBJ_EX(obj, ret, domobject) \
- if (!php_dom_create_object(obj, ret, NULL, return_value, domobject TSRMLS_CC)) { \
+#define DOM_RET_OBJ(obj, ret, domobject) \
+ if (!php_dom_create_object(obj, ret, return_value, domobject TSRMLS_CC)) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object"); \
RETURN_FALSE; \
}
-#define DOM_RET_OBJ(zval, obj, ret, domobject) DOM_RET_OBJ_EX(obj, ret, domobject)
-
#define DOM_GET_THIS(zval) \
if (NULL == (zval = getThis())) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Underlying object missing"); \
diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c
index b5a31d7f92..342854654e 100644
--- a/ext/dom/xpath.c
+++ b/ext/dom/xpath.c
@@ -164,7 +164,7 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs,
node->parent = nsparent;
node->ns = curns;
}
- child = php_dom_create_object(node, &ret, NULL, child, (dom_object *)intern TSRMLS_CC);
+ child = php_dom_create_object(node, &ret, child, (dom_object *)intern TSRMLS_CC);
add_next_index_zval(args[i], child);
}
}
@@ -216,7 +216,7 @@ static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs,
if (Z_TYPE(handler) == IS_STRING) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler));
}
- /* retval is == NULL, when an exception occured, don't report anything, because PHP itself will handle that */
+ /* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */
} else if (retval == NULL) {
} else {
if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) {
@@ -331,7 +331,8 @@ int dom_xpath_document_read(dom_object *obj, zval **retval TSRMLS_DC)
ALLOC_ZVAL(*retval);
tmp = *retval;
- if (NULL == (*retval = php_dom_create_object((xmlNodePtr) docp, &ret, NULL, *retval, obj TSRMLS_CC))) {
+
+ if (NULL == (*retval = php_dom_create_object((xmlNodePtr) docp, &ret, *retval, obj TSRMLS_CC))) {
FREE_ZVAL(tmp);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
return FAILURE;
@@ -498,7 +499,7 @@ static void php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
node->parent = nsparent;
node->ns = curns;
}
- child = php_dom_create_object(node, &ret, NULL, child, (dom_object *)intern TSRMLS_CC);
+ child = php_dom_create_object(node, &ret, child, (dom_object *)intern TSRMLS_CC);
add_next_index_zval(retval, child);
}
}
diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c
index dcc39e267b..357f3cb034 100644
--- a/ext/enchant/enchant.c
+++ b/ext/enchant/enchant.c
@@ -124,7 +124,7 @@ ZEND_END_ARG_INFO()
*
* Every user visible function must have an entry in enchant_functions[].
*/
-function_entry enchant_functions[] = {
+zend_function_entry enchant_functions[] = {
PHP_FE(enchant_broker_init, arginfo_enchant_broker_init)
PHP_FE(enchant_broker_free, arginfo_enchant_broker_free)
PHP_FE(enchant_broker_get_error, arginfo_enchant_broker_free)
@@ -244,8 +244,8 @@ static void php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{
if (broker->pbroker) {
if (broker->dictcnt && broker->dict) {
if (broker->dict) {
- int total, tofree;
- tofree = total = broker->dictcnt-1;
+ int total;
+ total = broker->dictcnt-1;
do {
zend_list_delete(broker->dict[total]->rsrc_id);
efree(broker->dict[total]);
@@ -357,8 +357,8 @@ PHP_FUNCTION(enchant_broker_init)
enchant_broker *broker;
EnchantBroker *pbroker;
- if (ZEND_NUM_ARGS()) {
- ZEND_WRONG_PARAM_COUNT();
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
}
pbroker = enchant_broker_init();
@@ -542,6 +542,11 @@ PHP_FUNCTION(enchant_broker_request_dict)
}
PHP_ENCHANT_GET_BROKER;
+
+ if (taglen == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tag cannot be empty");
+ RETURN_FALSE;
+ }
d = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag);
if (d) {
@@ -586,11 +591,7 @@ PHP_FUNCTION(enchant_broker_request_pwl_dict)
int pwllen;
int pos;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &pwl, &pwllen) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(pwl) != pwllen) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &broker, &pwl, &pwllen) == FAILURE) {
RETURN_FALSE;
}
diff --git a/ext/ereg/config.w32 b/ext/ereg/config.w32
index d4b06747df..18a002b44d 100644
--- a/ext/ereg/config.w32
+++ b/ext/ereg/config.w32
@@ -4,7 +4,7 @@
ARG_WITH("ereg", "POSIX extended regular expressions", "yes");
if (PHP_EREG != "no") {
- EXTENSION("ereg", "ereg.c", false /* never shared */, "-Dregexec=php_regexec -Dregerror=php_regerror -Dregfree=php_regfree -Dregcomp=php_regcomp -Iext/ereg/regex");
+ EXTENSION("ereg", "ereg.c", PHP_EREG_SHARED, "-Dregexec=php_regexec -Dregerror=php_regerror -Dregfree=php_regfree -Dregcomp=php_regcomp -Iext/ereg/regex");
ADD_SOURCES("ext/ereg/regex", "regcomp.c regexec.c regerror.c regfree.c", "ereg");
AC_DEFINE('REGEX', 1, 'Bundled regex');
AC_DEFINE('HSREGEX', 1, 'Bundled regex');
diff --git a/ext/ereg/ereg.c b/ext/ereg/ereg.c
index 2f4a96fea4..bbfc83b10c 100644
--- a/ext/ereg/ereg.c
+++ b/ext/ereg/ereg.c
@@ -74,22 +74,34 @@ static int reg_magic = 0;
/* }}} */
ZEND_DECLARE_MODULE_GLOBALS(ereg)
+static PHP_GINIT_FUNCTION(ereg);
+static PHP_GSHUTDOWN_FUNCTION(ereg);
/* {{{ Module entry */
zend_module_entry ereg_module_entry = {
STANDARD_MODULE_HEADER,
"ereg",
ereg_functions,
- PHP_MINIT(ereg),
- PHP_MSHUTDOWN(ereg),
+ NULL,
+ NULL,
NULL,
NULL,
PHP_MINFO(ereg),
NO_VERSION_YET,
- STANDARD_MODULE_PROPERTIES
+ PHP_MODULE_GLOBALS(ereg),
+ PHP_GINIT(ereg),
+ PHP_GSHUTDOWN(ereg),
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
+/* {{{ COMPILE_DL_EREG */
+#ifdef COMPILE_DL_EREG
+ZEND_GET_MODULE(ereg)
+#endif
+/* }}} */
+
/* {{{ ereg_lru_cmp */
static int ereg_lru_cmp(const void *a, const void *b TSRMLS_DC)
{
@@ -124,12 +136,11 @@ static int ereg_clean_cache(void *data, void *arg TSRMLS_DC)
/* {{{ _php_regcomp
*/
-static int _php_regcomp(regex_t *preg, const char *pattern, int cflags)
+static int _php_regcomp(regex_t *preg, const char *pattern, int cflags TSRMLS_DC)
{
int r = 0;
int patlen = strlen(pattern);
reg_cache *rc = NULL;
- TSRMLS_FETCH();
if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) {
/* easier than dealing with overflow as it happens */
@@ -201,33 +212,24 @@ static void _free_ereg_cache(reg_cache *rc)
#undef regfree
#define regfree(a);
#undef regcomp
-#define regcomp(a, b, c) _php_regcomp(a, b, c)
-
-static void php_ereg_init_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
+#define regcomp(a, b, c) _php_regcomp(a, b, c TSRMLS_CC)
+
+/* {{{ PHP_GINIT_FUNCTION
+ */
+static PHP_GINIT_FUNCTION(ereg)
{
zend_hash_init(&ereg_globals->ht_rc, 0, NULL, (void (*)(void *)) _free_ereg_cache, 1);
ereg_globals->lru_counter = 0;
}
+/* }}} */
-static void php_ereg_destroy_globals(zend_ereg_globals *ereg_globals TSRMLS_DC)
+/* {{{ PHP_GSHUTDOWN_FUNCTION
+ */
+static PHP_GSHUTDOWN_FUNCTION(ereg)
{
zend_hash_destroy(&ereg_globals->ht_rc);
}
-
-PHP_MINIT_FUNCTION(ereg)
-{
- ZEND_INIT_MODULE_GLOBALS(ereg, php_ereg_init_globals, php_ereg_destroy_globals);
- return SUCCESS;
-}
-
-PHP_MSHUTDOWN_FUNCTION(ereg)
-{
-#ifndef ZTS
- php_ereg_destroy_globals(&ereg_globals TSRMLS_CC);
-#endif
-
- return SUCCESS;
-}
+/* }}} */
PHP_MINFO_FUNCTION(ereg)
{
@@ -244,7 +246,7 @@ PHP_MINFO_FUNCTION(ereg)
/* {{{ php_ereg_eprint
* php_ereg_eprint - convert error number to name
*/
-static void php_ereg_eprint(int err, regex_t *re) {
+static void php_ereg_eprint(int err, regex_t *re TSRMLS_DC) {
char *buf = NULL, *message = NULL;
size_t len;
size_t buf_len;
@@ -263,8 +265,6 @@ static void php_ereg_eprint(int err, regex_t *re) {
#endif
len = regerror(err, re, NULL, 0);
if (len) {
- TSRMLS_FETCH();
-
message = (char *)safe_emalloc((buf_len + len + 2), sizeof(char), 0);
if (!message) {
return; /* fail silently */
@@ -328,7 +328,7 @@ static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
}
if (err) {
- php_ereg_eprint(err, &re);
+ php_ereg_eprint(err, &re TSRMLS_CC);
RETURN_FALSE;
}
@@ -341,7 +341,7 @@ static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
/* actually execute the regular expression */
err = regexec(&re, string, re.re_nsub+1, subs, 0);
if (err && err != REG_NOMATCH) {
- php_ereg_eprint(err, &re);
+ php_ereg_eprint(err, &re TSRMLS_CC);
regfree(&re);
efree(subs);
RETURN_FALSE;
@@ -400,7 +400,7 @@ PHP_FUNCTION(eregi)
/* {{{ php_ereg_replace
* this is the meat and potatoes of regex replacement! */
-PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended)
+PHP_EREG_API char *php_ereg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended TSRMLS_DC)
{
regex_t re;
regmatch_t *subs;
@@ -424,7 +424,7 @@ PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const ch
err = regcomp(&re, pattern, copts);
if (err) {
- php_ereg_eprint(err, &re);
+ php_ereg_eprint(err, &re TSRMLS_CC);
return ((char *) -1);
}
@@ -443,7 +443,7 @@ PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const ch
err = regexec(&re, &string[pos], re.re_nsub+1, subs, (pos ? REG_NOTBOL : 0));
if (err && err != REG_NOMATCH) {
- php_ereg_eprint(err, &re);
+ php_ereg_eprint(err, &re TSRMLS_CC);
efree(subs);
efree(buf);
regfree(&re);
@@ -474,7 +474,7 @@ PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const ch
if (new_l + 1 > buf_len) {
buf_len = 1 + buf_len + 2 * new_l;
nbuf = emalloc(buf_len);
- strncpy(nbuf, buf, buf_len-1);
+ strncpy(nbuf, buf, buf_len - 1);
nbuf[buf_len - 1] = '\0';
efree(buf);
buf = nbuf;
@@ -487,7 +487,7 @@ PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const ch
walkbuf = &buf[tmp + subs[0].rm_so];
walk = replace;
while (*walk) {
- if ('\\' == *walk && isdigit((unsigned char)walk[1]) && ((unsigned char)walk[1]) - '0' <= (int)re.re_nsub) {
+ if ('\\' == *walk && isdigit((unsigned char)walk[1]) && (unsigned char)walk[1] - '0' <= (int)re.re_nsub) {
if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1
/* this next case shouldn't happen. it does. */
&& subs[walk[1] - '0'].rm_so <= subs[walk[1] - '0'].rm_eo) {
@@ -594,7 +594,7 @@ static void php_do_ereg_replace(INTERNAL_FUNCTION_PARAMETERS, int icase)
}
/* do the actual work */
- ret = php_ereg_replace(pattern, replace, string, icase, 1);
+ ret = php_ereg_replace(pattern, replace, string, icase, 1 TSRMLS_CC);
if (ret == (char *) -1) {
RETVAL_FALSE;
} else {
@@ -648,7 +648,7 @@ static void php_split(INTERNAL_FUNCTION_PARAMETERS, int icase)
err = regcomp(&re, spliton, REG_EXTENDED | copts);
if (err) {
- php_ereg_eprint(err, &re);
+ php_ereg_eprint(err, &re TSRMLS_CC);
RETURN_FALSE;
}
@@ -692,7 +692,7 @@ static void php_split(INTERNAL_FUNCTION_PARAMETERS, int icase)
/* see if we encountered an error */
if (err && err != REG_NOMATCH) {
- php_ereg_eprint(err, &re);
+ php_ereg_eprint(err, &re TSRMLS_CC);
regfree(&re);
zend_hash_destroy(Z_ARRVAL_P(return_value));
efree(Z_ARRVAL_P(return_value));
@@ -728,7 +728,7 @@ PHP_FUNCTION(spliti)
/* {{{ proto string sql_regcase(string string)
Make regular expression for case insensitive match */
-PHPAPI PHP_FUNCTION(sql_regcase)
+PHP_EREG_API PHP_FUNCTION(sql_regcase)
{
char *string, *tmp;
int string_len;
diff --git a/ext/ereg/php_ereg.h b/ext/ereg/php_ereg.h
index b27db060d9..eea70a1578 100644
--- a/ext/ereg/php_ereg.h
+++ b/ext/ereg/php_ereg.h
@@ -27,7 +27,15 @@
extern zend_module_entry ereg_module_entry;
#define phpext_ereg_ptr &ereg_module_entry
-PHPAPI char *php_ereg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended);
+#ifdef PHP_WIN32
+# define PHP_EREG_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define PHP_EREG_API __attribute__ ((visibility("default")))
+#else
+# define PHP_EREG_API
+#endif
+
+PHP_EREG_API char *php_ereg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended TSRMLS_DC);
PHP_FUNCTION(ereg);
PHP_FUNCTION(eregi);
@@ -35,7 +43,7 @@ PHP_FUNCTION(eregi_replace);
PHP_FUNCTION(ereg_replace);
PHP_FUNCTION(split);
PHP_FUNCTION(spliti);
-PHPAPI PHP_FUNCTION(sql_regcase);
+PHP_EREG_API PHP_FUNCTION(sql_regcase);
ZEND_BEGIN_MODULE_GLOBALS(ereg)
HashTable ht_rc;
@@ -43,8 +51,6 @@ ZEND_BEGIN_MODULE_GLOBALS(ereg)
ZEND_END_MODULE_GLOBALS(ereg)
/* Module functions */
-PHP_MINIT_FUNCTION(ereg);
-PHP_MSHUTDOWN_FUNCTION(ereg);
PHP_MINFO_FUNCTION(ereg);
#ifdef ZTS
@@ -53,4 +59,6 @@ PHP_MINFO_FUNCTION(ereg);
#define EREG(v) (ereg_globals.v)
#endif
+ZEND_EXTERN_MODULE_GLOBALS(ereg)
+
#endif /* REG_H */
diff --git a/ext/ereg/tests/ereg_replace_variation_001.phpt b/ext/ereg/tests/ereg_replace_variation_001.phpt
index ebb1504f63..1e16d1c8cb 100644
--- a/ext/ereg/tests/ereg_replace_variation_001.phpt
+++ b/ext/ereg/tests/ereg_replace_variation_001.phpt
@@ -122,23 +122,28 @@ Arg value 0.5
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
Error: 2 - ereg_replace(): REG_EMPTY, %s(74)
bool(false)
+Error: 8 - Array to string conversion, %sereg_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
Error: 2 - ereg_replace(): REG_EMPTY, %s(74)
bool(false)
+Error: 8 - Array to string conversion, %sereg_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(8) "original"
+Error: 8 - Array to string conversion, %sereg_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(8) "original"
+Error: 8 - Array to string conversion, %sereg_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(8) "original"
+Error: 8 - Array to string conversion, %sereg_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
diff --git a/ext/ereg/tests/ereg_replace_variation_002.phpt b/ext/ereg/tests/ereg_replace_variation_002.phpt
index 19f91c6b94..afaece6b22 100644
--- a/ext/ereg/tests/ereg_replace_variation_002.phpt
+++ b/ext/ereg/tests/ereg_replace_variation_002.phpt
@@ -119,22 +119,27 @@ string(5) "ho%21"
Arg value 0.5
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(5) "ho%21"
+Error: 8 - Array to string conversion, %sereg_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(5) "ho%21"
+Error: 8 - Array to string conversion, %sereg_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(8) "h%01o%21"
+Error: 8 - Array to string conversion, %sereg_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(8) "h%01o%21"
+Error: 8 - Array to string conversion, %sereg_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(8) "h%01o%21"
+Error: 8 - Array to string conversion, %sereg_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
diff --git a/ext/ereg/tests/ereg_replace_variation_003.phpt b/ext/ereg/tests/ereg_replace_variation_003.phpt
index c6a606e31a..b189c4efc6 100644
--- a/ext/ereg/tests/ereg_replace_variation_003.phpt
+++ b/ext/ereg/tests/ereg_replace_variation_003.phpt
@@ -119,26 +119,31 @@ string(29) "new value.0765432new valueE-9"
Arg value 0.5
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
string(3) "0.5"
+Error: 8 - Array to string conversion, %sereg_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
Error: 2 - ereg_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
Error: 2 - ereg_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
Error: 2 - ereg_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
Error: 2 - ereg_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function ereg_replace() is deprecated, %s(74)
diff --git a/ext/ereg/tests/ereg_variation_001.phpt b/ext/ereg/tests/ereg_variation_001.phpt
index 52b88abb71..8e28d89a90 100644
--- a/ext/ereg/tests/ereg_variation_001.phpt
+++ b/ext/ereg/tests/ereg_variation_001.phpt
@@ -120,26 +120,31 @@ bool(false)
Arg value 0.5
Error: 8192 - Function ereg() is deprecated, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %sereg_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %sereg_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %sereg_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %sereg_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %sereg_variation_001.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(75)
diff --git a/ext/ereg/tests/ereg_variation_002.phpt b/ext/ereg/tests/ereg_variation_002.phpt
index 1b3e3fc46c..33e0fe1d10 100644
--- a/ext/ereg/tests/ereg_variation_002.phpt
+++ b/ext/ereg/tests/ereg_variation_002.phpt
@@ -119,26 +119,31 @@ int(1)
Arg value 0.5
Error: 8192 - Function ereg() is deprecated, %s(74)
bool(false)
+Error: 8 - Array to string conversion, %sereg_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(74)
Error: 2 - ereg() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(74)
Error: 2 - ereg() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(74)
Error: 2 - ereg() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(74)
Error: 2 - ereg() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sereg_variation_002.php(%d)
Arg value Array
Error: 8192 - Function ereg() is deprecated, %s(74)
diff --git a/ext/ereg/tests/eregi_replace_variation_001.phpt b/ext/ereg/tests/eregi_replace_variation_001.phpt
index af2935db6e..e3d2b655f5 100644
--- a/ext/ereg/tests/eregi_replace_variation_001.phpt
+++ b/ext/ereg/tests/eregi_replace_variation_001.phpt
@@ -122,23 +122,28 @@ Arg value 0.5
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
Error: 2 - eregi_replace(): REG_EMPTY, %s(74)
bool(false)
+Error: 8 - Array to string conversion, %seregi_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
Error: 2 - eregi_replace(): REG_EMPTY, %s(74)
bool(false)
+Error: 8 - Array to string conversion, %seregi_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(8) "original"
+Error: 8 - Array to string conversion, %seregi_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(8) "original"
+Error: 8 - Array to string conversion, %seregi_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(8) "original"
+Error: 8 - Array to string conversion, %seregi_replace_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
diff --git a/ext/ereg/tests/eregi_replace_variation_002.phpt b/ext/ereg/tests/eregi_replace_variation_002.phpt
index e14c5a185b..46229e0f57 100644
--- a/ext/ereg/tests/eregi_replace_variation_002.phpt
+++ b/ext/ereg/tests/eregi_replace_variation_002.phpt
@@ -119,22 +119,27 @@ string(5) "ho%21"
Arg value 0.5
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(5) "ho%21"
+Error: 8 - Array to string conversion, %seregi_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(5) "ho%21"
+Error: 8 - Array to string conversion, %seregi_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(8) "h%01o%21"
+Error: 8 - Array to string conversion, %seregi_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(8) "h%01o%21"
+Error: 8 - Array to string conversion, %seregi_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(8) "h%01o%21"
+Error: 8 - Array to string conversion, %seregi_replace_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
diff --git a/ext/ereg/tests/eregi_replace_variation_003.phpt b/ext/ereg/tests/eregi_replace_variation_003.phpt
index 8e8e5086bd..ae9edba829 100644
--- a/ext/ereg/tests/eregi_replace_variation_003.phpt
+++ b/ext/ereg/tests/eregi_replace_variation_003.phpt
@@ -119,26 +119,31 @@ string(29) "new value.0765432new valueE-9"
Arg value 0.5
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
string(3) "0.5"
+Error: 8 - Array to string conversion, %seregi_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
Error: 2 - eregi_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
Error: 2 - eregi_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
Error: 2 - eregi_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
Error: 2 - eregi_replace() expects parameter 3 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_replace_variation_003.php(%d)
Arg value Array
Error: 8192 - Function eregi_replace() is deprecated, %s(74)
diff --git a/ext/ereg/tests/eregi_variation_001.phpt b/ext/ereg/tests/eregi_variation_001.phpt
index 54e80bb16e..38c2cbaef3 100644
--- a/ext/ereg/tests/eregi_variation_001.phpt
+++ b/ext/ereg/tests/eregi_variation_001.phpt
@@ -120,26 +120,31 @@ bool(false)
Arg value 0.5
Error: 8192 - Function eregi() is deprecated, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %seregi_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %seregi_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %seregi_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %seregi_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(75)
Error: 8 - Array to string conversion, %s(75)
bool(false)
+Error: 8 - Array to string conversion, %seregi_variation_001.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(75)
diff --git a/ext/ereg/tests/eregi_variation_002.phpt b/ext/ereg/tests/eregi_variation_002.phpt
index bb7fc35636..8e803b55fa 100644
--- a/ext/ereg/tests/eregi_variation_002.phpt
+++ b/ext/ereg/tests/eregi_variation_002.phpt
@@ -119,26 +119,31 @@ int(1)
Arg value 0.5
Error: 8192 - Function eregi() is deprecated, %s(74)
bool(false)
+Error: 8 - Array to string conversion, %seregi_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(74)
Error: 2 - eregi() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(74)
Error: 2 - eregi() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(74)
Error: 2 - eregi() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(74)
Error: 2 - eregi() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %seregi_variation_002.php(%d)
Arg value Array
Error: 8192 - Function eregi() is deprecated, %s(74)
diff --git a/ext/ereg/tests/split_variation_001.phpt b/ext/ereg/tests/split_variation_001.phpt
index 454c4b4250..9d9fc9d518 100644
--- a/ext/ereg/tests/split_variation_001.phpt
+++ b/ext/ereg/tests/split_variation_001.phpt
@@ -152,26 +152,31 @@ array(1) {
[0]=>
string(16) "1 a 1 Array 1 c "
}
+Error: 8 - Array to string conversion, %ssplit_variation_001.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_001.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_001.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_001.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_001.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
diff --git a/ext/ereg/tests/split_variation_002.phpt b/ext/ereg/tests/split_variation_002.phpt
index 2a07353136..b1ea57c787 100644
--- a/ext/ereg/tests/split_variation_002.phpt
+++ b/ext/ereg/tests/split_variation_002.phpt
@@ -148,26 +148,31 @@ array(1) {
[0]=>
string(3) "0.5"
}
+Error: 8 - Array to string conversion, %ssplit_variation_002.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_002.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_002.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_002.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
Error: 2 - split() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_002.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(74)
diff --git a/ext/ereg/tests/split_variation_003.phpt b/ext/ereg/tests/split_variation_003.phpt
index 480db35bc9..edef9cfeb9 100644
--- a/ext/ereg/tests/split_variation_003.phpt
+++ b/ext/ereg/tests/split_variation_003.phpt
@@ -116,26 +116,31 @@ array(1) {
[0]=>
string(9) "1 2 3 4 5"
}
+Error: 8 - Array to string conversion, %ssplit_variation_003.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(73)
Error: 2 - split() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_003.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(73)
Error: 2 - split() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_003.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(73)
Error: 2 - split() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_003.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(73)
Error: 2 - split() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %ssplit_variation_003.php(%d)
Arg value Array
Error: 8192 - Function split() is deprecated, %s(73)
diff --git a/ext/ereg/tests/spliti_variation_001.phpt b/ext/ereg/tests/spliti_variation_001.phpt
index 08c6ba0d99..e5493b34ad 100644
--- a/ext/ereg/tests/spliti_variation_001.phpt
+++ b/ext/ereg/tests/spliti_variation_001.phpt
@@ -152,26 +152,31 @@ array(1) {
[0]=>
string(16) "1 a 1 Array 1 c "
}
+Error: 8 - Array to string conversion, %sspliti_variation_001.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_001.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_001.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_001.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_001.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
diff --git a/ext/ereg/tests/spliti_variation_002.phpt b/ext/ereg/tests/spliti_variation_002.phpt
index 03fc131e94..752cafc4f5 100644
--- a/ext/ereg/tests/spliti_variation_002.phpt
+++ b/ext/ereg/tests/spliti_variation_002.phpt
@@ -148,26 +148,31 @@ array(1) {
[0]=>
string(3) "0.5"
}
+Error: 8 - Array to string conversion, %sspliti_variation_002.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_002.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_002.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_002.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
Error: 2 - spliti() expects parameter 2 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_002.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(74)
diff --git a/ext/ereg/tests/spliti_variation_003.phpt b/ext/ereg/tests/spliti_variation_003.phpt
index beee4c643e..3cfeaeae1a 100644
--- a/ext/ereg/tests/spliti_variation_003.phpt
+++ b/ext/ereg/tests/spliti_variation_003.phpt
@@ -116,26 +116,31 @@ array(1) {
[0]=>
string(9) "1 2 3 4 5"
}
+Error: 8 - Array to string conversion, %sspliti_variation_003.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(73)
Error: 2 - spliti() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_003.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(73)
Error: 2 - spliti() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_003.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(73)
Error: 2 - spliti() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_003.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(73)
Error: 2 - spliti() expects parameter 3 to be long, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sspliti_variation_003.php(%d)
Arg value Array
Error: 8192 - Function spliti() is deprecated, %s(73)
diff --git a/ext/ereg/tests/sql_regcase_variation_001.phpt b/ext/ereg/tests/sql_regcase_variation_001.phpt
index c2c28ab50e..0efbe92622 100644
--- a/ext/ereg/tests/sql_regcase_variation_001.phpt
+++ b/ext/ereg/tests/sql_regcase_variation_001.phpt
@@ -117,26 +117,31 @@ string(16) "1.07654321[Ee]-9"
Arg value 0.5
Error: 8192 - Function sql_regcase() is deprecated, %s(72)
string(3) "0.5"
+Error: 8 - Array to string conversion, %ssql_regcase_variation_001.php(%d)
Arg value Array
Error: 8192 - Function sql_regcase() is deprecated, %s(72)
Error: 2 - sql_regcase() expects parameter 1 to be string, array given, %s(72)
NULL
+Error: 8 - Array to string conversion, %ssql_regcase_variation_001.php(%d)
Arg value Array
Error: 8192 - Function sql_regcase() is deprecated, %s(72)
Error: 2 - sql_regcase() expects parameter 1 to be string, array given, %s(72)
NULL
+Error: 8 - Array to string conversion, %ssql_regcase_variation_001.php(%d)
Arg value Array
Error: 8192 - Function sql_regcase() is deprecated, %s(72)
Error: 2 - sql_regcase() expects parameter 1 to be string, array given, %s(72)
NULL
+Error: 8 - Array to string conversion, %ssql_regcase_variation_001.php(%d)
Arg value Array
Error: 8192 - Function sql_regcase() is deprecated, %s(72)
Error: 2 - sql_regcase() expects parameter 1 to be string, array given, %s(72)
NULL
+Error: 8 - Array to string conversion, %ssql_regcase_variation_001.php(%d)
Arg value Array
Error: 8192 - Function sql_regcase() is deprecated, %s(72)
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index 604010b039..9db6674742 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -76,16 +76,6 @@
#include "ext/standard/php_image.h"
#include "ext/standard/info.h"
-#if defined(PHP_WIN32) || (HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING))
-#define EXIF_USE_MBSTRING 1
-#else
-#define EXIF_USE_MBSTRING 0
-#endif
-
-#if EXIF_USE_MBSTRING
-#include "ext/mbstring/mbstring.h"
-#endif
-
/* needed for ssize_t definition */
#include <sys/types.h>
@@ -186,23 +176,31 @@ ZEND_DECLARE_MODULE_GLOBALS(exif)
ZEND_INI_MH(OnUpdateEncode)
{
-#if EXIF_USE_MBSTRING
- if (new_value && strlen(new_value) && !php_mb_check_encoding_list(new_value TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
- return FAILURE;
+ if (new_value && new_value_length) {
+ const zend_encoding **return_list;
+ size_t return_size;
+ if (FAILURE == zend_multibyte_parse_encoding_list(new_value, new_value_length,
+ &return_list, &return_size, 0 TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
+ return FAILURE;
+ }
+ efree(return_list);
}
-#endif
return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
}
ZEND_INI_MH(OnUpdateDecode)
{
-#if EXIF_USE_MBSTRING
- if (!php_mb_check_encoding_list(new_value TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
- return FAILURE;
+ if (new_value) {
+ const zend_encoding **return_list;
+ size_t return_size;
+ if (FAILURE == zend_multibyte_parse_encoding_list(new_value, new_value_length,
+ &return_list, &return_size, 0 TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value);
+ return FAILURE;
+ }
+ efree(return_list);
}
-#endif
return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
}
@@ -234,7 +232,11 @@ static PHP_GINIT_FUNCTION(exif)
PHP_MINIT_FUNCTION(exif)
{
REGISTER_INI_ENTRIES();
- REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", EXIF_USE_MBSTRING, CONST_CS | CONST_PERSISTENT);
+ if (zend_hash_exists(&module_registry, "mbstring", sizeof("mbstring"))) {
+ REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 1, CONST_CS | CONST_PERSISTENT);
+ } else {
+ REGISTER_LONG_CONSTANT("EXIF_USE_MBSTRING", 0, CONST_CS | CONST_PERSISTENT);
+ }
return SUCCESS;
}
/* }}} */
@@ -251,9 +253,7 @@ PHP_MSHUTDOWN_FUNCTION(exif)
/* {{{ exif dependencies */
static const zend_module_dep exif_module_deps[] = {
ZEND_MOD_REQUIRED("standard")
-#if EXIF_USE_MBSTRING
- ZEND_MOD_REQUIRED("mbstring")
-#endif
+ ZEND_MOD_OPTIONAL("mbstring")
ZEND_MOD_END
};
/* }}} */
@@ -1697,11 +1697,7 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c
case TAG_FMT_STRING:
if (value) {
length = php_strnlen(value, length);
- if (PG(magic_quotes_runtime)) {
- info_value->s = php_addslashes(value, length, &length, 0 TSRMLS_CC);
- } else {
- info_value->s = estrndup(value, length);
- }
+ info_value->s = estrndup(value, length);
info_data->length = length;
} else {
info_data->length = 0;
@@ -1724,11 +1720,7 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c
case TAG_FMT_UNDEFINED:
if (value) {
/* do not recompute length here */
- if (PG(magic_quotes_runtime)) {
- info_value->s = php_addslashes(value, length, &length, 0 TSRMLS_CC);
- } else {
- info_value->s = estrndup(value, length);
- }
+ info_value->s = estrndup(value, length);
info_data->length = length;
} else {
info_data->length = 0;
@@ -1850,11 +1842,7 @@ static void exif_iif_add_str(image_info_type *image_info, int section_index, cha
info_data->format = TAG_FMT_STRING;
info_data->length = 1;
info_data->name = estrdup(name);
- if (PG(magic_quotes_runtime)) {
- info_data->value.s = php_addslashes(value, strlen(value), NULL, 0 TSRMLS_CC);
- } else {
- info_data->value.s = estrdup(value);
- }
+ info_data->value.s = estrdup(value);
image_info->sections_found |= 1<<section_index;
image_info->info_list[section_index].count++;
}
@@ -1895,17 +1883,9 @@ static void exif_iif_add_buffer(image_info_type *image_info, int section_index,
info_data->format = TAG_FMT_UNDEFINED;
info_data->length = length;
info_data->name = estrdup(name);
- if (PG(magic_quotes_runtime)) {
-#ifdef EXIF_DEBUG
- exif_error_docref(NULL EXIFERR_CC, image_info, E_NOTICE, "Adding %s as buffer%s", name, exif_char_dump(value, length, 0));
-#endif
- info_data->value.s = php_addslashes(value, length, &length, 0 TSRMLS_CC);
- info_data->length = length;
- } else {
- info_data->value.s = safe_emalloc(length, 1, 1);
- memcpy(info_data->value.s, value, length);
- info_data->value.s[length] = 0;
- }
+ info_data->value.s = safe_emalloc(length, 1, 1);
+ memcpy(info_data->value.s, value, length);
+ info_data->value.s[length] = 0;
image_info->sections_found |= 1<<section_index;
image_info->info_list[section_index].count++;
}
@@ -2598,7 +2578,6 @@ static int exif_process_undefined(char **result, char *value, size_t byte_count
/* {{{ exif_process_string_raw
* Copy a string in Exif header to a character string returns length of allocated buffer if any. */
-#if !EXIF_USE_MBSTRING
static int exif_process_string_raw(char **result, char *value, size_t byte_count) {
/* we cannot use strlcpy - here the problem is that we have to copy NUL
* chars up to byte_count, we also have to add a single NUL character to
@@ -2612,7 +2591,6 @@ static int exif_process_string_raw(char **result, char *value, size_t byte_count
}
return 0;
}
-#endif
/* }}} */
/* {{{ exif_process_string
@@ -2639,11 +2617,8 @@ static int exif_process_string(char **result, char *value, size_t byte_count TSR
static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoPtr, char **pszEncoding, char *szValuePtr, int ByteCount TSRMLS_DC)
{
int a;
-
-#if EXIF_USE_MBSTRING
char *decode;
size_t len;;
-#endif
*pszEncoding = NULL;
/* Copy the comment */
@@ -2652,7 +2627,6 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
*pszEncoding = estrdup((const char*)szValuePtr);
szValuePtr = szValuePtr+8;
ByteCount -= 8;
-#if EXIF_USE_MBSTRING
/* First try to detect BOM: ZERO WIDTH NOBREAK SPACE (FEFF 16)
* since we have no encoding support for the BOM yet we skip that.
*/
@@ -2669,34 +2643,38 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
} else {
decode = ImageInfo->decode_unicode_le;
}
- *pszInfoPtr = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, decode, &len TSRMLS_CC);
+ if (zend_multibyte_encoding_converter(
+ (unsigned char**)pszInfoPtr,
+ &len,
+ (unsigned char*)szValuePtr,
+ ByteCount,
+ zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
+ zend_multibyte_fetch_encoding(decode TSRMLS_CC)
+ TSRMLS_CC) < 0) {
+ len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
+ }
return len;
-#else
- return exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
-#endif
- } else
- if (!memcmp(szValuePtr, "ASCII\0\0\0", 8)) {
+ } else if (!memcmp(szValuePtr, "ASCII\0\0\0", 8)) {
*pszEncoding = estrdup((const char*)szValuePtr);
szValuePtr = szValuePtr+8;
ByteCount -= 8;
- } else
- if (!memcmp(szValuePtr, "JIS\0\0\0\0\0", 8)) {
+ } else if (!memcmp(szValuePtr, "JIS\0\0\0\0\0", 8)) {
/* JIS should be tanslated to MB or we leave it to the user - leave it to the user */
*pszEncoding = estrdup((const char*)szValuePtr);
szValuePtr = szValuePtr+8;
ByteCount -= 8;
-#if EXIF_USE_MBSTRING
- if (ImageInfo->motorola_intel) {
- *pszInfoPtr = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_jis, ImageInfo->decode_jis_be, &len TSRMLS_CC);
- } else {
- *pszInfoPtr = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_jis, ImageInfo->decode_jis_le, &len TSRMLS_CC);
+ if (zend_multibyte_encoding_converter(
+ (unsigned char**)pszInfoPtr,
+ &len,
+ (unsigned char*)szValuePtr,
+ ByteCount,
+ zend_multibyte_fetch_encoding(ImageInfo->encode_jis TSRMLS_CC),
+ zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_jis_be : ImageInfo->decode_jis_le TSRMLS_CC)
+ TSRMLS_CC) < 0) {
+ len = exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
}
return len;
-#else
- return exif_process_string_raw(pszInfoPtr, szValuePtr, ByteCount);
-#endif
- } else
- if (!memcmp(szValuePtr, "\0\0\0\0\0\0\0\0", 8)) {
+ } else if (!memcmp(szValuePtr, "\0\0\0\0\0\0\0\0", 8)) {
/* 8 NULL means undefined and should be ASCII... */
*pszEncoding = estrdup("UNDEFINED");
szValuePtr = szValuePtr+8;
@@ -2724,19 +2702,17 @@ static int exif_process_unicode(image_info_type *ImageInfo, xp_field_type *xp_fi
xp_field->tag = tag;
/* Copy the comment */
-#if EXIF_USE_MBSTRING
-/* What if MS supports big-endian with XP? */
-/* if (ImageInfo->motorola_intel) {
- xp_field->value = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, ImageInfo->decode_unicode_be, &xp_field->size TSRMLS_CC);
- } else {
- xp_field->value = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, ImageInfo->decode_unicode_le, &xp_field->size TSRMLS_CC);
- }*/
- xp_field->value = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, ImageInfo->decode_unicode_le, &xp_field->size TSRMLS_CC);
- return xp_field->size;
-#else
- xp_field->size = exif_process_string_raw(&xp_field->value, szValuePtr, ByteCount);
+ if (zend_multibyte_encoding_converter(
+ (unsigned char**)&xp_field->value,
+ &xp_field->size,
+ (unsigned char*)szValuePtr,
+ ByteCount,
+ zend_multibyte_fetch_encoding(ImageInfo->encode_unicode TSRMLS_CC),
+ zend_multibyte_fetch_encoding(ImageInfo->motorola_intel ? ImageInfo->decode_unicode_be : ImageInfo->decode_unicode_le TSRMLS_CC)
+ TSRMLS_CC) < 0) {
+ xp_field->size = exif_process_string_raw(&xp_field->value, szValuePtr, ByteCount);
+ }
return xp_field->size;
-#endif
}
/* }}} */
@@ -3884,7 +3860,7 @@ static int exif_read_file(image_info_type *ImageInfo, char *FileName, int read_t
ImageInfo->motorola_intel = -1; /* flag as unknown */
- ImageInfo->infile = php_stream_open_wrapper(FileName, "rb", STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
+ ImageInfo->infile = php_stream_open_wrapper(FileName, "rb", STREAM_MUST_SEEK|IGNORE_PATH, NULL);
if (!ImageInfo->infile) {
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Unable to open file");
return FALSE;
@@ -3946,7 +3922,7 @@ PHP_FUNCTION(exif_read_data)
image_info_type ImageInfo;
char tmp[64], *sections_str, *s;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbb", &p_name, &p_name_len, &p_sections_needed, &p_sections_needed_len, &sub_arrays, &read_thumbnail) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbb", &p_name, &p_name_len, &p_sections_needed, &p_sections_needed_len, &sub_arrays, &read_thumbnail) == FAILURE) {
return;
}
@@ -4127,7 +4103,7 @@ PHP_FUNCTION(exif_thumbnail)
WRONG_PARAM_COUNT;
}
- if (zend_parse_parameters(arg_c TSRMLS_CC, "s|z/z/z/", &p_name, &p_name_len, &p_width, &p_height, &p_imagetype) == FAILURE) {
+ if (zend_parse_parameters(arg_c TSRMLS_CC, "p|z/z/z/", &p_name, &p_name_len, &p_width, &p_height, &p_imagetype) == FAILURE) {
return;
}
@@ -4189,7 +4165,7 @@ PHP_FUNCTION(exif_imagetype)
return;
}
- stream = php_stream_open_wrapper(imagefile, "rb", IGNORE_PATH|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(imagefile, "rb", IGNORE_PATH|REPORT_ERRORS, NULL);
if (stream == NULL) {
RETURN_FALSE;
diff --git a/ext/exif/tests/bug34704.phpt b/ext/exif/tests/bug34704.phpt
index b6b26de78d..7688ce861a 100644
--- a/ext/exif/tests/bug34704.phpt
+++ b/ext/exif/tests/bug34704.phpt
@@ -3,7 +3,6 @@ Bug #34704 (Infinite recursion due to corrupt JPEG)
--SKIPIF--
<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
--INI--
-magic_quotes_runtime=0
output_handler=
zlib.output_compression=0
--FILE--
diff --git a/ext/exif/tests/exif002.phpt b/ext/exif/tests/exif002.phpt
index 1b1220c600..2a70f2920c 100644
--- a/ext/exif/tests/exif002.phpt
+++ b/ext/exif/tests/exif002.phpt
@@ -3,7 +3,6 @@ Check for exif_thumbnail
--SKIPIF--
<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
--INI--
-magic_quotes_runtime=0
output_handler=
zlib.output_compression=0
--FILE--
diff --git a/ext/exif/tests/exif006.phpt b/ext/exif/tests/exif006.phpt
deleted file mode 100644
index 10458c083d..0000000000
--- a/ext/exif/tests/exif006.phpt
+++ /dev/null
@@ -1,90 +0,0 @@
---TEST--
-Check for exif_read_data, magic_quotes_runtime
---SKIPIF--
-<?php
- if (!extension_loaded('exif')) die('skip exif extension not available');
- if (version_compare(PHP_VERSION, "4.4.0-dev", "<")) die('skip PHP 4.4 required');
-?>
---INI--
-output_handler=
-zlib.output_compression=0
-magic_quotes_runtime=1
---FILE--
-<?php
-/*
- test1.jpg is a 1*1 image that does not contain any Exif/Comment information
- test2.jpg is the same image but contains Exif/Comment information and a
- copy of test1.jpg as a thumbnail.
- test6.jpg is the same as test2.jpg but with a UNICODE UserComment: &Auml;&Ouml;&&Uuml;&szlig;&auml;&ouml;&uuml;
-*/
-var_dump(exif_read_data(dirname(__FILE__).'/test6.jpg','',true,false));
-?>
---EXPECTF--
-Deprecated: Directive 'magic_quotes_runtime' is deprecated in PHP 5.3 and greater in Unknown on line 0
-array(5) {
- ["FILE"]=>
- array(6) {
- ["FileName"]=>
- string(9) "test6.jpg"
- ["FileDateTime"]=>
- int(%d)
- ["FileSize"]=>
- int(1240)
- ["FileType"]=>
- int(2)
- ["MimeType"]=>
- string(10) "image/jpeg"
- ["SectionsFound"]=>
- string(33) "ANY_TAG, IFD0, THUMBNAIL, COMMENT"
- }
- ["COMPUTED"]=>
- array(12) {
- ["html"]=>
- string(24) "width=\"1\" height=\"1\""
- ["Height"]=>
- int(1)
- ["Width"]=>
- int(1)
- ["IsColor"]=>
- int(1)
- ["ByteOrderMotorola"]=>
- int(1)
- ["UserComment"]=>
- string(16) "Hallo \'Du\'+da!"
- ["UserCommentEncoding"]=>
- string(5) "ASCII"
- ["Copyright"]=>
- string(45) "Photo \"M. Boerger\"., Edited \'M. Boerger\'."
- ["Copyright.Photographer"]=>
- string(21) "Photo \"M. Boerger\"."
- ["Copyright.Editor"]=>
- string(22) "Edited \'M. Boerger\'."
- ["Thumbnail.FileType"]=>
- int(2)
- ["Thumbnail.MimeType"]=>
- string(10) "image/jpeg"
- }
- ["IFD0"]=>
- array(2) {
- ["Copyright"]=>
- string(21) "Photo \"M. Boerger\"."
- ["UserComment"]=>
- string(5) "ASCII"
- }
- ["THUMBNAIL"]=>
- array(2) {
- ["JPEGInterchangeFormat"]=>
- int(134)
- ["JPEGInterchangeFormatLength"]=>
- int(523)
- }
- ["COMMENT"]=>
- array(3) {
- [0]=>
- string(13) "Comment \"1\""
- [1]=>
- string(13) "Comment \'2\'"
- [2]=>
- string(13) "Comment #3end"
- }
-}
diff --git a/ext/fileinfo/config.w32 b/ext/fileinfo/config.w32
index 46b87b56dc..873a12c2f4 100644
--- a/ext/fileinfo/config.w32
+++ b/ext/fileinfo/config.w32
@@ -4,22 +4,16 @@
ARG_ENABLE("fileinfo", "fileinfo support", "no");
if (PHP_FILEINFO != 'no') {
- if (CHECK_HEADER_ADD_INCLUDE("dirent.h", "CFLAGS_FILEINFO") &&
- CHECK_LIB("dirent_a.lib", "fileinfo", PHP_FILEINFO)) {
- LIBMAGIC_SOURCES=" apprentice.c apptype.c ascmagic.c \
- cdf.c cdf_time.c compress.c \
- encoding.c fsmagic.c funcs.c \
- is_tar.c magic.c print.c \
- readcdf.c readelf.c softmagic.c";
+ LIBMAGIC_SOURCES=" apprentice.c apptype.c ascmagic.c \
+ cdf.c cdf_time.c compress.c \
+ encoding.c fsmagic.c funcs.c \
+ is_tar.c magic.c print.c \
+ readcdf.c readelf.c softmagic.c";
- if (VCVERS < 1500) {
- ADD_FLAG('CFLAGS', '/Zm1000');
- }
+ if (VCVERS < 1500) {
+ ADD_FLAG('CFLAGS', '/Zm1000');
+ }
- EXTENSION('fileinfo', 'fileinfo.c', true, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname);
- ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo");
- } else {
- WARNING("fileinfo not enabled; libraries and headers not found");
- PHP_FILEINFO = "no";
- }
+ EXTENSION('fileinfo', 'fileinfo.c', true, "/I" + configure_module_dirname + "/libmagic /I" + configure_module_dirname);
+ ADD_SOURCES(configure_module_dirname + '\\libmagic', LIBMAGIC_SOURCES, "fileinfo");
}
diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c
index 0c82898e43..e5e52f0995 100644
--- a/ext/fileinfo/fileinfo.c
+++ b/ext/fileinfo/fileinfo.c
@@ -98,13 +98,12 @@ PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_typ
{
zend_object_value retval;
struct finfo_object *intern;
- zval *tmp;
intern = emalloc(sizeof(struct finfo_object));
memset(intern, 0, sizeof(struct finfo_object));
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,(void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
intern->ptr = NULL;
@@ -297,14 +296,14 @@ PHP_FUNCTION(finfo_open)
FILEINFO_DECLARE_INIT_OBJECT(object)
char resolved_path[MAXPATHLEN];
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &options, &file, &file_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lp", &options, &file, &file_len) == FAILURE) {
FILEINFO_DESTROY_OBJECT(object);
RETURN_FALSE;
}
-
+
if (object) {
struct finfo_object *finfo_obj = (struct finfo_object*)zend_object_store_get_object(object TSRMLS_CC);
-
+
if (finfo_obj->ptr) {
magic_close(finfo_obj->ptr->magic);
efree(finfo_obj->ptr);
@@ -315,15 +314,6 @@ PHP_FUNCTION(finfo_open)
if (file_len == 0) {
file = NULL;
} else if (file && *file) { /* user specified file, perform open_basedir checks */
- if (strlen(file) != file_len) {
- FILEINFO_DESTROY_OBJECT(object);
- RETURN_FALSE;
- }
- if (!VCWD_REALPATH(file, resolved_path)) {
- FILEINFO_DESTROY_OBJECT(object);
- RETURN_FALSE;
- }
- file = resolved_path;
#if PHP_API_VERSION < 20100412
if ((PG(safe_mode) && (!php_checkuid(file, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(file TSRMLS_CC)) {
@@ -333,6 +323,11 @@ PHP_FUNCTION(finfo_open)
FILEINFO_DESTROY_OBJECT(object);
RETURN_FALSE;
}
+ if (!expand_filepath_with_mode(file, resolved_path, NULL, 0, CWD_EXPAND TSRMLS_CC)) {
+ FILEINFO_DESTROY_OBJECT(object);
+ RETURN_FALSE;
+ }
+ file = resolved_path;
}
finfo = emalloc(sizeof(struct php_fileinfo));
diff --git a/ext/fileinfo/libmagic.patch b/ext/fileinfo/libmagic.patch
index d8ce5a3b49..ecb178ffa9 100644
--- a/ext/fileinfo/libmagic.patch
+++ b/ext/fileinfo/libmagic.patch
@@ -1,6 +1,6 @@
-diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
---- libmagic.orig/apprentice.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/apprentice.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/apprentice.c libmagic/apprentice.c
+--- libmagic.origin/apprentice.c Sat Dec 17 18:17:18 2011
++++ libmagic/apprentice.c Tue Oct 16 10:21:49 2012
@@ -29,6 +29,8 @@
* apprentice - make one pass through /etc/magic, learning its secrets.
*/
@@ -10,7 +10,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
#include "file.h"
#ifndef lint
-@@ -36,18 +38,34 @@
+@@ -36,18 +38,31 @@
#endif /* lint */
#include "magic.h"
@@ -43,13 +43,11 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
-#ifdef QUICK
-#include <sys/mman.h>
-#endif
-+#ifndef PHP_WIN32
- #include <dirent.h>
-+#endif
+-#include <dirent.h>
#define EATAB {while (isascii((unsigned char) *l) && \
isspace((unsigned char) *l)) ++l;}
-@@ -112,12 +130,10 @@
+@@ -112,12 +127,10 @@
private int parse_strength(struct magic_set *, struct magic_entry *, const char *);
private int parse_apple(struct magic_set *, struct magic_entry *, const char *);
@@ -62,7 +60,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
private struct {
const char *name;
size_t len;
-@@ -131,38 +147,7 @@
+@@ -131,38 +144,7 @@
{ NULL, 0, NULL }
};
@@ -102,7 +100,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
static const struct type_tbl_s {
const char name[16];
-@@ -218,6 +203,10 @@
+@@ -218,6 +200,10 @@
# undef XX_NULL
};
@@ -113,7 +111,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
private int
get_type(const char *l, const char **t)
{
-@@ -275,15 +264,17 @@
+@@ -275,15 +261,17 @@
if (rv != 0)
return -1;
rv = apprentice_compile(ms, &magic, &nmagic, fn);
@@ -136,7 +134,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
if (rv != 0)
return -1;
}
-@@ -295,11 +286,7 @@
+@@ -295,11 +283,7 @@
return -1;
}
@@ -149,7 +147,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
ml->magic = magic;
ml->nmagic = nmagic;
-@@ -318,7 +305,6 @@
+@@ -318,7 +302,6 @@
}
return 0;
@@ -157,7 +155,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
}
protected void
-@@ -327,22 +313,18 @@
+@@ -327,22 +310,18 @@
if (p == NULL)
return;
switch (type) {
@@ -186,7 +184,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
default:
abort();
}
-@@ -355,23 +337,27 @@
+@@ -355,23 +334,27 @@
char *p, *mfn;
int file_err, errs = -1;
struct mlist *mlist;
@@ -223,7 +221,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
mlist->next = mlist->prev = mlist;
while (fn) {
-@@ -385,13 +371,13 @@
+@@ -385,13 +368,13 @@
fn = p;
}
if (errs == -1) {
@@ -240,7 +238,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
return mlist;
}
-@@ -524,6 +510,7 @@
+@@ -524,6 +507,7 @@
abort();
}
@@ -248,7 +246,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
/*
* Magic entries with no description get a bonus because they depend
* on subsequent magic entries to print something.
-@@ -539,8 +526,8 @@
+@@ -539,8 +523,8 @@
private int
apprentice_sort(const void *a, const void *b)
{
@@ -259,7 +257,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
size_t sa = apprentice_magic_strength(ma->mp);
size_t sb = apprentice_magic_strength(mb->mp);
if (sa == sb)
-@@ -671,12 +658,22 @@
+@@ -671,12 +655,22 @@
load_1(struct magic_set *ms, int action, const char *fn, int *errs,
struct magic_entry **marray, uint32_t *marraycount)
{
@@ -286,7 +284,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
if (errno != ENOENT)
file_error(ms, errno, "cannot read magic file `%s'",
fn);
-@@ -684,9 +681,12 @@
+@@ -684,9 +678,12 @@
return;
}
@@ -302,7 +300,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
if (len == 0) /* null line, garbage, etc */
continue;
if (line[len - 1] == '\n') {
-@@ -736,8 +736,7 @@
+@@ -736,8 +733,7 @@
break;
}
}
@@ -312,21 +310,25 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
}
/*
-@@ -754,23 +753,19 @@
+@@ -754,23 +750,21 @@
apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
const char *fn, int action)
{
- int errs = 0;
-+ int errs = 0, mflen = 0;
++ int errs = 0;
struct magic_entry *marray;
uint32_t marraycount, i, mentrycount = 0, starttest;
- size_t slen, files = 0, maxfiles = 0;
- char **filearr = NULL, *mfn;
+ size_t files = 0, maxfiles = 0;
-+ char **filearr = NULL, mfn[MAXPATHLEN];
++ char **filearr = NULL;
struct stat st;
- DIR *dir;
- struct dirent *d;
+- DIR *dir;
+- struct dirent *d;
++ php_stream *dir;
++ php_stream_dirent d;
++
++ TSRMLS_FETCH();
ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
@@ -341,26 +343,33 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
marraycount = 0;
/* print silly verbose header for USG compat. */
-@@ -778,14 +773,16 @@
+@@ -778,22 +772,26 @@
(void)fprintf(stderr, "%s\n", usg_hdr);
/* load directory or file */
- if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
+- dir = opendir(fn);
+ /* FIXME: Read file names and sort them to prevent
+ non-determinism. See Debian bug #488562. */
+ if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
- dir = opendir(fn);
++ int mflen;
++ char mfn[MAXPATHLEN];
++
++ dir = php_stream_opendir(fn, REPORT_ERRORS, NULL);
if (!dir) {
errs++;
goto out;
}
- while ((d = readdir(dir)) != NULL) {
+- while ((d = readdir(dir)) != NULL) {
- if (asprintf(&mfn, "%s/%s", fn, d->d_name) < 0) {
-+ if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d->d_name)) < 0) {
++ while (php_stream_readdir(dir, &d)) {
++ if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d.d_name)) < 0) {
file_oomem(ms,
- strlen(fn) + strlen(d->d_name) + 2);
+- strlen(fn) + strlen(d->d_name) + 2);
++ strlen(fn) + strlen(d.d_name) + 2);
errs++;
-@@ -793,7 +790,6 @@
+- closedir(dir);
++ php_stream_closedir(dir);
goto out;
}
if (stat(mfn, &st) == -1 || !S_ISREG(st.st_mode)) {
@@ -368,20 +377,22 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
continue;
}
if (files >= maxfiles) {
-@@ -803,20 +799,19 @@
+@@ -803,20 +801,19 @@
if ((filearr = CAST(char **,
realloc(filearr, mlen))) == NULL) {
file_oomem(ms, mlen);
- free(mfn);
- closedir(dir);
+- closedir(dir);
++ php_stream_closedir(dir);
errs++;
goto out;
}
}
- filearr[files++] = mfn;
-+ filearr[files++] = estrndup(mfn, mflen);
++ filearr[files++] = estrndup(mfn, (mflen > sizeof(mfn) - 1)? sizeof(mfn) - 1: mflen);
}
- closedir(dir);
+- closedir(dir);
++ php_stream_closedir(dir);
qsort(filearr, files, sizeof(*filearr), cmpstrp);
for (i = 0; i < files; i++) {
load_1(ms, action, filearr[i], &errs, &marray,
@@ -391,7 +402,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
}
free(filearr);
} else
-@@ -882,12 +877,7 @@
+@@ -882,12 +879,7 @@
for (i = 0; i < marraycount; i++)
mentrycount += marray[i].cont_count;
@@ -405,7 +416,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
mentrycount = 0;
for (i = 0; i < marraycount; i++) {
-@@ -896,9 +886,14 @@
+@@ -896,9 +888,14 @@
mentrycount += marray[i].cont_count;
}
out:
@@ -423,7 +434,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
if (errs) {
*magicp = NULL;
*nmagicp = 0;
-@@ -1175,14 +1170,13 @@
+@@ -1175,14 +1172,13 @@
return -1;
}
me = &(*mentryp)[*nmentryp - 1];
@@ -442,7 +453,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
me->mp = m = nm;
me->max_count = CAST(uint32_t, cnt);
}
-@@ -1194,23 +1188,13 @@
+@@ -1194,23 +1190,13 @@
struct magic_entry *mp;
maxmagic += ALLOC_INCR;
@@ -469,7 +480,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
me->mp = m;
me->max_count = ALLOC_CHUNK;
} else
-@@ -1353,6 +1337,10 @@
+@@ -1353,6 +1339,10 @@
if (m->type == FILE_INVALID) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "type `%s' invalid", l);
@@ -480,7 +491,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
return -1;
}
-@@ -1361,7 +1349,7 @@
+@@ -1361,7 +1351,7 @@
m->mask_op = 0;
if (*l == '~') {
@@ -489,7 +500,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
m->mask_op |= FILE_OPINVERSE;
else if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "'~' invalid for string types");
-@@ -1370,7 +1358,7 @@
+@@ -1370,7 +1360,7 @@
m->str_range = 0;
m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0;
if ((op = get_op(*l)) != -1) {
@@ -498,7 +509,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
uint64_t val;
++l;
m->mask_op |= op;
-@@ -1558,11 +1546,6 @@
+@@ -1558,11 +1548,6 @@
if (check_format(ms, m) == -1)
return -1;
}
@@ -510,7 +521,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
m->mimetype[0] = '\0'; /* initialise MIME type to none */
if (m->cont_level == 0)
++(*nmentryp); /* make room for next */
-@@ -2195,56 +2178,69 @@
+@@ -2195,56 +2180,79 @@
/*
* handle a compiled file.
@@ -541,6 +552,16 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
+ ret = 3;
+ goto internal_loaded;
+ }
++
++#ifdef PHP_WIN32
++ /* Don't bother on windows with php_stream_open_wrapper,
++ return to give apprentice_load() a chance. */
++ if (php_stream_stat_path_ex(fn, 0, &st, NULL) == SUCCESS) {
++ if (st.sb.st_mode & S_IFDIR) {
++ goto error2;
++ }
++ }
++#endif
dbname = mkdbname(ms, fn, 0);
if (dbname == NULL)
@@ -603,7 +624,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
ptr = (uint32_t *)(void *)*magicp;
if (*ptr != MAGICNO) {
if (swap4(*ptr) != MAGICNO) {
-@@ -2259,35 +2255,55 @@
+@@ -2259,35 +2267,55 @@
else
version = ptr[1];
if (version != VERSIONNO) {
@@ -675,7 +696,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
return -1;
}
-@@ -2301,42 +2317,49 @@
+@@ -2301,42 +2329,49 @@
apprentice_compile(struct magic_set *ms, struct magic **magicp,
uint32_t *nmagicp, const char *fn)
{
@@ -736,7 +757,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
return rv;
}
-@@ -2349,6 +2372,7 @@
+@@ -2349,6 +2384,7 @@
{
const char *p, *q;
char *buf;
@@ -744,7 +765,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
if (strip) {
if ((p = strrchr(fn, '/')) != NULL)
-@@ -2370,14 +2394,14 @@
+@@ -2370,14 +2406,14 @@
q++;
/* Compatibility with old code that looked in .mime */
if (ms->flags & MAGIC_MIME) {
@@ -763,7 +784,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
/* Compatibility with old code that looked in .mime */
if (strstr(p, ".mime") != NULL)
-@@ -2467,7 +2491,7 @@
+@@ -2467,7 +2503,7 @@
m->offset = swap4((uint32_t)m->offset);
m->in_offset = swap4((uint32_t)m->in_offset);
m->lineno = swap4((uint32_t)m->lineno);
@@ -772,9 +793,9 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
m->str_range = swap4(m->str_range);
m->str_flags = swap4(m->str_flags);
}
-diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c
---- libmagic.orig/ascmagic.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/ascmagic.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/ascmagic.c libmagic/ascmagic.c
+--- libmagic.origin/ascmagic.c Sat Dec 17 18:17:18 2011
++++ libmagic/ascmagic.c Tue Apr 10 09:46:33 2012
@@ -139,10 +139,8 @@
/* malloc size is a conservative overestimate; could be
improved, or at least realloced after conversion. */
@@ -798,9 +819,9 @@ diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c
return rv;
}
-diff -u libmagic.orig/cdf.c libmagic/cdf.c
---- libmagic.orig/cdf.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/cdf.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/cdf.c libmagic/cdf.c
+--- libmagic.origin/cdf.c Mon Feb 20 23:35:29 2012
++++ libmagic/cdf.c Tue Apr 10 09:46:33 2012
@@ -43,7 +43,17 @@
#include <err.h>
#endif
@@ -862,9 +883,9 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c
cdf_print_elapsed_time(buf, sizeof(buf), tp);
(void)fprintf(stderr, "timestamp %s\n", buf);
} else {
-diff -u libmagic.orig/cdf.h libmagic/cdf.h
---- libmagic.orig/cdf.h 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/cdf.h 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/cdf.h libmagic/cdf.h
+--- libmagic.origin/cdf.h Fri Feb 17 06:28:31 2012
++++ libmagic/cdf.h Tue Apr 10 09:46:34 2012
@@ -35,7 +35,7 @@
#ifndef _H_CDF_
#define _H_CDF_
@@ -900,9 +921,9 @@ diff -u libmagic.orig/cdf.h libmagic/cdf.h
int cdf_read_header(const cdf_info_t *, cdf_header_t *);
void cdf_swap_header(cdf_header_t *);
void cdf_unpack_header(cdf_header_t *, char *);
-diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c
---- libmagic.orig/cdf_time.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/cdf_time.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/cdf_time.c libmagic/cdf_time.c
+--- libmagic.origin/cdf_time.c Tue Dec 13 14:48:41 2011
++++ libmagic/cdf_time.c Tue Apr 10 09:46:34 2012
@@ -96,7 +96,7 @@
}
@@ -959,9 +980,9 @@ diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c
static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL;
static const char *ref = "Sat Apr 23 01:30:00 1977";
char *p, *q;
-diff -u libmagic.orig/compress.c libmagic/compress.c
---- libmagic.orig/compress.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/compress.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/compress.c libmagic/compress.c
+--- libmagic.origin/compress.c Sat Dec 17 18:17:18 2011
++++ libmagic/compress.c Tue Apr 10 09:46:34 2012
@@ -32,6 +32,7 @@
* uncompress(method, old, n, newch) - uncompress old into new,
* using method, return sizeof new
@@ -1122,9 +1143,9 @@ diff -u libmagic.orig/compress.c libmagic/compress.c
}
-#endif
+#endif /* if PHP_FILEINFO_UNCOMPRESS */
-diff -u libmagic.orig/file.h libmagic/file.h
---- libmagic.orig/file.h 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/file.h 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/file.h libmagic/file.h
+--- libmagic.origin/file.h Tue Sep 20 17:30:14 2011
++++ libmagic/file.h Mon Apr 23 17:58:54 2012
@@ -33,11 +33,9 @@
#ifndef __file_h__
#define __file_h__
@@ -1282,22 +1303,24 @@ diff -u libmagic.orig/file.h libmagic/file.h
size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_GETLINE
-@@ -500,4 +487,12 @@
- #define FILE_RCSID(id)
+@@ -498,6 +485,14 @@
#endif
-
+ #else
+ #define FILE_RCSID(id)
++#endif
++
+#ifdef PHP_WIN32
+#define FINFO_LSEEK_FUNC _lseek
+#define FINFO_READ_FUNC _read
+#else
+#define FINFO_LSEEK_FUNC lseek
+#define FINFO_READ_FUNC read
-+#endif
-+
+ #endif
+
#endif /* __file_h__ */
-diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c
---- libmagic.orig/fsmagic.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/fsmagic.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/fsmagic.c libmagic/fsmagic.c
+--- libmagic.origin/fsmagic.c Tue Aug 23 10:57:10 2011
++++ libmagic/fsmagic.c Tue Apr 10 09:46:34 2012
@@ -59,27 +59,21 @@
# define minor(dev) ((dev) & 0xff)
#endif
@@ -1508,10 +1531,10 @@ diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c
-#else
- if (file_printf(ms, "block special") == -1)
- return -1;
--#endif
+ #endif
- }
- return 1;
- #endif
+-#endif
- /* TODO add code to handle V7 MUX and Blit MUX files */
+
#ifdef S_IFIFO
@@ -1620,9 +1643,9 @@ diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c
}
/*
-diff -u libmagic.orig/funcs.c libmagic/funcs.c
---- libmagic.orig/funcs.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/funcs.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/funcs.c libmagic/funcs.c
+--- libmagic.origin/funcs.c Sat Dec 17 18:17:18 2011
++++ libmagic/funcs.c Mon Apr 23 17:58:54 2012
@@ -41,52 +41,42 @@
#if defined(HAVE_WCTYPE_H)
#include <wctype.h>
@@ -1916,10 +1939,9 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c
+ return rep_cnt;
}
+
-Common subdirectories: libmagic.orig/.libs and libmagic/.libs
-diff -u libmagic.orig/magic.c libmagic/magic.c
---- libmagic.orig/magic.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/magic.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/magic.c libmagic/magic.c
+--- libmagic.origin/magic.c Thu May 26 03:27:59 2011
++++ libmagic/magic.c Tue Apr 10 09:46:34 2012
@@ -25,11 +25,6 @@
* SUCH DAMAGE.
*/
@@ -2295,9 +2317,9 @@ diff -u libmagic.orig/magic.c libmagic/magic.c
public const char *
magic_error(struct magic_set *ms)
-diff -u libmagic.orig/magic.h libmagic/magic.h
---- libmagic.orig/magic.h 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/magic.h 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/magic.h libmagic/magic.h
+--- libmagic.origin/magic.h Sun Dec 18 15:54:43 2011
++++ libmagic/magic.h Tue Apr 10 09:46:34 2012
@@ -85,6 +85,7 @@
const char *magic_getpath(const char *, int);
@@ -2314,20 +2336,27 @@ diff -u libmagic.orig/magic.h libmagic/magic.h
int magic_list(magic_t, const char *);
int magic_errno(magic_t);
-diff -u libmagic.orig/print.c libmagic/print.c
---- libmagic.orig/print.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/print.c 2012-10-19 11:07:35.000000000 +0800
-@@ -29,6 +29,9 @@
+diff -u libmagic.origin/print.c libmagic/print.c
+--- libmagic.origin/print.c Tue Sep 20 17:28:09 2011
++++ libmagic/print.c Tue Oct 16 10:13:39 2012
+@@ -29,12 +29,16 @@
* print.c - debugging printout routines
*/
++#define _GNU_SOURCE
+#include "php.h"
-+#include "main/snprintf.h"
+
#include "file.h"
#ifndef lint
-@@ -45,174 +48,21 @@
+ FILE_RCSID("@(#)$File: print.c,v 1.71 2011/09/20 15:28:09 christos Exp $")
+ #endif /* lint */
+
++#include <stdio.h>
+ #include <string.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+@@ -45,174 +49,21 @@
#define SZOF(a) (sizeof(a) / sizeof(a[0]))
@@ -2509,9 +2538,9 @@ diff -u libmagic.orig/print.c libmagic/print.c
}
protected const char *
-diff -u libmagic.orig/readcdf.c libmagic/readcdf.c
---- libmagic.orig/readcdf.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/readcdf.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/readcdf.c libmagic/readcdf.c
+--- libmagic.origin/readcdf.c Mon Feb 20 21:04:58 2012
++++ libmagic/readcdf.c Tue Apr 10 09:46:34 2012
@@ -30,7 +30,11 @@
#endif
@@ -2557,9 +2586,9 @@ diff -u libmagic.orig/readcdf.c libmagic/readcdf.c
c = cdf_ctime(&ts.tv_sec);
if ((ec = strchr(c, '\n')) != NULL)
*ec = '\0';
-diff -u libmagic.orig/readelf.c libmagic/readelf.c
---- libmagic.orig/readelf.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/readelf.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/readelf.c libmagic/readelf.c
+--- libmagic.origin/readelf.c Tue Aug 23 10:57:10 2011
++++ libmagic/readelf.c Tue Apr 10 09:46:34 2012
@@ -49,7 +49,7 @@
off_t, int *, int);
private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
@@ -2714,9 +2743,9 @@ diff -u libmagic.orig/readelf.c libmagic/readelf.c
fd = file_pipe2file(ms, fd, buf, nbytes);
if (fstat(fd, &st) == -1) {
-diff -u libmagic.orig/softmagic.c libmagic/softmagic.c
---- libmagic.orig/softmagic.c 2012-10-19 11:07:28.000000000 +0800
-+++ libmagic/softmagic.c 2012-10-19 11:07:35.000000000 +0800
+diff -u libmagic.origin/softmagic.c libmagic/softmagic.c
+--- libmagic.origin/softmagic.c Sat Dec 17 18:17:18 2011
++++ libmagic/softmagic.c Fri May 25 09:59:25 2012
@@ -41,6 +41,11 @@
#include <stdlib.h>
#include <time.h>
diff --git a/ext/fileinfo/libmagic/apprentice.c b/ext/fileinfo/libmagic/apprentice.c
index 98bde27a2d..787eb79367 100644
--- a/ext/fileinfo/libmagic/apprentice.c
+++ b/ext/fileinfo/libmagic/apprentice.c
@@ -63,9 +63,6 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.173 2011/12/08 12:38:24 rrt Exp $")
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
-#ifndef PHP_WIN32
-#include <dirent.h>
-#endif
#define EATAB {while (isascii((unsigned char) *l) && \
isspace((unsigned char) *l)) ++l;}
@@ -753,14 +750,16 @@ private int
apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
const char *fn, int action)
{
- int errs = 0, mflen = 0;
+ int errs = 0;
struct magic_entry *marray;
uint32_t marraycount, i, mentrycount = 0, starttest;
size_t files = 0, maxfiles = 0;
- char **filearr = NULL, mfn[MAXPATHLEN];
+ char **filearr = NULL;
struct stat st;
- DIR *dir;
- struct dirent *d;
+ php_stream *dir;
+ php_stream_dirent d;
+
+ TSRMLS_FETCH();
ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
@@ -776,17 +775,20 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
/* FIXME: Read file names and sort them to prevent
non-determinism. See Debian bug #488562. */
if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
- dir = opendir(fn);
+ int mflen;
+ char mfn[MAXPATHLEN];
+
+ dir = php_stream_opendir(fn, REPORT_ERRORS, NULL);
if (!dir) {
errs++;
goto out;
}
- while ((d = readdir(dir)) != NULL) {
- if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d->d_name)) < 0) {
+ while (php_stream_readdir(dir, &d)) {
+ if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d.d_name)) < 0) {
file_oomem(ms,
- strlen(fn) + strlen(d->d_name) + 2);
+ strlen(fn) + strlen(d.d_name) + 2);
errs++;
- closedir(dir);
+ php_stream_closedir(dir);
goto out;
}
if (stat(mfn, &st) == -1 || !S_ISREG(st.st_mode)) {
@@ -799,14 +801,14 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
if ((filearr = CAST(char **,
realloc(filearr, mlen))) == NULL) {
file_oomem(ms, mlen);
- closedir(dir);
+ php_stream_closedir(dir);
errs++;
goto out;
}
}
- filearr[files++] = estrndup(mfn, mflen);
+ filearr[files++] = estrndup(mfn, (mflen > sizeof(mfn) - 1)? sizeof(mfn) - 1: mflen);
}
- closedir(dir);
+ php_stream_closedir(dir);
qsort(filearr, files, sizeof(*filearr), cmpstrp);
for (i = 0; i < files; i++) {
load_1(ms, action, filearr[i], &errs, &marray,
@@ -2204,6 +2206,16 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
goto internal_loaded;
}
+#ifdef PHP_WIN32
+ /* Don't bother on windows with php_stream_open_wrapper,
+ return to give apprentice_load() a chance. */
+ if (php_stream_stat_path_ex(fn, 0, &st, NULL) == SUCCESS) {
+ if (st.sb.st_mode & S_IFDIR) {
+ goto error2;
+ }
+ }
+#endif
+
dbname = mkdbname(ms, fn, 0);
if (dbname == NULL)
goto error2;
diff --git a/ext/fileinfo/libmagic/print.c b/ext/fileinfo/libmagic/print.c
index ef626708dd..8370f50c28 100644
--- a/ext/fileinfo/libmagic/print.c
+++ b/ext/fileinfo/libmagic/print.c
@@ -29,8 +29,8 @@
* print.c - debugging printout routines
*/
+#define _GNU_SOURCE
#include "php.h"
-#include "main/snprintf.h"
#include "file.h"
@@ -38,6 +38,7 @@
FILE_RCSID("@(#)$File: print.c,v 1.71 2011/09/20 15:28:09 christos Exp $")
#endif /* lint */
+#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
diff --git a/ext/fileinfo/php_fileinfo.h b/ext/fileinfo/php_fileinfo.h
index 3f0326bfda..330bad89c0 100644
--- a/ext/fileinfo/php_fileinfo.h
+++ b/ext/fileinfo/php_fileinfo.h
@@ -24,7 +24,7 @@
extern zend_module_entry fileinfo_module_entry;
#define phpext_fileinfo_ptr &fileinfo_module_entry
-#define PHP_FILEINFO_VERSION "1.0.5-dev"
+#define PHP_FILEINFO_VERSION "1.0.5"
#ifdef PHP_WIN32
#define PHP_FILEINFO_API __declspec(dllexport)
diff --git a/ext/fileinfo/tests/finfo_open_001.phpt b/ext/fileinfo/tests/finfo_open_001.phpt
index 69696ebe33..17935c3676 100644
--- a/ext/fileinfo/tests/finfo_open_001.phpt
+++ b/ext/fileinfo/tests/finfo_open_001.phpt
@@ -14,10 +14,28 @@ var_dump(finfo_open(FILEINFO_MIME, '/foo/bar/inexistent'));
?>
--EXPECTF--
-Warning: finfo_open(): Failed to load magic database at ''. in %s on line %d
+Warning: finfo_open() expects parameter 2 to be a valid path, string given in %s on line %d
bool(false)
resource(%d) of type (file_info)
resource(%d) of type (file_info)
+
+Warning: finfo_open(%s123): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(%s123): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(): Failed to load magic database at '%s123'. in %s on line %d
bool(false)
+
+Warning: finfo_open(%s1): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(%s1): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(): Failed to load magic database at '%s1'. in %s on line %d
bool(false)
+
+Warning: finfo_open(%sinexistent): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(%sinexistent): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(): Failed to load magic database at '%sinexistent'. in %s on line %d
bool(false)
diff --git a/ext/fileinfo/tests/finfo_open_error-win32.phpt b/ext/fileinfo/tests/finfo_open_error-win32.phpt
index bd50327b2d..0260ca5708 100644
--- a/ext/fileinfo/tests/finfo_open_error-win32.phpt
+++ b/ext/fileinfo/tests/finfo_open_error-win32.phpt
@@ -17,6 +17,7 @@ $magicFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'magic';
echo "*** Testing finfo_open() : error functionality ***\n";
+// on 5_4, this line generates additional warning messages that 5_3 does not. functionally, it should be fine (should pass)
var_dump( finfo_open( FILEINFO_MIME, 'foobarfile' ) );
var_dump( finfo_open( array(), $magicFile ) );
var_dump( finfo_open( FILEINFO_MIME, $magicFile, 'extraArg' ) );
@@ -29,18 +30,24 @@ var_dump( new finfo('foobar') );
===DONE===
--EXPECTF--
*** Testing finfo_open() : error functionality ***
+
+Warning: finfo_open(%sfoobarfile): failed to open stream: No such file or directory in %sfinfo_open_error-win32.php on line %d
+
+Warning: finfo_open(%sfoobarfile): failed to open stream: No such file or directory in %sfinfo_open_error-win32.php on line %d
+
+Warning: finfo_open(): Failed to load magic database at '%sfoobarfile'. in %sfinfo_open_error-win32.php on line %d
bool(false)
-Warning: finfo_open() expects parameter 1 to be long, array given in %s on line %d
+Warning: finfo_open() expects parameter 1 to be long, array given in %sfinfo_open_error-win32.php on line %d
bool(false)
-Warning: finfo_open() expects at most 2 parameters, 3 given in %s on line %d
+Warning: finfo_open() expects at most 2 parameters, 3 given in %sfinfo_open_error-win32.php on line %d
bool(false)
-resource(%d) of type (file_info)
+resource(6) of type (file_info)
-Warning: finfo_open() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d
+Warning: finfo_open() expects parameter 1 to be long, string given in %sfinfo_open_error-win32.php on line %d
bool(false)
-Warning: finfo::finfo() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d
+Warning: finfo::finfo() expects parameter 1 to be long, string given in %sfinfo_open_error-win32.php on line %d
NULL
===DONE===
diff --git a/ext/fileinfo/tests/finfo_open_error.phpt b/ext/fileinfo/tests/finfo_open_error.phpt
index 7bf60bfe63..5d1eff5973 100644
--- a/ext/fileinfo/tests/finfo_open_error.phpt
+++ b/ext/fileinfo/tests/finfo_open_error.phpt
@@ -29,6 +29,12 @@ var_dump( new finfo('foobar') );
===DONE===
--EXPECTF--
*** Testing finfo_open() : error functionality ***
+
+Warning: finfo_open(%sfoobarfile): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(%sfoobarfile): failed to open stream: No such file or directory in %s on line %d
+
+Warning: finfo_open(): Failed to load magic database at '%sfoobarfile'. in %s on line %d
bool(false)
Warning: finfo_open() expects parameter 1 to be long, array given in %s on line %d
@@ -40,9 +46,9 @@ bool(false)
Notice: finfo_open(): Warning: using regular magic file `%s' in %s on line %d
resource(%d) of type (file_info)
-Warning: finfo_open() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d
+Warning: finfo_open() expects parameter 1 to be long, string given in %s on line %d
bool(false)
-Warning: finfo::finfo() expects parameter 1 to be long, %unicode_string_optional% given in %s on line %d
+Warning: finfo::finfo() expects parameter 1 to be long, string given in %s on line %d
NULL
===DONE===
diff --git a/ext/filter/filter.c b/ext/filter/filter.c
index 2b8c730d7d..e523cdc882 100644
--- a/ext/filter/filter.c
+++ b/ext/filter/filter.c
@@ -276,7 +276,7 @@ PHP_MINIT_FUNCTION(filter)
REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_RES_RANGE", FILTER_FLAG_NO_RES_RANGE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_PRIV_RANGE", FILTER_FLAG_NO_PRIV_RANGE, CONST_CS | CONST_PERSISTENT);
- sapi_register_input_filter(php_sapi_filter, php_sapi_filter_init);
+ sapi_register_input_filter(php_sapi_filter, php_sapi_filter_init TSRMLS_CC);
return SUCCESS;
}
@@ -406,7 +406,6 @@ static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int
{
zval new_var, raw_var;
zval *array_ptr = NULL, *orig_array_ptr = NULL;
- char *orig_var = NULL;
int retval = 0;
assert(*val != NULL);
@@ -447,13 +446,7 @@ static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int
}
if (array_ptr) {
- /* Make a copy of the variable name, as php_register_variable_ex seems to
- * modify it */
- orig_var = estrdup(var);
-
/* Store the RAW variable internally */
- /* FIXME: Should not use php_register_variable_ex as that also registers
- * globals when register_globals is turned on */
Z_STRLEN(raw_var) = val_len;
Z_STRVAL(raw_var) = estrndup(*val, val_len);
Z_TYPE(raw_var) = IS_STRING;
@@ -463,8 +456,6 @@ static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int
if (val_len) {
/* Register mangled variable */
- /* FIXME: Should not use php_register_variable_ex as that also registers
- * globals when register_globals is turned on */
Z_STRLEN(new_var) = val_len;
Z_TYPE(new_var) = IS_STRING;
@@ -473,8 +464,6 @@ static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int
Z_STRVAL(new_var) = estrndup(*val, val_len);
INIT_PZVAL(tmp_new_var);
php_zval_filter(&tmp_new_var, IF_G(default_filter), IF_G(default_filter_flags), NULL, NULL/*charset*/, 0 TSRMLS_CC);
- } else if (PG(magic_quotes_gpc) && !retval) { /* for PARSE_STRING php_register_variable_safe() will do the addslashes() */
- Z_STRVAL(new_var) = php_addslashes(*val, Z_STRLEN(new_var), &Z_STRLEN(new_var), 0 TSRMLS_CC);
} else {
Z_STRVAL(new_var) = estrndup(*val, val_len);
}
@@ -483,10 +472,7 @@ static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int
}
if (orig_array_ptr) {
- php_register_variable_ex(orig_var, &new_var, orig_array_ptr TSRMLS_CC);
- }
- if (array_ptr) {
- efree(orig_var);
+ php_register_variable_ex(var, &new_var, orig_array_ptr TSRMLS_CC);
}
if (retval) {
@@ -539,7 +525,6 @@ static zval *php_filter_get_storage(long arg TSRMLS_DC)/* {{{ */
{
zval *array_ptr = NULL;
- zend_bool jit_initialization = (PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays));
switch (arg) {
case PARSE_GET:
@@ -552,13 +537,13 @@ static zval *php_filter_get_storage(long arg TSRMLS_DC)/* {{{ */
array_ptr = IF_G(cookie_array);
break;
case PARSE_SERVER:
- if (jit_initialization) {
+ if (PG(auto_globals_jit)) {
zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
}
array_ptr = IF_G(server_array);
break;
case PARSE_ENV:
- if (jit_initialization) {
+ if (PG(auto_globals_jit)) {
zend_is_auto_global("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
}
array_ptr = IF_G(env_array) ? IF_G(env_array) : PG(http_globals)[TRACK_VARS_ENV];
diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h
index daa688b4ac..2ec2f62fae 100644
--- a/ext/filter/filter_private.h
+++ b/ext/filter/filter_private.h
@@ -99,12 +99,14 @@
} \
return; \
-#define PHP_FILTER_TRIM_DEFAULT(p, len) { \
+#define PHP_FILTER_TRIM_DEFAULT(p, len) PHP_FILTER_TRIM_DEFAULT_EX(p, len, 1);
+
+#define PHP_FILTER_TRIM_DEFAULT_EX(p, len, return_if_empty) { \
while ((len > 0) && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\v' || *p == '\n')) { \
p++; \
len--; \
} \
- if (len < 1) { \
+ if (len < 1 && return_if_empty) { \
RETURN_VALIDATION_FAILED \
} \
while (p[len-1] == ' ' || p[len-1] == '\t' || p[len-1] == '\r' || p[len-1] == '\v' || p[len-1] == '\n') { \
diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
index 5c3811ab25..4de6b83e00 100644
--- a/ext/filter/logical_filters.c
+++ b/ext/filter/logical_filters.c
@@ -235,12 +235,15 @@ void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
int len = Z_STRLEN_P(value);
int ret;
- PHP_FILTER_TRIM_DEFAULT(str, len);
+ PHP_FILTER_TRIM_DEFAULT_EX(str, len, 0);
/* returns true for "1", "true", "on" and "yes"
* returns false for "0", "false", "off", "no", and ""
* null otherwise. */
switch (len) {
+ case 0:
+ ret = 0;
+ break;
case 1:
if (*str == '1') {
ret = 1;
@@ -286,7 +289,7 @@ void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
ret = -1;
}
- if (ret == -1) {
+ if (ret == -1) {
RETURN_VALIDATION_FAILED
} else {
zval_dtor(value);
diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c
index 935177f012..17160b457f 100644
--- a/ext/filter/sanitizing_filters.c
+++ b/ext/filter/sanitizing_filters.c
@@ -51,7 +51,7 @@ static void php_filter_encode_html(zval *value, const unsigned char *chars)
}
smart_str_0(&str);
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = str.c;
Z_STRLEN_P(value) = str.len;
}
@@ -102,7 +102,7 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const
s++;
}
*p = '\0';
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = (char *)str;
Z_STRLEN_P(value) = p - str;
}
@@ -131,7 +131,7 @@ static void php_filter_strip(zval *value, long flags)
}
/* update zval string data */
buf[c] = '\0';
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = (char *)buf;
Z_STRLEN_P(value) = c;
}
@@ -169,7 +169,7 @@ static void filter_map_apply(zval *value, filter_map *map)
}
/* update zval string data */
buf[c] = '\0';
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = (char *)buf;
Z_STRLEN_P(value) = c;
}
@@ -250,7 +250,8 @@ void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
{
char *buf;
- int len, quotes;
+ size_t len;
+ int quotes;
if (!(flags & FILTER_FLAG_NO_ENCODE_QUOTES)) {
quotes = ENT_QUOTES;
@@ -258,7 +259,7 @@ void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
quotes = ENT_NOQUOTES;
}
buf = php_escape_html_entities_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 1, quotes, SG(default_charset), 0 TSRMLS_CC);
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = buf;
Z_STRLEN_P(value) = len;
}
@@ -372,7 +373,7 @@ void php_filter_magic_quotes(PHP_INPUT_FILTER_PARAM_DECL)
/* just call php_addslashes quotes */
buf = php_addslashes(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 0 TSRMLS_CC);
- efree(Z_STRVAL_P(value));
+ str_efree(Z_STRVAL_P(value));
Z_STRVAL_P(value) = buf;
Z_STRLEN_P(value) = len;
}
diff --git a/ext/filter/tests/bug39763.phpt b/ext/filter/tests/bug39763.phpt
deleted file mode 100644
index 69d451bbd8..0000000000
--- a/ext/filter/tests/bug39763.phpt
+++ /dev/null
@@ -1,19 +0,0 @@
---TEST--
-Bug #39763 (filter applies magic_quotes twice in parse_str())
---SKIPIF--
-<?php if (!extension_loaded("filter")) die("skip"); ?>
---INI--
-magic_quotes_gpc=1
-filter.default=
---FILE--
-<?php
-$arr = array();
-parse_str("val=%22probably+a+bug%22", $arr);
-echo $arr['val'] . "\n";
-parse_str("val=%22probably+a+bug%22");
-echo $val . "\n";
-?>
---EXPECT--
-Deprecated: Directive 'magic_quotes_gpc' is deprecated in PHP 5.3 and greater in Unknown on line 0
-\"probably a bug\"
-\"probably a bug\"
diff --git a/ext/filter/tests/bug42718-2.phpt b/ext/filter/tests/bug42718-2.phpt
index 13cd990d00..ed210681d3 100644
--- a/ext/filter/tests/bug42718-2.phpt
+++ b/ext/filter/tests/bug42718-2.phpt
@@ -4,7 +4,6 @@ Bug #42718 - 2 (unsafe_raw filter not applied when configured as default filter)
<?php if (!extension_loaded("filter")) die("skip"); ?>
--INI--
display_errors=0
-magic_quotes_gpc=1
filter.default=unsafe_raw
filter.default_flags=
--GET--
@@ -13,9 +12,7 @@ a=1%00
<?php
echo ini_get('filter.default') . "\n";
echo ini_get('filter.default_flags') . "\n";
-echo addcslashes($_GET['a'],"\0") . "\n";
?>
--EXPECT--
unsafe_raw
-1\0
diff --git a/ext/filter/tests/bug42718.phpt b/ext/filter/tests/bug42718.phpt
index d1ede3f7d2..ba56d3988a 100644
--- a/ext/filter/tests/bug42718.phpt
+++ b/ext/filter/tests/bug42718.phpt
@@ -5,7 +5,6 @@ FILTER_UNSAFE_RAW not applied when configured as default filter, even with flags
--SKIPIF--
<?php if (!extension_loaded("filter")) die("skip"); ?>
--INI--
-magic_quotes_gpc=0
filter.default=unsafe_raw
filter.default_flags=4
--GET--
diff --git a/ext/filter/tests/bug49510.phpt b/ext/filter/tests/bug49510.phpt
new file mode 100644
index 0000000000..3f365cc431
--- /dev/null
+++ b/ext/filter/tests/bug49510.phpt
@@ -0,0 +1,36 @@
+--TEST--
+#49510 boolean validation fails with FILTER_NULL_ON_FAILURE
+--FILE--
+<?php
+var_dump(filter_var(false, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var(0, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("0", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("off", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("false", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("no", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+
+var_dump(filter_var(true, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var(1, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("1", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("on", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+var_dump(filter_var("yes", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+
+var_dump(filter_var("invalid", FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE));
+?>
+==DONE==
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+NULL
+==DONE==
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 8b74e03c1a..4156a04581 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -243,6 +243,7 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
{
#if HAVE_OPENSSL_EXT
SSL_CTX *ctx = NULL;
+ long ssl_ctx_options = SSL_OP_ALL;
#endif
if (ftp == NULL) {
return 0;
@@ -279,7 +280,10 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC)
return 0;
}
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
+#if OPENSSL_VERSION_NUMBER >= 0x0090605fL
+ ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+#endif
+ SSL_CTX_set_options(ctx, ssl_ctx_options);
ftp->ssl_handle = SSL_new(ctx);
if (ftp->ssl_handle == NULL) {
@@ -1495,6 +1499,7 @@ data_accept(databuf_t *data, ftpbuf_t *ftp TSRMLS_DC)
#if HAVE_OPENSSL_EXT
SSL_CTX *ctx;
+ long ssl_ctx_options = SSL_OP_ALL;
#endif
if (data->fd != -1) {
@@ -1521,7 +1526,10 @@ data_accepted:
return 0;
}
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
+#if OPENSSL_VERSION_NUMBER >= 0x0090605fL
+ ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+#endif
+ SSL_CTX_set_options(ctx, ssl_ctx_options);
data->ssl_handle = SSL_new(ctx);
if (data->ssl_handle == NULL) {
diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c
index 94eb635446..6e232a5df2 100644
--- a/ext/ftp/php_ftp.c
+++ b/ext/ftp/php_ftp.c
@@ -41,7 +41,7 @@
#include "php_ftp.h"
#include "ftp.h"
-static int le_ftpbuf;
+static int le_ftpbuf;
#define le_ftpbuf_name "FTP Buffer"
/* {{{ arginfo */
@@ -607,7 +607,7 @@ PHP_FUNCTION(ftp_chmod)
int filename_len;
long mode;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &z_ftp, &mode, &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlp", &z_ftp, &mode, &filename, &filename_len) == FAILURE) {
RETURN_FALSE;
}
@@ -660,7 +660,7 @@ PHP_FUNCTION(ftp_nlist)
char **nlist, **ptr, *dir;
int dir_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &dir, &dir_len) == FAILURE) {
return;
}
@@ -857,7 +857,7 @@ PHP_FUNCTION(ftp_get)
int local_len, remote_len;
long mode, resumepos=0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
return;
}
@@ -874,9 +874,9 @@ PHP_FUNCTION(ftp_get)
#endif
if (ftp->autoseek && resumepos) {
- outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL);
if (outstream == NULL) {
- outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
}
if (outstream != NULL) {
/* if autoresume is wanted seek to end */
@@ -888,7 +888,7 @@ PHP_FUNCTION(ftp_get)
}
}
} else {
- outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
}
if (outstream == NULL) {
@@ -935,9 +935,9 @@ PHP_FUNCTION(ftp_nb_get)
mode = FTPTYPE_IMAGE;
#endif
if (ftp->autoseek && resumepos) {
- outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL);
if (outstream == NULL) {
- outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
}
if (outstream != NULL) {
/* if autoresume is wanted seek to end */
@@ -949,7 +949,7 @@ PHP_FUNCTION(ftp_nb_get)
}
}
} else {
- outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
}
if (outstream == NULL) {
@@ -1124,14 +1124,14 @@ PHP_FUNCTION(ftp_put)
long mode, startpos=0;
php_stream *instream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
XTYPE(xtype, mode);
- if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL))) {
+ if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
RETURN_FALSE;
}
@@ -1177,14 +1177,14 @@ PHP_FUNCTION(ftp_nb_put)
long mode, startpos=0;
php_stream *instream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
XTYPE(xtype, mode);
- if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL))) {
+ if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
RETURN_FALSE;
}
@@ -1233,7 +1233,7 @@ PHP_FUNCTION(ftp_size)
char *file;
int file_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &file, &file_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &file, &file_len) == FAILURE) {
return;
}
@@ -1253,7 +1253,7 @@ PHP_FUNCTION(ftp_mdtm)
char *file;
int file_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &file, &file_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &file, &file_len) == FAILURE) {
return;
}
diff --git a/ext/gd/config.m4 b/ext/gd/config.m4
index ebbdb92fb9..79a74e1408 100644
--- a/ext/gd/config.m4
+++ b/ext/gd/config.m4
@@ -10,6 +10,11 @@ PHP_ARG_WITH(gd, for GD support,
[ --with-gd[=DIR] Include GD support. DIR is the GD library base
install directory [BUNDLED]])
+if test -z "$PHP_VPX_DIR"; then
+ PHP_ARG_WITH(vpx-dir, for the location of libvpx,
+ [ --with-vpx-dir[=DIR] GD: Set the path to libvpx install prefix], no, no)
+fi
+
if test -z "$PHP_JPEG_DIR"; then
PHP_ARG_WITH(jpeg-dir, for the location of libjpeg,
[ --with-jpeg-dir[=DIR] GD: Set the path to libjpeg install prefix], no, no)
@@ -68,6 +73,32 @@ AC_DEFUN([PHP_GD_ZLIB],[
fi
])
+AC_DEFUN([PHP_GD_VPX],[
+ if test "$PHP_VPX_DIR" != "no"; then
+
+ for i in $PHP_VPX_DIR /usr/local /usr; do
+ test -f $i/include/vpx_codec.h || test -f $i/include/vpx/vpx_codec.h && GD_VPX_DIR=$i && break
+ done
+
+ if test -z "$GD_VPX_DIR"; then
+ AC_MSG_ERROR([vpx_codec.h not found.])
+ fi
+
+ PHP_CHECK_LIBRARY(vpx,vpx_codec_destroy,
+ [
+ PHP_ADD_INCLUDE($GD_VPX_DIR/include)
+ PHP_ADD_LIBRARY(pthread)
+ PHP_ADD_LIBRARY_WITH_PATH(vpx, $GD_VPX_DIR/$PHP_LIBDIR, GD_SHARED_LIBADD)
+ ],[
+ AC_MSG_ERROR([Problem with libvpx.(a|so). Please check config.log for more information.])
+ ],[
+ -L$GD_VPX_DIR/$PHP_LIBDIR
+ ])
+ else
+ AC_MSG_RESULT([If configure fails try --with-vpx-dir=<DIR>])
+ fi
+])
+
AC_DEFUN([PHP_GD_JPEG],[
if test "$PHP_JPEG_DIR" != "no"; then
@@ -261,12 +292,12 @@ dnl
if test "$PHP_GD" = "yes"; then
GD_MODULE_TYPE=builtin
extra_sources="libgd/gd.c libgd/gd_gd.c libgd/gd_gd2.c libgd/gd_io.c libgd/gd_io_dp.c \
- libgd/gd_io_file.c libgd/gd_ss.c libgd/gd_io_ss.c libgd/gd_png.c libgd/gd_jpeg.c \
- libgd/gdxpm.c libgd/gdfontt.c libgd/gdfonts.c libgd/gdfontmb.c libgd/gdfontl.c \
- libgd/gdfontg.c libgd/gdtables.c libgd/gdft.c libgd/gdcache.c libgd/gdkanji.c \
- libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c libgd/gd_topal.c libgd/gd_gif_in.c \
- libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c libgd/gd_filter.c \
- libgd/gd_pixelate.c libgd/gd_arc.c libgd/gd_rotate.c libgd/gd_color.c"
+ libgd/gd_io_file.c libgd/gd_ss.c libgd/gd_io_ss.c libgd/webpimg.c libgd/gd_webp.c \
+ libgd/gd_png.c libgd/gd_jpeg.c libgd/gdxpm.c libgd/gdfontt.c libgd/gdfonts.c \
+ libgd/gdfontmb.c libgd/gdfontl.c libgd/gdfontg.c libgd/gdtables.c libgd/gdft.c \
+ libgd/gdcache.c libgd/gdkanji.c libgd/wbmp.c libgd/gd_wbmp.c libgd/gdhelpers.c \
+ libgd/gd_topal.c libgd/gd_gif_in.c libgd/xbm.c libgd/gd_gif_out.c libgd/gd_security.c \
+ libgd/gd_filter.c libgd/gd_pixelate.c libgd/gd_arc.c libgd/gd_rotate.c libgd/gd_color.c"
dnl check for fabsf and floorf which are available since C99
AC_CHECK_FUNCS(fabsf floorf)
@@ -279,6 +310,7 @@ dnl Various checks for GD features
PHP_GD_TTSTR
PHP_GD_JISX0208
PHP_GD_JPEG
+ PHP_GD_VPX
PHP_GD_PNG
PHP_GD_XPM
PHP_GD_FREETYPE2
@@ -313,6 +345,11 @@ dnl Make sure the libgd/ is first in the include path
dnl Depending which libraries were included to PHP configure,
dnl enable the support in bundled GD library
+ if test -n "$GD_VPX_DIR"; then
+ AC_DEFINE(HAVE_GD_WEBP, 1, [ ])
+ GDLIB_CFLAGS="$GDLIB_CFLAGS -DHAVE_LIBVPX"
+ fi
+
if test -n "$GD_JPEG_DIR"; then
AC_DEFINE(HAVE_GD_JPG, 1, [ ])
GDLIB_CFLAGS="$GDLIB_CFLAGS -DHAVE_LIBJPEG"
@@ -345,6 +382,7 @@ else
dnl Various checks for GD features
PHP_GD_ZLIB
PHP_GD_TTSTR
+ PHP_GD_VPX
PHP_GD_JPEG
PHP_GD_PNG
PHP_GD_XPM
diff --git a/ext/gd/config.w32 b/ext/gd/config.w32
index 9b5eb7bcef..8c932a037c 100644
--- a/ext/gd/config.w32
+++ b/ext/gd/config.w32
@@ -5,7 +5,9 @@ ARG_WITH("gd", "Bundled GD support", "yes,shared");
ARG_WITH("t1lib", "t1lib support", "yes");
if (PHP_GD != "no") {
- if (CHECK_LIB("libjpeg_a.lib;libjpeg.lib", "gd", PHP_GD) &&
+ if (
+ CHECK_LIB("vpxmt.lib", "gd", PHP_GD) &&
+ CHECK_LIB("libjpeg_a.lib;libjpeg.lib", "gd", PHP_GD) &&
CHECK_LIB("freetype_a.lib;freetype.lib", "gd", PHP_GD) &&
CHECK_LIB("libpng_a.lib;libpng.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("gd.h", "CFLAGS_GD", PHP_GD + ";ext\\gd\\libgd") &&
@@ -36,7 +38,7 @@ if (PHP_GD != "no") {
gdft.c gd_gd2.c gd_gd.c gd_gif_in.c gd_gif_out.c gdhelpers.c gd_io.c gd_io_dp.c \
gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \
gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c xbm.c gd_security.c \
- gd_filter.c gd_pixelate.c gd_arc.c gd_rotate.c gd_color.c", "gd");
+ gd_filter.c gd_pixelate.c gd_arc.c gd_rotate.c gd_color.c webpimg.c gd_webp.c ", "gd");
AC_DEFINE('HAVE_LIBGD', 1, 'GD support');
ADD_FLAG("CFLAGS_GD", " \
/D HAVE_GD_DYNAMIC_CTX_EX=1 \
@@ -57,12 +59,14 @@ if (PHP_GD != "no") {
/D HAVE_GD_WBMP \
/D HAVE_GD_XBM \
/D HAVE_GD_XPM \
+/D HAVE_GD_WEBP \
/D HAVE_LIBFREETYPE=1 \
/D HAVE_LIBGD13=1 \
/D HAVE_LIBGD15=1 \
/D HAVE_LIBGD20=1 \
/D HAVE_LIBGD204=1 \
/D HAVE_LIBJPEG \
+/D HAVE_LIBVPX \
/D HAVE_LIBPNG \
/D HAVE_XPM \
/D HAVE_COLORCLOSESTHWB \
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 3039cdd492..cfcc3e876c 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -351,6 +351,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefrompng, 0)
ZEND_END_ARG_INFO()
#endif
+#ifdef HAVE_GD_WEBP
+ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromwebp, 0)
+ ZEND_ARG_INFO(0, filename)
+ZEND_END_ARG_INFO()
+#endif
+
#ifdef HAVE_GD_XBM
ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromxbm, 0)
ZEND_ARG_INFO(0, filename)
@@ -409,6 +415,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_imagepng, 0, 0, 1)
ZEND_END_ARG_INFO()
#endif
+#ifdef HAVE_GD_WEBP
+ZEND_BEGIN_ARG_INFO_EX(arginfo_imagewebp, 0, 0, 1)
+ ZEND_ARG_INFO(0, im)
+ ZEND_ARG_INFO(0, filename)
+ZEND_END_ARG_INFO()
+#endif
+
#ifdef HAVE_GD_JPG
ZEND_BEGIN_ARG_INFO_EX(arginfo_imagejpeg, 0, 0, 1)
ZEND_ARG_INFO(0, im)
@@ -498,12 +511,13 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagecolorexact, 0)
ZEND_ARG_INFO(0, blue)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO(arginfo_imagecolorset, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_imagecolorset, 0, 0, 5)
ZEND_ARG_INFO(0, im)
ZEND_ARG_INFO(0, color)
ZEND_ARG_INFO(0, red)
ZEND_ARG_INFO(0, green)
ZEND_ARG_INFO(0, blue)
+ ZEND_ARG_INFO(0, alpha)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_imagecolorsforindex, 0)
@@ -945,6 +959,9 @@ const zend_function_entry gd_functions[] = {
#ifdef HAVE_GD_PNG
PHP_FE(imagecreatefrompng, arginfo_imagecreatefrompng)
#endif
+#ifdef HAVE_GD_WEBP
+ PHP_FE(imagecreatefromwebp, arginfo_imagecreatefromwebp)
+#endif
#ifdef HAVE_GD_GIF_READ
PHP_FE(imagecreatefromgif, arginfo_imagecreatefromgif)
#endif
@@ -968,6 +985,9 @@ const zend_function_entry gd_functions[] = {
#ifdef HAVE_GD_PNG
PHP_FE(imagepng, arginfo_imagepng)
#endif
+#ifdef HAVE_GD_WEBP
+ PHP_FE(imagewebp, arginfo_imagewebp)
+#endif
#ifdef HAVE_GD_GIF_CREATE
PHP_FE(imagegif, arginfo_imagegif)
#endif
@@ -1475,7 +1495,7 @@ PHP_FUNCTION(imageloadfont)
return;
}
- stream = php_stream_open_wrapper(file, "rb", ENFORCE_SAFE_MODE | IGNORE_PATH | IGNORE_URL_WIN | REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(file, "rb", IGNORE_PATH | IGNORE_URL_WIN | REPORT_ERRORS, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
@@ -1564,7 +1584,7 @@ PHP_FUNCTION(imageloadfont)
* that overlap with the old fonts (with indices 1-5). The first
* list index given out is always 1.
*/
- ind = 5 + zend_list_insert(font, le_gd_font);
+ ind = 5 + zend_list_insert(font, le_gd_font TSRMLS_CC);
RETURN_LONG(ind);
}
@@ -2427,7 +2447,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
}
}
- stream = php_stream_open_wrapper(file, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+ stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
@@ -2436,6 +2456,23 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
ioctx_func_p = NULL; /* don't allow sockets without IOCtx */
#endif
+ if (image_type == PHP_GDIMG_TYPE_WEBP) {
+ size_t buff_size;
+ char *buff;
+
+ /* needs to be malloc (persistent) - GD will free() it later */
+ buff_size = php_stream_copy_to_mem(stream, &buff, PHP_STREAM_COPY_ALL, 1);
+ if (!buff_size) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot read image data");
+ goto out_err;
+ }
+ im = (*ioctx_func_p)(buff_size, buff);
+ if (!im) {
+ goto out_err;
+ }
+ goto register_im;
+ }
+
/* try and avoid allocating a FILE* if the stream is not naturally a FILE* */
if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
@@ -2513,6 +2550,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
fflush(fp);
}
+register_im:
if (im) {
ZEND_REGISTER_RESOURCE(return_value, im, le_gd);
php_stream_close(stream);
@@ -2557,6 +2595,16 @@ PHP_FUNCTION(imagecreatefrompng)
/* }}} */
#endif /* HAVE_GD_PNG */
+#ifdef HAVE_GD_WEBP
+/* {{{ proto resource imagecreatefrompng(string filename)
+ Create a new image from PNG file or URL */
+PHP_FUNCTION(imagecreatefromwebp)
+{
+ _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageCreateFromWebpPtr, gdImageCreateFromWebpPtr);
+}
+/* }}} */
+#endif /* HAVE_GD_VPX */
+
#ifdef HAVE_GD_XBM
/* {{{ proto resource imagecreatefromxbm(string filename)
Create a new image from XBM file or URL */
@@ -2630,7 +2678,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char
/* When called from imagewbmp() the quality parameter stands for the foreground color. Default: black. */
/* The quality parameter for gd2 stands for chunk size */
- if (zend_parse_parameters(argc TSRMLS_CC, "r|sll", &imgind, &file, &file_len, &quality, &type) == FAILURE) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "r|pll", &imgind, &file, &file_len, &quality, &type) == FAILURE) {
return;
}
@@ -2647,9 +2695,6 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char
}
if (argc >= 2 && file_len) {
- if (strlen(file) != file_len) {
- RETURN_FALSE;
- }
PHP_GD_CHECK_OPEN_BASEDIR(fn, "Invalid filename");
fp = VCWD_FOPEN(fn, "wb");
@@ -2781,7 +2826,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char
#if HAVE_GD_BUNDLED
PHP_FUNCTION(imagexbm)
{
- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx);
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "GIF", gdImageXbmCtx);
}
#endif
/* }}} */
@@ -2791,11 +2836,7 @@ PHP_FUNCTION(imagexbm)
Output GIF image to browser or file */
PHP_FUNCTION(imagegif)
{
-#ifdef HAVE_GD_GIF_CTX
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
-#else
- _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGif);
-#endif
}
/* }}} */
#endif /* HAVE_GD_GIF_CREATE */
@@ -2805,25 +2846,29 @@ PHP_FUNCTION(imagegif)
Output PNG image to browser or file */
PHP_FUNCTION(imagepng)
{
-#ifdef USE_GD_IOCTX
- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtxEx);
-#else
- _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePng);
-#endif
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "GIF", gdImagePngCtxEx);
}
/* }}} */
#endif /* HAVE_GD_PNG */
+
+#ifdef HAVE_GD_WEBP
+/* {{{ proto bool imagewebp(resource im [, string filename[, quality]] )
+ Output PNG image to browser or file */
+PHP_FUNCTION(imagewebp)
+{
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "GIF", gdImageWebpCtx);
+}
+/* }}} */
+#endif /* HAVE_GD_WEBP */
+
+
#ifdef HAVE_GD_JPG
/* {{{ proto bool imagejpeg(resource im [, string filename [, int quality]])
Output JPEG image to browser or file */
PHP_FUNCTION(imagejpeg)
{
-#ifdef USE_GD_IOCTX
- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpegCtx);
-#else
- _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpeg);
-#endif
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "GIF", gdImageJpegCtx);
}
/* }}} */
#endif /* HAVE_GD_JPG */
@@ -2833,11 +2878,7 @@ PHP_FUNCTION(imagejpeg)
Output WBMP image to browser or file */
PHP_FUNCTION(imagewbmp)
{
-#ifdef USE_GD_IOCTX
- _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMPCtx);
-#else
- _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMP);
-#endif
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "GIF", gdImageWBMPCtx);
}
/* }}} */
#endif /* HAVE_GD_WBMP */
@@ -3066,11 +3107,11 @@ PHP_FUNCTION(imagecolorexact)
PHP_FUNCTION(imagecolorset)
{
zval *IM;
- long color, red, green, blue;
+ long color, red, green, blue, alpha = 0;
int col;
gdImagePtr im;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllll", &IM, &color, &red, &green, &blue) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllll|l", &IM, &color, &red, &green, &blue, &alpha) == FAILURE) {
return;
}
@@ -3082,6 +3123,7 @@ PHP_FUNCTION(imagecolorset)
im->red[col] = red;
im->green[col] = green;
im->blue[col] = blue;
+ im->alpha[col] = alpha;
} else {
RETURN_FALSE;
}
@@ -4101,7 +4143,7 @@ PHP_FUNCTION(imagepscopyfont)
}
nf_ind->extend = 1;
- l_ind = zend_list_insert(nf_ind, le_ps_font);
+ l_ind = zend_list_insert(nf_ind, le_ps_font TSRMLS_CC);
RETURN_LONG(l_ind);
}
*/
@@ -4150,7 +4192,7 @@ PHP_FUNCTION(imagepsencodefont)
RETURN_FALSE;
}
- zend_list_insert(enc_vector, le_ps_enc);
+ zend_list_insert(enc_vector, le_ps_enc TSRMLS_CC);
RETURN_TRUE;
}
@@ -4555,7 +4597,7 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
long ignore_warning;
#endif
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sslll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pplll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) {
return;
}
@@ -4565,14 +4607,6 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
dest_width = width;
int_threshold = threshold;
- if (strlen(f_org) != f_org_len) {
- RETURN_FALSE;
- }
-
- if (strlen(f_dest) != f_dest_len) {
- RETURN_FALSE;
- }
-
/* Check threshold value */
if (int_threshold < 0 || int_threshold > 8) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid threshold value '%d'", int_threshold);
diff --git a/ext/gd/gd_ctx.c b/ext/gd/gd_ctx.c
index cbf0731b69..1523816ed9 100644
--- a/ext/gd/gd_ctx.c
+++ b/ext/gd/gd_ctx.c
@@ -46,6 +46,33 @@ static void _php_image_output_ctxfree(struct gdIOCtx *ctx)
}
}
+static void _php_image_stream_putc(struct gdIOCtx *ctx, int c) {
+ char ch = (char) c;
+ php_stream * stream = (php_stream *)ctx->data;
+ TSRMLS_FETCH();
+ php_stream_write(stream, &ch, 1);
+}
+
+static int _php_image_stream_putbuf(struct gdIOCtx *ctx, const void* buf, int l)
+{
+ php_stream * stream = (php_stream *)ctx->data;
+ TSRMLS_FETCH();
+ return php_stream_write(stream, (void *)buf, l);
+}
+
+static void _php_image_stream_ctxfree(struct gdIOCtx *ctx)
+{
+ TSRMLS_FETCH();
+
+ if(ctx->data) {
+ php_stream_close((php_stream *) ctx->data);
+ ctx->data = NULL;
+ }
+ if(ctx) {
+ efree(ctx);
+ }
+}
+
/* {{{ _php_image_output_ctx */
static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
{
@@ -54,64 +81,62 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
int file_len = 0;
long quality, basefilter;
gdImagePtr im;
- FILE *fp = NULL;
int argc = ZEND_NUM_ARGS();
int q = -1, i;
int f = -1;
- gdIOCtx *ctx;
+ gdIOCtx *ctx = NULL;
+ zval *to_zval = NULL;
+ php_stream *stream;
/* The third (quality) parameter for Wbmp stands for the threshold when called from image2wbmp().
* The third (quality) parameter for Wbmp and Xbm stands for the foreground color index when called
* from imagey<type>().
*/
-
if (image_type == PHP_GDIMG_TYPE_XBM) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!|ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp!|ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) {
return;
}
} else {
/* PHP_GDIMG_TYPE_GIF
* PHP_GDIMG_TYPE_PNG
* PHP_GDIMG_TYPE_JPG
- * PHP_GDIMG_TYPE_WBM */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) {
+ * PHP_GDIMG_TYPE_WBM
+ * PHP_GDIMG_TYPE_WEBP
+ * */
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z/!ll", &imgind, &to_zval, &quality, &basefilter) == FAILURE) {
return;
}
}
ZEND_FETCH_RESOURCE(im, gdImagePtr, &imgind, -1, "Image", phpi_get_le_gd());
- if (argc > 1) {
- if (argc >= 3) {
- q = quality; /* or colorindex for foreground of BW images (defaults to black) */
- if (argc == 4) {
- f = basefilter;
- }
+ if (argc >= 3) {
+ q = quality; /* or colorindex for foreground of BW images (defaults to black) */
+ if (argc == 4) {
+ f = basefilter;
}
}
- if (argc > 1 && file_len) {
- if (strlen(file) != file_len) {
- RETURN_FALSE;
- }
- PHP_GD_CHECK_OPEN_BASEDIR(file, "Invalid filename");
-
- fp = VCWD_FOPEN(file, "wb");
- if (!fp) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing: %s", file, strerror(errno));
+ if (argc > 1 && to_zval != NULL) {
+ if (Z_TYPE_P(to_zval) == IS_RESOURCE) {
+ php_stream_from_zval_no_verify(stream, &to_zval);
+ if (stream == NULL) {
+ RETURN_FALSE;
+ }
+ } else if (Z_TYPE_P(to_zval) == IS_STRING) {
+ stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+ if (stream == NULL) {
+ RETURN_FALSE;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid 2nd parameter, it must a filename or a stream");
RETURN_FALSE;
}
-
- ctx = gdNewFileCtx(fp);
} else {
ctx = emalloc(sizeof(gdIOCtx));
ctx->putC = _php_image_output_putc;
ctx->putBuf = _php_image_output_putbuf;
-#if HAVE_LIBGD204
ctx->gd_free = _php_image_output_ctxfree;
-#else
- ctx->free = _php_image_output_ctxfree;
-#endif
#if APACHE && defined(CHARSET_EBCDIC)
/* XXX this is unlikely to work any more thies@thieso.net */
@@ -120,6 +145,14 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
#endif
}
+ if (!ctx) {
+ ctx = emalloc(sizeof(gdIOCtx));
+ ctx->putC = _php_image_stream_putc;
+ ctx->putBuf = _php_image_stream_putbuf;
+ ctx->gd_free = _php_image_stream_ctxfree;
+ ctx->data = (void *)stream;
+ }
+
switch(image_type) {
case PHP_GDIMG_CONVERT_WBM:
if(q<0||q>255) {
@@ -128,6 +161,12 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
case PHP_GDIMG_TYPE_JPG:
(*func_p)(im, ctx, q);
break;
+ case PHP_GDIMG_TYPE_WEBP:
+ if (q == -1) {
+ q = 80;
+ }
+ (*func_p)(im, ctx, q);
+ break;
case PHP_GDIMG_TYPE_PNG:
(*func_p)(im, ctx, q, f);
break;
@@ -156,12 +195,7 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
ctx->free(ctx);
#endif
- if(fp) {
- fflush(fp);
- fclose(fp);
- }
-
- RETURN_TRUE;
+ RETURN_TRUE;
}
/* }}} */
diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h
index 34bf4c6444..8aedc2c38c 100644
--- a/ext/gd/libgd/gd.h
+++ b/ext/gd/libgd/gd.h
@@ -249,6 +249,9 @@ gdImagePtr gdImageCreateFromWBMP(FILE *inFile);
gdImagePtr gdImageCreateFromWBMPCtx(gdIOCtx *infile);
gdImagePtr gdImageCreateFromJpeg(FILE *infile, int ignore_warning);
gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile, int ignore_warning);
+gdImagePtr gdImageCreateFromWebp(FILE *fd);
+gdImagePtr gdImageCreateFromWebpCtx(gdIOCtxPtr in);
+gdImagePtr gdImageCreateFromWebpPtr (int size, void *data);
int gdJpegGetVersionInt();
const char * gdPngGetVersionString();
@@ -487,6 +490,8 @@ void *gdImageWBMPPtr(gdImagePtr im, int *size, int fg);
void gdImageJpeg(gdImagePtr im, FILE *out, int quality);
void gdImageJpegCtx(gdImagePtr im, gdIOCtx *out, int quality);
+void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization);
+
/* Best to free this memory with gdFree(), not free() */
void *gdImageJpegPtr(gdImagePtr im, int *size, int quality);
diff --git a/ext/gd/libgd/gd_io.h b/ext/gd/libgd/gd_io.h
index b893751b7b..a4d66bb349 100644
--- a/ext/gd/libgd/gd_io.h
+++ b/ext/gd/libgd/gd_io.h
@@ -19,6 +19,7 @@ typedef struct gdIOCtx {
void (*gd_free)(struct gdIOCtx*);
+ void *data;
} gdIOCtx;
typedef struct gdIOCtx *gdIOCtxPtr;
diff --git a/ext/gd/libgd/gd_webp.c b/ext/gd/libgd/gd_webp.c
new file mode 100644
index 0000000000..889f5f10a6
--- /dev/null
+++ b/ext/gd/libgd/gd_webp.c
@@ -0,0 +1,201 @@
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+
+
+#ifdef HAVE_LIBVPX
+#include "webpimg.h"
+#include "gdhelpers.h"
+
+extern void gd_YUV420toRGBA(uint8* Y,
+ uint8* U,
+ uint8* V,
+ gdImagePtr im);
+
+extern void gd_RGBAToYUV420(gdImagePtr im2,
+ uint8* Y,
+ uint8* U,
+ uint8* V);
+
+const char * gdWebpGetVersionString()
+{
+ return "not defined";
+}
+
+gdImagePtr gdImageCreateFromWebp (FILE * inFile)
+{
+ gdImagePtr im;
+ gdIOCtx *in = gdNewFileCtx(inFile);
+ im = gdImageCreateFromWebpCtx(in);
+ in->gd_free(in);
+
+ return im;
+}
+
+gdImagePtr gdImageCreateFromWebpPtr (int size, void *data)
+{
+ int width, height, ret;
+ unsigned char *Y = NULL;
+ unsigned char *U = NULL;
+ unsigned char *V = NULL;
+ gdImagePtr im;
+
+ ret = WebPDecode(data, size, &Y, &U, &V, &width, &height);
+ if (ret != webp_success) {
+ if (Y) free(Y);
+ if (U) free(U);
+ if (V) free(V);
+ php_gd_error("WebP decode: fail to decode input data");
+ return NULL;
+ }
+ im = gdImageCreateTrueColor(width, height);
+ if (!im) {
+ return NULL;
+ }
+ gd_YUV420toRGBA(Y, U, V, im);
+ return im;
+}
+
+gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
+{
+ int width, height, ret;
+ unsigned char *filedata;
+ unsigned char dummy[1024];
+ unsigned char *Y = NULL;
+ unsigned char *U = NULL;
+ unsigned char *V = NULL;
+ size_t size = 0, n;
+ gdImagePtr im;
+
+ do {
+ n = gdGetBuf(dummy, 1024, infile);
+ size += n;
+ } while (n != EOF);
+
+ filedata = gdMalloc(size);
+ if (!filedata) {
+ php_gd_error("WebP decode: alloc failed");
+ return NULL;
+ }
+ gdGetBuf(filedata, size, infile);
+ ret = WebPDecode(filedata, size, &Y, &U, &V, &width, &height);
+ gdFree(filedata);
+ if (ret != webp_success) {
+ if (Y) free(Y);
+ if (U) free(U);
+ if (V) free(V);
+ php_gd_error("WebP decode: fail to decode input data");
+ return NULL;
+ }
+ im = gdImageCreateTrueColor(width, height);
+ gd_YUV420toRGBA(Y, U, V, im);
+ return im;
+}
+
+void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization)
+{
+ gdIOCtx *out = gdNewFileCtx(outFile);
+ gdImageWebpCtx(im, out, quantization);
+ out->gd_free(out);
+}
+
+void gdImageWebp (gdImagePtr im, FILE * outFile)
+{
+ gdIOCtx *out = gdNewFileCtx(outFile);
+ gdImageWebpCtx(im, out, -1);
+ out->gd_free(out);
+}
+
+void * gdImageWebpPtr (gdImagePtr im, int *size)
+{
+ void *rv;
+ gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
+ gdImageWebpCtx(im, out, -1);
+ rv = gdDPExtractData(out, size);
+ out->gd_free(out);
+
+ return rv;
+}
+
+void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization)
+{
+ void *rv;
+ gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
+ gdImageWebpCtx(im, out, quantization);
+ rv = gdDPExtractData(out, size);
+ out->gd_free(out);
+ return rv;
+}
+
+/*
+ * Maps normalized QP (quality) to VP8 QP
+ */
+int mapQualityToVP8QP(int quality) {
+#define MIN_QUALITY 0
+#define MAX_QUALITY 100
+#define MIN_VP8QP 1
+#define MAX_VP8QP 63
+ const float scale = MAX_VP8QP - MIN_VP8QP;
+ const float vp8qp =
+ scale * (MAX_QUALITY - quality) / (MAX_QUALITY - MIN_QUALITY) + MIN_VP8QP;
+ if (quality < MIN_QUALITY || quality > MAX_QUALITY) {
+ php_gd_error("Wrong quality value %d.", quality);
+ return -1;
+ }
+
+ return (int)(vp8qp + 0.5);
+}
+
+/* This routine is based in part on code from Dale Lutz (Safe Software Inc.)
+ * and in part on demo code from Chapter 15 of "PNG: The Definitive Guide"
+ * (http://www.cdrom.com/pub/png/pngbook.html).
+ */
+void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization)
+{
+ int width = im->sx;
+ int height = im->sy;
+ int colors = im->colorsTotal;
+ int *open = im->open;
+
+ int yuv_width, yuv_height, yuv_nbytes, ret;
+ int vp8_quality;
+ unsigned char *Y = NULL,
+ *U = NULL,
+ *V = NULL;
+ unsigned char *filedata = NULL;
+
+ /* Conversion to Y,U,V buffer */
+ yuv_width = (width + 1) >> 1;
+ yuv_height = (height + 1) >> 1;
+ yuv_nbytes = width * height + 2 * yuv_width * yuv_height;
+
+ if ((Y = (unsigned char *)gdCalloc(yuv_nbytes, sizeof(unsigned char))) == NULL) {
+ php_gd_error("gd-webp error: cannot allocate Y buffer");
+ return;
+ }
+ vp8_quality = mapQualityToVP8QP(quantization);
+
+ U = Y + width * height;
+ V = U + yuv_width * yuv_height;
+ gd_RGBAToYUV420(im, Y, U, V);
+
+ /* Encode Y,U,V and write data to file */
+ ret = WebPEncode(Y, U, V, width, height, width, yuv_width, yuv_height, yuv_width,
+ vp8_quality, &filedata, &yuv_nbytes, NULL);
+ gdFree(Y);
+
+ if (ret != webp_success) {
+ if (filedata) {
+ free(filedata);
+ }
+ php_gd_error("gd-webp error: WebP Encoder failed");
+ return;
+ }
+
+ gdPutBuf (filedata, yuv_nbytes, outfile);
+ free(filedata);
+}
+
+#endif /* HAVE_LIBVPX */
diff --git a/ext/gd/libgd/webpimg.c b/ext/gd/libgd/webpimg.c
new file mode 100644
index 0000000000..01bef93c48
--- /dev/null
+++ b/ext/gd/libgd/webpimg.c
@@ -0,0 +1,900 @@
+/*===========================================================================*
+ - Copyright 2010 Google Inc.
+ -
+ - This code is licensed under the same terms as WebM:
+ - Software License Agreement: http://www.webmproject.org/license/software/
+ - Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+ *===========================================================================*/
+
+/*
+ * Encoding/Decoding of WebP still image compression format.
+ *
+ * 1. WebPDecode: Takes an array of bytes (string) corresponding to the WebP
+ * encoded image and generates output in the YUV format with
+ * the color components U, V subsampled to 1/2 resolution along
+ * each dimension.
+ *
+ * 2. YUV420toRGBA: Converts from YUV (with color subsampling) such as produced
+ * by the WebPDecode routine into 32 bits per pixel RGBA data
+ * array. This data array can be directly used by the Leptonica
+ * Pix in-memory image format.
+ *
+ * 3. WebPEncode: Takes a Y, U, V data buffers (with color components U and V
+ * subsampled to 1/2 resolution) and generates the WebP string
+ *
+ * 4. RGBAToYUV420: Generates Y, U, V data (with color subsampling) from 32 bits
+ * per pixel RGBA data buffer. The resulting YUV data can be
+ * directly fed into the WebPEncode routine.
+ *
+ * 5. AdjustColorspace:
+ *
+ * 6. AdjustColorspaceBack:
+ */
+#include "gd.h"
+#ifdef HAVE_LIBVPX
+#include "webpimg.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+#include "gd.h"
+
+/*---------------------------------------------------------------------*
+ * color conversions *
+ *---------------------------------------------------------------------*/
+
+#ifndef inline
+# define inline __inline
+#endif
+static inline int clip(float v, int a, int b) {
+ return (v > b) ? b : (v < 0) ? 0 : (int)(v);
+}
+enum {
+ COLOR_RED = 0,
+ COLOR_GREEN = 1,
+ COLOR_BLUE = 2,
+ ALPHA_CHANNEL = 3
+};
+
+/* endian neutral extractions of RGBA from a 32 bit pixel */
+static const uint32 RED_SHIFT =
+ 8 * (sizeof(uint32) - 1 - COLOR_RED); /* 24 */
+static const uint32 GREEN_SHIFT =
+ 8 * (sizeof(uint32) - 1 - COLOR_GREEN); /* 16 */
+static const uint32 BLUE_SHIFT =
+ 8 * (sizeof(uint32) - 1 - COLOR_BLUE); /* 8 */
+static const uint32 ALPHA_SHIFT =
+ 8 * (sizeof(uint32) - 1 - ALPHA_CHANNEL); /* 0 */
+
+static inline int GetRed(const uint32* rgba) {
+ return gdTrueColorGetRed(*rgba);
+}
+
+static inline int GetGreen(const uint32* rgba) {
+ return gdTrueColorGetGreen(*rgba);
+}
+
+static inline int GetBlue(const uint32* rgba) {
+ return gdTrueColorGetBlue(*rgba);
+}
+
+enum { YUV_FRAC = 16 };
+
+static inline int clip_uv(int v) {
+ v = (v + (257 << (YUV_FRAC + 2 - 1))) >> (YUV_FRAC + 2);
+ return ((v & ~0xff) == 0) ? v : v < 0 ? 0u : 255u;
+}
+
+
+/* YUV <-----> RGB conversions */
+/* The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
+ * More information at: http://en.wikipedia.org/wiki/YCbCr
+ */
+static inline int GetLumaY(int r, int g, int b) {
+ const int kRound = (1 << (YUV_FRAC - 1)) + (16 << YUV_FRAC);
+ // Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
+ const int luma = 16839 * r + 33059 * g + 6420 * b;
+ return (luma + kRound) >> YUV_FRAC;
+}
+
+static inline int GetLumaYfromPtr(uint32* rgba) {
+ const int r = GetRed(rgba);
+ const int g = GetGreen(rgba);
+ const int b = GetBlue(rgba);
+ return GetLumaY(r, g, b);
+}
+
+static inline int GetChromaU(int r, int g, int b) {
+ // U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
+ return clip_uv(-9719 * r - 19081 * g + 28800 * b);
+}
+
+static inline int GetChromaV(int r, int g, int b) {
+ // V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
+ return clip_uv(+28800 * r - 24116 * g - 4684 * b);
+}
+
+/* Converts YUV to RGB and writes into a 32 bit pixel in endian
+ * neutral fashion
+ */
+enum { RGB_FRAC = 16, RGB_HALF = (1 << RGB_FRAC) / 2,
+ RGB_RANGE_MIN = -227, RGB_RANGE_MAX = 256 + 226 };
+
+static int init_done = 0;
+static int16_t kVToR[256], kUToB[256];
+static int32_t kVToG[256], kUToG[256];
+static uint8_t kClip[RGB_RANGE_MAX - RGB_RANGE_MIN];
+
+static void InitTables() {
+ int i;
+ for (i = 0; i < 256; ++i) {
+ kVToR[i] = (89858 * (i - 128) + RGB_HALF) >> RGB_FRAC;
+ kUToG[i] = -22014 * (i - 128) + RGB_HALF;
+ kVToG[i] = -45773 * (i - 128);
+ kUToB[i] = (113618 * (i - 128) + RGB_HALF) >> RGB_FRAC;
+ }
+ for (i = RGB_RANGE_MIN; i < RGB_RANGE_MAX; ++i) {
+ const int j = ((i - 16) * 76283 + RGB_HALF) >> RGB_FRAC;
+ kClip[i - RGB_RANGE_MIN] = (j < 0) ? 0 : (j > 255) ? 255 : j;
+ }
+
+ init_done = 1;
+}
+
+static void ToRGB(int y, int u, int v, uint32* const dst) {
+ const int r_off = kVToR[v];
+ const int g_off = (kVToG[v] + kUToG[u]) >> RGB_FRAC;
+ const int b_off = kUToB[u];
+ const int r = kClip[y + r_off - RGB_RANGE_MIN];
+ const int g = kClip[y + g_off - RGB_RANGE_MIN];
+ const int b = kClip[y + b_off - RGB_RANGE_MIN];
+ *dst = (r << RED_SHIFT) | (g << GREEN_SHIFT) | (b << BLUE_SHIFT);
+}
+
+static inline uint32 get_le32(const uint8* const data) {
+ return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+}
+
+/* Returns the difference (in dB) between two images represented in YUV format
+ *
+ * Input:
+ * Y1/U1/V1: The Y/U/V data of the first image
+ * Y2/U2/V2: The Y/U/V data of the second image
+ *
+ * Returns the PSNR (http://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio)
+ * value computed bewteen the two images
+ */
+double GetPSNRYuv(const uint8* Y1,
+ const uint8* U1,
+ const uint8* V1,
+ const uint8* Y2,
+ const uint8* U2,
+ const uint8* V2,
+ int y_width,
+ int y_height) {
+ int x, y, row_idx;
+ const int uv_width = ((y_width + 1) >> 1);
+ const int uv_height = ((y_height + 1) >> 1);
+ double sse = 0., count = 0.;
+ for (y = 0; y < y_height; ++y) {
+ count += y_width;
+ row_idx = y * y_width;
+ for (x = 0; x < y_width; ++x) {
+ double diff = Y1[row_idx + x] - Y2[row_idx + x];
+ sse += diff * diff;
+ }
+ }
+ for (y = 0; y < uv_height; ++y) {
+ count += 2 * uv_width;
+ row_idx = y * uv_width;
+ for (x = 0; x < uv_width; ++x) {
+ const double diff_U = U1[row_idx + x] - U2[row_idx + x];
+ const double diff_V = V1[row_idx + x] - V2[row_idx + x];
+ sse += diff_U * diff_U + diff_V * diff_V;
+ }
+ }
+ return -4.3429448 * log(sse / (255. * 255. * count));
+}
+
+/* Returns the difference (in dB) between two images. One represented
+ * using Y,U,V vectors and the other is webp image data.
+ * Input:
+ * Y1/U1/V1: The Y/U/V data of the first image
+ * imgdata: data buffer containing webp image
+ * imgdata_size: size of the imgdata buffer
+ *
+ * Returns the PSNR value computed bewteen the two images
+ */
+double WebPGetPSNR(const uint8* Y1,
+ const uint8* U1,
+ const uint8* V1,
+ uint8* imgdata,
+ int imgdata_size) {
+ uint8* Y2 = NULL;
+ uint8* U2 = NULL;
+ uint8* V2 = NULL;
+ int w = 0, h = 0;
+ double psnr = 0;
+
+ WebPDecode(imgdata,
+ imgdata_size,
+ &Y2,
+ &U2,
+ &V2,
+ &w,
+ &h);
+
+ psnr = GetPSNRYuv(Y1, U1, V1, Y2, U2, V2, w, h);
+ free(Y2);
+
+ return psnr;
+}
+
+/*---------------------------------------------------------------------*
+ * Reading WebP *
+ *---------------------------------------------------------------------*/
+
+/* RIFF layout is:
+ * 0ffset tag
+ * 0...3 "RIFF" 4-byte tag
+ * 4...7 size of image data (including metadata) starting at offset 8
+ * 8...11 "WEBP" our form-type signature
+ * 12..15 "VP8 " 4-byte tags, describing the raw video format used
+ * 16..19 size of the raw WebP image data, starting at offset 20
+ * 20.... the WebP bytes
+ * There can be extra chunks after the "VP8 " chunk (ICMT, ICOP, ...)
+ * All 32-bits sizes are in little-endian order.
+ * Note: chunk data must be padded to multiple of 2 in size
+ */
+
+int SkipRiffHeader(const uint8** data_ptr, int *data_size_ptr) {
+ /* 20 bytes RIFF header 10 bytes VP8 header */
+ const int kHeaderSize = (20 + 10);
+ uint32 chunk_size = 0xffffffffu;
+
+ if (*data_size_ptr >= kHeaderSize && !memcmp(*data_ptr, "RIFF", 4)) {
+ if (memcmp(*data_ptr + 8, "WEBP", 4)) {
+ return 0; /* wrong image file signature */
+ } else {
+ const uint32 riff_size = get_le32(*data_ptr + 4);
+ if (memcmp(*data_ptr + 12, "VP8 ", 4)) {
+ return 0; /* invalid compression format */
+ }
+ chunk_size = get_le32(*data_ptr + 16);
+ if ((chunk_size > riff_size + 8) || (chunk_size & 1)) {
+ return 0; /* inconsistent size information. */
+ }
+ /* We have a RIFF container. Skip it. */
+ *data_ptr += 20;
+ *data_size_ptr -= 20;
+ }
+ }
+ return chunk_size;
+}
+
+/* Generate RGBA row from an YUV row (with width upsampling of chrome data)
+ * Input:
+ * 1, 2, 3. y_src, u_src, v_src - Pointers to input Y, U, V row data
+ * respectively. We reuse these variables, they iterate over all pixels in
+ * the row.
+ * 4. y_width: width of the Y image plane (aka image width)
+ * Output:
+ * 5. rgb_sat: pointer to the output rgb row. We reuse this variable, it
+ * iterates over all pixels in the row.
+ */
+static void YUV420toRGBLine(uint8* y_src,
+ uint8* u_src,
+ uint8* v_src,
+ int y_width,
+ uint32* rgb_dst) {
+ int x;
+ for (x = 0; x < (y_width >> 1); ++x) {
+ const int U = u_src[0];
+ const int V = v_src[0];
+ ToRGB(y_src[0], U, V, rgb_dst);
+ ToRGB(y_src[1], U, V, rgb_dst + 1);
+ ++u_src;
+ ++v_src;
+ y_src += 2;
+ rgb_dst += 2;
+ }
+ if (y_width & 1) { /* Rightmost pixel */
+ ToRGB(y_src[0], (*u_src), (*v_src), rgb_dst);
+ }
+}
+
+/* Converts from YUV (with color subsampling) such as produced by the WebPDecode
+ * routine into 32 bits per pixel RGBA data array. This data array can be
+ * directly used by the Leptonica Pix in-memory image format.
+ * Input:
+ * 1, 2, 3. Y, U, V: the input data buffers
+ * 4. pixwpl: the desired words per line corresponding to the supplied
+ * output pixdata.
+ * 5. width, height: the dimensions of the image whose data resides in Y,
+ * U, V.
+ * Output:
+ * 6. pixdata: the output data buffer. Caller should allocate
+ * height * pixwpl bytes of memory before calling this routine.
+ */
+void YUV420toRGBA(uint8* Y,
+ uint8* U,
+ uint8* V,
+ int words_per_line,
+ int width,
+ int height,
+ uint32* pixdata) {
+ int y_width = width;
+ int y_stride = y_width;
+ int uv_width = ((y_width + 1) >> 1);
+ int uv_stride = uv_width;
+ int y;
+
+ if (!init_done)
+ InitTables();
+
+ /* note that the U, V upsampling in height is happening here as the U, V
+ * buffers sent to successive odd-even pair of lines is same.
+ */
+ for (y = 0; y < height; ++y) {
+ YUV420toRGBLine(Y + y * y_stride,
+ U + (y >> 1) * uv_stride,
+ V + (y >> 1) * uv_stride,
+ width,
+ pixdata + y * words_per_line);
+ }
+}
+
+void gd_YUV420toRGBA(uint8* Y,
+ uint8* U,
+ uint8* V,
+ gdImagePtr im) {
+ int width = im->sx;
+ int height = im->sy;
+ int y_width = width;
+ int y_stride = y_width;
+ int uv_width = ((y_width + 1) >> 1);
+ int uv_stride = uv_width;
+ int y;
+
+ /* output im must be truecolor */
+ if (!im->trueColor) {
+ return;
+ }
+
+ if (!init_done)
+ InitTables();
+
+ /* note that the U, V upsampling in height is happening here as the U, V
+ * buffers sent to successive odd-even pair of lines is same.
+ */
+ for (y = 0; y < height; ++y) {
+ YUV420toRGBLine(Y + y * y_stride,
+ U + (y >> 1) * uv_stride,
+ V + (y >> 1) * uv_stride,
+ width,
+ im->tpixels[y]);
+ }
+}
+
+static WebPResult VPXDecode(const uint8* data,
+ int data_size,
+ uint8** p_Y,
+ uint8** p_U,
+ uint8** p_V,
+ int* p_width,
+ int* p_height) {
+ vpx_codec_ctx_t dec;
+ vp8_postproc_cfg_t ppcfg;
+ WebPResult result = webp_failure;
+
+ if (!data || data_size <= 10 || !p_Y || !p_U || !p_V
+ || *p_Y != NULL || *p_U != NULL || *p_V != NULL) {
+ return webp_failure;
+ }
+
+ if (vpx_codec_dec_init(&dec,
+ &vpx_codec_vp8_dx_algo, NULL, 0) != VPX_CODEC_OK) {
+ return webp_failure;
+ }
+
+ ppcfg.post_proc_flag = VP8_NOFILTERING;
+ vpx_codec_control(&dec, VP8_SET_POSTPROC, &ppcfg);
+
+
+ if (vpx_codec_decode(&dec, data, data_size, NULL, 0) == VPX_CODEC_OK) {
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t* const img = vpx_codec_get_frame(&dec, &iter);
+ if (img) {
+ int y_width = img->d_w;
+ int y_height = img->d_h;
+ int y_stride = y_width;
+ int uv_width = (y_width + 1) >> 1;
+ int uv_stride = uv_width;
+ int uv_height = ((y_height + 1) >> 1);
+ int y;
+
+ *p_width = y_width;
+ *p_height = y_height;
+ if ((*p_Y = (uint8 *)(calloc(y_stride * y_height
+ + 2 * uv_stride * uv_height,
+ sizeof(uint8)))) != NULL) {
+ *p_U = *p_Y + y_height * y_stride;
+ *p_V = *p_U + uv_height * uv_stride;
+ for (y = 0; y < y_height; ++y) {
+ memcpy(*p_Y + y * y_stride,
+ img->planes[0] + y * img->stride[0],
+ y_width);
+ }
+ for (y = 0; y < uv_height; ++y) {
+ memcpy(*p_U + y * uv_stride,
+ img->planes[1] + y * img->stride[1],
+ uv_width);
+ memcpy(*p_V + y * uv_stride,
+ img->planes[2] + y * img->stride[2],
+ uv_width);
+ }
+ result = webp_success;
+ }
+ }
+ }
+ vpx_codec_destroy(&dec);
+
+ return result;
+}
+
+WebPResult WebPDecode(const uint8* data,
+ int data_size,
+ uint8** p_Y,
+ uint8** p_U,
+ uint8** p_V,
+ int* p_width,
+ int* p_height) {
+
+ const uint32 chunk_size = SkipRiffHeader(&data, &data_size);
+ if (!chunk_size) {
+ return webp_failure; /* unsupported RIFF header */
+ }
+
+ return VPXDecode(data, data_size, p_Y, p_U, p_V, p_width, p_height);
+}
+
+/*---------------------------------------------------------------------*
+ * Writing WebP *
+ *---------------------------------------------------------------------*/
+
+/* Takes a pair of RGBA row data as input and generates 2 rows of Y data and one
+ * row of subsampled U, V data as output
+ * Input:
+ * 1, 2. rgb_line1, rgb_line2 - input rgba rows
+ * 3. width - image width
+ * Outout:
+ * 4, 5, 6: Output Y, U, V row
+ */
+static void RGBALinepairToYUV420(uint32* rgb_line1,
+ uint32* rgb_line2,
+ int width,
+ uint8* Y_dst1,
+ uint8* Y_dst2,
+ uint8* u_dst,
+ uint8* v_dst) {
+ int x;
+ for (x = (width >> 1); x > 0; --x) {
+ const int sum_r =
+ GetRed(rgb_line1 + 0) + GetRed(rgb_line1 + 1) +
+ GetRed(rgb_line2 + 0) + GetRed(rgb_line2 + 1);
+ const int sum_g =
+ GetGreen(rgb_line1 + 0) + GetGreen(rgb_line1 + 1) +
+ GetGreen(rgb_line2 + 0) + GetGreen(rgb_line2 + 1);
+ const int sum_b =
+ GetBlue(rgb_line1 + 0) + GetBlue(rgb_line1 + 1) +
+ GetBlue(rgb_line2 + 0) + GetBlue(rgb_line2 + 1);
+
+ Y_dst1[0] = GetLumaYfromPtr(rgb_line1 + 0);
+ Y_dst1[1] = GetLumaYfromPtr(rgb_line1 + 1);
+ Y_dst2[0] = GetLumaYfromPtr(rgb_line2 + 0);
+ Y_dst2[1] = GetLumaYfromPtr(rgb_line2 + 1);
+
+ *u_dst++ = GetChromaU(sum_r, sum_g, sum_b);
+ *v_dst++ = GetChromaV(sum_r, sum_g, sum_b);
+
+ rgb_line1 += 2;
+ rgb_line2 += 2;
+ Y_dst1 += 2;
+ Y_dst2 += 2;
+ }
+
+ if (width & 1) { /* rightmost pixel. */
+ const int sum_r = GetRed(rgb_line1) + GetRed(rgb_line2);
+ const int sum_g = GetGreen(rgb_line1) + GetGreen(rgb_line2);
+ const int sum_b = GetBlue(rgb_line1) + GetBlue(rgb_line2);
+
+ Y_dst1[0] = GetLumaYfromPtr(rgb_line1);
+ Y_dst2[0] = GetLumaYfromPtr(rgb_line2);
+ *u_dst = GetChromaU(2 * sum_r, 2 * sum_g, 2 * sum_b);
+ *v_dst = GetChromaV(2 * sum_r, 2 * sum_g, 2 * sum_b);
+ }
+}
+
+/* Generates Y, U, V data (with color subsampling) from 32 bits
+ * per pixel RGBA data buffer. The resulting YUV data can be directly fed into
+ * the WebPEncode routine.
+ * Input:
+ * 1. pixdatainput rgba data buffer
+ * 2. words per line corresponding to pixdata
+ * 3, 4. image width and height respectively
+ * Output:
+ * 5, 6, 7. Output YUV data buffers
+ */
+void gd_RGBAToYUV420(gdImagePtr im2,
+ uint8* Y,
+ uint8* U,
+ uint8* V) {
+ int y_width = im2->sx;
+ int y_height = im2->sy;
+ int y_stride = y_width;
+ int uv_width = ((y_width + 1) >> 1);
+ int uv_stride = uv_width;
+ int y;
+ gdImagePtr im = NULL;
+ int free_im = 0;
+
+ if (!im2->trueColor) {
+ /* Todo: Replace the color/YUV functions with our own and simplify
+ that should boost the conversion a bit as well, not only for
+ palette image. */
+ im = gdImageCreateTrueColor(im2->sx, im2->sy);
+ if (!im) {
+ php_gd_error("gd-webp error: cannot convert palette input to truecolor");
+ return;
+ }
+ gdImageCopy(im, im2, 0, 0, 0, 0, im->sx, im->sy);
+ free_im = 1;
+ } else {
+ im = im2;
+ }
+ for (y = 0; y < (y_height >> 1); ++y) {
+ RGBALinepairToYUV420(im->tpixels[2 * y],
+ im->tpixels[2 * y + 1],
+ y_width,
+ Y + 2 * y * y_stride,
+ Y + (2 * y + 1) * y_stride,
+ U + y * uv_stride,
+ V + y * uv_stride);
+ }
+ if (y_height & 1) {
+ RGBALinepairToYUV420(im->tpixels[y_height - 1],
+ im->tpixels[y_height - 1],
+ y_width,
+ Y + (y_height - 1) * y_stride,
+ Y + (y_height - 1) * y_stride,
+ U + (y_height >> 1) * uv_stride,
+ V + (y_height >> 1) * uv_stride);
+ }
+ if (free_im) {
+ gdImageDestroy(im);
+ }
+}
+
+/* Generates Y, U, V data (with color subsampling) from 32 bits
+ * per pixel RGBA data buffer. The resulting YUV data can be directly fed into
+ * the WebPEncode routine.
+ * Input:
+ * 1. pixdatainput rgba data buffer
+ * 2. words per line corresponding to pixdata
+ * 3, 4. image width and height respectively
+ * Output:
+ * 5, 6, 7. Output YUV data buffers
+ */
+void RGBAToYUV420(uint32* pixdata,
+ int words_per_line,
+ int width,
+ int height,
+ uint8* Y,
+ uint8* U,
+ uint8* V) {
+ int y_width = width;
+ int y_height = height;
+ int y_stride = y_width;
+ int uv_width = ((y_width + 1) >> 1);
+ int uv_stride = uv_width;
+ int y;
+
+ for (y = 0; y < (y_height >> 1); ++y) {
+ RGBALinepairToYUV420(pixdata + 2 * y * words_per_line,
+ pixdata + (2 * y + 1) * words_per_line,
+ y_width,
+ Y + 2 * y * y_stride,
+ Y + (2 * y + 1) * y_stride,
+ U + y * uv_stride,
+ V + y * uv_stride);
+ }
+ if (y_height & 1) {
+ RGBALinepairToYUV420(pixdata + (y_height - 1) * words_per_line,
+ pixdata + (y_height - 1) * words_per_line,
+ y_width,
+ Y + (y_height - 1) * y_stride,
+ Y + (y_height - 1) * y_stride,
+ U + (y_height >> 1) * uv_stride,
+ V + (y_height >> 1) * uv_stride);
+ }
+}
+
+static int codec_ctl(vpx_codec_ctx_t *enc,
+ enum vp8e_enc_control_id id,
+ int value) {
+ const vpx_codec_err_t res = vpx_codec_control_(enc, id, value);
+ if (res != VPX_CODEC_OK) {
+ return webp_failure;
+ }
+ return webp_success;
+}
+
+static void SetupParams(vpx_codec_enc_cfg_t* cfg,
+ int QP) {
+ cfg->g_threads = 2;
+ cfg->rc_min_quantizer = QP;
+ cfg->rc_max_quantizer = QP;
+ cfg->kf_mode = VPX_KF_FIXED;
+}
+
+/* VPXEncode: Takes a Y, U, V data buffers (with color components U and V
+ * subsampled to 1/2 resolution) and generates the VPX string.
+ * Output VPX string is placed in the *p_out buffer. container_size
+ * indicates number of bytes to be left blank at the beginning of
+ * *p_out buffer to accommodate for a container header.
+ *
+ * Return: success/failure
+ */
+static WebPResult VPXEncode(const uint8* Y,
+ const uint8* U,
+ const uint8* V,
+ int y_width,
+ int y_height,
+ int y_stride,
+ int uv_width,
+ int uv_height,
+ int uv_stride,
+ int QP,
+ int container_size,
+ unsigned char** p_out,
+ int* p_out_size_bytes) {
+ vpx_codec_iface_t* iface = &vpx_codec_vp8_cx_algo;
+ vpx_codec_err_t res;
+ vpx_codec_enc_cfg_t cfg;
+ vpx_codec_ctx_t enc;
+ WebPResult result = webp_failure;
+ vpx_image_t img;
+
+ *p_out = NULL;
+ *p_out_size_bytes = 0;
+
+
+ /* validate input parameters. */
+ if (!p_out || !Y || !U || !V
+ || y_width <= 0 || y_height <= 0 || uv_width <= 0 || uv_height <= 0
+ || y_stride < y_width || uv_stride < uv_width
+ || QP < 0 || QP > 63) {
+ return webp_failure;
+ }
+
+ res = vpx_codec_enc_config_default(iface, &cfg, 0);
+ if (res != VPX_CODEC_OK) {
+ return webp_failure;
+ }
+
+ SetupParams(&cfg, QP);
+ cfg.g_w = y_width;
+ cfg.g_h = y_height;
+
+ res = vpx_codec_enc_init(&enc, iface, &cfg, 0);
+
+ if (res == VPX_CODEC_OK) {
+ codec_ctl(&enc, VP8E_SET_CPUUSED, 3);
+ codec_ctl(&enc, VP8E_SET_NOISE_SENSITIVITY, 0);
+ codec_ctl(&enc, VP8E_SET_SHARPNESS, 0);
+ codec_ctl(&enc, VP8E_SET_ENABLEAUTOALTREF, 0);
+ codec_ctl(&enc, VP8E_SET_ARNR_MAXFRAMES, 0);
+ codec_ctl(&enc, VP8E_SET_ARNR_TYPE, 0);
+ codec_ctl(&enc, VP8E_SET_ARNR_STRENGTH, 0);
+ codec_ctl(&enc, VP8E_SET_STATIC_THRESHOLD, 0);
+ codec_ctl(&enc, VP8E_SET_TOKEN_PARTITIONS, 2);
+
+ vpx_img_wrap(&img, IMG_FMT_I420,
+ y_width, y_height, 16, (uint8*)(Y));
+ img.planes[PLANE_Y] = (uint8*)(Y);
+ img.planes[PLANE_U] = (uint8*)(U);
+ img.planes[PLANE_V] = (uint8*)(V);
+ img.stride[PLANE_Y] = y_stride;
+ img.stride[PLANE_U] = uv_stride;
+ img.stride[PLANE_V] = uv_stride;
+
+ res = vpx_codec_encode(&enc, &img, 0, 1, 0, VPX_DL_BEST_QUALITY);
+
+ if (res == VPX_CODEC_OK) {
+ vpx_codec_iter_t iter = NULL;
+ const vpx_codec_cx_pkt_t* pkt = vpx_codec_get_cx_data(&enc, &iter);
+ if (pkt != NULL) {
+ *p_out = (unsigned char*)(calloc(container_size + pkt->data.frame.sz,
+ 1));
+
+ memcpy(*p_out + container_size,
+ (const void*)(pkt->data.frame.buf),
+ pkt->data.frame.sz);
+ *p_out_size_bytes = container_size + pkt->data.frame.sz;
+
+ result = webp_success;
+ }
+ }
+ }
+
+ vpx_codec_destroy(&enc);
+
+ return result;
+}
+
+WebPResult WebPEncode(const uint8* Y,
+ const uint8* U,
+ const uint8* V,
+ int y_width,
+ int y_height,
+ int y_stride,
+ int uv_width,
+ int uv_height,
+ int uv_stride,
+ int QP,
+ unsigned char** p_out,
+ int* p_out_size_bytes,
+ double *psnr) {
+
+ const int kRiffHeaderSize = 20;
+
+ if (VPXEncode(Y, U, V,
+ y_width, y_height, y_stride,
+ uv_width, uv_height, uv_stride,
+ QP, kRiffHeaderSize,
+ p_out, p_out_size_bytes) != webp_success) {
+ return webp_failure;
+ } else {
+ /* Write RIFF header */
+ const int img_size_bytes = *p_out_size_bytes - kRiffHeaderSize;
+ const int chunk_size = (img_size_bytes + 1) & ~1; /* make size even */
+ const int riff_size = chunk_size + 12;
+ const uint8_t kRiffHeader[20] = { 'R', 'I', 'F', 'F',
+ (riff_size >> 0) & 255,
+ (riff_size >> 8) & 255,
+ (riff_size >> 16) & 255,
+ (riff_size >> 24) & 255,
+ 'W', 'E', 'B', 'P',
+ 'V', 'P', '8', ' ',
+ (chunk_size >> 0) & 255,
+ (chunk_size >> 8) & 255,
+ (chunk_size >> 16) & 255,
+ (chunk_size >> 24) & 255 };
+ memcpy(*p_out, kRiffHeader, kRiffHeaderSize);
+
+ if (psnr) {
+ *psnr = WebPGetPSNR(Y, U, V, *p_out, *p_out_size_bytes);
+ }
+
+ return webp_success;
+ }
+}
+
+void AdjustColorspace(uint8* Y, uint8* U, uint8* V, int width, int height) {
+ int y_width = width;
+ int y_height = height;
+ int y_stride = y_width;
+ int uv_width = ((y_width + 1) >> 1);
+ int uv_height = ((y_height + 1) >> 1);
+ int uv_stride = uv_width;
+ int x, y;
+ /* convert luma */
+ for (y = 0; y < y_height; ++y) {
+ uint8* const Yrow = Y + y * y_stride;
+ for (x = 0; x < y_width; ++x) {
+ /* maps [0..255] to [16..235] */
+ Yrow[x] = ((Yrow[x] * 55 + 32) >> 6) + 16;
+ }
+ }
+ /* convert chroma */
+ for (y = 0; y < uv_height; ++y) {
+ uint8* const Urow = U + y * uv_stride;
+ uint8* const Vrow = V + y * uv_stride;
+ for (x = 0; x < uv_width; ++x) {
+ /* maps [0..255] to [16..240] */
+ Urow[x] = (((Urow[x] - 127) * 7) >> 3) + 128;
+ Vrow[x] = (((Vrow[x] - 127) * 7) >> 3) + 128;
+ }
+ }
+}
+
+void AdjustColorspaceBack(uint8* Y, uint8* U, uint8* V, int width, int height) {
+ int y_width = width;
+ int y_height = height;
+ int y_stride = y_width;
+ int uv_width = ((y_width + 1) >> 1);
+ int uv_height = ((y_height + 1) >> 1);
+ int uv_stride = uv_width;
+ int x, y;
+ /* convert luma */
+ for (y = 0; y < y_height; ++y) {
+ uint8* const Yrow = Y + y * y_stride;
+ for (x = 0; x < y_width; ++x) {
+ /* maps [16..235] to [0..255] */
+ const int v = ((Yrow[x] - 16) * 149 + 64) >> 7;
+ Yrow[x] = (v < 0) ? 0 : (v > 255) ? 255u : v;
+ }
+ }
+ /* convert chroma */
+ for (y = 0; y < uv_height; ++y) {
+ uint8* const Urow = U + y * uv_stride;
+ uint8* const Vrow = V + y * uv_stride;
+ for (x = 0; x < uv_width; ++x) {
+ /* maps [0..255] to [16..240] */
+ const int ru = (((Urow[x] - 128) * 73) >> 6) + 128;
+ const int rv = (((Vrow[x] - 128) * 73) >> 6) + 128;
+ Urow[x] = (ru < 0) ? 0 : (ru > 255) ? 255u : ru;
+ Vrow[x] = (rv < 0) ? 0 : (rv > 255) ? 255u : rv;
+ }
+ }
+}
+
+WebPResult WebPGetInfo(const uint8* data,
+ int data_size,
+ int *width,
+ int *height) {
+ const uint32 chunk_size = SkipRiffHeader(&data, &data_size);
+
+ if (width) *width = 0;
+ if (height) *height = 0;
+
+ if (!chunk_size) {
+ return webp_failure; /* unsupported RIFF header */
+ }
+
+ /* Validate raw video data */
+ if (data_size < 10) {
+ return webp_failure; /* not enough data */
+ }
+
+ /* check signature */
+ if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a) {
+ return webp_failure; /* Wrong signature. */
+ } else {
+ const uint32 bits = data[0] | (data[1] << 8) | (data[2] << 16);
+
+ if ((bits & 1)) { /* Not a keyframe. */
+ return webp_failure;
+ } else {
+ const int profile = (bits >> 1) & 7;
+ const int show_frame = (bits >> 4) & 1;
+ const uint32 partition_length = (bits >> 5);
+
+ if (profile > 3) {
+ return webp_failure; /* unknown profile */
+ }
+ if (!show_frame) {
+ return webp_failure; /* first frame is invisible! */
+ }
+ if (partition_length >= chunk_size) {
+ return webp_failure; /* inconsistent size information. */
+ } else {
+ const int w = ((data[7] << 8) | data[6]) & 0x3fff;
+ const int h = ((data[9] << 8) | data[8]) & 0x3fff;
+ if (width) *width = w;
+ if (height) *height = h;
+
+ return webp_success;
+ }
+ }
+ }
+ return webp_failure;
+}
+#endif /* HAVE_LIBVPX */
diff --git a/ext/gd/libgd/webpimg.h b/ext/gd/libgd/webpimg.h
new file mode 100644
index 0000000000..8a05429a73
--- /dev/null
+++ b/ext/gd/libgd/webpimg.h
@@ -0,0 +1,181 @@
+/*===========================================================================*
+ - Copyright 2010 Google Inc.
+ -
+ - This code is licensed under the same terms as WebM:
+ - Software License Agreement: http://www.webmproject.org/license/software/
+ - Additional IP Rights Grant: http://www.webmproject.org/license/additional/
+ *===========================================================================*/
+
+/*
+ * Encoding/Decoding of WebP still image compression format.
+ *
+ * 1. WebPDecode: Takes an array of bytes (string) corresponding to the WebP
+ * encoded image and generates output in the YUV format with
+ * the color components U, V subsampled to 1/2 resolution along
+ * each dimension.
+ *
+ * 2. YUV420toRGBA: Converts from YUV (with color subsampling) such as produced
+ * by the WebPDecode routine into 32 bits per pixel RGBA data
+ * array. This data array can be directly used by the Leptonica
+ * Pix in-memory image format.
+ *
+ * 3. WebPEncode: Takes a Y, U, V data buffers (with color components U and V
+ * subsampled to 1/2 resolution) and generates the WebP string
+ *
+ * 4. RGBAToYUV420: Generates Y, U, V data (with color subsampling) from 32 bits
+ * per pixel RGBA data buffer. The resulting YUV data can be
+ * directly fed into the WebPEncode routine.
+ *
+ * 5. AdjustColorspace:
+ *
+ * 6. AdjustColorspaceBack:
+ */
+
+#ifndef THIRD_PARTY_VP8_VP8IMG_H_
+#define THIRD_PARTY_VP8_VP8IMG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef enum WebPResultType {
+ webp_success = 0,
+ webp_failure = -1
+} WebPResult;
+
+/* Takes an array of bytes (string) corresponding to the WebP
+ * encoded image and generates output in the YUV format with
+ * the color components U, V subsampled to 1/2 resolution along
+ * each dimension.
+ * Input:
+ * 1. data: the WebP data stream (array of bytes)
+ * 2. data_size: count of bytes in the WebP data stream
+ *
+ * Output:
+ * 3. p_Y/p_U/p_V : pointer to the Y/U/V data buffer (this routine will
+ * allocate memory for the buffer, fill the buffer with
+ * appropriate data and transfer owner ship of the buffer
+ * to caller. Caller is reponsible for freeing the memory).
+ * Note that the memory for Y, U, V buffers is alloacted
+ * in one chunk, hence one should call free(*p_Y) only.
+ * Do not try to free the U and V buffers.
+ *
+ * 6. p_width: this routine returns the width of the decoded image here
+ * 7. p_height: this routine returns the width of the decoded image here
+ * Return: success/failure
+ */
+WebPResult WebPDecode(const uint8* data,
+ int data_size,
+ uint8** p_Y,
+ uint8** p_U,
+ uint8** p_V,
+ int* p_width,
+ int* p_height);
+
+/* WebPEncode: Takes a Y, U, V data buffers (with color components U and V
+ * subsampled to 1/2 resolution) and generates the WebP string.
+ * Input:
+ * 1, 2, 3. Y, U, V: The input YUV data buffers
+ * 4, 5. y_width, y_height: The width and height of the image whose data
+ * is in Y, U, V. This matches the Y plane. The U
+ * and V planes typically have 1/2 width and
+ * height.
+ * 6. y_stride: The width (in bytes) of one row of Y data. This may not
+ * match width if there is end of row padding (e.g., for 32
+ * bit row aligment).
+ * 7. QP: the quantization parameter. This parameter controls the
+ * compression vs quality tradeoff. Use smaller numbers for better
+ * quality (compression will be lesser) and vice versa. 20 is a
+ * good optimal value.
+ * Output:
+ * 8. p_out: the output array of bytes corresponding to the encoded WebP
+ * image. This routine allocates memory for the buffer, fills it
+ * with appropriate values and transfers ownership to caller.
+ * Caller responsible for freeing of memory.
+ * Return: success/failure
+ */
+WebPResult WebPEncode(const uint8* Y,
+ const uint8* U,
+ const uint8* V,
+ int y_width,
+ int y_height,
+ int y_stride,
+ int uv_width,
+ int uv_height,
+ int uv_stride,
+ int QP,
+ unsigned char** p_out,
+ int* p_out_size_bytes,
+ double* psnr);
+
+/* Converts from YUV (with color subsampling) such as produced by the WebPDecode
+ * routine into 32 bits per pixel RGBA data array. This data array can be
+ * directly used by the Leptonica Pix in-memory image format.
+ * Input:
+ * 1, 2, 3. Y, U, V: the input data buffers
+ * 4. pixwpl: the desired words per line corresponding to the supplied
+ * output pixdata.
+ * 5. width, height: the dimensions of the image whose data resides in Y,
+ * U, V.
+ * Output:
+ * 6. pixdata: the output data buffer. Caller should allocate
+ * height * pixwpl bytes of memory before calling this routine.
+ */
+void YUV420toRGBA(uint8* Y,
+ uint8* U,
+ uint8* V,
+ int words_per_line,
+ int width,
+ int height,
+ uint32* pixdata);
+
+/* Generates Y, U, V data (with color subsampling) from 32 bits
+ * per pixel RGBA data buffer. The resulting YUV data can be directly fed into
+ * the WebPEncode routine.
+ * Input:
+ * 1. pix data input rgba data buffer
+ * 2. words per line corresponding to pixdata
+ * 3, 4. image width and height respectively
+ * Output:
+ * 5, 6, 7. Output YUV data buffers
+ */
+void RGBAToYUV420(uint32* pixdata,
+ int words_per_line,
+ int width,
+ int height,
+ uint8* Y,
+ uint8* U,
+ uint8* V);
+
+/* This function adjust from YUV420J (jpeg decoding) to YUV420 (webp input)
+ * Hints: http://en.wikipedia.org/wiki/YCbCr
+ */
+void AdjustColorspace(uint8* Y, uint8* U, uint8* V, int width, int height);
+
+/* Inverse function: convert from YUV420 to YUV420J */
+void AdjustColorspaceBack(uint8* Y, uint8* U, uint8* V, int width, int height);
+
+/* Checks WebP image header and outputs height and width information of
+ * the image
+ *
+ * Input:
+ * 1. data: the WebP data stream (array of bytes)
+ * 2. data_size: count of bytes in the WebP data stream
+ *
+ * Outut:
+ * width/height: width and height of the image
+ *
+ * Return: success/failure
+ */
+WebPResult WebPGetInfo(const uint8* data,
+ int data_size,
+ int *width,
+ int *height);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* THIRD_PARTY_VP8_VP8IMG_H_ */
diff --git a/ext/gd/php_gd.h b/ext/gd/php_gd.h
index 6121f91e98..f8433d609f 100644
--- a/ext/gd/php_gd.h
+++ b/ext/gd/php_gd.h
@@ -33,12 +33,10 @@
#if HAVE_LIBGD
/* open_basedir and safe_mode checks */
-#define PHP_GD_CHECK_OPEN_BASEDIR(filename, errormsg) \
- if (!filename || php_check_open_basedir(filename TSRMLS_CC) || \
- (PG(safe_mode) && !php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR)) \
- ) { \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, errormsg); \
- RETURN_FALSE; \
+#define PHP_GD_CHECK_OPEN_BASEDIR(filename, errormsg) \
+ if (!filename || php_check_open_basedir(filename TSRMLS_CC)) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, errormsg); \
+ RETURN_FALSE; \
}
#define PHP_GDIMG_TYPE_GIF 1
@@ -50,7 +48,8 @@
#define PHP_GDIMG_CONVERT_WBM 7
#define PHP_GDIMG_TYPE_GD 8
#define PHP_GDIMG_TYPE_GD2 9
-#define PHP_GDIMG_TYPE_GD2PART 10
+#define PHP_GDIMG_TYPE_GD2PART 10
+#define PHP_GDIMG_TYPE_WEBP 11
#ifdef PHP_WIN32
# define PHP_GD_API __declspec(dllexport)
@@ -137,6 +136,7 @@ PHP_FUNCTION(imagecreatefromstring);
PHP_FUNCTION(imagecreatefromgif);
PHP_FUNCTION(imagecreatefromjpeg);
PHP_FUNCTION(imagecreatefromxbm);
+PHP_FUNCTION(imagecreatefromwebp);
PHP_FUNCTION(imagecreatefrompng);
PHP_FUNCTION(imagecreatefromwbmp);
PHP_FUNCTION(imagecreatefromgd);
@@ -158,6 +158,7 @@ PHP_FUNCTION(imagefontheight);
PHP_FUNCTION(imagegif );
PHP_FUNCTION(imagejpeg );
PHP_FUNCTION(imagepng);
+PHP_FUNCTION(imagewebp);
PHP_FUNCTION(imagewbmp);
PHP_FUNCTION(imagegd);
PHP_FUNCTION(imagegd2);
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index 22e76d5c94..3b78ec459e 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -667,7 +667,7 @@ static inline void gmp_zval_unary_op(zval *return_value, zval **a_arg, gmp_unary
/* {{{ gmp_zval_unary_ui_op
*/
-static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_unary_ui_op_t gmp_op)
+static inline void gmp_zval_unary_ui_op(zval *return_value, zval **a_arg, gmp_unary_ui_op_t gmp_op TSRMLS_DC)
{
mpz_t *gmpnum_result;
@@ -691,7 +691,7 @@ static inline void _gmp_unary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_ui_o
return;
}
- gmp_zval_unary_ui_op(return_value, a_arg, gmp_op);
+ gmp_zval_unary_ui_op(return_value, a_arg, gmp_op TSRMLS_CC);
}
/* }}} */
@@ -960,7 +960,7 @@ ZEND_FUNCTION(gmp_mod)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &a_arg, &b_arg) == FAILURE){
return;
- }
+ }
gmp_zval_binary_ui_op_ex(return_value, a_arg, b_arg, mpz_mod, (gmp_binary_ui_op_t)mpz_mod_ui, 1, 1, 0 TSRMLS_CC);
}
@@ -1022,7 +1022,7 @@ ZEND_FUNCTION(gmp_fact)
}
}
- gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui);
+ gmp_zval_unary_ui_op(return_value, a_arg, mpz_fac_ui TSRMLS_CC);
}
/* }}} */
diff --git a/ext/gmp/tests/022-win32.phpt b/ext/gmp/tests/022-win32.phpt
deleted file mode 100644
index 7abb0e82bd..0000000000
--- a/ext/gmp/tests/022-win32.phpt
+++ /dev/null
@@ -1,90 +0,0 @@
---TEST--
-gmp_gcdext() basic tests
---SKIPIF--
-<?php if (!extension_loaded("gmp")) print "skip";
-if(substr(PHP_OS, 0, 3) != 'WIN' ) {
- die('skip windows only test');
-}
-?>
---FILE--
-<?php
-
-$n = gmp_init("34293864345");
-$n1 = gmp_init("23434293864345");
-
-$a = array(
- array(123,45),
- array(4341,9734),
- array(23487,333),
- array(-234234,-123123),
- array(-100,-2234),
- array(345,"34587345"),
- array(345,"0"),
- array("345556456",345873),
- array("34545345556456","323432445873"),
- array($n, $n1),
- );
-
-foreach ($a as $val) {
- $r = gmp_gcdext($val[0],$val[1]);
- var_dump(gmp_strval($r['g']));
- var_dump(gmp_strval($r['s']));
- var_dump(gmp_strval($r['t']));
-}
-
-var_dump(gmp_gcdext($val[0],array()));
-var_dump(gmp_gcdext(array(),array()));
-var_dump(gmp_gcdext(array(),array(),1));
-var_dump(gmp_gcdext(array()));
-var_dump(gmp_gcdext());
-
-echo "Done\n";
-?>
---EXPECTF--
-string(1) "3"
-string(2) "41"
-string(4) "-112"
-string(1) "1"
-string(4) "-805"
-string(3) "359"
-string(1) "3"
-string(2) "32"
-string(5) "-2257"
-string(4) "3003"
-string(3) "-10"
-string(2) "19"
-string(1) "2"
-string(2) "67"
-string(2) "-3"
-string(2) "15"
-string(7) "-601519"
-string(1) "6"
-string(3) "345"
-string(1) "1"
-string(1) "0"
-string(1) "1"
-string(5) "84319"
-string(9) "-84241831"
-string(1) "1"
-string(12) "167180205823"
-string(15) "-17856272782919"
-string(3) "195"
-string(15) "-23387298979862"
-string(11) "34225091793"
-
-Warning: gmp_gcdext(): Unable to convert variable to GMP - wrong type in %s on line %d
-bool(false)
-
-Warning: gmp_gcdext(): Unable to convert variable to GMP - wrong type in %s on line %d
-bool(false)
-
-Warning: gmp_gcdext() expects exactly 2 parameters, 3 given in %s on line %d
-NULL
-
-Warning: gmp_gcdext() expects exactly 2 parameters, 1 given in %s on line %d
-NULL
-
-Warning: gmp_gcdext() expects exactly 2 parameters, 0 given in %s on line %d
-NULL
-Done
-
diff --git a/ext/gmp/tests/022.phpt b/ext/gmp/tests/022.phpt
index f699e8283d..469aa3013d 100644
--- a/ext/gmp/tests/022.phpt
+++ b/ext/gmp/tests/022.phpt
@@ -2,9 +2,6 @@
gmp_gcdext() basic tests
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip";
-if (substr(PHP_OS, 0, 3) == 'WIN') {
- die('skip.. only for Non Windows Systems');
-}
?>
--FILE--
<?php
diff --git a/ext/gmp/tests/gmp_nextprime-win32.phpt b/ext/gmp/tests/gmp_nextprime-win32.phpt
deleted file mode 100644
index e725315a13..0000000000
--- a/ext/gmp/tests/gmp_nextprime-win32.phpt
+++ /dev/null
@@ -1,45 +0,0 @@
---TEST--
-gmp_nextprime()
---SKIPIF--
-<?php if (!extension_loaded("gmp")) print "skip";
-if(substr(PHP_OS, 0, 3) != 'WIN' ) {
- die('skip windows only test');
-}
-?>
---FILE--
-<?php
-
-$n = gmp_nextprime(-1);
-var_dump(gmp_strval($n));
-$n = gmp_nextprime(0);
-var_dump(gmp_strval($n));
-$n = gmp_nextprime(-1000);
-var_dump(gmp_strval($n));
-$n = gmp_nextprime(1000);
-var_dump(gmp_strval($n));
-$n = gmp_nextprime(100000);
-var_dump(gmp_strval($n));
-$n = gmp_nextprime(array());
-var_dump(gmp_strval($n));
-$n = gmp_nextprime("");
-var_dump(gmp_strval($n));
-$n = gmp_nextprime(new stdclass());
-var_dump(gmp_strval($n));
-
-echo "Done\n";
-?>
---EXPECTF--
-string(1) "2"
-string(1) "2"
-string(4) "-997"
-string(4) "1009"
-string(6) "100003"
-
-Warning: gmp_nextprime(): Unable to convert variable to GMP - wrong type in %s on line %d
-string(1) "0"
-string(1) "0"
-
-Warning: gmp_nextprime(): Unable to convert variable to GMP - wrong type in %s on line %d
-string(1) "0"
-Done
-
diff --git a/ext/gmp/tests/gmp_nextprime.phpt b/ext/gmp/tests/gmp_nextprime.phpt
index 623ccbed07..5683c8c31f 100644
--- a/ext/gmp/tests/gmp_nextprime.phpt
+++ b/ext/gmp/tests/gmp_nextprime.phpt
@@ -2,9 +2,6 @@
gmp_nextprime()
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip";
-if (substr(PHP_OS, 0, 3) == 'WIN') {
- die('skip.. only for Non Windows Systems');
-}
?>
--FILE--
<?php
diff --git a/ext/hash/config.m4 b/ext/hash/config.m4
index d8a26fd11f..79ac25e19f 100644
--- a/ext/hash/config.m4
+++ b/ext/hash/config.m4
@@ -27,11 +27,11 @@ if test "$PHP_HASH" != "no"; then
EXT_HASH_SOURCES="hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c \
hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c hash_adler32.c \
- hash_crc32.c hash_salsa.c"
+ hash_crc32.c hash_fnv.c hash_joaat.c"
EXT_HASH_HEADERS="php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h \
php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h \
- php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h php_hash_salsa.h \
- php_hash_types.h"
+ php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h \
+ php_hash_fnv.h php_hash_joaat.h php_hash_types.h"
PHP_NEW_EXTENSION(hash, $EXT_HASH_SOURCES, $ext_shared)
ifdef([PHP_INSTALL_HEADERS], [
diff --git a/ext/hash/config.w32 b/ext/hash/config.w32
index 5fc63a3c78..abe8675f30 100644
--- a/ext/hash/config.w32
+++ b/ext/hash/config.w32
@@ -15,11 +15,11 @@ if (PHP_HASH != "no") {
AC_DEFINE('HAVE_HASH_EXT', 1);
EXTENSION("hash", "hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c "
+ "hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c "
- + "hash_adler32.c hash_crc32.c hash_salsa.c");
+ + "hash_adler32.c hash_crc32.c hash_joaat.c hash_fnv.c");
PHP_INSTALL_HEADERS("ext/hash/", "php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h " +
"php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h " +
- "php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h php_hash_salsa.h " +
+ "php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h " +
"php_hash_types.h");
}
diff --git a/ext/hash/hash.c b/ext/hash/hash.c
index 4c6253140c..895d64da33 100644
--- a/ext/hash/hash.c
+++ b/ext/hash/hash.c
@@ -43,7 +43,7 @@ struct mhash_bc_entry {
int value;
};
-#define MHASH_NUM_ALGOS 29
+#define MHASH_NUM_ALGOS 34
static struct mhash_bc_entry mhash_to_hash[MHASH_NUM_ALGOS] = {
{"CRC32", "crc32", 0},
@@ -74,7 +74,12 @@ static struct mhash_bc_entry mhash_to_hash[MHASH_NUM_ALGOS] = {
{"RIPEMD320", "ripemd320", 25},
{NULL, NULL, 26}, /* support needs to be added for snefru 128 */
{"SNEFRU256", "snefru256", 27},
- {"MD2", "md2", 28}
+ {"MD2", "md2", 28},
+ {"FNV132", "fnv132", 29},
+ {"FNV1A32", "fnv1a32", 30},
+ {"FNV164", "fnv164", 31},
+ {"FNV1A64", "fnv1a64", 32},
+ {"JOAAT", "joaat", 33},
};
#endif
@@ -136,7 +141,10 @@ static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_
RETURN_FALSE;
}
if (isfilename) {
- stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL, DEFAULT_CONTEXT);
+ if (CHECK_NULL_PATH(data, data_len)) {
+ RETURN_FALSE;
+ }
+ stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT);
if (!stream) {
/* Stream will report errors opening file */
RETURN_FALSE;
@@ -214,7 +222,7 @@ static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename,
RETURN_FALSE;
}
if (isfilename) {
- stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL, DEFAULT_CONTEXT);
+ stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT);
if (!stream) {
/* Stream will report errors opening file */
RETURN_FALSE;
@@ -448,7 +456,7 @@ PHP_FUNCTION(hash_update_file)
ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
context = php_stream_context_from_zval(zcontext, 0);
- stream = php_stream_open_wrapper_ex(filename, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL, context);
+ stream = php_stream_open_wrapper_ex(filename, "rb", REPORT_ERRORS, NULL, context);
if (!stream) {
/* Stream will report errors opening file */
RETURN_FALSE;
@@ -843,8 +851,9 @@ PHP_MINIT_FUNCTION(hash)
php_hash_register_algo("adler32", &php_hash_adler32_ops);
php_hash_register_algo("crc32", &php_hash_crc32_ops);
php_hash_register_algo("crc32b", &php_hash_crc32b_ops);
- php_hash_register_algo("salsa10", &php_hash_salsa10_ops);
- php_hash_register_algo("salsa20", &php_hash_salsa20_ops);
+ php_hash_register_algo("fnv132", &php_hash_fnv132_ops);
+ php_hash_register_algo("fnv164", &php_hash_fnv164_ops);
+ php_hash_register_algo("joaat", &php_hash_joaat_ops);
PHP_HASH_HAVAL_REGISTER(3,128);
PHP_HASH_HAVAL_REGISTER(3,160);
diff --git a/ext/hash/hash_adler32.c b/ext/hash/hash_adler32.c
index fd2cb99caf..758080ca36 100644
--- a/ext/hash/hash_adler32.c
+++ b/ext/hash/hash_adler32.c
@@ -34,9 +34,16 @@ PHP_HASH_API void PHP_ADLER32Update(PHP_ADLER32_CTX *context, const unsigned cha
s[0] = context->state & 0xffff;
s[1] = (context->state >> 16) & 0xffff;
for (i = 0; i < len; ++i) {
- s[0] = (s[0] + input[i]) % 65521;
- s[1] = (s[1] + s[0]) % 65521;
+ s[0] += input[i];
+ s[1] += s[0];
+ if (s[1]>=0x7fffffff)
+ {
+ s[0] = s[0] % 65521;
+ s[1] = s[1] % 65521;
+ }
}
+ s[0] = s[0] % 65521;
+ s[1] = s[1] % 65521;
context->state = s[0] + (s[1] << 16);
}
diff --git a/ext/hash/hash_fnv.c b/ext/hash/hash_fnv.c
new file mode 100644
index 0000000000..04faabce82
--- /dev/null
+++ b/ext/hash/hash_fnv.c
@@ -0,0 +1,229 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Michael Maclean <mgdm@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+/* Based on the public domain algorithm found at
+ http://www.isthe.com/chongo/tech/comp/fnv/index.html */
+
+#include "php_hash.h"
+#include "php_hash_fnv.h"
+
+const php_hash_ops php_hash_fnv132_ops = {
+ (php_hash_init_func_t) PHP_FNV132Init,
+ (php_hash_update_func_t) PHP_FNV132Update,
+ (php_hash_final_func_t) PHP_FNV132Final,
+ (php_hash_copy_func_t) php_hash_copy,
+ 4,
+ 4,
+ sizeof(PHP_FNV132_CTX)
+};
+
+ const php_hash_ops php_hash_fnv1a32_ops = {
+ (php_hash_init_func_t) PHP_FNV132Init,
+ (php_hash_update_func_t) PHP_FNV1a32Update,
+ (php_hash_final_func_t) PHP_FNV132Final,
+ (php_hash_copy_func_t) php_hash_copy,
+ 4,
+ 4,
+ sizeof(PHP_FNV132_CTX)
+};
+
+const php_hash_ops php_hash_fnv164_ops = {
+ (php_hash_init_func_t) PHP_FNV164Init,
+ (php_hash_update_func_t) PHP_FNV164Update,
+ (php_hash_final_func_t) PHP_FNV164Final,
+ (php_hash_copy_func_t) php_hash_copy,
+ 8,
+ 4,
+ sizeof(PHP_FNV164_CTX)
+};
+
+const php_hash_ops php_hash_fnv1a64_ops = {
+ (php_hash_init_func_t) PHP_FNV164Init,
+ (php_hash_update_func_t) PHP_FNV1a64Update,
+ (php_hash_final_func_t) PHP_FNV164Final,
+ (php_hash_copy_func_t) php_hash_copy,
+ 8,
+ 4,
+ sizeof(PHP_FNV164_CTX)
+};
+
+/* {{{ PHP_FNV132Init
+ * 32-bit FNV-1 hash initialisation
+ */
+PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context)
+{
+ context->state = PHP_FNV1_32_INIT;
+}
+/* }}} */
+
+PHP_HASH_API void PHP_FNV132Update(PHP_FNV132_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ context->state = fnv_32_buf((void *)input, inputLen, context->state, 0);
+}
+
+PHP_HASH_API void PHP_FNV1a32Update(PHP_FNV132_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ context->state = fnv_32_buf((void *)input, inputLen, context->state, 1);
+}
+
+PHP_HASH_API void PHP_FNV132Final(unsigned char digest[4], PHP_FNV132_CTX * context)
+{
+#ifdef WORDS_BIGENDIAN
+ memcpy(digest, &context->state, 4);
+#else
+ int i = 0;
+ unsigned char *c = (unsigned char *) &context->state;
+
+ for (i = 0; i < 4; i++) {
+ digest[i] = c[3 - i];
+ }
+#endif
+}
+
+/* {{{ PHP_FNV164Init
+ * 64-bit FNV-1 hash initialisation
+ */
+PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context)
+{
+ context->state = PHP_FNV1_64_INIT;
+}
+/* }}} */
+
+PHP_HASH_API void PHP_FNV164Update(PHP_FNV164_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ context->state = fnv_64_buf((void *)input, inputLen, context->state, 0);
+}
+
+PHP_HASH_API void PHP_FNV1a64Update(PHP_FNV164_CTX *context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ context->state = fnv_64_buf((void *)input, inputLen, context->state, 1);
+}
+
+PHP_HASH_API void PHP_FNV164Final(unsigned char digest[8], PHP_FNV164_CTX * context)
+{
+#ifdef WORDS_BIGENDIAN
+ memcpy(digest, &context->state, 8);
+#else
+ int i = 0;
+ unsigned char *c = (unsigned char *) &context->state;
+
+ for (i = 0; i < 8; i++) {
+ digest[i] = c[7 - i];
+ }
+#endif
+}
+
+
+/*
+ * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ * hval - previous hash value or 0 if first call
+ * alternate - if > 0 use the alternate version
+ *
+ * returns:
+ * 32 bit hash as a static hash type
+ */
+static php_hash_uint32
+fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate)
+{
+ unsigned char *bp = (unsigned char *)buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
+
+ /*
+ * FNV-1 hash each octet in the buffer
+ */
+ while (bp < be) {
+
+ if (alternate == 0) {
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+ hval *= PHP_FNV_32_PRIME;
+
+ /* xor the bottom with the current octet */
+ hval ^= (php_hash_uint32)*bp++;
+ } else {
+ /* xor the bottom with the current octet */
+ hval ^= (php_hash_uint32)*bp++;
+
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+ hval *= PHP_FNV_32_PRIME;
+ }
+ }
+
+ /* return our new hash value */
+ return hval;
+}
+
+/*
+ * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ * hval - previous hash value or 0 if first call
+ * alternate - if > 0 use the alternate version
+ *
+ * returns:
+ * 64 bit hash as a static hash type
+ */
+static php_hash_uint64
+fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate)
+{
+ unsigned char *bp = (unsigned char *)buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
+
+ /*
+ * FNV-1 hash each octet of the buffer
+ */
+ while (bp < be) {
+
+ if (alternate == 0) {
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+ hval *= PHP_FNV_64_PRIME;
+
+ /* xor the bottom with the current octet */
+ hval ^= (php_hash_uint64)*bp++;
+ } else {
+ /* xor the bottom with the current octet */
+ hval ^= (php_hash_uint64)*bp++;
+
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+ hval *= PHP_FNV_64_PRIME;
+ }
+ }
+
+ /* return our new hash value */
+ return hval;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/hash/hash_joaat.c b/ext/hash/hash_joaat.c
new file mode 100644
index 0000000000..f6395dd991
--- /dev/null
+++ b/ext/hash/hash_joaat.c
@@ -0,0 +1,99 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Martin Jansen <mj@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+/* Implements Jenkins's one-at-a-time hashing algorithm as presented on
+ * http://www.burtleburtle.net/bob/hash/doobs.html.
+ */
+
+#include "php_hash.h"
+#include "php_hash_joaat.h"
+
+const php_hash_ops php_hash_joaat_ops = {
+ (php_hash_init_func_t) PHP_JOAATInit,
+ (php_hash_update_func_t) PHP_JOAATUpdate,
+ (php_hash_final_func_t) PHP_JOAATFinal,
+ (php_hash_copy_func_t) php_hash_copy,
+ 4,
+ 4,
+ sizeof(PHP_JOAAT_CTX)
+};
+
+PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context)
+{
+ context->state = 0;
+}
+
+PHP_HASH_API void PHP_JOAATUpdate(PHP_JOAAT_CTX *context, const unsigned char *input, unsigned int inputLen)
+{
+ context->state = joaat_buf((void *)input, inputLen, context->state);
+}
+
+PHP_HASH_API void PHP_JOAATFinal(unsigned char digest[4], PHP_JOAAT_CTX * context)
+{
+#ifdef WORDS_BIGENDIAN
+ memcpy(digest, &context->state, 4);
+#else
+ int i = 0;
+ unsigned char *c = (unsigned char *) &context->state;
+
+ for (i = 0; i < 4; i++) {
+ digest[i] = c[3 - i];
+ }
+#endif
+ context->state = 0;
+}
+
+/*
+ * joaat_buf - perform a Jenkins's one-at-a-time hash on a buffer
+ *
+ * input:
+ * buf - start of buffer to hash
+ * len - length of buffer in octets
+ *
+ * returns:
+ * 32 bit hash as a static hash type
+ */
+static php_hash_uint32
+joaat_buf(void *buf, size_t len, php_hash_uint32 hval)
+{
+ size_t i;
+ unsigned char *input = (unsigned char *)buf;
+
+ for (i = 0; i < len; i++) {
+ hval += input[i];
+ hval += (hval << 10);
+ hval ^= (hval >> 6);
+ }
+
+ hval += (hval << 3);
+ hval ^= (hval >> 11);
+ hval += (hval << 15);
+
+ return hval;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/hash/hash_md.c b/ext/hash/hash_md.c
index aa09618968..647ac561e2 100644
--- a/ext/hash/hash_md.c
+++ b/ext/hash/hash_md.c
@@ -144,11 +144,11 @@ PHP_NAMED_FUNCTION(php_if_md5_file)
int n;
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
return;
}
- stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
+ stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
if (!stream) {
RETURN_FALSE;
}
diff --git a/ext/hash/hash_salsa.c b/ext/hash/hash_salsa.c
deleted file mode 100644
index 1532dfdcba..0000000000
--- a/ext/hash/hash_salsa.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Michael Wallner <mike@php.net> |
- | Sara Golemon <pollita@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-#include "php_hash.h"
-#include "php_hash_salsa.h"
-
-#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
-
-/* {{{ Salsa10
-
- The 64-byte input x to Salsa10 is viewed in little-endian form as 16 integers
- x0, x1, x2, ..., x15 in {0,1,...,2^32-1}. These 16 integers are fed through
- 320 invertible modifications, where each modification changes one integer.
- The modifications involve, overall,
-
- * 10 additions of constants modulo 2^32;
- * 320 more additions modulo 2^32;
- * 80 ``or'' operations;
- * 240 ``xor'' operations; and
- * 320 constant-distance rotations.
-
- The resulting 16 integers are added to the original x0, x1, x2, ..., x15
- respectively modulo 2^32, producing, in little-endian form, the 64-byte output
- Salsa10(x).
-
- D.J.Bernstein
-*/
-static void Salsa10(php_hash_uint32 x[16], php_hash_uint32 in[16])
-{
- int i;
-
- for (i = 10; i > 0; --i) {
- x[ 4] ^= R(x[ 0]+x[12], 6); x[ 8] ^= R(x[ 4]+x[ 0],17);
- x[12] += R(x[ 8]|x[ 4],16); x[ 0] += R(x[12]^x[ 8], 5);
- x[ 9] += R(x[ 5]|x[ 1], 8); x[13] += R(x[ 9]|x[ 5], 7);
- x[ 1] ^= R(x[13]+x[ 9],17); x[ 5] += R(x[ 1]^x[13],12);
- x[14] ^= R(x[10]+x[ 6], 7); x[ 2] += R(x[14]^x[10],15);
- x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],15);
- x[ 3] += R(x[15]|x[11],20); x[ 7] ^= R(x[ 3]+x[15],16);
- x[11] += R(x[ 7]^x[ 3], 7); x[15] += R(x[11]^x[ 7], 8);
- x[ 1] += R(x[ 0]|x[ 3], 8)^i;x[ 2] ^= R(x[ 1]+x[ 0],14);
- x[ 3] ^= R(x[ 2]+x[ 1], 6); x[ 0] += R(x[ 3]^x[ 2],18);
- x[ 6] += R(x[ 5]^x[ 4], 8); x[ 7] += R(x[ 6]^x[ 5],12);
- x[ 4] += R(x[ 7]|x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],15);
- x[11] ^= R(x[10]+x[ 9],18); x[ 8] += R(x[11]^x[10],11);
- x[ 9] ^= R(x[ 8]+x[11], 8); x[10] += R(x[ 9]|x[ 8], 6);
- x[12] += R(x[15]^x[14],17); x[13] ^= R(x[12]+x[15],15);
- x[14] += R(x[13]|x[12], 9); x[15] += R(x[14]^x[13], 7);
- }
- for (i = 0; i < 16; ++i) {
- x[i] += in[i];
- }
-}
-/* }}} */
-
-/* {{{ Salsa20
-
- The 64-byte input x to Salsa20 is viewed in little-endian form as 16 words
- x0, x1, x2, ..., x15 in {0,1,...,2^32-1}. These 16 words are fed through 320
- invertible modifications, where each modification changes one word. The
- resulting 16 words are added to the original x0, x1, x2, ..., x15 respectively
- modulo 2^32, producing, in little-endian form, the 64-byte output Salsa20(x).
-
- Each modification involves xor'ing into one word a rotated version of the sum
- of two other words modulo 2^32. Thus the 320 modifications involve, overall,
- 320 additions, 320 xor's, and 320 rotations. The rotations are all by constant
- distances.
-
- The entire series of modifications is a series of 10 identical double-rounds.
- Each double-round is a series of 2 rounds. Each round is a set of 4 parallel
- quarter-rounds. Each quarter-round modifies 4 words.
-
- D.J.Bernstein
-*/
-static void Salsa20(php_hash_uint32 x[16], php_hash_uint32 in[16])
-{
- int i;
-
- for (i = 20; i > 0; i -= 2) {
- x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
- x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
- x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
- x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
- x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
- x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
- x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
- x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
- x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
- x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
- x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
- x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
- x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
- x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
- x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
- x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
- }
- for (i = 0; i < 16; ++i) {
- x[i] += in[i];
- }
-}
-/* }}} */
-
-static inline void SalsaTransform(PHP_SALSA_CTX *context, const unsigned char input[64])
-{
- php_hash_uint32 i, j, a[16];
-
-#if 0
- fprintf(stderr, "> INPUT: %.*s\n", 64, input);
-#endif
-
- for (i = 0, j = 0; j < 64; i++, j += 4) {
- a[i] = ((php_hash_uint32) input[j + 3]) | (((php_hash_uint32) input[j + 2]) << 8) |
- (((php_hash_uint32) input[j + 1]) << 16) | (((php_hash_uint32) input[j]) << 24);
- }
-
- if (!context->init) {
- memcpy(context->state, a, sizeof(a));
- context->init = 1;
- }
-
- context->Transform(context->state, a);
- memset(a, 0, sizeof(a));
-}
-
-PHP_HASH_API void PHP_SALSA10Init(PHP_SALSA_CTX *context)
-{
- memset(context, 0, sizeof(*context));
- context->Transform = Salsa10;
-}
-
-PHP_HASH_API void PHP_SALSA20Init(PHP_SALSA_CTX *context)
-{
- memset(context, 0, sizeof(*context));
- context->Transform = Salsa20;
-}
-
-PHP_HASH_API void PHP_SALSAUpdate(PHP_SALSA_CTX *context, const unsigned char *input, size_t len)
-{
- if (context->length + len < 64) {
- memcpy(&context->buffer[context->length], input, len);
- context->length += len;
- } else {
- size_t i = 0, r = (context->length + len) % 64;
-
- if (context->length) {
- i = 64 - context->length;
- memcpy(&context->buffer[context->length], input, i);
- SalsaTransform(context, context->buffer);
- memset(context->buffer, 0, 64);
- }
-
- for (; i + 64 <= len; i += 64) {
- SalsaTransform(context, input + i);
- }
-
- memcpy(context->buffer, input + i, r);
- context->length = r;
- }
-}
-
-PHP_HASH_API void PHP_SALSAFinal(unsigned char digest[64], PHP_SALSA_CTX *context)
-{
- php_hash_uint32 i, j;
-
- if (context->length) {
- SalsaTransform(context, context->buffer);
- }
-
- for (i = 0, j = 0; j < 64; i++, j += 4) {
- digest[j] = (unsigned char) ((context->state[i] >> 24) & 0xff);
- digest[j + 1] = (unsigned char) ((context->state[i] >> 16) & 0xff);
- digest[j + 2] = (unsigned char) ((context->state[i] >> 8) & 0xff);
- digest[j + 3] = (unsigned char) (context->state[i] & 0xff);
- }
-
- memset(context, 0, sizeof(*context));
-}
-
-const php_hash_ops php_hash_salsa10_ops = {
- (php_hash_init_func_t) PHP_SALSA10Init,
- (php_hash_update_func_t) PHP_SALSAUpdate,
- (php_hash_final_func_t) PHP_SALSAFinal,
- (php_hash_copy_func_t) php_hash_copy,
- 64,
- 64,
- sizeof(PHP_SALSA_CTX)
-};
-
-const php_hash_ops php_hash_salsa20_ops = {
- (php_hash_init_func_t) PHP_SALSA20Init,
- (php_hash_update_func_t) PHP_SALSAUpdate,
- (php_hash_final_func_t) PHP_SALSAFinal,
- (php_hash_copy_func_t) php_hash_copy,
- 64,
- 64,
- sizeof(PHP_SALSA_CTX)
-};
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
diff --git a/ext/hash/hash_sha.c b/ext/hash/hash_sha.c
index 61c950543d..908f9a8ede 100644
--- a/ext/hash/hash_sha.c
+++ b/ext/hash/hash_sha.c
@@ -128,11 +128,11 @@ PHP_FUNCTION(sha1_file)
int n;
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
return;
}
- stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
+ stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
if (!stream) {
RETURN_FALSE;
}
diff --git a/ext/hash/hash_tiger.c b/ext/hash/hash_tiger.c
index 40188ebee0..bd1d79bb92 100644
--- a/ext/hash/hash_tiger.c
+++ b/ext/hash/hash_tiger.c
@@ -120,7 +120,7 @@
{ \
register php_hash_uint64 a, b, c, tmpa, x0, x1, x2, x3, x4, x5, x6, x7; \
php_hash_uint64 aa, bb, cc; \
- int pass_no; \
+ unsigned int pass_no; \
\
a = state[0]; \
b = state[1]; \
@@ -169,6 +169,15 @@ static inline void TigerFinalize(PHP_TIGER_CTX *context)
tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state);
}
+static inline void TigerDigest(unsigned char *digest_str, unsigned int digest_len, PHP_TIGER_CTX *context)
+{
+ unsigned int i;
+
+ for (i = 0; i < digest_len; ++i) {
+ digest_str[i] = (unsigned char) ((context->state[i/8] >> (8 * (i%8))) & 0xff);
+ }
+}
+
PHP_HASH_API void PHP_3TIGERInit(PHP_TIGER_CTX *context)
{
memset(context, 0, sizeof(*context));
@@ -216,84 +225,21 @@ PHP_HASH_API void PHP_TIGERUpdate(PHP_TIGER_CTX *context, const unsigned char *i
PHP_HASH_API void PHP_TIGER128Final(unsigned char digest[16], PHP_TIGER_CTX *context)
{
TigerFinalize(context);
-
- digest[0] = (unsigned char) ((context->state[0] >> 56) & 0xff);
- digest[1] = (unsigned char) ((context->state[0] >> 48) & 0xff);
- digest[2] = (unsigned char) ((context->state[0] >> 40) & 0xff);
- digest[3] = (unsigned char) ((context->state[0] >> 32) & 0xff);
- digest[4] = (unsigned char) ((context->state[0] >> 24) & 0xff);
- digest[5] = (unsigned char) ((context->state[0] >> 16) & 0xff);
- digest[6] = (unsigned char) ((context->state[0] >> 8) & 0xff);
- digest[7] = (unsigned char) (context->state[0] & 0xff);
- digest[8] = (unsigned char) ((context->state[1] >> 56) & 0xff);
- digest[9] = (unsigned char) ((context->state[1] >> 48) & 0xff);
- digest[10] = (unsigned char) ((context->state[1] >> 40) & 0xff);
- digest[11] = (unsigned char) ((context->state[1] >> 32) & 0xff);
- digest[12] = (unsigned char) ((context->state[1] >> 24) & 0xff);
- digest[13] = (unsigned char) ((context->state[1] >> 16) & 0xff);
- digest[14] = (unsigned char) ((context->state[1] >> 8) & 0xff);
- digest[15] = (unsigned char) (context->state[1] & 0xff);
-
+ TigerDigest(digest, 16, context);
memset(context, 0, sizeof(*context));
}
PHP_HASH_API void PHP_TIGER160Final(unsigned char digest[20], PHP_TIGER_CTX *context)
{
TigerFinalize(context);
-
- digest[0] = (unsigned char) ((context->state[0] >> 56) & 0xff);
- digest[1] = (unsigned char) ((context->state[0] >> 48) & 0xff);
- digest[2] = (unsigned char) ((context->state[0] >> 40) & 0xff);
- digest[3] = (unsigned char) ((context->state[0] >> 32) & 0xff);
- digest[4] = (unsigned char) ((context->state[0] >> 24) & 0xff);
- digest[5] = (unsigned char) ((context->state[0] >> 16) & 0xff);
- digest[6] = (unsigned char) ((context->state[0] >> 8) & 0xff);
- digest[7] = (unsigned char) (context->state[0] & 0xff);
- digest[8] = (unsigned char) ((context->state[1] >> 56) & 0xff);
- digest[9] = (unsigned char) ((context->state[1] >> 48) & 0xff);
- digest[10] = (unsigned char) ((context->state[1] >> 40) & 0xff);
- digest[11] = (unsigned char) ((context->state[1] >> 32) & 0xff);
- digest[12] = (unsigned char) ((context->state[1] >> 24) & 0xff);
- digest[13] = (unsigned char) ((context->state[1] >> 16) & 0xff);
- digest[14] = (unsigned char) ((context->state[1] >> 8) & 0xff);
- digest[15] = (unsigned char) (context->state[1] & 0xff);
- digest[16] = (unsigned char) ((context->state[2] >> 56) & 0xff);
- digest[17] = (unsigned char) ((context->state[2] >> 48) & 0xff);
- digest[18] = (unsigned char) ((context->state[2] >> 40) & 0xff);
- digest[19] = (unsigned char) ((context->state[2] >> 32) & 0xff);
-
+ TigerDigest(digest, 20, context);
memset(context, 0, sizeof(*context));
}
PHP_HASH_API void PHP_TIGER192Final(unsigned char digest[24], PHP_TIGER_CTX *context)
{
TigerFinalize(context);
-
- digest[0] = (unsigned char) ((context->state[0] >> 56) & 0xff);
- digest[1] = (unsigned char) ((context->state[0] >> 48) & 0xff);
- digest[2] = (unsigned char) ((context->state[0] >> 40) & 0xff);
- digest[3] = (unsigned char) ((context->state[0] >> 32) & 0xff);
- digest[4] = (unsigned char) ((context->state[0] >> 24) & 0xff);
- digest[5] = (unsigned char) ((context->state[0] >> 16) & 0xff);
- digest[6] = (unsigned char) ((context->state[0] >> 8) & 0xff);
- digest[7] = (unsigned char) (context->state[0] & 0xff);
- digest[8] = (unsigned char) ((context->state[1] >> 56) & 0xff);
- digest[9] = (unsigned char) ((context->state[1] >> 48) & 0xff);
- digest[10] = (unsigned char) ((context->state[1] >> 40) & 0xff);
- digest[11] = (unsigned char) ((context->state[1] >> 32) & 0xff);
- digest[12] = (unsigned char) ((context->state[1] >> 24) & 0xff);
- digest[13] = (unsigned char) ((context->state[1] >> 16) & 0xff);
- digest[14] = (unsigned char) ((context->state[1] >> 8) & 0xff);
- digest[15] = (unsigned char) (context->state[1] & 0xff);
- digest[16] = (unsigned char) ((context->state[2] >> 56) & 0xff);
- digest[17] = (unsigned char) ((context->state[2] >> 48) & 0xff);
- digest[18] = (unsigned char) ((context->state[2] >> 40) & 0xff);
- digest[19] = (unsigned char) ((context->state[2] >> 32) & 0xff);
- digest[20] = (unsigned char) ((context->state[2] >> 24) & 0xff);
- digest[21] = (unsigned char) ((context->state[2] >> 16) & 0xff);
- digest[22] = (unsigned char) ((context->state[2] >> 8) & 0xff);
- digest[23] = (unsigned char) (context->state[2] & 0xff);
-
+ TigerDigest(digest, 24, context);
memset(context, 0, sizeof(*context));
}
diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h
index 6accb6db3c..87050cb8e5 100644
--- a/ext/hash/php_hash.h
+++ b/ext/hash/php_hash.h
@@ -78,8 +78,9 @@ extern const php_hash_ops php_hash_gost_ops;
extern const php_hash_ops php_hash_adler32_ops;
extern const php_hash_ops php_hash_crc32_ops;
extern const php_hash_ops php_hash_crc32b_ops;
-extern const php_hash_ops php_hash_salsa10_ops;
-extern const php_hash_ops php_hash_salsa20_ops;
+extern const php_hash_ops php_hash_fnv132_ops;
+extern const php_hash_ops php_hash_fnv164_ops;
+extern const php_hash_ops php_hash_joaat_ops;
#define PHP_HASH_HAVAL_OPS(p,b) extern const php_hash_ops php_hash_##p##haval##b##_ops;
diff --git a/ext/hash/php_hash_fnv.h b/ext/hash/php_hash_fnv.h
new file mode 100644
index 0000000000..ab91b7045a
--- /dev/null
+++ b/ext/hash/php_hash_fnv.h
@@ -0,0 +1,79 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Michael Maclean <mgdm@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_HASH_FNV_H
+#define PHP_HASH_FNV_H
+
+#define PHP_FNV1_32_INIT ((php_hash_uint32)0x811c9dc5)
+#define PHP_FNV1_32A_INIT PHP_FNV1_32_INIT
+
+#define PHP_FNV_32_PRIME ((php_hash_uint32)0x01000193)
+
+#define PHP_FNV1_64_INIT ((php_hash_uint64)0xcbf29ce484222325ULL)
+#define PHP_FNV1A_64_INIT FNV1_64_INIT
+
+#define PHP_FNV_64_PRIME ((php_hash_uint64)0x100000001b3ULL)
+
+
+/*
+ * hash types
+ */
+enum php_fnv_type {
+ PHP_FNV_NONE = 0, /* invalid FNV hash type */
+ PHP_FNV0_32 = 1, /* FNV-0 32 bit hash */
+ PHP_FNV1_32 = 2, /* FNV-1 32 bit hash */
+ PHP_FNV1a_32 = 3, /* FNV-1a 32 bit hash */
+ PHP_FNV0_64 = 4, /* FNV-0 64 bit hash */
+ PHP_FNV1_64 = 5, /* FNV-1 64 bit hash */
+ PHP_FNV1a_64 = 6, /* FNV-1a 64 bit hash */
+};
+
+typedef struct {
+ php_hash_uint32 state;
+} PHP_FNV132_CTX;
+
+typedef struct {
+ php_hash_uint64 state;
+} PHP_FNV164_CTX;
+
+
+PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context);
+PHP_HASH_API void PHP_FNV132Update(PHP_FNV132_CTX *context, const unsigned char *input, unsigned int inputLen);
+PHP_HASH_API void PHP_FNV1a32Update(PHP_FNV132_CTX *context, const unsigned char *input, unsigned int inputLen);
+PHP_HASH_API void PHP_FNV132Final(unsigned char digest[16], PHP_FNV132_CTX * context);
+
+PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context);
+PHP_HASH_API void PHP_FNV164Update(PHP_FNV164_CTX *context, const unsigned char *input, unsigned int inputLen);
+PHP_HASH_API void PHP_FNV1a64Update(PHP_FNV164_CTX *context, const unsigned char *input, unsigned int inputLen);
+PHP_HASH_API void PHP_FNV164Final(unsigned char digest[16], PHP_FNV164_CTX * context);
+
+static php_hash_uint32 fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate);
+static php_hash_uint64 fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/main/safe_mode.h b/ext/hash/php_hash_joaat.h
index 2b21960c4a..e54ae62904 100644
--- a/main/safe_mode.h
+++ b/ext/hash/php_hash_joaat.h
@@ -12,30 +12,32 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: |
+ | Author: Martin Jansen <mj@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id$ */
+/* $Id*/
-#ifndef SAFE_MODE_H
-#define SAFE_MODE_H
+#ifndef PHP_HASH_JOAAT_H
+#define PHP_HASH_JOAAT_H
-/* mode's for php_checkuid() */
-#define CHECKUID_DISALLOW_FILE_NOT_EXISTS 0
-#define CHECKUID_ALLOW_FILE_NOT_EXISTS 1
-#define CHECKUID_CHECK_FILE_AND_DIR 2
-#define CHECKUID_ALLOW_ONLY_DIR 3
-#define CHECKUID_CHECK_MODE_PARAM 4
-#define CHECKUID_ALLOW_ONLY_FILE 5
+typedef struct {
+ php_hash_uint32 state;
+} PHP_JOAAT_CTX;
-/* flags for php_checkuid_ex() */
-#define CHECKUID_NO_ERRORS 0x01
+PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context);
+PHP_HASH_API void PHP_JOAATUpdate(PHP_JOAAT_CTX *context, const unsigned char *input, unsigned int inputLen);
+PHP_HASH_API void PHP_JOAATFinal(unsigned char digest[16], PHP_JOAAT_CTX * context);
-BEGIN_EXTERN_C()
-PHPAPI int php_checkuid(const char *filename, const char *fopen_mode, int mode);
-PHPAPI int php_checkuid_ex(const char *filename, const char *fopen_mode, int mode, int flags);
-PHPAPI char *php_get_current_user(void);
-END_EXTERN_C()
+static php_hash_uint32 joaat_buf(void *buf, size_t len, php_hash_uint32 hval);
#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/hash/tests/fnv132.phpt b/ext/hash/tests/fnv132.phpt
new file mode 100644
index 0000000000..051386ab75
--- /dev/null
+++ b/ext/hash/tests/fnv132.phpt
@@ -0,0 +1,202 @@
+--TEST--
+FNV
+--SKIPIF--
+<?php extension_loaded('hash') or die ('Skip - hash extension not available'); ?>
+--FILE--
+<?php
+
+function R10($t) {
+ return str_repeat($t, 10);
+}
+
+function R500($t) {
+ return str_repeat($t, 500);
+}
+
+$tests = array(
+ array( "", "811c9dc5" ),
+ array( "a", "050c5d7e" ),
+ array( "b", "050c5d7d" ),
+ array( "c", "050c5d7c" ),
+ array( "d", "050c5d7b" ),
+ array( "e", "050c5d7a" ),
+ array( "f", "050c5d79" ),
+ array( "fo", "6b772514" ),
+ array( "foo", "408f5e13" ),
+ array( "foob", "b4b1178b" ),
+ array( "fooba", "fdc80fb0" ),
+ array( "foobar", "31f0b262" ),
+ array( "\0", "050c5d1f" ),
+ array( "a\0", "70772d5a" ),
+ array( "b\0", "6f772bc7" ),
+ array( "c\0", "6e772a34" ),
+ array( "d\0", "6d7728a1" ),
+ array( "e\0", "6c77270e" ),
+ array( "f\0", "6b77257b" ),
+ array( "fo\0", "408f5e7c" ),
+ array( "foo\0", "b4b117e9" ),
+ array( "foob\0", "fdc80fd1" ),
+ array( "fooba\0", "31f0b210" ),
+ array( "foobar\0", "ffe8d046" ),
+ array( "ch", "6e772a5c" ),
+ array( "cho", "4197aebb" ),
+ array( "chon", "fcc8100f" ),
+ array( "chong", "fdf147fa" ),
+ array( "chongo", "bcd44ee1" ),
+ array( "chongo ", "23382c13" ),
+ array( "chongo w", "846d619e" ),
+ array( "chongo wa", "1630abdb" ),
+ array( "chongo was", "c99e89b2" ),
+ array( "chongo was ", "1692c316" ),
+ array( "chongo was h", "9f091bca" ),
+ array( "chongo was he", "2556be9b" ),
+ array( "chongo was her", "628e0e73" ),
+ array( "chongo was here", "98a0bf6c" ),
+ array( "chongo was here!", "b10d5725" ),
+ array( "chongo was here!\n", "dd002f35" ),
+ array( "ch\0", "4197aed4" ),
+ array( "cho\0", "fcc81061" ),
+ array( "chon\0", "fdf1479d" ),
+ array( "chong\0", "bcd44e8e" ),
+ array( "chongo\0", "23382c33" ),
+ array( "chongo \0", "846d61e9" ),
+ array( "chongo w\0", "1630abba" ),
+ array( "chongo wa\0", "c99e89c1" ),
+ array( "chongo was\0", "1692c336" ),
+ array( "chongo was \0", "9f091ba2" ),
+ array( "chongo was h\0", "2556befe" ),
+ array( "chongo was he\0", "628e0e01" ),
+ array( "chongo was her\0", "98a0bf09" ),
+ array( "chongo was here\0", "b10d5704" ),
+ array( "chongo was here!\0", "dd002f3f" ),
+ array( "chongo was here!\n\0", "1c4a506f" ),
+ array( "cu", "6e772a41" ),
+ array( "cur", "26978421" ),
+ array( "curd", "e184ff97" ),
+ array( "curds", "9b5e5ac6" ),
+ array( "curds ", "5b88e592" ),
+ array( "curds a", "aa8164b7" ),
+ array( "curds an", "20b18c7b" ),
+ array( "curds and", "f28025c5" ),
+ array( "curds and ", "84bb753f" ),
+ array( "curds and w", "3219925a" ),
+ array( "curds and wh", "384163c6" ),
+ array( "curds and whe", "54f010d7" ),
+ array( "curds and whey", "8cea820c" ),
+ array( "curds and whey\n", "e12ab8ee" ),
+ array( "cu\0", "26978453" ),
+ array( "cur\0", "e184fff3" ),
+ array( "curd\0", "9b5e5ab5" ),
+ array( "curds\0", "5b88e5b2" ),
+ array( "curds \0", "aa8164d6" ),
+ array( "curds a\0", "20b18c15" ),
+ array( "curds an\0", "f28025a1" ),
+ array( "curds and\0", "84bb751f" ),
+ array( "curds and \0", "3219922d" ),
+ array( "curds and w\0", "384163ae" ),
+ array( "curds and wh\0", "54f010b2" ),
+ array( "curds and whe\0", "8cea8275" ),
+ array( "curds and whey\0", "e12ab8e4" ),
+ array( "curds and whey\n\0", "64411eaa" ),
+ array( "line 1\nline 2\nline 3", "31ae8f83" ),
+ array( "chongo <Landon Curt Noll> /\\../\\", "995fa9c4" ),
+ array( "chongo <Landon Curt Noll> /\\../\\\0", "35983f8c" ),
+ array( "chongo (Landon Curt Noll) /\\../\\", "5036a251" ),
+ array( "chongo (Landon Curt Noll) /\\../\\\0", "97018583" ),
+ array( "http://antwrp.gsfc.nasa.gov/apod/astropix.html", "b4448d60" ),
+ array( "http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash", "025dfe59" ),
+ array( "http://epod.usra.edu/", "c5eab3af" ),
+ array( "http://exoplanet.eu/", "7d21ba1e" ),
+ array( "http://hvo.wr.usgs.gov/cam3/", "7704cddb" ),
+ array( "http://hvo.wr.usgs.gov/cams/HMcam/", "d0071bfe" ),
+ array( "http://hvo.wr.usgs.gov/kilauea/update/deformation.html", "0ff3774c" ),
+ array( "http://hvo.wr.usgs.gov/kilauea/update/images.html", "b0fea0ea" ),
+ array( "http://hvo.wr.usgs.gov/kilauea/update/maps.html", "58177303" ),
+ array( "http://hvo.wr.usgs.gov/volcanowatch/current_issue.html", "4f599cda" ),
+ array( "http://neo.jpl.nasa.gov/risk/", "3e590a47" ),
+ array( "http://norvig.com/21-days.html", "965595f8" ),
+ array( "http://primes.utm.edu/curios/home.php", "c37f178d" ),
+ array( "http://slashdot.org/", "9711dd26" ),
+ array( "http://tux.wr.usgs.gov/Maps/155.25-19.5.html", "23c99b7f" ),
+ array( "http://volcano.wr.usgs.gov/kilaueastatus.php", "6e568b17" ),
+ array( "http://www.avo.alaska.edu/activity/Redoubt.php", "43f0245b" ),
+ array( "http://www.dilbert.com/fast/", "bcb7a001" ),
+ array( "http://www.fourmilab.ch/gravitation/orbits/", "12e6dffe" ),
+ array( "http://www.fpoa.net/", "0792f2d6" ),
+ array( "http://www.ioccc.org/index.html", "b966936b" ),
+ array( "http://www.isthe.com/cgi-bin/number.cgi", "46439ac5" ),
+ array( "http://www.isthe.com/chongo/bio.html", "728d49af" ),
+ array( "http://www.isthe.com/chongo/index.html", "d33745c9" ),
+ array( "http://www.isthe.com/chongo/src/calc/lucas-calc", "bc382a57" ),
+ array( "http://www.isthe.com/chongo/tech/astro/venus2004.html", "4bda1d31" ),
+ array( "http://www.isthe.com/chongo/tech/astro/vita.html", "ce35ccae" ),
+ array( "http://www.isthe.com/chongo/tech/comp/c/expert.html", "3b6eed94" ),
+ array( "http://www.isthe.com/chongo/tech/comp/calc/index.html", "445c9c58" ),
+ array( "http://www.isthe.com/chongo/tech/comp/fnv/index.html", "3db8bf9d" ),
+ array( "http://www.isthe.com/chongo/tech/math/number/howhigh.html", "2dee116d" ),
+ array( "http://www.isthe.com/chongo/tech/math/number/number.html", "c18738da" ),
+ array( "http://www.isthe.com/chongo/tech/math/prime/mersenne.html", "5b156176" ),
+ array( "http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest", "2aa7d593" ),
+ array( "http://www.lavarnd.org/cgi-bin/corpspeak.cgi", "b2409658" ),
+ array( "http://www.lavarnd.org/cgi-bin/haiku.cgi", "e1489528" ),
+ array( "http://www.lavarnd.org/cgi-bin/rand-none.cgi", "fe1ee07e" ),
+ array( "http://www.lavarnd.org/cgi-bin/randdist.cgi", "e8842315" ),
+ array( "http://www.lavarnd.org/index.html", "3a6a63a2" ),
+ array( "http://www.lavarnd.org/what/nist-test.html", "06d2c18c" ),
+ array( "http://www.macosxhints.com/", "f8ef7225" ),
+ array( "http://www.mellis.com/", "843d3300" ),
+ array( "http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm", "bb24f7ae" ),
+ array( "http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm", "878c0ec9" ),
+ array( "http://www.paulnoll.com/", "b557810f" ),
+ array( "http://www.pepysdiary.com/", "57423246" ),
+ array( "http://www.sciencenews.org/index/home/activity/view", "87f7505e" ),
+ array( "http://www.skyandtelescope.com/", "bb809f20" ),
+ array( "http://www.sput.nl/~rob/sirius.html", "8932abb5" ),
+ array( "http://www.systemexperts.com/", "0a9b3aa0" ),
+ array( "http://www.tq-international.com/phpBB3/index.php", "b8682a24" ),
+ array( "http://www.travelquesttours.com/index.htm", "a7ac1c56" ),
+ array( "http://www.wunderground.com/global/stations/89606.html", "11409252" ),
+ array( R10("21701"), "a987f517" ),
+ array( R10("M21701"), "f309e7ed" ),
+ array( R10("2^21701-1"), "c9e8f417" ),
+ array( R10("\x54\xc5"), "7f447bdd" ),
+ array( R10("\xc5\x54"), "b929adc5" ),
+ array( R10("23209"), "57022879" ),
+ array( R10("M23209"), "dcfd2c49" ),
+ array( R10("2^23209-1"), "6edafff5" ),
+ array( R10("\x5a\xa9"), "f04fb1f1" ),
+ array( R10("\xa9\x5a"), "fb7de8b9" ),
+ array( R10("391581216093"), "c5f1d7e9" ),
+ array( R10("391581*2^216093-1"), "32c1f439" ),
+ array( R10("\x05\xf9\x9d\x03\x4c\x81"), "7fd3eb7d" ),
+ array( R10("FEDCBA9876543210"), "81597da5" ),
+ array( R10("\xfe\xdc\xba\x98\x76\x54\x32\x10"), "05eb7a25" ),
+ array( R10("EFCDAB8967452301"), "9c0fa1b5" ),
+ array( R10("\xef\xcd\xab\x89\x67\x45\x23\x01"), "53ccb1c5" ),
+ array( R10("0123456789ABCDEF"), "fabece15" ),
+ array( R10("\x01\x23\x45\x67\x89\xab\xcd\xef"), "4ad745a5" ),
+ array( R10("1032547698BADCFE"), "e5bdc495" ),
+ array( R10("\x10\x32\x54\x76\x98\xba\xdc\xfe"), "23b3c0a5" ),
+ array( R500("\x00"), "fa823dd5" ),
+ array( R500("\x07"), "0c6c58b9" ),
+ array( R500("~"), "e2dbccd5" ),
+ array( R500("\x7f"), "db7f50f9" ),
+);
+
+$i = 0;
+$pass = true;
+foreach($tests as $test) {
+ $result = hash('fnv132', $test[0]);
+ if ($result != $test[1]) {
+ echo "Iteration " . $i . " failed - expected '" . $test[1] . "', got '" . $result . "' for '" . $test[1] . "'\n";
+ $pass = false;
+ }
+ $i++;
+}
+
+if($pass) {
+ echo "PASS";
+}
+?>
+--EXPECT--
+PASS
diff --git a/ext/hash/tests/fnv164.phpt b/ext/hash/tests/fnv164.phpt
new file mode 100644
index 0000000000..b5e69420a6
--- /dev/null
+++ b/ext/hash/tests/fnv164.phpt
@@ -0,0 +1,202 @@
+--TEST--
+FNV
+--SKIPIF--
+<?php extension_loaded('hash') or die ('Skip - hash extension not available'); ?>
+--FILE--
+<?php
+
+function R10($t) {
+ return str_repeat($t, 10);
+}
+
+function R500($t) {
+ return str_repeat($t, 500);
+}
+
+$tests = array(
+ array( "", "cbf29ce484222325" ),
+ array( "a", "af63bd4c8601b7be" ),
+ array( "b", "af63bd4c8601b7bd" ),
+ array( "c", "af63bd4c8601b7bc" ),
+ array( "d", "af63bd4c8601b7bb" ),
+ array( "e", "af63bd4c8601b7ba" ),
+ array( "f", "af63bd4c8601b7b9" ),
+ array( "fo", "08326207b4eb2f34" ),
+ array( "foo", "d8cbc7186ba13533" ),
+ array( "foob", "0378817ee2ed65cb" ),
+ array( "fooba", "d329d59b9963f790" ),
+ array( "foobar", "340d8765a4dda9c2" ),
+ array( "\0", "af63bd4c8601b7df" ),
+ array( "a\0", "08326707b4eb37da" ),
+ array( "b\0", "08326607b4eb3627" ),
+ array( "c\0", "08326507b4eb3474" ),
+ array( "d\0", "08326407b4eb32c1" ),
+ array( "e\0", "08326307b4eb310e" ),
+ array( "f\0", "08326207b4eb2f5b" ),
+ array( "fo\0", "d8cbc7186ba1355c" ),
+ array( "foo\0", "0378817ee2ed65a9" ),
+ array( "foob\0", "d329d59b9963f7f1" ),
+ array( "fooba\0", "340d8765a4dda9b0" ),
+ array( "foobar\0", "50a6d3b724a774a6" ),
+ array( "ch", "08326507b4eb341c" ),
+ array( "cho", "d8d5c8186ba98bfb" ),
+ array( "chon", "1ccefc7ef118dbef" ),
+ array( "chong", "0c92fab3ad3db77a" ),
+ array( "chongo", "9b77794f5fdec421" ),
+ array( "chongo ", "0ac742dfe7874433" ),
+ array( "chongo w", "d7dad5766ad8e2de" ),
+ array( "chongo wa", "a1bb96378e897f5b" ),
+ array( "chongo was", "5b3f9b6733a367d2" ),
+ array( "chongo was ", "b07ce25cbea969f6" ),
+ array( "chongo was h", "8d9e9997f9df0d6a" ),
+ array( "chongo was he", "838c673d9603cb7b" ),
+ array( "chongo was her", "8b5ee8a5e872c273" ),
+ array( "chongo was here", "4507c4e9fb00690c" ),
+ array( "chongo was here!", "4c9ca59581b27f45" ),
+ array( "chongo was here!\n", "e0aca20b624e4235" ),
+ array( "ch\0", "d8d5c8186ba98b94" ),
+ array( "cho\0", "1ccefc7ef118db81" ),
+ array( "chon\0", "0c92fab3ad3db71d" ),
+ array( "chong\0", "9b77794f5fdec44e" ),
+ array( "chongo\0", "0ac742dfe7874413" ),
+ array( "chongo \0", "d7dad5766ad8e2a9" ),
+ array( "chongo w\0", "a1bb96378e897f3a" ),
+ array( "chongo wa\0", "5b3f9b6733a367a1" ),
+ array( "chongo was\0", "b07ce25cbea969d6" ),
+ array( "chongo was \0", "8d9e9997f9df0d02" ),
+ array( "chongo was h\0", "838c673d9603cb1e" ),
+ array( "chongo was he\0", "8b5ee8a5e872c201" ),
+ array( "chongo was her\0", "4507c4e9fb006969" ),
+ array( "chongo was here\0", "4c9ca59581b27f64" ),
+ array( "chongo was here!\0", "e0aca20b624e423f" ),
+ array( "chongo was here!\n\0", "13998e580afa800f" ),
+ array( "cu", "08326507b4eb3401" ),
+ array( "cur", "d8d5ad186ba95dc1" ),
+ array( "curd", "1c72e17ef0ca4e97" ),
+ array( "curds", "2183c1b327c38ae6" ),
+ array( "curds ", "b66d096c914504f2" ),
+ array( "curds a", "404bf57ad8476757" ),
+ array( "curds an", "887976bd815498bb" ),
+ array( "curds and", "3afd7f02c2bf85a5" ),
+ array( "curds and ", "fc4476b0eb70177f" ),
+ array( "curds and w", "186d2da00f77ecba" ),
+ array( "curds and wh", "f97140fa48c74066" ),
+ array( "curds and whe", "a2b1cf49aa926d37" ),
+ array( "curds and whey", "0690712cd6cf940c" ),
+ array( "curds and whey\n", "f7045b3102b8906e" ),
+ array( "cu\0", "d8d5ad186ba95db3" ),
+ array( "cur\0", "1c72e17ef0ca4ef3" ),
+ array( "curd\0", "2183c1b327c38a95" ),
+ array( "curds\0", "b66d096c914504d2" ),
+ array( "curds \0", "404bf57ad8476736" ),
+ array( "curds a\0", "887976bd815498d5" ),
+ array( "curds an\0", "3afd7f02c2bf85c1" ),
+ array( "curds and\0", "fc4476b0eb70175f" ),
+ array( "curds and \0", "186d2da00f77eccd" ),
+ array( "curds and w\0", "f97140fa48c7400e" ),
+ array( "curds and wh\0", "a2b1cf49aa926d52" ),
+ array( "curds and whe\0", "0690712cd6cf9475" ),
+ array( "curds and whey\0", "f7045b3102b89064" ),
+ array( "curds and whey\n\0", "74f762479f9d6aea" ),
+ array( "line 1\nline 2\nline 3", "a64e5f36c9e2b0e3" ),
+ array( "chongo <Landon Curt Noll> /\\../\\", "8fd0680da3088a04" ),
+ array( "chongo <Landon Curt Noll> /\\../\\\0", "67aad32c078284cc" ),
+ array( "chongo (Landon Curt Noll) /\\../\\", "b37d55d81c57b331" ),
+ array( "chongo (Landon Curt Noll) /\\../\\\0", "55ac0f3829057c43" ),
+ array( "http://antwrp.gsfc.nasa.gov/apod/astropix.html", "cb27f4b8e1b6cc20" ),
+ array( "http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash", "26caf88bcbef2d19" ),
+ array( "http://epod.usra.edu/", "8e6e063b97e61b8f" ),
+ array( "http://exoplanet.eu/", "b42750f7f3b7c37e" ),
+ array( "http://hvo.wr.usgs.gov/cam3/", "f3c6ba64cf7ca99b" ),
+ array( "http://hvo.wr.usgs.gov/cams/HMcam/", "ebfb69b427ea80fe" ),
+ array( "http://hvo.wr.usgs.gov/kilauea/update/deformation.html", "39b50c3ed970f46c" ),
+ array( "http://hvo.wr.usgs.gov/kilauea/update/images.html", "5b9b177aa3eb3e8a" ),
+ array( "http://hvo.wr.usgs.gov/kilauea/update/maps.html", "6510063ecf4ec903" ),
+ array( "http://hvo.wr.usgs.gov/volcanowatch/current_issue.html", "2b3bbd2c00797c7a" ),
+ array( "http://neo.jpl.nasa.gov/risk/", "f1d6204ff5cb4aa7" ),
+ array( "http://norvig.com/21-days.html", "4836e27ccf099f38" ),
+ array( "http://primes.utm.edu/curios/home.php", "82efbb0dd073b44d" ),
+ array( "http://slashdot.org/", "4a80c282ffd7d4c6" ),
+ array( "http://tux.wr.usgs.gov/Maps/155.25-19.5.html", "305d1a9c9ee43bdf" ),
+ array( "http://volcano.wr.usgs.gov/kilaueastatus.php", "15c366948ffc6997" ),
+ array( "http://www.avo.alaska.edu/activity/Redoubt.php", "80153ae218916e7b" ),
+ array( "http://www.dilbert.com/fast/", "fa23e2bdf9e2a9e1" ),
+ array( "http://www.fourmilab.ch/gravitation/orbits/", "d47e8d8a2333c6de" ),
+ array( "http://www.fpoa.net/", "7e128095f688b056" ),
+ array( "http://www.ioccc.org/index.html", "2f5356890efcedab" ),
+ array( "http://www.isthe.com/cgi-bin/number.cgi", "95c2b383014f55c5" ),
+ array( "http://www.isthe.com/chongo/bio.html", "4727a5339ce6070f" ),
+ array( "http://www.isthe.com/chongo/index.html", "b0555ecd575108e9" ),
+ array( "http://www.isthe.com/chongo/src/calc/lucas-calc", "48d785770bb4af37" ),
+ array( "http://www.isthe.com/chongo/tech/astro/venus2004.html", "09d4701c12af02b1" ),
+ array( "http://www.isthe.com/chongo/tech/astro/vita.html", "79f031e78f3cf62e" ),
+ array( "http://www.isthe.com/chongo/tech/comp/c/expert.html", "52a1ee85db1b5a94" ),
+ array( "http://www.isthe.com/chongo/tech/comp/calc/index.html", "6bd95b2eb37fa6b8" ),
+ array( "http://www.isthe.com/chongo/tech/comp/fnv/index.html", "74971b7077aef85d" ),
+ array( "http://www.isthe.com/chongo/tech/math/number/howhigh.html", "b4e4fae2ffcc1aad" ),
+ array( "http://www.isthe.com/chongo/tech/math/number/number.html", "2bd48bd898b8f63a" ),
+ array( "http://www.isthe.com/chongo/tech/math/prime/mersenne.html", "e9966ac1556257f6" ),
+ array( "http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest", "92a3d1cd078ba293" ),
+ array( "http://www.lavarnd.org/cgi-bin/corpspeak.cgi", "f81175a482e20ab8" ),
+ array( "http://www.lavarnd.org/cgi-bin/haiku.cgi", "5bbb3de722e73048" ),
+ array( "http://www.lavarnd.org/cgi-bin/rand-none.cgi", "6b4f363492b9f2be" ),
+ array( "http://www.lavarnd.org/cgi-bin/randdist.cgi", "c2d559df73d59875" ),
+ array( "http://www.lavarnd.org/index.html", "f75f62284bc7a8c2" ),
+ array( "http://www.lavarnd.org/what/nist-test.html", "da8dd8e116a9f1cc" ),
+ array( "http://www.macosxhints.com/", "bdc1e6ab76057885" ),
+ array( "http://www.mellis.com/", "fec6a4238a1224a0" ),
+ array( "http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm", "c03f40f3223e290e" ),
+ array( "http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm", "1ed21673466ffda9" ),
+ array( "http://www.paulnoll.com/", "df70f906bb0dd2af" ),
+ array( "http://www.pepysdiary.com/", "f3dcda369f2af666" ),
+ array( "http://www.sciencenews.org/index/home/activity/view", "9ebb11573cdcebde" ),
+ array( "http://www.skyandtelescope.com/", "81c72d9077fedca0" ),
+ array( "http://www.sput.nl/~rob/sirius.html", "0ec074a31be5fb15" ),
+ array( "http://www.systemexperts.com/", "2a8b3280b6c48f20" ),
+ array( "http://www.tq-international.com/phpBB3/index.php", "fd31777513309344" ),
+ array( "http://www.travelquesttours.com/index.htm", "194534a86ad006b6" ),
+ array( "http://www.wunderground.com/global/stations/89606.html", "3be6fdf46e0cfe12" ),
+ array( R10("21701"), "017cc137a07eb057" ),
+ array( R10("M21701"), "9428fc6e7d26b54d" ),
+ array( R10("2^21701-1"), "9aaa2e3603ef8ad7" ),
+ array( R10("\x54\xc5"), "82c6d3f3a0ccdf7d" ),
+ array( R10("\xc5\x54"), "c86eeea00cf09b65" ),
+ array( R10("23209"), "705f8189dbb58299" ),
+ array( R10("M23209"), "415a7f554391ca69" ),
+ array( R10("2^23209-1"), "cfe3d49fa2bdc555" ),
+ array( R10("\x5a\xa9"), "f0f9c56039b25191" ),
+ array( R10("\xa9\x5a"), "7075cb6abd1d32d9" ),
+ array( R10("391581216093"), "43c94e2c8b277509" ),
+ array( R10("391581*2^216093-1"), "3cbfd4e4ea670359" ),
+ array( R10("\x05\xf9\x9d\x03\x4c\x81"), "c05887810f4d019d" ),
+ array( R10("FEDCBA9876543210"), "14468ff93ac22dc5" ),
+ array( R10("\xfe\xdc\xba\x98\x76\x54\x32\x10"), "ebed699589d99c05" ),
+ array( R10("EFCDAB8967452301"), "6d99f6df321ca5d5" ),
+ array( R10("\xef\xcd\xab\x89\x67\x45\x23\x01"), "0cd410d08c36d625" ),
+ array( R10("0123456789ABCDEF"), "ef1b2a2c86831d35" ),
+ array( R10("\x01\x23\x45\x67\x89\xab\xcd\xef"), "3b349c4d69ee5f05" ),
+ array( R10("1032547698BADCFE"), "55248ce88f45f035" ),
+ array( R10("\x10\x32\x54\x76\x98\xba\xdc\xfe"), "aa69ca6a18a4c885" ),
+ array( R500("\x00"), "1fe3fce62bd816b5" ),
+ array( R500("\x07"), "0289a488a8df69d9" ),
+ array( R500("~"), "15e96e1613df98b5" ),
+ array( R500("\x7f"), "e6be57375ad89b99" ),
+);
+
+$i = 0;
+$pass = true;
+foreach($tests as $test) {
+ $result = hash('fnv164', $test[0]);
+ if ($result != $test[1]) {
+ echo "Iteration " . $i . " failed - expected '" . $test[1] . "', got '" . $result . "' for '" . $test[1] . "'\n";
+ $pass = false;
+ }
+ $i++;
+}
+
+if($pass) {
+ echo "PASS";
+}
+?>
+--EXPECT--
+PASS
diff --git a/ext/hash/tests/hash_algos.phpt b/ext/hash/tests/hash_algos.phpt
index 9818dfc958..55796ecbce 100644
--- a/ext/hash/tests/hash_algos.phpt
+++ b/ext/hash/tests/hash_algos.phpt
@@ -18,90 +18,92 @@ var_dump(hash_algos());
===Done===
--EXPECTF--
*** Testing hash_algos() : basic functionality ***
-array(42) {
- [0]=>
+array(43) {
+ [%d]=>
string(3) "md2"
- [1]=>
+ [%d]=>
string(3) "md4"
- [2]=>
+ [%d]=>
string(3) "md5"
- [3]=>
+ [%d]=>
string(4) "sha1"
- [4]=>
+ [%d]=>
string(6) "sha224"
- [5]=>
+ [%d]=>
string(6) "sha256"
- [6]=>
+ [%d]=>
string(6) "sha384"
- [7]=>
+ [%d]=>
string(6) "sha512"
- [8]=>
+ [%d]=>
string(9) "ripemd128"
- [9]=>
+ [%d]=>
string(9) "ripemd160"
- [10]=>
+ [%d]=>
string(9) "ripemd256"
- [11]=>
+ [%d]=>
string(9) "ripemd320"
- [12]=>
+ [%d]=>
string(9) "whirlpool"
- [13]=>
+ [%d]=>
string(10) "tiger128,3"
- [14]=>
+ [%d]=>
string(10) "tiger160,3"
- [15]=>
+ [%d]=>
string(10) "tiger192,3"
- [16]=>
+ [%d]=>
string(10) "tiger128,4"
- [17]=>
+ [%d]=>
string(10) "tiger160,4"
- [18]=>
+ [%d]=>
string(10) "tiger192,4"
- [19]=>
+ [%d]=>
string(6) "snefru"
- [20]=>
+ [%d]=>
string(9) "snefru256"
- [21]=>
+ [%d]=>
string(4) "gost"
- [22]=>
+ [%d]=>
string(7) "adler32"
- [23]=>
+ [%d]=>
string(5) "crc32"
- [24]=>
+ [%d]=>
string(6) "crc32b"
- [25]=>
- string(7) "salsa10"
- [26]=>
- string(7) "salsa20"
- [27]=>
+ [%d]=>
+ string(6) "fnv132"
+ [%d]=>
+ string(6) "fnv164"
+ [%d]=>
+ string(5) "joaat"
+ [%d]=>
string(10) "haval128,3"
- [28]=>
+ [%d]=>
string(10) "haval160,3"
- [29]=>
+ [%d]=>
string(10) "haval192,3"
- [30]=>
+ [%d]=>
string(10) "haval224,3"
- [31]=>
+ [%d]=>
string(10) "haval256,3"
- [32]=>
+ [%d]=>
string(10) "haval128,4"
- [33]=>
+ [%d]=>
string(10) "haval160,4"
- [34]=>
+ [%d]=>
string(10) "haval192,4"
- [35]=>
+ [%d]=>
string(10) "haval224,4"
- [36]=>
+ [%d]=>
string(10) "haval256,4"
- [37]=>
+ [%d]=>
string(10) "haval128,5"
- [38]=>
+ [%d]=>
string(10) "haval160,5"
- [39]=>
+ [%d]=>
string(10) "haval192,5"
- [40]=>
+ [%d]=>
string(10) "haval224,5"
- [41]=>
+ [%d]=>
string(10) "haval256,5"
}
===Done=== \ No newline at end of file
diff --git a/ext/hash/tests/hash_copy_001.phpt b/ext/hash/tests/hash_copy_001.phpt
index 35d50a5cd9..638b7f5fc1 100644
--- a/ext/hash/tests/hash_copy_001.phpt
+++ b/ext/hash/tests/hash_copy_001.phpt
@@ -8,6 +8,7 @@ hash_copy() basic tests
$algos = hash_algos();
foreach ($algos as $algo) {
+ var_dump($algo);
$orig = hash_init($algo);
hash_update($orig, b"I can't remember anything");
$copy = hash_copy($orig);
@@ -17,6 +18,7 @@ foreach ($algos as $algo) {
}
foreach ($algos as $algo) {
+ var_dump($algo);
$orig = hash_init($algo);
hash_update($orig, b"I can't remember anything");
$copy = hash_copy($orig);
@@ -29,172 +31,262 @@ foreach ($algos as $algo) {
echo "Done\n";
?>
--EXPECTF--
+string(3) "md2"
string(32) "d5ac4ffd08f6a57b9bd402b8068392ff"
string(32) "d5ac4ffd08f6a57b9bd402b8068392ff"
+string(3) "md4"
string(32) "302c45586b53a984bd3a1237cb81c15f"
string(32) "302c45586b53a984bd3a1237cb81c15f"
+string(3) "md5"
string(32) "e35759f6ea35db254e415b5332269435"
string(32) "e35759f6ea35db254e415b5332269435"
+string(4) "sha1"
string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15"
string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15"
+string(6) "sha224"
string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29"
string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29"
+string(6) "sha256"
string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba"
string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba"
+string(6) "sha384"
string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3"
string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3"
+string(6) "sha512"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
+string(9) "ripemd128"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
+string(9) "ripemd160"
string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269"
string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269"
+string(9) "ripemd256"
string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2"
string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2"
+string(9) "ripemd320"
string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6"
string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6"
+string(9) "whirlpool"
string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082"
string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082"
-string(32) "a92be6c58be7688dc6cf9585a47aa625"
-string(32) "a92be6c58be7688dc6cf9585a47aa625"
-string(40) "a92be6c58be7688dc6cf9585a47aa62535fc2482"
-string(40) "a92be6c58be7688dc6cf9585a47aa62535fc2482"
-string(48) "a92be6c58be7688dc6cf9585a47aa62535fc2482e0e5d12c"
-string(48) "a92be6c58be7688dc6cf9585a47aa62535fc2482e0e5d12c"
-string(32) "32fb748ef5a36ca222511bcb99b044ee"
-string(32) "32fb748ef5a36ca222511bcb99b044ee"
-string(40) "32fb748ef5a36ca222511bcb99b044ee1d740bf3"
-string(40) "32fb748ef5a36ca222511bcb99b044ee1d740bf3"
-string(48) "32fb748ef5a36ca222511bcb99b044ee1d740bf300593703"
-string(48) "32fb748ef5a36ca222511bcb99b044ee1d740bf300593703"
+string(10) "tiger128,3"
+string(32) "8d68e78bc5e62ba925a67aa48595cfc6"
+string(32) "8d68e78bc5e62ba925a67aa48595cfc6"
+string(10) "tiger160,3"
+string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0"
+string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0"
+string(10) "tiger192,3"
+string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35"
+string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35"
+string(10) "tiger128,4"
+string(32) "a26ca3f58e74fb32ee44b099cb1b5122"
+string(32) "a26ca3f58e74fb32ee44b099cb1b5122"
+string(10) "tiger160,4"
+string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900"
+string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900"
+string(10) "tiger192,4"
+string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d"
+string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d"
+string(6) "snefru"
string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26"
string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26"
+string(9) "snefru256"
string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26"
string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26"
+string(4) "gost"
string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5"
string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5"
+string(7) "adler32"
string(8) "6f7c0928"
string(8) "6f7c0928"
+string(5) "crc32"
string(8) "e5cfc160"
string(8) "e5cfc160"
+string(6) "crc32b"
string(8) "69147a4e"
string(8) "69147a4e"
-string(128) "aa39bc97c2bbcb0d79bbebfddca0bf8d769c7919c9e537e456efb5fc67f33f161758dd9da3ddcec7bbbd9c04553a03f74d2dbd26175dd75c353e9300674caa4e"
-string(128) "aa39bc97c2bbcb0d79bbebfddca0bf8d769c7919c9e537e456efb5fc67f33f161758dd9da3ddcec7bbbd9c04553a03f74d2dbd26175dd75c353e9300674caa4e"
-string(128) "2ecbea42273e1e18affc7ef028674c8e55f9382f36de21e5fc38af76e4a7231d0a92feca9bdf586ac18d8a5bdd82be8a1cb1e9186871d6ff785c76a9090ac774"
-string(128) "2ecbea42273e1e18affc7ef028674c8e55f9382f36de21e5fc38af76e4a7231d0a92feca9bdf586ac18d8a5bdd82be8a1cb1e9186871d6ff785c76a9090ac774"
+string(6) "fnv132"
+string(8) "98139504"
+string(8) "98139504"
+string(6) "fnv164"
+string(16) "14522659f8138684"
+string(16) "14522659f8138684"
+string(5) "joaat"
+string(8) "aaebf370"
+string(8) "aaebf370"
+string(10) "haval128,3"
string(32) "86362472c8895e68e223ef8b3711d8d9"
string(32) "86362472c8895e68e223ef8b3711d8d9"
+string(10) "haval160,3"
string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4"
string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4"
+string(10) "haval192,3"
string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47"
string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47"
+string(10) "haval224,3"
string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2"
string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2"
+string(10) "haval256,3"
string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239"
string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239"
+string(10) "haval128,4"
string(32) "ee44418e0195a0c4a35d112722919a9c"
string(32) "ee44418e0195a0c4a35d112722919a9c"
+string(10) "haval160,4"
string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1"
string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1"
+string(10) "haval192,4"
string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db"
string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db"
+string(10) "haval224,4"
string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200"
string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200"
+string(10) "haval256,4"
string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061"
string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061"
+string(10) "haval128,5"
string(32) "8d0b157828328ae7d34d60b4b60c1dab"
string(32) "8d0b157828328ae7d34d60b4b60c1dab"
+string(10) "haval160,5"
string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3"
string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3"
+string(10) "haval192,5"
string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7"
string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7"
+string(10) "haval224,5"
string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234"
string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234"
+string(10) "haval256,5"
string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a"
string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a"
+string(3) "md2"
string(32) "d5ac4ffd08f6a57b9bd402b8068392ff"
string(32) "5c36f61062d091a8324991132c5e8dbd"
+string(3) "md4"
string(32) "302c45586b53a984bd3a1237cb81c15f"
string(32) "1d4196526aada3506efb4c7425651584"
+string(3) "md5"
string(32) "e35759f6ea35db254e415b5332269435"
string(32) "f255c114bd6ce94aad092b5141c00d46"
+string(4) "sha1"
string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15"
string(40) "a273396f056554dcd491b5dea1e7baa3b89b802b"
+string(6) "sha224"
string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29"
string(56) "1aee028400c56ceb5539625dc2f395abf491409336ca0f3e177a50e2"
+string(6) "sha256"
string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba"
string(64) "268e7f4cf88504a53fd77136c4c4748169f46ff7150b376569ada9c374836944"
+string(6) "sha384"
string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3"
string(96) "0d44981d04bb11b1ef75d5c2932bd0aa2785e7bc454daac954d77e2ca10047879b58997533fc99650b20049c6cb9a6cc"
+string(6) "sha512"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2"
+string(9) "ripemd128"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(32) "f95f5e22b8875ee0c48219ae97f0674b"
+string(9) "ripemd160"
string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269"
string(40) "900d615c1abe714e340f4ecd6a3d65599fd30ff4"
+string(9) "ripemd256"
string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2"
string(64) "b9799db40d1af5614118c329169cdcd2c718db6af03bf945ea7f7ba72b8e14f4"
+string(9) "ripemd320"
string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6"
string(80) "d6d12c1fca7a9c4a59c1be4f40188e92a746a035219e0a6ca1ee53b36a8282527187f7dffaa57ecc"
+string(9) "whirlpool"
string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082"
string(128) "e8c6a921e7d8eac2fd21d4df6054bb27a02321b2beb5b01b6f88c40706164e64d67ec97519bf76c8af8df896745478b78d42a0159f1a0db16777771fd9d420dc"
-string(32) "a92be6c58be7688dc6cf9585a47aa625"
-string(32) "dc80d448032c9da9f1e0262985353c0f"
-string(40) "a92be6c58be7688dc6cf9585a47aa62535fc2482"
-string(40) "dc80d448032c9da9f1e0262985353c0fe37e9551"
-string(48) "a92be6c58be7688dc6cf9585a47aa62535fc2482e0e5d12c"
-string(48) "dc80d448032c9da9f1e0262985353c0fe37e9551165c82e1"
-string(32) "32fb748ef5a36ca222511bcb99b044ee"
-string(32) "e5c4212432c0e266e581d4ee6a8e20a9"
-string(40) "32fb748ef5a36ca222511bcb99b044ee1d740bf3"
-string(40) "e5c4212432c0e266e581d4ee6a8e20a9d0d944e3"
-string(48) "32fb748ef5a36ca222511bcb99b044ee1d740bf300593703"
-string(48) "e5c4212432c0e266e581d4ee6a8e20a9d0d944e34804b0c4"
+string(10) "tiger128,3"
+string(32) "8d68e78bc5e62ba925a67aa48595cfc6"
+string(32) "a99d2c0348d480dc0f3c35852926e0f1"
+string(10) "tiger160,3"
+string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0"
+string(40) "a99d2c0348d480dc0f3c35852926e0f1e1825c16"
+string(10) "tiger192,3"
+string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35"
+string(48) "a99d2c0348d480dc0f3c35852926e0f1e1825c1651957ee3"
+string(10) "tiger128,4"
+string(32) "a26ca3f58e74fb32ee44b099cb1b5122"
+string(32) "66e2c0322421c4e5a9208e6aeed481e5"
+string(10) "tiger160,4"
+string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900"
+string(40) "66e2c0322421c4e5a9208e6aeed481e5c4b00448"
+string(10) "tiger192,4"
+string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d"
+string(48) "66e2c0322421c4e5a9208e6aeed481e5c4b00448e344d9d0"
+string(6) "snefru"
string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26"
string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0"
+string(9) "snefru256"
string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26"
string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0"
+string(4) "gost"
string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5"
string(64) "a00961e371287c71c527a41c14564f13b6ed12ac7cd9d5f5dfb3542a25e28d3b"
+string(7) "adler32"
string(8) "6f7c0928"
string(8) "d9141747"
+string(5) "crc32"
string(8) "e5cfc160"
string(8) "59f8d3d2"
+string(6) "crc32b"
string(8) "69147a4e"
string(8) "3ee63999"
-string(128) "aa39bc97c2bbcb0d79bbebfddca0bf8d769c7919c9e537e456efb5fc67f33f161758dd9da3ddcec7bbbd9c04553a03f74d2dbd26175dd75c353e9300674caa4e"
-string(128) "709b9196710f035e3602649fdae94f939775fa6a5a0bf01f9884d8af54579cafa01a81ee23d511b85d7fb11c4d827e4309953e3c844b8d66a80c57b6eaf2d8c1"
-string(128) "2ecbea42273e1e18affc7ef028674c8e55f9382f36de21e5fc38af76e4a7231d0a92feca9bdf586ac18d8a5bdd82be8a1cb1e9186871d6ff785c76a9090ac774"
-string(128) "272fd2209f237b9be674eb4917eda0bd978908d56190e62aec283585d6325d8fcbba2b616dd7ba90f93cc5ecdede7185d17a06467b2a17b5c836ee115974ca20"
+string(6) "fnv132"
+string(8) "98139504"
+string(8) "59ad036f"
+string(6) "fnv164"
+string(16) "14522659f8138684"
+string(16) "5e8c64fba6a5ffcf"
+string(5) "joaat"
+string(8) "aaebf370"
+string(8) "513479b4"
+string(10) "haval128,3"
string(32) "86362472c8895e68e223ef8b3711d8d9"
string(32) "ebeeeb05c18af1e53d2d127b561d5e0d"
+string(10) "haval160,3"
string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4"
string(40) "f1a2c9604fb40899ad502abe0dfcec65115c8a9a"
+string(10) "haval192,3"
string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47"
string(48) "d3a7315773a326678208650ed02510ed96cd488d74cd5231"
+string(10) "haval224,3"
string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2"
string(56) "6d7132fabc83c9ab7913748b79ecf10e25409569d3ed144177f46731"
+string(10) "haval256,3"
string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239"
string(64) "7a469868ad4b92891a3a44524c58a2b8d0f3bebb92b4cf47d19bc6aba973eb95"
+string(10) "haval128,4"
string(32) "ee44418e0195a0c4a35d112722919a9c"
string(32) "6ecddb39615f43fd211839287ff38461"
+string(10) "haval160,4"
string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1"
string(40) "bcd2e7821723ac22e122b8b7cbbd2daaa9a862df"
+string(10) "haval192,4"
string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db"
string(48) "ae74619a88dcec1fbecde28e27f009a65ecc12170824d2cd"
+string(10) "haval224,4"
string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200"
string(56) "fdaba6563f1334d40de24e311f14b324577f97c3b78b9439c408cdca"
+string(10) "haval256,4"
string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061"
string(64) "289a2ba4820218bdb25a6534fbdf693f9de101362584fdd41e32244c719caa37"
+string(10) "haval128,5"
string(32) "8d0b157828328ae7d34d60b4b60c1dab"
string(32) "ffa7993a4e183b245263fb1f63e27343"
+string(10) "haval160,5"
string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3"
string(40) "375ee5ab3a9bd07a1dbe5d071e07b2afb3165e3b"
+string(10) "haval192,5"
string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7"
string(48) "c650585f93c6e041e835caedc621f8c42d8bc6829fb76789"
+string(10) "haval224,5"
string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234"
string(56) "bc674d465a822817d939f19b38edde083fe5668759836c203c56e3e4"
+string(10) "haval256,5"
string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a"
string(64) "da70ad9bd09ed7c9675329ea2b5279d57761807c7aeac6340d94b5d494809457"
Done
diff --git a/ext/hash/tests/hash_file_basic1.phpt b/ext/hash/tests/hash_file_basic1.phpt
index 0e177e909a..339d237f06 100644
--- a/ext/hash/tests/hash_file_basic1.phpt
+++ b/ext/hash/tests/hash_file_basic1.phpt
@@ -77,7 +77,7 @@ sha256: a0f5702fa5d3670b80033d668e8732b70550392abb53841355447f8bb0f72245
sha384: a35d875ed96d94b6452acad910f97978200faa2398d8a0e6b9cffa33704c3809e3d2e5b0d63700d8f32a0716e7d2d528
sha512: 1f42adaf938fbf136e381b164bae5f984c7f9fe60c82728bd889c14f187c7d63e81a0305a1731c7e0a8f3ed9fd2ec92a3833a93502bdf269532601f0b8e2bab0
snefru: d414b2345d3e7fa1a31c044cf334bfc1fec24d89e464411998d579d24663895f
-tiger192,3: c6fa75a0be4ecf7afa3cafb4e2a08efc3a40534c0e46b971
+tiger192,3: 7acf4ebea075fac6fc8ea0e2b4af3cfa71b9460e4c53403a
whirlpool: 4248b149e000477269a4a5f1a84d97cfc3d0199b7aaf505913e6f010a6f83276029d11a9ad545374bc710eb59c7d958985023ab886ffa9ec9a23852844c764ec
adler32(raw): ff87222e
md5(raw): 704bf818448f5bbb94061332d2c889aa
diff --git a/ext/hash/tests/hash_hmac_basic.phpt b/ext/hash/tests/hash_hmac_basic.phpt
index 801e99a313..9631aa52c0 100644
--- a/ext/hash/tests/hash_hmac_basic.phpt
+++ b/ext/hash/tests/hash_hmac_basic.phpt
@@ -58,7 +58,7 @@ sha256: 49bde3496b9510a17d0edd8a4b0ac70148e32a1d51e881ec76faa96534125838
sha384: b781415b856744834e532b9899e1aa0bec5a82cf09a838f0a833470468e2a42648a52428cfd9012385d04de5cd9bd122
sha512: 7de05636b18e2b0ca3427e03f53074af3a48a7b9df226daba4f22324c570638e7d7b26430e214799c9ce0db5ee88dad3292ca0f38bf99b8eaebed59b3a9c140a
snefru: 67af483046f9cf16fe19f9087929ccfc6ad176ade3290b4d33f43e0ddb07e711
-tiger192,3: 82779797cdc439e886884953ba21fa38e35679041e95ee27
+tiger192,3: 00a0f884f15a9e5549ed0e40ca0190522d369027e16d5b59
whirlpool: 4a0f1582b21b7aff59bfba7f9c29131c69741b2ce80acdc7d314040f3b768cf5a17e30b74cceb86fbc6b34b1692e0addd5bfd7cfc043d40c0621f1b97e26fa49
adler32(raw): 12c803f7
md5(raw): 2a632783e2812cf23de100d7d6a463ae
diff --git a/ext/hash/tests/hash_hmac_file_basic.phpt b/ext/hash/tests/hash_hmac_file_basic.phpt
index c8caf71c27..858d673275 100644
--- a/ext/hash/tests/hash_hmac_file_basic.phpt
+++ b/ext/hash/tests/hash_hmac_file_basic.phpt
@@ -86,7 +86,7 @@ sha256: 9135286ca4c84dec711e4b831f6cd39e672e5ff93d011321274eb76733cc1e40
sha384: 364fdc45a4c742763366ab5d3d1c17c24057e6c3b641607a36d969f00c88da25b19c8b88c8632411e3a0a02397f88aca
sha512: d460aabdf0353655059ed0d408efa91f19c4cda46acc2a4e0adf4764b06951c899fbb2ed41519db78b58ff7be17b1b2910aebe674a56861b232143571b35c83f
snefru: 7b79787e1c1d926b6cc98327f05c5d04ba6227ab51c1398661861196016ef34c
-tiger192,3: 5577f21e2af269fff41e023db30e2b01bfd8b8f669177929
+tiger192,3: ca89badf843ba68e3fae5832635aa848a72a4bc11676edd4
whirlpool: 37a0fbb90547690d5e5e11c046f6654ffdb7bab15e16d9d79c7d85765cc4bdcbfd9df8db7a3ce9558f3f244fead00ca29cf05297f75596555195a0683f15d69f
adler32(raw): 0f8c02f9
md5(raw): 8bddf39dd1c566c27acc7fa85ec36acf
diff --git a/ext/hash/tests/joaat.phpt b/ext/hash/tests/joaat.phpt
new file mode 100644
index 0000000000..fa310a96e2
--- /dev/null
+++ b/ext/hash/tests/joaat.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Jenkins's one-at-a-time
+--SKIPIF--
+<?php extension_loaded('hash') or die ('Skip - hash extension not available'); ?>
+--FILE--
+<?php
+$tests = array(
+ array("hello world", "3e4a5a57"),
+ array("", 0),
+ array("", "000000"),
+ array("a", "ca2e9442"),
+ array("aa", "7081738e"),
+);
+
+$i = 0;
+$pass = true;
+
+foreach ($tests as $test) {
+ ++$i;
+
+ $result = hash("joaat", $test[0]);
+ if ($result != $test[1]) {
+ echo "Iteration " . $i . " failed - expected '" . $test[1] . "', got '" . $result . "' for '" . $test[1] . "'\n";
+
+ $pass = false;
+ }
+}
+
+if($pass) {
+ echo "PASS";
+}
+?>
+--EXPECT--
+PASS
diff --git a/ext/hash/tests/mhash_001.phpt b/ext/hash/tests/mhash_001.phpt
index b2a92839be..e8aac9b5e0 100644
--- a/ext/hash/tests/mhash_001.phpt
+++ b/ext/hash/tests/mhash_001.phpt
@@ -1,7 +1,5 @@
--TEST--
mhash() test
---INI--
-magic_quotes_runtime=0
--SKIPIF--
<?php
include "skip_mhash.inc";
@@ -18,7 +16,7 @@ $supported_hash_al = array(
"MHASH_HAVAL160" => "c6b36f87750b18576981bc17b4f22271947bf9cb",
"MHASH_RIPEMD160" => "6c47435aa1d359c4b7c6af46349f0c3e1258583d",
"MHASH_GOST" => "101b0a2552cebdf5137cadf15147f21e55b6432935bb9c2c03c7e28d188b2d9e",
-"MHASH_TIGER" => "fdb9019a79c33a95677e2097abae91eb0de00b3054bb5c39",
+"MHASH_TIGER" => "953ac3799a01b9fdeb91aeab97207e67395cbb54300be00d",
"MHASH_CRC32" => "83041db8",
"MHASH_CRC32B" => "df5ab7a4"
);
diff --git a/ext/hash/tests/mhash_003.phpt b/ext/hash/tests/mhash_003.phpt
index 7dcf247e1c..38d1a8b5f0 100644
--- a/ext/hash/tests/mhash_003.phpt
+++ b/ext/hash/tests/mhash_003.phpt
@@ -16,7 +16,7 @@ $supported_hash_al = array(
"MHASH_HAVAL160" => "d6e5f0ef07f3facced646eedb6364758ecde6dc6fb061e00a496f5ceb723f78ea135884d9682226ded69c11d8431240ef97cad583c4f29593bbf3dd3cab0b8792eb3d86022ca6002ebd0d9b4429909d4af85bed2b5a96b3e47b9b8cac919c1177ec40d7e",
"MHASH_RIPEMD160" => "e4d5db469af29f78e2b90dc735c9cf020a1d5b19a6674458677794d4dca144d426c562aff98d8e866a8a924299ebf6b0ea9a1637f987a1fb5de9b647edc35b1447605e1babc3084be7a003931117eb33432d4142e225df044b033f3ff64bb4a18682a4f9",
"MHASH_GOST" => "c044f669bd7e8643953d77c682fd179242d9df157dadf873be4d9601e4647c018234689359e7220ab0492a6240d184c478634073dea87f79be7f86fd4e2564f7d709b68a46440a121250e00fc7d57d45a9c07ee23a704ff4148c0dad7077ec527b194d87",
-"MHASH_TIGER" => "67eac97b9dca0a47b1f6262f330264e4ce1c233760fe3255f642512fd3127929baccf1e758236b2768a4c2c0c06e118b19e40e2f04a5f745820fb8a99bdbc00698702a4d3120171856c4c94bda79ba1b4f60d509d7f8954da818a29797368dd47c1122aa",
+"MHASH_TIGER" => "470aca9d7bc9ea67e46402332f26f6b15532fe6037231cce297912d32f5142f6276b2358e7f1ccba8b116ec0c0c2a46845f7a5042f0ee41906c0db9ba9b80f82181720314d2a70981bba79da4bc9c4564d95f8d709d5604fd48d369797a218a862196f48",
"MHASH_CRC32" => "481c40148c26185f9a59ef18e86f51c5d2d0315b46711d22ae08c1ccdd669fe956c817380815e3a545f6ee453c9da48d1d994dbc3ac8ba85a572108412f06b2a16b1489cda75b118e82f7d9bdfdb68336957bbf19e4a3f76750d6985a53dd557229dfcf3",
"MHASH_CRC32B" => "65ab6cb5fb7d3ea67f5da92a9bd746b6628a13368fcbcd43af49092e9c6a960fd030a5ce3c1f0ddb512ec698be96e77969748db66278b0fd837d24d8c898f50bd70993b48cc8accf4b44c54431e91385ddf04c7560a1a7368fc9e6f763457c90b07f04f1"
);
diff --git a/ext/hash/tests/mhash_004.phpt b/ext/hash/tests/mhash_004.phpt
index 2721663332..b928a794b1 100644
--- a/ext/hash/tests/mhash_004.phpt
+++ b/ext/hash/tests/mhash_004.phpt
@@ -1,7 +1,5 @@
--TEST--
mhash() modifying algorithm parameter
---INI--
-magic_quotes_runtime=0
--SKIPIF--
<?php
include "skip_mhash.inc";
diff --git a/ext/hash/tests/tiger.phpt b/ext/hash/tests/tiger.phpt
index ee3f249bf1..468fc8f699 100644
--- a/ext/hash/tests/tiger.phpt
+++ b/ext/hash/tests/tiger.phpt
@@ -11,8 +11,9 @@ echo hash('tiger192,3', str_repeat('abc', 61)),"\n";
echo hash('tiger192,3', str_repeat('abc', 64)),"\n";
?>
--EXPECT--
-24f0130c63ac933216166e76b1bb925ff373de2d49584e7a
-f258c1e88414ab2a527ab541ffc5b8bf935f7b951c132951
-8ee409a14e6066933b63d5b2abca63d71a78f55e29eb4649
-2586156d16bf9ab1e6e48bdf5e038f8053c30e071db3bcb0
-3ee8a9405396ddba1bc038508af4164ac1fe59ef58916a85
+3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3
+2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93
+9366604ea109e48ed763caabb2d5633b4946eb295ef5781a
+b19abf166d158625808f035edf8be4e6b0bcb31d070ec353
+badd965340a9e83e4a16f48a5038c01b856a9158ef59fec1
+
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 26b835ac2f..9cae535138 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -112,11 +112,6 @@ ZEND_BEGIN_ARG_INFO(arginfo_iconv, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO(arginfo_ob_iconv_handler, 0)
- ZEND_ARG_INFO(0, contents)
- ZEND_ARG_INFO(0, status)
-ZEND_END_ARG_INFO()
-
ZEND_BEGIN_ARG_INFO(arginfo_iconv_set_encoding, 0)
ZEND_ARG_INFO(0, type)
ZEND_ARG_INFO(0, charset)
@@ -132,7 +127,6 @@ ZEND_END_ARG_INFO()
*/
const zend_function_entry iconv_functions[] = {
PHP_RAW_NAMED_FE(iconv,php_if_iconv, arginfo_iconv)
- PHP_FE(ob_iconv_handler, arginfo_ob_iconv_handler)
PHP_FE(iconv_get_encoding, arginfo_iconv_get_encoding)
PHP_FE(iconv_set_encoding, arginfo_iconv_set_encoding)
PHP_FE(iconv_strlen, arginfo_iconv_strlen)
@@ -196,7 +190,7 @@ typedef enum _php_iconv_enc_scheme_t {
#define PHP_ICONV_MIME_DECODE_STRICT (1<<0)
#define PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR (1<<1)
-/* {{{ prototypes */
+/* {{{ prototypes */
static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, iconv_t cd);
static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd);
@@ -214,6 +208,10 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
static php_iconv_err_t php_iconv_stream_filter_register_factory(TSRMLS_D);
static php_iconv_err_t php_iconv_stream_filter_unregister_factory(TSRMLS_D);
+
+static int php_iconv_output_conflict(const char *handler_name, size_t handler_name_len TSRMLS_DC);
+static php_output_handler *php_iconv_output_handler_init(const char *name, size_t name_len, size_t chunk_size, int flags TSRMLS_DC);
+static int php_iconv_output_handler(void **nothing, php_output_context *output_context);
/* }}} */
/* {{{ static globals */
@@ -251,7 +249,7 @@ PHP_MINIT_FUNCTION(miconv)
{
static char buf[16];
snprintf(buf, sizeof(buf), "%d.%d",
- ((_libiconv_version >> 8) & 0x0f), (_libiconv_version & 0x0f));
+ ((_libiconv_version >> 8) & 0x0f), (_libiconv_version & 0x0f));
version = buf;
}
#elif HAVE_GLIBC_ICONV
@@ -278,6 +276,9 @@ PHP_MINIT_FUNCTION(miconv)
return FAILURE;
}
+ php_output_handler_alias_register(ZEND_STRL("ob_iconv_handler"), php_iconv_output_handler_init TSRMLS_CC);
+ php_output_handler_conflict_register(ZEND_STRL("ob_iconv_handler"), php_iconv_output_conflict TSRMLS_CC);
+
return SUCCESS;
}
/* }}} */
@@ -312,6 +313,69 @@ PHP_MINFO_FUNCTION(miconv)
}
/* }}} */
+static int php_iconv_output_conflict(const char *handler_name, size_t handler_name_len TSRMLS_DC)
+{
+ if (php_output_get_level(TSRMLS_C)) {
+ if (php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("ob_iconv_handler") TSRMLS_CC)
+ || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("mb_output_handler") TSRMLS_CC)) {
+ return FAILURE;
+ }
+ }
+ return SUCCESS;
+}
+
+static php_output_handler *php_iconv_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC)
+{
+ return php_output_handler_create_internal(handler_name, handler_name_len, php_iconv_output_handler, chunk_size, flags TSRMLS_CC);
+}
+
+static int php_iconv_output_handler(void **nothing, php_output_context *output_context)
+{
+ char *s, *content_type, *mimetype = NULL;
+ int output_status, mimetype_len = 0;
+ PHP_OUTPUT_TSRMLS(output_context);
+
+ if (output_context->op & PHP_OUTPUT_HANDLER_START) {
+ output_status = php_output_get_status(TSRMLS_C);
+ if (output_status & PHP_OUTPUT_SENT) {
+ return FAILURE;
+ }
+
+ if (SG(sapi_headers).mimetype && !strncasecmp(SG(sapi_headers).mimetype, "text/", 5)) {
+ if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
+ mimetype = SG(sapi_headers).mimetype;
+ } else {
+ mimetype = SG(sapi_headers).mimetype;
+ mimetype_len = s - SG(sapi_headers).mimetype;
+ }
+ } else if (SG(sapi_headers).send_default_content_type) {
+ mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
+ }
+
+ if (mimetype != NULL && !(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) {
+ int len;
+ char *p = strstr(ICONVG(output_encoding), "//");
+
+ if (p) {
+ len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, (int)(p - ICONVG(output_encoding)), ICONVG(output_encoding));
+ } else {
+ len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, ICONVG(output_encoding));
+ }
+ if (content_type && SUCCESS == sapi_add_header(content_type, len, 0)) {
+ SG(sapi_headers).send_default_content_type = 0;
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
+ }
+ }
+ }
+
+ if (output_context->in.used) {
+ output_context->out.free = 1;
+ _php_iconv_show_error(php_iconv_string(output_context->in.data, output_context->in.used, &output_context->out.data, &output_context->out.used, ICONVG(output_encoding), ICONVG(internal_encoding)), ICONVG(output_encoding), ICONVG(internal_encoding) TSRMLS_CC);
+ }
+
+ return SUCCESS;
+}
+
/* {{{ _php_iconv_appendl() */
static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, iconv_t cd)
{
@@ -336,7 +400,7 @@ static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l,
if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
#if ICONV_SUPPORTS_ERRNO
- switch (errno) {
+ switch (errno) {
case EINVAL:
return PHP_ICONV_ERR_ILLEGAL_CHAR;
@@ -351,7 +415,7 @@ static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l,
}
#else
if (prev_in_left == in_left) {
- return PHP_ICONV_ERR_UNKNOWN;
+ return PHP_ICONV_ERR_UNKNOWN;
}
#endif
}
@@ -382,7 +446,7 @@ static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l,
#else
if (out_left != 0) {
return PHP_ICONV_ERR_UNKNOWN;
- }
+ }
#endif
}
(d)->len += (buf_growth - out_left);
@@ -428,31 +492,35 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
in_size = in_len;
cd = iconv_open(out_charset, in_charset);
-
+
if (cd == (iconv_t)(-1)) {
return PHP_ICONV_ERR_UNKNOWN;
}
out_buffer = (char *) emalloc(out_size + 1);
out_p = out_buffer;
-
+
#ifdef NETWARE
result = iconv(cd, (char **) &in_p, &in_size, (char **)
#else
result = iconv(cd, (const char **) &in_p, &in_size, (char **)
#endif
&out_p, &out_left);
-
+
if (result == (size_t)(-1)) {
efree(out_buffer);
return PHP_ICONV_ERR_UNKNOWN;
}
if (out_left < 8) {
- out_buffer = (char *) erealloc(out_buffer, out_size + 8);
+ size_t pos = out_p - out_buffer;
+ out_buffer = (char *) safe_erealloc(out_buffer, out_size, 1, 8);
+ out_p = out_buffer+pos;
+ out_size += 7;
+ out_left += 7;
}
- /* flush the shift-out sequences */
+ /* flush the shift-out sequences */
result = iconv(cd, NULL, NULL, &out_p, &out_left);
if (result == (size_t)(-1)) {
@@ -491,10 +559,10 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
}
}
in_left= in_len;
- out_left = in_len + 32; /* Avoid realloc() most cases */
+ out_left = in_len + 32; /* Avoid realloc() most cases */
out_size = 0;
bsz = out_left;
- out_buf = (char *) emalloc(bsz+1);
+ out_buf = (char *) emalloc(bsz+1);
out_p = out_buf;
while (in_left > 0) {
@@ -509,14 +577,14 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
out_p = out_buf = tmp_buf;
out_p += out_size;
out_left = bsz - out_size;
- continue;
+ continue;
}
}
break;
}
if (result != (size_t)(-1)) {
- /* flush the shift-out sequences */
+ /* flush the shift-out sequences */
for (;;) {
result = iconv(cd, NULL, NULL, (char **) &out_p, &out_left);
out_size = bsz - out_left;
@@ -528,7 +596,7 @@ PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
if (errno == E2BIG) {
bsz += 16;
tmp_buf = (char *) erealloc(out_buf, bsz);
-
+
out_p = out_buf = tmp_buf;
out_p += out_size;
out_left = bsz - out_size;
@@ -620,7 +688,7 @@ static php_iconv_err_t _php_iconv_strlen(unsigned int *pretval, const char *str,
}
if (out_left > 0) {
- cnt -= out_left / GENERIC_SUPERSET_NBYTES;
+ cnt -= out_left / GENERIC_SUPERSET_NBYTES;
}
#if ICONV_SUPPORTS_ERRNO
@@ -671,12 +739,12 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
unsigned int cnt;
int total_len;
-
+
err = _php_iconv_strlen(&total_len, str, nbytes, enc);
if (err != PHP_ICONV_ERR_SUCCESS) {
return err;
}
-
+
if (len < 0) {
if ((len += (total_len - offset)) < 0) {
return PHP_ICONV_ERR_SUCCESS;
@@ -708,7 +776,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
smart_str_0(pretval);
return PHP_ICONV_ERR_SUCCESS;
}
-
+
cd1 = iconv_open(GENERIC_SUPERSET_NAME, enc);
if (cd1 == (iconv_t)(-1)) {
@@ -793,7 +861,7 @@ static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
if (cd2 != (iconv_t)NULL) {
iconv_close(cd2);
- }
+ }
return err;
}
@@ -978,7 +1046,7 @@ static php_iconv_err_t _php_iconv_strpos(unsigned int *pretval,
if (ndl_buf) {
efree(ndl_buf);
}
-
+
iconv_close(cd);
return err;
@@ -1025,7 +1093,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
if ((fname_nbytes + 2) >= max_line_len
|| (out_charset_len + 12) >= max_line_len) {
/* field name is too long */
- err = PHP_ICONV_ERR_TOO_BIG;
+ err = PHP_ICONV_ERR_TOO_BIG;
goto out;
}
@@ -1067,7 +1135,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
char_cnt -= 2;
in_p = fval;
- in_left = fval_nbytes;
+ in_left = fval_nbytes;
do {
size_t prev_in_left;
@@ -1078,8 +1146,8 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
smart_str_appendl(pretval, lfchars, lfchars_len);
smart_str_appendc(pretval, ' ');
char_cnt = max_line_len - 1;
- }
-
+ }
+
smart_str_appendl(pretval, "=?", sizeof("=?") - 1);
char_cnt -= 2;
smart_str_appendl(pretval, out_charset, out_charset_len);
@@ -1231,7 +1299,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
goto out;
}
break;
-
+
default:
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
@@ -1308,7 +1376,7 @@ out:
}
if (encoded != NULL) {
efree(encoded);
- }
+ }
if (buf != NULL) {
efree(buf);
}
@@ -1327,7 +1395,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
size_t str_left;
unsigned int scan_stat = 0;
const char *csname = NULL;
- size_t csname_len;
+ size_t csname_len;
const char *encoded_text = NULL;
size_t encoded_text_len = 0;
const char *encoded_word = NULL;
@@ -1366,7 +1434,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
case '\n':
- scan_stat = 8;
+ scan_stat = 8;
break;
case '=': /* first letter of an encoded chunk */
@@ -1391,7 +1459,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
case 1: /* expecting a delimiter */
if (*p1 != '?') {
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1406,7 +1474,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
csname = p1 + 1;
scan_stat = 2;
break;
-
+
case 2: /* expecting a charset name */
switch (*p1) {
case '?': /* normal delimiter: encoding scheme follows */
@@ -1416,7 +1484,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
case '*': /* new style delimiter: locale id follows */
scan_stat = 10;
break;
- }
+ }
if (scan_stat != 2) {
char tmpbuf[80];
@@ -1429,7 +1497,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if (csname_len > sizeof(tmpbuf) - 1) {
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1485,7 +1553,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
--str_left;
}
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1544,12 +1612,12 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
}
}
break;
-
+
case 4: /* expecting a delimiter */
if (*p1 != '?') {
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
/* pass the entire chunk through the converter */
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1605,7 +1673,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if (*p1 != '=') {
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
/* pass the entire chunk through the converter */
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1632,17 +1700,17 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
switch (*p1) {
default:
/* Handle non-RFC-compliant formats
- *
+ *
* RFC2047 requires the character that comes right
* after an encoded word (chunk) to be a whitespace,
* while there are lots of broken implementations that
* generate such malformed headers that don't fulfill
* that requirement.
- */
- if (!eos) {
+ */
+ if (!eos) {
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
/* pass the entire chunk through the converter */
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1674,7 +1742,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if (decoded_text == NULL) {
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
/* pass the entire chunk through the converter */
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
}
@@ -1697,7 +1765,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if (err != PHP_ICONV_ERR_SUCCESS) {
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
/* pass the entire chunk through the converter */
- err = _php_iconv_appendl(pretval, encoded_word, (size_t)(p1 - encoded_word), cd_pl);
+ err = _php_iconv_appendl(pretval, encoded_word, (size_t)(p1 - encoded_word), cd_pl);
encoded_word = NULL;
if (err != PHP_ICONV_ERR_SUCCESS) {
break;
@@ -1752,7 +1820,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
case '\n':
- scan_stat = 8;
+ scan_stat = 8;
break;
case '=': /* first letter of an encoded chunk */
@@ -1892,7 +1960,7 @@ PHP_FUNCTION(iconv_strlen)
char *charset = ICONVG(internal_encoding);
int charset_len = 0;
char *str;
- int str_len;
+ int str_len;
php_iconv_err_t err;
@@ -1908,7 +1976,7 @@ PHP_FUNCTION(iconv_strlen)
RETURN_FALSE;
}
- err = _php_iconv_strlen(&retval, str, str_len, charset);
+ err = _php_iconv_strlen(&retval, str, str_len, charset);
_php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset TSRMLS_CC);
if (err == PHP_ICONV_ERR_SUCCESS) {
RETVAL_LONG(retval);
@@ -1925,7 +1993,7 @@ PHP_FUNCTION(iconv_substr)
char *charset = ICONVG(internal_encoding);
int charset_len = 0;
char *str;
- int str_len;
+ int str_len;
long offset, length = 0;
php_iconv_err_t err;
@@ -1944,10 +2012,10 @@ PHP_FUNCTION(iconv_substr)
}
if (ZEND_NUM_ARGS() < 3) {
- length = str_len;
+ length = str_len;
}
- err = _php_iconv_substr(&retval, str, str_len, offset, length, charset);
+ err = _php_iconv_substr(&retval, str, str_len, offset, length, charset);
_php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset TSRMLS_CC);
if (err == PHP_ICONV_ERR_SUCCESS && str != NULL && retval.c != NULL) {
@@ -1965,7 +2033,7 @@ PHP_FUNCTION(iconv_strpos)
char *charset = ICONVG(internal_encoding);
int charset_len = 0;
char *haystk;
- int haystk_len;
+ int haystk_len;
char *ndl;
int ndl_len;
long offset = 0;
@@ -1995,7 +2063,7 @@ PHP_FUNCTION(iconv_strpos)
}
err = _php_iconv_strpos(&retval, haystk, haystk_len, ndl, ndl_len,
- offset, charset);
+ offset, charset);
_php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset TSRMLS_CC);
if (err == PHP_ICONV_ERR_SUCCESS && retval != (unsigned int)-1) {
@@ -2013,7 +2081,7 @@ PHP_FUNCTION(iconv_strrpos)
char *charset = ICONVG(internal_encoding);
int charset_len = 0;
char *haystk;
- int haystk_len;
+ int haystk_len;
char *ndl;
int ndl_len;
@@ -2037,7 +2105,7 @@ PHP_FUNCTION(iconv_strrpos)
}
err = _php_iconv_strpos(&retval, haystk, haystk_len, ndl, ndl_len,
- -1, charset);
+ -1, charset);
_php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset TSRMLS_CC);
if (err == PHP_ICONV_ERR_SUCCESS && retval != (unsigned int)-1) {
@@ -2177,7 +2245,7 @@ PHP_FUNCTION(iconv_mime_decode)
char *charset = ICONVG(internal_encoding);
int charset_len = 0;
long mode = 0;
-
+
smart_str retval = {0};
php_iconv_err_t err;
@@ -2218,7 +2286,7 @@ PHP_FUNCTION(iconv_mime_decode_headers)
char *charset = ICONVG(internal_encoding);
int charset_len = 0;
long mode = 0;
-
+
php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls",
@@ -2286,14 +2354,14 @@ PHP_FUNCTION(iconv_mime_decode_headers)
zend_hash_update(Z_ARRVAL_P(return_value), header_name, header_name_len, (void *)&new_elem, sizeof(new_elem), NULL);
elem = &new_elem;
- }
+ }
add_next_index_stringl(*elem, header_value, header_value_len, 1);
} else {
add_assoc_stringl_ex(return_value, header_name, header_name_len, header_value, header_value_len, 1);
}
}
encoded_str_len -= next_pos - encoded_str;
- encoded_str = next_pos;
+ encoded_str = next_pos;
smart_str_free(&decoded_header);
}
@@ -2314,7 +2382,7 @@ PHP_NAMED_FUNCTION(php_if_iconv)
size_t out_len;
int in_charset_len = 0, out_charset_len = 0, in_buffer_len;
php_iconv_err_t err;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss",
&in_charset, &in_charset_len, &out_charset, &out_charset_len, &in_buffer, &in_buffer_len) == FAILURE)
return;
@@ -2326,70 +2394,15 @@ PHP_NAMED_FUNCTION(php_if_iconv)
err = php_iconv_string(in_buffer, (size_t)in_buffer_len,
&out_buffer, &out_len, out_charset, in_charset);
- _php_iconv_show_error(err, out_charset, in_charset TSRMLS_CC);
- if (out_buffer != NULL) {
+ _php_iconv_show_error(err, out_charset, in_charset TSRMLS_CC);
+ if (err == PHP_ICONV_ERR_SUCCESS && out_buffer != NULL) {
RETVAL_STRINGL(out_buffer, out_len, 0);
} else {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto string ob_iconv_handler(string contents, int status)
- Returns str in output buffer converted to the iconv.output_encoding character set */
-PHP_FUNCTION(ob_iconv_handler)
-{
- char *out_buffer, *content_type, *mimetype = NULL, *s;
- zval *zv_string;
- size_t out_len;
- int mimetype_alloced = 0;
- long status;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &zv_string, &status) == FAILURE)
- return;
-
- convert_to_string(zv_string);
-
- if (SG(sapi_headers).mimetype &&
- strncasecmp(SG(sapi_headers).mimetype, "text/", 5) == 0) {
- if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
- mimetype = SG(sapi_headers).mimetype;
- } else {
- mimetype = estrndup(SG(sapi_headers).mimetype, s-SG(sapi_headers).mimetype);
- mimetype_alloced = 1;
- }
- } else if (SG(sapi_headers).send_default_content_type) {
- mimetype =(SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE);
- }
- if (mimetype != NULL) {
- php_iconv_err_t err = php_iconv_string(Z_STRVAL_P(zv_string),
- Z_STRLEN_P(zv_string), &out_buffer, &out_len,
- ICONVG(output_encoding), ICONVG(internal_encoding));
- _php_iconv_show_error(err, ICONVG(output_encoding), ICONVG(internal_encoding) TSRMLS_CC);
if (out_buffer != NULL) {
- int len;
- char *p = strstr(ICONVG(output_encoding), "//");
- if (p) {
- len = spprintf(&content_type, 0, "Content-Type:%s; charset=%.*s", mimetype, (int)(p - ICONVG(output_encoding)), ICONVG(output_encoding));
- } else {
- len = spprintf(&content_type, 0, "Content-Type:%s; charset=%s", mimetype, ICONVG(output_encoding));
- }
- if (content_type && sapi_add_header(content_type, len, 0) != FAILURE) {
- SG(sapi_headers).send_default_content_type = 0;
- }
- if (mimetype_alloced) {
- efree(mimetype);
- }
- RETURN_STRINGL(out_buffer, out_len, 0);
- }
- if (mimetype_alloced) {
- efree(mimetype);
+ efree(out_buffer);
}
+ RETURN_FALSE;
}
-
- zval_dtor(return_value);
- *return_value = *zv_string;
- zval_copy_ctor(return_value);
}
/* }}} */
@@ -2521,7 +2534,7 @@ static int php_iconv_stream_filter_append_bucket(
char *pd, *pt;
size_t ocnt, prev_ocnt, icnt, tcnt;
size_t initial_out_buf_size;
-
+
if (ps == NULL) {
initial_out_buf_size = 64;
icnt = 1;
@@ -2530,7 +2543,7 @@ static int php_iconv_stream_filter_append_bucket(
icnt = buf_len;
}
- out_buf_size = ocnt = prev_ocnt = initial_out_buf_size;
+ out_buf_size = ocnt = prev_ocnt = initial_out_buf_size;
if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
return FAILURE;
}
@@ -2817,7 +2830,7 @@ static php_stream_filter *php_iconv_stream_filter_factory_create(const char *nam
pefree(inst, persistent);
}
- return retval;
+ return retval;
}
/* }}} */
diff --git a/ext/iconv/tests/bug52211.phpt b/ext/iconv/tests/bug52211.phpt
new file mode 100644
index 0000000000..c851cbad6a
--- /dev/null
+++ b/ext/iconv/tests/bug52211.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #52211 (iconv() returns part of string on error)
+--SKIPIF--
+<?php
+include('skipif.inc');
+?>
+--FILE--
+<?php
+
+$str = "PATHOLOGIES MÉDICO-CHIRUR. ADUL. PL";
+$str_iconv = iconv('CP850', 'ISO-8859-1', $str );
+var_dump($str_iconv);
+
+?>
+--EXPECTF--
+Notice: iconv(): Detected an illegal character in input string in %s on line %d
+bool(false)
diff --git a/ext/iconv/tests/translit-utf8.phpt b/ext/iconv/tests/translit-utf8.phpt
index aa5131f2c3..0151dc385c 100644
--- a/ext/iconv/tests/translit-utf8.phpt
+++ b/ext/iconv/tests/translit-utf8.phpt
@@ -6,7 +6,6 @@ include('skipif.inc');
( ICONV_IMPL != "libiconv" ) and die("skip ICONV_IMPL != \"libiconv\"");
?>
--INI--
-magic_quotes_runtime=0
error_reporting=2047
--FILE--
<?php // vim600: syn=php
diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
index 802bb51643..32161f3b6c 100644
--- a/ext/imap/php_imap.c
+++ b/ext/imap/php_imap.c
@@ -1153,7 +1153,7 @@ static void php_imap_do_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
zval *params = NULL;
int argc = ZEND_NUM_ARGS();
- if (zend_parse_parameters(argc TSRMLS_CC, "sss|lla", &mailbox, &mailbox_len, &user, &user_len,
+ if (zend_parse_parameters(argc TSRMLS_CC, "pss|lla", &mailbox, &mailbox_len, &user, &user_len,
&passwd, &passwd_len, &flags, &retries, &params) == FAILURE) {
return;
}
@@ -1218,15 +1218,9 @@ static void php_imap_do_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
IMAPG(imap_password) = 0;
}
- /* local filename, need to perform open_basedir and safe_mode checks */
- if (mailbox[0] != '{') {
- if (strlen(mailbox) != mailbox_len) {
- RETURN_FALSE;
- }
- if (php_check_open_basedir(mailbox TSRMLS_CC) ||
- (PG(safe_mode) && !php_checkuid(mailbox, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
+ /* local filename, need to perform open_basedir check */
+ if (mailbox[0] != '{' && php_check_open_basedir(mailbox TSRMLS_CC)) {
+ RETURN_FALSE;
}
IMAPG(imap_user) = estrndup(user, user_len);
@@ -1299,10 +1293,8 @@ PHP_FUNCTION(imap_reopen)
mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
}
#endif
- /* local filename, need to perform open_basedir and safe_mode checks */
- if (mailbox[0] != '{' &&
- (php_check_open_basedir(mailbox TSRMLS_CC) ||
- (PG(safe_mode) && !php_checkuid(mailbox, NULL, CHECKUID_CHECK_FILE_AND_DIR)))) {
+ /* local filename, need to perform open_basedir check */
+ if (mailbox[0] != '{' && php_check_open_basedir(mailbox TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -2441,7 +2433,7 @@ PHP_FUNCTION(imap_savebody)
default:
convert_to_string_ex(out);
- writer = php_stream_open_wrapper(Z_STRVAL_PP(out), "wb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+ writer = php_stream_open_wrapper(Z_STRVAL_PP(out), "wb", REPORT_ERRORS, NULL);
break;
}
diff --git a/ext/imap/tests/imap_errors_basic.phpt b/ext/imap/tests/imap_errors_basic.phpt
index 9d2ca30ece..91be3286aa 100644
--- a/ext/imap/tests/imap_errors_basic.phpt
+++ b/ext/imap/tests/imap_errors_basic.phpt
@@ -7,7 +7,7 @@ require_once(dirname(__FILE__).'/skipif.inc');
--FILE--
<?php
/* Prototype : array imap_errors ( void )
- * Description: Returns all of the IMAP errors that have occured.
+ * Description: Returns all of the IMAP errors that have occurred.
* Source code: ext/imap/php_imap.c
*/
diff --git a/ext/interbase/ibase_query.c b/ext/interbase/ibase_query.c
index d7637040a2..1c6de4e73e 100644
--- a/ext/interbase/ibase_query.c
+++ b/ext/interbase/ibase_query.c
@@ -1325,12 +1325,7 @@ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{
data = ((IBVARY *) data)->vary_string;
/* no break */
case SQL_TEXT:
- if (PG(magic_quotes_runtime)) {
- Z_STRVAL_P(val) = php_addslashes(data, len, &Z_STRLEN_P(val), 0 TSRMLS_CC);
- Z_TYPE_P(val) = IS_STRING;
- } else {
- ZVAL_STRINGL(val,(char *) data,len,1);
- }
+ ZVAL_STRINGL(val,(char *) data,len,1);
break;
case SQL_SHORT:
n = *(short *) data;
@@ -1850,7 +1845,7 @@ PHP_FUNCTION(ibase_execute)
if (ib_query->statement_type == isc_info_sql_stmt_exec_procedure) {
result->stmt = NULL;
}
- ib_query->result_res_id = zend_list_insert(result, le_result);
+ ib_query->result_res_id = zend_list_insert(result, le_result TSRMLS_CC);
RETVAL_RESOURCE(ib_query->result_res_id);
}
} while (0);
diff --git a/ext/interbase/interbase.rc b/ext/interbase/interbase.rc
deleted file mode 100644
index ad3287be31..0000000000
--- a/ext/interbase/interbase.rc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Ard Biesheuvel <a.k.biesheuvel@its.tudelft.nl> |
- +----------------------------------------------------------------------+
- */
-
-/* $Id$ */
-
-#ifdef APSTUDIO_INVOKED
-#error This file cannot be opened from the Visual Studio IDE
-#endif
-
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-#include "winres.h"
-#undef APSTUDIO_READONLY_SYMBOLS
-
-#include "php_version.h"
-
-#ifdef _DEBUG
-# define BUILD_TYPE "Debug"
-#else
-# define BUILD_TYPE "Release"
-#endif
-
-#include <ibase.h>
-#include "interbase.c"
-
-#ifdef FB_SQLDA
-#define CLIENT_LIB "fbclient.dll"
-#else
-#define CLIENT_LIB "gds32.dll"
-#endif
-
-#ifndef _MAC
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION,0
- PRODUCTVERSION PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION,0
-#ifndef _DEBUG
- FILEFLAGS 0x0L
-#else
- FILEFLAGS 0x1L
-#endif
- FILEFLAGSMASK 0x3fL
- FILEOS VOS__WINDOWS32
- FILETYPE VFT_DLL
- FILESUBTYPE VFT2_UNKNOWN
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "000004b0"
- BEGIN
- VALUE "FileDescription", "PHP Interbase module\0"
- VALUE "FileVersion", PHP_VERSION "\0"
- VALUE "LegalCopyright", "Copyright © 2003 The PHP Group\0"
- VALUE "Build Type", BUILD_TYPE "\0"
- VALUE "Client Library", CLIENT_LIB "\0"
- VALUE "URL", "http://www.php.net\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0, 1200
- END
-END
-
-#endif // !_MAC
diff --git a/ext/intl/collator/collator_class.c b/ext/intl/collator/collator_class.c
index 38b2e978ce..d1fa10ef2c 100644
--- a/ext/intl/collator/collator_class.c
+++ b/ext/intl/collator/collator_class.c
@@ -67,6 +67,7 @@ zend_object_value Collator_object_create(
intern = ecalloc( 1, sizeof(Collator_object) );
intl_error_init( COLLATOR_ERROR_P( intern ) TSRMLS_CC );
zend_object_std_init( &intern->zo, ce TSRMLS_CC );
+ object_properties_init(&intern->zo, ce);
retval.handle = zend_objects_store_put(
intern,
@@ -112,7 +113,7 @@ ZEND_END_ARG_INFO()
* Every 'Collator' class method has an entry in this table
*/
-function_entry Collator_class_functions[] = {
+zend_function_entry Collator_class_functions[] = {
PHP_ME( Collator, __construct, collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
ZEND_FENTRY( create, ZEND_FN( collator_create ), collator_1_arg, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
PHP_NAMED_FE( compare, ZEND_FN( collator_compare ), collator_2_args )
diff --git a/ext/intl/common/common_error.c b/ext/intl/common/common_error.c
index 3ab7fdfbdd..282172224c 100644
--- a/ext/intl/common/common_error.c
+++ b/ext/intl/common/common_error.c
@@ -24,7 +24,7 @@
#include "common_error.h"
/* {{{ proto int intl_get_error_code()
- * Get code of the last occured error.
+ * Get code of the last occurred error.
*/
PHP_FUNCTION( intl_get_error_code )
{
@@ -33,7 +33,7 @@ PHP_FUNCTION( intl_get_error_code )
/* }}} */
/* {{{ proto string intl_get_error_message()
- * Get text description of the last occured error.
+ * Get text description of the last occurred error.
*/
PHP_FUNCTION( intl_get_error_message )
{
@@ -232,7 +232,6 @@ void intl_expose_icu_error_codes( INIT_FUNC_ARGS )
INTL_EXPOSE_CONST( U_REGEX_ERROR_LIMIT );
/* The error code in the range 0x10400-0x104ff are reserved for IDNA related error codes */
-#if defined(U_IDNA_PROHIBITED_ERROR)
INTL_EXPOSE_CONST( U_IDNA_PROHIBITED_ERROR );
INTL_EXPOSE_CONST( U_IDNA_ERROR_START );
INTL_EXPOSE_CONST( U_IDNA_UNASSIGNED_ERROR );
@@ -241,9 +240,13 @@ void intl_expose_icu_error_codes( INIT_FUNC_ARGS )
INTL_EXPOSE_CONST( U_IDNA_ACE_PREFIX_ERROR );
INTL_EXPOSE_CONST( U_IDNA_VERIFICATION_ERROR );
INTL_EXPOSE_CONST( U_IDNA_LABEL_TOO_LONG_ERROR );
+#if U_ICU_VERSION_MAJOR_NUM > 3 || U_ICU_VERSION_MAJOR_NUM == 3 && U_ICU_VERSION_MINOR_NUM >= 6
INTL_EXPOSE_CONST( U_IDNA_ZERO_LENGTH_LABEL_ERROR );
- INTL_EXPOSE_CONST( U_IDNA_ERROR_LIMIT );
#endif
+#if U_ICU_VERSION_MAJOR_NUM > 3 || U_ICU_VERSION_MAJOR_NUM == 3 && U_ICU_VERSION_MINOR_NUM >= 8
+ INTL_EXPOSE_CONST( U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR );
+#endif
+ INTL_EXPOSE_CONST( U_IDNA_ERROR_LIMIT );
/* Aliases for StringPrep */
INTL_EXPOSE_CONST( U_STRINGPREP_PROHIBITED_ERROR );
diff --git a/ext/intl/config.m4 b/ext/intl/config.m4
index dc235db08c..0477c7f59d 100644
--- a/ext/intl/config.m4
+++ b/ext/intl/config.m4
@@ -9,7 +9,14 @@ if test "$PHP_INTL" != "no"; then
PHP_SETUP_ICU(INTL_SHARED_LIBADD)
PHP_SUBST(INTL_SHARED_LIBADD)
PHP_REQUIRE_CXX()
-
+ if test "$icu_version" -ge "4002"; then
+ icu_spoof_src=" spoofchecker/spoofchecker_class.c \
+ spoofchecker/spoofchecker.c\
+ spoofchecker/spoofchecker_create.c\
+ spoofchecker/spoofchecker_main.c"
+ else
+ icu_spoof_src=""
+ fi
PHP_NEW_EXTENSION(intl, php_intl.c \
intl_error.c \
intl_convert.c \
@@ -55,8 +62,11 @@ if test "$PHP_INTL" != "no"; then
resourcebundle/resourcebundle.c \
resourcebundle/resourcebundle_class.c \
resourcebundle/resourcebundle_iterator.c \
- idn/idn.c, $ext_shared,,$ICU_INCS)
-
+ transliterator/transliterator.c \
+ transliterator/transliterator_class.c \
+ transliterator/transliterator_methods.c \
+ idn/idn.c \
+ $icu_spoof_src, $ext_shared,,$ICU_INCS)
PHP_ADD_BUILD_DIR($ext_builddir/collator)
PHP_ADD_BUILD_DIR($ext_builddir/common)
PHP_ADD_BUILD_DIR($ext_builddir/formatter)
@@ -66,5 +76,7 @@ if test "$PHP_INTL" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/msgformat)
PHP_ADD_BUILD_DIR($ext_builddir/grapheme)
PHP_ADD_BUILD_DIR($ext_builddir/resourcebundle)
+ PHP_ADD_BUILD_DIR($ext_builddir/transliterator)
PHP_ADD_BUILD_DIR($ext_builddir/idn)
+ PHP_ADD_BUILD_DIR($ext_builddir/spoofchecker)
fi
diff --git a/ext/intl/config.w32 b/ext/intl/config.w32
index 68ccadf2d8..437fedb7d3 100644
--- a/ext/intl/config.w32
+++ b/ext/intl/config.w32
@@ -71,6 +71,22 @@ if (PHP_INTL != "no") {
resourcebundle_class.c \
resourcebundle_iterator.c",
"intl");
+
+ if (CHECK_HEADER_ADD_INCLUDE("unicode/uspoof.h", "CFLAGS_INTL")) {
+ ADD_SOURCES(configure_module_dirname + "/spoofchecker", "\
+ spoofchecker.c \
+ spoofchecker_class.c \
+ spoofchecker_create.c \
+ spoofchecker_main.c",
+ "intl");
+ AC_DEFINE("HAVE_INTL", 1, "Internationalization support enabled");
+ }
+
+ ADD_SOURCES(configure_module_dirname + "/transliterator", "\
+ transliterator.c \
+ transliterator_class.c \
+ transliterator_methods.c",
+ "intl");
ADD_FLAG("LIBS_INTL", "icudt.lib icuin.lib icuio.lib icule.lib iculx.lib");
AC_DEFINE("HAVE_INTL", 1, "Internationalization support enabled");
} else {
diff --git a/ext/intl/dateformat/dateformat_class.c b/ext/intl/dateformat/dateformat_class.c
index a7227ef03d..49f316f787 100644
--- a/ext/intl/dateformat/dateformat_class.c
+++ b/ext/intl/dateformat/dateformat_class.c
@@ -65,6 +65,7 @@ zend_object_value IntlDateFormatter_object_create(zend_class_entry *ce TSRMLS_DC
intern = ecalloc( 1, sizeof(IntlDateFormatter_object) );
dateformat_data_init( &intern->datef_data TSRMLS_CC );
zend_object_std_init( &intern->zo, ce TSRMLS_CC );
+ object_properties_init(&intern->zo, ce);
intern->date_type = 0;
intern->time_type = 0;
intern->calendar = 1; /* Gregorian calendar */
@@ -158,7 +159,7 @@ ZEND_END_ARG_INFO()
/* {{{ IntlDateFormatter_class_functions
* Every 'IntlDateFormatter' class method has an entry in this table
*/
-static function_entry IntlDateFormatter_class_functions[] = {
+static zend_function_entry IntlDateFormatter_class_functions[] = {
PHP_ME( IntlDateFormatter, __construct, arginfo_intldateformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
ZEND_FENTRY( create, ZEND_FN( datefmt_create ), arginfo_intldateformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
PHP_NAMED_FE( getDateType, ZEND_FN( datefmt_get_datetype ), arginfo_intldateformatter_getdatetype )
diff --git a/ext/intl/doc/collator_api.php b/ext/intl/doc/collator_api.php
index 5428783750..ef7250243b 100644
--- a/ext/intl/doc/collator_api.php
+++ b/ext/intl/doc/collator_api.php
@@ -116,7 +116,7 @@ class Collator {
/**
* Return error text for the last ICU operation.
*
- * @return string Description of an error occured in the last
+ * @return string Description of an error occurred in the last
* Collator method call.
*/
public function getErrorMessage() {}
@@ -236,7 +236,7 @@ class Collator {
*
* @return string Real locale name from which the
* collation data comes. If the collator
- * was instantiated from rules or an error occured,
+ * was instantiated from rules or an error occurred,
* returns false.
*/
public function getLocale( $type ) {}
@@ -331,7 +331,7 @@ function collator_sort_with_sort_keys( $coll, $arr ) {}
*
* @return string Real locale name from which the
* collation data comes. If the collator
- * was instantiated from rules or an error occured,
+ * was instantiated from rules or an error occurred,
* returns false.
*/
function collator_get_locale( $coll, $type ) {}
@@ -391,7 +391,7 @@ function collator_get_error_code( $coll ) {}
*
* @param Collator $coll Collator object.
*
- * @return string Description of an error occured in the last
+ * @return string Description of an error occurred in the last
* Collator API function call.
*/
function collator_get_error_message( $coll ) {}
diff --git a/ext/intl/doc/common_api.php b/ext/intl/doc/common_api.php
index ce2329fe3b..993dab180b 100644
--- a/ext/intl/doc/common_api.php
+++ b/ext/intl/doc/common_api.php
@@ -1,7 +1,7 @@
<?php
/**
- * Handling of errors occured in static methods
+ * Handling of errors occurred in static methods
* when there's no object to get error code/message from.
*
* Example #1:
@@ -29,7 +29,7 @@ function intl_get_error_code() {}
/**
* Get description of the last error.
*
- * @return string Description of an error occured in the last
+ * @return string Description of an error occurred in the last
* API function call.
*/
function intl_get_error_message() {}
diff --git a/ext/intl/doc/datefmt_api.php b/ext/intl/doc/datefmt_api.php
index 0c5002e281..272abdb57c 100644
--- a/ext/intl/doc/datefmt_api.php
+++ b/ext/intl/doc/datefmt_api.php
@@ -215,7 +215,7 @@ class DateFormatter {
/**
* Sets the pattern to use
* @param string $pattern new pattern string to use
- * @return boolean 'true' if successful, 'false' if an error occured. Bad format
+ * @return boolean 'true' if successful, 'false' if an error occurred. Bad format
* strings are usually the cause of the latter.
*/
public function setPattern($pattern) {}
@@ -410,7 +410,7 @@ class DateFormatter {
* Sets the pattern to use
* @param DateFormatter $fmt The date formatter resource
* @param string $pattern new pattern string to use
- * @return boolean 'true' if successful, 'false' if an error occured. Bad format
+ * @return boolean 'true' if successful, 'false' if an error occurred. Bad format
* strings are usually the cause of the latter.
*/
function datefmt_set_pattern($fmt , $pattern) {}
diff --git a/ext/intl/doc/formatter_api.php b/ext/intl/doc/formatter_api.php
index 754b16c62f..14d98db66a 100644
--- a/ext/intl/doc/formatter_api.php
+++ b/ext/intl/doc/formatter_api.php
@@ -317,7 +317,7 @@ class NumberFormatter {
/**
* Get the error text from the last operation.
*
- * @return string Description of the last occured error.
+ * @return string Description of the last occurred error.
*/
public public function getErrorMessage() {}
@@ -495,6 +495,6 @@ function numfmt_get_error_code($formatter) {}
* Get the error text from the last operation.
*
* @param NumberFormatter $formatter The formatter resource
- * @return string Description of the last occured error.
+ * @return string Description of the last occurred error.
*/
function numfmt_get_error_message($formatter) {}
diff --git a/ext/intl/doc/msgfmt_api.php b/ext/intl/doc/msgfmt_api.php
index 5d178f1273..e4d047b979 100644
--- a/ext/intl/doc/msgfmt_api.php
+++ b/ext/intl/doc/msgfmt_api.php
@@ -54,7 +54,7 @@ class MessageFormatter {
* @param string $locale the locale to use when formatting numbers and dates and suchlike
* @param string $pattern the pattern string to insert things into
* @param array $args the array of values to insert into $pattern
- * @return string the formatted pattern string or false if an error occured
+ * @return string the formatted pattern string or false if an error occurred
*/
public static function formatMessage($locale, $pattern, $args) {}
@@ -148,7 +148,7 @@ class MessageFormatter {
* @param string $locale the locale to use when formatting numbers and dates and suchlike
* @param string $pattern the pattern string to insert things into
* @param array $args the array of values to insert into $pattern
- * @return string the formatted pattern string or false if an error occured
+ * @return string the formatted pattern string or false if an error occurred
*/
function msgfmt_format_message($locale, $pattern, $args) {}
diff --git a/ext/intl/formatter/formatter_class.c b/ext/intl/formatter/formatter_class.c
index 9de1e1e96e..2246cd29a5 100644
--- a/ext/intl/formatter/formatter_class.c
+++ b/ext/intl/formatter/formatter_class.c
@@ -64,6 +64,7 @@ zend_object_value NumberFormatter_object_create(zend_class_entry *ce TSRMLS_DC)
intern = ecalloc( 1, sizeof(NumberFormatter_object) );
formatter_data_init( &intern->nf_data TSRMLS_CC );
zend_object_std_init( &intern->zo, ce TSRMLS_CC );
+ object_properties_init(&intern->zo, ce);
retval.handle = zend_objects_store_put(
intern,
@@ -168,7 +169,7 @@ ZEND_END_ARG_INFO()
/* {{{ NumberFormatter_class_functions
* Every 'NumberFormatter' class method has an entry in this table
*/
-static function_entry NumberFormatter_class_functions[] = {
+static zend_function_entry NumberFormatter_class_functions[] = {
PHP_ME( NumberFormatter, __construct, arginfo_numberformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
ZEND_FENTRY( create, ZEND_FN( numfmt_create ), arginfo_numberformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
PHP_NAMED_FE( format, ZEND_FN( numfmt_format ), arginfo_numberformatter_format )
diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c
index 0b7ecdb27d..475bbe4184 100644
--- a/ext/intl/grapheme/grapheme_string.c
+++ b/ext/intl/grapheme/grapheme_string.c
@@ -554,13 +554,17 @@ PHP_FUNCTION(grapheme_substr)
length += iter_val;
}
- if ( UBRK_DONE == sub_str_end_pos && length < 0) {
+ if ( UBRK_DONE == sub_str_end_pos) {
+ if(length < 0) {
- intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: length not contained in string", 1 TSRMLS_CC );
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: length not contained in string", 1 TSRMLS_CC );
- efree(ustr);
- ubrk_close(bi);
- RETURN_FALSE;
+ efree(ustr);
+ ubrk_close(bi);
+ RETURN_FALSE;
+ } else {
+ sub_str_end_pos = ustr_len;
+ }
}
sub_str = NULL;
diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.c
index 23cd0ea872..6332488cc9 100644
--- a/ext/intl/idn/idn.c
+++ b/ext/intl/idn/idn.c
@@ -13,6 +13,7 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Pierre A. Joye <pierre@php.net> |
+ | Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
@@ -29,14 +30,25 @@
#include "ext/standard/php_string.h"
#include "intl_error.h"
- #include "intl_convert.h"
+#include "intl_convert.h"
/* }}} */
+#ifdef UIDNA_INFO_INITIALIZER
+#define HAVE_46_API 1 /* has UTS#46 API (introduced in ICU 4.6) */
+#endif
+
+enum {
+ INTL_IDN_VARIANT_2003 = 0,
+ INTL_IDN_VARIANT_UTS46
+};
+
/* {{{ grapheme_register_constants
* Register API constants
*/
void idn_register_constants( INIT_FUNC_ARGS )
{
+ /* OPTIONS */
+
/* Option to prohibit processing of unassigned codepoints in the input and
do not check if the input conforms to STD-3 ASCII rules. */
REGISTER_LONG_CONSTANT("IDNA_DEFAULT", UIDNA_DEFAULT, CONST_CS | CONST_PERSISTENT);
@@ -46,6 +58,50 @@ void idn_register_constants( INIT_FUNC_ARGS )
/* Option to check if input conforms to STD-3 ASCII rules */
REGISTER_LONG_CONSTANT("IDNA_USE_STD3_RULES", UIDNA_USE_STD3_RULES, CONST_CS | CONST_PERSISTENT);
+
+#ifdef HAVE_46_API
+
+ /* Option to check for whether the input conforms to the BiDi rules.
+ * Ignored by the IDNA2003 implementation. (IDNA2003 always performs a BiDi check.) */
+ REGISTER_LONG_CONSTANT("IDNA_CHECK_BIDI", UIDNA_CHECK_BIDI, CONST_CS | CONST_PERSISTENT);
+
+ /* Option to check for whether the input conforms to the CONTEXTJ rules.
+ * Ignored by the IDNA2003 implementation. (The CONTEXTJ check is new in IDNA2008.) */
+ REGISTER_LONG_CONSTANT("IDNA_CHECK_CONTEXTJ", UIDNA_CHECK_CONTEXTJ, CONST_CS | CONST_PERSISTENT);
+
+ /* Option for nontransitional processing in ToASCII().
+ * By default, ToASCII() uses transitional processing.
+ * Ignored by the IDNA2003 implementation. */
+ REGISTER_LONG_CONSTANT("IDNA_NONTRANSITIONAL_TO_ASCII", UIDNA_NONTRANSITIONAL_TO_ASCII, CONST_CS | CONST_PERSISTENT);
+
+ /* Option for nontransitional processing in ToUnicode().
+ * By default, ToUnicode() uses transitional processing.
+ * Ignored by the IDNA2003 implementation. */
+ REGISTER_LONG_CONSTANT("IDNA_NONTRANSITIONAL_TO_UNICODE", UIDNA_NONTRANSITIONAL_TO_UNICODE, CONST_CS | CONST_PERSISTENT);
+#endif
+
+ /* VARIANTS */
+ REGISTER_LONG_CONSTANT("INTL_IDNA_VARIANT_2003", INTL_IDN_VARIANT_2003, CONST_CS | CONST_PERSISTENT);
+#ifdef HAVE_46_API
+ REGISTER_LONG_CONSTANT("INTL_IDNA_VARIANT_UTS46", INTL_IDN_VARIANT_UTS46, CONST_CS | CONST_PERSISTENT);
+#endif
+
+#ifdef HAVE_46_API
+ /* PINFO ERROR CODES */
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_EMPTY_LABEL", UIDNA_ERROR_EMPTY_LABEL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_LABEL_TOO_LONG", UIDNA_ERROR_LABEL_TOO_LONG, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_DOMAIN_NAME_TOO_LONG", UIDNA_ERROR_DOMAIN_NAME_TOO_LONG, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_LEADING_HYPHEN", UIDNA_ERROR_LEADING_HYPHEN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_TRAILING_HYPHEN", UIDNA_ERROR_TRAILING_HYPHEN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_HYPHEN_3_4", UIDNA_ERROR_HYPHEN_3_4, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_LEADING_COMBINING_MARK", UIDNA_ERROR_LEADING_COMBINING_MARK, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_DISALLOWED", UIDNA_ERROR_DISALLOWED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_PUNYCODE", UIDNA_ERROR_PUNYCODE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_LABEL_HAS_DOT", UIDNA_ERROR_LABEL_HAS_DOT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_INVALID_ACE_LABEL", UIDNA_ERROR_INVALID_ACE_LABEL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_BIDI", UIDNA_ERROR_BIDI, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IDNA_ERROR_CONTEXTJ", UIDNA_ERROR_CONTEXTJ, CONST_CS | CONST_PERSISTENT);
+#endif
}
/* }}} */
@@ -54,11 +110,100 @@ enum {
INTL_IDN_TO_UTF8
};
-static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS, int mode)
+/* like INTL_CHECK_STATUS, but as a function and varying the name of the func */
+static int php_intl_idn_check_status(UErrorCode err, const char *msg, int mode TSRMLS_DC)
+{
+ intl_error_set_code(NULL, err TSRMLS_CC);
+ if (U_FAILURE(err)) {
+ char *buff;
+ spprintf(&buff, 0, "%s: %s",
+ mode == INTL_IDN_TO_ASCII ? "idn_to_ascii" : "idn_to_utf8",
+ msg);
+ intl_error_set_custom_msg(NULL, buff, 1 TSRMLS_CC);
+ efree(buff);
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+static inline void php_intl_bad_args(const char *msg, int mode TSRMLS_DC)
+{
+ php_intl_idn_check_status(U_ILLEGAL_ARGUMENT_ERROR, msg, mode TSRMLS_CC);
+}
+
+#ifdef HAVE_46_API
+static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS,
+ const char *domain, int domain_len, uint32_t option, int mode, zval *idna_info)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UIDNA *uts46;
+ int32_t len;
+ int32_t buffer_capac = 255; /* no domain name may exceed this */
+ char *buffer = emalloc(buffer_capac);
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ int buffer_used = 0;
+
+ uts46 = uidna_openUTS46(option, &status);
+ if (php_intl_idn_check_status(status, "failed to open UIDNA instance",
+ mode TSRMLS_CC) == FAILURE) {
+ efree(buffer);
+ RETURN_FALSE;
+ }
+
+ if (mode == INTL_IDN_TO_ASCII) {
+ len = uidna_nameToASCII_UTF8(uts46, domain, (int32_t)domain_len,
+ buffer, buffer_capac, &info, &status);
+ } else {
+ len = uidna_nameToUnicodeUTF8(uts46, domain, (int32_t)domain_len,
+ buffer, buffer_capac, &info, &status);
+ }
+ if (php_intl_idn_check_status(status, "failed to convert name",
+ mode TSRMLS_CC) == FAILURE) {
+ uidna_close(uts46);
+ efree(buffer);
+ RETURN_FALSE;
+ }
+ if (len >= 255) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "ICU returned an unexpected length");
+ }
+
+ buffer[len] = '\0';
+
+ if (info.errors == 0) {
+ RETVAL_STRINGL(buffer, len, 0);
+ buffer_used = 1;
+ } else {
+ RETVAL_FALSE;
+ }
+
+ if (idna_info) {
+ if (buffer_used) { /* used in return_value then */
+ zval_addref_p(return_value);
+ add_assoc_zval_ex(idna_info, "result", sizeof("result"), return_value);
+ } else {
+ zval *zv;
+ ALLOC_INIT_ZVAL(zv);
+ ZVAL_STRINGL(zv, buffer, len, 0);
+ buffer_used = 1;
+ add_assoc_zval_ex(idna_info, "result", sizeof("result"), zv);
+ }
+ add_assoc_bool_ex(idna_info, "isTransitionalDifferent",
+ sizeof("isTransitionalDifferent"), info.isTransitionalDifferent);
+ add_assoc_long_ex(idna_info, "errors", sizeof("errors"), (long)info.errors);
+ }
+
+ if (!buffer_used) {
+ efree(buffer);
+ }
+
+ uidna_close(uts46);
+}
+#endif
+
+static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS,
+ const char *domain, int domain_len, uint32_t option, int mode)
{
- unsigned char* domain;
- int domain_len;
- long option = 0;
UChar* ustring = NULL;
int ustring_len = 0;
UErrorCode status;
@@ -67,18 +212,9 @@ static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS, int mode)
UChar converted[MAXPATHLEN];
int32_t converted_ret_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", (char **)&domain, &domain_len, &option) == FAILURE) {
- return;
- }
-
- if (domain_len < 1) {
- intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "idn_to_ascii: empty domain name", 0 TSRMLS_CC );
- RETURN_FALSE;
- }
-
/* convert the string to UTF-16. */
status = U_ZERO_ERROR;
- intl_convert_utf8_to_utf16(&ustring, &ustring_len, (char*) domain, domain_len, &status );
+ intl_convert_utf8_to_utf16(&ustring, &ustring_len, domain, domain_len, &status);
if (U_FAILURE(status)) {
intl_error_set_code(NULL, status TSRMLS_CC);
@@ -123,20 +259,84 @@ static void php_intl_idn_to(INTERNAL_FUNCTION_PARAMETERS, int mode)
RETURN_STRINGL(((char *)converted_utf8), converted_utf8_len, 0);
}
-/* {{{ proto int idn_to_ascii(string domain[, int options])
+static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode)
+{
+ char *domain;
+ int domain_len;
+ long option = 0,
+ variant = INTL_IDN_VARIANT_2003;
+ zval *idna_info = NULL;
+
+ intl_error_reset(NULL TSRMLS_CC);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|llz",
+ &domain, &domain_len, &option, &variant, &idna_info) == FAILURE) {
+ php_intl_bad_args("bad arguments", mode TSRMLS_CC);
+ RETURN_NULL(); /* don't set FALSE because that's not the way it was before... */
+ }
+
+#ifdef HAVE_46_API
+ if (variant != INTL_IDN_VARIANT_2003 && variant != INTL_IDN_VARIANT_UTS46) {
+ php_intl_bad_args("invalid variant, must be one of {"
+ "INTL_IDNA_VARIANT_2003, INTL_IDNA_VARIANT_UTS46}", mode TSRMLS_CC);
+ RETURN_FALSE;
+ }
+#else
+ if (variant != INTL_IDN_VARIANT_2003) {
+ php_intl_bad_args("invalid variant, PHP was compiled against "
+ "an old version of ICU and only supports INTL_IDN_VARIANT_2003",
+ mode TSRMLS_CC);
+ RETURN_FALSE;
+ }
+#endif
+
+ if (domain_len < 1) {
+ php_intl_bad_args("empty domain name", mode TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ if (domain_len > INT32_MAX - 1) {
+ php_intl_bad_args("domain name too large", mode TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ /* don't check options; it wasn't checked before */
+
+ if (idna_info != NULL) {
+ if (variant == INTL_IDN_VARIANT_2003) {
+ php_error_docref0(NULL TSRMLS_CC, E_NOTICE,
+ "4 arguments were provided, but INTL_IDNA_VARIANT_2003 only "
+ "takes 3 - extra argument ignored");
+ } else {
+ zval_dtor(idna_info);
+ array_init(idna_info);
+ }
+ }
+
+ if (variant == INTL_IDN_VARIANT_2003) {
+ php_intl_idn_to(INTERNAL_FUNCTION_PARAM_PASSTHRU,
+ domain, domain_len, (uint32_t)option, mode);
+ }
+#ifdef HAVE_46_API
+ else {
+ php_intl_idn_to_46(INTERNAL_FUNCTION_PARAM_PASSTHRU, domain, domain_len,
+ (uint32_t)option, mode, idna_info);
+ }
+#endif
+}
+
+/* {{{ proto int idn_to_ascii(string domain[, int options[, int variant[, array &idna_info]]])
Converts an Unicode domain to ASCII representation, as defined in the IDNA RFC */
PHP_FUNCTION(idn_to_ascii)
{
- php_intl_idn_to(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_ASCII);
+ php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_ASCII);
}
/* }}} */
-/* {{{ proto int idn_to_utf8(string domain[, int options])
+/* {{{ proto int idn_to_utf8(string domain[, int options[, int variant[, array &idna_info]]])
Converts an ASCII representation of the domain to Unicode (UTF-8), as defined in the IDNA RFC */
PHP_FUNCTION(idn_to_utf8)
{
- php_intl_idn_to(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_UTF8);
+ php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_UTF8);
}
/* }}} */
diff --git a/ext/intl/intl_convert.c b/ext/intl/intl_convert.c
index 33f1730625..92cdc4cef4 100644
--- a/ext/intl/intl_convert.c
+++ b/ext/intl/intl_convert.c
@@ -67,7 +67,7 @@ void intl_convert_utf8_to_utf16(
return;
}
- /* Bail out if an unexpected error occured.
+ /* Bail out if an unexpected error occurred.
* (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
* (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty).
*/
@@ -119,7 +119,7 @@ void intl_convert_utf16_to_utf8(
*status = U_ZERO_ERROR;
u_strToUTF8( NULL, 0, &dst_len, src, src_len, status );
- /* Bail out if an unexpected error occured.
+ /* Bail out if an unexpected error occurred.
* (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
* (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty).
*/
diff --git a/ext/intl/locale/locale_class.c b/ext/intl/locale/locale_class.c
index d433bf5839..432cfb28fc 100644
--- a/ext/intl/locale/locale_class.c
+++ b/ext/intl/locale/locale_class.c
@@ -66,7 +66,7 @@ ZEND_END_ARG_INFO()
* Every 'Locale' class method has an entry in this table
*/
-function_entry Locale_class_functions[] = {
+zend_function_entry Locale_class_functions[] = {
ZEND_FENTRY( getDefault, zif_locale_get_default , locale_0_args , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
ZEND_FENTRY( setDefault, zif_locale_set_default , locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
ZEND_FENTRY( getPrimaryLanguage, ZEND_FN( locale_get_primary_language ), locale_1_arg , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
diff --git a/ext/intl/msgformat/msgformat_class.c b/ext/intl/msgformat/msgformat_class.c
index d6ba9b1c67..bb3b55f39c 100644
--- a/ext/intl/msgformat/msgformat_class.c
+++ b/ext/intl/msgformat/msgformat_class.c
@@ -62,6 +62,7 @@ zend_object_value MessageFormatter_object_create(zend_class_entry *ce TSRMLS_DC)
intern = ecalloc( 1, sizeof(MessageFormatter_object) );
msgformat_data_init( &intern->mf_data TSRMLS_CC );
zend_object_std_init( &intern->zo, ce TSRMLS_CC );
+ object_properties_init(&intern->zo, ce);
retval.handle = zend_objects_store_put(
intern,
@@ -140,7 +141,7 @@ ZEND_END_ARG_INFO()
/* {{{ MessageFormatter_class_functions
* Every 'MessageFormatter' class method has an entry in this table
*/
-static function_entry MessageFormatter_class_functions[] = {
+static zend_function_entry MessageFormatter_class_functions[] = {
PHP_ME( MessageFormatter, __construct, arginfo_messageformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
ZEND_FENTRY( create, ZEND_FN( msgfmt_create ), arginfo_messageformatter___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
PHP_NAMED_FE( format, ZEND_FN( msgfmt_format ), arginfo_messageformatter_format )
diff --git a/ext/intl/normalizer/normalizer_class.c b/ext/intl/normalizer/normalizer_class.c
index c5adf781ad..154d877e3f 100644
--- a/ext/intl/normalizer/normalizer_class.c
+++ b/ext/intl/normalizer/normalizer_class.c
@@ -41,7 +41,7 @@ ZEND_END_ARG_INFO()
* Every 'Normalizer' class method has an entry in this table
*/
-function_entry Normalizer_class_functions[] = {
+zend_function_entry Normalizer_class_functions[] = {
ZEND_FENTRY( normalize, ZEND_FN( normalizer_normalize ), normalizer_3_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
ZEND_FENTRY( isNormalized, ZEND_FN( normalizer_is_normalized ), normalizer_3_args, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
PHP_FE_END
diff --git a/ext/intl/normalizer/normalizer_normalize.c b/ext/intl/normalizer/normalizer_normalize.c
index 466ab97e12..f46285e9d9 100644
--- a/ext/intl/normalizer/normalizer_normalize.c
+++ b/ext/intl/normalizer/normalizer_normalize.c
@@ -110,7 +110,7 @@ PHP_FUNCTION( normalizer_normalize )
/* normalize */
size_needed = unorm_normalize( uinput, uinput_len, form, (int32_t) 0 /* options */, uret_buf, uret_len, &status);
- /* Bail out if an unexpected error occured.
+ /* Bail out if an unexpected error occurred.
* (U_BUFFER_OVERFLOW_ERROR means that *target buffer is not large enough).
* (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty).
*/
@@ -133,7 +133,7 @@ PHP_FUNCTION( normalizer_normalize )
/* try normalize again */
size_needed = unorm_normalize( uinput, uinput_len, form, (int32_t) 0 /* options */, uret_buf, uret_len, &status);
- /* Bail out if an unexpected error occured. */
+ /* Bail out if an unexpected error occurred. */
if( U_FAILURE(status) ) {
/* Set error messages. */
intl_error_set_custom_msg( NULL,"Error normalizing string", 0 TSRMLS_CC );
@@ -234,7 +234,7 @@ PHP_FUNCTION( normalizer_is_normalized )
efree( uinput );
- /* Bail out if an unexpected error occured. */
+ /* Bail out if an unexpected error occurred. */
if( U_FAILURE(status) ) {
/* Set error messages. */
intl_error_set_custom_msg( NULL,"Error testing if string is the given normalization form.", 0 TSRMLS_CC );
diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c
index dc6c0fffa3..90e3573c1b 100644
--- a/ext/intl/php_intl.c
+++ b/ext/intl/php_intl.c
@@ -64,8 +64,19 @@
#include "resourcebundle/resourcebundle_class.h"
+#include "transliterator/transliterator.h"
+#include "transliterator/transliterator_class.h"
+#include "transliterator/transliterator_methods.h"
+
#include "idn/idn.h"
+#if U_ICU_VERSION_MAJOR_NUM * 1000 + U_ICU_VERSION_MINOR_NUM >= 4002
+# include "spoofchecker/spoofchecker_class.h"
+# include "spoofchecker/spoofchecker.h"
+# include "spoofchecker/spoofchecker_create.h"
+# include "spoofchecker/spoofchecker_main.h"
+#endif
+
#include "msgformat/msgformat.h"
#include "common/common_error.h"
@@ -324,13 +335,15 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_idn_to_ascii, 0, 0, 1)
ZEND_ARG_INFO(0, domain)
ZEND_ARG_INFO(0, option)
- ZEND_ARG_INFO(0, status)
+ ZEND_ARG_INFO(0, variant)
+ ZEND_ARG_INFO(1, idn_info)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_idn_to_utf8, 0, 0, 1)
ZEND_ARG_INFO(0, domain)
ZEND_ARG_INFO(0, option)
- ZEND_ARG_INFO(0, status)
+ ZEND_ARG_INFO(0, variant)
+ ZEND_ARG_INFO(1, idn_info)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_create_proc, 0, 0, 2 )
@@ -361,6 +374,33 @@ ZEND_BEGIN_ARG_INFO_EX( arginfo_resourcebundle_get_error_message_proc, 0, 0, 1 )
ZEND_ARG_INFO( 0, bundle )
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX( arginfo_transliterator_void, 0, 0, 0 )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( arginfo_transliterator_create, 0, 0, 1 )
+ ZEND_ARG_INFO( 0, id )
+ ZEND_ARG_INFO( 0, direction )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( arginfo_transliterator_create_from_rules, 0, 0, 1 )
+ ZEND_ARG_INFO( 0, rules )
+ ZEND_ARG_INFO( 0, direction )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( arginfo_transliterator_create_inverse, 0, 0, 1 )
+ ZEND_ARG_OBJ_INFO( 0, orig_trans, Transliterator, 0 )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( arginfo_transliterator_transliterate, 0, 0, 2 )
+ ZEND_ARG_INFO( 0, trans )
+ ZEND_ARG_INFO( 0, subject )
+ ZEND_ARG_INFO( 0, start )
+ ZEND_ARG_INFO( 0, end )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( arginfo_transliterator_error, 0, 0, 1 )
+ ZEND_ARG_OBJ_INFO( 0, trans, Transliterator, 0 )
+ZEND_END_ARG_INFO()
/* }}} */
@@ -480,6 +520,15 @@ zend_function_entry intl_functions[] = {
PHP_FE( resourcebundle_locales, arginfo_resourcebundle_locales_proc )
PHP_FE( resourcebundle_get_error_code, arginfo_resourcebundle_get_error_code_proc )
PHP_FE( resourcebundle_get_error_message, arginfo_resourcebundle_get_error_message_proc )
+
+ /* Transliterator functions */
+ PHP_FE( transliterator_create, arginfo_transliterator_create )
+ PHP_FE( transliterator_create_from_rules, arginfo_transliterator_create_from_rules )
+ PHP_FE( transliterator_list_ids, arginfo_transliterator_void )
+ PHP_FE( transliterator_create_inverse, arginfo_transliterator_create_inverse)
+ PHP_FE( transliterator_transliterate, arginfo_transliterator_transliterate )
+ PHP_FE( transliterator_get_error_code, arginfo_transliterator_error )
+ PHP_FE( transliterator_get_error_message, arginfo_transliterator_error )
/* common functions */
PHP_FE( intl_get_error_code, intl_0_args )
@@ -585,12 +634,25 @@ PHP_MINIT_FUNCTION( intl )
/* Register 'ResourceBundle' PHP class */
resourcebundle_register_class( TSRMLS_C);
+ /* Register 'Transliterator' PHP class */
+ transliterator_register_Transliterator_class( TSRMLS_C );
+
+ /* Register Transliterator constants */
+ transliterator_register_constants( INIT_FUNC_ARGS_PASSTHRU );
+
/* Expose ICU error codes to PHP scripts. */
intl_expose_icu_error_codes( INIT_FUNC_ARGS_PASSTHRU );
/* Expose IDN constants to PHP scripts. */
idn_register_constants(INIT_FUNC_ARGS_PASSTHRU);
+#if U_ICU_VERSION_MAJOR_NUM * 1000 + U_ICU_VERSION_MINOR_NUM >= 4002
+ /* Register 'Spoofchecker' PHP class */
+ spoofchecker_register_Spoofchecker_class( TSRMLS_C );
+
+ /* Expose Spoofchecker constants to PHP scripts */
+ spoofchecker_register_constants( INIT_FUNC_ARGS_PASSTHRU );
+#endif
/* Global error handling. */
intl_error_init( NULL TSRMLS_CC );
diff --git a/ext/intl/resourcebundle/resourcebundle.c b/ext/intl/resourcebundle/resourcebundle.c
index 237d6c8d1e..6d39dfb7e0 100644
--- a/ext/intl/resourcebundle/resourcebundle.c
+++ b/ext/intl/resourcebundle/resourcebundle.c
@@ -1,4 +1,4 @@
- /*
+/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c
index 9c0459e1a3..a6a73f5f04 100644
--- a/ext/intl/resourcebundle/resourcebundle_class.c
+++ b/ext/intl/resourcebundle/resourcebundle_class.c
@@ -63,6 +63,7 @@ static zend_object_value ResourceBundle_object_create( zend_class_entry *ce TSRM
rb = ecalloc( 1, sizeof(ResourceBundle_object) );
zend_object_std_init( (zend_object *) rb, ce TSRMLS_CC );
+ object_properties_init((zend_object *) rb, ce);
intl_error_init( INTL_DATA_ERROR_P(rb) TSRMLS_CC );
rb->me = NULL;
@@ -91,7 +92,7 @@ static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
intl_error_reset( NULL TSRMLS_CC );
- if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|b",
+ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s!s!|b",
&locale, &locale_len, &bundlename, &bundlename_len, &fallback ) == FAILURE )
{
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
@@ -101,6 +102,10 @@ static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
}
INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
+
+ if (locale == NULL) {
+ locale = INTL_G(default_locale);
+ }
if (fallback) {
rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
@@ -110,13 +115,17 @@ static void resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS)
INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle");
- if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
- intl_errors_set_code( NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC );
- spprintf( &pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource '%s' without fallback from %s to %s",
- bundlename, locale, ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)) );
- intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC );
+ if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING ||
+ INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
+ intl_errors_set_code(NULL, INTL_DATA_ERROR_CODE(rb) TSRMLS_CC);
+ spprintf(&pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource "
+ "'%s' without fallback from %s to %s",
+ bundlename ? bundlename : "(default data)", locale,
+ ures_getLocaleByType(
+ rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)));
+ intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb), pbuf, 1 TSRMLS_CC);
efree(pbuf);
- zval_dtor( return_value );
+ zval_dtor(return_value);
RETURN_NULL();
}
}
@@ -398,7 +407,7 @@ PHP_FUNCTION( resourcebundle_get_error_message )
/* {{{ ResourceBundle_class_functions
* Every 'ResourceBundle' class method has an entry in this table
*/
-static function_entry ResourceBundle_class_functions[] = {
+static zend_function_entry ResourceBundle_class_functions[] = {
PHP_ME( ResourceBundle, __construct, arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR )
ZEND_NAMED_ME( create, ZEND_FN( resourcebundle_create ), arginfo_resourcebundle___construct, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC )
ZEND_NAMED_ME( get, ZEND_FN(resourcebundle_get), arginfo_resourcebundle_get, ZEND_ACC_PUBLIC )
diff --git a/ext/intl/spoofchecker/spoofchecker.c b/ext/intl/spoofchecker/spoofchecker.c
new file mode 100644
index 0000000000..42a014a90e
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker.c
@@ -0,0 +1,60 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "spoofchecker_class.h"
+#include "spoofchecker.h"
+
+#include <unicode/uspoof.h>
+
+
+/* {{{ spoofchecker_register_constants
+ * Register constants
+ */
+void spoofchecker_register_constants(INIT_FUNC_ARGS)
+{
+ if (!Spoofchecker_ce_ptr)
+ {
+ zend_error(E_ERROR, "Spoofchecker class not defined");
+ return;
+ }
+
+ #define SPOOFCHECKER_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long(Spoofchecker_ce_ptr, ZEND_STRS( #x ) - 1, USPOOF_##x TSRMLS_CC);
+
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(SINGLE_SCRIPT_CONFUSABLE)
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(MIXED_SCRIPT_CONFUSABLE)
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(WHOLE_SCRIPT_CONFUSABLE)
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(ANY_CASE)
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(SINGLE_SCRIPT)
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(INVISIBLE)
+ SPOOFCHECKER_EXPOSE_CLASS_CONST(CHAR_LIMIT)
+
+
+ #undef SPOOFCHECKER_EXPOSE_CLASS_CONST
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/spoofchecker/spoofchecker.h b/ext/intl/spoofchecker/spoofchecker.h
new file mode 100644
index 0000000000..f976d639ac
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker.h
@@ -0,0 +1,24 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef SPOOFCHECKER_SPOOFCHECKER_H
+#define SPOOFCHECKER_SPOOFCHECKER_H
+
+#include <php.h>
+
+void spoofchecker_register_constants(INIT_FUNC_ARGS);
+
+#endif // SPOOFCHECKER_SPOOFCHECKER_H
diff --git a/ext/intl/spoofchecker/spoofchecker_class.c b/ext/intl/spoofchecker/spoofchecker_class.c
new file mode 100644
index 0000000000..6c2b79034d
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker_class.c
@@ -0,0 +1,210 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "spoofchecker_class.h"
+#include "spoofchecker_main.h"
+#include "spoofchecker_create.h"
+#include "php_intl.h"
+#include "intl_error.h"
+
+#include <unicode/uspoof.h>
+
+zend_class_entry *Spoofchecker_ce_ptr = NULL;
+static zend_object_handlers Spoofchecker_handlers;
+
+/*
+ * Auxiliary functions needed by objects of 'Spoofchecker' class
+ */
+
+/* {{{ Spoofchecker_objects_dtor */
+static void Spoofchecker_objects_dtor(
+ void *object,
+ zend_object_handle handle TSRMLS_DC)
+{
+ zend_objects_destroy_object(object, handle TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ Spoofchecker_objects_free */
+void Spoofchecker_objects_free(zend_object *object TSRMLS_DC)
+{
+ Spoofchecker_object* co = (Spoofchecker_object*)object;
+
+ zend_object_std_dtor(&co->zo TSRMLS_CC);
+
+ spoofchecker_object_destroy(co TSRMLS_CC);
+
+ efree(co);
+}
+/* }}} */
+
+/* {{{ Spoofchecker_object_create */
+zend_object_value Spoofchecker_object_create(
+ zend_class_entry *ce TSRMLS_DC)
+{
+ zend_object_value retval;
+ Spoofchecker_object* intern;
+
+ intern = ecalloc(1, sizeof(Spoofchecker_object));
+ intl_error_init(SPOOFCHECKER_ERROR_P(intern) TSRMLS_CC);
+ zend_object_std_init(&intern->zo, ce TSRMLS_CC);
+ object_properties_init(&intern->zo, ce);
+
+ retval.handle = zend_objects_store_put(
+ intern,
+ Spoofchecker_objects_dtor,
+ (zend_objects_free_object_storage_t)Spoofchecker_objects_free,
+ NULL TSRMLS_CC);
+
+ retval.handlers = &Spoofchecker_handlers;
+
+ return retval;
+}
+/* }}} */
+
+/*
+ * 'Spoofchecker' class registration structures & functions
+ */
+
+/* {{{ Spoofchecker methods arguments info */
+ZEND_BEGIN_ARG_INFO_EX(spoofchecker_0_args, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(spoofchecker_set_checks, 0, 0, 1)
+ ZEND_ARG_INFO(0, checks)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(spoofchecker_set_allowed_locales, 0, 0, 1)
+ ZEND_ARG_INFO(0, locale_list)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(spoofchecker_is_suspicous, 0, 0, 1)
+ ZEND_ARG_INFO(0, text)
+ ZEND_ARG_INFO(1, error)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(spoofchecker_are_confusable, 0, 0, 2)
+ ZEND_ARG_INFO(0, s1)
+ ZEND_ARG_INFO(0, s2)
+ ZEND_ARG_INFO(1, error)
+ZEND_END_ARG_INFO()
+
+/* }}} */
+
+/* {{{ Spoofchecker_class_functions
+ * Every 'Spoofchecker' class method has an entry in this table
+ */
+
+zend_function_entry Spoofchecker_class_functions[] = {
+ PHP_ME(Spoofchecker, __construct, spoofchecker_0_args, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+ PHP_ME(Spoofchecker, isSuspicious, spoofchecker_is_suspicous, ZEND_ACC_PUBLIC)
+ PHP_ME(Spoofchecker, areConfusable, spoofchecker_are_confusable, ZEND_ACC_PUBLIC)
+ PHP_ME(Spoofchecker, setAllowedLocales, spoofchecker_set_allowed_locales, ZEND_ACC_PUBLIC)
+ PHP_ME(Spoofchecker, setChecks, spoofchecker_set_checks, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+/* }}} */
+
+static zend_object_value spoofchecker_clone_obj(zval *object TSRMLS_DC) /* {{{ */
+{
+ zend_object_value new_obj_val;
+ zend_object_handle handle = Z_OBJ_HANDLE_P(object);
+ Spoofchecker_object *sfo, *new_sfo;
+
+ sfo = (Spoofchecker_object *) zend_object_store_get_object(object TSRMLS_CC);
+ intl_error_reset(SPOOFCHECKER_ERROR_P(sfo) TSRMLS_CC);
+
+ new_obj_val = Spoofchecker_ce_ptr->create_object(Z_OBJCE_P(object) TSRMLS_CC);
+ new_sfo = (Spoofchecker_object *)zend_object_store_get_object_by_handle(new_obj_val.handle TSRMLS_CC);
+ /* clone standard parts */
+ zend_objects_clone_members(&new_sfo->zo, new_obj_val, &sfo->zo, handle TSRMLS_CC);
+ /* clone internal object */
+ new_sfo->uspoof = uspoof_clone(sfo->uspoof, SPOOFCHECKER_ERROR_CODE_P(new_sfo));
+ if(U_FAILURE(SPOOFCHECKER_ERROR_CODE(new_sfo))) {
+ /* set up error in case error handler is interested */
+ intl_error_set( NULL, SPOOFCHECKER_ERROR_CODE(new_sfo), "Failed to clone SpoofChecker object", 0 TSRMLS_CC );
+ Spoofchecker_objects_dtor(new_sfo, new_obj_val.handle TSRMLS_CC); /* free new object */
+ zend_error(E_ERROR, "Failed to clone SpoofChecker object");
+ }
+ return new_obj_val;
+}
+/* }}} */
+
+/* {{{ spoofchecker_register_Spoofchecker_class
+ * Initialize 'Spoofchecker' class
+ */
+void spoofchecker_register_Spoofchecker_class(TSRMLS_D)
+{
+ zend_class_entry ce;
+
+ /* Create and register 'Spoofchecker' class. */
+ INIT_CLASS_ENTRY(ce, "Spoofchecker", Spoofchecker_class_functions);
+ ce.create_object = Spoofchecker_object_create;
+ Spoofchecker_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
+
+ memcpy(&Spoofchecker_handlers, zend_get_std_object_handlers(),
+ sizeof Spoofchecker_handlers);
+ Spoofchecker_handlers.clone_obj = spoofchecker_clone_obj;
+
+ if (!Spoofchecker_ce_ptr) {
+ zend_error(E_ERROR,
+ "Spoofchecker: attempt to create properties "
+ "on a non-registered class.");
+ return;
+ }
+}
+/* }}} */
+
+/* {{{ void spoofchecker_object_init( Spoofchecker_object* co )
+ * Initialize internals of Spoofchecker_object.
+ * Must be called before any other call to 'spoofchecker_object_...' functions.
+ */
+void spoofchecker_object_init(Spoofchecker_object* co TSRMLS_DC)
+{
+ if (!co) {
+ return;
+ }
+
+ intl_error_init(SPOOFCHECKER_ERROR_P(co) TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ void spoofchecker_object_destroy( Spoofchecker_object* co )
+ * Clean up mem allocted by internals of Spoofchecker_object
+ */
+void spoofchecker_object_destroy(Spoofchecker_object* co TSRMLS_DC)
+{
+ if (!co) {
+ return;
+ }
+
+ if (co->uspoof) {
+ uspoof_close(co->uspoof);
+ co->uspoof = NULL;
+ }
+
+ intl_error_reset(SPOOFCHECKER_ERROR_P(co) TSRMLS_CC);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/spoofchecker/spoofchecker_class.h b/ext/intl/spoofchecker/spoofchecker_class.h
new file mode 100644
index 0000000000..ec043d9dc8
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker_class.h
@@ -0,0 +1,76 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef SPOOFCHECKER_CLASS_H
+#define SPOOFCHECKER_CLASS_H
+
+#include <php.h>
+
+#include "intl_common.h"
+#include "spoofchecker_create.h"
+#include "intl_error.h"
+#include "intl_data.h"
+
+#include <unicode/uspoof.h>
+
+typedef struct {
+ zend_object zo;
+
+ // error handling
+ intl_error err;
+
+ // ICU Spoofchecker
+ USpoofChecker* uspoof;
+} Spoofchecker_object;
+
+#define SPOOFCHECKER_ERROR(co) (co)->err
+#define SPOOFCHECKER_ERROR_P(co) &(SPOOFCHECKER_ERROR(co))
+
+#define SPOOFCHECKER_ERROR_CODE(co) INTL_ERROR_CODE(SPOOFCHECKER_ERROR(co))
+#define SPOOFCHECKER_ERROR_CODE_P(co) &(INTL_ERROR_CODE(SPOOFCHECKER_ERROR(co)))
+
+void spoofchecker_register_Spoofchecker_class(TSRMLS_D);
+
+void spoofchecker_object_init(Spoofchecker_object* co TSRMLS_DC);
+void spoofchecker_object_destroy(Spoofchecker_object* co TSRMLS_DC);
+
+extern zend_class_entry *Spoofchecker_ce_ptr;
+
+/* Auxiliary macros */
+
+#define SPOOFCHECKER_METHOD_INIT_VARS \
+ zval* object = getThis(); \
+ Spoofchecker_object* co = NULL; \
+ intl_error_reset(NULL TSRMLS_CC); \
+
+#define SPOOFCHECKER_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT(Spoofchecker, co)
+#define SPOOFCHECKER_METHOD_FETCH_OBJECT \
+ SPOOFCHECKER_METHOD_FETCH_OBJECT_NO_CHECK; \
+ if (co->uspoof == NULL) { \
+ intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR, \
+ "Found unconstructed Spoofchecker", 0 TSRMLS_CC); \
+ RETURN_FALSE; \
+ }
+
+// Macro to check return value of a ucol_* function call.
+#define SPOOFCHECKER_CHECK_STATUS(co, msg) \
+ intl_error_set_code(NULL, SPOOFCHECKER_ERROR_CODE(co) TSRMLS_CC); \
+ if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { \
+ intl_errors_set_custom_msg(SPOOFCHECKER_ERROR_P(co), msg, 0 TSRMLS_CC); \
+ RETURN_FALSE; \
+ } \
+
+#endif // #ifndef SPOOFCHECKER_CLASS_H
diff --git a/ext/intl/spoofchecker/spoofchecker_create.c b/ext/intl/spoofchecker/spoofchecker_create.c
new file mode 100644
index 0000000000..cf0173f997
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker_create.c
@@ -0,0 +1,59 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "spoofchecker_class.h"
+#include "spoofchecker_create.h"
+#include "intl_data.h"
+
+/* {{{ proto Spoofchecker Spoofchecker::__construct()
+ * Spoofchecker object constructor.
+ */
+PHP_METHOD(Spoofchecker, __construct)
+{
+ int checks;
+ SPOOFCHECKER_METHOD_INIT_VARS;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ SPOOFCHECKER_METHOD_FETCH_OBJECT_NO_CHECK;
+
+ co->uspoof = uspoof_open(SPOOFCHECKER_ERROR_CODE_P(co));
+ INTL_CTOR_CHECK_STATUS(co, "spoofchecker: unable to open ICU Spoof Checker");
+
+ /* Single-script enforcement is on by default. This fails for languages
+ like Japanese that legally use multiple scripts within a single word,
+ so we turn it off.
+ */
+ checks = uspoof_getChecks(co->uspoof, SPOOFCHECKER_ERROR_CODE_P(co));
+ uspoof_setChecks(co->uspoof, checks & ~USPOOF_SINGLE_SCRIPT, SPOOFCHECKER_ERROR_CODE_P(co));
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/spoofchecker/spoofchecker_create.h b/ext/intl/spoofchecker/spoofchecker_create.h
new file mode 100644
index 0000000000..313faab8a3
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker_create.h
@@ -0,0 +1,24 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef SPOOFCHECKER_CREATE_H
+#define SPOOFCHECKER_CREATE_H
+
+#include <php.h>
+
+PHP_METHOD(Spoofchecker, __construct);
+
+#endif // SPOOFCHECKER_CREATE_H
diff --git a/ext/intl/spoofchecker/spoofchecker_main.c b/ext/intl/spoofchecker/spoofchecker_main.c
new file mode 100644
index 0000000000..c37b9186a2
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker_main.c
@@ -0,0 +1,142 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "spoofchecker_class.h"
+
+/* {{{ proto bool Spoofchecker::isSuspicious( string text[, int &error_code ] )
+ * Checks if a given text contains any suspicious characters
+ */
+PHP_METHOD(Spoofchecker, isSuspicious)
+{
+ int ret;
+ char *text;
+ int text_len;
+ zval *error_code = NULL;
+ SPOOFCHECKER_METHOD_INIT_VARS;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &text, &text_len, &error_code)) {
+ return;
+ }
+
+ SPOOFCHECKER_METHOD_FETCH_OBJECT;
+
+ ret = uspoof_checkUTF8(co->uspoof, text, text_len, NULL, SPOOFCHECKER_ERROR_CODE_P(co));
+
+ if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co)));
+ RETURN_TRUE;
+ }
+
+ if (error_code) {
+ zval_dtor(error_code);
+ ZVAL_LONG(error_code, ret);
+ }
+ RETVAL_BOOL(ret != 0);
+}
+/* }}} */
+
+/* {{{ proto bool Spoofchecker::areConfusable( string str1, string str2[, int &error_code ] )
+ * Checks if a given text contains any confusable characters
+ */
+PHP_METHOD(Spoofchecker, areConfusable)
+{
+ int ret;
+ char *s1, *s2;
+ int s1_len, s2_len;
+ zval *error_code = NULL;
+ SPOOFCHECKER_METHOD_INIT_VARS;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &s1, &s1_len,
+ &s2, &s2_len, &error_code)) {
+ return;
+ }
+
+ SPOOFCHECKER_METHOD_FETCH_OBJECT;
+
+ ret = uspoof_areConfusableUTF8(co->uspoof, s1, s1_len, s2, s2_len, SPOOFCHECKER_ERROR_CODE_P(co));
+
+ if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co)));
+ RETURN_TRUE;
+ }
+
+ if (error_code) {
+ zval_dtor(error_code);
+ ZVAL_LONG(error_code, ret);
+ }
+ RETVAL_BOOL(ret != 0);
+}
+/* }}} */
+
+/* {{{ proto void Spoofchecker::setAllowedLocales( string locales )
+ * Locales to use when running checks
+ */
+PHP_METHOD(Spoofchecker, setAllowedLocales)
+{
+ char *locales;
+ int locales_len;
+ SPOOFCHECKER_METHOD_INIT_VARS;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &locales, &locales_len)) {
+ return;
+ }
+
+ SPOOFCHECKER_METHOD_FETCH_OBJECT;
+
+ uspoof_setAllowedLocales(co->uspoof, locales, SPOOFCHECKER_ERROR_CODE_P(co));
+
+ if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co)));
+ return;
+ }
+}
+/* }}} */
+
+/* {{{ proto void Spoofchecker::setChecks( int checks )
+ * Set the checks to run
+ */
+PHP_METHOD(Spoofchecker, setChecks)
+{
+ long checks;
+ SPOOFCHECKER_METHOD_INIT_VARS;
+
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &checks)) {
+ return;
+ }
+
+ SPOOFCHECKER_METHOD_FETCH_OBJECT;
+
+ uspoof_setChecks(co->uspoof, checks, SPOOFCHECKER_ERROR_CODE_P(co));
+
+ if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%d) %s", SPOOFCHECKER_ERROR_CODE(co), u_errorName(SPOOFCHECKER_ERROR_CODE(co)));
+ }
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/spoofchecker/spoofchecker_main.h b/ext/intl/spoofchecker/spoofchecker_main.h
new file mode 100644
index 0000000000..fb920d7841
--- /dev/null
+++ b/ext/intl/spoofchecker/spoofchecker_main.h
@@ -0,0 +1,27 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Scott MacVicar <scottmac@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef SPOOFCHECKER_MAIN_H
+#define SPOOFCHECKER_MAIN_H
+
+#include <php.h>
+
+PHP_METHOD(Spoofchecker, isSuspicious);
+PHP_METHOD(Spoofchecker, areConfusable);
+PHP_METHOD(Spoofchecker, setAllowedLocales);
+PHP_METHOD(Spoofchecker, setChecks);
+
+#endif // SPOOFCHECKER_MAIN_H
diff --git a/ext/intl/tests/bug55562.phpt b/ext/intl/tests/bug55562.phpt
new file mode 100644
index 0000000000..dd053c0ee9
--- /dev/null
+++ b/ext/intl/tests/bug55562.phpt
@@ -0,0 +1,13 @@
+--TEST--
+grapheme_substr() - Bug55562 - grapheme_substr() returns false if length parameter is to large
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+var_dump(
+ grapheme_substr('FOK', 1, 20), // expected: OK
+ grapheme_substr('한국어', 1, 20) //expected: 국어
+);
+--EXPECT--
+string(2) "OK"
+string(6) "êµ­ì–´"
diff --git a/ext/intl/tests/bug62915-2.phpt b/ext/intl/tests/bug62915-2.phpt
index 6bccf38ff9..bcb069cab6 100644
--- a/ext/intl/tests/bug62915-2.phpt
+++ b/ext/intl/tests/bug62915-2.phpt
@@ -16,8 +16,11 @@ class B extends NumberFormatter {
class C extends MessageFormatter {
static $ARGS = array("en_US", "foo");
}
+class D extends Spoofchecker {
+ static $ARGS = array();
+}
-foreach (range('A', 'C') as $subclass) {
+foreach (range('A', 'D') as $subclass) {
$rc = new ReflectionClass($subclass);
$obj = $rc->newInstanceArgs($subclass::$ARGS);
$clone = clone $obj;
@@ -27,3 +30,4 @@ foreach (range('A', 'C') as $subclass) {
string(1) "A"
string(1) "B"
string(1) "C"
+string(1) "D"
diff --git a/ext/intl/tests/formatter_get_error.phpt b/ext/intl/tests/formatter_get_error.phpt
index c7b3972709..acb683e894 100644
--- a/ext/intl/tests/formatter_get_error.phpt
+++ b/ext/intl/tests/formatter_get_error.phpt
@@ -19,7 +19,7 @@ function ut_main()
if( $num === false )
return $fmt->getErrorMessage() . " (" . $fmt->getErrorCode() . ")\n";
else
- return "Ooops, an error should have occured.";
+ return "Ooops, an error should have occurred.";
}
include_once( 'ut_common.inc' );
diff --git a/ext/intl/tests/idn_uts46_basic.phpt b/ext/intl/tests/idn_uts46_basic.phpt
new file mode 100644
index 0000000000..2ca185092d
--- /dev/null
+++ b/ext/intl/tests/idn_uts46_basic.phpt
@@ -0,0 +1,53 @@
+--TEST--
+IDN UTS #46 API basic tests
+--SKIPIF--
+<?php
+ if (!extension_loaded('intl'))
+ die('skip');
+ if (!defined('INTL_IDNA_VARIANT_UTS46'))
+ die('skip no UTS #46 API');
+--FILE--
+<?php
+$utf8dn = "www.fußball.com";
+$asciiNonTrans = "www.xn--fuball-cta.com";
+
+echo "all ok, no details:", "\n";
+var_dump(idn_to_ascii($utf8dn,
+ IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46));
+
+echo "all ok, no details, transitional:", "\n";
+var_dump(idn_to_ascii($utf8dn, 0, INTL_IDNA_VARIANT_UTS46));
+
+echo "all ok, with details:", "\n";
+var_dump(idn_to_ascii($utf8dn, IDNA_NONTRANSITIONAL_TO_ASCII,
+ INTL_IDNA_VARIANT_UTS46, $info));
+var_dump($info);
+
+echo "reverse, ok, with details:", "\n";
+var_dump(idn_to_utf8($asciiNonTrans, 0, INTL_IDNA_VARIANT_UTS46, $info));
+var_dump($info);
+--EXPECT--
+all ok, no details:
+string(22) "www.xn--fuball-cta.com"
+all ok, no details, transitional:
+string(16) "www.fussball.com"
+all ok, with details:
+string(22) "www.xn--fuball-cta.com"
+array(3) {
+ ["result"]=>
+ string(22) "www.xn--fuball-cta.com"
+ ["isTransitionalDifferent"]=>
+ bool(true)
+ ["errors"]=>
+ int(0)
+}
+reverse, ok, with details:
+string(16) "www.fußball.com"
+array(3) {
+ ["result"]=>
+ string(16) "www.fußball.com"
+ ["isTransitionalDifferent"]=>
+ bool(false)
+ ["errors"]=>
+ int(0)
+}
diff --git a/ext/intl/tests/idn_uts46_errors.phpt b/ext/intl/tests/idn_uts46_errors.phpt
new file mode 100644
index 0000000000..a336e698c4
--- /dev/null
+++ b/ext/intl/tests/idn_uts46_errors.phpt
@@ -0,0 +1,89 @@
+--TEST--
+IDN UTS #46 API error tests
+--SKIPIF--
+<?php
+ if (!extension_loaded('intl'))
+ die('skip');
+ if (!defined('INTL_IDNA_VARIANT_UTS46'))
+ die('skip no UTS #46 API');
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+echo "=> PHP level errors", "\n";
+
+echo "bad args:", "\n";
+var_dump(idn_to_ascii("", 0, array()));
+var_dump(idn_to_ascii("", 0, INTL_IDNA_VARIANT_UTS46, $foo, null));
+
+echo "bad variant:", "\n";
+var_dump(idn_to_ascii("", 0, INTL_IDNA_VARIANT_UTS46 + 10));
+
+echo "empty domain:", "\n";
+var_dump(idn_to_ascii("", 0, INTL_IDNA_VARIANT_UTS46));
+
+echo "fourth arg for 2003 variant (only notice raised):", "\n";
+var_dump(idn_to_ascii("foo.com", 0, INTL_IDNA_VARIANT_2003, $foo));
+
+echo "with error, but no details arg:", "\n";
+var_dump(idn_to_ascii("www.fußball.com-", 0, INTL_IDNA_VARIANT_UTS46));
+
+echo "with error, with details arg:", "\n";
+var_dump(idn_to_ascii("www.fußball.com-", IDNA_NONTRANSITIONAL_TO_ASCII,
+ INTL_IDNA_VARIANT_UTS46, $foo));
+var_dump($foo);
+
+echo "with error, with details arg, contextj:", "\n";
+var_dump(idn_to_ascii(
+ html_entity_decode("www.a&#x200D;b.com", 0, "UTF-8"),
+ IDNA_NONTRANSITIONAL_TO_ASCII | IDNA_CHECK_CONTEXTJ,
+ INTL_IDNA_VARIANT_UTS46, $foo));
+var_dump($foo);
+var_dump($foo["errors"]==IDNA_ERROR_CONTEXTJ);
+--EXPECTF--
+=> PHP level errors
+bad args:
+
+Warning: idn_to_ascii() expects parameter 3 to be long, array given in %s on line %d
+
+Warning: idn_to_ascii(): idn_to_ascii: bad arguments in %s on line %d
+NULL
+
+Warning: idn_to_ascii() expects at most 4 parameters, 5 given in %s on line %d
+
+Warning: idn_to_ascii(): idn_to_ascii: bad arguments in %s on line %d
+NULL
+bad variant:
+
+Warning: idn_to_ascii(): idn_to_ascii: invalid variant, must be one of {INTL_IDNA_VARIANT_2003, INTL_IDNA_VARIANT_UTS46} in %s on line %d
+bool(false)
+empty domain:
+
+Warning: idn_to_ascii(): idn_to_ascii: empty domain name in %s on line %d
+bool(false)
+fourth arg for 2003 variant (only notice raised):
+
+Notice: idn_to_ascii(): 4 arguments were provided, but INTL_IDNA_VARIANT_2003 only takes 3 - extra argument ignored in %s on line %d
+string(7) "foo.com"
+with error, but no details arg:
+bool(false)
+with error, with details arg:
+bool(false)
+array(3) {
+ ["result"]=>
+ string(23) "www.xn--fuball-cta.com-"
+ ["isTransitionalDifferent"]=>
+ bool(true)
+ ["errors"]=>
+ int(16)
+}
+with error, with details arg, contextj:
+bool(false)
+array(3) {
+ ["result"]=>
+ string(18) "www.xn--ab-m1t.com"
+ ["isTransitionalDifferent"]=>
+ bool(true)
+ ["errors"]=>
+ int(4096)
+}
+bool(true)
diff --git a/ext/intl/tests/locale_accept.phpt b/ext/intl/tests/locale_accept.phpt
index 923571f8f0..cf1dc6e675 100644
--- a/ext/intl/tests/locale_accept.phpt
+++ b/ext/intl/tests/locale_accept.phpt
@@ -24,7 +24,7 @@ function ut_main()
foreach($http_acc as $http) {
$res = ut_loc_accept_http($http);
- $res_str .= "Accepting $http: $res\n";
+ $res_str .= @"Accepting $http: $res\n";
}
return $res_str;
diff --git a/ext/intl/tests/locale_get_display_script2.phpt b/ext/intl/tests/locale_get_display_script2.phpt
index af4834ad0f..2b9e037b78 100644
--- a/ext/intl/tests/locale_get_display_script2.phpt
+++ b/ext/intl/tests/locale_get_display_script2.phpt
@@ -1,5 +1,5 @@
--TEST--
-locale_get_display_script() icu >= 4.8
+locale_get_display_script() icu = 4.8
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
<?php if(version_compare(INTL_ICU_VERSION, '4.8') < 0 || version_compare(INTL_ICU_VERSION, '49') >= 0) print 'skip'; ?>
diff --git a/ext/intl/tests/locale_get_display_script3.phpt b/ext/intl/tests/locale_get_display_script3.phpt
new file mode 100644
index 0000000000..447766e6bd
--- /dev/null
+++ b/ext/intl/tests/locale_get_display_script3.phpt
@@ -0,0 +1,275 @@
+--TEST--
+locale_get_display_script() icu >= 49
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+<?php if(version_compare(INTL_ICU_VERSION, '49') < 0) print 'skip'; ?>
+--FILE--
+<?php
+
+/*
+ * Try getting the display_script for different locales
+ * with Procedural and Object methods.
+ */
+
+function ut_main()
+{
+ $res_str = '';
+
+ $disp_locales=array('en','fr','de');
+
+ $locales = array(
+ 'uk-ua_CALIFORNIA@currency=;currency=GRN',
+ 'root',
+ 'uk@currency=EURO',
+ 'Hindi',
+//Simple language subtag
+ 'de',
+ 'fr',
+ 'ja',
+ 'i-enochian', //(example of a grandfathered tag)
+//Language subtag plus Script subtag:
+ 'zh-Hant',
+ 'zh-Hans',
+ 'sr-Cyrl',
+ 'sr-Latn',
+//Language-Script-Region
+ 'zh-Hans-CN',
+ 'sr-Latn-CS',
+//Language-Variant
+ 'sl-rozaj',
+ 'sl-nedis',
+//Language-Region-Variant
+ 'de-CH-1901',
+ 'sl-IT-nedis',
+//Language-Script-Region-Variant
+ 'sl-Latn-IT-nedis',
+//Language-Region:
+ 'de-DE',
+ 'en-US',
+ 'es-419',
+//Private use subtags:
+ 'de-CH-x-phonebk',
+ 'az-Arab-x-AZE-derbend',
+//Extended language subtags
+ 'zh-min',
+ 'zh-min-nan-Hant-CN',
+//Private use registry values
+ 'x-whatever',
+ 'qaa-Qaaa-QM-x-southern',
+ 'sr-Latn-QM',
+ 'sr-Qaaa-CS',
+/*Tags that use extensions (examples ONLY: extensions MUST be defined
+ by revision or update to this document or by RFC): */
+ 'en-US-u-islamCal',
+ 'zh-CN-a-myExt-x-private',
+ 'en-a-myExt-b-another',
+//Some Invalid Tags:
+ 'de-419-DE',
+ 'a-DE',
+ 'ar-a-aaa-b-bbb-a-ccc'
+ );
+
+
+ $res_str = '';
+
+ foreach( $locales as $locale )
+ {
+ $res_str .= "locale='$locale'\n";
+ foreach( $disp_locales as $disp_locale )
+ {
+ $scr = ut_loc_get_display_script( $locale ,$disp_locale );
+ $res_str .= "disp_locale=$disp_locale : display_script=$scr";
+ $res_str .= "\n";
+ }
+ $res_str .= "-----------------\n";
+ }
+
+ return $res_str;
+
+}
+
+include_once( 'ut_common.inc' );
+ut_run();
+
+?>
+--EXPECT--
+locale='uk-ua_CALIFORNIA@currency=;currency=GRN'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='root'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='uk@currency=EURO'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='Hindi'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='de'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='fr'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='ja'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='i-enochian'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='zh-Hant'
+disp_locale=en : display_script=Traditional Han
+disp_locale=fr : display_script=chinois traditionnel
+disp_locale=de : display_script=Traditionelles Chinesisch
+-----------------
+locale='zh-Hans'
+disp_locale=en : display_script=Simplified Han
+disp_locale=fr : display_script=chinois simplifié
+disp_locale=de : display_script=Vereinfachtes Chinesisch
+-----------------
+locale='sr-Cyrl'
+disp_locale=en : display_script=Cyrillic
+disp_locale=fr : display_script=cyrillique
+disp_locale=de : display_script=Kyrillisch
+-----------------
+locale='sr-Latn'
+disp_locale=en : display_script=Latin
+disp_locale=fr : display_script=latin
+disp_locale=de : display_script=Lateinisch
+-----------------
+locale='zh-Hans-CN'
+disp_locale=en : display_script=Simplified Han
+disp_locale=fr : display_script=chinois simplifié
+disp_locale=de : display_script=Vereinfachtes Chinesisch
+-----------------
+locale='sr-Latn-CS'
+disp_locale=en : display_script=Latin
+disp_locale=fr : display_script=latin
+disp_locale=de : display_script=Lateinisch
+-----------------
+locale='sl-rozaj'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='sl-nedis'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='de-CH-1901'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='sl-IT-nedis'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='sl-Latn-IT-nedis'
+disp_locale=en : display_script=Latin
+disp_locale=fr : display_script=latin
+disp_locale=de : display_script=Lateinisch
+-----------------
+locale='de-DE'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='en-US'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='es-419'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='de-CH-x-phonebk'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='az-Arab-x-AZE-derbend'
+disp_locale=en : display_script=Arabic
+disp_locale=fr : display_script=arabe
+disp_locale=de : display_script=Arabisch
+-----------------
+locale='zh-min'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='zh-min-nan-Hant-CN'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='x-whatever'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='qaa-Qaaa-QM-x-southern'
+disp_locale=en : display_script=Qaaa
+disp_locale=fr : display_script=Qaaa
+disp_locale=de : display_script=Qaaa
+-----------------
+locale='sr-Latn-QM'
+disp_locale=en : display_script=Latin
+disp_locale=fr : display_script=latin
+disp_locale=de : display_script=Lateinisch
+-----------------
+locale='sr-Qaaa-CS'
+disp_locale=en : display_script=Qaaa
+disp_locale=fr : display_script=Qaaa
+disp_locale=de : display_script=Qaaa
+-----------------
+locale='en-US-u-islamCal'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='zh-CN-a-myExt-x-private'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='en-a-myExt-b-another'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='de-419-DE'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='a-DE'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
+locale='ar-a-aaa-b-bbb-a-ccc'
+disp_locale=en : display_script=
+disp_locale=fr : display_script=
+disp_locale=de : display_script=
+-----------------
diff --git a/ext/intl/tests/resourcebundle_null_mandatory_args.phpt b/ext/intl/tests/resourcebundle_null_mandatory_args.phpt
new file mode 100644
index 0000000000..17fab6d630
--- /dev/null
+++ b/ext/intl/tests/resourcebundle_null_mandatory_args.phpt
@@ -0,0 +1,28 @@
+--TEST--
+ResourceBundle constructor bundle accepts NULL for first two arguments
+--INI--
+date.timezone=Atlantic/Azores
+--SKIPIF--
+<?php
+if (!extension_loaded('intl'))
+ die('skip intl extension not enabled');
+if (version_compare(INTL_ICU_VERSION, '4.8') < 0)
+ die('skip ICU >= 4.8 only');
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+
+$r = new ResourceBundle('en_US', NULL);
+$c = $r->get('calendar')->get('gregorian')->get('DateTimePatterns')->get(0);
+var_dump($c);
+
+ini_set('intl.default_locale', 'pt_PT');
+$r = new ResourceBundle(NULL, NULL);
+$c = $r->get('calendar')->get('gregorian')->get('DateTimePatterns')->get(0);
+var_dump($c);
+?>
+==DONE==
+--EXPECT--
+string(14) "h:mm:ss a zzzz"
+string(12) "H:mm:ss zzzz"
+==DONE==
diff --git a/ext/intl/tests/spoofchecker_001.phpt b/ext/intl/tests/spoofchecker_001.phpt
new file mode 100644
index 0000000000..7904b3a4c0
--- /dev/null
+++ b/ext/intl/tests/spoofchecker_001.phpt
@@ -0,0 +1,23 @@
+--TEST--
+spoofchecker suspicious character checker
+--SKIPIF--
+<?php if(!extension_loaded('intl') || !class_exists("Spoofchecker")) print 'skip'; ?>
+--FILE--
+<?php
+
+$url = "http://www.payp\xD0\xB0l.com";
+
+$x = new Spoofchecker();
+echo "paypal with Cyrillic spoof characters\n";
+var_dump($x->isSuspicious($url));
+
+echo "certain all-uppercase Latin sequences can be spoof of Greek\n";
+var_dump($x->isSuspicious("NAPKIN PEZ"));
+var_dump($x->isSuspicious("napkin pez"));
+?>
+--EXPECTF--
+paypal with Cyrillic spoof characters
+bool(true)
+certain all-uppercase Latin sequences can be spoof of Greek
+bool(true)
+bool(false)
diff --git a/ext/intl/tests/spoofchecker_002.phpt b/ext/intl/tests/spoofchecker_002.phpt
new file mode 100644
index 0000000000..d570917350
--- /dev/null
+++ b/ext/intl/tests/spoofchecker_002.phpt
@@ -0,0 +1,20 @@
+--TEST--
+spoofchecker confusable tests
+--SKIPIF--
+<?php if(!extension_loaded('intl') || !class_exists("Spoofchecker")) print 'skip'; ?>
+--FILE--
+<?php
+
+$url = "http://www.payp\xD0\xB0l.com";
+
+$x = new Spoofchecker();
+echo "Checking if words are confusable\n";
+var_dump($x->areConfusable("hello, world", "goodbye, world"));
+var_dump($x->areConfusable("hello, world", "hello, world"));
+var_dump($x->areConfusable("hello, world", "he11o, wor1d"));
+?>
+--EXPECTF--
+Checking if words are confusable
+bool(false)
+bool(true)
+bool(true)
diff --git a/ext/intl/tests/spoofchecker_003.phpt b/ext/intl/tests/spoofchecker_003.phpt
new file mode 100644
index 0000000000..0be9bfa409
--- /dev/null
+++ b/ext/intl/tests/spoofchecker_003.phpt
@@ -0,0 +1,25 @@
+--TEST--
+spoofchecker with locale settings
+--SKIPIF--
+<?php if(!extension_loaded('intl') || !class_exists("Spoofchecker")) print 'skip'; ?>
+--FILE--
+<?php
+
+$korean = "\xED\x95\x9C" . "\xEA\xB5\xAD" . "\xEB\xA7\x90";
+
+$x = new Spoofchecker();
+echo "Is suspcious, en_US\n";
+
+$x->setAllowedLocales('en_US');
+var_dump($x->isSuspicious($korean));
+
+echo "Is suspcious, ko_KR\n";
+
+$x->setAllowedLocales('en_US, ko_KR');
+var_dump($x->isSuspicious($korean));
+?>
+--EXPECTF--
+Is suspcious, en_US
+bool(true)
+Is suspcious, ko_KR
+bool(false)
diff --git a/ext/intl/tests/spoofchecker_004.phpt b/ext/intl/tests/spoofchecker_004.phpt
new file mode 100644
index 0000000000..b38c61d717
--- /dev/null
+++ b/ext/intl/tests/spoofchecker_004.phpt
@@ -0,0 +1,28 @@
+--TEST--
+spoofchecker with settings changed
+--SKIPIF--
+<?php if(!extension_loaded('intl') || !class_exists("Spoofchecker")) print 'skip'; ?>
+--FILE--
+<?php
+
+$korean = "\xED\x95\x9C" . "\xEA\xB5\xAD" . "\xEB\xA7\x90";
+
+$x = new Spoofchecker();
+echo "Check with default settings\n";
+var_dump($x->areConfusable("HELLO", "H\xD0\x95LLO"));
+var_dump($x->areConfusable("hello", "h\xD0\xB5llo"));
+
+echo "Change confusable settings\n";
+$x->setChecks(Spoofchecker::MIXED_SCRIPT_CONFUSABLE |
+ Spoofchecker::WHOLE_SCRIPT_CONFUSABLE |
+ Spoofchecker::SINGLE_SCRIPT_CONFUSABLE);
+var_dump($x->areConfusable("HELLO", "H\xD0\x95LLO"));
+var_dump($x->areConfusable("hello", "h\xD0\xB5llo"));
+?>
+--EXPECTF--
+Check with default settings
+bool(true)
+bool(true)
+Change confusable settings
+bool(false)
+bool(true)
diff --git a/ext/intl/tests/transliterator_clone.phpt b/ext/intl/tests/transliterator_clone.phpt
new file mode 100644
index 0000000000..23d569b898
--- /dev/null
+++ b/ext/intl/tests/transliterator_clone.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Transliterator clone handler
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+$str = "a U+4E07";
+
+$t = Transliterator::create("hex-any");
+echo $t->id, ": ", $t->transliterate($str), "\n";
+
+$u = clone $t;
+echo $u->id, ": ", $u->transliterate($str), "\n";
+
+echo "Done.\n";
+
+--EXPECT--
+hex-any: a 万
+hex-any: a 万
+Done.
diff --git a/ext/intl/tests/transliterator_create_basic.phpt b/ext/intl/tests/transliterator_create_basic.phpt
new file mode 100644
index 0000000000..4de032dbd6
--- /dev/null
+++ b/ext/intl/tests/transliterator_create_basic.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Transliterator::create (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+$t = Transliterator::create("any-latin");
+echo $t->id,"\n";
+
+$t = transliterator_create("any-latin");
+echo $t->id,"\n";
+
+echo "Done.\n";
+
+--EXPECT--
+any-latin
+any-latin
+Done.
+
diff --git a/ext/intl/tests/transliterator_create_error.phpt b/ext/intl/tests/transliterator_create_error.phpt
new file mode 100644
index 0000000000..31aef68feb
--- /dev/null
+++ b/ext/intl/tests/transliterator_create_error.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Transliterator::create (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+ini_set("intl.error_level", E_WARNING);
+Transliterator::create("inexistant id");
+echo intl_get_error_message(), "\n";
+Transliterator::create("bad UTF-8 \x8F");
+echo intl_get_error_message(), "\n";
+
+echo "Done.\n";
+--EXPECTF--
+Warning: Transliterator::create(): transliterator_create: unable to open ICU transliterator with id "inexistant id" in %s on line %d
+transliterator_create: unable to open ICU transliterator with id "inexistant id": U_INVALID_ID
+
+Warning: Transliterator::create(): String conversion of id to UTF-16 failed in %s on line %d
+String conversion of id to UTF-16 failed: U_INVALID_CHAR_FOUND
+Done.
diff --git a/ext/intl/tests/transliterator_create_from_rule_basic.phpt b/ext/intl/tests/transliterator_create_from_rule_basic.phpt
new file mode 100644
index 0000000000..eb8d5da787
--- /dev/null
+++ b/ext/intl/tests/transliterator_create_from_rule_basic.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Transliterator::createFromRules (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+
+$rules = <<<RULES
+α <> y;
+\`\` } a > “;
+RULES;
+
+$t = Transliterator::createFromRules($rules);
+echo $t->id,"\n";
+
+echo $t->transliterate("``akk ``bkk ``aooy"),"\n";
+
+$u = transliterator_create_from_rules($rules, Transliterator::REVERSE);
+
+echo $u->transliterate("``akk ``bkk ``aooy"), "\n";
+
+echo "Done.\n";
+--EXPECT--
+RulesTransPHP
+“akk ``bkk “aooy
+``akk ``bkk ``aooα
+Done.
diff --git a/ext/intl/tests/transliterator_create_from_rule_error.phpt b/ext/intl/tests/transliterator_create_from_rule_error.phpt
new file mode 100644
index 0000000000..cad73ab608
--- /dev/null
+++ b/ext/intl/tests/transliterator_create_from_rule_error.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Transliterator::createFromRules (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+
+$t = Transliterator::createFromRules();
+echo intl_get_error_message(),"\n";
+
+$t = Transliterator::createFromRules("a","b");
+echo intl_get_error_message(),"\n";
+
+$t = Transliterator::createFromRules("\x8Fss");
+echo intl_get_error_message(),"\n";
+
+$rules = <<<RULES
+\`\` } a > “;
+\`\` } a > b;
+RULES;
+
+$t = Transliterator::createFromRules($rules);
+echo intl_get_error_message(),"\n";
+
+$rules = <<<RULES
+ffff
+RULES;
+
+$t = Transliterator::createFromRules($rules);
+echo intl_get_error_message(),"\n";
+echo "Done.\n";
+
+--EXPECTF--
+Warning: Transliterator::createFromRules() expects at least 1 parameter, 0 given in %s on line %d
+
+Warning: Transliterator::createFromRules(): transliterator_create_from_rules: bad arguments in %s on line %d
+transliterator_create_from_rules: bad arguments: U_ILLEGAL_ARGUMENT_ERROR
+
+Warning: Transliterator::createFromRules() expects parameter 2 to be long, string given in %s on line %d
+
+Warning: Transliterator::createFromRules(): transliterator_create_from_rules: bad arguments in %s on line %d
+transliterator_create_from_rules: bad arguments: U_ILLEGAL_ARGUMENT_ERROR
+
+Warning: Transliterator::createFromRules(): String conversion of rules to UTF-16 failed in %s on line %d
+String conversion of rules to UTF-16 failed: U_INVALID_CHAR_FOUND
+
+Warning: Transliterator::createFromRules(): transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error after "{'``'}a > “;", before or at "{'``'}a > b;") in %s on line %d
+transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error after "{'``'}a > “;", before or at "{'``'}a > b;"): U_RULE_MASK_ERROR
+
+Warning: Transliterator::createFromRules(): transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error at offset 0, before or at "ffff") in %s on line %d
+transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error at offset 0, before or at "ffff"): U_MISSING_OPERATOR
+Done.
diff --git a/ext/intl/tests/transliterator_create_inverse_basic.phpt b/ext/intl/tests/transliterator_create_inverse_basic.phpt
new file mode 100644
index 0000000000..3241403d3d
--- /dev/null
+++ b/ext/intl/tests/transliterator_create_inverse_basic.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Transliterator::createInverse (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+ini_set("intl.error_level", E_WARNING);
+
+$tr = Transliterator::create("Katakana-Latin");
+$orstr = "オーシャンビュー";
+$new_str = $tr->transliterate($orstr);
+
+$revtr = $tr->createInverse();
+$recovstr = $revtr->transliterate($new_str);
+
+$revtr2 = transliterator_create_inverse($tr);
+$recovstr2 = $revtr2->transliterate($new_str);
+
+echo $orstr,"\n";
+echo $new_str,"\n";
+echo $recovstr,"\n";
+
+var_dump(($orstr == $recovstr) == $recovstr2);
+
+echo "Done.\n";
+--EXPECT--
+オーシャンビュー
+ÅshanbyÅ«
+オーシャンビュー
+bool(true)
+Done.
diff --git a/ext/intl/tests/transliterator_create_inverse_error.phpt b/ext/intl/tests/transliterator_create_inverse_error.phpt
new file mode 100644
index 0000000000..92141c93d4
--- /dev/null
+++ b/ext/intl/tests/transliterator_create_inverse_error.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Transliterator::createInverse (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+ini_set("intl.error_level", E_WARNING);
+
+$tr = Transliterator::create("Katakana-Latin");
+$tr->createInverse(array());
+
+$tr = Transliterator::create("Katakana-Latin");
+transliterator_create_inverse("jj");
+
+--EXPECTF--
+Warning: Transliterator::createInverse() expects exactly 0 parameters, 1 given in %s on line %d
+
+Warning: Transliterator::createInverse(): transliterator_create_inverse: bad arguments in %s on line %d
+
+Catchable fatal error: Argument 1 passed to transliterator_create_inverse() must be an instance of Transliterator, string given in %s on line %d
diff --git a/ext/intl/tests/transliterator_get_error_code_basic.phpt b/ext/intl/tests/transliterator_get_error_code_basic.phpt
new file mode 100644
index 0000000000..3d16a8a9a0
--- /dev/null
+++ b/ext/intl/tests/transliterator_get_error_code_basic.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Transliterator::getErrorCode (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+$t = Transliterator::create("[\p{Bidi_Mirrored}] Hex");
+var_dump($t->transliterate("\x8F"));
+echo transliterator_get_error_code($t), "\n";
+
+echo $t->getErrorCode(), "\n";
+
+var_dump($t->transliterate(""));
+echo $t->getErrorCode(), "\n";
+
+echo "Done.\n";
+--EXPECTF--
+Warning: Transliterator::transliterate(): String conversion of string to UTF-16 failed in %s on line %d
+bool(false)
+10
+10
+string(0) ""
+0
+Done.
diff --git a/ext/intl/tests/transliterator_get_error_code_error.phpt b/ext/intl/tests/transliterator_get_error_code_error.phpt
new file mode 100644
index 0000000000..94daa120d7
--- /dev/null
+++ b/ext/intl/tests/transliterator_get_error_code_error.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Transliterator::getErrorCode (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+$t = Transliterator::create("[\p{Bidi_Mirrored}] Hex");
+echo transliterator_get_error_code(), "\n";
+echo $t->getErrorCode(null), "\n";
+echo transliterator_get_error_code(array()), "\n";
+
+--EXPECTF--
+Warning: transliterator_get_error_code() expects exactly 1 parameter, 0 given in %s on line %d
+
+Warning: transliterator_get_error_code(): transliterator_get_error_code: unable to parse input params in %s on line %d
+
+
+Warning: Transliterator::getErrorCode() expects exactly 0 parameters, 1 given in %s on line %d
+
+Warning: Transliterator::getErrorCode(): transliterator_get_error_code: unable to parse input params in %s on line %d
+
+
+Catchable fatal error: Argument 1 passed to transliterator_get_error_code() must be an instance of Transliterator, array given in %s on line %d
diff --git a/ext/intl/tests/transliterator_get_error_message_basic.phpt b/ext/intl/tests/transliterator_get_error_message_basic.phpt
new file mode 100644
index 0000000000..4e918530b2
--- /dev/null
+++ b/ext/intl/tests/transliterator_get_error_message_basic.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Transliterator::getErrorMessage (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+$t = Transliterator::create("[\p{Bidi_Mirrored}] Hex");
+var_dump($t->transliterate("\x8F"));
+echo transliterator_get_error_message($t), "\n";
+
+echo $t->getErrorMessage(), "\n";
+
+var_dump($t->transliterate(""));
+echo $t->getErrorMessage(), "\n";
+
+echo "Done.\n";
+--EXPECTF--
+Warning: Transliterator::transliterate(): String conversion of string to UTF-16 failed in %s on line %d
+bool(false)
+String conversion of string to UTF-16 failed: U_INVALID_CHAR_FOUND
+String conversion of string to UTF-16 failed: U_INVALID_CHAR_FOUND
+string(0) ""
+U_ZERO_ERROR
+Done.
diff --git a/ext/intl/tests/transliterator_get_error_message_error.phpt b/ext/intl/tests/transliterator_get_error_message_error.phpt
new file mode 100644
index 0000000000..4ab21045b2
--- /dev/null
+++ b/ext/intl/tests/transliterator_get_error_message_error.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Transliterator::getErrorMessage (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+$t = Transliterator::create("[\p{Bidi_Mirrored}] Hex");
+echo transliterator_get_error_message(), "\n";
+echo $t->getErrorMessage(null), "\n";
+echo transliterator_get_error_message(array()), "\n";
+
+--EXPECTF--
+Warning: transliterator_get_error_message() expects exactly 1 parameter, 0 given in %s on line %d
+
+Warning: transliterator_get_error_message(): transliterator_get_error_message: unable to parse input params in %s on line %d
+
+
+Warning: Transliterator::getErrorMessage() expects exactly 0 parameters, 1 given in %s on line %d
+
+Warning: Transliterator::getErrorMessage(): transliterator_get_error_message: unable to parse input params in %s on line %d
+
+
+Catchable fatal error: Argument 1 passed to transliterator_get_error_message() must be an instance of Transliterator, array given in %s on line %d
diff --git a/ext/intl/tests/transliterator_list_ids_basic.phpt b/ext/intl/tests/transliterator_list_ids_basic.phpt
new file mode 100644
index 0000000000..af65b5853e
--- /dev/null
+++ b/ext/intl/tests/transliterator_list_ids_basic.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Transliterator::listIDs (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+ini_set("intl.error_level", E_WARNING);
+var_dump(count(transliterator_list_ids()) > 100);
+var_dump(count(Transliterator::listIDs()) > 100);
+
+echo "Done.\n";
+--EXPECT--
+bool(true)
+bool(true)
+Done.
diff --git a/ext/intl/tests/transliterator_list_ids_error.phpt b/ext/intl/tests/transliterator_list_ids_error.phpt
new file mode 100644
index 0000000000..d1066a8920
--- /dev/null
+++ b/ext/intl/tests/transliterator_list_ids_error.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Transliterator::listIDs (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+ini_set("intl.error_level", E_WARNING);
+var_dump(transliterator_list_ids(array()));
+
+echo "Done.\n";
+
+--EXPECTF--
+Warning: transliterator_list_ids() expects exactly 0 parameters, 1 given in %s on line %d
+
+Warning: transliterator_list_ids(): transliterator_list_ids: bad arguments in %s on line %d
+bool(false)
+Done.
diff --git a/ext/intl/tests/transliterator_property_id.phpt b/ext/intl/tests/transliterator_property_id.phpt
new file mode 100644
index 0000000000..b5337b68e6
--- /dev/null
+++ b/ext/intl/tests/transliterator_property_id.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Transliterator - "id" property
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+$tr = Transliterator::create("Katakana-Latin");
+echo $tr->id, "\n";
+$revtr = $tr->createInverse();
+echo $revtr->id, "\n";
+var_dump($revtr);
+
+echo "Done.\n";
+--EXPECTF--
+Katakana-Latin
+Latin-Katakana
+object(Transliterator)#%d (%d) {
+ ["id"]=>
+ string(%d) "Latin-Katakana"
+}
+Done.
diff --git a/ext/intl/tests/transliterator_transliterate_basic.phpt b/ext/intl/tests/transliterator_transliterate_basic.phpt
new file mode 100644
index 0000000000..f117834781
--- /dev/null
+++ b/ext/intl/tests/transliterator_transliterate_basic.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Transliterator::transliterate (basic)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+$t = transliterator_create("Latin; Title");
+$s = "Κοντογιαννάτος, Βασίλης";
+echo $t->transliterate($s),"\n";
+echo transliterator_transliterate($t, $s),"\n";
+echo $t->transliterate($s, 3),"\n";
+echo $t->transliterate($s, 3, 4),"\n";
+
+echo "Done.\n";
+--EXPECT--
+Kontogiannátos, Basílēs
+Kontogiannátos, Basílēs
+ΚονTogiannátos, Basílēs
+ΚονTογιαννάτος, Βασίλης
+Done.
diff --git a/ext/intl/tests/transliterator_transliterate_error.phpt b/ext/intl/tests/transliterator_transliterate_error.phpt
new file mode 100644
index 0000000000..cdddcfb87b
--- /dev/null
+++ b/ext/intl/tests/transliterator_transliterate_error.phpt
@@ -0,0 +1,60 @@
+--TEST--
+Transliterator::transliterate (error)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+ini_set("intl.error_level", E_WARNING);
+
+$tr = Transliterator::create("latin");
+
+//Arguments
+var_dump(transliterator_transliterate());
+var_dump(transliterator_transliterate($tr,array()));
+var_dump(transliterator_transliterate($tr,"str",7));
+var_dump(transliterator_transliterate($tr,"str",7,6));
+var_dump(transliterator_transliterate($tr,"str",2,-1,"extra"));
+
+//Arguments
+var_dump($tr->transliterate());
+var_dump($tr->transliterate(array()));
+
+//bad UTF-8
+transliterator_transliterate($tr, "\x80\x03");
+
+echo "Done.\n";
+--EXPECTF--
+Warning: transliterator_transliterate() expects at least 2 parameters, 0 given in %s on line %d
+
+Warning: transliterator_transliterate(): transliterator_transliterate: bad arguments in %s on line %d
+bool(false)
+
+Warning: transliterator_transliterate() expects parameter 2 to be string, array given in %s on line %d
+
+Warning: transliterator_transliterate(): transliterator_transliterate: bad arguments in %s on line %d
+bool(false)
+
+Warning: transliterator_transliterate(): transliterator_transliterate: Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 3) in %s on line %d
+bool(false)
+
+Warning: transliterator_transliterate(): transliterator_transliterate: "start" argument should be non-negative and not bigger than "end" (if defined) in %s on line %d
+bool(false)
+
+Warning: transliterator_transliterate() expects at most 4 parameters, 5 given in %s on line %d
+
+Warning: transliterator_transliterate(): transliterator_transliterate: bad arguments in %s on line %d
+bool(false)
+
+Warning: Transliterator::transliterate() expects at least 1 parameter, 0 given in %s on line %d
+
+Warning: Transliterator::transliterate(): transliterator_transliterate: bad arguments in %s on line %d
+bool(false)
+
+Warning: Transliterator::transliterate() expects parameter 1 to be string, array given in %s on line %d
+
+Warning: Transliterator::transliterate(): transliterator_transliterate: bad arguments in %s on line %d
+bool(false)
+
+Warning: transliterator_transliterate(): String conversion of string to UTF-16 failed in %s on line %d
+Done.
diff --git a/ext/intl/tests/transliterator_transliterate_variant1.phpt b/ext/intl/tests/transliterator_transliterate_variant1.phpt
new file mode 100644
index 0000000000..fc77a4e3ac
--- /dev/null
+++ b/ext/intl/tests/transliterator_transliterate_variant1.phpt
@@ -0,0 +1,37 @@
+--TEST--
+transliterator_transliterate (variant 1, non-transliterator 1st arg)
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+//exec('pause');
+$str = " o";
+echo transliterator_transliterate("[\p{White_Space}] hex", $str), "\n";
+
+echo transliterator_transliterate("\x8F", $str), "\n";
+echo intl_get_error_message(), "\n";
+
+class A {
+function __toString() { return "inexistant id"; }
+}
+
+echo transliterator_transliterate(new A(), $str), "\n";
+echo intl_get_error_message(), "\n";
+
+echo "Done.\n";
+--EXPECTF--
+\u0020o
+
+Warning: transliterator_transliterate(): String conversion of id to UTF-16 failed in %s on line %d
+
+Warning: transliterator_transliterate(): Could not create transliterator with ID %s
+
+String conversion of id to UTF-16 failed: U_INVALID_CHAR_FOUND
+
+Warning: transliterator_transliterate(): transliterator_create: unable to open ICU transliterator with id "inexistant id" in %s on line %d
+
+Warning: transliterator_transliterate(): Could not create transliterator with ID "inexistant id" (transliterator_create: unable to open ICU transliterator with id "inexistant id": U_INVALID_ID) in %s on line %d
+
+transliterator_create: unable to open ICU transliterator with id "inexistant id": U_INVALID_ID
+Done.
diff --git a/ext/intl/transliterator/transliterator.c b/ext/intl/transliterator/transliterator.c
new file mode 100644
index 0000000000..75c9eaabda
--- /dev/null
+++ b/ext/intl/transliterator/transliterator.c
@@ -0,0 +1,138 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "transliterator_class.h"
+#include "transliterator.h"
+#include "intl_convert.h"
+
+#include <unicode/ustring.h>
+
+/* {{{ transliterator_register_constants
+ * Register constants common for both (OO and procedural) APIs.
+ */
+void transliterator_register_constants( INIT_FUNC_ARGS )
+{
+ if( !Transliterator_ce_ptr )
+ {
+ zend_error( E_ERROR, "Transliterator class not defined" );
+ return;
+ }
+
+ #define TRANSLITERATOR_EXPOSE_CONST( x ) REGISTER_LONG_CONSTANT( #x, x, CONST_CS )
+ #define TRANSLITERATOR_EXPOSE_CLASS_CONST( x ) zend_declare_class_constant_long( Transliterator_ce_ptr, ZEND_STRS( #x ) - 1, TRANSLITERATOR_##x TSRMLS_CC );
+ #define TRANSLITERATOR_EXPOSE_CUSTOM_CLASS_CONST( name, value ) zend_declare_class_constant_long( Transliterator_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC );*/
+
+ /* Normalization form constants */
+ TRANSLITERATOR_EXPOSE_CLASS_CONST( FORWARD );
+ TRANSLITERATOR_EXPOSE_CLASS_CONST( REVERSE );
+
+ #undef NORMALIZER_EXPOSE_CUSTOM_CLASS_CONST
+ #undef NORMALIZER_EXPOSE_CLASS_CONST
+ #undef NORMALIZER_EXPOSE_CONST
+}
+/* }}} */
+
+/* {{{ transliterator_parse_error_to_string
+ * Transforms parse errors in strings.
+ */
+smart_str transliterator_parse_error_to_string( UParseError* pe )
+{
+ smart_str ret = {0};
+ char *buf;
+ int u8len;
+ UErrorCode status;
+ int any = 0;
+
+ assert( pe != NULL );
+
+ smart_str_appends( &ret, "parse error " );
+ if( pe->line > 0 )
+ {
+ smart_str_appends( &ret, "on line " );
+ smart_str_append_long( &ret, (long ) pe->line );
+ any = 1;
+ }
+ if( pe->offset >= 0 ) {
+ if( any )
+ smart_str_appends( &ret, ", " );
+ else
+ smart_str_appends( &ret, "at " );
+
+ smart_str_appends( &ret, "offset " );
+ smart_str_append_long( &ret, (long ) pe->offset );
+ any = 1;
+ }
+
+ if (pe->preContext[0] != 0 ) {
+ if( any )
+ smart_str_appends( &ret, ", " );
+
+ smart_str_appends( &ret, "after \"" );
+ intl_convert_utf16_to_utf8( &buf, &u8len, pe->preContext, -1, &status );
+ if( U_FAILURE( status ) )
+ {
+ smart_str_appends( &ret, "(could not convert parser error pre-context to UTF-8)" );
+ }
+ else {
+ smart_str_appendl( &ret, buf, u8len );
+ efree( buf );
+ }
+ smart_str_appends( &ret, "\"" );
+ any = 1;
+ }
+
+ if( pe->postContext[0] != 0 )
+ {
+ if( any )
+ smart_str_appends( &ret, ", " );
+
+ smart_str_appends( &ret, "before or at \"" );
+ intl_convert_utf16_to_utf8( &buf, &u8len, pe->postContext, -1, &status );
+ if( U_FAILURE( status ) )
+ {
+ smart_str_appends( &ret, "(could not convert parser error post-context to UTF-8)" );
+ }
+ else
+ {
+ smart_str_appendl( &ret, buf, u8len );
+ efree( buf );
+ }
+ smart_str_appends( &ret, "\"" );
+ any = 1;
+ }
+
+ if( !any )
+ {
+ smart_str_free( &ret );
+ smart_str_appends( &ret, "no parse error" );
+ }
+
+ smart_str_0( &ret );
+ return ret;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/transliterator/transliterator.h b/ext/intl/transliterator/transliterator.h
new file mode 100644
index 0000000000..cfd5d38dbd
--- /dev/null
+++ b/ext/intl/transliterator/transliterator.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@netcabo.ot> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef TRANSLITERATOR_TRANSLITERATOR_H
+#define TRANSLITERATOR_TRANSLITERATOR_H
+
+#include <php.h>
+#include <unicode/utypes.h>
+#include <unicode/utrans.h>
+
+#include "ext/standard/php_smart_str.h"
+
+void transliterator_register_constants( INIT_FUNC_ARGS );
+smart_str transliterator_parse_error_to_string( UParseError* pe );
+
+#endif /* #ifndef TRANSLITERATOR_TRANSLITERATOR_H */
diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c
new file mode 100644
index 0000000000..5ef80fb482
--- /dev/null
+++ b/ext/intl/transliterator/transliterator_class.c
@@ -0,0 +1,434 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "transliterator_class.h"
+#include "php_intl.h"
+#include "transliterator_methods.h"
+#include "intl_error.h"
+#include "intl_convert.h"
+#include "intl_data.h"
+
+#include <unicode/utrans.h>
+
+zend_class_entry *Transliterator_ce_ptr = NULL;
+
+zend_object_handlers Transliterator_handlers;
+
+/* {{{ int transliterator_object_construct( zval *object, UTransliterator *utrans, UErrorCode *status TSRMLS_DC )
+ * Initialize internals of Transliterator_object.
+ */
+int transliterator_object_construct( zval *object,
+ UTransliterator *utrans,
+ UErrorCode *status TSRMLS_DC )
+{
+ const UChar *ustr_id;
+ int32_t ustr_id_len;
+ char *str_id;
+ int str_id_len;
+ Transliterator_object *to;
+
+ TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
+
+ assert( to->utrans == NULL );
+ /* this assignment must happen before any return with failure because the
+ * caller relies on it always being made (so it can just destroy the object
+ * to close the transliterator) */
+ to->utrans = utrans;
+
+ ustr_id = utrans_getUnicodeID( utrans, &ustr_id_len );
+ intl_convert_utf16_to_utf8( &str_id, &str_id_len, ustr_id, (int ) ustr_id_len, status );
+ if( U_FAILURE( *status ) )
+ {
+ return FAILURE;
+ }
+
+ zend_update_property_stringl( Transliterator_ce_ptr, object,
+ "id", sizeof( "id" ) - 1, str_id, str_id_len TSRMLS_CC );
+ efree( str_id );
+ return SUCCESS;
+}
+/* }}} */
+
+/*
+ * Auxiliary functions needed by objects of 'Transliterator' class
+ */
+
+/* {{{ void transliterator_object_init( Transliterator_object* to )
+ * Initialize internals of Transliterator_object.
+ */
+static void transliterator_object_init( Transliterator_object* to TSRMLS_DC )
+{
+ if( !to )
+ return;
+
+ intl_error_init( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
+}
+/* }}} */
+
+/* {{{ void transliterator_object_destroy( Transliterator_object* to )
+ * Clean up mem allocted by internals of Transliterator_object
+ */
+static void transliterator_object_destroy( Transliterator_object* to TSRMLS_DC )
+{
+ if( !to )
+ return;
+
+ if( to->utrans )
+ {
+ utrans_close( to->utrans );
+ to->utrans = NULL;
+ }
+
+ intl_error_reset( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
+}
+/* }}} */
+
+/* {{{ Transliterator_objects_dtor */
+static void Transliterator_objects_dtor(
+ void *object,
+ zend_object_handle handle TSRMLS_DC )
+{
+ zend_objects_destroy_object( object, handle TSRMLS_CC );
+}
+/* }}} */
+
+/* {{{ Transliterator_objects_free */
+static void Transliterator_objects_free( zend_object *object TSRMLS_DC )
+{
+ Transliterator_object* to = (Transliterator_object*) object;
+
+ zend_object_std_dtor( &to->zo TSRMLS_CC );
+
+ transliterator_object_destroy( to TSRMLS_CC );
+
+ efree( to );
+}
+/* }}} */
+
+/* {{{ Transliterator_object_create */
+static zend_object_value Transliterator_object_create(
+ zend_class_entry *ce TSRMLS_DC )
+{
+ zend_object_value retval;
+ Transliterator_object* intern;
+
+ intern = ecalloc( 1, sizeof( Transliterator_object ) );
+
+ zend_object_std_init( &intern->zo, ce TSRMLS_CC );
+#if PHP_VERSION_ID < 50399
+ zend_hash_copy( intern->zo.properties, &(ce->default_properties ),
+ (copy_ctor_func_t) zval_add_ref, NULL, sizeof( zval* ) );
+#else
+ object_properties_init( (zend_object*) intern, ce );
+#endif
+ transliterator_object_init( intern TSRMLS_CC );
+
+ retval.handle = zend_objects_store_put(
+ intern,
+ Transliterator_objects_dtor,
+ (zend_objects_free_object_storage_t) Transliterator_objects_free,
+ NULL TSRMLS_CC );
+
+ retval.handlers = &Transliterator_handlers;
+
+ return retval;
+}
+/* }}} */
+
+/*
+ * Object handlers for Transliterator class (and subclasses)
+ */
+
+/* {{{ clone handler for Transliterator */
+static zend_object_value Transliterator_clone_obj( zval *object TSRMLS_DC )
+{
+ Transliterator_object *to_orig,
+ *to_new;
+ zend_object_value ret_val;
+ intl_error_reset( NULL TSRMLS_CC );
+
+ to_orig = zend_object_store_get_object( object TSRMLS_CC );
+ intl_error_reset( INTL_DATA_ERROR_P( to_orig ) TSRMLS_CC );
+ ret_val = Transliterator_ce_ptr->create_object( Z_OBJCE_P( object ) TSRMLS_CC );
+ to_new = zend_object_store_get_object_by_handle( ret_val.handle TSRMLS_CC );
+
+ zend_objects_clone_members( &to_new->zo, ret_val,
+ &to_orig->zo, Z_OBJ_HANDLE_P( object ) TSRMLS_CC );
+
+ if( to_orig->utrans != NULL )
+ {
+ UTransliterator *utrans = NULL;
+ zval tempz; /* dummy zval to pass to transliterator_object_construct */
+
+ /* guaranteed to return NULL if it fails */
+ utrans = utrans_clone( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to_orig ) );
+
+ if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
+ goto err;
+
+ Z_OBJVAL( tempz ) = ret_val;
+ transliterator_object_construct( &tempz, utrans,
+ TRANSLITERATOR_ERROR_CODE_P( to_orig ) TSRMLS_CC );
+
+ if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
+ {
+ char *err_msg;
+err:
+
+ if( utrans != NULL )
+ transliterator_object_destroy( to_new TSRMLS_CC );
+
+ /* set the error anyway, in case in the future we decide not to
+ * throw an error. It also helps build the error message */
+ intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( to_orig ) TSRMLS_CC );
+ intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to_orig ),
+ "Could not clone transliterator", 0 TSRMLS_CC );
+
+ err_msg = intl_error_get_message( TRANSLITERATOR_ERROR_P( to_orig ) TSRMLS_CC );
+ php_error_docref( NULL TSRMLS_CC, E_ERROR, "%s", err_msg );
+ efree( err_msg ); /* if it's changed into a warning */
+ /* do not destroy tempz; we need to return something */
+ }
+ }
+ else
+ {
+ /* We shouldn't have unconstructed objects in the first place */
+ php_error_docref( NULL TSRMLS_CC, E_WARNING,
+ "Cloning unconstructed transliterator." );
+ }
+
+ return ret_val;
+}
+/* }}} */
+
+#if PHP_VERSION_ID >= 50399
+# define TRANSLITERATOR_PROPERTY_HANDLER_PROLOG \
+ zval tmp_member; \
+ if( Z_TYPE_P( member ) != IS_STRING ) \
+ { \
+ tmp_member = *member; \
+ zval_copy_ctor( &tmp_member ); \
+ convert_to_string( &tmp_member ); \
+ member = &tmp_member; \
+ key = NULL; \
+ }
+#else
+# define TRANSLITERATOR_PROPERTY_HANDLER_PROLOG \
+ zval tmp_member; \
+ if( Z_TYPE_P( member ) != IS_STRING ) \
+ { \
+ tmp_member = *member; \
+ zval_copy_ctor( &tmp_member ); \
+ convert_to_string( &tmp_member ); \
+ member = &tmp_member; \
+ }
+#endif
+
+#define TRANSLITERATOR_PROPERTY_HANDLER_EPILOG \
+ if( member == &tmp_member ) \
+ { \
+ zval_dtor( &tmp_member ); \
+ }
+
+/* {{{ get_property_ptr_ptr handler */
+#if PHP_VERSION_ID < 50399
+static zval **Transliterator_get_property_ptr_ptr( zval *object, zval *member TSRMLS_DC )
+#else
+static zval **Transliterator_get_property_ptr_ptr( zval *object, zval *member,
+ const struct _zend_literal *key TSRMLS_DC )
+#endif
+{
+ zval **retval;
+
+ TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
+
+ if(zend_binary_strcmp( "id", sizeof( "id" ) - 1,
+ Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 )
+ {
+ retval = NULL; /* fallback to read_property */
+ }
+ else
+ {
+#if PHP_VERSION_ID < 50399
+ retval = std_object_handlers.get_property_ptr_ptr( object, member TSRMLS_CC );
+#else
+ retval = std_object_handlers.get_property_ptr_ptr( object, member, key TSRMLS_CC );
+#endif
+ }
+
+ TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
+
+ return retval;
+}
+/* }}} */
+
+/* {{{ read_property handler */
+#if PHP_VERSION_ID < 50399
+static zval *Transliterator_read_property( zval *object, zval *member, int type TSRMLS_DC ) /* {{{ */
+#else
+static zval *Transliterator_read_property( zval *object, zval *member, int type,
+ const struct _zend_literal *key TSRMLS_DC ) /* {{{ */
+#endif
+{
+ zval *retval;
+
+ TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
+
+ if( ( type != BP_VAR_R && type != BP_VAR_IS ) &&
+ ( zend_binary_strcmp( "id", sizeof( "id" ) - 1,
+ Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) )
+ {
+ php_error_docref0( NULL TSRMLS_CC, E_WARNING, "The property \"id\" is read-only" );
+ retval = &EG( uninitialized_zval );
+ }
+ else
+ {
+#if PHP_VERSION_ID < 50399
+ retval = std_object_handlers.read_property( object, member, type TSRMLS_CC );
+#else
+ retval = std_object_handlers.read_property( object, member, type, key TSRMLS_CC );
+#endif
+ }
+
+ TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
+
+ return retval;
+}
+
+/* }}} */
+
+/* {{{ write_property handler */
+#if PHP_VERSION_ID < 50399
+static void Transliterator_write_property( zval *object, zval *member, zval *value TSRMLS_DC )
+#else
+static void Transliterator_write_property( zval *object, zval *member, zval *value,
+ const struct _zend_literal *key TSRMLS_DC )
+#endif
+{
+ TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
+
+ if( ( EG( scope ) != Transliterator_ce_ptr ) &&
+ ( zend_binary_strcmp( "id", sizeof( "id" ) - 1,
+ Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) )
+ {
+ php_error_docref0( NULL TSRMLS_CC, E_WARNING, "The property \"id\" is read-only" );
+ }
+ else
+ {
+#if PHP_VERSION_ID < 50399
+ std_object_handlers.write_property( object, member, value TSRMLS_CC );
+#else
+ std_object_handlers.write_property( object, member, value, key TSRMLS_CC );
+#endif
+ }
+
+ TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
+}
+/* }}} */
+
+/*
+ * 'Transliterator' class registration structures & functions
+ */
+
+/* {{{ Transliterator methods arguments info */
+
+ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_void, 0, 0, 0 )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_create, 0, 0, 1 )
+ ZEND_ARG_INFO( 0, id )
+ ZEND_ARG_INFO( 0, direction )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_create_from_rules, 0, 0, 1 )
+ ZEND_ARG_INFO( 0, rules )
+ ZEND_ARG_INFO( 0, direction )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_create_inverse, 0, 0, 1 )
+ ZEND_ARG_OBJ_INFO( 0, orig_trans, Transliterator, 0 )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_me_transliterate, 0, 0, 1 )
+ ZEND_ARG_INFO( 0, subject )
+ ZEND_ARG_INFO( 0, start )
+ ZEND_ARG_INFO( 0, end )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX( ainfo_trans_error, 0, 0, 1 )
+ ZEND_ARG_OBJ_INFO( 0, trans, Transliterator, 0 )
+ZEND_END_ARG_INFO()
+
+/* }}} */
+
+/* {{{ Transliterator_class_functions
+ * Every 'Transliterator' class method has an entry in this table
+ */
+zend_function_entry Transliterator_class_functions[] = {
+ PHP_ME( Transliterator, __construct, ainfo_trans_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR | ZEND_ACC_FINAL )
+ PHP_ME_MAPPING( create, transliterator_create, ainfo_trans_create, ZEND_ACC_STATIC |ZEND_ACC_PUBLIC )
+ PHP_ME_MAPPING( createFromRules,transliterator_create_from_rules, ainfo_trans_create_from_rules, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC )
+ PHP_ME_MAPPING( createInverse, transliterator_create_inverse, ainfo_trans_void, ZEND_ACC_PUBLIC )
+ PHP_ME_MAPPING( listIDs, transliterator_list_ids, ainfo_trans_void, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC )
+ PHP_ME_MAPPING( transliterate, transliterator_transliterate, ainfo_trans_me_transliterate, ZEND_ACC_PUBLIC )
+ PHP_ME_MAPPING( getErrorCode, transliterator_get_error_code, ainfo_trans_void, ZEND_ACC_PUBLIC )
+ PHP_ME_MAPPING( getErrorMessage,transliterator_get_error_message, ainfo_trans_void, ZEND_ACC_PUBLIC )
+ PHP_FE_END
+};
+/* }}} */
+
+/* {{{ transliterator_register_Transliterator_class
+ * Initialize 'Transliterator' class
+ */
+void transliterator_register_Transliterator_class( TSRMLS_D )
+{
+ zend_class_entry ce;
+
+ /* Create and register 'Transliterator' class. */
+ INIT_CLASS_ENTRY( ce, "Transliterator", Transliterator_class_functions );
+ ce.create_object = Transliterator_object_create;
+ Transliterator_ce_ptr = zend_register_internal_class( &ce TSRMLS_CC );
+ memcpy( &Transliterator_handlers, zend_get_std_object_handlers(),
+ sizeof Transliterator_handlers );
+ Transliterator_handlers.clone_obj = Transliterator_clone_obj;
+ Transliterator_handlers.get_property_ptr_ptr = Transliterator_get_property_ptr_ptr;
+ Transliterator_handlers.read_property = Transliterator_read_property;
+ Transliterator_handlers.write_property = Transliterator_write_property;
+
+ /* Declare 'Transliterator' class properties */
+ if( !Transliterator_ce_ptr )
+ {
+ zend_error( E_ERROR,
+ "Transliterator: attempt to create properties "
+ "on a non-registered class." );
+ return;
+ }
+ zend_declare_property_null( Transliterator_ce_ptr,
+ "id", sizeof( "id" ) - 1, ZEND_ACC_PUBLIC TSRMLS_CC );
+
+ /* constants are declared in transliterator_register_constants, called from MINIT */
+
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/transliterator/transliterator_class.h b/ext/intl/transliterator/transliterator_class.h
new file mode 100644
index 0000000000..5ca50ed2f4
--- /dev/null
+++ b/ext/intl/transliterator/transliterator_class.h
@@ -0,0 +1,65 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@netcabo.pt> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef TRANSLITERATOR_CLASS_H
+#define TRANSLITERATOR_CLASS_H
+
+#include <php.h>
+
+#include "intl_common.h"
+#include "intl_error.h"
+
+#include <unicode/utrans.h>
+
+typedef struct {
+ zend_object zo;
+
+ // error handling
+ intl_error err;
+
+ // ICU transliterator
+ UTransliterator* utrans;
+} Transliterator_object;
+
+#define TRANSLITERATOR_FORWARD UTRANS_FORWARD
+#define TRANSLITERATOR_REVERSE UTRANS_REVERSE
+
+#define TRANSLITERATOR_ERROR( co ) (co)->err
+#define TRANSLITERATOR_ERROR_P( co ) &(TRANSLITERATOR_ERROR( co ))
+
+#define TRANSLITERATOR_ERROR_CODE( co ) INTL_ERROR_CODE(TRANSLITERATOR_ERROR( co ))
+#define TRANSLITERATOR_ERROR_CODE_P( co ) &(INTL_ERROR_CODE(TRANSLITERATOR_ERROR( co )))
+
+#define TRANSLITERATOR_METHOD_INIT_VARS INTL_METHOD_INIT_VARS( Transliterator, to )
+#define TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK INTL_METHOD_FETCH_OBJECT( Transliterator, to )
+#define TRANSLITERATOR_METHOD_FETCH_OBJECT\
+ TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; \
+ if( to->utrans == NULL ) \
+ { \
+ intl_errors_set( &to->err, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed transliterator", 0 TSRMLS_CC ); \
+ RETURN_FALSE; \
+ }
+
+int transliterator_object_construct( zval *object,
+ UTransliterator *utrans,
+ UErrorCode *status TSRMLS_DC );
+
+void transliterator_register_Transliterator_class( TSRMLS_D );
+
+extern zend_class_entry *Transliterator_ce_ptr;
+extern zend_object_handlers Transliterator_handlers;
+
+#endif /* #ifndef TRANSLITERATOR_CLASS_H */
diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c
new file mode 100644
index 0000000000..d0cfb9790d
--- /dev/null
+++ b/ext/intl/transliterator/transliterator_methods.c
@@ -0,0 +1,542 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_intl.h"
+#include "transliterator.h"
+#include "transliterator_class.h"
+#include "transliterator_methods.h"
+#include "intl_data.h"
+#include "intl_convert.h"
+
+#include <zend_exceptions.h>
+
+static int create_transliterator( char *str_id, int str_id_len, long direction, zval *object TSRMLS_DC )
+{
+ Transliterator_object *to;
+ UChar *ustr_id = NULL;
+ int32_t ustr_id_len = 0;
+ UTransliterator *utrans;
+ UParseError parse_error = {0, -1};
+
+ intl_error_reset( NULL TSRMLS_CC );
+
+ if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_create: invalid direction", 0 TSRMLS_CC );
+ return FAILURE;
+ }
+
+ object_init_ex( object, Transliterator_ce_ptr );
+ TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* fetch zend object from zval "object" into "to" */
+
+ /* Convert transliterator id to UTF-16 */
+ intl_convert_utf8_to_utf16( &ustr_id, &ustr_id_len, str_id, str_id_len, TRANSLITERATOR_ERROR_CODE_P( to ) );
+ if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
+ {
+ intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) TSRMLS_CC );
+ intl_error_set_custom_msg( NULL, "String conversion of id to UTF-16 failed", 0 TSRMLS_CC );
+ zval_dtor( object );
+ return FAILURE;
+ }
+
+ /* Open ICU Transliterator. */
+ utrans = utrans_openU( ustr_id, ustr_id_len, (UTransDirection ) direction,
+ NULL, -1, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) );
+ if (ustr_id) {
+ efree( ustr_id );
+ }
+
+ if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
+ {
+ char *buf = NULL;
+ intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) TSRMLS_CC );
+ spprintf( &buf, 0, "transliterator_create: unable to open ICU transliterator"
+ " with id \"%s\"", str_id );
+ if( buf == NULL ) {
+ intl_error_set_custom_msg( NULL,
+ "transliterator_create: unable to open ICU transliterator", 0 TSRMLS_CC );
+ }
+ else
+ {
+ intl_error_set_custom_msg( NULL, buf, /* copy message */ 1 TSRMLS_CC );
+ efree( buf );
+ }
+ zval_dtor( object );
+ return FAILURE;
+ }
+
+ transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) TSRMLS_CC );
+ /* no need to close the transliterator manually on construction error */
+ if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
+ {
+ intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) TSRMLS_CC );
+ intl_error_set_custom_msg( NULL,
+ "transliterator_create: internal constructor call failed", 0 TSRMLS_CC );
+ zval_dtor( object );
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+/* {{{ proto Transliterator transliterator_create( string id [, int direction ] )
+ * proto Transliterator Transliterator::create( string id [, int direction ] )
+ * Opens a transliterator by id.
+ */
+PHP_FUNCTION( transliterator_create )
+{
+ char *str_id;
+ int str_id_len;
+ long direction = TRANSLITERATOR_FORWARD;
+ int res;
+
+ TRANSLITERATOR_METHOD_INIT_VARS;
+
+ (void) to; /* unused */
+
+ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
+ &str_id, &str_id_len, &direction ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_create: bad arguments", 0 TSRMLS_CC );
+ RETURN_NULL();
+ }
+
+ object = return_value;
+ res = create_transliterator( str_id, str_id_len, direction, object TSRMLS_CC );
+ if( res == FAILURE )
+ RETURN_NULL();
+
+ /* success, leave return_value as it is (set by create_transliterator) */
+}
+/* }}} */
+
+/* {{{ proto Transliterator transliterator_create_from_rules( string rules [, int direction ] )
+ * proto Transliterator Transliterator::createFromRules( string rules [, int direction ] )
+ * Opens a transliterator by id.
+ */
+PHP_FUNCTION( transliterator_create_from_rules )
+{
+ char *str_rules;
+ int str_rules_len;
+ UChar *ustr_rules = NULL;
+ int32_t ustr_rules_len = 0;
+ long direction = TRANSLITERATOR_FORWARD;
+ UParseError parse_error = {0, -1};
+ UTransliterator *utrans;
+ UChar id[] = {0x52, 0x75, 0x6C, 0x65, 0x73, 0x54, 0x72,
+ 0x61, 0x6E, 0x73, 0x50, 0x48, 0x50, 0}; /* RulesTransPHP */
+ TRANSLITERATOR_METHOD_INIT_VARS;
+
+ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
+ &str_rules, &str_rules_len, &direction ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_create_from_rules: bad arguments", 0 TSRMLS_CC );
+ RETURN_NULL();
+ }
+
+ if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_create_from_rules: invalid direction", 0 TSRMLS_CC );
+ RETURN_NULL();
+ }
+
+ object = return_value;
+ object_init_ex( object, Transliterator_ce_ptr );
+ TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
+
+ intl_convert_utf8_to_utf16( &ustr_rules, &ustr_rules_len,
+ str_rules, str_rules_len, TRANSLITERATOR_ERROR_CODE_P( to ) );
+ /* (I'm not a big fan of non-obvious flow control macros ).
+ * This one checks the error value, destroys object and returns false */
+ INTL_CTOR_CHECK_STATUS( to, "String conversion of rules to UTF-16 failed" );
+
+ /* Open ICU Transliterator. */
+ utrans = utrans_openU( id, ( sizeof( id ) - 1 ) / ( sizeof( *id ) ), (UTransDirection ) direction,
+ ustr_rules, ustr_rules_len, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) );
+ if (ustr_rules) {
+ efree( ustr_rules );
+ }
+
+ intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( to ) TSRMLS_CC );
+ if( U_FAILURE( INTL_DATA_ERROR_CODE( to ) ) )
+ {
+ char *msg = NULL;
+ smart_str parse_error_str;
+ parse_error_str = transliterator_parse_error_to_string( &parse_error );
+ spprintf( &msg, 0, "transliterator_create_from_rules: unable to "
+ "create ICU transliterator from rules (%s)", parse_error_str.c );
+ smart_str_free( &parse_error_str );
+ if( msg != NULL )
+ {
+ intl_errors_set_custom_msg( INTL_DATA_ERROR_P( to ), msg, 1 TSRMLS_CC );
+ efree( msg );
+ }
+ zval_dtor( return_value );
+ RETURN_NULL();
+ }
+ transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) TSRMLS_CC );
+ /* no need to close the transliterator manually on construction error */
+ INTL_CTOR_CHECK_STATUS( to, "transliterator_create_from_rules: internal constructor call failed" );
+}
+/* }}} */
+
+/* {{{ proto Transliterator transliterator_create_inverse( Transliterator orig_trans )
+ * proto Transliterator Transliterator::createInverse()
+ * Opens the inverse transliterator transliterator.
+ */
+PHP_FUNCTION( transliterator_create_inverse )
+{
+ Transliterator_object *to_orig;
+ UTransliterator *utrans;
+ TRANSLITERATOR_METHOD_INIT_VARS;
+
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
+ &object, Transliterator_ce_ptr ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_create_inverse: bad arguments", 0 TSRMLS_CC );
+ RETURN_NULL();
+ }
+
+ TRANSLITERATOR_METHOD_FETCH_OBJECT;
+ to_orig = to;
+
+ object = return_value;
+ object_init_ex( object, Transliterator_ce_ptr );
+ TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* change "to" into new object (from "object" ) */
+
+ utrans = utrans_openInverse( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to ) );
+ INTL_CTOR_CHECK_STATUS( to, "transliterator_create_inverse: could not create "
+ "inverse ICU transliterator" );
+ transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) TSRMLS_CC );
+ /* no need to close the transliterator manually on construction error */
+ INTL_CTOR_CHECK_STATUS( to, "transliterator_create: internal constructor call failed" );
+}
+/* }}} */
+
+/* {{{ proto array transliterator_list_ids()
+ * proto array Transliterator::listIDs()
+ * Return an array with the registered transliterator IDs.
+ */
+PHP_FUNCTION( transliterator_list_ids )
+{
+ UEnumeration *en;
+ const UChar *elem;
+ int32_t elem_len;
+ UErrorCode status = U_ZERO_ERROR;
+
+ intl_error_reset( NULL TSRMLS_CC );
+
+ if( zend_parse_parameters_none() == FAILURE )
+ {
+ /* seems to be the convention in this lib to return false instead of
+ * null on bad parameter types, except on constructors and factory
+ * methods */
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_list_ids: bad arguments", 0 TSRMLS_CC );
+ RETURN_FALSE;
+ }
+
+ en = utrans_openIDs( &status );
+ INTL_CHECK_STATUS( status,
+ "transliterator_list_ids: Failed to obtain registered transliterators" );
+
+ array_init( return_value );
+ while( (elem = uenum_unext( en, &elem_len, &status )) )
+ {
+ char *el_char = NULL;
+ int el_len = 0;
+
+ intl_convert_utf16_to_utf8( &el_char, &el_len, elem, elem_len, &status );
+
+ if( U_FAILURE( status ) )
+ {
+ efree( el_char );
+ break;
+ }
+ else
+ {
+ add_next_index_stringl( return_value, el_char, el_len, 0 );
+ }
+ }
+ uenum_close( en );
+
+ intl_error_set_code( NULL, status TSRMLS_CC );
+ if( U_FAILURE( status ) )
+ {
+ zval_dtor( return_value );
+ RETVAL_FALSE;
+ intl_error_set_custom_msg( NULL, "transliterator_list_ids: "
+ "Failed to build array of registered transliterators", 0 TSRMLS_CC );
+ }
+}
+/* }}} */
+
+/* {{{ proto string transliterator_transliterate( Transliterator trans, string subject [, int start = 0 [, int end = -1 ]] )
+ * proto string Transliterator::transliterate( string subject [, int start = 0 [, int end = -1 ]] )
+ * Transliterate a string. */
+PHP_FUNCTION( transliterator_transliterate )
+{
+ char *str;
+ UChar *ustr = NULL,
+ *uresult = NULL;
+ int str_len;
+ int32_t ustr_len = 0,
+ capacity,
+ uresult_len;
+ long start = 0,
+ limit = -1;
+ int success = 0,
+ temp_trans = 0;
+ TRANSLITERATOR_METHOD_INIT_VARS;
+
+ object = getThis();
+
+ if( object == NULL )
+ {
+ /* in non-OOP version, accept both a transliterator and a string */
+ zval **arg1;
+ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "Zs|ll",
+ &arg1, &str, &str_len, &start, &limit ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_transliterate: bad arguments", 0 TSRMLS_CC );
+ RETURN_FALSE;
+ }
+
+ if( Z_TYPE_PP( arg1 ) == IS_OBJECT &&
+ instanceof_function( Z_OBJCE_PP( arg1 ), Transliterator_ce_ptr TSRMLS_CC ) )
+ {
+ object = *arg1;
+ }
+ else
+ { /* not a transliterator object as first argument */
+ int res;
+ if(Z_TYPE_PP( arg1 ) != IS_STRING )
+ {
+ SEPARATE_ZVAL( arg1 );
+ convert_to_string( *arg1 );
+ }
+ ALLOC_INIT_ZVAL( object );
+ temp_trans = 1;
+ res = create_transliterator( Z_STRVAL_PP( arg1 ), Z_STRLEN_PP( arg1 ),
+ TRANSLITERATOR_FORWARD, object TSRMLS_CC );
+ if( res == FAILURE )
+ {
+ char *message = intl_error_get_message( NULL TSRMLS_CC );
+ php_error_docref0( NULL TSRMLS_CC, E_WARNING, "Could not create "
+ "transliterator with ID \"%s\" (%s)", Z_STRVAL_PP( arg1 ), message );
+ efree( message );
+ /* don't set U_ILLEGAL_ARGUMENT_ERROR to allow fetching of inner error */
+ goto cleanup;
+ }
+ }
+ }
+ else if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s|ll",
+ &str, &str_len, &start, &limit ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_transliterate: bad arguments", 0 TSRMLS_CC );
+ RETURN_FALSE;
+ }
+
+ if( limit < -1 )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_transliterate: \"end\" argument should be "
+ "either non-negative or -1", 0 TSRMLS_CC );
+ RETURN_FALSE;
+ }
+
+ if( start < 0 || ((limit != -1 ) && (start > limit )) )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_transliterate: \"start\" argument should be "
+ "non-negative and not bigger than \"end\" (if defined)", 0 TSRMLS_CC );
+ RETURN_FALSE;
+ }
+
+ /* end argument parsing/validation */
+
+ TRANSLITERATOR_METHOD_FETCH_OBJECT;
+
+ intl_convert_utf8_to_utf16( &ustr, &ustr_len, str, str_len,
+ TRANSLITERATOR_ERROR_CODE_P( to ) );
+ INTL_METHOD_CHECK_STATUS( to, "String conversion of string to UTF-16 failed" );
+
+ /* we've started allocating resources, goto from now on */
+
+ if( ( start > ustr_len ) || (( limit != -1 ) && (limit > ustr_len ) ) )
+ {
+ char *msg;
+ spprintf( &msg, 0,
+ "transliterator_transliterate: Neither \"start\" nor the \"end\" "
+ "arguments can exceed the number of UTF-16 code units "
+ "(in this case, %d)", (int) ustr_len );
+ if(msg != NULL )
+ {
+ intl_errors_set( TRANSLITERATOR_ERROR_P( to ), U_ILLEGAL_ARGUMENT_ERROR,
+ msg, 1 TSRMLS_CC );
+ efree( msg );
+ }
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+
+ uresult = safe_emalloc( ustr_len, sizeof( UChar ), 1 * sizeof( UChar ) );
+ capacity = ustr_len + 1;
+
+ while( 1 )
+ {
+ int32_t temp_limit = ( limit == -1 ? ustr_len : (int32_t) limit );
+ memcpy( uresult, ustr, ustr_len * sizeof( UChar ) );
+ uresult_len = ustr_len;
+
+ utrans_transUChars( to->utrans, uresult, &uresult_len, capacity, (int32_t) start,
+ &temp_limit, TRANSLITERATOR_ERROR_CODE_P( to ) );
+ if( TRANSLITERATOR_ERROR_CODE( to ) == U_BUFFER_OVERFLOW_ERROR )
+ {
+ efree( uresult );
+
+ uresult = safe_emalloc( uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) );
+ capacity = uresult_len + 1;
+
+ intl_error_reset( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
+ }
+ else if(TRANSLITERATOR_ERROR_CODE( to ) == U_STRING_NOT_TERMINATED_WARNING )
+ {
+ uresult = safe_erealloc( uresult, uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) );
+
+ intl_error_reset( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
+ break;
+ }
+ else if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
+ {
+ intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) TSRMLS_CC );
+ intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to ),
+ "transliterator_transliterate: transliteration failed", 0 TSRMLS_CC );
+ goto cleanup;
+ }
+ else
+ break;
+ }
+
+ uresult[uresult_len] = (UChar) 0;
+
+ success = 1;
+
+cleanup:
+ if( ustr )
+ efree( ustr );
+
+ if( success ) {
+ /* frees uresult even on error */
+ INTL_METHOD_RETVAL_UTF8( to, uresult, uresult_len, 1 );
+ }
+ else
+ {
+ if( uresult )
+ efree( uresult );
+ RETVAL_FALSE;
+ }
+
+ if (temp_trans )
+ zval_ptr_dtor( &object );
+}
+/* }}} */
+
+PHP_METHOD( Transliterator, __construct )
+{
+ /* this constructor shouldn't be called as it's private */
+ zend_throw_exception( NULL,
+ "An object of this type cannot be created with the new operator.",
+ 0 TSRMLS_CC );
+}
+
+/* {{{ proto int transliterator_get_error_code( Transliterator trans )
+ * proto int Transliterator::getErrorCode()
+ * Get the last error code for this transliterator.
+ */
+PHP_FUNCTION( transliterator_get_error_code )
+{
+ TRANSLITERATOR_METHOD_INIT_VARS
+
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
+ &object, Transliterator_ce_ptr ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_get_error_code: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+ /* Fetch the object (without resetting its last error code ). */
+ to = zend_object_store_get_object( object TSRMLS_CC );
+ if (to == NULL )
+ RETURN_FALSE;
+
+ RETURN_LONG( (long) TRANSLITERATOR_ERROR_CODE( to ) );
+}
+/* }}} */
+
+
+/* {{{ proto string transliterator_get_error_message( Transliterator trans )
+ * proto string Transliterator::getErrorMessage()
+ * Get the last error message for this transliterator.
+ */
+PHP_FUNCTION( transliterator_get_error_message )
+{
+ const char* message = NULL;
+ TRANSLITERATOR_METHOD_INIT_VARS
+
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
+ &object, Transliterator_ce_ptr ) == FAILURE )
+ {
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "transliterator_get_error_message: unable to parse input params", 0 TSRMLS_CC );
+
+ RETURN_FALSE;
+ }
+
+
+ /* Fetch the object (without resetting its last error code ). */
+ to = zend_object_store_get_object( object TSRMLS_CC );
+ if (to == NULL )
+ RETURN_FALSE;
+
+ /* Return last error message. */
+ message = intl_error_get_message( TRANSLITERATOR_ERROR_P( to ) TSRMLS_CC );
+ RETURN_STRING( message, 0 );
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/intl/transliterator/transliterator_methods.h b/ext/intl/transliterator/transliterator_methods.h
new file mode 100644
index 0000000000..b806de84fb
--- /dev/null
+++ b/ext/intl/transliterator/transliterator_methods.h
@@ -0,0 +1,38 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef TRANSLITERATOR_METHODS_H
+#define TRANSLITERATOR_METHODS_H
+
+#include <php.h>
+
+PHP_FUNCTION( transliterator_create );
+
+PHP_FUNCTION( transliterator_create_from_rules );
+
+PHP_FUNCTION( transliterator_list_ids );
+
+PHP_FUNCTION( transliterator_create_inverse );
+
+PHP_FUNCTION( transliterator_transliterate );
+
+PHP_METHOD( Transliterator, __construct );
+
+PHP_FUNCTION( transliterator_get_error_code );
+
+PHP_FUNCTION( transliterator_get_error_message );
+
+#endif /* #ifndef TRANSLITERATOR_METHODS_H */
diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c
index ec07a4803d..dd832a7cbd 100644
--- a/ext/json/JSON_parser.c
+++ b/ext/json/JSON_parser.c
@@ -291,12 +291,14 @@ static int dehexchar(char c)
}
-static void json_create_zval(zval **z, smart_str *buf, int type)
+static void json_create_zval(zval **z, smart_str *buf, int type, int options)
{
ALLOC_INIT_ZVAL(*z);
if (type == IS_LONG)
{
+ zend_bool bigint = 0;
+
if (buf->c[0] == '-') {
buf->len--;
}
@@ -306,8 +308,21 @@ static void json_create_zval(zval **z, smart_str *buf, int type)
int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
- goto use_double;
+ bigint = 1;
+ }
+ } else {
+ bigint = 1;
+ }
+ }
+
+ if (bigint) {
+ /* value too large to represent as a long */
+ if (options & PHP_JSON_BIGINT_AS_STRING) {
+ if (buf->c[0] == '-') {
+ /* Restore last char consumed above */
+ buf->len++;
}
+ goto use_string;
} else {
goto use_double;
}
@@ -322,6 +337,7 @@ use_double:
}
else if (type == IS_STRING)
{
+use_string:
ZVAL_STRINGL(*z, buf->c, buf->len, 1);
}
else if (type == IS_BOOL)
@@ -420,12 +436,13 @@ static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int ass
machine with a stack.
*/
int
-parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
+parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int options TSRMLS_DC)
{
int next_char; /* the next character */
int next_class; /* the next character class */
int next_state; /* the next state */
int the_index;
+ int assoc = options & PHP_JSON_OBJECT_AS_ARRAY;
smart_str buf = {0};
smart_str key = {0};
@@ -530,7 +547,7 @@ parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int
zval *mval;
smart_str_0(&buf);
- json_create_zval(&mval, &buf, type);
+ json_create_zval(&mval, &buf, type, options);
if (!assoc) {
add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
@@ -558,7 +575,7 @@ parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int
zval *mval;
smart_str_0(&buf);
- json_create_zval(&mval, &buf, type);
+ json_create_zval(&mval, &buf, type, options);
add_next_index_zval(jp->the_zstack[jp->top], mval);
buf.len = 0;
JSON_RESET_TYPE();
@@ -670,7 +687,7 @@ parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int
jp->stack[jp->top] == MODE_ARRAY))
{
smart_str_0(&buf);
- json_create_zval(&mval, &buf, type);
+ json_create_zval(&mval, &buf, type, options);
}
switch (jp->stack[jp->top]) {
diff --git a/ext/json/JSON_parser.h b/ext/json/JSON_parser.h
index 746190bb35..541664b8c6 100644
--- a/ext/json/JSON_parser.h
+++ b/ext/json/JSON_parser.h
@@ -5,6 +5,7 @@
#include "php.h"
#include "ext/standard/php_smart_str.h"
+#include "php_json.h"
#define JSON_PARSER_DEFAULT_DEPTH 512
@@ -28,6 +29,12 @@ enum error_codes {
};
extern JSON_parser new_JSON_parser(int depth);
-extern int parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC);
+extern int parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int options TSRMLS_DC);
extern int free_JSON_parser(JSON_parser jp);
+
+static inline int parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
+{
+ return parse_JSON_ex(jp, z, utf16_json, length, assoc ? PHP_JSON_OBJECT_AS_ARRAY : 0 TSRMLS_CC);
+}
+
#endif
diff --git a/ext/json/config.w32 b/ext/json/config.w32
index a3559e08b7..06a48e05ed 100644
--- a/ext/json/config.w32
+++ b/ext/json/config.w32
@@ -6,5 +6,6 @@ ARG_ENABLE("json", "JavaScript Object Serialization support", "yes");
if (PHP_JSON != "no") {
EXTENSION('json', 'json.c', PHP_JSON_SHARED, "");
ADD_SOURCES(configure_module_dirname, "JSON_parser.c utf8_decode.c utf8_to_utf16.c", "json");
+ PHP_INSTALL_HEADERS("ext/json/", "php_json.h");
}
diff --git a/ext/json/json.c b/ext/json/json.c
index 5b62c2feea..786b21ac91 100644
--- a/ext/json/json.c
+++ b/ext/json/json.c
@@ -29,6 +29,7 @@
#include "utf8_to_utf16.h"
#include "JSON_parser.h"
#include "php_json.h"
+#include <zend_exceptions.h>
static PHP_MINFO_FUNCTION(json);
static PHP_FUNCTION(json_encode);
@@ -37,6 +38,8 @@ static PHP_FUNCTION(json_last_error);
static const char digits[] = "0123456789abcdef";
+zend_class_entry *php_json_serializable_ce;
+
ZEND_DECLARE_MODULE_GLOBALS(json)
/* {{{ arginfo */
@@ -49,6 +52,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
ZEND_ARG_INFO(0, json)
ZEND_ARG_INFO(0, assoc)
ZEND_ARG_INFO(0, depth)
+ ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_json_last_error, 0)
@@ -56,7 +60,7 @@ ZEND_END_ARG_INFO()
/* }}} */
/* {{{ json_functions[] */
-static const function_entry json_functions[] = {
+static const zend_function_entry json_functions[] = {
PHP_FE(json_encode, arginfo_json_encode)
PHP_FE(json_decode, arginfo_json_decode)
PHP_FE(json_last_error, arginfo_json_last_error)
@@ -64,15 +68,34 @@ static const function_entry json_functions[] = {
};
/* }}} */
+/* {{{ JsonSerializable methods */
+ZEND_BEGIN_ARG_INFO(json_serialize_arginfo, 0)
+ /* No arguments */
+ZEND_END_ARG_INFO();
+
+static const zend_function_entry json_serializable_interface[] = {
+ PHP_ABSTRACT_ME(JsonSerializable, jsonSerialize, json_serialize_arginfo)
+ PHP_FE_END
+};
+/* }}} */
+
/* {{{ MINIT */
static PHP_MINIT_FUNCTION(json)
{
+ zend_class_entry ce;
+
+ INIT_CLASS_ENTRY(ce, "JsonSerializable", json_serializable_interface);
+ php_json_serializable_ce = zend_register_internal_interface(&ce TSRMLS_CC);
+
REGISTER_LONG_CONSTANT("JSON_HEX_TAG", PHP_JSON_HEX_TAG, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_HEX_AMP", PHP_JSON_HEX_AMP, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_HEX_QUOT", PHP_JSON_HEX_QUOT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_FORCE_OBJECT", PHP_JSON_FORCE_OBJECT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_NUMERIC_CHECK", PHP_JSON_NUMERIC_CHECK, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_UNESCAPED_SLASHES", PHP_JSON_UNESCAPED_SLASHES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_PRETTY_PRINT", PHP_JSON_PRETTY_PRINT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_DEPTH", PHP_JSON_ERROR_DEPTH, CONST_CS | CONST_PERSISTENT);
@@ -81,6 +104,9 @@ static PHP_MINIT_FUNCTION(json)
REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_BIGINT_AS_STRING", PHP_JSON_BIGINT_AS_STRING, CONST_CS | CONST_PERSISTENT);
+
return SUCCESS;
}
/* }}} */
@@ -89,6 +115,7 @@ static PHP_MINIT_FUNCTION(json)
*/
static PHP_GINIT_FUNCTION(json)
{
+ json_globals->encoder_depth = 0;
json_globals->error_code = 0;
}
/* }}} */
@@ -166,6 +193,30 @@ static int json_determine_array_type(zval **val TSRMLS_DC) /* {{{ */
}
/* }}} */
+/* {{{ Pretty printing support functions */
+
+static inline void json_pretty_print_char(smart_str *buf, int options, char c TSRMLS_DC) /* {{{ */
+{
+ if (options & PHP_JSON_PRETTY_PRINT) {
+ smart_str_appendc(buf, c);
+ }
+}
+/* }}} */
+
+static inline void json_pretty_print_indent(smart_str *buf, int options TSRMLS_DC) /* {{{ */
+{
+ int i;
+
+ if (options & PHP_JSON_PRETTY_PRINT) {
+ for (i = 0; i < JSON_G(encoder_depth); ++i) {
+ smart_str_appendl(buf, " ", 4);
+ }
+ }
+}
+/* }}} */
+
+/* }}} */
+
static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC) /* {{{ */
{
int i, r;
@@ -191,6 +242,9 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
smart_str_appendc(buf, '{');
}
+ json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
+ ++JSON_G(encoder_depth);
+
i = myht ? zend_hash_num_elements(myht) : 0;
if (i > 0)
@@ -218,10 +272,12 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
if (r == PHP_JSON_OUTPUT_ARRAY) {
if (need_comma) {
smart_str_appendc(buf, ',');
+ json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
} else {
need_comma = 1;
}
-
+
+ json_pretty_print_indent(buf, options TSRMLS_CC);
php_json_encode(buf, *data, options TSRMLS_CC);
} else if (r == PHP_JSON_OUTPUT_OBJECT) {
if (i == HASH_KEY_IS_STRING) {
@@ -235,26 +291,36 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
if (need_comma) {
smart_str_appendc(buf, ',');
+ json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
} else {
need_comma = 1;
}
+ json_pretty_print_indent(buf, options TSRMLS_CC);
+
json_escape_string(buf, key, key_len - 1, options & ~PHP_JSON_NUMERIC_CHECK TSRMLS_CC);
smart_str_appendc(buf, ':');
+ json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
+
php_json_encode(buf, *data, options TSRMLS_CC);
} else {
if (need_comma) {
smart_str_appendc(buf, ',');
+ json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
} else {
need_comma = 1;
}
+ json_pretty_print_indent(buf, options TSRMLS_CC);
+
smart_str_appendc(buf, '"');
smart_str_append_long(buf, (long) index);
smart_str_appendc(buf, '"');
smart_str_appendc(buf, ':');
+ json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
+
php_json_encode(buf, *data, options TSRMLS_CC);
}
}
@@ -266,6 +332,10 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
}
}
+ --JSON_G(encoder_depth);
+ json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
+ json_pretty_print_indent(buf, options TSRMLS_CC);
+
if (r == PHP_JSON_OUTPUT_ARRAY) {
smart_str_appendc(buf, ']');
} else {
@@ -278,9 +348,10 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
static void json_escape_string(smart_str *buf, char *s, int len, int options TSRMLS_DC) /* {{{ */
{
- int pos = 0;
+ int pos = 0, ulen = 0;
unsigned short us;
unsigned short *utf16;
+ size_t newlen;
if (len == 0) {
smart_str_appendl(buf, "\"\"", 2);
@@ -308,17 +379,16 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
}
return;
}
-
- }
- utf16 = (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
+ }
- len = utf8_to_utf16(utf16, s, len);
- if (len <= 0) {
+ utf16 = (options & PHP_JSON_UNESCAPED_UNICODE) ? NULL : (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
+ ulen = utf8_to_utf16(utf16, s, len);
+ if (ulen <= 0) {
if (utf16) {
efree(utf16);
}
- if (len < 0) {
+ if (ulen < 0) {
JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
if (!PG(display_errors)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid UTF-8 sequence in argument");
@@ -329,12 +399,17 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
}
return;
}
+ if (!(options & PHP_JSON_UNESCAPED_UNICODE)) {
+ len = ulen;
+ }
+ /* pre-allocate for string length plus 2 quotes */
+ smart_str_alloc(buf, len+2, 0);
smart_str_appendc(buf, '"');
while (pos < len)
{
- us = utf16[pos++];
+ us = (options & PHP_JSON_UNESCAPED_UNICODE) ? s[pos++] : utf16[pos++];
switch (us)
{
@@ -351,7 +426,11 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
break;
case '/':
- smart_str_appendl(buf, "\\/", 2);
+ if (options & PHP_JSON_UNESCAPED_SLASHES) {
+ smart_str_appendc(buf, '/');
+ } else {
+ smart_str_appendl(buf, "\\/", 2);
+ }
break;
case '\b':
@@ -407,7 +486,7 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
break;
default:
- if (us >= ' ' && (us & 127) == us) {
+ if (us >= ' ' && ((options & PHP_JSON_UNESCAPED_UNICODE) || (us & 127) == us)) {
smart_str_appendc(buf, (unsigned char) us);
} else {
smart_str_appendl(buf, "\\u", 2);
@@ -426,7 +505,56 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
}
smart_str_appendc(buf, '"');
- efree(utf16);
+ if (utf16) {
+ efree(utf16);
+ }
+}
+/* }}} */
+
+
+static void json_encode_serializable_object(smart_str *buf, zval *val, int options TSRMLS_DC) /* {{{ */
+{
+ zend_class_entry *ce = Z_OBJCE_P(val);
+ zval *retval = NULL, fname;
+ HashTable* myht;
+
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ myht = HASH_OF(val);
+ } else {
+ myht = Z_OBJPROP_P(val);
+ }
+
+ if (myht && myht->nApplyCount > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
+ smart_str_appendl(buf, "null", 4);
+ return;
+ }
+
+ ZVAL_STRING(&fname, "jsonSerialize", 0);
+
+ if (FAILURE == call_user_function_ex(EG(function_table), &val, &fname, &retval, 0, NULL, 1, NULL TSRMLS_CC) || !retval) {
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed calling %s::jsonSerialize()", ce->name);
+ smart_str_appendl(buf, "null", sizeof("null") - 1);
+ return;
+ }
+
+ if (EG(exception)) {
+ /* Error already raised */
+ zval_ptr_dtor(&retval);
+ smart_str_appendl(buf, "null", sizeof("null") - 1);
+ return;
+ }
+
+ if ((Z_TYPE_P(retval) == IS_OBJECT) &&
+ (Z_OBJ_HANDLE_P(retval) == Z_OBJ_HANDLE_P(val))) {
+ /* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
+ json_encode_array(buf, &retval, options TSRMLS_CC);
+ } else {
+ /* All other types, encode as normal */
+ php_json_encode(buf, retval, options TSRMLS_CC);
+ }
+
+ zval_ptr_dtor(&retval);
}
/* }}} */
@@ -471,8 +599,13 @@ PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_
json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options TSRMLS_CC);
break;
- case IS_ARRAY:
case IS_OBJECT:
+ if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce TSRMLS_CC)) {
+ json_encode_serializable_object(buf, val, options TSRMLS_CC);
+ break;
+ }
+ /* fallthrough -- Non-serializable object */
+ case IS_ARRAY:
json_encode_array(buf, &val, options TSRMLS_CC);
break;
@@ -486,7 +619,7 @@ PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_
}
/* }}} */
-PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC) /* {{{ */
+PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, int options, long depth TSRMLS_DC) /* {{{ */
{
int utf16_len;
zval *z;
@@ -512,7 +645,7 @@ PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, ze
ALLOC_INIT_ZVAL(z);
jp = new_JSON_parser(depth);
- if (parse_JSON(jp, z, utf16, utf16_len, assoc TSRMLS_CC)) {
+ if (parse_JSON_ex(jp, z, utf16, utf16_len, options TSRMLS_CC)) {
*return_value = *z;
}
else
@@ -555,6 +688,7 @@ PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, ze
}
/* }}} */
+
/* {{{ proto string json_encode(mixed data [, int options])
Returns the JSON representation of a value */
static PHP_FUNCTION(json_encode)
@@ -585,8 +719,9 @@ static PHP_FUNCTION(json_decode)
int str_len;
zend_bool assoc = 0; /* return JS objects as PHP objects by default */
long depth = JSON_PARSER_DEFAULT_DEPTH;
+ long options = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &str, &str_len, &assoc, &depth) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bll", &str, &str_len, &assoc, &depth, &options) == FAILURE) {
return;
}
@@ -596,7 +731,14 @@ static PHP_FUNCTION(json_decode)
RETURN_NULL();
}
- php_json_decode(return_value, str, str_len, assoc, depth TSRMLS_CC);
+ /* For BC reasons, the bool $assoc overrides the long $options bit for PHP_JSON_OBJECT_AS_ARRAY */
+ if (assoc) {
+ options |= PHP_JSON_OBJECT_AS_ARRAY;
+ } else {
+ options &= ~PHP_JSON_OBJECT_AS_ARRAY;
+ }
+
+ php_json_decode_ex(return_value, str, str_len, options, depth TSRMLS_CC);
}
/* }}} */
diff --git a/ext/json/php_json.h b/ext/json/php_json.h
index b104d4ca6a..ef3e4b5a79 100644
--- a/ext/json/php_json.h
+++ b/ext/json/php_json.h
@@ -38,6 +38,7 @@ extern zend_module_entry json_module_entry;
#endif
ZEND_BEGIN_MODULE_GLOBALS(json)
+ int encoder_depth;
int error_code;
ZEND_END_MODULE_GLOBALS(json)
@@ -48,17 +49,34 @@ ZEND_END_MODULE_GLOBALS(json)
#endif
PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_DC);
-PHP_JSON_API void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC);
+PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len, int options, long depth TSRMLS_DC);
+extern zend_class_entry *php_json_serializable_ce;
+
+/* json_encode() options */
#define PHP_JSON_HEX_TAG (1<<0)
#define PHP_JSON_HEX_AMP (1<<1)
#define PHP_JSON_HEX_APOS (1<<2)
#define PHP_JSON_HEX_QUOT (1<<3)
#define PHP_JSON_FORCE_OBJECT (1<<4)
#define PHP_JSON_NUMERIC_CHECK (1<<5)
+#define PHP_JSON_UNESCAPED_SLASHES (1<<6)
+#define PHP_JSON_PRETTY_PRINT (1<<7)
+#define PHP_JSON_UNESCAPED_UNICODE (1<<8)
+
+/* Internal flags */
+#define PHP_JSON_OUTPUT_ARRAY 0
+#define PHP_JSON_OUTPUT_OBJECT 1
+
+/* json_decode() options */
+#define PHP_JSON_OBJECT_AS_ARRAY (1<<0)
+#define PHP_JSON_BIGINT_AS_STRING (1<<1)
+
+static inline void php_json_decode(zval *return_value, char *str, int str_len, zend_bool assoc, long depth TSRMLS_DC)
+{
+ php_json_decode_ex(return_value, str, str_len, assoc ? PHP_JSON_OBJECT_AS_ARRAY : 0, depth TSRMLS_CC);
+}
-#define PHP_JSON_OUTPUT_ARRAY 0
-#define PHP_JSON_OUTPUT_OBJECT 1
#endif /* PHP_JSON_H */
diff --git a/ext/json/tests/008.phpt b/ext/json/tests/008.phpt
new file mode 100644
index 0000000000..f2354d381f
--- /dev/null
+++ b/ext/json/tests/008.phpt
@@ -0,0 +1,17 @@
+--TEST--
+json_decode() with large integers
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+$json = '{"largenum":123456789012345678901234567890}';
+$x = json_decode($json);
+var_dump($x->largenum);
+$x = json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
+var_dump($x->largenum);
+echo "Done\n";
+?>
+--EXPECT--
+float(1.2345678901235E+29)
+string(30) "123456789012345678901234567890"
+Done
diff --git a/ext/json/tests/bug53946.phpt b/ext/json/tests/bug53946.phpt
new file mode 100644
index 0000000000..abbb81238b
--- /dev/null
+++ b/ext/json/tests/bug53946.phpt
@@ -0,0 +1,16 @@
+--TEST--
+bug #53946 (json_encode() with JSON_UNESCAPED_UNICODE)
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+var_dump(json_encode("latin 1234 -/ russian мама мыла раму specialchars \x02 \x08 \n U+1D11E >ð„ž<"));
+var_dump(json_encode("latin 1234 -/ russian мама мыла раму specialchars \x02 \x08 \n U+1D11E >ð„ž<", JSON_UNESCAPED_UNICODE));
+var_dump(json_encode("ab\xE0"));
+var_dump(json_encode("ab\xE0", JSON_UNESCAPED_UNICODE));
+?>
+--EXPECT--
+string(156) ""latin 1234 -\/ russian \u043c\u0430\u043c\u0430 \u043c\u044b\u043b\u0430 \u0440\u0430\u043c\u0443 specialchars \u0002 \b \n U+1D11E >\ud834\udd1e<""
+string(100) ""latin 1234 -\/ russian мама мыла раму specialchars \u0002 \b \n U+1D11E >ð„ž<""
+string(4) "null"
+string(4) "null"
diff --git a/ext/json/tests/bug61978.phpt b/ext/json/tests/bug61978.phpt
new file mode 100644
index 0000000000..2c732979ef
--- /dev/null
+++ b/ext/json/tests/bug61978.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #61978 (Object recursion not detected for classes that implement JsonSerializable)
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+class JsonTest1 {
+ public $test;
+ public $me;
+ public function __construct() {
+ $this->test = '123';
+ $this->me = $this;
+ }
+}
+
+class JsonTest2 implements JsonSerializable {
+ public $test;
+ public function __construct() {
+ $this->test = '123';
+ }
+ public function jsonSerialize() {
+ return array(
+ 'test' => $this->test,
+ 'me' => $this
+ );
+ }
+}
+
+
+$obj1 = new JsonTest1();
+var_dump(json_encode($obj1));
+
+echo "\n==\n";
+
+$obj2 = new JsonTest2();
+var_dump(json_encode($obj2));
+
+?>
+--EXPECTF--
+Warning: json_encode(): recursion detected in %s on line %d
+string(44) "{"test":"123","me":{"test":"123","me":null}}"
+
+==
+
+Warning: json_encode(): recursion detected in %s on line %d
+string(44) "{"test":"123","me":{"test":"123","me":null}}"
diff --git a/ext/json/tests/json_decode_error.phpt b/ext/json/tests/json_decode_error.phpt
index f3387c21be..4d5d4e4bee 100644
--- a/ext/json/tests/json_decode_error.phpt
+++ b/ext/json/tests/json_decode_error.phpt
@@ -20,7 +20,7 @@ var_dump( json_decode() );
echo "\n-- Testing json_decode() function with more than expected no. of arguments --\n";
$extra_arg = 10;
-var_dump( json_decode('"abc"', TRUE, 512, $extra_arg) );
+var_dump( json_decode('"abc"', TRUE, 512, 0, $extra_arg) );
?>
===Done===
@@ -34,6 +34,6 @@ NULL
-- Testing json_decode() function with more than expected no. of arguments --
-Warning: json_decode() expects at most 3 parameters, 4 given in %s on line %d
+Warning: json_decode() expects at most 4 parameters, 5 given in %s on line %d
NULL
===Done===
diff --git a/ext/json/tests/json_encode_basic.phpt b/ext/json/tests/json_encode_basic.phpt
index 003fcd44c6..152e24444c 100644
--- a/ext/json/tests/json_encode_basic.phpt
+++ b/ext/json/tests/json_encode_basic.phpt
@@ -155,4 +155,4 @@ Warning: json_encode(): type is unsupported, encoded as null in %s on line %d
string(4) "null"
-- Iteration 27 --
string(82) "{"MyInt":99,"MyFloat":123.45,"MyBool":true,"MyNull":null,"MyString":"Hello World"}"
-===Done===
+===Done=== \ No newline at end of file
diff --git a/ext/json/tests/json_encode_numeric.phpt b/ext/json/tests/json_encode_numeric.phpt
new file mode 100644
index 0000000000..5392350194
--- /dev/null
+++ b/ext/json/tests/json_encode_numeric.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Test json_encode() function with numeric flag
+--SKIPIF--
+<?php
+if (!extension_loaded("json")) {
+ die('skip JSON extension not available in this build');
+}
+?>
+--FILE--
+<?php
+var_dump(
+ json_encode("1", JSON_NUMERIC_CHECK),
+ json_encode("9.4324", JSON_NUMERIC_CHECK),
+ json_encode(array("122321", "3232595.33423"), JSON_NUMERIC_CHECK),
+ json_encode("1"),
+ json_encode("9.4324"),
+ json_encode(array("122321", "3232595.33423"))
+);
+?>
+--EXPECT--
+string(1) "1"
+string(6) "9.4324"
+string(22) "[122321,3232595.33423]"
+string(3) ""1""
+string(8) ""9.4324""
+string(26) "["122321","3232595.33423"]"
diff --git a/ext/json/tests/json_encode_pretty_print.phpt b/ext/json/tests/json_encode_pretty_print.phpt
new file mode 100644
index 0000000000..43b93aafe6
--- /dev/null
+++ b/ext/json/tests/json_encode_pretty_print.phpt
@@ -0,0 +1,40 @@
+--TEST--
+json_encode() with JSON_PRETTY_PRINT
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+function encode_decode($json) {
+ $struct = json_decode($json);
+ $pretty = json_encode($struct, JSON_PRETTY_PRINT);
+ echo "$pretty\n";
+ $pretty = json_decode($pretty);
+ printf("Match: %d\n", $pretty == $struct);
+}
+
+encode_decode('[1,2,3,[1,2,3]]');
+encode_decode('{"a":1,"b":[1,2],"c":{"d":42}}');
+?>
+--EXPECT--
+[
+ 1,
+ 2,
+ 3,
+ [
+ 1,
+ 2,
+ 3
+ ]
+]
+Match: 1
+{
+ "a": 1,
+ "b": [
+ 1,
+ 2
+ ],
+ "c": {
+ "d": 42
+ }
+}
+Match: 1
diff --git a/ext/json/tests/json_encode_unescaped_slashes.phpt b/ext/json/tests/json_encode_unescaped_slashes.phpt
new file mode 100644
index 0000000000..72ebae927a
--- /dev/null
+++ b/ext/json/tests/json_encode_unescaped_slashes.phpt
@@ -0,0 +1,12 @@
+--TEST--
+json_decode() tests
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+var_dump(json_encode('a/b'));
+var_dump(json_encode('a/b', JSON_UNESCAPED_SLASHES));
+?>
+--EXPECT--
+string(6) ""a\/b""
+string(5) ""a/b""
diff --git a/ext/json/tests/serialize.phpt b/ext/json/tests/serialize.phpt
new file mode 100644
index 0000000000..5c513d58ad
--- /dev/null
+++ b/ext/json/tests/serialize.phpt
@@ -0,0 +1,80 @@
+--TEST--
+json_encode() Serialization tests
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+class NonSerializingTest
+{
+ public $data;
+
+ public function __construct($data)
+ {
+ $this->data = $data;
+ }
+}
+
+class SerializingTest extends NonSerializingTest implements JsonSerializable
+{
+ public function jsonSerialize()
+ {
+ return $this->data;
+ }
+}
+
+class ValueSerializingTest extends SerializingTest
+{
+ public function jsonSerialize()
+ {
+ return array_values(is_array($this->data) ? $this->data : get_object_vars($this->data));
+ }
+}
+
+class SelfSerializingTest extends SerializingTest
+{
+ public function jsonSerialize()
+ {
+ return $this;
+ }
+}
+
+$adata = array(
+ 'str' => 'foo',
+ 'int' => 1,
+ 'float' => 2.3,
+ 'bool' => false,
+ 'nil' => null,
+ 'arr' => array(1,2,3),
+ 'obj' => new StdClass,
+);
+
+$ndata = array_values($adata);
+
+$odata = (object)$adata;
+
+foreach(array('NonSerializingTest','SerializingTest','ValueSerializingTest','SelfSerializingTest') as $class) {
+ echo "==$class==\n";
+ echo json_encode(new $class($adata)), "\n";
+ echo json_encode(new $class($ndata)), "\n";
+ echo json_encode(new $class($odata)), "\n";
+}
+--EXPECT--
+==NonSerializingTest==
+{"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}}
+{"data":["foo",1,2.3,false,null,[1,2,3],{}]}
+{"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}}
+==SerializingTest==
+{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}
+["foo",1,2.3,false,null,[1,2,3],{}]
+{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}
+==ValueSerializingTest==
+["foo",1,2.3,false,null,[1,2,3],{}]
+["foo",1,2.3,false,null,[1,2,3],{}]
+["foo",1,2.3,false,null,[1,2,3],{}]
+==SelfSerializingTest==
+{"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}}
+{"data":["foo",1,2.3,false,null,[1,2,3],{}]}
+{"data":{"str":"foo","int":1,"float":2.3,"bool":false,"nil":null,"arr":[1,2,3],"obj":{}}}
+
+
diff --git a/ext/json/utf8_to_utf16.c b/ext/json/utf8_to_utf16.c
index 599f0e13b4..508bc9368a 100644
--- a/ext/json/utf8_to_utf16.c
+++ b/ext/json/utf8_to_utf16.c
@@ -30,7 +30,7 @@ SOFTWARE.
#include "utf8_decode.h"
int
-utf8_to_utf16(unsigned short w[], char p[], int length)
+utf8_to_utf16(unsigned short *w, char p[], int length)
{
int c;
int the_index = 0;
@@ -43,14 +43,17 @@ utf8_to_utf16(unsigned short w[], char p[], int length)
return (c == UTF8_END) ? the_index : UTF8_ERROR;
}
if (c < 0x10000) {
- w[the_index] = (unsigned short)c;
+ if (w) {
+ w[the_index] = (unsigned short)c;
+ }
the_index += 1;
} else {
c -= 0x10000;
- w[the_index] = (unsigned short)(0xD800 | (c >> 10));
- the_index += 1;
- w[the_index] = (unsigned short)(0xDC00 | (c & 0x3FF));
- the_index += 1;
+ if (w) {
+ w[the_index] = (unsigned short)(0xD800 | (c >> 10));
+ w[the_index + 1] = (unsigned short)(0xDC00 | (c & 0x3FF));
+ }
+ the_index += 2;
}
}
}
diff --git a/ext/json/utf8_to_utf16.h b/ext/json/utf8_to_utf16.h
index 5aff0268bf..5c9685a991 100644
--- a/ext/json/utf8_to_utf16.h
+++ b/ext/json/utf8_to_utf16.h
@@ -1,3 +1,3 @@
/* utf8_to_utf16.h */
-extern int utf8_to_utf16(unsigned short w[], char p[], int length);
+extern int utf8_to_utf16(unsigned short *w, char p[], int length);
diff --git a/ext/ldap/config.w32 b/ext/ldap/config.w32
index d9a270d298..2fa05f4383 100644
--- a/ext/ldap/config.w32
+++ b/ext/ldap/config.w32
@@ -11,19 +11,16 @@ if (PHP_LDAP != "no") {
CHECK_LIB("ssleay32.lib", "ldap", PHP_LDAP) &&
CHECK_LIB("libeay32.lib", "ldap", PHP_LDAP) &&
CHECK_LIB("oldap32_a.lib", "ldap", PHP_LDAP) &&
- CHECK_LIB("olber32_a.lib", "ldap", PHP_LDAP)
- ) {
- if (CHECK_LIB("libsasl.lib", "ldap", PHP_LDAP)) {
- AC_DEFINE('HAVE_LDAP_SASL', 1);
- AC_DEFINE('HAVE_LDAP_SASL_SASL_H', 1);
- PHP_LDAP = 1;
- }
+ CHECK_LIB("olber32_a.lib", "ldap", PHP_LDAP)&&
+ CHECK_LIB("libsasl.lib", "ldap", PHP_LDAP)) {
EXTENSION('ldap', 'ldap.c');
AC_DEFINE('HAVE_LDAP_PARSE_RESULT', 1);
AC_DEFINE('HAVE_LDAP_PARSE_REFERENCE', 1);
AC_DEFINE('HAVE_LDAP_START_TLS_S', 1);
AC_DEFINE('HAVE_LDAP', 1);
+ AC_DEFINE('HAVE_LDAP_SASL', 1);
+ AC_DEFINE('HAVE_LDAP_SASL_SASL_H', 1);
AC_DEFINE('LDAP_DEPRECATED', 1);
} else {
diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c
index aea21da0c1..47d3ab167a 100644
--- a/ext/ldap/ldap.c
+++ b/ext/ldap/ldap.c
@@ -587,7 +587,7 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, in
*/
static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
{
- zval *link, *base_dn, **filter, *attrs, **attr;
+ zval *link, *base_dn, **filter, *attrs = NULL, **attr;
long attrsonly, sizelimit, timelimit, deref;
char *ldap_base_dn = NULL, *ldap_filter = NULL, **ldap_attrs = NULL;
ldap_linkdata *ld = NULL;
@@ -2185,6 +2185,192 @@ PHP_FUNCTION(ldap_8859_to_t61)
/* }}} */
#endif
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+/* {{{ proto mixed ldap_control_paged_result(resource link, int pagesize [, bool iscritical [, string cookie]])
+ Inject paged results control*/
+PHP_FUNCTION(ldap_control_paged_result)
+{
+ long pagesize;
+ zend_bool iscritical;
+ zval *link;
+ char *cookie = NULL;
+ int cookie_len = 0;
+ struct berval lcookie = { 0, NULL };
+ ldap_linkdata *ld;
+ LDAP *ldap;
+ BerElement *ber = NULL;
+ LDAPControl ctrl, *ctrlsp[2];
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|bs", &link, &pagesize, &iscritical, &cookie, &cookie_len) != SUCCESS) {
+ return;
+ }
+
+ if (Z_TYPE_P(link) == IS_NULL) {
+ ldap = NULL;
+ } else {
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
+ ldap = ld->link;
+ }
+
+ ber = ber_alloc_t(LBER_USE_DER);
+ if (ber == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control");
+ RETURN_FALSE;
+ }
+
+ ctrl.ldctl_iscritical = 0;
+
+ switch (myargcount) {
+ case 4:
+ lcookie.bv_val = cookie;
+ lcookie.bv_len = cookie_len;
+ /* fallthru */
+ case 3:
+ ctrl.ldctl_iscritical = (int)iscritical;
+ /* fallthru */
+ }
+
+ if (ber_printf(ber, "{iO}", (int)pagesize, &lcookie) == LBER_ERROR) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER printf paged results control");
+ RETVAL_FALSE;
+ goto lcpr_error_out;
+ }
+ rc = ber_flatten2(ber, &ctrl.ldctl_value, 0);
+ if (rc == LBER_ERROR) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode paged results control");
+ RETVAL_FALSE;
+ goto lcpr_error_out;
+ }
+
+ ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+
+ if (ldap) {
+ /* directly set the option */
+ ctrlsp[0] = &ctrl;
+ ctrlsp[1] = NULL;
+
+ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp);
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc);
+ RETVAL_FALSE;
+ goto lcpr_error_out;
+ }
+ RETVAL_TRUE;
+ } else {
+ /* return a PHP control object */
+ array_init(return_value);
+
+ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1);
+ if (ctrl.ldctl_value.bv_len) {
+ add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len, 1);
+ }
+ if (ctrl.ldctl_iscritical) {
+ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical);
+ }
+ }
+
+lcpr_error_out:
+ if (ber != NULL) {
+ ber_free(ber, 1);
+ }
+ return;
+}
+/* }}} */
+
+/* {{{ proto bool ldap_control_paged_result_response(resource link, resource result [, string &cookie [, int &estimated]])
+ Extract paged results control response */
+PHP_FUNCTION(ldap_control_paged_result_response)
+{
+ zval *link, *result, *cookie, *estimated;
+ struct berval lcookie;
+ int lestimated;
+ ldap_linkdata *ld;
+ LDAPMessage *ldap_result;
+ LDAPControl **lserverctrls, *lctrl;
+ BerElement *ber;
+ ber_tag_t tag;
+ int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|zz", &link, &result, &cookie, &estimated) != SUCCESS) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
+ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
+
+ rc = ldap_parse_result(ld->link,
+ ldap_result,
+ &lerrcode,
+ NULL, /* matcheddn */
+ NULL, /* errmsg */
+ NULL, /* referrals */
+ &lserverctrls,
+ 0);
+
+ if (rc != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc);
+ RETURN_FALSE;
+ }
+
+ if (lerrcode != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode);
+ RETURN_FALSE;
+ }
+
+ if (lserverctrls == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result");
+ RETURN_FALSE;
+ }
+
+ lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls);
+ if (lctrl == NULL) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result");
+ RETURN_FALSE;
+ }
+
+ ber = ber_init(&lctrl->ldctl_value);
+ if (ber == NULL) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response");
+ RETURN_FALSE;
+ }
+
+ tag = ber_scanf(ber, "{io}", &lestimated, &lcookie);
+ (void)ber_free(ber, 1);
+
+ if (tag == LBER_ERROR) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response");
+ RETURN_FALSE;
+ }
+
+ if (lestimated < 0) {
+ ldap_controls_free(lserverctrls);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value");
+ RETURN_FALSE;
+ }
+
+ ldap_controls_free(lserverctrls);
+ if (myargcount == 4) {
+ zval_dtor(estimated);
+ ZVAL_LONG(estimated, lestimated);
+ }
+
+ zval_dtor(cookie);
+ if (lcookie.bv_len == 0) {
+ ZVAL_EMPTY_STRING(cookie);
+ } else {
+ ZVAL_STRINGL(cookie, lcookie.bv_val, lcookie.bv_len, 1);
+ }
+ ldap_memfree(lcookie.bv_val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0)
ZEND_ARG_INFO(0, hostname)
@@ -2364,6 +2550,22 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3)
ZEND_ARG_INFO(0, sortfilter)
ZEND_END_ARG_INFO()
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_control_paged_result, 0, 0, 2)
+ ZEND_ARG_INFO(0, link)
+ ZEND_ARG_INFO(0, pagesize)
+ ZEND_ARG_INFO(0, iscritical)
+ ZEND_ARG_INFO(0, cookie)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_control_paged_result_response, 0, 0, 2)
+ ZEND_ARG_INFO(0, link)
+ ZEND_ARG_INFO(0, result)
+ ZEND_ARG_INFO(1, cookie)
+ ZEND_ARG_INFO(1, estimated)
+ZEND_END_ARG_INFO();
+#endif
+
#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5)
ZEND_ARG_INFO(0, link_identifier)
@@ -2506,6 +2708,10 @@ const zend_function_entry ldap_functions[] = {
PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61)
#endif
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ PHP_FE(ldap_control_paged_result, arginfo_ldap_control_paged_result)
+ PHP_FE(ldap_control_paged_result_response, arginfo_ldap_control_paged_result_response)
+#endif
PHP_FE_END
};
/* }}} */
diff --git a/ext/ldap/tests/ldap_control_paged_results_variation1.phpt b/ext/ldap/tests/ldap_control_paged_results_variation1.phpt
new file mode 100644
index 0000000000..0e894464f4
--- /dev/null
+++ b/ext/ldap/tests/ldap_control_paged_results_variation1.phpt
@@ -0,0 +1,56 @@
+--TEST--
+ldap_ldap_control_paged_result() test (fetching the first page)
+--CREDITS--
+Jean-Sebastien Hedde <jeanseb@au-fil-du.net>
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifbindfailure.inc');
+?>
+--FILE--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$dn = "dc=my-domain,dc=com";
+$filter = "(cn=*)";
+var_dump(
+ ldap_control_paged_result($link, 1),
+ $result = ldap_search($link, $dn, $filter, array('cn')),
+ ldap_get_entries($link, $result)
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+remove_dummy_data($link);
+?>
+--EXPECTF--
+bool(true)
+resource(6) of type (ldap result)
+array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ array(4) {
+ ["cn"]=>
+ array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ string(5) "userA"
+ }
+ [0]=>
+ string(2) "cn"
+ ["count"]=>
+ int(1)
+ ["dn"]=>
+ string(28) "cn=userA,dc=my-domain,dc=com"
+ }
+}
+===DONE===
diff --git a/ext/ldap/tests/ldap_control_paged_results_variation2.phpt b/ext/ldap/tests/ldap_control_paged_results_variation2.phpt
new file mode 100644
index 0000000000..fee43fc4d6
--- /dev/null
+++ b/ext/ldap/tests/ldap_control_paged_results_variation2.phpt
@@ -0,0 +1,72 @@
+--TEST--
+ldap_ldap_control_paged_result() test (fetching the first page with a pagesize=2)
+--CREDITS--
+Jean-Sebastien Hedde <jeanseb@au-fil-du.net>
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifbindfailure.inc');
+?>
+--FILE--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$dn = "dc=my-domain,dc=com";
+$filter = "(cn=*)";
+var_dump(
+ ldap_control_paged_result($link, 2),
+ $result = ldap_search($link, $dn, $filter, array('cn')),
+ ldap_get_entries($link, $result)
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+remove_dummy_data($link);
+?>
+--EXPECTF--
+bool(true)
+resource(6) of type (ldap result)
+array(3) {
+ ["count"]=>
+ int(2)
+ [0]=>
+ array(4) {
+ ["cn"]=>
+ array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ string(5) "userA"
+ }
+ [0]=>
+ string(2) "cn"
+ ["count"]=>
+ int(1)
+ ["dn"]=>
+ string(28) "cn=userA,dc=my-domain,dc=com"
+ }
+ [1]=>
+ array(4) {
+ ["cn"]=>
+ array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ string(5) "userB"
+ }
+ [0]=>
+ string(2) "cn"
+ ["count"]=>
+ int(1)
+ ["dn"]=>
+ string(28) "cn=userB,dc=my-domain,dc=com"
+ }
+}
+===DONE===
diff --git a/ext/ldap/tests/ldap_control_paged_results_variation3.phpt b/ext/ldap/tests/ldap_control_paged_results_variation3.phpt
new file mode 100644
index 0000000000..43a68aea79
--- /dev/null
+++ b/ext/ldap/tests/ldap_control_paged_results_variation3.phpt
@@ -0,0 +1,100 @@
+--TEST--
+ldap_ldap_control_paged_result() test (fetching the first page then the next final page)
+--CREDITS--
+Jean-Sebastien Hedde <jeanseb@au-fil-du.net>
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifbindfailure.inc');
+?>
+--FILE--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$dn = "dc=my-domain,dc=com";
+$filter = "(cn=*)";
+$cookie = '';
+var_dump(
+ ldap_control_paged_result($link, 2, true, $cookie),
+ $result = ldap_search($link, $dn, $filter, array('cn')),
+ ldap_get_entries($link, $result),
+ ldap_control_paged_result_response($link, $result, $cookie),
+ ldap_control_paged_result($link, 20, true, $cookie),
+ $result = ldap_search($link, $dn, $filter, array('cn')),
+ ldap_get_entries($link, $result)
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+remove_dummy_data($link);
+?>
+--EXPECTF--
+bool(true)
+resource(%d) of type (ldap result)
+array(3) {
+ ["count"]=>
+ int(2)
+ [0]=>
+ array(4) {
+ ["cn"]=>
+ array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ string(5) "userA"
+ }
+ [0]=>
+ string(2) "cn"
+ ["count"]=>
+ int(1)
+ ["dn"]=>
+ string(28) "cn=userA,dc=my-domain,dc=com"
+ }
+ [1]=>
+ array(4) {
+ ["cn"]=>
+ array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ string(5) "userB"
+ }
+ [0]=>
+ string(2) "cn"
+ ["count"]=>
+ int(1)
+ ["dn"]=>
+ string(28) "cn=userB,dc=my-domain,dc=com"
+ }
+}
+bool(true)
+bool(true)
+resource(%d) of type (ldap result)
+array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ array(4) {
+ ["cn"]=>
+ array(2) {
+ ["count"]=>
+ int(1)
+ [0]=>
+ string(5) "userC"
+ }
+ [0]=>
+ string(2) "cn"
+ ["count"]=>
+ int(1)
+ ["dn"]=>
+ string(37) "cn=userC,cn=userB,dc=my-domain,dc=com"
+ }
+}
+===DONE===
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 788736e756..c97ee6724d 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -26,6 +26,7 @@
#endif
#include "php.h"
+#include "SAPI.h"
#define PHP_XML_INTERNAL
#include "zend_variables.h"
@@ -53,6 +54,8 @@
/* a true global for initialization */
static int _php_libxml_initialized = 0;
+static int _php_libxml_per_request_initialization = 1;
+static xmlExternalEntityLoader _php_libxml_default_entity_loader;
typedef struct _php_libxml_func_handler {
php_libxml_export_node export_func;
@@ -68,6 +71,7 @@ static PHP_FUNCTION(libxml_use_internal_errors);
static PHP_FUNCTION(libxml_get_last_error);
static PHP_FUNCTION(libxml_clear_errors);
static PHP_FUNCTION(libxml_get_errors);
+static PHP_FUNCTION(libxml_set_external_entity_loader);
static PHP_FUNCTION(libxml_disable_entity_loader);
static zend_class_entry *libxmlerror_class_entry;
@@ -109,6 +113,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_disable_entity_loader, 0, 0, 0)
ZEND_ARG_INFO(0, disable)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_libxml_set_external_entity_loader, 0, 0, 1)
+ ZEND_ARG_INFO(0, resolver_function)
+ZEND_END_ARG_INFO()
/* }}} */
/* {{{ extension definition structures */
@@ -119,6 +126,7 @@ static const zend_function_entry libxml_functions[] = {
PHP_FE(libxml_clear_errors, arginfo_libxml_clear_errors)
PHP_FE(libxml_get_errors, arginfo_libxml_get_errors)
PHP_FE(libxml_disable_entity_loader, arginfo_libxml_disable_entity_loader)
+ PHP_FE(libxml_set_external_entity_loader, arginfo_libxml_set_external_entity_loader)
PHP_FE_END
};
@@ -261,6 +269,18 @@ static PHP_GINIT_FUNCTION(libxml)
libxml_globals->stream_context = NULL;
libxml_globals->error_buffer.c = NULL;
libxml_globals->error_list = NULL;
+ libxml_globals->entity_loader.fci.size = 0;
+}
+
+static void _php_libxml_destroy_fci(zend_fcall_info *fci)
+{
+ if (fci->size > 0) {
+ zval_ptr_dtor(&fci->function_name);
+ if (fci->object_ptr != NULL) {
+ zval_ptr_dtor(&fci->object_ptr);
+ }
+ fci->size = 0;
+ }
}
/* Channel libxml file io layer through the PHP streams subsystem.
@@ -278,8 +298,9 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char
TSRMLS_FETCH();
- uri = xmlParseURI((xmlChar *)filename);
- if (uri && (uri->scheme == NULL || (xmlStrncmp(uri->scheme, "file", 4) == 0))) {
+ uri = xmlParseURI(filename);
+ if (uri && (uri->scheme == NULL ||
+ (xmlStrncmp(BAD_CAST uri->scheme, BAD_CAST "file", 4) == 0))) {
resolved_path = xmlURIUnescapeString(filename, 0, NULL);
isescaped = 1;
} else {
@@ -300,7 +321,7 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char
that the streams layer puts out at times, but for libxml we
may try to open files that don't exist, but it is not a failure
in xml processing (eg. DTD files) */
- wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC);
+ wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, 0 TSRMLS_CC);
if (wrapper && read_only && wrapper->wops->url_stat) {
if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssbuf, NULL TSRMLS_CC) == -1) {
if (isescaped) {
@@ -311,8 +332,8 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char
}
context = php_stream_context_from_zval(LIBXML(stream_context), 0);
-
- ret_val = php_stream_open_wrapper_ex(path_to_open, (char *)mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, context);
+
+ ret_val = php_stream_open_wrapper_ex(path_to_open, (char *)mode, REPORT_ERRORS, NULL, context);
if (isescaped) {
xmlFree(resolved_path);
}
@@ -528,6 +549,152 @@ static void php_libxml_internal_error_handler(int error_type, void *ctx, const c
}
}
+static xmlParserInputPtr _php_libxml_external_entity_loader(const char *URL,
+ const char *ID, xmlParserCtxtPtr context)
+{
+ xmlParserInputPtr ret = NULL;
+ const char *resource = NULL;
+ zval *public = NULL,
+ *system = NULL,
+ *ctxzv = NULL,
+ **params[] = {&public, &system, &ctxzv},
+ *retval_ptr = NULL;
+ int retval;
+ zend_fcall_info *fci;
+ TSRMLS_FETCH();
+
+ fci = &LIBXML(entity_loader).fci;
+
+ if (fci->size == 0) {
+ /* no custom user-land callback set up; delegate to original loader */
+ return _php_libxml_default_entity_loader(URL, ID, context);
+ }
+
+ ALLOC_INIT_ZVAL(public);
+ if (ID != NULL) {
+ ZVAL_STRING(public, ID, 1);
+ }
+ ALLOC_INIT_ZVAL(system);
+ if (URL != NULL) {
+ ZVAL_STRING(system, URL, 1);
+ }
+ MAKE_STD_ZVAL(ctxzv);
+ array_init_size(ctxzv, 4);
+
+#define ADD_NULL_OR_STRING_KEY(memb) \
+ if (context->memb == NULL) { \
+ add_assoc_null_ex(ctxzv, #memb, sizeof(#memb)); \
+ } else { \
+ add_assoc_string_ex(ctxzv, #memb, sizeof(#memb), \
+ (char *)context->memb, 1); \
+ }
+
+ ADD_NULL_OR_STRING_KEY(directory)
+ ADD_NULL_OR_STRING_KEY(intSubName)
+ ADD_NULL_OR_STRING_KEY(extSubURI)
+ ADD_NULL_OR_STRING_KEY(extSubSystem)
+
+#undef ADD_NULL_OR_STRING_KEY
+
+ fci->retval_ptr_ptr = &retval_ptr;
+ fci->params = params;
+ fci->param_count = sizeof(params)/sizeof(*params);
+ fci->no_separation = 1;
+
+ retval = zend_call_function(fci, &LIBXML(entity_loader).fcc TSRMLS_CC);
+ if (retval != SUCCESS || fci->retval_ptr_ptr == NULL) {
+ php_libxml_ctx_error(context,
+ "Call to user entity loader callback '%s' has failed",
+ fci->function_name);
+ } else {
+ retval_ptr = *fci->retval_ptr_ptr;
+ if (retval_ptr == NULL) {
+ php_libxml_ctx_error(context,
+ "Call to user entity loader callback '%s' has failed; "
+ "probably it has thrown an exception",
+ fci->function_name);
+ } else if (Z_TYPE_P(retval_ptr) == IS_STRING) {
+is_string:
+ resource = Z_STRVAL_P(retval_ptr);
+ } else if (Z_TYPE_P(retval_ptr) == IS_RESOURCE) {
+ php_stream *stream;
+ php_stream_from_zval_no_verify(stream, &retval_ptr);
+ if (stream == NULL) {
+ php_libxml_ctx_error(context,
+ "The user entity loader callback '%s' has returned a "
+ "resource, but it is not a stream",
+ fci->function_name);
+ } else {
+ /* TODO: allow storing the encoding in the stream context? */
+ xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+ xmlParserInputBufferPtr pib = xmlAllocParserInputBuffer(enc);
+ if (pib == NULL) {
+ php_libxml_ctx_error(context, "Could not allocate parser "
+ "input buffer");
+ } else {
+ /* make stream not being closed when the zval is freed */
+ zend_list_addref(stream->rsrc_id);
+ pib->context = stream;
+ pib->readcallback = php_libxml_streams_IO_read;
+ pib->closecallback = php_libxml_streams_IO_close;
+
+ ret = xmlNewIOInputStream(context, pib, enc);
+ if (ret == NULL) {
+ xmlFreeParserInputBuffer(pib);
+ }
+ }
+ }
+ } else if (Z_TYPE_P(retval_ptr) != IS_NULL) {
+ /* retval not string nor resource nor null; convert to string */
+ SEPARATE_ZVAL(&retval_ptr);
+ convert_to_string(retval_ptr);
+ goto is_string;
+ } /* else is null; don't try anything */
+ }
+
+ if (ret == NULL) {
+ if (resource == NULL) {
+ if (ID == NULL) {
+ ID = "NULL";
+ }
+ php_libxml_ctx_error(context,
+ "Failed to load external entity \"%s\"\n", ID);
+ } else {
+ /* we got the resource in the form of a string; open it */
+ ret = xmlNewInputFromFile(context, resource);
+ }
+ }
+
+ zval_ptr_dtor(&public);
+ zval_ptr_dtor(&system);
+ zval_ptr_dtor(&ctxzv);
+ if (retval_ptr != NULL) {
+ zval_ptr_dtor(&retval_ptr);
+ }
+ return ret;
+}
+
+static xmlParserInputPtr _php_libxml_pre_ext_ent_loader(const char *URL,
+ const char *ID, xmlParserCtxtPtr context)
+{
+ TSRMLS_FETCH();
+
+ /* Check whether we're running in a PHP context, since the entity loader
+ * we've defined is an application level (true global) setting.
+ * If we are, we also want to check whether we've finished activating
+ * the modules (RINIT phase). Using our external entity loader during a
+ * RINIT should not be problem per se (though during MINIT it is, because
+ * we don't even have a resource list by then), but then whether one
+ * extension would be using the custom external entity loader or not
+ * could depend on extension loading order
+ * (if _php_libxml_per_request_initialization */
+ if (xmlGenericError == php_libxml_error_handler && PG(modules_activated)) {
+ return _php_libxml_external_entity_loader(URL, ID, context);
+ } else {
+ return _php_libxml_default_entity_loader(URL, ID, context);
+ }
+}
+
PHP_LIBXML_API void php_libxml_ctx_error(void *ctx, const char *msg, ...)
{
va_list args;
@@ -565,6 +732,9 @@ PHP_LIBXML_API void php_libxml_initialize(void)
if (!_php_libxml_initialized) {
/* we should be the only one's to ever init!! */
xmlInitParser();
+
+ _php_libxml_default_entity_loader = xmlGetExternalEntityLoader();
+ xmlSetExternalEntityLoader(_php_libxml_pre_ext_ent_loader);
zend_hash_init(&php_libxml_exports, 0, NULL, NULL, 1);
@@ -580,6 +750,8 @@ PHP_LIBXML_API void php_libxml_shutdown(void)
#endif
xmlCleanupParser();
zend_hash_destroy(&php_libxml_exports);
+
+ xmlSetExternalEntityLoader(_php_libxml_default_entity_loader);
_php_libxml_initialized = 0;
}
}
@@ -616,6 +788,7 @@ static PHP_MINIT_FUNCTION(libxml)
REGISTER_LONG_CONSTANT("LIBXML_NSCLEAN", XML_PARSE_NSCLEAN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LIBXML_NOCDATA", XML_PARSE_NOCDATA, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LIBXML_NONET", XML_PARSE_NONET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("LIBXML_PEDANTIC", XML_PARSE_PEDANTIC, CONST_CS | CONST_PERSISTENT);
#if LIBXML_VERSION >= 20621
REGISTER_LONG_CONSTANT("LIBXML_COMPACT", XML_PARSE_COMPACT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LIBXML_NOXMLDECL", XML_SAVE_NO_DECL, CONST_CS | CONST_PERSISTENT);
@@ -625,6 +798,15 @@ static PHP_MINIT_FUNCTION(libxml)
#endif
REGISTER_LONG_CONSTANT("LIBXML_NOEMPTYTAG", LIBXML_SAVE_NOEMPTYTAG, CONST_CS | CONST_PERSISTENT);
+ /* Additional constants for use with loading html */
+#if LIBXML_VERSION >= 20707
+ REGISTER_LONG_CONSTANT("LIBXML_HTML_NOIMPLIED", HTML_PARSE_NOIMPLIED, CONST_CS | CONST_PERSISTENT);
+#endif
+
+#if LIBXML_VERSION >= 20708
+ REGISTER_LONG_CONSTANT("LIBXML_HTML_NODEFDTD", HTML_PARSE_NODEFDTD, CONST_CS | CONST_PERSISTENT);
+#endif
+
/* Error levels */
REGISTER_LONG_CONSTANT("LIBXML_ERR_NONE", XML_ERR_NONE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("LIBXML_ERR_WARNING", XML_ERR_WARNING, CONST_CS | CONST_PERSISTENT);
@@ -634,22 +816,55 @@ static PHP_MINIT_FUNCTION(libxml)
INIT_CLASS_ENTRY(ce, "LibXMLError", NULL);
libxmlerror_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
+ if (sapi_module.name) {
+ static const char * const supported_sapis[] = {
+ "cgi-fcgi",
+ "fpm-fcgi",
+ "litespeed",
+ NULL
+ };
+ const char * const *sapi_name;
+
+ for (sapi_name = supported_sapis; *sapi_name; sapi_name++) {
+ if (strcmp(sapi_module.name, *sapi_name) == 0) {
+ _php_libxml_per_request_initialization = 0;
+ break;
+ }
+ }
+ }
+
+ if (!_php_libxml_per_request_initialization) {
+ /* report errors via handler rather than stderr */
+ xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
+ xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
+ xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename);
+ }
+
return SUCCESS;
}
static PHP_RINIT_FUNCTION(libxml)
{
- /* report errors via handler rather than stderr */
- xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
- xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
- xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename);
+ if (_php_libxml_per_request_initialization) {
+ /* report errors via handler rather than stderr */
+ xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
+ xmlParserInputBufferCreateFilenameDefault(php_libxml_input_buffer_create_filename);
+ xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename);
+ }
return SUCCESS;
}
static PHP_MSHUTDOWN_FUNCTION(libxml)
{
+ if (!_php_libxml_per_request_initialization) {
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlSetStructuredErrorFunc(NULL, NULL);
+
+ xmlParserInputBufferCreateFilenameDefault(NULL);
+ xmlOutputBufferCreateFilenameDefault(NULL);
+ }
php_libxml_shutdown();
return SUCCESS;
@@ -659,11 +874,13 @@ static int php_libxml_post_deactivate()
{
TSRMLS_FETCH();
/* reset libxml generic error handling */
- xmlSetGenericErrorFunc(NULL, NULL);
- xmlSetStructuredErrorFunc(NULL, NULL);
+ if (_php_libxml_per_request_initialization) {
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlSetStructuredErrorFunc(NULL, NULL);
- xmlParserInputBufferCreateFilenameDefault(NULL);
- xmlOutputBufferCreateFilenameDefault(NULL);
+ xmlParserInputBufferCreateFilenameDefault(NULL);
+ xmlOutputBufferCreateFilenameDefault(NULL);
+ }
if (LIBXML(stream_context)) {
/* the steam_context resource will be released by resource list destructor */
@@ -677,6 +894,8 @@ static int php_libxml_post_deactivate()
LIBXML(error_list) = NULL;
}
xmlResetLastError();
+
+ _php_libxml_destroy_fci(&LIBXML(entity_loader).fci);
return SUCCESS;
}
@@ -859,6 +1078,32 @@ static PHP_FUNCTION(libxml_disable_entity_loader)
}
/* }}} */
+/* {{{ proto void libxml_set_external_entity_loader(callback resolver_function)
+ Changes the default external entity loader */
+static PHP_FUNCTION(libxml_set_external_entity_loader)
+{
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcc;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f!", &fci, &fcc)
+ == FAILURE) {
+ return;
+ }
+
+ _php_libxml_destroy_fci(&LIBXML(entity_loader).fci);
+
+ if (fci.size > 0) { /* argument not null */
+ LIBXML(entity_loader).fci = fci;
+ Z_ADDREF_P(fci.function_name);
+ if (fci.object_ptr != NULL) {
+ Z_ADDREF_P(fci.object_ptr);
+ }
+ LIBXML(entity_loader).fcc = fcc;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
/* {{{ Common functions shared by extensions */
int php_libxml_xmlCheckUTF8(const unsigned char *s)
{
diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h
index 2cff7326f5..a11d059f71 100644
--- a/ext/libxml/php_libxml.h
+++ b/ext/libxml/php_libxml.h
@@ -43,6 +43,10 @@ ZEND_BEGIN_MODULE_GLOBALS(libxml)
zval *stream_context;
smart_str error_buffer;
zend_llist *error_list;
+ struct _php_libxml_entity_resolver {
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcc;
+ } entity_loader;
ZEND_END_MODULE_GLOBALS(libxml)
typedef struct _libxml_doc_props {
diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_basic.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_basic.phpt
new file mode 100644
index 0000000000..51ab777052
--- /dev/null
+++ b/ext/libxml/tests/libxml_set_external_entity_loader_basic.phpt
@@ -0,0 +1,48 @@
+--TEST--
+libxml_set_external_entity_loader() basic test
+--SKIPIF--
+<?php if (!extension_loaded('dom')) die('skip'); ?>
+--FILE--
+<?php
+$xml = <<<XML
+<!DOCTYPE foo PUBLIC "-//FOO/BAR" "http://example.com/foobar">
+<foo>bar</foo>
+XML;
+
+$dtd = <<<DTD
+<!ELEMENT foo (#PCDATA)>
+DTD;
+
+libxml_set_external_entity_loader(
+ function ($public, $system, $context) use($dtd){
+ var_dump($public);
+ var_dump($system);
+ var_dump($context);
+ $f = fopen("php://temp", "r+");
+ fwrite($f, $dtd);
+ rewind($f);
+ return $f;
+ }
+);
+
+$dd = new DOMDocument;
+$r = $dd->loadXML($xml);
+var_dump($dd->validate());
+
+echo "Done.\n";
+
+--EXPECT--
+string(10) "-//FOO/BAR"
+string(25) "http://example.com/foobar"
+array(4) {
+ ["directory"]=>
+ NULL
+ ["intSubName"]=>
+ NULL
+ ["extSubURI"]=>
+ NULL
+ ["extSubSystem"]=>
+ NULL
+}
+bool(true)
+Done.
diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_error1.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_error1.phpt
new file mode 100644
index 0000000000..5ed079d8dd
--- /dev/null
+++ b/ext/libxml/tests/libxml_set_external_entity_loader_error1.phpt
@@ -0,0 +1,39 @@
+--TEST--
+libxml_set_external_entity_loader() error: bad arguments
+--SKIPIF--
+<?php if (!extension_loaded('dom')) die('skip'); ?>
+--FILE--
+<?php
+$xml = <<<XML
+<!DOCTYPE foo PUBLIC "-//FOO/BAR" "http://example.com/foobar">
+<foo>bar</foo>
+XML;
+
+$dd = new DOMDocument;
+$r = $dd->loadXML($xml);
+
+var_dump(libxml_set_external_entity_loader([]));
+var_dump(libxml_set_external_entity_loader());
+var_dump(libxml_set_external_entity_loader(function() {}, 2));
+
+var_dump(libxml_set_external_entity_loader(function($a, $b, $c, $d) {}));
+var_dump($dd->validate());
+
+echo "Done.\n";
+
+--EXPECTF--
+Warning: libxml_set_external_entity_loader() expects parameter 1 to be a valid callback, array must have exactly two members in %s on line %d
+NULL
+
+Warning: libxml_set_external_entity_loader() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: libxml_set_external_entity_loader() expects exactly 1 parameter, 2 given in %s on line %d
+NULL
+bool(true)
+
+Warning: Missing argument 4 for {closure}() in %s on line %d
+
+Warning: DOMDocument::validate(): Could not load the external subset "http://example.com/foobar" in %s on line %d
+bool(false)
+Done.
diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt
new file mode 100644
index 0000000000..c9c45940b9
--- /dev/null
+++ b/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt
@@ -0,0 +1,72 @@
+--TEST--
+libxml_set_external_entity_loader() variation: resolve externals and entities
+--SKIPIF--
+<?php if (!extension_loaded('dom')) die('skip'); ?>
+--FILE--
+<?php
+chdir(__DIR__);
+$xml = <<<XML
+<!DOCTYPE foo PUBLIC "-//FOO/BAR" "http://example.com/foobar">
+<foo>bar&fooz;</foo>
+XML;
+
+$dtd = <<<DTD
+<!ELEMENT foo (#PCDATA)>
+<!ENTITY % fooentity PUBLIC
+ "-//FOO/ENTITY"
+ "fooentity.ent">
+%fooentity;
+DTD;
+
+$entity = <<<ENT
+<!ENTITY fooz "baz">
+ENT;
+
+libxml_set_external_entity_loader(
+ function ($public, $system, $context) use($dtd,$entity){
+ static $first = true;
+ var_dump($public);
+ var_dump($system);
+ var_dump($context);
+ $f = fopen("php://temp", "r+");
+ fwrite($f, $first ? $dtd : $entity);
+ $first = false;
+ rewind($f);
+ return $f;
+ }
+);
+
+$dd = new DOMDocument;
+$dd->resolveExternals = true;
+$r = $dd->loadXML($xml);
+var_dump($dd->validate());
+
+echo "Done.\n";
+
+--EXPECTF--
+string(10) "-//FOO/BAR"
+string(25) "http://example.com/foobar"
+array(4) {
+ ["directory"]=>
+ string(%d) "%s"
+ ["intSubName"]=>
+ string(3) "foo"
+ ["extSubURI"]=>
+ string(25) "http://example.com/foobar"
+ ["extSubSystem"]=>
+ string(10) "-//FOO/BAR"
+}
+string(13) "-//FOO/ENTITY"
+string(32) "http://example.com/fooentity.ent"
+array(4) {
+ ["directory"]=>
+ string(%d) "%s"
+ ["intSubName"]=>
+ string(3) "foo"
+ ["extSubURI"]=>
+ string(25) "http://example.com/foobar"
+ ["extSubSystem"]=>
+ string(10) "-//FOO/BAR"
+}
+bool(true)
+Done.
diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
new file mode 100644
index 0000000000..b6251bea6d
--- /dev/null
+++ b/ext/libxml/tests/libxml_set_external_entity_loader_variation2.phpt
@@ -0,0 +1,45 @@
+--TEST--
+libxml_set_external_entity_loader() variation: restore original handler; returning NULL
+--SKIPIF--
+<?php if (!extension_loaded('dom')) die('skip'); ?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . "/foobar.dtd");
+--FILE--
+<?php
+chdir(__DIR__);
+$xml = <<<XML
+<!DOCTYPE foo PUBLIC "-//FOO/BAR" "foobar.dtd">
+<foo>bar</foo>
+XML;
+
+$dtd = <<<DTD
+<!ELEMENT foo (#PCDATA)>
+DTD;
+
+
+libxml_set_external_entity_loader(
+ function ($public, $system, $context) {
+ var_dump($public,$system);
+ return null;
+ }
+);
+
+$dd = new DOMDocument;
+$r = $dd->loadXML($xml);
+var_dump($dd->validate());
+
+libxml_set_external_entity_loader(NULL);
+file_put_contents(__DIR__ . "/foobar.dtd", $dtd);
+var_dump($dd->validate());
+
+echo "Done.\n";
+
+--EXPECTF--
+string(10) "-//FOO/BAR"
+string(%d) "%sfoobar.dtd"
+
+Warning: DOMDocument::validate(): Could not load the external subset "foobar.dtd" in %s on line %d
+bool(false)
+bool(true)
+Done.
diff --git a/ext/mbstring/config.m4 b/ext/mbstring/config.m4
index a28af46629..5d70d45b80 100644
--- a/ext/mbstring/config.m4
+++ b/ext/mbstring/config.m4
@@ -235,14 +235,18 @@ AC_DEFUN([PHP_MBSTRING_SETUP_LIBMBFL], [
libmbfl/filters/mbfilter_cp866.c
libmbfl/filters/mbfilter_cp932.c
libmbfl/filters/mbfilter_cp936.c
+ libmbfl/filters/mbfilter_gb18030.c
libmbfl/filters/mbfilter_euc_cn.c
libmbfl/filters/mbfilter_euc_jp.c
+ libmbfl/filters/mbfilter_euc_jp_2004.c
libmbfl/filters/mbfilter_euc_jp_win.c
libmbfl/filters/mbfilter_euc_kr.c
libmbfl/filters/mbfilter_euc_tw.c
libmbfl/filters/mbfilter_htmlent.c
libmbfl/filters/mbfilter_hz.c
libmbfl/filters/mbfilter_iso2022_jp_ms.c
+ libmbfl/filters/mbfilter_iso2022jp_2004.c
+ libmbfl/filters/mbfilter_iso2022jp_mobile.c
libmbfl/filters/mbfilter_iso2022_kr.c
libmbfl/filters/mbfilter_iso8859_1.c
libmbfl/filters/mbfilter_iso8859_10.c
@@ -264,6 +268,9 @@ AC_DEFUN([PHP_MBSTRING_SETUP_LIBMBFL], [
libmbfl/filters/mbfilter_qprint.c
libmbfl/filters/mbfilter_sjis.c
libmbfl/filters/mbfilter_sjis_open.c
+ libmbfl/filters/mbfilter_sjis_mobile.c
+ libmbfl/filters/mbfilter_sjis_mac.c
+ libmbfl/filters/mbfilter_sjis_2004.c
libmbfl/filters/mbfilter_tl_jisx0201_jisx0208.c
libmbfl/filters/mbfilter_ucs2.c
libmbfl/filters/mbfilter_ucs4.c
@@ -273,6 +280,7 @@ AC_DEFUN([PHP_MBSTRING_SETUP_LIBMBFL], [
libmbfl/filters/mbfilter_utf7.c
libmbfl/filters/mbfilter_utf7imap.c
libmbfl/filters/mbfilter_utf8.c
+ libmbfl/filters/mbfilter_utf8_mobile.c
libmbfl/filters/mbfilter_uuencode.c
libmbfl/filters/mbfilter_koi8u.c
libmbfl/mbfl/mbfilter.c
diff --git a/ext/mbstring/config.w32 b/ext/mbstring/config.w32
index ae0972f62a..7bc9518cb8 100644
--- a/ext/mbstring/config.w32
+++ b/ext/mbstring/config.w32
@@ -29,13 +29,15 @@ if (PHP_MBSTRING != "no") {
mbfilter_iso8859_2.c mbfilter_iso8859_3.c mbfilter_iso8859_4.c \
mbfilter_iso8859_5.c mbfilter_iso8859_6.c mbfilter_iso8859_7.c \
mbfilter_iso8859_8.c mbfilter_iso8859_9.c mbfilter_jis.c \
- mbfilter_iso2022_jp_ms.c \
+ mbfilter_iso2022_jp_ms.c mbfilter_gb18030.c mbfilter_sjis_2004.c \
mbfilter_koi8r.c mbfilter_qprint.c mbfilter_sjis.c mbfilter_ucs2.c \
mbfilter_ucs4.c mbfilter_uhc.c mbfilter_utf16.c mbfilter_utf32.c \
- mbfilter_utf7.c mbfilter_utf7imap.c mbfilter_utf8.c \
- mbfilter_koi8u.c mbfilter_cp1254.c \
+ mbfilter_utf7.c mbfilter_utf7imap.c mbfilter_utf8.c mbfilter_utf8_mobile.c \
+ mbfilter_koi8u.c mbfilter_cp1254.c mbfilter_euc_jp_2004.c \
mbfilter_uuencode.c mbfilter_armscii8.c mbfilter_cp850.c \
- mbfilter_cp5022x.c mbfilter_sjis_open.c \
+ mbfilter_cp5022x.c mbfilter_sjis_open.c mbfilter_sjis_mobile.c \
+ mbfilter_sjis_mac.c \
+ mbfilter_iso2022jp_2004.c mbfilter_iso2022jp_mobile.c \
mbfilter_tl_jisx0201_jisx0208.c", "mbstring");
ADD_SOURCES("ext/mbstring/libmbfl/mbfl", "mbfilter.c mbfilter_8bit.c \
diff --git a/ext/mbstring/libmbfl/NEWS b/ext/mbstring/libmbfl/NEWS
new file mode 100644
index 0000000000..fc16367ed1
--- /dev/null
+++ b/ext/mbstring/libmbfl/NEWS
@@ -0,0 +1,30 @@
+
+version 1.3.2 August 20, 2011
+
+- added JISX-0213:2004 based encoding : Shift_JIS-2004, EUC-JP-2004, ISO-2022-JP-2004 (rui).
+- added gb18030 encoding (rui).
+- added CP950 with user user defined area based on Big5 (rui).
+- added mapping for user defined character area to CP936 (rui).
+- added UTF-8-Mobile to support the pictogram characters defined by mobile phone carrier in Japan (rui).
+
+version 1.3.1 August 5, 2011
+
+- added check for invalid/obsolete utf-8 encoding (rui).
+
+version 1.3.0 August 1, 2011
+
+- added encoding conversion between Shift_JIS and Unicode (6.0 or PUA)
+ for pictogram characters defined by mobile phone carrier in Japan (rui).
+
+ Detailed info:https://github.com/hirokawa/libmbfl/wiki/Introduction-to-libmbflhttps:--github.com-hirokawa-libmbfl-wiki-Introduction-to-libmbfl-_edit%23
+
+- fixed encoding conversion of cp5022x for user defined area (rui).
+- added MacJapanese (SJIS-mac) for legacy encoding support (rui).
+- backport from PHP 5.2 (rui).
+
+version 1.1.0 March 02, 2010
+
+- added cp5022x encoding (moriyoshi)
+- added ISO-2022-JP-MS (moriyoshi)
+- moved to github.com from sourceforge.jp (moriyoshi)
+
diff --git a/ext/mbstring/libmbfl/filters/Makefile.am b/ext/mbstring/libmbfl/filters/Makefile.am
index 99df73b8dc..33f9049ae9 100644
--- a/ext/mbstring/libmbfl/filters/Makefile.am
+++ b/ext/mbstring/libmbfl/filters/Makefile.am
@@ -1,6 +1,7 @@
-EXTRA_DIST=mk_sb_tbl.awk
+EXTRA_DIST=Makefile.bcc32 mk_sb_tbl.awk
noinst_LTLIBRARIES=libmbfl_filters.la
INCLUDES=-I../mbfl
+PERL=perl
libmbfl_filters_la_LDFLAGS=-version-info $(SHLIB_VERSION)
libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
mbfilter_hz.c \
@@ -32,7 +33,10 @@ libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
mbfilter_uuencode.c \
mbfilter_base64.c \
mbfilter_sjis.c \
+ mbfilter_sjis_2004.c \
mbfilter_sjis_open.c \
+ mbfilter_sjis_mobile.c \
+ mbfilter_sjis_mac.c \
mbfilter_7bit.c \
mbfilter_qprint.c \
mbfilter_ucs4.c \
@@ -40,15 +44,20 @@ libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
mbfilter_utf32.c \
mbfilter_utf16.c \
mbfilter_utf8.c \
+ mbfilter_utf8_mobile.c \
mbfilter_utf7.c \
mbfilter_utf7imap.c \
mbfilter_euc_jp_win.c \
+ mbfilter_euc_jp_2004.c \
mbfilter_cp932.c \
mbfilter_cp51932.c \
mbfilter_euc_cn.c \
mbfilter_euc_kr.c \
mbfilter_uhc.c \
mbfilter_iso2022_jp_ms.c \
+ mbfilter_iso2022jp_2004.c \
+ mbfilter_iso2022jp_mobile.c \
+ mbfilter_gb18030.c \
mbfilter_iso2022_kr.c \
mbfilter_cp866.c \
mbfilter_koi8r.c \
@@ -72,14 +81,18 @@ libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
mbfilter_cp866.h \
mbfilter_cp932.h \
mbfilter_cp936.h \
+ mbfilter_gb18030.h \
mbfilter_euc_cn.h \
mbfilter_euc_jp.h \
+ mbfilter_euc_jp_2004.h \
mbfilter_euc_jp_win.h \
mbfilter_euc_kr.h \
mbfilter_euc_tw.h \
mbfilter_htmlent.h \
mbfilter_hz.h \
mbfilter_iso2022_jp_ms.h \
+ mbfilter_iso2022jp_2004.h \
+ mbfilter_iso2022jp_mobile.h \
mbfilter_iso2022_kr.h \
mbfilter_iso8859_1.h \
mbfilter_iso8859_10.h \
@@ -102,6 +115,8 @@ libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
mbfilter_qprint.h \
mbfilter_sjis.h \
mbfilter_sjis_open.h \
+ mbfilter_sjis_mobile.h \
+ mbfilter_sjis_mac.h \
mbfilter_ucs2.h \
mbfilter_ucs4.h \
mbfilter_uhc.h \
@@ -110,6 +125,7 @@ libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
mbfilter_utf7.h \
mbfilter_utf7imap.h \
mbfilter_utf8.h \
+ mbfilter_utf8_mobile.h \
mbfilter_uuencode.h \
mbfilter_cp5022x.h \
mbfilter_cp51932.h \
@@ -143,7 +159,9 @@ libmbfl_filters_la_SOURCES=mbfilter_cp936.c \
unicode_table_armscii8.h \
unicode_table_cp850.h \
unicode_table_uhc.h \
- translit_kana_jisx0201_jisx0208.h
+ unicode_table_gb18030.h \
+ translit_kana_jisx0201_jisx0208.h \
+ emoji2uni.h
mbfilter_iso8859_2.c: unicode_table_iso8859_2.h
@@ -238,8 +256,14 @@ unicode_table_iso8859_16.h: mk_sb_tbl.awk
$(AWK) -v TABLE_NAME=iso8859_16_ucs_table \
-v IFNDEF_NAME=UNICODE_TABLEISO8859_16_H -f mk_sb_tbl.awk 8859-16.TXT > $@
+EmojiSources.txt :
+ $(FETCH_VIA_FTP) ftp://ftp.unicode.org/Public/UNIDATA/$@
+
+emoji2uni.h : mk_emoji_tbl.pl
+ $(PERL) mk_emoji_tbl.pl EmojiSources.txt
+
unidata: 8859-1.TXT 8859-2.TXT 8859-3.TXT 8859-4.TXT 8859-5.TXT 8859-6.TXT \
8859-7.TXT 8859-8.TXT 8859-9.TXT 8859-10.TXT 8859-11.TXT 8859-13.TXT \
-8859-14.TXT 8859-15.TXT 8859-16.TXT
+8859-14.TXT 8859-15.TXT 8859-16.TXT EmojiSources.txt
.PHONY: unidata
diff --git a/ext/mbstring/libmbfl/filters/emoji2uni.h b/ext/mbstring/libmbfl/filters/emoji2uni.h
new file mode 100644
index 0000000000..37f44c5964
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/emoji2uni.h
@@ -0,0 +1,1227 @@
+static const int mb_tbl_code2uni_docomo1_min = 0x28c2;
+static const int mb_tbl_code2uni_docomo1_max = 0x29db;
+
+static const unsigned short mb_tbl_code2uni_docomo1[] = { // 0x28c2 - 0x29db
+ 0x2600, 0x2601, 0x2614, 0x26c4,
+ 0x26a1, 0xf300, 0xf301, 0xf302,
+ 0x2648, 0x2649, 0x264a, 0x264b,
+ 0x264c, 0x264d, 0x264e, 0x264f,
+ 0x2650, 0x2651, 0x2652, 0x2653,
+ 0xf3bd, 0x26be, 0x26f3, 0xf3be,
+ 0x26bd, 0xf3bf, 0xf3c0, 0xf3c1,
+ 0xf4df, 0xf683, 0x24c2, 0xf684,
+ 0xf697, 0xf699, 0xf68c, 0xf6a2,
+ 0x2708, 0xf3e0, 0xf3e2, 0xf3e3,
+ 0xf3e5, 0xf3e6, 0xf3e7, 0xf3e8,
+ 0xf3ea, 0x26fd, 0xf17f, 0xf6a5,
+ 0xf6bb, 0xf374, 0x2615, 0xf378,
+ 0xf37a, 0xf354, 0xf460, 0x2702,
+ 0xf3a4, 0xf3a5, 0x2197, 0xf3a0,
+ 0xf3a7, 0xf3a8, 0xf3a9, 0xf3aa,
+ 0xf3ab, 0xf6ac, 0xf6ad, 0xf4f7,
+ 0xf45c, 0xf4d6, 0xf380, 0xf381,
+ 0xf382, 0x260e, 0xf4f1, 0xf4dd,
+ 0xf4fa, 0xf3ae, 0xf4bf, 0x2665,
+ 0x2660, 0x2666, 0x2663, 0xf440,
+ 0xf442, 0x270a, 0x270c, 0x270b,
+ 0x2198, 0x2196, 0xf463, 0xf45f,
+ 0xf453, 0x267f, 0xf311, 0xf314,
+ 0xf313, 0xf319, 0xf315, 0xf436,
+ 0xf431, 0x26f5, 0xf384, 0x2199,
+ 0xEE16, 0xEE17, 0xEE18, 0xEE19,
+ 0xEE1A, 0xEE1B, 0xf3ac, 0xf45d,
+ 0x2712, 0xEE1C, 0xEE1D, 0xf464,
+ 0xf4ba, 0xf303, 0xEE1E, 0xEE1F,
+ 0xEE20, 0xf51c, 0xf51b, 0xf51a,
+ 0x23f0, 0xEE21, 0xEE22, 0xEE23,
+ 0xEE24, 0xEE25, 0xEE26, 0xEE27,
+ 0xEE28, 0xEE29, 0xEE2A, 0xEE2B,
+ 0xEE2C, 0xEE2D, 0xEE2E, 0xEE2F,
+ 0xEE30, 0xEE31, 0xEE32, 0xEE33,
+ 0xf4f2, 0xf4e9, 0xf4e0, 0xEE10,
+ 0xEE11, 0x2709, 0xEE12, 0xEE13,
+ 0xf4b4, 0xf193, 0xf194, 0xf511,
+ 0x21a9, 0xf191, 0xf50d, 0xf195,
+ 0xf6a9, 0x27bf, 0x0023, 0xE82D,
+ 0x0031, 0x0032, 0x0033, 0x0034,
+ 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x0030, 0x2764, 0xf493,
+ 0xf494, 0xf495, 0xf603, 0xf620,
+ 0xf61e, 0xf616, 0xf635, 0x2934,
+ 0xf3b5, 0x2668, 0xf4a0, 0xf48b,
+ 0x2728, 0xf4a1, 0xf4a2, 0xf44a,
+ 0xf4a3, 0xf3b6, 0x2935, 0xf4a4,
+ 0x2757, 0x2049, 0x203c, 0xf4a5,
+ 0xf4a6, 0xf4a7, 0xf4a8, 0x3030,
+ 0x27b0, 0xf197, 0xEE14, 0xEE15,
+ 0xf455, 0xf45b, 0xf484, 0xf456,
+ 0xf3c2, 0xf514, 0xf6aa, 0xf4b0,
+ 0xf4bb, 0xf48c, 0xf527, 0x270f,
+ 0xf451, 0xf48d, 0x23f3, 0xf6b2,
+ 0xf375, 0x231a, 0xf614, 0xf60c,
+ 0xf605, 0xf613, 0xf621, 0xf612,
+ 0xf60d, 0xf44d, 0xf61c, 0xf609,
+ 0xf606, 0xf623, 0xf60f, 0xf62d,
+ 0xf622, 0xf196, 0xf4ce, 0x00a9,
+ 0x2122, 0xf3c3, 0x3299, 0x267b,
+ 0x00ae, 0x26a0, 0xf232, 0xf233,
+ 0xf234, 0xf235, 0x2194, 0x2195,
+ 0xf3eb, 0xf30a, 0xf5fb, 0xf340,
+ 0xf352, 0xf337, 0xf34c, 0xf34e,
+ 0xf331, 0xf341, 0xf338, 0xf359,
+ 0xf370, 0xf376, 0xf35c, 0xf35e,
+ 0xf40c, 0xf424, 0xf427, 0xf41f,
+ 0xf60b, 0xf601, 0xf434, 0xf437,
+ 0xf377, 0xf631, };
+static const int mb_tbl_code2uni_kddi1_min = 0x24b8;
+static const int mb_tbl_code2uni_kddi1_max = 0x25c6;
+
+static const unsigned short mb_tbl_code2uni_kddi1[] = { // 0x24b8 - 0x25c6
+ 0xf342, 0xf4bc, 0x26f2, 0x26fa,
+ 0xf004, 0xf19a, 0xf3c6, 0xf422,
+ 0xf1ea, 0xf1f7, 0xf6a7, 0xf6c0,
+ 0xf38c, 0xf306, 0xf423, 0xf4b9,
+ 0xf46e, 0xf3e3, 0xf3e5, 0xf3eb,
+ 0xf3e8, 0xf6a2, 0xf51e, 0xf4f6,
+ 0xf192, 0xf239, 0xf202, 0xf194,
+ 0xf235, 0xf233, 0xf22f, 0xf23a,
+ 0xf446, 0xf447, 0xf52e, 0xf4f3,
+ 0xf4f4, 0xf4dd, 0xf454, 0xf33a,
+ 0xf490, 0xf335, 0xf376, 0xf37b,
+ 0x3297, 0xf48a, 0xf388, 0xf389,
+ 0xEE42, 0xf452, 0xf462, 0xf485,
+ 0xf487, 0xf488, 0xf458, 0xf459,
+ 0x2665, 0xf496, 0xf499, 0xf49a,
+ 0xf49b, 0xf49c, 0x2728, 0xf3bf,
+ 0x2b55, 0xf375, 0xf35e, 0xf366,
+ 0xf35f, 0xf361, 0xf358, 0xf35a,
+ 0xf35d, 0xf35b, 0xf362, 0xf363,
+ 0xf34e, 0xf34a, 0xf345, 0xf346,
+ 0xf371, 0xf372, 0xf60f, 0xf614,
+ 0xf624, 0xf623, 0xf616, 0xf62a,
+ 0xf60c, 0xf628, 0xf637, 0xf633,
+ 0xf612, 0xf632, 0xf630, 0xf3bc,
+ 0xf60a, 0xf61a, 0xf618, 0xf443,
+ 0xf444, 0xf64f, 0xf44f, 0xf44c,
+ 0xf44e, 0xf44b, 0xf645, 0xf646,
+ 0xf647, 0xf491, 0xf46f, 0xf3ba,
+ 0xf3b1, 0xf3ca, 0xf692, 0xf691,
+ 0xf693, 0xf3a2, 0xf38d, 0xf38e,
+ 0xf393, 0xf392, 0xf38f, 0xf302,
+ 0xf470, 0xf367, 0xf387, 0xf41a,
+ 0xf390, 0xf383, 0xf391, 0xf385,
+ 0xf303, 0xf308, 0xf3e9, 0xf305,
+ 0xf3a9, 0xf3ec, 0xf3ef, 0xf3f0,
+ 0xf3ed, 0xf1eb, 0xf1e9, 0xf1ee,
+ 0xf1ec, 0xf1e8, 0xf1f0, 0xf471,
+ 0xf472, 0xf473, 0xf474, 0xf475,
+ 0xf476, 0xf477, 0xf478, 0xf42c,
+ 0xf483, 0xf420, 0xf41b, 0xf418,
+ 0xf428, 0xf42e, 0xf40d, 0xf414,
+ 0xf417, 0xf42b, 0xf170, 0xf171,
+ 0xf17e, 0xf18e, 0xf463, 0xf45f,
+ 0xf6a9, 0x2934, 0x2935, 0x2049,
+ 0x203c, 0x27b0, 0xf348, 0xf34d,
+ 0xf347, 0xf34c, 0xf33d, 0xf344,
+ 0xf330, 0xf351, 0xf360, 0xf355,
+ 0xf357, 0xf38b, 0xf379, 0xf432,
+ 0xf3b9, 0xf3c4, 0xf3a3, 0xf3b3,
+ 0xf479, 0xf47a, 0xf43c, 0xf445,
+ 0xf43d, 0xf33c, 0xf368, 0xf369,
+ 0xf36a, 0xf36b, 0xf36c, 0xf36d,
+ 0xf648, 0xf64a, 0xf649, 0xf30b,
+ 0xf49d, 0xf524, 0xf36e, 0xf41d,
+ 0xf41e, 0xf36f, 0xf34f, 0xf4b8,
+ 0xf4ab, 0xf621, 0xf63e, 0xf30c,
+ 0xf63d, 0xf63a, 0xf4e9, 0xf639,
+ 0xf602, 0xf63b, 0xf640, 0xf629,
+ 0xf63f, 0xf622, 0xf63c, 0xf457,
+ 0xf5ff, 0xf689, 0xf3b4, 0xf0cf,
+ 0xf364, 0xf4e7, 0xf6b6, 0xf6a8,
+ 0xEE43, 0xf493, 0xf425, 0xf456,
+ 0xf48c, 0x267b, 0x2194, 0x2195,
+ 0xf30a, 0xf331, 0xf40c, 0xf638,
+ 0xf601, 0xEE44, 0xf33f, 0x270a,
+ 0x0023, 0xf64b, 0xf64c, 0xf64d,
+ 0xf64e, 0xEE45, 0xEE46, 0xEE47,
+ 0xEE48, 0xEE49, 0xEE4A};
+static const int mb_tbl_code2uni_kddi2_min = 0x26ec;
+static const int mb_tbl_code2uni_kddi2_max = 0x2863;
+
+static const unsigned short mb_tbl_code2uni_kddi2[] = { // 0x26ec - 0x2863
+ 0xf320, 0xf300, 0xf6a5, 0xf3c3,
+ 0x2747, 0xf3a1, 0xf3b0, 0xf38a,
+ 0xf433, 0xf603, 0xf620, 0xf62d,
+ 0xf62b, 0xf4a4, 0xf4a1, 0xf494,
+ 0xf495, 0x2734, 0xf4a3, 0xf525,
+ 0x23f3, 0xf6ac, 0xf6ad, 0x267f,
+ 0xf530, 0x26a0, 0x2757, 0x2753,
+ 0x26d4, 0x26c4, 0xf319, 0x26a1,
+ 0x2600, 0xf31b, 0x2744, 0x2b50,
+ 0x2614, 0x2601, 0x26c5, 0x2648,
+ 0x2649, 0x264a, 0x264b, 0x264c,
+ 0x264d, 0x264e, 0x264f, 0x2650,
+ 0x2651, 0x2652, 0x2653, 0x26ce,
+ 0xf45c, 0xf4d4, 0xf3ab, 0xf4d6,
+ 0xf4ce, 0x270f, 0xf4d0, 0xf3e7,
+ 0xf3ea, 0xf6bb, 0xf17f, 0xf68f,
+ 0xf4e1, 0x2693, 0xf3e6, 0xf3e0,
+ 0xf374, 0xf3e2, 0xf6b2, 0xf68c,
+ 0xf685, 0xf697, 0xf69a, 0x2708,
+ 0x26f5, 0xf683, 0x26bd, 0xf3be,
+ 0xf3c2, 0xf3c1, 0x26be, 0xf3c8,
+ 0x2668, 0xf3ee, 0xf3ac, 0xf309,
+ 0xf5fc, 0xf377, 0xf378, 0xf37a,
+ 0xf356, 0xf3af, 0xf3ae, 0xf4b0,
+ 0xf3b2, 0xf384, 0xf338, 0xf47b,
+ 0xf1ef, 0xf349, 0xf341, 0xf381,
+ 0xf370, 0xf373, 0xf352, 0xf421,
+ 0xf353, 0xf359, 0xf354, 0xf430,
+ 0xf434, 0xf435, 0xf438, 0xf431,
+ 0xf427, 0xf41c, 0xf437, 0xf429,
+ 0xf424, 0xf436, 0xf334, 0xf33b,
+ 0xf337, 0xf4a2, 0xf4a7, 0xf61c,
+ 0xf198, 0xf4aa, 0xf498, 0xf48b,
+ 0xf47e, 0xf365, 0xf43e, 0xf47f,
+ 0xf4ae, 0x3299, 0xf4af, 0xf44a,
+ 0xf4a8, 0xf4a9, 0x261d, 0xf250,
+ 0xf480, 0xf44d, 0xf469, 0x263a,
+ 0xf468, 0xf4ac, 0xf453, 0xf448,
+ 0xf449, 0xf46a, 0xf4fa, 0xf3a4,
+ 0xf45b, 0xf3b6, 0xf3b8, 0xf3bb,
+ 0xf3a7, 0xf484, 0xf52b, 0xf486,
+ 0xf4bf, 0xf45a, 0xf47d, 0xf199,
+ 0xf489, 0xf50a, 0xf514, 0xf340,
+ 0xf48d, 0xf4f7, 0x2702, 0xf3a5,
+ 0xf50d, 0xf511, 0xf460, 0xf4ea,
+ 0xf512, 0xf4db, 0xf4de, 0xf4e6,
+ 0xf4e0, 0x2709, 0x0031, 0x0032,
+ 0x0033, 0x0034, 0x0035, 0x0036,
+ 0x0037, 0x0038, 0x0039, 0xf51f,
+ 0xE82D, 0x25c0, 0x25b6, 0x23ea,
+ 0x23e9, 0x25ab, 0x25aa, 0x2139,
+ 0x25fd, 0x25fe, 0xf538, 0xf539,
+ 0x25fb, 0x25fc, 0x26aa, 0x26ab,
+ 0x2795, 0x2796, 0x2733, 0x2b06,
+ 0x2b07, 0xf6ab, 0xf53d, 0xf53c,
+ 0x23ec, 0x23eb, 0xf536, 0xf537,
+ 0x2b1c, 0x2b1b, 0xf534, 0xf535,
+ 0x2196, 0x2198, 0x2122, 0x2716,
+ 0x274c, 0x274e, 0x27a1, 0x2b05,
+ 0x2797, 0x2197, 0x2199, 0x2714,
+ 0x00a9, 0x00ae, 0xf53a, 0xf53b,
+ 0x21aa, 0x21a9, 0x2705, 0xf4dc,
+ 0xf4cd, 0xf4c3, 0xf4be, 0xf4c5,
+ 0xf4cb, 0xf4d7, 0xf4d8, 0xf4d9,
+ 0xf4d5, 0xf4c4, 0xf4c6, 0xf4d3,
+ 0xf4c7, 0xf4cc, 0xf4d2, 0xf4da,
+ 0xf4cf, 0x26fd, 0xf5fe, 0xf1fa,
+ 0xf4ca, 0xf4c8, 0xf4c9, 0xEE40,
+ 0xf193, 0xf4b2, 0x231a, 0x231b,
+ 0xf4b3, 0xf4b4, 0xf4f9, 0xf52a,
+ 0xf4fc, 0xf529, 0xf4bd, 0xf526,
+ 0xf50b, 0xf4b5, 0xE83C, 0xf527,
+ 0xf4f1, 0xf50c, 0xf517, 0xf4f0,
+ 0x2003, 0x2002, 0x2005, 0xf4c1,
+ 0xf4c2, 0xf4e8, 0xf4e4, 0xf4e5,
+ 0x23f0, 0x2764, 0x260e, 0x2615,
+ 0xf301, 0x26f3, 0xf3c0, 0xf4df,
+ 0xf3a8, 0xf3ad, 0xf3aa, 0xf380,
+ 0xf382, 0x2660, 0x2666, 0x2663,
+ 0xf440, 0xf442, 0x270c, 0x270b,
+ 0xf311, 0xf314, 0xf313, 0xf191,
+ 0x0030, 0xf197, 0xf635, 0xf49e,
+ 0xf4a5, 0xf4a6, 0xEE41, 0xf30f,
+ 0xf35c, 0xEB89, 0xf510, 0xf520,
+ 0xf521, 0xf522, 0xf523, 0xf251,
+ 0x2611, 0x2712, 0xf518, 0xf50e,
+ 0xf519, 0xf516, 0xf4f2, 0xf3e1,
+ 0xf4eb, 0xf4d1, 0xf50f, 0xf503,
+ 0xf195, 0xf455, 0xf45e, 0xf4bb,
+ 0xf4fb, 0xf339, 0x26ea, 0xf687,
+ 0xf5fb, 0xf3b5, 0xf47c, 0xf42f,
+ 0xf43b, 0xf42d, 0xf609, 0xf60d,
+ 0xf631, 0xf613, 0xf419, 0xf680,
+ 0xf451, 0xf48f, 0xf528, 0xf386,
+ };
+static const int mb_tbl_code2uni_sb1_min = 0x27a9;
+static const int mb_tbl_code2uni_sb1_max = 0x2861;
+
+static const unsigned short mb_tbl_code2uni_sb1[] = { // 0x27a9 - 0x2861
+ 0xf4eb, 0xf4ee, 0xf4e9, 0xf4f2,
+ 0xf61c, 0xf60d, 0xf631, 0xf613,
+ 0xf435, 0xf419, 0xf437, 0xf47d,
+ 0xf680, 0xf451, 0xf4a1, 0xf340,
+ 0xf48f, 0xf381, 0xf52b, 0xf50d,
+ 0xf3c3, 0xf528, 0xf386, 0xf341,
+ 0xf342, 0xf47f, 0xf47b, 0xf480,
+ 0xf525, 0xf4bc, 0xf4ba, 0xf354,
+ 0x26f2, 0x26fa, 0x2668, 0xf3a1,
+ 0xf3ab, 0xf4bf, 0xf4c0, 0xf4fb,
+ 0xf4fc, 0xf4fa, 0xf47e, 0x303d,
+ 0xf004, 0xf19a, 0xf4b0, 0xf3af,
+ 0xf3c6, 0xf3c1, 0xf3b0, 0xf40e,
+ 0xf6a4, 0xf6b2, 0xf6a7, 0xf6b9,
+ 0xf6ba, 0xf6bc, 0xf489, 0xf4a4,
+ 0x26a1, 0xf460, 0xf6c0, 0xf6bd,
+ 0xf50a, 0xf4e2, 0xf38c, 0xf512,
+ 0xf513, 0xf306, 0xf373, 0xf4d6,
+ 0xf4b1, 0xf4b9, 0xf4e1, 0xf4aa,
+ 0xf3e6, 0xf6a5, 0xf17f, 0xf68f,
+ 0xf6bb, 0xf46e, 0xf3e3, 0xf3e7,
+ 0xf3e5, 0xf3ea, 0xf3eb, 0xf3e8,
+ 0xf68c, 0xf695, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf6b6,
+ 0xf6a2, 0xf201, 0xf49f, 0x2734,
+ 0x2733, 0xf51e, 0xf6ad, 0xf530,
+ 0x267f, 0xf4f6, 0x2665, 0x2666,
+ 0x2660, 0x2663, 0x0023, 0x27bf,
+ 0xf195, 0xf199, 0xf192, 0xf236,
+ 0xf21a, 0xf237, 0xf238, 0xf534,
+ 0xf532, 0xf533, 0x0031, 0x0032,
+ 0x0033, 0x0034, 0x0035, 0x0036,
+ 0x0037, 0x0038, 0x0039, 0x0030,
+ 0xf250, 0xf239, 0xf202, 0xf194,
+ 0xf235, 0xf233, 0xf22f, 0xf23a,
+ 0xf446, 0xf447, 0xf448, 0xf449,
+ 0x2b06, 0x2b07, 0x27a1, 0x2b05,
+ 0x2197, 0x2196, 0x2198, 0x2199,
+ 0x25b6, 0x25c0, 0x23e9, 0x23ea,
+ 0xf52f, 0x2648, 0x2649, 0x264a,
+ 0x264b, 0x264c, 0x264d, 0x264e,
+ 0x264f, 0x2650, 0x2651, 0x2652,
+ 0x2653, 0x26ce, 0xf51d, 0xf197,
+ 0x00a9, 0x00ae, 0xf4f3, 0xf4f4,
+ 0x26a0, 0xf481, 0xEE77, 0xEE78,
+ 0xEE79, 0xEE7A, 0xEE7B, 0xEE7C,
+ 0xEE7D};
+
+static const int mb_tbl_code2uni_sb2_min = 0x2921;
+static const int mb_tbl_code2uni_sb2_max = 0x29cc;
+
+static const unsigned short mb_tbl_code2uni_sb2[] = { // 0x2921 - 0x29cc
+ 0xf466, 0xf467, 0xf48b, 0xf468,
+ 0xf469, 0xf455, 0xf45f, 0xf4f7,
+ 0x260e, 0xf4f1, 0xf4e0, 0xf4bb,
+ 0xf44a, 0xf44d, 0x261d, 0x270a,
+ 0x270c, 0x270b, 0xf3bf, 0x26f3,
+ 0xf3be, 0x26be, 0xf3c4, 0x26bd,
+ 0xf41f, 0xf434, 0xf697, 0x26f5,
+ 0x2708, 0xf683, 0xf685, 0x2753,
+ 0x2757, 0x2764, 0xf494, 0xf550,
+ 0xf551, 0xf552, 0xf553, 0xf554,
+ 0xf555, 0xf556, 0xf557, 0xf558,
+ 0xf559, 0xf55a, 0xf55b, 0xf338,
+ 0xf531, 0xf339, 0xf384, 0xf48d,
+ 0xf48e, 0xf3e0, 0x26ea, 0xf3e2,
+ 0xf689, 0x26fd, 0xf5fb, 0xf3a4,
+ 0xf3a5, 0xf3b5, 0xf511, 0xf3b7,
+ 0xf3b8, 0xf3ba, 0xf374, 0xf378,
+ 0x2615, 0xf370, 0xf37a, 0x26c4,
+ 0x2601, 0x2600, 0x2614, 0xf319,
+ 0xf304, 0xf47c, 0xf431, 0xf42f,
+ 0xf43b, 0xf436, 0xf42d, 0xf433,
+ 0xf427, 0xf60a, 0xf603, 0xf61e,
+ 0xf620, 0xf4a9, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf4dd,
+ 0xf454, 0xf33a, 0xf337, 0xf33b,
+ 0xf490, 0xf334, 0xf335, 0xf6be,
+ 0xf3a7, 0xf376, 0xf37b, 0x3297,
+ 0xf6ac, 0xf48a, 0xf388, 0xf4a3,
+ 0xf389, 0x2702, 0xf380, 0x3299,
+ 0xf4bd, 0xf4e3, 0xf452, 0xf457,
+ 0xf461, 0xf462, 0xf484, 0xf485,
+ 0xf486, 0xf487, 0xf488, 0xf458,
+ 0xf459, 0xf45c, 0xf3ac, 0xf514,
+ 0xf3b6, 0xf493, 0xf497, 0xf498,
+ 0xf499, 0xf49a, 0xf49b, 0xf49c,
+ 0x2728, 0x2b50, 0xf4a8, 0xf4a6,
+ 0x2b55, 0x274c, 0xf4a2, 0xf31f,
+ 0x2754, 0x2755, 0xf375, 0xf35e,
+ 0xf366, 0xf35f, 0xf361, 0xf358,
+ 0xf35a, 0xf35d, 0xf35c, 0xf35b,
+ 0xf359, 0xf362, 0xf363, 0xf34e,
+ 0xf34a, 0xf353, 0xf349, 0xf345,
+ 0xf346, 0xf382, 0xf371, 0xf372,
+ };
+static const int mb_tbl_code2uni_sb3_min = 0x2a99;
+static const int mb_tbl_code2uni_sb3_max = 0x2b35;
+
+static const unsigned short mb_tbl_code2uni_sb3[] = { // 0x2a99 - 0x2b35
+ 0xf625, 0xf60f, 0xf614, 0xf601,
+ 0xf609, 0xf623, 0xf616, 0xf62a,
+ 0xf61d, 0xf60c, 0xf628, 0xf637,
+ 0xf633, 0xf612, 0xf630, 0xf632,
+ 0xf62d, 0xf602, 0xf622, 0x263a,
+ 0xf604, 0xf621, 0xf61a, 0xf618,
+ 0xf440, 0xf443, 0xf442, 0xf444,
+ 0xf64f, 0xf44b, 0xf44f, 0xf44c,
+ 0xf44e, 0xf450, 0xf645, 0xf646,
+ 0xf491, 0xf647, 0xf64c, 0xf46b,
+ 0xf46f, 0xf3c0, 0xf3c8, 0xf3b1,
+ 0xf3ca, 0xf699, 0xf69a, 0xf692,
+ 0xf691, 0xf693, 0xf3a2, 0xf687,
+ 0xf684, 0xf38d, 0xf49d, 0xf38e,
+ 0xf393, 0xf392, 0xf38f, 0xf302,
+ 0xf492, 0xf30a, 0xf367, 0xf387,
+ 0xf41a, 0xf390, 0xf300, 0xf33e,
+ 0xf383, 0xf391, 0xf343, 0xf385,
+ 0xf305, 0xf307, 0xf303, 0xf308,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0xf3e9,
+ 0xf3a8, 0xf3a9, 0xf3ec, 0xf3ef,
+ 0xf3f0, 0xf3a6, 0xf3ed, 0xf5fc,
+ 0xE4C5, 0xf1ef, 0xf1fa, 0xf1eb,
+ 0xf1e9, 0xf1ee, 0xf1ec, 0xf1ea,
+ 0xf1f7, 0xf1e8, 0xf1f0, 0xf471,
+ 0xf472, 0xf473, 0xf474, 0xf475,
+ 0xf476, 0xf477, 0xf478, 0xf5fd,
+ 0xf482, 0xf483, 0xf42c, 0xf426,
+ 0xf420, 0xf424, 0xf439, 0xf41b,
+ 0xf418, 0xf428, 0xf412, 0xf411,
+ 0xf43a, 0xf42e, 0xf430, 0xf40d,
+ 0xf414, 0xf417, 0xf42b, 0xf438,
+ 0xf170, 0xf171, 0xf18e, 0xf17e,
+ 0xf463, 0x2122, 0xEE70, 0xEE71,
+ 0xEE72, 0xEE73, 0xEE74, 0xEE75,
+ 0xEE76};
+
+
+
+static const int mb_tbl_uni_docomo2code1_min = 0x0023;
+static const int mb_tbl_uni_docomo2code1_max = 0x00ae;
+
+static const unsigned short mb_tbl_uni_docomo2code1_key[] = { // 0x0023 - 0x00ae
+ 0x0023, 0x0030, 0x0031, 0x0032,
+ 0x0033, 0x0034, 0x0035, 0x0036,
+ 0x0037, 0x0038, 0x0039, 0x00a9,
+ 0x00ae, };
+
+static const unsigned short mb_tbl_uni_docomo2code1_value[] = { // 0x0023 - 0x00ae
+ 0x2964, 0x296f, 0x2966, 0x2967,
+ 0x2968, 0x2969, 0x296a, 0x296b,
+ 0x296c, 0x296d, 0x296e, 0x29b5,
+ 0x29ba, };
+
+static const int mb_tbl_uni_docomo2code1_len = sizeof(mb_tbl_uni_docomo2code1_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_docomo2code2_min = 0x203c;
+static const int mb_tbl_uni_docomo2code2_max = 0x3299;
+
+static const unsigned short mb_tbl_uni_docomo2code2_key[] = { // 0x203c - 0x3299
+ 0x203c, 0x2049, 0x2122, 0x2194,
+ 0x2195, 0x2196, 0x2197, 0x2198,
+ 0x2199, 0x21a9, 0x231a, 0x23f0,
+ 0x23f3, 0x24c2, 0x2600, 0x2601,
+ 0x260e, 0x2614, 0x2615, 0x2648,
+ 0x2649, 0x264a, 0x264b, 0x264c,
+ 0x264d, 0x264e, 0x264f, 0x2650,
+ 0x2651, 0x2652, 0x2653, 0x2660,
+ 0x2663, 0x2665, 0x2666, 0x2668,
+ 0x267b, 0x267f, 0x26a0, 0x26a1,
+ 0x26bd, 0x26be, 0x26c4, 0x26f3,
+ 0x26f5, 0x26fd, 0x2702, 0x2708,
+ 0x2709, 0x270a, 0x270b, 0x270c,
+ 0x270f, 0x2712, 0x2728, 0x2757,
+ 0x2764, 0x27b0, 0x27bf, 0x2934,
+ 0x2935, 0x3030, 0x3299, };
+
+static const unsigned short mb_tbl_uni_docomo2code2_value[] = { // 0x203c - 0x3299
+ 0x2988, 0x2987, 0x29b6, 0x29c0,
+ 0x29c1, 0x291b, 0x28fc, 0x291a,
+ 0x2929, 0x295e, 0x29a3, 0x293e,
+ 0x29a0, 0x28e0, 0x28c2, 0x28c3,
+ 0x290b, 0x28c4, 0x28f4, 0x28ca,
+ 0x28cb, 0x28cc, 0x28cd, 0x28ce,
+ 0x28cf, 0x28d0, 0x28d1, 0x28d2,
+ 0x28d3, 0x28d4, 0x28d5, 0x2912,
+ 0x2914, 0x2911, 0x2913, 0x297b,
+ 0x29b9, 0x291f, 0x29bb, 0x28c6,
+ 0x28da, 0x28d7, 0x28c5, 0x28d8,
+ 0x2927, 0x28ef, 0x28f9, 0x28e6,
+ 0x2957, 0x2917, 0x2919, 0x2918,
+ 0x299d, 0x2932, 0x297e, 0x2986,
+ 0x2970, 0x298e, 0x2963, 0x2979,
+ 0x2984, 0x298d, 0x29b8, };
+
+static const int mb_tbl_uni_docomo2code2_len = sizeof(mb_tbl_uni_docomo2code2_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_docomo2code3_min = 0x1f17f;
+static const int mb_tbl_uni_docomo2code3_max = 0x1f6bb;
+
+static const unsigned short mb_tbl_uni_docomo2code3_key[] = { // 0x1f17f - 0x1f6bb
+ 0xf17f, 0xf191, 0xf193, 0xf194,
+ 0xf195, 0xf196, 0xf197, 0xf232,
+ 0xf233, 0xf234, 0xf235, 0xf300,
+ 0xf301, 0xf302, 0xf303, 0xf30a,
+ 0xf311, 0xf313, 0xf314, 0xf315,
+ 0xf319, 0xf331, 0xf337, 0xf338,
+ 0xf340, 0xf341, 0xf34c, 0xf34e,
+ 0xf352, 0xf354, 0xf359, 0xf35c,
+ 0xf35e, 0xf370, 0xf374, 0xf375,
+ 0xf376, 0xf377, 0xf378, 0xf37a,
+ 0xf380, 0xf381, 0xf382, 0xf384,
+ 0xf3a0, 0xf3a4, 0xf3a5, 0xf3a7,
+ 0xf3a8, 0xf3a9, 0xf3aa, 0xf3ab,
+ 0xf3ac, 0xf3ae, 0xf3b5, 0xf3b6,
+ 0xf3bd, 0xf3be, 0xf3bf, 0xf3c0,
+ 0xf3c1, 0xf3c2, 0xf3c3, 0xf3e0,
+ 0xf3e2, 0xf3e3, 0xf3e5, 0xf3e6,
+ 0xf3e7, 0xf3e8, 0xf3ea, 0xf3eb,
+ 0xf40c, 0xf41f, 0xf424, 0xf427,
+ 0xf431, 0xf434, 0xf436, 0xf437,
+ 0xf440, 0xf442, 0xf44a, 0xf44d,
+ 0xf451, 0xf453, 0xf455, 0xf456,
+ 0xf45b, 0xf45c, 0xf45d, 0xf45f,
+ 0xf460, 0xf463, 0xf464, 0xf484,
+ 0xf48b, 0xf48c, 0xf48d, 0xf493,
+ 0xf494, 0xf495, 0xf4a0, 0xf4a1,
+ 0xf4a2, 0xf4a3, 0xf4a4, 0xf4a5,
+ 0xf4a6, 0xf4a7, 0xf4a8, 0xf4b0,
+ 0xf4b4, 0xf4ba, 0xf4bb, 0xf4bf,
+ 0xf4ce, 0xf4d6, 0xf4dd, 0xf4df,
+ 0xf4e0, 0xf4e9, 0xf4f1, 0xf4f2,
+ 0xf4f7, 0xf4fa, 0xf50d, 0xf511,
+ 0xf514, 0xf51a, 0xf51b, 0xf51c,
+ 0xf527, 0xf5fb, 0xf601, 0xf603,
+ 0xf605, 0xf606, 0xf609, 0xf60b,
+ 0xf60c, 0xf60d, 0xf60f, 0xf612,
+ 0xf613, 0xf614, 0xf616, 0xf61c,
+ 0xf61e, 0xf620, 0xf621, 0xf622,
+ 0xf623, 0xf62d, 0xf631, 0xf635,
+ 0xf683, 0xf684, 0xf68c, 0xf697,
+ 0xf699, 0xf6a2, 0xf6a5, 0xf6a9,
+ 0xf6aa, 0xf6ac, 0xf6ad, 0xf6b2,
+ 0xf6bb, };
+
+static const unsigned short mb_tbl_uni_docomo2code3_value[] = { // 0x1f17f - 0x1f6bb
+ 0x28f0, 0x295f, 0x295b, 0x295c,
+ 0x2961, 0x29b3, 0x298f, 0x29bc,
+ 0x29bd, 0x29be, 0x29bf, 0x28c7,
+ 0x28c8, 0x28c9, 0x2937, 0x29c3,
+ 0x2920, 0x2922, 0x2921, 0x2924,
+ 0x2923, 0x29ca, 0x29c7, 0x29cc,
+ 0x29c5, 0x29cb, 0x29c8, 0x29c9,
+ 0x29c6, 0x28f7, 0x29cd, 0x29d0,
+ 0x29d1, 0x29ce, 0x28f3, 0x29a2,
+ 0x29cf, 0x29da, 0x28f5, 0x28f6,
+ 0x2908, 0x2909, 0x290a, 0x2928,
+ 0x28fd, 0x28fa, 0x28fb, 0x28fe,
+ 0x28ff, 0x2900, 0x2901, 0x2902,
+ 0x2930, 0x290f, 0x297a, 0x2983,
+ 0x28d6, 0x28d9, 0x28db, 0x28dc,
+ 0x28dd, 0x2996, 0x29b7, 0x28e7,
+ 0x28e8, 0x28e9, 0x28ea, 0x28eb,
+ 0x28ec, 0x28ed, 0x28ee, 0x29c2,
+ 0x29d2, 0x29d5, 0x29d3, 0x29d4,
+ 0x2926, 0x29d8, 0x2925, 0x29d9,
+ 0x2915, 0x2916, 0x2981, 0x29ab,
+ 0x299e, 0x291e, 0x2992, 0x2995,
+ 0x2993, 0x2906, 0x2931, 0x291d,
+ 0x28f8, 0x291c, 0x2935, 0x2994,
+ 0x297d, 0x299b, 0x299f, 0x2971,
+ 0x2972, 0x2973, 0x297c, 0x297f,
+ 0x2980, 0x2982, 0x2985, 0x2989,
+ 0x298a, 0x298b, 0x298c, 0x2999,
+ 0x295a, 0x2936, 0x299a, 0x2910,
+ 0x29b4, 0x2907, 0x290d, 0x28de,
+ 0x2954, 0x2953, 0x290c, 0x2952,
+ 0x2905, 0x290e, 0x2960, 0x295d,
+ 0x2997, 0x293d, 0x293c, 0x293b,
+ 0x299c, 0x29c4, 0x29d7, 0x2974,
+ 0x29a6, 0x29ae, 0x29ad, 0x29d6,
+ 0x29a5, 0x29aa, 0x29b0, 0x29a9,
+ 0x29a7, 0x29a4, 0x2977, 0x29ac,
+ 0x2976, 0x2975, 0x29a8, 0x29b2,
+ 0x29af, 0x29b1, 0x29db, 0x2978,
+ 0x28df, 0x28e1, 0x28e4, 0x28e2,
+ 0x28e3, 0x28e5, 0x28f1, 0x2962,
+ 0x2998, 0x2903, 0x2904, 0x29a1,
+ 0x28f2, };
+
+static const int mb_tbl_uni_docomo2code3_len = sizeof(mb_tbl_uni_docomo2code3_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_kddi2code1_min = 0x0023;
+static const int mb_tbl_uni_kddi2code1_max = 0x00ae;
+
+static const unsigned short mb_tbl_uni_kddi2code1_key[] = { // 0x0023 - 0x00ae
+ 0x0023, 0x0030, 0x0031, 0x0032,
+ 0x0033, 0x0034, 0x0035, 0x0036,
+ 0x0037, 0x0038, 0x0039, 0x00a9,
+ 0x00ae, };
+
+static const unsigned short mb_tbl_uni_kddi2code1_value[] = { // 0x0023 - 0x00ae
+ 0x25bc, 0x2830, 0x27a6, 0x27a7,
+ 0x27a8, 0x27a9, 0x27aa, 0x27ab,
+ 0x27ac, 0x27ad, 0x27ae, 0x27dc,
+ 0x27dd, };
+
+static const int mb_tbl_uni_kddi2code1_len = sizeof(mb_tbl_uni_kddi2code1_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_kddi2code2_min = 0x2002;
+static const int mb_tbl_uni_kddi2code2_max = 0x3299;
+
+static const unsigned short mb_tbl_uni_kddi2code2_key[] = { // 0x2002 - 0x3299
+ 0x2002, 0x2003, 0x2005, 0x203c,
+ 0x2049, 0x2122, 0x2139, 0x2194,
+ 0x2195, 0x2196, 0x2197, 0x2198,
+ 0x2199, 0x21a9, 0x21aa, 0x231a,
+ 0x231b, 0x23e9, 0x23ea, 0x23eb,
+ 0x23ec, 0x23f0, 0x23f3, 0x25aa,
+ 0x25ab, 0x25b6, 0x25c0, 0x25fb,
+ 0x25fc, 0x25fd, 0x25fe, 0x2600,
+ 0x2601, 0x260e, 0x2611, 0x2614,
+ 0x2615, 0x261d, 0x263a, 0x2648,
+ 0x2649, 0x264a, 0x264b, 0x264c,
+ 0x264d, 0x264e, 0x264f, 0x2650,
+ 0x2651, 0x2652, 0x2653, 0x2660,
+ 0x2663, 0x2665, 0x2666, 0x2668,
+ 0x267b, 0x267f, 0x2693, 0x26a0,
+ 0x26a1, 0x26aa, 0x26ab, 0x26bd,
+ 0x26be, 0x26c4, 0x26c5, 0x26ce,
+ 0x26d4, 0x26ea, 0x26f2, 0x26f3,
+ 0x26f5, 0x26fa, 0x26fd, 0x2702,
+ 0x2705, 0x2708, 0x2709, 0x270a,
+ 0x270b, 0x270c, 0x270f, 0x2712,
+ 0x2714, 0x2716, 0x2728, 0x2733,
+ 0x2734, 0x2744, 0x2747, 0x274c,
+ 0x274e, 0x2753, 0x2757, 0x2764,
+ 0x2795, 0x2796, 0x2797, 0x27a1,
+ 0x27b0, 0x2934, 0x2935, 0x2b05,
+ 0x2b06, 0x2b07, 0x2b1b, 0x2b1c,
+ 0x2b50, 0x2b55, 0x3297, 0x3299,
+ };
+
+static const unsigned short mb_tbl_uni_kddi2code2_value[] = { // 0x2002 - 0x3299
+ 0x2811, 0x2810, 0x2812, 0x2568,
+ 0x2567, 0x27d2, 0x27b7, 0x25b2,
+ 0x25b3, 0x27d0, 0x27d9, 0x27d1,
+ 0x27da, 0x27e1, 0x27e0, 0x27fe,
+ 0x27ff, 0x27b4, 0x27b3, 0x27c9,
+ 0x27c8, 0x2818, 0x2700, 0x27b6,
+ 0x27b5, 0x27b2, 0x27b1, 0x27bc,
+ 0x27bd, 0x27b8, 0x27b9, 0x270c,
+ 0x2711, 0x281a, 0x2840, 0x2710,
+ 0x281b, 0x277a, 0x277f, 0x2713,
+ 0x2714, 0x2715, 0x2716, 0x2717,
+ 0x2718, 0x2719, 0x271a, 0x271b,
+ 0x271c, 0x271d, 0x271e, 0x2825,
+ 0x2827, 0x24f0, 0x2826, 0x2740,
+ 0x25b1, 0x2703, 0x272d, 0x2705,
+ 0x270b, 0x27be, 0x27bf, 0x273a,
+ 0x273e, 0x2709, 0x2712, 0x271f,
+ 0x2708, 0x2852, 0x24ba, 0x281d,
+ 0x2738, 0x24bb, 0x27f5, 0x279a,
+ 0x27e2, 0x2737, 0x27a5, 0x25bb,
+ 0x282b, 0x282a, 0x2725, 0x2841,
+ 0x27db, 0x27d3, 0x24f6, 0x27c2,
+ 0x26fd, 0x270e, 0x26f0, 0x27d4,
+ 0x27d5, 0x2707, 0x2706, 0x2819,
+ 0x27c0, 0x27c1, 0x27d8, 0x27d6,
+ 0x2569, 0x2565, 0x2566, 0x27d7,
+ 0x27c3, 0x27c4, 0x27cd, 0x27cc,
+ 0x270f, 0x24f8, 0x24e4, 0x2775,
+ };
+
+static const int mb_tbl_uni_kddi2code2_len = sizeof(mb_tbl_uni_kddi2code2_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_kddi2code3_min = 0x1f004;
+static const int mb_tbl_uni_kddi2code3_max = 0x1f6c0;
+
+static const unsigned short mb_tbl_uni_kddi2code3_key[] = { // 0x1f004 - 0x1f6c0
+ 0xf004, 0xf0cf, 0xf170, 0xf171,
+ 0xf17e, 0xf17f, 0xf18e, 0xf191,
+ 0xf192, 0xf193, 0xf194, 0xf195,
+ 0xf197, 0xf198, 0xf199, 0xf19a,
+ 0xf1e8, 0xf1e9, 0xf1ea, 0xf1eb,
+ 0xf1ec, 0xf1ee, 0xf1ef, 0xf1f0,
+ 0xf1f7, 0xf1fa, 0xf202, 0xf22f,
+ 0xf233, 0xf235, 0xf239, 0xf23a,
+ 0xf250, 0xf251, 0xf300, 0xf301,
+ 0xf302, 0xf303, 0xf305, 0xf306,
+ 0xf308, 0xf309, 0xf30a, 0xf30b,
+ 0xf30c, 0xf30f, 0xf311, 0xf313,
+ 0xf314, 0xf319, 0xf31b, 0xf320,
+ 0xf330, 0xf331, 0xf334, 0xf335,
+ 0xf337, 0xf338, 0xf339, 0xf33a,
+ 0xf33b, 0xf33c, 0xf33d, 0xf33f,
+ 0xf340, 0xf341, 0xf342, 0xf344,
+ 0xf345, 0xf346, 0xf347, 0xf348,
+ 0xf349, 0xf34a, 0xf34c, 0xf34d,
+ 0xf34e, 0xf34f, 0xf351, 0xf352,
+ 0xf353, 0xf354, 0xf355, 0xf356,
+ 0xf357, 0xf358, 0xf359, 0xf35a,
+ 0xf35b, 0xf35c, 0xf35d, 0xf35e,
+ 0xf35f, 0xf360, 0xf361, 0xf362,
+ 0xf363, 0xf364, 0xf365, 0xf366,
+ 0xf367, 0xf368, 0xf369, 0xf36a,
+ 0xf36b, 0xf36c, 0xf36d, 0xf36e,
+ 0xf36f, 0xf370, 0xf371, 0xf372,
+ 0xf373, 0xf374, 0xf375, 0xf376,
+ 0xf377, 0xf378, 0xf379, 0xf37a,
+ 0xf37b, 0xf380, 0xf381, 0xf382,
+ 0xf383, 0xf384, 0xf385, 0xf386,
+ 0xf387, 0xf388, 0xf389, 0xf38a,
+ 0xf38b, 0xf38c, 0xf38d, 0xf38e,
+ 0xf38f, 0xf390, 0xf391, 0xf392,
+ 0xf393, 0xf3a1, 0xf3a2, 0xf3a3,
+ 0xf3a4, 0xf3a5, 0xf3a7, 0xf3a8,
+ 0xf3a9, 0xf3aa, 0xf3ab, 0xf3ac,
+ 0xf3ad, 0xf3ae, 0xf3af, 0xf3b0,
+ 0xf3b1, 0xf3b2, 0xf3b3, 0xf3b4,
+ 0xf3b5, 0xf3b6, 0xf3b8, 0xf3b9,
+ 0xf3ba, 0xf3bb, 0xf3bc, 0xf3be,
+ 0xf3bf, 0xf3c0, 0xf3c1, 0xf3c2,
+ 0xf3c3, 0xf3c4, 0xf3c6, 0xf3c8,
+ 0xf3ca, 0xf3e0, 0xf3e1, 0xf3e2,
+ 0xf3e3, 0xf3e5, 0xf3e6, 0xf3e7,
+ 0xf3e8, 0xf3e9, 0xf3ea, 0xf3eb,
+ 0xf3ec, 0xf3ed, 0xf3ee, 0xf3ef,
+ 0xf3f0, 0xf40c, 0xf40d, 0xf414,
+ 0xf417, 0xf418, 0xf419, 0xf41a,
+ 0xf41b, 0xf41c, 0xf41d, 0xf41e,
+ 0xf420, 0xf421, 0xf422, 0xf423,
+ 0xf424, 0xf425, 0xf427, 0xf428,
+ 0xf429, 0xf42b, 0xf42c, 0xf42d,
+ 0xf42e, 0xf42f, 0xf430, 0xf431,
+ 0xf432, 0xf433, 0xf434, 0xf435,
+ 0xf436, 0xf437, 0xf438, 0xf43b,
+ 0xf43c, 0xf43d, 0xf43e, 0xf440,
+ 0xf442, 0xf443, 0xf444, 0xf445,
+ 0xf446, 0xf447, 0xf448, 0xf449,
+ 0xf44a, 0xf44b, 0xf44c, 0xf44d,
+ 0xf44e, 0xf44f, 0xf451, 0xf452,
+ 0xf453, 0xf454, 0xf455, 0xf456,
+ 0xf457, 0xf458, 0xf459, 0xf45a,
+ 0xf45b, 0xf45c, 0xf45e, 0xf45f,
+ 0xf460, 0xf462, 0xf463, 0xf468,
+ 0xf469, 0xf46a, 0xf46e, 0xf46f,
+ 0xf470, 0xf471, 0xf472, 0xf473,
+ 0xf474, 0xf475, 0xf476, 0xf477,
+ 0xf478, 0xf479, 0xf47a, 0xf47b,
+ 0xf47c, 0xf47d, 0xf47e, 0xf47f,
+ 0xf480, 0xf483, 0xf484, 0xf485,
+ 0xf486, 0xf487, 0xf488, 0xf489,
+ 0xf48a, 0xf48b, 0xf48c, 0xf48d,
+ 0xf48f, 0xf490, 0xf491, 0xf493,
+ 0xf494, 0xf495, 0xf496, 0xf498,
+ 0xf499, 0xf49a, 0xf49b, 0xf49c,
+ 0xf49d, 0xf49e, 0xf4a1, 0xf4a2,
+ 0xf4a3, 0xf4a4, 0xf4a5, 0xf4a6,
+ 0xf4a7, 0xf4a8, 0xf4a9, 0xf4aa,
+ 0xf4ab, 0xf4ac, 0xf4ae, 0xf4af,
+ 0xf4b0, 0xf4b2, 0xf4b3, 0xf4b4,
+ 0xf4b5, 0xf4b8, 0xf4b9, 0xf4bb,
+ 0xf4bc, 0xf4bd, 0xf4be, 0xf4bf,
+ 0xf4c1, 0xf4c2, 0xf4c3, 0xf4c4,
+ 0xf4c5, 0xf4c6, 0xf4c7, 0xf4c8,
+ 0xf4c9, 0xf4ca, 0xf4cb, 0xf4cc,
+ 0xf4cd, 0xf4ce, 0xf4cf, 0xf4d0,
+ 0xf4d1, 0xf4d2, 0xf4d3, 0xf4d4,
+ 0xf4d5, 0xf4d6, 0xf4d7, 0xf4d8,
+ 0xf4d9, 0xf4da, 0xf4db, 0xf4dc,
+ 0xf4dd, 0xf4de, 0xf4df, 0xf4e0,
+ 0xf4e1, 0xf4e4, 0xf4e5, 0xf4e6,
+ 0xf4e7, 0xf4e8, 0xf4e9, 0xf4ea,
+ 0xf4eb, 0xf4f0, 0xf4f1, 0xf4f2,
+ 0xf4f3, 0xf4f4, 0xf4f6, 0xf4f7,
+ 0xf4f9, 0xf4fa, 0xf4fb, 0xf4fc,
+ 0xf503, 0xf50a, 0xf50b, 0xf50c,
+ 0xf50d, 0xf50e, 0xf50f, 0xf510,
+ 0xf511, 0xf512, 0xf514, 0xf516,
+ 0xf517, 0xf518, 0xf519, 0xf51e,
+ 0xf51f, 0xf520, 0xf521, 0xf522,
+ 0xf523, 0xf524, 0xf525, 0xf526,
+ 0xf527, 0xf528, 0xf529, 0xf52a,
+ 0xf52b, 0xf52e, 0xf530, 0xf534,
+ 0xf535, 0xf536, 0xf537, 0xf538,
+ 0xf539, 0xf53a, 0xf53b, 0xf53c,
+ 0xf53d, 0xf5fb, 0xf5fc, 0xf5fe,
+ 0xf5ff, 0xf601, 0xf602, 0xf603,
+ 0xf609, 0xf60a, 0xf60c, 0xf60d,
+ 0xf60f, 0xf612, 0xf613, 0xf614,
+ 0xf616, 0xf618, 0xf61a, 0xf61c,
+ 0xf620, 0xf621, 0xf622, 0xf623,
+ 0xf624, 0xf628, 0xf629, 0xf62a,
+ 0xf62b, 0xf62d, 0xf630, 0xf631,
+ 0xf632, 0xf633, 0xf635, 0xf637,
+ 0xf638, 0xf639, 0xf63a, 0xf63b,
+ 0xf63c, 0xf63d, 0xf63e, 0xf63f,
+ 0xf640, 0xf645, 0xf646, 0xf647,
+ 0xf648, 0xf649, 0xf64a, 0xf64b,
+ 0xf64c, 0xf64d, 0xf64e, 0xf64f,
+ 0xf680, 0xf683, 0xf685, 0xf687,
+ 0xf689, 0xf68c, 0xf68f, 0xf691,
+ 0xf692, 0xf693, 0xf697, 0xf69a,
+ 0xf6a2, 0xf6a5, 0xf6a7, 0xf6a8,
+ 0xf6a9, 0xf6ab, 0xf6ac, 0xf6ad,
+ 0xf6b2, 0xf6b6, 0xf6bb, 0xf6c0,
+ };
+
+static const unsigned short mb_tbl_uni_kddi2code3_value[] = { // 0x1f004 - 0x1f6c0
+ 0x24bc, 0x25a7, 0x255e, 0x255f,
+ 0x2560, 0x272a, 0x2561, 0x282f,
+ 0x24d0, 0x27fc, 0x24d3, 0x284c,
+ 0x2831, 0x276c, 0x2793, 0x24bd,
+ 0x2549, 0x2546, 0x24c0, 0x2545,
+ 0x2548, 0x2547, 0x2750, 0x254a,
+ 0x24c1, 0x27f7, 0x24d2, 0x24d6,
+ 0x24d5, 0x24d4, 0x24d1, 0x24d7,
+ 0x277b, 0x283f, 0x26ed, 0x281c,
+ 0x2533, 0x253c, 0x253f, 0x24c5,
+ 0x253d, 0x2743, 0x25b4, 0x258b,
+ 0x2597, 0x2837, 0x282c, 0x282e,
+ 0x282d, 0x270a, 0x270d, 0x26ec,
+ 0x2570, 0x25b5, 0x2766, 0x24e1,
+ 0x2768, 0x274e, 0x2851, 0x24df,
+ 0x2767, 0x2581, 0x256e, 0x25ba,
+ 0x2797, 0x2752, 0x24b8, 0x256f,
+ 0x2506, 0x2507, 0x256c, 0x256a,
+ 0x2751, 0x2505, 0x256d, 0x256b,
+ 0x2504, 0x2592, 0x2571, 0x2756,
+ 0x2758, 0x275a, 0x2573, 0x2748,
+ 0x2574, 0x24fe, 0x2759, 0x24ff,
+ 0x2501, 0x2838, 0x2500, 0x24fa,
+ 0x24fc, 0x2572, 0x24fd, 0x2502,
+ 0x2503, 0x25a8, 0x2771, 0x24fb,
+ 0x2535, 0x2582, 0x2583, 0x2584,
+ 0x2585, 0x2586, 0x2587, 0x258e,
+ 0x2591, 0x2754, 0x2508, 0x2509,
+ 0x2755, 0x2730, 0x24f9, 0x24e2,
+ 0x2745, 0x2746, 0x2576, 0x2747,
+ 0x24e3, 0x2823, 0x2753, 0x2824,
+ 0x2539, 0x274d, 0x253b, 0x2863,
+ 0x2536, 0x24e6, 0x24e7, 0x26f3,
+ 0x2575, 0x24c4, 0x252e, 0x252f,
+ 0x2532, 0x2538, 0x253a, 0x2531,
+ 0x2530, 0x26f1, 0x252d, 0x257a,
+ 0x2787, 0x279b, 0x278c, 0x2820,
+ 0x2540, 0x2822, 0x2722, 0x2742,
+ 0x2821, 0x274a, 0x2749, 0x26f2,
+ 0x2528, 0x274c, 0x257b, 0x25a6,
+ 0x2855, 0x2789, 0x278a, 0x2578,
+ 0x2527, 0x278b, 0x2517, 0x273b,
+ 0x24f7, 0x281e, 0x273d, 0x273c,
+ 0x26ef, 0x2579, 0x24be, 0x273f,
+ 0x2529, 0x272f, 0x2847, 0x2731,
+ 0x24c9, 0x24ca, 0x272e, 0x2727,
+ 0x24cc, 0x253e, 0x2728, 0x24cb,
+ 0x2541, 0x2544, 0x2741, 0x2542,
+ 0x2543, 0x25b6, 0x255a, 0x255b,
+ 0x255c, 0x2557, 0x285e, 0x2537,
+ 0x2556, 0x2761, 0x258f, 0x2590,
+ 0x2555, 0x2757, 0x24bf, 0x24c6,
+ 0x2764, 0x25ae, 0x2760, 0x2558,
+ 0x2763, 0x255d, 0x2553, 0x2859,
+ 0x2559, 0x2857, 0x275b, 0x275f,
+ 0x2577, 0x26f4, 0x275c, 0x275d,
+ 0x2765, 0x2762, 0x275e, 0x2858,
+ 0x257e, 0x2580, 0x2772, 0x2828,
+ 0x2829, 0x251b, 0x251c, 0x257f,
+ 0x24d8, 0x24d9, 0x2783, 0x2784,
+ 0x2777, 0x2521, 0x251f, 0x277d,
+ 0x2520, 0x251e, 0x2860, 0x24e9,
+ 0x2782, 0x24de, 0x284d, 0x25af,
+ 0x25a3, 0x24ee, 0x24ef, 0x2791,
+ 0x2788, 0x2720, 0x284e, 0x2563,
+ 0x279e, 0x24ea, 0x2562, 0x2780,
+ 0x277e, 0x2785, 0x24c8, 0x2526,
+ 0x2534, 0x254b, 0x254c, 0x254d,
+ 0x254e, 0x254f, 0x2550, 0x2551,
+ 0x2552, 0x257c, 0x257d, 0x274f,
+ 0x2856, 0x2792, 0x2770, 0x2773,
+ 0x277c, 0x2554, 0x278d, 0x24eb,
+ 0x278f, 0x24ec, 0x24ed, 0x2794,
+ 0x24e5, 0x276f, 0x25b0, 0x2798,
+ 0x2861, 0x24e0, 0x2525, 0x25ad,
+ 0x26fb, 0x26fc, 0x24f1, 0x276e,
+ 0x24f2, 0x24f3, 0x24f4, 0x24f5,
+ 0x258c, 0x2833, 0x26fa, 0x2769,
+ 0x26fe, 0x26f9, 0x2834, 0x2835,
+ 0x276a, 0x2778, 0x2779, 0x276d,
+ 0x2594, 0x2781, 0x2774, 0x2776,
+ 0x274b, 0x27fd, 0x2800, 0x2801,
+ 0x2809, 0x2593, 0x24c7, 0x284f,
+ 0x24b9, 0x2806, 0x27e6, 0x2790,
+ 0x2813, 0x2814, 0x27e5, 0x27ed,
+ 0x27e7, 0x27ee, 0x27f0, 0x27f9,
+ 0x27fa, 0x27f8, 0x27e8, 0x27f1,
+ 0x27e4, 0x2724, 0x27f4, 0x2726,
+ 0x2849, 0x27f2, 0x27ef, 0x2721,
+ 0x27ec, 0x2723, 0x27e9, 0x27ea,
+ 0x27eb, 0x27f3, 0x27a1, 0x27e3,
+ 0x24dd, 0x27a2, 0x281f, 0x27a4,
+ 0x272c, 0x2816, 0x2817, 0x27a3,
+ 0x25a9, 0x2815, 0x259a, 0x279f,
+ 0x2848, 0x280f, 0x280c, 0x2846,
+ 0x24db, 0x24dc, 0x24cf, 0x2799,
+ 0x2802, 0x2786, 0x2850, 0x2804,
+ 0x284b, 0x2795, 0x2808, 0x280d,
+ 0x279c, 0x2843, 0x284a, 0x283a,
+ 0x279d, 0x27a0, 0x2796, 0x2845,
+ 0x280e, 0x2842, 0x2844, 0x24ce,
+ 0x27af, 0x283b, 0x283c, 0x283d,
+ 0x283e, 0x258d, 0x26ff, 0x2807,
+ 0x280b, 0x2862, 0x2805, 0x2803,
+ 0x278e, 0x24da, 0x2704, 0x27ce,
+ 0x27cf, 0x27ca, 0x27cb, 0x27ba,
+ 0x27bb, 0x27de, 0x27df, 0x27c7,
+ 0x27c6, 0x2854, 0x2744, 0x27f6,
+ 0x25a4, 0x25b8, 0x259c, 0x26f5,
+ 0x285a, 0x2518, 0x2510, 0x285b,
+ 0x250a, 0x2514, 0x285d, 0x250b,
+ 0x250e, 0x251a, 0x2519, 0x276b,
+ 0x26f6, 0x2595, 0x25a1, 0x250d,
+ 0x250c, 0x2511, 0x259f, 0x250f,
+ 0x26f8, 0x26f7, 0x2516, 0x285c,
+ 0x2515, 0x2513, 0x2832, 0x2512,
+ 0x25b7, 0x259b, 0x2599, 0x259d,
+ 0x25a2, 0x2598, 0x2596, 0x25a0,
+ 0x259e, 0x2522, 0x2523, 0x2524,
+ 0x2588, 0x258a, 0x2589, 0x25bd,
+ 0x25be, 0x25bf, 0x25c0, 0x251d,
+ 0x285f, 0x2739, 0x2734, 0x2853,
+ 0x25a5, 0x2733, 0x272b, 0x252b,
+ 0x252a, 0x252c, 0x2735, 0x2736,
+ 0x24cd, 0x26ee, 0x24c2, 0x25ab,
+ 0x2564, 0x27c5, 0x2701, 0x2702,
+ 0x2732, 0x25aa, 0x2729, 0x24c3,
+ };
+
+static const int mb_tbl_uni_kddi2code3_len = sizeof(mb_tbl_uni_kddi2code3_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_sb2code1_min = 0x0023;
+static const int mb_tbl_uni_sb2code1_max = 0x00ae;
+
+static const unsigned short mb_tbl_uni_sb2code1_key[] = { // 0x0023 - 0x00ae
+ 0x0023, 0x0030, 0x0031, 0x0032,
+ 0x0033, 0x0034, 0x0035, 0x0036,
+ 0x0037, 0x0038, 0x0039, 0x00a9,
+ 0x00ae, };
+
+static const unsigned short mb_tbl_uni_sb2code1_value[] = { // 0x0023 - 0x00ae
+ 0x2817, 0x282c, 0x2823, 0x2824,
+ 0x2825, 0x2826, 0x2827, 0x2828,
+ 0x2829, 0x282a, 0x282b, 0x2855,
+ 0x2856, };
+
+static const int mb_tbl_uni_sb2code1_len = sizeof(mb_tbl_uni_sb2code1_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_sb2code2_min = 0x2122;
+static const int mb_tbl_uni_sb2code2_max = 0x3299;
+
+static const unsigned short mb_tbl_uni_sb2code2_key[] = { // 0x2122 - 0x3299
+ 0x2122, 0x2196, 0x2197, 0x2198,
+ 0x2199, 0x23e9, 0x23ea, 0x25b6,
+ 0x25c0, 0x2600, 0x2601, 0x260e,
+ 0x2614, 0x2615, 0x261d, 0x263a,
+ 0x2648, 0x2649, 0x264a, 0x264b,
+ 0x264c, 0x264d, 0x264e, 0x264f,
+ 0x2650, 0x2651, 0x2652, 0x2653,
+ 0x2660, 0x2663, 0x2665, 0x2666,
+ 0x2668, 0x267f, 0x26a0, 0x26a1,
+ 0x26bd, 0x26be, 0x26c4, 0x26ce,
+ 0x26ea, 0x26f2, 0x26f3, 0x26f5,
+ 0x26fa, 0x26fd, 0x2702, 0x2708,
+ 0x270a, 0x270b, 0x270c, 0x2728,
+ 0x2733, 0x2734, 0x274c, 0x2753,
+ 0x2754, 0x2755, 0x2757, 0x2764,
+ 0x27a1, 0x27bf, 0x2b05, 0x2b06,
+ 0x2b07, 0x2b50, 0x2b55, 0x303d,
+ 0x3297, 0x3299, };
+
+static const unsigned short mb_tbl_uni_sb2code2_value[] = { // 0x2122 - 0x3299
+ 0x2b2e, 0x283e, 0x283d, 0x283f,
+ 0x2840, 0x2843, 0x2844, 0x2841,
+ 0x2842, 0x296a, 0x2969, 0x2929,
+ 0x296b, 0x2965, 0x292f, 0x2aac,
+ 0x2846, 0x2847, 0x2848, 0x2849,
+ 0x284a, 0x284b, 0x284c, 0x284d,
+ 0x284e, 0x284f, 0x2850, 0x2851,
+ 0x2815, 0x2816, 0x2813, 0x2814,
+ 0x27cb, 0x2811, 0x2859, 0x27e5,
+ 0x2938, 0x2936, 0x2968, 0x2852,
+ 0x2957, 0x27c9, 0x2934, 0x293c,
+ 0x27ca, 0x295a, 0x2992, 0x293d,
+ 0x2930, 0x2932, 0x2931, 0x29ad,
+ 0x280d, 0x280c, 0x29b2, 0x2940,
+ 0x29b5, 0x29b6, 0x2941, 0x2942,
+ 0x283b, 0x2818, 0x283c, 0x2839,
+ 0x283a, 0x29ae, 0x29b1, 0x27d4,
+ 0x298c, 0x2994, };
+
+static const int mb_tbl_uni_sb2code2_len = sizeof(mb_tbl_uni_sb2code2_key)/sizeof(unsigned short);
+
+static const int mb_tbl_uni_sb2code3_min = 0x1f004;
+static const int mb_tbl_uni_sb2code3_max = 0x1f6c0;
+
+static const unsigned short mb_tbl_uni_sb2code3_key[] = { // 0x1f004 - 0x1f6c0
+ 0xf004, 0xf170, 0xf171, 0xf17e,
+ 0xf17f, 0xf18e, 0xf192, 0xf194,
+ 0xf195, 0xf197, 0xf199, 0xf19a,
+ 0xf1e8, 0xf1e9, 0xf1ea, 0xf1eb,
+ 0xf1ec, 0xf1ee, 0xf1ef, 0xf1f0,
+ 0xf1f7, 0xf1fa, 0xf201, 0xf202,
+ 0xf21a, 0xf22f, 0xf233, 0xf235,
+ 0xf236, 0xf237, 0xf238, 0xf239,
+ 0xf23a, 0xf250, 0xf300, 0xf302,
+ 0xf303, 0xf304, 0xf305, 0xf306,
+ 0xf307, 0xf308, 0xf30a, 0xf319,
+ 0xf31f, 0xf334, 0xf335, 0xf337,
+ 0xf338, 0xf339, 0xf33a, 0xf33b,
+ 0xf33e, 0xf340, 0xf341, 0xf342,
+ 0xf343, 0xf345, 0xf346, 0xf349,
+ 0xf34a, 0xf34e, 0xf353, 0xf354,
+ 0xf358, 0xf359, 0xf35a, 0xf35b,
+ 0xf35c, 0xf35d, 0xf35e, 0xf35f,
+ 0xf361, 0xf362, 0xf363, 0xf366,
+ 0xf367, 0xf370, 0xf371, 0xf372,
+ 0xf373, 0xf374, 0xf375, 0xf376,
+ 0xf378, 0xf37a, 0xf37b, 0xf380,
+ 0xf381, 0xf382, 0xf383, 0xf384,
+ 0xf385, 0xf386, 0xf387, 0xf388,
+ 0xf389, 0xf38c, 0xf38d, 0xf38e,
+ 0xf38f, 0xf390, 0xf391, 0xf392,
+ 0xf393, 0xf3a1, 0xf3a2, 0xf3a4,
+ 0xf3a5, 0xf3a6, 0xf3a7, 0xf3a8,
+ 0xf3a9, 0xf3ab, 0xf3ac, 0xf3af,
+ 0xf3b0, 0xf3b1, 0xf3b5, 0xf3b6,
+ 0xf3b7, 0xf3b8, 0xf3ba, 0xf3be,
+ 0xf3bf, 0xf3c0, 0xf3c1, 0xf3c3,
+ 0xf3c4, 0xf3c6, 0xf3c8, 0xf3ca,
+ 0xf3e0, 0xf3e2, 0xf3e3, 0xf3e5,
+ 0xf3e6, 0xf3e7, 0xf3e8, 0xf3e9,
+ 0xf3ea, 0xf3eb, 0xf3ec, 0xf3ed,
+ 0xf3ef, 0xf3f0, 0xf40d, 0xf40e,
+ 0xf411, 0xf412, 0xf414, 0xf417,
+ 0xf418, 0xf419, 0xf41a, 0xf41b,
+ 0xf41f, 0xf420, 0xf424, 0xf426,
+ 0xf427, 0xf428, 0xf42b, 0xf42c,
+ 0xf42d, 0xf42e, 0xf42f, 0xf430,
+ 0xf431, 0xf433, 0xf434, 0xf435,
+ 0xf436, 0xf437, 0xf438, 0xf439,
+ 0xf43a, 0xf43b, 0xf440, 0xf442,
+ 0xf443, 0xf444, 0xf446, 0xf447,
+ 0xf448, 0xf449, 0xf44a, 0xf44b,
+ 0xf44c, 0xf44d, 0xf44e, 0xf44f,
+ 0xf450, 0xf451, 0xf452, 0xf454,
+ 0xf455, 0xf457, 0xf458, 0xf459,
+ 0xf45c, 0xf45f, 0xf460, 0xf461,
+ 0xf462, 0xf463, 0xf466, 0xf467,
+ 0xf468, 0xf469, 0xf46b, 0xf46e,
+ 0xf46f, 0xf471, 0xf472, 0xf473,
+ 0xf474, 0xf475, 0xf476, 0xf477,
+ 0xf478, 0xf47b, 0xf47c, 0xf47d,
+ 0xf47e, 0xf47f, 0xf480, 0xf481,
+ 0xf482, 0xf483, 0xf484, 0xf485,
+ 0xf486, 0xf487, 0xf488, 0xf489,
+ 0xf48a, 0xf48b, 0xf48d, 0xf48e,
+ 0xf48f, 0xf490, 0xf491, 0xf492,
+ 0xf493, 0xf494, 0xf497, 0xf498,
+ 0xf499, 0xf49a, 0xf49b, 0xf49c,
+ 0xf49d, 0xf49f, 0xf4a1, 0xf4a2,
+ 0xf4a3, 0xf4a4, 0xf4a6, 0xf4a8,
+ 0xf4a9, 0xf4aa, 0xf4b0, 0xf4b1,
+ 0xf4b9, 0xf4ba, 0xf4bb, 0xf4bc,
+ 0xf4bd, 0xf4bf, 0xf4c0, 0xf4d6,
+ 0xf4dd, 0xf4e0, 0xf4e1, 0xf4e2,
+ 0xf4e3, 0xf4e9, 0xf4eb, 0xf4ee,
+ 0xf4f1, 0xf4f2, 0xf4f3, 0xf4f4,
+ 0xf4f6, 0xf4f7, 0xf4fa, 0xf4fb,
+ 0xf4fc, 0xf50a, 0xf50d, 0xf511,
+ 0xf512, 0xf513, 0xf514, 0xf51d,
+ 0xf51e, 0xf525, 0xf528, 0xf52b,
+ 0xf52f, 0xf530, 0xf531, 0xf532,
+ 0xf533, 0xf534, 0xf550, 0xf551,
+ 0xf552, 0xf553, 0xf554, 0xf555,
+ 0xf556, 0xf557, 0xf558, 0xf559,
+ 0xf55a, 0xf55b, 0xf5fb, 0xf5fc,
+ 0xf5fd, 0xf601, 0xf602, 0xf603,
+ 0xf604, 0xf609, 0xf60a, 0xf60c,
+ 0xf60d, 0xf60f, 0xf612, 0xf613,
+ 0xf614, 0xf616, 0xf618, 0xf61a,
+ 0xf61c, 0xf61d, 0xf61e, 0xf620,
+ 0xf621, 0xf622, 0xf623, 0xf625,
+ 0xf628, 0xf62a, 0xf62d, 0xf630,
+ 0xf631, 0xf632, 0xf633, 0xf637,
+ 0xf645, 0xf646, 0xf647, 0xf64c,
+ 0xf64f, 0xf680, 0xf683, 0xf684,
+ 0xf685, 0xf687, 0xf689, 0xf68c,
+ 0xf68f, 0xf691, 0xf692, 0xf693,
+ 0xf695, 0xf697, 0xf699, 0xf69a,
+ 0xf6a2, 0xf6a4, 0xf6a5, 0xf6a7,
+ 0xf6ac, 0xf6ad, 0xf6b2, 0xf6b6,
+ 0xf6b9, 0xf6ba, 0xf6bb, 0xf6bc,
+ 0xf6bd, 0xf6be, 0xf6c0, };
+
+static const unsigned short mb_tbl_uni_sb2code3_value[] = { // 0x1f004 - 0x1f6c0
+ 0x27d5, 0x2b29, 0x2b2a, 0x2b2c,
+ 0x27f7, 0x2b2b, 0x281b, 0x2830,
+ 0x2819, 0x2854, 0x281a, 0x27d6,
+ 0x2b0a, 0x2b05, 0x2b08, 0x2b04,
+ 0x2b07, 0x2b06, 0x2b02, 0x2b0b,
+ 0x2b09, 0x2b03, 0x280a, 0x282f,
+ 0x281d, 0x2833, 0x2832, 0x2831,
+ 0x281c, 0x281e, 0x281f, 0x282e,
+ 0x2834, 0x282d, 0x2adb, 0x2ad4,
+ 0x2ae3, 0x296d, 0x2ae1, 0x27ee,
+ 0x2ae2, 0x2ae4, 0x2ad6, 0x296c,
+ 0x29b4, 0x2986, 0x2987, 0x2983,
+ 0x2950, 0x2952, 0x2982, 0x2984,
+ 0x2adc, 0x27b8, 0x27c0, 0x27c1,
+ 0x2adf, 0x29c8, 0x29c9, 0x29c7,
+ 0x29c5, 0x29c4, 0x29c6, 0x27c8,
+ 0x29bc, 0x29c1, 0x29bd, 0x29c0,
+ 0x29bf, 0x29be, 0x29b8, 0x29ba,
+ 0x29bb, 0x29c2, 0x29c3, 0x29b9,
+ 0x2ad7, 0x2966, 0x29cb, 0x29cc,
+ 0x27ef, 0x2963, 0x29b7, 0x298a,
+ 0x2964, 0x2967, 0x298b, 0x2993,
+ 0x27ba, 0x29ca, 0x2add, 0x2953,
+ 0x2ae0, 0x27bf, 0x2ad8, 0x298f,
+ 0x2991, 0x27eb, 0x2ace, 0x2ad0,
+ 0x2ad3, 0x2ada, 0x2ade, 0x2ad2,
+ 0x2ad1, 0x27cc, 0x2acb, 0x295c,
+ 0x295d, 0x2afe, 0x2989, 0x2af9,
+ 0x2afa, 0x27cd, 0x29a3, 0x27d8,
+ 0x27db, 0x2ac4, 0x295e, 0x29a5,
+ 0x2960, 0x2961, 0x2962, 0x2935,
+ 0x2933, 0x2ac2, 0x27da, 0x27bd,
+ 0x2937, 0x27d9, 0x2ac3, 0x2ac5,
+ 0x2956, 0x2958, 0x27fb, 0x27fd,
+ 0x27f5, 0x27fc, 0x2800, 0x2af8,
+ 0x27fe, 0x27ff, 0x2afb, 0x2aff,
+ 0x2afc, 0x2afd, 0x2b24, 0x27dc,
+ 0x2b20, 0x2b1f, 0x2b25, 0x2b26,
+ 0x2b1d, 0x27b2, 0x2ad9, 0x2b1c,
+ 0x2939, 0x2b19, 0x2b1a, 0x2b18,
+ 0x2975, 0x2b1e, 0x2b27, 0x2b17,
+ 0x2973, 0x2b22, 0x2970, 0x2b23,
+ 0x296f, 0x2974, 0x293a, 0x27b1,
+ 0x2972, 0x27b3, 0x2b28, 0x2b1b,
+ 0x2b21, 0x2971, 0x2ab1, 0x2ab3,
+ 0x2ab2, 0x2ab4, 0x2835, 0x2836,
+ 0x2837, 0x2838, 0x292d, 0x2ab6,
+ 0x2ab8, 0x292e, 0x2ab9, 0x2ab7,
+ 0x2aba, 0x27b6, 0x2997, 0x2981,
+ 0x2926, 0x2998, 0x29a0, 0x29a1,
+ 0x29a2, 0x2927, 0x27e6, 0x2999,
+ 0x299a, 0x2b2d, 0x2921, 0x2922,
+ 0x2924, 0x2925, 0x2ac0, 0x27fa,
+ 0x2ac1, 0x2b0c, 0x2b0d, 0x2b0e,
+ 0x2b0f, 0x2b10, 0x2b11, 0x2b12,
+ 0x2b13, 0x27c3, 0x296e, 0x27b4,
+ 0x27d3, 0x27c2, 0x27c4, 0x285a,
+ 0x2b15, 0x2b16, 0x299b, 0x299c,
+ 0x299d, 0x299e, 0x299f, 0x27e3,
+ 0x298e, 0x2923, 0x2954, 0x2955,
+ 0x27b9, 0x2985, 0x2abd, 0x2ad5,
+ 0x29a6, 0x2943, 0x29a7, 0x29a8,
+ 0x29a9, 0x29aa, 0x29ab, 0x29ac,
+ 0x2acf, 0x280b, 0x27b7, 0x29b3,
+ 0x2990, 0x27e4, 0x29b0, 0x29af,
+ 0x297a, 0x27f4, 0x27d7, 0x27f1,
+ 0x27f2, 0x27c7, 0x292c, 0x27c6,
+ 0x2995, 0x27ce, 0x27cf, 0x27f0,
+ 0x2980, 0x292b, 0x27f3, 0x27ea,
+ 0x2996, 0x27ab, 0x27a9, 0x27aa,
+ 0x292a, 0x27ac, 0x2857, 0x2858,
+ 0x2812, 0x2928, 0x27d2, 0x27d0,
+ 0x27d1, 0x27e9, 0x27bc, 0x295f,
+ 0x27ec, 0x27ed, 0x29a4, 0x2853,
+ 0x280e, 0x27c5, 0x27be, 0x27bb,
+ 0x2845, 0x2810, 0x2951, 0x2821,
+ 0x2822, 0x2820, 0x2944, 0x2945,
+ 0x2946, 0x2947, 0x2948, 0x2949,
+ 0x294a, 0x294b, 0x294c, 0x294d,
+ 0x294e, 0x294f, 0x295b, 0x2b00,
+ 0x2b14, 0x2a9c, 0x2aaa, 0x2977,
+ 0x2aad, 0x2a9d, 0x2976, 0x2aa2,
+ 0x27ae, 0x2a9a, 0x2aa6, 0x27b0,
+ 0x2a9b, 0x2a9f, 0x2ab0, 0x2aaf,
+ 0x27ad, 0x2aa1, 0x2978, 0x2979,
+ 0x2aae, 0x2aab, 0x2a9e, 0x2a99,
+ 0x2aa3, 0x2aa0, 0x2aa9, 0x2aa7,
+ 0x27af, 0x2aa8, 0x2aa5, 0x2aa4,
+ 0x2abb, 0x2abc, 0x2abe, 0x2abf,
+ 0x2ab5, 0x27b5, 0x293e, 0x2acd,
+ 0x293f, 0x2acc, 0x2959, 0x2801,
+ 0x27f8, 0x2ac9, 0x2ac8, 0x2aca,
+ 0x2802, 0x293b, 0x2ac6, 0x2ac7,
+ 0x2809, 0x27dd, 0x27f6, 0x27df,
+ 0x298d, 0x280f, 0x27de, 0x2808,
+ 0x27e0, 0x27e1, 0x27f9, 0x27e2,
+ 0x27e8, 0x2988, 0x27e7, };
+
+static const int mb_tbl_uni_sb2code3_len = sizeof(mb_tbl_uni_sb2code3_key)/sizeof(unsigned short);
+
+/* unsupported in Unicode 6.0 */
+
+static const int mb_tbl_uni_docomo2code5_min = 0xfe82d;
+static const int mb_tbl_uni_docomo2code5_max = 0xfee33;
+
+static const unsigned short mb_tbl_uni_docomo2code5_key[] = { // 0xfe82d - 0xfee33
+ 0xE82D, 0xEE10, 0xEE11, 0xEE12,
+ 0xEE13, 0xEE14, 0xEE15, 0xEE16,
+ 0xEE17, 0xEE18, 0xEE19, 0xEE1A,
+ 0xEE1B, 0xEE1C, 0xEE1D, 0xEE1E,
+ 0xEE1F, 0xEE20, 0xEE21, 0xEE22,
+ 0xEE23, 0xEE24, 0xEE25, 0xEE26,
+ 0xEE27, 0xEE28, 0xEE29, 0xEE2A,
+ 0xEE2B, 0xEE2C, 0xEE2D, 0xEE2E,
+ 0xEE2F, 0xEE30, 0xEE31, 0xEE32,
+ 0xEE33, };
+
+static const unsigned short mb_tbl_uni_docomo2code5_val[] = { // 0xfe82d - 0xfee33
+ 0x2965, 0x2955, 0x2956, 0x2958,
+ 0x2959, 0x2990, 0x2991, 0x292A,
+ 0x292B, 0x292C, 0x292D, 0x292E,
+ 0x292F, 0x2933, 0x2934, 0x2938,
+ 0x2939, 0x293A, 0x293F, 0x2940,
+ 0x2941, 0x2942, 0x2943, 0x2944,
+ 0x2945, 0x2946, 0x2947, 0x2948,
+ 0x2949, 0x294A, 0x294B, 0x294C,
+ 0x294D, 0x294E, 0x294F, 0x2950,
+ 0x2951, };
+
+static const unsigned short mb_tbl_uni_docomo2code5_len = sizeof(mb_tbl_uni_docomo2code5_key)/sizeof(unsigned short);
+
+
+static const int mb_tbl_uni_kddi2code5_min = 0xfe82d;
+static const int mb_tbl_uni_kddi2code5_max = 0xfee4a;
+
+static const unsigned short mb_tbl_uni_kddi2code5_key[] = { // 0xfe82d - 0xfee4a
+ 0xE82D, 0xE83C, 0xEB89, 0xEE40,
+ 0xEE41, 0xEE42, 0xEE43, 0xEE44,
+ 0xEE45, 0xEE46, 0xEE47, 0xEE48,
+ 0xEE49, 0xEE4A, };
+
+static const unsigned short mb_tbl_uni_kddi2code5_val[] = { // 0xfe82d - 0xfee4a
+ 0x27B0, 0x280A, 0x2839, 0x27FB,
+ 0x2836, 0x24E8, 0x25AC, 0x25B9,
+ 0x25C1, 0x25C2, 0x25C3, 0x25C4,
+ 0x25C5, 0x25C6, };
+
+static const unsigned short mb_tbl_uni_kddi2code5_len = sizeof(mb_tbl_uni_kddi2code5_key)/sizeof(unsigned short);
+
+
+static const int mb_tbl_uni_sb2code5_min = 0xfe4c5;
+static const int mb_tbl_uni_sb2code5_max = 0xfee7d;
+
+static const unsigned short mb_tbl_uni_sb2code5_key[] = { // 0xfe4c5 - 0xfee7d
+ 0xE4C5, 0xEE70, 0xEE71, 0xEE72,
+ 0xEE73, 0xEE74, 0xEE75, 0xEE76,
+ 0xEE77, 0xEE78, 0xEE79, 0xEE7A,
+ 0xEE7B, 0xEE7C, 0xEE7D, };
+
+static const unsigned short mb_tbl_uni_sb2code5_val[] = { // 0xfe4c5 - 0xfee7d
+ 0x2B01, 0x2B2F, 0x2B30, 0x2B31,
+ 0x2B32, 0x2B33, 0x2B34, 0x2B35,
+ 0x285B, 0x285C, 0x285D, 0x285E,
+ 0x285F, 0x2860, 0x2861, };
+
+static const unsigned short mb_tbl_uni_sb2code5_len = sizeof(mb_tbl_uni_sb2code5_key)/sizeof(unsigned short);
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_ascii.c b/ext/mbstring/libmbfl/filters/mbfilter_ascii.c
index 34366db6c0..77871fb96d 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_ascii.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_ascii.c
@@ -37,7 +37,7 @@
static int mbfl_filt_ident_ascii(int c, mbfl_identify_filter *filter);
-static const char *mbfl_encoding_ascii_aliases[] = {"ANSI_X3.4-1968", "iso-ir-6", "ANSI_X3.4-1986", "ISO_646.irv:1991", "US-ASCII", "ISO646-US", "us", "IBM367", "cp367", "csASCII", NULL};
+static const char *mbfl_encoding_ascii_aliases[] = {"ANSI_X3.4-1968", "iso-ir-6", "ANSI_X3.4-1986", "ISO_646.irv:1991", "US-ASCII", "ISO646-US", "us", "IBM367", "IBM-367", "cp367", "csASCII", NULL};
const mbfl_encoding mbfl_encoding_ascii = {
mbfl_no_encoding_ascii,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_base64.c b/ext/mbstring/libmbfl/filters/mbfilter_base64.c
index 13341f9e9f..198f38c3d2 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_base64.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_base64.c
@@ -41,7 +41,7 @@ const mbfl_encoding mbfl_encoding_base64 = {
"BASE64",
NULL,
NULL,
- MBFL_ENCTYPE_SBCS
+ MBFL_ENCTYPE_ENC_STRM | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_convert_vtbl vtbl_8bit_b64 = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_big5.c b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
index fe5effe044..099f8e6af0 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_big5.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
@@ -57,7 +57,7 @@ static const unsigned char mblen_table_big5[] = { /* 0x81-0xFE */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1
};
-static const char *mbfl_encoding_big5_aliases[] = {"CN-BIG5", "BIG-FIVE", "BIGFIVE", "CP950", NULL};
+static const char *mbfl_encoding_big5_aliases[] = {"CN-BIG5", "BIG-FIVE", "BIGFIVE", NULL};
const mbfl_encoding mbfl_encoding_big5 = {
mbfl_no_encoding_big5,
@@ -65,7 +65,16 @@ const mbfl_encoding mbfl_encoding_big5 = {
"BIG5",
(const char *(*)[])&mbfl_encoding_big5_aliases,
mblen_table_big5,
- MBFL_ENCTYPE_MBCS
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const mbfl_encoding mbfl_encoding_cp950 = {
+ mbfl_no_encoding_cp950,
+ "CP950",
+ "BIG5",
+ NULL,
+ mblen_table_big5,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_big5 = {
@@ -75,6 +84,13 @@ const struct mbfl_identify_vtbl vtbl_identify_big5 = {
mbfl_filt_ident_big5
};
+const struct mbfl_identify_vtbl vtbl_identify_cp950 = {
+ mbfl_no_encoding_cp950,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_big5
+};
+
const struct mbfl_convert_vtbl vtbl_big5_wchar = {
mbfl_no_encoding_big5,
mbfl_no_encoding_wchar,
@@ -93,21 +109,57 @@ const struct mbfl_convert_vtbl vtbl_wchar_big5 = {
mbfl_filt_conv_common_flush
};
+const struct mbfl_convert_vtbl vtbl_cp950_wchar = {
+ mbfl_no_encoding_cp950,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_big5_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_cp950 = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_cp950,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_big5,
+ mbfl_filt_conv_common_flush
+};
+
#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+/* 63 + 94 = 157 or 94 */
+static unsigned short cp950_pua_tbl[][4] = {
+ {0xe000,0xe310,0xfa40,0xfefe},
+ {0xe311,0xeeb7,0x8e40,0xa0fe},
+ {0xeeb8,0xf6b0,0x8140,0x8dfe},
+ {0xf6b1,0xf70e,0xc6a1,0xc6fe},
+ {0xf70f,0xf848,0xc740,0xc8fe},
+};
+
/*
* Big5 => wchar
*/
int
mbfl_filt_conv_big5_wchar(int c, mbfl_convert_filter *filter)
{
- int c1, w;
+ int k;
+ int c1, w, c2;
switch (filter->status) {
case 0:
- if (c >= 0 && c < 0x80) { /* latin */
+ if (filter->from->no_encoding == mbfl_no_encoding_cp950) {
+ c1 = 0x80;
+ } else {
+ c1 = 0xa0;
+ }
+
+ if (c >= 0 && c <= 0x80) { /* latin */
CK((*filter->output_function)(c, filter->data));
- } else if (c > 0xa0 && c < 0xff) { /* dbcs lead byte */
+ } else if (c == 0xff) {
+ CK((*filter->output_function)(0xf8f8, filter->data));
+ } else if (c > c1 && c < 0xff) { /* dbcs lead byte */
filter->status = 1;
filter->cache = c;
} else {
@@ -131,6 +183,30 @@ mbfl_filt_conv_big5_wchar(int c, mbfl_convert_filter *filter)
} else {
w = 0;
}
+
+ if (filter->from->no_encoding == mbfl_no_encoding_cp950) {
+ /* PUA for CP950 */
+ if (w <= 0 &&
+ (((c1 >= 0xfa && c1 <= 0xfe) || (c1 >= 0x8e && c1 <= 0xa0) ||
+ (c1 >= 0x81 && c1 <= 0x8d) ||(c1 >= 0xc7 && c1 <= 0xc8))
+ && ((c > 0x39 && c < 0x7f) || (c > 0xa0 && c < 0xff))) ||
+ ((c1 == 0xc6) && (c > 0xa0 && c < 0xff))) {
+ c2 = c1 << 8 | c;
+ for (k = 0; k < sizeof(cp950_pua_tbl)/(sizeof(unsigned short)*4); k++) {
+ if (c2 >= cp950_pua_tbl[k][2] && c2 <= cp950_pua_tbl[k][3]) {
+ break;
+ }
+ }
+
+ if ((cp950_pua_tbl[k][2] & 0xff) == 0x40) {
+ w = 157*(c1 - (cp950_pua_tbl[k][2]>>8)) + c - (c >= 0xa1 ? 0x62 : 0x40)
+ + cp950_pua_tbl[k][0];
+ } else {
+ w = c2 - cp950_pua_tbl[k][2] + cp950_pua_tbl[k][0];
+ }
+ }
+ }
+
if (w <= 0) {
w = (c1 << 8) | c;
w &= MBFL_WCSPLANE_MASK;
@@ -161,7 +237,8 @@ mbfl_filt_conv_big5_wchar(int c, mbfl_convert_filter *filter)
int
mbfl_filt_conv_wchar_big5(int c, mbfl_convert_filter *filter)
{
- int c1, s;
+ int k;
+ int c1, s, c2;
s = 0;
if (c >= ucs_a1_big5_table_min && c < ucs_a1_big5_table_max) {
@@ -179,6 +256,39 @@ mbfl_filt_conv_wchar_big5(int c, mbfl_convert_filter *filter)
} else if (c >= ucs_r2_big5_table_min && c < ucs_r2_big5_table_max) {
s = ucs_r2_big5_table[c - ucs_r2_big5_table_min];
}
+
+ if (filter->to->no_encoding == mbfl_no_encoding_cp950) {
+ if (c >= 0xe000 && c <= 0xf848) { /* PUA for CP950 */
+ for (k = 0; k < sizeof(cp950_pua_tbl)/(sizeof(unsigned short)*4); k++) {
+ if (c <= cp950_pua_tbl[k][1]) {
+ break;
+ }
+ }
+ c1 = c - cp950_pua_tbl[k][0];
+ if ((cp950_pua_tbl[k][2] & 0xff) == 0x40) {
+ c2 = cp950_pua_tbl[k][2] >> 8;
+ s = ((c1 / 157) + c2) << 8; c1 %= 157;
+ s |= c1 + (c1 >= 0x3f ? 0x62 : 0x40);
+ } else {
+ s = c1 + cp950_pua_tbl[k][2];
+ }
+ }
+
+ if (c == 0x80) {
+ s = 0x80;
+ } else if (c == 0xf8f8) {
+ s = 0xff;
+ } else if (c == 0x256d) {
+ s = 0xa27e;
+ } else if (c == 0x256e) {
+ s = 0xa2a1;
+ } else if (c == 0x256f) {
+ s = 0xa2a3;
+ } else if (c == 0x2570) {
+ s = 0xa2a2;
+ }
+ }
+
if (s <= 0) {
c1 = c & ~MBFL_WCSPLANE_MASK;
if (c1 == MBFL_WCSPLANE_BIG5) {
@@ -191,7 +301,7 @@ mbfl_filt_conv_wchar_big5(int c, mbfl_convert_filter *filter)
}
}
if (s >= 0) {
- if (s < 0x80) { /* latin */
+ if (s <= 0x80 || s == 0xff) { /* latin */
CK((*filter->output_function)(s, filter->data));
} else {
CK((*filter->output_function)((s >> 8) & 0xff, filter->data));
@@ -208,6 +318,13 @@ mbfl_filt_conv_wchar_big5(int c, mbfl_convert_filter *filter)
static int mbfl_filt_ident_big5(int c, mbfl_identify_filter *filter)
{
+ int c1;
+ if (filter->encoding->no_encoding == mbfl_no_encoding_cp950) {
+ c1 = 0x80;
+ } else {
+ c1 = 0xa0;
+ }
+
if (filter->status) { /* kanji second char */
if (c < 0x40 || (c > 0x7e && c < 0xa1) ||c > 0xfe) { /* bad */
filter->flag = 1;
@@ -215,7 +332,7 @@ static int mbfl_filt_ident_big5(int c, mbfl_identify_filter *filter)
filter->status = 0;
} else if (c >= 0 && c < 0x80) { /* latin ok */
;
- } else if (c > 0xa0 && c < 0xff) { /* DBCS lead byte */
+ } else if (c > c1 && c < 0xff) { /* DBCS lead byte */
filter->status = 1;
} else { /* bad */
filter->flag = 1;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_big5.h b/ext/mbstring/libmbfl/filters/mbfilter_big5.h
index 6b6a26563b..93d10de61a 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_big5.h
+++ b/ext/mbstring/libmbfl/filters/mbfilter_big5.h
@@ -37,6 +37,11 @@ extern const struct mbfl_identify_vtbl vtbl_identify_big5;
extern const struct mbfl_convert_vtbl vtbl_big5_wchar;
extern const struct mbfl_convert_vtbl vtbl_wchar_big5;
+extern const mbfl_encoding mbfl_encoding_cp950;
+extern const struct mbfl_identify_vtbl vtbl_identify_cp950;
+extern const struct mbfl_convert_vtbl vtbl_cp950_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_cp950;
+
int mbfl_filt_conv_big5_wchar(int c, mbfl_convert_filter *filter);
int mbfl_filt_conv_wchar_big5(int c, mbfl_convert_filter *filter);
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
index 587bff88cf..8d733a9d19 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
@@ -54,7 +54,7 @@ const mbfl_encoding mbfl_encoding_jis_ms = {
"ISO-2022-JP",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const mbfl_encoding mbfl_encoding_cp50220 = {
@@ -63,7 +63,7 @@ const mbfl_encoding mbfl_encoding_cp50220 = {
"ISO-2022-JP",
(const char *(*)[])NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const mbfl_encoding mbfl_encoding_cp50220raw = {
@@ -72,7 +72,7 @@ const mbfl_encoding mbfl_encoding_cp50220raw = {
"ISO-2022-JP",
(const char *(*)[])NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const mbfl_encoding mbfl_encoding_cp50221 = {
@@ -81,7 +81,7 @@ const mbfl_encoding mbfl_encoding_cp50221 = {
"ISO-2022-JP",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const mbfl_encoding mbfl_encoding_cp50222 = {
@@ -90,7 +90,7 @@ const mbfl_encoding mbfl_encoding_cp50222 = {
"ISO-2022-JP",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_jis_ms = {
@@ -250,7 +250,7 @@ retry:
CK((*filter->output_function)(0x203e, filter->data));
} else if (filter->status == 0x20 && c > 0x20 && c < 0x60) { /* kana */
CK((*filter->output_function)(0xff40 + c, filter->data));
- } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x7f) { /* kanji first char */
+ } else if ((filter->status == 0x80 || filter->status == 0x90) && c > 0x20 && c < 0x93) { /* kanji first char */
filter->cache = c;
filter->status += 1;
} else if (c >= 0 && c < 0x80) { /* latin, CTLs */
@@ -282,10 +282,7 @@ retry:
w = cp932ext3_ucs_table[s - cp932ext3_ucs_table_min];
} else if (s >= 94 * 94 && s < 114 * 94) {
/* user-defined => PUA (Microsoft extended) */
- w = (s & 0xff) + ((s >> 8) - 94) * 94 + 0xe000;
- } else if (s >= 212 * 94 && s < 222 * 94) {
- /* user-defined => PUA (G3 85 - 94 Ku) */
- w = (s & 0xff) + ((s >> 8) - 212) * 94 + 0xe000 + 10 * 94;
+ w = s - 94*94 + 0xe000;
} else {
w = 0;
}
@@ -462,7 +459,7 @@ mbfl_filt_conv_wchar_jis_ms(int c, mbfl_convert_filter *filter)
s = 0x224c;
}
}
- if (s <= 0 || s >= 0x8080 && s < 0x10000) {
+ if (s <= 0 || (s >= 0x8080 && s < 0x10000)) {
int i;
s = -1;
@@ -693,7 +690,7 @@ mbfl_filt_conv_wchar_cp50221(int c, mbfl_convert_filter *filter)
s = 0x224c;
}
}
- if (s <= 0 || s >= 0x8080 && s < 0x10000) {
+ if (s <= 0 || (s >= 0x8080 && s < 0x10000)) {
int i;
s = -1;
@@ -841,7 +838,7 @@ mbfl_filt_conv_wchar_cp50222(int c, mbfl_convert_filter *filter)
s = 0x224c;
}
}
- if (s <= 0 || s >= 0x8080 && s < 0x10000) {
+ if (s <= 0 || (s >= 0x8080 && s < 0x10000)) {
int i;
s = -1;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp850.c b/ext/mbstring/libmbfl/filters/mbfilter_cp850.c
index 5388c048b1..9e4696a5a9 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp850.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp850.c
@@ -33,7 +33,7 @@
static int mbfl_filt_ident_cp850(int c, mbfl_identify_filter *filter);
-static const char *mbfl_encoding_cp850_aliases[] = {"CP850", "CP-850", "IBM-850", NULL};
+static const char *mbfl_encoding_cp850_aliases[] = {"CP850", "CP-850", "IBM850", "IBM-850", NULL};
const mbfl_encoding mbfl_encoding_cp850 = {
mbfl_no_encoding_cp850,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp866.c b/ext/mbstring/libmbfl/filters/mbfilter_cp866.c
index 7725d7a266..22e109fe5b 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp866.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp866.c
@@ -37,7 +37,7 @@
static int mbfl_filt_ident_cp866(int c, mbfl_identify_filter *filter);
-static const char *mbfl_encoding_cp866_aliases[] = {"CP866", "CP-866", "IBM-866", NULL};
+static const char *mbfl_encoding_cp866_aliases[] = {"CP866", "CP-866", "IBM866", "IBM-866", NULL};
const mbfl_encoding mbfl_encoding_cp866 = {
mbfl_no_encoding_cp866,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp932.c b/ext/mbstring/libmbfl/filters/mbfilter_cp932.c
index 6e54d53f44..40ba849651 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp932.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp932.c
@@ -66,7 +66,7 @@ const mbfl_encoding mbfl_encoding_cp932 = {
"Shift_JIS",
(const char *(*)[])&mbfl_encoding_cp932_aliases,
mblen_table_sjis,
- MBFL_ENCTYPE_MBCS
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_cp932 = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp936.c b/ext/mbstring/libmbfl/filters/mbfilter_cp936.c
index 561dc3003b..caf26e329b 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp936.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp936.c
@@ -33,7 +33,7 @@
#include "mbfilter.h"
#include "mbfilter_cp936.h"
-
+#define UNICODE_TABLE_CP936_DEF
#include "unicode_table_cp936.h"
static int mbfl_filt_ident_cp936(int c, mbfl_identify_filter *filter);
@@ -65,7 +65,7 @@ const mbfl_encoding mbfl_encoding_cp936 = {
"CP936",
(const char *(*)[])&mbfl_encoding_cp936_aliases,
mblen_table_cp936,
- MBFL_ENCTYPE_MBCS
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_cp936 = {
@@ -102,7 +102,8 @@ const struct mbfl_convert_vtbl vtbl_wchar_cp936 = {
int
mbfl_filt_conv_cp936_wchar(int c, mbfl_convert_filter *filter)
{
- int c1, w;
+ int k;
+ int c1, c2, w = -1;
switch (filter->status) {
case 0:
@@ -110,39 +111,68 @@ mbfl_filt_conv_cp936_wchar(int c, mbfl_convert_filter *filter)
CK((*filter->output_function)(c, filter->data));
} else if (c == 0x80) { /* euro sign */
CK((*filter->output_function)(0x20ac, filter->data));
- } else if (c > 0x80 && c < 0xff) { /* dbcs lead byte */
+ } else if (c < 0xff) { /* dbcs lead byte */
filter->status = 1;
filter->cache = c;
- } else {
- w = c & MBFL_WCSGROUP_MASK;
- w |= MBFL_WCSGROUP_THROUGH;
- CK((*filter->output_function)(w, filter->data));
+ } else { /* 0xff */
+ CK((*filter->output_function)(0xf8f5, filter->data));
}
break;
case 1: /* dbcs second byte */
filter->status = 0;
c1 = filter->cache;
- if ( c1 < 0xff && c1 > 0x80 && c > 0x39 && c < 0xff && c != 0x7f) {
- w = (c1 - 0x81)*192 + (c - 0x40);
- if (w >= 0 && w < cp936_ucs_table_size) {
- w = cp936_ucs_table[w];
- } else {
- w = 0;
+
+ if (((c1 >= 0xaa && c1 <= 0xaf) || (c1 >= 0xf8 && c1 <= 0xfe)) &&
+ (c >= 0xa1 && c <= 0xfe)) {
+ /* UDA part1,2: U+E000-U+E4C5 */
+ w = 94*(c1 >= 0xf8 ? c1 - 0xf2 : c1 - 0xaa) + (c - 0xa1) + 0xe000;
+ CK((*filter->output_function)(w, filter->data));
+ } else if (c1 >= 0xa1 && c1 <= 0xa7 && c >= 0x40 && c < 0xa1 && c != 0x7f) {
+ /* UDA part3 : U+E4C6-U+E765*/
+ w = 96*(c1 - 0xa1) + c - (c >= 0x80 ? 0x41 : 0x40) + 0xe4c6;
+ CK((*filter->output_function)(w, filter->data));
+ }
+
+ c2 = (c1 << 8) | c;
+
+ if (w <= 0 &&
+ ((c2 >= 0xa2ab && c2 <= 0xa9f0 + (0xe80f-0xe801)) ||
+ (c2 >= 0xd7fa && c2 <= 0xd7fa + (0xe814-0xe810)) ||
+ (c2 >= 0xfe50 && c2 <= 0xfe80 + (0xe864-0xe844)))) {
+ for (k = 0; k < mbfl_cp936_pua_tbl_max; k++) {
+ if (c2 >= mbfl_cp936_pua_tbl[k][2] &&
+ c2 <= mbfl_cp936_pua_tbl[k][2] +
+ mbfl_cp936_pua_tbl[k][1] - mbfl_cp936_pua_tbl[k][0]) {
+ w = c2 - mbfl_cp936_pua_tbl[k][2] + mbfl_cp936_pua_tbl[k][0];
+ CK((*filter->output_function)(w, filter->data));
+ break;
+ }
}
- if (w <= 0) {
+ }
+
+ if (w <= 0) {
+ if (c1 < 0xff && c1 > 0x80 && c > 0x39 && c < 0xff && c != 0x7f) {
+ w = (c1 - 0x81)*192 + (c - 0x40);
+ if (w >= 0 && w < cp936_ucs_table_size) {
+ w = cp936_ucs_table[w];
+ } else {
+ w = 0;
+ }
+ if (w <= 0) {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_WINCP936;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
w = (c1 << 8) | c;
- w &= MBFL_WCSPLANE_MASK;
- w |= MBFL_WCSPLANE_WINCP936;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
}
- CK((*filter->output_function)(w, filter->data));
- } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
- CK((*filter->output_function)(c, filter->data));
- } else {
- w = (c1 << 8) | c;
- w &= MBFL_WCSGROUP_MASK;
- w |= MBFL_WCSGROUP_THROUGH;
- CK((*filter->output_function)(w, filter->data));
}
break;
@@ -160,25 +190,75 @@ mbfl_filt_conv_cp936_wchar(int c, mbfl_convert_filter *filter)
int
mbfl_filt_conv_wchar_cp936(int c, mbfl_convert_filter *filter)
{
- int c1, s;
+ int k, k1, k2;
+ int c1, s = 0;
- s = 0;
if (c >= ucs_a1_cp936_table_min && c < ucs_a1_cp936_table_max) {
+ /* U+0000 - U+0451 */
s = ucs_a1_cp936_table[c - ucs_a1_cp936_table_min];
} else if (c >= ucs_a2_cp936_table_min && c < ucs_a2_cp936_table_max) {
- s = ucs_a2_cp936_table[c - ucs_a2_cp936_table_min];
+ /* U+2000 - U+26FF */
+ if (c == 0x203e) {
+ s = 0xa3fe;
+ } else if (c == 0x2218) {
+ s = 0xa1e3;
+ } else if (c == 0x223c) {
+ s = 0xa1ab;
+ } else {
+ s = ucs_a2_cp936_table[c - ucs_a2_cp936_table_min];
+ }
} else if (c >= ucs_a3_cp936_table_min && c < ucs_a3_cp936_table_max) {
+ /* U+2F00 - U+33FF */
s = ucs_a3_cp936_table[c - ucs_a3_cp936_table_min];
} else if (c >= ucs_i_cp936_table_min && c < ucs_i_cp936_table_max) {
+ /* U+4D00-9FFF CJK Unified Ideographs (+ Extension A) */
s = ucs_i_cp936_table[c - ucs_i_cp936_table_min];
+ } else if (c >= 0xe000 && c <= 0xe864) { /* PUA */
+ if (c < 0xe766) {
+ if (c < 0xe4c6) {
+ c1 = c - 0xe000;
+ s = (c1 % 94) + 0xa1; c1 /= 94;
+ s |= (c1 < 0x06 ? c1 + 0xaa : c1 + 0xf2) << 8;
+ } else {
+ c1 = c - 0xe4c6;
+ s = ((c1 / 96) + 0xa1) << 8; c1 %= 96;
+ s |= c1 + (c1 >= 0x3f ? 0x41 : 0x40);
+ }
+ } else {
+ /* U+E766..U+E864 */
+ k1 = 0; k2 = mbfl_cp936_pua_tbl_max;
+ while (k1 < k2) {
+ k = (k1 + k2) >> 1;
+ if (c < mbfl_cp936_pua_tbl[k][0]) {
+ k2 = k;
+ } else if (c > mbfl_cp936_pua_tbl[k][1]) {
+ k1 = k + 1;
+ } else {
+ s = c - mbfl_cp936_pua_tbl[k][0] + mbfl_cp936_pua_tbl[k][2];
+ break;
+ }
+ }
+ }
+ } else if (c == 0xf8f5) {
+ s = 0xff;
} else if (c >= ucs_ci_cp936_table_min && c < ucs_ci_cp936_table_max) {
+ /* U+F900-FA2F CJK Compatibility Ideographs */
s = ucs_ci_cp936_table[c - ucs_ci_cp936_table_min];
} else if (c >= ucs_cf_cp936_table_min && c < ucs_cf_cp936_table_max) {
s = ucs_cf_cp936_table[c - ucs_cf_cp936_table_min];
} else if (c >= ucs_sfv_cp936_table_min && c < ucs_sfv_cp936_table_max) {
- s = ucs_sfv_cp936_table[c - ucs_sfv_cp936_table_min];
- } else if (c >= ucs_hff_cp936_table_min && c < ucs_hff_cp936_table_max) {
- s = ucs_hff_cp936_table[c - ucs_hff_cp936_table_min];
+ s = ucs_sfv_cp936_table[c - ucs_sfv_cp936_table_min]; /* U+FE50-FE6F Small Form Variants */
+ } else if (c >= ucs_hff_cp936_table_min && c < ucs_hff_cp936_table_max) {
+ /* U+FF00-FFFF HW/FW Forms */
+ if (c == 0xff04) {
+ s = 0xa1e7;
+ } else if (c == 0xff5e) {
+ s = 0xa1ab;
+ } else if (c >= 0xff01 && c <= 0xff5d) {
+ s = c - 0xff01 + 0xa3a1;
+ } else if (c >= 0xffe0 && c <= 0xffe5) {
+ s = ucs_hff_s_cp936_table[c-0xffe0];
+ }
}
if (s <= 0) {
c1 = c & ~MBFL_WCSPLANE_MASK;
@@ -192,7 +272,7 @@ mbfl_filt_conv_wchar_cp936(int c, mbfl_convert_filter *filter)
}
}
if (s >= 0) {
- if (s <= 0x80) { /* latin */
+ if (s <= 0x80 || s == 0xff) { /* latin */
CK((*filter->output_function)(s, filter->data));
} else {
CK((*filter->output_function)((s >> 8) & 0xff, filter->data));
@@ -224,5 +304,3 @@ static int mbfl_filt_ident_cp936(int c, mbfl_identify_filter *filter)
return c;
}
-
-
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c
index cc2bcc1cee..f91edf364a 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c
@@ -169,7 +169,15 @@ mbfl_filt_conv_wchar_euccn(int c, mbfl_convert_filter *filter)
} else if (c >= ucs_i_cp936_table_min && c < ucs_i_cp936_table_max) {
s = ucs_i_cp936_table[c - ucs_i_cp936_table_min];
} else if (c >= ucs_hff_cp936_table_min && c < ucs_hff_cp936_table_max) {
- s = ucs_hff_cp936_table[c - ucs_hff_cp936_table_min];
+ if (c == 0xff04) {
+ s = 0xa1e7;
+ } else if (c == 0xff5e) {
+ s = 0xa1ab;
+ } else if (c >= 0xff01 && c <= 0xff5d) {
+ s = c - 0xff01 + 0xa3a1;
+ } else if (c >= 0xffe0 && c <= 0xffe5) {
+ s = ucs_hff_s_cp936_table[c-0xffe0];
+ }
}
c1 = (s >> 8) & 0xff;
c2 = s & 0xff;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c
index f5c9643772..7015df4eae 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c
@@ -37,9 +37,9 @@
#include "unicode_table_cp932_ext.h"
#include "unicode_table_jis.h"
-static int mbfl_filt_ident_eucjp(int c, mbfl_identify_filter *filter);
+int mbfl_filt_ident_eucjp(int c, mbfl_identify_filter *filter);
-static const unsigned char mblen_table_eucjp[] = { /* 0xA1-0xFE */
+const unsigned char mblen_table_eucjp[] = { /* 0xA1-0xFE */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -275,7 +275,7 @@ mbfl_filt_conv_wchar_eucjp(int c, mbfl_convert_filter *filter)
return c;
}
-static int mbfl_filt_ident_eucjp(int c, mbfl_identify_filter *filter)
+int mbfl_filt_ident_eucjp(int c, mbfl_identify_filter *filter)
{
switch (filter->status) {
case 0: /* latin */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c
new file mode 100644
index 0000000000..2905ce8dfa
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c
@@ -0,0 +1,78 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_ja.c
+ * by rui hirokawa <hirokawa@php.net> on 16 aug 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_euc_jp_2004.h"
+#include "mbfilter_sjis_2004.h"
+
+#include "unicode_table_jis2004.h"
+
+extern int mbfl_filt_ident_eucjp(int c, mbfl_identify_filter *filter);
+extern const unsigned char mblen_table_eucjp[];
+
+static const char *mbfl_encoding_eucjp2004_aliases[] = {"EUC_JP-2004", NULL};
+
+const mbfl_encoding mbfl_encoding_eucjp2004 = {
+ mbfl_no_encoding_eucjp2004,
+ "EUC-JP-2004",
+ "EUC-JP",
+ (const char *(*)[])&mbfl_encoding_eucjp2004_aliases,
+ mblen_table_eucjp,
+ MBFL_ENCTYPE_MBCS
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_eucjp2004 = {
+ mbfl_no_encoding_eucjp2004,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_eucjp
+};
+
+const struct mbfl_convert_vtbl vtbl_eucjp2004_wchar = {
+ mbfl_no_encoding_eucjp2004,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_jis2004_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_eucjp2004 = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_eucjp2004,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_jis2004,
+ mbfl_filt_conv_jis2004_flush
+};
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.h b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.h
new file mode 100644
index 0000000000..ce4b60aacc
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.h
@@ -0,0 +1,43 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_ja.h
+ * by rui hirokawa <hirokawa@php.net> on 15 aug 2011.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_EUC_JP_2004_H
+#define MBFL_MBFILTER_EUC_JP_2004_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_eucjp2004;
+extern const struct mbfl_identify_vtbl vtbl_identify_eucjp2004;
+extern const struct mbfl_convert_vtbl vtbl_eucjp2004_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_eucjp2004;
+
+int mbfl_filt_conv_eucjp2004_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_eucjp2004(int c, mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_EUC_JP_2004_H */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c b/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c
new file mode 100644
index 0000000000..f6f12be449
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c
@@ -0,0 +1,473 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * the source code included in this files was separated from mbfilter_cp936.c
+ * by rui hirokawa <hirokawa@php.net> on 11 Aug 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_gb18030.h"
+
+#include "unicode_table_cp936.h"
+#include "unicode_table_gb18030.h"
+
+static int mbfl_filt_ident_gb18030(int c, mbfl_identify_filter *filter);
+
+static const char *mbfl_encoding_gb18030_aliases[] = {"gb-18030", "gb-18030-2000", NULL};
+
+const mbfl_encoding mbfl_encoding_gb18030 = {
+ mbfl_no_encoding_gb18030,
+ "GB18030",
+ "GB18030",
+ (const char *(*)[])&mbfl_encoding_gb18030_aliases,
+ NULL,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_gb18030 = {
+ mbfl_no_encoding_gb18030,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_gb18030
+};
+
+const struct mbfl_convert_vtbl vtbl_gb18030_wchar = {
+ mbfl_no_encoding_gb18030,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_gb18030_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_gb18030 = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_gb18030,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_gb18030,
+ mbfl_filt_conv_common_flush
+};
+
+#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+
+
+int
+mbfl_bisec_srch(int w, const unsigned short *tbl, int n)
+{
+ int k, k1 = 0, k2 = n-1;
+
+ while (k1 < k2) {
+ k = (k1+k2) >> 1;
+ if (w <= tbl[2*k+1]) {
+ k2 = k;
+ } else if (w >= tbl[2*k+2]) {
+ k1 = k + 1;
+ } else {
+ return -1;
+ }
+ }
+ return k1;
+}
+
+int
+mbfl_bisec_srch2(int w, const unsigned short tbl[], int n)
+{
+ int k, k1 = 0, k2 = n;
+
+ if (w == tbl[0]) {
+ return 0;
+ }
+
+ while (k2 - k1 > 1) {
+ k = (k1 + k2) >> 1;
+ if (w < tbl[k]) {
+ k2 = k;
+ } else if (w > tbl[k]) {
+ k1 = k;
+ } else {
+ return k;
+ }
+ }
+ return -1;
+}
+
+/*
+ * GB18030 => wchar
+ */
+int
+mbfl_filt_conv_gb18030_wchar(int c, mbfl_convert_filter *filter)
+{
+ int k;
+ int c1, c2, c3, w = -1;
+
+ switch (filter->status) {
+ case 0:
+ if (c >= 0 && c < 0x80) { /* latin */
+ CK((*filter->output_function)(c, filter->data));
+ } else if (c == 0x80) { /* euro sign */
+ CK((*filter->output_function)(0x20ac, filter->data));
+ } else if (c == 0xff) {
+ CK((*filter->output_function)(0x00ff, filter->data));
+ } else if (c > 0x80 && c < 0xff) { /* dbcs/qbcs lead byte */
+ filter->status = 1;
+ filter->cache = c;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ case 1: /* dbcs/qbcs second byte */
+ c1 = filter->cache;
+ filter->status = 0;
+
+ if (c1 >= 0x81 && c1 <= 0x84 && c >= 0x30 && c <= 0x39) { /* 4 byte range: Unicode BMP */
+ filter->status = 2;
+ filter->cache = (c1 << 8) | c;
+ return c;
+ } else if (c1 >= 0x90 && c1 <= 0xe3 && c >= 0x30 && c <= 0x39) {
+ /* 4 byte range: Unicode 16 planes */
+ filter->status = 2;
+ filter->cache = (c1 << 8) | c;
+ return c;
+ } else if (((c1 >= 0xaa && c1 <= 0xaf) || (c1 >= 0xf8 && c1 <= 0xfe)) &&
+ (c >= 0xa1 && c <= 0xfe)) { /* UDA part1,2: U+E000-U+E4C5 */
+ w = 94*(c1 >= 0xf8 ? c1 - 0xf2 : c1 - 0xaa) + (c - 0xa1) + 0xe000;
+ CK((*filter->output_function)(w, filter->data));
+ } else if (c1 >= 0xa1 && c1 <= 0xa7 && c >= 0x40 && c < 0xa1 && c != 0x7f) {
+ /* UDA part3 : U+E4C6-U+E765*/
+ w = 96*(c1 - 0xa1) + c - (c >= 0x80 ? 0x41 : 0x40) + 0xe4c6;
+ CK((*filter->output_function)(w, filter->data));
+ }
+
+ c2 = (c1 << 8) | c;
+
+ if (w <= 0 &&
+ ((c2 >= 0xa2ab && c2 <= 0xa9f0 + (0xe80f-0xe801)) ||
+ (c2 >= 0xd7fa && c2 <= 0xd7fa + (0xe814-0xe810)) ||
+ (c2 >= 0xfe50 && c2 <= 0xfe80 + (0xe864-0xe844)))) {
+ for (k = 0; k < mbfl_gb18030_pua_tbl_max; k++) {
+ if (c2 >= mbfl_gb18030_pua_tbl[k][2] &&
+ c2 <= mbfl_gb18030_pua_tbl[k][2] + mbfl_gb18030_pua_tbl[k][1]
+ - mbfl_gb18030_pua_tbl[k][0]) {
+ w = c2 - mbfl_gb18030_pua_tbl[k][2] + mbfl_gb18030_pua_tbl[k][0];
+ CK((*filter->output_function)(w, filter->data));
+ break;
+ }
+ }
+ }
+
+ if (w <= 0) {
+ if ((c1 >= 0xa1 && c1 <= 0xa9 && c >= 0xa1 && c <= 0xfe) ||
+ (c1 >= 0xb0 && c1 <= 0xf7 && c >= 0xa1 && c <= 0xfe) ||
+ (c1 >= 0x81 && c1 <= 0xa0 && c >= 0x40 && c <= 0xfe && c != 0x7f) ||
+ (c1 >= 0xaa && c1 <= 0xfe && c >= 0x40 && c <= 0xa0 && c != 0x7f) ||
+ (c1 >= 0xa8 && c1 <= 0xa9 && c >= 0x40 && c <= 0xa0 && c != 0x7f)) {
+ w = (c1 - 0x81)*192 + (c - 0x40);
+ if (w >= 0 && w < cp936_ucs_table_size) {
+ w = cp936_ucs_table[w];
+ } else {
+ w = 0;
+ }
+ if (w <= 0) {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_GB18030;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ }
+ break;
+ case 2: /* qbcs third byte */
+ c1 = (filter->cache >> 8) & 0xff;
+ c2 = filter->cache & 0xff;
+ filter->status = 0;
+ filter->cache = 0;
+ if (((c1 >= 0x81 && c1 <= 0x84) || (c1 >= 0x90 && c1 <= 0xe3)) &&
+ c2 >= 0x30 && c2 <= 0x39 && c >= 0x81 && c <= 0xfe) {
+ filter->cache = (c1 << 16) | (c2 << 8) | c;
+ filter->status = 3;
+ } else {
+ w = (c1 << 16) | (c2 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ case 3: /* qbcs fourth byte */
+ c1 = (filter->cache >> 16) & 0xff;
+ c2 = (filter->cache >> 8) & 0xff;
+ c3 = filter->cache & 0xff;
+ filter->status = 0;
+ filter->cache = 0;
+ if (((c1 >= 0x81 && c1 <= 0x84) || (c1 >= 0x90 && c1 <= 0xe3)) &&
+ c2 >= 0x30 && c2 <= 0x39 && c3 >= 0x81 && c3 <= 0xfe && c >= 0x30 && c <= 0x39) {
+ if (c1 >= 0x90 && c1 <= 0xe3) {
+ w = ((c1 - 0x90)*10 + (c2 - 0x30)*126 + (c3 - 0x81))*10 + (c - 0x30) + 0x10000;
+ } else { /* Unicode BMP */
+ w = (((c1 - 0x81)*10 + (c2 - 0x30))*126 + (c3 - 0x81))*10 + (c - 0x30);
+ if (w >= 0 && w <= 39419) {
+ k = mbfl_bisec_srch(w, mbfl_gb2uni_tbl, mbfl_gb_uni_max);
+ if (k<0) {
+ /* error */
+ w = (c1 << 24) | (c2 << 16) | (c3 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ return c;
+ }
+ w += mbfl_gb_uni_ofst[k];
+ } else {
+ w = (c1 << 24) | (c2 << 16) | (c3 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ return c;
+ }
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else {
+ w = (c1 << 24) | (c2 << 16) | (c3 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
+
+/*
+ * wchar => GB18030
+ */
+int
+mbfl_filt_conv_wchar_gb18030(int c, mbfl_convert_filter *filter)
+{
+ int k, k1, k2;
+ int c1, s = 0, s1 = 0;
+
+ if (c >= ucs_a1_cp936_table_min && c < ucs_a1_cp936_table_max) {
+ s = ucs_a1_cp936_table[c - ucs_a1_cp936_table_min];
+ } else if (c >= ucs_a2_cp936_table_min && c < ucs_a2_cp936_table_max) {
+ s = ucs_a2_cp936_table[c - ucs_a2_cp936_table_min];
+ } else if (c >= ucs_a3_cp936_table_min && c < ucs_a3_cp936_table_max) {
+ s = ucs_a3_cp936_table[c - ucs_a3_cp936_table_min];
+ } else if (c >= ucs_i_cp936_table_min && c < ucs_i_cp936_table_max) {
+ s = ucs_i_cp936_table[c - ucs_i_cp936_table_min];
+ } else if (c >= ucs_ci_cp936_table_min && c < ucs_ci_cp936_table_max) {
+ /* U+F900-FA2F CJK Compatibility Ideographs */
+ if (c == 0xf92c) {
+ s = 0xfd9c;
+ } else if (c == 0xf979) {
+ s = 0xfd9d;
+ } else if (c == 0xf995) {
+ s = 0xfd9e;
+ } else if (c == 0xf9e7) {
+ s = 0xfd9f;
+ } else if (c == 0xf9f1) {
+ s = 0xfda0;
+ } else if (c >= 0xfa0c && c <= 0xfa29) {
+ s = ucs_ci_s_cp936_table[c - 0xfa0c];
+ }
+ } else if (c >= ucs_cf_cp936_table_min && c < ucs_cf_cp936_table_max) {
+ /* FE30h CJK Compatibility Forms */
+ s = ucs_cf_cp936_table[c - ucs_cf_cp936_table_min];
+ } else if (c >= ucs_sfv_cp936_table_min && c < ucs_sfv_cp936_table_max) {
+ /* U+FE50-FE6F Small Form Variants */
+ s = ucs_sfv_cp936_table[c - ucs_sfv_cp936_table_min];
+ } else if (c >= ucs_hff_cp936_table_min && c < ucs_hff_cp936_table_max) {
+ /* U+FF00-FFFF HW/FW Forms */
+ if (c == 0xff04) {
+ s = 0xa1e7;
+ } else if (c == 0xff5e) {
+ s = 0xa1ab;
+ } else if (c >= 0xff01 && c <= 0xff5d) {
+ s = c - 0xff01 + 0xa3a1;
+ } else if (c >= 0xffe0 && c <= 0xffe5) {
+ s = ucs_hff_s_cp936_table[c-0xffe0];
+ }
+ }
+
+ if (c == 0x20ac) { /* euro-sign */
+ s = 0xa2e3;
+ }
+
+ if (s <= 0 && c >= mbfl_gb18030_c_tbl_key[0] &&
+ c <= mbfl_gb18030_c_tbl_key[mbfl_gb18030_c_tbl_max-1]) {
+ k1 = mbfl_bisec_srch2(c, mbfl_gb18030_c_tbl_key, mbfl_gb18030_c_tbl_max);
+ if (k1 >= 0) {
+ s = mbfl_gb18030_c_tbl_val[k1];
+ }
+ }
+
+ if (c >= 0xe000 && c <= 0xe864) { /* PUA */
+ if (c < 0xe766) {
+ if (c < 0xe4c6) {
+ c1 = c - 0xe000;
+ s = (c1 % 94) + 0xa1; c1 /= 94;
+ s |= (c1 < 0x06 ? c1 + 0xaa : c1 + 0xf2) << 8;
+ } else {
+ c1 = c - 0xe4c6;
+ s = ((c1 / 96) + 0xa1) << 8; c1 %= 96;
+ s |= c1 + (c1 >= 0x3f ? 0x41 : 0x40);
+ }
+ } else {
+ /* U+E766..U+E864 */
+ k1 = 0; k2 = mbfl_gb18030_pua_tbl_max;
+ while (k1 < k2) {
+ k = (k1 + k2) >> 1;
+ if (c < mbfl_gb18030_pua_tbl[k][0]) {
+ k2 = k;
+ } else if (c > mbfl_gb18030_pua_tbl[k][1]) {
+ k1 = k + 1;
+ } else {
+ s = c - mbfl_gb18030_pua_tbl[k][0] + mbfl_gb18030_pua_tbl[k][2];
+ break;
+ }
+ }
+ }
+ }
+
+ if (s <= 0 && c >= 0x0080 && c <= 0xffff) { /* BMP */
+ s = mbfl_bisec_srch(c, mbfl_uni2gb_tbl, mbfl_gb_uni_max);
+ if (s >= 0) {
+ c1 = c - mbfl_gb_uni_ofst[s];
+ s = (c1 % 10) + 0x30; c1 /= 10;
+ s |= ((c1 % 126) + 0x81) << 8; c1 /= 126;
+ s |= ((c1 % 10) + 0x30) << 16; c1 /= 10;
+ s1 = c1 + 0x81;
+ }
+ } else if (c >= 0x10000 && c <= 0x10ffff) { /* Code set 3: Unicode U+10000..U+10FFFF */
+ c1 = c - 0x10000;
+ s = (c1 % 10) + 0x30; c1 /= 10;
+ s |= ((c1 % 126) + 0x81) << 8; c1 /= 126;
+ s |= ((c1 % 10) + 0x30) << 16; c1 /= 10;
+ s1 = c1 + 0x90;
+ }
+
+ if (s <= 0) {
+ c1 = c & ~MBFL_WCSPLANE_MASK;
+ if (c1 == MBFL_WCSPLANE_WINCP936) {
+ s = c & MBFL_WCSPLANE_MASK;
+ }
+ if (c == 0) {
+ s = 0;
+ } else if (s <= 0) {
+ s = -1;
+ }
+ }
+ if (s >= 0) {
+ if (s <= 0x80) { /* latin */
+ CK((*filter->output_function)(s, filter->data));
+ } else if (s1 > 0) { /* qbcs */
+ CK((*filter->output_function)(s1 & 0xff, filter->data));
+ CK((*filter->output_function)((s >> 16) & 0xff, filter->data));
+ CK((*filter->output_function)((s >> 8) & 0xff, filter->data));
+ CK((*filter->output_function)(s & 0xff, filter->data));
+ } else { /* dbcs */
+ CK((*filter->output_function)((s >> 8) & 0xff, filter->data));
+ CK((*filter->output_function)(s & 0xff, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+
+ return c;
+}
+
+static int mbfl_filt_ident_gb18030(int c, mbfl_identify_filter *filter)
+{
+ int c1;
+
+ c1 = (filter->status >> 8) & 0xff;
+ filter->status &= 0xff;
+
+ if (filter->status == 0) {
+ if (c <= 0x80 || c == 0xff) {
+ filter->status = 0;
+ } else {
+ filter->status = 1;
+ filter->status |= (c << 8);
+ }
+ } else if (filter->status == 1) { /* dbcs/qbcs 2nd byte */
+ if (((c1 >= 0x81 && c1 <= 0x84) || (c1 >= 0x90 && c1 <= 0xe3)) && c >= 0x30 && c <= 0x39) { /* qbcs */
+ filter->status = 2;
+ } else if (((c1 >= 0xaa && c1 <= 0xaf) || (c1 >= 0xf8 && c1 <= 0xfe)) && (c >= 0xa1 && c <= 0xfe)) {
+ filter->status = 0; /* UDA part 1,2 */
+ } else if (c1 >= 0xa1 && c1 <= 0xa7 && c >= 0x40 && c < 0xa1 && c != 0x7f) {
+ filter->status = 0; /* UDA part 3 */
+ } else if ((c1 >= 0xa1 && c1 <= 0xa9 && c >= 0xa1 && c <= 0xfe) ||
+ (c1 >= 0xb0 && c1 <= 0xf7 && c >= 0xa1 && c <= 0xfe) ||
+ (c1 >= 0x81 && c1 <= 0xa0 && c >= 0x40 && c <= 0xfe && c != 0x7f) ||
+ (c1 >= 0xaa && c1 <= 0xfe && c >= 0x40 && c <= 0xa0 && c != 0x7f) ||
+ (c1 >= 0xa8 && c1 <= 0xa9 && c >= 0x40 && c <= 0xa0 && c != 0x7f)) {
+ filter->status = 0; /* DBCS */
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status = 0;
+ }
+ } else if (filter->status == 2) { /* qbcs 3rd byte */
+ if (c > 0x80 && c < 0xff) {
+ filter->status = 3;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status = 0;
+ }
+ } else if (filter->status == 3) { /* qbcs 4th byte */
+ if (c >= 0x30 && c < 0x40) {
+ filter->status = 0;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status = 0;
+ }
+ } else { /* bad */
+ filter->flag = 1;
+ }
+
+ return c;
+}
+
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_gb18030.h b/ext/mbstring/libmbfl/filters/mbfilter_gb18030.h
new file mode 100644
index 0000000000..e182a39555
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_gb18030.h
@@ -0,0 +1,43 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * the source code included in this files was separated from mbfilter_cn.h
+ * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_GB18030_H
+#define MBFL_MBFILTER_GB18030_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_gb18030;
+extern const struct mbfl_identify_vtbl vtbl_identify_gb18030;
+extern const struct mbfl_convert_vtbl vtbl_gb18030_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_gb18030;
+
+int mbfl_filt_conv_gb18030_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_gb18030(int c, mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_GB18030_H */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c b/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c
index 1fe0e6b732..56c364d867 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c
@@ -70,7 +70,7 @@ const mbfl_encoding mbfl_encoding_html_ent = {
"HTML-ENTITIES",
(const char *(*)[])&mbfl_encoding_html_ent_aliases,
NULL,
- MBFL_ENCTYPE_HTML_ENT
+ MBFL_ENCTYPE_ENC_STRM | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_convert_vtbl vtbl_wchar_html = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_hz.c b/ext/mbstring/libmbfl/filters/mbfilter_hz.c
index 7c7eaffc07..893ad5f740 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_hz.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_hz.c
@@ -44,7 +44,7 @@ const mbfl_encoding mbfl_encoding_hz = {
"HZ-GB-2312",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_hz = {
@@ -165,7 +165,15 @@ mbfl_filt_conv_wchar_hz(int c, mbfl_convert_filter *filter)
} else if (c >= ucs_i_cp936_table_min && c < ucs_i_cp936_table_max) {
s = ucs_i_cp936_table[c - ucs_i_cp936_table_min];
} else if (c >= ucs_hff_cp936_table_min && c < ucs_hff_cp936_table_max) {
- s = ucs_hff_cp936_table[c - ucs_hff_cp936_table_min];
+ if (c == 0xff04) {
+ s = 0xa1e7;
+ } else if (c == 0xff5e) {
+ s = 0xa1ab;
+ } else if (c >= 0xff01 && c <= 0xff5d) {
+ s = c - 0xff01 + 0xa3a1;
+ } else if (c >= 0xffe0 && c <= 0xffe5) {
+ s = ucs_hff_s_cp936_table[c-0xffe0];
+ }
}
if (s & 0x8000) {
s -= 0x8080;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c b/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c
index 1bf77172b6..a7daf2b913 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c
@@ -38,7 +38,7 @@
#include "unicode_table_jis.h"
#include "cp932_table.h"
-static int mbfl_filt_ident_2022jpms(int c, mbfl_identify_filter *filter);
+int mbfl_filt_ident_2022jpms(int c, mbfl_identify_filter *filter);
static const char *mbfl_encoding_2022jpms_aliases[] = {"ISO2022JPMS", NULL};
@@ -48,7 +48,7 @@ const mbfl_encoding mbfl_encoding_2022jpms = {
"ISO-2022-JP",
(const char *(*)[])&mbfl_encoding_2022jpms_aliases,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_2022jpms = {
@@ -433,7 +433,7 @@ mbfl_filt_conv_any_2022jpms_flush(mbfl_convert_filter *filter)
return 0;
}
-static int mbfl_filt_ident_2022jpms(int c, mbfl_identify_filter *filter)
+int mbfl_filt_ident_2022jpms(int c, mbfl_identify_filter *filter)
{
retry:
switch (filter->status & 0xf) {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022_kr.c b/ext/mbstring/libmbfl/filters/mbfilter_iso2022_kr.c
index 77c95c5ad2..01c01a4477 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso2022_kr.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022_kr.c
@@ -43,7 +43,7 @@ const mbfl_encoding mbfl_encoding_2022kr = {
"ISO-2022-KR",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_2022kr = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.c b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.c
new file mode 100644
index 0000000000..d855374bf0
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.c
@@ -0,0 +1,168 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_jis.c
+ * by rui hirokawa <hirokawa@php.net> on 18 aug 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_iso2022jp_2004.h"
+#include "mbfilter_sjis_2004.h"
+
+#include "unicode_table_jis2004.h"
+#include "unicode_table_jis.h"
+
+extern int mbfl_filt_conv_any_jis_flush(mbfl_convert_filter *filter);
+static int mbfl_filt_ident_2022jp_2004(int c, mbfl_identify_filter *filter);
+
+const mbfl_encoding mbfl_encoding_2022jp_2004 = {
+ mbfl_no_encoding_2022jp_2004,
+ "ISO-2022-JP-2004",
+ "ISO-2022-JP-2004",
+ NULL,
+ NULL,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_2022jp_2004 = {
+ mbfl_no_encoding_2022jp_2004,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_2022jp_2004
+};
+
+const struct mbfl_convert_vtbl vtbl_2022jp_2004_wchar = {
+ mbfl_no_encoding_2022jp_2004,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_jis2004_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_2022jp_2004 = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_2022jp_2004,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_jis2004,
+ mbfl_filt_conv_jis2004_flush
+};
+
+static int mbfl_filt_ident_2022jp_2004(int c, mbfl_identify_filter *filter)
+{
+retry:
+ switch (filter->status & 0xf) {
+/* case 0x00: ASCII */
+/* case 0x80: X 0212 */
+/* case 0x90: X 0213 plane 1 */
+/* case 0xa0: X 0213 plane 2 */
+ case 0:
+ if (c == 0x1b) {
+ filter->status += 2;
+ } else if (filter->status == 0x80 && c > 0x20 && c < 0x7f) { /* kanji first char */
+ filter->status += 1;
+ } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
+ ;
+ } else {
+ filter->flag = 1; /* bad */
+ }
+ break;
+
+/* case 0x81: X 0208 second char */
+ case 1:
+ if (c == 0x1b) {
+ filter->status++;
+ } else {
+ filter->status &= ~0xf;
+ if (c < 0x21 || c > 0x7e) { /* bad */
+ filter->flag = 1;
+ }
+ }
+ break;
+
+ /* ESC */
+ case 2:
+ if (c == 0x24) { /* '$' */
+ filter->status++;
+ } else if (c == 0x28) { /* '(' */
+ filter->status += 3;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status &= ~0xf;
+ goto retry;
+ }
+ break;
+
+ /* ESC $ */
+ case 3:
+ if (c == 0x42) { /* 'B' */
+ filter->status = 0x80;
+ } else if (c == 0x28) { /* '(' */
+ filter->status++;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status &= ~0xf;
+ goto retry;
+ }
+ break;
+
+ /* ESC $ ( */
+ case 4:
+ if (c == 0x51) { /* JIS X 0213 plane 1 */
+ filter->status = 0x90;
+ } else if (c == 0x50) { /* JIS X 0213 plane 2 */
+ filter->status = 0xa0;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status &= ~0xf;
+ goto retry;
+ }
+ break;
+
+ /* ESC ( */
+ case 5:
+ if (c == 0x42) { /* 'B' */
+ filter->status = 0;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status &= ~0xf;
+ goto retry;
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
+
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.h b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.h
new file mode 100644
index 0000000000..f6e56b9b9d
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_2004.h
@@ -0,0 +1,44 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_ja.c
+ * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_2022JP_2004_H
+#define MBFL_MBFILTER_2022JP_2004_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_2022jp_2004;
+extern const struct mbfl_identify_vtbl vtbl_identify_2022jp_2004;
+extern const struct mbfl_convert_vtbl vtbl_2022jp_2004_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_2022jp_2004;
+
+int mbfl_filt_conv_2022jp_2004_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_2022jp_2004(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_any_2022jp_2004_flush(mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_2022JP_2004_H */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c
new file mode 100644
index 0000000000..4deb02960c
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c
@@ -0,0 +1,433 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_iso2022_jp_ms.c
+ * by Rui Hirokawa <hirokawa@php.net> on 25 July 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_iso2022jp_mobile.h"
+#include "mbfilter_sjis_mobile.h"
+
+#include "unicode_table_cp932_ext.h"
+#include "unicode_table_jis.h"
+#include "cp932_table.h"
+
+extern int mbfl_filt_conv_any_jis_flush(mbfl_convert_filter *filter);
+extern int mbfl_filt_ident_2022jpms(int c, mbfl_identify_filter *filter);
+
+static const char *mbfl_encoding_2022jp_kddi_aliases[] = {"ISO-2022-JP-KDDI", NULL};
+
+const mbfl_encoding mbfl_encoding_2022jp_kddi = {
+ mbfl_no_encoding_2022jp_kddi,
+ "ISO-2022-JP-MOBILE#KDDI",
+ "ISO-2022-JP",
+ mbfl_encoding_2022jp_kddi_aliases,
+ NULL,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_2022jp_kddi = {
+ mbfl_no_encoding_2022jp_kddi,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_2022jpms
+};
+
+const struct mbfl_convert_vtbl vtbl_2022jp_kddi_wchar = {
+ mbfl_no_encoding_2022jp_kddi,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_2022jp_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_2022jp_kddi = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_2022jp_kddi,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_2022jp_mobile,
+ mbfl_filt_conv_any_jis_flush
+};
+
+#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+
+#define sjistoidx(c1, c2) \
+ (((c1) > 0x9f) \
+ ? (((c1) - 0xc1) * 188 + (c2) - (((c2) > 0x7e) ? 0x41 : 0x40)) \
+ : (((c1) - 0x81) * 188 + (c2) - (((c2) > 0x7e) ? 0x41 : 0x40)))
+#define idxtojis1(c) (((c) / 94) + 0x21)
+#define idxtojis2(c) (((c) % 94) + 0x21)
+
+#define SJIS_ENCODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ s1--; \
+ s1 >>= 1; \
+ if ((c1) < 0x5f) { \
+ s1 += 0x71; \
+ } else { \
+ s1 += 0xb1; \
+ } \
+ s2 = c2; \
+ if ((c1) & 1) { \
+ if ((c2) < 0x60) { \
+ s2--; \
+ } \
+ s2 += 0x20; \
+ } else { \
+ s2 += 0x7e; \
+ } \
+ } while (0)
+
+#define SJIS_DECODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ if (s1 < 0xa0) { \
+ s1 -= 0x81; \
+ } else { \
+ s1 -= 0xc1; \
+ } \
+ s1 <<= 1; \
+ s1 += 0x21; \
+ s2 = c2; \
+ if (s2 < 0x9f) { \
+ if (s2 < 0x7f) { \
+ s2++; \
+ } \
+ s2 -= 0x20; \
+ } else { \
+ s1++; \
+ s2 -= 0x7e; \
+ } \
+ } while (0)
+
+#define CODE2JIS(c1,c2,s1,s2) \
+ c1 = (s1)/94+0x21; \
+ c2 = (s1)-94*((c1)-0x21)+0x21; \
+ s1 = ((c1) << 8) | (c2); \
+ s2 = 1
+
+/*
+ * ISO-2022-JP-Mobile => wchar
+ */
+int
+mbfl_filt_conv_2022jp_mobile_wchar(int c, mbfl_convert_filter *filter)
+{
+ int c1, s, w, snd;
+
+retry:
+ switch (filter->status & 0xf) {
+/* case 0x00: ASCII */
+/* case 0x10: X 0201 latin */
+/* case 0x20: X 0201 kana */
+/* case 0x80: X 0208 */
+ case 0:
+ if (c == 0x1b) {
+ filter->status += 2;
+ } else if (filter->status == 0x20 && c > 0x20 && c < 0x60) { /* kana */
+ CK((*filter->output_function)(0xff40 + c, filter->data));
+ } else if (filter->status == 0x80 && c > 0x20 && c < 0x80) { /* kanji first char */
+ filter->cache = c;
+ filter->status += 1;
+ } else if (c >= 0 && c < 0x80) { /* latin, CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else if (c > 0xa0 && c < 0xe0) { /* GR kana */
+ CK((*filter->output_function)(0xfec0 + c, filter->data));
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+/* case 0x81: X 0208 second char */
+ case 1:
+ w = 0;
+ filter->status &= ~0xf;
+ c1 = filter->cache;
+ if (c > 0x20 && c < 0x7f) {
+ s = (c1 - 0x21)*94 + c - 0x21;
+
+ if (s <= 137) {
+ if (s == 31) {
+ w = 0xff3c; /* FULLWIDTH REVERSE SOLIDUS */
+ } else if (s == 32) {
+ w = 0xff5e; /* FULLWIDTH TILDE */
+ } else if (s == 33) {
+ w = 0x2225; /* PARALLEL TO */
+ } else if (s == 60) {
+ w = 0xff0d; /* FULLWIDTH HYPHEN-MINUS */
+ } else if (s == 80) {
+ w = 0xffe0; /* FULLWIDTH CENT SIGN */
+ } else if (s == 81) {
+ w = 0xffe1; /* FULLWIDTH POUND SIGN */
+ } else if (s == 137) {
+ w = 0xffe2; /* FULLWIDTH NOT SIGN */
+ }
+ }
+
+ if (w == 0) {
+ if (s >= cp932ext1_ucs_table_min && s < cp932ext1_ucs_table_max) { /* vendor ext1 (13ku) */
+ w = cp932ext1_ucs_table[s - cp932ext1_ucs_table_min];
+ } else if (s >= 0 && s < jisx0208_ucs_table_size) {
+ w = jisx0208_ucs_table[s];
+ } else {
+ w = 0;
+ }
+ }
+
+ if (s >= (84*94) && s < 91*94) {
+ s += 22*94;
+ if (filter->from->no_encoding == mbfl_no_encoding_2022jp_kddi) {
+ w = mbfilter_sjis_emoji_kddi2unicode(s, &snd);
+ }
+ if (w > 0 && snd > 0) {
+ CK((*filter->output_function)(snd, filter->data));
+ }
+ }
+
+ if (w <= 0) {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_JIS0208;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else if (c == 0x1b) {
+ filter->status += 2;
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ /* ESC */
+/* case 0x02: */
+/* case 0x12: */
+/* case 0x22: */
+/* case 0x82: */
+ case 2:
+ if (c == 0x24) { /* '$' */
+ filter->status++;
+ } else if (c == 0x28) { /* '(' */
+ filter->status += 3;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC $ */
+/* case 0x03: */
+/* case 0x13: */
+/* case 0x23: */
+/* case 0x83: */
+ case 3:
+ if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
+ filter->status = 0x80;
+ } else if (c == 0x28) { /* '(' */
+ filter->status++;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC $ ( */
+/* case 0x04: */
+/* case 0x14: */
+/* case 0x24: */
+/* case 0x84: */
+ case 4:
+ if (c == 0x40 || c == 0x42) { /* '@' or 'B' */
+ filter->status = 0x80;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ CK((*filter->output_function)(0x28, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC ( */
+/* case 0x05: */
+/* case 0x15: */
+/* case 0x25: */
+/* case 0x85: */
+ case 5:
+ if (c == 0x42) { /* 'B' */
+ filter->status = 0;
+ } else if (c == 0x4a) { /* 'J' */
+ filter->status = 0;
+ } else if (c == 0x49) { /* 'I' */
+ filter->status = 0x20;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x28, filter->data));
+ goto retry;
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
+
+/*
+ * wchar => ISO-2022-JP-Mobile
+ */
+int
+mbfl_filt_conv_wchar_2022jp_mobile(int c, mbfl_convert_filter *filter)
+{
+ int c1, c2, s1, s2;
+
+ s1 = 0;
+ s2 = 0;
+ if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
+ s1 = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
+ } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
+ s1 = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
+ } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
+ s1 = ucs_i_jis_table[c - ucs_i_jis_table_min];
+ } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
+ s1 = ucs_r_jis_table[c - ucs_r_jis_table_min];
+ } else if (c >= 0xe000 && c < (0xe000 + 20*94)) { /* user (95ku - 114ku) */
+ s1 = c - 0xe000;
+ c1 = s1/94 + 0x7f;
+ c2 = s1%94 + 0x21;
+ s1 = (c1 << 8) | c2;
+ }
+ if (s1 <= 0) {
+ c1 = c & ~MBFL_WCSPLANE_MASK;
+ if (c1 == MBFL_WCSPLANE_WINCP932) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ s2 = 1;
+ } else if (c1 == MBFL_WCSPLANE_JIS0208) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ } else if (c1 == MBFL_WCSPLANE_JIS0212) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ s1 |= 0x8080;
+ } else if (c == 0xa5) { /* YEN SIGN */
+ s1 = 0x216f; /* FULLWIDTH YEN SIGN */
+ } else if (c == 0x203e) { /* OVER LINE */
+ s1 = 0x2131; /* FULLWIDTH MACRON */
+ } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
+ s1 = 0x2140;
+ } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
+ s1 = 0x2141;
+ } else if (c == 0x2225) { /* PARALLEL TO */
+ s1 = 0x2142;
+ } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
+ s1 = 0x215d;
+ } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
+ s1 = 0x2171;
+ } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
+ s1 = 0x2172;
+ } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
+ s1 = 0x224c;
+ }
+ }
+
+ if ((s1 <= 0) || (s1 >= 0xa1a1 && s2 == 0)) { /* not found or X 0212 */
+ s1 = -1;
+ c1 = 0;
+ c2 = cp932ext1_ucs_table_max - cp932ext1_ucs_table_min;
+ while (c1 < c2) { /* CP932 vendor ext1 (13ku) */
+ if (c == cp932ext1_ucs_table[c1]) {
+ s1 = ((c1/94 + 0x2d) << 8) + (c1%94 + 0x21);
+ break;
+ }
+ c1++;
+ }
+ if (c == 0) {
+ s1 = 0;
+ } else if (s1 <= 0) {
+ s1 = -1;
+ }
+ }
+
+ if (filter->to->no_encoding == mbfl_no_encoding_2022jp_kddi &&
+ mbfilter_unicode2sjis_emoji_kddi(c, &s1, filter) > 0) {
+ CODE2JIS(c1,c2,s1,s2);
+ s1 -= 0x1600;
+ }
+
+ if (filter->status == 1 && filter->cache > 0) {
+ return c;
+ }
+
+ if (s1 >= 0) {
+ if (s1 < 0x80) { /* latin */
+ if ((filter->status & 0xff00) != 0) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
+ }
+ CK((*filter->output_function)(s1, filter->data));
+ filter->status = 0;
+ } else if (s1 > 0xa0 && s1 < 0xe0) { /* kana */
+ if ((filter->status & 0xff00) != 0x100) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x49, filter->data)); /* 'I' */
+ }
+ filter->status = 0x100;
+ CK((*filter->output_function)(s1 & 0x7f, filter->data));
+ } else if (s1 < 0x7e7f) { /* X 0208 */
+ if ((filter->status & 0xff00) != 0x200) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x24, filter->data)); /* '$' */
+ CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
+ }
+ filter->status = 0x200;
+ CK((*filter->output_function)((s1 >> 8) & 0xff, filter->data));
+ CK((*filter->output_function)(s1 & 0x7f, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.h b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.h
new file mode 100644
index 0000000000..7ae1da2ddc
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.h
@@ -0,0 +1,43 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_iso2022_jp_ms.h
+ * by Rui Hirokawa <hirokawa@php.net> on 25 July 2011.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_ISO2022_JP_MOBILE_H
+#define MBFL_MBFILTER_ISO2022_JP_MOBILE_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_2022jp_kddi;
+extern const struct mbfl_identify_vtbl vtbl_identify_2022jp_kddi;
+extern const struct mbfl_convert_vtbl vtbl_2022jp_kddi_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_2022jp_kddi;
+
+int mbfl_filt_conv_2022jp_mobile_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_2022jp_mobile(int c, mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_ISO2022_JP_MOBILE_H */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_jis.c b/ext/mbstring/libmbfl/filters/mbfilter_jis.c
index 6b1aef3643..7fa1fd35b9 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_jis.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_jis.c
@@ -46,7 +46,7 @@ const mbfl_encoding mbfl_encoding_jis = {
"ISO-2022-JP",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const mbfl_encoding mbfl_encoding_2022jp = {
@@ -55,7 +55,7 @@ const mbfl_encoding mbfl_encoding_2022jp = {
"ISO-2022-JP",
NULL,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_jis = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_qprint.c b/ext/mbstring/libmbfl/filters/mbfilter_qprint.c
index 188d088ed0..df9752bc3b 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_qprint.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_qprint.c
@@ -43,7 +43,7 @@ const mbfl_encoding mbfl_encoding_qprint = {
"Quoted-Printable",
(const char *(*)[])&mbfl_encoding_qprint_aliases,
NULL,
- MBFL_ENCTYPE_SBCS
+ MBFL_ENCTYPE_ENC_STRM | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_convert_vtbl vtbl_8bit_qprint = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c
index 83ef565927..7c463cd7b1 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c
@@ -34,12 +34,15 @@
#include "mbfilter.h"
#include "mbfilter_sjis.h"
+#define UNICODE_TABLE_CP932_DEF
+#define UNICODE_TABLE_JIS_DEF
+
#include "unicode_table_cp932_ext.h"
#include "unicode_table_jis.h"
-static int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter);
+int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter);
-static const unsigned char mblen_table_sjis[] = { /* 0x80-0x9f,0xE0-0xFF */
+const unsigned char mblen_table_sjis[] = { /* 0x80-0x9f,0xE0-0xFF */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -66,7 +69,7 @@ const mbfl_encoding mbfl_encoding_sjis = {
"Shift_JIS",
(const char *(*)[])&mbfl_encoding_sjis_aliases,
mblen_table_sjis,
- MBFL_ENCTYPE_MBCS
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_sjis = {
@@ -273,7 +276,7 @@ mbfl_filt_conv_wchar_sjis(int c, mbfl_convert_filter *filter)
return c;
}
-static int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter)
+int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter)
{
if (filter->status) { /* kanji second char */
if (c < 0x40 || c > 0xfc || c == 0x7f) { /* bad */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c
new file mode 100644
index 0000000000..4e1838f060
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c
@@ -0,0 +1,725 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_sjis.c
+ * by rui hirokawa <hirokawa@php.net> on 15 aug 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_sjis_2004.h"
+
+#include "unicode_table_jis2004.h"
+#include "unicode_table_jis.h"
+
+extern const unsigned char mblen_table_sjis[];
+
+static int mbfl_filt_ident_sjis2004(int c, mbfl_identify_filter *filter);
+
+extern int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter);
+extern int mbfl_bisec_srch(int w, const unsigned short *tbl, int n);
+extern int mbfl_bisec_srch2(int w, const unsigned short tbl[], int n);
+
+static const char *mbfl_encoding_sjis2004_aliases[] = {"SJIS2004","Shift_JIS-2004", NULL};
+
+const mbfl_encoding mbfl_encoding_sjis2004 = {
+ mbfl_no_encoding_sjis2004,
+ "SJIS-2004",
+ "Shift_JIS",
+ (const char *(*)[])&mbfl_encoding_sjis2004_aliases,
+ mblen_table_sjis,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_sjis2004 = {
+ mbfl_no_encoding_sjis2004,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_sjis
+};
+
+const struct mbfl_convert_vtbl vtbl_sjis2004_wchar = {
+ mbfl_no_encoding_sjis2004,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_jis2004_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_sjis2004 = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_sjis2004,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_jis2004,
+ mbfl_filt_conv_jis2004_flush
+};
+
+#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+
+#define SJIS_ENCODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ s1--; \
+ s1 >>= 1; \
+ if ((c1) < 0x5f) { \
+ s1 += 0x71; \
+ } else { \
+ s1 += 0xb1; \
+ } \
+ s2 = c2; \
+ if ((c1) & 1) { \
+ if ((c2) < 0x60) { \
+ s2--; \
+ } \
+ s2 += 0x20; \
+ } else { \
+ s2 += 0x7e; \
+ } \
+ } while (0)
+
+#define SJIS_DECODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ if (s1 < 0xa0) { \
+ s1 -= 0x81; \
+ } else { \
+ s1 -= 0xc1; \
+ } \
+ s1 <<= 1; \
+ s1 += 0x21; \
+ s2 = c2; \
+ if (s2 < 0x9f) { \
+ if (s2 < 0x7f) { \
+ s2++; \
+ } \
+ s2 -= 0x20; \
+ } else { \
+ s1++; \
+ s2 -= 0x7e; \
+ } \
+ } while (0)
+
+
+/*
+ * JIS-2004 => wchar
+ */
+int
+mbfl_filt_conv_jis2004_wchar(int c, mbfl_convert_filter *filter)
+{
+ int k;
+ int c1, c2, s, s1, s2, w = 0, w1;
+
+retry:
+ switch (filter->status & 0xf) {
+ case 0:
+ if (c >= 0 && c < 0x80) { /* latin */
+ if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
+ CK((*filter->output_function)(c, filter->data));
+ } else if (filter->from->no_encoding == mbfl_no_encoding_sjis2004) {
+ if (c == 0x5c) {
+ CK((*filter->output_function)(0x00a5, filter->data));
+ } else if (c == 0x7e) {
+ CK((*filter->output_function)(0x203e, filter->data));
+ } else {
+ CK((*filter->output_function)(c, filter->data));
+ }
+ } else { /* ISO-2022-JP-2004 */
+ if (c == 0x1b) {
+ filter->status += 6;
+ } else if ((filter->status == 0x80 || filter->status == 0x90 || filter->status == 0xa0)
+ && c > 0x20 && c < 0x7f) { /* kanji first char */
+ filter->cache = c;
+ if (filter->status == 0x90) {
+ filter->status += 1; /* JIS X 0213 plane 1 */
+ } else if (filter->status == 0xa0) {
+ filter->status += 4; /* JIS X 0213 plane 2 */
+ } else {
+ filter->status += 5; /* JIS X 0208 */
+ }
+ } else {
+ CK((*filter->output_function)(c, filter->data));
+ }
+ }
+ } else {
+ if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
+ if (c > 0xa0 && c < 0xff) { /* X 0213 plane 1 first char */
+ filter->status = 1;
+ filter->cache = c;
+ } else if (c == 0x8e) { /* kana first char */
+ filter->status = 2;
+ } else if (c == 0x8f) { /* X 0213 plane 2 first char */
+ filter->status = 3;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ } else if (filter->from->no_encoding == mbfl_no_encoding_sjis2004) {
+ if (c > 0xa0 && c < 0xe0) { /* kana */
+ CK((*filter->output_function)(0xfec0 + c, filter->data));
+ } else if (c > 0x80 && c < 0xfd && c != 0xa0) { /* kanji first char */
+ filter->status = 1;
+ filter->cache = c;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ }
+ break;
+
+ case 1: /* kanji second char */
+ filter->status &= ~0xf;
+ c1 = filter->cache;
+
+ if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
+ if (c > 0xa0 && c < 0xff) {
+ s1 = c1 - 0x80;
+ s2 = c - 0x80;
+ }
+ } else if (filter->from->no_encoding == mbfl_no_encoding_sjis2004) {
+ if (c >= 0x40 && c <= 0xfc && c != 0x7f) {
+ SJIS_DECODE(c1, c, s1, s2);
+ }
+ } else {
+ s1 = c1;
+ s2 = c;
+ }
+ w1 = (s1 << 8) | s2;
+
+ if (w1 >= 0x2121) {
+ /* conversion for combining characters */
+ if ((w1 >= 0x2477 && w1 <= 0x2479) || (w1 >= 0x2479 && w1 <= 0x247B) ||
+ (w1 >= 0x2577 && w1 <= 0x257E) || w1 == 0x2678 || w1 == 0x2B44 ||
+ (w1 >= 0x2B48 && w1 <= 0x2B4F) || (w1 >= 0x2B65 && w1 <= 0x2B66)) {
+ k = mbfl_bisec_srch2(w1, jisx0213_u2_key, jisx0213_u2_tbl_len);
+ if (k >= 0) {
+ w = jisx0213_u2_tbl[2*k];
+ CK((*filter->output_function)(w, filter->data));
+ w = jisx0213_u2_tbl[2*k+1];
+ }
+ }
+
+ /* conversion for BMP */
+ if (w <= 0) {
+ w1 = (s1 - 0x21)*94 + s2 - 0x21;
+ if (w1 >= 0 && w1 < jisx0213_ucs_table_size) {
+ w = jisx0213_ucs_table[w1];
+ }
+ }
+
+ /* conversion for CJK Unified Ideographs ext.B (U+2XXXX) */
+ if (w <= 0) {
+ w1 = (s1 << 8) | s2;
+ k = mbfl_bisec_srch2(w1, jisx0213_jis_u5_key, jisx0213_u5_tbl_len);
+ if (k >= 0) {
+ w = jisx0213_jis_u5_tbl[k] + 0x20000;
+ }
+ }
+
+ if (w <= 0) {
+ if (s1 < 0x7f && s2 < 0x7f) {
+ w = (s1 << 8) | s2;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_JIS0213;
+ } else {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ }
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ case 2: /* got 0x8e : EUC-JP-2004 kana */
+ filter->status = 0;
+ if (c > 0xa0 && c < 0xe0) {
+ w = 0xfec0 + c;
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ w = 0x8e00 | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ case 3: /* X 0213 plane 2 first char : EUC-JP-2004 (0x8f), ISO-2022-JP-2004 */
+ if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ filter->status = 0;
+ } else {
+ if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
+ s1 = c - 0x80;
+ } else {
+ s1 = c;
+ }
+ if (s1 > 0x20 && s1 < 0x80) {
+ filter->cache = s1;
+ filter->status++;
+ } else {
+ if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ w = c | 0x8f00;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ } else {
+ w = c & 0x7f;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_JIS0213;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ }
+ }
+ break;
+
+ case 4: /* X 0213 plane 2 second char : EUC-JP-2004, ISO-2022-JP-2004 */
+
+ filter->status &= ~0xf;
+ c1 = filter->cache;
+ if (filter->from->no_encoding == mbfl_no_encoding_eucjp2004) {
+ c2 = c - 0x80;
+ } else {
+ c2 = c;
+ }
+ s1 = c1 - 0x21;
+ s2 = c2 - 0x21;
+
+ if (((s1 >= 0 && s1 <= 4 && s1 != 1) || s1 == 7 || (s1 >= 11 && s1 <= 14) ||
+ (s1 >= 77 && s1 < 94)) && s2 >= 0 && s2 < 94) {
+ /* calc offset from ku */
+ for (k = 0; k < jisx0213_p2_ofst_len; k++) {
+ if (s1 == jisx0213_p2_ofst[k]-1) {
+ break;
+ }
+ }
+ k = k - (jisx0213_p2_ofst[k]-1);
+
+ /* check for japanese chars in BMP */
+ s = (s1 + 94 + k)*94 + s2;
+ if (s >= 0 && s < jisx0213_ucs_table_size) {
+ w = jisx0213_ucs_table[s];
+ } else {
+ w = 0;
+ }
+
+ /* check for japanese chars in CJK Unified Ideographs ext.B (U+2XXXX) */
+ if (w <= 0) {
+ w1 = ((c1 + k + 94) << 8) | c2;
+ k = mbfl_bisec_srch2(w1, jisx0213_jis_u5_key, jisx0213_u5_tbl_len);
+ if (k >= 0) {
+ w = jisx0213_jis_u5_tbl[k] + 0x20000;
+ }
+ }
+
+ if (w <= 0) {
+ w = ((c1 & 0x7f) << 8) | (c2 & 0x7f);
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_JIS0213;
+ }
+
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ w = (c1 << 8) | c | 0x8f0000;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ } else {
+ w = ((c1 & 0x7f) << 8) | (c2 & 0x7f);
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_JIS0213;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ }
+
+ break;
+
+ case 5: /* X 0208 : ISO-2022-JP-2004 */
+ filter->status &= ~0xf;
+ c1 = filter->cache;
+ if (c > 0x20 && c < 0x7f) {
+ s = (c1 - 0x21)*94 + c - 0x21;
+ if (s >= 0 && s < jisx0208_ucs_table_size) {
+ w = jisx0208_ucs_table[s];
+ }
+ }
+ if (w <= 0) {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_JIS0208;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ break;
+
+ /* ESC : ISO-2022-JP-2004 */
+/* case 0x06: */
+/* case 0x16: */
+/* case 0x26: */
+/* case 0x86: */
+/* case 0x96: */
+/* case 0xa6: */
+ case 6:
+ if (c == 0x24) { /* '$' */
+ filter->status++;
+ } else if (c == 0x28) { /* '(' */
+ filter->status += 3;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC $ : ISO-2022-JP-2004 */
+/* case 0x07: */
+/* case 0x17: */
+/* case 0x27: */
+/* case 0x87: */
+/* case 0x97: */
+/* case 0xa7: */
+ case 7:
+ if (c == 0x42) { /* 'B' -> JIS X 0208-1983 */
+ filter->status = 0x80;
+ } else if (c == 0x28) { /* '(' */
+ filter->status++;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ goto retry;
+ }
+ break;
+
+ break;
+
+ /* ESC $ ( : ISO-2022-JP-2004 */
+/* case 0x08: */
+/* case 0x18: */
+/* case 0x28: */
+/* case 0x88: */
+/* case 0x98: */
+/* case 0xa8: */
+ case 8:
+ if (c == 0x51) { /* JIS X 0213 plane 1 */
+ filter->status = 0x90;
+ } else if (c == 0x50) { /* JIS X 0213 plane 2 */
+ filter->status = 0xa0;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ CK((*filter->output_function)(0x28, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC ( : ISO-2022-JP-2004 */
+/* case 0x09: */
+/* case 0x19: */
+/* case 0x29: */
+/* case 0x89: */
+/* case 0x99: */
+ case 9:
+ if (c == 0x42) { /* 'B' : ASCII */
+ filter->status = 0;
+ } else {
+ filter->status &= ~0xf;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x28, filter->data));
+ goto retry;
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
+
+int
+mbfl_filt_conv_wchar_jis2004(int c, mbfl_convert_filter *filter) {
+ int k;
+ int c1, c2, s1 = 0, s2;
+
+retry:
+
+ /* check for 1st char of combining characters */
+ if ((filter->status & 0xf)== 0 && (
+ c == 0x00E6 ||
+ (c >= 0x0254 && c <= 0x02E9) ||
+ (c >= 0x304B && c <= 0x3053) ||
+ (c >= 0x30AB && c <= 0x30C8) ||
+ c == 0x31F7)) {
+ for (k=0;k<jisx0213_u2_tbl_len;k++) {
+ if (c == jisx0213_u2_tbl[2*k]) {
+ filter->status++;
+ filter->cache = k;
+ return c;
+ }
+ }
+ }
+
+ /* check for 2nd char of combining characters */
+ if ((filter->status & 0xf) == 1 &&
+ filter->cache >= 0 && filter->cache <= jisx0213_u2_tbl_len) {
+ k = filter->cache;
+ filter->status &= ~0xf;
+ filter->cache = 0;
+
+ c1 = jisx0213_u2_tbl[2*k];
+ if ((c1 == 0x0254 || c1 == 0x028C || c1 == 0x0259 || c1 == 0x025A)
+ && c == 0x0301) {
+ k++;
+ }
+ if (c == jisx0213_u2_tbl[2*k+1]) {
+ s1 = jisx0213_u2_key[k];
+ } else { /* fallback */
+ s1 = jisx0213_u2_fb_tbl[k];
+
+ if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
+ c1 = (s1 >> 8) & 0xff;
+ c2 = s1 & 0xff;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ } else if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ s2 = (s1 & 0xff) + 0x80;
+ s1 = ((s1 >> 8) & 0xff) + 0x80;
+ } else {
+ if (filter->status != 0x200) {
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ CK((*filter->output_function)(0x28, filter->data));
+ CK((*filter->output_function)(0x51, filter->data));
+ }
+ filter->status = 0x200;
+
+ s2 = s1 & 0x7f;
+ s1 = (s1 >> 8) & 0x7f;
+ }
+
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ goto retry;
+ }
+ }
+
+ /* check for major japanese chars: U+4E00 - U+9FFF */
+ if (s1 <= 0) {
+ for (k=0; k < uni2jis_tbl_len ;k++) {
+ if (c >= uni2jis_tbl_range[k][0] && c <= uni2jis_tbl_range[k][1]) {
+ s1 = uni2jis_tbl[k][c-uni2jis_tbl_range[k][0]];
+ break;
+ }
+ }
+ }
+
+ /* check for japanese chars in compressed mapping area: U+1E00 - U+4DBF */
+ if (s1 <= 0 && c >= ucs_c1_jisx0213_min && c <= ucs_c1_jisx0213_max) {
+ k = mbfl_bisec_srch(c, ucs_c1_jisx0213_tbl, ucs_c1_jisx0213_tbl_len);
+ if (k >= 0) {
+ s1 = ucs_c1_jisx0213_ofst[k] + c - ucs_c1_jisx0213_tbl[2*k];
+ }
+ }
+
+ /* check for japanese chars in CJK Unified Ideographs ext.B (U+2XXXX) */
+ if (s1 <= 0 && c >= jisx0213_u5_tbl_min && c <= jisx0213_u5_tbl_max) {
+ k = mbfl_bisec_srch2(c - 0x20000, jisx0213_u5_jis_key, jisx0213_u5_tbl_len);
+ if (k >= 0) {
+ s1 = jisx0213_u5_jis_tbl[k];
+ }
+ }
+
+ if (s1 <= 0) {
+ /* CJK Compatibility Forms: U+FE30 - U+FE4F */
+ if (c == 0xfe45) {
+ s1 = 0x233e;
+ } else if (c == 0xfe46) {
+ s1 = 0x233d;
+ } else if (c >= 0xf91d && c <= 0xf9dc) {
+ /* CJK Compatibility Ideographs: U+F900 - U+F92A */
+ k = mbfl_bisec_srch2(c, ucs_r2b_jisx0213_cmap_key, ucs_r2b_jisx0213_cmap_len);
+ if (k >= 0) {
+ s1 = ucs_r2b_jisx0213_cmap_val[k];
+ }
+ }
+ }
+
+ if (s1 <= 0) {
+ c1 = c & ~MBFL_WCSPLANE_MASK;
+ if (c1 == MBFL_WCSPLANE_JIS0213) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ }
+ if (c == 0) {
+ s1 = 0;
+ } else if (s1 <= 0) {
+ s1 = -1;
+ }
+ } else if (s1 >= 0x9980) {
+ s1 = -1;
+ }
+
+ if (s1 >= 0) {
+ if (s1 < 0x80) { /* ASCII */
+ if (filter->to->no_encoding == mbfl_no_encoding_2022jp_2004 &&
+ (filter->status & 0xff00) != 0) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
+ }
+ filter->status = 0;
+ CK((*filter->output_function)(s1, filter->data));
+ } else if (s1 < 0x100) { /* latin or kana */
+ if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ CK((*filter->output_function)(0x8e, filter->data));
+ }
+ CK((*filter->output_function)(s1, filter->data));
+ } else if (s1 < 0x7f00) { /* X 0213 plane 1 */
+ if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
+ c1 = (s1 >> 8) & 0xff;
+ c2 = s1 & 0xff;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ } else if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ s2 = (s1 & 0xff) + 0x80;
+ s1 = ((s1 >> 8) & 0xff) + 0x80;
+ } else {
+ if ((filter->status & 0xff00) != 0x200) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x24, filter->data)); /* '$' */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x51, filter->data)); /* 'Q' */
+ }
+ filter->status = 0x200;
+ s2 = s1 & 0xff;
+ s1 = (s1 >> 8) & 0xff;
+ }
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ } else { /* X 0213 plane 2 */
+ if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
+ c1 = (s1 >> 8) & 0xff;
+ c2 = s1 & 0xff;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ } else {
+ s2 = s1 & 0xff;
+ k = ((s1 >> 8) & 0xff) - 0x7f;
+ if (k >= 0 && k < jisx0213_p2_ofst_len) {
+ s1 = jisx0213_p2_ofst[k] - 1 + 0x21;
+ }
+ if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ s2 |= 0x80;
+ s1 |= 0x80;
+ CK((*filter->output_function)(0x8f, filter->data));
+ } else {
+ if ((filter->status & 0xff00) != 0x200) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x24, filter->data)); /* '$' */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x50, filter->data)); /* 'P' */
+ }
+ filter->status = 0x200;
+ }
+ }
+
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+}
+
+int
+mbfl_filt_conv_jis2004_flush(mbfl_convert_filter *filter)
+{
+ int k, c1, c2, s1, s2;
+
+ k = filter->cache;
+ filter->cache = 0;
+
+ if (filter->status == 1 && k >= 0 && k <= jisx0213_u2_tbl_len) {
+ s1 = jisx0213_u2_fb_tbl[k];
+
+ if (filter->to->no_encoding == mbfl_no_encoding_sjis2004) {
+ c1 = (s1 >> 8) & 0xff;
+ c2 = s1 & 0xff;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ } else if (filter->to->no_encoding == mbfl_no_encoding_eucjp2004) {
+ s2 = (s1 & 0xff) | 0x80;
+ s1 = ((s1 >> 8) & 0xff) | 0x80;
+ } else {
+ s2 = s1 & 0x7f;
+ s1 = (s1 >> 8) & 0x7f;
+ if ((filter->status & 0xff00) != 0x200) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x24, filter->data)); /* '$' */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x51, filter->data)); /* 'Q' */
+ }
+ filter->status = 0x200;
+ }
+
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+
+ /* back to latin */
+ if ((filter->status & 0xff00) != 0) {
+ CK((*filter->output_function)(0x1b, filter->data)); /* ESC */
+ CK((*filter->output_function)(0x28, filter->data)); /* '(' */
+ CK((*filter->output_function)(0x42, filter->data)); /* 'B' */
+ }
+
+ filter->status = 0;
+
+ if (filter->flush_function != NULL) {
+ return (*filter->flush_function)(filter->data);
+ }
+
+ return 0;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.h b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.h
new file mode 100644
index 0000000000..cf91f7a06b
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.h
@@ -0,0 +1,49 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter_sjis.c
+ * by rui hirokawa <hirokawa@php.net> on 15 aug 2011.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_SJIS_2004_H
+#define MBFL_MBFILTER_SJIS_2004_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_sjis2004;
+extern const struct mbfl_identify_vtbl vtbl_identify_sjis2004;
+extern const struct mbfl_convert_vtbl vtbl_sjis2004_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_sjis2004;
+
+int mbfl_filt_conv_jis2004_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_jis2004(int c, mbfl_convert_filter *filter);
+
+int mbfl_filt_conv_jis2004_flush(mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_SJIS_2004_H */
+
+/*
+ * charset=UTF-8
+ */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c
new file mode 100644
index 0000000000..2f84edff21
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c
@@ -0,0 +1,700 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * the source code included in this files was separated from mbfilter_sjis_open.c
+ * by Rui Hirokawa <hirokawa@php.net> on 25 July 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_sjis_mac.h"
+
+#include "unicode_table_cp932_ext.h"
+#include "unicode_table_jis.h"
+
+#include "sjis_mac2uni.h"
+
+extern int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter);
+extern const unsigned char mblen_table_sjis[];
+
+static int mbfl_filt_conv_sjis_mac_flush(mbfl_convert_filter *filter);
+
+static const char *mbfl_encoding_sjis_mac_aliases[] = {"MacJapanese", "x-Mac-Japanese", NULL};
+
+const mbfl_encoding mbfl_encoding_sjis_mac = {
+ mbfl_no_encoding_sjis_mac,
+ "SJIS-mac",
+ "Shift_JIS",
+ (const char *(*)[])&mbfl_encoding_sjis_mac_aliases,
+ mblen_table_sjis,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_sjis_mac = {
+ mbfl_no_encoding_sjis_mac,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_sjis
+};
+
+const struct mbfl_convert_vtbl vtbl_sjis_mac_wchar = {
+ mbfl_no_encoding_sjis_mac,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_sjis_mac_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_sjis_mac = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_sjis_mac,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_sjis_mac,
+ mbfl_filt_conv_sjis_mac_flush
+};
+
+#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+
+#define SJIS_ENCODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ s1--; \
+ s1 >>= 1; \
+ if ((c1) < 0x5f) { \
+ s1 += 0x71; \
+ } else { \
+ s1 += 0xb1; \
+ } \
+ s2 = c2; \
+ if ((c1) & 1) { \
+ if ((c2) < 0x60) { \
+ s2--; \
+ } \
+ s2 += 0x20; \
+ } else { \
+ s2 += 0x7e; \
+ } \
+ } while (0)
+
+#define SJIS_DECODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ if (s1 < 0xa0) { \
+ s1 -= 0x81; \
+ } else { \
+ s1 -= 0xc1; \
+ } \
+ s1 <<= 1; \
+ s1 += 0x21; \
+ s2 = c2; \
+ if (s2 < 0x9f) { \
+ if (s2 < 0x7f) { \
+ s2++; \
+ } \
+ s2 -= 0x20; \
+ } else { \
+ s1++; \
+ s2 -= 0x7e; \
+ } \
+ } while (0)
+
+/*
+ * SJIS-mac => wchar
+ */
+int
+mbfl_filt_conv_sjis_mac_wchar(int c, mbfl_convert_filter *filter)
+{
+ int i, j, n;
+ int c1, s, s1, s2, w;
+
+ switch (filter->status) {
+ case 0:
+ if (c >= 0 && c < 0x80 && c != 0x5c) { /* latin */
+ CK((*filter->output_function)(c, filter->data));
+ } else if (c > 0xa0 && c < 0xe0) { /* kana */
+ CK((*filter->output_function)(0xfec0 + c, filter->data));
+ } else if (c > 0x80 && c < 0xfd && c != 0xa0) { /* kanji first char */
+ filter->status = 1;
+ filter->cache = c;
+ } else if (c == 0x5c) {
+ CK((*filter->output_function)(0x00a5, filter->data));
+ } else if (c == 0x80) {
+ CK((*filter->output_function)(0x005c, filter->data));
+ } else if (c == 0xa0) {
+ CK((*filter->output_function)(0x00a0, filter->data));
+ } else if (c == 0xfd) {
+ CK((*filter->output_function)(0x00a9, filter->data));
+ } else if (c == 0xfe) {
+ CK((*filter->output_function)(0x2122, filter->data));
+ } else if (c == 0xff) {
+ CK((*filter->output_function)(0x2026, filter->data));
+ CK((*filter->output_function)(0xf87f, filter->data));
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ case 1: /* kanji second char */
+ filter->status = 0;
+ c1 = filter->cache;
+ if (c >= 0x40 && c <= 0xfc && c != 0x7f) {
+ w = 0;
+ SJIS_DECODE(c1, c, s1, s2);
+ s = (s1 - 0x21)*94 + s2 - 0x21;
+ if (s <= 0x89) {
+ if (s == 0x1c) {
+ w = 0x2014; /* EM DASH */
+ } else if (s == 0x1f) {
+ w = 0xff3c; /* FULLWIDTH REVERSE SOLIDUS */
+ } else if (s == 0x20) {
+ w = 0x301c; /* FULLWIDTH TILDE */
+ } else if (s == 0x21) {
+ w = 0x2016; /* PARALLEL TO */
+ } else if (s == 0x3c) {
+ w = 0x2212; /* FULLWIDTH HYPHEN-MINUS */
+ } else if (s == 0x50) {
+ w = 0x00a2; /* FULLWIDTH CENT SIGN */
+ } else if (s == 0x51) {
+ w = 0x00a3; /* FULLWIDTH POUND SIGN */
+ } else if (s == 0x89) {
+ w = 0x00ac; /* FULLWIDTH NOT SIGN */
+ }
+ }
+
+ /* apple gaiji area 0x8540 - 0x886d */
+ if (w == 0) {
+ for (i=0; i<7; i++) {
+ if (s >= code_tbl[i][0] && s <= code_tbl[i][1]) {
+ w = s - code_tbl[i][0] + code_tbl[i][2];
+ break;
+ }
+ }
+ }
+
+ if (w == 0) {
+
+ for (i=0; i<code_tbl_m_len; i++) {
+ if (s == code_tbl_m[i][0]) {
+ if (code_tbl_m[i][1] == 0xf860) {
+ n = 4;
+ } else if (code_tbl_m[i][1] == 0xf861) {
+ n = 5;
+ } else {
+ n = 6;
+ }
+ for (j=1; j<n-1; j++) {
+ CK((*filter->output_function)(code_tbl_m[i][j], filter->data));
+ }
+ w = code_tbl_m[i][n-1];
+ break;
+ }
+ }
+ }
+
+ if (w == 0) {
+ for (i=0; i<8; i++) {
+ if (s >= code_ofst_tbl[i][0] && s <= code_ofst_tbl[i][1]) {
+ w = code_map[i][s - code_ofst_tbl[i][0]];
+ s2 = 0;
+ if (s >= 0x043e && s <= 0x0441) {
+ s2 = 0xf87a;
+ } else if (s == 0x03b1 || s == 0x03b7) {
+ s2 = 0xf87f;
+ } else if (s == 0x04b8 || s == 0x04b9 || s == 0x04c4) {
+ s2 = 0x20dd;
+ } else if (s == 0x1ed9 || s == 0x1eda || s == 0x1ee8 || s == 0x1ef3 ||
+ (s >= 0x1ef5 && s <= 0x1efb) || s == 0x1f05 || s == 0x1f06 ||
+ s == 0x1f18 || (s >= 0x1ff2 && s <= 0x20a5)) {
+ s2 = 0xf87e;
+ }
+ if (s2 > 0) {
+ CK((*filter->output_function)(w, filter->data));
+ w = s2;
+ }
+ break;
+ }
+ }
+ }
+
+ if (w == 0 && s >= 0 && s < jisx0208_ucs_table_size) { /* X 0208 */
+ w = jisx0208_ucs_table[s];
+ }
+
+ if (w <= 0) {
+ w = (s1 << 8) | s2;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_WINCP932;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
+
+/*
+ * wchar => SJIS-mac
+ */
+int
+mbfl_filt_conv_wchar_sjis_mac(int c, mbfl_convert_filter *filter)
+{
+ int i;
+ int c1, c2, s1, s2, mode;
+
+ s1 = 0;
+ s2 = 0;
+
+ // a1: U+0000 -> U+046F
+ // a2: U+2000 -> U+30FF
+ // i: U+4E00 -> U+9FFF
+ // r: U+FF00 -> U+FFFF
+
+ switch (filter->status) {
+
+ case 1:
+ c1 = filter->cache;
+ filter->cache = 0;
+ filter->status = 0;
+
+ s1 = 0;
+ s2 = 0;
+
+ if (c == 0xf87a) {
+ for (i=0;i<4;i++) {
+ if (c1 == s_form_tbl[i+34+3+3]) {
+ s1 = s_form_sjis_tbl[i+34+3+3];
+ break;
+ }
+ }
+ if (s1 <= 0) {
+ s2 = c1;
+ }
+ } else if (c == 0x20dd) {
+ for (i=0;i<3;i++) {
+ if (c1 == s_form_tbl[i+34+3]) {
+ s1 = s_form_sjis_tbl[i+34+3];
+ break;
+ }
+ }
+ if (s1 <= 0) {
+ s2 = c1;
+ }
+ } else if (c == 0xf87f) {
+ for (i=0;i<3;i++) {
+ if (c1 == s_form_tbl[i+34]) {
+ s1 = s_form_sjis_tbl[i+34];
+ break;
+ }
+ }
+ if (s1 <= 0) {
+ s2 = c1; s1 = -1;
+ }
+ } else if (c == 0xf87e) {
+ for (i=0;i<34;i++) {
+ if (c1 == s_form_tbl[i]) {
+ s1 = s_form_sjis_tbl[i];
+ break;
+ }
+ }
+ if (s1 <= 0) {
+ s2 = c1; s1 = -1;
+ }
+ } else {
+ s2 = c1;
+ s1 = c;
+ }
+
+ if (s2 > 0) {
+ for (i=0;i<s_form_tbl_len;i++) {
+ if (c1 == s_form_tbl[i]) {
+ s1 = s_form_sjis_fallback_tbl[i];
+ break;
+ }
+ }
+ }
+
+ if (s1 >= 0) {
+ if (s1 < 0x100) {
+ CK((*filter->output_function)(s1, filter->data));
+ } else {
+ CK((*filter->output_function)((s1 >> 8) & 0xff, filter->data));
+ CK((*filter->output_function)(s1 & 0xff, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+
+ if (s2 <= 0 || s1 == -1) {
+ break;
+ }
+
+ case 0:
+
+ if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
+ s1 = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
+ if (c == 0x5c) {
+ s1 = 0x80;
+ } else if (c == 0xa9) {
+ s1 = 0xfd;
+ }
+ } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
+ s1 = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
+ if (c == 0x2122) {
+ s1 = 0xfe;
+ } else if (c == 0x2014) {
+ s1 = 0x213d;
+ } else if (c == 0x2116) {
+ s1 = 0x2c1d;
+ }
+ } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
+ s1 = ucs_i_jis_table[c - ucs_i_jis_table_min];
+ } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
+ s1 = ucs_r_jis_table[c - ucs_r_jis_table_min];
+ }
+
+ if (c >= 0x2000) {
+ for (i=0;i<s_form_tbl_len;i++) {
+ if (c == s_form_tbl[i]) {
+ filter->status = 1;
+ filter->cache = c;
+ return c;
+ }
+ }
+
+ if (c == 0xf860 || c == 0xf861 || c == 0xf862) {
+ filter->status = 2;
+ filter->cache = c;
+ return c;
+ }
+ }
+
+ if (s1 <= 0) {
+ c1 = c & ~MBFL_WCSPLANE_MASK;
+ if (c1 == MBFL_WCSPLANE_WINCP932) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ s2 = 1;
+ } else if (c1 == MBFL_WCSPLANE_JIS0208) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ } else if (c1 == MBFL_WCSPLANE_JIS0212) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ s1 |= 0x8080;
+ } else if (c == 0xa0) {
+ s1 = 0x00a0;
+ } else if (c == 0xa5) { /* YEN SIGN */
+ s1 = 0x216f; /* FULLWIDTH YEN SIGN */
+ } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
+ s1 = 0x2140;
+ }
+ }
+
+ if (s1 <= 0) {
+ for (i=0; i<wchar2sjis_mac_r_tbl_len; i++) {
+ if (c >= wchar2sjis_mac_r_tbl[i][0] && c <= wchar2sjis_mac_r_tbl[i][1]) {
+ s1 = c - wchar2sjis_mac_r_tbl[i][0] + wchar2sjis_mac_r_tbl[i][2];
+ break;
+ }
+ }
+
+ if (s1 <= 0) {
+ for (i=0; i<wchar2sjis_mac_r_map_len; i++) {
+ if (c >= wchar2sjis_mac_r_map[i][0] && c <= wchar2sjis_mac_r_map[i][1]) {
+ s1 = wchar2sjis_mac_code_map[i][c-wchar2sjis_mac_r_map[i][0]];
+ break;
+ }
+ }
+ }
+
+ if (s1 <= 0) {
+ for (i=0; i<wchar2sjis_mac_wchar_tbl_len ; i++) {
+ if ( c == wchar2sjis_mac_wchar_tbl[i][0]) {
+ s1 = wchar2sjis_mac_wchar_tbl[i][1] & 0xffff;
+ break;
+ }
+ }
+ }
+
+ if (s1 > 0) {
+ c1 = s1/94+0x21;
+ c2 = s1-94*(c1-0x21)+0x21;
+ s1 = (c1 << 8) | c2;
+ s2 = 1;
+ }
+ }
+
+ if ((s1 <= 0) || (s1 >= 0x8080 && s2 == 0)) { /* not found or X 0212 */
+ s1 = -1;
+ c1 = 0;
+
+ if (c == 0) {
+ s1 = 0;
+ } else if (s1 <= 0) {
+ s1 = -1;
+ }
+ }
+
+ if (s1 >= 0) {
+ if (s1 < 0x100) { /* latin or kana */
+ CK((*filter->output_function)(s1, filter->data));
+ } else { /* kanji */
+ c1 = (s1 >> 8) & 0xff;
+ c2 = s1 & 0xff;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+ break;
+
+
+ case 2:
+ c1 = filter->cache;
+ filter->cache = 0;
+ filter->status = 0;
+ if (c1 == 0xf860) {
+ for (i=0; i<5; i++) {
+ if (c == code_tbl_m[i][2]) {
+ filter->cache = c | 0x10000;
+ filter->status = 3;
+ break;
+ }
+ }
+ } else if (c1 == 0xf861) {
+ for (i=0; i<3; i++) {
+ if (c == code_tbl_m[i+5][2]) {
+ filter->cache = c | 0x20000;
+ filter->status = 3;
+ break;
+ }
+ }
+ } else if (c1 == 0xf862) {
+ for (i=0; i<4; i++) {
+ if (c == code_tbl_m[i+5+3][2]) {
+ filter->cache = c | 0x40000;
+ filter->status = 3;
+ break;
+ }
+ }
+ }
+
+ if (filter->status == 0 && filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c1, filter));
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+
+ break;
+
+ case 3:
+ s1 = 0;
+ c1 = filter->cache & 0xffff;
+ mode = (filter->cache & 0xf0000) >> 16;
+
+ filter->cache = 0;
+ filter->status = 0;
+
+ if (mode == 0x1) {
+ for (i=0; i<5; i++) {
+ if (c1 == code_tbl_m[i][2] && c == code_tbl_m[i][3]) {
+ s1 = code_tbl_m[i][0];
+ break;
+ }
+ }
+
+ if (s1 > 0) {
+ c1 = s1/94+0x21;
+ c2 = s1-94*(c1-0x21)+0x21;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+
+ if (s1 <= 0 && filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(0xf860, filter));
+ CK(mbfl_filt_conv_illegal_output(c1, filter));
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+
+ } else if (mode == 0x2) {
+ for (i=0; i<3; i++) {
+ if (c1 == code_tbl_m[i+5][2] && c == code_tbl_m[i+5][3]) {
+ filter->cache = c | 0x20000;
+ filter->status = 4;
+ break;
+ }
+ }
+ } else if (mode == 0x4) {
+ for (i=0; i<4; i++) {
+ if (c1 == code_tbl_m[i+8][2] && c == code_tbl_m[i+8][3]) {
+ filter->cache = c | 0x40000;
+ filter->status = 4;
+ break;
+ }
+ }
+ }
+ break;
+
+ case 4:
+ s1 = 0;
+ c1 = filter->cache & 0xffff;
+ mode = (filter->cache & 0xf0000) >> 16;
+
+ filter->cache = 0;
+ filter->status = 0;
+
+ if (mode == 0x2) {
+ for (i=0; i<3; i++) {
+ if (c1 == code_tbl_m[i+5][3] && c == code_tbl_m[i+5][4]) {
+ s1 = code_tbl_m[i+5][0];
+ break;
+ }
+ }
+
+ if (s1 > 0) {
+ c1 = s1/94+0x21;
+ c2 = s1-94*(c1-0x21)+0x21;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+
+ if (s1 <= 0 && filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(0xf861, filter));
+ for (i=0; i<3; i++) {
+ if (c1 == code_tbl_m[i+5][3]) {
+ CK(mbfl_filt_conv_illegal_output(code_tbl_m[i+5][2], filter));
+ break;
+ }
+ }
+ CK(mbfl_filt_conv_illegal_output(c1, filter));
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ } else if (mode == 0x4) {
+ for (i=0; i<4; i++) {
+ if (c1 == code_tbl_m[i+8][3] && c == code_tbl_m[i+8][4]) {
+ filter->cache = c | 0x40000;
+ filter->status = 5;
+ break;
+ }
+ }
+ }
+ break;
+
+ case 5:
+ s1 = 0;
+ c1 = filter->cache & 0xffff;
+ mode = (filter->cache & 0xf0000) >> 16;
+
+ filter->cache = 0;
+ filter->status = 0;
+
+ if (mode == 0x4) {
+ for (i=0; i<4; i++) {
+ if (c1 == code_tbl_m[i+8][4] && c == code_tbl_m[i+8][5]) {
+ s1 = code_tbl_m[i+8][0];
+ break;
+ }
+ }
+
+ if (s1 > 0) {
+ c1 = s1/94+0x21;
+ c2 = s1-94*(c1-0x21)+0x21;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+
+ if (s1 <= 0 && filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(0xf862, filter));
+ for (i=0; i<4; i++) {
+ if (c1 == code_tbl_m[i+8][4]) {
+ CK(mbfl_filt_conv_illegal_output( code_tbl_m[i+8][2], filter));
+ CK(mbfl_filt_conv_illegal_output( code_tbl_m[i+8][3], filter));
+ break;
+ }
+ }
+ CK(mbfl_filt_conv_illegal_output(c1, filter));
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+ return c;
+}
+
+static int
+mbfl_filt_conv_sjis_mac_flush(mbfl_convert_filter *filter)
+{
+ int i, c1, s1 = 0;
+ if (filter->status == 1 && filter->cache > 0) {
+ c1 = filter->cache;
+ for (i=0;i<s_form_tbl_len;i++) {
+ if (c1 == s_form_tbl[i]) {
+ s1 = s_form_sjis_fallback_tbl[i];
+ break;
+ }
+ }
+ if (s1 > 0) {
+ CK((*filter->output_function)((s1 >> 8) & 0xff, filter->data));
+ CK((*filter->output_function)(s1 & 0xff, filter->data));
+ }
+ }
+ filter->cache = 0;
+ filter->status = 0;
+
+ if (filter->flush_function != NULL) {
+ return (*filter->flush_function)(filter->data);
+ }
+
+ return 0;
+}
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.h b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.h
new file mode 100644
index 0000000000..3b191aa418
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.h
@@ -0,0 +1,44 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * the source code included in this files was separated from mbfilter_sjis_open.c
+ * by Rui Hirokawa <hirokawa@php.net> on 25 July 2011.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_SJIS_MAC_H
+#define MBFL_MBFILTER_SJIS_MAC_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_sjis_mac;
+
+extern const struct mbfl_identify_vtbl vtbl_identify_sjis_mac;
+extern const struct mbfl_convert_vtbl vtbl_sjis_mac_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_sjis_mac;
+
+int mbfl_filt_conv_sjis_mac_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_sjis_mac(int c, mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_SJIS_MAC_H */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c
new file mode 100644
index 0000000000..7a549af666
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c
@@ -0,0 +1,927 @@
+
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * the source code included in this files was separated from mbfilter_sjis_open.c
+ * by Rui Hirokawa <hirokawa@php.net> on 25 July 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+#include "mbfilter_sjis_mobile.h"
+
+#include "unicode_table_cp932_ext.h"
+#include "unicode_table_jis.h"
+
+#include "emoji2uni.h"
+
+extern int mbfl_bisec_srch2(int w, const unsigned short tbl[], int n);
+extern int mbfl_filt_ident_sjis(int c, mbfl_identify_filter *filter);
+extern const unsigned char mblen_table_sjis[];
+
+static const char *mbfl_encoding_sjis_docomo_aliases[] = {"SJIS-DOCOMO", "shift_jis-imode", "x-sjis-emoji-docomo", NULL};
+static const char *mbfl_encoding_sjis_kddi_aliases[] = {"SJIS-KDDI", "shift_jis-kddi", "x-sjis-emoji-kddi", NULL};
+static const char *mbfl_encoding_sjis_sb_aliases[] = {"SJIS-SOFTBANK", "shift_jis-softbank", "x-sjis-emoji-softbank", NULL};
+
+const mbfl_encoding mbfl_encoding_sjis_docomo = {
+ mbfl_no_encoding_sjis_docomo,
+ "SJIS-Mobile#DOCOMO",
+ "Shift_JIS",
+ (const char *(*)[])&mbfl_encoding_sjis_docomo_aliases,
+ mblen_table_sjis,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const mbfl_encoding mbfl_encoding_sjis_kddi = {
+ mbfl_no_encoding_sjis_kddi,
+ "SJIS-Mobile#KDDI",
+ "Shift_JIS",
+ (const char *(*)[])&mbfl_encoding_sjis_kddi_aliases,
+ mblen_table_sjis,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const mbfl_encoding mbfl_encoding_sjis_sb = {
+ mbfl_no_encoding_sjis_sb,
+ "SJIS-Mobile#SOFTBANK",
+ "Shift_JIS",
+ (const char *(*)[])&mbfl_encoding_sjis_sb_aliases,
+ mblen_table_sjis,
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_sjis_docomo = {
+ mbfl_no_encoding_sjis_docomo,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_sjis
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_sjis_kddi = {
+ mbfl_no_encoding_sjis_kddi,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_sjis
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_sjis_sb = {
+ mbfl_no_encoding_sjis_sb,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_sjis
+};
+
+const struct mbfl_convert_vtbl vtbl_sjis_docomo_wchar = {
+ mbfl_no_encoding_sjis_docomo,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_sjis_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_sjis_docomo = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_sjis_docomo,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_sjis_mobile,
+ mbfl_filt_conv_sjis_mobile_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_sjis_kddi_wchar = {
+ mbfl_no_encoding_sjis_kddi,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_sjis_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_sjis_kddi = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_sjis_kddi,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_sjis_mobile,
+ mbfl_filt_conv_sjis_mobile_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_sjis_sb_wchar = {
+ mbfl_no_encoding_sjis_sb,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_sjis_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_sjis_sb = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_sjis_sb,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_sjis_mobile,
+ mbfl_filt_conv_sjis_mobile_flush
+};
+
+static const char nflags_s[10][2] = {"CN","DE","ES","FR","GB","IT","JP","KR","RU","US"};
+static const int nflags_code_kddi[10] = {0x2549, 0x2546, 0x24c0, 0x2545, 0x2548, 0x2547, 0x2750, 0x254a, 0x24c1, 0x27f7};
+static const int nflags_code_sb[10] = {0x2b0a, 0x2b05, 0x2b08, 0x2b04, 0x2b07, 0x2b06, 0x2b02, 0x2b0b, 0x2b09, 0x2b03};
+
+const unsigned short mbfl_docomo2uni_pua[4][3] = {
+ {0x28c2, 0x292f, 0xe63e},
+ {0x2930, 0x2934, 0xe6ac},
+ {0x2935, 0x2951, 0xe6b1},
+ {0x2952, 0x29db, 0xe6ce},
+};
+
+const unsigned short mbfl_kddi2uni_pua[7][3] = {
+ {0x26ec, 0x2838, 0xe468},
+ {0x284c, 0x2863, 0xe5b5},
+ {0x24b8, 0x24ca, 0xe5cd},
+ {0x24cb, 0x2545, 0xea80},
+ {0x2839, 0x284b, 0xeafb},
+ {0x2546, 0x25c0, 0xeb0e},
+ {0x25c1, 0x25c6, 0xeb89},
+};
+
+const unsigned short mbfl_sb2uni_pua[6][3] = {
+ {0x27a9, 0x2802, 0xe101},
+ {0x2808, 0x2861, 0xe201},
+ {0x2921, 0x297a, 0xe001},
+ {0x2980, 0x29cc, 0xe301},
+ {0x2a99, 0x2ae4, 0xe401},
+ {0x2af8, 0x2b35, 0xe501},
+};
+
+const unsigned short mbfl_kddi2uni_pua_b[8][3] = {
+ {0x24b8, 0x24f6, 0xec40},
+ {0x24f7, 0x2573, 0xec80},
+ {0x2574, 0x25b2, 0xed40},
+ {0x25b3, 0x25c6, 0xed80},
+ {0x26ec, 0x272a, 0xef40},
+ {0x272b, 0x27a7, 0xef80},
+ {0x27a8, 0x27e6, 0xf040},
+ {0x27e7, 0x2863, 0xf080},
+};
+
+#define NFLAGS(c) (0x1F1A5+(int)(c))
+
+#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+
+#define SJIS_ENCODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ s1--; \
+ s1 >>= 1; \
+ if ((c1) < 0x5f) { \
+ s1 += 0x71; \
+ } else { \
+ s1 += 0xb1; \
+ } \
+ s2 = c2; \
+ if ((c1) & 1) { \
+ if ((c2) < 0x60) { \
+ s2--; \
+ } \
+ s2 += 0x20; \
+ } else { \
+ s2 += 0x7e; \
+ } \
+ } while (0)
+
+#define SJIS_DECODE(c1,c2,s1,s2) \
+ do { \
+ s1 = c1; \
+ if (s1 < 0xa0) { \
+ s1 -= 0x81; \
+ } else { \
+ s1 -= 0xc1; \
+ } \
+ s1 <<= 1; \
+ s1 += 0x21; \
+ s2 = c2; \
+ if (s2 < 0x9f) { \
+ if (s2 < 0x7f) { \
+ s2++; \
+ } \
+ s2 -= 0x20; \
+ } else { \
+ s1++; \
+ s2 -= 0x7e; \
+ } \
+ } while (0)
+
+#define CODE2JIS(c1,c2,s1,s2) \
+ c1 = (s1)/94+0x21; \
+ c2 = (s1)-94*((c1)-0x21)+0x21; \
+ s1 = ((c1) << 8) | (c2); \
+ s2 = 1
+
+int
+mbfilter_conv_map_tbl(int c, int *w, const unsigned short map[][3], int n)
+{
+ int i, match = 0;
+
+ for (i = 0; i < n; i++) {
+ if (map[i][0] <= c && c <= map[i][1]) {
+ *w = c - map[i][0] + map[i][2];
+ match = 1;
+ break;
+ }
+ }
+ return match;
+}
+
+int
+mbfilter_conv_r_map_tbl(int c, int *w, const unsigned short map[][3], int n)
+{
+ int i, match = 0;
+
+ for (i = 0; i < n; i++) {
+ if (map[i][2] <= c && c <= map[i][2] - map[i][0] + map[i][1]) {
+ *w = c + map[i][0] - map[i][2];
+ match = 1;
+ break;
+ }
+ }
+ return match;
+}
+
+int
+mbfilter_sjis_emoji_docomo2unicode(int s, int *snd)
+{
+ int w = s;
+ if (s >= mb_tbl_code2uni_docomo1_min && s <= mb_tbl_code2uni_docomo1_max) {
+ if (s >= mb_tbl_code2uni_docomo1_min + 0x00a2 &&
+ s <= mb_tbl_code2uni_docomo1_min + 0x00ad &&
+ s != mb_tbl_code2uni_docomo1_min + 0x00a3) {
+ w = 0x20E3;
+ *snd = mb_tbl_code2uni_docomo1[s - mb_tbl_code2uni_docomo1_min];
+ if (*snd > 0xf000) {
+ *snd += 0x10000;
+ }
+ } else {
+ w = mb_tbl_code2uni_docomo1[s - mb_tbl_code2uni_docomo1_min];
+ if (w > 0xf000) {
+ w += 0x10000;
+ } else if (w > 0xe000) { /* unsuported by Unicode 6.0 */
+ w += 0xf0000;
+ }
+ *snd = 0;
+ if (!w) {
+ w = s;
+ }
+ }
+ }
+
+ return w;
+}
+
+int
+mbfilter_sjis_emoji_kddi2unicode(int s, int *snd)
+{
+ int w = s, si, c;
+ const int nflags_order_kddi[] = {3, 1, 5, 4, 0, 7};
+
+ *snd = 0;
+ if (s >= mb_tbl_code2uni_kddi1_min && s <= mb_tbl_code2uni_kddi1_max) {
+ si = s - mb_tbl_code2uni_kddi1_min;
+ if (si == 0x0008) { /* ES */
+ *snd = NFLAGS(nflags_s[2][0]); w = NFLAGS(nflags_s[2][1]);
+ } else if (si == 0x0009) { /* RU */
+ *snd = NFLAGS(nflags_s[8][0]); w = NFLAGS(nflags_s[8][1]);
+ } else if (si >= 0x008d && si <= 0x0092) {
+ c = nflags_order_kddi[si-0x008d];
+ *snd = NFLAGS(nflags_s[c][0]); w = NFLAGS(nflags_s[c][1]);
+ } else if (si == 0x0104) {
+ *snd = 0x0023; w = 0x20E3;
+ } else {
+ w = mb_tbl_code2uni_kddi1[si];
+ if (w > 0xf000) {
+ w += 0x10000;
+ } else if (w > 0xe000) { /* unsuported by Unicode 6.0 */
+ w += 0xf0000;
+ }
+ }
+ } else if (s >= mb_tbl_code2uni_kddi2_min && s <= mb_tbl_code2uni_kddi2_max) {
+ si = s - mb_tbl_code2uni_kddi2_min;
+ if (si == 100) { /* JP */
+ *snd = NFLAGS(nflags_s[6][0]); w = NFLAGS(nflags_s[6][1]);
+ } else if (si >= 0x00ba && si <= 0x00c2) {
+ *snd = si-0x00ba+0x0031; w = 0x20E3;
+ } else if (si == 0x010b) { /* US */
+ *snd = NFLAGS(nflags_s[9][0]); w = NFLAGS(nflags_s[9][1]);
+ } else if (si == 0x0144) {
+ *snd = 0x0030; w = 0x20E3;
+ } else {
+ w = mb_tbl_code2uni_kddi2[si];
+ if (w > 0xf000) {
+ w += 0x10000;
+ } else if (w > 0xe000) { /* unsuported by Unicode 6.0 */
+ w += 0xf0000;
+ }
+ }
+ }
+ return w;
+}
+
+int
+mbfilter_sjis_emoji_sb2unicode(int s, int *snd)
+{
+ int w = s, si, c;
+ const int nflags_order_sb[10] = {6, 9, 3, 1, 5, 4, 2, 8, 0, 7};
+
+ *snd = 0;
+ if (s >= mb_tbl_code2uni_sb1_min && s <= mb_tbl_code2uni_sb1_max) {
+ si = s - mb_tbl_code2uni_sb1_min;
+ if (si == 0x006e || (si >= 0x007a && si <= 0x0083)) {
+ *snd = mb_tbl_code2uni_sb1[si];
+ if (*snd > 0xf000) {
+ *snd += 0x10000;
+ }
+ w = 0x20E3;
+ } else {
+ w = mb_tbl_code2uni_sb1[si];
+ if (w > 0xf000) {
+ w += 0x10000;
+ } else if (w > 0xe000) { /* unsuported by Unicode 6.0 */
+ w += 0xf0000;
+ }
+ }
+ } else if (s >= mb_tbl_code2uni_sb2_min && s <= mb_tbl_code2uni_sb2_max) {
+ si = s - mb_tbl_code2uni_sb2_min;
+ w = mb_tbl_code2uni_sb2[si];
+ if (w > 0xf000) {
+ w += 0x10000;
+ } else if (w > 0xe000) { /* unsuported by Unicode 6.0 */
+ w += 0xf0000;
+ }
+ } else if (s >= mb_tbl_code2uni_sb3_min && s <= mb_tbl_code2uni_sb3_max) {
+ si = s - mb_tbl_code2uni_sb3_min;
+ if (si >= 0x0069 && si <= 0x0072) {
+ c = nflags_order_sb[si-0x0069];
+ *snd = NFLAGS(nflags_s[c][0]); w = NFLAGS(nflags_s[c][1]);
+ } else {
+ w = mb_tbl_code2uni_sb3[si];
+ if (w > 0xf000) {
+ w += 0x10000;
+ } else if (w > 0xe000) { /* unsuported by Unicode 6.0 */
+ w += 0xf0000;
+ }
+ }
+ }
+ return w;
+}
+
+int
+mbfilter_unicode2sjis_emoji_docomo(int c, int *s1, mbfl_convert_filter *filter)
+{
+ int i, match = 0, c1s;
+
+ if (filter->status == 1) {
+ c1s = filter->cache;
+ filter->cache = 0;
+ filter->status = 0;
+ if (c == 0x20E3) {
+ if (c1s == 0x0023) {
+ *s1 = 0x2964;
+ match = 1;
+ } else if (c1s == 0x0030) {
+ *s1 = 0x296f;
+ match = 1;
+ } else if (c1s >= 0x0031 && c1s <= 0x0039) {
+ *s1 = 0x2966 + (c1s - 0x0031);
+ match = 1;
+ }
+ } else {
+ CK((*filter->output_function)(c1s, filter->data));
+ }
+ } else {
+ if (c == 0x0023 || (c >= 0x0030 && c<=0x0039)) {
+ filter->status = 1;
+ filter->cache = c;
+ *s1 = -1;
+ return match;
+ }
+
+ if (c == 0x00A9) {
+ *s1 = 0x29b5; match = 1;
+ } else if (c == 0x00AE) {
+ *s1 = 0x29ba; match = 1;
+ } else if (c >= mb_tbl_uni_docomo2code2_min && c <= mb_tbl_uni_docomo2code2_max) {
+ i = mbfl_bisec_srch2(c, mb_tbl_uni_docomo2code2_key, mb_tbl_uni_docomo2code2_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_docomo2code2_value[i];
+ match = 1;
+ }
+ } else if (c >= mb_tbl_uni_docomo2code3_min && c <= mb_tbl_uni_docomo2code3_max) {
+ i = mbfl_bisec_srch2(c - 0x10000, mb_tbl_uni_docomo2code3_key, mb_tbl_uni_docomo2code3_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_docomo2code3_value[i];
+ match = 1;
+ }
+ } else if (c >= mb_tbl_uni_docomo2code5_min && c <= mb_tbl_uni_docomo2code5_max) {
+ i = mbfl_bisec_srch2(c - 0xf0000, mb_tbl_uni_docomo2code5_key, mb_tbl_uni_docomo2code5_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_docomo2code5_val[i];
+ match = 1;
+ }
+ }
+ }
+
+ return match;
+}
+
+int
+mbfilter_unicode2sjis_emoji_kddi(int c, int *s1, mbfl_convert_filter *filter)
+{
+ int i, match = 0, c1s;
+
+ if (filter->status == 1) {
+ c1s = filter->cache;
+ filter->cache = 0;
+ filter->status = 0;
+ if (c == 0x20E3) {
+ if (c1s == 0x0023) {
+ *s1 = 0x25bc;
+ match = 1;
+ } else if (c1s == 0x0030) {
+ *s1 = 0x2830;
+ match = 1;
+ } else if (c1s >= 0x0031 && c1s <= 0x0039) {
+ *s1 = 0x27a6 + (c1s - 0x0031);
+ match = 1;
+ }
+ } else if ((c >= NFLAGS(0x41) && c <= NFLAGS(0x5A)) && (c1s >= NFLAGS(0x41) && c1s <= NFLAGS(0x5A))) {
+ for (i=0; i<10; i++) {
+ if (c1s == NFLAGS(nflags_s[i][0]) && c == NFLAGS(nflags_s[i][1])) {
+ *s1 = nflags_code_kddi[i];
+ match = 1;
+ break;
+ }
+ }
+ } else {
+ if (c1s >= ucs_a1_jis_table_min && c1s < ucs_a1_jis_table_max) {
+ c1s = ucs_a1_jis_table[c1s - ucs_a1_jis_table_min];
+ CK((*filter->output_function)(c1s, filter->data));
+ }
+ }
+ } else {
+ if (c == 0x0023 || ( c >= 0x0030 && c<=0x0039) ||
+ (c >= NFLAGS(0x41) && c<= NFLAGS(0x5A))) {
+ filter->status = 1;
+ filter->cache = c;
+ *s1 = -1;
+ return match;
+ }
+
+ if (c == 0x00A9) {
+ *s1 = 0x27dc; match = 1;
+ } else if (c == 0x00AE) {
+ *s1 = 0x27dd; match = 1;
+ } else if (c >= mb_tbl_uni_kddi2code2_min && c <= mb_tbl_uni_kddi2code2_max) {
+ i = mbfl_bisec_srch2(c, mb_tbl_uni_kddi2code2_key, mb_tbl_uni_kddi2code2_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_kddi2code2_value[i];
+ match = 1;
+ }
+ } else if (c >= mb_tbl_uni_kddi2code3_min && c <= mb_tbl_uni_kddi2code3_max) {
+ i = mbfl_bisec_srch2(c - 0x10000, mb_tbl_uni_kddi2code3_key, mb_tbl_uni_kddi2code3_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_kddi2code3_value[i];
+ match = 1;
+ }
+ } else if (c >= mb_tbl_uni_kddi2code5_min && c <= mb_tbl_uni_kddi2code5_max) {
+ i = mbfl_bisec_srch2(c - 0xf0000, mb_tbl_uni_kddi2code5_key, mb_tbl_uni_kddi2code5_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_kddi2code5_val[i];
+ match = 1;
+ }
+ }
+ }
+
+ return match;
+}
+
+int
+mbfilter_unicode2sjis_emoji_sb(int c, int *s1, mbfl_convert_filter *filter)
+{
+ int i, match = 0, c1s;
+
+ if (filter->status == 1) {
+ filter->status = 0;
+ c1s = filter->cache;
+ filter->cache = 0;
+ if (c == 0x20E3) {
+ if (c1s == 0x0023) {
+ *s1 = 0x2817;
+ match = 1;
+ } else if (c1s == 0x0030) {
+ *s1 = 0x282c;
+ match = 1;
+ } else if (c1s >= 0x0031 && c1s <= 0x0039) {
+ *s1 = 0x2823 + (c1s - 0x0031);
+ match = 1;
+ }
+ } else if ((c >= NFLAGS(0x41) && c <= NFLAGS(0x5A)) && (c1s >= NFLAGS(0x41) && c1s <= NFLAGS(0x5A))) {
+ for (i=0; i<10; i++) {
+ if (c1s == NFLAGS(nflags_s[i][0]) && c == NFLAGS(nflags_s[i][1])) {
+ *s1 = nflags_code_sb[i];
+ match = 1;
+ break;
+ }
+ }
+ } else {
+ if (c1s >= ucs_a1_jis_table_min && c1s < ucs_a1_jis_table_max) {
+ c1s = ucs_a1_jis_table[c1s - ucs_a1_jis_table_min];
+ CK((*filter->output_function)(c1s, filter->data));
+ }
+ }
+ } else {
+ if (c == 0x0023 || ( c >= 0x0030 && c<=0x0039) || (c >= NFLAGS(0x41) && c<= NFLAGS(0x5A))) {
+ filter->status = 1;
+ filter->cache = c;
+ *s1 = -1;
+ return match;
+ }
+
+ if (c == 0x00A9) {
+ *s1 = 0x2855; match = 1;
+ } else if (c == 0x00AE) {
+ *s1 = 0x2856; match = 1;
+ } else if (c >= mb_tbl_uni_sb2code2_min && c <= mb_tbl_uni_sb2code2_max) {
+ i = mbfl_bisec_srch2(c, mb_tbl_uni_sb2code2_key, mb_tbl_uni_sb2code2_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_sb2code2_value[i];
+ match = 1;
+ }
+ } else if (c >= mb_tbl_uni_sb2code3_min && c <= mb_tbl_uni_sb2code3_max) {
+ i = mbfl_bisec_srch2(c - 0x10000, mb_tbl_uni_sb2code3_key, mb_tbl_uni_sb2code3_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_sb2code3_value[i];
+ match = 1;
+ }
+ } else if (c >= mb_tbl_uni_sb2code5_min && c <= mb_tbl_uni_sb2code5_max) {
+ i = mbfl_bisec_srch2(c - 0xf0000, mb_tbl_uni_sb2code5_key, mb_tbl_uni_sb2code5_len);
+ if (i >= 0) {
+ *s1 = mb_tbl_uni_sb2code5_val[i];
+ match = 1;
+ }
+ }
+ }
+ return match;
+}
+
+/*
+ * SJIS-win => wchar
+ */
+int
+mbfl_filt_conv_sjis_mobile_wchar(int c, mbfl_convert_filter *filter)
+{
+ int c1, s, s1, s2, w;
+ int snd = 0;
+
+retry:
+ switch (filter->status) {
+ case 0:
+ if (c >= 0 && c < 0x80) { /* latin */
+ if (filter->from->no_encoding == mbfl_no_encoding_sjis_sb && c == 0x1b) {
+ filter->cache = c;
+ filter->status = 2;
+ } else {
+ CK((*filter->output_function)(c, filter->data));
+ }
+ } else if (c > 0xa0 && c < 0xe0) { /* kana */
+ CK((*filter->output_function)(0xfec0 + c, filter->data));
+ } else if (c > 0x80 && c < 0xfd && c != 0xa0) { /* kanji first char */
+ filter->status = 1;
+ filter->cache = c;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+
+ case 1: /* kanji second char */
+ filter->status = 0;
+ c1 = filter->cache;
+ if (c >= 0x40 && c <= 0xfc && c != 0x7f) {
+ w = 0;
+ SJIS_DECODE(c1, c, s1, s2);
+ s = (s1 - 0x21)*94 + s2 - 0x21;
+ if (s <= 137) {
+ if (s == 31) {
+ w = 0xff3c; /* FULLWIDTH REVERSE SOLIDUS */
+ } else if (s == 32) {
+ w = 0xff5e; /* FULLWIDTH TILDE */
+ } else if (s == 33) {
+ w = 0x2225; /* PARALLEL TO */
+ } else if (s == 60) {
+ w = 0xff0d; /* FULLWIDTH HYPHEN-MINUS */
+ } else if (s == 80) {
+ w = 0xffe0; /* FULLWIDTH CENT SIGN */
+ } else if (s == 81) {
+ w = 0xffe1; /* FULLWIDTH POUND SIGN */
+ } else if (s == 137) {
+ w = 0xffe2; /* FULLWIDTH NOT SIGN */
+ }
+ }
+ if (w == 0) {
+ if (s >= cp932ext1_ucs_table_min && s < cp932ext1_ucs_table_max) { /* vendor ext1 (13ku) */
+ w = cp932ext1_ucs_table[s - cp932ext1_ucs_table_min];
+ } else if (s >= 0 && s < jisx0208_ucs_table_size) { /* X 0208 */
+ w = jisx0208_ucs_table[s];
+ } else if (s >= cp932ext2_ucs_table_min && s < cp932ext2_ucs_table_max) { /* vendor ext2 (89ku - 92ku) */
+ w = cp932ext2_ucs_table[s - cp932ext2_ucs_table_min];
+ } else if (s >= cp932ext3_ucs_table_min && s < cp932ext3_ucs_table_max) { /* vendor ext3 (115ku - 119ku) */
+ w = cp932ext3_ucs_table[s - cp932ext3_ucs_table_min];
+ } else if (s >= (94*94) && s < (114*94)) { /* user (95ku - 114ku) */
+ w = s - (94*94) + 0xe000;
+ }
+
+ if (s >= (94*94) && s < 119*94) {
+ if (filter->from->no_encoding == mbfl_no_encoding_sjis_docomo) {
+ w = mbfilter_sjis_emoji_docomo2unicode(s, &snd);
+ } else if (filter->from->no_encoding == mbfl_no_encoding_sjis_kddi) {
+ w = mbfilter_sjis_emoji_kddi2unicode(s, &snd);
+ } else if (filter->from->no_encoding == mbfl_no_encoding_sjis_sb) {
+ w = mbfilter_sjis_emoji_sb2unicode(s, &snd);
+ }
+
+ if (w > 0 && snd > 0) {
+ CK((*filter->output_function)(snd, filter->data));
+ }
+ }
+ }
+ if (w <= 0) {
+ w = (s1 << 8) | s2;
+ w &= MBFL_WCSPLANE_MASK;
+ w |= MBFL_WCSPLANE_WINCP932;
+ }
+ CK((*filter->output_function)(w, filter->data));
+ } else if ((c >= 0 && c < 0x21) || c == 0x7f) { /* CTLs */
+ CK((*filter->output_function)(c, filter->data));
+ } else {
+ w = (c1 << 8) | c;
+ w &= MBFL_WCSGROUP_MASK;
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ }
+ break;
+ /* ESC : Softbank Emoji */
+ case 2:
+ if (filter->from->no_encoding == mbfl_no_encoding_sjis_sb &&
+ c == 0x24) {
+ filter->cache = c;
+ filter->status++;
+ } else {
+ filter->cache = 0;
+ filter->status = 0;
+ CK((*filter->output_function)(0x1b, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC $ : Softbank Emoji */
+ case 3:
+ if (filter->from->no_encoding == mbfl_no_encoding_sjis_sb &&
+ ((c >= 0x45 && c <= 0x47) || (c >= 0x4f && c <= 0x51))) {
+ filter->cache = c;
+ filter->status++;
+ } else {
+ filter->cache = 0;
+ filter->status = 0;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ goto retry;
+ }
+ break;
+
+ /* ESC [GEFOPQ] : Softbank Emoji */
+ case 4:
+ w = 0;
+ if (filter->from->no_encoding == mbfl_no_encoding_sjis_sb) {
+ c1 = filter->cache;
+
+ if (c == 0x0f) {
+ w = c;
+ filter->cache = 0;
+ filter->status = 0;
+ } else {
+ if (c1 == 0x47 && c >= 0x21 && c <= 0x7a) {
+ s1 = 0x91; s2 = c;
+ } else if (c1 == 0x45 && c >= 0x21 && c <= 0x7a) {
+ s1 = 0x8d; s2 = c;
+ } else if (c1 == 0x46 && c >= 0x21 && c <= 0x7a) {
+ s1 = 0x8e; s2 = c;
+ } else if (c1 == 0x4f && c >= 0x21 && c <= 0x6d) {
+ s1 = 0x92; s2 = c;
+ } else if (c1 == 0x50 && c >= 0x21 && c <= 0x6c) {
+ s1 = 0x95; s2 = c;
+ } else if (c1 == 0x51 && c >= 0x21 && c <= 0x5e) {
+ s1 = 0x96; s2 = c;
+ }
+ s = (s1 - 0x21)*94 + s2 - 0x21;
+ w = mbfilter_sjis_emoji_sb2unicode(s, &snd);
+ if (w > 0) {
+ if (snd > 0) {
+ CK((*filter->output_function)(snd, filter->data));
+ }
+ CK((*filter->output_function)(w, filter->data));
+ }
+ }
+ }
+
+ if (w <= 0) {
+ c1 = filter->cache;
+ filter->cache = 0;
+ filter->status = 0;
+ CK((*filter->output_function)(0x1b, filter->data));
+ CK((*filter->output_function)(0x24, filter->data));
+ CK((*filter->output_function)(c1 & 0xff, filter->data));
+ goto retry;
+ }
+ break;
+
+ default:
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
+
+/*
+ * wchar => SJIS-win
+ */
+int
+mbfl_filt_conv_wchar_sjis_mobile(int c, mbfl_convert_filter *filter)
+{
+ int c1, c2, s1, s2;
+
+ s1 = 0;
+ s2 = 0;
+ if (c >= ucs_a1_jis_table_min && c < ucs_a1_jis_table_max) {
+ s1 = ucs_a1_jis_table[c - ucs_a1_jis_table_min];
+ } else if (c >= ucs_a2_jis_table_min && c < ucs_a2_jis_table_max) {
+ s1 = ucs_a2_jis_table[c - ucs_a2_jis_table_min];
+ } else if (c >= ucs_i_jis_table_min && c < ucs_i_jis_table_max) {
+ s1 = ucs_i_jis_table[c - ucs_i_jis_table_min];
+ } else if (c >= ucs_r_jis_table_min && c < ucs_r_jis_table_max) {
+ s1 = ucs_r_jis_table[c - ucs_r_jis_table_min];
+ } else if (c >= 0xe000 && c < (0xe000 + 20*94)) { /* user (95ku - 114ku) */
+ s1 = c - 0xe000;
+ c1 = s1/94 + 0x7f;
+ c2 = s1%94 + 0x21;
+ s1 = (c1 << 8) | c2;
+ s2 = 1;
+ }
+ if (s1 <= 0) {
+ c1 = c & ~MBFL_WCSPLANE_MASK;
+ if (c1 == MBFL_WCSPLANE_WINCP932) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ s2 = 1;
+ } else if (c1 == MBFL_WCSPLANE_JIS0208) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ } else if (c1 == MBFL_WCSPLANE_JIS0212) {
+ s1 = c & MBFL_WCSPLANE_MASK;
+ s1 |= 0x8080;
+ } else if (c == 0xa5) { /* YEN SIGN */
+ s1 = 0x216f; /* FULLWIDTH YEN SIGN */
+ } else if (c == 0x203e) { /* OVER LINE */
+ s1 = 0x2131; /* FULLWIDTH MACRON */
+ } else if (c == 0xff3c) { /* FULLWIDTH REVERSE SOLIDUS */
+ s1 = 0x2140;
+ } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
+ s1 = 0x2141;
+ } else if (c == 0x2225) { /* PARALLEL TO */
+ s1 = 0x2142;
+ } else if (c == 0xff0d) { /* FULLWIDTH HYPHEN-MINUS */
+ s1 = 0x215d;
+ } else if (c == 0xffe0) { /* FULLWIDTH CENT SIGN */
+ s1 = 0x2171;
+ } else if (c == 0xffe1) { /* FULLWIDTH POUND SIGN */
+ s1 = 0x2172;
+ } else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
+ s1 = 0x224c;
+ }
+ }
+
+ if ((s1 <= 0) || (s1 >= 0x8080 && s2 == 0)) { /* not found or X 0212 */
+ s1 = -1;
+ c1 = 0;
+ c2 = cp932ext1_ucs_table_max - cp932ext1_ucs_table_min;
+ while (c1 < c2) { /* CP932 vendor ext1 (13ku) */
+ if (c == cp932ext1_ucs_table[c1]) {
+ s1 = ((c1/94 + 0x2d) << 8) + (c1%94 + 0x21);
+ break;
+ }
+ c1++;
+ }
+ if (s1 <= 0) {
+ c1 = 0;
+ c2 = cp932ext2_ucs_table_max - cp932ext2_ucs_table_min;
+ while (c1 < c2) { /* CP932 vendor ext2 (115ku - 119ku) */
+ if (c == cp932ext2_ucs_table[c1]) {
+ s1 = ((c1/94 + 0x93) << 8) + (c1%94 + 0x21);
+ break;
+ }
+ c1++;
+ }
+ }
+
+ if (s1 <= 0) {
+ c1 = 0;
+ c2 = cp932ext3_ucs_table_max - cp932ext3_ucs_table_min;
+ while (c1 < c2) { /* CP932 vendor ext3 (115ku - 119ku) */
+ if (c == cp932ext3_ucs_table[c1]) {
+ s1 = ((c1/94 + 0x93) << 8) + (c1%94 + 0x21);
+ break;
+ }
+ c1++;
+ }
+ }
+ if (c == 0) {
+ s1 = 0;
+ } else if (s1 <= 0) {
+ s1 = -1;
+ }
+ }
+
+ if ((filter->to->no_encoding == mbfl_no_encoding_sjis_docomo &&
+ mbfilter_unicode2sjis_emoji_docomo(c, &s1, filter) > 0) ||
+ (filter->to->no_encoding == mbfl_no_encoding_sjis_kddi &&
+ mbfilter_unicode2sjis_emoji_kddi(c, &s1, filter) > 0) ||
+ (filter->to->no_encoding == mbfl_no_encoding_sjis_sb &&
+ mbfilter_unicode2sjis_emoji_sb(c, &s1, filter) > 0 )) {
+ CODE2JIS(c1,c2,s1,s2);
+ }
+
+ if (filter->status == 1 && filter->cache > 0) {
+ return c;
+ }
+
+ if (s1 >= 0) {
+ if (s1 < 0x100) { /* latin or kana */
+ CK((*filter->output_function)(s1, filter->data));
+ } else { /* kanji */
+ c1 = (s1 >> 8) & 0xff;
+ c2 = s1 & 0xff;
+ SJIS_ENCODE(c1, c2, s1, s2);
+ CK((*filter->output_function)(s1, filter->data));
+ CK((*filter->output_function)(s2, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+
+ return c;
+}
+
+int
+mbfl_filt_conv_sjis_mobile_flush(mbfl_convert_filter *filter)
+{
+ int c1 = filter->cache;
+ if (filter->status == 1 && (c1 == 0x0023 || (c1 >= 0x0030 && c1<=0x0039))) {
+ CK((*filter->output_function)(c1, filter->data));
+ }
+ filter->status = 0;
+ filter->cache = 0;
+
+ if (filter->flush_function != NULL) {
+ return (*filter->flush_function)(filter->data);
+ }
+
+ return 0;
+}
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.h b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.h
new file mode 100644
index 0000000000..15a91a58b5
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.h
@@ -0,0 +1,70 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * the source code included in this files was separated from mbfilter_sjis_open.c
+ * by Rui Hirokawa <hirokawa@php.net> on 25 July 2011.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_SJIS_MOBILE_H
+#define MBFL_MBFILTER_SJIS_MOBILE_H
+
+#include "mbfilter.h"
+
+extern const mbfl_encoding mbfl_encoding_sjis_docomo;
+extern const mbfl_encoding mbfl_encoding_sjis_kddi;
+extern const mbfl_encoding mbfl_encoding_sjis_sb;
+
+extern const struct mbfl_identify_vtbl vtbl_identify_sjis_docomo;
+extern const struct mbfl_identify_vtbl vtbl_identify_sjis_kddi;
+extern const struct mbfl_identify_vtbl vtbl_identify_sjis_sb;
+
+extern const struct mbfl_convert_vtbl vtbl_sjis_docomo_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_sjis_docomo;
+extern const struct mbfl_convert_vtbl vtbl_sjis_kddi_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_sjis_kddi;
+extern const struct mbfl_convert_vtbl vtbl_sjis_sb_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_sjis_sb;
+
+extern const unsigned short mbfl_docomo2uni_pua[4][3];
+extern const unsigned short mbfl_kddi2uni_pua[7][3];
+extern const unsigned short mbfl_sb2uni_pua[6][3];
+extern const unsigned short mbfl_kddi2uni_pua_b[8][3];
+
+int mbfl_filt_conv_sjis_mobile_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_sjis_mobile(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_sjis_mobile_flush(mbfl_convert_filter *filter);
+
+int mbfilter_sjis_emoji_docomo2unicode(int s, int *snd);
+int mbfilter_sjis_emoji_kddi2unicode(int s, int *snd);
+int mbfilter_sjis_emoji_sb2unicode(int s, int *snd);
+
+int mbfilter_unicode2sjis_emoji_docomo(int c, int *s1, mbfl_convert_filter *filter);
+int mbfilter_unicode2sjis_emoji_kddi(int c, int *s1, mbfl_convert_filter *filter);
+int mbfilter_unicode2sjis_emoji_sb(int c, int *s1, mbfl_convert_filter *filter);
+
+int mbfilter_conv_map_tbl(int c, int *w, const unsigned short map[][3], int n);
+int mbfilter_conv_r_map_tbl(int c, int *w, const unsigned short map[][3], int n);
+
+#endif /* MBFL_MBFILTER_SJIS_MOBILE_H */
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c
index 38244a0ac9..81ab32edfd 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c
@@ -66,7 +66,7 @@ const mbfl_encoding mbfl_encoding_sjis_open = {
"Shift_JIS",
(const char *(*)[])&mbfl_encoding_sjis_open_aliases,
mblen_table_sjis,
- MBFL_ENCTYPE_MBCS
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_sjis_open = {
@@ -139,7 +139,6 @@ const struct mbfl_convert_vtbl vtbl_wchar_sjis_open = {
} \
} while (0)
-
/*
* SJIS-win => wchar
*/
@@ -308,6 +307,7 @@ mbfl_filt_conv_wchar_sjis_open(int c, mbfl_convert_filter *filter)
s1 = -1;
}
}
+
if (s1 >= 0) {
if (s1 < 0x100) { /* latin or kana */
CK((*filter->output_function)(s1, filter->data));
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.h b/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.h
index 0bfe1d21ab..f24e42ea22 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.h
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.h
@@ -33,6 +33,7 @@
#include "mbfilter.h"
extern const mbfl_encoding mbfl_encoding_sjis_open;
+
extern const struct mbfl_identify_vtbl vtbl_identify_sjis_open;
extern const struct mbfl_convert_vtbl vtbl_sjis_open_wchar;
extern const struct mbfl_convert_vtbl vtbl_wchar_sjis_open;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_uhc.c b/ext/mbstring/libmbfl/filters/mbfilter_uhc.c
index c72d93f5fb..86765b2ece 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_uhc.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_uhc.c
@@ -33,6 +33,7 @@
#include "mbfilter.h"
#include "mbfilter_uhc.h"
+#define UNICODE_TABLE_UHC_DEF
#include "unicode_table_uhc.h"
static int mbfl_filt_ident_uhc(int c, mbfl_identify_filter *filter);
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf32.c b/ext/mbstring/libmbfl/filters/mbfilter_utf32.c
index 56d6dd4c97..3cef6b051a 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf32.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf32.c
@@ -173,6 +173,9 @@ int mbfl_filt_conv_utf32_wchar(int c, mbfl_convert_filter *filter)
filter->status &= ~0xff;
if (n < MBFL_WCSPLANE_UTF32MAX && (n < 0xd800 || n > 0xdfff)) {
CK((*filter->output_function)(n, filter->data));
+ } else {
+ n = (n & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(n, filter->data));
}
}
break;
@@ -205,6 +208,9 @@ int mbfl_filt_conv_utf32be_wchar(int c, mbfl_convert_filter *filter)
n = (c & 0xff) | filter->cache;
if (n < MBFL_WCSPLANE_UTF32MAX && (n < 0xd800 || n > 0xdfff)) {
CK((*filter->output_function)(n, filter->data));
+ } else {
+ n = (n & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(n, filter->data));
}
}
return c;
@@ -253,7 +259,10 @@ int mbfl_filt_conv_utf32le_wchar(int c, mbfl_convert_filter *filter)
n = ((c & 0xff) << 24) | filter->cache;
if (n < MBFL_WCSPLANE_UTF32MAX && (n < 0xd800 || n > 0xdfff)) {
CK((*filter->output_function)(n, filter->data));
- }
+ } else {
+ n = (n & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(n, filter->data));
+ }
}
return c;
}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf7.c b/ext/mbstring/libmbfl/filters/mbfilter_utf7.c
index ad0205bee1..2bb1dfada1 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf7.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf7.c
@@ -57,7 +57,7 @@ const mbfl_encoding mbfl_encoding_utf7 = {
"UTF-7",
(const char *(*)[])&mbfl_encoding_utf7_aliases,
NULL,
- MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE
+ MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_SHFTCODE | MBFL_ENCTYPE_GL_UNSAFE
};
const struct mbfl_identify_vtbl vtbl_identify_utf7 = {
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c
index c6777b29fd..fcee610533 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c
@@ -34,25 +34,25 @@
#include "mbfilter.h"
#include "mbfilter_utf8.h"
-static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter);
+int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter);
-static const unsigned char mblen_table_utf8[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
+const unsigned char mblen_table_utf8[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
static const char *mbfl_encoding_utf8_aliases[] = {"utf8", NULL};
@@ -98,73 +98,106 @@ const struct mbfl_convert_vtbl vtbl_wchar_utf8 = {
*/
int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter)
{
- int s;
+ int s, c1, w = 0, flag = 0;
if (c < 0x80) {
+ if (filter->status != 0) {
+ w = (filter->cache & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ filter->status = 0;
+ filter->cache = 0;
+ }
if (c >= 0) {
CK((*filter->output_function)(c, filter->data));
}
- filter->status = 0;
} else if (c < 0xc0) {
int status = filter->status & 0xff;
switch (status) {
- case 0x10: /* 2byte code 2nd char */
- case 0x21: /* 3byte code 3rd char */
- case 0x32: /* 4byte code 4th char */
- case 0x43: /* 5byte code 5th char */
- case 0x54: /* 6byte code 6th char */
+ case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
+ case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
+ case 0x32: /* 4byte code 4th char: 0x80-0xbf */
filter->status = 0;
s = filter->cache | (c & 0x3f);
+ filter->cache = 0;
if ((status == 0x10 && s >= 0x80) ||
(status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) ||
- (status == 0x32 && s >= 0x10000) ||
- (status == 0x43 && s >= 0x200000) ||
- (status == 0x54 && s >= 0x4000000 && s < MBFL_WCSGROUP_UCS4MAX)) {
+ (status == 0x32 && s >= 0x10000 && s < 0x110000)) {
CK((*filter->output_function)(s, filter->data));
+ } else {
+ w = s & MBFL_WCSGROUP_MASK;
+ flag = 1;
}
break;
- case 0x20: /* 3byte code 2nd char */
- case 0x31: /* 4byte code 3rd char */
- case 0x42: /* 5byte code 4th char */
- case 0x53: /* 6byte code 5th char */
- filter->cache |= ((c & 0x3f) << 6);
- filter->status++;
- break;
- case 0x30: /* 4byte code 2nd char */
- case 0x41: /* 5byte code 3rd char */
- case 0x52: /* 6byte code 4th char */
- filter->cache |= ((c & 0x3f) << 12);
- filter->status++;
+ case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
+ s = filter->cache | ((c & 0x3f) << 6);
+ c1 = (s >> 12) & 0xf;
+ if ((c1 == 0x0 && c >= 0xa0) ||
+ (c1 == 0xd && c < 0xa0) ||
+ (c1 > 0x0 && c1 != 0xd)) {
+ filter->cache = s;
+ filter->status++;
+ } else {
+ w = s & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
break;
- case 0x40: /* 5byte code 2nd char */
- case 0x51: /* 6byte code 3rd char */
- filter->cache |= ((c & 0x3f) << 18);
+ case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
+ filter->cache |= ((c & 0x3f) << 6);
filter->status++;
break;
- case 0x50: /* 6byte code 2nd char */
- filter->cache |= ((c & 0x3f) << 24);
- filter->status++;
+ case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
+ s = filter->cache | ((c & 0x3f) << 12);
+ c1 = (s >> 18) & 0x7;
+ if ((c1 == 0x0 && c >= 0x90) ||
+ (c1 > 0x0 && c1 < 0x4) ||
+ (c1 == 0x4 && c < 0x90)) {
+ filter->cache = s;
+ filter->status++;
+ } else {
+ w = s & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
break;
default:
- filter->status = 0;
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
break;
}
- } else if (c < 0xe0) { /* 2byte code first char */
- filter->status = 0x10;
- filter->cache = (c & 0x1f) << 6;
- } else if (c < 0xf0) { /* 3byte code first char */
- filter->status = 0x20;
- filter->cache = (c & 0xf) << 12;
- } else if (c < 0xf8) { /* 4byte code first char */
- filter->status = 0x30;
- filter->cache = (c & 0x7) << 18;
- } else if (c < 0xfc) { /* 5byte code first char */
- filter->status = 0x40;
- filter->cache = (c & 0x3) << 24;
- } else if (c < 0xfe) { /* 6 byte code first char */
- filter->status = 0x50;
- filter->cache = (c & 0x1) << 30;
+ } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */
+ if (filter->status == 0x0) {
+ filter->status = 0x10;
+ filter->cache = (c & 0x1f) << 6;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */
+ if (filter->status == 0x0) {
+ filter->status = 0x20;
+ filter->cache = (c & 0xf) << 12;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */
+ if (filter->status == 0x0) {
+ filter->status = 0x30;
+ filter->cache = (c & 0x7) << 18;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
} else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+
+ if (flag) {
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
filter->status = 0;
filter->cache = 0;
}
@@ -177,7 +210,7 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter)
*/
int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter)
{
- if (c >= 0 && c < MBFL_WCSGROUP_UCS4MAX) {
+ if (c >= 0 && c < 0x110000) {
if (c < 0x80) {
CK((*filter->output_function)(c, filter->data));
} else if (c < 0x800) {
@@ -187,21 +220,8 @@ int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter)
CK((*filter->output_function)(((c >> 12) & 0x0f) | 0xe0, filter->data));
CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
- } else if (c < 0x200000) {
- CK((*filter->output_function)(((c >> 18) & 0x07) | 0xf0, filter->data));
- CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
- CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
- CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
- } else if (c < 0x4000000) {
- CK((*filter->output_function)(((c >> 24) & 0x03) | 0xf8, filter->data));
- CK((*filter->output_function)(((c >> 18) & 0x3f) | 0x80, filter->data));
- CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
- CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
- CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
} else {
- CK((*filter->output_function)(((c >> 30) & 0x01) | 0xfc, filter->data));
- CK((*filter->output_function)(((c >> 24) & 0x3f) | 0x80, filter->data));
- CK((*filter->output_function)(((c >> 18) & 0x3f) | 0x80, filter->data));
+ CK((*filter->output_function)(((c >> 18) & 0x07) | 0xf0, filter->data));
CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
@@ -215,8 +235,13 @@ int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter)
return c;
}
-static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
+int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
{
+ int c1;
+
+ c1 = (filter->status >> 8) & 0xff;
+ filter->status &= 0xff;
+
if (c < 0x80) {
if (c < 0) {
filter->flag = 1; /* bad */
@@ -227,22 +252,31 @@ static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
} else if (c < 0xc0) {
switch (filter->status) {
case 0x20: /* 3 byte code 2nd char */
+ if ((c1 == 0x0 && c >= 0xa0) ||
+ (c1 == 0xd && c < 0xa0) ||
+ (c1 > 0x0 && c1 != 0xd)) {
+ filter->status++;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status = 0;
+ }
+ break;
case 0x30: /* 4 byte code 2nd char */
+ if ((c1 == 0x0 && c >= 0x90) ||
+ (c1 > 0x0 && c1 < 0x4) ||
+ (c1 == 0x4 && c < 0x90)) {
+ filter->status++;
+ } else {
+ filter->flag = 1; /* bad */
+ filter->status = 0;
+ }
+ break;
case 0x31: /* 4 byte code 3rd char */
- case 0x40: /* 5 byte code 2nd char */
- case 0x41: /* 5 byte code 3rd char */
- case 0x42: /* 5 byte code 4th char */
- case 0x50: /* 6 byte code 2nd char */
- case 0x51: /* 6 byte code 3rd char */
- case 0x52: /* 6 byte code 4th char */
- case 0x53: /* 6 byte code 5th char */
filter->status++;
break;
case 0x10: /* 2 byte code 2nd char */
case 0x21: /* 3 byte code 3rd char */
case 0x32: /* 4 byte code 4th char */
- case 0x43: /* 5 byte code 5th char */
- case 0x54: /* 6 byte code 6th char */
filter->status = 0;
break;
default:
@@ -250,6 +284,9 @@ static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
filter->status = 0;
break;
}
+ } else if (c < 0xc2) { /* 0xc0,0xc1 */
+ filter->flag = 1; /* bad */
+ filter->status = 0;
} else {
if (filter->status) {
filter->flag = 1; /* bad */
@@ -259,12 +296,10 @@ static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
filter->status = 0x10;
} else if (c < 0xf0) { /* 3 byte code 1st char */
filter->status = 0x20;
- } else if (c < 0xf8) { /* 4 byte code 1st char */
+ filter->status |= (c & 0xf) << 8;
+ } else if (c < 0xf5) { /* 4 byte code 1st char */
filter->status = 0x30;
- } else if (c < 0xfc) { /* 5 byte code 1st char */
- filter->status = 0x40;
- } else if (c < 0xfe) { /* 6 byte code 1st char */
- filter->status = 0x50;
+ filter->status |= (c & 0x7) << 8;
} else {
filter->flag = 1; /* bad */
}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c
new file mode 100644
index 0000000000..62feca40b6
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c
@@ -0,0 +1,362 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter.c
+ * by rui hrokawa <hirokawa@php.net> on 8 aug 2011.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mbfilter.h"
+
+#include "mbfilter_utf8_mobile.h"
+#include "mbfilter_sjis_mobile.h"
+
+extern int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter);
+
+extern const unsigned char mblen_table_utf8[];
+
+static const char *mbfl_encoding_utf8_docomo_aliases[] = {"UTF-8-DOCOMO", "UTF8-DOCOMO", NULL};
+static const char *mbfl_encoding_utf8_kddi_a_aliases[] = {NULL};
+static const char *mbfl_encoding_utf8_kddi_b_aliases[] = {"UTF-8-Mobile#KDDI", "UTF-8-KDDI", "UTF8-KDDI", NULL};
+static const char *mbfl_encoding_utf8_sb_aliases[] = {"UTF-8-SOFTBANK", "UTF8-SOFTBANK", NULL};
+
+const mbfl_encoding mbfl_encoding_utf8_docomo = {
+ mbfl_no_encoding_utf8_docomo,
+ "UTF-8-Mobile#DOCOMO",
+ "UTF-8",
+ (const char *(*)[])&mbfl_encoding_utf8_docomo_aliases,
+ mblen_table_utf8,
+ MBFL_ENCTYPE_MBCS
+};
+
+const mbfl_encoding mbfl_encoding_utf8_kddi_a = {
+ mbfl_no_encoding_utf8_kddi_a,
+ "UTF-8-Mobile#KDDI-A",
+ "UTF-8",
+ (const char *(*)[])&mbfl_encoding_utf8_kddi_a_aliases,
+ mblen_table_utf8,
+ MBFL_ENCTYPE_MBCS
+};
+
+const mbfl_encoding mbfl_encoding_utf8_kddi_b = {
+ mbfl_no_encoding_utf8_kddi_b,
+ "UTF-8-Mobile#KDDI-B",
+ "UTF-8",
+ (const char *(*)[])&mbfl_encoding_utf8_kddi_b_aliases,
+ mblen_table_utf8,
+ MBFL_ENCTYPE_MBCS
+};
+
+const mbfl_encoding mbfl_encoding_utf8_sb = {
+ mbfl_no_encoding_utf8_sb,
+ "UTF-8-Mobile#SOFTBANK",
+ "UTF-8",
+ (const char *(*)[])&mbfl_encoding_utf8_sb_aliases,
+ mblen_table_utf8,
+ MBFL_ENCTYPE_MBCS
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf8_docomo = {
+ mbfl_no_encoding_utf8_docomo,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_utf8
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf8_kddi_a = {
+ mbfl_no_encoding_utf8_kddi_a,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_utf8
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf8_kddi_b = {
+ mbfl_no_encoding_utf8_kddi_b,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_utf8
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf8_sb = {
+ mbfl_no_encoding_utf8_sb,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_common_dtor,
+ mbfl_filt_ident_utf8
+};
+
+const struct mbfl_convert_vtbl vtbl_utf8_docomo_wchar = {
+ mbfl_no_encoding_utf8_docomo,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_utf8_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_utf8_docomo = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_utf8_docomo,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_utf8_mobile,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_utf8_kddi_a_wchar = {
+ mbfl_no_encoding_utf8_kddi_a,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_utf8_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_a = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_utf8_kddi_a,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_utf8_mobile,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_utf8_kddi_b_wchar = {
+ mbfl_no_encoding_utf8_kddi_b,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_utf8_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_b = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_utf8_kddi_b,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_utf8_mobile,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_utf8_sb_wchar = {
+ mbfl_no_encoding_utf8_sb,
+ mbfl_no_encoding_wchar,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_utf8_mobile_wchar,
+ mbfl_filt_conv_common_flush
+};
+
+const struct mbfl_convert_vtbl vtbl_wchar_utf8_sb = {
+ mbfl_no_encoding_wchar,
+ mbfl_no_encoding_utf8_sb,
+ mbfl_filt_conv_common_ctor,
+ mbfl_filt_conv_common_dtor,
+ mbfl_filt_conv_wchar_utf8_mobile,
+ mbfl_filt_conv_common_flush
+};
+
+#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
+
+/*
+ * UTF-8 => wchar
+ */
+int mbfl_filt_conv_utf8_mobile_wchar(int c, mbfl_convert_filter *filter)
+{
+ int s, w = 0, flag = 0;
+ int s1 = 0, c1 = 0, snd = 0;
+
+ if (c < 0x80) {
+ if (c >= 0) {
+ CK((*filter->output_function)(c, filter->data));
+ }
+ filter->status = 0;
+ } else if (c < 0xc0) {
+ int status = filter->status & 0xff;
+ switch (status) {
+ case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
+ case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
+ case 0x32: /* 4byte code 4th char: 0x80-0xbf */
+ filter->status = 0;
+ s = filter->cache | (c & 0x3f);
+ filter->cache = 0;
+ if ((status == 0x10 && s >= 0x80) ||
+ (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) ||
+ (status == 0x32 && s >= 0x10000 && s < 0x110000)) {
+
+ if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo &&
+ mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) {
+ s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd);
+ } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a &&
+ mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) {
+ s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd);
+ } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b &&
+ mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) {
+ s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd);
+ } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb &&
+ mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) {
+ s = mbfilter_sjis_emoji_sb2unicode(s1, &snd);
+ }
+
+ if (snd > 0) {
+ CK((*filter->output_function)(snd, filter->data));
+ }
+ CK((*filter->output_function)(s, filter->data));
+ } else {
+ w = s & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ break;
+ case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
+ s = filter->cache | ((c & 0x3f) << 6);
+ c1 = (s >> 12) & 0xf;
+ if ((c1 == 0x0 && c >= 0xa0) ||
+ (c1 == 0xd && c < 0xa0) ||
+ (c1 > 0x0 && c1 != 0xd)) {
+ filter->cache = s;
+ filter->status++;
+ } else {
+ w = s & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ break;
+ case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
+ filter->cache |= ((c & 0x3f) << 6);
+ filter->status++;
+ break;
+ case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
+ s = filter->cache | ((c & 0x3f) << 12);
+ c1 = (s >> 18) & 0x7;
+ if ((c1 == 0x0 && c >= 0x90) ||
+ (c1 > 0x0 && c1 < 0x4) ||
+ (c1 == 0x4 && c < 0x90)) {
+ filter->cache = s;
+ filter->status++;
+ } else {
+ w = s & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ break;
+ default:
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ break;
+ }
+ } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */
+ if (filter->status == 0x0) {
+ filter->status = 0x10;
+ filter->cache = (c & 0x1f) << 6;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */
+ if (filter->status == 0x0) {
+ filter->status = 0x20;
+ filter->cache = (c & 0xf) << 12;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */
+ if (filter->status == 0x0) {
+ filter->status = 0x30;
+ filter->cache = (c & 0x7) << 18;
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+ } else {
+ w = c & MBFL_WCSGROUP_MASK;
+ flag = 1;
+ }
+
+ if (flag) {
+ w |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(w, filter->data));
+ filter->status = 0;
+ filter->cache = 0;
+ }
+
+ return c;
+}
+
+/*
+ * wchar => UTF-8
+ */
+int mbfl_filt_conv_wchar_utf8_mobile(int c, mbfl_convert_filter *filter)
+{
+ if (c >= 0 && c < 0x110000) {
+ int s1, c1;
+
+ if ((filter->to->no_encoding == mbfl_no_encoding_utf8_docomo &&
+ mbfilter_unicode2sjis_emoji_docomo(c, &s1, filter) > 0 &&
+ mbfilter_conv_map_tbl(s1, &c1, mbfl_docomo2uni_pua, 4) > 0) ||
+ (filter->to->no_encoding == mbfl_no_encoding_utf8_kddi_a &&
+ mbfilter_unicode2sjis_emoji_kddi(c, &s1, filter) > 0 &&
+ mbfilter_conv_map_tbl(s1, &c1, mbfl_kddi2uni_pua, 7) > 0) ||
+ (filter->to->no_encoding == mbfl_no_encoding_utf8_kddi_b &&
+ mbfilter_unicode2sjis_emoji_kddi(c, &s1, filter) > 0 &&
+ mbfilter_conv_map_tbl(s1, &c1, mbfl_kddi2uni_pua_b, 8) > 0) ||
+ (filter->to->no_encoding == mbfl_no_encoding_utf8_sb &&
+ mbfilter_unicode2sjis_emoji_sb(c, &s1, filter) > 0 &&
+ mbfilter_conv_map_tbl(s1, &c1, mbfl_sb2uni_pua, 6) > 0)) {
+ c = c1;
+ }
+
+ if (filter->status == 1 && filter->cache > 0) {
+ return c;
+ }
+
+ if (c < 0x80) {
+ CK((*filter->output_function)(c, filter->data));
+ } else if (c < 0x800) {
+ CK((*filter->output_function)(((c >> 6) & 0x1f) | 0xc0, filter->data));
+ CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
+ } else if (c < 0x10000) {
+ CK((*filter->output_function)(((c >> 12) & 0x0f) | 0xe0, filter->data));
+ CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
+ CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
+ } else {
+ CK((*filter->output_function)(((c >> 18) & 0x07) | 0xf0, filter->data));
+ CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
+ CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
+ CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
+ }
+ } else {
+ if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
+ CK(mbfl_filt_conv_illegal_output(c, filter));
+ }
+ }
+
+ return c;
+}
+
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.h b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.h
new file mode 100644
index 0000000000..ef5e6da7f9
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.h
@@ -0,0 +1,55 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file:
+ *
+ */
+/*
+ * The source code included in this files was separated from mbfilter.c
+ * by rui hrokawa <hirokawa@php.net> on 8 aug 2011.
+ *
+ */
+
+#ifndef MBFL_MBFILTER_UTF8_MOBILE_H
+#define MBFL_MBFILTER_UTF8_MOBILE_H
+
+extern const mbfl_encoding mbfl_encoding_utf8_docomo;
+extern const mbfl_encoding mbfl_encoding_utf8_kddi_a;
+extern const mbfl_encoding mbfl_encoding_utf8_kddi_b;
+extern const mbfl_encoding mbfl_encoding_utf8_sb;
+
+extern const struct mbfl_identify_vtbl vtbl_identify_utf8_docomo;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf8_kddi_a;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf8_kddi_b;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf8_sb;
+
+extern const struct mbfl_convert_vtbl vtbl_utf8_docomo_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_utf8_docomo;
+extern const struct mbfl_convert_vtbl vtbl_utf8_kddi_a_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_a;
+extern const struct mbfl_convert_vtbl vtbl_utf8_kddi_b_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_b;
+extern const struct mbfl_convert_vtbl vtbl_utf8_sb_wchar;
+extern const struct mbfl_convert_vtbl vtbl_wchar_utf8_sb;
+
+int mbfl_filt_conv_utf8_mobile_wchar(int c, mbfl_convert_filter *filter);
+int mbfl_filt_conv_wchar_utf8_mobile(int c, mbfl_convert_filter *filter);
+
+#endif /* MBFL_MBFILTER_UTF8_MOBILE_H */
diff --git a/ext/mbstring/libmbfl/filters/mk_emoji_tbl.pl b/ext/mbstring/libmbfl/filters/mk_emoji_tbl.pl
new file mode 100755
index 0000000000..5b5c3d63ff
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/mk_emoji_tbl.pl
@@ -0,0 +1,425 @@
+#!/usr/bin/perl
+# script to generate Shift_JIS encoded Emoji to/from Unicode conversion table.
+# Rui Hirokawa <hirokawa@php.net>
+#
+# usage: mktbl.pl EmojiSources.txt
+#
+# Unicoe;DoCoMo;KDDI;SoftBank
+
+@docomo = ();
+@kddi = ();
+@softbank = ();
+
+@to_docomo = ();
+@to_kddi = ();
+@to_sb = ();
+
+$fname = "emoji2uni.h";
+open(OUT,">$fname") or die $!;
+
+sub sjis2code {
+ my @c = unpack("C*", pack("H4", $_[0]));
+
+ # Shift_JIS -> JIS
+ $c[0] = (($c[0]-($c[0]<160?112:176))<<1)-($c[1]<159?1:0);
+ $c[1] -= ($c[1]<159?($c[1]>127?32:31):126);
+
+ $s = ($c[0] - 0x21)*94 + $c[1]-0x21;
+
+ return $s;
+}
+
+sub show_code {
+ my @c = @_;
+ $s = "\t";
+ for ($i=0; $i<=$#c; $i++) {#
+ if ($c[$i]) {
+ @v = split(' ',$c[$i]);
+ $s .= "0x$v[0], \t";
+ if ($#v > 0) {
+ print "$i $v[0] $v[1]\n";
+ }
+ } else {
+ $s .= "0x0000, \t";
+ }
+ if ($i % 4 == 3) {
+ $s .= "\n\t";
+ }
+ }
+ return $s;
+}
+
+while(<>) {
+ if ($_ =~ /^\d+/) {
+ @v = split(/;/,$_);
+ if ($v[1] =~ /[\dA-F]+/) {
+ $code = &sjis2code($v[1]);
+ $docomo{$code} = $v[0];
+ $to_docomo{$v[0]} = $code;
+ }
+ if ($v[2] =~ /[\dA-F]+/) {
+ $code = &sjis2code($v[2]);
+ $kddi{$code} = $v[0];
+ $to_kddi{$v[0]} = $code;
+ }
+ if ($v[3] =~ /[\dA-F]+/) {
+ $code = &sjis2code($v[3]);
+ $softbank{$code} = $v[0];
+ $to_sb{$v[0]} = $code;
+ }
+ }
+}
+
+print "DoCoMo\n";
+
+$docomo_min = 10434;
+$docomo_max = 10434+281;
+@docomo_v = ();
+
+foreach $key (sort {hex($a) <=> hex($b)} keys(%docomo)) {
+ $s = $key;
+ $pos = $s % 94;
+ $ku = ($s - $pos)/94;
+ $v = $key - $docomo_min;
+ #print "$ku:$pos - ". $v ."=> $docomo{$key}\n";
+ $docomo_v[$key-$docomo_min] = $docomo{$key};
+}
+
+$to_docomo_min = 10434;
+
+$to_docomo_min1 = 0x0023;
+$to_docomo_max1 = 0x00AE;
+$to_docomo_min2 = 0x203C;
+$to_docomo_max2 = 0x3299;
+$to_docomo_min3 = 0x1F17F;
+$to_docomo_max3 = 0x1F6BB;
+
+@r_docomo1_key = ();
+@r_docomo1_val = ();
+
+@r_docomo2_key = ();
+@r_docomo2_val = ();
+
+@r_docomo3_key = ();
+@r_docomo3_val = ();
+
+
+foreach $key (sort {hex($a) <=> hex($b)} keys(%to_docomo)) {
+ $s = $to_docomo{$key};
+
+ $pos = $s % 94;
+ $ku = ($s - $pos)/94;
+ $v = $to_docomo{$key} - $to_docomo_min;
+ $h = sprintf("%x",$s);
+ #print "$ku:$pos = $h ($v) <= $key\n";
+ if (hex($key) <= $to_docomo_max1) {
+ push(@r_docomo1_key, $key);
+ push(@r_docomo1_val, sprintf("%x", $to_docomo{$key}));
+ } elsif (hex($key) <= $to_docomo_max2) {
+ push(@r_docomo2_key, $key);
+ push(@r_docomo2_val, $h);
+ } elsif (hex($key) >= $to_docomo_max3) {
+ push(@r_docomo3_key, $key);
+ push(@r_docomo3_val, $h);
+ }
+}
+
+push(@r_docomo1_key, 0x00);
+push(@r_docomo1_val, 0x00);
+push(@r_docomo2_key, 0x00);
+push(@r_docomo2_val, 0x00);
+push(@r_docomo3_key, 0x00);
+push(@r_docomo3_val, 0x00);
+
+print OUT "int mb_tbl_code2uni_docomo_min = $docomo_min;\n";
+print OUT "int mb_tbl_code2uni_docomo_max = $docomo_max;\n\n";
+
+print OUT "int mb_tbl_code2uni_docomo[] = {\n";
+print OUT &show_code(@docomo_v);
+print OUT "};\n\n";
+
+print OUT "int mb_tbl_uni_docomo2code_min1 = $to_docomo_min1;\n";
+print OUT "int mb_tbl_uni_docomo2code_max1 = $to_docomo_max1;\n";
+print OUT "int mb_tbl_uni_docomo2code_min2 = $to_docomo_min2;\n";
+print OUT "int mb_tbl_uni_docomo2code_max2 = $to_docomo_max2;\n";
+print OUT "int mb_tbl_uni_docomo2code_min3 = $to_docomo_min3;\n";
+print OUT "int mb_tbl_uni_docomo2code_max3 = $to_docomo_max3;\n\n";
+
+#print "DOCOMO reverse 1\n";
+
+print OUT "int mb_tbl_uni_docomo2code_key1[] = {\n";
+print OUT &show_code(@r_docomo1_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_docomo2code_val1[] = {\n";
+print OUT &show_code(@r_docomo1_val),"\n";
+print OUT "};\n\n";
+
+#print "DOCOMO reverse 2\n";
+
+print OUT "int mb_tbl_uni_docomo2code_key2[] = {\n";
+print OUT &show_code(@r_docomo2_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_docomo2code_val2[] = {\n";
+print OUT &show_code(@r_docomo2_val),"\n";
+print OUT "};\n\n";
+
+print "DOCOMO reverse 3\n";
+
+print OUT "int mb_tbl_uni_docomo2code_key3[] = {\n";
+print OUT &show_code(@r_docomo3_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_docomo2code_val3[] = {\n";
+print OUT &show_code(@r_docomo3_val),"\n";
+print OUT "};\n\n";
+
+#print "DOCOMO reverse end \n";
+
+$kddi_min1 = 9400;
+$kddi_max1 = 9400+264;
+$kddi_min2 = 9400+564;
+$kddi_max2 = 9400+939;
+
+@kddi_v1 = ();
+@kddi_v2 = ();
+
+#print "KDDI\n";
+
+foreach $key (sort {hex($a) <=> hex($b)} keys(%kddi)) {
+ $s = $key;
+ $pos = $s % 94;
+ $ku = ($s - $pos)/94;
+ $v = $key - $kddi_min1;
+ $h = sprintf("%x",$key);
+ #print "$ku:$pos :: $v ($h) => $kddi{$key}\n";
+
+ if ($key <= $kddi_max1) {
+ $kddi_v1[$key-$kddi_min1] = $kddi{$key};
+ } elsif ($key <= $kddi_max2) {
+ $kddi_v2[$key-$kddi_min2] = $kddi{$key};
+ }
+}
+
+$to_kddi_min = 9660;
+$to_kddi_min1 = 0x0030;
+$to_kddi_max1 = 0x00AE;
+$to_kddi_min2 = 0x2002;
+$to_kddi_max2 = 0x3299;
+$to_kddi_min3 = 0x1F004;
+$to_kddi_max3 = 0x1F6C0;
+
+@r_kddi1_key = (); @r_kddi1_val = ();
+@r_kddi2_key = (); @r_kddi2_val = ();
+@r_kddi3_key = (); @r_kddi3_val = ();
+
+foreach $key (sort {hex($a) <=> hex($b)} keys(%to_kddi)) {
+ $s = $to_kddi{$key};
+
+ $pos = $s % 94;
+ $ku = ($s - $pos)/94;
+ $v = $to_kddi{$key} - $to_kddi_min;
+ $h = sprintf("%x",$s);
+ #print "$ku:$pos = $h ($v) <= $key\n";
+ if (hex($key) <= $to_kddi_max1) {
+ push(@r_kddi1_key, $key);
+ push(@r_kddi1_val, $h);
+ } elsif (hex($key) <= $to_kddi_max2) {
+ push(@r_kddi2_key, $key);
+ push(@r_kddi2_val, $h);
+ } else {
+ push(@r_kddi3_key, $key);
+ push(@r_kddi3_val, $h);
+ }
+}
+
+push(@r_kddi1_key, 0x00);
+push(@r_kddi1_val, 0x00);
+push(@r_kddi2_key, 0x00);
+push(@r_kddi2_val, 0x00);
+push(@r_kddi3_key, 0x00);
+push(@r_kddi3_val, 0x00);
+
+print OUT "int mb_tbl_code2uni_kddi1_min = $kddi_min1;\n";
+print OUT "int mb_tbl_code2uni_kddi1_max = $kddi_max1;\n";
+print OUT "int mb_tbl_code2uni_kddi2_min = $kddi_min2;\n";
+print OUT "int mb_tbl_code2uni_kddi2_max = $kddi_max2;\n\n";
+
+#print "KDDI 1\n";
+
+print OUT "int mb_tbl_code2uni_kddi1[] = {\n";
+print OUT &show_code(@kddi_v1);
+print OUT "};\n\n";
+
+#print "KDDI 2\n";
+
+print OUT "int mb_tbl_code2uni_kddi2[] = {\n";
+print OUT &show_code(@kddi_v2);
+print OUT "};\n\n";
+
+print OUT "int mb_tbl_uni_kddi2code_min1 = $to_kddi_min1;\n";
+print OUT "int mb_tbl_uni_kddi2code_max1 = $to_kddi_max1;\n";
+print OUT "int mb_tbl_uni_kddi2code_min2 = $to_kddi_min2;\n";
+print OUT "int mb_tbl_uni_kddi2code_max2 = $to_kddi_max2;\n";
+print OUT "int mb_tbl_uni_kddi2code_min3 = $to_kddi_min3;\n";
+print OUT "int mb_tbl_uni_kddi2code_max3 = $to_kddi_max3;\n\n";
+
+#print "KDDI reverse 1\n";
+
+print OUT "int mb_tbl_uni_kddi2code_key1[] = {\n";
+print OUT &show_code(@r_kddi1_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_kddi2code_val1[] = {\n";
+print OUT &show_code(@r_kddi1_val),"\n";
+print OUT "};\n\n";
+
+#print "KDDI reverse 1\n";
+
+print OUT "int mb_tbl_uni_kddi2code_key2[] = {\n";
+print OUT &show_code(@r_kddi2_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_kddi2code_val2[] = {\n";
+print OUT &show_code(@r_kddi2_val),"\n";
+print OUT "};\n\n";
+
+#print "KDDI reverse 3\n";
+
+print OUT "int mb_tbl_uni_kddi2code_key3[] = {\n";
+print OUT &show_code(@r_kddi3_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_kddi2code_val3[] = {\n";
+print OUT &show_code(@r_kddi3_val),"\n";
+print OUT "};\n\n";
+
+
+$sb_min1 = 10153;
+$sb_max1 = 10153+177;
+$sb_min2 = 10153+376;
+$sb_max2 = 10153+547;
+$sb_min3 = 10153+752;
+$sb_max3 = 10153+901;
+
+@sb_v1 = ();
+@sb_v2 = ();
+@sb_v3 = ();
+
+if (1) {
+ print "SoftBank\n";
+
+ foreach $key (sort {hex($a) <=> hex($b)} keys(%softbank)) {
+ $s = $key;
+ $pos = $s % 94;
+ $ku = ($s - $pos)/94;
+ $v = $key - $sb_min1;
+ $h = sprintf("%x",$key);
+ #print "$ku:$pos :: $v ($h) => $softbank{$key}\n";
+ if ($key <= $sb_max1) {
+ $sb_v1[$key-$sb_min1] = $softbank{$key};
+ } elsif ($key <= $sb_max2) {
+ $sb_v2[$key-$sb_min2] = $softbank{$key};
+ } elsif ($key <= $sb_max3) {
+ $sb_v3[$key-$sb_min3] = $softbank{$key};
+ }
+ }
+
+}
+
+$to_sb_min = 10263;
+$to_sb_min1 = 0x0023;
+$to_sb_max1 = 0x00AE;
+$to_sb_min2 = 0x2122;
+$to_sb_max2 = 0x3299;
+$to_sb_min3 = 0x1F004;
+$to_sb_max3 = 0x1F6C0;
+
+@r_sb1_key = (); @r_sb1_val = ();
+@r_sb2_key = (); @r_sb2_val = ();
+@r_sb3_key = (); @r_sb3_val = ();
+
+foreach $key (sort {hex($a) <=> hex($b)} keys(%to_sb)) {
+ $s = $to_sb{$key};
+
+ $pos = $s % 94;
+ $ku = ($s - $pos)/94;
+ $v = $to_sb{$key} - $to_sb_min;
+ $h = sprintf("%x",$s);
+ #print "$ku:$pos = $h ($v) <= $key\n";
+ if (hex($key) <= $to_sb_max1) {
+ push(@r_sb1_key, $key);
+ push(@r_sb1_val, $h);
+ } elsif (hex($key) >= $to_sb_min2 && hex($key) <= $to_sb_max2) {
+ push(@r_sb2_key, $key);
+ push(@r_sb2_val, $h);
+ } else {
+ push(@r_sb3_key, $key);
+ push(@r_sb3_val, $h);
+ }
+}
+
+push(@r_sb1_key, 0x00);
+push(@r_sb1_val, 0x00);
+push(@r_sb2_key, 0x00);
+push(@r_sb2_val, 0x00);
+push(@r_sb3_key, 0x00);
+push(@r_sb3_val, 0x00);
+
+
+print OUT "int mb_tbl_code2uni_sb1_min = $sb_min1;\n";
+print OUT "int mb_tbl_code2uni_sb1_max = $sb_max1;\n";
+print OUT "int mb_tbl_code2uni_sb2_min = $sb_min2;\n";
+print OUT "int mb_tbl_code2uni_sb2_max = $sb_max2;\n";
+print OUT "int mb_tbl_code2uni_sb3_min = $sb_min3;\n";
+print OUT "int mb_tbl_code2uni_sb3_max = $sb_max3;\n\n";
+
+#print "SoftBank 1\n";
+
+print OUT "int mb_tbl_code2uni_sb1[] = {\n";
+print OUT &show_code(@sb_v1);
+print OUT "};\n\n";
+
+#print "SoftBank 2\n";
+
+print OUT "int mb_tbl_code2uni_sb2[] = {\n";
+print OUT &show_code(@sb_v2);
+print OUT "};\n\n";
+
+#print "SoftBank 3\n";
+
+print OUT "int mb_tbl_code2uni_sb3[] = {\n";
+print OUT &show_code(@sb_v3);
+print OUT "};\n\n";
+
+print OUT "int mb_tbl_uni_sb2code_min1 = $to_sb_min1;\n";
+print OUT "int mb_tbl_uni_sb2code_max1 = $to_sb_max1;\n";
+print OUT "int mb_tbl_uni_sb2code_min2 = $to_sb_min2;\n";
+print OUT "int mb_tbl_uni_sb2code_max2 = $to_sb_max2;\n";
+print OUT "int mb_tbl_uni_sb2code_min3 = $to_sb_min3;\n";
+print OUT "int mb_tbl_uni_sb2code_max3 = $to_sb_max3;\n\n";
+
+#print "SB reverse 1\n";
+
+print OUT "int mb_tbl_uni_sb2code_key1[] = {\n";
+print OUT &show_code(@r_sb1_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_sb2code_val1[] = {\n";
+print OUT &show_code(@r_sb1_val),"\n";
+print OUT "};\n\n";
+
+#print "SB reverse 2\n";
+
+print OUT "int mb_tbl_uni_sb2code_key2[] = {\n";
+print OUT &show_code(@r_sb2_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_sb2code_val2[] = {\n";
+print OUT &show_code(@r_sb2_val),"\n";
+print OUT "};\n\n";
+
+#print "SB reverse 3\n";
+
+print OUT "int mb_tbl_uni_sb2code_key3[] = {\n";
+print OUT &show_code(@r_sb3_key),"\n";
+print OUT "};\n\n";
+print OUT "int mb_tbl_uni_sb2code_val3[] = {\n";
+print OUT &show_code(@r_sb3_val),"\n";
+print OUT "};\n\n";
+
+
+close(OUT);
diff --git a/ext/mbstring/libmbfl/filters/sjis_mac2uni.h b/ext/mbstring/libmbfl/filters/sjis_mac2uni.h
new file mode 100644
index 0000000000..1bd77c91a3
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/sjis_mac2uni.h
@@ -0,0 +1,349 @@
+
+
+static const unsigned short sjis_mac2wchar1[] = { // 0x03ac - 0x03c9
+0x339c, 0x339f, 0x339d, 0x33a0,
+0x33a4, 0xff4d, 0x33a1, 0x33a5,
+0x339e, 0x33a2, 0x338e, 0xff47,
+0x338f, 0x33c4, 0x3396, 0x3397,
+0x2113, 0x3398, 0x33b3, 0x33b2,
+0x33b1, 0x33b0, 0x2109, 0x33d4,
+0x33cb, 0x3390, 0x3385, 0x3386,
+0x3387, 0xf860, };
+static const unsigned short sjis_mac2wchar2[] = { // 0x0406 - 0x0420
+0x2116, 0x33cd,
+0x2121, 0xf861, 0x2664, 0x2667,
+0x2661, 0x2662, 0x2660, 0x2663,
+0x2665, 0x2666, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x3020, 0x260e,
+0x3004, };
+static const unsigned short sjis_mac2wchar3[] = { // 0x0432 - 0x0441
+0x261e, 0x261c,
+0x261d, 0x261f, 0x21c6, 0x21c4,
+0x21c5, 0xf860, 0x21e8, 0x21e6,
+0x21e7, 0x21e9, 0x21e8, 0x21e6,
+0x21e7, 0x21e9, };
+static const unsigned short sjis_mac2wchar4[] = { // 0x0468 - 0x0480
+0x3230, 0x322a, 0x322b, 0x322c,
+0x322d, 0x322e, 0x322f, 0x3240,
+0x3237, 0x3242, 0x3243, 0x3239,
+0x323a, 0x3231, 0x323e, 0x3234,
+0x3232, 0x323b, 0x3236, 0x3233,
+0x3235, 0x323c, 0x323d, 0x323f,
+0x3238, };
+static const unsigned short sjis_mac2wchar5[] = { // 0x04b8 - 0x04e8
+0x5927, 0x5c0f, 0x32a4, 0x32a5,
+0x32a6, 0x32a7, 0x32a8, 0x32a9,
+0x3296, 0x329d, 0x3298, 0x329e,
+0x63a7, 0x3299, 0x3349, 0x3322,
+0x334d, 0x3314, 0x3316, 0x3305,
+0x3333, 0x334e, 0x3303, 0x3336,
+0x3318, 0x3315, 0x3327, 0x3351,
+0x334a, 0x3339, 0x3357, 0x330d,
+0x3342, 0x3323, 0x3326, 0x333b,
+0x332b, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x3300, 0x331e, 0x332a, 0x3331,
+0x3347, };
+static const unsigned short sjis_mac2wchar6[] = { // 0x050c - 0x0551
+0x337e, 0x337d, 0x337c, 0x337b,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x337f, 0xf862, 0xf862,
+0x222e, 0x221f, 0x22bf, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x301d, 0x301f, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x3094, 0x0000, 0x30f7, 0x30f8,
+0x30f9, 0x30fa, };
+static const unsigned short sjis_mac2wchar7[] = { // 0x1ed9 - 0x1f18
+0x3001, 0x3002, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0xffe3, 0xfe33, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x30fc,
+0xfe31, 0x2010, 0x0000, 0x0000,
+0x301c, 0x2016, 0xff5c, 0x2026,
+0xfe30, 0x0000, 0x0000, 0x0000,
+0x0000, 0xfe35, 0xfe36, 0xfe39,
+0xfe3a, 0xff3b, 0xff3d, 0xfe37,
+0xfe38, 0xfe3f, 0xfe40, 0xfe3d,
+0xfe3e, 0xfe41, 0xfe42, 0xfe43,
+0xfe44, 0xfe3b, 0xfe3c, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0xff1d, };
+static const unsigned short sjis_mac2wchar8[] = { // 0x1ff2 - 0x20a5
+0x3041, 0x0000,
+0x3043, 0x0000, 0x3045, 0x0000,
+0x3047, 0x0000, 0x3049, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x3063, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x3083, 0x0000, 0x3085, 0x0000,
+0x3087, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x308e,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x30a1, 0x0000, 0x30a3, 0x0000,
+0x30a5, 0x0000, 0x30a7, 0x0000,
+0x30a9, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x30c3, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x30e3, 0x0000,
+0x30e5, 0x0000, 0x30e7, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x30ee, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x30f5, 0x30f6, };
+
+static const unsigned short wchar2sjis_mac4[] = { // 0x2660 - 0x2667
+0x040e, 0x040c, 0x040d, 0x040f,
+0x040a, 0x0410, 0x0411, 0x040b,
+};
+
+static const unsigned short wchar2sjis_mac7[] = { // 0x322a - 0x3243
+0x0469, 0x046a,
+0x046b, 0x046c, 0x046d, 0x046e,
+0x0468, 0x0475, 0x0478, 0x047b,
+0x0477, 0x047c, 0x047a, 0x0470,
+0x0480, 0x0473, 0x0474, 0x0479,
+0x047d, 0x047e, 0x0476, 0x047f,
+0x046f, 0x0000, 0x0471, 0x0472,
+};
+
+static const unsigned short wchar2sjis_mac8[] = { // 0x3296 - 0x329e
+0x04c0, 0x0000,
+0x04c2, 0x04c5, 0x0000, 0x0000,
+0x0000, 0x04c1, 0x04c3, };
+
+static const unsigned short wchar2sjis_mac9[] = { // 0x3300 - 0x33d4
+0x04e4, 0x0000, 0x0000, 0x04ce,
+0x0000, 0x04cb, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x04d7, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x04c9, 0x04d1, 0x04ca, 0x0000,
+0x04d0, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x04e5, 0x0000,
+0x0000, 0x0000, 0x04c7, 0x04d9,
+0x0000, 0x0000, 0x04da, 0x04d2,
+0x0000, 0x0000, 0x04e6, 0x04dc,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x04e7, 0x0000, 0x04cc,
+0x0000, 0x0000, 0x04cf, 0x0000,
+0x0000, 0x04d5, 0x0000, 0x04db,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x04d8, 0x0000,
+0x0000, 0x0000, 0x0000, 0x04e8,
+0x0000, 0x04c6, 0x04d4, 0x0000,
+0x0000, 0x04c8, 0x04cd, 0x0000,
+0x0000, 0x04d3, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x04d6,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x050f,
+0x050e, 0x050d, 0x050c, 0x0521,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x03c6, 0x03c7, 0x03c8,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x03b6, 0x03b8,
+0x03c5, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x03ba, 0x03bb,
+0x03bd, 0x0000, 0x0000, 0x0000,
+0x03ac, 0x03ae, 0x03b4, 0x03ad,
+0x03af, 0x03b2, 0x03b5, 0x0000,
+0x03b0, 0x03b3, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x03c1, 0x03c0, 0x03bf, 0x03be,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x03b9, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x03c4,
+0x0000, 0x0407, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000,
+0x03c3, };
+
+static const unsigned short wchar2sjis_mac10[] = { // 0xfe30 - 0xfe44
+0x1efc, 0x1ef4, 0x0000, 0x1ee9,
+0x0000, 0x1f01, 0x1f02, 0x1f07,
+0x1f08, 0x1f03, 0x1f04, 0x1f11,
+0x1f12, 0x1f0b, 0x1f0c, 0x1f09,
+0x1f0a, 0x1f0d, 0x1f0e, 0x1f0f,
+0x1f10, };
+
+static const unsigned short code_tbl[][3] = {
+ {0x02f0, 0x0303, 0x2460},
+ {0x030e, 0x0321, 0x2474},
+ {0x032c, 0x0334, 0x2776},
+ {0x0341, 0x0349, 0x2488},
+ {0x034e, 0x0359, 0x2160},
+ {0x0362, 0x036d, 0x2170},
+ {0x038a, 0x03a3, 0x249c},
+};
+
+static const unsigned short code_ofst_tbl[] [2]= {
+ {0x03ac, 0x03c9},
+ {0x0406, 0x0420},
+ {0x0432, 0x0441},
+ {0x0468, 0x0480},
+ {0x04b8, 0x04e8},
+ {0x050c, 0x0551},
+ {0x1ed9, 0x1f18},
+ {0x1ff2, 0x20a5},
+};
+
+static const unsigned short *code_map[] = {
+ sjis_mac2wchar1, sjis_mac2wchar2, sjis_mac2wchar3, sjis_mac2wchar4,
+ sjis_mac2wchar5, sjis_mac2wchar6, sjis_mac2wchar7, sjis_mac2wchar8};
+
+static const unsigned short code_tbl_m[][6] = {
+ {0x0340, 0xf860, 0x0030, 0x002e, 0x0000, 0x0000},
+ {0x03c9, 0xf860, 0x0054, 0x0042, 0x0000, 0x0000},
+ {0x035c, 0xf860, 0x0058, 0x0056, 0x0000, 0x0000},
+ {0x0370, 0xf860, 0x0078, 0x0076, 0x0000, 0x0000},
+ {0x0439, 0xf860, 0x2193, 0x2191, 0x0000, 0x0000},
+ {0x0409, 0xf861, 0x0046, 0x0041, 0x0058, 0x0000},
+ {0x035b, 0xf861, 0x0058, 0x0049, 0x0056, 0x0000},
+ {0x036f, 0xf861, 0x0078, 0x0069, 0x0076, 0x0000},
+ {0x035a, 0xf862, 0x0058, 0x0049, 0x0049, 0x0049},
+ {0x036e, 0xf862, 0x0078, 0x0069, 0x0069, 0x0069},
+ {0x0522, 0xf862, 0x6709, 0x9650, 0x4f1a, 0x793e},
+ {0x0523, 0xf862, 0x8ca1, 0x56e3, 0x6cd5, 0x4eba},
+};
+
+static int code_tbl_m_len = sizeof(code_tbl_m)/(sizeof(unsigned short)*6);
+
+static const unsigned short s_form_tbl[] = {
+ 0x2010,0x2016,0x2026,
+ 0x3001,0x3002,0x301c,0x3041,0x3043,0x3045,0x3047,0x3049,
+ 0x3063,0x3083,0x3085,0x3087,0x308e,0x30a1,0x30a3,0x30a5,
+ 0x30a7,0x30a9,0x30c3,0x30e3,0x30e5,0x30e7,0x30ee,0x30f5,
+ 0x30f6,0x30fc,0xff1d,0xff3b,0xff3d,0xff5c,0xffe3, // vertical f87e (34)
+ 0x2026,0xff47,0xff4d, // halfwidth f87f (3)
+ 0x5927,0x5c0f,0x63a7, // enclosing circle 20dd (3)
+ 0x21e6,0x21e7,0x21e8,0x21e9, // black arrow f87a (4)
+};
+
+static int s_form_tbl_len = sizeof(s_form_tbl)/sizeof(unsigned short);
+
+static const unsigned short s_form_sjis_tbl[] = {
+ 0xeb5d,0xeb61,0xeb63,
+ 0xeb41,0xeb42,0xeb60,0xec9f,0xeca1,0xeca3,0xeca5,0xeca7,
+ 0xecc1,0xece1,0xece3,0xece5,0xecec,0xed40,0xed42,0xed44,
+ 0xed46,0xed48,0xed62,0xed83,0xed85,0xed87,0xed8e,0xed95,
+ 0xed96,0xeb5b,0xeb81,0xeb6d,0xeb6e,0xeb62,0xeb50, // vertical
+ 0x00ff,0x864b,0x8645, // halfwidth
+ 0x8791,0x8792,0x879d, // enclosing circle
+ 0x86d4,0x86d5,0x86d3,0x86d6, // black arrow
+};
+
+static const unsigned short s_form_sjis_fallback_tbl[] = {
+ 0x815d,0x8161,0x8163,
+ 0x8141,0x8142,0x8160,0x829f,0x82a1,0x82a3,0x82a5,0x82a7,
+ 0x82c1,0x82e1,0x82e3,0x82e5,0x82ec,0x8340,0x8342,0x8344,
+ 0x8346,0x8348,0x8362,0x8383,0x8385,0x8387,0x838e,0x8395,
+ 0x8396,0x815b,0x8181,0x816d,0x816e,0x8162,0x8150, // vertical
+ 0x815d,0x8287,0x828d, // halfwidth
+ 0x91e5,0x8fac,0x8d54, // enclosing circle
+ 0x86d0,0x86d1,0x86cf,0x86d2, // arrow
+};
+
+static const unsigned short wchar2sjis_mac_r_tbl[][3] = {
+ {0x2160, 0x216b, 0x034e},
+ {0x2170, 0x217b, 0x0362},
+ {0x2460, 0x2473, 0x02f0},
+ {0x2474, 0x2487, 0x030e},
+ {0x2488, 0x2490, 0x0341},
+ {0x249c, 0x24b5, 0x038a},
+ {0x2776, 0x277e, 0x032c},
+ {0x30f7, 0x30fa, 0x054e},
+ {0x32a4, 0x32a9, 0x04ba},
+};
+
+static int wchar2sjis_mac_r_tbl_len = sizeof(wchar2sjis_mac_r_tbl)/(3*sizeof(unsigned short));
+
+static const unsigned short wchar2sjis_mac_r_map[][2] = {
+ {0x2660, 0x2667},
+ {0x322a, 0x3243},
+ {0x3296, 0x329e},
+ {0x3300, 0x33d4},
+ {0xfe30, 0xfe44},
+};
+
+static int wchar2sjis_mac_r_map_len = sizeof(wchar2sjis_mac_r_map)/(2*sizeof(unsigned short));
+
+static const unsigned short *wchar2sjis_mac_code_map[] = {
+ wchar2sjis_mac4, wchar2sjis_mac7, wchar2sjis_mac8, wchar2sjis_mac9, wchar2sjis_mac10};
+
+static const unsigned short wchar2sjis_mac_wchar_tbl[][2] = {
+ {0x2109, 0x03c2},
+ {0x2113, 0x03bc},
+ {0x2116, 0x0406},
+ {0x2121, 0x0408},
+ {0x21c4, 0x0437},
+ {0x21c5, 0x0438},
+ {0x21c6, 0x0436},
+ {0x21e6, 0x043b},
+ {0x21e7, 0x043c},
+ {0x21e8, 0x043a},
+ {0x21e9, 0x043d},
+ {0x221f, 0x0525},
+ {0x222e, 0x0524},
+ {0x22bf, 0x0526},
+ {0x260e, 0x041f},
+ {0x261c, 0x0433},
+ {0x261d, 0x0434},
+ {0x261e, 0x0432},
+ {0x261f, 0x0435},
+ {0x3004, 0x0420},
+ {0x301d, 0x0538},
+ {0x301f, 0x0539},
+ {0x3020, 0x041e},
+ {0x3094, 0x054c},
+};
+
+static int wchar2sjis_mac_wchar_tbl_len = sizeof(wchar2sjis_mac_wchar_tbl)/(2*sizeof(unsigned short));
diff --git a/ext/mbstring/libmbfl/filters/unicode_table_cp932_ext.h b/ext/mbstring/libmbfl/filters/unicode_table_cp932_ext.h
index c948dfa16b..b685713142 100644
--- a/ext/mbstring/libmbfl/filters/unicode_table_cp932_ext.h
+++ b/ext/mbstring/libmbfl/filters/unicode_table_cp932_ext.h
@@ -25,7 +25,9 @@
#ifndef UNICODE_TABLE_CP932_EXT_H
#define UNICODE_TABLE_CP932_EXT_H
-static const unsigned short cp932ext1_ucs_table[] = {
+#ifdef UNICODE_TABLE_CP932_DEF
+
+const unsigned short cp932ext1_ucs_table[] = {
/* ku 13 */
0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
@@ -40,10 +42,10 @@ static const unsigned short cp932ext1_ucs_table[] = {
0x2261,0x222B,0x222E,0x2211,0x221A,0x22A5,0x2220,0x221F,
0x22BF,0x2235,0x2229,0x222A,0x0000,0x0000
};
-static const int cp932ext1_ucs_table_min = (13 - 1)*94;
-static const int cp932ext1_ucs_table_max = (13 - 1)*94 + (sizeof (cp932ext1_ucs_table) / sizeof (unsigned short));
+const int cp932ext1_ucs_table_min = (13 - 1)*94;
+const int cp932ext1_ucs_table_max = (13 - 1)*94 + (sizeof (cp932ext1_ucs_table) / sizeof (unsigned short));
-static const unsigned short cp932ext2_ucs_table[] = {
+const unsigned short cp932ext2_ucs_table[] = {
/* ku 89 */
0x7E8A,0x891C,0x9348,0x9288,0x84DC,0x4FC9,0x70BB,0x6631,
0x68C8,0x92F9,0x66FB,0x5F45,0x4E28,0x4EE1,0x4EFC,0x4F00,
@@ -100,10 +102,10 @@ static const unsigned short cp932ext2_ucs_table[] = {
0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,
0x2178,0x2179,0xFFE2,0xFFE4,0xFF07,0xFF02
};
-static const int cp932ext2_ucs_table_min = (89 - 1)*94;
-static const int cp932ext2_ucs_table_max = (89 - 1)*94 + (sizeof (cp932ext2_ucs_table) / sizeof (unsigned short));
+const int cp932ext2_ucs_table_min = (89 - 1)*94;
+const int cp932ext2_ucs_table_max = (89 - 1)*94 + (sizeof (cp932ext2_ucs_table) / sizeof (unsigned short));
-static const unsigned short cp932ext3_ucs_table[] = {
+const unsigned short cp932ext3_ucs_table[] = {
/* ku 115 */
0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,
0x2178,0x2179,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,
@@ -164,7 +166,22 @@ static const unsigned short cp932ext3_ucs_table[] = {
0x9ADC,0x9B75,0x9B72,0x9B8F,0x9BB1,0x9BBB,0x9C00,0x9D70,
0x9D6B,0xFA2D,0x9E19,0x9ED1
};
-static const int cp932ext3_ucs_table_min = (115 - 1)*94;
-static const int cp932ext3_ucs_table_max = (115 - 1)*94 + (sizeof (cp932ext3_ucs_table) / sizeof (unsigned short));
+const int cp932ext3_ucs_table_min = (115 - 1)*94;
+const int cp932ext3_ucs_table_max = (115 - 1)*94 + (sizeof (cp932ext3_ucs_table) / sizeof (unsigned short));
+
+#else
+
+extern const unsigned short cp932ext1_ucs_table[];
+extern const unsigned short cp932ext2_ucs_table[];
+extern const unsigned short cp932ext3_ucs_table[];
+
+extern const int cp932ext1_ucs_table_min;
+extern const int cp932ext1_ucs_table_max;
+extern const int cp932ext2_ucs_table_min;
+extern const int cp932ext2_ucs_table_max;
+extern const int cp932ext3_ucs_table_min;
+extern const int cp932ext3_ucs_table_max;
+
+#endif
#endif /* UNICODE_TABLE_CP932_EXT_H */
diff --git a/ext/mbstring/libmbfl/filters/unicode_table_cp936.h b/ext/mbstring/libmbfl/filters/unicode_table_cp936.h
index aa024d1a45..173c8f4b3f 100644
--- a/ext/mbstring/libmbfl/filters/unicode_table_cp936.h
+++ b/ext/mbstring/libmbfl/filters/unicode_table_cp936.h
@@ -28,8 +28,9 @@
/*
* Unicode table
*/
+#ifdef UNICODE_TABLE_CP936_DEF
-static const unsigned short cp936_ucs_table[] = {
+const unsigned short cp936_ucs_table[] = {
/* 0x8100 */
0x4e02,0x4e04,0x4e05,0x4e06,0x4e0f,0x4e12,0x4e17,0x4e1f,
0x4e20,0x4e21,0x4e23,0x4e26,0x4e29,0x4e2e,0x4e2f,0x4e31,
@@ -876,7 +877,7 @@ static const unsigned short cp936_ucs_table[] = {
0x2477,0x2478,0x2479,0x247a,0x247b,0x247c,0x247d,0x247e,
0x247f,0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,
0x2487,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,
-0x2467,0x2468,0x2469,0x0000,0x0000,0x3220,0x3221,0x3222,
+0x2467,0x2468,0x2469,0x20ac,0x0000,0x3220,0x3221,0x3222,
0x3223,0x3224,0x3225,0x3226,0x3227,0x3228,0x3229,0x0000,
0x0000,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,
0x2167,0x2168,0x2169,0x216a,0x216b,0x0000,0x0000,0x0000,
@@ -1021,7 +1022,7 @@ static const unsigned short cp936_ucs_table[] = {
0x0000,0x0101,0x00e1,0x01ce,0x00e0,0x0113,0x00e9,0x011b,
0x00e8,0x012b,0x00ed,0x01d0,0x00ec,0x014d,0x00f3,0x01d2,
0x00f2,0x016b,0x00fa,0x01d4,0x00f9,0x01d6,0x01d8,0x01da,
-0x01dc,0x00fc,0x00ea,0x0251,0x0000,0x0144,0x0148,0x0000,
+0x01dc,0x00fc,0x00ea,0x0251,0x0000,0x0144,0x0148,0x01f9,
0x0261,0x0000,0x0000,0x0000,0x0000,0x3105,0x3106,0x3107,
0x3108,0x3109,0x310a,0x310b,0x310c,0x310d,0x310e,0x310f,
0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117,
@@ -1040,8 +1041,8 @@ static const unsigned short cp936_ucs_table[] = {
0xfe51,0xfe52,0xfe54,0xfe55,0xfe56,0xfe57,0xfe59,0xfe5a,
0xfe5b,0xfe5c,0xfe5d,0xfe5e,0xfe5f,0xfe60,0xfe61,0x0000,
0xfe62,0xfe63,0xfe64,0xfe65,0xfe66,0xfe68,0xfe69,0xfe6a,
-0xfe6b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3007,0x0000,
+0xfe6b,0x303e,0x2ff0,0x2ff1,0x2ff2,0x2ff3,0x2ff4,0x2ff5,
+0x2ff6,0x2ff7,0x2ff8,0x2ff9,0x2ffa,0x2ffb,0x3007,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x2500,0x2501,0x2502,0x2503,
0x2504,0x2505,0x2506,0x2507,0x2508,0x2509,0x250a,0x250b,
@@ -3157,13 +3158,24 @@ static const unsigned short cp936_ucs_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/* 0xfe00 */
0xfa0c,0xfa0d,0xfa0e,0xfa0f,0xfa11,0xfa13,0xfa14,0xfa18,
-0xfa1f,0xfa20,0xfa21,0xfa23,0xfa24,0xfa27,0xfa28,0xfa29};
+0xfa1f,0xfa20,0xfa21,0xfa23,0xfa24,0xfa27,0xfa28,0xfa29,
+0x2e81,0x0000,0x0000,0x0000,0x2e84,0x3473,0x3447,0x2e88,
+0x2e8b,0x0000,0x359e,0x361a,0x360e,0x2e8c,0x2e97,0x396e,
+0x3918,0x0000,0x39cf,0x39df,0x3a73,0x39d0,0x0000,0x0000,
+0x3b4e,0x3c6e,0x3ce0,0x2ea7,0x0000,0x0000,0x2eaa,0x4056,
+0x415f,0x2eae,0x4337,0x2eb3,0x2eb6,0x2eb7,0x0000,0x43b1,
+0x43ac,0x2ebb,0x43dd,0x44d6,0x4661,0x464c,0x0000,0x0000,
+0x4723,0x4729,0x477c,0x478d,0x2eca,0x4947,0x497a,0x497d,
+0x4982,0x4983,0x4985,0x4986,0x499f,0x499b,0x49b7,0x49b6,
+0x0000,0x0000,0x4ca3,0x4c9f,0x4ca0,0x4ca1,0x4c77,0x4ca2,
+0x4d13,0x4d14,0x4d15,0x4d16,0x4d17,0x4d18,0x4d19,0x4dae,
+};
-static const int cp936_ucs_table_size = (sizeof(cp936_ucs_table)/sizeof(unsigned short));
+const int cp936_ucs_table_size = (sizeof(cp936_ucs_table)/sizeof(unsigned short));
/* UCS -> CP936 */
-static const unsigned short ucs_a1_cp936_table[] = {
+const unsigned short ucs_a1_cp936_table[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -3228,7 +3240,7 @@ static const unsigned short ucs_a1_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0xa8bf,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/* 0x0200 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -3308,11 +3320,11 @@ static const unsigned short ucs_a1_cp936_table[] = {
0xa7ea,0xa7eb,0xa7ec,0xa7ed,0xa7ee,0xa7ef,0xa7f0,0xa7f1,
0x0000,0xa7d7};
-static const int ucs_a1_cp936_table_min = 0x0000;
-static const int ucs_a1_cp936_table_max = 0x0000 + (sizeof (ucs_a1_cp936_table) / sizeof (unsigned short));
+const int ucs_a1_cp936_table_min = 0x0000;
+const int ucs_a1_cp936_table_max = 0x0000 + (sizeof (ucs_a1_cp936_table) / sizeof (unsigned short));
/* 0x2000 */
-static const unsigned short ucs_a2_cp936_table[] = {
+const unsigned short ucs_a2_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0xa95c,0x0000,0x0000,0xa843,0xa1aa,0xa844,0xa1ac,0x0000,
@@ -3544,10 +3556,10 @@ static const unsigned short ucs_a2_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-static const int ucs_a2_cp936_table_min = 0x2000;
-static const int ucs_a2_cp936_table_max = 0x2000 + (sizeof (ucs_a2_cp936_table) / sizeof (unsigned short));
+const int ucs_a2_cp936_table_min = 0x2000;
+const int ucs_a2_cp936_table_max = 0x2000 + (sizeof (ucs_a2_cp936_table) / sizeof (unsigned short));
-static const unsigned short ucs_a3_cp936_table[] = {
+const unsigned short ucs_a3_cp936_table[] = {
/* 0x2f00 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -3579,8 +3591,9 @@ static const unsigned short ucs_a3_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0xa98a,0xa98b,0xa98c,0xa98d,0xa98e,0xa98f,0xa990,0xa991,
+0xa992,0xa993,0xa994,0xa995,0x0000,0x0000,0x0000,0x0000,
+/* 0x3000 */
0xa1a1,0xa1a2,0xa1a3,0xa1a8,0x0000,0xa1a9,0xa965,0xa996,
0xa1b4,0xa1b5,0xa1b6,0xa1b7,0xa1b8,0xa1b9,0xa1ba,0xa1bb,
0xa1be,0xa1bf,0xa893,0xa1fe,0xa1b2,0xa1b3,0xa1bc,0xa1bd,
@@ -3588,7 +3601,7 @@ static const unsigned short ucs_a3_cp936_table[] = {
0x0000,0xa940,0xa941,0xa942,0xa943,0xa944,0xa945,0xa946,
0xa947,0xa948,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xa989,0x0000,
0x0000,0xa4a1,0xa4a2,0xa4a3,0xa4a4,0xa4a5,0xa4a6,0xa4a7,
0xa4a8,0xa4a9,0xa4aa,0xa4ab,0xa4ac,0xa4ad,0xa4ae,0xa4af,
0xa4b0,0xa4b1,0xa4b2,0xa4b3,0xa4b4,0xa4b5,0xa4b6,0xa4b7,
@@ -3714,14 +3727,16 @@ static const unsigned short ucs_a3_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-static const int ucs_a3_cp936_table_min = 0x2f00;
-static const int ucs_a3_cp936_table_max = 0x2f00 + (sizeof (ucs_a3_cp936_table) / sizeof (unsigned short));
+const int ucs_a3_cp936_table_min = 0x2f00;
+const int ucs_a3_cp936_table_max = 0x2f00 + (sizeof (ucs_a3_cp936_table) / sizeof (unsigned short));
/* 4d00h CJK Unified Ideographs (+ Extension A) */
-static const unsigned short ucs_i_cp936_table[] = {
+const unsigned short ucs_i_cp936_table[] = {
/* 0x4d00 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0xfe98,0xfe99,0xfe9a,0xfe9b,0xfe9c,
+0xfe9d,0xfe9e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -3739,9 +3754,7 @@ static const unsigned short ucs_i_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfe9f,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -6377,113 +6390,163 @@ static const unsigned short ucs_i_cp936_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
}; /* 9fffh */
-static const int ucs_i_cp936_table_min = 0x4d00;
-static const int ucs_i_cp936_table_max = 0x4d00 + (sizeof (ucs_i_cp936_table) / sizeof (unsigned short));
+const int ucs_i_cp936_table_min = 0x4d00;
+const int ucs_i_cp936_table_max = 0x4d00 + (sizeof (ucs_i_cp936_table) / sizeof (unsigned short));
+/* 0xf900 CJK Compatibility Ideographs (with fallback) */
+static const unsigned short ucs_ci_cp936_table[] = { // 0xf900 - 0xfa2f
-/* 0xf900 CJK Compatibility Ideographs */
-static const unsigned short ucs_ci_cp936_table[] = {
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0xfd9c,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0xfd9d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0xfd9e,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfd9f,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0xfda0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-/* 0xfa00 */
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0xfe40,0xfe41,0xfe42,0xfe43,
-0x0000,0xfe44,0x0000,0xfe45,0xfe46,0x0000,0x0000,0x0000,
-0xfe47,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfe48,
-0xfe49,0xfe4a,0x0000,0xfe4b,0xfe4c,0x0000,0x0000,0xfe4d,
-0xfe4e,0xfe4f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
-static const int ucs_ci_cp936_table_min = 0xf900;
-static const int ucs_ci_cp936_table_max = 0xf900 + (sizeof (ucs_ci_cp936_table) / sizeof (unsigned short));
+/* F900h */
+0xD84D,0xB8FC,0xDC87,0xD95A,0xBBAC,0xB4AE,0xBEE4,0xFD94,
+0xFD94,0xC6F5,0xBDF0,0xC0AE,0xC4CE,0x91D0,0xB05D,0xC15F,
+0xCC7D,0xC2DD,0xC2E3,0xDF89,0x98B7,0xC2E5,0xC0D3,0xE7F3,
+0xC2E4,0xC0D2,0xF198,0x8179,0xC2D1,0x99DA,0xA080,0xCC6D,
+0xFB5B,0x8DB9,0x9E45,0xCB7B,0xD268,0xC0AD,0xC544,0xCF9E,
+0xC0C8,0xC0CA,0xC0CB,0xC0C7,0xFD9C,0x81ED,0xC0E4,0x84DA,
+0x93EF,0x99A9,0xA074,0xB152,0xC0CF,0xCC4A,0xCC94,0xC2B7,
+0xC2B6,0xF494,0xFA98,0xC2B5,0xB593,0xBE47,0xC78A,0xE49B,
+0xC2B9,0xD593,0x89C5,0xC5AA,0xBB5C,0xC340,0xC0CE,0xC0DA,
+0xD954,0xC0D7,0x89BE,0x8CD2,0x98C7,0x9C49,0xC2A9,0xC0DB,
+0xBF7C,0xC2AA,0xC0D5,0xC0DF,0x8443,0xC1E8,0xB6A0,0xBE63,
+0xC1E2,0xC1EA,0xD778,0x9282,0x98B7,0xD65A,0xB5A4,0x8C8E,
+0xC5AD,0xC2CA,0xAE90,0xB1B1,0xB491,0xB1E3,0x8FCD,0xB2BB,
+0xC3DA,0x94B5,0xCBF7,0x85A2,0xC8FB,0xCAA1,0xC87E,0xD566,
+0x9AA2,0xB3BD,0xC9F2,0xCAB0,0xC8F4,0xC2D3,0xC2D4,0xC1C1,
+0x83C9,0xFD9D,0xC1BA,0xBC5A,0xC1BC,0xD58F,0xC1BF,0x84EE,
+0x85CE,0xC5AE,0x8F5D,0xC2C3,0x9E56,0xB55A,0xE982,0xF350,
+0xFB90,0xC0E8,0xC1A6,0x95D1,0x9A76,0xDE5D,0xC4EA,0x917A,
+0x91D9,0x93D3,0x9D69,0x9F92,0xAD49,0xFD9E,0xBE9A,0xC293,
+0xDD82,0xC98F,0xDF42,0xE580,0xC1D0,0xC1D3,0xD1CA,0xC1D2,
+0xC1D1,0xD566,0xC1AE,0xC4EE,0xC4ED,0x9A9A,0xBA9F,0xAB43,
+0xC1EE,0xE0F2,0x8C8E,0x8E58,0xC1AF,0xC1E1,0xAC93,0xC1E7,
+0xF1F6,0xE28F,0xC1E3,0xEC60,0xEE49,0xC0FD,0xB659,0xF5B7,
+0xEB60,0x90BA,0xC1CB,0xC1C5,0xE5BC,0xC4F2,0xC1CF,0x98B7,
+0xC1C7,0xAF9F,0xDEA4,0xDF7C,0xFD88,0x959E,0xC8EE,0x84A2,
+0x9683,0xC1F8,0xC1F7,0xC1EF,0xC1F0,0xC1F4,0xC1F2,0xBC7E,
+0xEE90,0xC1F9,0xC2BE,0xEA91,0x8290,0x8D91,0x9C53,0xDD86,
+0xC2C9,0x90FC,0xC0F5,0xC2CA,0xC2A1,0xC0FB,0xC0F4,0xC2C4,
+0xD2D7,0xC0EE,0xC0E6,0xC4E0,0xC0ED,0xC1A1,0xEEBE,0xFD9F,
+0xD165,0xC0EF,0xEB78,0xC4E4,0xC4E7,0xC1DF,0x9FFB,0xAD55,
+0xCC41,0xFDA0,0xF75B,0xF7EB,0xC1D6,0xC1DC,0xC552,0xC1A2,
+0xF3D2,0xC1A3,0xA0EE,0xD6CB,0xD752,0xCAB2,0xB2E8,0xB4CC,
+
+/* FA00h */
+0xC7D0,0xB6C8,0xCDD8,0xCCC7,0xD5AC,0xB6B4,0xB1A9,0xDD97,
+0xD0D0,0xBDB5,0xD28A,0xC0AA,0xFE40,0xFE41,0xFE42,0xFE43,
+0x8956,0xFE44,0xC7E7,0xFE45,0xFE46,0x8444,0xD869,0xD2E6,
+0xFE47,0xC9F1,0xCFE9,0xB8A3,0xBEB8,0xBEAB,0xD3F0,0xFE48,
+0xFE49,0xFE4A,0xD654,0xFE4B,0xFE4C,0xD2DD,0xB6BC,0xFE4D,
+0xFE4E,0xFE4F,0xEF88,0xEF95,0xF05E,0xFA51,0x0000,0x0000,
+};
+
+const int ucs_ci_cp936_table_min = 0xf900;
+const int ucs_ci_cp936_table_max = 0xfa2f;
+/* reduced map for GBK: U+FA0C - U+FA29 */
+const unsigned short ucs_ci_s_cp936_table[] = {
+ 0xfe40,0xfe41,0xfe42,0xfe43,
+ 0x0000,0xfe44,0x0000,0xfe45,0xfe46,0x0000,0x0000,0x0000,
+ 0xfe47,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfe48,
+ 0xfe49,0xfe4a,0x0000,0xfe4b,0xfe4c,0x0000,0x0000,0xfe4d,
+ 0xfe4e,0xfe4f};
/* FE30h CJK Compatibility Forms */
-static const unsigned short ucs_cf_cp936_table[] = {
+const unsigned short ucs_cf_cp936_table[] = {
0xa955,0xa6f2,0x0000,0xa6f4,0xa6f5,0xa6e0,0xa6e1,0xa6f0,
0xa6f1,0xa6e2,0xa6e3,0xa6ee,0xa6ef,0xa6e6,0xa6e7,0xa6e4,
0xa6e5,0xa6e8,0xa6e9,0xa6ea,0xa6eb,0x0000,0x0000,0x0000,
0x0000,0xa968,0xa969,0xa96a,0xa96b,0xa96c,0xa96d,0xa96e};
-static const int ucs_cf_cp936_table_min = 0xfe30;
-static const int ucs_cf_cp936_table_max = 0xfe30 + (sizeof (ucs_cf_cp936_table) / sizeof (unsigned short));
+const int ucs_cf_cp936_table_min = 0xfe30;
+const int ucs_cf_cp936_table_max = 0xfe30 + (sizeof (ucs_cf_cp936_table) / sizeof (unsigned short));
/* FE50h Small Form Variants */
-static const unsigned short ucs_sfv_cp936_table[] = {
+const unsigned short ucs_sfv_cp936_table[] = {
0xa96f,0xa970,0xa971,0x0000,0xa972,0xa973,0xa974,0xa975,
0x0000,0xa976,0xa977,0xa978,0xa979,0xa97a,0xa97b,0xa97c,
0xa97d,0xa97e,0xa980,0xa981,0xa982,0xa983,0xa984,0x0000,
0xa985,0xa986,0xa987,0xa988,0x0000,0x0000,0x0000,0x0000};
-static const int ucs_sfv_cp936_table_min = 0xfe50;
-static const int ucs_sfv_cp936_table_max = 0xfe50 + (sizeof (ucs_sfv_cp936_table) / sizeof (unsigned short));
+const int ucs_sfv_cp936_table_min = 0xfe50;
+const int ucs_sfv_cp936_table_max = 0xfe50 + (sizeof (ucs_sfv_cp936_table) / sizeof (unsigned short));
/* FF00h Halfwidth and Fullwidth Forms */
-static const unsigned short ucs_hff_cp936_table[] = {
-0x0000,0xa3a1,0xa3a2,0xa3a3,0xa1e7,0xa3a5,0xa3a6,0xa3a7,
-0xa3a8,0xa3a9,0xa3aa,0xa3ab,0xa3ac,0xa3ad,0xa3ae,0xa3af,
-0xa3b0,0xa3b1,0xa3b2,0xa3b3,0xa3b4,0xa3b5,0xa3b6,0xa3b7,
-0xa3b8,0xa3b9,0xa3ba,0xa3bb,0xa3bc,0xa3bd,0xa3be,0xa3bf,
-0xa3c0,0xa3c1,0xa3c2,0xa3c3,0xa3c4,0xa3c5,0xa3c6,0xa3c7,
-0xa3c8,0xa3c9,0xa3ca,0xa3cb,0xa3cc,0xa3cd,0xa3ce,0xa3cf,
-0xa3d0,0xa3d1,0xa3d2,0xa3d3,0xa3d4,0xa3d5,0xa3d6,0xa3d7,
-0xa3d8,0xa3d9,0xa3da,0xa3db,0xa3dc,0xa3dd,0xa3de,0xa3df,
-0xa3e0,0xa3e1,0xa3e2,0xa3e3,0xa3e4,0xa3e5,0xa3e6,0xa3e7,
-0xa3e8,0xa3e9,0xa3ea,0xa3eb,0xa3ec,0xa3ed,0xa3ee,0xa3ef,
-0xa3f0,0xa3f1,0xa3f2,0xa3f3,0xa3f4,0xa3f5,0xa3f6,0xa3f7,
-0xa3f8,0xa3f9,0xa3fa,0xa3fb,0xa3fc,0xa3fd,0xa1ab,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0xa1e9,0xa1ea,0xa956,0xa3fe,0xa957,0xa3a4,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
-0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
+
+/* reduced map: U+FFE0 - U+FFE5 */
+const unsigned short ucs_hff_s_cp936_table[] = {
+ 0xa1e9,0xa1ea,0xa956,0xa3fe,0xa957,0xa3a4,
};
-static const int ucs_hff_cp936_table_min = 0xff00;
-static const int ucs_hff_cp936_table_max = 0xff00 + (sizeof (ucs_hff_cp936_table) / sizeof (unsigned short));
+
+const int ucs_hff_cp936_table_min = 0xff00;
+const int ucs_hff_cp936_table_max = 0xffff;
+
+/* CP936 local */
+
+static const unsigned short mbfl_cp936_pua_tbl[][3] = {
+ {0xe766, 0xe76b, 0xa2ab},
+ {0xe76c, 0xe76d, 0xa2e3},
+ {0xe76e, 0xe76f, 0xa2ef},
+ {0xe770, 0xe771, 0xa2fd},
+ {0xe772, 0xe77c, 0xa4f4},
+ {0xe77d, 0xe784, 0xa5f7},
+ {0xe785, 0xe78c, 0xa6b9},
+ {0xe78d, 0xe793, 0xa6d9},
+ {0xe794, 0xe795, 0xa6ec},
+ {0xe796, 0xe796, 0xa6f3},
+ {0xe797, 0xe79f, 0xa6f6},
+ {0xe7a0, 0xe7ae, 0xa7c2},
+ {0xe7af, 0xe7bb, 0xa7f2},
+ {0xe7bc, 0xe7c6, 0xa896},
+ {0xe7c7, 0xe7c7, 0xa8bc},
+ {0xe7c8, 0xe7c8, 0xa8bf},
+ {0xe7c9, 0xe7cc, 0xa8c1},
+ {0xe7cd, 0xe7e1, 0xa8ea},
+ {0xe7e2, 0xe7e2, 0xa958},
+ {0xe7e3, 0xe7e3, 0xa95b},
+ {0xe7e4, 0xe7e6, 0xa95d},
+ {0xe7e7, 0xe7f3, 0xa989},
+ {0xe7f4, 0xe800, 0xa997},
+ {0xe801, 0xe80f, 0xa9f0},
+ {0xe810, 0xe814, 0xd7fa},
+ {0xe815, 0xe843, 0xfe50},
+ {0xe844, 0xe864, 0xfe80},
+};
+
+static const int mbfl_cp936_pua_tbl_max = sizeof(mbfl_cp936_pua_tbl)/(sizeof(unsigned short)*3);
+
+#else
+
+extern const unsigned short cp936_ucs_table[];
+extern const unsigned short ucs_a1_cp936_table[];
+extern const unsigned short ucs_a2_cp936_table[];
+extern const unsigned short ucs_a3_cp936_table[];
+extern const unsigned short ucs_i_cp936_table[];
+extern const unsigned short ucs_cf_cp936_table[];
+extern const unsigned short ucs_sfv_cp936_table[];
+
+extern const unsigned short ucs_ci_s_cp936_table[];
+extern const unsigned short ucs_hff_s_cp936_table[];
+
+extern const int cp936_ucs_table_size;
+extern const int ucs_a1_cp936_table_min;
+extern const int ucs_a1_cp936_table_max;
+extern const int ucs_a2_cp936_table_min;
+extern const int ucs_a2_cp936_table_max;
+extern const int ucs_a3_cp936_table_min;
+extern const int ucs_a3_cp936_table_max;
+extern const int ucs_i_cp936_table_min;
+extern const int ucs_i_cp936_table_max;
+extern const int ucs_ci_cp936_table_min;
+extern const int ucs_ci_cp936_table_max;
+extern const int ucs_cf_cp936_table_min;
+extern const int ucs_cf_cp936_table_max;
+extern const int ucs_sfv_cp936_table_min;
+extern const int ucs_sfv_cp936_table_max;
+extern const int ucs_hff_cp936_table_min;
+extern const int ucs_hff_cp936_table_max;
+
+#endif
#endif /* UNICODE_TABLE_CP936_H */
diff --git a/ext/mbstring/libmbfl/filters/unicode_table_gb18030.h b/ext/mbstring/libmbfl/filters/unicode_table_gb18030.h
new file mode 100644
index 0000000000..7c38045638
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/unicode_table_gb18030.h
@@ -0,0 +1,233 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file: Rui Hirokawa <hirokawa@php.net>
+ *
+ */
+
+#ifndef UNICODE_TABLE_GB18030_H
+#define UNICODE_TABLE_GB18030_H
+
+static const unsigned short mbfl_gb18030_c_tbl_val[58] =
+{
+ 0xfe50,0xfe54,0xfe57,0xfe58,0xfe5d,0xfe5e,0xfe6b,0xfe6e,
+ 0xfe71,0xfe73,0xfe74,0xfe75,0xfe79,0xfe84,0xfe56,0xfe55,
+ 0xfe5a,0xfe5c,0xfe5b,0xfe60,0xfe5f,0xfe62,0xfe65,0xfe63,
+ 0xfe64,0xfe68,0xfe69,0xfe6a,0xfe6f,0xfe70,0xfe72,0xfe78,
+ 0xfe77,0xfe7a,0xfe7b,0xfe7d,0xfe7c,0xfe80,0xfe81,0xfe82,
+ 0xfe83,0xfe85,0xfe86,0xfe87,0xfe88,0xfe89,0xfe8a,0xfe8b,
+ 0xfe8d,0xfe8c,0xfe8f,0xfe8e,0xfe96,0xfe93,0xfe94,0xfe95,
+ 0xfe97,0xfe92,
+};
+
+static const unsigned short mbfl_gb18030_c_tbl_key[58] =
+{
+ 0x2e81,0x2e84,0x2e88,0x2e8b,0x2e8c,0x2e97,0x2ea7,0x2eaa,
+ 0x2eae,0x2eb3,0x2eb6,0x2eb7,0x2ebb,0x2eca,0x3447,0x3473,
+ 0x359e,0x360e,0x361a,0x3918,0x396e,0x39cf,0x39d0,0x39df,
+ 0x3a73,0x3b4e,0x3c6e,0x3ce0,0x4056,0x415f,0x4337,0x43ac,
+ 0x43b1,0x43dd,0x44d6,0x464c,0x4661,0x4723,0x4729,0x477c,
+ 0x478d,0x4947,0x497a,0x497d,0x4982,0x4983,0x4985,0x4986,
+ 0x499b,0x499f,0x49b6,0x49b7,0x4c77,0x4c9f,0x4ca0,0x4ca1,
+ 0x4ca2,0x4ca3,
+};
+
+static const int mbfl_gb18030_c_tbl_max = sizeof(mbfl_gb18030_c_tbl_key)/sizeof(unsigned short);
+
+static const unsigned short mbfl_gb18030_pua_tbl[][3] = {
+ {0xe766, 0xe76b, 0xa2ab},
+ {0xe76d, 0xe76d, 0xa2e4},
+ {0xe76e, 0xe76f, 0xa2ef},
+ {0xe770, 0xe771, 0xa2fd},
+ {0xe772, 0xe77c, 0xa4f4},
+ {0xe77d, 0xe784, 0xa5f7},
+ {0xe785, 0xe78c, 0xa6b9},
+ {0xe78d, 0xe793, 0xa6d9},
+ {0xe794, 0xe795, 0xa6ec},
+ {0xe796, 0xe796, 0xa6f3},
+ {0xe797, 0xe79f, 0xa6f6},
+ {0xe7a0, 0xe7ae, 0xa7c2},
+ {0xe7af, 0xe7bb, 0xa7f2},
+ {0xe7bc, 0xe7c6, 0xa896},
+ {0xe7c7, 0xe7c7, 0xa8bc},
+ {0xe7c9, 0xe7cc, 0xa8c1},
+ {0xe7cd, 0xe7e1, 0xa8ea},
+ {0xe7e2, 0xe7e2, 0xa958},
+ {0xe7e3, 0xe7e3, 0xa95b},
+ {0xe7e4, 0xe7e6, 0xa95d},
+ {0xe7f4, 0xe800, 0xa997},
+ {0xe801, 0xe80f, 0xa9f0},
+ {0xe810, 0xe814, 0xd7fa},
+ {0xe816, 0xe818, 0xfe51},
+ {0xe81e, 0xe81e, 0xfe59},
+ {0xe826, 0xe826, 0xfe61},
+ {0xe82b, 0xe82c, 0xfe66},
+ {0xe831, 0xe832, 0xfe6c},
+ {0xe83b, 0xe83b, 0xfe76},
+ {0xe843, 0xe843, 0xfe7e},
+ {0xe854, 0xe855, 0xfe90},
+ {0xe864, 0xe864, 0xfea0},
+};
+
+static const int mbfl_gb18030_pua_tbl_max = sizeof(mbfl_gb18030_pua_tbl)/(sizeof(unsigned short)*3);
+
+static const unsigned short mbfl_gb2uni_tbl[] = {
+0x0000, 0x0023, 0x0024, 0x0025, 0x0026, 0x002c, 0x002d, 0x0031,
+0x0032, 0x0050, 0x0051, 0x0058, 0x0059, 0x005e, 0x005f, 0x005f,
+0x0060, 0x0063, 0x0064, 0x0066, 0x0067, 0x0067, 0x0068, 0x0068,
+0x0069, 0x006c, 0x006d, 0x007d, 0x007e, 0x0084, 0x0085, 0x0093,
+0x0094, 0x00ab, 0x00ac, 0x00ae, 0x00af, 0x00b2, 0x00b3, 0x00cf,
+0x00d0, 0x0131, 0x0132, 0x0132, 0x0133, 0x0133, 0x0134, 0x0134,
+0x0135, 0x0135, 0x0136, 0x0136, 0x0137, 0x0137, 0x0138, 0x0138,
+0x0139, 0x0154, 0x0155, 0x01ab, 0x01ac, 0x01ba, 0x01bb, 0x021f,
+0x0220, 0x0220, 0x0221, 0x022d, 0x022e, 0x02e4, 0x02e5, 0x02e5,
+0x02e6, 0x02ec, 0x02ed, 0x02ed, 0x02ee, 0x0324, 0x0325, 0x0332,
+0x0333, 0x0333, 0x0334, 0x1ef1, 0x1ef2, 0x1ef3, 0x1ef4, 0x1ef4,
+0x1ef5, 0x1ef6, 0x1ef7, 0x1efd, 0x1efe, 0x1f06, 0x1f07, 0x1f07,
+0x1f08, 0x1f08, 0x1f09, 0x1f0d, 0x1f0e, 0x1f7d, 0x1f7e, 0x1fd3,
+0x1fd4, 0x1fd4, 0x1fd5, 0x1fd7, 0x1fd8, 0x1fe3, 0x1fe4, 0x1fed,
+0x1fee, 0x202b, 0x202c, 0x202f, 0x2030, 0x2045, 0x2046, 0x2047,
+0x2048, 0x20b5, 0x20b6, 0x20bb, 0x20bc, 0x20bc, 0x20bd, 0x20bf,
+0x20c0, 0x20c3, 0x20c4, 0x20c5, 0x20c6, 0x20c7, 0x20c8, 0x20c8,
+0x20c9, 0x20c9, 0x20ca, 0x20cb, 0x20cc, 0x20d0, 0x20d1, 0x20d5,
+0x20d6, 0x20df, 0x20e0, 0x20e2, 0x20e3, 0x20e7, 0x20e8, 0x20f4,
+0x20f5, 0x20f6, 0x20f7, 0x20fc, 0x20fd, 0x2121, 0x2122, 0x2124,
+0x2125, 0x212f, 0x2130, 0x2148, 0x2149, 0x219a, 0x219b, 0x22e7,
+0x22e8, 0x22f1, 0x22f2, 0x2355, 0x2356, 0x2359, 0x235a, 0x2366,
+0x2367, 0x2369, 0x236a, 0x2373, 0x2374, 0x2383, 0x2384, 0x238b,
+0x238c, 0x2393, 0x2394, 0x2396, 0x2397, 0x2398, 0x2399, 0x23aa,
+0x23ab, 0x23c9, 0x23ca, 0x23cb, 0x23cc, 0x2401, 0x2402, 0x2402,
+0x2403, 0x2c40, 0x2c41, 0x2c42, 0x2c43, 0x2c45, 0x2c46, 0x2c47,
+0x2c48, 0x2c51, 0x2c52, 0x2c60, 0x2c61, 0x2c62, 0x2c63, 0x2c65,
+0x2c66, 0x2c69, 0x2c6a, 0x2c6b, 0x2c6c, 0x2c6e, 0x2c6f, 0x2c7c,
+0x2c7d, 0x2da1, 0x2da2, 0x2da5, 0x2da6, 0x2da6, 0x2da7, 0x2dab,
+0x2dac, 0x2dad, 0x2dae, 0x2dc1, 0x2dc2, 0x2dc3, 0x2dc4, 0x2dca,
+0x2dcb, 0x2dcc, 0x2dcd, 0x2dd1, 0x2dd2, 0x2dd7, 0x2dd8, 0x2ecd,
+0x2ece, 0x2ed4, 0x2ed5, 0x2f45, 0x2f46, 0x302f, 0x3030, 0x303b,
+0x303c, 0x303d, 0x303e, 0x305f, 0x3060, 0x3068, 0x3069, 0x306a,
+0x306b, 0x306c, 0x306d, 0x30dd, 0x30de, 0x3108, 0x3109, 0x3232,
+0x3233, 0x32a1, 0x32a2, 0x32ac, 0x32ad, 0x35a9, 0x35aa, 0x35fe,
+0x35ff, 0x365e, 0x365f, 0x366c, 0x366d, 0x36ff, 0x3700, 0x37d9,
+0x37da, 0x38f8, 0x38f9, 0x3969, 0x396a, 0x3cde, 0x3cdf, 0x3de6,
+0x3de7, 0x3fbd, 0x3fbe, 0x4031, 0x4032, 0x4035, 0x4036, 0x4060,
+0x4061, 0x4158, 0x4159, 0x42cd, 0x42ce, 0x42e1, 0x42e2, 0x43a2,
+0x43a3, 0x43a7, 0x43a8, 0x43f9, 0x43fa, 0x4409, 0x440a, 0x45c2,
+0x45c3, 0x45f4, 0x45f5, 0x45f6, 0x45f7, 0x45fa, 0x45fb, 0x45fb,
+0x45fc, 0x460f, 0x4610, 0x4612, 0x4613, 0x4628, 0x4629, 0x48e7,
+0x48e8, 0x490e, 0x490f, 0x497d, 0x497e, 0x4a11, 0x4a12, 0x4a62,
+0x4a63, 0x82bc, 0x82bd, 0x82bd, 0x82be, 0x82be, 0x82bf, 0x82cb,
+0x82cc, 0x82cc, 0x82cd, 0x82d1, 0x82d2, 0x82d8, 0x82d9, 0x82dc,
+0x82dd, 0x82e0, 0x82e1, 0x82e8, 0x82e9, 0x82ef, 0x82f0, 0x82ff,
+0x8300, 0x830d, 0x830e, 0x93d4, 0x93d5, 0x9420, 0x9421, 0x943b,
+0x943c, 0x948c, 0x948d, 0x9495, 0x9496, 0x94af, 0x94b0, 0x94b0,
+0x94b1, 0x94b1, 0x94b2, 0x94b4, 0x94b5, 0x94ba, 0x94bb, 0x94bb,
+0x94bc, 0x94bd, 0x94be, 0x98c3, 0x98c4, 0x98c4, 0x98c5, 0x98c8,
+0x98c9, 0x98c9, 0x98ca, 0x98ca, 0x98cb, 0x98cb, 0x98cc, 0x9960,
+0x9961, 0x99e1, 0x99e2, 0x99fb,
+};
+
+static const unsigned short mbfl_uni2gb_tbl[] = {
+0x0080, 0x00a3, 0x00a5, 0x00a6, 0x00a9, 0x00af, 0x00b2, 0x00b6,
+0x00b8, 0x00d6, 0x00d8, 0x00df, 0x00e2, 0x00e7, 0x00eb, 0x00eb,
+0x00ee, 0x00f1, 0x00f4, 0x00f6, 0x00f8, 0x00f8, 0x00fb, 0x00fb,
+0x00fd, 0x0100, 0x0102, 0x0112, 0x0114, 0x011a, 0x011c, 0x012a,
+0x012c, 0x0143, 0x0145, 0x0147, 0x0149, 0x014c, 0x014e, 0x016a,
+0x016c, 0x01cd, 0x01cf, 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3,
+0x01d5, 0x01d5, 0x01d7, 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db,
+0x01dd, 0x01f8, 0x01fa, 0x0250, 0x0252, 0x0260, 0x0262, 0x02c6,
+0x02c8, 0x02c8, 0x02cc, 0x02d8, 0x02da, 0x0390, 0x03a2, 0x03a2,
+0x03aa, 0x03b0, 0x03c2, 0x03c2, 0x03ca, 0x0400, 0x0402, 0x040f,
+0x0450, 0x0450, 0x0452, 0x200f, 0x2011, 0x2012, 0x2017, 0x2017,
+0x201a, 0x201b, 0x201e, 0x2024, 0x2027, 0x202f, 0x2031, 0x2031,
+0x2034, 0x2034, 0x2036, 0x203a, 0x203c, 0x20ab, 0x20ad, 0x2102,
+0x2104, 0x2104, 0x2106, 0x2108, 0x210a, 0x2115, 0x2117, 0x2120,
+0x2122, 0x215f, 0x216c, 0x216f, 0x217a, 0x218f, 0x2194, 0x2195,
+0x219a, 0x2207, 0x2209, 0x220e, 0x2210, 0x2210, 0x2212, 0x2214,
+0x2216, 0x2219, 0x221b, 0x221c, 0x2221, 0x2222, 0x2224, 0x2224,
+0x2226, 0x2226, 0x222c, 0x222d, 0x222f, 0x2233, 0x2238, 0x223c,
+0x223e, 0x2247, 0x2249, 0x224b, 0x224d, 0x2251, 0x2253, 0x225f,
+0x2262, 0x2263, 0x2268, 0x226d, 0x2270, 0x2294, 0x2296, 0x2298,
+0x229a, 0x22a4, 0x22a6, 0x22be, 0x22c0, 0x2311, 0x2313, 0x245f,
+0x246a, 0x2473, 0x249c, 0x24ff, 0x254c, 0x254f, 0x2574, 0x2580,
+0x2590, 0x2592, 0x2596, 0x259f, 0x25a2, 0x25b1, 0x25b4, 0x25bb,
+0x25be, 0x25c5, 0x25c8, 0x25ca, 0x25cc, 0x25cd, 0x25d0, 0x25e1,
+0x25e6, 0x2604, 0x2607, 0x2608, 0x260a, 0x263f, 0x2641, 0x2641,
+0x2643, 0x2e80, 0x2e82, 0x2e83, 0x2e85, 0x2e87, 0x2e89, 0x2e8a,
+0x2e8d, 0x2e96, 0x2e98, 0x2ea6, 0x2ea8, 0x2ea9, 0x2eab, 0x2ead,
+0x2eaf, 0x2eb2, 0x2eb4, 0x2eb5, 0x2eb8, 0x2eba, 0x2ebc, 0x2ec9,
+0x2ecb, 0x2fef, 0x2ffc, 0x2fff, 0x3004, 0x3004, 0x3018, 0x301c,
+0x301f, 0x3020, 0x302a, 0x303d, 0x303f, 0x3040, 0x3094, 0x309a,
+0x309f, 0x30a0, 0x30f7, 0x30fb, 0x30ff, 0x3104, 0x312a, 0x321f,
+0x322a, 0x3230, 0x3232, 0x32a2, 0x32a4, 0x338d, 0x3390, 0x339b,
+0x339f, 0x33a0, 0x33a2, 0x33c3, 0x33c5, 0x33cd, 0x33cf, 0x33d0,
+0x33d3, 0x33d4, 0x33d6, 0x3446, 0x3448, 0x3472, 0x3474, 0x359d,
+0x359f, 0x360d, 0x360f, 0x3619, 0x361b, 0x3917, 0x3919, 0x396d,
+0x396f, 0x39ce, 0x39d1, 0x39de, 0x39e0, 0x3a72, 0x3a74, 0x3b4d,
+0x3b4f, 0x3c6d, 0x3c6f, 0x3cdf, 0x3ce1, 0x4055, 0x4057, 0x415e,
+0x4160, 0x4336, 0x4338, 0x43ab, 0x43ad, 0x43b0, 0x43b2, 0x43dc,
+0x43de, 0x44d5, 0x44d7, 0x464b, 0x464d, 0x4660, 0x4662, 0x4722,
+0x4724, 0x4728, 0x472a, 0x477b, 0x477d, 0x478c, 0x478e, 0x4946,
+0x4948, 0x4979, 0x497b, 0x497c, 0x497e, 0x4981, 0x4984, 0x4984,
+0x4987, 0x499a, 0x499c, 0x499e, 0x49a0, 0x49b5, 0x49b8, 0x4c76,
+0x4c78, 0x4c9e, 0x4ca4, 0x4d12, 0x4d1a, 0x4dad, 0x4daf, 0x4dff,
+0x9fa6, 0xd7ff, 0xe76c, 0xe76c, 0xe7c8, 0xe7c8, 0xe7e7, 0xe7f3,
+0xe815, 0xe815, 0xe819, 0xe81d, 0xe81f, 0xe825, 0xe827, 0xe82a,
+0xe82d, 0xe830, 0xe833, 0xe83a, 0xe83c, 0xe842, 0xe844, 0xe853,
+0xe856, 0xe863, 0xe865, 0xf92b, 0xf92d, 0xf978, 0xf97a, 0xf994,
+0xf996, 0xf9e6, 0xf9e8, 0xf9f0, 0xf9f2, 0xfa0b, 0xfa10, 0xfa10,
+0xfa12, 0xfa12, 0xfa15, 0xfa17, 0xfa19, 0xfa1e, 0xfa22, 0xfa22,
+0xfa25, 0xfa26, 0xfa2a, 0xfe2f, 0xfe32, 0xfe32, 0xfe45, 0xfe48,
+0xfe53, 0xfe53, 0xfe58, 0xfe58, 0xfe67, 0xfe67, 0xfe6c, 0xff00,
+0xff5f, 0xffdf, 0xffe6, 0xffff,
+};
+
+static const unsigned short mbfl_gb_uni_ofst[] = {
+ 128, 129, 131, 133, 134, 135, 137, 140,
+ 142, 144, 145, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 171, 172, 189, 196, 213, 220, 221,
+ 285, 286, 287, 291, 293, 295, 297, 298,
+ 300, 301, 302, 303, 304, 305, 306, 307,
+ 308, 320, 330, 334, 338, 339, 340, 341,
+ 342, 343, 347, 348, 349, 354, 355, 359,
+ 360, 361, 362, 363, 365, 369, 371, 372,
+ 373, 374, 375, 376, 386, 426, 502, 538,
+ 553, 556, 558, 560, 562, 564, 565, 567,
+ 571, 573, 574, 575, 576, 577, 578, 579,
+ 581, 582, 583, 584, 585, 586, 588, 589,
+ 590, 602, 606, 625, 627, 636, 637, 720,
+ 724, 810, 813, 850, 860, 861, 862, 864,
+ 867, 868, 869, 870, 872, 873, 874, 875,
+ 876, 877, 878, 879, 880, 882, 883, 884,
+ 885, 886, 887, 888, 889, 890, 891, 892,
+ 893, 894, 895, 896, 897, 898, 899, 900,
+ 901, 902, 903, 905, 907, 908, 909, 911,
+ 912, 917, 924, 925, 21827, 25775, 25866, 25896,
+ 25929, 25932, 25933, 25934, 25936, 25938, 25939, 25940,
+ 25942, 25943, 25944, 25945, 25946, 25947, 25948, 25952,
+ 25953, 25955, 25956, 25959, 25961, 25964, 25966, 25984,
+ 25994, 25998, 26012, 26016, 26110, 26116,
+};
+
+static const int mbfl_gb_uni_max = sizeof(mbfl_gb_uni_ofst)/sizeof(unsigned short);
+
+
+#endif /* UNICODE_TABLE_GB18030_H */
diff --git a/ext/mbstring/libmbfl/filters/unicode_table_jis.h b/ext/mbstring/libmbfl/filters/unicode_table_jis.h
index 5671c4e851..9132d4b33c 100644
--- a/ext/mbstring/libmbfl/filters/unicode_table_jis.h
+++ b/ext/mbstring/libmbfl/filters/unicode_table_jis.h
@@ -27,10 +27,12 @@
#ifndef UNICODE_TABLE_JIS_H
#define UNICODE_TABLE_JIS_H
+#ifdef UNICODE_TABLE_JIS_DEF
+
/*
* Unicode table
*/
-static const unsigned short jisx0208_ucs_table[] = {
+const unsigned short jisx0208_ucs_table[] = {
/* ku 1 */
0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
@@ -1197,9 +1199,9 @@ static const unsigned short jisx0208_ucs_table[] = {
0x582F,0x69C7,0x9059,0x7464,0x51DC,0x7199
};
-static const int jisx0208_ucs_table_size = (sizeof (jisx0208_ucs_table) / sizeof (unsigned short));
+const int jisx0208_ucs_table_size = (sizeof (jisx0208_ucs_table) / sizeof (unsigned short));
-static const unsigned short jisx0212_ucs_table[] = {
+const unsigned short jisx0212_ucs_table[] = {
/* ku 1 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -2276,9 +2278,9 @@ static const unsigned short jisx0212_ucs_table[] = {
0x9FA2,0x9FA3,0x9FA5
};
-static const int jisx0212_ucs_table_size = (sizeof (jisx0212_ucs_table) / sizeof (unsigned short));
+const int jisx0212_ucs_table_size = (sizeof (jisx0212_ucs_table) / sizeof (unsigned short));
-static const unsigned short ucs_a1_jis_table[] = {
+const unsigned short ucs_a1_jis_table[] = {
/* 0000h */
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
@@ -2429,11 +2431,11 @@ static const unsigned short ucs_a1_jis_table[] = {
0x0000,0x2757,0xA7F2,0xA7F3,0xA7F4,0xA7F5,0xA7F6,0xA7F7,
0xA7F8,0xA7F9,0xA7FA,0xA7FB,0xA7FC,0x0000,0xA7FD,0xA7FE
};
-static const int ucs_a1_jis_table_min = 0x0000;
-static const int ucs_a1_jis_table_max = 0x0000 + (sizeof (ucs_a1_jis_table) / sizeof (unsigned short));
+const int ucs_a1_jis_table_min = 0x0000;
+const int ucs_a1_jis_table_max = 0x0000 + (sizeof (ucs_a1_jis_table) / sizeof (unsigned short));
-static const unsigned short ucs_a2_jis_table[] = {
+const unsigned short ucs_a2_jis_table[] = {
/* 2000h */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -3012,11 +3014,11 @@ static const unsigned short ucs_a2_jis_table[] = {
0x2570,0x2571,0x2572,0x2573,0x2574,0x2575,0x2576,0x0000,
0x0000,0x0000,0x0000,0x2126,0x213C,0x2133,0x2134,0x0000
};
-static const int ucs_a2_jis_table_min = 0x2000;
-static const int ucs_a2_jis_table_max = 0x2000 + (sizeof (ucs_a2_jis_table) / sizeof (unsigned short));
+const int ucs_a2_jis_table_min = 0x2000;
+const int ucs_a2_jis_table_max = 0x2000 + (sizeof (ucs_a2_jis_table) / sizeof (unsigned short));
-static const unsigned short ucs_i_jis_table[] = {
+const unsigned short ucs_i_jis_table[] = {
/* 4E00h */
0x306C,0x437A,0xB0A1,0x3C37,0xB0A2,0xB0A3,0x0000,0x4B7C,
0x3E66,0x3B30,0x3E65,0x323C,0xB0A4,0x4954,0x4D3F,0x0000,
@@ -5805,11 +5807,11 @@ static const unsigned short ucs_i_jis_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
-static const int ucs_i_jis_table_min = 0x4E00;
-static const int ucs_i_jis_table_max = 0x4E00 + (sizeof (ucs_i_jis_table) / sizeof (unsigned short));
+const int ucs_i_jis_table_min = 0x4E00;
+const int ucs_i_jis_table_max = 0x4E00 + (sizeof (ucs_i_jis_table) / sizeof (unsigned short));
-static const unsigned short ucs_r_jis_table[] = {
+const unsigned short ucs_r_jis_table[] = {
/* FF00h */
0x0000,0x212A,0x0000,0x2174,0x2170,0x2173,0x2175,0x0000,
0x214A,0x214B,0x2176,0x215C,0x2124,0x0000,0x2125,0x213F,
@@ -5818,7 +5820,7 @@ static const unsigned short ucs_r_jis_table[] = {
0x2177,0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,
0x2348,0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F,
0x2350,0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,
- 0x2358,0x2359,0x235A,0x214E,0x2140,0x214F,0x2130,0x2132,
+ 0x2358,0x2359,0x235A,0x214E,0x0000,0x214F,0x2130,0x2132,
0x212E,0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,
0x2368,0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F,
0x2370,0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,
@@ -5841,7 +5843,30 @@ static const unsigned short ucs_r_jis_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x2131,0x0000,0x216F
};
-static const int ucs_r_jis_table_min = 0xFF00;
-static const int ucs_r_jis_table_max = 0xFF00 + (sizeof (ucs_r_jis_table) / sizeof (unsigned short));
+int ucs_r_jis_table_min = 0xFF00;
+int ucs_r_jis_table_max = 0xFF00 + (sizeof (ucs_r_jis_table) / sizeof (unsigned short));
+
+#else
+
+extern const unsigned short jisx0208_ucs_table[];
+extern const unsigned short jisx0212_ucs_table[];
+extern const unsigned short ucs_a1_jis_table[];
+extern const unsigned short ucs_a2_jis_table[];
+extern const unsigned short ucs_i_jis_table[];
+extern const unsigned short ucs_r_jis_table[];
+
+extern const int jisx0208_ucs_table_size;
+extern const int jisx0212_ucs_table_size;
+extern const int ucs_a1_jis_table_min;
+extern const int ucs_a1_jis_table_max;
+extern const int ucs_a2_jis_table_min;
+extern const int ucs_a2_jis_table_max;
+extern const int ucs_i_jis_table_min;
+extern const int ucs_i_jis_table_max;
+extern int ucs_r_jis_table_min;
+extern int ucs_r_jis_table_max;
+
+#endif
+
#endif /* UNICODE_TABLE_JIS_H */
diff --git a/ext/mbstring/libmbfl/filters/unicode_table_jis2004.h b/ext/mbstring/libmbfl/filters/unicode_table_jis2004.h
new file mode 100644
index 0000000000..5ae282e91b
--- /dev/null
+++ b/ext/mbstring/libmbfl/filters/unicode_table_jis2004.h
@@ -0,0 +1,5067 @@
+/*
+ * "streamable kanji code filter and converter"
+ * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
+ *
+ * LICENSE NOTICES
+ *
+ * This file is part of "streamable kanji code filter and converter",
+ * which is distributed under the terms of GNU Lesser General Public
+ * License (version 2) as published by the Free Software Foundation.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with "streamable kanji code filter and converter";
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The author of this file: Rui Hirokawa <hirokawa@php.net>
+ */
+
+#ifndef UNICODE_TABLE_JIS2004_H
+#define UNICODE_TABLE_JIS2004_H
+
+/*
+ * Unicode table
+ */
+
+static const unsigned short jisx0213_ucs_table[] = { // 0x0000 - 0x2C0F
+
+/* plane 1 ku 1 */
+0x3000,0x3001,0x3002,0xFF0C,0xFF0E,0x30FB,0xFF1A,0xFF1B,
+0xFF1F,0xFF01,0x309B,0x309C,0x00B4,0xFF40,0x00A8,0xFF3E,
+0xFFE3,0xFF3F,0x30FD,0x30FE,0x309D,0x309E,0x3003,0x4EDD,
+0x3005,0x3006,0x3007,0x30FC,0x2014,0x2010,0xFF0F,0xFF3C,
+0x301C,0x2016,0xFF5C,0x2026,0x2025,0x2018,0x2019,0x201C,
+0x201D,0xFF08,0xFF09,0x3014,0x3015,0xFF3B,0xFF3D,0xFF5B,
+0xFF5D,0x3008,0x3009,0x300A,0x300B,0x300C,0x300D,0x300E,
+0x300F,0x3010,0x3011,0xFF0B,0x2212,0x00B1,0x00D7,0x00F7,
+0xFF1D,0x2260,0xFF1C,0xFF1E,0x2266,0x2267,0x221E,0x2234,
+0x2642,0x2640,0x00B0,0x2032,0x2033,0x2103,0xFFE5,0xFF04,
+0x00A2,0x00A3,0xFF05,0xFF03,0xFF06,0xFF0A,0xFF20,0x00A7,
+0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7,
+/* plane 1 ku 2 */
+0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,0x25BD,0x25BC,0x203B,
+0x3012,0x2192,0x2190,0x2191,0x2193,0x3013,0xFF07,0xFF02,
+0xFF0D,0xFF5E,0x3033,0x3034,0x3035,0x303B,0x303C,0x30FF,
+0x309F,0x2208,0x220B,0x2286,0x2287,0x2282,0x2283,0x222A,
+0x2229,0x2284,0x2285,0x228A,0x228B,0x2209,0x2205,0x2305,
+0x2306,0x2227,0x2228,0x00AC,0x21D2,0x21D4,0x2200,0x2203,
+0x2295,0x2296,0x2297,0x2225,0x2226,0xFF5F,0xFF60,0x3018,
+0x3019,0x3016,0x3017,0x2220,0x22A5,0x2312,0x2202,0x2207,
+0x2261,0x2252,0x226A,0x226B,0x221A,0x223D,0x221D,0x2235,
+0x222B,0x222C,0x2262,0x2243,0x2245,0x2248,0x2276,0x2277,
+0x2194,0x212B,0x2030,0x266F,0x266D,0x266A,0x2020,0x2021,
+0x00B6,0x266E,0x266B,0x266C,0x2669,0x25EF,
+/* plane 1 ku 3 */
+0x25B7,0x25B6,0x25C1,0x25C0,0x2197,0x2198,0x2196,0x2199,
+0x21C4,0x21E8,0x21E6,0x21E7,0x21E9,0x2934,0x2935,0xFF10,
+0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,
+0xFF19,0x29BF,0x25C9,0x303D,0xFE46,0xFE45,0x25E6,0x2022,
+0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,
+0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,
+0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,
+0xFF39,0xFF3A,0x2213,0x2135,0x210F,0x33CB,0x2113,0x2127,
+0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,
+0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,
+0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,
+0xFF59,0xFF5A,0x30A0,0x2013,0x29FA,0x29FB,
+/* plane 1 ku 4 */
+0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,
+0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,
+0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,
+0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,
+0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,
+0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,
+0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,
+0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,
+0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,
+0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,
+0x3091,0x3092,0x3093,0x3094,0x3095,0x3096,0x0000,0x304D,
+0x304F,0x3051,0x3053,0x0000,0x0000,0x0000,
+/* plane 1 ku 5 */
+0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,
+0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,
+0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,
+0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,
+0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,
+0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,
+0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,
+0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,0x30E0,
+0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,
+0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,0x30F0,
+0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6,0x30AB,0x30AD,
+0x30AF,0x30B1,0x30B3,0x30BB,0x30C4,0x30C8,
+/* plane 1 ku 6 */
+0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
+0x0399,0x039A,0x039B,0x039C,0x039D,0x039E,0x039F,0x03A0,
+0x03A1,0x03A3,0x03A4,0x03A5,0x03A6,0x03A7,0x03A8,0x03A9,
+0x2664,0x2660,0x2662,0x2666,0x2661,0x2665,0x2667,0x2663,
+0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,
+0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF,0x03C0,
+0x03C1,0x03C3,0x03C4,0x03C5,0x03C6,0x03C7,0x03C8,0x03C9,
+0x03C2,0x24F5,0x24F6,0x24F7,0x24F8,0x24F9,0x24FA,0x24FB,
+0x24FC,0x24FD,0x24FE,0x2616,0x2617,0x3020,0x260E,0x2600,
+0x2601,0x2602,0x2603,0x2668,0x25B1,0x31F0,0x31F1,0x31F2,
+0x31F3,0x31F4,0x31F5,0x31F6,0x31F7,0x31F8,0x31F9,0x31F7,
+0x31FA,0x31FB,0x31FC,0x31FD,0x31FE,0x31FF,
+/* plane 1 ku 7 */
+0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,
+0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,
+0x041F,0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,
+0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,
+0x042F,0x23BE,0x23BF,0x23C0,0x23C1,0x23C2,0x23C3,0x23C4,
+0x23C5,0x23C6,0x23C7,0x23C8,0x23C9,0x23CA,0x23CB,0x23CC,
+0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0451,0x0436,
+0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,
+0x043F,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,
+0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,
+0x044F,0x30F7,0x30F8,0x30F9,0x30FA,0x22DA,0x22DB,0x2153,
+0x2154,0x2155,0x2713,0x2318,0x2423,0x23CE,
+/* plane 1 ku 8 */
+0x2500,0x2502,0x250C,0x2510,0x2518,0x2514,0x251C,0x252C,
+0x2524,0x2534,0x253C,0x2501,0x2503,0x250F,0x2513,0x251B,
+0x2517,0x2523,0x2533,0x252B,0x253B,0x254B,0x2520,0x252F,
+0x2528,0x2537,0x253F,0x251D,0x2530,0x2525,0x2538,0x2542,
+0x3251,0x3252,0x3253,0x3254,0x3255,0x3256,0x3257,0x3258,
+0x3259,0x325A,0x325B,0x325C,0x325D,0x325E,0x325F,0x32B1,
+0x32B2,0x32B3,0x32B4,0x32B5,0x32B6,0x32B7,0x32B8,0x32B9,
+0x32BA,0x32BB,0x32BC,0x32BD,0x32BE,0x32BF,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x25D0,0x25D1,
+0x25D2,0x25D3,0x203C,0x2047,0x2048,0x2049,0x01CD,0x01CE,
+0x01D0,0x1E3E,0x1E3F,0x01F8,0x01F9,0x01D1,0x01D2,0x01D4,
+0x01D6,0x01D8,0x01DA,0x01DC,0x0000,0x0000,
+/* plane 1 ku 9 */
+0x20AC,0x00A0,0x00A1,0x00A4,0x00A6,0x00A9,0x00AA,0x00AB,
+0x00AD,0x00AE,0x00AF,0x00B2,0x00B3,0x00B7,0x00B8,0x00B9,
+0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF,0x00C0,0x00C1,
+0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,
+0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF,0x00D0,0x00D1,
+0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D8,0x00D9,0x00DA,
+0x00DB,0x00DC,0x00DD,0x00DE,0x00DF,0x00E0,0x00E1,0x00E2,
+0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,0x00E8,0x00E9,0x00EA,
+0x00EB,0x00EC,0x00ED,0x00EE,0x00EF,0x00F0,0x00F1,0x00F2,
+0x00F3,0x00F4,0x00F5,0x00F6,0x00F8,0x00F9,0x00FA,0x00FB,
+0x00FC,0x00FD,0x00FE,0x00FF,0x0100,0x012A,0x016A,0x0112,
+0x014C,0x0101,0x012B,0x016B,0x0113,0x014D,
+/* plane 1 ku 10 */
+0x0104,0x02D8,0x0141,0x013D,0x015A,0x0160,0x015E,0x0164,
+0x0179,0x017D,0x017B,0x0105,0x02DB,0x0142,0x013E,0x015B,
+0x02C7,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
+0x0154,0x0102,0x0139,0x0106,0x010C,0x0118,0x011A,0x010E,
+0x0143,0x0147,0x0150,0x0158,0x016E,0x0170,0x0162,0x0155,
+0x0103,0x013A,0x0107,0x010D,0x0119,0x011B,0x010F,0x0111,
+0x0144,0x0148,0x0151,0x0159,0x016F,0x0171,0x0163,0x02D9,
+0x0108,0x011C,0x0124,0x0134,0x015C,0x016C,0x0109,0x011D,
+0x0125,0x0135,0x015D,0x016D,0x0271,0x028B,0x027E,0x0283,
+0x0292,0x026C,0x026E,0x0279,0x0288,0x0256,0x0273,0x027D,
+0x0282,0x0290,0x027B,0x026D,0x025F,0x0272,0x029D,0x028E,
+0x0261,0x014B,0x0270,0x0281,0x0127,0x0295,
+/* plane 1 ku 11 */
+0x0294,0x0266,0x0298,0x01C2,0x0253,0x0257,0x0284,0x0260,
+0x0193,0x0153,0x0152,0x0268,0x0289,0x0258,0x0275,0x0259,
+0x025C,0x025E,0x0250,0x026F,0x028A,0x0264,0x028C,0x0254,
+0x0251,0x0252,0x028D,0x0265,0x02A2,0x02A1,0x0255,0x0291,
+0x027A,0x0267,0x025A,0x00E6,0x01FD,0x1F70,0x1F71,0x0254,
+0x0254,0x028C,0x028C,0x0259,0x0259,0x025A,0x025A,0x1F72,
+0x1F73,0x0361,0x02C8,0x02CC,0x02D0,0x02D1,0x0306,0x203F,
+0x030B,0x0301,0x0304,0x0300,0x030F,0x030C,0x0302,0x02E5,
+0x02E6,0x02E7,0x02E8,0x02E9,0x02E9,0x02E5,0x0325,0x032C,
+0x0339,0x031C,0x031F,0x0320,0x0308,0x033D,0x0329,0x032F,
+0x02DE,0x0324,0x0330,0x033C,0x0334,0x031D,0x031E,0x0318,
+0x0319,0x032A,0x033A,0x033B,0x0303,0x031A,
+/* plane 1 ku 12 */
+0x2776,0x2777,0x2778,0x2779,0x277A,0x277B,0x277C,0x277D,
+0x277E,0x277F,0x24EB,0x24EC,0x24ED,0x24EE,0x24EF,0x24F0,
+0x24F1,0x24F2,0x24F3,0x24F4,0x2170,0x2171,0x2172,0x2173,
+0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0x217A,0x217B,
+0x24D0,0x24D1,0x24D2,0x24D3,0x24D4,0x24D5,0x24D6,0x24D7,
+0x24D8,0x24D9,0x24DA,0x24DB,0x24DC,0x24DD,0x24DE,0x24DF,
+0x24E0,0x24E1,0x24E2,0x24E3,0x24E4,0x24E5,0x24E6,0x24E7,
+0x24E8,0x24E9,0x32D0,0x32D1,0x32D2,0x32D3,0x32D4,0x32D5,
+0x32D6,0x32D7,0x32D8,0x32D9,0x32DA,0x32DB,0x32DC,0x32DD,
+0x32DE,0x32DF,0x32E0,0x32E1,0x32E2,0x32E3,0x32FA,0x32E9,
+0x32E5,0x32ED,0x32EC,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x2051,0x2042,
+/* plane 1 ku 13 */
+0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
+0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
+0x2470,0x2471,0x2472,0x2473,0x2160,0x2161,0x2162,0x2163,
+0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,0x216A,0x3349,
+0x3314,0x3322,0x334D,0x3318,0x3327,0x3303,0x3336,0x3351,
+0x3357,0x330D,0x3326,0x3323,0x332B,0x334A,0x333B,0x339C,
+0x339D,0x339E,0x338E,0x338F,0x33C4,0x33A1,0x216B,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x337B,0x301D,
+0x301F,0x2116,0x33CD,0x2121,0x32A4,0x32A5,0x32A6,0x32A7,
+0x32A8,0x3231,0x3232,0x3239,0x337E,0x337D,0x337C,0x0000,
+0x0000,0x0000,0x222E,0x0000,0x0000,0x0000,0x0000,0x221F,
+0x22BF,0x0000,0x0000,0x0000,0x2756,0x261E,
+/* plane 1 ku 14 */
+0x4FF1,0x0000,0x3402,0x4E28,0x4E2F,0x4E30,0x4E8D,0x4EE1,
+0x4EFD,0x4EFF,0x4F03,0x4F0B,0x4F60,0x4F48,0x4F49,0x4F56,
+0x4F5F,0x4F6A,0x4F6C,0x4F7E,0x4F8A,0x4F94,0x4F97,0xFA30,
+0x4FC9,0x4FE0,0x5001,0x5002,0x500E,0x5018,0x5027,0x502E,
+0x5040,0x503B,0x5041,0x5094,0x50CC,0x50F2,0x50D0,0x50E6,
+0xFA31,0x5106,0x5103,0x510B,0x511E,0x5135,0x514A,0xFA32,
+0x5155,0x5157,0x34B5,0x519D,0x51C3,0x51CA,0x51DE,0x51E2,
+0x51EE,0x5201,0x34DB,0x5213,0x5215,0x5249,0x5257,0x5261,
+0x5293,0x52C8,0xFA33,0x52CC,0x52D0,0x52D6,0x52DB,0xFA34,
+0x52F0,0x52FB,0x5300,0x5307,0x531C,0xFA35,0x5361,0x5363,
+0x537D,0x5393,0x539D,0x53B2,0x5412,0x5427,0x544D,0x549C,
+0x546B,0x5474,0x547F,0x5488,0x5496,0x54A1,
+/* plane 1 ku 15 */
+0x54A9,0x54C6,0x54FF,0x550E,0x552B,0x5535,0x5550,0x555E,
+0x5581,0x5586,0x558E,0xFA36,0x55AD,0x55CE,0xFA37,0x5608,
+0x560E,0x563B,0x5649,0x5676,0x5666,0xFA38,0x566F,0x5671,
+0x5672,0x5699,0x569E,0x56A9,0x56AC,0x56B3,0x56C9,0x56CA,
+0x570A,0x0000,0x5721,0x572F,0x5733,0x5734,0x5770,0x5777,
+0x577C,0x579C,0xFA0F,0x0000,0x57B8,0x57C7,0x57C8,0x57CF,
+0x57E4,0x57ED,0x57F5,0x57F6,0x57FF,0x5809,0xFA10,0x5861,
+0x5864,0xFA39,0x587C,0x5889,0x589E,0xFA3A,0x58A9,0x0000,
+0x58D2,0x58CE,0x58D4,0x58DA,0x58E0,0x58E9,0x590C,0x8641,
+0x595D,0x596D,0x598B,0x5992,0x59A4,0x59C3,0x59D2,0x59DD,
+0x5A13,0x5A23,0x5A67,0x5A6D,0x5A77,0x5A7E,0x5A84,0x5A9E,
+0x5AA7,0x5AC4,0x0000,0x5B19,0x5B25,0x525D,
+/* plane 1 ku 16 */
+0x4E9C,0x5516,0x5A03,0x963F,0x54C0,0x611B,0x6328,0x59F6,
+0x9022,0x8475,0x831C,0x7A50,0x60AA,0x63E1,0x6E25,0x65ED,
+0x8466,0x82A6,0x9BF5,0x6893,0x5727,0x65A1,0x6271,0x5B9B,
+0x59D0,0x867B,0x98F4,0x7D62,0x7DBE,0x9B8E,0x6216,0x7C9F,
+0x88B7,0x5B89,0x5EB5,0x6309,0x6697,0x6848,0x95C7,0x978D,
+0x674F,0x4EE5,0x4F0A,0x4F4D,0x4F9D,0x5049,0x56F2,0x5937,
+0x59D4,0x5A01,0x5C09,0x60DF,0x610F,0x6170,0x6613,0x6905,
+0x70BA,0x754F,0x7570,0x79FB,0x7DAD,0x7DEF,0x80C3,0x840E,
+0x8863,0x8B02,0x9055,0x907A,0x533B,0x4E95,0x4EA5,0x57DF,
+0x80B2,0x90C1,0x78EF,0x4E00,0x58F1,0x6EA2,0x9038,0x7A32,
+0x8328,0x828B,0x9C2F,0x5141,0x5370,0x54BD,0x54E1,0x56E0,
+0x59FB,0x5F15,0x98F2,0x6DEB,0x80E4,0x852D,
+/* plane 1 ku 17 */
+0x9662,0x9670,0x96A0,0x97FB,0x540B,0x53F3,0x5B87,0x70CF,
+0x7FBD,0x8FC2,0x96E8,0x536F,0x9D5C,0x7ABA,0x4E11,0x7893,
+0x81FC,0x6E26,0x5618,0x5504,0x6B1D,0x851A,0x9C3B,0x59E5,
+0x53A9,0x6D66,0x74DC,0x958F,0x5642,0x4E91,0x904B,0x96F2,
+0x834F,0x990C,0x53E1,0x55B6,0x5B30,0x5F71,0x6620,0x66F3,
+0x6804,0x6C38,0x6CF3,0x6D29,0x745B,0x76C8,0x7A4E,0x9834,
+0x82F1,0x885B,0x8A60,0x92ED,0x6DB2,0x75AB,0x76CA,0x99C5,
+0x60A6,0x8B01,0x8D8A,0x95B2,0x698E,0x53AD,0x5186,0x5712,
+0x5830,0x5944,0x5BB4,0x5EF6,0x6028,0x63A9,0x63F4,0x6CBF,
+0x6F14,0x708E,0x7114,0x7159,0x71D5,0x733F,0x7E01,0x8276,
+0x82D1,0x8597,0x9060,0x925B,0x9D1B,0x5869,0x65BC,0x6C5A,
+0x7525,0x51F9,0x592E,0x5965,0x5F80,0x5FDC,
+/* plane 1 ku 18 */
+0x62BC,0x65FA,0x6A2A,0x6B27,0x6BB4,0x738B,0x7FC1,0x8956,
+0x9D2C,0x9D0E,0x9EC4,0x5CA1,0x6C96,0x837B,0x5104,0x5C4B,
+0x61B6,0x81C6,0x6876,0x7261,0x4E59,0x4FFA,0x5378,0x6069,
+0x6E29,0x7A4F,0x97F3,0x4E0B,0x5316,0x4EEE,0x4F55,0x4F3D,
+0x4FA1,0x4F73,0x52A0,0x53EF,0x5609,0x590F,0x5AC1,0x5BB6,
+0x5BE1,0x79D1,0x6687,0x679C,0x67B6,0x6B4C,0x6CB3,0x706B,
+0x73C2,0x798D,0x79BE,0x7A3C,0x7B87,0x82B1,0x82DB,0x8304,
+0x8377,0x83EF,0x83D3,0x8766,0x8AB2,0x5629,0x8CA8,0x8FE6,
+0x904E,0x971E,0x868A,0x4FC4,0x5CE8,0x6211,0x7259,0x753B,
+0x81E5,0x82BD,0x86FE,0x8CC0,0x96C5,0x9913,0x99D5,0x4ECB,
+0x4F1A,0x89E3,0x56DE,0x584A,0x58CA,0x5EFB,0x5FEB,0x602A,
+0x6094,0x6062,0x61D0,0x6212,0x62D0,0x6539,
+/* plane 1 ku 19 */
+0x9B41,0x6666,0x68B0,0x6D77,0x7070,0x754C,0x7686,0x7D75,
+0x82A5,0x87F9,0x958B,0x968E,0x8C9D,0x51F1,0x52BE,0x5916,
+0x54B3,0x5BB3,0x5D16,0x6168,0x6982,0x6DAF,0x788D,0x84CB,
+0x8857,0x8A72,0x93A7,0x9AB8,0x6D6C,0x99A8,0x86D9,0x57A3,
+0x67FF,0x86CE,0x920E,0x5283,0x5687,0x5404,0x5ED3,0x62E1,
+0x64B9,0x683C,0x6838,0x6BBB,0x7372,0x78BA,0x7A6B,0x899A,
+0x89D2,0x8D6B,0x8F03,0x90ED,0x95A3,0x9694,0x9769,0x5B66,
+0x5CB3,0x697D,0x984D,0x984E,0x639B,0x7B20,0x6A2B,0x6A7F,
+0x68B6,0x9C0D,0x6F5F,0x5272,0x559D,0x6070,0x62EC,0x6D3B,
+0x6E07,0x6ED1,0x845B,0x8910,0x8F44,0x4E14,0x9C39,0x53F6,
+0x691B,0x6A3A,0x9784,0x682A,0x515C,0x7AC3,0x84B2,0x91DC,
+0x938C,0x565B,0x9D28,0x6822,0x8305,0x8431,
+/* plane 1 ku 20 */
+0x7CA5,0x5208,0x82C5,0x74E6,0x4E7E,0x4F83,0x51A0,0x5BD2,
+0x520A,0x52D8,0x52E7,0x5DFB,0x559A,0x582A,0x59E6,0x5B8C,
+0x5B98,0x5BDB,0x5E72,0x5E79,0x60A3,0x611F,0x6163,0x61BE,
+0x63DB,0x6562,0x67D1,0x6853,0x68FA,0x6B3E,0x6B53,0x6C57,
+0x6F22,0x6F97,0x6F45,0x74B0,0x7518,0x76E3,0x770B,0x7AFF,
+0x7BA1,0x7C21,0x7DE9,0x7F36,0x7FF0,0x809D,0x8266,0x839E,
+0x89B3,0x8ACC,0x8CAB,0x9084,0x9451,0x9593,0x9591,0x95A2,
+0x9665,0x97D3,0x9928,0x8218,0x4E38,0x542B,0x5CB8,0x5DCC,
+0x73A9,0x764C,0x773C,0x5CA9,0x7FEB,0x8D0B,0x96C1,0x9811,
+0x9854,0x9858,0x4F01,0x4F0E,0x5371,0x559C,0x5668,0x57FA,
+0x5947,0x5B09,0x5BC4,0x5C90,0x5E0C,0x5E7E,0x5FCC,0x63EE,
+0x673A,0x65D7,0x65E2,0x671F,0x68CB,0x68C4,
+/* plane 1 ku 21 */
+0x6A5F,0x5E30,0x6BC5,0x6C17,0x6C7D,0x757F,0x7948,0x5B63,
+0x7A00,0x7D00,0x5FBD,0x898F,0x8A18,0x8CB4,0x8D77,0x8ECC,
+0x8F1D,0x98E2,0x9A0E,0x9B3C,0x4E80,0x507D,0x5100,0x5993,
+0x5B9C,0x622F,0x6280,0x64EC,0x6B3A,0x72A0,0x7591,0x7947,
+0x7FA9,0x87FB,0x8ABC,0x8B70,0x63AC,0x83CA,0x97A0,0x5409,
+0x5403,0x55AB,0x6854,0x6A58,0x8A70,0x7827,0x6775,0x9ECD,
+0x5374,0x5BA2,0x811A,0x8650,0x9006,0x4E18,0x4E45,0x4EC7,
+0x4F11,0x53CA,0x5438,0x5BAE,0x5F13,0x6025,0x6551,0x673D,
+0x6C42,0x6C72,0x6CE3,0x7078,0x7403,0x7A76,0x7AAE,0x7B08,
+0x7D1A,0x7CFE,0x7D66,0x65E7,0x725B,0x53BB,0x5C45,0x5DE8,
+0x62D2,0x62E0,0x6319,0x6E20,0x865A,0x8A31,0x8DDD,0x92F8,
+0x6F01,0x79A6,0x9B5A,0x4EA8,0x4EAB,0x4EAC,
+/* plane 1 ku 22 */
+0x4F9B,0x4FA0,0x50D1,0x5147,0x7AF6,0x5171,0x51F6,0x5354,
+0x5321,0x537F,0x53EB,0x55AC,0x5883,0x5CE1,0x5F37,0x5F4A,
+0x602F,0x6050,0x606D,0x631F,0x6559,0x6A4B,0x6CC1,0x72C2,
+0x72ED,0x77EF,0x80F8,0x8105,0x8208,0x854E,0x90F7,0x93E1,
+0x97FF,0x9957,0x9A5A,0x4EF0,0x51DD,0x5C2D,0x6681,0x696D,
+0x5C40,0x66F2,0x6975,0x7389,0x6850,0x7C81,0x50C5,0x52E4,
+0x5747,0x5DFE,0x9326,0x65A4,0x6B23,0x6B3D,0x7434,0x7981,
+0x79BD,0x7B4B,0x7DCA,0x82B9,0x83CC,0x887F,0x895F,0x8B39,
+0x8FD1,0x91D1,0x541F,0x9280,0x4E5D,0x5036,0x53E5,0x533A,
+0x72D7,0x7396,0x77E9,0x82E6,0x8EAF,0x99C6,0x99C8,0x99D2,
+0x5177,0x611A,0x865E,0x55B0,0x7A7A,0x5076,0x5BD3,0x9047,
+0x9685,0x4E32,0x6ADB,0x91E7,0x5C51,0x5C48,
+/* plane 1 ku 23 */
+0x6398,0x7A9F,0x6C93,0x9774,0x8F61,0x7AAA,0x718A,0x9688,
+0x7C82,0x6817,0x7E70,0x6851,0x936C,0x52F2,0x541B,0x85AB,
+0x8A13,0x7FA4,0x8ECD,0x90E1,0x5366,0x8888,0x7941,0x4FC2,
+0x50BE,0x5211,0x5144,0x5553,0x572D,0x73EA,0x578B,0x5951,
+0x5F62,0x5F84,0x6075,0x6176,0x6167,0x61A9,0x63B2,0x643A,
+0x656C,0x666F,0x6842,0x6E13,0x7566,0x7A3D,0x7CFB,0x7D4C,
+0x7D99,0x7E4B,0x7F6B,0x830E,0x834A,0x86CD,0x8A08,0x8A63,
+0x8B66,0x8EFD,0x981A,0x9D8F,0x82B8,0x8FCE,0x9BE8,0x5287,
+0x621F,0x6483,0x6FC0,0x9699,0x6841,0x5091,0x6B20,0x6C7A,
+0x6F54,0x7A74,0x7D50,0x8840,0x8A23,0x6708,0x4EF6,0x5039,
+0x5026,0x5065,0x517C,0x5238,0x5263,0x55A7,0x570F,0x5805,
+0x5ACC,0x5EFA,0x61B2,0x61F8,0x62F3,0x6372,
+/* plane 1 ku 24 */
+0x691C,0x6A29,0x727D,0x72AC,0x732E,0x7814,0x786F,0x7D79,
+0x770C,0x80A9,0x898B,0x8B19,0x8CE2,0x8ED2,0x9063,0x9375,
+0x967A,0x9855,0x9A13,0x9E78,0x5143,0x539F,0x53B3,0x5E7B,
+0x5F26,0x6E1B,0x6E90,0x7384,0x73FE,0x7D43,0x8237,0x8A00,
+0x8AFA,0x9650,0x4E4E,0x500B,0x53E4,0x547C,0x56FA,0x59D1,
+0x5B64,0x5DF1,0x5EAB,0x5F27,0x6238,0x6545,0x67AF,0x6E56,
+0x72D0,0x7CCA,0x88B4,0x80A1,0x80E1,0x83F0,0x864E,0x8A87,
+0x8DE8,0x9237,0x96C7,0x9867,0x9F13,0x4E94,0x4E92,0x4F0D,
+0x5348,0x5449,0x543E,0x5A2F,0x5F8C,0x5FA1,0x609F,0x68A7,
+0x6A8E,0x745A,0x7881,0x8A9E,0x8AA4,0x8B77,0x9190,0x4E5E,
+0x9BC9,0x4EA4,0x4F7C,0x4FAF,0x5019,0x5016,0x5149,0x516C,
+0x529F,0x52B9,0x52FE,0x539A,0x53E3,0x5411,
+/* plane 1 ku 25 */
+0x540E,0x5589,0x5751,0x57A2,0x597D,0x5B54,0x5B5D,0x5B8F,
+0x5DE5,0x5DE7,0x5DF7,0x5E78,0x5E83,0x5E9A,0x5EB7,0x5F18,
+0x6052,0x614C,0x6297,0x62D8,0x63A7,0x653B,0x6602,0x6643,
+0x66F4,0x676D,0x6821,0x6897,0x69CB,0x6C5F,0x6D2A,0x6D69,
+0x6E2F,0x6E9D,0x7532,0x7687,0x786C,0x7A3F,0x7CE0,0x7D05,
+0x7D18,0x7D5E,0x7DB1,0x8015,0x8003,0x80AF,0x80B1,0x8154,
+0x818F,0x822A,0x8352,0x884C,0x8861,0x8B1B,0x8CA2,0x8CFC,
+0x90CA,0x9175,0x9271,0x783F,0x92FC,0x95A4,0x964D,0x9805,
+0x9999,0x9AD8,0x9D3B,0x525B,0x52AB,0x53F7,0x5408,0x58D5,
+0x62F7,0x6FE0,0x8C6A,0x8F5F,0x9EB9,0x514B,0x523B,0x544A,
+0x56FD,0x7A40,0x9177,0x9D60,0x9ED2,0x7344,0x6F09,0x8170,
+0x7511,0x5FFD,0x60DA,0x9AA8,0x72DB,0x8FBC,
+/* plane 1 ku 26 */
+0x6B64,0x9803,0x4ECA,0x56F0,0x5764,0x58BE,0x5A5A,0x6068,
+0x61C7,0x660F,0x6606,0x6839,0x68B1,0x6DF7,0x75D5,0x7D3A,
+0x826E,0x9B42,0x4E9B,0x4F50,0x53C9,0x5506,0x5D6F,0x5DE6,
+0x5DEE,0x67FB,0x6C99,0x7473,0x7802,0x8A50,0x9396,0x88DF,
+0x5750,0x5EA7,0x632B,0x50B5,0x50AC,0x518D,0x6700,0x54C9,
+0x585E,0x59BB,0x5BB0,0x5F69,0x624D,0x63A1,0x683D,0x6B73,
+0x6E08,0x707D,0x91C7,0x7280,0x7815,0x7826,0x796D,0x658E,
+0x7D30,0x83DC,0x88C1,0x8F09,0x969B,0x5264,0x5728,0x6750,
+0x7F6A,0x8CA1,0x51B4,0x5742,0x962A,0x583A,0x698A,0x80B4,
+0x54B2,0x5D0E,0x57FC,0x7895,0x9DFA,0x4F5C,0x524A,0x548B,
+0x643E,0x6628,0x6714,0x67F5,0x7A84,0x7B56,0x7D22,0x932F,
+0x685C,0x9BAD,0x7B39,0x5319,0x518A,0x5237,
+/* plane 1 ku 27 */
+0x5BDF,0x62F6,0x64AE,0x64E6,0x672D,0x6BBA,0x85A9,0x96D1,
+0x7690,0x9BD6,0x634C,0x9306,0x9BAB,0x76BF,0x6652,0x4E09,
+0x5098,0x53C2,0x5C71,0x60E8,0x6492,0x6563,0x685F,0x71E6,
+0x73CA,0x7523,0x7B97,0x7E82,0x8695,0x8B83,0x8CDB,0x9178,
+0x9910,0x65AC,0x66AB,0x6B8B,0x4ED5,0x4ED4,0x4F3A,0x4F7F,
+0x523A,0x53F8,0x53F2,0x55E3,0x56DB,0x58EB,0x59CB,0x59C9,
+0x59FF,0x5B50,0x5C4D,0x5E02,0x5E2B,0x5FD7,0x601D,0x6307,
+0x652F,0x5B5C,0x65AF,0x65BD,0x65E8,0x679D,0x6B62,0x6B7B,
+0x6C0F,0x7345,0x7949,0x79C1,0x7CF8,0x7D19,0x7D2B,0x80A2,
+0x8102,0x81F3,0x8996,0x8A5E,0x8A69,0x8A66,0x8A8C,0x8AEE,
+0x8CC7,0x8CDC,0x96CC,0x98FC,0x6B6F,0x4E8B,0x4F3C,0x4F8D,
+0x5150,0x5B57,0x5BFA,0x6148,0x6301,0x6642,
+/* plane 1 ku 28 */
+0x6B21,0x6ECB,0x6CBB,0x723E,0x74BD,0x75D4,0x78C1,0x793A,
+0x800C,0x8033,0x81EA,0x8494,0x8F9E,0x6C50,0x9E7F,0x5F0F,
+0x8B58,0x9D2B,0x7AFA,0x8EF8,0x5B8D,0x96EB,0x4E03,0x53F1,
+0x57F7,0x5931,0x5AC9,0x5BA4,0x6089,0x6E7F,0x6F06,0x75BE,
+0x8CEA,0x5B9F,0x8500,0x7BE0,0x5072,0x67F4,0x829D,0x5C61,
+0x854A,0x7E1E,0x820E,0x5199,0x5C04,0x6368,0x8D66,0x659C,
+0x716E,0x793E,0x7D17,0x8005,0x8B1D,0x8ECA,0x906E,0x86C7,
+0x90AA,0x501F,0x52FA,0x5C3A,0x6753,0x707C,0x7235,0x914C,
+0x91C8,0x932B,0x82E5,0x5BC2,0x5F31,0x60F9,0x4E3B,0x53D6,
+0x5B88,0x624B,0x6731,0x6B8A,0x72E9,0x73E0,0x7A2E,0x816B,
+0x8DA3,0x9152,0x9996,0x5112,0x53D7,0x546A,0x5BFF,0x6388,
+0x6A39,0x7DAC,0x9700,0x56DA,0x53CE,0x5468,
+/* plane 1 ku 29 */
+0x5B97,0x5C31,0x5DDE,0x4FEE,0x6101,0x62FE,0x6D32,0x79C0,
+0x79CB,0x7D42,0x7E4D,0x7FD2,0x81ED,0x821F,0x8490,0x8846,
+0x8972,0x8B90,0x8E74,0x8F2F,0x9031,0x914B,0x916C,0x96C6,
+0x919C,0x4EC0,0x4F4F,0x5145,0x5341,0x5F93,0x620E,0x67D4,
+0x6C41,0x6E0B,0x7363,0x7E26,0x91CD,0x9283,0x53D4,0x5919,
+0x5BBF,0x6DD1,0x795D,0x7E2E,0x7C9B,0x587E,0x719F,0x51FA,
+0x8853,0x8FF0,0x4FCA,0x5CFB,0x6625,0x77AC,0x7AE3,0x821C,
+0x99FF,0x51C6,0x5FAA,0x65EC,0x696F,0x6B89,0x6DF3,0x6E96,
+0x6F64,0x76FE,0x7D14,0x5DE1,0x9075,0x9187,0x9806,0x51E6,
+0x521D,0x6240,0x6691,0x66D9,0x6E1A,0x5EB6,0x7DD2,0x7F72,
+0x66F8,0x85AF,0x85F7,0x8AF8,0x52A9,0x53D9,0x5973,0x5E8F,
+0x5F90,0x6055,0x92E4,0x9664,0x50B7,0x511F,
+/* ku 30 */
+0x52DD,0x5320,0x5347,0x53EC,0x54E8,0x5546,0x5531,0x5617,
+0x5968,0x59BE,0x5A3C,0x5BB5,0x5C06,0x5C0F,0x5C11,0x5C1A,
+0x5E84,0x5E8A,0x5EE0,0x5F70,0x627F,0x6284,0x62DB,0x638C,
+0x6377,0x6607,0x660C,0x662D,0x6676,0x677E,0x68A2,0x6A1F,
+0x6A35,0x6CBC,0x6D88,0x6E09,0x6E58,0x713C,0x7126,0x7167,
+0x75C7,0x7701,0x785D,0x7901,0x7965,0x79F0,0x7AE0,0x7B11,
+0x7CA7,0x7D39,0x8096,0x83D6,0x848B,0x8549,0x885D,0x88F3,
+0x8A1F,0x8A3C,0x8A54,0x8A73,0x8C61,0x8CDE,0x91A4,0x9266,
+0x937E,0x9418,0x969C,0x9798,0x4E0A,0x4E08,0x4E1E,0x4E57,
+0x5197,0x5270,0x57CE,0x5834,0x58CC,0x5B22,0x5E38,0x60C5,
+0x64FE,0x6761,0x6756,0x6D44,0x72B6,0x7573,0x7A63,0x84B8,
+0x8B72,0x91B8,0x9320,0x5631,0x57F4,0x98FE,
+/* ku 31 */
+0x62ED,0x690D,0x6B96,0x71ED,0x7E54,0x8077,0x8272,0x89E6,
+0x98DF,0x8755,0x8FB1,0x5C3B,0x4F38,0x4FE1,0x4FB5,0x5507,
+0x5A20,0x5BDD,0x5BE9,0x5FC3,0x614E,0x632F,0x65B0,0x664B,
+0x68EE,0x699B,0x6D78,0x6DF1,0x7533,0x75B9,0x771F,0x795E,
+0x79E6,0x7D33,0x81E3,0x82AF,0x85AA,0x89AA,0x8A3A,0x8EAB,
+0x8F9B,0x9032,0x91DD,0x9707,0x4EBA,0x4EC1,0x5203,0x5875,
+0x58EC,0x5C0B,0x751A,0x5C3D,0x814E,0x8A0A,0x8FC5,0x9663,
+0x976D,0x7B25,0x8ACF,0x9808,0x9162,0x56F3,0x53A8,0x9017,
+0x5439,0x5782,0x5E25,0x63A8,0x6C34,0x708A,0x7761,0x7C8B,
+0x7FE0,0x8870,0x9042,0x9154,0x9310,0x9318,0x968F,0x745E,
+0x9AC4,0x5D07,0x5D69,0x6570,0x67A2,0x8DA8,0x96DB,0x636E,
+0x6749,0x6919,0x83C5,0x9817,0x96C0,0x88FE,
+/* plane 1 ku 32 */
+0x6F84,0x647A,0x5BF8,0x4E16,0x702C,0x755D,0x662F,0x51C4,
+0x5236,0x52E2,0x59D3,0x5F81,0x6027,0x6210,0x653F,0x6574,
+0x661F,0x6674,0x68F2,0x6816,0x6B63,0x6E05,0x7272,0x751F,
+0x76DB,0x7CBE,0x8056,0x58F0,0x88FD,0x897F,0x8AA0,0x8A93,
+0x8ACB,0x901D,0x9192,0x9752,0x9759,0x6589,0x7A0E,0x8106,
+0x96BB,0x5E2D,0x60DC,0x621A,0x65A5,0x6614,0x6790,0x77F3,
+0x7A4D,0x7C4D,0x7E3E,0x810A,0x8CAC,0x8D64,0x8DE1,0x8E5F,
+0x78A9,0x5207,0x62D9,0x63A5,0x6442,0x6298,0x8A2D,0x7A83,
+0x7BC0,0x8AAC,0x96EA,0x7D76,0x820C,0x8749,0x4ED9,0x5148,
+0x5343,0x5360,0x5BA3,0x5C02,0x5C16,0x5DDD,0x6226,0x6247,
+0x64B0,0x6813,0x6834,0x6CC9,0x6D45,0x6D17,0x67D3,0x6F5C,
+0x714E,0x717D,0x65CB,0x7A7F,0x7BAD,0x7DDA,
+/* plane 1 ku 33 */
+0x7E4A,0x7FA8,0x817A,0x821B,0x8239,0x85A6,0x8A6E,0x8CCE,
+0x8DF5,0x9078,0x9077,0x92AD,0x9291,0x9583,0x9BAE,0x524D,
+0x5584,0x6F38,0x7136,0x5168,0x7985,0x7E55,0x81B3,0x7CCE,
+0x564C,0x5851,0x5CA8,0x63AA,0x66FE,0x66FD,0x695A,0x72D9,
+0x758F,0x758E,0x790E,0x7956,0x79DF,0x7C97,0x7D20,0x7D44,
+0x8607,0x8A34,0x963B,0x9061,0x9F20,0x50E7,0x5275,0x53CC,
+0x53E2,0x5009,0x55AA,0x58EE,0x594F,0x723D,0x5B8B,0x5C64,
+0x531D,0x60E3,0x60F3,0x635C,0x6383,0x633F,0x63BB,0x64CD,
+0x65E9,0x66F9,0x5DE3,0x69CD,0x69FD,0x6F15,0x71E5,0x4E89,
+0x75E9,0x76F8,0x7A93,0x7CDF,0x7DCF,0x7D9C,0x8061,0x8349,
+0x8358,0x846C,0x84BC,0x85FB,0x88C5,0x8D70,0x9001,0x906D,
+0x9397,0x971C,0x9A12,0x50CF,0x5897,0x618E,
+/* plane 1 ku 34 */
+0x81D3,0x8535,0x8D08,0x9020,0x4FC3,0x5074,0x5247,0x5373,
+0x606F,0x6349,0x675F,0x6E2C,0x8DB3,0x901F,0x4FD7,0x5C5E,
+0x8CCA,0x65CF,0x7D9A,0x5352,0x8896,0x5176,0x63C3,0x5B58,
+0x5B6B,0x5C0A,0x640D,0x6751,0x905C,0x4ED6,0x591A,0x592A,
+0x6C70,0x8A51,0x553E,0x5815,0x59A5,0x60F0,0x6253,0x67C1,
+0x8235,0x6955,0x9640,0x99C4,0x9A28,0x4F53,0x5806,0x5BFE,
+0x8010,0x5CB1,0x5E2F,0x5F85,0x6020,0x614B,0x6234,0x66FF,
+0x6CF0,0x6EDE,0x80CE,0x817F,0x82D4,0x888B,0x8CB8,0x9000,
+0x902E,0x968A,0x9EDB,0x9BDB,0x4EE3,0x53F0,0x5927,0x7B2C,
+0x918D,0x984C,0x9DF9,0x6EDD,0x7027,0x5353,0x5544,0x5B85,
+0x6258,0x629E,0x62D3,0x6CA2,0x6FEF,0x7422,0x8A17,0x9438,
+0x6FC1,0x8AFE,0x8338,0x51E7,0x86F8,0x53EA,
+/* plane 1 ku 35 */
+0x53E9,0x4F46,0x9054,0x8FB0,0x596A,0x8131,0x5DFD,0x7AEA,
+0x8FBF,0x68DA,0x8C37,0x72F8,0x9C48,0x6A3D,0x8AB0,0x4E39,
+0x5358,0x5606,0x5766,0x62C5,0x63A2,0x65E6,0x6B4E,0x6DE1,
+0x6E5B,0x70AD,0x77ED,0x7AEF,0x7BAA,0x7DBB,0x803D,0x80C6,
+0x86CB,0x8A95,0x935B,0x56E3,0x58C7,0x5F3E,0x65AD,0x6696,
+0x6A80,0x6BB5,0x7537,0x8AC7,0x5024,0x77E5,0x5730,0x5F1B,
+0x6065,0x667A,0x6C60,0x75F4,0x7A1A,0x7F6E,0x81F4,0x8718,
+0x9045,0x99B3,0x7BC9,0x755C,0x7AF9,0x7B51,0x84C4,0x9010,
+0x79E9,0x7A92,0x8336,0x5AE1,0x7740,0x4E2D,0x4EF2,0x5B99,
+0x5FE0,0x62BD,0x663C,0x67F1,0x6CE8,0x866B,0x8877,0x8A3B,
+0x914E,0x92F3,0x99D0,0x6A17,0x7026,0x732A,0x82E7,0x8457,
+0x8CAF,0x4E01,0x5146,0x51CB,0x558B,0x5BF5,
+/* plane 1 ku 36 */
+0x5E16,0x5E33,0x5E81,0x5F14,0x5F35,0x5F6B,0x5FB4,0x61F2,
+0x6311,0x66A2,0x671D,0x6F6E,0x7252,0x753A,0x773A,0x8074,
+0x8139,0x8178,0x8776,0x8ABF,0x8ADC,0x8D85,0x8DF3,0x929A,
+0x9577,0x9802,0x9CE5,0x52C5,0x6357,0x76F4,0x6715,0x6C88,
+0x73CD,0x8CC3,0x93AE,0x9673,0x6D25,0x589C,0x690E,0x69CC,
+0x8FFD,0x939A,0x75DB,0x901A,0x585A,0x6802,0x63B4,0x69FB,
+0x4F43,0x6F2C,0x67D8,0x8FBB,0x8526,0x7DB4,0x9354,0x693F,
+0x6F70,0x576A,0x58F7,0x5B2C,0x7D2C,0x722A,0x540A,0x91E3,
+0x9DB4,0x4EAD,0x4F4E,0x505C,0x5075,0x5243,0x8C9E,0x5448,
+0x5824,0x5B9A,0x5E1D,0x5E95,0x5EAD,0x5EF7,0x5F1F,0x608C,
+0x62B5,0x633A,0x63D0,0x68AF,0x6C40,0x7887,0x798E,0x7A0B,
+0x7DE0,0x8247,0x8A02,0x8AE6,0x8E44,0x9013,
+/* plane 1 ku 37 */
+0x90B8,0x912D,0x91D8,0x9F0E,0x6CE5,0x6458,0x64E2,0x6575,
+0x6EF4,0x7684,0x7B1B,0x9069,0x93D1,0x6EBA,0x54F2,0x5FB9,
+0x64A4,0x8F4D,0x8FED,0x9244,0x5178,0x586B,0x5929,0x5C55,
+0x5E97,0x6DFB,0x7E8F,0x751C,0x8CBC,0x8EE2,0x985B,0x70B9,
+0x4F1D,0x6BBF,0x6FB1,0x7530,0x96FB,0x514E,0x5410,0x5835,
+0x5857,0x59AC,0x5C60,0x5F92,0x6597,0x675C,0x6E21,0x767B,
+0x83DF,0x8CED,0x9014,0x90FD,0x934D,0x7825,0x783A,0x52AA,
+0x5EA6,0x571F,0x5974,0x6012,0x5012,0x515A,0x51AC,0x51CD,
+0x5200,0x5510,0x5854,0x5858,0x5957,0x5B95,0x5CF6,0x5D8B,
+0x60BC,0x6295,0x642D,0x6771,0x6843,0x68BC,0x68DF,0x76D7,
+0x6DD8,0x6E6F,0x6D9B,0x706F,0x71C8,0x5F53,0x75D8,0x7977,
+0x7B49,0x7B54,0x7B52,0x7CD6,0x7D71,0x5230,
+/* plane 1 ku 38 */
+0x8463,0x8569,0x85E4,0x8A0E,0x8B04,0x8C46,0x8E0F,0x9003,
+0x900F,0x9419,0x9676,0x982D,0x9A30,0x95D8,0x50CD,0x52D5,
+0x540C,0x5802,0x5C0E,0x61A7,0x649E,0x6D1E,0x77B3,0x7AE5,
+0x80F4,0x8404,0x9053,0x9285,0x5CE0,0x9D07,0x533F,0x5F97,
+0x5FB3,0x6D9C,0x7279,0x7763,0x79BF,0x7BE4,0x6BD2,0x72EC,
+0x8AAD,0x6803,0x6A61,0x51F8,0x7A81,0x6934,0x5C4A,0x9CF6,
+0x82EB,0x5BC5,0x9149,0x701E,0x5678,0x5C6F,0x60C7,0x6566,
+0x6C8C,0x8C5A,0x9041,0x9813,0x5451,0x66C7,0x920D,0x5948,
+0x90A3,0x5185,0x4E4D,0x51EA,0x8599,0x8B0E,0x7058,0x637A,
+0x934B,0x6962,0x99B4,0x7E04,0x7577,0x5357,0x6960,0x8EDF,
+0x96E3,0x6C5D,0x4E8C,0x5C3C,0x5F10,0x8FE9,0x5302,0x8CD1,
+0x8089,0x8679,0x5EFF,0x65E5,0x4E73,0x5165,
+/* plane 1 ku 39 */
+0x5982,0x5C3F,0x97EE,0x4EFB,0x598A,0x5FCD,0x8A8D,0x6FE1,
+0x79B0,0x7962,0x5BE7,0x8471,0x732B,0x71B1,0x5E74,0x5FF5,
+0x637B,0x649A,0x71C3,0x7C98,0x4E43,0x5EFC,0x4E4B,0x57DC,
+0x56A2,0x60A9,0x6FC3,0x7D0D,0x80FD,0x8133,0x81BF,0x8FB2,
+0x8997,0x86A4,0x5DF4,0x628A,0x64AD,0x8987,0x6777,0x6CE2,
+0x6D3E,0x7436,0x7834,0x5A46,0x7F75,0x82AD,0x99AC,0x4FF3,
+0x5EC3,0x62DD,0x6392,0x6557,0x676F,0x76C3,0x724C,0x80CC,
+0x80BA,0x8F29,0x914D,0x500D,0x57F9,0x5A92,0x6885,0x6973,
+0x7164,0x72FD,0x8CB7,0x58F2,0x8CE0,0x966A,0x9019,0x877F,
+0x79E4,0x77E7,0x8429,0x4F2F,0x5265,0x535A,0x62CD,0x67CF,
+0x6CCA,0x767D,0x7B94,0x7C95,0x8236,0x8584,0x8FEB,0x66DD,
+0x6F20,0x7206,0x7E1B,0x83AB,0x99C1,0x9EA6,
+/* plane 1 ku 40 */
+0x51FD,0x7BB1,0x7872,0x7BB8,0x8087,0x7B48,0x6AE8,0x5E61,
+0x808C,0x7551,0x7560,0x516B,0x9262,0x6E8C,0x767A,0x9197,
+0x9AEA,0x4F10,0x7F70,0x629C,0x7B4F,0x95A5,0x9CE9,0x567A,
+0x5859,0x86E4,0x96BC,0x4F34,0x5224,0x534A,0x53CD,0x53DB,
+0x5E06,0x642C,0x6591,0x677F,0x6C3E,0x6C4E,0x7248,0x72AF,
+0x73ED,0x7554,0x7E41,0x822C,0x85E9,0x8CA9,0x7BC4,0x91C6,
+0x7169,0x9812,0x98EF,0x633D,0x6669,0x756A,0x76E4,0x78D0,
+0x8543,0x86EE,0x532A,0x5351,0x5426,0x5983,0x5E87,0x5F7C,
+0x60B2,0x6249,0x6279,0x62AB,0x6590,0x6BD4,0x6CCC,0x75B2,
+0x76AE,0x7891,0x79D8,0x7DCB,0x7F77,0x80A5,0x88AB,0x8AB9,
+0x8CBB,0x907F,0x975E,0x98DB,0x6A0B,0x7C38,0x5099,0x5C3E,
+0x5FAE,0x6787,0x6BD8,0x7435,0x7709,0x7F8E,
+/* plane 1 ku 41 */
+0x9F3B,0x67CA,0x7A17,0x5339,0x758B,0x9AED,0x5F66,0x819D,
+0x83F1,0x8098,0x5F3C,0x5FC5,0x7562,0x7B46,0x903C,0x6867,
+0x59EB,0x5A9B,0x7D10,0x767E,0x8B2C,0x4FF5,0x5F6A,0x6A19,
+0x6C37,0x6F02,0x74E2,0x7968,0x8868,0x8A55,0x8C79,0x5EDF,
+0x63CF,0x75C5,0x79D2,0x82D7,0x9328,0x92F2,0x849C,0x86ED,
+0x9C2D,0x54C1,0x5F6C,0x658C,0x6D5C,0x7015,0x8CA7,0x8CD3,
+0x983B,0x654F,0x74F6,0x4E0D,0x4ED8,0x57E0,0x592B,0x5A66,
+0x5BCC,0x51A8,0x5E03,0x5E9C,0x6016,0x6276,0x6577,0x65A7,
+0x666E,0x6D6E,0x7236,0x7B26,0x8150,0x819A,0x8299,0x8B5C,
+0x8CA0,0x8CE6,0x8D74,0x961C,0x9644,0x4FAE,0x64AB,0x6B66,
+0x821E,0x8461,0x856A,0x90E8,0x5C01,0x6953,0x98A8,0x847A,
+0x8557,0x4F0F,0x526F,0x5FA9,0x5E45,0x670D,
+/* plane 1 ku 42 */
+0x798F,0x8179,0x8907,0x8986,0x6DF5,0x5F17,0x6255,0x6CB8,
+0x4ECF,0x7269,0x9B92,0x5206,0x543B,0x5674,0x58B3,0x61A4,
+0x626E,0x711A,0x596E,0x7C89,0x7CDE,0x7D1B,0x96F0,0x6587,
+0x805E,0x4E19,0x4F75,0x5175,0x5840,0x5E63,0x5E73,0x5F0A,
+0x67C4,0x4E26,0x853D,0x9589,0x965B,0x7C73,0x9801,0x50FB,
+0x58C1,0x7656,0x78A7,0x5225,0x77A5,0x8511,0x7B86,0x504F,
+0x5909,0x7247,0x7BC7,0x7DE8,0x8FBA,0x8FD4,0x904D,0x4FBF,
+0x52C9,0x5A29,0x5F01,0x97AD,0x4FDD,0x8217,0x92EA,0x5703,
+0x6355,0x6B69,0x752B,0x88DC,0x8F14,0x7A42,0x52DF,0x5893,
+0x6155,0x620A,0x66AE,0x6BCD,0x7C3F,0x83E9,0x5023,0x4FF8,
+0x5305,0x5446,0x5831,0x5949,0x5B9D,0x5CF0,0x5CEF,0x5D29,
+0x5E96,0x62B1,0x6367,0x653E,0x65B9,0x670B,
+/* plane 1 ku 43 */
+0x6CD5,0x6CE1,0x70F9,0x7832,0x7E2B,0x80DE,0x82B3,0x840C,
+0x84EC,0x8702,0x8912,0x8A2A,0x8C4A,0x90A6,0x92D2,0x98FD,
+0x9CF3,0x9D6C,0x4E4F,0x4EA1,0x508D,0x5256,0x574A,0x59A8,
+0x5E3D,0x5FD8,0x5FD9,0x623F,0x66B4,0x671B,0x67D0,0x68D2,
+0x5192,0x7D21,0x80AA,0x81A8,0x8B00,0x8C8C,0x8CBF,0x927E,
+0x9632,0x5420,0x982C,0x5317,0x50D5,0x535C,0x58A8,0x64B2,
+0x6734,0x7267,0x7766,0x7A46,0x91E6,0x52C3,0x6CA1,0x6B86,
+0x5800,0x5E4C,0x5954,0x672C,0x7FFB,0x51E1,0x76C6,0x6469,
+0x78E8,0x9B54,0x9EBB,0x57CB,0x59B9,0x6627,0x679A,0x6BCE,
+0x54E9,0x69D9,0x5E55,0x819C,0x6795,0x9BAA,0x67FE,0x9C52,
+0x685D,0x4EA6,0x4FE3,0x53C8,0x62B9,0x672B,0x6CAB,0x8FC4,
+0x4FAD,0x7E6D,0x9EBF,0x4E07,0x6162,0x6E80,
+/* plane 1 ku 44 */
+0x6F2B,0x8513,0x5473,0x672A,0x9B45,0x5DF3,0x7B95,0x5CAC,
+0x5BC6,0x871C,0x6E4A,0x84D1,0x7A14,0x8108,0x5999,0x7C8D,
+0x6C11,0x7720,0x52D9,0x5922,0x7121,0x725F,0x77DB,0x9727,
+0x9D61,0x690B,0x5A7F,0x5A18,0x51A5,0x540D,0x547D,0x660E,
+0x76DF,0x8FF7,0x9298,0x9CF4,0x59EA,0x725D,0x6EC5,0x514D,
+0x68C9,0x7DBF,0x7DEC,0x9762,0x9EBA,0x6478,0x6A21,0x8302,
+0x5984,0x5B5F,0x6BDB,0x731B,0x76F2,0x7DB2,0x8017,0x8499,
+0x5132,0x6728,0x9ED9,0x76EE,0x6762,0x52FF,0x9905,0x5C24,
+0x623B,0x7C7E,0x8CB0,0x554F,0x60B6,0x7D0B,0x9580,0x5301,
+0x4E5F,0x51B6,0x591C,0x723A,0x8036,0x91CE,0x5F25,0x77E2,
+0x5384,0x5F79,0x7D04,0x85AC,0x8A33,0x8E8D,0x9756,0x67F3,
+0x85AE,0x9453,0x6109,0x6108,0x6CB9,0x7652,
+/* plane 1 ku 45 */
+0x8AED,0x8F38,0x552F,0x4F51,0x512A,0x52C7,0x53CB,0x5BA5,
+0x5E7D,0x60A0,0x6182,0x63D6,0x6709,0x67DA,0x6E67,0x6D8C,
+0x7336,0x7337,0x7531,0x7950,0x88D5,0x8A98,0x904A,0x9091,
+0x90F5,0x96C4,0x878D,0x5915,0x4E88,0x4F59,0x4E0E,0x8A89,
+0x8F3F,0x9810,0x50AD,0x5E7C,0x5996,0x5BB9,0x5EB8,0x63DA,
+0x63FA,0x64C1,0x66DC,0x694A,0x69D8,0x6D0B,0x6EB6,0x7194,
+0x7528,0x7AAF,0x7F8A,0x8000,0x8449,0x84C9,0x8981,0x8B21,
+0x8E0A,0x9065,0x967D,0x990A,0x617E,0x6291,0x6B32,0x6C83,
+0x6D74,0x7FCC,0x7FFC,0x6DC0,0x7F85,0x87BA,0x88F8,0x6765,
+0x83B1,0x983C,0x96F7,0x6D1B,0x7D61,0x843D,0x916A,0x4E71,
+0x5375,0x5D50,0x6B04,0x6FEB,0x85CD,0x862D,0x89A7,0x5229,
+0x540F,0x5C65,0x674E,0x68A8,0x7406,0x7483,
+/* plane 1 ku 46 */
+0x75E2,0x88CF,0x88E1,0x91CC,0x96E2,0x9678,0x5F8B,0x7387,
+0x7ACB,0x844E,0x63A0,0x7565,0x5289,0x6D41,0x6E9C,0x7409,
+0x7559,0x786B,0x7C92,0x9686,0x7ADC,0x9F8D,0x4FB6,0x616E,
+0x65C5,0x865C,0x4E86,0x4EAE,0x50DA,0x4E21,0x51CC,0x5BEE,
+0x6599,0x6881,0x6DBC,0x731F,0x7642,0x77AD,0x7A1C,0x7CE7,
+0x826F,0x8AD2,0x907C,0x91CF,0x9675,0x9818,0x529B,0x7DD1,
+0x502B,0x5398,0x6797,0x6DCB,0x71D0,0x7433,0x81E8,0x8F2A,
+0x96A3,0x9C57,0x9E9F,0x7460,0x5841,0x6D99,0x7D2F,0x985E,
+0x4EE4,0x4F36,0x4F8B,0x51B7,0x52B1,0x5DBA,0x601C,0x73B2,
+0x793C,0x82D3,0x9234,0x96B7,0x96F6,0x970A,0x9E97,0x9F62,
+0x66A6,0x6B74,0x5217,0x52A3,0x70C8,0x88C2,0x5EC9,0x604B,
+0x6190,0x6F23,0x7149,0x7C3E,0x7DF4,0x806F,
+/* plane 1 ku 47 */
+0x84EE,0x9023,0x932C,0x5442,0x9B6F,0x6AD3,0x7089,0x8CC2,
+0x8DEF,0x9732,0x52B4,0x5A41,0x5ECA,0x5F04,0x6717,0x697C,
+0x6994,0x6D6A,0x6F0F,0x7262,0x72FC,0x7BED,0x8001,0x807E,
+0x874B,0x90CE,0x516D,0x9E93,0x7984,0x808B,0x9332,0x8AD6,
+0x502D,0x548C,0x8A71,0x6B6A,0x8CC4,0x8107,0x60D1,0x67A0,
+0x9DF2,0x4E99,0x4E98,0x9C10,0x8A6B,0x85C1,0x8568,0x6900,
+0x6E7E,0x7897,0x8155,0x0000,0x5B41,0x5B56,0x5B7D,0x5B93,
+0x5BD8,0x5BEC,0x5C12,0x5C1E,0x5C23,0x5C2B,0x378D,0x5C62,
+0xFA3B,0xFA3C,0x0000,0x5C7A,0x5C8F,0x5C9F,0x5CA3,0x5CAA,
+0x5CBA,0x5CCB,0x5CD0,0x5CD2,0x5CF4,0x0000,0x37E2,0x5D0D,
+0x5D27,0xFA11,0x5D46,0x5D47,0x5D53,0x5D4A,0x5D6D,0x5D81,
+0x5DA0,0x5DA4,0x5DA7,0x5DB8,0x5DCB,0x541E,
+/* plane 1 ku 48 */
+0x5F0C,0x4E10,0x4E15,0x4E2A,0x4E31,0x4E36,0x4E3C,0x4E3F,
+0x4E42,0x4E56,0x4E58,0x4E82,0x4E85,0x8C6B,0x4E8A,0x8212,
+0x5F0D,0x4E8E,0x4E9E,0x4E9F,0x4EA0,0x4EA2,0x4EB0,0x4EB3,
+0x4EB6,0x4ECE,0x4ECD,0x4EC4,0x4EC6,0x4EC2,0x4ED7,0x4EDE,
+0x4EED,0x4EDF,0x4EF7,0x4F09,0x4F5A,0x4F30,0x4F5B,0x4F5D,
+0x4F57,0x4F47,0x4F76,0x4F88,0x4F8F,0x4F98,0x4F7B,0x4F69,
+0x4F70,0x4F91,0x4F6F,0x4F86,0x4F96,0x5118,0x4FD4,0x4FDF,
+0x4FCE,0x4FD8,0x4FDB,0x4FD1,0x4FDA,0x4FD0,0x4FE4,0x4FE5,
+0x501A,0x5028,0x5014,0x502A,0x5025,0x5005,0x4F1C,0x4FF6,
+0x5021,0x5029,0x502C,0x4FFE,0x4FEF,0x5011,0x5006,0x5043,
+0x5047,0x6703,0x5055,0x5050,0x5048,0x505A,0x5056,0x506C,
+0x5078,0x5080,0x509A,0x5085,0x50B4,0x50B2,
+/* plane 1 ku 49 */
+0x50C9,0x50CA,0x50B3,0x50C2,0x50D6,0x50DE,0x50E5,0x50ED,
+0x50E3,0x50EE,0x50F9,0x50F5,0x5109,0x5101,0x5102,0x5116,
+0x5115,0x5114,0x511A,0x5121,0x513A,0x5137,0x513C,0x513B,
+0x513F,0x5140,0x5152,0x514C,0x5154,0x5162,0x7AF8,0x5169,
+0x516A,0x516E,0x5180,0x5182,0x56D8,0x518C,0x5189,0x518F,
+0x5191,0x5193,0x5195,0x5196,0x51A4,0x51A6,0x51A2,0x51A9,
+0x51AA,0x51AB,0x51B3,0x51B1,0x51B2,0x51B0,0x51B5,0x51BD,
+0x51C5,0x51C9,0x51DB,0x51E0,0x8655,0x51E9,0x51ED,0x51F0,
+0x51F5,0x51FE,0x5204,0x520B,0x5214,0x520E,0x5227,0x522A,
+0x522E,0x5233,0x5239,0x524F,0x5244,0x524B,0x524C,0x525E,
+0x5254,0x526A,0x5274,0x5269,0x5273,0x527F,0x527D,0x528D,
+0x5294,0x5292,0x5271,0x5288,0x5291,0x8FA8,
+/* plane 1 ku 50 */
+0x8FA7,0x52AC,0x52AD,0x52BC,0x52B5,0x52C1,0x52CD,0x52D7,
+0x52DE,0x52E3,0x52E6,0x98ED,0x52E0,0x52F3,0x52F5,0x52F8,
+0x52F9,0x5306,0x5308,0x7538,0x530D,0x5310,0x530F,0x5315,
+0x531A,0x5323,0x532F,0x5331,0x5333,0x5338,0x5340,0x5346,
+0x5345,0x4E17,0x5349,0x534D,0x51D6,0x535E,0x5369,0x536E,
+0x5918,0x537B,0x5377,0x5382,0x5396,0x53A0,0x53A6,0x53A5,
+0x53AE,0x53B0,0x53B6,0x53C3,0x7C12,0x96D9,0x53DF,0x66FC,
+0x71EE,0x53EE,0x53E8,0x53ED,0x53FA,0x5401,0x543D,0x5440,
+0x542C,0x542D,0x543C,0x542E,0x5436,0x5429,0x541D,0x544E,
+0x548F,0x5475,0x548E,0x545F,0x5471,0x5477,0x5470,0x5492,
+0x547B,0x5480,0x5476,0x5484,0x5490,0x5486,0x54C7,0x54A2,
+0x54B8,0x54A5,0x54AC,0x54C4,0x54C8,0x54A8,
+/* plane 1 ku 51 */
+0x54AB,0x54C2,0x54A4,0x54BE,0x54BC,0x54D8,0x54E5,0x54E6,
+0x550F,0x5514,0x54FD,0x54EE,0x54ED,0x54FA,0x54E2,0x5539,
+0x5540,0x5563,0x554C,0x552E,0x555C,0x5545,0x5556,0x5557,
+0x5538,0x5533,0x555D,0x5599,0x5580,0x54AF,0x558A,0x559F,
+0x557B,0x557E,0x5598,0x559E,0x55AE,0x557C,0x5583,0x55A9,
+0x5587,0x55A8,0x55DA,0x55C5,0x55DF,0x55C4,0x55DC,0x55E4,
+0x55D4,0x5614,0x55F7,0x5616,0x55FE,0x55FD,0x561B,0x55F9,
+0x564E,0x5650,0x71DF,0x5634,0x5636,0x5632,0x5638,0x566B,
+0x5664,0x562F,0x566C,0x566A,0x5686,0x5680,0x568A,0x56A0,
+0x5694,0x568F,0x56A5,0x56AE,0x56B6,0x56B4,0x56C2,0x56BC,
+0x56C1,0x56C3,0x56C0,0x56C8,0x56CE,0x56D1,0x56D3,0x56D7,
+0x56EE,0x56F9,0x5700,0x56FF,0x5704,0x5709,
+/* plane 1 ku 52 */
+0x5708,0x570B,0x570D,0x5713,0x5718,0x5716,0x55C7,0x571C,
+0x5726,0x5737,0x5738,0x574E,0x573B,0x5740,0x574F,0x5769,
+0x57C0,0x5788,0x5761,0x577F,0x5789,0x5793,0x57A0,0x57B3,
+0x57A4,0x57AA,0x57B0,0x57C3,0x57C6,0x57D4,0x57D2,0x57D3,
+0x580A,0x57D6,0x57E3,0x580B,0x5819,0x581D,0x5872,0x5821,
+0x5862,0x584B,0x5870,0x6BC0,0x5852,0x583D,0x5879,0x5885,
+0x58B9,0x589F,0x58AB,0x58BA,0x58DE,0x58BB,0x58B8,0x58AE,
+0x58C5,0x58D3,0x58D1,0x58D7,0x58D9,0x58D8,0x58E5,0x58DC,
+0x58E4,0x58DF,0x58EF,0x58FA,0x58F9,0x58FB,0x58FC,0x58FD,
+0x5902,0x590A,0x5910,0x591B,0x68A6,0x5925,0x592C,0x592D,
+0x5932,0x5938,0x593E,0x7AD2,0x5955,0x5950,0x594E,0x595A,
+0x5958,0x5962,0x5960,0x5967,0x596C,0x5969,
+/* plane 1 ku 53 */
+0x5978,0x5981,0x599D,0x4F5E,0x4FAB,0x59A3,0x59B2,0x59C6,
+0x59E8,0x59DC,0x598D,0x59D9,0x59DA,0x5A25,0x5A1F,0x5A11,
+0x5A1C,0x5A09,0x5A1A,0x5A40,0x5A6C,0x5A49,0x5A35,0x5A36,
+0x5A62,0x5A6A,0x5A9A,0x5ABC,0x5ABE,0x5ACB,0x5AC2,0x5ABD,
+0x5AE3,0x5AD7,0x5AE6,0x5AE9,0x5AD6,0x5AFA,0x5AFB,0x5B0C,
+0x5B0B,0x5B16,0x5B32,0x5AD0,0x5B2A,0x5B36,0x5B3E,0x5B43,
+0x5B45,0x5B40,0x5B51,0x5B55,0x5B5A,0x5B5B,0x5B65,0x5B69,
+0x5B70,0x5B73,0x5B75,0x5B78,0x6588,0x5B7A,0x5B80,0x5B83,
+0x5BA6,0x5BB8,0x5BC3,0x5BC7,0x5BC9,0x5BD4,0x5BD0,0x5BE4,
+0x5BE6,0x5BE2,0x5BDE,0x5BE5,0x5BEB,0x5BF0,0x5BF6,0x5BF3,
+0x5C05,0x5C07,0x5C08,0x5C0D,0x5C13,0x5C20,0x5C22,0x5C28,
+0x5C38,0x5C39,0x5C41,0x5C46,0x5C4E,0x5C53,
+/* plane 1 ku 54 */
+0x5C50,0x5C4F,0x5B71,0x5C6C,0x5C6E,0x4E62,0x5C76,0x5C79,
+0x5C8C,0x5C91,0x5C94,0x599B,0x5CAB,0x5CBB,0x5CB6,0x5CBC,
+0x5CB7,0x5CC5,0x5CBE,0x5CC7,0x5CD9,0x5CE9,0x5CFD,0x5CFA,
+0x5CED,0x5D8C,0x5CEA,0x5D0B,0x5D15,0x5D17,0x5D5C,0x5D1F,
+0x5D1B,0x5D11,0x5D14,0x5D22,0x5D1A,0x5D19,0x5D18,0x5D4C,
+0x5D52,0x5D4E,0x5D4B,0x5D6C,0x5D73,0x5D76,0x5D87,0x5D84,
+0x5D82,0x5DA2,0x5D9D,0x5DAC,0x5DAE,0x5DBD,0x5D90,0x5DB7,
+0x5DBC,0x5DC9,0x5DCD,0x5DD3,0x5DD2,0x5DD6,0x5DDB,0x5DEB,
+0x5DF2,0x5DF5,0x5E0B,0x5E1A,0x5E19,0x5E11,0x5E1B,0x5E36,
+0x5E37,0x5E44,0x5E43,0x5E40,0x5E4E,0x5E57,0x5E54,0x5E5F,
+0x5E62,0x5E64,0x5E47,0x5E75,0x5E76,0x5E7A,0x9EBC,0x5E7F,
+0x5EA0,0x5EC1,0x5EC2,0x5EC8,0x5ED0,0x5ECF,
+/* plane 1 ku 55 */
+0x5ED6,0x5EE3,0x5EDD,0x5EDA,0x5EDB,0x5EE2,0x5EE1,0x5EE8,
+0x5EE9,0x5EEC,0x5EF1,0x5EF3,0x5EF0,0x5EF4,0x5EF8,0x5EFE,
+0x5F03,0x5F09,0x5F5D,0x5F5C,0x5F0B,0x5F11,0x5F16,0x5F29,
+0x5F2D,0x5F38,0x5F41,0x5F48,0x5F4C,0x5F4E,0x5F2F,0x5F51,
+0x5F56,0x5F57,0x5F59,0x5F61,0x5F6D,0x5F73,0x5F77,0x5F83,
+0x5F82,0x5F7F,0x5F8A,0x5F88,0x5F91,0x5F87,0x5F9E,0x5F99,
+0x5F98,0x5FA0,0x5FA8,0x5FAD,0x5FBC,0x5FD6,0x5FFB,0x5FE4,
+0x5FF8,0x5FF1,0x5FDD,0x60B3,0x5FFF,0x6021,0x6060,0x6019,
+0x6010,0x6029,0x600E,0x6031,0x601B,0x6015,0x602B,0x6026,
+0x600F,0x603A,0x605A,0x6041,0x606A,0x6077,0x605F,0x604A,
+0x6046,0x604D,0x6063,0x6043,0x6064,0x6042,0x606C,0x606B,
+0x6059,0x6081,0x608D,0x60E7,0x6083,0x609A,
+/* plane 1 ku 56 */
+0x6084,0x609B,0x6096,0x6097,0x6092,0x60A7,0x608B,0x60E1,
+0x60B8,0x60E0,0x60D3,0x60B4,0x5FF0,0x60BD,0x60C6,0x60B5,
+0x60D8,0x614D,0x6115,0x6106,0x60F6,0x60F7,0x6100,0x60F4,
+0x60FA,0x6103,0x6121,0x60FB,0x60F1,0x610D,0x610E,0x6147,
+0x613E,0x6128,0x6127,0x614A,0x613F,0x613C,0x612C,0x6134,
+0x613D,0x6142,0x6144,0x6173,0x6177,0x6158,0x6159,0x615A,
+0x616B,0x6174,0x616F,0x6165,0x6171,0x615F,0x615D,0x6153,
+0x6175,0x6199,0x6196,0x6187,0x61AC,0x6194,0x619A,0x618A,
+0x6191,0x61AB,0x61AE,0x61CC,0x61CA,0x61C9,0x61F7,0x61C8,
+0x61C3,0x61C6,0x61BA,0x61CB,0x7F79,0x61CD,0x61E6,0x61E3,
+0x61F6,0x61FA,0x61F4,0x61FF,0x61FD,0x61FC,0x61FE,0x6200,
+0x6208,0x6209,0x620D,0x620C,0x6214,0x621B,
+/* plane 1 ku 57 */
+0x621E,0x6221,0x622A,0x622E,0x6230,0x6232,0x6233,0x6241,
+0x624E,0x625E,0x6263,0x625B,0x6260,0x6268,0x627C,0x6282,
+0x6289,0x627E,0x6292,0x6293,0x6296,0x62D4,0x6283,0x6294,
+0x62D7,0x62D1,0x62BB,0x62CF,0x62FF,0x62C6,0x64D4,0x62C8,
+0x62DC,0x62CC,0x62CA,0x62C2,0x62C7,0x629B,0x62C9,0x630C,
+0x62EE,0x62F1,0x6327,0x6302,0x6308,0x62EF,0x62F5,0x6350,
+0x633E,0x634D,0x641C,0x634F,0x6396,0x638E,0x6380,0x63AB,
+0x6376,0x63A3,0x638F,0x6389,0x639F,0x63B5,0x636B,0x6369,
+0x63BE,0x63E9,0x63C0,0x63C6,0x63E3,0x63C9,0x63D2,0x63F6,
+0x63C4,0x6416,0x6434,0x6406,0x6413,0x6426,0x6436,0x651D,
+0x6417,0x6428,0x640F,0x6467,0x646F,0x6476,0x644E,0x652A,
+0x6495,0x6493,0x64A5,0x64A9,0x6488,0x64BC,
+/* plane 1 ku 58 */
+0x64DA,0x64D2,0x64C5,0x64C7,0x64BB,0x64D8,0x64C2,0x64F1,
+0x64E7,0x8209,0x64E0,0x64E1,0x62AC,0x64E3,0x64EF,0x652C,
+0x64F6,0x64F4,0x64F2,0x64FA,0x6500,0x64FD,0x6518,0x651C,
+0x6505,0x6524,0x6523,0x652B,0x6534,0x6535,0x6537,0x6536,
+0x6538,0x754B,0x6548,0x6556,0x6555,0x654D,0x6558,0x655E,
+0x655D,0x6572,0x6578,0x6582,0x6583,0x8B8A,0x659B,0x659F,
+0x65AB,0x65B7,0x65C3,0x65C6,0x65C1,0x65C4,0x65CC,0x65D2,
+0x65DB,0x65D9,0x65E0,0x65E1,0x65F1,0x6772,0x660A,0x6603,
+0x65FB,0x6773,0x6635,0x6636,0x6634,0x661C,0x664F,0x6644,
+0x6649,0x6641,0x665E,0x665D,0x6664,0x6667,0x6668,0x665F,
+0x6662,0x6670,0x6683,0x6688,0x668E,0x6689,0x6684,0x6698,
+0x669D,0x66C1,0x66B9,0x66C9,0x66BE,0x66BC,
+/* plane 1 ku 59 */
+0x66C4,0x66B8,0x66D6,0x66DA,0x66E0,0x663F,0x66E6,0x66E9,
+0x66F0,0x66F5,0x66F7,0x670F,0x6716,0x671E,0x6726,0x6727,
+0x9738,0x672E,0x673F,0x6736,0x6741,0x6738,0x6737,0x6746,
+0x675E,0x6760,0x6759,0x6763,0x6764,0x6789,0x6770,0x67A9,
+0x677C,0x676A,0x678C,0x678B,0x67A6,0x67A1,0x6785,0x67B7,
+0x67EF,0x67B4,0x67EC,0x67B3,0x67E9,0x67B8,0x67E4,0x67DE,
+0x67DD,0x67E2,0x67EE,0x67B9,0x67CE,0x67C6,0x67E7,0x6A9C,
+0x681E,0x6846,0x6829,0x6840,0x684D,0x6832,0x684E,0x68B3,
+0x682B,0x6859,0x6863,0x6877,0x687F,0x689F,0x688F,0x68AD,
+0x6894,0x689D,0x689B,0x6883,0x6AAE,0x68B9,0x6874,0x68B5,
+0x68A0,0x68BA,0x690F,0x688D,0x687E,0x6901,0x68CA,0x6908,
+0x68D8,0x6922,0x6926,0x68E1,0x690C,0x68CD,
+/* plane 1 ku 60 */
+0x68D4,0x68E7,0x68D5,0x6936,0x6912,0x6904,0x68D7,0x68E3,
+0x6925,0x68F9,0x68E0,0x68EF,0x6928,0x692A,0x691A,0x6923,
+0x6921,0x68C6,0x6979,0x6977,0x695C,0x6978,0x696B,0x6954,
+0x697E,0x696E,0x6939,0x6974,0x693D,0x6959,0x6930,0x6961,
+0x695E,0x695D,0x6981,0x696A,0x69B2,0x69AE,0x69D0,0x69BF,
+0x69C1,0x69D3,0x69BE,0x69CE,0x5BE8,0x69CA,0x69DD,0x69BB,
+0x69C3,0x69A7,0x6A2E,0x6991,0x69A0,0x699C,0x6995,0x69B4,
+0x69DE,0x69E8,0x6A02,0x6A1B,0x69FF,0x6B0A,0x69F9,0x69F2,
+0x69E7,0x6A05,0x69B1,0x6A1E,0x69ED,0x6A14,0x69EB,0x6A0A,
+0x6A12,0x6AC1,0x6A23,0x6A13,0x6A44,0x6A0C,0x6A72,0x6A36,
+0x6A78,0x6A47,0x6A62,0x6A59,0x6A66,0x6A48,0x6A38,0x6A22,
+0x6A90,0x6A8D,0x6AA0,0x6A84,0x6AA2,0x6AA3,
+/* plane 1 ku 61 */
+0x6A97,0x8617,0x6ABB,0x6AC3,0x6AC2,0x6AB8,0x6AB3,0x6AAC,
+0x6ADE,0x6AD1,0x6ADF,0x6AAA,0x6ADA,0x6AEA,0x6AFB,0x6B05,
+0x8616,0x6AFA,0x6B12,0x6B16,0x9B31,0x6B1F,0x6B38,0x6B37,
+0x76DC,0x6B39,0x98EE,0x6B47,0x6B43,0x6B49,0x6B50,0x6B59,
+0x6B54,0x6B5B,0x6B5F,0x6B61,0x6B78,0x6B79,0x6B7F,0x6B80,
+0x6B84,0x6B83,0x6B8D,0x6B98,0x6B95,0x6B9E,0x6BA4,0x6BAA,
+0x6BAB,0x6BAF,0x6BB2,0x6BB1,0x6BB3,0x6BB7,0x6BBC,0x6BC6,
+0x6BCB,0x6BD3,0x6BDF,0x6BEC,0x6BEB,0x6BF3,0x6BEF,0x9EBE,
+0x6C08,0x6C13,0x6C14,0x6C1B,0x6C24,0x6C23,0x6C5E,0x6C55,
+0x6C62,0x6C6A,0x6C82,0x6C8D,0x6C9A,0x6C81,0x6C9B,0x6C7E,
+0x6C68,0x6C73,0x6C92,0x6C90,0x6CC4,0x6CF1,0x6CD3,0x6CBD,
+0x6CD7,0x6CC5,0x6CDD,0x6CAE,0x6CB1,0x6CBE,
+/* plane 1 ku 62 */
+0x6CBA,0x6CDB,0x6CEF,0x6CD9,0x6CEA,0x6D1F,0x884D,0x6D36,
+0x6D2B,0x6D3D,0x6D38,0x6D19,0x6D35,0x6D33,0x6D12,0x6D0C,
+0x6D63,0x6D93,0x6D64,0x6D5A,0x6D79,0x6D59,0x6D8E,0x6D95,
+0x6FE4,0x6D85,0x6DF9,0x6E15,0x6E0A,0x6DB5,0x6DC7,0x6DE6,
+0x6DB8,0x6DC6,0x6DEC,0x6DDE,0x6DCC,0x6DE8,0x6DD2,0x6DC5,
+0x6DFA,0x6DD9,0x6DE4,0x6DD5,0x6DEA,0x6DEE,0x6E2D,0x6E6E,
+0x6E2E,0x6E19,0x6E72,0x6E5F,0x6E3E,0x6E23,0x6E6B,0x6E2B,
+0x6E76,0x6E4D,0x6E1F,0x6E43,0x6E3A,0x6E4E,0x6E24,0x6EFF,
+0x6E1D,0x6E38,0x6E82,0x6EAA,0x6E98,0x6EC9,0x6EB7,0x6ED3,
+0x6EBD,0x6EAF,0x6EC4,0x6EB2,0x6ED4,0x6ED5,0x6E8F,0x6EA5,
+0x6EC2,0x6E9F,0x6F41,0x6F11,0x704C,0x6EEC,0x6EF8,0x6EFE,
+0x6F3F,0x6EF2,0x6F31,0x6EEF,0x6F32,0x6ECC,
+/* plane 1 ku 63 */
+0x6F3E,0x6F13,0x6EF7,0x6F86,0x6F7A,0x6F78,0x6F81,0x6F80,
+0x6F6F,0x6F5B,0x6FF3,0x6F6D,0x6F82,0x6F7C,0x6F58,0x6F8E,
+0x6F91,0x6FC2,0x6F66,0x6FB3,0x6FA3,0x6FA1,0x6FA4,0x6FB9,
+0x6FC6,0x6FAA,0x6FDF,0x6FD5,0x6FEC,0x6FD4,0x6FD8,0x6FF1,
+0x6FEE,0x6FDB,0x7009,0x700B,0x6FFA,0x7011,0x7001,0x700F,
+0x6FFE,0x701B,0x701A,0x6F74,0x701D,0x7018,0x701F,0x7030,
+0x703E,0x7032,0x7051,0x7063,0x7099,0x7092,0x70AF,0x70F1,
+0x70AC,0x70B8,0x70B3,0x70AE,0x70DF,0x70CB,0x70DD,0x70D9,
+0x7109,0x70FD,0x711C,0x7119,0x7165,0x7155,0x7188,0x7166,
+0x7162,0x714C,0x7156,0x716C,0x718F,0x71FB,0x7184,0x7195,
+0x71A8,0x71AC,0x71D7,0x71B9,0x71BE,0x71D2,0x71C9,0x71D4,
+0x71CE,0x71E0,0x71EC,0x71E7,0x71F5,0x71FC,
+/* plane 1 ku 64 */
+0x71F9,0x71FF,0x720D,0x7210,0x721B,0x7228,0x722D,0x722C,
+0x7230,0x7232,0x723B,0x723C,0x723F,0x7240,0x7246,0x724B,
+0x7258,0x7274,0x727E,0x7282,0x7281,0x7287,0x7292,0x7296,
+0x72A2,0x72A7,0x72B9,0x72B2,0x72C3,0x72C6,0x72C4,0x72CE,
+0x72D2,0x72E2,0x72E0,0x72E1,0x72F9,0x72F7,0x500F,0x7317,
+0x730A,0x731C,0x7316,0x731D,0x7334,0x732F,0x7329,0x7325,
+0x733E,0x734E,0x734F,0x9ED8,0x7357,0x736A,0x7368,0x7370,
+0x7378,0x7375,0x737B,0x737A,0x73C8,0x73B3,0x73CE,0x73BB,
+0x73C0,0x73E5,0x73EE,0x73DE,0x74A2,0x7405,0x746F,0x7425,
+0x73F8,0x7432,0x743A,0x7455,0x743F,0x745F,0x7459,0x7441,
+0x745C,0x7469,0x7470,0x7463,0x746A,0x7476,0x747E,0x748B,
+0x749E,0x74A7,0x74CA,0x74CF,0x74D4,0x73F1,
+/* plane 1 ku 65 */
+0x74E0,0x74E3,0x74E7,0x74E9,0x74EE,0x74F2,0x74F0,0x74F1,
+0x74F8,0x74F7,0x7504,0x7503,0x7505,0x750C,0x750E,0x750D,
+0x7515,0x7513,0x751E,0x7526,0x752C,0x753C,0x7544,0x754D,
+0x754A,0x7549,0x755B,0x7546,0x755A,0x7569,0x7564,0x7567,
+0x756B,0x756D,0x7578,0x7576,0x7586,0x7587,0x7574,0x758A,
+0x7589,0x7582,0x7594,0x759A,0x759D,0x75A5,0x75A3,0x75C2,
+0x75B3,0x75C3,0x75B5,0x75BD,0x75B8,0x75BC,0x75B1,0x75CD,
+0x75CA,0x75D2,0x75D9,0x75E3,0x75DE,0x75FE,0x75FF,0x75FC,
+0x7601,0x75F0,0x75FA,0x75F2,0x75F3,0x760B,0x760D,0x7609,
+0x761F,0x7627,0x7620,0x7621,0x7622,0x7624,0x7634,0x7630,
+0x763B,0x7647,0x7648,0x7646,0x765C,0x7658,0x7661,0x7662,
+0x7668,0x7669,0x766A,0x7667,0x766C,0x7670,
+/* plane 1 ku 66 */
+0x7672,0x7676,0x7678,0x767C,0x7680,0x7683,0x7688,0x768B,
+0x768E,0x7696,0x7693,0x7699,0x769A,0x76B0,0x76B4,0x76B8,
+0x76B9,0x76BA,0x76C2,0x76CD,0x76D6,0x76D2,0x76DE,0x76E1,
+0x76E5,0x76E7,0x76EA,0x862F,0x76FB,0x7708,0x7707,0x7704,
+0x7729,0x7724,0x771E,0x7725,0x7726,0x771B,0x7737,0x7738,
+0x7747,0x775A,0x7768,0x776B,0x775B,0x7765,0x777F,0x777E,
+0x7779,0x778E,0x778B,0x7791,0x77A0,0x779E,0x77B0,0x77B6,
+0x77B9,0x77BF,0x77BC,0x77BD,0x77BB,0x77C7,0x77CD,0x77D7,
+0x77DA,0x77DC,0x77E3,0x77EE,0x77FC,0x780C,0x7812,0x7926,
+0x7820,0x792A,0x7845,0x788E,0x7874,0x7886,0x787C,0x789A,
+0x788C,0x78A3,0x78B5,0x78AA,0x78AF,0x78D1,0x78C6,0x78CB,
+0x78D4,0x78BE,0x78BC,0x78C5,0x78CA,0x78EC,
+/* plane 1 ku 67 */
+0x78E7,0x78DA,0x78FD,0x78F4,0x7907,0x7912,0x7911,0x7919,
+0x792C,0x792B,0x7940,0x7960,0x7957,0x795F,0x795A,0x7955,
+0x7953,0x797A,0x797F,0x798A,0x799D,0x79A7,0x9F4B,0x79AA,
+0x79AE,0x79B3,0x79B9,0x79BA,0x79C9,0x79D5,0x79E7,0x79EC,
+0x79E1,0x79E3,0x7A08,0x7A0D,0x7A18,0x7A19,0x7A20,0x7A1F,
+0x7980,0x7A31,0x7A3B,0x7A3E,0x7A37,0x7A43,0x7A57,0x7A49,
+0x7A61,0x7A62,0x7A69,0x9F9D,0x7A70,0x7A79,0x7A7D,0x7A88,
+0x7A97,0x7A95,0x7A98,0x7A96,0x7AA9,0x7AC8,0x7AB0,0x7AB6,
+0x7AC5,0x7AC4,0x7ABF,0x9083,0x7AC7,0x7ACA,0x7ACD,0x7ACF,
+0x7AD5,0x7AD3,0x7AD9,0x7ADA,0x7ADD,0x7AE1,0x7AE2,0x7AE6,
+0x7AED,0x7AF0,0x7B02,0x7B0F,0x7B0A,0x7B06,0x7B33,0x7B18,
+0x7B19,0x7B1E,0x7B35,0x7B28,0x7B36,0x7B50,
+/* plane 1 ku 68 */
+0x7B7A,0x7B04,0x7B4D,0x7B0B,0x7B4C,0x7B45,0x7B75,0x7B65,
+0x7B74,0x7B67,0x7B70,0x7B71,0x7B6C,0x7B6E,0x7B9D,0x7B98,
+0x7B9F,0x7B8D,0x7B9C,0x7B9A,0x7B8B,0x7B92,0x7B8F,0x7B5D,
+0x7B99,0x7BCB,0x7BC1,0x7BCC,0x7BCF,0x7BB4,0x7BC6,0x7BDD,
+0x7BE9,0x7C11,0x7C14,0x7BE6,0x7BE5,0x7C60,0x7C00,0x7C07,
+0x7C13,0x7BF3,0x7BF7,0x7C17,0x7C0D,0x7BF6,0x7C23,0x7C27,
+0x7C2A,0x7C1F,0x7C37,0x7C2B,0x7C3D,0x7C4C,0x7C43,0x7C54,
+0x7C4F,0x7C40,0x7C50,0x7C58,0x7C5F,0x7C64,0x7C56,0x7C65,
+0x7C6C,0x7C75,0x7C83,0x7C90,0x7CA4,0x7CAD,0x7CA2,0x7CAB,
+0x7CA1,0x7CA8,0x7CB3,0x7CB2,0x7CB1,0x7CAE,0x7CB9,0x7CBD,
+0x7CC0,0x7CC5,0x7CC2,0x7CD8,0x7CD2,0x7CDC,0x7CE2,0x9B3B,
+0x7CEF,0x7CF2,0x7CF4,0x7CF6,0x7CFA,0x7D06,
+/* plane 1 ku 69 */
+0x7D02,0x7D1C,0x7D15,0x7D0A,0x7D45,0x7D4B,0x7D2E,0x7D32,
+0x7D3F,0x7D35,0x7D46,0x7D73,0x7D56,0x7D4E,0x7D72,0x7D68,
+0x7D6E,0x7D4F,0x7D63,0x7D93,0x7D89,0x7D5B,0x7D8F,0x7D7D,
+0x7D9B,0x7DBA,0x7DAE,0x7DA3,0x7DB5,0x7DC7,0x7DBD,0x7DAB,
+0x7E3D,0x7DA2,0x7DAF,0x7DDC,0x7DB8,0x7D9F,0x7DB0,0x7DD8,
+0x7DDD,0x7DE4,0x7DDE,0x7DFB,0x7DF2,0x7DE1,0x7E05,0x7E0A,
+0x7E23,0x7E21,0x7E12,0x7E31,0x7E1F,0x7E09,0x7E0B,0x7E22,
+0x7E46,0x7E66,0x7E3B,0x7E35,0x7E39,0x7E43,0x7E37,0x7E32,
+0x7E3A,0x7E67,0x7E5D,0x7E56,0x7E5E,0x7E59,0x7E5A,0x7E79,
+0x7E6A,0x7E69,0x7E7C,0x7E7B,0x7E83,0x7DD5,0x7E7D,0x8FAE,
+0x7E7F,0x7E88,0x7E89,0x7E8C,0x7E92,0x7E90,0x7E93,0x7E94,
+0x7E96,0x7E8E,0x7E9B,0x7E9C,0x7F38,0x7F3A,
+/* plane 1 ku 70 */
+0x7F45,0x7F4C,0x7F4D,0x7F4E,0x7F50,0x7F51,0x7F55,0x7F54,
+0x7F58,0x7F5F,0x7F60,0x7F68,0x7F69,0x7F67,0x7F78,0x7F82,
+0x7F86,0x7F83,0x7F88,0x7F87,0x7F8C,0x7F94,0x7F9E,0x7F9D,
+0x7F9A,0x7FA3,0x7FAF,0x7FB2,0x7FB9,0x7FAE,0x7FB6,0x7FB8,
+0x8B71,0x7FC5,0x7FC6,0x7FCA,0x7FD5,0x7FD4,0x7FE1,0x7FE6,
+0x7FE9,0x7FF3,0x7FF9,0x98DC,0x8006,0x8004,0x800B,0x8012,
+0x8018,0x8019,0x801C,0x8021,0x8028,0x803F,0x803B,0x804A,
+0x8046,0x8052,0x8058,0x805A,0x805F,0x8062,0x8068,0x8073,
+0x8072,0x8070,0x8076,0x8079,0x807D,0x807F,0x8084,0x8086,
+0x8085,0x809B,0x8093,0x809A,0x80AD,0x5190,0x80AC,0x80DB,
+0x80E5,0x80D9,0x80DD,0x80C4,0x80DA,0x80D6,0x8109,0x80EF,
+0x80F1,0x811B,0x8129,0x8123,0x812F,0x814B,
+/* plane 1 ku 71 */
+0x968B,0x8146,0x813E,0x8153,0x8151,0x80FC,0x8171,0x816E,
+0x8165,0x8166,0x8174,0x8183,0x8188,0x818A,0x8180,0x8182,
+0x81A0,0x8195,0x81A4,0x81A3,0x815F,0x8193,0x81A9,0x81B0,
+0x81B5,0x81BE,0x81B8,0x81BD,0x81C0,0x81C2,0x81BA,0x81C9,
+0x81CD,0x81D1,0x81D9,0x81D8,0x81C8,0x81DA,0x81DF,0x81E0,
+0x81E7,0x81FA,0x81FB,0x81FE,0x8201,0x8202,0x8205,0x8207,
+0x820A,0x820D,0x8210,0x8216,0x8229,0x822B,0x8238,0x8233,
+0x8240,0x8259,0x8258,0x825D,0x825A,0x825F,0x8264,0x8262,
+0x8268,0x826A,0x826B,0x822E,0x8271,0x8277,0x8278,0x827E,
+0x828D,0x8292,0x82AB,0x829F,0x82BB,0x82AC,0x82E1,0x82E3,
+0x82DF,0x82D2,0x82F4,0x82F3,0x82FA,0x8393,0x8303,0x82FB,
+0x82F9,0x82DE,0x8306,0x82DC,0x8309,0x82D9,
+/* plane 1 ku 72 */
+0x8335,0x8334,0x8316,0x8332,0x8331,0x8340,0x8339,0x8350,
+0x8345,0x832F,0x832B,0x8317,0x8318,0x8385,0x839A,0x83AA,
+0x839F,0x83A2,0x8396,0x8323,0x838E,0x8387,0x838A,0x837C,
+0x83B5,0x8373,0x8375,0x83A0,0x8389,0x83A8,0x83F4,0x8413,
+0x83EB,0x83CE,0x83FD,0x8403,0x83D8,0x840B,0x83C1,0x83F7,
+0x8407,0x83E0,0x83F2,0x840D,0x8422,0x8420,0x83BD,0x8438,
+0x8506,0x83FB,0x846D,0x842A,0x843C,0x855A,0x8484,0x8477,
+0x846B,0x84AD,0x846E,0x8482,0x8469,0x8446,0x842C,0x846F,
+0x8479,0x8435,0x84CA,0x8462,0x84B9,0x84BF,0x849F,0x84D9,
+0x84CD,0x84BB,0x84DA,0x84D0,0x84C1,0x84C6,0x84D6,0x84A1,
+0x8521,0x84FF,0x84F4,0x8517,0x8518,0x852C,0x851F,0x8515,
+0x8514,0x84FC,0x8540,0x8563,0x8558,0x8548,
+/* plane 1 ku 73 */
+0x8541,0x8602,0x854B,0x8555,0x8580,0x85A4,0x8588,0x8591,
+0x858A,0x85A8,0x856D,0x8594,0x859B,0x85EA,0x8587,0x859C,
+0x8577,0x857E,0x8590,0x85C9,0x85BA,0x85CF,0x85B9,0x85D0,
+0x85D5,0x85DD,0x85E5,0x85DC,0x85F9,0x860A,0x8613,0x860B,
+0x85FE,0x85FA,0x8606,0x8622,0x861A,0x8630,0x863F,0x864D,
+0x4E55,0x8654,0x865F,0x8667,0x8671,0x8693,0x86A3,0x86A9,
+0x86AA,0x868B,0x868C,0x86B6,0x86AF,0x86C4,0x86C6,0x86B0,
+0x86C9,0x8823,0x86AB,0x86D4,0x86DE,0x86E9,0x86EC,0x86DF,
+0x86DB,0x86EF,0x8712,0x8706,0x8708,0x8700,0x8703,0x86FB,
+0x8711,0x8709,0x870D,0x86F9,0x870A,0x8734,0x873F,0x8737,
+0x873B,0x8725,0x8729,0x871A,0x8760,0x875F,0x8778,0x874C,
+0x874E,0x8774,0x8757,0x8768,0x876E,0x8759,
+/* plane 1 ku 74 */
+0x8753,0x8763,0x876A,0x8805,0x87A2,0x879F,0x8782,0x87AF,
+0x87CB,0x87BD,0x87C0,0x87D0,0x96D6,0x87AB,0x87C4,0x87B3,
+0x87C7,0x87C6,0x87BB,0x87EF,0x87F2,0x87E0,0x880F,0x880D,
+0x87FE,0x87F6,0x87F7,0x880E,0x87D2,0x8811,0x8816,0x8815,
+0x8822,0x8821,0x8831,0x8836,0x8839,0x8827,0x883B,0x8844,
+0x8842,0x8852,0x8859,0x885E,0x8862,0x886B,0x8881,0x887E,
+0x889E,0x8875,0x887D,0x88B5,0x8872,0x8882,0x8897,0x8892,
+0x88AE,0x8899,0x88A2,0x888D,0x88A4,0x88B0,0x88BF,0x88B1,
+0x88C3,0x88C4,0x88D4,0x88D8,0x88D9,0x88DD,0x88F9,0x8902,
+0x88FC,0x88F4,0x88E8,0x88F2,0x8904,0x890C,0x890A,0x8913,
+0x8943,0x891E,0x8925,0x892A,0x892B,0x8941,0x8944,0x893B,
+0x8936,0x8938,0x894C,0x891D,0x8960,0x895E,
+/* plane 1 ku 75 */
+0x8966,0x8964,0x896D,0x896A,0x896F,0x8974,0x8977,0x897E,
+0x8983,0x8988,0x898A,0x8993,0x8998,0x89A1,0x89A9,0x89A6,
+0x89AC,0x89AF,0x89B2,0x89BA,0x89BD,0x89BF,0x89C0,0x89DA,
+0x89DC,0x89DD,0x89E7,0x89F4,0x89F8,0x8A03,0x8A16,0x8A10,
+0x8A0C,0x8A1B,0x8A1D,0x8A25,0x8A36,0x8A41,0x8A5B,0x8A52,
+0x8A46,0x8A48,0x8A7C,0x8A6D,0x8A6C,0x8A62,0x8A85,0x8A82,
+0x8A84,0x8AA8,0x8AA1,0x8A91,0x8AA5,0x8AA6,0x8A9A,0x8AA3,
+0x8AC4,0x8ACD,0x8AC2,0x8ADA,0x8AEB,0x8AF3,0x8AE7,0x8AE4,
+0x8AF1,0x8B14,0x8AE0,0x8AE2,0x8AF7,0x8ADE,0x8ADB,0x8B0C,
+0x8B07,0x8B1A,0x8AE1,0x8B16,0x8B10,0x8B17,0x8B20,0x8B33,
+0x97AB,0x8B26,0x8B2B,0x8B3E,0x8B28,0x8B41,0x8B4C,0x8B4F,
+0x8B4E,0x8B49,0x8B56,0x8B5B,0x8B5A,0x8B6B,
+/* plane 1 ku 76 */
+0x8B5F,0x8B6C,0x8B6F,0x8B74,0x8B7D,0x8B80,0x8B8C,0x8B8E,
+0x8B92,0x8B93,0x8B96,0x8B99,0x8B9A,0x8C3A,0x8C41,0x8C3F,
+0x8C48,0x8C4C,0x8C4E,0x8C50,0x8C55,0x8C62,0x8C6C,0x8C78,
+0x8C7A,0x8C82,0x8C89,0x8C85,0x8C8A,0x8C8D,0x8C8E,0x8C94,
+0x8C7C,0x8C98,0x621D,0x8CAD,0x8CAA,0x8CBD,0x8CB2,0x8CB3,
+0x8CAE,0x8CB6,0x8CC8,0x8CC1,0x8CE4,0x8CE3,0x8CDA,0x8CFD,
+0x8CFA,0x8CFB,0x8D04,0x8D05,0x8D0A,0x8D07,0x8D0F,0x8D0D,
+0x8D10,0x9F4E,0x8D13,0x8CCD,0x8D14,0x8D16,0x8D67,0x8D6D,
+0x8D71,0x8D73,0x8D81,0x8D99,0x8DC2,0x8DBE,0x8DBA,0x8DCF,
+0x8DDA,0x8DD6,0x8DCC,0x8DDB,0x8DCB,0x8DEA,0x8DEB,0x8DDF,
+0x8DE3,0x8DFC,0x8E08,0x8E09,0x8DFF,0x8E1D,0x8E1E,0x8E10,
+0x8E1F,0x8E42,0x8E35,0x8E30,0x8E34,0x8E4A,
+/* plane 1 ku 77 */
+0x8E47,0x8E49,0x8E4C,0x8E50,0x8E48,0x8E59,0x8E64,0x8E60,
+0x8E2A,0x8E63,0x8E55,0x8E76,0x8E72,0x8E7C,0x8E81,0x8E87,
+0x8E85,0x8E84,0x8E8B,0x8E8A,0x8E93,0x8E91,0x8E94,0x8E99,
+0x8EAA,0x8EA1,0x8EAC,0x8EB0,0x8EC6,0x8EB1,0x8EBE,0x8EC5,
+0x8EC8,0x8ECB,0x8EDB,0x8EE3,0x8EFC,0x8EFB,0x8EEB,0x8EFE,
+0x8F0A,0x8F05,0x8F15,0x8F12,0x8F19,0x8F13,0x8F1C,0x8F1F,
+0x8F1B,0x8F0C,0x8F26,0x8F33,0x8F3B,0x8F39,0x8F45,0x8F42,
+0x8F3E,0x8F4C,0x8F49,0x8F46,0x8F4E,0x8F57,0x8F5C,0x8F62,
+0x8F63,0x8F64,0x8F9C,0x8F9F,0x8FA3,0x8FAD,0x8FAF,0x8FB7,
+0x8FDA,0x8FE5,0x8FE2,0x8FEA,0x8FEF,0x9087,0x8FF4,0x9005,
+0x8FF9,0x8FFA,0x9011,0x9015,0x9021,0x900D,0x901E,0x9016,
+0x900B,0x9027,0x9036,0x9035,0x9039,0x8FF8,
+/* plane 1 ku 78 */
+0x904F,0x9050,0x9051,0x9052,0x900E,0x9049,0x903E,0x9056,
+0x9058,0x905E,0x9068,0x906F,0x9076,0x96A8,0x9072,0x9082,
+0x907D,0x9081,0x9080,0x908A,0x9089,0x908F,0x90A8,0x90AF,
+0x90B1,0x90B5,0x90E2,0x90E4,0x6248,0x90DB,0x9102,0x9112,
+0x9119,0x9132,0x9130,0x914A,0x9156,0x9158,0x9163,0x9165,
+0x9169,0x9173,0x9172,0x918B,0x9189,0x9182,0x91A2,0x91AB,
+0x91AF,0x91AA,0x91B5,0x91B4,0x91BA,0x91C0,0x91C1,0x91C9,
+0x91CB,0x91D0,0x91D6,0x91DF,0x91E1,0x91DB,0x91FC,0x91F5,
+0x91F6,0x921E,0x91FF,0x9214,0x922C,0x9215,0x9211,0x925E,
+0x9257,0x9245,0x9249,0x9264,0x9248,0x9295,0x923F,0x924B,
+0x9250,0x929C,0x9296,0x9293,0x929B,0x925A,0x92CF,0x92B9,
+0x92B7,0x92E9,0x930F,0x92FA,0x9344,0x932E,
+/* plane 1 ku 79 */
+0x9319,0x9322,0x931A,0x9323,0x933A,0x9335,0x933B,0x935C,
+0x9360,0x937C,0x936E,0x9356,0x93B0,0x93AC,0x93AD,0x9394,
+0x93B9,0x93D6,0x93D7,0x93E8,0x93E5,0x93D8,0x93C3,0x93DD,
+0x93D0,0x93C8,0x93E4,0x941A,0x9414,0x9413,0x9403,0x9407,
+0x9410,0x9436,0x942B,0x9435,0x9421,0x943A,0x9441,0x9452,
+0x9444,0x945B,0x9460,0x9462,0x945E,0x946A,0x9229,0x9470,
+0x9475,0x9477,0x947D,0x945A,0x947C,0x947E,0x9481,0x947F,
+0x9582,0x9587,0x958A,0x9594,0x9596,0x9598,0x9599,0x95A0,
+0x95A8,0x95A7,0x95AD,0x95BC,0x95BB,0x95B9,0x95BE,0x95CA,
+0x6FF6,0x95C3,0x95CD,0x95CC,0x95D5,0x95D4,0x95D6,0x95DC,
+0x95E1,0x95E5,0x95E2,0x9621,0x9628,0x962E,0x962F,0x9642,
+0x964C,0x964F,0x964B,0x9677,0x965C,0x965E,
+/* plane 1 ku 80 */
+0x965D,0x965F,0x9666,0x9672,0x966C,0x968D,0x9698,0x9695,
+0x9697,0x96AA,0x96A7,0x96B1,0x96B2,0x96B0,0x96B4,0x96B6,
+0x96B8,0x96B9,0x96CE,0x96CB,0x96C9,0x96CD,0x894D,0x96DC,
+0x970D,0x96D5,0x96F9,0x9704,0x9706,0x9708,0x9713,0x970E,
+0x9711,0x970F,0x9716,0x9719,0x9724,0x972A,0x9730,0x9739,
+0x973D,0x973E,0x9744,0x9746,0x9748,0x9742,0x9749,0x975C,
+0x9760,0x9764,0x9766,0x9768,0x52D2,0x976B,0x9771,0x9779,
+0x9785,0x977C,0x9781,0x977A,0x9786,0x978B,0x978F,0x9790,
+0x979C,0x97A8,0x97A6,0x97A3,0x97B3,0x97B4,0x97C3,0x97C6,
+0x97C8,0x97CB,0x97DC,0x97ED,0x9F4F,0x97F2,0x7ADF,0x97F6,
+0x97F5,0x980F,0x980C,0x9838,0x9824,0x9821,0x9837,0x983D,
+0x9846,0x984F,0x984B,0x986B,0x986F,0x9870,
+/* plane 1 ku 81 */
+0x9871,0x9874,0x9873,0x98AA,0x98AF,0x98B1,0x98B6,0x98C4,
+0x98C3,0x98C6,0x98E9,0x98EB,0x9903,0x9909,0x9912,0x9914,
+0x9918,0x9921,0x991D,0x991E,0x9924,0x9920,0x992C,0x992E,
+0x993D,0x993E,0x9942,0x9949,0x9945,0x9950,0x994B,0x9951,
+0x9952,0x994C,0x9955,0x9997,0x9998,0x99A5,0x99AD,0x99AE,
+0x99BC,0x99DF,0x99DB,0x99DD,0x99D8,0x99D1,0x99ED,0x99EE,
+0x99F1,0x99F2,0x99FB,0x99F8,0x9A01,0x9A0F,0x9A05,0x99E2,
+0x9A19,0x9A2B,0x9A37,0x9A45,0x9A42,0x9A40,0x9A43,0x9A3E,
+0x9A55,0x9A4D,0x9A5B,0x9A57,0x9A5F,0x9A62,0x9A65,0x9A64,
+0x9A69,0x9A6B,0x9A6A,0x9AAD,0x9AB0,0x9ABC,0x9AC0,0x9ACF,
+0x9AD1,0x9AD3,0x9AD4,0x9ADE,0x9ADF,0x9AE2,0x9AE3,0x9AE6,
+0x9AEF,0x9AEB,0x9AEE,0x9AF4,0x9AF1,0x9AF7,
+/* plane 1 ku 82 */
+0x9AFB,0x9B06,0x9B18,0x9B1A,0x9B1F,0x9B22,0x9B23,0x9B25,
+0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2E,0x9B2F,0x9B32,0x9B44,
+0x9B43,0x9B4F,0x9B4D,0x9B4E,0x9B51,0x9B58,0x9B74,0x9B93,
+0x9B83,0x9B91,0x9B96,0x9B97,0x9B9F,0x9BA0,0x9BA8,0x9BB4,
+0x9BC0,0x9BCA,0x9BB9,0x9BC6,0x9BCF,0x9BD1,0x9BD2,0x9BE3,
+0x9BE2,0x9BE4,0x9BD4,0x9BE1,0x9C3A,0x9BF2,0x9BF1,0x9BF0,
+0x9C15,0x9C14,0x9C09,0x9C13,0x9C0C,0x9C06,0x9C08,0x9C12,
+0x9C0A,0x9C04,0x9C2E,0x9C1B,0x9C25,0x9C24,0x9C21,0x9C30,
+0x9C47,0x9C32,0x9C46,0x9C3E,0x9C5A,0x9C60,0x9C67,0x9C76,
+0x9C78,0x9CE7,0x9CEC,0x9CF0,0x9D09,0x9D08,0x9CEB,0x9D03,
+0x9D06,0x9D2A,0x9D26,0x9DAF,0x9D23,0x9D1F,0x9D44,0x9D15,
+0x9D12,0x9D41,0x9D3F,0x9D3E,0x9D46,0x9D48,
+/* plane 1 ku 83 */
+0x9D5D,0x9D5E,0x9D64,0x9D51,0x9D50,0x9D59,0x9D72,0x9D89,
+0x9D87,0x9DAB,0x9D6F,0x9D7A,0x9D9A,0x9DA4,0x9DA9,0x9DB2,
+0x9DC4,0x9DC1,0x9DBB,0x9DB8,0x9DBA,0x9DC6,0x9DCF,0x9DC2,
+0x9DD9,0x9DD3,0x9DF8,0x9DE6,0x9DED,0x9DEF,0x9DFD,0x9E1A,
+0x9E1B,0x9E1E,0x9E75,0x9E79,0x9E7D,0x9E81,0x9E88,0x9E8B,
+0x9E8C,0x9E92,0x9E95,0x9E91,0x9E9D,0x9EA5,0x9EA9,0x9EB8,
+0x9EAA,0x9EAD,0x9761,0x9ECC,0x9ECE,0x9ECF,0x9ED0,0x9ED4,
+0x9EDC,0x9EDE,0x9EDD,0x9EE0,0x9EE5,0x9EE8,0x9EEF,0x9EF4,
+0x9EF6,0x9EF7,0x9EF9,0x9EFB,0x9EFC,0x9EFD,0x9F07,0x9F08,
+0x76B7,0x9F15,0x9F21,0x9F2C,0x9F3E,0x9F4A,0x9F52,0x9F54,
+0x9F63,0x9F5F,0x9F60,0x9F61,0x9F66,0x9F67,0x9F6C,0x9F6A,
+0x9F77,0x9F72,0x9F76,0x9F95,0x9F9C,0x9FA0,
+/* plane 1 ku 84 */
+0x582F,0x69C7,0x9059,0x7464,0x51DC,0x7199,0x5653,0x5DE2,
+0x5E14,0x5E18,0x5E58,0x5E5E,0x5EBE,0xF928,0x5ECB,0x5EF9,
+0x5F00,0x5F02,0x5F07,0x5F1D,0x5F23,0x5F34,0x5F36,0x5F3D,
+0x5F40,0x5F45,0x5F54,0x5F58,0x5F64,0x5F67,0x5F7D,0x5F89,
+0x5F9C,0x5FA7,0x5FAF,0x5FB5,0x5FB7,0x5FC9,0x5FDE,0x5FE1,
+0x5FE9,0x600D,0x6014,0x6018,0x6033,0x6035,0x6047,0xFA3D,
+0x609D,0x609E,0x60CB,0x60D4,0x60D5,0x60DD,0x60F8,0x611C,
+0x612B,0x6130,0x6137,0xFA3E,0x618D,0xFA3F,0x61BC,0x61B9,
+0xFA40,0x6222,0x623E,0x6243,0x6256,0x625A,0x626F,0x6285,
+0x62C4,0x62D6,0x62FC,0x630A,0x6318,0x6339,0x6343,0x6365,
+0x637C,0x63E5,0x63ED,0x63F5,0x6410,0x6414,0x6422,0x6479,
+0x6451,0x6460,0x646D,0x64CE,0x64BE,0x64BF,
+/* plane 1 ku 85 */
+0x64C4,0x64CA,0x64D0,0x64F7,0x64FB,0x6522,0x6529,0xFA41,
+0x6567,0x659D,0xFA42,0x6600,0x6609,0x6615,0x661E,0x663A,
+0x6622,0x6624,0x662B,0x6630,0x6631,0x6633,0x66FB,0x6648,
+0x664C,0x0000,0x6659,0x665A,0x6661,0x6665,0x6673,0x6677,
+0x6678,0x668D,0xFA43,0x66A0,0x66B2,0x66BB,0x66C6,0x66C8,
+0x3B22,0x66DB,0x66E8,0x66FA,0x6713,0xF929,0x6733,0x6766,
+0x6747,0x6748,0x677B,0x6781,0x6793,0x6798,0x679B,0x67BB,
+0x67F9,0x67C0,0x67D7,0x67FC,0x6801,0x6852,0x681D,0x682C,
+0x6831,0x685B,0x6872,0x6875,0xFA44,0x68A3,0x68A5,0x68B2,
+0x68C8,0x68D0,0x68E8,0x68ED,0x68F0,0x68F1,0x68FC,0x690A,
+0x6949,0x0000,0x6935,0x6942,0x6957,0x6963,0x6964,0x6968,
+0x6980,0xFA14,0x69A5,0x69AD,0x69CF,0x3BB6,
+/* plane 1 ku 86 */
+0x3BC3,0x69E2,0x69E9,0x69EA,0x69F5,0x69F6,0x6A0F,0x6A15,
+0x0000,0x6A3B,0x6A3E,0x6A45,0x6A50,0x6A56,0x6A5B,0x6A6B,
+0x6A73,0x0000,0x6A89,0x6A94,0x6A9D,0x6A9E,0x6AA5,0x6AE4,
+0x6AE7,0x3C0F,0xF91D,0x6B1B,0x6B1E,0x6B2C,0x6B35,0x6B46,
+0x6B56,0x6B60,0x6B65,0x6B67,0x6B77,0x6B82,0x6BA9,0x6BAD,
+0xF970,0x6BCF,0x6BD6,0x6BD7,0x6BFF,0x6C05,0x6C10,0x6C33,
+0x6C59,0x6C5C,0x6CAA,0x6C74,0x6C76,0x6C85,0x6C86,0x6C98,
+0x6C9C,0x6CFB,0x6CC6,0x6CD4,0x6CE0,0x6CEB,0x6CEE,0x0000,
+0x6D04,0x6D0E,0x6D2E,0x6D31,0x6D39,0x6D3F,0x6D58,0x6D65,
+0xFA45,0x6D82,0x6D87,0x6D89,0x6D94,0x6DAA,0x6DAC,0x6DBF,
+0x6DC4,0x6DD6,0x6DDA,0x6DDB,0x6DDD,0x6DFC,0xFA46,0x6E34,
+0x6E44,0x6E5C,0x6E5E,0x6EAB,0x6EB1,0x6EC1,
+/* plane 1 ku 87 */
+0x6EC7,0x6ECE,0x6F10,0x6F1A,0xFA47,0x6F2A,0x6F2F,0x6F33,
+0x6F51,0x6F59,0x6F5E,0x6F61,0x6F62,0x6F7E,0x6F88,0x6F8C,
+0x6F8D,0x6F94,0x6FA0,0x6FA7,0x6FB6,0x6FBC,0x6FC7,0x6FCA,
+0x6FF9,0x6FF0,0x6FF5,0x7005,0x7006,0x7028,0x704A,0x705D,
+0x705E,0x704E,0x7064,0x7075,0x7085,0x70A4,0x70AB,0x70B7,
+0x70D4,0x70D8,0x70E4,0x710F,0x712B,0x711E,0x7120,0x712E,
+0x7130,0x7146,0x7147,0x7151,0xFA48,0x7152,0x715C,0x7160,
+0x7168,0xFA15,0x7185,0x7187,0x7192,0x71C1,0x71BA,0x71C4,
+0x71FE,0x7200,0x7215,0x7255,0x7256,0x3E3F,0x728D,0x729B,
+0x72BE,0x72C0,0x72FB,0x0000,0x7327,0x7328,0xFA16,0x7350,
+0x7366,0x737C,0x7395,0x739F,0x73A0,0x73A2,0x73A6,0x73AB,
+0x73C9,0x73CF,0x73D6,0x73D9,0x73E3,0x73E9,
+/* plane 1 ku 88 */
+0x7407,0x740A,0x741A,0x741B,0xFA4A,0x7426,0x7428,0x742A,
+0x742B,0x742C,0x742E,0x742F,0x7430,0x7444,0x7446,0x7447,
+0x744B,0x7457,0x7462,0x746B,0x746D,0x7486,0x7487,0x7489,
+0x7498,0x749C,0x749F,0x74A3,0x7490,0x74A6,0x74A8,0x74A9,
+0x74B5,0x74BF,0x74C8,0x74C9,0x74DA,0x74FF,0x7501,0x7517,
+0x752F,0x756F,0x7579,0x7592,0x3F72,0x75CE,0x75E4,0x7600,
+0x7602,0x7608,0x7615,0x7616,0x7619,0x761E,0x762D,0x7635,
+0x7643,0x764B,0x7664,0x7665,0x766D,0x766F,0x7671,0x7681,
+0x769B,0x769D,0x769E,0x76A6,0x76AA,0x76B6,0x76C5,0x76CC,
+0x76CE,0x76D4,0x76E6,0x76F1,0x76FC,0x770A,0x7719,0x7734,
+0x7736,0x7746,0x774D,0x774E,0x775C,0x775F,0x7762,0x777A,
+0x7780,0x7794,0x77AA,0x77E0,0x782D,0x0000,
+/* plane 1 ku 89 */
+0x7843,0x784E,0x784F,0x7851,0x7868,0x786E,0xFA4B,0x78B0,
+0x0000,0x78AD,0x78E4,0x78F2,0x7900,0x78F7,0x791C,0x792E,
+0x7931,0x7934,0xFA4C,0xFA4D,0x7945,0x7946,0xFA4E,0xFA4F,
+0xFA50,0x795C,0xFA51,0xFA19,0xFA1A,0x7979,0xFA52,0xFA53,
+0xFA1B,0x7998,0x79B1,0x79B8,0x79C8,0x79CA,0x0000,0x79D4,
+0x79DE,0x79EB,0x79ED,0x7A03,0xFA54,0x7A39,0x7A5D,0x7A6D,
+0xFA55,0x7A85,0x7AA0,0x0000,0x7AB3,0x7ABB,0x7ACE,0x7AEB,
+0x7AFD,0x7B12,0x7B2D,0x7B3B,0x7B47,0x7B4E,0x7B60,0x7B6D,
+0x7B6F,0x7B72,0x7B9E,0xFA56,0x7BD7,0x7BD9,0x7C01,0x7C31,
+0x7C1E,0x7C20,0x7C33,0x7C36,0x4264,0x0000,0x7C59,0x7C6D,
+0x7C79,0x7C8F,0x7C94,0x7CA0,0x7CBC,0x7CD5,0x7CD9,0x7CDD,
+0x7D07,0x7D08,0x7D13,0x7D1D,0x7D23,0x7D31,
+/* plane 1 ku 90 */
+0x7D41,0x7D48,0x7D53,0x7D5C,0x7D7A,0x7D83,0x7D8B,0x7DA0,
+0x7DA6,0x7DC2,0x7DCC,0x7DD6,0x7DE3,0xFA57,0x7E28,0x7E08,
+0x7E11,0x7E15,0xFA59,0x7E47,0x7E52,0x7E61,0x7E8A,0x7E8D,
+0x7F47,0xFA5A,0x7F91,0x7F97,0x7FBF,0x7FCE,0x7FDB,0x7FDF,
+0x7FEC,0x7FEE,0x7FFA,0xFA5B,0x8014,0x8026,0x8035,0x8037,
+0x803C,0x80CA,0x80D7,0x80E0,0x80F3,0x8118,0x814A,0x8160,
+0x8167,0x8168,0x816D,0x81BB,0x81CA,0x81CF,0x81D7,0xFA5C,
+0x4453,0x445B,0x8260,0x8274,0x0000,0x828E,0x82A1,0x82A3,
+0x82A4,0x82A9,0x82AE,0x82B7,0x82BE,0x82BF,0x82C6,0x82D5,
+0x82FD,0x82FE,0x8300,0x8301,0x8362,0x8322,0x832D,0x833A,
+0x8343,0x8347,0x8351,0x8355,0x837D,0x8386,0x8392,0x8398,
+0x83A7,0x83A9,0x83BF,0x83C0,0x83C7,0x83CF,
+/* plane 1 ku 91 */
+0x83D1,0x83E1,0x83EA,0x8401,0x8406,0x840A,0xFA5F,0x8448,
+0x845F,0x8470,0x8473,0x8485,0x849E,0x84AF,0x84B4,0x84BA,
+0x84C0,0x84C2,0x0000,0x8532,0x851E,0x8523,0x852F,0x8559,
+0x8564,0xFA1F,0x85AD,0x857A,0x858C,0x858F,0x85A2,0x85B0,
+0x85CB,0x85CE,0x85ED,0x8612,0x85FF,0x8604,0x8605,0x8610,
+0x0000,0x8618,0x8629,0x8638,0x8657,0x865B,0xF936,0x8662,
+0x459D,0x866C,0x8675,0x8698,0x86B8,0x86FA,0x86FC,0x86FD,
+0x870B,0x8771,0x8787,0x8788,0x87AC,0x87AD,0x87B5,0x45EA,
+0x87D6,0x87EC,0x8806,0x880A,0x8810,0x8814,0x881F,0x8898,
+0x88AA,0x88CA,0x88CE,0x0000,0x88F5,0x891C,0xFA60,0x8918,
+0x8919,0x891A,0x8927,0x8930,0x8932,0x8939,0x8940,0x8994,
+0xFA61,0x89D4,0x89E5,0x89F6,0x8A12,0x8A15,
+/* plane 1 ku 92 */
+0x8A22,0x8A37,0x8A47,0x8A4E,0x8A5D,0x8A61,0x8A75,0x8A79,
+0x8AA7,0x8AD0,0x8ADF,0x8AF4,0x8AF6,0xFA22,0xFA62,0xFA63,
+0x8B46,0x8B54,0x8B59,0x8B69,0x8B9D,0x8C49,0x8C68,0xFA64,
+0x8CE1,0x8CF4,0x8CF8,0x8CFE,0xFA65,0x8D12,0x8D1B,0x8DAF,
+0x8DCE,0x8DD1,0x8DD7,0x8E20,0x8E23,0x8E3D,0x8E70,0x8E7B,
+0x0000,0x8EC0,0x4844,0x8EFA,0x8F1E,0x8F2D,0x8F36,0x8F54,
+0x0000,0x8FA6,0x8FB5,0x8FE4,0x8FE8,0x8FEE,0x9008,0x902D,
+0xFA67,0x9088,0x9095,0x9097,0x9099,0x909B,0x90A2,0x90B3,
+0x90BE,0x90C4,0x90C5,0x90C7,0x90D7,0x90DD,0x90DE,0x90EF,
+0x90F4,0xFA26,0x9114,0x9115,0x9116,0x9122,0x9123,0x9127,
+0x912F,0x9131,0x9134,0x913D,0x9148,0x915B,0x9183,0x919E,
+0x91AC,0x91B1,0x91BC,0x91D7,0x91FB,0x91E4,
+/* plane 1 ku 93 */
+0x91E5,0x91ED,0x91F1,0x9207,0x9210,0x9238,0x9239,0x923A,
+0x923C,0x9240,0x9243,0x924F,0x9278,0x9288,0x92C2,0x92CB,
+0x92CC,0x92D3,0x92E0,0x92FF,0x9304,0x931F,0x9321,0x9325,
+0x9348,0x9349,0x934A,0x9364,0x9365,0x936A,0x9370,0x939B,
+0x93A3,0x93BA,0x93C6,0x93DE,0x93DF,0x9404,0x93FD,0x9433,
+0x944A,0x9463,0x946B,0x9471,0x9472,0x958E,0x959F,0x95A6,
+0x95A9,0x95AC,0x95B6,0x95BD,0x95CB,0x95D0,0x95D3,0x49B0,
+0x95DA,0x95DE,0x9658,0x9684,0xF9DC,0x969D,0x96A4,0x96A5,
+0x96D2,0x96DE,0xFA68,0x96E9,0x96EF,0x9733,0x973B,0x974D,
+0x974E,0x974F,0x975A,0x976E,0x9773,0x9795,0x97AE,0x97BA,
+0x97C1,0x97C9,0x97DE,0x97DB,0x97F4,0xFA69,0x980A,0x981E,
+0x982B,0x9830,0xFA6A,0x9852,0x9853,0x9856,
+/* plane 1 ku 94 */
+0x9857,0x9859,0x985A,0xF9D0,0x9865,0x986C,0x98BA,0x98C8,
+0x98E7,0x9958,0x999E,0x9A02,0x9A03,0x9A24,0x9A2D,0x9A2E,
+0x9A38,0x9A4A,0x9A4E,0x9A52,0x9AB6,0x9AC1,0x9AC3,0x9ACE,
+0x9AD6,0x9AF9,0x9B02,0x9B08,0x9B20,0x4C17,0x9B2D,0x9B5E,
+0x9B79,0x9B66,0x9B72,0x9B75,0x9B84,0x9B8A,0x9B8F,0x9B9E,
+0x9BA7,0x9BC1,0x9BCE,0x9BE5,0x9BF8,0x9BFD,0x9C00,0x9C23,
+0x9C41,0x9C4F,0x9C50,0x9C53,0x9C63,0x9C65,0x9C77,0x9D1D,
+0x9D1E,0x9D43,0x9D47,0x9D52,0x9D63,0x9D70,0x9D7C,0x9D8A,
+0x9D96,0x9DC0,0x9DAC,0x9DBC,0x9DD7,0x0000,0x9DE7,0x9E07,
+0x9E15,0x9E7C,0x9E9E,0x9EA4,0x9EAC,0x9EAF,0x9EB4,0x9EB5,
+0x9EC3,0x9ED1,0x9F10,0x9F39,0x9F57,0x9F90,0x9F94,0x9F97,
+0x9FA2,0x59F8,0x5C5B,0x5E77,0x7626,0x7E6B,
+/* plane 2 ku 1 */
+0x0000,0x4E02,0x4E0F,0x4E12,0x4E29,0x4E2B,0x4E2E,0x4E40,
+0x4E47,0x4E48,0x0000,0x4E51,0x3406,0x0000,0x4E5A,0x4E69,
+0x4E9D,0x342C,0x342E,0x4EB9,0x4EBB,0x0000,0x4EBC,0x4EC3,
+0x4EC8,0x4ED0,0x4EEB,0x4EDA,0x4EF1,0x4EF5,0x4F00,0x4F16,
+0x4F64,0x4F37,0x4F3E,0x4F54,0x4F58,0x0000,0x4F77,0x4F78,
+0x4F7A,0x4F7D,0x4F82,0x4F85,0x4F92,0x4F9A,0x4FE6,0x4FB2,
+0x4FBE,0x4FC5,0x4FCB,0x4FCF,0x4FD2,0x346A,0x4FF2,0x5000,
+0x5010,0x5013,0x501C,0x501E,0x5022,0x3468,0x5042,0x5046,
+0x504E,0x5053,0x5057,0x5063,0x5066,0x506A,0x5070,0x50A3,
+0x5088,0x5092,0x5093,0x5095,0x5096,0x509C,0x50AA,0x0000,
+0x50B1,0x50BA,0x50BB,0x50C4,0x50C7,0x50F3,0x0000,0x50CE,
+0x0000,0x50D4,0x50D9,0x50E1,0x50E9,0x3492,
+/* plane 2 ku 8 */
+0x5B96,0x5BAC,0x3761,0x5BC0,0x3762,0x5BCE,0x5BD6,0x376C,
+0x376B,0x5BF1,0x5BFD,0x3775,0x5C03,0x5C29,0x5C30,0x0000,
+0x5C5F,0x5C63,0x5C67,0x5C68,0x5C69,0x5C70,0x0000,0x0000,
+0x5C7C,0x0000,0x0000,0x5C88,0x5C8A,0x37C1,0x0000,0x0000,
+0x5CA0,0x5CA2,0x5CA6,0x5CA7,0x0000,0x5CAD,0x5CB5,0x0000,
+0x5CC9,0x0000,0x0000,0x5D06,0x5D10,0x5D2B,0x5D1D,0x5D20,
+0x5D24,0x5D26,0x5D31,0x5D39,0x5D42,0x37E8,0x5D61,0x5D6A,
+0x37F4,0x5D70,0x0000,0x37FD,0x5D88,0x3800,0x5D92,0x5D94,
+0x5D97,0x5D99,0x5DB0,0x5DB2,0x5DB4,0x0000,0x5DB9,0x5DD1,
+0x5DD7,0x5DD8,0x5DE0,0x0000,0x5DE4,0x5DE9,0x382F,0x5E00,
+0x3836,0x5E12,0x5E15,0x3840,0x5E1F,0x5E2E,0x5E3E,0x5E49,
+0x385C,0x5E56,0x3861,0x5E6B,0x5E6C,0x5E6D,
+/* plane 2 ku 3 */
+0x5108,0x0000,0x5117,0x511B,0x0000,0x5160,0x0000,0x5173,
+0x5183,0x518B,0x34BC,0x5198,0x51A3,0x51AD,0x34C7,0x51BC,
+0x0000,0x0000,0x51F3,0x51F4,0x5202,0x5212,0x5216,0x0000,
+0x5255,0x525C,0x526C,0x5277,0x5284,0x5282,0x0000,0x5298,
+0x0000,0x52A4,0x52A6,0x52AF,0x52BA,0x52BB,0x52CA,0x351F,
+0x52D1,0x0000,0x52F7,0x530A,0x530B,0x5324,0x5335,0x533E,
+0x5342,0x0000,0x0000,0x5367,0x536C,0x537A,0x53A4,0x53B4,
+0x0000,0x53B7,0x53C0,0x0000,0x355D,0x355E,0x53D5,0x53DA,
+0x3563,0x53F4,0x53F5,0x5455,0x5424,0x5428,0x356E,0x5443,
+0x5462,0x5466,0x546C,0x548A,0x548D,0x5495,0x54A0,0x54A6,
+0x54AD,0x54AE,0x54B7,0x54BA,0x54BF,0x54C3,0x0000,0x54EC,
+0x54EF,0x54F1,0x54F3,0x5500,0x5501,0x5509,
+/* plane 2 ku 4 */
+0x553C,0x5541,0x35A6,0x5547,0x554A,0x35A8,0x5560,0x5561,
+0x5564,0x0000,0x557D,0x5582,0x5588,0x5591,0x35C5,0x55D2,
+0x0000,0x0000,0x55BF,0x55C9,0x55CC,0x55D1,0x55DD,0x35DA,
+0x55E2,0x0000,0x55E9,0x5628,0x0000,0x5607,0x5610,0x5630,
+0x5637,0x35F4,0x563D,0x563F,0x5640,0x5647,0x565E,0x5660,
+0x566D,0x3605,0x5688,0x568C,0x5695,0x569A,0x569D,0x56A8,
+0x56AD,0x56B2,0x56C5,0x56CD,0x56DF,0x56E8,0x56F6,0x56F7,
+0x0000,0x5715,0x5723,0x0000,0x5729,0x0000,0x5745,0x5746,
+0x574C,0x574D,0x0000,0x5768,0x576F,0x5773,0x5774,0x5775,
+0x577B,0x0000,0x0000,0x57AC,0x579A,0x579D,0x579E,0x57A8,
+0x57D7,0x0000,0x57CC,0x0000,0x0000,0x57DE,0x57E6,0x57F0,
+0x364A,0x57F8,0x57FB,0x57FD,0x5804,0x581E,
+/* plane 2 ku 5 */
+0x5820,0x5827,0x5832,0x5839,0x0000,0x5849,0x584C,0x5867,
+0x588A,0x588B,0x588D,0x588F,0x5890,0x5894,0x589D,0x58AA,
+0x58B1,0x0000,0x58C3,0x58CD,0x58E2,0x58F3,0x58F4,0x5905,
+0x5906,0x590B,0x590D,0x5914,0x5924,0x0000,0x3691,0x593D,
+0x3699,0x5946,0x3696,0x0000,0x595B,0x595F,0x0000,0x5975,
+0x5976,0x597C,0x599F,0x59AE,0x59BC,0x59C8,0x59CD,0x59DE,
+0x59E3,0x59E4,0x59E7,0x59EE,0x0000,0x0000,0x36CF,0x5A0C,
+0x5A0D,0x5A17,0x5A27,0x5A2D,0x5A55,0x5A65,0x5A7A,0x5A8B,
+0x5A9C,0x5A9F,0x5AA0,0x5AA2,0x5AB1,0x5AB3,0x5AB5,0x5ABA,
+0x5ABF,0x5ADA,0x5ADC,0x5AE0,0x5AE5,0x5AF0,0x5AEE,0x5AF5,
+0x5B00,0x5B08,0x5B17,0x5B34,0x5B2D,0x5B4C,0x5B52,0x5B68,
+0x5B6F,0x5B7C,0x5B7F,0x5B81,0x5B84,0x0000,
+/* plane 2 ku 12 */
+0x5E6E,0x0000,0x5EA5,0x5EAA,0x5EAC,0x5EB9,0x5EBF,0x5EC6,
+0x5ED2,0x5ED9,0x0000,0x5EFD,0x5F08,0x5F0E,0x5F1C,0x0000,
+0x5F1E,0x5F47,0x5F63,0x5F72,0x5F7E,0x5F8F,0x5FA2,0x5FA4,
+0x5FB8,0x5FC4,0x38FA,0x5FC7,0x5FCB,0x5FD2,0x5FD3,0x5FD4,
+0x5FE2,0x5FEE,0x5FEF,0x5FF3,0x5FFC,0x3917,0x6017,0x6022,
+0x6024,0x391A,0x604C,0x607F,0x608A,0x6095,0x60A8,0x0000,
+0x60B0,0x60B1,0x60BE,0x60C8,0x60D9,0x60DB,0x60EE,0x60F2,
+0x60F5,0x6110,0x6112,0x6113,0x6119,0x611E,0x613A,0x396F,
+0x6141,0x6146,0x6160,0x617C,0x0000,0x6192,0x6193,0x6197,
+0x6198,0x61A5,0x61A8,0x61AD,0x0000,0x61D5,0x61DD,0x61DF,
+0x61F5,0x0000,0x6215,0x6223,0x6229,0x6246,0x624C,0x6251,
+0x6252,0x6261,0x6264,0x627B,0x626D,0x6273,
+/* plane 2 ku 13 */
+0x6299,0x62A6,0x62D5,0x0000,0x62FD,0x6303,0x630D,0x6310,
+0x0000,0x0000,0x6332,0x6335,0x633B,0x633C,0x6341,0x6344,
+0x634E,0x0000,0x6359,0x0000,0x0000,0x636C,0x6384,0x6399,
+0x0000,0x6394,0x63BD,0x63F7,0x63D4,0x63D5,0x63DC,0x63E0,
+0x63EB,0x63EC,0x63F2,0x6409,0x641E,0x6425,0x6429,0x642F,
+0x645A,0x645B,0x645D,0x6473,0x647D,0x6487,0x6491,0x649D,
+0x649F,0x64CB,0x64CC,0x64D5,0x64D7,0x0000,0x64E4,0x64E5,
+0x64FF,0x6504,0x3A6E,0x650F,0x6514,0x6516,0x3A73,0x651E,
+0x6532,0x6544,0x6554,0x656B,0x657A,0x6581,0x6584,0x6585,
+0x658A,0x65B2,0x65B5,0x65B8,0x65BF,0x65C2,0x65C9,0x65D4,
+0x3AD6,0x65F2,0x65F9,0x65FC,0x6604,0x6608,0x6621,0x662A,
+0x6645,0x6651,0x664E,0x3AEA,0x0000,0x6657,
+/* plane 2 ku 14 */
+0x665B,0x6663,0x0000,0x0000,0x666A,0x666B,0x666C,0x666D,
+0x667B,0x6680,0x6690,0x6692,0x6699,0x3B0E,0x66AD,0x66B1,
+0x66B5,0x3B1A,0x66BF,0x3B1C,0x66EC,0x3AD7,0x6701,0x6705,
+0x6712,0x0000,0x6719,0x0000,0x0000,0x674C,0x674D,0x6754,
+0x675D,0x0000,0x0000,0x0000,0x6774,0x6776,0x0000,0x6792,
+0x0000,0x8363,0x6810,0x67B0,0x67B2,0x67C3,0x67C8,0x67D2,
+0x67D9,0x67DB,0x67F0,0x67F7,0x0000,0x0000,0x0000,0x6818,
+0x681F,0x682D,0x0000,0x6833,0x683B,0x683E,0x6844,0x6845,
+0x6849,0x684C,0x6855,0x6857,0x3B77,0x686B,0x686E,0x687A,
+0x687C,0x6882,0x6890,0x6896,0x3B6D,0x6898,0x6899,0x689A,
+0x689C,0x68AA,0x68AB,0x68B4,0x68BB,0x68FB,0x0000,0x0000,
+0xFA13,0x68C3,0x68C5,0x68CC,0x68CF,0x68D6,
+/* plane 2 ku 15 */
+0x68D9,0x68E4,0x68E5,0x68EC,0x68F7,0x6903,0x6907,0x3B87,
+0x3B88,0x0000,0x693B,0x3B8D,0x6946,0x6969,0x696C,0x6972,
+0x697A,0x697F,0x6992,0x3BA4,0x6996,0x6998,0x69A6,0x69B0,
+0x69B7,0x69BA,0x69BC,0x69C0,0x69D1,0x69D6,0x0000,0x0000,
+0x6A30,0x0000,0x0000,0x69E3,0x69EE,0x69EF,0x69F3,0x3BCD,
+0x69F4,0x69FE,0x6A11,0x6A1A,0x6A1D,0x0000,0x6A32,0x6A33,
+0x6A34,0x6A3F,0x6A46,0x6A49,0x6A7A,0x6A4E,0x6A52,0x6A64,
+0x0000,0x6A7E,0x6A83,0x6A8B,0x3BF0,0x6A91,0x6A9F,0x6AA1,
+0x0000,0x6AAB,0x6ABD,0x6AC6,0x6AD4,0x6AD0,0x6ADC,0x6ADD,
+0x0000,0x0000,0x6AEC,0x6AF1,0x6AF2,0x6AF3,0x6AFD,0x0000,
+0x6B0B,0x6B0F,0x6B10,0x6B11,0x0000,0x6B17,0x3C26,0x6B2F,
+0x6B4A,0x6B58,0x6B6C,0x6B75,0x6B7A,0x6B81,
+/* plane 2 ku 78 */
+0x6B9B,0x6BAE,0x0000,0x6BBD,0x6BBE,0x6BC7,0x6BC8,0x6BC9,
+0x6BDA,0x6BE6,0x6BE7,0x6BEE,0x6BF1,0x6C02,0x6C0A,0x6C0E,
+0x6C35,0x6C36,0x6C3A,0x0000,0x6C3F,0x6C4D,0x6C5B,0x6C6D,
+0x6C84,0x6C89,0x3CC3,0x6C94,0x6C95,0x6C97,0x6CAD,0x6CC2,
+0x6CD0,0x3CD2,0x6CD6,0x6CDA,0x6CDC,0x6CE9,0x6CEC,0x6CED,
+0x0000,0x6D00,0x6D0A,0x6D24,0x6D26,0x6D27,0x6C67,0x6D2F,
+0x6D3C,0x6D5B,0x6D5E,0x6D60,0x6D70,0x6D80,0x6D81,0x6D8A,
+0x6D8D,0x6D91,0x6D98,0x0000,0x6E17,0x0000,0x0000,0x0000,
+0x6DAB,0x6DAE,0x6DB4,0x6DC2,0x6D34,0x6DC8,0x6DCE,0x6DCF,
+0x6DD0,0x6DDF,0x6DE9,0x6DF6,0x6E36,0x6E1E,0x6E22,0x6E27,
+0x3D11,0x6E32,0x6E3C,0x6E48,0x6E49,0x6E4B,0x6E4C,0x6E4F,
+0x6E51,0x6E53,0x6E54,0x6E57,0x6E63,0x3D1E,
+/* plane 2 ku 79 */
+0x6E93,0x6EA7,0x6EB4,0x6EBF,0x6EC3,0x6ECA,0x6ED9,0x6F35,
+0x6EEB,0x6EF9,0x6EFB,0x6F0A,0x6F0C,0x6F18,0x6F25,0x6F36,
+0x6F3C,0x0000,0x6F52,0x6F57,0x6F5A,0x6F60,0x6F68,0x6F98,
+0x6F7D,0x6F90,0x6F96,0x6FBE,0x6F9F,0x6FA5,0x6FAF,0x3D64,
+0x6FB5,0x6FC8,0x6FC9,0x6FDA,0x6FDE,0x6FE9,0x0000,0x6FFC,
+0x7000,0x7007,0x700A,0x7023,0x0000,0x7039,0x703A,0x703C,
+0x7043,0x7047,0x704B,0x3D9A,0x7054,0x7065,0x7069,0x706C,
+0x706E,0x7076,0x707E,0x7081,0x7086,0x7095,0x7097,0x70BB,
+0x0000,0x709F,0x70B1,0x0000,0x70EC,0x70CA,0x70D1,0x70D3,
+0x70DC,0x7103,0x7104,0x7106,0x7107,0x7108,0x710C,0x3DC0,
+0x712F,0x7131,0x7150,0x714A,0x7153,0x715E,0x3DD4,0x7196,
+0x7180,0x719B,0x71A0,0x71A2,0x71AE,0x71AF,
+/* plane 2 ku 80 */
+0x71B3,0x0000,0x71CB,0x71D3,0x71D9,0x71DC,0x7207,0x3E05,
+0xFA49,0x722B,0x7234,0x7238,0x7239,0x4E2C,0x7242,0x7253,
+0x7257,0x7263,0x0000,0x726E,0x726F,0x7278,0x727F,0x728E,
+0x0000,0x72AD,0x72AE,0x72B0,0x72B1,0x72C1,0x3E60,0x72CC,
+0x3E66,0x3E68,0x72F3,0x72FA,0x7307,0x7312,0x7318,0x7319,
+0x3E83,0x7339,0x732C,0x7331,0x7333,0x733D,0x7352,0x3E94,
+0x736B,0x736C,0x0000,0x736E,0x736F,0x7371,0x7377,0x7381,
+0x7385,0x738A,0x7394,0x7398,0x739C,0x739E,0x73A5,0x73A8,
+0x73B5,0x73B7,0x73B9,0x73BC,0x73BF,0x73C5,0x73CB,0x73E1,
+0x73E7,0x73F9,0x7413,0x73FA,0x7401,0x7424,0x7431,0x7439,
+0x7453,0x7440,0x7443,0x744D,0x7452,0x745D,0x7471,0x7481,
+0x7485,0x7488,0x0000,0x7492,0x7497,0x7499,
+/* plane 2 ku 81 */
+0x74A0,0x74A1,0x74A5,0x74AA,0x74AB,0x74B9,0x74BB,0x74BA,
+0x74D6,0x74D8,0x74DE,0x74EF,0x74EB,0x0000,0x74FA,0x0000,
+0x7520,0x7524,0x752A,0x3F57,0x0000,0x753D,0x753E,0x7540,
+0x7548,0x754E,0x7550,0x7552,0x756C,0x7572,0x7571,0x757A,
+0x757D,0x757E,0x7581,0x0000,0x758C,0x3F75,0x75A2,0x3F77,
+0x75B0,0x75B7,0x75BF,0x75C0,0x75C6,0x75CF,0x75D3,0x75DD,
+0x75DF,0x75E0,0x75E7,0x75EC,0x75EE,0x75F1,0x75F9,0x7603,
+0x7618,0x7607,0x760F,0x3FAE,0x0000,0x7613,0x761B,0x761C,
+0x0000,0x7625,0x7628,0x763C,0x7633,0x0000,0x3FC9,0x7641,
+0x0000,0x7649,0x7655,0x3FD7,0x766E,0x7695,0x769C,0x76A1,
+0x76A0,0x76A7,0x76A8,0x76AF,0x0000,0x76C9,0x0000,0x76E8,
+0x76EC,0x0000,0x7717,0x771A,0x772D,0x7735,
+/* plane 2 ku 82 */
+0x0000,0x4039,0x0000,0x0000,0x7758,0x7760,0x776A,0x0000,
+0x7772,0x777C,0x777D,0x0000,0x4058,0x779A,0x779F,0x77A2,
+0x77A4,0x77A9,0x77DE,0x77DF,0x77E4,0x77E6,0x77EA,0x77EC,
+0x4093,0x77F0,0x77F4,0x77FB,0x0000,0x7805,0x7806,0x7809,
+0x780D,0x7819,0x7821,0x782C,0x7847,0x7864,0x786A,0x0000,
+0x788A,0x7894,0x78A4,0x789D,0x789E,0x789F,0x78BB,0x78C8,
+0x78CC,0x78CE,0x78D5,0x78E0,0x78E1,0x78E6,0x78F9,0x78FA,
+0x78FB,0x78FE,0x0000,0x7910,0x791B,0x7930,0x7925,0x793B,
+0x794A,0x7958,0x795B,0x4105,0x7967,0x7972,0x7994,0x7995,
+0x7996,0x799B,0x79A1,0x79A9,0x79B4,0x79BB,0x79C2,0x79C7,
+0x79CC,0x79CD,0x79D6,0x4148,0x0000,0x0000,0x414F,0x7A0A,
+0x7A11,0x7A15,0x7A1B,0x7A1E,0x4163,0x7A2D,
+/* plane 2 ku 83 */
+0x7A38,0x7A47,0x7A4C,0x7A56,0x7A59,0x7A5C,0x7A5F,0x7A60,
+0x7A67,0x7A6A,0x7A75,0x7A78,0x7A82,0x7A8A,0x7A90,0x7AA3,
+0x7AAC,0x0000,0x41B4,0x7AB9,0x7ABC,0x7ABE,0x41BF,0x7ACC,
+0x7AD1,0x7AE7,0x7AE8,0x7AF4,0x0000,0x0000,0x7B07,0x0000,
+0x7B3D,0x7B27,0x7B2A,0x7B2E,0x7B2F,0x7B31,0x41E6,0x41F3,
+0x7B7F,0x7B41,0x41EE,0x7B55,0x7B79,0x7B64,0x7B66,0x7B69,
+0x7B73,0x0000,0x4207,0x7B90,0x7B91,0x7B9B,0x420E,0x7BAF,
+0x7BB5,0x7BBC,0x7BC5,0x7BCA,0x0000,0x0000,0x7BD4,0x7BD6,
+0x7BDA,0x7BEA,0x7BF0,0x7C03,0x7C0B,0x7C0E,0x7C0F,0x7C26,
+0x7C45,0x7C4A,0x7C51,0x7C57,0x7C5E,0x7C61,0x7C69,0x7C6E,
+0x7C6F,0x7C70,0x0000,0x0000,0x0000,0x7CA6,0x0000,0x7CB6,
+0x7CB7,0x7CBF,0x0000,0x7CC4,0x0000,0x7CC8,
+/* plane 2 ku 84 */
+0x7CCD,0x0000,0x7CD7,0x0000,0x7CE6,0x7CEB,0x0000,0x7CF5,
+0x7D03,0x7D09,0x42C6,0x7D12,0x7D1E,0x0000,0x0000,0x7D3D,
+0x7D3E,0x7D40,0x7D47,0x0000,0x0000,0x42D6,0x7D59,0x7D5A,
+0x7D6A,0x7D70,0x42DD,0x7D7F,0x0000,0x7D86,0x7D88,0x7D8C,
+0x7D97,0x0000,0x7D9D,0x7DA7,0x7DAA,0x7DB6,0x7DB7,0x7DC0,
+0x7DD7,0x7DD9,0x7DE6,0x7DF1,0x7DF9,0x4302,0x0000,0xFA58,
+0x7E10,0x7E17,0x7E1D,0x7E20,0x7E27,0x7E2C,0x7E45,0x7E73,
+0x7E75,0x7E7E,0x7E86,0x7E87,0x432B,0x7E91,0x7E98,0x7E9A,
+0x4343,0x7F3C,0x7F3B,0x7F3E,0x7F43,0x7F44,0x7F4F,0x34C1,
+0x0000,0x7F52,0x0000,0x7F61,0x7F63,0x7F64,0x7F6D,0x7F7D,
+0x7F7E,0x0000,0x7F90,0x517B,0x0000,0x7F96,0x7F9C,0x7FAD,
+0x0000,0x7FC3,0x7FCF,0x7FE3,0x7FE5,0x7FEF,
+/* plane 2 ku 85 */
+0x7FF2,0x8002,0x800A,0x8008,0x800E,0x8011,0x8016,0x8024,
+0x802C,0x8030,0x8043,0x8066,0x8071,0x8075,0x807B,0x8099,
+0x809C,0x80A4,0x80A7,0x80B8,0x0000,0x80C5,0x80D5,0x80D8,
+0x80E6,0x0000,0x810D,0x80F5,0x80FB,0x43EE,0x8135,0x8116,
+0x811E,0x43F0,0x8124,0x8127,0x812C,0x0000,0x813D,0x4408,
+0x8169,0x4417,0x8181,0x441C,0x8184,0x8185,0x4422,0x8198,
+0x81B2,0x81C1,0x81C3,0x81D6,0x81DB,0x0000,0x81E4,0x0000,
+0x81EC,0x0000,0x81FD,0x81FF,0x0000,0x8204,0x0000,0x8219,
+0x8221,0x8222,0x0000,0x8232,0x8234,0x823C,0x8246,0x8249,
+0x8245,0x0000,0x824B,0x4476,0x824F,0x447A,0x8257,0x0000,
+0x825C,0x8263,0x0000,0xFA5D,0xFA5E,0x8279,0x4491,0x827D,
+0x827F,0x8283,0x828A,0x8293,0x82A7,0x82A8,
+/* plane 2 ku 86 */
+0x82B2,0x82B4,0x82BA,0x82BC,0x82E2,0x82E8,0x82F7,0x8307,
+0x8308,0x830C,0x8354,0x831B,0x831D,0x8330,0x833C,0x8344,
+0x8357,0x44BE,0x837F,0x44D4,0x44B3,0x838D,0x8394,0x8395,
+0x839B,0x839D,0x83C9,0x83D0,0x83D4,0x83DD,0x83E5,0x83F9,
+0x840F,0x8411,0x8415,0x0000,0x8417,0x8439,0x844A,0x844F,
+0x8451,0x8452,0x8459,0x845A,0x845C,0x0000,0x8465,0x8476,
+0x8478,0x847C,0x8481,0x450D,0x84DC,0x8497,0x84A6,0x84BE,
+0x4508,0x84CE,0x84CF,0x84D3,0x0000,0x84E7,0x84EA,0x84EF,
+0x84F0,0x84F1,0x84FA,0x84FD,0x850C,0x851B,0x8524,0x8525,
+0x852B,0x8534,0x854F,0x856F,0x4525,0x4543,0x853E,0x8551,
+0x8553,0x855E,0x8561,0x8562,0x0000,0x857B,0x857D,0x857F,
+0x8581,0x8586,0x8593,0x859D,0x859F,0x0000,
+/* plane 2 ku 87 */
+0x0000,0x0000,0x85B7,0x85BC,0x85C7,0x85CA,0x85D8,0x85D9,
+0x85DF,0x85E1,0x85E6,0x85F6,0x8600,0x8611,0x861E,0x8621,
+0x8624,0x8627,0x0000,0x8639,0x863C,0x0000,0x8640,0xFA20,
+0x8653,0x8656,0x866F,0x8677,0x867A,0x8687,0x8689,0x868D,
+0x8691,0x869C,0x869D,0x86A8,0xFA21,0x86B1,0x86B3,0x86C1,
+0x86C3,0x86D1,0x86D5,0x86D7,0x86E3,0x86E6,0x45B8,0x8705,
+0x8707,0x870E,0x8710,0x8713,0x8719,0x871F,0x8721,0x8723,
+0x8731,0x873A,0x873E,0x8740,0x8743,0x8751,0x8758,0x8764,
+0x8765,0x8772,0x877C,0x0000,0x0000,0x87A7,0x8789,0x878B,
+0x8793,0x87A0,0x0000,0x45E5,0x87BE,0x0000,0x87C1,0x87CE,
+0x87F5,0x87DF,0x0000,0x87E3,0x87E5,0x87E6,0x87EA,0x87EB,
+0x87ED,0x8801,0x8803,0x880B,0x8813,0x8828,
+/* plane 2 ku 88 */
+0x882E,0x8832,0x883C,0x460F,0x884A,0x8858,0x885F,0x8864,
+0x0000,0x0000,0x8869,0x0000,0x886F,0x88A0,0x88BC,0x88BD,
+0x88BE,0x88C0,0x88D2,0x0000,0x88D1,0x88D3,0x88DB,0x88F0,
+0x88F1,0x4641,0x8901,0x0000,0x8937,0x0000,0x8942,0x8945,
+0x8949,0x0000,0x4665,0x8962,0x8980,0x8989,0x8990,0x899F,
+0x89B0,0x89B7,0x89D6,0x89D8,0x89EB,0x46A1,0x89F1,0x89F3,
+0x89FD,0x89FF,0x46AF,0x8A11,0x8A14,0x0000,0x8A21,0x8A35,
+0x8A3E,0x8A45,0x8A4D,0x8A58,0x8AAE,0x8A90,0x8AB7,0x8ABE,
+0x8AD7,0x8AFC,0x0000,0x8B0A,0x8B05,0x8B0D,0x8B1C,0x8B1F,
+0x8B2D,0x8B43,0x470C,0x8B51,0x8B5E,0x8B76,0x8B7F,0x8B81,
+0x8B8B,0x8B94,0x8B95,0x8B9C,0x8B9E,0x8C39,0x0000,0x8C3D,
+0x0000,0x0000,0x8C45,0x8C47,0x8C4F,0x8C54,
+/* plane 2 ku 89 */
+0x8C57,0x8C69,0x8C6D,0x8C73,0x0000,0x8C93,0x8C92,0x8C99,
+0x4764,0x8C9B,0x8CA4,0x8CD6,0x8CD5,0x8CD9,0x0000,0x8CF0,
+0x8CF1,0x0000,0x8D09,0x8D0E,0x8D6C,0x8D84,0x8D95,0x8DA6,
+0x0000,0x8DC6,0x8DC8,0x8DD9,0x8DEC,0x8E0C,0x47FD,0x8DFD,
+0x8E06,0x0000,0x8E14,0x8E16,0x8E21,0x8E22,0x8E27,0x0000,
+0x4816,0x8E36,0x8E39,0x8E4B,0x8E54,0x8E62,0x8E6C,0x8E6D,
+0x8E6F,0x8E98,0x8E9E,0x8EAE,0x8EB3,0x8EB5,0x8EB6,0x8EBB,
+0x0000,0x8ED1,0x8ED4,0x484E,0x8EF9,0x0000,0x8F00,0x8F08,
+0x8F17,0x8F2B,0x8F40,0x8F4A,0x8F58,0x0000,0x8FA4,0x8FB4,
+0xFA66,0x8FB6,0x0000,0x8FC1,0x8FC6,0xFA24,0x8FCA,0x8FCD,
+0x8FD3,0x8FD5,0x8FE0,0x8FF1,0x8FF5,0x8FFB,0x9002,0x900C,
+0x9037,0x0000,0x9043,0x9044,0x905D,0x0000,
+/* plane 2 ku 90 */
+0x0000,0x9085,0x908C,0x9090,0x961D,0x90A1,0x48B5,0x90B0,
+0x90B6,0x90C3,0x90C8,0x0000,0x90DC,0x90DF,0x0000,0x90F6,
+0x90F2,0x9100,0x90EB,0x90FE,0x90FF,0x9104,0x9106,0x9118,
+0x911C,0x911E,0x9137,0x9139,0x913A,0x9146,0x9147,0x9157,
+0x9159,0x9161,0x9164,0x9174,0x9179,0x9185,0x918E,0x91A8,
+0x91AE,0x91B3,0x91B6,0x91C3,0x91C4,0x91DA,0x0000,0x0000,
+0x91EC,0x91EE,0x9201,0x920A,0x9216,0x9217,0x0000,0x9233,
+0x9242,0x9247,0x924A,0x924E,0x9251,0x9256,0x9259,0x9260,
+0x9261,0x9265,0x9267,0x9268,0x0000,0x0000,0x927C,0x927D,
+0x927F,0x9289,0x928D,0x9297,0x9299,0x929F,0x92A7,0x92AB,
+0x0000,0x0000,0x92B2,0x92BF,0x92C0,0x92C6,0x92CE,0x92D0,
+0x92D7,0x92D9,0x92E5,0x92E7,0x9311,0x0000,
+/* plane 2 ku 91 */
+0x0000,0x92F7,0x92F9,0x92FB,0x9302,0x930D,0x9315,0x931D,
+0x931E,0x9327,0x9329,0x0000,0x0000,0x9347,0x9351,0x9357,
+0x935A,0x936B,0x9371,0x9373,0x93A1,0x0000,0x0000,0x9388,
+0x938B,0x938F,0x939E,0x93F5,0x0000,0x0000,0x93F1,0x93C1,
+0x93C7,0x93DC,0x93E2,0x93E7,0x9409,0x940F,0x9416,0x9417,
+0x93FB,0x9432,0x9434,0x943B,0x9445,0x0000,0x0000,0x946D,
+0x946F,0x9578,0x9579,0x9586,0x958C,0x958D,0x0000,0x95AB,
+0x95B4,0x0000,0x95C8,0x0000,0x0000,0x962C,0x9633,0x9634,
+0x0000,0x963C,0x9641,0x9661,0x0000,0x9682,0x0000,0x969A,
+0x0000,0x49E7,0x96A9,0x96AF,0x96B3,0x96BA,0x96BD,0x49FA,
+0x0000,0x96D8,0x96DA,0x96DD,0x4A04,0x9714,0x9723,0x4A29,
+0x9736,0x9741,0x9747,0x9755,0x9757,0x975B,
+/* plane 2 ku 92 */
+0x976A,0x0000,0x0000,0x9796,0x979A,0x979E,0x97A2,0x97B1,
+0x97B2,0x97BE,0x97CC,0x97D1,0x97D4,0x97D8,0x97D9,0x97E1,
+0x97F1,0x9804,0x980D,0x980E,0x9814,0x9816,0x4ABC,0x0000,
+0x9823,0x9832,0x9833,0x9825,0x9847,0x9866,0x98AB,0x98AD,
+0x98B0,0x0000,0x98B7,0x98B8,0x98BB,0x98BC,0x98BF,0x98C2,
+0x98C7,0x98CB,0x98E0,0x0000,0x98E1,0x98E3,0x98E5,0x98EA,
+0x98F0,0x98F1,0x98F3,0x9908,0x4B3B,0x0000,0x9916,0x9917,
+0x0000,0x991A,0x991B,0x991C,0x0000,0x9931,0x9932,0x9933,
+0x993A,0x993B,0x993C,0x9940,0x9941,0x9946,0x994D,0x994E,
+0x995C,0x995F,0x9960,0x99A3,0x99A6,0x99B9,0x99BD,0x99BF,
+0x99C3,0x99C9,0x99D4,0x99D9,0x99DE,0x0000,0x99F0,0x99F9,
+0x99FC,0x9A0A,0x9A11,0x9A16,0x9A1A,0x9A20,
+/* plane 2 ku 93 */
+0x9A31,0x9A36,0x9A44,0x9A4C,0x9A58,0x4BC2,0x9AAF,0x4BCA,
+0x9AB7,0x4BD2,0x9AB9,0x0000,0x9AC6,0x9AD0,0x9AD2,0x9AD5,
+0x4BE8,0x9ADC,0x9AE0,0x9AE5,0x9AE9,0x9B03,0x9B0C,0x9B10,
+0x9B12,0x9B16,0x9B1C,0x9B2B,0x9B33,0x9B3D,0x4C20,0x9B4B,
+0x9B63,0x9B65,0x9B6B,0x9B6C,0x9B73,0x9B76,0x9B77,0x9BA6,
+0x9BAC,0x9BB1,0x0000,0x0000,0x9BB2,0x9BB8,0x9BBE,0x9BC7,
+0x9BF3,0x9BD8,0x9BDD,0x9BE7,0x9BEA,0x9BEB,0x9BEF,0x9BEE,
+0x0000,0x9BFA,0x0000,0x9BF7,0x0000,0x9C16,0x9C18,0x9C19,
+0x9C1A,0x9C1D,0x9C22,0x9C27,0x9C29,0x9C2A,0x0000,0x9C31,
+0x9C36,0x9C37,0x9C45,0x9C5C,0x0000,0x9C49,0x9C4A,0x0000,
+0x9C54,0x9C58,0x9C5B,0x9C5D,0x9C5F,0x9C69,0x9C6A,0x9C6B,
+0x9C6D,0x9C6E,0x9C70,0x9C72,0x9C75,0x9C7A,
+/* plane 2 ku 94 */
+0x9CE6,0x9CF2,0x9D0B,0x9D02,0x0000,0x9D11,0x9D17,0x9D18,
+0x0000,0x4CC4,0x0000,0x9D32,0x4CD1,0x9D42,0x9D4A,0x9D5F,
+0x9D62,0x0000,0x9D69,0x9D6B,0x0000,0x9D73,0x9D76,0x9D77,
+0x9D7E,0x9D84,0x9D8D,0x9D99,0x9DA1,0x9DBF,0x9DB5,0x9DB9,
+0x9DBD,0x9DC3,0x9DC7,0x9DC9,0x9DD6,0x9DDA,0x9DDF,0x9DE0,
+0x9DE3,0x9DF4,0x4D07,0x9E0A,0x9E02,0x9E0D,0x9E19,0x9E1C,
+0x9E1D,0x9E7B,0x0000,0x9E80,0x9E85,0x9E9B,0x9EA8,0x0000,
+0x9EBD,0x0000,0x9EDF,0x9EE7,0x9EEE,0x9EFF,0x9F02,0x4D77,
+0x9F03,0x9F17,0x9F19,0x9F2F,0x9F37,0x9F3A,0x9F3D,0x9F41,
+0x9F45,0x9F46,0x9F53,0x9F55,0x9F58,0x0000,0x9F5D,0x0000,
+0x9F69,0x0000,0x9F6D,0x9F70,0x9F75,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,};
+
+static const int jisx0213_ucs_table_size = (sizeof(jisx0213_ucs_table)/sizeof(unsigned short));
+
+
+static const unsigned short ucs_a1_jisx0213_table[] = { // 0x0000 - 0x045f
+
+/* 0000h */
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2922,0x2923,0x2171,0x2172,0x2924,0x005C,0x2925,0x2178,
+0x212F,0x2926,0x2927,0x2928,0x224C,0x2929,0x292A,0x292B,
+0x216B,0x215E,0x292C,0x292D,0x212D,0x0000,0x2279,0x292E,
+0x292F,0x2930,0x2931,0x2932,0x2933,0x2934,0x2935,0x2936,
+0x2937,0x2938,0x2939,0x293A,0x293B,0x293C,0x293D,0x293E,
+0x293F,0x2940,0x2941,0x2942,0x2943,0x2944,0x2945,0x2946,
+0x2947,0x2948,0x2949,0x294A,0x294B,0x294C,0x294D,0x215F,
+0x294E,0x294F,0x2950,0x2951,0x2952,0x2953,0x2954,0x2955,
+0x2956,0x2957,0x2958,0x2959,0x295A,0x295B,0x295C,0x295D,
+0x295E,0x295F,0x2960,0x2961,0x2962,0x2963,0x2964,0x2965,
+0x2966,0x2967,0x2968,0x2969,0x296A,0x296B,0x296C,0x2160,
+0x296D,0x296E,0x296F,0x2970,0x2971,0x2972,0x2973,0x2974,
+
+/* 0100h */
+0x2975,0x297A,0x2A3A,0x2A49,0x2A21,0x2A2C,0x2A3C,0x2A4B,
+0x2A59,0x2A5F,0x0000,0x0000,0x2A3D,0x2A4C,0x2A40,0x2A4F,
+0x0000,0x2A50,0x2978,0x297D,0x0000,0x0000,0x0000,0x0000,
+0x2A3E,0x2A4D,0x2A3F,0x2A4E,0x2A5A,0x2A60,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x2A5B,0x2A61,0x0000,0x2A7D,
+0x0000,0x0000,0x2976,0x297B,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x2A5C,0x2A62,0x0000,0x0000,
+0x0000,0x2A3B,0x2A4A,0x0000,0x0000,0x2A24,0x2A2F,0x0000,
+0x0000,0x2A23,0x2A2E,0x2A41,0x2A51,0x0000,0x0000,0x2A42,
+0x2A52,0x0000,0x0000,0x2A7A,0x2979,0x297E,0x0000,0x0000,
+0x2A43,0x2A53,0x2B2B,0x2B2A,0x2A39,0x2A48,0x0000,0x0000,
+0x2A44,0x2A54,0x2A25,0x2A30,0x2A5D,0x2A63,0x2A27,0x2A33,
+0x2A26,0x2A32,0x2A47,0x2A57,0x2A28,0x2A34,0x0000,0x0000,
+0x0000,0x0000,0x2977,0x297C,0x2A5E,0x2A64,0x2A45,0x2A55,
+0x2A46,0x2A56,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x2A29,0x2A35,0x2A2B,0x2A38,0x2A2A,0x2A37,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2B29,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x2B24,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x286F,0x2870,0x0000,
+0x2871,0x2876,0x2877,0x0000,0x2878,0x0000,0x2879,0x0000,
+0x287A,0x0000,0x287B,0x0000,0x287C,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2874,0x2875,0x0000,0x0000,0x0000,0x2B45,0x0000,0x0000,
+
+/* 0200h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2B33,0x2B39,0x2B3A,0x2B25,0x2B38,0x2B3F,0x2A6E,0x2B26,
+0x2B2E,0x2B30,0x2B43,0x0000,0x2B31,0x0000,0x2B32,0x2A75,
+0x2B28,0x2A79,0x0000,0x0000,0x2B36,0x2B3C,0x2B22,0x2B42,
+0x2B2C,0x0000,0x0000,0x0000,0x2A6A,0x2A74,0x2A6B,0x2B34,
+0x2A7B,0x2A65,0x2A76,0x2A6F,0x0000,0x2B2F,0x0000,0x0000,
+0x0000,0x2A6C,0x2B41,0x2A73,0x0000,0x2A70,0x2A67,0x0000,
+0x0000,0x2A7C,0x2A71,0x2A68,0x2B27,0x0000,0x0000,0x0000,
+0x2A6D,0x2B2D,0x2B35,0x2A66,0x2B37,0x2B3B,0x2A78,0x0000,
+0x2A72,0x2B40,0x2A69,0x0000,0x2B21,0x2A7E,0x0000,0x0000,
+0x2B23,0x0000,0x0000,0x0000,0x0000,0x2A77,0x0000,0x0000,
+0x0000,0x2B3E,0x2B3D,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2A31,
+0x2B53,0x0000,0x0000,0x0000,0x2B54,0x0000,0x0000,0x0000,
+0x2B55,0x2B56,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2A22,0x2A58,0x0000,0x2A2D,0x0000,0x2A36,0x2B71,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x2B60,0x2B61,0x2B62,
+0x2B63,0x2B64,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 0300h */
+0x2B5C,0x2B5A,0x2B5F,0x2B7D,0x2B5B,0x0000,0x2B57,0x0000,
+0x2B6D,0x0000,0x0000,0x2B59,0x2B5E,0x0000,0x0000,0x2B5D,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2B78,0x2B79,0x2B7E,0x0000,0x2B6A,0x2B76,0x2B77,0x2B6B,
+0x2B6C,0x0000,0x0000,0x0000,0x2B72,0x2B67,0x0000,0x0000,
+0x0000,0x2B6F,0x2B7A,0x0000,0x2B68,0x0000,0x0000,0x2B70,
+0x2B73,0x0000,0x0000,0x0000,0x2B75,0x0000,0x0000,0x0000,
+0x0000,0x2B69,0x2B7B,0x2B7C,0x2B74,0x2B6E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x2B52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,
+0x2628,0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F,
+0x2630,0x2631,0x0000,0x2632,0x2633,0x2634,0x2635,0x2636,
+0x2637,0x2638,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x2641,0x2642,0x2643,0x2644,0x2645,0x2646,0x2647,
+0x2648,0x2649,0x264A,0x264B,0x264C,0x264D,0x264E,0x264F,
+0x2650,0x2651,0x2659,0x2652,0x2653,0x2654,0x2655,0x2656,
+0x2657,0x2658,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 0400h */
+0x0000,0x2727,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2721,0x2722,0x2723,0x2724,0x2725,0x2726,0x2728,0x2729,
+0x272A,0x272B,0x272C,0x272D,0x272E,0x272F,0x2730,0x2731,
+0x2732,0x2733,0x2734,0x2735,0x2736,0x2737,0x2738,0x2739,
+0x273A,0x273B,0x273C,0x273D,0x273E,0x273F,0x2740,0x2741,
+0x2751,0x2752,0x2753,0x2754,0x2755,0x2756,0x2758,0x2759,
+0x275A,0x275B,0x275C,0x275D,0x275E,0x275F,0x2760,0x2761,
+0x2762,0x2763,0x2764,0x2765,0x2766,0x2767,0x2768,0x2769,
+0x276A,0x276B,0x276C,0x276D,0x276E,0x276F,0x2770,0x2771,
+0x0000,0x2757,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+};
+
+static const int ucs_a1_jisx0213_table_min = 0x0000;
+static const int ucs_a1_jisx0213_table_max = 0x0000 +
+ (sizeof(ucs_a1_jisx0213_table)/sizeof(unsigned short));
+
+static const unsigned short ucs_hk_jisx0213_table[] = { // 0x3000 - 0x30ff
+/* 3000h */
+0x2121,0x2122,0x2123,0x2137,0x0000,0x2139,0x213A,0x213B,
+0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,
+0x215A,0x215B,0x2229,0x222E,0x214C,0x214D,0x225A,0x225B,
+0x2258,0x2259,0x0000,0x0000,0x2141,0x2D60,0x0000,0x2D61,
+0x2666,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2233,0x2234,0x2235,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2236,0x2237,0x233C,0x0000,0x0000,
+0x0000,0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,
+0x2428,0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,
+0x2430,0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,
+0x2438,0x2439,0x243A,0x243B,0x243C,0x243D,0x243E,0x243F,
+0x2440,0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447,
+0x2448,0x2449,0x244A,0x244B,0x244C,0x244D,0x244E,0x244F,
+0x2450,0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457,
+0x2458,0x2459,0x245A,0x245B,0x245C,0x245D,0x245E,0x245F,
+0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,
+0x2468,0x2469,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,
+0x2470,0x2471,0x2472,0x2473,0x2474,0x2475,0x2476,0x0000,
+0x0000,0x0000,0x0000,0x212B,0x212C,0x2135,0x2136,0x2239,
+0x237B,0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527,
+0x2528,0x2529,0x252A,0x252B,0x252C,0x252D,0x252E,0x252F,
+0x2530,0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537,
+0x2538,0x2539,0x253A,0x253B,0x253C,0x253D,0x253E,0x253F,
+0x2540,0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547,
+0x2548,0x2549,0x254A,0x254B,0x254C,0x254D,0x254E,0x254F,
+0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,
+0x2558,0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,0x255F,
+0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,
+0x2568,0x2569,0x256A,0x256B,0x256C,0x256D,0x256E,0x256F,
+0x2570,0x2571,0x2572,0x2573,0x2574,0x2575,0x2576,0x2772,
+0x2773,0x2774,0x2775,0x2126,0x213C,0x2133,0x2134,0x2238,
+};
+
+static const int ucs_hk_jisx0213_min = 0x3000;
+static const int ucs_hk_jisx0213_max = 0x30FF;
+
+static const unsigned short ucs_i_jisx0213_table[] = { // 0x4e00 - 0x9fff
+
+/* 4E00h */
+0x306C,0x437A,0x7F22,0x3C37,0x0000,0x0000,0x0000,0x4B7C,
+0x3E66,0x3B30,0x3E65,0x323C,0x0000,0x4954,0x4D3F,0x7F23,
+0x5022,0x312F,0x7F24,0x0000,0x336E,0x5023,0x4024,0x5242,
+0x3556,0x4A3A,0x0000,0x0000,0x0000,0x0000,0x3E67,0x0000,
+0x0000,0x4E3E,0x0000,0x0000,0x0000,0x0000,0x4A42,0x0000,
+0x2E24,0x7F25,0x5024,0x7F26,0x8A2E,0x4366,0x7F27,0x2E25,
+0x2E26,0x5025,0x367A,0x0000,0x0000,0x0000,0x5026,0x0000,
+0x345D,0x4330,0x0000,0x3C67,0x5027,0x0000,0x0000,0x5028,
+0x7F28,0x0000,0x5029,0x4735,0x0000,0x3557,0x0000,0x7F29,
+0x7F2A,0x0000,0x0000,0x4737,0x0000,0x4663,0x3843,0x4B33,
+0x0000,0x7F2C,0x0000,0x0000,0x0000,0x6949,0x502A,0x3E68,
+0x502B,0x3235,0x7F2F,0x0000,0x0000,0x3665,0x3870,0x4C69,
+0x0000,0x0000,0x5626,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x7F30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4D70,0x0000,0x467D,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3425,0x0000,
+0x3535,0x0000,0x502C,0x0000,0x0000,0x502D,0x4E3B,0x0000,
+0x4D3D,0x4168,0x502F,0x3B76,0x4673,0x2E27,0x5032,0x0000,
+0x0000,0x313E,0x385F,0x0000,0x385E,0x3066,0x0000,0x0000,
+0x4F4B,0x4F4A,0x0000,0x3A33,0x3021,0x7F31,0x5033,0x5034,
+0x5035,0x4B34,0x5036,0x0000,0x3872,0x3067,0x4B72,0x0000,
+0x357C,0x0000,0x0000,0x357D,0x357E,0x4462,0x4E3C,0x0000,
+0x5037,0x0000,0x0000,0x5038,0x0000,0x0000,0x5039,0x0000,
+0x0000,0x7F34,0x3F4D,0x7F35,0x7F37,0x0000,0x0000,0x0000,
+0x3D3A,0x3F4E,0x503E,0x7F38,0x503C,0x0000,0x503D,0x3558,
+0x7F39,0x0000,0x3A23,0x3270,0x0000,0x503B,0x503A,0x4A29,
+0x7F3A,0x0000,0x0000,0x0000,0x3B46,0x3B45,0x423E,0x503F,
+0x4955,0x4067,0x7F3C,0x0000,0x0000,0x2138,0x5040,0x5042,
+0x0000,0x2E28,0x0000,0x4265,0x4E61,0x304A,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7F3B,0x0000,0x5041,0x323E,0x0000,
+0x3644,0x7F3D,0x4367,0x0000,0x0000,0x7F3E,0x376F,0x5043,
+0x0000,0x0000,0x0000,0x4724,0x0000,0x2E29,0x0000,0x2E2A,
+
+/* 4F00h */
+0x7F3F,0x346B,0x0000,0x2E2B,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x5044,0x304B,0x2E2C,0x0000,0x3860,0x346C,0x497A,
+0x4832,0x3559,0x0000,0x0000,0x0000,0x0000,0x7F40,0x0000,
+0x0000,0x0000,0x3271,0x0000,0x5067,0x4541,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x476C,
+0x5046,0x0000,0x0000,0x0000,0x483C,0x0000,0x4E62,0x7F42,
+0x3F2D,0x0000,0x3B47,0x0000,0x3B77,0x3240,0x7F43,0x0000,
+0x0000,0x0000,0x0000,0x4451,0x0000,0x0000,0x4322,0x504A,
+0x2E2E,0x2E2F,0x0000,0x0000,0x0000,0x304C,0x4463,0x3D3B,
+0x3A34,0x4D24,0x0000,0x424E,0x7F44,0x323F,0x2E30,0x5049,
+0x7F45,0x4D3E,0x5045,0x5047,0x3A6E,0x5048,0x5524,0x2E31,
+0x2E2D,0x0000,0x0000,0x0000,0x7F41,0x0000,0x0000,0x0000,
+0x0000,0x5050,0x2E32,0x0000,0x2E33,0x0000,0x0000,0x5053,
+0x5051,0x0000,0x0000,0x3242,0x0000,0x4A3B,0x504B,0x7F47,
+0x7F48,0x0000,0x7F49,0x504F,0x3873,0x7F4A,0x2E34,0x3B48,
+0x0000,0x0000,0x7F4B,0x3426,0x0000,0x7F4C,0x5054,0x0000,
+0x504C,0x0000,0x2E35,0x4E63,0x0000,0x3B78,0x0000,0x504D,
+0x0000,0x5052,0x7F4D,0x0000,0x2E36,0x0000,0x5055,0x2E37,
+0x504E,0x0000,0x7F4E,0x3621,0x0000,0x304D,0x0000,0x0000,
+0x3622,0x3241,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x5525,0x0000,0x4B79,0x496E,0x3874,
+0x0000,0x0000,0x7F50,0x0000,0x0000,0x3F2F,0x4E37,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7F51,0x4A58,
+0x0000,0x0000,0x3738,0x4225,0x3264,0x7F52,0x0000,0x0000,
+0x0000,0x2E39,0x3D53,0x7F53,0x0000,0x0000,0x5059,0x7F54,
+0x505E,0x505C,0x7F55,0x0000,0x5057,0x0000,0x0000,0x422F,
+0x505A,0x0000,0x505D,0x505B,0x0000,0x4A5D,0x0000,0x5058,
+0x2E3A,0x3F2E,0x0000,0x4B73,0x505F,0x5060,0x7F4F,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3D24,0x506D,
+0x0000,0x2E21,0x7F57,0x4750,0x0000,0x4936,0x5068,0x0000,
+0x4A70,0x0000,0x3236,0x0000,0x0000,0x0000,0x506C,0x0000,
+
+/* 5000h */
+0x7F58,0x2E3B,0x2E3C,0x0000,0x0000,0x5066,0x506F,0x0000,
+0x0000,0x4152,0x0000,0x3844,0x0000,0x475C,0x2E3D,0x6047,
+0x7F59,0x506E,0x455D,0x7F5A,0x5063,0x0000,0x3876,0x0000,
+0x2E3E,0x3875,0x5061,0x0000,0x7F5B,0x0000,0x7F5C,0x3C5A,
+0x0000,0x5069,0x7F5D,0x4A6F,0x434D,0x5065,0x3771,0x2E3F,
+0x5062,0x506A,0x5064,0x4E51,0x506B,0x4F41,0x2E40,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3666,0x0000,
+0x0000,0x3770,0x0000,0x2E42,0x0000,0x0000,0x0000,0x0000,
+0x2E41,0x2E43,0x7F5F,0x5070,0x0000,0x0000,0x7F60,0x5071,
+0x5075,0x304E,0x0000,0x0000,0x0000,0x0000,0x7F61,0x4A50,
+0x5074,0x0000,0x0000,0x7F62,0x0000,0x5073,0x5077,0x7F63,
+0x0000,0x0000,0x5076,0x0000,0x4464,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7F64,0x0000,0x3772,0x7F65,0x0000,
+0x0000,0x0000,0x7F66,0x0000,0x5078,0x0000,0x0000,0x0000,
+0x7F67,0x0000,0x3C45,0x0000,0x4226,0x4465,0x3676,0x0000,
+0x5079,0x0000,0x0000,0x0000,0x0000,0x3536,0x0000,0x0000,
+0x507A,0x0000,0x0000,0x0000,0x0000,0x507C,0x0000,0x0000,
+0x7F69,0x0000,0x0000,0x0000,0x0000,0x4B35,0x0000,0x0000,
+0x0000,0x3766,0x7F6A,0x7F6B,0x2E44,0x7F6C,0x7F6D,0x0000,
+0x3B31,0x4877,0x507B,0x0000,0x7F6E,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7F68,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7F6F,0x0000,0x3A45,0x4D43,0x0000,0x0000,
+0x0000,0x7F71,0x507E,0x5123,0x507D,0x3A44,0x0000,0x3D7D,
+0x0000,0x0000,0x7F72,0x7F73,0x0000,0x0000,0x3739,0x0000,
+0x0000,0x0000,0x5124,0x0000,0x7F74,0x364F,0x0000,0x7F75,
+0x0000,0x5121,0x5122,0x0000,0x2E45,0x462F,0x7F78,0x417C,
+0x2E47,0x3623,0x0000,0x0000,0x7F7A,0x4B4D,0x5125,0x0000,
+0x0000,0x7F7B,0x4E3D,0x0000,0x0000,0x0000,0x5126,0x0000,
+0x0000,0x7F7C,0x0000,0x5129,0x0000,0x5127,0x2E48,0x414E,
+0x0000,0x7F7D,0x0000,0x0000,0x0000,0x5128,0x512A,0x0000,
+0x0000,0x0000,0x2E46,0x7F76,0x0000,0x512C,0x0000,0x0000,
+0x0000,0x512B,0x0000,0x4A48,0x0000,0x0000,0x0000,0x0000,
+
+/* 5100h */
+0x3537,0x512E,0x512F,0x2E4B,0x322F,0x0000,0x2E4A,0x0000,
+0x8121,0x512D,0x0000,0x2E4C,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x3C74,0x0000,0x5132,0x5131,0x5130,0x8123,
+0x5056,0x0000,0x5133,0x8124,0x0000,0x0000,0x2E4D,0x3D7E,
+0x0000,0x5134,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4D25,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4C59,0x0000,0x0000,0x2E4E,0x0000,0x5136,
+0x0000,0x0000,0x5135,0x5138,0x5137,0x0000,0x0000,0x5139,
+0x513A,0x3074,0x0000,0x3835,0x373B,0x3D3C,0x437B,0x3624,
+0x4068,0x3877,0x2E4F,0x396E,0x513C,0x4C48,0x4546,0x0000,
+0x3B79,0x0000,0x513B,0x0000,0x513D,0x2E51,0x0000,0x2E52,
+0x0000,0x0000,0x455E,0x0000,0x3375,0x0000,0x0000,0x0000,
+0x8126,0x0000,0x513E,0x0000,0x0000,0x467E,0x0000,0x0000,
+0x4134,0x5140,0x5141,0x482C,0x3878,0x4F3B,0x5142,0x0000,
+0x0000,0x3626,0x0000,0x8128,0x0000,0x4A3C,0x4236,0x3671,
+0x4535,0x0000,0x0000,0x8E74,0x3773,0x0000,0x0000,0x0000,
+0x5143,0x0000,0x5144,0x8129,0x0000,0x4662,0x315F,0x0000,
+0x0000,0x5147,0x3A7D,0x812A,0x5146,0x3A46,0x0000,0x5148,
+0x666E,0x5149,0x4B41,0x514A,0x0000,0x514B,0x514C,0x3E69,
+0x812C,0x3C4C,0x0000,0x0000,0x0000,0x2E54,0x0000,0x0000,
+0x3427,0x0000,0x514F,0x812D,0x514D,0x4C3D,0x514E,0x0000,
+0x495A,0x5150,0x5151,0x5152,0x455F,0x812E,0x0000,0x0000,
+0x5156,0x5154,0x5155,0x5153,0x3A63,0x5157,0x4C6A,0x4E64,
+0x0000,0x0000,0x0000,0x0000,0x8130,0x5158,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2E55,0x4028,0x5159,0x3D5A,0x0000,
+0x0000,0x515A,0x2E56,0x437C,0x4E3F,0x4560,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5245,0x0000,
+0x0000,0x0000,0x0000,0x515B,0x7425,0x3645,0x2E57,0x0000,
+0x515C,0x4B5E,0x2E58,0x0000,0x0000,0x0000,0x3D68,0x427C,
+0x0000,0x515E,0x4664,0x0000,0x0000,0x515F,0x2E59,0x0000,
+0x5160,0x332E,0x0000,0x8133,0x8134,0x5161,0x3627,0x0000,
+0x464C,0x317A,0x3D50,0x0000,0x0000,0x4821,0x5162,0x0000,
+
+/* 5200h */
+0x4561,0x2E5A,0x8135,0x3F4F,0x5163,0x0000,0x4A2C,0x405A,
+0x3422,0x0000,0x3429,0x5164,0x0000,0x0000,0x5166,0x0000,
+0x0000,0x373A,0x8136,0x2E5C,0x5165,0x2E5D,0x8137,0x4E73,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x3D69,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x483D,0x4A4C,0x0000,0x5167,
+0x0000,0x4D78,0x5168,0x0000,0x0000,0x0000,0x5169,0x0000,
+0x457E,0x0000,0x0000,0x516A,0x0000,0x0000,0x4029,0x3A7E,
+0x3774,0x516B,0x3B49,0x396F,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x4466,0x516D,0x0000,0x0000,0x4227,
+0x0000,0x2E5E,0x3A6F,0x516E,0x516F,0x4130,0x0000,0x516C,
+0x0000,0x0000,0x0000,0x0000,0x5171,0x8139,0x4B36,0x2E5F,
+0x0000,0x0000,0x0000,0x3964,0x813A,0x2F7E,0x5170,0x0000,
+0x0000,0x2E60,0x0000,0x3775,0x3A5E,0x476D,0x0000,0x0000,
+0x0000,0x5174,0x5172,0x0000,0x813B,0x0000,0x0000,0x497B,
+0x3E6A,0x517B,0x3364,0x5175,0x5173,0x414F,0x0000,0x813C,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x5177,0x0000,0x5176,
+0x0000,0x0000,0x813E,0x3344,0x813D,0x0000,0x0000,0x3760,
+0x517C,0x4E2D,0x0000,0x0000,0x0000,0x5178,0x0000,0x0000,
+0x0000,0x517D,0x517A,0x2E61,0x5179,0x0000,0x0000,0x0000,
+0x8140,0x0000,0x0000,0x4E4F,0x0000,0x0000,0x0000,0x3879,
+0x3243,0x0000,0x0000,0x4E74,0x8142,0x0000,0x8143,0x0000,
+0x0000,0x3D75,0x4558,0x3965,0x5222,0x5223,0x0000,0x8144,
+0x0000,0x4E65,0x0000,0x0000,0x4F2B,0x5225,0x0000,0x0000,
+0x0000,0x387A,0x8145,0x8146,0x5224,0x0000,0x332F,0x0000,
+0x0000,0x5226,0x0000,0x4B56,0x0000,0x443C,0x0000,0x4D26,
+0x2E62,0x4A59,0x8147,0x0000,0x2E64,0x5227,0x0000,0x0000,
+0x2E65,0x8149,0x7055,0x0000,0x0000,0x4630,0x2E66,0x5228,
+0x342A,0x4C33,0x0000,0x2E67,0x0000,0x3E21,0x5229,0x4A67,
+0x522D,0x0000,0x402A,0x522A,0x3650,0x0000,0x522B,0x342B,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2E69,0x0000,0x372E,0x522E,0x0000,0x522F,0x0000,0x814B,
+0x5230,0x5231,0x3C5B,0x2E6A,0x0000,0x0000,0x387B,0x4C5E,
+
+/* 5300h */
+0x2E6B,0x4C68,0x4677,0x0000,0x0000,0x4A71,0x5232,0x2E6C,
+0x5233,0x0000,0x814C,0x814D,0x0000,0x5235,0x0000,0x5237,
+0x5236,0x0000,0x0000,0x0000,0x0000,0x5238,0x323D,0x4B4C,
+0x0000,0x3A7C,0x5239,0x0000,0x2E6D,0x4159,0x0000,0x0000,
+0x3E22,0x3629,0x0000,0x523A,0x814E,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x485B,0x0000,0x0000,0x0000,0x0000,0x523B,
+0x0000,0x523C,0x0000,0x523D,0x0000,0x814F,0x0000,0x0000,
+0x523E,0x4924,0x3668,0x3065,0x0000,0x0000,0x8150,0x463F,
+0x523F,0x3D3D,0x8151,0x4069,0x0000,0x5241,0x5240,0x3E23,
+0x3861,0x5243,0x483E,0x0000,0x0000,0x5244,0x0000,0x0000,
+0x0000,0x485C,0x4234,0x426E,0x3628,0x0000,0x0000,0x466E,
+0x4331,0x0000,0x476E,0x0000,0x4B4E,0x0000,0x5246,0x0000,
+0x406A,0x2E6F,0x0000,0x2E70,0x0000,0x0000,0x3735,0x8154,
+0x0000,0x5247,0x0000,0x0000,0x8155,0x0000,0x5248,0x312C,
+0x3075,0x346D,0x0000,0x4228,0x3551,0x4D71,0x0000,0x524B,
+0x3237,0x0000,0x8156,0x524A,0x0000,0x2E71,0x0000,0x362A,
+0x0000,0x0000,0x524C,0x0000,0x4C71,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2E72,0x0000,0x0000,0x524D,0x0000,
+0x4E52,0x0000,0x387C,0x0000,0x0000,0x2E73,0x0000,0x3836,
+0x524E,0x0000,0x0000,0x0000,0x8157,0x5250,0x524F,0x0000,
+0x3F5F,0x3139,0x0000,0x0000,0x0000,0x315E,0x5251,0x0000,
+0x5252,0x0000,0x2E74,0x3837,0x8158,0x0000,0x5253,0x815A,
+0x0000,0x0000,0x0000,0x356E,0x0000,0x0000,0x0000,0x0000,
+0x815B,0x0000,0x3B32,0x5254,0x0000,0x0000,0x0000,0x0000,
+0x4B74,0x3A35,0x355A,0x4D27,0x4150,0x483F,0x3C7D,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x3D47,0x815F,0x3C68,0x3C75,
+0x0000,0x3D76,0x8160,0x4840,0x0000,0x0000,0x0000,0x5257,
+0x0000,0x3143,0x4151,0x387D,0x3845,0x3667,0x0000,0x0000,
+0x525B,0x4321,0x427E,0x362B,0x3E24,0x525C,0x525A,0x3244,
+0x4266,0x3C38,0x3B4B,0x3126,0x8162,0x8163,0x3370,0x3966,
+0x3B4A,0x0000,0x525D,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 5400h */
+0x0000,0x525E,0x0000,0x3549,0x3346,0x0000,0x0000,0x0000,
+0x3967,0x3548,0x445F,0x3125,0x4631,0x4C3E,0x3921,0x4D79,
+0x4547,0x387E,0x2E75,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x372F,0x0000,0x5267,0x4F7E,0x3663,
+0x4B4A,0x0000,0x0000,0x0000,0x8165,0x0000,0x485D,0x2E76,
+0x8166,0x5266,0x0000,0x345E,0x5261,0x5262,0x5264,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5265,0x0000,
+0x355B,0x3F61,0x0000,0x4A2D,0x5263,0x525F,0x3863,0x0000,
+0x5260,0x0000,0x4F24,0x8168,0x0000,0x0000,0x4A72,0x0000,
+0x4468,0x3862,0x3970,0x0000,0x0000,0x2E77,0x5268,0x0000,
+0x0000,0x465D,0x0000,0x0000,0x0000,0x8164,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x526C,
+0x0000,0x0000,0x8169,0x0000,0x0000,0x0000,0x816A,0x0000,
+0x3C7E,0x0000,0x3C76,0x2E79,0x816B,0x0000,0x0000,0x0000,
+0x526F,0x526D,0x0000,0x4C23,0x2E7A,0x526A,0x5273,0x526E,
+0x0000,0x0000,0x0000,0x5271,0x3846,0x4C3F,0x0000,0x2E7B,
+0x5272,0x0000,0x0000,0x0000,0x5274,0x0000,0x5276,0x0000,
+0x2E7C,0x0000,0x816C,0x3A70,0x4F42,0x816D,0x526B,0x5269,
+0x5275,0x0000,0x5270,0x0000,0x0000,0x816E,0x2E7D,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x2E78,0x0000,0x0000,0x0000,
+0x816F,0x2E7E,0x5278,0x0000,0x5323,0x527A,0x8170,0x0000,
+0x527E,0x2F21,0x0000,0x5321,0x527B,0x8171,0x8172,0x533E,
+0x0000,0x0000,0x3A69,0x3331,0x0000,0x0000,0x0000,0x8173,
+0x5279,0x0000,0x8174,0x0000,0x5325,0x3076,0x5324,0x8175,
+0x3025,0x494A,0x5322,0x8176,0x527C,0x0000,0x2F22,0x5277,
+0x527D,0x3A48,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5326,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3077,0x532F,0x0000,0x0000,0x5327,0x5328,0x0000,
+0x3E25,0x4B69,0x0000,0x0000,0x8178,0x532D,0x532C,0x8179,
+0x0000,0x817A,0x452F,0x817B,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x532E,0x0000,0x0000,0x532B,0x0000,0x2F23,
+
+/* 5500h */
+0x817C,0x817D,0x0000,0x0000,0x3134,0x0000,0x3A36,0x3F30,
+0x0000,0x817E,0x0000,0x0000,0x0000,0x0000,0x2F24,0x5329,
+0x4562,0x0000,0x0000,0x0000,0x532A,0x0000,0x3022,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2F25,0x0000,0x0000,0x5334,0x4D23,
+0x0000,0x3E27,0x0000,0x533A,0x0000,0x2F26,0x0000,0x0000,
+0x5339,0x5330,0x0000,0x0000,0x8221,0x0000,0x4243,0x0000,
+0x5331,0x8222,0x0000,0x0000,0x426F,0x5336,0x3E26,0x8224,
+0x0000,0x0000,0x8225,0x0000,0x5333,0x0000,0x0000,0x4C64,
+0x2F27,0x0000,0x0000,0x373C,0x0000,0x0000,0x5337,0x5338,
+0x0000,0x0000,0x0000,0x0000,0x5335,0x533B,0x2F28,0x0000,
+0x8227,0x8228,0x0000,0x5332,0x8229,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x5341,0x5346,0x822B,0x5342,0x0000,
+0x533D,0x2F29,0x822C,0x5347,0x4131,0x0000,0x2F2A,0x5349,
+0x822D,0x3922,0x533F,0x437D,0x0000,0x0000,0x2F2B,0x0000,
+0x0000,0x822E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5343,0x533C,0x342D,0x0000,0x346E,0x3365,0x5344,0x5340,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3776,
+0x534A,0x5348,0x4153,0x354A,0x362C,0x2F2D,0x5345,0x0000,
+0x3674,0x0000,0x0000,0x0000,0x0000,0x0000,0x3144,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8233,
+0x0000,0x0000,0x0000,0x0000,0x534E,0x534C,0x0000,0x5427,
+0x0000,0x8234,0x0000,0x0000,0x8235,0x0000,0x2F2E,0x0000,
+0x0000,0x8236,0x8230,0x0000,0x5351,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x534B,0x0000,0x534F,0x8237,0x0000,0x534D,
+0x0000,0x0000,0x8239,0x3B4C,0x5350,0x0000,0x0000,0x0000,
+0x0000,0x823B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5353,
+0x0000,0x5358,0x0000,0x0000,0x0000,0x5356,0x5355,0x0000,
+
+/* 5600h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4332,0x823E,
+0x2F30,0x3245,0x0000,0x0000,0x0000,0x0000,0x2F31,0x0000,
+0x823F,0x0000,0x0000,0x0000,0x5352,0x0000,0x5354,0x3E28,
+0x3133,0x0000,0x0000,0x5357,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x823C,0x325E,0x0000,0x0000,0x0000,0x0000,0x0000,0x5362,
+0x8240,0x3E7C,0x535E,0x0000,0x535C,0x0000,0x535D,0x8241,
+0x535F,0x0000,0x0000,0x2F32,0x0000,0x8243,0x0000,0x8244,
+0x8245,0x0000,0x313D,0x0000,0x0000,0x0000,0x0000,0x8246,
+0x0000,0x2F33,0x0000,0x0000,0x4139,0x0000,0x5359,0x0000,
+0x535A,0x0000,0x0000,0x7427,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x337A,0x0000,0x0000,0x8247,0x0000,
+0x8248,0x0000,0x0000,0x0000,0x5361,0x0000,0x2F35,0x0000,
+0x346F,0x0000,0x5364,0x5360,0x5363,0x8249,0x0000,0x2F37,
+0x0000,0x2F38,0x2F39,0x0000,0x4A2E,0x0000,0x2F34,0x0000,
+0x4655,0x0000,0x4838,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5366,0x0000,0x0000,0x0000,0x0000,0x0000,0x5365,0x3345,
+0x824B,0x0000,0x5367,0x0000,0x824C,0x0000,0x0000,0x536A,
+0x0000,0x0000,0x0000,0x0000,0x5369,0x824D,0x0000,0x0000,
+0x0000,0x2F3A,0x824E,0x0000,0x0000,0x824F,0x2F3B,0x0000,
+0x5368,0x0000,0x4739,0x0000,0x0000,0x536B,0x0000,0x0000,
+0x8250,0x2F3C,0x0000,0x0000,0x2F3D,0x8251,0x536C,0x0000,
+0x0000,0x0000,0x8252,0x2F3E,0x536E,0x0000,0x536D,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x5370,0x0000,0x0000,0x0000,
+0x5373,0x5371,0x536F,0x5372,0x0000,0x8253,0x0000,0x0000,
+0x5374,0x2F3F,0x2F40,0x0000,0x0000,0x8254,0x5375,0x0000,
+0x0000,0x5376,0x0000,0x5377,0x0000,0x0000,0x0000,0x5378,
+0x5145,0x0000,0x3C7C,0x3B4D,0x0000,0x0000,0x3273,0x8255,
+0x3078,0x0000,0x0000,0x4344,0x0000,0x0000,0x0000,0x0000,
+0x8256,0x0000,0x0000,0x0000,0x0000,0x0000,0x5379,0x0000,
+0x3A24,0x0000,0x304F,0x3F5E,0x0000,0x0000,0x8257,0x8258,
+0x0000,0x537A,0x3847,0x0000,0x0000,0x3971,0x0000,0x537C,
+
+/* 5700h */
+0x537B,0x0000,0x0000,0x4A60,0x537D,0x0000,0x0000,0x0000,
+0x5421,0x537E,0x2F41,0x5422,0x0000,0x5423,0x0000,0x3777,
+0x0000,0x0000,0x3160,0x5424,0x0000,0x825A,0x5426,0x0000,
+0x5425,0x0000,0x0000,0x0000,0x5428,0x0000,0x0000,0x455A,
+0x0000,0x2F43,0x0000,0x825B,0x0000,0x0000,0x5429,0x3035,
+0x3A5F,0x825D,0x0000,0x0000,0x0000,0x373D,0x0000,0x2F44,
+0x434F,0x0000,0x0000,0x2F45,0x2F46,0x0000,0x0000,0x542A,
+0x542B,0x0000,0x0000,0x542D,0x0000,0x0000,0x0000,0x0000,
+0x542E,0x0000,0x3A64,0x0000,0x0000,0x825F,0x8260,0x3651,
+0x0000,0x0000,0x4B37,0x0000,0x8261,0x8262,0x542C,0x542F,
+0x3A41,0x3923,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x5433,0x0000,0x0000,0x3A25,0x0000,0x4333,0x0000,
+0x8264,0x5430,0x445A,0x0000,0x0000,0x0000,0x0000,0x8265,
+0x2F47,0x0000,0x0000,0x8266,0x8267,0x8268,0x0000,0x2F48,
+0x0000,0x0000,0x0000,0x8269,0x2F49,0x0000,0x0000,0x5434,
+0x0000,0x0000,0x3F62,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5432,0x5435,0x0000,0x373F,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x5436,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x826D,0x0000,0x2F4A,0x826E,0x826F,0x0000,
+0x5437,0x0000,0x3924,0x3340,0x5439,0x0000,0x0000,0x0000,
+0x8270,0x0000,0x543A,0x0000,0x826C,0x0000,0x0000,0x0000,
+0x543B,0x0000,0x0000,0x5438,0x0000,0x0000,0x0000,0x0000,
+0x2F4D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5431,0x0000,0x0000,0x543C,0x0000,0x0000,0x543D,0x2F4E,
+0x2F4F,0x0000,0x0000,0x4B64,0x8273,0x0000,0x3E6B,0x2F50,
+0x0000,0x0000,0x543F,0x5440,0x543E,0x0000,0x5442,0x8271,
+0x0000,0x0000,0x0000,0x0000,0x4738,0x0000,0x8276,0x3068,
+0x4956,0x0000,0x0000,0x5443,0x2F51,0x0000,0x8277,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x2F52,0x0000,0x0000,
+0x8278,0x0000,0x0000,0x0000,0x3E7D,0x2F53,0x2F54,0x3C39,
+0x827A,0x475D,0x3470,0x827B,0x3A6B,0x827C,0x0000,0x2F55,
+
+/* 5800h */
+0x4B59,0x0000,0x4632,0x0000,0x827D,0x3778,0x424F,0x0000,
+0x0000,0x2F56,0x5441,0x5444,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x4244,0x0000,0x0000,
+0x0000,0x5445,0x0000,0x0000,0x0000,0x5446,0x827E,0x0000,
+0x8321,0x5448,0x0000,0x0000,0x4469,0x0000,0x0000,0x8322,
+0x0000,0x0000,0x342E,0x0000,0x0000,0x0000,0x0000,0x7421,
+0x3161,0x4A73,0x8323,0x0000,0x3E6C,0x4548,0x0000,0x0000,
+0x0000,0x8324,0x3A66,0x0000,0x0000,0x544E,0x0000,0x0000,
+0x4A3D,0x4E5D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x8326,0x3274,0x544A,0x8327,0x0000,0x0000,0x0000,
+0x0000,0x413A,0x544D,0x0000,0x4563,0x0000,0x0000,0x4549,
+0x4564,0x4839,0x444D,0x0000,0x0000,0x0000,0x3A49,0x0000,
+0x0000,0x2F58,0x5449,0x0000,0x2F59,0x0000,0x0000,0x8328,
+0x0000,0x3176,0x0000,0x4536,0x0000,0x0000,0x0000,0x0000,
+0x544B,0x0000,0x5447,0x0000,0x0000,0x3F50,0x0000,0x0000,
+0x0000,0x544F,0x0000,0x0000,0x2F5B,0x0000,0x3D4E,0x0000,
+0x0000,0x0000,0x0000,0x362D,0x0000,0x5450,0x0000,0x0000,
+0x0000,0x2F5C,0x8329,0x832A,0x0000,0x832B,0x0000,0x832C,
+0x832D,0x0000,0x0000,0x4A68,0x832E,0x0000,0x0000,0x417D,
+0x0000,0x0000,0x0000,0x0000,0x4446,0x832F,0x2F5D,0x5452,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4B4F,0x2F5F,0x8330,0x5453,0x0000,0x0000,0x5458,0x0000,
+0x0000,0x8331,0x0000,0x4A2F,0x0000,0x0000,0x0000,0x0000,
+0x5457,0x5451,0x5454,0x5456,0x0000,0x0000,0x3A26,0x0000,
+0x0000,0x4A49,0x0000,0x8333,0x0000,0x5459,0x0000,0x4345,
+0x0000,0x0000,0x3275,0x0000,0x3E6D,0x8334,0x2F62,0x0000,
+0x0000,0x545B,0x2F61,0x545A,0x2F63,0x3968,0x0000,0x545C,
+0x545E,0x545D,0x2F64,0x0000,0x5460,0x0000,0x5455,0x5462,
+0x2F65,0x0000,0x8335,0x0000,0x5461,0x545F,0x0000,0x0000,
+0x0000,0x2F66,0x0000,0x3B4E,0x3F51,0x0000,0x4154,0x5463,
+0x403C,0x306D,0x4764,0x8336,0x8337,0x0000,0x0000,0x445B,
+0x0000,0x5465,0x5464,0x5466,0x5467,0x5468,0x0000,0x0000,
+
+/* 5900h */
+0x0000,0x0000,0x5469,0x0000,0x0000,0x8338,0x8339,0x0000,
+0x0000,0x4A51,0x546A,0x833A,0x2F67,0x833B,0x0000,0x3246,
+0x546B,0x0000,0x0000,0x0000,0x833C,0x4D3C,0x3330,0x0000,
+0x5249,0x3D48,0x423F,0x546C,0x4C6B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4C34,0x0000,0x833D,0x546E,0x0000,0x4267,
+0x0000,0x4537,0x4240,0x4957,0x546F,0x5470,0x317B,0x0000,
+0x0000,0x3C3A,0x5471,0x0000,0x0000,0x0000,0x0000,0x3050,
+0x5472,0x0000,0x0000,0x0000,0x0000,0x8340,0x5473,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x3162,0x0000,0x8342,0x3471,
+0x4660,0x4A74,0x0000,0x0000,0x0000,0x0000,0x5477,0x4155,
+0x5476,0x3740,0x0000,0x0000,0x4B5B,0x5475,0x0000,0x4565,
+0x5479,0x0000,0x5478,0x8345,0x0000,0x2F69,0x0000,0x8346,
+0x547B,0x0000,0x547A,0x0000,0x0000,0x317C,0x0000,0x547C,
+0x3E29,0x547E,0x4325,0x0000,0x547D,0x2F6A,0x4A33,0x0000,
+0x0000,0x0000,0x0000,0x3D77,0x455B,0x8348,0x8349,0x0000,
+0x5521,0x0000,0x0000,0x0000,0x834A,0x3925,0x0000,0x0000,
+0x0000,0x5522,0x4721,0x485E,0x4C51,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4725,0x2F6B,0x0000,0x552B,0x0000,0x0000,
+0x0000,0x0000,0x2F6C,0x3538,0x0000,0x0000,0x4D45,0x0000,
+0x0000,0x4C2F,0x0000,0x562C,0x0000,0x5523,0x0000,0x834B,
+0x0000,0x0000,0x0000,0x5526,0x2F6D,0x4245,0x0000,0x0000,
+0x4B38,0x0000,0x0000,0x0000,0x454A,0x0000,0x834C,0x0000,
+0x0000,0x0000,0x5527,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4B65,0x0000,0x3A4A,0x834D,0x0000,0x3E2A,0x0000,
+0x0000,0x0000,0x0000,0x2F6E,0x0000,0x0000,0x5528,0x0000,
+0x834E,0x3B50,0x0000,0x3B4F,0x0000,0x834F,0x0000,0x0000,
+0x3039,0x3848,0x2F6F,0x402B,0x3051,0x0000,0x0000,0x0000,
+0x0000,0x552C,0x552D,0x0000,0x552A,0x2F70,0x8350,0x0000,
+0x0000,0x0000,0x0000,0x8351,0x8352,0x3138,0x342F,0x8353,
+0x5529,0x0000,0x4C45,0x4931,0x0000,0x0000,0x8354,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3028,0x0000,
+0x7E7A,0x0000,0x0000,0x3079,0x0000,0x0000,0x0000,0x3B51,
+
+/* 5A00h */
+0x0000,0x3052,0x0000,0x3023,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x5532,0x0000,0x0000,0x8358,0x8359,0x0000,0x0000,
+0x0000,0x5530,0x0000,0x2F71,0x0000,0x0000,0x0000,0x835A,
+0x4C3C,0x0000,0x5533,0x0000,0x5531,0x0000,0x0000,0x552F,
+0x3F31,0x0000,0x0000,0x2F72,0x0000,0x552E,0x0000,0x835B,
+0x0000,0x4A5A,0x0000,0x0000,0x0000,0x835C,0x0000,0x3864,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x5537,0x5538,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x3E2B,0x0000,0x0000,0x0000,
+0x5534,0x4F2C,0x0000,0x0000,0x0000,0x0000,0x474C,0x0000,
+0x0000,0x5536,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x835D,0x0000,0x0000,
+0x0000,0x0000,0x3A27,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x5539,0x0000,0x0000,0x835E,0x4958,0x2F73,
+0x0000,0x0000,0x553A,0x0000,0x5535,0x2F74,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2F75,
+0x0000,0x0000,0x835F,0x0000,0x0000,0x0000,0x2F76,0x4C3B,
+0x0000,0x0000,0x0000,0x0000,0x2F77,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x8360,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x475E,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x553B,0x4932,0x8361,0x0000,0x2F78,0x8362,
+0x8363,0x0000,0x8364,0x0000,0x0000,0x0000,0x0000,0x2F79,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x8365,0x0000,0x8366,0x0000,0x8367,0x0000,0x0000,
+0x0000,0x0000,0x8368,0x0000,0x553C,0x5540,0x553D,0x8369,
+0x0000,0x3247,0x553F,0x0000,0x2F7A,0x0000,0x0000,0x0000,
+0x0000,0x3C3B,0x0000,0x553E,0x3779,0x0000,0x0000,0x0000,
+0x554C,0x0000,0x0000,0x0000,0x0000,0x0000,0x5545,0x5542,
+0x0000,0x0000,0x836A,0x0000,0x836B,0x0000,0x0000,0x0000,
+0x836C,0x4364,0x0000,0x5541,0x0000,0x836D,0x5543,0x0000,
+0x0000,0x5544,0x0000,0x0000,0x0000,0x0000,0x836F,0x0000,
+0x836E,0x0000,0x0000,0x0000,0x0000,0x8370,0x0000,0x0000,
+0x0000,0x0000,0x5546,0x5547,0x0000,0x0000,0x0000,0x0000,
+
+/* 5B00h */
+0x8371,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8372,0x3472,0x0000,0x5549,0x5548,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x554A,0x8373,
+0x0000,0x2F7C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x3E6E,0x0000,0x0000,0x2F7D,0x0000,0x0000,
+0x0000,0x0000,0x554D,0x0000,0x445C,0x8375,0x0000,0x0000,
+0x3145,0x0000,0x554B,0x0000,0x8374,0x0000,0x554E,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x554F,0x0000,
+0x5552,0x4F55,0x0000,0x5550,0x0000,0x5551,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x8376,0x0000,0x0000,0x0000,
+0x3B52,0x5553,0x8377,0x0000,0x3926,0x5554,0x4F56,0x3B7A,
+0x4238,0x0000,0x5555,0x5556,0x3B5A,0x3927,0x0000,0x4C52,
+0x0000,0x0000,0x0000,0x3528,0x3849,0x5557,0x3358,0x0000,
+0x8378,0x5558,0x0000,0x4239,0x0000,0x0000,0x0000,0x8379,
+0x5559,0x5623,0x0000,0x555A,0x0000,0x555B,0x0000,0x0000,
+0x555C,0x0000,0x555E,0x0000,0x837A,0x4F57,0x0000,0x837B,
+0x555F,0x837C,0x0000,0x5560,0x837D,0x4270,0x0000,0x3127,
+0x3C69,0x3042,0x0000,0x4157,0x3430,0x3C35,0x0000,0x3928,
+0x0000,0x0000,0x0000,0x4F58,0x0000,0x4566,0x8021,0x3D21,
+0x3431,0x4368,0x446A,0x3038,0x3539,0x4A75,0x0000,0x3C42,
+0x0000,0x0000,0x3552,0x406B,0x3C3C,0x4D28,0x5561,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x8022,0x0000,0x355C,0x0000,
+0x3A4B,0x0000,0x0000,0x3332,0x3163,0x3E2C,0x3248,0x0000,
+0x5562,0x4D46,0x0000,0x0000,0x0000,0x0000,0x0000,0x3D49,
+0x8024,0x0000,0x3C64,0x5563,0x3473,0x4652,0x4C29,0x5564,
+0x0000,0x5565,0x0000,0x0000,0x4959,0x0000,0x8026,0x0000,
+0x5567,0x0000,0x3428,0x3677,0x5566,0x0000,0x8027,0x0000,
+0x4F59,0x0000,0x0000,0x3432,0x0000,0x3F32,0x556B,0x3B21,
+0x0000,0x3249,0x556A,0x0000,0x5568,0x556C,0x5569,0x472B,
+0x5C4D,0x3F33,0x0000,0x556D,0x4F5A,0x0000,0x4E40,0x0000,
+0x556E,0x802A,0x0000,0x5570,0x0000,0x437E,0x556F,0x0000,
+0x4023,0x0000,0x3B7B,0x0000,0x0000,0x802B,0x4250,0x3C77,
+
+/* 5C00h */
+0x0000,0x4975,0x406C,0x802D,0x3C4D,0x5571,0x3E2D,0x5572,
+0x5573,0x3053,0x423A,0x3F52,0x0000,0x5574,0x4633,0x3E2E,
+0x0000,0x3E2F,0x4F5B,0x5575,0x0000,0x0000,0x406D,0x0000,
+0x0000,0x0000,0x3E30,0x0000,0x0000,0x0000,0x4F5C,0x0000,
+0x5576,0x0000,0x5577,0x4F5D,0x4C60,0x0000,0x0000,0x0000,
+0x5578,0x802E,0x0000,0x4F5E,0x0000,0x3646,0x0000,0x0000,
+0x802F,0x3D22,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5579,0x557A,0x3C5C,0x3F2C,0x4674,0x3F54,0x4878,0x4722,
+0x3649,0x557B,0x0000,0x0000,0x0000,0x356F,0x557C,0x0000,
+0x367E,0x0000,0x464F,0x3230,0x0000,0x3B53,0x557D,0x5622,
+0x5621,0x367D,0x0000,0x557E,0x0000,0x4538,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7E7B,0x0000,0x0000,0x4230,0x8031,
+0x454B,0x3C48,0x4F60,0x8032,0x4158,0x4D7A,0x0000,0x8033,
+0x8034,0x8035,0x0000,0x0000,0x5624,0x0000,0x5625,0x4656,
+0x8036,0x3B33,0x0000,0x0000,0x0000,0x0000,0x5627,0x0000,
+0x0000,0x5628,0x4F64,0x0000,0x8039,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x803C,0x0000,0x803D,0x0000,0x5629,0x0000,0x0000,0x4F65,
+0x3474,0x562A,0x0000,0x0000,0x562B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4F66,
+0x8041,0x322C,0x8042,0x4F67,0x0000,0x0000,0x8043,0x8044,
+0x413B,0x3464,0x4F68,0x562D,0x4C28,0x8046,0x0000,0x0000,
+0x0000,0x4252,0x0000,0x3359,0x0000,0x8047,0x562F,0x5631,
+0x345F,0x0000,0x4F69,0x562E,0x5630,0x0000,0x5633,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x5632,0x0000,0x5634,
+0x0000,0x8049,0x0000,0x4F6A,0x0000,0x0000,0x0000,0x0000,
+0x4F6B,0x0000,0x4F6C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x5635,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x463D,0x362E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x3265,0x5636,0x563B,0x0000,0x0000,0x5639,0x0000,0x4A77,
+0x4A76,0x0000,0x0000,0x0000,0x4F6D,0x0000,0x4567,0x0000,
+0x0000,0x0000,0x5638,0x3D54,0x0000,0x5637,0x0000,0x0000,
+
+/* 5D00h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x804C,0x3F72,
+0x0000,0x0000,0x0000,0x563C,0x0000,0x4F70,0x3A6A,0x0000,
+0x804D,0x5642,0x0000,0x0000,0x5643,0x563D,0x3333,0x563E,
+0x5647,0x5646,0x5645,0x5641,0x0000,0x804F,0x0000,0x5640,
+0x8050,0x0000,0x5644,0x0000,0x8051,0x0000,0x8052,0x4F71,
+0x0000,0x4A78,0x0000,0x804E,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x8053,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x8054,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x8055,0x0000,0x0000,0x0000,0x4F73,0x4F74,
+0x0000,0x0000,0x4F76,0x564B,0x5648,0x0000,0x564A,0x0000,
+0x4D72,0x0000,0x5649,0x4F75,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x563F,0x0000,0x0000,0x0000,
+0x0000,0x8057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3F73,0x8058,0x0000,0x564C,0x4F77,0x0000,0x3A37,
+0x805A,0x0000,0x0000,0x564D,0x0000,0x0000,0x564E,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4F78,0x5651,0x0000,0x5650,0x0000,0x0000,0x564F,
+0x805D,0x0000,0x0000,0x4568,0x563A,0x0000,0x0000,0x0000,
+0x5657,0x0000,0x805F,0x0000,0x8060,0x0000,0x0000,0x8061,
+0x0000,0x8062,0x0000,0x0000,0x0000,0x5653,0x0000,0x0000,
+0x4F79,0x0000,0x5652,0x0000,0x4F7A,0x0000,0x0000,0x4F7B,
+0x0000,0x0000,0x0000,0x0000,0x5654,0x0000,0x5655,0x0000,
+0x8063,0x0000,0x8064,0x0000,0x8065,0x0000,0x0000,0x5658,
+0x4F7C,0x8067,0x4E66,0x0000,0x5659,0x5656,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x565A,0x0000,0x4F7D,0x3460,0x565B,0x0000,0x0000,
+0x0000,0x8068,0x565D,0x565C,0x0000,0x0000,0x565E,0x8069,
+0x806A,0x0000,0x0000,0x565F,0x0000,0x406E,0x3D23,0x0000,
+0x806B,0x3D64,0x7428,0x4163,0x806D,0x3929,0x3A38,0x392A,
+0x3570,0x806E,0x0000,0x5660,0x0000,0x0000,0x3A39,0x0000,
+0x0000,0x384A,0x5661,0x4C26,0x4743,0x5662,0x0000,0x392B,
+0x0000,0x0000,0x0000,0x342C,0x0000,0x4327,0x3652,0x0000,
+
+/* 5E00h */
+0x8070,0x0000,0x3B54,0x495B,0x0000,0x0000,0x4841,0x0000,
+0x0000,0x0000,0x0000,0x5663,0x3475,0x0000,0x0000,0x0000,
+0x0000,0x5666,0x8072,0x0000,0x7429,0x8073,0x4421,0x0000,
+0x742A,0x5665,0x5664,0x5667,0x0000,0x446B,0x0000,0x8075,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x3F63,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3B55,0x0000,0x404A,0x8076,0x4253,
+0x3522,0x0000,0x0000,0x4422,0x0000,0x0000,0x5668,0x5669,
+0x3E6F,0x0000,0x0000,0x0000,0x0000,0x4B39,0x8077,0x0000,
+0x566C,0x0000,0x0000,0x566B,0x566A,0x497D,0x0000,0x5673,
+0x0000,0x8078,0x0000,0x0000,0x4B5A,0x0000,0x566D,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x566F,0x4B6B,0x807A,0x566E,
+0x742B,0x0000,0x0000,0x0000,0x0000,0x0000,0x742C,0x5670,
+0x0000,0x4828,0x5671,0x4A3E,0x5672,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x807C,0x807D,0x807E,0x8421,0x0000,
+0x0000,0x0000,0x3433,0x4A3F,0x472F,0x5674,0x5675,0x7E7C,
+0x392C,0x3434,0x5676,0x3838,0x4D44,0x4D29,0x3476,0x5678,
+0x0000,0x4423,0x0000,0x392D,0x3E31,0x0000,0x0000,0x485F,
+0x0000,0x0000,0x3E32,0x0000,0x0000,0x0000,0x0000,0x3D78,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x446C,0x4A79,0x4539,
+0x0000,0x0000,0x392E,0x0000,0x495C,0x0000,0x0000,0x0000,
+0x5679,0x0000,0x0000,0x0000,0x0000,0x8423,0x4559,0x3A42,
+0x0000,0x0000,0x8424,0x384B,0x8425,0x446D,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x3043,0x3D6E,0x392F,
+0x4D47,0x8426,0x0000,0x0000,0x0000,0x0000,0x742D,0x8427,
+0x0000,0x567A,0x567B,0x4751,0x0000,0x0000,0x8428,0x0000,
+0x567C,0x4E77,0x4F2D,0x742F,0x0000,0x0000,0x0000,0x567E,
+0x567D,0x0000,0x8429,0x3347,0x0000,0x0000,0x5721,0x0000,
+0x0000,0x842A,0x5724,0x5725,0x0000,0x5723,0x0000,0x4940,
+0x3E33,0x5727,0x5726,0x5722,0x0000,0x0000,0x0000,0x0000,
+0x5728,0x5729,0x0000,0x0000,0x572A,0x0000,0x0000,0x0000,
+0x572D,0x572B,0x0000,0x572C,0x572E,0x0000,0x3164,0x446E,
+0x572F,0x7430,0x377A,0x3276,0x4736,0x842C,0x5730,0x467B,
+
+/* 5F00h */
+0x7431,0x4A5B,0x7432,0x5731,0x4F2E,0x0000,0x0000,0x7433,
+0x842D,0x5732,0x4A40,0x5735,0x5021,0x5031,0x842E,0x3C30,
+0x4675,0x5736,0x0000,0x355D,0x4424,0x307A,0x5737,0x4A26,
+0x3930,0x0000,0x0000,0x4350,0x842F,0x7434,0x8431,0x446F,
+0x0000,0x0000,0x0000,0x7435,0x0000,0x4C6F,0x3839,0x384C,
+0x0000,0x5738,0x0000,0x0000,0x0000,0x5739,0x0000,0x573F,
+0x0000,0x3C65,0x0000,0x0000,0x7436,0x4425,0x7437,0x362F,
+0x573A,0x0000,0x0000,0x0000,0x492B,0x7438,0x4346,0x0000,
+0x7439,0x573B,0x0000,0x0000,0x0000,0x743A,0x0000,0x8432,
+0x573C,0x0000,0x3630,0x0000,0x573D,0x0000,0x573E,0x0000,
+0x0000,0x5740,0x0000,0x4576,0x743B,0x0000,0x5741,0x5742,
+0x743C,0x5743,0x0000,0x0000,0x5734,0x5733,0x0000,0x0000,
+0x0000,0x5744,0x3741,0x8433,0x743D,0x0000,0x4927,0x743E,
+0x0000,0x3A4C,0x4937,0x4426,0x494B,0x5745,0x0000,0x0000,
+0x3E34,0x3146,0x8434,0x5746,0x0000,0x0000,0x0000,0x5747,
+0x0000,0x4C72,0x0000,0x0000,0x4860,0x743F,0x8435,0x574A,
+0x317D,0x402C,0x5749,0x5748,0x3742,0x4254,0x0000,0x574E,
+0x574C,0x7440,0x574B,0x4E27,0x3865,0x0000,0x0000,0x8436,
+0x3D79,0x574D,0x454C,0x3D3E,0x0000,0x0000,0x0000,0x4640,
+0x5751,0x5750,0x0000,0x0000,0x7441,0x0000,0x574F,0x0000,
+0x5752,0x3866,0x8437,0x0000,0x8438,0x0000,0x0000,0x7442,
+0x5753,0x497C,0x3D5B,0x0000,0x0000,0x5754,0x4879,0x7443,
+0x0000,0x0000,0x0000,0x4641,0x4427,0x7444,0x0000,0x7445,
+0x8439,0x4530,0x0000,0x0000,0x5755,0x352B,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3F34,0x843A,0x492C,0x0000,0x843C,
+0x0000,0x7446,0x0000,0x843D,0x3477,0x4726,0x0000,0x0000,
+0x0000,0x0000,0x843E,0x843F,0x8440,0x0000,0x5756,0x3B56,
+0x4B3A,0x4B3B,0x0000,0x0000,0x317E,0x575B,0x7447,0x0000,
+0x4369,0x7448,0x8441,0x0000,0x5758,0x0000,0x0000,0x0000,
+0x0000,0x7449,0x0000,0x3277,0x0000,0x0000,0x8442,0x8443,
+0x582D,0x575A,0x0000,0x8444,0x0000,0x4730,0x0000,0x0000,
+0x5759,0x0000,0x0000,0x5757,0x8445,0x397A,0x0000,0x575D,
+
+/* 6000h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x744A,0x5763,0x5769,
+0x5761,0x0000,0x455C,0x0000,0x744B,0x5766,0x495D,0x8447,
+0x744C,0x5760,0x0000,0x5765,0x4E67,0x3B57,0x0000,0x0000,
+0x4255,0x575E,0x8448,0x0000,0x8449,0x355E,0x5768,0x402D,
+0x3165,0x5762,0x3278,0x5767,0x0000,0x0000,0x0000,0x3631,
+0x0000,0x5764,0x0000,0x744D,0x0000,0x744E,0x0000,0x0000,
+0x0000,0x0000,0x576A,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x576C,0x5776,0x5774,0x0000,0x0000,0x5771,0x744F,
+0x0000,0x0000,0x5770,0x4E78,0x844B,0x5772,0x0000,0x0000,
+0x3632,0x0000,0x3931,0x0000,0x0000,0x3D7A,0x0000,0x0000,
+0x0000,0x5779,0x576B,0x0000,0x0000,0x0000,0x0000,0x576F,
+0x575F,0x0000,0x327A,0x5773,0x5775,0x4351,0x0000,0x0000,
+0x3A28,0x3238,0x576D,0x5778,0x5777,0x3633,0x0000,0x4229,
+0x3366,0x0000,0x0000,0x0000,0x0000,0x3743,0x0000,0x576E,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x844C,
+0x0000,0x577A,0x0000,0x577D,0x5821,0x0000,0x0000,0x0000,
+0x0000,0x3C3D,0x844D,0x5827,0x4470,0x577B,0x0000,0x0000,
+0x0000,0x0000,0x5825,0x0000,0x3279,0x844E,0x5823,0x5824,
+0x0000,0x0000,0x577E,0x5822,0x0000,0x7451,0x7452,0x3867,
+0x4D2A,0x0000,0x0000,0x3435,0x0000,0x0000,0x3159,0x5826,
+0x844F,0x473A,0x302D,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8451,0x8452,0x4861,0x575C,0x582C,0x5830,0x4C65,0x0000,
+0x5829,0x0000,0x0000,0x0000,0x4569,0x582E,0x8453,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x3E70,0x582F,0x4657,
+0x8454,0x0000,0x0000,0x7453,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4F47,0x0000,0x582B,0x7454,0x7455,0x0000,0x0000,
+0x5831,0x8455,0x397B,0x8456,0x404B,0x7456,0x0000,0x3054,
+0x582A,0x5828,0x0000,0x415A,0x0000,0x0000,0x0000,0x577C,
+0x3B34,0x0000,0x0000,0x0000,0x0000,0x0000,0x8457,0x0000,
+0x4246,0x583D,0x8458,0x415B,0x5838,0x8459,0x5835,0x5836,
+0x7457,0x3C66,0x5839,0x583C,0x0000,0x0000,0x0000,0x0000,
+
+/* 6100h */
+0x5837,0x3D25,0x0000,0x583A,0x0000,0x0000,0x5834,0x0000,
+0x4C7C,0x4C7B,0x0000,0x0000,0x0000,0x583E,0x583F,0x3055,
+0x845A,0x0000,0x845B,0x845C,0x0000,0x5833,0x0000,0x0000,
+0x0000,0x845D,0x3672,0x3026,0x7458,0x0000,0x845E,0x3436,
+0x0000,0x583B,0x0000,0x0000,0x0000,0x0000,0x0000,0x5843,
+0x5842,0x0000,0x0000,0x7459,0x5847,0x0000,0x0000,0x0000,
+0x745A,0x0000,0x0000,0x0000,0x5848,0x0000,0x0000,0x745B,
+0x0000,0x0000,0x845F,0x0000,0x5846,0x5849,0x5841,0x5845,
+0x0000,0x8461,0x584A,0x0000,0x584B,0x0000,0x8462,0x5840,
+0x3B7C,0x0000,0x5844,0x4256,0x3932,0x5832,0x3F35,0x0000,
+0x0000,0x0000,0x0000,0x5858,0x0000,0x4A69,0x0000,0x0000,
+0x584E,0x584F,0x5850,0x0000,0x0000,0x5857,0x0000,0x5856,
+0x8463,0x0000,0x4B7D,0x3437,0x0000,0x5854,0x0000,0x3745,
+0x3334,0x0000,0x0000,0x5851,0x0000,0x0000,0x4E38,0x5853,
+0x3056,0x5855,0x0000,0x584C,0x5852,0x5859,0x3744,0x584D,
+0x0000,0x0000,0x0000,0x0000,0x8464,0x0000,0x4D5D,0x0000,
+0x0000,0x0000,0x4D2B,0x0000,0x0000,0x0000,0x0000,0x585C,
+0x0000,0x0000,0x5860,0x0000,0x0000,0x745D,0x417E,0x0000,
+0x4E79,0x5861,0x8466,0x8467,0x585E,0x0000,0x585B,0x8468,
+0x8469,0x585A,0x585F,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x4A30,0x846A,0x0000,0x4634,
+0x846B,0x3746,0x0000,0x5862,0x585D,0x846C,0x5863,0x0000,
+0x0000,0x0000,0x377B,0x0000,0x0000,0x0000,0x3231,0x0000,
+0x0000,0x7460,0x586B,0x0000,0x745F,0x0000,0x3438,0x0000,
+0x0000,0x0000,0x0000,0x5869,0x0000,0x0000,0x586A,0x3A29,
+0x5868,0x5866,0x5865,0x586C,0x5864,0x586E,0x0000,0x0000,
+0x327B,0x0000,0x0000,0x0000,0x0000,0x846E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x846F,0x0000,0x8470,
+0x0000,0x0000,0x0000,0x5870,0x0000,0x0000,0x586F,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4428,0x0000,0x5873,0x8471,0x5871,0x5867,
+0x377C,0x0000,0x5872,0x0000,0x5876,0x5875,0x5877,0x5874,
+
+/* 6200h */
+0x5878,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5879,0x587A,0x4A6A,0x0000,0x587C,0x587B,0x3D3F,0x0000,
+0x402E,0x3266,0x327C,0x0000,0x587D,0x8473,0x303F,0x0000,
+0x0000,0x0000,0x404C,0x587E,0x0000,0x6C43,0x5921,0x3761,
+0x0000,0x5922,0x7462,0x8474,0x0000,0x0000,0x406F,0x0000,
+0x0000,0x8475,0x5923,0x0000,0x0000,0x0000,0x5924,0x353A,
+0x5925,0x0000,0x5926,0x5927,0x4257,0x0000,0x0000,0x0000,
+0x384D,0x0000,0x0000,0x4C61,0x0000,0x0000,0x7463,0x4B3C,
+0x3D6A,0x5928,0x0000,0x7464,0x0000,0x0000,0x8476,0x4070,
+0x6E3D,0x4862,0x0000,0x3C6A,0x8477,0x3A4D,0x5929,0x0000,
+0x0000,0x8478,0x8479,0x4247,0x0000,0x4A27,0x7465,0x0000,
+0x4271,0x0000,0x7466,0x592C,0x0000,0x0000,0x592A,0x0000,
+0x592D,0x847A,0x0000,0x592B,0x847B,0x0000,0x0000,0x0000,
+0x592E,0x0000,0x0000,0x0000,0x0000,0x847D,0x4A31,0x7467,
+0x0000,0x3037,0x0000,0x847E,0x0000,0x0000,0x495E,0x0000,
+0x0000,0x4863,0x0000,0x847C,0x592F,0x0000,0x5932,0x3E35,
+0x353B,0x0000,0x5930,0x5937,0x3E36,0x7468,0x0000,0x0000,
+0x0000,0x5931,0x4744,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4D5E,0x5933,0x5934,0x5938,0x456A,0x5935,0x3933,
+0x405E,0x8521,0x0000,0x5946,0x4834,0x0000,0x4272,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8522,0x0000,
+0x0000,0x0000,0x0000,0x4864,0x5A2D,0x0000,0x0000,0x0000,
+0x0000,0x4A7A,0x0000,0x0000,0x0000,0x4471,0x0000,0x0000,
+0x0000,0x4B75,0x0000,0x593B,0x3221,0x436A,0x0000,0x0000,
+0x0000,0x0000,0x5944,0x0000,0x7469,0x4334,0x593E,0x5945,
+0x5940,0x5947,0x5943,0x0000,0x5942,0x476F,0x0000,0x593C,
+0x327D,0x593A,0x3571,0x4273,0x5936,0x8523,0x746A,0x5939,
+0x3934,0x405B,0x0000,0x3E37,0x5941,0x4752,0x0000,0x0000,
+0x3572,0x3348,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x3367,0x3F21,0x5949,0x594E,
+0x0000,0x594A,0x0000,0x377D,0x0000,0x594F,0x3B22,0x3969,
+0x0000,0x0000,0x0000,0x0000,0x746B,0x8525,0x3D26,0x593D,
+
+/* 6300h */
+0x0000,0x3B7D,0x594C,0x8526,0x0000,0x0000,0x0000,0x3B58,
+0x594D,0x3044,0x746C,0x0000,0x5948,0x8527,0x0000,0x0000,
+0x8528,0x4429,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x746D,0x3573,0x0000,0x0000,0x0000,0x0000,0x0000,0x3634,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x594B,
+0x3027,0x0000,0x0000,0x3A43,0x0000,0x0000,0x0000,0x3F36,
+0x0000,0x0000,0x852B,0x0000,0x0000,0x852C,0x0000,0x0000,
+0x0000,0x746E,0x4472,0x852D,0x852E,0x4854,0x5951,0x415E,
+0x0000,0x852F,0x0000,0x746F,0x8530,0x0000,0x0000,0x0000,
+0x0000,0x422A,0x0000,0x0000,0x3B2B,0x5952,0x8531,0x5954,
+0x5950,0x0000,0x0000,0x0000,0x0000,0x4A61,0x0000,0x443D,
+0x0000,0x8533,0x0000,0x0000,0x415C,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7470,0x0000,0x4A7B,
+0x3C4E,0x5960,0x0000,0x595F,0x8536,0x0000,0x3F78,0x0000,
+0x0000,0x0000,0x377E,0x0000,0x0000,0x0000,0x5959,0x3E39,
+0x0000,0x0000,0x4668,0x4731,0x7471,0x0000,0x0000,0x0000,
+0x5957,0x0000,0x0000,0x415D,0x8537,0x0000,0x0000,0x0000,
+0x3C78,0x595C,0x0000,0x0000,0x3E38,0x0000,0x5956,0x595B,
+0x0000,0x0000,0x4753,0x0000,0x853A,0x0000,0x5955,0x0000,
+0x3721,0x8538,0x0000,0x335D,0x0000,0x0000,0x0000,0x595D,
+0x4E2B,0x3A4E,0x4335,0x595A,0x0000,0x405C,0x0000,0x3935,
+0x3F64,0x3166,0x413C,0x5958,0x3545,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x3747,0x0000,0x444F,0x595E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x415F,0x0000,0x853B,0x5961,0x0000,
+0x5963,0x0000,0x0000,0x4237,0x5969,0x0000,0x5964,0x0000,
+0x0000,0x5966,0x0000,0x0000,0x0000,0x0000,0x0000,0x4941,
+0x4473,0x0000,0x5967,0x0000,0x853D,0x853E,0x4D2C,0x0000,
+0x0000,0x0000,0x4D48,0x3439,0x853F,0x0000,0x0000,0x0000,
+0x8540,0x302E,0x0000,0x5965,0x0000,0x7472,0x0000,0x0000,
+0x0000,0x5962,0x0000,0x8541,0x8542,0x7473,0x3478,0x0000,
+0x0000,0x0000,0x8543,0x0000,0x3167,0x7474,0x5968,0x853C,
+0x0000,0x0000,0x4D49,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 6400h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x596C,0x0000,
+0x0000,0x8544,0x0000,0x0000,0x0000,0x423B,0x0000,0x5973,
+0x7475,0x0000,0x0000,0x596D,0x7476,0x0000,0x596A,0x5971,
+0x0000,0x0000,0x0000,0x0000,0x5953,0x0000,0x8545,0x0000,
+0x0000,0x0000,0x7477,0x0000,0x0000,0x8546,0x596E,0x0000,
+0x5972,0x8547,0x0000,0x0000,0x4842,0x456B,0x0000,0x8548,
+0x0000,0x0000,0x0000,0x0000,0x596B,0x0000,0x596F,0x0000,
+0x0000,0x0000,0x3748,0x0000,0x0000,0x0000,0x3A71,0x0000,
+0x0000,0x0000,0x405D,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5977,0x0000,
+0x0000,0x7479,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4526,0x0000,0x8549,0x854A,0x0000,0x854B,0x0000,0x0000,
+0x747A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5974,
+0x0000,0x4B60,0x0000,0x0000,0x0000,0x747B,0x0000,0x5975,
+0x0000,0x0000,0x0000,0x854C,0x0000,0x0000,0x5976,0x0000,
+0x4C4E,0x7478,0x4022,0x0000,0x0000,0x854D,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3762,0x0000,0x0000,0x0000,0x854E,
+0x597D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x854F,0x3B35,0x597A,0x0000,0x5979,0x0000,0x0000,
+0x0000,0x0000,0x4732,0x0000,0x0000,0x8550,0x4635,0x8551,
+0x0000,0x0000,0x0000,0x0000,0x4531,0x597B,0x0000,0x0000,
+0x0000,0x597C,0x0000,0x496F,0x0000,0x4745,0x3B23,0x0000,
+0x4071,0x0000,0x4B50,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3349,0x0000,0x5A25,0x597E,0x0000,0x747D,0x747E,
+0x0000,0x4D4A,0x5A27,0x0000,0x7521,0x5A23,0x0000,0x5A24,
+0x0000,0x0000,0x7522,0x8552,0x8553,0x4160,0x747C,0x0000,
+0x7523,0x0000,0x5A22,0x0000,0x593F,0x8554,0x0000,0x8555,
+0x5A26,0x0000,0x5A21,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5A2B,0x5A2C,0x4527,0x5A2E,0x8557,0x8558,0x3B24,0x5A29,
+0x0000,0x0000,0x0000,0x0000,0x353C,0x0000,0x0000,0x5A2F,
+0x0000,0x5A28,0x5A33,0x0000,0x5A32,0x0000,0x5A31,0x7524,
+0x0000,0x0000,0x5A34,0x7525,0x0000,0x5A36,0x3E71,0x8559,
+
+/* 6500h */
+0x5A35,0x0000,0x0000,0x0000,0x855A,0x5A39,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x855C,
+0x0000,0x0000,0x0000,0x0000,0x855D,0x0000,0x855E,0x0000,
+0x5A37,0x0000,0x0000,0x0000,0x5A38,0x5970,0x8560,0x0000,
+0x0000,0x0000,0x7526,0x5A3B,0x5A3A,0x0000,0x0000,0x0000,
+0x0000,0x7527,0x5978,0x5A3C,0x5A30,0x0000,0x0000,0x3B59,
+0x0000,0x0000,0x8561,0x0000,0x5A3D,0x5A3E,0x5A40,0x5A3F,
+0x5A41,0x327E,0x0000,0x3936,0x0000,0x0000,0x4A7C,0x402F,
+0x0000,0x0000,0x0000,0x0000,0x8562,0x384E,0x0000,0x0000,
+0x5A43,0x0000,0x0000,0x0000,0x0000,0x5A46,0x0000,0x4952,
+0x0000,0x355F,0x0000,0x0000,0x8563,0x5A45,0x5A44,0x4754,
+0x5A47,0x3635,0x0000,0x0000,0x0000,0x5A49,0x5A48,0x0000,
+0x0000,0x0000,0x343A,0x3B36,0x0000,0x0000,0x4658,0x7529,
+0x0000,0x0000,0x0000,0x8564,0x3749,0x0000,0x0000,0x0000,
+0x3F74,0x0000,0x5A4A,0x0000,0x4030,0x4528,0x0000,0x495F,
+0x5A4B,0x0000,0x8565,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x8566,0x5A4C,0x5A4D,0x8567,0x8568,0x0000,0x4A38,
+0x555D,0x4046,0x8569,0x0000,0x494C,0x0000,0x3A58,0x0000,
+0x4865,0x4843,0x0000,0x0000,0x0000,0x0000,0x0000,0x454D,
+0x0000,0x4E41,0x0000,0x5A4F,0x3C50,0x752A,0x0000,0x5A50,
+0x0000,0x3036,0x0000,0x0000,0x3654,0x404D,0x0000,0x4960,
+0x0000,0x0000,0x0000,0x5A51,0x3B42,0x4347,0x0000,0x3B5B,
+0x3F37,0x0000,0x856A,0x0000,0x0000,0x856B,0x0000,0x5A52,
+0x856C,0x4A7D,0x0000,0x0000,0x3177,0x3B5C,0x0000,0x856D,
+0x0000,0x5A55,0x856E,0x5A53,0x5A56,0x4E39,0x5A54,0x0000,
+0x0000,0x856F,0x0000,0x407B,0x5A57,0x0000,0x0000,0x4232,
+0x0000,0x0000,0x5A58,0x0000,0x8570,0x0000,0x0000,0x347A,
+0x0000,0x5A5A,0x0000,0x5A59,0x0000,0x0000,0x0000,0x0000,
+0x5A5B,0x5A5C,0x347B,0x0000,0x0000,0x467C,0x4336,0x356C,
+0x3B5D,0x4161,0x0000,0x0000,0x3D5C,0x3030,0x0000,0x0000,
+0x0000,0x5A5D,0x8572,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x8573,0x3222,0x5A61,0x8574,0x0000,0x0000,0x0000,
+
+/* 6600h */
+0x752C,0x0000,0x3937,0x5A60,0x8575,0x0000,0x3A2B,0x3E3A,
+0x8576,0x752D,0x5A5F,0x0000,0x3E3B,0x0000,0x4C40,0x3A2A,
+0x0000,0x0000,0x0000,0x3057,0x404E,0x752E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x5A66,0x0000,0x752F,0x4031,
+0x3147,0x8577,0x7531,0x0000,0x7532,0x3D55,0x0000,0x4B66,
+0x3A72,0x0000,0x8578,0x7533,0x0000,0x3E3C,0x0000,0x4027,
+0x7534,0x7535,0x0000,0x7536,0x5A65,0x5A63,0x5A64,0x0000,
+0x0000,0x0000,0x7530,0x0000,0x436B,0x0000,0x0000,0x5B26,
+0x0000,0x5A6A,0x3B7E,0x3938,0x5A68,0x8579,0x0000,0x0000,
+0x7538,0x5A69,0x0000,0x3F38,0x7539,0x0000,0x857B,0x5A67,
+0x0000,0x857A,0x3B2F,0x0000,0x0000,0x0000,0x0000,0x857E,
+0x0000,0x753B,0x753C,0x8621,0x0000,0x5A6C,0x5A6B,0x5A70,
+0x0000,0x753D,0x5A71,0x8622,0x5A6D,0x753E,0x3322,0x5A6E,
+0x5A6F,0x4855,0x8625,0x8626,0x8627,0x8628,0x4961,0x374A,
+0x5A72,0x0000,0x0000,0x753F,0x4032,0x0000,0x3E3D,0x7540,
+0x7541,0x0000,0x4352,0x8629,0x0000,0x0000,0x0000,0x0000,
+0x862A,0x3647,0x0000,0x5A73,0x5A77,0x0000,0x0000,0x324B,
+0x5A74,0x5A76,0x0000,0x0000,0x0000,0x7542,0x5A75,0x0000,
+0x862B,0x3D6B,0x862C,0x0000,0x0000,0x0000,0x4348,0x3045,
+0x5A78,0x862D,0x0000,0x0000,0x0000,0x5A79,0x0000,0x0000,
+0x7544,0x0000,0x442A,0x0000,0x0000,0x0000,0x4E71,0x0000,
+0x0000,0x0000,0x0000,0x3B43,0x0000,0x862F,0x4A6B,0x0000,
+0x0000,0x8630,0x7545,0x0000,0x4B3D,0x8631,0x0000,0x0000,
+0x5B22,0x5A7B,0x0000,0x7546,0x5A7E,0x0000,0x5A7D,0x8633,
+0x0000,0x5A7A,0x0000,0x0000,0x5B21,0x0000,0x7547,0x465E,
+0x7548,0x5A7C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5B23,0x0000,
+0x0000,0x3D6C,0x5B24,0x754A,0x4D4B,0x4778,0x0000,0x0000,
+0x5B25,0x0000,0x0000,0x0000,0x0000,0x0000,0x5B27,0x0000,
+0x754B,0x5B28,0x0000,0x0000,0x8635,0x0000,0x0000,0x0000,
+0x5B29,0x0000,0x364A,0x3148,0x3939,0x5B2A,0x0000,0x5B2B,
+0x3D71,0x4162,0x754C,0x7537,0x5258,0x413E,0x413D,0x4258,
+
+/* 6700h */
+0x3A47,0x8637,0x0000,0x5072,0x0000,0x8638,0x0000,0x0000,
+0x376E,0x4D2D,0x0000,0x4A7E,0x0000,0x497E,0x0000,0x5B2C,
+0x0000,0x0000,0x8639,0x754D,0x3A73,0x443F,0x5B2D,0x4F2F,
+0x0000,0x863B,0x0000,0x4B3E,0x0000,0x442B,0x5B2E,0x347C,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5B2F,0x5B30,
+0x4C5A,0x0000,0x4C24,0x4B76,0x4B5C,0x3B25,0x5B32,0x0000,
+0x0000,0x3C6B,0x0000,0x754F,0x4B51,0x0000,0x5B34,0x5B37,
+0x5B36,0x0000,0x3479,0x0000,0x0000,0x3560,0x0000,0x5B33,
+0x0000,0x5B35,0x0000,0x0000,0x0000,0x0000,0x5B38,0x7551,
+0x7552,0x3F79,0x0000,0x0000,0x863E,0x863F,0x4D7B,0x3049,
+0x3A60,0x423C,0x0000,0x3C5D,0x8640,0x0000,0x3E73,0x0000,
+0x0000,0x5B3B,0x0000,0x0000,0x454E,0x8641,0x5B39,0x422B,
+0x5B3A,0x3E72,0x4C5D,0x5B3C,0x5B3D,0x4D68,0x7550,0x0000,
+0x0000,0x0000,0x5B42,0x0000,0x0000,0x393A,0x0000,0x4755,
+0x5B3F,0x456C,0x5A5E,0x5A62,0x8645,0x354F,0x8646,0x4747,
+0x0000,0x0000,0x0000,0x7553,0x5B41,0x0000,0x3E3E,0x4844,
+0x0000,0x7554,0x0000,0x0000,0x0000,0x5B47,0x0000,0x487A,
+0x0000,0x5B3E,0x0000,0x5B44,0x5B43,0x0000,0x0000,0x0000,
+0x404F,0x0000,0x8648,0x7555,0x0000,0x4B6D,0x0000,0x4E53,
+0x7556,0x0000,0x4B67,0x7557,0x324C,0x3B5E,0x0000,0x0000,
+0x4F48,0x5B46,0x3F75,0x0000,0x0000,0x0000,0x5B45,0x0000,
+0x0000,0x5B40,0x0000,0x0000,0x0000,0x0000,0x0000,0x384F,
+0x864C,0x0000,0x864D,0x5B4C,0x5B4A,0x0000,0x324D,0x5B48,
+0x5B4E,0x5B54,0x0000,0x7558,0x0000,0x0000,0x0000,0x0000,
+0x755A,0x4248,0x0000,0x864E,0x4A41,0x0000,0x5B56,0x0000,
+0x864F,0x0000,0x4922,0x0000,0x0000,0x0000,0x5B55,0x4770,
+0x4B3F,0x343B,0x8650,0x4077,0x3D40,0x0000,0x0000,0x755B,
+0x4453,0x8651,0x4D2E,0x8652,0x0000,0x5B51,0x5B50,0x0000,
+0x0000,0x0000,0x5B52,0x0000,0x5B4F,0x0000,0x0000,0x5B57,
+0x0000,0x5B4D,0x0000,0x0000,0x5B4B,0x0000,0x5B53,0x5B49,
+0x8653,0x436C,0x0000,0x4C78,0x3C46,0x3A74,0x0000,0x8654,
+0x0000,0x7559,0x0000,0x3A3A,0x755C,0x0000,0x4B6F,0x3341,
+
+/* 6800h */
+0x0000,0x755D,0x444E,0x464A,0x3149,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x864B,0x0000,0x0000,0x4072,0x0000,0x0000,0x4034,0x372A,
+0x8658,0x0000,0x0000,0x0000,0x0000,0x755F,0x5B59,0x8659,
+0x0000,0x393B,0x337C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x5B5B,0x3374,0x5B61,0x7560,0x865A,0x0000,0x0000,
+0x0000,0x7561,0x5B5E,0x865C,0x4073,0x0000,0x0000,0x0000,
+0x334B,0x3A2C,0x0000,0x865D,0x334A,0x3A4F,0x865E,0x0000,
+0x5B5C,0x3765,0x374B,0x456D,0x865F,0x8660,0x5B5A,0x0000,
+0x3046,0x8661,0x0000,0x0000,0x8662,0x5B5D,0x5B5F,0x0000,
+0x364D,0x372C,0x755E,0x343C,0x354B,0x8663,0x0000,0x8664,
+0x0000,0x5B62,0x0000,0x7562,0x3A79,0x4B71,0x0000,0x3B37,
+0x0000,0x0000,0x0000,0x5B63,0x0000,0x0000,0x0000,0x4930,
+0x0000,0x0000,0x0000,0x8666,0x0000,0x0000,0x8667,0x0000,
+0x0000,0x0000,0x7563,0x0000,0x5B6F,0x7564,0x3233,0x5B64,
+0x0000,0x0000,0x8668,0x0000,0x8669,0x0000,0x5B75,0x5B65,
+0x0000,0x4E42,0x866A,0x5B6C,0x0000,0x475F,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x5B74,0x0000,0x5B67,
+0x866B,0x0000,0x0000,0x3034,0x5B69,0x0000,0x866C,0x393C,
+0x866E,0x866F,0x8670,0x5B6B,0x8671,0x5B6A,0x0000,0x5B66,
+0x5B71,0x0000,0x3E3F,0x7566,0x0000,0x7567,0x546D,0x3868,
+0x4D7C,0x0000,0x8672,0x8673,0x0000,0x5B68,0x0000,0x4474,
+0x3323,0x3A2D,0x7568,0x5B60,0x8674,0x5B70,0x3361,0x0000,
+0x0000,0x5B6E,0x5B72,0x8675,0x456E,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x867A,0x347E,0x867B,0x5C32,0x0000,
+0x7569,0x4C49,0x5B77,0x347D,0x867C,0x5B7E,0x0000,0x867D,
+0x756A,0x0000,0x4B40,0x0000,0x5C21,0x5C23,0x867E,0x5C27,
+0x5B79,0x8721,0x432A,0x0000,0x0000,0x0000,0x0000,0x456F,
+0x5C2B,0x5B7C,0x0000,0x5C28,0x8722,0x8723,0x0000,0x5C22,
+0x756B,0x0000,0x0000,0x0000,0x8724,0x756C,0x3F39,0x5C2C,
+0x756D,0x756E,0x4033,0x0000,0x0000,0x0000,0x0000,0x8725,
+0x0000,0x5C2A,0x343D,0x8676,0x756F,0x0000,0x0000,0x0000,
+
+/* 6900h */
+0x4F50,0x5B76,0x0000,0x8726,0x5C26,0x3058,0x0000,0x8727,
+0x5B78,0x0000,0x7570,0x4C3A,0x5B7D,0x3F22,0x4447,0x5B73,
+0x0000,0x0000,0x5C25,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3F7A,0x5C2F,0x3371,0x3821,0x0000,0x0000,0x0000,
+0x0000,0x5C31,0x5B7A,0x5C30,0x0000,0x5C29,0x5B7B,0x0000,
+0x5C2D,0x0000,0x5C2E,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5C3F,0x0000,0x0000,0x0000,0x464E,0x7573,0x5C24,0x0000,
+0x0000,0x5C3B,0x0000,0x872B,0x0000,0x5C3D,0x0000,0x4458,
+0x0000,0x0000,0x7574,0x0000,0x0000,0x0000,0x872D,0x0000,
+0x0000,0x7571,0x4D4C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x4976,0x5C38,0x424A,0x0000,0x7575,
+0x0000,0x5C3E,0x413F,0x0000,0x5C35,0x5C42,0x5C41,0x0000,
+0x466F,0x5C40,0x466A,0x7576,0x7577,0x0000,0x0000,0x0000,
+0x7578,0x872E,0x5C44,0x5C37,0x872F,0x3648,0x5C3A,0x3D5D,
+0x0000,0x0000,0x8730,0x4760,0x5C3C,0x364B,0x0000,0x5C34,
+0x5C36,0x5C33,0x8731,0x0000,0x4F30,0x335A,0x5C39,0x8732,
+0x7579,0x5C43,0x3335,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x3A67,0x0000,0x0000,0x0000,0x315D,0x0000,
+0x0000,0x5C54,0x8733,0x0000,0x4F31,0x5C57,0x8735,0x0000,
+0x8736,0x0000,0x0000,0x3F3A,0x5C56,0x0000,0x0000,0x0000,
+0x5C55,0x0000,0x0000,0x0000,0x0000,0x757B,0x8737,0x5C52,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x757C,0x5C46,0x0000,
+0x8738,0x5C63,0x5C45,0x0000,0x5C58,0x0000,0x0000,0x8739,
+0x0000,0x0000,0x873A,0x5C50,0x873B,0x0000,0x5C4B,0x5C48,
+0x873C,0x5C49,0x0000,0x5C51,0x0000,0x0000,0x0000,0x7422,
+0x0000,0x0000,0x5C4E,0x393D,0x4448,0x4164,0x5C4C,0x757D,
+0x5C47,0x873D,0x0000,0x5C4A,0x0000,0x0000,0x873E,0x0000,
+0x4D4D,0x4B6A,0x0000,0x0000,0x0000,0x5C4F,0x5C59,0x0000,
+0x0000,0x0000,0x7622,0x8744,0x0000,0x0000,0x0000,0x5C61,
+0x5C5A,0x7623,0x7624,0x5C67,0x0000,0x5C65,0x8745,0x8746,
+0x0000,0x0000,0x5C60,0x8747,0x8749,0x7625,0x7626,0x0000,
+0x0000,0x5C5F,0x0000,0x4450,0x0000,0x4165,0x874A,0x5C5D,
+
+/* 6A00h */
+0x0000,0x0000,0x5C5B,0x0000,0x0000,0x5C62,0x0000,0x0000,
+0x0000,0x0000,0x5C68,0x4875,0x5C6E,0x0000,0x0000,0x7627,
+0x0000,0x874B,0x5C69,0x5C6C,0x5C66,0x7628,0x0000,0x4374,
+0x0000,0x4938,0x874C,0x5C5C,0x0000,0x874D,0x5C64,0x3E40,
+0x0000,0x4C4F,0x5C78,0x5C6B,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3822,0x3223,0x335F,0x0000,0x0000,0x5C53,0x0000,
+0x8741,0x0000,0x874F,0x8750,0x8751,0x3E41,0x5C70,0x0000,
+0x5C77,0x3C79,0x3372,0x762A,0x0000,0x432E,0x762B,0x8752,
+0x0000,0x0000,0x0000,0x0000,0x5C6D,0x762C,0x8753,0x5C72,
+0x5C76,0x8754,0x0000,0x3636,0x0000,0x0000,0x8756,0x0000,
+0x762D,0x0000,0x8757,0x0000,0x0000,0x0000,0x762E,0x0000,
+0x354C,0x5C74,0x0000,0x762F,0x0000,0x0000,0x0000,0x3521,
+0x0000,0x464B,0x5C73,0x0000,0x8758,0x0000,0x5C75,0x0000,
+0x0000,0x0000,0x0000,0x7630,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x5C6F,0x7631,0x0000,0x0000,0x0000,0x0000,
+0x5C71,0x0000,0x8755,0x0000,0x0000,0x0000,0x875A,0x3360,
+0x4349,0x0000,0x0000,0x875B,0x5C7C,0x0000,0x0000,0x0000,
+0x0000,0x7633,0x0000,0x875C,0x0000,0x5C7A,0x3869,0x0000,
+0x5C79,0x875E,0x0000,0x0000,0x7634,0x0000,0x0000,0x5D21,
+0x0000,0x0000,0x0000,0x0000,0x5B58,0x7635,0x7636,0x875F,
+0x5C7B,0x8760,0x5C7D,0x5C7E,0x0000,0x7637,0x0000,0x0000,
+0x0000,0x0000,0x5D2C,0x8762,0x5D28,0x0000,0x5B6D,0x0000,
+0x0000,0x0000,0x0000,0x5D27,0x0000,0x0000,0x0000,0x0000,
+0x5D26,0x0000,0x0000,0x5D23,0x0000,0x8763,0x0000,0x0000,
+0x0000,0x5C6A,0x5D25,0x5D24,0x0000,0x0000,0x8764,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8766,0x5D2A,0x0000,0x4F26,0x8765,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x5D2D,0x367B,0x8767,0x8768,0x5D29,0x5D2B,
+0x0000,0x0000,0x0000,0x0000,0x7638,0x0000,0x0000,0x7639,
+0x4827,0x0000,0x5D2E,0x0000,0x876B,0x0000,0x0000,0x0000,
+0x0000,0x876C,0x876D,0x876E,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x5D32,0x5D2F,0x0000,0x876F,0x0000,0x0000,
+
+/* 6B00h */
+0x0000,0x0000,0x0000,0x0000,0x4D73,0x5D30,0x0000,0x0000,
+0x0000,0x0000,0x5C5E,0x8771,0x0000,0x0000,0x0000,0x8772,
+0x8773,0x8774,0x5D33,0x0000,0x0000,0x0000,0x5D34,0x8776,
+0x0000,0x0000,0x0000,0x763C,0x0000,0x3135,0x763D,0x5D36,
+0x3767,0x3C21,0x0000,0x3655,0x0000,0x0000,0x0000,0x3224,
+0x0000,0x0000,0x0000,0x0000,0x763E,0x0000,0x0000,0x8778,
+0x0000,0x0000,0x4D5F,0x0000,0x0000,0x763F,0x0000,0x5D38,
+0x5D37,0x5D3A,0x353D,0x0000,0x0000,0x3656,0x343E,0x0000,
+0x0000,0x0000,0x0000,0x5D3D,0x0000,0x0000,0x7640,0x5D3C,
+0x0000,0x5D3E,0x8779,0x0000,0x324E,0x0000,0x4337,0x0000,
+0x5D3F,0x0000,0x0000,0x343F,0x5D41,0x0000,0x7641,0x0000,
+0x877A,0x5D40,0x0000,0x5D42,0x0000,0x0000,0x0000,0x5D43,
+0x7642,0x5D44,0x3B5F,0x4035,0x3A21,0x7643,0x4970,0x7644,
+0x0000,0x4A62,0x4F44,0x0000,0x877B,0x0000,0x0000,0x3B75,
+0x0000,0x0000,0x0000,0x3A50,0x4E72,0x877C,0x0000,0x7645,
+0x5D45,0x5D46,0x877D,0x3B60,0x0000,0x0000,0x0000,0x5D47,
+0x5D48,0x877E,0x7646,0x5D4A,0x5D49,0x0000,0x4B58,0x0000,
+0x0000,0x3D5E,0x3C6C,0x3B44,0x0000,0x5D4B,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x5D4D,0x3F23,0x0000,
+0x5D4C,0x0000,0x0000,0x8821,0x0000,0x0000,0x5D4E,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x5D4F,0x0000,0x0000,0x0000,
+0x0000,0x7647,0x5D50,0x5D51,0x0000,0x7648,0x8822,0x5D52,
+0x0000,0x5D54,0x5D53,0x5D55,0x3225,0x434A,0x0000,0x5D56,
+0x0000,0x0000,0x3B26,0x334C,0x5D57,0x8824,0x8825,0x4542,
+0x544C,0x0000,0x0000,0x0000,0x0000,0x3523,0x5D58,0x8826,
+0x8827,0x8828,0x0000,0x5D59,0x0000,0x4A6C,0x4B68,0x764A,
+0x0000,0x0000,0x4647,0x5D5A,0x4866,0x0000,0x764B,0x764C,
+0x487B,0x0000,0x8829,0x4C53,0x0000,0x0000,0x0000,0x5D5B,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x882A,0x882B,
+0x0000,0x0000,0x0000,0x5D5D,0x5D5C,0x0000,0x882C,0x5D5F,
+0x0000,0x882D,0x0000,0x5D5E,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x764D,
+
+/* 6C00h */
+0x0000,0x0000,0x882E,0x0000,0x0000,0x764E,0x0000,0x0000,
+0x5D61,0x0000,0x882F,0x0000,0x0000,0x0000,0x8830,0x3B61,
+0x764F,0x4C31,0x0000,0x5D62,0x5D63,0x0000,0x0000,0x3524,
+0x0000,0x0000,0x0000,0x5D64,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x5D66,0x5D65,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7650,0x3F65,0x8831,0x8832,0x4939,
+0x314A,0x0000,0x8833,0x0000,0x0000,0x0000,0x4845,0x8835,
+0x4475,0x3D41,0x3561,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x8836,0x4846,0x0000,
+0x3C2E,0x0000,0x0000,0x0000,0x0000,0x5D68,0x0000,0x3440,
+0x0000,0x7651,0x3178,0x8837,0x7652,0x4672,0x5D67,0x393E,
+0x4353,0x0000,0x5D69,0x0000,0x0000,0x0000,0x0000,0x884F,
+0x5D71,0x0000,0x5D6A,0x0000,0x0000,0x8838,0x0000,0x0000,
+0x4241,0x0000,0x3562,0x5D72,0x7654,0x0000,0x7655,0x0000,
+0x0000,0x0000,0x3768,0x0000,0x0000,0x3525,0x5D70,0x0000,
+0x0000,0x5D6E,0x5D6B,0x4D60,0x8839,0x7656,0x7657,0x0000,
+0x4440,0x883A,0x0000,0x0000,0x4659,0x5D6C,0x0000,0x0000,
+0x5D74,0x0000,0x5D73,0x3723,0x883C,0x883D,0x322D,0x883E,
+0x7658,0x3A3B,0x5D6D,0x5D6F,0x7659,0x0000,0x0000,0x0000,
+0x0000,0x4B57,0x4274,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7653,0x4B77,0x0000,0x883F,0x5D7C,0x0000,
+0x0000,0x5D7D,0x0000,0x324F,0x0000,0x0000,0x0000,0x0000,
+0x4A28,0x4C7D,0x5E21,0x3C23,0x3E42,0x5D78,0x5D7E,0x3168,
+0x0000,0x3637,0x8840,0x0000,0x5D75,0x5D7A,0x765B,0x0000,
+0x0000,0x4074,0x4771,0x0000,0x4867,0x0000,0x0000,0x0000,
+0x8841,0x0000,0x0000,0x5D77,0x765C,0x4B21,0x8843,0x5D79,
+0x0000,0x5E24,0x8844,0x5E22,0x8845,0x5D7B,0x0000,0x0000,
+0x765D,0x4B22,0x4748,0x3563,0x0000,0x4525,0x0000,0x0000,
+0x436D,0x8846,0x5E25,0x765E,0x8847,0x8848,0x765F,0x5E23,
+0x4259,0x5D76,0x0000,0x314B,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x765A,0x0000,0x0000,0x0000,0x0000,
+
+/* 6D00h */
+0x884A,0x0000,0x0000,0x0000,0x7661,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x884B,0x4D4E,0x5E30,0x0000,0x7662,0x0000,
+0x0000,0x0000,0x5E2F,0x0000,0x0000,0x0000,0x0000,0x4076,
+0x0000,0x5E2C,0x0000,0x4D6C,0x0000,0x0000,0x4636,0x5E26,
+0x0000,0x0000,0x0000,0x0000,0x884C,0x4445,0x884D,0x884E,
+0x0000,0x314C,0x393F,0x5E29,0x0000,0x0000,0x7663,0x8850,
+0x0000,0x7664,0x3D27,0x5E2E,0x8865,0x5E2D,0x5E28,0x0000,
+0x5E2B,0x7665,0x0000,0x3368,0x8851,0x5E2A,0x4749,0x7666,
+0x0000,0x4E2E,0x0000,0x0000,0x3E74,0x4075,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7667,0x5E36,0x5E34,0x8852,0x494D,0x0000,0x8853,0x0000,
+0x8854,0x0000,0x0000,0x5E31,0x5E33,0x7668,0x313A,0x0000,
+0x0000,0x3940,0x4F32,0x0000,0x333D,0x0000,0x4962,0x0000,
+0x8855,0x0000,0x0000,0x0000,0x4D61,0x0000,0x0000,0x3324,
+0x3F3B,0x5E35,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8856,0x8857,0x766A,0x0000,0x0000,0x5E3A,0x0000,0x766B,
+0x3E43,0x766C,0x8858,0x0000,0x4D30,0x8859,0x5E37,0x0000,
+0x0000,0x885A,0x0000,0x5E32,0x766D,0x5E38,0x0000,0x0000,
+0x885B,0x4E5E,0x0000,0x4573,0x4642,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x766E,0x8861,0x766F,0x0000,0x8862,0x3336,
+0x0000,0x0000,0x3155,0x0000,0x8863,0x5E3E,0x0000,0x0000,
+0x5E41,0x0000,0x0000,0x0000,0x4E43,0x0000,0x0000,0x7670,
+0x4D64,0x0000,0x8864,0x0000,0x7671,0x5E48,0x5E42,0x5E3F,
+0x8866,0x0000,0x0000,0x4E54,0x5E45,0x0000,0x8867,0x8868,
+0x8869,0x3D4A,0x5E47,0x0000,0x0000,0x5E4C,0x7672,0x0000,
+0x4571,0x5E4A,0x7673,0x7674,0x0000,0x7675,0x5E44,0x886A,
+0x0000,0x4338,0x0000,0x0000,0x5E4B,0x0000,0x5E40,0x0000,
+0x5E46,0x886B,0x5E4D,0x307C,0x5E43,0x0000,0x5E4E,0x0000,
+0x0000,0x3F3C,0x0000,0x3D5F,0x0000,0x4A25,0x886C,0x3A2E,
+0x0000,0x5E3B,0x5E49,0x453A,0x7676,0x0000,0x0000,0x0000,
+
+/* 6E00h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x4036,0x0000,0x3369,
+0x3A51,0x3E44,0x5E3D,0x3D42,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x374C,0x0000,0x5E3C,0x0000,0x885D,
+0x0000,0x5E52,0x3D6D,0x383A,0x0000,0x5E61,0x886E,0x5E5B,
+0x3574,0x454F,0x886F,0x5E56,0x5E5F,0x302F,0x3132,0x8870,
+0x0000,0x3239,0x0000,0x5E58,0x422C,0x5E4F,0x5E51,0x3941,
+0x0000,0x0000,0x8872,0x0000,0x7678,0x0000,0x886D,0x0000,
+0x5E62,0x0000,0x5E5D,0x0000,0x8873,0x0000,0x5E55,0x0000,
+0x0000,0x0000,0x0000,0x5E5C,0x7679,0x0000,0x0000,0x0000,
+0x8874,0x8875,0x4C2B,0x8876,0x8877,0x5E5A,0x5E5E,0x8878,
+0x0000,0x8879,0x0000,0x887A,0x887B,0x0000,0x3850,0x887C,
+0x3E45,0x0000,0x0000,0x4339,0x767A,0x0000,0x767B,0x5E54,
+0x0000,0x0000,0x0000,0x887D,0x0000,0x0000,0x0000,0x4D2F,
+0x0000,0x0000,0x0000,0x5E57,0x0000,0x0000,0x5E50,0x4572,
+0x0000,0x0000,0x5E53,0x0000,0x0000,0x0000,0x5E59,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4F51,0x3C3E,
+0x4B7E,0x0000,0x5E63,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x482E,0x0000,0x0000,0x5E6F,
+0x383B,0x0000,0x0000,0x8921,0x0000,0x0000,0x3D60,0x0000,
+0x5E65,0x0000,0x0000,0x0000,0x4E2F,0x3942,0x0000,0x5E72,
+0x0000,0x0000,0x306E,0x0000,0x0000,0x5E70,0x0000,0x8922,
+0x0000,0x0000,0x5E64,0x767C,0x0000,0x0000,0x0000,0x5E6A,
+0x0000,0x767D,0x5E6C,0x0000,0x8923,0x0000,0x4D4F,0x5E67,
+0x0000,0x0000,0x452E,0x0000,0x0000,0x5E69,0x0000,0x8924,
+0x0000,0x767E,0x5E71,0x8925,0x5E6B,0x4C47,0x0000,0x7721,
+0x0000,0x5E66,0x8926,0x3C22,0x5E7E,0x0000,0x7722,0x0000,
+0x0000,0x336A,0x0000,0x5E68,0x5E6D,0x5E6E,0x0000,0x0000,
+0x0000,0x8927,0x0000,0x0000,0x0000,0x426C,0x425A,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x8929,0x5E76,0x0000,0x0000,0x5E7C,
+0x0000,0x0000,0x5E7A,0x0000,0x4529,0x0000,0x0000,0x5F23,
+0x5E77,0x892A,0x0000,0x892B,0x0000,0x0000,0x5E78,0x5E60,
+
+/* 6F00h */
+0x0000,0x3579,0x493A,0x0000,0x0000,0x0000,0x3C3F,0x0000,
+0x0000,0x3977,0x892C,0x0000,0x892D,0x0000,0x0000,0x4F33,
+0x7723,0x5E74,0x0000,0x5F22,0x3169,0x4166,0x0000,0x0000,
+0x892E,0x0000,0x7724,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4779,0x0000,0x3441,0x4E7A,0x0000,0x892F,0x0000,0x0000,
+0x0000,0x0000,0x7726,0x4C21,0x4452,0x0000,0x0000,0x7727,
+0x0000,0x5E7B,0x5E7D,0x7728,0x0000,0x8928,0x8930,0x0000,
+0x4132,0x0000,0x0000,0x0000,0x8931,0x0000,0x5F21,0x5E79,
+0x0000,0x5E73,0x0000,0x0000,0x0000,0x3443,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x7729,0x8933,0x0000,0x3769,0x0000,0x0000,0x8934,
+0x5F2F,0x772A,0x8935,0x5F2A,0x4078,0x0000,0x772B,0x3363,
+0x8936,0x772C,0x772D,0x0000,0x3D61,0x0000,0x5F33,0x0000,
+0x8937,0x0000,0x0000,0x0000,0x0000,0x5F2C,0x442C,0x5F29,
+0x4459,0x0000,0x0000,0x0000,0x5F4C,0x0000,0x0000,0x0000,
+0x5F26,0x0000,0x5F25,0x0000,0x5F2E,0x8939,0x772E,0x0000,
+0x5F28,0x5F27,0x5F2D,0x0000,0x4021,0x0000,0x5F24,0x0000,
+0x772F,0x0000,0x0000,0x0000,0x7730,0x7731,0x5F30,0x0000,
+0x893A,0x5F31,0x0000,0x0000,0x7732,0x0000,0x893B,0x3442,
+0x8938,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x893D,
+0x7733,0x5F36,0x0000,0x5F35,0x5F37,0x893E,0x0000,0x7734,
+0x0000,0x0000,0x5F3A,0x0000,0x0000,0x0000,0x0000,0x893F,
+0x0000,0x4543,0x0000,0x5F34,0x0000,0x8941,0x7735,0x0000,
+0x0000,0x5F38,0x0000,0x0000,0x7736,0x0000,0x893C,0x0000,
+0x3763,0x4279,0x5F32,0x473B,0x0000,0x0000,0x5F39,0x7737,
+0x8942,0x8943,0x7738,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x5F3E,0x5F3C,0x0000,0x0000,
+0x5F3F,0x0000,0x8944,0x5F42,0x0000,0x0000,0x8945,0x5F3B,
+0x396A,0x4728,0x0000,0x0000,0x5E39,0x0000,0x0000,0x0000,
+0x0000,0x8946,0x0000,0x4D74,0x5F3D,0x0000,0x5F41,0x4275,
+0x773A,0x5F40,0x0000,0x5F2B,0x0000,0x773B,0x6F69,0x0000,
+0x0000,0x7739,0x5F45,0x0000,0x8948,0x0000,0x5F49,0x0000,
+
+/* 7000h */
+0x8949,0x5F47,0x0000,0x0000,0x0000,0x773C,0x773D,0x894A,
+0x0000,0x5F43,0x894B,0x5F44,0x0000,0x0000,0x0000,0x5F48,
+0x0000,0x5F46,0x0000,0x0000,0x0000,0x494E,0x0000,0x0000,
+0x5F4E,0x0000,0x5F4B,0x5F4A,0x0000,0x5F4D,0x4654,0x5F4F,
+0x0000,0x0000,0x0000,0x894C,0x0000,0x0000,0x4375,0x426D,
+0x773E,0x0000,0x0000,0x0000,0x4025,0x0000,0x0000,0x0000,
+0x5F50,0x0000,0x5F52,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x894E,0x894F,0x0000,0x8950,0x0000,0x5F51,0x0000,
+0x0000,0x0000,0x0000,0x8951,0x0000,0x0000,0x0000,0x8952,
+0x0000,0x0000,0x773F,0x8953,0x5E75,0x0000,0x7742,0x0000,
+0x0000,0x5F53,0x0000,0x0000,0x8955,0x0000,0x0000,0x0000,
+0x4667,0x0000,0x0000,0x0000,0x0000,0x7740,0x7741,0x0000,
+0x0000,0x0000,0x0000,0x5F54,0x7743,0x8956,0x0000,0x0000,
+0x0000,0x8957,0x0000,0x3250,0x8958,0x0000,0x8959,0x4574,
+0x3325,0x0000,0x0000,0x0000,0x0000,0x7744,0x895A,0x0000,
+0x3564,0x0000,0x0000,0x0000,0x3C5E,0x3A52,0x895B,0x0000,
+0x0000,0x895C,0x0000,0x0000,0x0000,0x7745,0x895D,0x0000,
+0x0000,0x4F27,0x3F66,0x0000,0x0000,0x0000,0x316A,0x0000,
+0x0000,0x0000,0x5F56,0x0000,0x0000,0x895E,0x0000,0x895F,
+0x0000,0x5F55,0x0000,0x0000,0x0000,0x0000,0x0000,0x8962,
+0x0000,0x0000,0x0000,0x0000,0x7746,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7747,0x5F59,0x433A,0x5F5C,0x5F57,
+0x0000,0x8963,0x0000,0x5F5B,0x0000,0x0000,0x0000,0x7748,
+0x5F5A,0x4540,0x3059,0x8960,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4E75,0x0000,0x8966,0x5F5E,0x0000,0x0000,0x0000,0x3128,
+0x0000,0x8967,0x0000,0x8968,0x7749,0x0000,0x0000,0x0000,
+0x774A,0x5F60,0x0000,0x0000,0x8969,0x5F5F,0x0000,0x5F5D,
+0x0000,0x0000,0x0000,0x0000,0x774B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x8965,0x0000,0x0000,0x0000,
+0x0000,0x5F58,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4B23,0x0000,0x0000,0x0000,0x5F62,0x0000,0x0000,
+
+/* 7100h */
+0x0000,0x0000,0x0000,0x896A,0x896B,0x0000,0x896C,0x896D,
+0x896E,0x5F61,0x0000,0x0000,0x896F,0x0000,0x0000,0x774C,
+0x0000,0x0000,0x0000,0x0000,0x316B,0x0000,0x0000,0x0000,
+0x0000,0x5F64,0x4A32,0x0000,0x5F63,0x0000,0x774E,0x0000,
+0x774F,0x4C35,0x0000,0x0000,0x0000,0x0000,0x3E47,0x0000,
+0x0000,0x0000,0x0000,0x774D,0x0000,0x0000,0x7750,0x8971,
+0x7751,0x8972,0x0000,0x0000,0x0000,0x0000,0x4133,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x3E46,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7752,0x7753,
+0x0000,0x4E7B,0x8974,0x0000,0x5F6A,0x0000,0x4079,0x0000,
+0x8973,0x7754,0x7756,0x8975,0x0000,0x5F66,0x5F6B,0x0000,
+0x0000,0x316C,0x0000,0x0000,0x7757,0x0000,0x8976,0x0000,
+0x7758,0x0000,0x5F69,0x0000,0x4761,0x5F65,0x5F68,0x3E48,
+0x7759,0x4851,0x0000,0x0000,0x5F6C,0x0000,0x3C51,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x407A,0x0000,0x0000,
+0x8979,0x0000,0x0000,0x0000,0x5F6F,0x775B,0x0000,0x775C,
+0x5F67,0x0000,0x3727,0x0000,0x0000,0x0000,0x0000,0x5F6D,
+0x0000,0x0000,0x775D,0x0000,0x4D50,0x5F70,0x8978,0x0000,
+0x0000,0x7426,0x0000,0x897A,0x0000,0x0000,0x0000,0x3D4F,
+0x897B,0x0000,0x897C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x5F71,0x0000,0x0000,0x0000,0x5F72,0x0000,0x897D,0x897E,
+0x0000,0x472E,0x0000,0x8A21,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x5F74,0x775F,0x0000,0x0000,0x0000,0x5F75,0x0000,
+0x0000,0x775E,0x0000,0x4733,0x7760,0x0000,0x0000,0x0000,
+0x4575,0x5F77,0x0000,0x8A23,0x0000,0x0000,0x5F79,0x0000,
+0x4E55,0x0000,0x5F76,0x8A24,0x5F78,0x316D,0x0000,0x5F73,
+0x0000,0x8A25,0x0000,0x0000,0x8A26,0x0000,0x0000,0x535B,
+0x5F7A,0x0000,0x0000,0x0000,0x0000,0x4167,0x3B38,0x5F7C,
+0x0000,0x0000,0x0000,0x0000,0x5F7B,0x3F24,0x5259,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x5F7D,0x0000,0x0000,
+0x0000,0x6021,0x0000,0x5F6E,0x5F7E,0x0000,0x7761,0x6022,
+
+/* 7200h */
+0x7762,0x0000,0x0000,0x0000,0x0000,0x0000,0x477A,0x8A27,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6023,0x0000,0x0000,
+0x6024,0x0000,0x0000,0x0000,0x0000,0x7763,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6025,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6026,0x0000,0x445E,0x8A2A,0x6028,0x6027,0x0000,0x0000,
+0x6029,0x0000,0x602A,0x0000,0x8A2B,0x3C5F,0x4963,0x0000,
+0x8A2C,0x8A2D,0x4C6C,0x602B,0x602C,0x4156,0x3C24,0x602D,
+0x602E,0x0000,0x8A2F,0x0000,0x0000,0x0000,0x602F,0x4A52,
+0x4847,0x0000,0x0000,0x6030,0x4757,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x442D,0x8A30,0x0000,0x7764,0x7765,0x8A31,
+0x6031,0x3267,0x0000,0x356D,0x0000,0x4C46,0x0000,0x4C36,
+0x0000,0x3234,0x4F34,0x8A32,0x0000,0x0000,0x0000,0x4B52,
+0x0000,0x4A2A,0x0000,0x0000,0x0000,0x0000,0x8A34,0x8A35,
+0x0000,0x0000,0x4037,0x0000,0x6032,0x0000,0x0000,0x0000,
+0x8A36,0x4643,0x0000,0x0000,0x0000,0x3823,0x6033,0x8A37,
+0x3A54,0x6035,0x6034,0x0000,0x0000,0x0000,0x0000,0x6036,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7767,0x8A38,0x0000,
+0x0000,0x0000,0x6037,0x0000,0x0000,0x0000,0x6038,0x0000,
+0x0000,0x0000,0x0000,0x7768,0x0000,0x0000,0x0000,0x0000,
+0x353E,0x0000,0x6039,0x0000,0x0000,0x0000,0x0000,0x603A,
+0x0000,0x0000,0x0000,0x0000,0x3824,0x8A3A,0x8A3B,0x4848,
+0x8A3C,0x8A3D,0x603C,0x0000,0x0000,0x0000,0x3E75,0x0000,
+0x0000,0x603B,0x0000,0x0000,0x0000,0x0000,0x7769,0x0000,
+0x776A,0x8A3E,0x3638,0x603D,0x603F,0x0000,0x603E,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x8A40,0x0000,0x6040,0x0000,
+0x3851,0x0000,0x6041,0x0000,0x0000,0x0000,0x0000,0x3669,
+0x0000,0x4140,0x0000,0x397D,0x0000,0x0000,0x0000,0x0000,
+0x6043,0x6044,0x6042,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3C6D,0x0000,0x0000,0x4648,0x3639,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x8A43,0x0000,0x0000,0x0000,0x6046,
+0x432C,0x6045,0x8A44,0x776B,0x4F35,0x4762,0x0000,0x0000,
+
+/* 7300h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8A45,
+0x0000,0x0000,0x6049,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x8A46,0x0000,0x0000,0x0000,0x604B,0x6048,
+0x8A47,0x8A48,0x0000,0x4C54,0x604A,0x604C,0x0000,0x4E44,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6050,0x0000,0x776D,
+0x776E,0x604F,0x4376,0x472D,0x8A4B,0x0000,0x3825,0x604E,
+0x0000,0x8A4C,0x0000,0x8A4D,0x604D,0x0000,0x4D31,0x4D32,
+0x0000,0x8A4A,0x0000,0x0000,0x0000,0x8A4E,0x6051,0x316E,
+0x0000,0x0000,0x0000,0x0000,0x3976,0x3B62,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6052,0x6053,
+0x7770,0x0000,0x8A4F,0x0000,0x0000,0x0000,0x0000,0x6055,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3D43,0x0000,0x0000,0x7771,0x0000,
+0x6057,0x0000,0x6056,0x8A51,0x8A52,0x0000,0x8A54,0x8A55,
+0x6058,0x8A56,0x334D,0x0000,0x0000,0x605A,0x0000,0x8A57,
+0x6059,0x0000,0x605C,0x605B,0x7772,0x0000,0x0000,0x0000,
+0x0000,0x8A58,0x0000,0x0000,0x383C,0x8A59,0x0000,0x4E28,
+0x0000,0x364C,0x8A5A,0x3226,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x8A5B,0x7773,0x366A,0x0000,
+0x8A5C,0x0000,0x0000,0x0000,0x8A5D,0x0000,0x8A5E,0x7774,
+0x7775,0x0000,0x7776,0x0000,0x0000,0x8A5F,0x7777,0x0000,
+0x8A60,0x3461,0x0000,0x7778,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4E68,0x605E,0x0000,0x8A61,0x0000,0x8A62,
+0x0000,0x8A63,0x0000,0x6060,0x8A64,0x0000,0x0000,0x8A65,
+0x6061,0x0000,0x3251,0x0000,0x0000,0x8A66,0x0000,0x0000,
+0x605D,0x7779,0x3B39,0x8A67,0x0000,0x4441,0x605F,0x777A,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x777B,0x0000,
+0x0000,0x777C,0x0000,0x0000,0x0000,0x0000,0x6064,0x0000,
+0x3C6E,0x8A68,0x0000,0x777D,0x0000,0x6062,0x0000,0x8A69,
+0x0000,0x777E,0x373E,0x0000,0x0000,0x4849,0x6063,0x0000,
+0x0000,0x607E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6069,0x8A6A,0x8A6C,0x0000,0x0000,0x0000,0x383D,0x0000,
+
+/* 7400h */
+0x0000,0x8A6D,0x0000,0x3565,0x0000,0x6066,0x4D7D,0x7821,
+0x0000,0x4E30,0x7822,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x8A6B,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7823,0x7824,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4276,0x0000,0x8A6E,0x6068,0x7826,0x0000,
+0x7827,0x0000,0x7828,0x7829,0x782A,0x0000,0x782B,0x782C,
+0x782D,0x8A6F,0x606A,0x4E56,0x3657,0x487C,0x474A,0x0000,
+0x0000,0x8A70,0x606B,0x0000,0x0000,0x0000,0x0000,0x606D,
+0x8A72,0x6070,0x0000,0x8A73,0x782E,0x0000,0x782F,0x7830,
+0x0000,0x0000,0x0000,0x7831,0x0000,0x8A74,0x0000,0x0000,
+0x0000,0x0000,0x8A75,0x8A71,0x0000,0x606C,0x0000,0x7832,
+0x0000,0x606F,0x386A,0x314D,0x6071,0x8A76,0x3F70,0x606E,
+0x4E5C,0x0000,0x7833,0x6074,0x7424,0x0000,0x0000,0x0000,
+0x0000,0x6072,0x6075,0x7834,0x0000,0x7835,0x0000,0x6067,
+0x6073,0x8A77,0x0000,0x3A3C,0x0000,0x0000,0x6076,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6077,0x0000,
+0x0000,0x8A78,0x0000,0x4D7E,0x0000,0x8A79,0x7836,0x7837,
+0x8A7A,0x7838,0x0000,0x6078,0x0000,0x0000,0x0000,0x0000,
+0x783D,0x0000,0x8A7C,0x0000,0x0000,0x0000,0x0000,0x8A7D,
+0x7839,0x8A7E,0x0000,0x0000,0x783A,0x0000,0x6079,0x783B,
+0x8B21,0x8B22,0x6065,0x783C,0x0000,0x8B23,0x783E,0x607A,
+0x783F,0x7840,0x8B24,0x8B25,0x0000,0x0000,0x0000,0x0000,
+0x3444,0x0000,0x0000,0x0000,0x0000,0x7841,0x0000,0x0000,
+0x0000,0x8B26,0x8B28,0x8B27,0x0000,0x3C25,0x0000,0x7842,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7843,0x7844,0x607B,0x0000,0x0000,0x0000,0x0000,0x607C,
+0x0000,0x0000,0x0000,0x0000,0x607D,0x0000,0x8B29,0x0000,
+0x8B2A,0x0000,0x7845,0x0000,0x313B,0x0000,0x8B2B,0x0000,
+0x6121,0x0000,0x493B,0x6122,0x0000,0x0000,0x3424,0x6123,
+0x0000,0x6124,0x0000,0x8B2D,0x0000,0x0000,0x6125,0x8B2C,
+0x6127,0x6128,0x6126,0x0000,0x0000,0x0000,0x4953,0x612A,
+0x6129,0x0000,0x8B2F,0x0000,0x0000,0x0000,0x0000,0x7846,
+
+/* 7500h */
+0x0000,0x7847,0x0000,0x612C,0x612B,0x612D,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x612E,0x6130,0x612F,0x0000,
+0x0000,0x3979,0x0000,0x6132,0x0000,0x6131,0x0000,0x7848,
+0x3445,0x0000,0x3F53,0x0000,0x453C,0x0000,0x6133,0x4038,
+0x8B31,0x0000,0x0000,0x3B3A,0x8B32,0x3179,0x6134,0x0000,
+0x4D51,0x0000,0x8B33,0x4A63,0x6135,0x0000,0x0000,0x7849,
+0x4544,0x4D33,0x3943,0x3F3D,0x0000,0x0000,0x0000,0x434B,
+0x5234,0x0000,0x442E,0x3268,0x6136,0x8B36,0x8B37,0x0000,
+0x8B38,0x0000,0x0000,0x0000,0x6137,0x0000,0x613C,0x0000,
+0x8B39,0x613A,0x6139,0x5A42,0x3326,0x6138,0x8B3A,0x305A,
+0x8B3B,0x482A,0x8B3C,0x0000,0x484A,0x0000,0x0000,0x0000,
+0x0000,0x4E31,0x613D,0x613B,0x435C,0x4026,0x0000,0x0000,
+0x482B,0x0000,0x492D,0x0000,0x613F,0x4E2C,0x374D,0x6140,
+0x0000,0x613E,0x4856,0x6141,0x8B3D,0x6142,0x0000,0x784A,
+0x305B,0x8B3F,0x8B3E,0x3E76,0x6147,0x0000,0x6144,0x466D,
+0x6143,0x784B,0x8B40,0x0000,0x0000,0x8B41,0x8B42,0x3526,
+0x0000,0x8B43,0x614A,0x0000,0x0000,0x0000,0x6145,0x6146,
+0x0000,0x6149,0x6148,0x4925,0x8B45,0x0000,0x4142,0x4141,
+0x0000,0x353F,0x784C,0x0000,0x614B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x614C,0x0000,0x0000,0x614D,0x0000,0x0000,
+0x0000,0x0000,0x8B47,0x614F,0x0000,0x614E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3156,0x0000,0x0000,0x0000,0x0000,
+0x8B49,0x6157,0x4868,0x6151,0x0000,0x6153,0x0000,0x8B4A,
+0x6155,0x3F3E,0x0000,0x0000,0x6156,0x6154,0x3C40,0x8B4B,
+0x8B4C,0x0000,0x6150,0x6152,0x0000,0x4942,0x8B4D,0x3E49,
+0x0000,0x0000,0x6159,0x0000,0x0000,0x6158,0x784E,0x8B4E,
+0x0000,0x0000,0x615A,0x8B4F,0x3C26,0x3A2F,0x0000,0x0000,
+0x4577,0x615B,0x0000,0x444B,0x0000,0x8B50,0x615D,0x8B51,
+0x8B52,0x0000,0x4E21,0x615C,0x784F,0x0000,0x0000,0x8B53,
+0x0000,0x4169,0x0000,0x0000,0x8B54,0x0000,0x8B55,0x0000,
+0x6162,0x8B56,0x6164,0x6165,0x4354,0x0000,0x0000,0x0000,
+0x0000,0x8B57,0x6163,0x0000,0x6160,0x0000,0x615E,0x615F,
+
+/* 7600h */
+0x7850,0x6161,0x7851,0x8B58,0x0000,0x0000,0x0000,0x8B5A,
+0x7852,0x6168,0x0000,0x6166,0x0000,0x6167,0x0000,0x8B5B,
+0x0000,0x0000,0x0000,0x8B5E,0x0000,0x7853,0x7854,0x0000,
+0x8B59,0x7855,0x0000,0x8B5F,0x8B60,0x0000,0x7856,0x6169,
+0x616B,0x616C,0x616D,0x0000,0x616E,0x8B62,0x7E7D,0x616A,
+0x8B63,0x0000,0x0000,0x0000,0x0000,0x7857,0x0000,0x0000,
+0x6170,0x0000,0x0000,0x8B65,0x616F,0x7858,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6171,0x8B64,0x0000,0x0000,0x0000,
+0x0000,0x8B68,0x4E45,0x7859,0x0000,0x0000,0x6174,0x6172,
+0x6173,0x8B6A,0x0000,0x785A,0x3462,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4C7E,0x0000,0x0000,0x8B6B,0x4A4A,0x0000,
+0x6176,0x0000,0x0000,0x0000,0x6175,0x0000,0x0000,0x0000,
+0x0000,0x6177,0x6178,0x0000,0x785B,0x785C,0x0000,0x617C,
+0x6179,0x617A,0x617B,0x0000,0x617D,0x785D,0x8B6D,0x785E,
+0x617E,0x785F,0x6221,0x0000,0x0000,0x0000,0x6222,0x0000,
+0x6223,0x0000,0x482F,0x4550,0x6224,0x4772,0x4934,0x0000,
+0x6225,0x7860,0x0000,0x6226,0x452A,0x0000,0x3327,0x3944,
+0x6227,0x0000,0x0000,0x6228,0x0000,0x0000,0x6229,0x0000,
+0x3B29,0x0000,0x0000,0x622B,0x0000,0x8B6E,0x622A,0x0000,
+0x0000,0x622C,0x622D,0x7861,0x8B6F,0x7862,0x7863,0x0000,
+0x8B71,0x8B70,0x0000,0x0000,0x0000,0x0000,0x7864,0x8B72,
+0x8B73,0x0000,0x7865,0x0000,0x0000,0x0000,0x4869,0x8B74,
+0x622E,0x0000,0x0000,0x0000,0x622F,0x0000,0x7866,0x7369,
+0x6230,0x6231,0x6232,0x0000,0x0000,0x0000,0x0000,0x3B2E,
+0x0000,0x0000,0x6233,0x4756,0x0000,0x7867,0x4B5F,0x0000,
+0x314E,0x8B76,0x3157,0x0000,0x7868,0x6234,0x7869,0x0000,
+0x0000,0x0000,0x6236,0x0000,0x786A,0x0000,0x6235,0x4570,
+0x0000,0x0000,0x0000,0x4039,0x5D39,0x0000,0x6237,0x4C41,
+0x0000,0x6238,0x0000,0x3446,0x4857,0x6239,0x786B,0x623A,
+0x8B78,0x0000,0x623B,0x0000,0x8B79,0x0000,0x4C5C,0x0000,
+0x0000,0x786C,0x4C55,0x0000,0x443E,0x0000,0x0000,0x0000,
+0x416A,0x0000,0x0000,0x623D,0x786D,0x0000,0x3D62,0x0000,
+
+/* 7700h */
+0x0000,0x3E4A,0x0000,0x0000,0x6240,0x0000,0x0000,0x623F,
+0x623E,0x487D,0x786E,0x3447,0x3829,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8B7B,
+0x0000,0x786F,0x8B7C,0x6246,0x0000,0x0000,0x6243,0x3F3F,
+0x4C32,0x0000,0x0000,0x0000,0x6242,0x6244,0x6245,0x0000,
+0x0000,0x6241,0x0000,0x0000,0x0000,0x8B7D,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x7870,0x8B7E,0x7871,0x6247,
+0x6248,0x0000,0x442F,0x0000,0x3463,0x0000,0x0000,0x0000,
+0x4365,0x0000,0x0000,0x0000,0x0000,0x0000,0x7872,0x6249,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7873,0x7874,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8C25,0x0000,0x624A,0x624D,0x7875,0x0000,0x0000,0x7876,
+0x8C26,0x3F67,0x7877,0x4644,0x0000,0x624E,0x4B53,0x0000,
+0x624B,0x0000,0x8C27,0x624C,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x8C29,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6251,0x7878,0x0000,0x8C2A,0x8C2B,0x6250,0x624F,
+0x7879,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6253,0x0000,0x0000,0x6252,0x0000,
+0x0000,0x6254,0x0000,0x0000,0x787A,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x8C2E,0x0000,0x0000,0x0000,0x6256,0x8C2F,
+0x6255,0x0000,0x8C30,0x0000,0x8C31,0x4A4D,0x0000,0x0000,
+0x0000,0x8C32,0x787B,0x0000,0x3D56,0x4E46,0x0000,0x0000,
+0x6257,0x0000,0x0000,0x4637,0x0000,0x0000,0x6258,0x0000,
+0x0000,0x6259,0x0000,0x625D,0x625B,0x625C,0x0000,0x625A,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x625E,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x625F,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6260,
+0x0000,0x0000,0x6261,0x4C37,0x6262,0x0000,0x8C33,0x8C34,
+0x787C,0x0000,0x4C70,0x6263,0x8C35,0x434E,0x8C36,0x476A,
+0x0000,0x366B,0x8C37,0x0000,0x8C38,0x433B,0x6264,0x363A,
+0x8C3A,0x0000,0x0000,0x4050,0x8C3B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x8C3C,0x6265,0x0000,0x0000,0x0000,
+
+/* 7800h */
+0x0000,0x0000,0x3A3D,0x0000,0x0000,0x8C3E,0x8C3F,0x0000,
+0x0000,0x8C40,0x0000,0x0000,0x6266,0x8C41,0x0000,0x0000,
+0x0000,0x0000,0x6267,0x0000,0x3826,0x3A55,0x0000,0x0000,
+0x0000,0x8C42,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6269,0x8C43,0x0000,0x0000,0x0000,0x4556,0x3A56,0x354E,
+0x0000,0x0000,0x0000,0x0000,0x8C44,0x787D,0x0000,0x0000,
+0x0000,0x0000,0x4B24,0x0000,0x474B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x4557,0x0000,0x0000,0x0000,0x0000,0x395C,
+0x0000,0x0000,0x0000,0x7921,0x0000,0x626B,0x0000,0x8C45,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7922,0x7923,
+0x0000,0x7924,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x3E4B,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x8C46,0x0000,0x0000,0x0000,
+0x7925,0x0000,0x8C47,0x4E32,0x3945,0x0000,0x7926,0x3827,
+0x0000,0x0000,0x4823,0x0000,0x626D,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x626F,0x0000,0x0000,0x0000,
+0x0000,0x386B,0x0000,0x0000,0x0000,0x0000,0x626E,0x4476,
+0x0000,0x0000,0x8C49,0x0000,0x6271,0x3337,0x626C,0x0000,
+0x0000,0x486A,0x0000,0x3130,0x8C4A,0x3A6C,0x0000,0x4F52,
+0x0000,0x0000,0x6270,0x0000,0x0000,0x8C4C,0x8C4D,0x8C4E,
+0x0000,0x0000,0x0000,0x6272,0x8C4B,0x0000,0x0000,0x4A4B,
+0x0000,0x4059,0x6274,0x0000,0x0000,0x792A,0x0000,0x6275,
+0x7928,0x0000,0x0000,0x0000,0x0000,0x6273,0x0000,0x0000,
+0x0000,0x0000,0x334E,0x8C4F,0x627B,0x0000,0x627A,0x0000,
+0x0000,0x3C27,0x0000,0x0000,0x0000,0x627C,0x6277,0x0000,
+0x8C50,0x0000,0x627D,0x6278,0x8C51,0x0000,0x8C52,0x0000,
+0x4858,0x6276,0x0000,0x0000,0x6279,0x8C53,0x0000,0x0000,
+0x0000,0x0000,0x6322,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8C54,0x8C55,0x0000,0x0000,0x792B,0x0000,0x8C56,0x6321,
+0x4B61,0x0000,0x0000,0x0000,0x627E,0x0000,0x0000,0x306B,
+0x0000,0x0000,0x792C,0x0000,0x6324,0x0000,0x0000,0x792E,
+0x0000,0x8C57,0x8C58,0x8C59,0x0000,0x6323,0x8C5A,0x0000,
+
+/* 7900h */
+0x792D,0x3E4C,0x0000,0x0000,0x0000,0x0000,0x0000,0x6325,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4143,0x0000,
+0x8C5C,0x6327,0x6326,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6328,0x0000,0x8C5D,0x792F,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x8C5F,0x6268,0x0000,
+0x0000,0x0000,0x626A,0x632A,0x6329,0x0000,0x7930,0x0000,
+0x8C5E,0x7931,0x0000,0x0000,0x7932,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x3C28,0x8C60,0x4E69,0x0000,0x3C52,0x0000,
+0x632B,0x3737,0x0000,0x0000,0x0000,0x7935,0x7936,0x3540,
+0x3527,0x3B63,0x8C61,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4D34,0x0000,0x0000,0x6331,0x0000,0x6330,0x4144,0x632D,
+0x8C62,0x0000,0x632F,0x8C63,0x793A,0x3D4B,0x3F40,0x632E,
+0x632C,0x0000,0x472A,0x0000,0x0000,0x3E4D,0x0000,0x8C65,
+0x493C,0x0000,0x0000,0x0000,0x0000,0x3A57,0x0000,0x0000,
+0x0000,0x0000,0x8C66,0x0000,0x0000,0x0000,0x0000,0x4578,
+0x0000,0x793E,0x6332,0x0000,0x0000,0x0000,0x0000,0x6333,
+0x6349,0x3658,0x0000,0x0000,0x4F3D,0x4135,0x0000,0x0000,
+0x0000,0x0000,0x6334,0x0000,0x0000,0x3252,0x4477,0x4A21,
+0x0000,0x0000,0x0000,0x0000,0x8C67,0x8C68,0x8C69,0x0000,
+0x7942,0x0000,0x0000,0x8C6A,0x0000,0x6335,0x0000,0x0000,
+0x0000,0x8C6B,0x0000,0x0000,0x0000,0x0000,0x357A,0x6336,
+0x0000,0x8C6C,0x6338,0x0000,0x0000,0x0000,0x6339,0x0000,
+0x4729,0x7943,0x0000,0x633A,0x8C6D,0x0000,0x0000,0x0000,
+0x7944,0x633B,0x633C,0x8C6E,0x0000,0x3659,0x3253,0x4645,
+0x3D28,0x3B64,0x8C6F,0x0000,0x0000,0x0000,0x0000,0x8C70,
+0x7945,0x633D,0x7946,0x3D29,0x8C71,0x8C72,0x0000,0x0000,
+0x0000,0x324A,0x4943,0x0000,0x7948,0x633E,0x8C73,0x0000,
+0x486B,0x0000,0x0000,0x0000,0x0000,0x0000,0x7949,0x4145,
+0x0000,0x6341,0x0000,0x6342,0x4769,0x0000,0x3F41,0x633F,
+0x0000,0x4361,0x0000,0x794A,0x6340,0x794B,0x0000,0x0000,
+0x3E4E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x305C,0x0000,0x0000,0x0000,0x0000,
+
+/* 7A00h */
+0x3529,0x0000,0x0000,0x794C,0x0000,0x0000,0x0000,0x0000,
+0x6343,0x0000,0x8C78,0x4478,0x0000,0x6344,0x4047,0x0000,
+0x0000,0x8C79,0x0000,0x0000,0x4C2D,0x8C7A,0x0000,0x4923,
+0x6345,0x6346,0x4355,0x8C7B,0x4E47,0x0000,0x8C7C,0x6348,
+0x6347,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x8C7E,0x3C6F,0x0000,
+0x0000,0x634A,0x3070,0x0000,0x0000,0x0000,0x0000,0x634D,
+0x8D21,0x794E,0x0000,0x634B,0x3254,0x374E,0x634C,0x3946,
+0x3972,0x0000,0x4A66,0x634E,0x0000,0x0000,0x4B54,0x8D22,
+0x0000,0x6350,0x0000,0x0000,0x8D23,0x4051,0x314F,0x323A,
+0x302C,0x0000,0x0000,0x0000,0x0000,0x0000,0x8D24,0x634F,
+0x0000,0x8D25,0x0000,0x0000,0x8D26,0x794F,0x0000,0x8D27,
+0x8D28,0x6351,0x6352,0x3E77,0x0000,0x0000,0x0000,0x8D29,
+0x0000,0x6353,0x8D2A,0x334F,0x0000,0x7950,0x0000,0x0000,
+0x6355,0x0000,0x0000,0x0000,0x376A,0x8D2B,0x3566,0x0000,
+0x8D2C,0x6356,0x3675,0x0000,0x0000,0x6357,0x0000,0x407C,
+0x0000,0x464D,0x8D2D,0x4060,0x3A75,0x7952,0x0000,0x0000,
+0x6358,0x0000,0x8D2E,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x8D2F,0x0000,0x4362,0x416B,0x0000,0x635A,0x635C,0x6359,
+0x635B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3722,
+0x7953,0x0000,0x0000,0x8D30,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x635D,0x3726,0x0000,0x8D31,0x0000,0x3567,0x4D52,
+0x635F,0x0000,0x0000,0x7955,0x0000,0x0000,0x6360,0x0000,
+0x0000,0x8D34,0x312E,0x7956,0x8D35,0x0000,0x8D36,0x6363,
+0x0000,0x0000,0x0000,0x3376,0x6362,0x6361,0x0000,0x6365,
+0x635E,0x0000,0x6366,0x4E29,0x8D38,0x6367,0x7957,0x6368,
+0x0000,0x8D39,0x5474,0x636A,0x0000,0x6369,0x0000,0x0000,
+0x0000,0x636B,0x636C,0x0000,0x4E35,0x636D,0x0000,0x706F,
+0x3E4F,0x636E,0x636F,0x3D57,0x0000,0x4638,0x6370,0x8D3A,
+0x8D3B,0x0000,0x4328,0x7958,0x0000,0x6371,0x0000,0x433C,
+0x6372,0x0000,0x0000,0x0000,0x8D3C,0x0000,0x3625,0x0000,
+0x513F,0x435D,0x3C33,0x0000,0x0000,0x7959,0x0000,0x3448,
+
+/* 7B00h */
+0x0000,0x0000,0x6373,0x0000,0x6422,0x0000,0x6376,0x8D3F,
+0x3568,0x0000,0x6375,0x6424,0x0000,0x0000,0x0000,0x6374,
+0x0000,0x3E50,0x795A,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6378,0x6379,0x0000,0x452B,0x0000,0x0000,0x637A,0x0000,
+0x335E,0x0000,0x0000,0x0000,0x0000,0x3F5A,0x4964,0x8D42,
+0x637C,0x0000,0x8D43,0x0000,0x4268,0x795B,0x8D44,0x8D45,
+0x0000,0x8D46,0x0000,0x6377,0x0000,0x637B,0x637D,0x0000,
+0x0000,0x3A7B,0x0000,0x795C,0x0000,0x8D41,0x0000,0x0000,
+0x0000,0x8D4A,0x0000,0x0000,0x0000,0x6426,0x492E,0x795D,
+0x4826,0x4579,0x0000,0x365A,0x6425,0x6423,0x795E,0x4835,
+0x637E,0x435E,0x457B,0x0000,0x457A,0x8D4C,0x3A76,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6438,0x0000,0x0000,
+0x795F,0x0000,0x0000,0x0000,0x8D4E,0x6428,0x8D4F,0x642A,
+0x0000,0x8D50,0x0000,0x0000,0x642D,0x7960,0x642E,0x7961,
+0x642B,0x642C,0x7962,0x8D51,0x6429,0x6427,0x0000,0x0000,
+0x0000,0x8D4D,0x6421,0x0000,0x0000,0x0000,0x0000,0x8D49,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4A4F,0x3255,
+0x0000,0x0000,0x0000,0x6435,0x0000,0x6432,0x0000,0x6437,
+0x8D54,0x8D55,0x6436,0x0000,0x4773,0x4C27,0x0000,0x3B3B,
+0x6430,0x6439,0x6434,0x8D56,0x6433,0x642F,0x7963,0x6431,
+0x0000,0x3449,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x433D,0x0000,0x0000,0x407D,0x0000,0x8D58,
+0x0000,0x4822,0x0000,0x0000,0x643E,0x8D59,0x0000,0x0000,
+0x4824,0x0000,0x0000,0x0000,0x8D5A,0x0000,0x0000,0x0000,
+0x4061,0x643B,0x0000,0x0000,0x484F,0x8D5B,0x643F,0x4A53,
+0x0000,0x435B,0x8D5C,0x643A,0x643C,0x0000,0x0000,0x643D,
+0x0000,0x0000,0x0000,0x0000,0x8D5F,0x0000,0x8D60,0x7965,
+0x0000,0x7966,0x8D61,0x0000,0x0000,0x6440,0x0000,0x0000,
+0x3C44,0x0000,0x0000,0x0000,0x4646,0x6445,0x6444,0x0000,
+0x0000,0x6441,0x8D62,0x0000,0x0000,0x4F36,0x0000,0x0000,
+0x8D63,0x0000,0x0000,0x644A,0x0000,0x0000,0x644E,0x644B,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 7C00h */
+0x6447,0x7967,0x0000,0x8D64,0x0000,0x0000,0x0000,0x6448,
+0x0000,0x0000,0x0000,0x8D65,0x0000,0x644D,0x8D66,0x8D67,
+0x0000,0x6442,0x5255,0x6449,0x6443,0x0000,0x0000,0x644C,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7969,0x6452,
+0x796A,0x344A,0x0000,0x644F,0x0000,0x0000,0x8D68,0x6450,
+0x0000,0x0000,0x6451,0x6454,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x7968,0x0000,0x796B,0x0000,0x0000,0x796C,0x6453,
+0x4876,0x0000,0x0000,0x0000,0x0000,0x6455,0x4E7C,0x4A6D,
+0x645A,0x0000,0x0000,0x6457,0x0000,0x8D69,0x0000,0x0000,
+0x0000,0x0000,0x8D6A,0x0000,0x6456,0x4052,0x0000,0x6459,
+0x645B,0x8D6B,0x0000,0x0000,0x6458,0x0000,0x645F,0x8D6C,
+0x645C,0x796F,0x0000,0x0000,0x0000,0x0000,0x8D6D,0x645D,
+0x6446,0x8D6E,0x0000,0x0000,0x645E,0x6460,0x0000,0x0000,
+0x0000,0x8D6F,0x0000,0x0000,0x6461,0x7970,0x8D70,0x8D71,
+0x8D72,0x0000,0x0000,0x4A46,0x0000,0x6462,0x0000,0x0000,
+0x0000,0x7971,0x0000,0x0000,0x0000,0x0000,0x4C62,0x0000,
+0x0000,0x364E,0x3729,0x6463,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4A34,0x0000,0x3F68,0x0000,0x4C30,0x0000,0x7972,
+0x6464,0x0000,0x4E33,0x0000,0x7973,0x4774,0x0000,0x4146,
+0x4734,0x0000,0x0000,0x3D4D,0x0000,0x0000,0x0000,0x3040,
+0x7974,0x6469,0x6467,0x0000,0x6465,0x3421,0x8D76,0x3E51,
+0x646A,0x0000,0x0000,0x6468,0x0000,0x6466,0x646E,0x0000,
+0x0000,0x646D,0x646C,0x646B,0x0000,0x0000,0x8D78,0x8D79,
+0x0000,0x646F,0x0000,0x0000,0x7975,0x6470,0x403A,0x8D7A,
+0x6471,0x0000,0x6473,0x0000,0x8D7C,0x6472,0x0000,0x0000,
+0x8D7E,0x0000,0x3852,0x0000,0x0000,0x8E21,0x4138,0x0000,
+0x0000,0x0000,0x6475,0x0000,0x0000,0x7976,0x457C,0x8E23,
+0x6474,0x7977,0x0000,0x0000,0x6476,0x7978,0x4A35,0x416C,
+0x3947,0x0000,0x6477,0x0000,0x0000,0x0000,0x8E25,0x4E48,
+0x0000,0x0000,0x0000,0x8E26,0x0000,0x0000,0x0000,0x6479,
+0x0000,0x0000,0x647A,0x0000,0x647B,0x8E28,0x647C,0x0000,
+0x3B65,0x0000,0x647D,0x374F,0x0000,0x0000,0x356A,0x0000,
+
+/* 7D00h */
+0x352A,0x0000,0x6521,0x8E29,0x4C73,0x3948,0x647E,0x7979,
+0x797A,0x8E2A,0x6524,0x4C66,0x0000,0x473C,0x0000,0x0000,
+0x4933,0x0000,0x8E2C,0x797B,0x3D63,0x6523,0x0000,0x3C53,
+0x3949,0x3B66,0x3569,0x4A36,0x6522,0x797C,0x8E2D,0x0000,
+0x4147,0x4B42,0x3A77,0x797D,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3B67,0x445D,0x0000,0x6527,0x4E5F,
+0x3A59,0x797E,0x6528,0x3F42,0x0000,0x652A,0x0000,0x0000,
+0x0000,0x3E52,0x3A30,0x0000,0x0000,0x8E30,0x8E31,0x6529,
+0x8E32,0x7A21,0x3D2A,0x383E,0x4148,0x6525,0x652B,0x8E33,
+0x7A22,0x0000,0x0000,0x6526,0x3750,0x0000,0x652E,0x6532,
+0x376B,0x0000,0x0000,0x7A23,0x0000,0x0000,0x652D,0x0000,
+0x0000,0x8E37,0x8E38,0x6536,0x7A24,0x0000,0x394A,0x0000,
+0x0000,0x4D6D,0x303C,0x6533,0x0000,0x0000,0x356B,0x0000,
+0x6530,0x0000,0x8E39,0x0000,0x0000,0x0000,0x6531,0x0000,
+0x8E3A,0x457D,0x652F,0x652C,0x0000,0x3328,0x4064,0x0000,
+0x0000,0x3828,0x7A25,0x0000,0x0000,0x6538,0x0000,0x8E3C,
+0x0000,0x0000,0x0000,0x7A26,0x0000,0x0000,0x8E3E,0x0000,
+0x8E3F,0x6535,0x0000,0x7A27,0x8E40,0x0000,0x0000,0x6537,
+0x0000,0x0000,0x0000,0x6534,0x0000,0x0000,0x0000,0x8E41,
+0x0000,0x3751,0x4233,0x6539,0x416E,0x8E43,0x0000,0x6546,
+0x7A28,0x0000,0x6542,0x653C,0x0000,0x0000,0x7A29,0x8E44,
+0x0000,0x0000,0x8E45,0x6540,0x3C7A,0x305D,0x653B,0x6543,
+0x6547,0x394B,0x4C56,0x0000,0x4456,0x653D,0x8E46,0x8E47,
+0x6545,0x0000,0x653A,0x433E,0x0000,0x653F,0x303D,0x4C4A,
+0x8E48,0x0000,0x7A2A,0x0000,0x0000,0x0000,0x0000,0x653E,
+0x0000,0x0000,0x365B,0x486C,0x7A2B,0x0000,0x0000,0x416D,
+0x0000,0x4E50,0x3D6F,0x0000,0x0000,0x656E,0x7A2C,0x8E49,
+0x6548,0x8E4A,0x407E,0x0000,0x6544,0x6549,0x654B,0x0000,
+0x4479,0x654E,0x0000,0x7A2D,0x654A,0x0000,0x8E4B,0x0000,
+0x4A54,0x344B,0x0000,0x0000,0x4C4B,0x0000,0x0000,0x305E,
+0x0000,0x8E4C,0x654D,0x0000,0x4E7D,0x0000,0x0000,0x0000,
+0x0000,0x8E4D,0x0000,0x654C,0x0000,0x0000,0x0000,0x0000,
+
+/* 7E00h */
+0x0000,0x316F,0x0000,0x0000,0x466C,0x654F,0x0000,0x0000,
+0x7A30,0x6556,0x6550,0x6557,0x0000,0x0000,0x0000,0x0000,
+0x8E51,0x7A31,0x6553,0x0000,0x0000,0x7A32,0x0000,0x8E52,
+0x0000,0x0000,0x0000,0x477B,0x0000,0x8E53,0x3C4A,0x6555,
+0x8E54,0x6552,0x6558,0x6551,0x0000,0x0000,0x3D44,0x8E55,
+0x7A2F,0x0000,0x0000,0x4B25,0x8E56,0x0000,0x3D4C,0x0000,
+0x0000,0x6554,0x6560,0x0000,0x0000,0x655C,0x0000,0x655F,
+0x0000,0x655D,0x6561,0x655B,0x0000,0x6541,0x4053,0x0000,
+0x0000,0x484B,0x0000,0x655E,0x0000,0x8E57,0x6559,0x7A34,
+0x0000,0x0000,0x4121,0x3752,0x0000,0x3D2B,0x0000,0x0000,
+0x0000,0x0000,0x7A35,0x0000,0x3F25,0x4136,0x6564,0x0000,
+0x0000,0x6566,0x6567,0x0000,0x0000,0x6563,0x6565,0x0000,
+0x0000,0x7A36,0x0000,0x0000,0x0000,0x0000,0x655A,0x6562,
+0x0000,0x656A,0x6569,0x7E7E,0x0000,0x4B7A,0x0000,0x0000,
+0x372B,0x0000,0x0000,0x8E58,0x0000,0x8E59,0x0000,0x0000,
+0x0000,0x6568,0x0000,0x656C,0x656B,0x656F,0x8E5A,0x6571,
+0x0000,0x0000,0x3B3C,0x656D,0x0000,0x0000,0x8E5B,0x8E5C,
+0x6572,0x6573,0x7A37,0x0000,0x6574,0x7A38,0x657A,0x453B,
+0x6576,0x8E5E,0x6575,0x6577,0x6578,0x0000,0x6579,0x0000,
+0x8E5F,0x0000,0x8E60,0x657B,0x657C,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 7F00h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x344C,0x0000,
+0x657D,0x0000,0x657E,0x8E63,0x8E62,0x0000,0x8E64,0x0000,
+0x0000,0x0000,0x0000,0x8E65,0x8E66,0x6621,0x0000,0x7A39,
+0x0000,0x0000,0x0000,0x0000,0x6622,0x6623,0x6624,0x8E67,
+0x6625,0x6626,0x8E6A,0x0000,0x6628,0x6627,0x0000,0x0000,
+0x6629,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x662A,
+0x662B,0x8E6C,0x0000,0x8E6D,0x8E6E,0x0000,0x0000,0x662E,
+0x662C,0x662D,0x3A61,0x3753,0x0000,0x8E6F,0x4356,0x0000,
+0x4833,0x0000,0x3D70,0x0000,0x0000,0x474D,0x0000,0x486D,
+0x662F,0x586D,0x0000,0x0000,0x0000,0x8E70,0x8E71,0x0000,
+0x0000,0x0000,0x6630,0x6632,0x0000,0x4D65,0x6631,0x6634,
+0x6633,0x0000,0x4D53,0x0000,0x6635,0x0000,0x487E,0x0000,
+0x8E73,0x7A3B,0x0000,0x0000,0x6636,0x0000,0x8E76,0x7A3C,
+0x0000,0x0000,0x6639,0x0000,0x8E77,0x6638,0x6637,0x0000,
+0x0000,0x0000,0x0000,0x663A,0x3732,0x0000,0x0000,0x0000,
+0x4122,0x3541,0x0000,0x0000,0x0000,0x8E78,0x663E,0x663B,
+0x0000,0x0000,0x663C,0x0000,0x0000,0x0000,0x663F,0x0000,
+0x6640,0x663D,0x0000,0x0000,0x0000,0x3129,0x0000,0x7A3D,
+0x0000,0x3227,0x0000,0x8E7A,0x0000,0x6642,0x6643,0x0000,
+0x0000,0x0000,0x6644,0x0000,0x4D62,0x0000,0x7A3E,0x8E7B,
+0x0000,0x0000,0x3D2C,0x0000,0x6646,0x6645,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7A3F,0x0000,0x0000,0x0000,0x7A40,
+0x3F69,0x6647,0x0000,0x8E7C,0x0000,0x8E7D,0x6648,0x0000,
+0x0000,0x6649,0x0000,0x3465,0x7A41,0x0000,0x7A42,0x8E7E,
+0x344D,0x0000,0x8F21,0x664A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x664B,0x7A43,0x4B5D,0x4D63,0x0000,0x0000,0x0000,
+
+/* 8000h */
+0x4D54,0x4F37,0x8F22,0x394D,0x664E,0x3C54,0x664D,0x0000,
+0x8F24,0x0000,0x8F23,0x664F,0x3C29,0x0000,0x8F25,0x0000,
+0x4251,0x8F26,0x6650,0x0000,0x7A45,0x394C,0x8F27,0x4C57,
+0x6651,0x6652,0x0000,0x0000,0x6653,0x0000,0x0000,0x0000,
+0x0000,0x6654,0x0000,0x0000,0x8F28,0x0000,0x7A46,0x0000,
+0x6655,0x0000,0x0000,0x0000,0x8F29,0x0000,0x0000,0x0000,
+0x8F2A,0x0000,0x0000,0x3C2A,0x0000,0x7A47,0x4C6D,0x7A48,
+0x0000,0x0000,0x0000,0x6657,0x7A49,0x433F,0x0000,0x6656,
+0x0000,0x0000,0x0000,0x8F2B,0x0000,0x0000,0x6659,0x0000,
+0x0000,0x0000,0x6658,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x665A,0x0000,0x0000,0x0000,0x403B,0x0000,
+0x665B,0x0000,0x665C,0x0000,0x0000,0x0000,0x4A39,0x665D,
+0x0000,0x416F,0x665E,0x0000,0x0000,0x0000,0x8F2C,0x0000,
+0x665F,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4E7E,
+0x6662,0x8F2D,0x6661,0x6660,0x4430,0x8F2E,0x6663,0x3F26,
+0x0000,0x6664,0x0000,0x8F2F,0x0000,0x6665,0x4F38,0x6666,
+0x0000,0x0000,0x0000,0x0000,0x6667,0x6669,0x6668,0x4825,
+0x0000,0x4679,0x0000,0x4F3E,0x4829,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x666B,0x0000,0x0000,0x3E53,0x0000,
+0x492A,0x8F30,0x666C,0x666A,0x8F31,0x344E,0x0000,0x0000,
+0x0000,0x3854,0x3B68,0x0000,0x8F32,0x486E,0x0000,0x8F33,
+0x0000,0x382A,0x4B43,0x0000,0x666F,0x666D,0x0000,0x394E,
+0x0000,0x394F,0x3069,0x0000,0x3A68,0x0000,0x0000,0x0000,
+0x8F34,0x0000,0x4759,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x305F,0x6674,0x8F36,0x4340,0x0000,
+0x0000,0x0000,0x7A4A,0x0000,0x4758,0x0000,0x425B,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x8F37,0x6676,0x7A4B,
+0x8F38,0x6672,0x6675,0x6670,0x0000,0x6673,0x4B26,0x0000,
+0x7A4C,0x3855,0x0000,0x0000,0x307D,0x6671,0x8F39,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6678,
+0x0000,0x6679,0x0000,0x7A4D,0x4639,0x8F3C,0x0000,0x0000,
+0x363B,0x0000,0x0000,0x8F3D,0x6726,0x473D,0x0000,0x0000,
+
+/* 8100h */
+0x0000,0x0000,0x3B69,0x0000,0x0000,0x363C,0x4048,0x4F46,
+0x4C2E,0x6677,0x4054,0x0000,0x0000,0x8F3B,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8F40,0x0000,
+0x7A4E,0x0000,0x3553,0x667A,0x0000,0x0000,0x8F41,0x0000,
+0x0000,0x0000,0x0000,0x667C,0x8F43,0x0000,0x0000,0x8F44,
+0x0000,0x667B,0x0000,0x0000,0x8F45,0x0000,0x0000,0x667D,
+0x0000,0x4326,0x0000,0x473E,0x0000,0x8F3F,0x0000,0x0000,
+0x0000,0x4431,0x0000,0x0000,0x0000,0x8F47,0x6723,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6722,0x0000,
+0x0000,0x0000,0x7A4F,0x667E,0x0000,0x0000,0x3F55,0x0000,
+0x4965,0x6725,0x0000,0x6724,0x3950,0x4F53,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6735,
+0x7A50,0x0000,0x0000,0x0000,0x0000,0x6729,0x672A,0x7A51,
+0x7A52,0x8F49,0x0000,0x3C70,0x0000,0x7A53,0x6728,0x0000,
+0x3978,0x6727,0x0000,0x0000,0x672B,0x0000,0x0000,0x0000,
+0x4432,0x4A22,0x4123,0x0000,0x0000,0x0000,0x0000,0x425C,
+0x672F,0x8F4B,0x6730,0x672C,0x8F4D,0x8F4E,0x0000,0x0000,
+0x672D,0x0000,0x672E,0x0000,0x0000,0x0000,0x0000,0x3951,
+0x0000,0x0000,0x0000,0x6736,0x0000,0x6732,0x0000,0x0000,
+0x8F50,0x0000,0x4966,0x0000,0x4B6C,0x4928,0x0000,0x0000,
+0x6731,0x0000,0x0000,0x6734,0x6733,0x0000,0x0000,0x0000,
+0x4B44,0x6737,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6738,0x0000,0x8F51,0x4137,0x0000,0x6739,0x0000,0x0000,
+0x673B,0x0000,0x673F,0x7A54,0x0000,0x673C,0x673A,0x473F,
+0x673D,0x8F52,0x673E,0x8F53,0x0000,0x0000,0x3232,0x0000,
+0x6745,0x6740,0x7A55,0x0000,0x0000,0x6741,0x0000,0x7A56,
+0x0000,0x6742,0x0000,0x4221,0x0000,0x0000,0x8F54,0x7A57,
+0x6744,0x6743,0x6746,0x8F55,0x0000,0x0000,0x0000,0x6747,
+0x6748,0x0000,0x0000,0x3F43,0x8F57,0x3269,0x0000,0x6749,
+0x4E57,0x0000,0x3C2B,0x0000,0x8F59,0x3D2D,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3B6A,0x4357,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x674A,0x674B,0x3131,0x8F5B,0x674C,0x8F5C,
+
+/* 8200h */
+0x0000,0x674D,0x674E,0x0000,0x8F5E,0x674F,0x0000,0x6750,
+0x363D,0x5A2A,0x6751,0x0000,0x4065,0x6752,0x3C4B,0x0000,
+0x6753,0x0000,0x5030,0x0000,0x0000,0x0000,0x6754,0x4A5E,
+0x345C,0x8F60,0x0000,0x4124,0x3D58,0x0000,0x4971,0x3D2E,
+0x0000,0x8F61,0x8F62,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6755,0x3952,0x6756,0x484C,0x0000,0x6764,0x0000,
+0x0000,0x0000,0x8F64,0x6758,0x8F65,0x4249,0x4775,0x383F,
+0x6757,0x4125,0x0000,0x0000,0x8F66,0x0000,0x0000,0x0000,
+0x6759,0x0000,0x0000,0x0000,0x0000,0x8F69,0x8F67,0x447A,
+0x0000,0x8F68,0x0000,0x8F6B,0x0000,0x0000,0x0000,0x8F6D,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8F6F,
+0x675B,0x675A,0x675D,0x0000,0x8F71,0x675C,0x0000,0x675E,
+0x7A5B,0x0000,0x6760,0x8F72,0x675F,0x0000,0x344F,0x0000,
+0x6761,0x0000,0x6762,0x6763,0x0000,0x0000,0x3A31,0x4E49,
+0x0000,0x6765,0x3F27,0x0000,0x7A5C,0x0000,0x3170,0x6766,
+0x6767,0x8F76,0x0000,0x0000,0x0000,0x8F78,0x6768,0x8F79,
+0x0000,0x0000,0x0000,0x8F7A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x8F7B,0x3072,0x0000,0x6769,0x7A5E,0x0000,
+0x0000,0x0000,0x676A,0x8F7C,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4967,0x0000,0x0000,0x0000,0x3C47,0x0000,0x676C,
+0x0000,0x7A5F,0x0000,0x7A60,0x7A61,0x3329,0x3032,0x8F7D,
+0x8F7E,0x7A62,0x0000,0x676B,0x676E,0x474E,0x7A63,0x3F44,
+0x0000,0x3256,0x9021,0x4B27,0x9022,0x0000,0x0000,0x7A64,
+0x375D,0x365C,0x9023,0x676D,0x9024,0x326A,0x7A65,0x7A66,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x3423,0x7A67,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3171,0x6772,0x4E6A,0x425D,0x7A68,0x0000,0x4944,
+0x0000,0x677E,0x0000,0x3257,0x677C,0x0000,0x677A,0x6771,
+0x0000,0x676F,0x9025,0x6770,0x0000,0x3C63,0x366C,0x4377,
+0x9026,0x0000,0x0000,0x4651,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3151,0x0000,0x6774,0x6773,0x0000,0x0000,0x9027,
+0x0000,0x6779,0x6775,0x6778,0x0000,0x7A69,0x7A6A,0x0000,
+
+/* 8300h */
+0x7A6B,0x7A6C,0x4C50,0x6777,0x3258,0x337D,0x677B,0x9028,
+0x9029,0x677D,0x0000,0x0000,0x902A,0x0000,0x3754,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6823,0x682C,
+0x682D,0x0000,0x0000,0x902C,0x302B,0x902D,0x0000,0x0000,
+0x0000,0x0000,0x7A6E,0x6834,0x0000,0x0000,0x0000,0x0000,
+0x3071,0x0000,0x0000,0x682B,0x0000,0x7A6F,0x0000,0x682A,
+0x902E,0x6825,0x6824,0x0000,0x6822,0x6821,0x4363,0x0000,
+0x427B,0x6827,0x7A70,0x0000,0x902F,0x0000,0x0000,0x0000,
+0x6826,0x0000,0x0000,0x7A71,0x9030,0x6829,0x0000,0x7A72,
+0x0000,0x4170,0x3755,0x0000,0x0000,0x0000,0x0000,0x3141,
+0x6828,0x7A73,0x3953,0x0000,0x902B,0x7A74,0x0000,0x9031,
+0x4171,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7A6D,0x864A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x683A,0x0000,0x683B,0x0000,0x3259,
+0x0000,0x0000,0x0000,0x322E,0x6838,0x7A75,0x0000,0x9033,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x682E,0x7A76,0x6836,
+0x0000,0x683D,0x6837,0x0000,0x0000,0x9036,0x6835,0x0000,
+0x0000,0x0000,0x7A77,0x6776,0x9037,0x9038,0x6833,0x0000,
+0x7A78,0x0000,0x682F,0x9039,0x0000,0x903A,0x3450,0x6831,
+0x683C,0x0000,0x6832,0x0000,0x0000,0x0000,0x0000,0x7A79,
+0x683E,0x7A7A,0x6830,0x477C,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4D69,0x0000,0x0000,0x0000,0x6839,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x684F,0x0000,0x7A7B,
+0x7A7C,0x6847,0x0000,0x0000,0x0000,0x3F7B,0x0000,0x7A7D,
+0x0000,0x903B,0x3546,0x0000,0x365D,0x0000,0x6842,0x7A7E,
+0x903C,0x7B21,0x0000,0x325B,0x903D,0x0000,0x3E54,0x0000,
+0x6845,0x0000,0x0000,0x0000,0x3A5A,0x903E,0x0000,0x4551,
+0x684A,0x7B22,0x0000,0x0000,0x0000,0x903F,0x0000,0x0000,
+0x0000,0x4A6E,0x7B23,0x6841,0x0000,0x0000,0x0000,0x325A,
+0x3856,0x4929,0x684B,0x0000,0x683F,0x0000,0x0000,0x6848,
+0x0000,0x9040,0x0000,0x6852,0x0000,0x6843,0x0000,0x0000,
+
+/* 8400h */
+0x0000,0x7B24,0x0000,0x6844,0x463A,0x0000,0x7B25,0x6849,
+0x0000,0x0000,0x7B26,0x6846,0x4B28,0x684C,0x3060,0x9041,
+0x0000,0x9042,0x0000,0x6840,0x0000,0x9043,0x0000,0x9045,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x684E,0x0000,0x684D,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x476B,0x6854,0x0000,0x685F,0x0000,0x0000,0x0000,
+0x0000,0x337E,0x0000,0x0000,0x0000,0x6862,0x0000,0x0000,
+0x6850,0x9046,0x0000,0x0000,0x6855,0x4D6E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x685E,0x0000,
+0x7B28,0x4D55,0x9047,0x0000,0x0000,0x0000,0x4E2A,0x9048,
+0x0000,0x9049,0x904A,0x0000,0x0000,0x0000,0x0000,0x4378,
+0x0000,0x904B,0x904C,0x336B,0x904D,0x0000,0x0000,0x7B29,
+0x0000,0x4972,0x6864,0x4621,0x0000,0x904F,0x3031,0x0000,
+0x0000,0x685D,0x0000,0x6859,0x4172,0x6853,0x685B,0x6860,
+0x7B2A,0x472C,0x0000,0x7B2B,0x0000,0x302A,0x9050,0x6858,
+0x9051,0x6861,0x4978,0x0000,0x9052,0x0000,0x0000,0x0000,
+0x0000,0x9053,0x685C,0x0000,0x6857,0x7B2C,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3E55,0x0000,0x0000,0x0000,0x0000,
+0x3D2F,0x0000,0x0000,0x0000,0x3C2C,0x0000,0x0000,0x9056,
+0x0000,0x4C58,0x0000,0x0000,0x4947,0x0000,0x7B2D,0x6867,
+0x0000,0x6870,0x0000,0x0000,0x0000,0x0000,0x9057,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x685A,0x0000,0x7B2E,
+0x0000,0x0000,0x3377,0x0000,0x7B2F,0x0000,0x0000,0x0000,
+0x3E78,0x6865,0x7B30,0x686A,0x4173,0x0000,0x9058,0x6866,
+0x7B31,0x686D,0x7B32,0x0000,0x435F,0x0000,0x686E,0x0000,
+0x0000,0x4D56,0x6863,0x3338,0x0000,0x6869,0x905A,0x905B,
+0x686C,0x4C2C,0x0000,0x905C,0x0000,0x0000,0x686F,0x0000,
+0x0000,0x6868,0x686B,0x0000,0x9055,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x905E,
+0x0000,0x0000,0x905F,0x0000,0x4B29,0x0000,0x4F21,0x9060,
+0x9061,0x9062,0x0000,0x0000,0x6873,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x9063,0x0000,0x687A,0x9064,0x0000,0x6872,
+
+/* 8500h */
+0x3C43,0x0000,0x0000,0x0000,0x0000,0x0000,0x6851,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x9065,0x0000,0x0000,0x0000,
+0x0000,0x4A4E,0x0000,0x4C22,0x6879,0x6878,0x0000,0x6874,
+0x6875,0x0000,0x3136,0x9066,0x0000,0x0000,0x7B35,0x6877,
+0x0000,0x6871,0x0000,0x7B36,0x9067,0x9068,0x4455,0x0000,
+0x0000,0x0000,0x0000,0x9069,0x6876,0x307E,0x0000,0x7B37,
+0x0000,0x0000,0x7B34,0x0000,0x906A,0x4222,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x4A43,0x906F,0x0000,
+0x687B,0x6921,0x0000,0x4859,0x0000,0x0000,0x0000,0x0000,
+0x687E,0x3E56,0x3C49,0x6923,0x0000,0x0000,0x363E,0x906B,
+0x0000,0x9070,0x0000,0x9071,0x0000,0x6924,0x0000,0x4979,
+0x687D,0x7B38,0x6856,0x0000,0x0000,0x0000,0x9072,0x0000,
+0x0000,0x9073,0x9074,0x687C,0x7B39,0x0000,0x0000,0x0000,
+0x4F4F,0x4622,0x4973,0x0000,0x0000,0x692B,0x0000,0x906C,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6931,
+0x0000,0x0000,0x7B3C,0x9076,0x0000,0x9077,0x6932,0x9078,
+0x6925,0x9079,0x0000,0x0000,0x4776,0x0000,0x907A,0x692F,
+0x6927,0x0000,0x6929,0x0000,0x7B3D,0x0000,0x0000,0x7B3E,
+0x6933,0x6928,0x0000,0x907B,0x692C,0x0000,0x0000,0x3172,
+0x0000,0x4665,0x0000,0x692D,0x6930,0x907C,0x0000,0x907D,
+0x0000,0x0000,0x7B3F,0x0000,0x6926,0x0000,0x4126,0x0000,
+0x692A,0x3B27,0x3F45,0x3730,0x4C74,0x7B3B,0x4C79,0x3D72,
+0x7B40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9123,
+0x0000,0x6937,0x6935,0x0000,0x9124,0x0000,0x0000,0x0000,
+0x0000,0x4F4E,0x0000,0x0000,0x0000,0x0000,0x0000,0x9125,
+0x0000,0x6934,0x9126,0x7B41,0x0000,0x4D75,0x7B42,0x6936,
+0x6938,0x0000,0x0000,0x0000,0x0000,0x6939,0x0000,0x0000,
+0x9127,0x9128,0x0000,0x0000,0x693C,0x693A,0x0000,0x9129,
+0x0000,0x912A,0x0000,0x0000,0x4623,0x693B,0x912B,0x0000,
+0x0000,0x484D,0x692E,0x0000,0x0000,0x7B43,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x912C,0x3D73,
+0x0000,0x693D,0x6942,0x4174,0x0000,0x0000,0x6941,0x7B45,
+
+/* 8600h */
+0x912D,0x0000,0x6922,0x0000,0x7B46,0x7B47,0x6943,0x4149,
+0x0000,0x0000,0x693E,0x6940,0x0000,0x0000,0x0000,0x0000,
+0x7B48,0x912E,0x7B44,0x693F,0x0000,0x0000,0x5D31,0x5D22,
+0x7B4A,0x0000,0x6945,0x0000,0x0000,0x0000,0x912F,0x0000,
+0x0000,0x9130,0x6944,0x0000,0x9131,0x0000,0x0000,0x9132,
+0x0000,0x7B4B,0x0000,0x0000,0x0000,0x4D76,0x0000,0x623C,
+0x6946,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7B4C,0x9134,0x0000,0x0000,0x9135,0x0000,0x0000,0x6947,
+0x9137,0x2F68,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6948,0x3857,0x0000,
+0x3554,0x0000,0x0000,0x9139,0x694A,0x515D,0x913A,0x7B4D,
+0x0000,0x0000,0x3575,0x7B4E,0x4E3A,0x0000,0x3673,0x694B,
+0x0000,0x0000,0x7B50,0x0000,0x0000,0x0000,0x0000,0x694C,
+0x0000,0x0000,0x0000,0x436E,0x7B52,0x0000,0x0000,0x913B,
+0x0000,0x694D,0x0000,0x0000,0x0000,0x7B53,0x0000,0x913C,
+0x0000,0x467A,0x913D,0x303A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x913E,
+0x0000,0x913F,0x3263,0x6952,0x6953,0x9140,0x0000,0x0000,
+0x0000,0x9141,0x0000,0x694E,0x0000,0x3B3D,0x0000,0x0000,
+0x7B54,0x0000,0x0000,0x0000,0x9142,0x9143,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x694F,0x4742,0x0000,0x0000,0x0000,
+0x9144,0x6950,0x6951,0x695B,0x0000,0x0000,0x0000,0x6955,
+0x6958,0x9146,0x0000,0x9147,0x0000,0x0000,0x6954,0x0000,
+0x7B55,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x9148,0x0000,0x9149,0x6956,0x0000,0x6957,0x3C58,
+0x0000,0x6959,0x0000,0x4341,0x0000,0x3756,0x3342,0x0000,
+0x0000,0x914A,0x0000,0x0000,0x695C,0x914B,0x0000,0x914C,
+0x0000,0x333F,0x0000,0x6961,0x0000,0x0000,0x695D,0x6960,
+0x0000,0x0000,0x0000,0x914D,0x483A,0x0000,0x914E,0x0000,
+0x0000,0x695E,0x0000,0x0000,0x695F,0x4948,0x485A,0x6962,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x427D,0x696C,0x7B56,0x6968,0x7B57,0x7B58,0x326B,0x0000,
+
+/* 8700h */
+0x6966,0x0000,0x4B2A,0x6967,0x0000,0x9150,0x6964,0x9151,
+0x6965,0x696A,0x696D,0x7B59,0x0000,0x696B,0x9152,0x0000,
+0x9153,0x6969,0x6963,0x9154,0x0000,0x0000,0x0000,0x0000,
+0x4358,0x9155,0x6974,0x0000,0x4C2A,0x0000,0x0000,0x9156,
+0x0000,0x9157,0x0000,0x9158,0x0000,0x6972,0x0000,0x0000,
+0x0000,0x6973,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x9159,0x0000,0x0000,0x696E,0x0000,0x0000,0x6970,
+0x0000,0x0000,0x915A,0x6971,0x0000,0x0000,0x915B,0x696F,
+0x915C,0x0000,0x0000,0x915D,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x4066,0x0000,0x4F39,0x6978,0x0000,0x6979,0x0000,
+0x0000,0x915E,0x0000,0x6A21,0x0000,0x3F2A,0x0000,0x697B,
+0x915F,0x697E,0x0000,0x0000,0x0000,0x0000,0x0000,0x6976,
+0x6975,0x0000,0x0000,0x6A22,0x9160,0x9161,0x325C,0x0000,
+0x697C,0x0000,0x6A23,0x0000,0x0000,0x0000,0x697D,0x0000,
+0x0000,0x7B5A,0x9162,0x0000,0x697A,0x0000,0x4433,0x0000,
+0x6977,0x0000,0x0000,0x0000,0x9163,0x0000,0x0000,0x4768,
+0x0000,0x0000,0x6A27,0x0000,0x0000,0x0000,0x0000,0x7B5B,
+0x7B5C,0x9167,0x0000,0x9168,0x0000,0x4D3B,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x9169,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6A26,
+0x916A,0x0000,0x6A25,0x0000,0x0000,0x0000,0x0000,0x9166,
+0x0000,0x0000,0x0000,0x6A2E,0x7B5D,0x7B5E,0x0000,0x6A28,
+0x0000,0x0000,0x0000,0x6A30,0x0000,0x7B5F,0x0000,0x0000,
+0x0000,0x0000,0x4D66,0x6A33,0x0000,0x6A2A,0x916D,0x0000,
+0x6A2B,0x916F,0x0000,0x0000,0x6A2F,0x0000,0x6A32,0x6A31,
+0x0000,0x0000,0x0000,0x6A29,0x0000,0x0000,0x9170,0x0000,
+0x6A2C,0x0000,0x6A3D,0x0000,0x0000,0x0000,0x7B61,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9172,
+0x6A36,0x0000,0x0000,0x9174,0x0000,0x9175,0x9176,0x0000,
+0x0000,0x0000,0x9177,0x9178,0x7B62,0x9179,0x0000,0x6A34,
+0x0000,0x0000,0x6A35,0x0000,0x0000,0x9171,0x6A3A,0x6A3B,
+0x0000,0x332A,0x0000,0x3542,0x0000,0x0000,0x6A39,0x0000,
+
+/* 8800h */
+0x0000,0x917A,0x0000,0x917B,0x0000,0x6A24,0x7B63,0x0000,
+0x0000,0x0000,0x7B64,0x917C,0x0000,0x6A38,0x6A3C,0x6A37,
+0x7B65,0x6A3E,0x0000,0x917D,0x7B66,0x6A40,0x6A3F,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7B67,
+0x0000,0x6A42,0x6A41,0x695A,0x0000,0x0000,0x0000,0x6A46,
+0x917E,0x0000,0x0000,0x0000,0x0000,0x0000,0x9221,0x0000,
+0x0000,0x6A43,0x9222,0x0000,0x0000,0x0000,0x6A44,0x0000,
+0x0000,0x6A45,0x0000,0x6A47,0x9223,0x0000,0x0000,0x0000,
+0x376C,0x0000,0x6A49,0x0000,0x6A48,0x0000,0x3D30,0x0000,
+0x0000,0x0000,0x9225,0x0000,0x3954,0x5E27,0x0000,0x0000,
+0x0000,0x0000,0x6A4A,0x3D51,0x0000,0x0000,0x0000,0x3339,
+0x9226,0x6A4B,0x0000,0x3152,0x0000,0x3E57,0x6A4C,0x9227,
+0x0000,0x3955,0x6A4D,0x3061,0x9228,0x0000,0x0000,0x0000,
+0x493D,0x922B,0x0000,0x6A4E,0x0000,0x0000,0x0000,0x922D,
+0x3F6A,0x0000,0x6A55,0x0000,0x0000,0x6A52,0x0000,0x436F,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6A53,0x6A50,0x365E,
+0x0000,0x6A4F,0x6A56,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x3736,0x0000,0x0000,0x425E,0x0000,0x6A5C,0x0000,0x0000,
+0x0000,0x0000,0x6A58,0x0000,0x0000,0x0000,0x4235,0x6A57,
+0x7B68,0x6A5A,0x0000,0x0000,0x0000,0x0000,0x6A51,0x0000,
+0x922E,0x0000,0x6A5B,0x0000,0x6A5D,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7B69,0x486F,0x0000,0x0000,0x6A59,0x0000,
+0x6A5E,0x6A60,0x0000,0x0000,0x3853,0x6A54,0x0000,0x3041,
+0x0000,0x0000,0x0000,0x0000,0x922F,0x9230,0x9231,0x6A5F,
+0x9232,0x3A5B,0x4E76,0x6A61,0x6A62,0x4175,0x0000,0x0000,
+0x0000,0x0000,0x7B6A,0x0000,0x0000,0x0000,0x7B6B,0x4E22,
+0x0000,0x9235,0x9233,0x9236,0x6A63,0x4D35,0x0000,0x0000,
+0x6A64,0x6A65,0x0000,0x9237,0x4A64,0x6A66,0x0000,0x3A40,
+0x0000,0x4E23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6A6B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x9238,0x9239,0x6A6C,0x3E58,0x6A6A,0x7B6D,0x0000,0x0000,
+0x4D67,0x6A67,0x0000,0x0000,0x6A69,0x403D,0x3F7E,0x0000,
+
+/* 8900h */
+0x0000,0x923B,0x6A68,0x0000,0x6A6D,0x0000,0x0000,0x4A23,
+0x0000,0x0000,0x6A6F,0x0000,0x6A6E,0x0000,0x0000,0x0000,
+0x336C,0x0000,0x4B2B,0x6A70,0x0000,0x0000,0x0000,0x0000,
+0x7B70,0x7B71,0x7B72,0x0000,0x7B6E,0x6A7C,0x6A72,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6A73,0x0000,0x7B73,
+0x0000,0x0000,0x6A74,0x6A75,0x0000,0x0000,0x0000,0x0000,
+0x7B74,0x0000,0x7B75,0x0000,0x0000,0x0000,0x6A79,0x923D,
+0x6A7A,0x7B76,0x0000,0x6A78,0x0000,0x0000,0x0000,0x0000,
+0x7B77,0x6A76,0x923F,0x6A71,0x6A77,0x9240,0x0000,0x0000,
+0x0000,0x9241,0x0000,0x0000,0x6A7B,0x7037,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3228,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6A7E,0x365F,
+0x6A7D,0x0000,0x9244,0x0000,0x6B22,0x0000,0x6B21,0x0000,
+0x0000,0x0000,0x6B24,0x0000,0x0000,0x6B23,0x0000,0x6B25,
+0x0000,0x0000,0x3D31,0x0000,0x6B26,0x0000,0x0000,0x6B27,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6B28,0x403E,
+0x9245,0x4D57,0x0000,0x6B29,0x0000,0x0000,0x4A24,0x4746,
+0x6B2A,0x9246,0x6B2B,0x382B,0x0000,0x0000,0x0000,0x352C,
+0x9247,0x0000,0x0000,0x6B2C,0x7B78,0x0000,0x3B6B,0x4741,
+0x6B2D,0x0000,0x3350,0x0000,0x0000,0x0000,0x0000,0x9248,
+0x0000,0x6B2E,0x0000,0x0000,0x0000,0x0000,0x6B30,0x4D77,
+0x0000,0x6B2F,0x3F46,0x0000,0x6B31,0x0000,0x0000,0x6B32,
+0x9249,0x0000,0x6B33,0x3451,0x0000,0x0000,0x0000,0x924A,
+0x0000,0x0000,0x6B34,0x0000,0x0000,0x6B35,0x0000,0x6B36,
+0x6B37,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x3351,0x0000,0x7B7A,0x0000,0x924B,0x0000,
+0x924C,0x0000,0x6B38,0x0000,0x6B39,0x6B3A,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3272,0x0000,0x7B7B,0x3F28,0x6B3B,
+0x0000,0x0000,0x0000,0x924D,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x924F,0x0000,0x9250,0x6B3C,0x0000,0x7B7C,0x0000,
+0x6B3D,0x0000,0x0000,0x0000,0x0000,0x9251,0x0000,0x9252,
+
+/* 8A00h */
+0x3840,0x0000,0x447B,0x6B3E,0x0000,0x0000,0x0000,0x0000,
+0x3757,0x0000,0x3F56,0x0000,0x6B41,0x0000,0x4624,0x0000,
+0x6B40,0x9254,0x7B7D,0x3731,0x9255,0x7B7E,0x6B3F,0x4277,
+0x352D,0x0000,0x0000,0x6B42,0x0000,0x6B43,0x0000,0x3E59,
+0x0000,0x9257,0x7C21,0x376D,0x0000,0x6B44,0x0000,0x0000,
+0x0000,0x0000,0x4B2C,0x0000,0x0000,0x405F,0x0000,0x0000,
+0x0000,0x3576,0x0000,0x4C75,0x414A,0x9258,0x6B45,0x7C22,
+0x0000,0x0000,0x3F47,0x4370,0x3E5A,0x0000,0x9259,0x0000,
+0x0000,0x6B46,0x0000,0x0000,0x0000,0x925A,0x6B49,0x7C23,
+0x6B4A,0x0000,0x0000,0x0000,0x0000,0x925B,0x7C24,0x0000,
+0x3A3E,0x4242,0x6B48,0x0000,0x3E5B,0x493E,0x0000,0x0000,
+0x925C,0x0000,0x0000,0x6B47,0x0000,0x7C25,0x3B6C,0x0000,
+0x3153,0x7C26,0x6B4E,0x3758,0x0000,0x0000,0x3B6E,0x0000,
+0x0000,0x3B6D,0x0000,0x4F4D,0x6B4D,0x6B4C,0x4127,0x0000,
+0x354D,0x4F43,0x333A,0x3E5C,0x0000,0x7C27,0x0000,0x0000,
+0x0000,0x7C28,0x0000,0x0000,0x6B4B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6B50,0x0000,0x6B51,0x6B4F,0x0000,0x3858,
+0x0000,0x4D40,0x0000,0x0000,0x3B6F,0x4727,0x0000,0x0000,
+0x925E,0x6B54,0x0000,0x4040,0x0000,0x4342,0x0000,0x0000,
+0x4D36,0x0000,0x6B57,0x0000,0x0000,0x0000,0x386C,0x0000,
+0x403F,0x6B53,0x0000,0x6B58,0x386D,0x6B55,0x6B56,0x7C29,
+0x6B52,0x0000,0x0000,0x0000,0x4062,0x4649,0x925D,0x0000,
+0x432F,0x0000,0x325D,0x0000,0x0000,0x0000,0x0000,0x925F,
+0x0000,0x4870,0x0000,0x0000,0x3543,0x0000,0x9260,0x4434,
+0x0000,0x0000,0x6B5B,0x0000,0x6B59,0x0000,0x0000,0x434C,
+0x0000,0x0000,0x0000,0x4041,0x3452,0x6B5A,0x0000,0x3F5B,
+0x7C2A,0x0000,0x4E4A,0x0000,0x0000,0x0000,0x4F40,0x9261,
+0x0000,0x0000,0x6B5C,0x6B67,0x4435,0x0000,0x6B66,0x7C2B,
+0x6B63,0x6B6B,0x6B64,0x0000,0x6B60,0x0000,0x447C,0x6B5F,
+0x0000,0x0000,0x0000,0x6B5D,0x0000,0x4D21,0x3B70,0x0000,
+0x0000,0x6B61,0x0000,0x6B5E,0x7C2C,0x0000,0x7C2D,0x6B65,
+0x3D74,0x0000,0x3841,0x0000,0x9262,0x0000,0x427A,0x0000,
+
+/* 8B00h */
+0x4B45,0x315A,0x3062,0x0000,0x4625,0x9265,0x0000,0x6B69,
+0x0000,0x0000,0x9264,0x0000,0x6B68,0x9266,0x4666,0x0000,
+0x6B6D,0x0000,0x0000,0x0000,0x6B62,0x0000,0x6B6C,0x6B6E,
+0x0000,0x382C,0x6B6A,0x3956,0x9267,0x3C55,0x0000,0x9268,
+0x6B6F,0x4D58,0x0000,0x0000,0x0000,0x0000,0x6B72,0x0000,
+0x6B75,0x0000,0x0000,0x6B73,0x4935,0x9269,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6B70,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3660,0x0000,0x0000,0x0000,0x0000,0x6B74,0x0000,
+0x0000,0x6B76,0x0000,0x926A,0x0000,0x0000,0x7C31,0x0000,
+0x0000,0x6B7A,0x0000,0x0000,0x6B77,0x0000,0x6B79,0x6B78,
+0x0000,0x926C,0x0000,0x0000,0x7C32,0x0000,0x6B7B,0x0000,
+0x3C31,0x7C33,0x6B7D,0x6B7C,0x4968,0x0000,0x926D,0x6C21,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3759,0x0000,
+0x0000,0x7C34,0x0000,0x6B7E,0x6C22,0x0000,0x0000,0x6C23,
+0x3544,0x6641,0x3E79,0x0000,0x6C24,0x0000,0x926E,0x386E,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6C25,0x0000,0x926F,
+0x6C26,0x9270,0x0000,0x3B3E,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x5A4E,0x9271,0x6C27,0x0000,0x6C28,0x0000,
+0x3D32,0x0000,0x6C29,0x6C2A,0x9272,0x9273,0x6C2B,0x0000,
+0x0000,0x6C2C,0x6C2D,0x0000,0x9274,0x7C35,0x9275,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 8C00h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x432B,
+0x0000,0x9276,0x6C2E,0x0000,0x0000,0x9278,0x0000,0x6C30,
+0x0000,0x6C2F,0x0000,0x0000,0x0000,0x927B,0x4626,0x927C,
+0x6C31,0x7C36,0x4B2D,0x0000,0x6C32,0x0000,0x6C33,0x927D,
+0x6C34,0x0000,0x0000,0x0000,0x927E,0x6C35,0x0000,0x9321,
+0x0000,0x0000,0x465A,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3E5D,0x6C36,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7C37,0x9322,0x396B,0x502E,0x6C37,0x9323,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x9324,0x0000,0x0000,0x0000,0x0000,
+0x6C38,0x493F,0x6C39,0x0000,0x6C41,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6C3A,0x0000,0x0000,0x6C3C,0x0000,0x0000,
+0x0000,0x6C3B,0x6C3D,0x0000,0x4B46,0x6C3E,0x6C3F,0x0000,
+0x0000,0x0000,0x9327,0x9326,0x6C40,0x0000,0x0000,0x0000,
+0x6C42,0x9328,0x0000,0x932A,0x0000,0x332D,0x4467,0x0000,
+0x4969,0x3A62,0x3957,0x0000,0x932B,0x0000,0x0000,0x494F,
+0x325F,0x484E,0x6C45,0x3453,0x4055,0x6C44,0x6C49,0x4379,
+0x4C63,0x0000,0x6C47,0x6C48,0x352E,0x0000,0x6C4A,0x4763,
+0x425F,0x0000,0x0000,0x4871,0x453D,0x6C46,0x0000,0x4B47,
+0x326C,0x6C4C,0x4F28,0x4442,0x4F45,0x0000,0x0000,0x3B71,
+0x6C4B,0x0000,0x4231,0x0000,0x0000,0x6C5C,0x4128,0x0000,
+0x0000,0x4678,0x0000,0x4950,0x0000,0x932D,0x932C,0x0000,
+0x0000,0x932E,0x6C4F,0x3B3F,0x3B72,0x0000,0x3E5E,0x0000,
+0x4765,0x7C39,0x382D,0x6C4E,0x6C4D,0x0000,0x496A,0x0000,
+0x0000,0x0000,0x3C41,0x0000,0x0000,0x4552,0x0000,0x0000,
+0x9330,0x9331,0x0000,0x0000,0x7C3A,0x0000,0x0000,0x0000,
+0x7C3B,0x0000,0x6C51,0x6C52,0x3958,0x6C50,0x7C3C,0x0000,
+
+/* 8D00h */
+0x0000,0x0000,0x0000,0x0000,0x6C53,0x6C54,0x0000,0x6C56,
+0x4223,0x9333,0x6C55,0x3466,0x0000,0x6C58,0x9334,0x6C57,
+0x6C59,0x0000,0x7C3E,0x6C5B,0x6C5D,0x0000,0x6C5E,0x0000,
+0x0000,0x0000,0x0000,0x7C3F,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x4056,0x0000,0x3C4F,0x6C5F,
+0x0000,0x0000,0x0000,0x3352,0x9335,0x6C60,0x0000,0x0000,
+0x4176,0x6C61,0x0000,0x6C62,0x496B,0x0000,0x0000,0x352F,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6C63,0x0000,0x0000,0x9336,0x4436,0x0000,0x0000,
+0x0000,0x0000,0x315B,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x9337,0x0000,0x0000,
+0x0000,0x6C64,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3C71,0x0000,0x0000,0x9338,0x0000,
+0x3F76,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C40,
+0x0000,0x0000,0x0000,0x422D,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6C67,0x0000,0x0000,0x0000,0x6C66,0x0000,
+0x0000,0x0000,0x6C65,0x0000,0x0000,0x0000,0x933A,0x0000,
+0x933B,0x0000,0x0000,0x6C6D,0x6C6B,0x0000,0x7C41,0x6C68,
+0x0000,0x7C42,0x0000,0x0000,0x0000,0x0000,0x6C6A,0x7C43,
+0x0000,0x933C,0x6C69,0x6C6C,0x0000,0x3577,0x0000,0x6C70,
+0x0000,0x4057,0x0000,0x6C71,0x0000,0x0000,0x0000,0x0000,
+0x3859,0x0000,0x6C6E,0x6C6F,0x933D,0x0000,0x0000,0x4F29,
+0x0000,0x0000,0x0000,0x4437,0x0000,0x4129,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x6C72,0x9340,0x0000,0x6C75,
+
+/* 8E00h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9341,0x0000,
+0x6C73,0x6C74,0x4D59,0x0000,0x933E,0x0000,0x0000,0x4627,
+0x6C78,0x0000,0x0000,0x0000,0x9343,0x0000,0x9344,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x6C76,0x6C77,0x6C79,
+0x7C44,0x9345,0x9346,0x7C45,0x0000,0x0000,0x0000,0x9347,
+0x0000,0x0000,0x6D29,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6C7C,0x0000,0x0000,0x0000,0x6C7D,0x6C7B,0x934A,0x0000,
+0x0000,0x934B,0x0000,0x0000,0x0000,0x7C46,0x0000,0x0000,
+0x0000,0x0000,0x6C7A,0x0000,0x447D,0x0000,0x0000,0x6D21,
+0x6D25,0x6D22,0x6C7E,0x934C,0x6D23,0x0000,0x0000,0x0000,
+0x6D24,0x0000,0x0000,0x0000,0x934D,0x6D2B,0x0000,0x0000,
+0x0000,0x6D26,0x0000,0x0000,0x0000,0x0000,0x0000,0x4058,
+0x6D28,0x0000,0x934E,0x6D2A,0x6D27,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x934F,0x9350,0x0000,0x9351,
+0x7C47,0x0000,0x6D2D,0x0000,0x3D33,0x0000,0x6D2C,0x0000,
+0x0000,0x0000,0x0000,0x7C48,0x6D2E,0x0000,0x0000,0x0000,
+0x0000,0x6D2F,0x0000,0x0000,0x6D32,0x6D31,0x0000,0x6D30,
+0x0000,0x0000,0x6D34,0x6D33,0x0000,0x4C76,0x0000,0x0000,
+0x0000,0x6D36,0x0000,0x6D35,0x6D37,0x0000,0x0000,0x0000,
+0x9352,0x6D38,0x0000,0x0000,0x0000,0x0000,0x9353,0x0000,
+0x0000,0x6D3A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6D39,0x3F48,0x6D3B,0x0000,0x9354,0x366D,
+0x6D3C,0x6D3E,0x0000,0x9355,0x0000,0x9356,0x9357,0x0000,
+0x0000,0x0000,0x0000,0x9358,0x0000,0x0000,0x6D3F,0x0000,
+0x7C4A,0x0000,0x0000,0x0000,0x0000,0x6D40,0x6D3D,0x0000,
+0x6D41,0x0000,0x3C56,0x6D42,0x3530,0x3733,0x0000,0x0000,
+0x0000,0x935A,0x382E,0x0000,0x935B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6D43,0x0000,0x0000,0x0000,0x4670,
+0x0000,0x0000,0x453E,0x6D44,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6D47,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x3C34,0x935D,0x7C4C,0x6D46,0x6D45,0x375A,0x6D48,0x0000,
+
+/* 8F00h */
+0x935F,0x0000,0x0000,0x3353,0x0000,0x6D4A,0x0000,0x0000,
+0x9360,0x3A5C,0x6D49,0x0000,0x6D52,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6D4C,0x6D4E,0x4A65,0x6D4B,0x0000,0x9361,
+0x0000,0x6D4D,0x0000,0x6D51,0x6D4F,0x3531,0x7C4D,0x6D50,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6D53,0x0000,
+0x0000,0x475A,0x4E58,0x9362,0x0000,0x7C4E,0x0000,0x3D34,
+0x0000,0x0000,0x0000,0x6D54,0x0000,0x0000,0x7C4F,0x0000,
+0x4D22,0x6D56,0x0000,0x6D55,0x0000,0x0000,0x6D59,0x4D41,
+0x9363,0x0000,0x6D58,0x0000,0x336D,0x6D57,0x6D5C,0x0000,
+0x0000,0x6D5B,0x9364,0x0000,0x6D5A,0x4532,0x6D5D,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x7C50,0x0000,0x0000,0x6D5E,
+0x9365,0x0000,0x0000,0x0000,0x6D5F,0x0000,0x0000,0x396C,
+0x0000,0x3725,0x6D60,0x6D61,0x6D62,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3F49,0x6D63,0x0000,0x3C2D,0x6D64,
+0x0000,0x0000,0x0000,0x6D65,0x9367,0x0000,0x7C52,0x5221,
+0x517E,0x0000,0x0000,0x0000,0x0000,0x6D66,0x6570,0x6D67,
+0x4324,0x3F2B,0x4740,0x0000,0x9368,0x7C53,0x936A,0x6D68,
+0x0000,0x0000,0x4A55,0x4454,0x397E,0x0000,0x0000,0x4329,
+0x0000,0x936C,0x312A,0x0000,0x4B78,0x3F57,0x936D,0x0000,
+0x0000,0x0000,0x936F,0x0000,0x0000,0x9370,0x375E,0x0000,
+0x0000,0x3661,0x0000,0x9371,0x4A56,0x9372,0x0000,0x0000,
+0x0000,0x0000,0x6D69,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x9373,0x0000,0x6D6B,0x0000,0x7C54,0x6D6A,0x3260,0x0000,
+0x7C55,0x4676,0x6D6C,0x4777,0x0000,0x4533,0x7C56,0x6D6D,
+0x3D52,0x9374,0x0000,0x0000,0x6D6F,0x9375,0x0000,0x4C42,
+0x6D7E,0x6D71,0x6D72,0x9376,0x0000,0x4449,0x0000,0x0000,
+
+/* 9000h */
+0x4260,0x4177,0x9377,0x4628,0x0000,0x6D70,0x3555,0x0000,
+0x7C57,0x0000,0x0000,0x6D79,0x9378,0x6D76,0x6E25,0x4629,
+0x4360,0x6D73,0x0000,0x447E,0x4553,0x6D74,0x6D78,0x3F60,
+0x0000,0x4767,0x444C,0x0000,0x0000,0x4042,0x6D77,0x422E,
+0x4224,0x6D75,0x3029,0x4F22,0x0000,0x0000,0x0000,0x6D7A,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7C58,0x4261,0x0000,
+0x0000,0x3D35,0x3F4A,0x0000,0x0000,0x6D7C,0x6D7B,0x9379,
+0x306F,0x6D7D,0x0000,0x0000,0x492F,0x0000,0x6E27,0x0000,
+0x0000,0x465B,0x3F6B,0x937B,0x937C,0x4359,0x0000,0x3678,
+0x0000,0x6E26,0x4D37,0x313F,0x0000,0x4A57,0x3261,0x6E21,
+0x6E22,0x6E23,0x6E24,0x463B,0x4323,0x3063,0x6E28,0x0000,
+0x6E29,0x7423,0x0000,0x0000,0x423D,0x937D,0x6E2A,0x0000,
+0x3173,0x414C,0x0000,0x382F,0x0000,0x4D5A,0x0000,0x0000,
+0x6E2B,0x452C,0x0000,0x0000,0x0000,0x4178,0x3C57,0x6E2C,
+0x0000,0x0000,0x6E2F,0x0000,0x0000,0x3D65,0x6E2D,0x412B,
+0x412A,0x0000,0x3064,0x0000,0x4E4B,0x6E31,0x0000,0x4872,
+0x6E33,0x6E32,0x6E30,0x6364,0x3454,0x9422,0x0000,0x6D6E,
+0x7C5A,0x6E35,0x6E34,0x0000,0x9423,0x0000,0x0000,0x6E36,
+0x9424,0x4D38,0x0000,0x0000,0x0000,0x7C5B,0x0000,0x7C5C,
+0x0000,0x7C5D,0x0000,0x7C5E,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x9426,0x7C5F,0x4661,0x0000,0x0000,0x4B2E,0x0000,
+0x6E37,0x0000,0x3C59,0x0000,0x0000,0x0000,0x0000,0x6E38,
+0x9428,0x6E39,0x0000,0x7C60,0x0000,0x6E3A,0x9429,0x0000,
+0x4521,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C61,0x0000,
+0x0000,0x306A,0x0000,0x942A,0x7C62,0x7C63,0x0000,0x7C64,
+0x942B,0x0000,0x3959,0x0000,0x0000,0x0000,0x4F3A,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C65,
+0x0000,0x0000,0x0000,0x6E3E,0x942D,0x7C66,0x7C67,0x942E,
+0x0000,0x3734,0x6E3B,0x0000,0x6E3C,0x0000,0x0000,0x0000,
+0x4974,0x0000,0x0000,0x9433,0x0000,0x3354,0x0000,0x7C68,
+0x0000,0x0000,0x9431,0x0000,0x7C69,0x4D39,0x9430,0x363F,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x4554,0x9434,0x9435,
+
+/* 9100h */
+0x9432,0x0000,0x6E3F,0x0000,0x9436,0x0000,0x9437,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6E40,0x0000,0x7C6B,0x7C6C,0x7C6D,0x0000,
+0x9438,0x6E41,0x0000,0x0000,0x9439,0x0000,0x943A,0x0000,
+0x0000,0x0000,0x7C6E,0x7C6F,0x0000,0x0000,0x0000,0x7C70,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x4522,0x0000,0x7C71,
+0x6E43,0x7C72,0x6E42,0x0000,0x7C73,0x0000,0x0000,0x943B,
+0x0000,0x943C,0x943D,0x0000,0x0000,0x7C74,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x943E,0x943F,
+0x7C75,0x4653,0x6E44,0x3D36,0x3C60,0x475B,0x4371,0x0000,
+0x0000,0x0000,0x3C72,0x0000,0x3F6C,0x0000,0x6E45,0x9440,
+0x6E46,0x9441,0x0000,0x7C76,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x9442,0x3F5D,0x6E47,0x9443,0x6E48,0x0000,0x0000,
+0x0000,0x6E49,0x4D6F,0x0000,0x3D37,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6E4B,0x6E4A,0x9444,0x395A,0x0000,0x3973,
+0x3B40,0x9445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6E4E,0x7C77,0x0000,0x9446,0x0000,0x3D66,
+0x0000,0x6E4D,0x0000,0x6E4C,0x0000,0x4269,0x9447,0x0000,
+0x386F,0x0000,0x4043,0x0000,0x0000,0x0000,0x0000,0x4830,
+0x0000,0x0000,0x0000,0x0000,0x3D39,0x0000,0x7C78,0x0000,
+0x0000,0x0000,0x6E4F,0x0000,0x3E5F,0x0000,0x0000,0x0000,
+0x9448,0x0000,0x6E52,0x6E50,0x7C79,0x0000,0x9449,0x6E51,
+0x0000,0x7C7A,0x0000,0x944A,0x6E54,0x6E53,0x944B,0x0000,
+0x3E7A,0x0000,0x6E55,0x0000,0x7C7B,0x0000,0x0000,0x0000,
+0x6E56,0x6E57,0x0000,0x944C,0x944D,0x0000,0x4850,0x3A53,
+0x3C61,0x6E58,0x0000,0x6E59,0x4E24,0x3D45,0x4C6E,0x4E4C,
+0x6E5A,0x3662,0x0000,0x0000,0x0000,0x0000,0x6E5B,0x7C7C,
+0x4523,0x0000,0x944E,0x6E5E,0x3378,0x3F4B,0x0000,0x6E5C,
+0x0000,0x6E5D,0x0000,0x4460,0x7C7E,0x7D21,0x4B55,0x367C,
+0x0000,0x0000,0x0000,0x0000,0x9451,0x7D22,0x9452,0x0000,
+0x0000,0x7D23,0x0000,0x0000,0x0000,0x6E60,0x6E61,0x0000,
+0x0000,0x0000,0x0000,0x7C7D,0x6E5F,0x0000,0x0000,0x6E63,
+
+/* 9200h */
+0x0000,0x9453,0x0000,0x0000,0x0000,0x0000,0x0000,0x7D24,
+0x0000,0x0000,0x9454,0x0000,0x0000,0x465F,0x3343,0x0000,
+0x7D25,0x6E67,0x0000,0x0000,0x6E64,0x6E66,0x9455,0x9456,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6E62,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6F4F,0x0000,0x0000,0x6E65,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x9458,0x4E6B,0x0000,0x0000,0x385A,
+0x7D26,0x7D27,0x7D28,0x0000,0x7D29,0x0000,0x0000,0x6E6F,
+0x7D2A,0x0000,0x9459,0x7D2B,0x4534,0x6E6A,0x0000,0x945A,
+0x6E6D,0x6E6B,0x945B,0x6E70,0x0000,0x0000,0x945C,0x7D2C,
+0x6E71,0x945D,0x0000,0x0000,0x0000,0x0000,0x945E,0x6E69,
+0x0000,0x945F,0x6E76,0x3174,0x0000,0x0000,0x6E68,0x0000,
+0x9460,0x9461,0x482D,0x0000,0x6E6C,0x9462,0x3E60,0x9463,
+0x9464,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x395B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7D2D,0x0000,0x0000,0x0000,0x9467,0x9468,0x4B48,0x9469,
+0x3664,0x0000,0x0000,0x3D46,0x0000,0x463C,0x0000,0x0000,
+0x7D2E,0x946A,0x0000,0x0000,0x0000,0x946B,0x0000,0x0000,
+0x0000,0x412D,0x0000,0x6E74,0x0000,0x6E6E,0x6E73,0x946C,
+0x4C43,0x946D,0x4438,0x6E75,0x6E72,0x0000,0x0000,0x946E,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x946F,
+0x0000,0x0000,0x0000,0x9470,0x0000,0x412C,0x0000,0x0000,
+0x0000,0x0000,0x9473,0x0000,0x0000,0x0000,0x0000,0x6E79,
+0x0000,0x6E78,0x0000,0x0000,0x0000,0x0000,0x0000,0x9474,
+0x9475,0x0000,0x7D2F,0x0000,0x0000,0x0000,0x9476,0x0000,
+0x0000,0x0000,0x0000,0x7D30,0x7D31,0x0000,0x9477,0x6E77,
+0x9478,0x0000,0x4B2F,0x7D32,0x0000,0x0000,0x0000,0x9479,
+0x0000,0x947A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7D33,0x0000,0x0000,0x0000,0x3D7B,0x947B,0x0000,0x947C,
+0x0000,0x6E7A,0x4A5F,0x0000,0x0000,0x3154,0x0000,0x0000,
+0x0000,0x0000,0x4946,0x4372,0x0000,0x0000,0x0000,0x9522,
+0x3578,0x9523,0x6E7C,0x9524,0x395D,0x0000,0x0000,0x7D34,
+
+/* 9300h */
+0x0000,0x0000,0x9525,0x0000,0x7D35,0x0000,0x3B2C,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x9526,0x0000,0x6E7B,
+0x3F6D,0x947D,0x0000,0x0000,0x0000,0x9527,0x0000,0x0000,
+0x3F6E,0x6F21,0x6F23,0x0000,0x0000,0x9528,0x9529,0x7D36,
+0x3E7B,0x7D37,0x6F22,0x6F24,0x0000,0x7D38,0x3653,0x952A,
+0x4945,0x952B,0x0000,0x3C62,0x4F23,0x0000,0x6E7E,0x3A78,
+0x0000,0x0000,0x4F3F,0x0000,0x0000,0x6F26,0x0000,0x0000,
+0x0000,0x0000,0x6F25,0x6F27,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x6E7D,0x0000,0x0000,0x952E,
+0x7D39,0x7D3A,0x7D3B,0x4669,0x0000,0x4555,0x0000,0x0000,
+0x0000,0x952F,0x0000,0x0000,0x4457,0x0000,0x6F2C,0x9530,
+0x0000,0x0000,0x9531,0x4343,0x6F28,0x0000,0x0000,0x0000,
+0x6F29,0x0000,0x0000,0x0000,0x7D3C,0x7D3D,0x0000,0x0000,
+0x0000,0x0000,0x7D3E,0x9532,0x372D,0x0000,0x6F2B,0x0000,
+0x7D3F,0x9533,0x0000,0x9534,0x0000,0x3830,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x6F2A,0x0000,0x3E61,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x9538,0x0000,0x0000,0x9539,0x3379,0x0000,0x0000,0x953A,
+0x0000,0x0000,0x0000,0x0000,0x6F30,0x0000,0x3A3F,0x4179,
+0x0000,0x0000,0x444A,0x7D40,0x0000,0x0000,0x953B,0x0000,
+0x0000,0x9535,0x0000,0x7D41,0x0000,0x0000,0x0000,0x333B,
+0x0000,0x0000,0x0000,0x0000,0x6F2E,0x6F2F,0x4443,0x0000,
+0x6F2D,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6F31,0x7D42,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x9540,0x0000,0x6F37,0x0000,0x0000,0x7D43,0x9541,
+0x6F3A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6F39,0x452D,0x0000,0x0000,0x0000,0x0000,0x6F32,0x6F33,
+0x6F36,0x0000,0x0000,0x0000,0x9542,0x6F38,0x7D44,0x7D45,
+0x0000,0x3640,0x9543,0x0000,0x6F3B,0x6F35,0x0000,0x9544,
+0x6F34,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x953F,0x0000,0x0000,0x0000,0x953C,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x9549,0x0000,0x7D47,0x0000,0x0000,
+
+/* 9400h */
+0x0000,0x0000,0x0000,0x6F3F,0x7D46,0x0000,0x0000,0x6F40,
+0x0000,0x9545,0x0000,0x0000,0x0000,0x0000,0x0000,0x9546,
+0x6F41,0x0000,0x0000,0x6F3E,0x6F3D,0x0000,0x9547,0x9548,
+0x3E62,0x462A,0x6F3C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6F45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6F43,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x954A,0x7D48,0x954B,0x6F44,0x6F42,0x0000,
+0x4278,0x0000,0x6F46,0x954C,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x6F47,0x0000,0x0000,0x6F49,0x954D,0x0000,0x0000,
+0x0000,0x0000,0x7D49,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x3455,0x6F48,0x4C7A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6F54,0x6F4A,0x0000,0x0000,0x6F4D,0x0000,
+0x6F4B,0x0000,0x6F4C,0x7D4A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x6F4E,0x7D4B,0x0000,0x9550,0x0000,0x9551,
+0x6F50,0x7D4C,0x7D4D,0x0000,0x0000,0x6F51,0x0000,0x6F52,
+0x0000,0x0000,0x0000,0x0000,0x6F55,0x6F53,0x6F56,0x6F58,
+0x0000,0x6F57,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 9500h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4439,
+0x9552,0x9553,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4C67,0x0000,0x6F59,0x412E,0x0000,0x0000,0x9554,0x6F5A,
+0x0000,0x4A44,0x6F5B,0x332B,0x9555,0x9556,0x7D4E,0x313C,
+0x0000,0x3457,0x0000,0x3456,0x6F5C,0x0000,0x6F5D,0x0000,
+0x6F5E,0x6F5F,0x0000,0x0000,0x0000,0x0000,0x0000,0x7D4F,
+0x6F60,0x0000,0x3458,0x3355,0x395E,0x4836,0x7D50,0x6F62,
+0x6F61,0x7D51,0x0000,0x9558,0x7D52,0x6F63,0x0000,0x0000,
+0x0000,0x0000,0x315C,0x0000,0x9559,0x0000,0x7D53,0x0000,
+0x0000,0x6F66,0x0000,0x6F65,0x6F64,0x7D54,0x6F67,0x0000,
+0x0000,0x0000,0x0000,0x6F6A,0x0000,0x0000,0x0000,0x3047,
+0x955B,0x0000,0x6F68,0x7D55,0x6F6C,0x6F6B,0x0000,0x0000,
+0x7D56,0x0000,0x0000,0x7D57,0x6F6E,0x6F6D,0x6F6F,0x0000,
+0x462E,0x0000,0x7D59,0x0000,0x6F70,0x0000,0x7D5A,0x0000,
+0x0000,0x6F71,0x6F73,0x0000,0x0000,0x6F72,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 9600h */
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x496C,0x9425,0x0000,0x0000,
+0x0000,0x6F74,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x6F75,0x0000,0x3A65,0x0000,0x955E,0x0000,0x6F76,0x6F77,
+0x0000,0x0000,0x4B49,0x955F,0x9560,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x414B,0x9562,0x0000,0x0000,0x3024,
+0x424B,0x9563,0x6F78,0x0000,0x496D,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6F7B,0x6F79,0x395F,0x0000,0x6F7A,
+0x3842,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7D5B,0x0000,0x0000,0x4A45,0x6F7D,0x7021,0x6F7E,0x7022,
+0x0000,0x9564,0x3121,0x3F58,0x3D7C,0x3459,0x7023,0x0000,
+0x0000,0x0000,0x4766,0x0000,0x7025,0x0000,0x0000,0x0000,
+0x3122,0x0000,0x7024,0x4444,0x0000,0x4E4D,0x462B,0x6F7C,
+0x4E26,0x0000,0x3831,0x0000,0x0000,0x4D5B,0x0000,0x0000,
+0x0000,0x0000,0x9566,0x0000,0x7D5C,0x3679,0x4E34,0x0000,
+0x3728,0x0000,0x4262,0x6721,0x0000,0x7026,0x332C,0x3F6F,
+0x0000,0x0000,0x0000,0x0000,0x3356,0x7028,0x0000,0x7029,
+0x7027,0x3764,0x9568,0x3A5D,0x3E63,0x7D5E,0x0000,0x0000,
+0x3123,0x0000,0x0000,0x4E59,0x7D5F,0x7D60,0x0000,0x702B,
+0x6E2E,0x956B,0x702A,0x0000,0x0000,0x0000,0x0000,0x956C,
+0x702E,0x702C,0x702D,0x956D,0x702F,0x0000,0x7030,0x4E6C,
+0x7031,0x7032,0x956E,0x4049,0x483B,0x956F,0x0000,0x0000,
+0x3F7D,0x3467,0x0000,0x0000,0x4D3A,0x326D,0x3D38,0x385B,
+0x0000,0x7035,0x0000,0x7034,0x3B73,0x7036,0x7033,0x0000,
+0x0000,0x3B28,0x7D61,0x0000,0x0000,0x703A,0x6A2D,0x0000,
+0x9572,0x5256,0x9573,0x3F77,0x7038,0x9574,0x7D62,0x0000,
+0x0000,0x0000,0x4E25,0x4671,0x0000,0x0000,0x0000,0x0000,
+0x312B,0x7D64,0x4063,0x3C36,0x0000,0x0000,0x0000,0x7D65,
+0x4A37,0x0000,0x3140,0x0000,0x0000,0x0000,0x4E6D,0x4D6B,
+0x0000,0x703B,0x0000,0x4545,0x0000,0x0000,0x0000,0x0000,
+
+/* 9700h */
+0x3C7B,0x0000,0x0000,0x0000,0x703C,0x0000,0x703D,0x3F4C,
+0x703E,0x0000,0x4E6E,0x0000,0x0000,0x7039,0x7040,0x7042,
+0x0000,0x7041,0x0000,0x703F,0x9576,0x0000,0x7043,0x0000,
+0x0000,0x7044,0x0000,0x0000,0x417A,0x0000,0x3262,0x0000,
+0x0000,0x0000,0x0000,0x9577,0x7045,0x0000,0x0000,0x4C38,
+0x0000,0x0000,0x7046,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7047,0x0000,0x4F2A,0x7D66,0x0000,0x0000,0x9579,0x0000,
+0x5B31,0x7048,0x0000,0x7D67,0x0000,0x7049,0x704A,0x0000,
+0x0000,0x957A,0x704E,0x0000,0x704B,0x0000,0x704C,0x957B,
+0x704D,0x704F,0x0000,0x0000,0x0000,0x7D68,0x7D69,0x7D6A,
+0x0000,0x0000,0x4044,0x0000,0x0000,0x957C,0x4C77,0x957D,
+0x0000,0x4045,0x7D6B,0x957E,0x7050,0x0000,0x4873,0x0000,
+0x7051,0x7353,0x4C4C,0x0000,0x7052,0x0000,0x7053,0x0000,
+0x7054,0x3357,0x9621,0x7056,0x0000,0x3F59,0x7D6C,0x0000,
+0x0000,0x7057,0x0000,0x7D6D,0x3724,0x0000,0x0000,0x0000,
+0x0000,0x7058,0x705C,0x0000,0x705A,0x0000,0x0000,0x0000,
+0x0000,0x705B,0x0000,0x0000,0x3373,0x7059,0x705D,0x0000,
+0x0000,0x0000,0x0000,0x705E,0x0000,0x3048,0x0000,0x705F,
+0x7060,0x0000,0x0000,0x0000,0x0000,0x7D6E,0x9624,0x0000,
+0x3E64,0x0000,0x9625,0x0000,0x7061,0x0000,0x9626,0x0000,
+0x3547,0x0000,0x9627,0x7064,0x0000,0x0000,0x7063,0x0000,
+0x7062,0x0000,0x0000,0x6B71,0x0000,0x4A5C,0x7D6F,0x0000,
+0x0000,0x9628,0x9629,0x7065,0x7066,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7D70,0x0000,0x0000,0x0000,0x962A,0x0000,
+0x0000,0x7D71,0x0000,0x7067,0x0000,0x0000,0x7068,0x0000,
+0x7069,0x7D72,0x0000,0x706A,0x962B,0x0000,0x0000,0x0000,
+0x0000,0x962C,0x0000,0x345A,0x962D,0x0000,0x0000,0x0000,
+0x962E,0x962F,0x0000,0x7D74,0x706B,0x0000,0x7D73,0x0000,
+0x0000,0x9630,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x706C,0x4723,0x0000,
+0x0000,0x9631,0x706E,0x323B,0x7D75,0x7071,0x7070,0x0000,
+0x0000,0x0000,0x0000,0x3124,0x0000,0x0000,0x0000,0x3641,
+
+/* 9800h */
+0x0000,0x4A47,0x443A,0x3A22,0x9632,0x3960,0x3D67,0x0000,
+0x3F5C,0x0000,0x7D77,0x0000,0x7073,0x9633,0x9634,0x7072,
+0x4D42,0x3468,0x4852,0x465C,0x9635,0x0000,0x9636,0x3F7C,
+0x4E4E,0x0000,0x375B,0x0000,0x0000,0x0000,0x7D78,0x0000,
+0x0000,0x7076,0x0000,0x9639,0x7075,0x963C,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7D79,0x4B4B,0x462C,0x0000,0x0000,
+0x7D7A,0x0000,0x963A,0x963B,0x3150,0x0000,0x0000,0x7077,
+0x7074,0x0000,0x0000,0x4951,0x4D6A,0x7078,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7079,0x963D,
+0x0000,0x0000,0x0000,0x707B,0x426A,0x335B,0x335C,0x707A,
+0x0000,0x0000,0x7D7C,0x7D7D,0x3469,0x3832,0x7D7E,0x7E21,
+0x346A,0x7E22,0x7E23,0x453F,0x0000,0x0000,0x4E60,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7E25,0x963E,0x385C,
+0x0000,0x0000,0x0000,0x707C,0x7E26,0x0000,0x0000,0x707D,
+0x707E,0x7121,0x0000,0x7123,0x7122,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4977,0x0000,0x7124,0x963F,0x0000,0x9640,0x0000,0x7125,
+0x9641,0x7126,0x0000,0x0000,0x0000,0x0000,0x7127,0x9643,
+0x9644,0x0000,0x7E27,0x9645,0x9646,0x0000,0x0000,0x9647,
+0x0000,0x0000,0x9648,0x7129,0x7128,0x0000,0x712A,0x9649,
+0x7E28,0x0000,0x0000,0x964A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x4874,0x664C,0x0000,0x0000,0x3F29,
+0x964B,0x964D,0x3532,0x964E,0x0000,0x964F,0x0000,0x7E29,
+0x0000,0x712B,0x9650,0x712C,0x0000,0x522C,0x5D3B,0x4853,
+0x9651,0x9652,0x307B,0x9653,0x303B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x3B74,0x4B30,0x3E7E,0x0000,
+
+/* 9900h */
+0x0000,0x0000,0x0000,0x712D,0x0000,0x4C5F,0x0000,0x0000,
+0x9654,0x712E,0x4D5C,0x0000,0x3142,0x0000,0x0000,0x0000,
+0x3B41,0x0000,0x712F,0x326E,0x7130,0x0000,0x9657,0x9658,
+0x7131,0x0000,0x965A,0x965B,0x965C,0x7133,0x7134,0x0000,
+0x7136,0x7132,0x0000,0x0000,0x7135,0x0000,0x0000,0x0000,
+0x345B,0x0000,0x0000,0x0000,0x7137,0x0000,0x7138,0x0000,
+0x0000,0x965E,0x965F,0x9660,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x9661,0x9662,0x9663,0x7139,0x713A,0x0000,
+0x9664,0x9665,0x713B,0x0000,0x0000,0x713D,0x9666,0x0000,
+0x0000,0x713C,0x0000,0x713F,0x7142,0x9667,0x9668,0x0000,
+0x713E,0x7140,0x7141,0x0000,0x0000,0x7143,0x0000,0x3642,
+0x7E2A,0x0000,0x0000,0x0000,0x9669,0x0000,0x0000,0x966A,
+0x966B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3C73,0x7144,
+0x7145,0x3961,0x0000,0x0000,0x0000,0x0000,0x7E2B,0x0000,
+0x0000,0x0000,0x0000,0x966C,0x0000,0x7146,0x966D,0x0000,
+0x333E,0x0000,0x0000,0x0000,0x474F,0x7147,0x7148,0x0000,
+0x0000,0x0000,0x0000,0x435A,0x466B,0x0000,0x0000,0x0000,
+0x0000,0x966E,0x0000,0x0000,0x7149,0x966F,0x0000,0x9670,
+0x0000,0x477D,0x0000,0x9671,0x424C,0x3158,0x366E,0x0000,
+0x366F,0x9672,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x4373,0x714E,0x3670,0x0000,0x9673,0x326F,0x0000,0x0000,
+0x714D,0x9674,0x0000,0x714B,0x0000,0x714C,0x9675,0x714A,
+0x0000,0x0000,0x7158,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x714F,0x7150,0x0000,
+0x9677,0x7151,0x7152,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7154,0x9678,0x0000,0x7153,0x9679,0x0000,0x0000,0x3D59,
+
+/* 9A00h */
+0x0000,0x7155,0x7E2C,0x7E2D,0x0000,0x7157,0x0000,0x0000,
+0x0000,0x0000,0x967A,0x0000,0x0000,0x0000,0x3533,0x7156,
+0x0000,0x967B,0x417B,0x3833,0x0000,0x0000,0x967C,0x0000,
+0x0000,0x7159,0x967D,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x967E,0x0000,0x0000,0x0000,0x7E2E,0x0000,0x0000,0x0000,
+0x424D,0x0000,0x0000,0x715A,0x0000,0x7E2F,0x7E30,0x0000,
+0x462D,0x9721,0x0000,0x0000,0x0000,0x0000,0x9722,0x715B,
+0x7E31,0x0000,0x0000,0x0000,0x0000,0x0000,0x7160,0x0000,
+0x715E,0x0000,0x715D,0x715F,0x9723,0x715C,0x0000,0x0000,
+0x0000,0x0000,0x7E32,0x0000,0x9724,0x7162,0x7E33,0x0000,
+0x0000,0x0000,0x7E34,0x0000,0x0000,0x7161,0x0000,0x7164,
+0x9725,0x0000,0x3643,0x7163,0x0000,0x0000,0x0000,0x7165,
+0x0000,0x0000,0x7166,0x0000,0x7168,0x7167,0x0000,0x0000,
+0x0000,0x7169,0x716B,0x716A,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x397C,0x0000,0x0000,0x0000,0x0000,0x716C,0x0000,0x9727,
+0x716D,0x0000,0x0000,0x0000,0x0000,0x0000,0x7E35,0x9729,
+0x333C,0x972B,0x0000,0x0000,0x716E,0x0000,0x0000,0x0000,
+0x716F,0x7E36,0x0000,0x7E37,0x3F71,0x0000,0x972D,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7E38,0x7170,
+0x972E,0x7171,0x972F,0x7172,0x7173,0x9730,0x7E39,0x0000,
+0x3962,0x0000,0x0000,0x0000,0x9732,0x0000,0x7174,0x7175,
+0x9733,0x0000,0x7176,0x7177,0x0000,0x9734,0x7178,0x0000,
+0x0000,0x9735,0x4831,0x717A,0x0000,0x4926,0x717B,0x7179,
+0x0000,0x717D,0x0000,0x0000,0x717C,0x0000,0x0000,0x717E,
+0x0000,0x7E3A,0x0000,0x7221,0x0000,0x0000,0x0000,0x0000,
+
+/* 9B00h */
+0x0000,0x0000,0x7E3B,0x9736,0x0000,0x0000,0x7222,0x0000,
+0x7E3C,0x0000,0x0000,0x0000,0x9737,0x0000,0x0000,0x0000,
+0x9738,0x0000,0x9739,0x0000,0x0000,0x0000,0x973A,0x0000,
+0x7223,0x0000,0x7224,0x0000,0x973B,0x0000,0x0000,0x7225,
+0x7E3D,0x0000,0x7226,0x7227,0x0000,0x7228,0x0000,0x7229,
+0x722A,0x722B,0x722C,0x973C,0x0000,0x7E3F,0x722D,0x722E,
+0x0000,0x5D35,0x722F,0x973D,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x6478,0x3534,0x973E,0x0000,0x0000,
+0x0000,0x3321,0x3A32,0x7231,0x7230,0x4C25,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x9740,0x0000,0x7233,0x7234,0x7232,
+0x0000,0x7235,0x0000,0x0000,0x4B62,0x0000,0x0000,0x0000,
+0x7236,0x0000,0x357B,0x0000,0x0000,0x0000,0x7E40,0x0000,
+0x0000,0x0000,0x0000,0x9741,0x0000,0x9742,0x7E42,0x0000,
+0x0000,0x0000,0x0000,0x9743,0x9744,0x0000,0x0000,0x4F25,
+0x0000,0x0000,0x7E43,0x9745,0x7237,0x7E44,0x9746,0x9747,
+0x0000,0x7E41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x7239,0x7E45,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x7E46,0x0000,0x0000,0x0000,0x303E,0x7E47,
+0x0000,0x723A,0x4A2B,0x7238,0x0000,0x0000,0x723B,0x723C,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7E48,0x723D,
+0x723E,0x0000,0x0000,0x0000,0x0000,0x0000,0x9748,0x7E49,
+0x723F,0x0000,0x4B6E,0x3B2D,0x9749,0x3A7A,0x412F,0x0000,
+0x0000,0x974A,0x974D,0x0000,0x7240,0x0000,0x0000,0x0000,
+0x974E,0x7243,0x0000,0x0000,0x0000,0x0000,0x974F,0x0000,
+0x7241,0x7E4A,0x0000,0x0000,0x0000,0x0000,0x7244,0x9750,
+0x0000,0x3871,0x7242,0x0000,0x0000,0x0000,0x7E4B,0x7245,
+0x0000,0x7246,0x7247,0x0000,0x724B,0x0000,0x3B2A,0x0000,
+0x9752,0x0000,0x0000,0x4264,0x0000,0x9753,0x0000,0x0000,
+0x0000,0x724C,0x7249,0x7248,0x724A,0x7E4C,0x0000,0x9754,
+0x375F,0x0000,0x9755,0x9756,0x0000,0x0000,0x9758,0x9757,
+0x7250,0x724F,0x724E,0x9751,0x0000,0x3033,0x0000,0x975C,
+0x7E4D,0x0000,0x975A,0x0000,0x0000,0x7E4E,0x0000,0x0000,
+
+/* 9C00h */
+0x7E4F,0x0000,0x0000,0x0000,0x725A,0x0000,0x7256,0x0000,
+0x7257,0x7253,0x7259,0x0000,0x7255,0x3362,0x0000,0x0000,
+0x4F4C,0x0000,0x7258,0x7254,0x7252,0x7251,0x975E,0x0000,
+0x975F,0x9760,0x9761,0x725C,0x0000,0x9762,0x0000,0x0000,
+0x0000,0x725F,0x9763,0x7E50,0x725E,0x725D,0x0000,0x9764,
+0x0000,0x9765,0x9766,0x0000,0x0000,0x4949,0x725B,0x3073,
+0x7260,0x9768,0x7262,0x0000,0x0000,0x0000,0x9769,0x976A,
+0x0000,0x336F,0x724D,0x3137,0x0000,0x0000,0x7264,0x0000,
+0x0000,0x7E51,0x0000,0x0000,0x0000,0x976B,0x7263,0x7261,
+0x432D,0x976E,0x976F,0x0000,0x0000,0x0000,0x0000,0x7E52,
+0x7E53,0x0000,0x4B70,0x7E54,0x9771,0x0000,0x0000,0x4E5A,
+0x9772,0x0000,0x7265,0x9773,0x976C,0x9774,0x0000,0x9775,
+0x7266,0x0000,0x0000,0x7E55,0x0000,0x7E56,0x0000,0x7267,
+0x0000,0x9776,0x9777,0x9778,0x0000,0x9779,0x977A,0x0000,
+0x977B,0x0000,0x977C,0x0000,0x0000,0x977D,0x7268,0x7E57,
+0x7269,0x0000,0x977E,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x443B,0x9821,0x726A,
+0x0000,0x4837,0x0000,0x726F,0x726B,0x0000,0x0000,0x0000,
+0x726C,0x0000,0x9822,0x4B31,0x4C44,0x0000,0x4650,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+/* 9D00h */
+0x0000,0x0000,0x9824,0x7270,0x0000,0x0000,0x7271,0x463E,
+0x726E,0x726D,0x0000,0x9823,0x0000,0x0000,0x322A,0x0000,
+0x0000,0x9826,0x7279,0x0000,0x0000,0x7278,0x0000,0x9827,
+0x9828,0x0000,0x0000,0x3175,0x0000,0x7E58,0x7E59,0x7276,
+0x0000,0x0000,0x0000,0x7275,0x0000,0x0000,0x7273,0x0000,
+0x337B,0x0000,0x7272,0x3C32,0x3229,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x982C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x3963,0x0000,0x0000,0x727C,0x727B,
+0x0000,0x727A,0x982E,0x7E5A,0x7277,0x0000,0x727D,0x7E5B,
+0x727E,0x0000,0x982F,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x7325,0x7324,0x7E5C,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x7326,0x0000,0x0000,0x312D,0x7321,0x7322,0x9830,
+0x3974,0x4C39,0x9831,0x7E5D,0x7323,0x0000,0x0000,0x0000,
+0x0000,0x9833,0x0000,0x9834,0x4B32,0x0000,0x0000,0x732B,
+0x7E5E,0x0000,0x7327,0x9836,0x0000,0x0000,0x9837,0x9838,
+0x0000,0x0000,0x732C,0x0000,0x7E5F,0x0000,0x9839,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x983A,0x0000,0x0000,0x7329,
+0x0000,0x7328,0x7E60,0x0000,0x0000,0x983B,0x0000,0x375C,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7E61,0x0000,
+0x0000,0x983C,0x732D,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x983D,0x0000,0x0000,0x732E,0x0000,0x0000,0x0000,
+0x0000,0x732F,0x0000,0x732A,0x7E63,0x0000,0x0000,0x7274,
+0x0000,0x0000,0x7330,0x0000,0x4461,0x983F,0x0000,0x0000,
+0x7334,0x9840,0x7335,0x7333,0x7E64,0x9841,0x0000,0x983E,
+0x7E62,0x7332,0x7338,0x9842,0x7331,0x0000,0x7336,0x9843,
+0x0000,0x9844,0x0000,0x0000,0x0000,0x0000,0x0000,0x7337,
+0x0000,0x0000,0x0000,0x733A,0x0000,0x0000,0x9845,0x7E65,
+0x0000,0x7339,0x9846,0x0000,0x0000,0x0000,0x0000,0x9847,
+0x9848,0x0000,0x0000,0x9849,0x0000,0x0000,0x733C,0x7E67,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x733D,0x0000,0x733E,
+0x0000,0x0000,0x4F49,0x0000,0x984A,0x0000,0x0000,0x0000,
+0x733B,0x426B,0x3A6D,0x0000,0x0000,0x733F,0x0000,0x0000,
+
+/* 9E00h */
+0x0000,0x0000,0x984D,0x0000,0x0000,0x0000,0x0000,0x7E68,
+0x0000,0x0000,0x984C,0x0000,0x0000,0x984E,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7E69,0x0000,0x0000,
+0x0000,0x984F,0x7340,0x7341,0x9850,0x9851,0x7342,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x7343,0x0000,0x0000,
+0x3834,0x7344,0x0000,0x9852,0x7E6A,0x7345,0x0000,0x3C2F,
+0x9854,0x7346,0x0000,0x0000,0x0000,0x9855,0x0000,0x0000,
+0x7347,0x0000,0x0000,0x7348,0x7349,0x0000,0x0000,0x0000,
+0x0000,0x734C,0x734A,0x4F3C,0x0000,0x734B,0x0000,0x4E6F,
+0x0000,0x0000,0x0000,0x9856,0x0000,0x734D,0x7E6B,0x4E5B,
+0x0000,0x0000,0x0000,0x0000,0x7E6C,0x734E,0x477E,0x0000,
+0x9857,0x734F,0x7351,0x0000,0x7E6D,0x7352,0x0000,0x7E6E,
+0x0000,0x0000,0x0000,0x0000,0x7E6F,0x7E70,0x0000,0x0000,
+0x7350,0x396D,0x4C4D,0x4B63,0x5677,0x9859,0x5D60,0x4B7B,
+0x0000,0x0000,0x0000,0x7E71,0x322B,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x7354,0x3550,0x7355,0x7356,
+0x7357,0x7E72,0x3975,0x0000,0x7358,0x0000,0x0000,0x0000,
+0x6054,0x4C5B,0x0000,0x4263,0x7359,0x735B,0x735A,0x985B,
+0x735C,0x0000,0x0000,0x0000,0x0000,0x735D,0x0000,0x985C,
+0x735E,0x0000,0x0000,0x0000,0x0000,0x0000,0x985D,0x735F,
+0x0000,0x0000,0x0000,0x0000,0x7360,0x0000,0x7361,0x7362,
+0x0000,0x7363,0x0000,0x7364,0x7365,0x7366,0x0000,0x985E,
+
+/* 9F00h */
+0x0000,0x0000,0x985F,0x9861,0x0000,0x0000,0x0000,0x7367,
+0x7368,0x0000,0x0000,0x0000,0x0000,0x0000,0x4524,0x0000,
+0x7E73,0x0000,0x0000,0x385D,0x0000,0x736A,0x0000,0x9862,
+0x0000,0x9863,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x414D,0x736B,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x736C,0x0000,0x0000,0x9864,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9865,
+0x0000,0x7E74,0x9866,0x4921,0x0000,0x9867,0x736D,0x0000,
+0x0000,0x9868,0x0000,0x0000,0x0000,0x9869,0x986A,0x0000,
+0x0000,0x0000,0x736E,0x6337,0x0000,0x0000,0x6C5A,0x706D,
+0x0000,0x0000,0x736F,0x986B,0x7370,0x986C,0x0000,0x7E75,
+0x986D,0x0000,0x0000,0x0000,0x0000,0x986F,0x0000,0x7372,
+0x7373,0x7374,0x4E70,0x7371,0x0000,0x0000,0x7375,0x7376,
+0x0000,0x9871,0x7378,0x0000,0x7377,0x9873,0x0000,0x0000,
+0x9874,0x0000,0x737A,0x0000,0x0000,0x9875,0x737B,0x7379,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x4E36,0x0000,0x0000,
+0x7E76,0x0000,0x0000,0x0000,0x7E77,0x737C,0x0000,0x7E78,
+0x0000,0x0000,0x0000,0x0000,0x737D,0x6354,0x0000,0x0000,
+0x737E,0x0000,0x7E79,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+};
+
+static const int ucs_i_jisx0213_table_min = 0x4E00;
+static const int ucs_i_jisx0213_table_max = 0x4E00 + (sizeof(ucs_i_jisx0213_table)/
+ sizeof(unsigned short));
+
+/* Halfwidth and Fullwidth Forms */
+static const unsigned short ucs_r_jisx0213_table[] = { // 0xff00 - 0xffe5
+
+/* FF00h */
+0x0000,0x212A,0x2230,0x2174,0x2170,0x2173,0x2175,0x222F,
+0x214A,0x214B,0x2176,0x215C,0x2124,0x2231,0x2125,0x213F,
+0x2330,0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,
+0x2338,0x2339,0x2127,0x2128,0x2163,0x2161,0x2164,0x2129,
+0x2177,0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,
+0x2348,0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F,
+0x2350,0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,
+0x2358,0x2359,0x235A,0x214E,0x2140,0x214F,0x2130,0x2132,
+0x212E,0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,
+0x2368,0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F,
+0x2370,0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,
+0x2378,0x2379,0x237A,0x2150,0x2143,0x2151,0x2232,0x2256,
+0x2257,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,
+0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF,
+0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,
+0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF,
+0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,
+0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF,
+0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,
+0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x2131,0x0000,0x216F,};
+
+static const int ucs_r_jisx0213_table_min = 0xFF00;
+static const int ucs_r_jisx0213_table_max = 0xFF00 + (sizeof(ucs_r_jisx0213_table)/
+ sizeof(unsigned short));
+
+/* CJK Compatibility Ideographs : U+F900 - U+FAFF */
+static const unsigned short ucs_r2_jisx0213_table[] = { // 0xfa0f - 0xfa6a
+0x2F4B,
+0x2F57,0x4F72,0x0000,0x8679,0x757A,0x775A,0x776F,0x0000,
+0x0000,0x793C,0x793D,0x7941,0x0000,0x0000,0x0000,0x7B3A,
+0x9138,0x9145,0x7C2E,0x0000,0x936E,0x0000,0x7C6A,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x2E38,0x2E49,0x2E50,0x2E63,0x2E68,0x2E6E,0x2F2C,0x2F2F,
+0x2F36,0x2F5A,0x2F5E,0x4F61,0x4F62,0x7450,0x745C,0x745E,
+0x7461,0x7528,0x752B,0x7543,0x7565,0x7669,0x7677,0x7725,
+0x7755,0x8A29,0x7825,0x7927,0x7933,0x7934,0x7937,0x7938,
+0x7939,0x793B,0x793F,0x7940,0x794D,0x7951,0x7964,0x7A2E,
+0x8E50,0x7A33,0x7A3A,0x7A44,0x7A58,0x8F74,0x8F75,0x7B27,
+0x7B6F,0x7B79,0x7C2F,0x7C30,0x7C38,0x7C3D,0x9369,0x7C59,
+0x7D63,0x7D76,0x7D7B,};
+
+static const int ucs_r2_jisx0213_min = 0xFA0F;
+static const int ucs_r2_jisx0213_max = 0xFA6A;
+
+/*
+ CJK Compatibility Ideographs: U+F900 - U+FAFF (seperate mapping for U+F9XX)
+*/
+static const unsigned short ucs_r2b_jisx0213_cmap_key[] = {
+ 0xf91d,0xf928,0xf929,0xf936,0xf970,0xf9d0,0xf9dc};
+
+static const unsigned short ucs_r2b_jisx0213_cmap_val[] = {
+ 0x763b,0x742e,0x754e,0x7b4f,0x7649,0x7e24,0x7d5d};
+
+static const int ucs_r2b_jisx0213_cmap_len =
+ sizeof(ucs_r2b_jisx0213_cmap_key)/sizeof(unsigned short);
+
+/*
+ U+1E00 - U+4DBF in compresed mapping
+
+ Latin Extended Additional: U+1E00 - U+1EFF
+ Greek Extended: U+1F00 - U+1FFF
+ General Punctuation: U+2000 - U+206F
+ Currency Symbols U+20A0 - U+20CF
+ Combining Diacritical Marks for Symbols: U+20D0 - 20FF
+ Number Forms: U+2150 - U+218F
+ Arrow : U+2190 - U+21FF
+ Mathematical Operations : U+2200 - U+22FF
+ Miscellaneous Technical : U+2300 - U+23FF
+ Enclosed Alphanumerics : U+2460 - U+24FF
+ Box Drawing: U+2500 - U+257F
+ Geometric Shapes: U+25A0 - U+25FF
+ Miscellanuous Symbols : U+2600 - U+26FF
+ Digbats : U+2700 - U+27BF
+ Supplemental Arrows-B: U+2900 - U+297F
+ Miscellaneous Mathematical Symbols-B: U+2980 - U+29FF
+ CJK Symbols and Punctution: U+3000 - U+303F
+ Hiragana (*1) : U+3040 - U+309F
+ Katakana (*1): U+30A0 - U+30FF
+ CJK Strokes: U+31C0-31EF
+ Katakana Phonetic Extensions : U+31F0 - U+31FF
+ CJK Unified Ideographs Extension A: U+3400 - U+4DBF
+
+ *1 U+3000 - U+30FF is also defined in ucs_hk to optimize for speed.
+ */
+static const unsigned short ucs_c1_jisx0213_tbl[] = { // 0x1e00 - 0x4dff
+0x1E3E,0x1E3F,0x1F70,0x1F71,0x1F72,0x1F73,0x2010,0x2010,
+0x2013,0x2013,0x2014,0x2014,0x2016,0x2016,0x2018,0x2019,
+0x201C,0x201D,0x2020,0x2021,0x2022,0x2022,0x2025,0x2025,
+0x2026,0x2026,0x2030,0x2030,0x2032,0x2033,0x203B,0x203B,
+0x203C,0x203C,0x203E,0x203E,0x203F,0x203F,0x2042,0x2042,
+0x2047,0x2049,0x2051,0x2051,0x20AC,0x20AC,0x2103,0x2103,
+0x210F,0x210F,0x2113,0x2113,0x2116,0x2116,0x2121,0x2121,
+0x2127,0x2127,0x212B,0x212B,0x2135,0x2135,0x2153,0x2155,
+0x2160,0x216A,0x216B,0x216B,0x2170,0x217B,0x2190,0x2191,
+0x2192,0x2192,0x2193,0x2193,0x2194,0x2194,0x2196,0x2196,
+0x2197,0x2198,0x2199,0x2199,0x21C4,0x21C4,0x21D2,0x21D2,
+0x21D4,0x21D4,0x21E6,0x21E7,0x21E8,0x21E8,0x21E9,0x21E9,
+0x2200,0x2200,0x2202,0x2202,0x2203,0x2203,0x2205,0x2205,
+0x2207,0x2207,0x2208,0x2208,0x2209,0x2209,0x220B,0x220B,
+0x2212,0x2212,0x2213,0x2213,0x221A,0x221A,0x221D,0x221D,
+0x221E,0x221E,0x221F,0x221F,0x2220,0x2220,0x2225,0x2226,
+0x2227,0x2228,0x2229,0x2229,0x222A,0x222A,0x222B,0x222C,
+0x222E,0x222E,0x2234,0x2234,0x2235,0x2235,0x223D,0x223D,
+0x2243,0x2243,0x2245,0x2245,0x2248,0x2248,0x2252,0x2252,
+0x2260,0x2260,0x2261,0x2261,0x2262,0x2262,0x2266,0x2267,
+0x226A,0x226B,0x2276,0x2277,0x2282,0x2283,0x2284,0x2285,
+0x2286,0x2287,0x228A,0x228B,0x2295,0x2297,0x22A5,0x22A5,
+0x22BF,0x22BF,0x22DA,0x22DB,0x2305,0x2306,0x2312,0x2312,
+0x2318,0x2318,0x23BE,0x23CC,0x23CE,0x23CE,0x2423,0x2423,
+0x2460,0x2473,0x24D0,0x24E9,0x24EB,0x24F4,0x24F5,0x24FE,
+0x2500,0x2500,0x2501,0x2501,0x2502,0x2502,0x2503,0x2503,
+0x250C,0x250C,0x250F,0x250F,0x2510,0x2510,0x2513,0x2513,
+0x2514,0x2514,0x2517,0x2517,0x2518,0x2518,0x251B,0x251B,
+0x251C,0x251C,0x251D,0x251D,0x2520,0x2520,0x2523,0x2523,
+0x2524,0x2524,0x2525,0x2525,0x2528,0x2528,0x252B,0x252B,
+0x252C,0x252C,0x252F,0x252F,0x2530,0x2530,0x2533,0x2533,
+0x2534,0x2534,0x2537,0x2537,0x2538,0x2538,0x253B,0x253B,
+0x253C,0x253C,0x253F,0x253F,0x2542,0x2542,0x254B,0x254B,
+0x25A0,0x25A0,0x25A1,0x25A1,0x25B1,0x25B1,0x25B2,0x25B2,
+0x25B3,0x25B3,0x25B6,0x25B6,0x25B7,0x25B7,0x25BC,0x25BC,
+0x25BD,0x25BD,0x25C0,0x25C0,0x25C1,0x25C1,0x25C6,0x25C6,
+0x25C7,0x25C7,0x25C9,0x25C9,0x25CB,0x25CB,0x25CE,0x25CE,
+0x25CF,0x25CF,0x25D0,0x25D3,0x25E6,0x25E6,0x25EF,0x25EF,
+0x2600,0x2603,0x2605,0x2605,0x2606,0x2606,0x260E,0x260E,
+0x2616,0x2617,0x261E,0x261E,0x2640,0x2640,0x2642,0x2642,
+0x2660,0x2660,0x2661,0x2661,0x2662,0x2662,0x2663,0x2663,
+0x2664,0x2664,0x2665,0x2665,0x2666,0x2666,0x2667,0x2667,
+0x2668,0x2668,0x2669,0x2669,0x266A,0x266A,0x266B,0x266C,
+0x266D,0x266D,0x266E,0x266E,0x266F,0x266F,0x2713,0x2713,
+0x2756,0x2756,0x2776,0x277F,0x2934,0x2935,0x29BF,0x29BF,
+0x29FA,0x29FB,0x3000,0x3002,0x3003,0x3003,0x3005,0x3007,
+0x3008,0x3011,0x3012,0x3012,0x3013,0x3013,0x3014,0x3015,
+0x3016,0x3017,0x3018,0x3019,0x301C,0x301C,0x301D,0x301D,
+0x301F,0x301F,0x3020,0x3020,0x3033,0x3035,0x303B,0x303C,
+0x303D,0x303D,0x3041,0x3096,0x309B,0x309C,0x309D,0x309E,
+0x309F,0x309F,0x30A0,0x30A0,0x30A1,0x30F6,0x30F7,0x30FA,
+0x30FB,0x30FB,0x30FC,0x30FC,0x30FD,0x30FE,0x30FF,0x30FF,
+0x31F0,0x31F9,0x31FA,0x31FF,0x3231,0x3232,0x3239,0x3239,
+0x3251,0x325F,0x32A4,0x32A8,0x32B1,0x32BF,0x32D0,0x32E3,
+0x32E5,0x32E5,0x32E9,0x32E9,0x32EC,0x32EC,0x32ED,0x32ED,
+0x32FA,0x32FA,0x3303,0x3303,0x330D,0x330D,0x3314,0x3314,
+0x3318,0x3318,0x3322,0x3322,0x3323,0x3323,0x3326,0x3326,
+0x3327,0x3327,0x332B,0x332B,0x3336,0x3336,0x333B,0x333B,
+0x3349,0x3349,0x334A,0x334A,0x334D,0x334D,0x3351,0x3351,
+0x3357,0x3357,0x337B,0x337B,0x337C,0x337C,0x337D,0x337D,
+0x337E,0x337E,0x338E,0x338F,0x339C,0x339E,0x33A1,0x33A1,
+0x33C4,0x33C4,0x33CB,0x33CB,0x33CD,0x33CD,0x3402,0x3402,
+0x3406,0x3406,0x342C,0x342C,0x342E,0x342E,0x3468,0x3468,
+0x346A,0x346A,0x3492,0x3492,0x34B5,0x34B5,0x34BC,0x34BC,
+0x34C1,0x34C1,0x34C7,0x34C7,0x34DB,0x34DB,0x351F,0x351F,
+0x355D,0x355E,0x3563,0x3563,0x356E,0x356E,0x35A6,0x35A6,
+0x35A8,0x35A8,0x35C5,0x35C5,0x35DA,0x35DA,0x35F4,0x35F4,
+0x3605,0x3605,0x364A,0x364A,0x3691,0x3691,0x3696,0x3696,
+0x3699,0x3699,0x36CF,0x36CF,0x3761,0x3761,0x3762,0x3762,
+0x376B,0x376B,0x376C,0x376C,0x3775,0x3775,0x378D,0x378D,
+0x37C1,0x37C1,0x37E2,0x37E2,0x37E8,0x37E8,0x37F4,0x37F4,
+0x37FD,0x37FD,0x3800,0x3800,0x382F,0x382F,0x3836,0x3836,
+0x3840,0x3840,0x385C,0x385C,0x3861,0x3861,0x38FA,0x38FA,
+0x3917,0x3917,0x391A,0x391A,0x396F,0x396F,0x3A6E,0x3A6E,
+0x3A73,0x3A73,0x3AD6,0x3AD6,0x3AD7,0x3AD7,0x3AEA,0x3AEA,
+0x3B0E,0x3B0E,0x3B1A,0x3B1A,0x3B1C,0x3B1C,0x3B22,0x3B22,
+0x3B6D,0x3B6D,0x3B77,0x3B77,0x3B87,0x3B88,0x3B8D,0x3B8D,
+0x3BA4,0x3BA4,0x3BB6,0x3BB6,0x3BC3,0x3BC3,0x3BCD,0x3BCD,
+0x3BF0,0x3BF0,0x3C0F,0x3C0F,0x3C26,0x3C26,0x3CC3,0x3CC3,
+0x3CD2,0x3CD2,0x3D11,0x3D11,0x3D1E,0x3D1E,0x3D64,0x3D64,
+0x3D9A,0x3D9A,0x3DC0,0x3DC0,0x3DD4,0x3DD4,0x3E05,0x3E05,
+0x3E3F,0x3E3F,0x3E60,0x3E60,0x3E66,0x3E66,0x3E68,0x3E68,
+0x3E83,0x3E83,0x3E94,0x3E94,0x3F57,0x3F57,0x3F72,0x3F72,
+0x3F75,0x3F75,0x3F77,0x3F77,0x3FAE,0x3FAE,0x3FC9,0x3FC9,
+0x3FD7,0x3FD7,0x4039,0x4039,0x4058,0x4058,0x4093,0x4093,
+0x4105,0x4105,0x4148,0x4148,0x414F,0x414F,0x4163,0x4163,
+0x41B4,0x41B4,0x41BF,0x41BF,0x41E6,0x41E6,0x41EE,0x41EE,
+0x41F3,0x41F3,0x4207,0x4207,0x420E,0x420E,0x4264,0x4264,
+0x42C6,0x42C6,0x42D6,0x42D6,0x42DD,0x42DD,0x4302,0x4302,
+0x432B,0x432B,0x4343,0x4343,0x43EE,0x43EE,0x43F0,0x43F0,
+0x4408,0x4408,0x4417,0x4417,0x441C,0x441C,0x4422,0x4422,
+0x4453,0x4453,0x445B,0x445B,0x4476,0x4476,0x447A,0x447A,
+0x4491,0x4491,0x44B3,0x44B3,0x44BE,0x44BE,0x44D4,0x44D4,
+0x4508,0x4508,0x450D,0x450D,0x4525,0x4525,0x4543,0x4543,
+0x459D,0x459D,0x45B8,0x45B8,0x45E5,0x45E5,0x45EA,0x45EA,
+0x460F,0x460F,0x4641,0x4641,0x4665,0x4665,0x46A1,0x46A1,
+0x46AF,0x46AF,0x470C,0x470C,0x4764,0x4764,0x47FD,0x47FD,
+0x4816,0x4816,0x4844,0x4844,0x484E,0x484E,0x48B5,0x48B5,
+0x49B0,0x49B0,0x49E7,0x49E7,0x49FA,0x49FA,0x4A04,0x4A04,
+0x4A29,0x4A29,0x4ABC,0x4ABC,0x4B3B,0x4B3B,0x4BC2,0x4BC2,
+0x4BCA,0x4BCA,0x4BD2,0x4BD2,0x4BE8,0x4BE8,0x4C17,0x4C17,
+0x4C20,0x4C20,0x4CC4,0x4CC4,0x4CD1,0x4CD1,0x4D07,0x4D07,
+0x4D77,0x4D77,};
+
+static const unsigned short ucs_c1_jisx0213_ofst[] = {
+0x2872,0x2B46,0x2B50,0x213E,0x237C,0x213D,0x2142,0x2146,
+0x2148,0x2277,0x2340,0x2145,0x2144,0x2273,0x216C,0x2228,
+0x286B,0x007E,0x2B58,0x2C7E,0x286C,0x2C7D,0x2921,0x216E,
+0x235D,0x235F,0x2D62,0x2D64,0x2360,0x2272,0x235C,0x2778,
+0x2D35,0x2D57,0x2C35,0x222B,0x222A,0x222D,0x2271,0x2327,
+0x2325,0x2328,0x2329,0x224D,0x224E,0x232B,0x232A,0x232D,
+0x224F,0x225F,0x2250,0x2247,0x2260,0x223A,0x2246,0x223B,
+0x215D,0x235B,0x2265,0x2267,0x2167,0x2D78,0x225C,0x2254,
+0x224A,0x2241,0x2240,0x2269,0x2D73,0x2168,0x2268,0x2266,
+0x226C,0x226D,0x226E,0x2262,0x2162,0x2261,0x226B,0x2165,
+0x2263,0x226F,0x223E,0x2242,0x223C,0x2244,0x2251,0x225D,
+0x2D79,0x2776,0x2248,0x225E,0x277C,0x2742,0x277E,0x277D,
+0x2D21,0x2C41,0x2C2B,0x265A,0x2821,0x282C,0x2822,0x282D,
+0x2823,0x282E,0x2824,0x282F,0x2826,0x2831,0x2825,0x2830,
+0x2827,0x283C,0x2837,0x2832,0x2829,0x283E,0x2839,0x2834,
+0x2828,0x2838,0x283D,0x2833,0x282A,0x283A,0x283F,0x2835,
+0x282B,0x283B,0x2840,0x2836,0x2223,0x2222,0x266D,0x2225,
+0x2224,0x2322,0x2321,0x2227,0x2226,0x2324,0x2323,0x2221,
+0x217E,0x233B,0x217B,0x217D,0x217C,0x2867,0x233F,0x227E,
+0x2668,0x217A,0x2179,0x2667,0x2664,0x2D7E,0x216A,0x2169,
+0x263A,0x263D,0x263B,0x2640,0x2639,0x263E,0x263C,0x263F,
+0x266C,0x227D,0x2276,0x227B,0x2275,0x227A,0x2274,0x277B,
+0x2D7D,0x2C21,0x232E,0x233A,0x237D,0x2121,0x2137,0x2139,
+0x2152,0x2229,0x222E,0x214C,0x225A,0x2258,0x2141,0x2D60,
+0x2D61,0x2666,0x2233,0x2236,0x233C,0x2421,0x212B,0x2135,
+0x2239,0x237B,0x2521,0x2772,0x2126,0x213C,0x2133,0x2238,
+0x266E,0x2679,0x2D6A,0x2D6C,0x2841,0x2D65,0x2850,0x2C5B,
+0x2C71,0x2C70,0x2C73,0x2C72,0x2C6F,0x2D46,0x2D4A,0x2D41,
+0x2D44,0x2D42,0x2D4C,0x2D4B,0x2D45,0x2D4D,0x2D47,0x2D4F,
+0x2D40,0x2D4E,0x2D43,0x2D48,0x2D49,0x2D5F,0x2D6F,0x2D6E,
+0x2D6D,0x2D53,0x2D50,0x2D56,0x2D55,0x235E,0x2D63,0x2E23,
+0x7F2D,0x7F32,0x7F33,0x7F5E,0x7F56,0x7F7E,0x2E53,0x812B,
+0x8E68,0x812F,0x2E5B,0x8148,0x815D,0x8161,0x8167,0x8223,
+0x8226,0x822F,0x8238,0x8242,0x824A,0x8279,0x833F,0x8343,
+0x8341,0x8357,0x8023,0x8025,0x8029,0x8028,0x802C,0x4F5F,
+0x803E,0x4F6F,0x8056,0x8059,0x805C,0x805E,0x806F,0x8071,
+0x8074,0x8079,0x807B,0x843B,0x8446,0x844A,0x8460,0x855B,
+0x855F,0x8571,0x8636,0x857C,0x862E,0x8632,0x8634,0x7549,
+0x866D,0x8665,0x8728,0x872C,0x8734,0x757E,0x7621,0x8748,
+0x875D,0x763A,0x8777,0x883B,0x8842,0x8871,0x887E,0x8940,
+0x8954,0x8970,0x8977,0x8A28,0x7766,0x8A3F,0x8A41,0x8A42,
+0x8A49,0x8A50,0x8B34,0x784D,0x8B46,0x8B48,0x8B5C,0x8B67,
+0x8B6C,0x8C22,0x8C2D,0x8C39,0x8C64,0x8C74,0x8C77,0x8C7D,
+0x8D33,0x8D37,0x8D47,0x8D4B,0x8D48,0x8D53,0x8D57,0x796D,
+0x8E2B,0x8E36,0x8E3B,0x8E4E,0x8E5D,0x8E61,0x8F3E,0x8F42,
+0x8F48,0x8F4A,0x8F4C,0x8F4F,0x7A59,0x7A5A,0x8F6C,0x8F6E,
+0x8F77,0x9035,0x9032,0x9034,0x9059,0x9054,0x906D,0x906E,
+0x7B51,0x914F,0x916C,0x7B60,0x9224,0x923A,0x9243,0x924E,
+0x9253,0x926B,0x9329,0x933F,0x9349,0x7C4B,0x935C,0x9427,
+0x7D58,0x956A,0x9570,0x9575,0x9578,0x9637,0x9655,0x9726,
+0x9728,0x972A,0x9731,0x7E3E,0x973F,0x982A,0x982D,0x984B,
+0x9860,};
+
+static const int ucs_c1_jisx0213_tbl_len = sizeof(ucs_c1_jisx0213_ofst)/sizeof(unsigned short);
+
+static const int ucs_c1_jisx0213_min = 0x1E00;
+static const int ucs_c1_jisx0213_max = 0x4DFF;
+
+/* CJK Unified ideographs Extension B: U+2XXXX */
+static const unsigned short jisx0213_jis_u5_tbl[] = {
+0x000B,0x123D,0x131B,0x146E,0x18BD,0x0B9F,0x16B4,0x1E34,
+0x31C4,0x35C4,0x373F,0x3763,0x3CFE,0x47F1,0x548E,0x550E,
+0x5771,0x59C4,0x5DA1,0x6AFF,0x6E40,0x70F4,0x7684,0x8277,
+0x83CD,0xA190,0x0089,0x00A2,0x00A4,0x01A2,0x0213,0x032B,
+0x0381,0x0371,0x1C56,0x1D2D,0x1D45,0x1D78,0x1D62,0x1DA1,
+0x1D9C,0x1D92,0x1DB7,0x1DE0,0x1E33,0x1F1E,0x1F76,0x1FFA,
+0x03F9,0x044A,0x0509,0x05D6,0x0628,0x074F,0x0807,0x083A,
+0x08B9,0x097C,0x099D,0x0AD3,0x0B1D,0x0D45,0x0DE1,0x0E95,
+0x0E6D,0x0E64,0x0F5F,0x1201,0x1255,0x127B,0x1274,0x12E4,
+0x12D7,0x12FD,0x1336,0x1344,0x13C4,0x146D,0x15D7,0x6C29,
+0x1647,0x1706,0x1742,0x19C3,0x217B,0x231E,0x23AD,0x26F3,
+0x285B,0x28AB,0x298F,0x2AB8,0x2B4F,0x2B50,0x2B46,0x2C1D,
+0x2BA6,0x2C24,0x2DE1,0x31C3,0x31F5,0x31B6,0x3372,0x33D3,
+0x33D2,0x33D0,0x33E4,0x33D5,0x33DA,0x33DF,0x344A,0x3451,
+0x344B,0x3465,0x34E4,0x355A,0x3594,0x3639,0x3647,0x3638,
+0x363A,0x371C,0x370C,0x3764,0x37FF,0x37E7,0x3824,0x383D,
+0x3A98,0x3C7F,0x3D00,0x3D40,0x3DFA,0x3DF9,0x3DD3,0x3F7E,
+0x4096,0x4103,0x41C6,0x41FE,0x43BC,0x4629,0x46A5,0x4896,
+0x4A4D,0x4B56,0x4B6F,0x4C16,0x4D14,0x4E0E,0x4E37,0x4E6A,
+0x4E8B,0x504A,0x5055,0x5122,0x51A9,0x51E5,0x51CD,0x521E,
+0x524C,0x542E,0x54D9,0x55A7,0x57A9,0x57B4,0x59D4,0x5AE4,
+0x5AE3,0x5AF1,0x5BB2,0x5C4B,0x5C64,0x5E2E,0x5E56,0x5E65,
+0x5E62,0x5ED8,0x5EC2,0x5EE8,0x5F23,0x5F5C,0x5FE0,0x5FD4,
+0x600C,0x5FFB,0x6017,0x6060,0x60ED,0x6270,0x6286,0x634C,
+0x3D0E,0x6402,0x667E,0x66B0,0x671D,0x68DD,0x68EA,0x6951,
+0x696F,0x69DD,0x6A1E,0x6A58,0x6A8C,0x6AB7,0x6C73,0x6CDD,
+0x6E65,0x6F94,0x6FF8,0x6FF6,0x6FF7,0x710D,0x7139,0x73DB,
+0x73DA,0x73FE,0x7410,0x7449,0x7615,0x7614,0x7631,0x7693,
+0x770E,0x7723,0x7752,0x7985,0x7A84,0x7BB3,0x7BBE,0x7BC7,
+0x7CB8,0x7DA0,0x7E10,0x7FB7,0x808A,0x80BB,0x8282,0x82F3,
+0x840C,0x8455,0x856B,0x85C8,0x85C9,0x86D7,0x86FA,0x8949,
+0x8946,0x896B,0x8987,0x8988,0x89BA,0x89BB,0x8A1E,0x8A29,
+0x8A71,0x8A43,0x8A99,0x8ACD,0x8AE4,0x8ADD,0x8BC1,0x8BEF,
+0x8D10,0x8D71,0x8DFB,0x8E1F,0x8E36,0x8E89,0x8EEB,0x8F32,
+0x8FF8,0x92A0,0x92B1,0x9490,0x95CF,0x967F,0x96F0,0x9719,
+0x9750,0x98C6,0x9A72,0x9DDB,0x9E3D,0x9E15,0x9E8A,0x9E49,
+0x9EC4,0x9EE9,0x9EDB,0x9FCE,0xA02F,0xA01A,0xA0F9,0xA082,
+0x2218,0xA38C,0xA437,0xA5F1,0xA602,0xA61A,0xA6B2,};
+
+static const unsigned short jisx0213_jis_u5_key[] = {
+0x2E22,0x2F42,0x2F4C,0x2F60,0x2F7B,0x4F54,0x4F63,0x4F6E,
+0x753A,0x7572,0x7629,0x7632,0x7660,0x776C,0x787E,0x7929,
+0x7947,0x7954,0x796E,0x7A5D,0x7B33,0x7B49,0x7B6C,0x7C49,
+0x7C51,0x7E66,0x7F21,0x7F2B,0x7F2E,0x7F36,0x7F46,0x7F70,
+0x7F77,0x7F79,0x8030,0x8037,0x8038,0x803A,0x803B,0x803F,
+0x8040,0x8045,0x8048,0x804A,0x804B,0x805B,0x8066,0x806C,
+0x8122,0x8125,0x8127,0x8131,0x8132,0x8138,0x813F,0x8141,
+0x814A,0x8152,0x8153,0x8159,0x815C,0x8177,0x822A,0x8231,
+0x8232,0x823A,0x823D,0x8259,0x825C,0x825E,0x8263,0x826A,
+0x826B,0x8272,0x8274,0x8275,0x8325,0x8332,0x833E,0x8344,
+0x8347,0x8355,0x8356,0x837E,0x8422,0x842B,0x8430,0x8450,
+0x8465,0x846D,0x8472,0x8524,0x8529,0x852A,0x8532,0x8534,
+0x8535,0x8539,0x8556,0x857D,0x8623,0x8624,0x863A,0x863C,
+0x863D,0x8642,0x8643,0x8644,0x8647,0x8649,0x8655,0x8656,
+0x8657,0x865B,0x8677,0x8678,0x872A,0x873F,0x8740,0x8742,
+0x8743,0x874E,0x8759,0x8761,0x8769,0x876A,0x8770,0x8775,
+0x8823,0x8834,0x8849,0x885C,0x885E,0x885F,0x8860,0x8932,
+0x8947,0x894D,0x8961,0x8964,0x8A22,0x8A33,0x8A39,0x8A53,
+0x8A7B,0x8B2E,0x8B30,0x8B35,0x8B44,0x8B5D,0x8B61,0x8B66,
+0x8B69,0x8B75,0x8B77,0x8B7A,0x8C21,0x8C23,0x8C24,0x8C28,
+0x8C2C,0x8C3D,0x8C48,0x8C5B,0x8C75,0x8C76,0x8D32,0x8D3D,
+0x8D3E,0x8D40,0x8D52,0x8D5D,0x8D5E,0x8D73,0x8D74,0x8D75,
+0x8D77,0x8D7B,0x8D7D,0x8E22,0x8E24,0x8E27,0x8E2E,0x8E2F,
+0x8E34,0x8E35,0x8E3D,0x8E42,0x8E4F,0x8E69,0x8E6B,0x8E72,
+0x8E75,0x8E79,0x8F35,0x8F3A,0x8F46,0x8F56,0x8F58,0x8F5A,
+0x8F5D,0x8F5F,0x8F63,0x8F6A,0x8F70,0x8F73,0x9044,0x904E,
+0x905D,0x9075,0x907E,0x9121,0x9122,0x9133,0x9136,0x9164,
+0x9165,0x916B,0x916E,0x9173,0x9229,0x922A,0x922C,0x9234,
+0x923C,0x923E,0x9242,0x9256,0x9263,0x9277,0x9279,0x927A,
+0x9325,0x932F,0x9332,0x9339,0x9342,0x9348,0x9359,0x935E,
+0x9366,0x936B,0x937A,0x937E,0x9421,0x942C,0x942F,0x944F,
+0x9450,0x9457,0x9465,0x9466,0x9471,0x9472,0x947E,0x9521,
+0x952C,0x952D,0x9536,0x9537,0x953D,0x953E,0x954E,0x954F,
+0x9557,0x955A,0x955C,0x955D,0x9561,0x9565,0x9567,0x9569,
+0x9571,0x9622,0x9623,0x9638,0x9642,0x964C,0x9656,0x9659,
+0x965D,0x9676,0x972C,0x974B,0x974C,0x9759,0x975B,0x975D,
+0x9767,0x976D,0x9770,0x9825,0x9829,0x982B,0x9832,0x9835,
+0x9853,0x9858,0x985A,0x986E,0x9870,0x9872,0x9876,};
+
+static const unsigned short jisx0213_u5_jis_tbl[] = {
+0x2E22,0x7F21,0x7F2B,0x7F2E,0x7F36,0x7F46,0x7F70,0x7F79,
+0x7F77,0x8122,0x8125,0x8127,0x8131,0x8132,0x8138,0x813F,
+0x8141,0x814A,0x8152,0x8153,0x8159,0x815C,0x4F54,0x8177,
+0x822A,0x823A,0x8232,0x8231,0x823D,0x8259,0x2F42,0x825C,
+0x8263,0x825E,0x826B,0x826A,0x8272,0x2F4C,0x8274,0x8275,
+0x8325,0x8332,0x2F60,0x833E,0x8347,0x4F63,0x8355,0x8356,
+0x2F7B,0x837E,0x8030,0x8037,0x8038,0x803B,0x803A,0x8045,
+0x8040,0x803F,0x8048,0x804A,0x804B,0x4F6E,0x805B,0x8066,
+0x806C,0x8422,0x9853,0x842B,0x8430,0x8450,0x8465,0x846D,
+0x8472,0x8524,0x8532,0x8529,0x852A,0x8535,0x8534,0x8539,
+0x8556,0x8624,0x857D,0x753A,0x8623,0x863A,0x8642,0x863D,
+0x863C,0x8644,0x8647,0x8649,0x8643,0x8655,0x8657,0x8656,
+0x865B,0x8677,0x8678,0x872A,0x7572,0x8742,0x873F,0x8743,
+0x8740,0x8759,0x874E,0x7629,0x7632,0x8761,0x876A,0x8769,
+0x8770,0x8775,0x8823,0x8834,0x7660,0x8849,0x8E75,0x885C,
+0x8860,0x885F,0x885E,0x8932,0x8947,0x894D,0x8961,0x8964,
+0x8A22,0x8A33,0x8A39,0x776C,0x8A53,0x8A7B,0x8B2E,0x8B30,
+0x8B35,0x8B44,0x8B5D,0x8B61,0x8B66,0x8B69,0x8B75,0x8B77,
+0x8B7A,0x8C21,0x8C24,0x8C23,0x8C28,0x8C2C,0x8C3D,0x787E,
+0x8C48,0x7929,0x8C5B,0x7947,0x8C75,0x8C76,0x7954,0x8D32,
+0x8D3E,0x8D3D,0x8D40,0x8D52,0x8D5D,0x8D5E,0x796E,0x8D73,
+0x8D74,0x8D77,0x8D75,0x8D7D,0x8D7B,0x8E22,0x8E24,0x8E27,
+0x8E2F,0x8E2E,0x8E35,0x8E34,0x8E3D,0x8E42,0x8E4F,0x8E69,
+0x8E6B,0x8E72,0x8E79,0x8F35,0x8F3A,0x8F46,0x8F56,0x8F58,
+0x8F5A,0x8F5D,0x8F5F,0x8F63,0x8F6A,0x8F70,0x8F73,0x7A5D,
+0x8344,0x9044,0x904E,0x7B33,0x905D,0x9075,0x9121,0x9122,
+0x907E,0x7B49,0x9133,0x9136,0x9165,0x9164,0x916B,0x916E,
+0x9173,0x922A,0x9229,0x922C,0x7B6C,0x9234,0x923C,0x923E,
+0x9242,0x9256,0x9263,0x9277,0x9279,0x927A,0x9325,0x932F,
+0x9332,0x9339,0x9342,0x9348,0x7C49,0x9359,0x935E,0x7C51,
+0x9366,0x936B,0x937A,0x937E,0x9421,0x942C,0x942F,0x9450,
+0x944F,0x9457,0x9465,0x9466,0x9471,0x9472,0x947E,0x9521,
+0x952D,0x952C,0x9536,0x9537,0x953E,0x953D,0x954E,0x954F,
+0x9557,0x955A,0x955C,0x955D,0x9561,0x9565,0x9567,0x9569,
+0x9571,0x9622,0x9623,0x9638,0x9642,0x964C,0x9656,0x9659,
+0x965D,0x9676,0x972C,0x974B,0x9759,0x974C,0x975D,0x975B,
+0x9767,0x9770,0x976D,0x9825,0x982B,0x9829,0x9835,0x9832,
+0x7E66,0x9858,0x985A,0x986E,0x9870,0x9872,0x9876,};
+
+static const unsigned short jisx0213_u5_jis_key[] = {
+0x000B,0x0089,0x00A2,0x00A4,0x01A2,0x0213,0x032B,0x0371,
+0x0381,0x03F9,0x044A,0x0509,0x05D6,0x0628,0x074F,0x0807,
+0x083A,0x08B9,0x097C,0x099D,0x0AD3,0x0B1D,0x0B9F,0x0D45,
+0x0DE1,0x0E64,0x0E6D,0x0E95,0x0F5F,0x1201,0x123D,0x1255,
+0x1274,0x127B,0x12D7,0x12E4,0x12FD,0x131B,0x1336,0x1344,
+0x13C4,0x146D,0x146E,0x15D7,0x1647,0x16B4,0x1706,0x1742,
+0x18BD,0x19C3,0x1C56,0x1D2D,0x1D45,0x1D62,0x1D78,0x1D92,
+0x1D9C,0x1DA1,0x1DB7,0x1DE0,0x1E33,0x1E34,0x1F1E,0x1F76,
+0x1FFA,0x217B,0x2218,0x231E,0x23AD,0x26F3,0x285B,0x28AB,
+0x298F,0x2AB8,0x2B46,0x2B4F,0x2B50,0x2BA6,0x2C1D,0x2C24,
+0x2DE1,0x31B6,0x31C3,0x31C4,0x31F5,0x3372,0x33D0,0x33D2,
+0x33D3,0x33D5,0x33DA,0x33DF,0x33E4,0x344A,0x344B,0x3451,
+0x3465,0x34E4,0x355A,0x3594,0x35C4,0x3638,0x3639,0x363A,
+0x3647,0x370C,0x371C,0x373F,0x3763,0x3764,0x37E7,0x37FF,
+0x3824,0x383D,0x3A98,0x3C7F,0x3CFE,0x3D00,0x3D0E,0x3D40,
+0x3DD3,0x3DF9,0x3DFA,0x3F7E,0x4096,0x4103,0x41C6,0x41FE,
+0x43BC,0x4629,0x46A5,0x47F1,0x4896,0x4A4D,0x4B56,0x4B6F,
+0x4C16,0x4D14,0x4E0E,0x4E37,0x4E6A,0x4E8B,0x504A,0x5055,
+0x5122,0x51A9,0x51CD,0x51E5,0x521E,0x524C,0x542E,0x548E,
+0x54D9,0x550E,0x55A7,0x5771,0x57A9,0x57B4,0x59C4,0x59D4,
+0x5AE3,0x5AE4,0x5AF1,0x5BB2,0x5C4B,0x5C64,0x5DA1,0x5E2E,
+0x5E56,0x5E62,0x5E65,0x5EC2,0x5ED8,0x5EE8,0x5F23,0x5F5C,
+0x5FD4,0x5FE0,0x5FFB,0x600C,0x6017,0x6060,0x60ED,0x6270,
+0x6286,0x634C,0x6402,0x667E,0x66B0,0x671D,0x68DD,0x68EA,
+0x6951,0x696F,0x69DD,0x6A1E,0x6A58,0x6A8C,0x6AB7,0x6AFF,
+0x6C29,0x6C73,0x6CDD,0x6E40,0x6E65,0x6F94,0x6FF6,0x6FF7,
+0x6FF8,0x70F4,0x710D,0x7139,0x73DA,0x73DB,0x73FE,0x7410,
+0x7449,0x7614,0x7615,0x7631,0x7684,0x7693,0x770E,0x7723,
+0x7752,0x7985,0x7A84,0x7BB3,0x7BBE,0x7BC7,0x7CB8,0x7DA0,
+0x7E10,0x7FB7,0x808A,0x80BB,0x8277,0x8282,0x82F3,0x83CD,
+0x840C,0x8455,0x856B,0x85C8,0x85C9,0x86D7,0x86FA,0x8946,
+0x8949,0x896B,0x8987,0x8988,0x89BA,0x89BB,0x8A1E,0x8A29,
+0x8A43,0x8A71,0x8A99,0x8ACD,0x8ADD,0x8AE4,0x8BC1,0x8BEF,
+0x8D10,0x8D71,0x8DFB,0x8E1F,0x8E36,0x8E89,0x8EEB,0x8F32,
+0x8FF8,0x92A0,0x92B1,0x9490,0x95CF,0x967F,0x96F0,0x9719,
+0x9750,0x98C6,0x9A72,0x9DDB,0x9E15,0x9E3D,0x9E49,0x9E8A,
+0x9EC4,0x9EDB,0x9EE9,0x9FCE,0xA01A,0xA02F,0xA082,0xA0F9,
+0xA190,0xA38C,0xA437,0xA5F1,0xA602,0xA61A,0xA6B2,};
+
+static const int jisx0213_u5_tbl_min = 0x2000B;
+static const int jisx0213_u5_tbl_max = 0x2A6B2;
+static const int jisx0213_u5_tbl_len = sizeof(jisx0213_u5_jis_key)/sizeof(unsigned short);
+
+/* combined chars in JIS X 0213 */
+static const unsigned short jisx0213_u2_key[] = {
+ 0x2477,0x2478,0x2479,0x247A,0x247B,0x2577,0x2578,0x2579,
+ 0x257A,0x257B,0x257C,0x257D,0x257E,0x2678,0x2B44,0x2B48,
+ 0x2B49,0x2B4A,0x2B4B,0x2B4C,0x2B4D,0x2B4E,0x2B4F,0x2B65,
+ 0x2B66};
+
+/* combined pairs in Unicode */
+static const unsigned short jisx0213_u2_tbl[] = {
+ 0x304B,0x309A,0x304D,0x309A,0x304F,0x309A,0x3051,0x309A,
+ 0x3053,0x309A,0x30AB,0x309A,0x30AD,0x309A,0x30AF,0x309A,
+ 0x30B1,0x309A,0x30B3,0x309A,0x30BB,0x309A,0x30C4,0x309A,
+ 0x30C8,0x309A,0x31F7,0x309A,0x00E6,0x0300,0x0254,0x0300,
+ 0x0254,0x0301,0x028C,0x0300,0x028C,0x0301,0x0259,0x0300,
+ 0x0259,0x0301,0x025A,0x0300,0x025A,0x0301,0x02E9,0x02E5,
+ 0x02E5,0x02E9};
+
+/* fallback chars for combined chars in Unicode */
+static const unsigned short jisx0213_u2_fb_tbl[] = {
+ 0x242B,0x242D,0x242F,0x2431,0x2433,0x252B,0x252D,0x252F,
+ 0x2531,0x2533,0x253B,0x2544,0x2548,0x2675,0x295C,0x2B38,
+ 0x2B38,0x2B37,0x2B37,0x2B30,0x2B30,0x2B43,0x2B43,0x2B64,
+ 0x2B60};
+
+static const int jisx0213_u2_tbl_len = sizeof(jisx0213_u2_key)/sizeof(unsigned short);
+
+
+static const unsigned short jisx0213_p2_ofst[] = {
+ 1, 8, 3, 4, 5, 12, 13, 14, 15, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94};
+
+static const int jisx0213_p2_ofst_len =
+ sizeof(jisx0213_p2_ofst)/sizeof(unsigned short);
+
+static const int uni2jis_tbl_range[][2] = {
+ {0x0000, 0x045f},
+ {0x3000, 0x30ff},
+ {0x4e00, 0x9fff},
+ {0xff00, 0xffe5},
+ {0xfa0f, 0xfa6a},
+};
+
+static const unsigned short *uni2jis_tbl[] = {
+ ucs_a1_jisx0213_table,
+ ucs_hk_jisx0213_table,
+ ucs_i_jisx0213_table,
+ ucs_r_jisx0213_table,
+ ucs_r2_jisx0213_table,
+};
+
+static const int uni2jis_tbl_len = sizeof(uni2jis_tbl_range)/(sizeof(int)*2);
+
+#endif /* UNICODE_TABLE_JIS2004_H */
+
diff --git a/ext/mbstring/libmbfl/filters/unicode_table_uhc.h b/ext/mbstring/libmbfl/filters/unicode_table_uhc.h
index 802e120e08..6b98c65b6f 100644
--- a/ext/mbstring/libmbfl/filters/unicode_table_uhc.h
+++ b/ext/mbstring/libmbfl/filters/unicode_table_uhc.h
@@ -28,8 +28,9 @@
/*
* Unicode table
*/
+#ifdef UNICODE_TABLE_UHC_DEF
-static const unsigned short uhc1_ucs_table[] = {
+const unsigned short uhc1_ucs_table[] = {
0xac02,0xac03,0xac05,0xac06,0xac0b,0xac0c,0xac0d,0xac0e,
0xac0f,0xac18,0xac1e,0xac1f,0xac21,0xac22,0xac23,0xac25,
0xac26,0xac27,0xac28,0xac29,0xac2a,0xac2b,0xac2e,0xac32,
@@ -792,9 +793,9 @@ static const unsigned short uhc1_ucs_table[] = {
0xc89a,0xc89b,0xc89c,0xc89e,0xc8a0,0xc8a2,0xc8a3,0xc8a4
};
-static const int uhc1_ucs_table_size = (sizeof(uhc1_ucs_table)/sizeof(unsigned short));
+const int uhc1_ucs_table_size = (sizeof(uhc1_ucs_table)/sizeof(unsigned short));
-static const unsigned short uhc2_ucs_table[] = {
+const unsigned short uhc2_ucs_table[] = {
0xc8a5,0xc8a6,0xc8a7,0xc8a9,0xc8aa,0xc8ab,0xc8ac,0xc8ad,
0xc8ae,0xc8af,0xc8b0,0xc8b1,0xc8b2,0xc8b3,0xc8b4,0xc8b5,
0xc8b6,0xc8b7,0xc8b8,0xc8b9,0xc8ba,0xc8bb,0xc8be,0xc8bf,
@@ -1699,9 +1700,9 @@ static const unsigned short uhc2_ucs_table[] = {
0xd3d0,0xd3d8,0xd3e1,0xd3e3,0xd3ec,0xd3ed,0xd3f0,0xd3f4,
0xd3fc,0xd3fd,0xd3ff,0xd401};
-static const int uhc2_ucs_table_size = (sizeof(uhc2_ucs_table)/sizeof(unsigned short));
+const int uhc2_ucs_table_size = (sizeof(uhc2_ucs_table)/sizeof(unsigned short));
-static const unsigned short uhc3_ucs_table[] = {
+const unsigned short uhc3_ucs_table[] = {
0xd408,0xd41d,0xd440,0xd444,0xd45c,0xd460,0xd464,0xd46d,
0xd46f,0xd478,0xd479,0xd47c,0xd47f,0xd480,0xd482,0xd488,
0xd489,0xd48b,0xd48d,0xd494,0xd4a9,0xd4cc,0xd4d0,0xd4d4,
@@ -2350,10 +2351,10 @@ static const unsigned short uhc3_ucs_table[] = {
0x665e,0x66e6,0x7199,0x71b9,0x71ba,0x72a7,0x79a7,0x7a00,
0x7fb2,0x8a70};
-static const int uhc3_ucs_table_size = (sizeof(uhc3_ucs_table)/sizeof(unsigned short));
+const int uhc3_ucs_table_size = (sizeof(uhc3_ucs_table)/sizeof(unsigned short));
/* UCS -> UHC */
-static const unsigned short ucs_a1_uhc_table[] = {
+const unsigned short ucs_a1_uhc_table[] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
@@ -2498,10 +2499,10 @@ static const unsigned short ucs_a1_uhc_table[] = {
0xacea,0xaceb,0xacec,0xaced,0xacee,0xacef,0xacf0,0xacf1,
0x0000,0xacd7};
-static const int ucs_a1_uhc_table_min = 0x0000;
-static const int ucs_a1_uhc_table_max = 0x0000 + (sizeof(ucs_a1_uhc_table)/sizeof(unsigned short));
+const int ucs_a1_uhc_table_min = 0x0000;
+const int ucs_a1_uhc_table_max = 0x0000 + (sizeof(ucs_a1_uhc_table)/sizeof(unsigned short));
-static const unsigned short ucs_a2_uhc_table[] = {
+const unsigned short ucs_a2_uhc_table[] = {
/* 0x2000 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -2714,10 +2715,10 @@ static const unsigned short ucs_a2_uhc_table[] = {
0xa2bc,0xa2bd,0x0000,0xa2c0,0xa2bb,0xa2be,0x0000,0xa2bf,
0xa2cd,0xa2db,0xa2dc,0x0000,0xa2dd,0xa2da};
-static const int ucs_a2_uhc_table_min = 0x2000;
-static const int ucs_a2_uhc_table_max = 0x2000 + (sizeof(ucs_a2_uhc_table)/sizeof(unsigned short));
+const int ucs_a2_uhc_table_min = 0x2000;
+const int ucs_a2_uhc_table_max = 0x2000 + (sizeof(ucs_a2_uhc_table)/sizeof(unsigned short));
-static const unsigned short ucs_a3_uhc_table[] = {
+const unsigned short ucs_a3_uhc_table[] = {
/* 0x2f00 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -2878,10 +2879,10 @@ static const unsigned short ucs_a3_uhc_table[] = {
0xa7ea,0x0000,0x0000,0xa7eb,0x0000,0x0000,0xa7df,0x0000,
0xa2e4,0x0000,0x0000,0xa7e4,0xa7ee,0xa7e9};
-static const int ucs_a3_uhc_table_min = 0x2f00;
-static const int ucs_a3_uhc_table_max = 0x2f00 + (sizeof(ucs_a3_uhc_table)/sizeof(unsigned short));
+const int ucs_a3_uhc_table_min = 0x2f00;
+const int ucs_a3_uhc_table_max = 0x2f00 + (sizeof(ucs_a3_uhc_table)/sizeof(unsigned short));
-static const unsigned short ucs_i_uhc_table[] = {
+const unsigned short ucs_i_uhc_table[] = {
/* 0x4d00 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -5591,10 +5592,10 @@ static const unsigned short ucs_i_uhc_table[] = {
0xdbc2,0x0000,0x0000,0x0000,0x0000,0xcafe,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0xcfcf};
-static const int ucs_i_uhc_table_min = 0x4d00;
-static const int ucs_i_uhc_table_max = 0x4d00 + (sizeof(ucs_i_uhc_table)/sizeof(unsigned short));
+const int ucs_i_uhc_table_min = 0x4d00;
+const int ucs_i_uhc_table_max = 0x4d00 + (sizeof(ucs_i_uhc_table)/sizeof(unsigned short));
-static const unsigned short ucs_s_uhc_table[] = {
+const unsigned short ucs_s_uhc_table[] = {
/* 0xab00 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -7070,10 +7071,10 @@ static const unsigned short ucs_s_uhc_table[] = {
0xc64f,0xc650,0xc651,0xc652};
-static const int ucs_s_uhc_table_min = 0xab00;
-static const int ucs_s_uhc_table_max = 0xab00 + (sizeof(ucs_s_uhc_table)/sizeof(unsigned short));
+const int ucs_s_uhc_table_min = 0xab00;
+const int ucs_s_uhc_table_max = 0xab00 + (sizeof(ucs_s_uhc_table)/sizeof(unsigned short));
-static const unsigned short ucs_r1_uhc_table[] = {
+const unsigned short ucs_r1_uhc_table[] = {
/* 0xf800 */
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -7142,10 +7143,10 @@ static const unsigned short ucs_r1_uhc_table[] = {
0xf4ee,0xf6f4,0xf6f6,0xf7b8,0xf7c8,0xf7d3,0xf8db,0xf8f0,
0xfaa1,0xfaa2,0xfae6,0xfca9};
-static const int ucs_r1_uhc_table_min = 0xf800;
-static const int ucs_r1_uhc_table_max = 0xf800 + (sizeof(ucs_r1_uhc_table)/sizeof(unsigned short));
+const int ucs_r1_uhc_table_min = 0xf800;
+const int ucs_r1_uhc_table_max = 0xf800 + (sizeof(ucs_r1_uhc_table)/sizeof(unsigned short));
-static const unsigned short ucs_r2_uhc_table[] = {
+const unsigned short ucs_r2_uhc_table[] = {
/* 0xff00 */
0x0000,0xa3a1,0xa3a2,0xa3a3,0xa3a4,0xa3a5,0xa3a6,0xa3a7,
0xa3a8,0xa3a9,0xa3aa,0xa3ab,0xa3ac,0xa3ad,0xa3ae,0xa3af,
@@ -7177,9 +7178,44 @@ static const unsigned short ucs_r2_uhc_table[] = {
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0xa1cb,0xa1cc,0xa1fe,0xa3fe,0x0000,0xa1cd,0xa3dc};
-static const int ucs_r2_uhc_table_min = 0xff00;
-static const int ucs_r2_uhc_table_max = 0xff00 + (sizeof (ucs_r2_uhc_table) / sizeof (unsigned short));
+const int ucs_r2_uhc_table_min = 0xff00;
+const int ucs_r2_uhc_table_max = 0xff00 + (sizeof (ucs_r2_uhc_table) / sizeof (unsigned short));
+#else
+
+extern const unsigned short uhc1_ucs_table[];
+extern const unsigned short uhc2_ucs_table[];
+extern const unsigned short uhc3_ucs_table[];
+extern const unsigned short ucs_a1_uhc_table[];
+extern const unsigned short ucs_a2_uhc_table[];
+extern const unsigned short ucs_a3_uhc_table[];
+extern const unsigned short ucs_i_uhc_table[];
+extern const unsigned short ucs_s_uhc_table[];
+extern const unsigned short ucs_r1_uhc_table[];
+extern const unsigned short ucs_r2_uhc_table[];
+
+extern const int uhc1_ucs_table_size;
+extern const int uhc2_ucs_table_size;
+extern const int uhc3_ucs_table_size;
+extern const int ucs_a1_uhc_table_min;
+extern const int ucs_a1_uhc_table_max;
+extern const int ucs_a2_uhc_table_min;
+extern const int ucs_a2_uhc_table_max;
+extern const int ucs_a3_uhc_table_min;
+extern const int ucs_a3_uhc_table_max;
+extern const int ucs_i_uhc_table_min;
+extern const int ucs_i_uhc_table_max;
+extern const int ucs_s_uhc_table_min;
+extern const int ucs_s_uhc_table_max;
+extern const int ucs_r1_uhc_table_min;
+extern const int ucs_r1_uhc_table_max;
+extern const int ucs_r2_uhc_table_min;
+extern const int ucs_r2_uhc_table_max;
+
+
+
+
+#endif
diff --git a/ext/mbstring/libmbfl/mbfl/eaw_table.h b/ext/mbstring/libmbfl/mbfl/eaw_table.h
index a4f1e4fdf1..af310ea1d8 100644
--- a/ext/mbstring/libmbfl/mbfl/eaw_table.h
+++ b/ext/mbstring/libmbfl/mbfl/eaw_table.h
@@ -2,8 +2,9 @@ static const struct {
int begin;
int end;
} mbfl_eaw_table[] = {
- { 0x1100, 0x1159 },
- { 0x115f, 0x115f },
+ { 0x1100, 0x115f },
+ { 0x11a3, 0x11a7 },
+ { 0x11fa, 0x11ff },
{ 0x2329, 0x232a },
{ 0x2e80, 0x2e99 },
{ 0x2e9b, 0x2ef3 },
@@ -12,25 +13,32 @@ static const struct {
{ 0x3000, 0x303e },
{ 0x3041, 0x3096 },
{ 0x3099, 0x30ff },
- { 0x3105, 0x312c },
+ { 0x3105, 0x312d },
{ 0x3131, 0x318e },
- { 0x3190, 0x31b7 },
+ { 0x3190, 0x31ba },
+ { 0x31c0, 0x31e3 },
{ 0x31f0, 0x321e },
- { 0x3220, 0x3243 },
- { 0x3250, 0x327d },
- { 0x327f, 0x32fe },
- { 0x3300, 0x4db5 },
- { 0x4e00, 0x9fa5 },
- { 0xa000, 0xa48c },
+ { 0x3220, 0x3247 },
+ { 0x3250, 0x32fe },
+ { 0x3300, 0x4dbf },
+ { 0x4e00, 0xa48c },
{ 0xa490, 0xa4c6 },
+ { 0xa960, 0xa97c },
{ 0xac00, 0xd7a3 },
- { 0xf900, 0xfa2d },
- { 0xfa30, 0xfa6a },
+ { 0xd7b0, 0xd7c6 },
+ { 0xd7cb, 0xd7fb },
+ { 0xf900, 0xfaff },
+ { 0xfe10, 0xfe19 },
{ 0xfe30, 0xfe52 },
{ 0xfe54, 0xfe66 },
{ 0xfe68, 0xfe6b },
{ 0xff01, 0xff60 },
{ 0xffe0, 0xffe6 },
+ { 0x1b000, 0x1b001 },
+ { 0x1f200, 0x1f202 },
+ { 0x1f210, 0x1f23a },
+ { 0x1f240, 0x1f248 },
+ { 0x1f250, 0x1f251 },
{ 0x20000, 0x2fffd },
{ 0x30000, 0x3fffd }
};
diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter.c b/ext/mbstring/libmbfl/mbfl/mbfilter.c
index 8f2c8bb14e..b3759f940d 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfilter.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfilter.c
@@ -128,6 +128,18 @@ mbfl_buffer_converter_new(
enum mbfl_no_encoding to,
int buf_initsz)
{
+ const mbfl_encoding *_from = mbfl_no2encoding(from);
+ const mbfl_encoding *_to = mbfl_no2encoding(to);
+
+ return mbfl_buffer_converter_new2(_from ? _from: &mbfl_encoding_pass, _to ? _to: &mbfl_encoding_pass, buf_initsz);
+}
+
+mbfl_buffer_converter *
+mbfl_buffer_converter_new2(
+ const mbfl_encoding *from,
+ const mbfl_encoding *to,
+ int buf_initsz)
+{
mbfl_buffer_converter *convd;
/* allocate */
@@ -137,14 +149,8 @@ mbfl_buffer_converter_new(
}
/* initialize */
- convd->from = mbfl_no2encoding(from);
- convd->to = mbfl_no2encoding(to);
- if (convd->from == NULL) {
- convd->from = &mbfl_encoding_pass;
- }
- if (convd->to == NULL) {
- convd->to = &mbfl_encoding_pass;
- }
+ convd->from = from;
+ convd->to = to;
/* create convert filter */
convd->filter1 = NULL;
@@ -173,6 +179,7 @@ mbfl_buffer_converter_new(
return convd;
}
+
void
mbfl_buffer_converter_delete(mbfl_buffer_converter *convd)
{
@@ -251,6 +258,12 @@ mbfl_buffer_converter_strncat(mbfl_buffer_converter *convd, const unsigned char
int
mbfl_buffer_converter_feed(mbfl_buffer_converter *convd, mbfl_string *string)
{
+ return mbfl_buffer_converter_feed2(convd, string, NULL);
+}
+
+int
+mbfl_buffer_converter_feed2(mbfl_buffer_converter *convd, mbfl_string *string, int *loc)
+{
int n;
unsigned char *p;
mbfl_convert_filter *filter;
@@ -263,20 +276,27 @@ mbfl_buffer_converter_feed(mbfl_buffer_converter *convd, mbfl_string *string)
/* feed data */
n = string->len;
p = string->val;
+
filter = convd->filter1;
if (filter != NULL) {
filter_function = filter->filter_function;
while (n > 0) {
if ((*filter_function)(*p++, filter) < 0) {
+ if (loc) {
+ *loc = p - string->val;
+ }
return -1;
}
n--;
}
}
-
+ if (loc) {
+ *loc = p - string->val;
+ }
return 0;
}
+
int
mbfl_buffer_converter_flush(mbfl_buffer_converter *convd)
{
@@ -400,6 +420,49 @@ mbfl_encoding_detector_new(enum mbfl_no_encoding *elist, int elistsz, int strict
return identd;
}
+mbfl_encoding_detector *
+mbfl_encoding_detector_new2(const mbfl_encoding **elist, int elistsz, int strict)
+{
+ mbfl_encoding_detector *identd;
+
+ int i, num;
+ mbfl_identify_filter *filter;
+
+ if (elist == NULL || elistsz <= 0) {
+ return NULL;
+ }
+
+ /* allocate */
+ identd = (mbfl_encoding_detector*)mbfl_malloc(sizeof(mbfl_encoding_detector));
+ if (identd == NULL) {
+ return NULL;
+ }
+ identd->filter_list = (mbfl_identify_filter **)mbfl_calloc(elistsz, sizeof(mbfl_identify_filter *));
+ if (identd->filter_list == NULL) {
+ mbfl_free(identd);
+ return NULL;
+ }
+
+ /* create filters */
+ i = 0;
+ num = 0;
+ while (i < elistsz) {
+ filter = mbfl_identify_filter_new2(elist[i]);
+ if (filter != NULL) {
+ identd->filter_list[num] = filter;
+ num++;
+ }
+ i++;
+ }
+ identd->filter_list_size = num;
+
+ /* set strict flag */
+ identd->strict = strict;
+
+ return identd;
+}
+
+
void
mbfl_encoding_detector_delete(mbfl_encoding_detector *identd)
{
@@ -454,33 +517,32 @@ mbfl_encoding_detector_feed(mbfl_encoding_detector *identd, mbfl_string *string)
return res;
}
-enum mbfl_no_encoding mbfl_encoding_detector_judge(mbfl_encoding_detector *identd)
+const mbfl_encoding *mbfl_encoding_detector_judge2(mbfl_encoding_detector *identd)
{
mbfl_identify_filter *filter;
- enum mbfl_no_encoding encoding;
+ const mbfl_encoding *encoding = NULL;
int n;
/* judge */
- encoding = mbfl_no_encoding_invalid;
if (identd != NULL) {
n = identd->filter_list_size - 1;
while (n >= 0) {
filter = identd->filter_list[n];
if (!filter->flag) {
if (!identd->strict || !filter->status) {
- encoding = filter->encoding->no_encoding;
+ encoding = filter->encoding;
}
}
n--;
}
/* fallback judge */
- if (encoding == mbfl_no_encoding_invalid) {
+ if (!encoding) {
n = identd->filter_list_size - 1;
while (n >= 0) {
filter = identd->filter_list[n];
if (!filter->flag) {
- encoding = filter->encoding->no_encoding;
+ encoding = filter->encoding;
}
n--;
}
@@ -490,6 +552,12 @@ enum mbfl_no_encoding mbfl_encoding_detector_judge(mbfl_encoding_detector *ident
return encoding;
}
+enum mbfl_no_encoding mbfl_encoding_detector_judge(mbfl_encoding_detector *identd)
+{
+ const mbfl_encoding *encoding = mbfl_encoding_detector_judge2(identd);
+ return !encoding ? mbfl_no_encoding_invalid: encoding->no_encoding;
+}
+
/*
* encoding converter
@@ -646,36 +714,88 @@ mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int el
return encoding;
}
-const char*
-mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict)
+const mbfl_encoding *
+mbfl_identify_encoding2(mbfl_string *string, const mbfl_encoding **elist, int elistsz, int strict)
{
+ int i, n, num, bad;
+ unsigned char *p;
+ mbfl_identify_filter *flist, *filter;
const mbfl_encoding *encoding;
- encoding = mbfl_identify_encoding(string, elist, elistsz, strict);
- if (encoding != NULL &&
- encoding->no_encoding > mbfl_no_encoding_charset_min &&
- encoding->no_encoding < mbfl_no_encoding_charset_max) {
- return encoding->name;
- } else {
+ /* flist is an array of mbfl_identify_filter instances */
+ flist = (mbfl_identify_filter *)mbfl_calloc(elistsz, sizeof(mbfl_identify_filter));
+ if (flist == NULL) {
return NULL;
}
-}
-enum mbfl_no_encoding
-mbfl_identify_encoding_no(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict)
-{
- const mbfl_encoding *encoding;
+ num = 0;
+ if (elist != NULL) {
+ for (i = 0; i < elistsz; i++) {
+ if (!mbfl_identify_filter_init2(&flist[num], elist[i])) {
+ num++;
+ }
+ }
+ }
- encoding = mbfl_identify_encoding(string, elist, elistsz, strict);
- if (encoding != NULL &&
- encoding->no_encoding > mbfl_no_encoding_charset_min &&
- encoding->no_encoding < mbfl_no_encoding_charset_max) {
- return encoding->no_encoding;
- } else {
- return mbfl_no_encoding_invalid;
+ /* feed data */
+ n = string->len;
+ p = string->val;
+
+ if (p != NULL) {
+ bad = 0;
+ while (n > 0) {
+ for (i = 0; i < num; i++) {
+ filter = &flist[i];
+ if (!filter->flag) {
+ (*filter->filter_function)(*p, filter);
+ if (filter->flag) {
+ bad++;
+ }
+ }
+ }
+ if ((num - 1) <= bad && !strict) {
+ break;
+ }
+ p++;
+ n--;
+ }
+ }
+
+ /* judge */
+ encoding = NULL;
+
+ for (i = 0; i < num; i++) {
+ filter = &flist[i];
+ if (!filter->flag) {
+ if (strict && filter->status) {
+ continue;
+ }
+ encoding = filter->encoding;
+ break;
+ }
+ }
+
+ /* fall-back judge */
+ if (!encoding) {
+ for (i = 0; i < num; i++) {
+ filter = &flist[i];
+ if (!filter->flag && (!strict || !filter->status)) {
+ encoding = filter->encoding;
+ break;
+ }
+ }
+ }
+
+ /* cleanup */
+ /* dtors should be called in reverse order */
+ i = num; while (--i >= 0) {
+ mbfl_identify_filter_cleanup(&flist[i]);
}
-}
+ mbfl_free((void *)flist);
+
+ return encoding;
+}
/*
* strlen
@@ -2626,7 +2746,9 @@ collector_decode_htmlnumericentity(int c, void *data)
}
break;
case 2:
- if (c >= 0x30 && c <= 0x39) { /* '0' - '9' */
+ if (c == 0x78) { /* 'x' */
+ pc->status = 4;
+ } else if (c >= 0x30 && c <= 0x39) { /* '0' - '9' */
pc->cache = c - 0x30;
pc->status = 3;
pc->digit = 1;
@@ -2690,6 +2812,89 @@ collector_decode_htmlnumericentity(int c, void *data)
(*pc->decoder->filter_function)(c, pc->decoder);
}
break;
+ case 4:
+ if (c >= 0x30 && c <= 0x39) { /* '0' - '9' */
+ pc->cache = c - 0x30;
+ pc->status = 5;
+ pc->digit = 1;
+ } else if (c >= 0x41 && c <= 0x46) { /* 'A' - 'F' */
+ pc->cache = c - 0x41 + 10;
+ pc->status = 5;
+ pc->digit = 1;
+ } else if (c >= 0x61 && c <= 0x66) { /* 'a' - 'f' */
+ pc->cache = c - 0x61 + 10;
+ pc->status = 5;
+ pc->digit = 1;
+ } else {
+ pc->status = 0;
+ (*pc->decoder->filter_function)(0x26, pc->decoder); /* '&' */
+ (*pc->decoder->filter_function)(0x23, pc->decoder); /* '#' */
+ (*pc->decoder->filter_function)(0x78, pc->decoder); /* 'x' */
+ (*pc->decoder->filter_function)(c, pc->decoder);
+ }
+ break;
+ case 5:
+ s = 0;
+ f = 0;
+ if ((c >= 0x30 && c <= 0x39) ||
+ (c >= 0x41 && c <= 0x46) ||
+ (c >= 0x61 && c <= 0x66)) { /* '0' - '9' or 'a' - 'f' */
+ if (pc->digit > 9) {
+ pc->status = 0;
+ s = pc->cache;
+ f = 1;
+ } else {
+ if (c >= 0x30 && c <= 0x39) {
+ s = pc->cache*16 + (c - 0x30);
+ } else if (c >= 0x41 && c <= 0x46) {
+ s = pc->cache*16 + (c - 0x41 + 10);
+ } else {
+ s = pc->cache*16 + (c - 0x61 + 10);
+ }
+ pc->cache = s;
+ pc->digit++;
+ }
+ } else {
+ pc->status = 0;
+ s = pc->cache;
+ f = 1;
+ n = 0;
+ size = pc->mapsize;
+ while (n < size) {
+ mapelm = &(pc->convmap[n*4]);
+ d = s - mapelm[2];
+ if (d >= mapelm[0] && d <= mapelm[1]) {
+ f = 0;
+ (*pc->decoder->filter_function)(d, pc->decoder);
+ if (c != 0x3b) { /* ';' */
+ (*pc->decoder->filter_function)(c, pc->decoder);
+ }
+ break;
+ }
+ n++;
+ }
+ }
+ if (f) {
+ (*pc->decoder->filter_function)(0x26, pc->decoder); /* '&' */
+ (*pc->decoder->filter_function)(0x23, pc->decoder); /* '#' */
+ (*pc->decoder->filter_function)(0x78, pc->decoder); /* 'x' */
+ r = 1;
+ n = pc->digit;
+ while (n > 0) {
+ r *= 16;
+ n--;
+ }
+ s %= r;
+ r /= 16;
+ while (r > 0) {
+ d = s/r;
+ s %= r;
+ r /= 16;
+ (*pc->decoder->filter_function)(mbfl_hexchar_table[d], pc->decoder);
+ }
+ (*pc->decoder->filter_function)(c, pc->decoder);
+ }
+ break;
default:
if (c == 0x26) { /* '&' */
pc->status = 1;
@@ -2702,6 +2907,53 @@ collector_decode_htmlnumericentity(int c, void *data)
return c;
}
+static int
+collector_encode_hex_htmlnumericentity(int c, void *data)
+{
+ struct collector_htmlnumericentity_data *pc = (struct collector_htmlnumericentity_data *)data;
+ int f, n, s, r, d, size, *mapelm;
+
+ size = pc->mapsize;
+ f = 0;
+ n = 0;
+ while (n < size) {
+ mapelm = &(pc->convmap[n*4]);
+ if (c >= mapelm[0] && c <= mapelm[1]) {
+ s = (c + mapelm[2]) & mapelm[3];
+ if (s >= 0) {
+ (*pc->decoder->filter_function)(0x26, pc->decoder); /* '&' */
+ (*pc->decoder->filter_function)(0x23, pc->decoder); /* '#' */
+ (*pc->decoder->filter_function)(0x78, pc->decoder); /* 'x' */
+ r = 0x1000000;
+ s %= r;
+ while (r > 0) {
+ d = s/r;
+ if (d || f) {
+ f = 1;
+ s %= r;
+ (*pc->decoder->filter_function)(mbfl_hexchar_table[d], pc->decoder);
+ }
+ r /= 16;
+ }
+ if (!f) {
+ f = 1;
+ (*pc->decoder->filter_function)(mbfl_hexchar_table[0], pc->decoder);
+ }
+ (*pc->decoder->filter_function)(0x3b, pc->decoder); /* ';' */
+ }
+ }
+ if (f) {
+ break;
+ }
+ n++;
+ }
+ if (!f) {
+ (*pc->decoder->filter_function)(c, pc->decoder);
+ }
+
+ return c;
+}
+
int mbfl_filt_decode_htmlnumericentity_flush(mbfl_convert_filter *filter)
{
struct collector_htmlnumericentity_data *pc = (struct collector_htmlnumericentity_data *)filter;
@@ -2737,6 +2989,32 @@ int mbfl_filt_decode_htmlnumericentity_flush(mbfl_convert_filter *filter)
}
break;
+ case 4: /* 'x' */
+ (*pc->decoder->filter_function)(0x26, pc->decoder); /* '&' */
+ (*pc->decoder->filter_function)(0x23, pc->decoder); /* '#' */
+ (*pc->decoder->filter_function)(0x78, pc->decoder); /* 'x' */
+ break;
+ case 5: /* '0'-'9','a'-'f' */
+ (*pc->decoder->filter_function)(0x26, pc->decoder); /* '&' */
+ (*pc->decoder->filter_function)(0x23, pc->decoder); /* '#' */
+ (*pc->decoder->filter_function)(0x78, pc->decoder); /* 'x' */
+
+ s = pc->cache;
+ r = 1;
+ n = pc->digit;
+ while (n > 0) {
+ r *= 16;
+ n--;
+ }
+ s %= r;
+ r /= 16;
+ while (r > 0) {
+ d = s/r;
+ s %= r;
+ r /= 16;
+ (*pc->decoder->filter_function)(mbfl_hexchar_table[d], pc->decoder);
+ }
+ break;
default:
break;
}
@@ -2749,6 +3027,7 @@ int mbfl_filt_decode_htmlnumericentity_flush(mbfl_convert_filter *filter)
return 0;
}
+
mbfl_string *
mbfl_html_numeric_entity(
mbfl_string *string,
@@ -2777,16 +3056,21 @@ mbfl_html_numeric_entity(
string->no_encoding,
mbfl_memory_device_output, 0, &device);
/* wchar filter */
- if (type == 0) {
+ if (type == 0) { /* decimal output */
encoder = mbfl_convert_filter_new(
string->no_encoding,
mbfl_no_encoding_wchar,
collector_encode_htmlnumericentity, 0, &pc);
- } else {
+ } else if (type == 2) { /* hex output */
+ encoder = mbfl_convert_filter_new(
+ string->no_encoding,
+ mbfl_no_encoding_wchar,
+ collector_encode_hex_htmlnumericentity, 0, &pc);
+ } else { /* type == 1: decimal/hex input */
encoder = mbfl_convert_filter_new(
string->no_encoding,
mbfl_no_encoding_wchar,
- collector_decode_htmlnumericentity,
+ collector_decode_htmlnumericentity,
(int (*)(void*))mbfl_filt_decode_htmlnumericentity_flush, &pc);
}
if (pc.decoder == NULL || encoder == NULL) {
diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter.h b/ext/mbstring/libmbfl/mbfl/mbfilter.h
index 4565fc6985..6108f93195 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfilter.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfilter.h
@@ -102,8 +102,8 @@
* version information
*/
#define MBFL_VERSION_MAJOR 1
-#define MBFL_VERSION_MINOR 1
-#define MBFL_VERSION_TEENY 0
+#define MBFL_VERSION_MINOR 3
+#define MBFL_VERSION_TEENY 2
/*
* convert filter
@@ -127,12 +127,14 @@ struct _mbfl_buffer_converter {
};
MBFLAPI extern mbfl_buffer_converter * mbfl_buffer_converter_new(enum mbfl_no_encoding from, enum mbfl_no_encoding to, int buf_initsz);
+MBFLAPI extern mbfl_buffer_converter * mbfl_buffer_converter_new2(const mbfl_encoding *from, const mbfl_encoding *to, int buf_initsz);
MBFLAPI extern void mbfl_buffer_converter_delete(mbfl_buffer_converter *convd);
MBFLAPI extern void mbfl_buffer_converter_reset(mbfl_buffer_converter *convd);
MBFLAPI extern int mbfl_buffer_converter_illegal_mode(mbfl_buffer_converter *convd, int mode);
MBFLAPI extern int mbfl_buffer_converter_illegal_substchar(mbfl_buffer_converter *convd, int substchar);
MBFLAPI extern int mbfl_buffer_converter_strncat(mbfl_buffer_converter *convd, const unsigned char *p, int n);
MBFLAPI extern int mbfl_buffer_converter_feed(mbfl_buffer_converter *convd, mbfl_string *string);
+MBFLAPI extern int mbfl_buffer_converter_feed2(mbfl_buffer_converter *convd, mbfl_string *string, int *loc);
MBFLAPI extern int mbfl_buffer_converter_flush(mbfl_buffer_converter *convd);
MBFLAPI extern mbfl_string * mbfl_buffer_converter_getbuffer(mbfl_buffer_converter *convd, mbfl_string *result);
MBFLAPI extern mbfl_string * mbfl_buffer_converter_result(mbfl_buffer_converter *convd, mbfl_string *result);
@@ -151,9 +153,11 @@ struct _mbfl_encoding_detector {
};
MBFLAPI extern mbfl_encoding_detector * mbfl_encoding_detector_new(enum mbfl_no_encoding *elist, int elistsz, int strict);
+MBFLAPI extern mbfl_encoding_detector * mbfl_encoding_detector_new2(const mbfl_encoding **elist, int elistsz, int strict);
MBFLAPI extern void mbfl_encoding_detector_delete(mbfl_encoding_detector *identd);
MBFLAPI extern int mbfl_encoding_detector_feed(mbfl_encoding_detector *identd, mbfl_string *string);
MBFLAPI extern enum mbfl_no_encoding mbfl_encoding_detector_judge(mbfl_encoding_detector *identd);
+MBFLAPI extern const mbfl_encoding *mbfl_encoding_detector_judge2(mbfl_encoding_detector *identd);
/*
@@ -169,12 +173,8 @@ mbfl_convert_encoding(mbfl_string *string, mbfl_string *result, enum mbfl_no_enc
MBFLAPI extern const mbfl_encoding *
mbfl_identify_encoding(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict);
-MBFLAPI extern const char *
-mbfl_identify_encoding_name(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict);
-
-MBFLAPI extern enum mbfl_no_encoding
-mbfl_identify_encoding_no(mbfl_string *string, enum mbfl_no_encoding *elist, int elistsz, int strict);
-
+MBFLAPI extern const mbfl_encoding *
+mbfl_identify_encoding2(mbfl_string *string, const mbfl_encoding **elist, int elistsz, int strict);
/*
* strlen
*/
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_consts.h b/ext/mbstring/libmbfl/mbfl/mbfl_consts.h
index b6c0bb2d87..6a630c8fcd 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_consts.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_consts.h
@@ -42,7 +42,8 @@
#define MBFL_ENCTYPE_MWC4BE 0x00000400
#define MBFL_ENCTYPE_MWC4LE 0x00000800
#define MBFL_ENCTYPE_SHFTCODE 0x00001000
-#define MBFL_ENCTYPE_HTML_ENT 0x00002000
+#define MBFL_ENCTYPE_ENC_STRM 0x00002000
+#define MBFL_ENCTYPE_GL_UNSAFE 0x00004000
/* wchar plane, special charactor */
#define MBFL_WCSPLANE_MASK 0xffff
@@ -50,6 +51,7 @@
#define MBFL_WCSPLANE_UTF32MAX 0x00110000
#define MBFL_WCSPLANE_SUPMIN 0x00010000
#define MBFL_WCSPLANE_SUPMAX 0x00200000
+#define MBFL_WCSPLANE_JIS0213 0x70e00000 /* JIS HEX : 2121h - 7E7Eh */
#define MBFL_WCSPLANE_JIS0208 0x70e10000 /* JIS HEX : 2121h - 7E7Eh */
#define MBFL_WCSPLANE_JIS0212 0x70e20000 /* JIS HEX : 2121h - 7E7Eh */
#define MBFL_WCSPLANE_WINCP932 0x70e30000 /* JIS HEX : 2121h - 9898h */
@@ -80,6 +82,7 @@
#define MBFL_WCSPLANE_KOI8U 0x70fc0000
#define MBFL_WCSPLANE_CP1254 0x70fd0000 /* 00h - FFh */
#define MBFL_WCSPLANE_CP850 0x70fe0000 /* 00h - FFh */
+#define MBFL_WCSPLANE_GB18030 0x70ff0000 /* a1a1h-e3329a35h */
#define MBFL_WCSGROUP_MASK 0xffffff
#define MBFL_WCSGROUP_UCS4MAX 0x70000000
#define MBFL_WCSGROUP_WCHARMAX 0x78000000
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_convert.c b/ext/mbstring/libmbfl/mbfl/mbfl_convert.c
index d81b533dd1..ae8deb25fb 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_convert.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_convert.c
@@ -52,11 +52,18 @@
#include "filters/mbfilter_iso2022_kr.h"
#include "filters/mbfilter_sjis.h"
#include "filters/mbfilter_sjis_open.h"
+#include "filters/mbfilter_sjis_2004.h"
+#include "filters/mbfilter_sjis_mobile.h"
+#include "filters/mbfilter_sjis_mac.h"
#include "filters/mbfilter_cp51932.h"
#include "filters/mbfilter_jis.h"
#include "filters/mbfilter_iso2022_jp_ms.h"
+#include "filters/mbfilter_iso2022jp_2004.h"
+#include "filters/mbfilter_iso2022jp_mobile.h"
#include "filters/mbfilter_euc_jp.h"
+#include "filters/mbfilter_euc_jp_2004.h"
#include "filters/mbfilter_euc_jp_win.h"
+#include "filters/mbfilter_gb18030.h"
#include "filters/mbfilter_ascii.h"
#include "filters/mbfilter_koi8r.h"
#include "filters/mbfilter_koi8u.h"
@@ -87,6 +94,7 @@
#include "filters/mbfilter_utf7.h"
#include "filters/mbfilter_utf7imap.h"
#include "filters/mbfilter_utf8.h"
+#include "filters/mbfilter_utf8_mobile.h"
#include "filters/mbfilter_utf16.h"
#include "filters/mbfilter_utf32.h"
#include "filters/mbfilter_byte2.h"
@@ -111,6 +119,8 @@ const struct mbfl_convert_vtbl *mbfl_convert_filter_list[] = {
&vtbl_wchar_sjis,
&vtbl_sjis_open_wchar,
&vtbl_wchar_sjis_open,
+ &vtbl_sjis2004_wchar,
+ &vtbl_wchar_sjis2004,
&vtbl_cp51932_wchar,
&vtbl_wchar_cp51932,
&vtbl_jis_wchar,
@@ -121,20 +131,46 @@ const struct mbfl_convert_vtbl *mbfl_convert_filter_list[] = {
&vtbl_wchar_2022jp,
&vtbl_2022jpms_wchar,
&vtbl_wchar_2022jpms,
+ &vtbl_2022jp_2004_wchar,
+ &vtbl_wchar_2022jp_2004,
+ &vtbl_2022jp_kddi_wchar,
+ &vtbl_wchar_2022jp_kddi,
&vtbl_eucjpwin_wchar,
&vtbl_wchar_eucjpwin,
+ &vtbl_eucjp2004_wchar,
+ &vtbl_wchar_eucjp2004,
&vtbl_cp932_wchar,
&vtbl_wchar_cp932,
+ &vtbl_sjis_docomo_wchar,
+ &vtbl_wchar_sjis_docomo,
+ &vtbl_sjis_kddi_wchar,
+ &vtbl_wchar_sjis_kddi,
+ &vtbl_sjis_sb_wchar,
+ &vtbl_wchar_sjis_sb,
+ &vtbl_sjis_mac_wchar,
+ &vtbl_wchar_sjis_mac,
+ &vtbl_utf8_docomo_wchar,
+ &vtbl_wchar_utf8_docomo,
+ &vtbl_utf8_kddi_a_wchar,
+ &vtbl_wchar_utf8_kddi_a,
+ &vtbl_utf8_kddi_b_wchar,
+ &vtbl_wchar_utf8_kddi_b,
+ &vtbl_utf8_sb_wchar,
+ &vtbl_wchar_utf8_sb,
&vtbl_euccn_wchar,
&vtbl_wchar_euccn,
&vtbl_cp936_wchar,
&vtbl_wchar_cp936,
+ &vtbl_gb18030_wchar,
+ &vtbl_wchar_gb18030,
&vtbl_hz_wchar,
&vtbl_wchar_hz,
&vtbl_euctw_wchar,
&vtbl_wchar_euctw,
&vtbl_big5_wchar,
&vtbl_wchar_big5,
+ &vtbl_cp950_wchar,
+ &vtbl_wchar_cp950,
&vtbl_euckr_wchar,
&vtbl_wchar_euckr,
&vtbl_uhc_wchar,
@@ -454,9 +490,15 @@ mbfl_filt_conv_illegal_output(int c, mbfl_convert_filter *filter)
case MBFL_WCSPLANE_JIS0212:
ret = mbfl_convert_filter_strcat(filter, (const unsigned char *)"JIS2+");
break;
+ case MBFL_WCSPLANE_JIS0213:
+ ret = mbfl_convert_filter_strcat(filter, (const unsigned char *)"JIS3+");
+ break;
case MBFL_WCSPLANE_WINCP932:
ret = mbfl_convert_filter_strcat(filter, (const unsigned char *)"W932+");
break;
+ case MBFL_WCSPLANE_GB18030:
+ ret = mbfl_convert_filter_strcat(filter, (const unsigned char *)"GB+");
+ break;
case MBFL_WCSPLANE_8859_1:
ret = mbfl_convert_filter_strcat(filter, (const unsigned char *)"I8859_1+");
break;
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c
index 17955b2c9a..adf0c3ae87 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c
@@ -58,11 +58,18 @@
#include "filters/mbfilter_iso2022_kr.h"
#include "filters/mbfilter_sjis.h"
#include "filters/mbfilter_sjis_open.h"
+#include "filters/mbfilter_sjis_mobile.h"
+#include "filters/mbfilter_sjis_mac.h"
+#include "filters/mbfilter_sjis_2004.h"
#include "filters/mbfilter_cp51932.h"
#include "filters/mbfilter_jis.h"
#include "filters/mbfilter_iso2022_jp_ms.h"
+#include "filters/mbfilter_iso2022jp_2004.h"
+#include "filters/mbfilter_iso2022jp_mobile.h"
#include "filters/mbfilter_euc_jp.h"
#include "filters/mbfilter_euc_jp_win.h"
+#include "filters/mbfilter_euc_jp_2004.h"
+#include "filters/mbfilter_gb18030.h"
#include "filters/mbfilter_ascii.h"
#include "filters/mbfilter_koi8r.h"
#include "filters/mbfilter_koi8u.h"
@@ -94,6 +101,7 @@
#include "filters/mbfilter_utf7.h"
#include "filters/mbfilter_utf7imap.h"
#include "filters/mbfilter_utf8.h"
+#include "filters/mbfilter_utf8_mobile.h"
#include "filters/mbfilter_utf16.h"
#include "filters/mbfilter_utf32.h"
#include "filters/mbfilter_byte2.h"
@@ -155,12 +163,23 @@ static const mbfl_encoding *mbfl_encoding_ptr_list[] = {
&mbfl_encoding_euc_jp,
&mbfl_encoding_sjis,
&mbfl_encoding_eucjp_win,
+ &mbfl_encoding_eucjp2004,
&mbfl_encoding_sjis_open,
+ &mbfl_encoding_sjis_docomo,
+ &mbfl_encoding_sjis_kddi,
+ &mbfl_encoding_sjis_sb,
+ &mbfl_encoding_sjis_mac,
+ &mbfl_encoding_sjis2004,
+ &mbfl_encoding_utf8_docomo,
+ &mbfl_encoding_utf8_kddi_a,
+ &mbfl_encoding_utf8_kddi_b,
+ &mbfl_encoding_utf8_sb,
&mbfl_encoding_cp932,
&mbfl_encoding_cp51932,
&mbfl_encoding_jis,
&mbfl_encoding_2022jp,
&mbfl_encoding_2022jpms,
+ &mbfl_encoding_gb18030,
&mbfl_encoding_cp1252,
&mbfl_encoding_cp1254,
&mbfl_encoding_8859_1,
@@ -182,6 +201,7 @@ static const mbfl_encoding *mbfl_encoding_ptr_list[] = {
&mbfl_encoding_hz,
&mbfl_encoding_euc_tw,
&mbfl_encoding_big5,
+ &mbfl_encoding_cp950,
&mbfl_encoding_euc_kr,
&mbfl_encoding_uhc,
&mbfl_encoding_2022kr,
@@ -192,6 +212,8 @@ static const mbfl_encoding *mbfl_encoding_ptr_list[] = {
&mbfl_encoding_armscii8,
&mbfl_encoding_cp850,
&mbfl_encoding_jis_ms,
+ &mbfl_encoding_2022jp_2004,
+ &mbfl_encoding_2022jp_kddi,
&mbfl_encoding_cp50220,
&mbfl_encoding_cp50220raw,
&mbfl_encoding_cp50221,
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h
index fd3a66df6e..ca7717cb7b 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h
@@ -62,18 +62,31 @@ enum mbfl_no_encoding {
mbfl_no_encoding_utf16be,
mbfl_no_encoding_utf16le,
mbfl_no_encoding_utf8,
+ mbfl_no_encoding_utf8_docomo,
+ mbfl_no_encoding_utf8_kddi_a,
+ mbfl_no_encoding_utf8_kddi_b,
+ mbfl_no_encoding_utf8_sb,
mbfl_no_encoding_utf7,
mbfl_no_encoding_utf7imap,
mbfl_no_encoding_ascii,
mbfl_no_encoding_euc_jp,
+ mbfl_no_encoding_eucjp2004,
mbfl_no_encoding_sjis,
mbfl_no_encoding_eucjp_win,
mbfl_no_encoding_sjis_open,
+ mbfl_no_encoding_sjis_docomo,
+ mbfl_no_encoding_sjis_kddi,
+ mbfl_no_encoding_sjis_sb,
+ mbfl_no_encoding_sjis_mac,
+ mbfl_no_encoding_sjis2004,
mbfl_no_encoding_cp932,
mbfl_no_encoding_cp51932,
mbfl_no_encoding_jis,
mbfl_no_encoding_2022jp,
+ mbfl_no_encoding_2022jp_2004,
+ mbfl_no_encoding_2022jp_kddi,
mbfl_no_encoding_2022jpms,
+ mbfl_no_encoding_gb18030,
mbfl_no_encoding_cp1252,
mbfl_no_encoding_cp1254,
mbfl_no_encoding_8859_1,
@@ -93,6 +106,7 @@ enum mbfl_no_encoding {
mbfl_no_encoding_cp936,
mbfl_no_encoding_euc_tw,
mbfl_no_encoding_big5,
+ mbfl_no_encoding_cp950,
mbfl_no_encoding_euc_kr,
mbfl_no_encoding_2022kr,
mbfl_no_encoding_uhc,
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_ident.c b/ext/mbstring/libmbfl/mbfl/mbfl_ident.c
index 9a89807053..4d6283f4f2 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_ident.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_ident.c
@@ -51,10 +51,15 @@
#include "filters/mbfilter_iso2022_kr.h"
#include "filters/mbfilter_sjis.h"
#include "filters/mbfilter_sjis_open.h"
+#include "filters/mbfilter_sjis_mobile.h"
#include "filters/mbfilter_jis.h"
#include "filters/mbfilter_iso2022_jp_ms.h"
+#include "filters/mbfilter_iso2022jp_2004.h"
+#include "filters/mbfilter_iso2022jp_mobile.h"
#include "filters/mbfilter_euc_jp.h"
#include "filters/mbfilter_euc_jp_win.h"
+#include "filters/mbfilter_euc_jp_2004.h"
+#include "filters/mbfilter_utf8_mobile.h"
#include "filters/mbfilter_ascii.h"
#include "filters/mbfilter_koi8r.h"
#include "filters/mbfilter_koi8u.h"
@@ -66,6 +71,7 @@
#include "filters/mbfilter_cp1254.h"
#include "filters/mbfilter_cp51932.h"
#include "filters/mbfilter_cp5022x.h"
+#include "filters/mbfilter_gb18030.h"
#include "filters/mbfilter_iso8859_1.h"
#include "filters/mbfilter_iso8859_2.h"
#include "filters/mbfilter_iso8859_3.h"
@@ -111,16 +117,27 @@ static const struct mbfl_identify_vtbl *mbfl_identify_filter_list[] = {
&vtbl_identify_sjis,
&vtbl_identify_sjis_open,
&vtbl_identify_eucjpwin,
+ &vtbl_identify_eucjp2004,
&vtbl_identify_cp932,
&vtbl_identify_jis,
&vtbl_identify_2022jp,
&vtbl_identify_2022jpms,
+ &vtbl_identify_2022jp_2004,
+ &vtbl_identify_2022jp_kddi,
&vtbl_identify_cp51932,
+ &vtbl_identify_sjis_docomo,
+ &vtbl_identify_sjis_kddi,
+ &vtbl_identify_sjis_sb,
+ &vtbl_identify_utf8_docomo,
+ &vtbl_identify_utf8_kddi_a,
+ &vtbl_identify_utf8_kddi_b,
+ &vtbl_identify_utf8_sb,
&vtbl_identify_euccn,
&vtbl_identify_cp936,
&vtbl_identify_hz,
&vtbl_identify_euctw,
&vtbl_identify_big5,
+ &vtbl_identify_cp950,
&vtbl_identify_euckr,
&vtbl_identify_uhc,
&vtbl_identify_2022kr,
@@ -149,6 +166,7 @@ static const struct mbfl_identify_vtbl *mbfl_identify_filter_list[] = {
&vtbl_identify_cp50220,
&vtbl_identify_cp50221,
&vtbl_identify_cp50222,
+ &vtbl_identify_gb18030,
&vtbl_identify_false,
NULL
};
@@ -191,15 +209,37 @@ mbfl_identify_filter *mbfl_identify_filter_new(enum mbfl_no_encoding encoding)
return filter;
}
+mbfl_identify_filter *mbfl_identify_filter_new2(const mbfl_encoding *encoding)
+{
+ mbfl_identify_filter *filter;
+
+ /* allocate */
+ filter = (mbfl_identify_filter *)mbfl_malloc(sizeof(mbfl_identify_filter));
+ if (filter == NULL) {
+ return NULL;
+ }
+
+ if (mbfl_identify_filter_init2(filter, encoding)) {
+ mbfl_free(filter);
+ return NULL;
+ }
+
+ return filter;
+}
+
+
int mbfl_identify_filter_init(mbfl_identify_filter *filter, enum mbfl_no_encoding encoding)
{
+ const mbfl_encoding *enc = mbfl_no2encoding(encoding);
+ return mbfl_identify_filter_init2(filter, enc ? enc: &mbfl_encoding_pass);
+}
+
+int mbfl_identify_filter_init2(mbfl_identify_filter *filter, const mbfl_encoding *encoding)
+{
const struct mbfl_identify_vtbl *vtbl;
/* encoding structure */
- filter->encoding = mbfl_no2encoding(encoding);
- if (filter->encoding == NULL) {
- filter->encoding = &mbfl_encoding_pass;
- }
+ filter->encoding = encoding;
filter->status = 0;
filter->flag = 0;
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_ident.h b/ext/mbstring/libmbfl/mbfl/mbfl_ident.h
index b0721fc413..12d81cde8c 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_ident.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_ident.h
@@ -58,8 +58,10 @@ struct mbfl_identify_vtbl {
MBFLAPI extern const struct mbfl_identify_vtbl * mbfl_identify_filter_get_vtbl(enum mbfl_no_encoding encoding);
MBFLAPI extern mbfl_identify_filter * mbfl_identify_filter_new(enum mbfl_no_encoding encoding);
+MBFLAPI extern mbfl_identify_filter * mbfl_identify_filter_new2(const mbfl_encoding *encoding);
MBFLAPI extern void mbfl_identify_filter_delete(mbfl_identify_filter *filter);
MBFLAPI extern int mbfl_identify_filter_init(mbfl_identify_filter *filter, enum mbfl_no_encoding encoding);
+MBFLAPI extern int mbfl_identify_filter_init2(mbfl_identify_filter *filter, const mbfl_encoding *encoding);
MBFLAPI void mbfl_identify_filter_cleanup(mbfl_identify_filter *filter);
MBFLAPI extern void mbfl_filt_ident_common_ctor(mbfl_identify_filter *filter);
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c b/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c
index 6d93fa3529..7509ef1a6a 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c
@@ -218,7 +218,7 @@ mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
const unsigned char *p;
len = 0;
- p = psrc;
+ p = (const unsigned char*)psrc;
while (*p) {
p++;
len++;
@@ -235,7 +235,7 @@ mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
device->buffer = tmp;
}
- p = psrc;
+ p = (const unsigned char*)psrc;
w = &device->buffer[device->pos];
device->pos += len;
while (len > 0) {
diff --git a/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk b/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk
index c7deb4cdf5..02c73f2025 100644
--- a/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk
+++ b/ext/mbstring/libmbfl/mbfl/mk_eaw_tbl.awk
@@ -18,7 +18,8 @@ BEGIN {
/^[0-9a-fA-F]+;/ {
if ($2 == "W" || $2 == "F") {
- v = ( "0x" $1 ) + 0
+
+ v = strtonum( "0x" $1 )
if (prev < 0) {
first = v
} else if (v - prev > 1) {
@@ -44,8 +45,8 @@ BEGIN {
/^[0-9a-fA-F]+\.\./ {
if ($4 == "W" || $4 == "F") {
- vs = ( "0x" $1 ) + 0
- ve = ( "0x" $3 ) + 0
+ vs = strtonum( "0x" $1 )
+ ve = strtonum( "0x" $3 )
if (prev < 0) {
first = vs
} else if (vs - prev > 1) {
diff --git a/ext/mbstring/libmbfl/tests/emoji.c b/ext/mbstring/libmbfl/tests/emoji.c
new file mode 100644
index 0000000000..4f6a346576
--- /dev/null
+++ b/ext/mbstring/libmbfl/tests/emoji.c
@@ -0,0 +1,119 @@
+/**
+ * this is a small sample script to use libmbfl.
+ * Rui Hirokawa <hirokawa@php.net>
+ *
+ * this file is encoded in EUC-JP.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mbfl/mbfilter.h"
+
+static void hexdump(const mbfl_string *ptr)
+{
+ unsigned int i;
+
+ for (i = 0; i < ptr->len; i++) {
+ printf("%%%02x", ptr->val[i]);
+ }
+
+ printf(" (%u)\n", ptr->len);
+}
+
+//#define TEST_DOCOMO
+//#define TEST_KDDI
+#define TEST_SOFTBANK
+
+int main(int argc, char **argv)
+{
+ enum mbfl_no_encoding from_encoding, to_encoding;
+ enum mbfl_no_language no_language;
+ mbfl_buffer_converter *convd = NULL, *convd2 = NULL;
+ mbfl_memory_device dev, dev2;
+ mbfl_string string, result, *ret;
+#ifdef TEST_DOCOMO
+ //char str[] = {0xF9,0xD7,0x00}; // U+2122
+ //char str[] = {0xF9,0x82,0x00}; // U+1F195
+ char str[] = {0xF9,0xD6,0x00}; // U+00A9
+#endif
+#ifdef TEST_KDDI
+ //char str[] = {0xF7,0x6A,0x00};// U+2122
+ //char str[] = {0xF7,0xE5,0x00}; // U+1F195
+ //char str[] = {0xF3,0xD2,0x00}; // U+1F1E8 U+1F1F3
+ char str[] = {0xF7,0x74,0x00}; // U+00A9
+#endif
+#ifdef TEST_SOFTBANK
+ //char str[] = {0xFB,0xD7,0x00};// U+2122
+ //char str[] = {0xF7,0xB2,0x00}; // U+1F195
+ //char str[] = {0xFB,0xB3,0x00}; // U+1F1E8 U+1F1F3
+ char str[] = {0xF7,0xEE,0x00}; // U+00A9
+#endif
+ int final = 0;
+ int state = 0;
+ int i;
+
+ no_language = mbfl_name2no_language("Japanese");
+#ifdef TEST_DOCOMO
+ from_encoding = mbfl_name2no_encoding("SJIS-win#DOCOMO");
+#endif
+#ifdef TEST_KDDI
+ from_encoding = mbfl_name2no_encoding("SJIS-win#KDDI");
+#endif
+#ifdef TEST_SOFTBANK
+ from_encoding = mbfl_name2no_encoding("SJIS-win#SOFTBANK");
+#endif
+ to_encoding = mbfl_name2no_encoding("UTF-8");
+
+ convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0);
+
+ mbfl_memory_device_init(&dev, 0, 4096);
+ mbfl_string_init_set(&string, no_language, from_encoding);
+ mbfl_memory_device_realloc(&dev, dev.length + dev.allocsz, dev.allocsz);
+
+ strcpy(dev.buffer, str);
+ dev.pos += strlen(str);
+
+ mbfl_memory_device_result(&dev, &string);
+ mbfl_string_init_set(&result, no_language, to_encoding);
+ ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
+
+#if 0
+ for (i = 0; i < result.len; i+= 2) {
+ if (result.val[i] >= 0xD8 && result.val[i] < 0xE0) { // Surrogate pair
+ int h = (result.val[i] & 0x07)<<8 | result.val[i+1];
+ int l = (result.val[i+2] & 0x03)<<8 | result.val[i+3];
+ int c = (h<<(2+8)) | l;
+ printf("U+%x\n",c+0x10000);
+ i+=2;
+ } else {
+ printf("U+%x\n",(result.val[i] << 8) | result.val[i+1]);
+ }
+ }
+ hexdump(&result);
+#endif
+
+
+#if 1
+ convd2 = mbfl_buffer_converter_new(to_encoding, from_encoding, 0);
+ mbfl_memory_device_init(&dev2, 0, 4096);
+ mbfl_string_init_set(&string, no_language, to_encoding);
+ mbfl_memory_device_realloc(&dev2, dev2.length + dev2.allocsz, dev2.allocsz);
+
+ memcpy(dev2.buffer, result.val, result.len+1);
+ dev2.pos += strlen(dev2.buffer);
+
+ mbfl_memory_device_result(&dev2, &string);
+ mbfl_string_init_set(&result, no_language, from_encoding);
+ ret = mbfl_buffer_converter_feed_result(convd2, &string, &result);
+ hexdump(&result);
+ mbfl_buffer_converter_delete(convd2);
+#endif
+ mbfl_string_clear(&result);
+ mbfl_string_clear(&string);
+
+ mbfl_buffer_converter_delete(convd);
+
+
+ return EXIT_SUCCESS;
+}
diff --git a/ext/mbstring/mb_gpc.c b/ext/mbstring/mb_gpc.c
index dd60302d03..0797b893d3 100644
--- a/ext/mbstring/mb_gpc.c
+++ b/ext/mbstring/mb_gpc.c
@@ -27,6 +27,7 @@
#include "php.h"
#include "php_ini.h"
#include "php_variables.h"
+#include "libmbfl/mbfl/mbfilter_pass.h"
#include "mbstring.h"
#include "ext/standard/php_string.h"
#include "ext/standard/php_mail.h"
@@ -56,11 +57,11 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
const char *c_var;
zval *array_ptr;
int free_buffer=0;
- enum mbfl_no_encoding detected;
+ const mbfl_encoding *detected;
php_mb_encoding_handler_info_t info;
if (arg != PARSE_STRING) {
- char *value = zend_ini_string("mbstring.internal_encoding", sizeof("mbstring.internal_encoding"), 0);
+ char *value = MBSTRG(internal_encoding_name);
_php_mb_ini_mbstring_internal_encoding_set(value, value ? strlen(value): 0 TSRMLS_CC);
}
@@ -136,22 +137,21 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
switch(arg) {
case PARSE_POST:
- MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid;
+ MBSTRG(http_input_identify_post) = NULL;
break;
case PARSE_GET:
- MBSTRG(http_input_identify_get) = mbfl_no_encoding_invalid;
+ MBSTRG(http_input_identify_get) = NULL;
break;
case PARSE_COOKIE:
- MBSTRG(http_input_identify_cookie) = mbfl_no_encoding_invalid;
+ MBSTRG(http_input_identify_cookie) = NULL;
break;
case PARSE_STRING:
- MBSTRG(http_input_identify_string) = mbfl_no_encoding_invalid;
+ MBSTRG(http_input_identify_string) = NULL;
break;
}
info.data_type = arg;
info.separator = separator;
- info.force_register_globals = 0;
info.report_errors = 0;
info.to_encoding = MBSTRG(internal_encoding);
info.to_language = MBSTRG(language);
@@ -164,7 +164,7 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
detected = _php_mb_encoding_handler_ex(&info, array_ptr, res TSRMLS_CC);
MBSTRG(http_input_identify) = detected;
- if (detected != mbfl_no_encoding_invalid) {
+ if (detected) {
switch(arg){
case PARSE_POST:
MBSTRG(http_input_identify_post) = detected;
@@ -192,7 +192,7 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
/* }}} */
/* {{{ mbfl_no_encoding _php_mb_encoding_handler_ex() */
-enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC)
+const mbfl_encoding *_php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC)
{
char *var, *val;
const char *s1, *s2;
@@ -201,21 +201,13 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
int n, num, *len_list = NULL;
unsigned int val_len, new_val_len;
mbfl_string string, resvar, resval;
- enum mbfl_no_encoding from_encoding = mbfl_no_encoding_invalid;
+ const mbfl_encoding *from_encoding = NULL;
mbfl_encoding_detector *identd = NULL;
mbfl_buffer_converter *convd = NULL;
- int prev_rg_state = 0;
- mbfl_string_init_set(&string, info->to_language, info->to_encoding);
- mbfl_string_init_set(&resvar, info->to_language, info->to_encoding);
- mbfl_string_init_set(&resval, info->to_language, info->to_encoding);
-
- /* register_globals stuff
- * XXX: this feature is going to be deprecated? */
-
- if (info->force_register_globals && !(prev_rg_state = PG(register_globals))) {
- zend_alter_ini_entry("register_globals", sizeof("register_globals"), "1", sizeof("1")-1, PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME);
- }
+ mbfl_string_init_set(&string, info->to_language, info->to_encoding->no_encoding);
+ mbfl_string_init_set(&resvar, info->to_language, info->to_encoding->no_encoding);
+ mbfl_string_init_set(&resval, info->to_language, info->to_encoding->no_encoding);
if (!res || *res == '\0') {
goto out;
@@ -266,14 +258,14 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
/* initialize converter */
if (info->num_from_encodings <= 0) {
- from_encoding = mbfl_no_encoding_pass;
+ from_encoding = &mbfl_encoding_pass;
} else if (info->num_from_encodings == 1) {
from_encoding = info->from_encodings[0];
} else {
/* auto detect */
- from_encoding = mbfl_no_encoding_invalid;
- identd = mbfl_encoding_detector_new((enum mbfl_no_encoding *)info->from_encodings, info->num_from_encodings, MBSTRG(strict_detection));
- if (identd) {
+ from_encoding = NULL;
+ identd = mbfl_encoding_detector_new2(info->from_encodings, info->num_from_encodings, MBSTRG(strict_detection));
+ if (identd != NULL) {
n = 0;
while (n < num) {
string.val = (unsigned char *)val_list[n];
@@ -283,20 +275,20 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
}
n++;
}
- from_encoding = mbfl_encoding_detector_judge(identd);
+ from_encoding = mbfl_encoding_detector_judge2(identd);
mbfl_encoding_detector_delete(identd);
}
- if (from_encoding == mbfl_no_encoding_invalid) {
+ if (!from_encoding) {
if (info->report_errors) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding");
}
- from_encoding = mbfl_no_encoding_pass;
+ from_encoding = &mbfl_encoding_pass;
}
}
convd = NULL;
- if (from_encoding != mbfl_no_encoding_pass) {
- convd = mbfl_buffer_converter_new(from_encoding, info->to_encoding, 0);
+ if (from_encoding != &mbfl_encoding_pass) {
+ convd = mbfl_buffer_converter_new2(from_encoding, info->to_encoding, 0);
if (convd != NULL) {
mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
@@ -309,7 +301,7 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
}
/* convert encoding */
- string.no_encoding = from_encoding;
+ string.no_encoding = from_encoding->no_encoding;
n = 0;
while (n < num) {
@@ -321,10 +313,10 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
var = val_list[n];
}
n++;
- string.val = val_list[n];
+ string.val = (unsigned char *)val_list[n];
string.len = len_list[n];
if (convd != NULL && mbfl_buffer_converter_feed_result(convd, &string, &resval) != NULL) {
- val = resval.val;
+ val = (char *)resval.val;
val_len = resval.len;
} else {
val = val_list[n];
@@ -346,11 +338,6 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
}
out:
- /* register_global stuff */
- if (info->force_register_globals && !prev_rg_state) {
- zend_alter_ini_entry("register_globals", sizeof("register_globals"), "0", sizeof("0")-1, PHP_INI_PERDIR, PHP_INI_STAGE_RUNTIME);
- }
-
if (convd != NULL) {
MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
mbfl_buffer_converter_delete(convd);
@@ -369,14 +356,13 @@ out:
/* {{{ SAPI_POST_HANDLER_FUNC(php_mb_post_handler) */
SAPI_POST_HANDLER_FUNC(php_mb_post_handler)
{
- enum mbfl_no_encoding detected;
+ const mbfl_encoding *detected;
php_mb_encoding_handler_info_t info;
- MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid;
+ MBSTRG(http_input_identify_post) = NULL;
info.data_type = PARSE_POST;
info.separator = "&";
- info.force_register_globals = 0;
info.report_errors = 0;
info.to_encoding = MBSTRG(internal_encoding);
info.to_language = MBSTRG(language);
@@ -387,7 +373,7 @@ SAPI_POST_HANDLER_FUNC(php_mb_post_handler)
detected = _php_mb_encoding_handler_ex(&info, arg, SG(request_info).post_data TSRMLS_CC);
MBSTRG(http_input_identify) = detected;
- if (detected != mbfl_no_encoding_invalid) {
+ if (detected) {
MBSTRG(http_input_identify_post) = detected;
}
}
diff --git a/ext/mbstring/mb_gpc.h b/ext/mbstring/mb_gpc.h
index 593b413253..ab6fcc86e0 100644
--- a/ext/mbstring/mb_gpc.h
+++ b/ext/mbstring/mb_gpc.h
@@ -32,13 +32,12 @@
typedef struct _php_mb_encoding_handler_info_t {
int data_type;
const char *separator;
- unsigned int force_register_globals: 1;
unsigned int report_errors: 1;
enum mbfl_no_language to_language;
- enum mbfl_no_encoding to_encoding;
+ const mbfl_encoding *to_encoding;
enum mbfl_no_language from_language;
- int num_from_encodings;
- const enum mbfl_no_encoding *from_encodings;
+ const mbfl_encoding **from_encodings;
+ size_t num_from_encodings;
} php_mb_encoding_handler_info_t;
/* }}}*/
@@ -48,7 +47,7 @@ SAPI_POST_HANDLER_FUNC(php_mb_post_handler);
MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data);
int _php_mb_enable_encoding_translation(int flag);
-enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC);
+const mbfl_encoding *_php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC);
/* }}} */
#endif /* HAVE_MBSTRING */
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index 3d55074acc..76654edbf8 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -62,6 +62,7 @@
#include "ext/standard/info.h"
#include "libmbfl/mbfl/mbfl_allocators.h"
+#include "libmbfl/mbfl/mbfilter_pass.h"
#include "php_variables.h"
#include "php_globals.h"
@@ -77,9 +78,7 @@
#include "php_mbregex.h"
#endif
-#ifdef ZEND_MULTIBYTE
#include "zend_multibyte.h"
-#endif /* ZEND_MULTIBYTE */
#if HAVE_ONIG
#include "php_onig_compat.h"
@@ -98,19 +97,21 @@ ZEND_DECLARE_MODULE_GLOBALS(mbstring)
static PHP_GINIT_FUNCTION(mbstring);
static PHP_GSHUTDOWN_FUNCTION(mbstring);
-#ifdef ZEND_MULTIBYTE
-static size_t php_mb_oddlen(const unsigned char *string, size_t length, const char *encoding TSRMLS_DC);
-static int php_mb_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const char *encoding_to, const char *encoding_from TSRMLS_DC);
-static char* php_mb_encoding_detector(const unsigned char *arg_string, size_t arg_length, char *arg_list TSRMLS_DC);
-static int php_mb_set_zend_encoding(TSRMLS_D);
-#endif
+static void php_mb_populate_current_detect_order_list(TSRMLS_D);
+
+static int php_mb_encoding_translation(TSRMLS_D);
+
+static void php_mb_gpc_get_detect_order(const zend_encoding ***list, size_t *list_size TSRMLS_DC);
+
+static void php_mb_gpc_set_input_encoding(const zend_encoding *encoding TSRMLS_DC);
+
/* }}} */
/* {{{ php_mb_default_identify_list */
typedef struct _php_mb_nls_ident_list {
enum mbfl_no_language lang;
- const enum mbfl_no_encoding* list;
- int list_size;
+ const enum mbfl_no_encoding *list;
+ size_t list_size;
} php_mb_nls_ident_list;
static const enum mbfl_no_encoding php_mb_default_identify_list_ja[] = {
@@ -411,6 +412,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_encode_numericentity, 0, 0, 2)
ZEND_ARG_INFO(0, string)
ZEND_ARG_INFO(0, convmap)
ZEND_ARG_INFO(0, encoding)
+ ZEND_ARG_INFO(0, is_hex)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_decode_numericentity, 0, 0, 2)
@@ -465,6 +467,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_eregi_replace, 0, 0, 3)
ZEND_ARG_INFO(0, string)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_replace_callback, 0, 0, 3)
+ ZEND_ARG_INFO(0, pattern)
+ ZEND_ARG_INFO(0, callback)
+ ZEND_ARG_INFO(0, string)
+ ZEND_ARG_INFO(0, option)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_split, 0, 0, 2)
ZEND_ARG_INFO(0, pattern)
ZEND_ARG_INFO(0, string)
@@ -563,7 +572,7 @@ const zend_function_entry mbstring_functions[] = {
/* {{{ zend_module_entry mbstring_module_entry */
zend_module_entry mbstring_module_entry = {
- STANDARD_MODULE_HEADER,
+ STANDARD_MODULE_HEADER,
"mbstring",
mbstring_functions,
PHP_MINIT(mbstring),
@@ -571,11 +580,11 @@ zend_module_entry mbstring_module_entry = {
PHP_RINIT(mbstring),
PHP_RSHUTDOWN(mbstring),
PHP_MINFO(mbstring),
- NO_VERSION_YET,
- PHP_MODULE_GLOBALS(mbstring),
- PHP_GINIT(mbstring),
- PHP_GSHUTDOWN(mbstring),
- NULL,
+ NO_VERSION_YET,
+ PHP_MODULE_GLOBALS(mbstring),
+ PHP_GINIT(mbstring),
+ PHP_GSHUTDOWN(mbstring),
+ NULL,
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
@@ -653,12 +662,12 @@ static sapi_post_entry mbstr_post_entries[] = {
* of parsed encodings.
*/
static int
-php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_encoding **return_list, int *return_size, int persistent TSRMLS_DC)
+php_mb_parse_encoding_list(const char *value, size_t value_length, const mbfl_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
{
- int n, l, size, bauto, ret = 1;
+ int size, bauto, ret = SUCCESS;
+ size_t n;
char *p, *p1, *p2, *endp, *tmpstr;
- enum mbfl_no_encoding no_encoding;
- enum mbfl_no_encoding *src, *entry, *list;
+ const mbfl_encoding **entry, **list;
list = NULL;
if (value == NULL || value_length <= 0) {
@@ -668,14 +677,8 @@ php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_enc
if (return_size) {
*return_size = 0;
}
- return 0;
+ return FAILURE;
} else {
- enum mbfl_no_encoding *identify_list;
- int identify_list_size;
-
- identify_list = MBSTRG(default_detect_order_list);
- identify_list_size = MBSTRG(default_detect_order_list_size);
-
/* copy the value string for work */
if (value[0]=='"' && value[value_length-1]=='"' && value_length>2) {
tmpstr = (char *)estrndup(value+1, value_length-2);
@@ -684,7 +687,7 @@ php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_enc
else
tmpstr = (char *)estrndup(value, value_length);
if (tmpstr == NULL) {
- return 0;
+ return FAILURE;
}
/* count the number of listed encoding names */
endp = tmpstr + value_length;
@@ -694,9 +697,9 @@ php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_enc
p1 = p2 + 1;
n++;
}
- size = n + identify_list_size;
+ size = n + MBSTRG(default_detect_order_list_size);
/* make list */
- list = (enum mbfl_no_encoding *)pecalloc(size, sizeof(int), persistent);
+ list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
if (list != NULL) {
entry = list;
n = 0;
@@ -720,19 +723,19 @@ php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_enc
/* convert to the encoding number and check encoding */
if (strcasecmp(p1, "auto") == 0) {
if (!bauto) {
+ const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
+ const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
+ size_t i;
bauto = 1;
- l = identify_list_size;
- src = identify_list;
- while (l > 0) {
- *entry++ = *src++;
- l--;
+ for (i = 0; i < identify_list_size; i++) {
+ *entry++ = mbfl_no2encoding(*src++);
n++;
}
}
} else {
- no_encoding = mbfl_name2no_encoding(p1);
- if (no_encoding != mbfl_no_encoding_invalid) {
- *entry++ = no_encoding;
+ const mbfl_encoding *encoding = mbfl_name2encoding(p1);
+ if (encoding) {
+ *entry++ = encoding;
n++;
} else {
ret = 0;
@@ -772,39 +775,26 @@ php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_enc
}
/* }}} */
-/* {{{ MBSTRING_API php_mb_check_encoding_list */
-MBSTRING_API int php_mb_check_encoding_list(const char *encoding_list TSRMLS_DC) {
- return php_mb_parse_encoding_list(encoding_list, strlen(encoding_list), NULL, NULL, 0 TSRMLS_CC);
-}
-/* }}} */
-
/* {{{ static int php_mb_parse_encoding_array()
* Return 0 if input contains any illegal encoding, otherwise 1.
* Even if any illegal encoding is detected the result may contain a list
* of parsed encodings.
*/
static int
-php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, int *return_size, int persistent TSRMLS_DC)
+php_mb_parse_encoding_array(zval *array, const mbfl_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
{
zval **hash_entry;
HashTable *target_hash;
- int i, n, l, size, bauto,ret = 1;
- enum mbfl_no_encoding no_encoding;
- enum mbfl_no_encoding *src, *list, *entry;
+ int i, n, size, bauto, ret = SUCCESS;
+ const mbfl_encoding **list, **entry;
list = NULL;
if (Z_TYPE_P(array) == IS_ARRAY) {
- enum mbfl_no_encoding *identify_list;
- int identify_list_size;
-
- identify_list = MBSTRG(default_detect_order_list);
- identify_list_size = MBSTRG(default_detect_order_list_size);
-
target_hash = Z_ARRVAL_P(array);
zend_hash_internal_pointer_reset(target_hash);
i = zend_hash_num_elements(target_hash);
- size = i + identify_list_size;
- list = (enum mbfl_no_encoding *)pecalloc(size, sizeof(int), persistent);
+ size = i + MBSTRG(default_detect_order_list_size);
+ list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
if (list != NULL) {
entry = list;
bauto = 0;
@@ -816,22 +806,23 @@ php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, in
convert_to_string_ex(hash_entry);
if (strcasecmp(Z_STRVAL_PP(hash_entry), "auto") == 0) {
if (!bauto) {
+ const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
+ const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
+ size_t j;
+
bauto = 1;
- l = identify_list_size;
- src = identify_list;
- while (l > 0) {
- *entry++ = *src++;
- l--;
+ for (j = 0; j < identify_list_size; j++) {
+ *entry++ = mbfl_no2encoding(*src++);
n++;
}
}
} else {
- no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(hash_entry));
- if (no_encoding != mbfl_no_encoding_invalid) {
- *entry++ = no_encoding;
+ const mbfl_encoding *encoding = mbfl_name2encoding(Z_STRVAL_PP(hash_entry));
+ if (encoding) {
+ *entry++ = encoding;
n++;
} else {
- ret = 0;
+ ret = FAILURE;
}
}
zend_hash_move_forward(target_hash);
@@ -848,7 +839,7 @@ php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, in
if (return_list) {
*return_list = NULL;
}
- ret = 0;
+ ret = FAILURE;
}
if (return_size) {
*return_size = n;
@@ -860,7 +851,7 @@ php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, in
if (return_size) {
*return_size = 0;
}
- ret = 0;
+ ret = FAILURE;
}
}
@@ -868,6 +859,118 @@ php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, in
}
/* }}} */
+/* {{{ zend_multibyte interface */
+static const zend_encoding* php_mb_zend_encoding_fetcher(const char *encoding_name TSRMLS_DC)
+{
+ return (const zend_encoding*)mbfl_name2encoding(encoding_name);
+}
+
+static const char *php_mb_zend_encoding_name_getter(const zend_encoding *encoding)
+{
+ return ((const mbfl_encoding *)encoding)->name;
+}
+
+static int php_mb_zend_encoding_lexer_compatibility_checker(const zend_encoding *_encoding)
+{
+ const mbfl_encoding *encoding = (const mbfl_encoding*)_encoding;
+ if (encoding->flag & MBFL_ENCTYPE_SBCS) {
+ return 1;
+ }
+ if ((encoding->flag & (MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE)) == MBFL_ENCTYPE_MBCS) {
+ return 1;
+ }
+ return 0;
+}
+
+static const zend_encoding *php_mb_zend_encoding_detector(const unsigned char *arg_string, size_t arg_length, const zend_encoding **list, size_t list_size TSRMLS_DC)
+{
+ mbfl_string string;
+
+ if (!list) {
+ list = (const zend_encoding **)MBSTRG(current_detect_order_list);
+ list_size = MBSTRG(current_detect_order_list_size);
+ }
+
+ mbfl_string_init(&string);
+ string.no_language = MBSTRG(language);
+ string.val = (unsigned char *)arg_string;
+ string.len = arg_length;
+ return (const zend_encoding *) mbfl_identify_encoding2(&string, (const mbfl_encoding **)list, list_size, 0);
+}
+
+static size_t php_mb_zend_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from TSRMLS_DC)
+{
+ mbfl_string string, result;
+ mbfl_buffer_converter *convd;
+ int status, loc;
+
+ /* new encoding */
+ /* initialize string */
+ mbfl_string_init(&string);
+ mbfl_string_init(&result);
+ string.no_encoding = ((const mbfl_encoding*)encoding_from)->no_encoding;
+ string.no_language = MBSTRG(language);
+ string.val = (unsigned char*)from;
+ string.len = from_length;
+
+ /* initialize converter */
+ convd = mbfl_buffer_converter_new2((const mbfl_encoding *)encoding_from, (const mbfl_encoding *)encoding_to, string.len);
+ if (convd == NULL) {
+ return -1;
+ }
+ mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
+ mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
+
+ /* do it */
+ status = mbfl_buffer_converter_feed2(convd, &string, &loc);
+ if (status) {
+ mbfl_buffer_converter_delete(convd);
+ return (size_t)-1;
+ }
+
+ mbfl_buffer_converter_flush(convd);
+ if (!mbfl_buffer_converter_result(convd, &result)) {
+ mbfl_buffer_converter_delete(convd);
+ return (size_t)-1;
+ }
+
+ *to = result.val;
+ *to_length = result.len;
+
+ mbfl_buffer_converter_delete(convd);
+
+ return loc;
+}
+
+static int php_mb_zend_encoding_list_parser(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
+{
+ return php_mb_parse_encoding_list(encoding_list, encoding_list_len, (const mbfl_encoding ***)return_list, return_size, persistent TSRMLS_CC);
+}
+
+static const zend_encoding *php_mb_zend_internal_encoding_getter(TSRMLS_D)
+{
+ return (const zend_encoding *)MBSTRG(internal_encoding);
+}
+
+static int php_mb_zend_internal_encoding_setter(const zend_encoding *encoding TSRMLS_DC)
+{
+ MBSTRG(internal_encoding) = (const mbfl_encoding *)encoding;
+ return SUCCESS;
+}
+
+static zend_multibyte_functions php_mb_zend_multibyte_functions = {
+ "mbstring",
+ php_mb_zend_encoding_fetcher,
+ php_mb_zend_encoding_name_getter,
+ php_mb_zend_encoding_lexer_compatibility_checker,
+ php_mb_zend_encoding_detector,
+ php_mb_zend_encoding_converter,
+ php_mb_zend_encoding_list_parser,
+ php_mb_zend_internal_encoding_getter,
+ php_mb_zend_internal_encoding_setter
+};
+/* }}} */
+
static void *_php_mb_compile_regex(const char *pattern TSRMLS_DC);
static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len);
static void _php_mb_free_regex(void *opaque);
@@ -942,7 +1045,7 @@ static void _php_mb_free_regex(void *opaque)
#endif
/* {{{ php_mb_nls_get_default_detect_order_list */
-static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, enum mbfl_no_encoding **plist, int* plist_size)
+static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, enum mbfl_no_encoding **plist, size_t *plist_size)
{
size_t i;
@@ -960,6 +1063,124 @@ static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang,
}
/* }}} */
+static char *php_mb_rfc1867_substring_conf(const zend_encoding *encoding, char *start, int len, char quote TSRMLS_DC)
+{
+ char *result = emalloc(len + 2);
+ char *resp = result;
+ int i;
+
+ for (i = 0; i < len && start[i] != quote; ++i) {
+ if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
+ *resp++ = start[++i];
+ } else {
+ size_t j = php_mb_mbchar_bytes_ex(start+i, (const mbfl_encoding *)encoding);
+
+ while (j-- > 0 && i < len) {
+ *resp++ = start[i++];
+ }
+ --i;
+ }
+ }
+
+ *resp = '\0';
+ return result;
+}
+
+static char *php_mb_rfc1867_getword(const zend_encoding *encoding, char **line, char stop TSRMLS_DC) /* {{{ */
+{
+ char *pos = *line, quote;
+ char *res;
+
+ while (*pos && *pos != stop) {
+ if ((quote = *pos) == '"' || quote == '\'') {
+ ++pos;
+ while (*pos && *pos != quote) {
+ if (*pos == '\\' && pos[1] && pos[1] == quote) {
+ pos += 2;
+ } else {
+ ++pos;
+ }
+ }
+ if (*pos) {
+ ++pos;
+ }
+ } else {
+ pos += php_mb_mbchar_bytes_ex(pos, (const mbfl_encoding *)encoding);
+
+ }
+ }
+ if (*pos == '\0') {
+ res = estrdup(*line);
+ *line += strlen(*line);
+ return res;
+ }
+
+ res = estrndup(*line, pos - *line);
+
+ while (*pos == stop) {
+ pos += php_mb_mbchar_bytes_ex(pos, (const mbfl_encoding *)encoding);
+ }
+
+ *line = pos;
+ return res;
+}
+/* }}} */
+
+static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *str TSRMLS_DC) /* {{{ */
+{
+ while (*str && isspace(*(unsigned char *)str)) {
+ ++str;
+ }
+
+ if (!*str) {
+ return estrdup("");
+ }
+
+ if (*str == '"' || *str == '\'') {
+ char quote = *str;
+
+ str++;
+ return php_mb_rfc1867_substring_conf(encoding, str, strlen(str), quote TSRMLS_CC);
+ } else {
+ char *strend = str;
+
+ while (*strend && !isspace(*(unsigned char *)strend)) {
+ ++strend;
+ }
+ return php_mb_rfc1867_substring_conf(encoding, str, strend - str, 0 TSRMLS_CC);
+ }
+}
+/* }}} */
+
+static char *php_mb_rfc1867_basename(const zend_encoding *encoding, char *filename TSRMLS_DC) /* {{{ */
+{
+ char *s, *s2;
+ const size_t filename_len = strlen(filename);
+
+ /* The \ check should technically be needed for win32 systems only where
+ * it is a valid path separator. However, IE in all it's wisdom always sends
+ * the full path of the file on the user's filesystem, which means that unless
+ * the user does basename() they get a bogus file name. Until IE's user base drops
+ * to nill or problem is fixed this code must remain enabled for all systems. */
+ s = php_mb_safe_strrchr_ex(filename, '\\', filename_len, (const mbfl_encoding *)encoding);
+ s2 = php_mb_safe_strrchr_ex(filename, '/', filename_len, (const mbfl_encoding *)encoding);
+
+ if (s && s2) {
+ if (s > s2) {
+ return ++s;
+ } else {
+ return ++s2;
+ }
+ } else if (s) {
+ return ++s;
+ } else if (s2) {
+ return ++s2;
+ } else {
+ return filename;
+ }
+}
+/* }}} */
+
/* {{{ php.ini directive handler */
/* {{{ static PHP_INI_MH(OnUpdate_mbstring_language) */
static PHP_INI_MH(OnUpdate_mbstring_language)
@@ -980,23 +1201,27 @@ static PHP_INI_MH(OnUpdate_mbstring_language)
/* {{{ static PHP_INI_MH(OnUpdate_mbstring_detect_order) */
static PHP_INI_MH(OnUpdate_mbstring_detect_order)
{
- enum mbfl_no_encoding *list;
- int size;
+ const mbfl_encoding **list;
+ size_t size;
- if (php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
- if (MBSTRG(detect_order_list)) {
- free(MBSTRG(detect_order_list));
- }
- MBSTRG(detect_order_list) = list;
- MBSTRG(detect_order_list_size) = size;
- } else {
+ if (!new_value) {
if (MBSTRG(detect_order_list)) {
- free(MBSTRG(detect_order_list));
- MBSTRG(detect_order_list) = NULL;
+ pefree(MBSTRG(detect_order_list), 1);
}
+ MBSTRG(detect_order_list) = NULL;
+ MBSTRG(detect_order_list_size) = 0;
+ return SUCCESS;
+ }
+
+ if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
return FAILURE;
}
+ if (MBSTRG(detect_order_list)) {
+ pefree(MBSTRG(detect_order_list), 1);
+ }
+ MBSTRG(detect_order_list) = list;
+ MBSTRG(detect_order_list_size) = size;
return SUCCESS;
}
/* }}} */
@@ -1004,24 +1229,28 @@ static PHP_INI_MH(OnUpdate_mbstring_detect_order)
/* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_input) */
static PHP_INI_MH(OnUpdate_mbstring_http_input)
{
- enum mbfl_no_encoding *list;
- int size;
+ const mbfl_encoding **list;
+ size_t size;
- if (php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
- if (MBSTRG(http_input_list)) {
- free(MBSTRG(http_input_list));
- }
- MBSTRG(http_input_list) = list;
- MBSTRG(http_input_list_size) = size;
- } else {
+ if (!new_value) {
if (MBSTRG(http_input_list)) {
- free(MBSTRG(http_input_list));
- MBSTRG(http_input_list) = NULL;
+ pefree(MBSTRG(http_input_list), 1);
}
+ MBSTRG(http_input_list) = NULL;
MBSTRG(http_input_list_size) = 0;
+ return SUCCESS;
+ }
+
+ if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
return FAILURE;
}
+ if (MBSTRG(http_input_list)) {
+ pefree(MBSTRG(http_input_list), 1);
+ }
+ MBSTRG(http_input_list) = list;
+ MBSTRG(http_input_list_size) = size;
+
return SUCCESS;
}
/* }}} */
@@ -1029,20 +1258,23 @@ static PHP_INI_MH(OnUpdate_mbstring_http_input)
/* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output) */
static PHP_INI_MH(OnUpdate_mbstring_http_output)
{
- enum mbfl_no_encoding no_encoding;
+ const mbfl_encoding *encoding;
- no_encoding = mbfl_name2no_encoding(new_value);
- if (no_encoding != mbfl_no_encoding_invalid) {
- MBSTRG(http_output_encoding) = no_encoding;
- MBSTRG(current_http_output_encoding) = no_encoding;
- } else {
- MBSTRG(http_output_encoding) = mbfl_no_encoding_pass;
- MBSTRG(current_http_output_encoding) = mbfl_no_encoding_pass;
- if (new_value != NULL && new_value_length > 0) {
- return FAILURE;
- }
+ if (new_value == NULL || new_value_length == 0) {
+ MBSTRG(http_output_encoding) = &mbfl_encoding_pass;
+ MBSTRG(current_http_output_encoding) = &mbfl_encoding_pass;
+ return SUCCESS;
+ }
+
+ encoding = mbfl_name2encoding(new_value);
+ if (!encoding) {
+ MBSTRG(http_output_encoding) = &mbfl_encoding_pass;
+ MBSTRG(current_http_output_encoding) = &mbfl_encoding_pass;
+ return FAILURE;
}
+ MBSTRG(http_output_encoding) = encoding;
+ MBSTRG(current_http_output_encoding) = encoding;
return SUCCESS;
}
/* }}} */
@@ -1050,62 +1282,44 @@ static PHP_INI_MH(OnUpdate_mbstring_http_output)
/* {{{ static _php_mb_ini_mbstring_internal_encoding_set */
int _php_mb_ini_mbstring_internal_encoding_set(const char *new_value, uint new_value_length TSRMLS_DC)
{
- enum mbfl_no_encoding no_encoding;
- const char *enc_name = NULL;
- uint enc_name_len = 0;
-
- no_encoding = new_value ? mbfl_name2no_encoding(new_value):
- mbfl_no_encoding_invalid;
- if (no_encoding != mbfl_no_encoding_invalid) {
- enc_name = new_value;
- enc_name_len = new_value_length;
- } else {
+ const mbfl_encoding *encoding;
+
+ if (!new_value || new_value_length == 0 || !(encoding = mbfl_name2encoding(new_value))) {
switch (MBSTRG(language)) {
case mbfl_no_language_uni:
- enc_name = "UTF-8";
- enc_name_len = sizeof("UTF-8") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_utf8);
break;
case mbfl_no_language_japanese:
- enc_name = "EUC-JP";
- enc_name_len = sizeof("EUC-JP") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_euc_jp);
break;
case mbfl_no_language_korean:
- enc_name = "EUC-KR";
- enc_name_len = sizeof("EUC-KR") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_euc_kr);
break;
case mbfl_no_language_simplified_chinese:
- enc_name = "EUC-CN";
- enc_name_len = sizeof("EUC-CN") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_euc_cn);
break;
case mbfl_no_language_traditional_chinese:
- enc_name = "EUC-TW";
- enc_name_len = sizeof("EUC-TW") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_euc_tw);
break;
case mbfl_no_language_russian:
- enc_name = "KOI8-R";
- enc_name_len = sizeof("KOI8-R") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_koi8r);
break;
case mbfl_no_language_german:
- enc_name = "ISO-8859-15";
- enc_name_len = sizeof("ISO-8859-15") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_8859_15);
break;
case mbfl_no_language_armenian:
- enc_name = "ArmSCII-8";
- enc_name_len = sizeof("ArmSCII-8") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_armscii8);
break;
case mbfl_no_language_turkish:
- enc_name = "ISO-8859-9";
- enc_name_len = sizeof("ISO-8859-9") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_8859_9);
break;
default:
- enc_name = "ISO-8859-1";
- enc_name_len = sizeof("ISO-8859-1") - 1;
+ encoding = mbfl_no2encoding(mbfl_no_encoding_8859_1);
break;
}
- no_encoding = mbfl_name2no_encoding(enc_name);
}
- MBSTRG(internal_encoding) = no_encoding;
- MBSTRG(current_internal_encoding) = no_encoding;
+ MBSTRG(internal_encoding) = encoding;
+ MBSTRG(current_internal_encoding) = encoding;
#if HAVE_MBREGEX
{
const char *enc_name = new_value;
@@ -1124,6 +1338,9 @@ int _php_mb_ini_mbstring_internal_encoding_set(const char *new_value, uint new_v
/* {{{ static PHP_INI_MH(OnUpdate_mbstring_internal_encoding) */
static PHP_INI_MH(OnUpdate_mbstring_internal_encoding)
{
+ if (OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN
|| stage == PHP_INI_STAGE_RUNTIME) {
return _php_mb_ini_mbstring_internal_encoding_set(new_value, new_value_length TSRMLS_CC);
@@ -1139,32 +1356,6 @@ static PHP_INI_MH(OnUpdate_mbstring_internal_encoding)
}
/* }}} */
-#ifdef ZEND_MULTIBYTE
-/* {{{ static PHP_INI_MH(OnUpdate_mbstring_script_encoding) */
-static PHP_INI_MH(OnUpdate_mbstring_script_encoding)
-{
- int *list, size;
-
- if (php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
- if (MBSTRG(script_encoding_list) != NULL) {
- free(MBSTRG(script_encoding_list));
- }
- MBSTRG(script_encoding_list) = list;
- MBSTRG(script_encoding_list_size) = size;
- } else {
- if (MBSTRG(script_encoding_list) != NULL) {
- free(MBSTRG(script_encoding_list));
- }
- MBSTRG(script_encoding_list) = NULL;
- MBSTRG(script_encoding_list_size) = 0;
- return FAILURE;
- }
-
- return SUCCESS;
-}
-/* }}} */
-#endif /* ZEND_MULTIBYTE */
-
/* {{{ static PHP_INI_MH(OnUpdate_mbstring_substitute_character) */
static PHP_INI_MH(OnUpdate_mbstring_substitute_character)
{
@@ -1207,7 +1398,7 @@ static PHP_INI_MH(OnUpdate_mbstring_substitute_character)
static PHP_INI_MH(OnUpdate_mbstring_encoding_translation)
{
if (new_value == NULL) {
- return FAILURE;
+ return FAILURE;
}
OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
@@ -1261,10 +1452,7 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("mbstring.detect_order", NULL, PHP_INI_ALL, OnUpdate_mbstring_detect_order)
PHP_INI_ENTRY("mbstring.http_input", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_input)
PHP_INI_ENTRY("mbstring.http_output", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_output)
- PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding)
-#ifdef ZEND_MULTIBYTE
- PHP_INI_ENTRY("mbstring.script_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_script_encoding)
-#endif /* ZEND_MULTIBYTE */
+ STD_PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding, internal_encoding_name, zend_mbstring_globals, mbstring_globals)
PHP_INI_ENTRY("mbstring.substitute_character", NULL, PHP_INI_ALL, OnUpdate_mbstring_substitute_character)
STD_PHP_INI_ENTRY("mbstring.func_overload", "0",
PHP_INI_SYSTEM, OnUpdateLong, func_overload, zend_mbstring_globals, mbstring_globals)
@@ -1289,19 +1477,15 @@ PHP_INI_END()
static PHP_GINIT_FUNCTION(mbstring)
{
mbstring_globals->language = mbfl_no_language_uni;
- mbstring_globals->internal_encoding = mbfl_no_encoding_invalid;
+ mbstring_globals->internal_encoding = NULL;
mbstring_globals->current_internal_encoding = mbstring_globals->internal_encoding;
-#ifdef ZEND_MULTIBYTE
- mbstring_globals->script_encoding_list = NULL;
- mbstring_globals->script_encoding_list_size = 0;
-#endif /* ZEND_MULTIBYTE */
- mbstring_globals->http_output_encoding = mbfl_no_encoding_pass;
- mbstring_globals->current_http_output_encoding = mbfl_no_encoding_pass;
- mbstring_globals->http_input_identify = mbfl_no_encoding_invalid;
- mbstring_globals->http_input_identify_get = mbfl_no_encoding_invalid;
- mbstring_globals->http_input_identify_post = mbfl_no_encoding_invalid;
- mbstring_globals->http_input_identify_cookie = mbfl_no_encoding_invalid;
- mbstring_globals->http_input_identify_string = mbfl_no_encoding_invalid;
+ mbstring_globals->http_output_encoding = &mbfl_encoding_pass;
+ mbstring_globals->current_http_output_encoding = &mbfl_encoding_pass;
+ mbstring_globals->http_input_identify = NULL;
+ mbstring_globals->http_input_identify_get = NULL;
+ mbstring_globals->http_input_identify_post = NULL;
+ mbstring_globals->http_input_identify_cookie = NULL;
+ mbstring_globals->http_input_identify_string = NULL;
mbstring_globals->http_input_list = NULL;
mbstring_globals->http_input_list_size = 0;
mbstring_globals->detect_order_list = NULL;
@@ -1332,11 +1516,6 @@ static PHP_GSHUTDOWN_FUNCTION(mbstring)
if (mbstring_globals->http_input_list) {
free(mbstring_globals->http_input_list);
}
-#ifdef ZEND_MULTIBYTE
- if (mbstring_globals->script_encoding_list) {
- free(mbstring_globals->script_encoding_list);
- }
-#endif /* ZEND_MULTIBYTE */
if (mbstring_globals->detect_order_list) {
free(mbstring_globals->detect_order_list);
}
@@ -1357,7 +1536,7 @@ PHP_MINIT_FUNCTION(mbstring)
REGISTER_INI_ENTRIES();
/* This is a global handler. Should not be set in a per-request handler. */
- sapi_register_treat_data(mbstr_treat_data);
+ sapi_register_treat_data(mbstr_treat_data TSRMLS_CC);
/* Post handlers are stored in the thread-local context. */
if (MBSTRG(encoding_translation)) {
@@ -1375,6 +1554,19 @@ PHP_MINIT_FUNCTION(mbstring)
#if HAVE_MBREGEX
PHP_MINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
#endif
+
+ if (FAILURE == zend_multibyte_set_functions(&php_mb_zend_multibyte_functions TSRMLS_CC)) {
+ return FAILURE;
+ }
+
+ php_rfc1867_set_multibyte_callbacks(
+ php_mb_encoding_translation,
+ php_mb_gpc_get_detect_order,
+ php_mb_gpc_set_input_encoding,
+ php_mb_rfc1867_getword,
+ php_mb_rfc1867_getword_conf,
+ php_mb_rfc1867_basename);
+
return SUCCESS;
}
/* }}} */
@@ -1383,7 +1575,7 @@ PHP_MINIT_FUNCTION(mbstring)
PHP_MSHUTDOWN_FUNCTION(mbstring)
{
UNREGISTER_INI_ENTRIES();
-
+
#if HAVE_MBREGEX
PHP_MSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
#endif
@@ -1395,8 +1587,6 @@ PHP_MSHUTDOWN_FUNCTION(mbstring)
/* {{{ PHP_RINIT_FUNCTION(mbstring) */
PHP_RINIT_FUNCTION(mbstring)
{
- int n;
- enum mbfl_no_encoding *list=NULL, *entry;
zend_function *func, *orig;
const struct mb_overload_def *p;
@@ -1407,22 +1597,7 @@ PHP_RINIT_FUNCTION(mbstring)
MBSTRG(illegalchars) = 0;
- n = 0;
- if (MBSTRG(detect_order_list)) {
- list = MBSTRG(detect_order_list);
- n = MBSTRG(detect_order_list_size);
- }
- if (n <= 0) {
- list = MBSTRG(default_detect_order_list);
- n = MBSTRG(default_detect_order_list_size);
- }
- entry = (enum mbfl_no_encoding *)safe_emalloc(n, sizeof(int), 0);
- MBSTRG(current_detect_order_list) = entry;
- MBSTRG(current_detect_order_list_size) = n;
- while (n > 0) {
- *entry++ = *list++;
- n--;
- }
+ php_mb_populate_current_detect_order_list(TSRMLS_C);
/* override original function. */
if (MBSTRG(func_overload)){
@@ -1454,10 +1629,7 @@ PHP_RINIT_FUNCTION(mbstring)
#if HAVE_MBREGEX
PHP_RINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
#endif
-#ifdef ZEND_MULTIBYTE
- zend_multibyte_set_internal_encoding(mbfl_no_encoding2name(MBSTRG(internal_encoding)) TSRMLS_CC);
- php_mb_set_zend_encoding(TSRMLS_C);
-#endif /* ZEND_MULTIBYTE */
+ zend_multibyte_set_internal_encoding((const zend_encoding *)MBSTRG(internal_encoding) TSRMLS_CC);
return SUCCESS;
}
@@ -1481,11 +1653,11 @@ PHP_RSHUTDOWN_FUNCTION(mbstring)
}
/* clear http input identification. */
- MBSTRG(http_input_identify) = mbfl_no_encoding_invalid;
- MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid;
- MBSTRG(http_input_identify_get) = mbfl_no_encoding_invalid;
- MBSTRG(http_input_identify_cookie) = mbfl_no_encoding_invalid;
- MBSTRG(http_input_identify_string) = mbfl_no_encoding_invalid;
+ MBSTRG(http_input_identify) = NULL;
+ MBSTRG(http_input_identify_post) = NULL;
+ MBSTRG(http_input_identify_get) = NULL;
+ MBSTRG(http_input_identify_cookie) = NULL;
+ MBSTRG(http_input_identify_string) = NULL;
/* clear overloaded function. */
if (MBSTRG(func_overload)){
@@ -1516,7 +1688,12 @@ PHP_MINFO_FUNCTION(mbstring)
php_info_print_table_start();
php_info_print_table_row(2, "Multibyte Support", "enabled");
php_info_print_table_row(2, "Multibyte string engine", "libmbfl");
- php_info_print_table_row(2, "HTTP input encoding translation", MBSTRG(encoding_translation) ? "enabled": "disabled");
+ php_info_print_table_row(2, "HTTP input encoding translation", MBSTRG(encoding_translation) ? "enabled": "disabled");
+ {
+ char tmp[256];
+ snprintf(tmp, sizeof(tmp), "%d.%d.%d", MBFL_VERSION_MAJOR, MBFL_VERSION_MINOR, MBFL_VERSION_TEENY);
+ php_info_print_table_row(2, "libmbfl version", tmp);
+ }
php_info_print_table_end();
php_info_print_table_start();
@@ -1560,33 +1737,27 @@ PHP_FUNCTION(mb_language)
Sets the current internal encoding or Returns the current internal encoding as a string */
PHP_FUNCTION(mb_internal_encoding)
{
- char *name = NULL;
+ const char *name = NULL;
int name_len;
- enum mbfl_no_encoding no_encoding;
+ const mbfl_encoding *encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
RETURN_FALSE;
}
if (name == NULL) {
- name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding));
+ name = MBSTRG(current_internal_encoding) ? MBSTRG(current_internal_encoding)->name: NULL;
if (name != NULL) {
RETURN_STRING(name, 1);
} else {
RETURN_FALSE;
}
} else {
- no_encoding = mbfl_name2no_encoding(name);
- if (no_encoding == mbfl_no_encoding_invalid) {
+ encoding = mbfl_name2encoding(name);
+ if (!encoding) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
RETURN_FALSE;
} else {
- MBSTRG(current_internal_encoding) = no_encoding;
-#ifdef ZEND_MULTIBYTE
- /* TODO: make independent from mbstring.encoding_translation? */
- if (MBSTRG(encoding_translation)) {
- zend_multibyte_set_internal_encoding(name TSRMLS_CC);
- }
-#endif /* ZEND_MULTIBYTE */
+ MBSTRG(current_internal_encoding) = encoding;
RETURN_TRUE;
}
}
@@ -1599,10 +1770,9 @@ PHP_FUNCTION(mb_http_input)
{
char *typ = NULL;
int typ_len;
- int retname, n;
- char *name, *list, *temp;
- enum mbfl_no_encoding *entry;
- enum mbfl_no_encoding result = mbfl_no_encoding_invalid;
+ int retname;
+ char *list, *temp;
+ const mbfl_encoding *result = NULL;
retname = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
@@ -1630,40 +1800,38 @@ PHP_FUNCTION(mb_http_input)
break;
case 'I':
case 'i':
- array_init(return_value);
- entry = MBSTRG(http_input_list);
- n = MBSTRG(http_input_list_size);
- while (n > 0) {
- name = (char *)mbfl_no_encoding2name(*entry);
- if (name) {
- add_next_index_string(return_value, name, 1);
+ {
+ const mbfl_encoding **entry = MBSTRG(http_input_list);
+ const size_t n = MBSTRG(http_input_list_size);
+ size_t i;
+ array_init(return_value);
+ for (i = 0; i < n; i++) {
+ add_next_index_string(return_value, (*entry)->name, 1);
+ entry++;
}
- entry++;
- n--;
+ retname = 0;
}
- retname = 0;
break;
case 'L':
case 'l':
- entry = MBSTRG(http_input_list);
- n = MBSTRG(http_input_list_size);
- list = NULL;
- while (n > 0) {
- name = (char *)mbfl_no_encoding2name(*entry);
- if (name) {
+ {
+ const mbfl_encoding **entry = MBSTRG(http_input_list);
+ const size_t n = MBSTRG(http_input_list_size);
+ size_t i;
+ list = NULL;
+ for (i = 0; i < n; i++) {
if (list) {
temp = list;
- spprintf(&list, 0, "%s,%s", temp, name);
+ spprintf(&list, 0, "%s,%s", temp, (*entry)->name);
efree(temp);
if (!list) {
break;
}
} else {
- list = estrdup(name);
+ list = estrdup((*entry)->name);
}
+ entry++;
}
- entry++;
- n--;
}
if (!list) {
RETURN_FALSE;
@@ -1678,9 +1846,8 @@ PHP_FUNCTION(mb_http_input)
}
if (retname) {
- if (result != mbfl_no_encoding_invalid &&
- (name = (char *)mbfl_no_encoding2name(result)) != NULL) {
- RETVAL_STRING(name, 1);
+ if (result) {
+ RETVAL_STRING(result->name, 1);
} else {
RETVAL_FALSE;
}
@@ -1692,28 +1859,28 @@ PHP_FUNCTION(mb_http_input)
Sets the current output_encoding or returns the current output_encoding as a string */
PHP_FUNCTION(mb_http_output)
{
- char *name = NULL;
+ const char *name = NULL;
int name_len;
- enum mbfl_no_encoding no_encoding;
+ const mbfl_encoding *encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", (char **)&name, &name_len) == FAILURE) {
RETURN_FALSE;
}
if (name == NULL) {
- name = (char *)mbfl_no_encoding2name(MBSTRG(current_http_output_encoding));
+ name = MBSTRG(current_http_output_encoding) ? MBSTRG(current_http_output_encoding)->name: NULL;
if (name != NULL) {
RETURN_STRING(name, 1);
} else {
RETURN_FALSE;
}
} else {
- no_encoding = mbfl_name2no_encoding(name);
- if (no_encoding == mbfl_no_encoding_invalid) {
+ encoding = mbfl_name2encoding(name);
+ if (!encoding) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
RETURN_FALSE;
} else {
- MBSTRG(current_http_output_encoding) = no_encoding;
+ MBSTRG(current_http_output_encoding) = encoding;
RETURN_TRUE;
}
}
@@ -1725,32 +1892,26 @@ PHP_FUNCTION(mb_http_output)
PHP_FUNCTION(mb_detect_order)
{
zval **arg1 = NULL;
- int n, size;
- enum mbfl_no_encoding *list, *entry;
- char *name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Z", &arg1) == FAILURE) {
return;
}
if (!arg1) {
+ size_t i;
+ size_t n = MBSTRG(current_detect_order_list_size);
+ const mbfl_encoding **entry = MBSTRG(current_detect_order_list);
array_init(return_value);
- entry = MBSTRG(current_detect_order_list);
- n = MBSTRG(current_detect_order_list_size);
- while (n > 0) {
- name = (char *)mbfl_no_encoding2name(*entry);
- if (name) {
- add_next_index_string(return_value, name, 1);
- }
+ for (i = 0; i < n; i++) {
+ add_next_index_string(return_value, (*entry)->name, 1);
entry++;
- n--;
}
} else {
- list = NULL;
- size = 0;
+ const mbfl_encoding **list = NULL;
+ size_t size = 0;
switch (Z_TYPE_PP(arg1)) {
case IS_ARRAY:
- if (!php_mb_parse_encoding_array(*arg1, &list, &size, 0 TSRMLS_CC)) {
+ if (FAILURE == php_mb_parse_encoding_array(*arg1, &list, &size, 0 TSRMLS_CC)) {
if (list) {
efree(list);
}
@@ -1759,7 +1920,7 @@ PHP_FUNCTION(mb_detect_order)
break;
default:
convert_to_string_ex(arg1);
- if (!php_mb_parse_encoding_list(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1), &list, &size, 0 TSRMLS_CC)) {
+ if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1), &list, &size, 0 TSRMLS_CC)) {
if (list) {
efree(list);
}
@@ -1879,15 +2040,15 @@ PHP_FUNCTION(mb_parse_str)
char *encstr = NULL;
int encstr_len;
php_mb_encoding_handler_info_t info;
- enum mbfl_no_encoding detected;
+ const mbfl_encoding *detected;
track_vars_array = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &encstr, &encstr_len, &track_vars_array) == FAILURE) {
return;
}
- /* Clear out the array */
if (track_vars_array != NULL) {
+ /* Clear out the array */
zval_dtor(track_vars_array);
array_init(track_vars_array);
}
@@ -1896,7 +2057,6 @@ PHP_FUNCTION(mb_parse_str)
info.data_type = PARSE_STRING;
info.separator = PG(arg_separator).input;
- info.force_register_globals = (track_vars_array == NULL);
info.report_errors = 1;
info.to_encoding = MBSTRG(current_internal_encoding);
info.to_language = MBSTRG(language);
@@ -1904,11 +2064,20 @@ PHP_FUNCTION(mb_parse_str)
info.num_from_encodings = MBSTRG(http_input_list_size);
info.from_language = MBSTRG(language);
- detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC);
+ if (track_vars_array != NULL) {
+ detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC);
+ } else {
+ zval tmp;
+ if (!EG(active_symbol_table)) {
+ zend_rebuild_symbol_table(TSRMLS_C);
+ }
+ Z_ARRVAL(tmp) = EG(active_symbol_table);
+ detected = _php_mb_encoding_handler_ex(&info, &tmp, encstr TSRMLS_CC);
+ }
MBSTRG(http_input_identify) = detected;
- RETVAL_BOOL(detected != mbfl_no_encoding_invalid);
+ RETVAL_BOOL(detected);
if (encstr != NULL) efree(encstr);
}
@@ -1924,7 +2093,7 @@ PHP_FUNCTION(mb_output_handler)
mbfl_string string, result;
const char *charset;
char *p;
- enum mbfl_no_encoding encoding;
+ const mbfl_encoding *encoding;
int last_feed, len;
unsigned char send_text_mimetype = 0;
char *s, *mimetype = NULL;
@@ -1943,7 +2112,7 @@ PHP_FUNCTION(mb_output_handler)
mbfl_buffer_converter_delete(MBSTRG(outconv));
MBSTRG(outconv) = NULL;
}
- if (encoding == mbfl_no_encoding_pass) {
+ if (encoding == &mbfl_encoding_pass) {
RETURN_STRINGL(arg_string, arg_string_len, 1);
}
@@ -1965,7 +2134,7 @@ PHP_FUNCTION(mb_output_handler)
/* if content-type is not yet set, set it and activate the converter */
if (SG(sapi_headers).send_default_content_type || send_text_mimetype) {
- charset = mbfl_no2preferred_mime_name(encoding);
+ charset = encoding->mime_name;
if (charset) {
len = spprintf( &p, 0, "Content-Type: %s; charset=%s", mimetype, charset );
if (sapi_add_header(p, len, 0) != FAILURE) {
@@ -1973,7 +2142,7 @@ PHP_FUNCTION(mb_output_handler)
}
}
/* activate the converter */
- MBSTRG(outconv) = mbfl_buffer_converter_new(MBSTRG(current_internal_encoding), encoding, 0);
+ MBSTRG(outconv) = mbfl_buffer_converter_new2(MBSTRG(current_internal_encoding), encoding, 0);
if (send_text_mimetype){
efree(mimetype);
}
@@ -1994,7 +2163,7 @@ PHP_FUNCTION(mb_output_handler)
/* feed the string */
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
string.val = (unsigned char *)arg_string;
string.len = arg_string_len;
mbfl_buffer_converter_feed(MBSTRG(outconv), &string);
@@ -2031,7 +2200,7 @@ PHP_FUNCTION(mb_strlen)
string.no_language = MBSTRG(language);
if (enc_name == NULL) {
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
} else {
string.no_encoding = mbfl_name2no_encoding(enc_name);
if (string.no_encoding == mbfl_no_encoding_invalid) {
@@ -2058,13 +2227,13 @@ PHP_FUNCTION(mb_strpos)
mbfl_string haystack, needle;
char *enc_name = NULL;
int enc_name_len;
-
+
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
offset = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &offset, &enc_name, &enc_name_len) == FAILURE) {
@@ -2129,9 +2298,9 @@ PHP_FUNCTION(mb_strrpos)
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Zs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &zoffset, &enc_name, &enc_name_len) == FAILURE) {
RETURN_FALSE;
@@ -2218,7 +2387,7 @@ PHP_FUNCTION(mb_stripos)
int n;
long offset;
mbfl_string haystack, needle;
- char *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
int from_encoding_len;
n = -1;
offset = 0;
@@ -2247,7 +2416,7 @@ PHP_FUNCTION(mb_strripos)
int n;
long offset;
mbfl_string haystack, needle;
- const char *from_encoding = mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
int from_encoding_len;
n = -1;
offset = 0;
@@ -2279,9 +2448,9 @@ PHP_FUNCTION(mb_strstr)
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
RETURN_FALSE;
@@ -2337,9 +2506,9 @@ PHP_FUNCTION(mb_strrchr)
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
RETURN_FALSE;
@@ -2392,13 +2561,13 @@ PHP_FUNCTION(mb_stristr)
unsigned int from_encoding_len, len, mblen;
int n;
mbfl_string haystack, needle, result, *ret = NULL;
- const char *from_encoding = mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
@@ -2450,13 +2619,13 @@ PHP_FUNCTION(mb_strrichr)
zend_bool part = 0;
int n, from_encoding_len, len, mblen;
mbfl_string haystack, needle, result, *ret = NULL;
- char *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->name;
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
@@ -2508,9 +2677,9 @@ PHP_FUNCTION(mb_substr_count)
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &enc_name, &enc_name_len) == FAILURE) {
return;
@@ -2546,15 +2715,16 @@ PHP_FUNCTION(mb_substr)
char *str, *encoding;
long from, len;
int mblen, str_len, encoding_len;
+ zval **z_len = NULL;
mbfl_string string, result, *ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|ls", &str, &str_len, &from, &len, &encoding, &encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|Zs", &str, &str_len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
return;
}
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (argc == 4) {
string.no_encoding = mbfl_name2no_encoding(encoding);
@@ -2567,8 +2737,11 @@ PHP_FUNCTION(mb_substr)
string.val = (unsigned char *)str;
string.len = str_len;
- if (argc < 3) {
+ if (argc < 3 || Z_TYPE_PP(z_len) == IS_NULL) {
len = str_len;
+ } else {
+ convert_to_long_ex(z_len);
+ len = Z_LVAL_PP(z_len);
}
/* measures length */
@@ -2619,13 +2792,14 @@ PHP_FUNCTION(mb_strcut)
char *encoding;
long from, len;
int encoding_len;
+ zval **z_len = NULL;
mbfl_string string, result, *ret;
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|ls", (char **)&string.val, (int **)&string.len, &from, &len, &encoding, &encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|Zs", (char **)&string.val, (int **)&string.len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
return;
}
@@ -2637,8 +2811,11 @@ PHP_FUNCTION(mb_strcut)
}
}
- if (argc < 3) {
+ if (argc < 3 || Z_TYPE_PP(z_len) == IS_NULL) {
len = string.len;
+ } else {
+ convert_to_long_ex(z_len);
+ len = Z_LVAL_PP(z_len);
}
/* if "from" position is negative, count start position from the end
@@ -2686,7 +2863,7 @@ PHP_FUNCTION(mb_strwidth)
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
return;
@@ -2725,9 +2902,9 @@ PHP_FUNCTION(mb_strimwidth)
mbfl_string_init(&string);
mbfl_string_init(&marker);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
marker.no_language = MBSTRG(language);
- marker.no_encoding = MBSTRG(current_internal_encoding);
+ marker.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
marker.val = NULL;
marker.len = 0;
@@ -2771,9 +2948,10 @@ PHP_FUNCTION(mb_strimwidth)
MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length, const char *_to_encoding, const char *_from_encodings, size_t *output_len TSRMLS_DC)
{
mbfl_string string, result, *ret;
- enum mbfl_no_encoding from_encoding, to_encoding;
+ const mbfl_encoding *from_encoding, *to_encoding;
mbfl_buffer_converter *convd;
- int size, *list;
+ size_t size;
+ const mbfl_encoding **list;
char *output=NULL;
if (output_len) {
@@ -2784,8 +2962,8 @@ MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length, co
}
/* new encoding */
if (_to_encoding && strlen(_to_encoding)) {
- to_encoding = mbfl_name2no_encoding(_to_encoding);
- if (to_encoding == mbfl_no_encoding_invalid) {
+ to_encoding = mbfl_name2encoding(_to_encoding);
+ if (!to_encoding) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", _to_encoding);
return NULL;
}
@@ -2797,7 +2975,7 @@ MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length, co
mbfl_string_init(&string);
mbfl_string_init(&result);
from_encoding = MBSTRG(current_internal_encoding);
- string.no_encoding = from_encoding;
+ string.no_encoding = from_encoding->no_encoding;
string.no_language = MBSTRG(language);
string.val = (unsigned char *)input;
string.len = length;
@@ -2806,20 +2984,20 @@ MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length, co
if (_from_encodings) {
list = NULL;
size = 0;
- php_mb_parse_encoding_list(_from_encodings, strlen(_from_encodings), &list, &size, 0 TSRMLS_CC);
+ php_mb_parse_encoding_list(_from_encodings, strlen(_from_encodings), &list, &size, 0 TSRMLS_CC);
if (size == 1) {
from_encoding = *list;
- string.no_encoding = from_encoding;
+ string.no_encoding = from_encoding->no_encoding;
} else if (size > 1) {
/* auto detect */
- from_encoding = mbfl_identify_encoding_no(&string, list, size, MBSTRG(strict_detection));
- if (from_encoding != mbfl_no_encoding_invalid) {
- string.no_encoding = from_encoding;
+ from_encoding = mbfl_identify_encoding2(&string, list, size, MBSTRG(strict_detection));
+ if (from_encoding) {
+ string.no_encoding = from_encoding->no_encoding;
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect character encoding");
- from_encoding = mbfl_no_encoding_pass;
+ from_encoding = &mbfl_encoding_pass;
to_encoding = from_encoding;
- string.no_encoding = from_encoding;
+ string.no_encoding = from_encoding->no_encoding;
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal character encoding specified");
@@ -2830,7 +3008,7 @@ MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length, co
}
/* initialize converter */
- convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len);
+ convd = mbfl_buffer_converter_new2(from_encoding, to_encoding, string.len);
if (convd == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create character encoding converter");
return NULL;
@@ -2931,7 +3109,8 @@ PHP_FUNCTION(mb_convert_encoding)
Returns a case-folded version of sourcestring */
PHP_FUNCTION(mb_convert_case)
{
- char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
+ char *str;
int str_len, from_encoding_len;
long case_mode = 0;
char *newstr;
@@ -2955,7 +3134,8 @@ PHP_FUNCTION(mb_convert_case)
*/
PHP_FUNCTION(mb_strtoupper)
{
- char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
+ char *str;
int str_len, from_encoding_len;
char *newstr;
size_t ret_len;
@@ -2978,7 +3158,8 @@ PHP_FUNCTION(mb_strtoupper)
*/
PHP_FUNCTION(mb_strtolower)
{
- char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
+ const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
+ char *str;
int str_len, from_encoding_len;
char *newstr;
size_t ret_len;
@@ -3006,9 +3187,9 @@ PHP_FUNCTION(mb_detect_encoding)
zval *encoding_list;
mbfl_string string;
- const char *ret;
- enum mbfl_no_encoding *elist;
- int size, *list;
+ const mbfl_encoding *ret;
+ const mbfl_encoding **elist, **list;
+ size_t size;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &str, &str_len, &encoding_list, &strict) == FAILURE) {
return;
@@ -3020,7 +3201,7 @@ PHP_FUNCTION(mb_detect_encoding)
if (ZEND_NUM_ARGS() >= 2 && !ZVAL_IS_NULL(encoding_list)) {
switch (Z_TYPE_P(encoding_list)) {
case IS_ARRAY:
- if (!php_mb_parse_encoding_array(encoding_list, &list, &size, 0 TSRMLS_CC)) {
+ if (FAILURE == php_mb_parse_encoding_array(encoding_list, &list, &size, 0 TSRMLS_CC)) {
if (list) {
efree(list);
list = NULL;
@@ -3030,7 +3211,7 @@ PHP_FUNCTION(mb_detect_encoding)
break;
default:
convert_to_string(encoding_list);
- if (!php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &list, &size, 0 TSRMLS_CC)) {
+ if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &list, &size, 0 TSRMLS_CC)) {
if (list) {
efree(list);
list = NULL;
@@ -3059,7 +3240,7 @@ PHP_FUNCTION(mb_detect_encoding)
string.no_language = MBSTRG(language);
string.val = (unsigned char *)str;
string.len = str_len;
- ret = mbfl_identify_encoding_name(&string, elist, size, strict);
+ ret = mbfl_identify_encoding2(&string, elist, size, strict);
if (list != NULL) {
efree((void *)list);
@@ -3069,7 +3250,7 @@ PHP_FUNCTION(mb_detect_encoding)
RETURN_FALSE;
}
- RETVAL_STRING((char *)ret, 1);
+ RETVAL_STRING((char *)ret->name, 1);
}
/* }}} */
@@ -3134,7 +3315,7 @@ PHP_FUNCTION(mb_encode_mimeheader)
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sssl", (char **)&string.val, &string.len, &charset_name, &charset_name_len, &trans_enc_name, &trans_enc_name_len, &linefeed, &linefeed_len, &indent) == FAILURE) {
return;
@@ -3168,7 +3349,7 @@ PHP_FUNCTION(mb_encode_mimeheader)
mbfl_string_init(&result);
ret = mbfl_mime_header_encode(&string, &result, charset, transenc, linefeed, indent);
if (ret != NULL) {
- RETVAL_STRINGL((char *)ret->val, ret->len, 0) /* the string is already strdup()'ed */
+ RETVAL_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
} else {
RETVAL_FALSE;
}
@@ -3183,16 +3364,16 @@ PHP_FUNCTION(mb_decode_mimeheader)
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", (char **)&string.val, &string.len) == FAILURE) {
return;
}
mbfl_string_init(&result);
- ret = mbfl_mime_header_decode(&string, &result, MBSTRG(current_internal_encoding));
+ ret = mbfl_mime_header_decode(&string, &result, MBSTRG(current_internal_encoding)->no_encoding);
if (ret != NULL) {
- RETVAL_STRINGL((char *)ret->val, ret->len, 0) /* the string is already strdup()'ed */
+ RETVAL_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
} else {
RETVAL_FALSE;
}
@@ -3212,7 +3393,7 @@ PHP_FUNCTION(mb_convert_kana)
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", (char **)&string.val, &string.len, &optstr, &optstr_len, &encname, &encname_len) == FAILURE) {
return;
@@ -3311,21 +3492,22 @@ PHP_FUNCTION(mb_convert_variables)
zval ***args, ***stack, **var, **hash_entry, **zfrom_enc;
HashTable *target_hash;
mbfl_string string, result, *ret;
- enum mbfl_no_encoding from_encoding, to_encoding;
+ const mbfl_encoding *from_encoding, *to_encoding;
mbfl_encoding_detector *identd;
mbfl_buffer_converter *convd;
- int n, to_enc_len, argc, stack_level, stack_max, elistsz;
- enum mbfl_no_encoding *elist;
- char *name, *to_enc;
+ int n, to_enc_len, argc, stack_level, stack_max;
+ size_t elistsz;
+ const mbfl_encoding **elist;
+ char *to_enc;
void *ptmp;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
return;
}
/* new encoding */
- to_encoding = mbfl_name2no_encoding(to_enc);
- if (to_encoding == mbfl_no_encoding_invalid) {
+ to_encoding = mbfl_name2encoding(to_enc);
+ if (!to_encoding) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", to_enc);
efree(args);
RETURN_FALSE;
@@ -3335,7 +3517,7 @@ PHP_FUNCTION(mb_convert_variables)
mbfl_string_init(&string);
mbfl_string_init(&result);
from_encoding = MBSTRG(current_internal_encoding);
- string.no_encoding = from_encoding;
+ string.no_encoding = from_encoding->no_encoding;
string.no_language = MBSTRG(language);
/* pre-conversion encoding */
@@ -3351,16 +3533,16 @@ PHP_FUNCTION(mb_convert_variables)
break;
}
if (elistsz <= 0) {
- from_encoding = mbfl_no_encoding_pass;
+ from_encoding = &mbfl_encoding_pass;
} else if (elistsz == 1) {
from_encoding = *elist;
} else {
/* auto detect */
- from_encoding = mbfl_no_encoding_invalid;
+ from_encoding = NULL;
stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
stack_level = 0;
- identd = mbfl_encoding_detector_new(elist, elistsz, MBSTRG(strict_detection));
+ identd = mbfl_encoding_detector_new2(elist, elistsz, MBSTRG(strict_detection));
if (identd != NULL) {
n = 0;
while (n < argc || stack_level > 0) {
@@ -3413,14 +3595,14 @@ PHP_FUNCTION(mb_convert_variables)
}
}
detect_end:
- from_encoding = mbfl_encoding_detector_judge(identd);
+ from_encoding = mbfl_encoding_detector_judge2(identd);
mbfl_encoding_detector_delete(identd);
}
efree(stack);
- if (from_encoding == mbfl_no_encoding_invalid) {
+ if (!from_encoding) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding");
- from_encoding = mbfl_no_encoding_pass;
+ from_encoding = &mbfl_encoding_pass;
}
}
if (elist != NULL) {
@@ -3428,8 +3610,8 @@ detect_end:
}
/* create converter */
convd = NULL;
- if (from_encoding != mbfl_no_encoding_pass) {
- convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0);
+ if (from_encoding != &mbfl_encoding_pass) {
+ convd = mbfl_buffer_converter_new2(from_encoding, to_encoding, 0);
if (convd == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
RETURN_FALSE;
@@ -3511,9 +3693,8 @@ detect_end:
efree(args);
- name = (char *)mbfl_no_encoding2name(from_encoding);
- if (name != NULL) {
- RETURN_STRING(name, 1);
+ if (from_encoding) {
+ RETURN_STRING(from_encoding->name, 1);
} else {
RETURN_FALSE;
}
@@ -3531,21 +3712,22 @@ php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
HashTable *target_hash;
size_t argc = ZEND_NUM_ARGS();
int i, *convmap, *mapelm, mapsize=0;
+ zend_bool is_hex = 0;
mbfl_string string, result, *ret;
enum mbfl_no_encoding no_encoding;
- if (zend_parse_parameters(argc TSRMLS_CC, "szs", &str, &str_len, &zconvmap, &encoding, &encoding_len) == FAILURE) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "sz|sb", &str, &str_len, &zconvmap, &encoding, &encoding_len, &is_hex) == FAILURE) {
return;
}
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
- string.no_encoding = MBSTRG(current_internal_encoding);
+ string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
string.val = (unsigned char *)str;
string.len = str_len;
/* encoding */
- if (argc == 3) {
+ if ((argc == 3 || argc == 4) && encoding_len > 0) {
no_encoding = mbfl_name2no_encoding(encoding);
if (no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
@@ -3555,6 +3737,12 @@ php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
}
}
+ if (argc == 4) {
+ if (type == 0 && is_hex) {
+ type = 2; /* output in hex format */
+ }
+ }
+
/* conversion map */
convmap = NULL;
if (Z_TYPE_P(zconvmap) == IS_ARRAY) {
@@ -3592,7 +3780,7 @@ php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
}
/* }}} */
-/* {{{ proto string mb_encode_numericentity(string string, array convmap [, string encoding])
+/* {{{ proto string mb_encode_numericentity(string string, array convmap [, string encoding [, bool is_hex]])
Converts specified characters to HTML numeric entities */
PHP_FUNCTION(mb_encode_numericentity)
{
@@ -3852,9 +4040,9 @@ PHP_FUNCTION(mb_send_mail)
mbfl_string orig_str, conv_str;
mbfl_string *pstr; /* pointer to mbfl string for return value */
enum mbfl_no_encoding
- tran_cs, /* transfar text charset */
- head_enc, /* header transfar encoding */
- body_enc; /* body transfar encoding */
+ tran_cs, /* transfar text charset */
+ head_enc, /* header transfar encoding */
+ body_enc; /* body transfar encoding */
mbfl_memory_device device; /* automatic allocateable buffer for additional header */
const mbfl_language *lang;
int err = 0;
@@ -3862,12 +4050,7 @@ PHP_FUNCTION(mb_send_mail)
smart_str *s;
extern void mbfl_memory_device_unput(mbfl_memory_device *device);
char *pp, *ee;
-
- if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The fifth parameter is disabled in SAFE MODE.");
- RETURN_FALSE;
- }
-
+
/* initialize */
mbfl_memory_device_init(&device, 0, 0);
mbfl_string_init(&orig_str);
@@ -3966,15 +4149,15 @@ PHP_FUNCTION(mb_send_mail)
/* To: */
if (to != NULL) {
- if (to_len > 0) {
- to_r = estrndup(to, to_len);
- for (; to_len; to_len--) {
- if (!isspace((unsigned char) to_r[to_len - 1])) {
- break;
- }
- to_r[to_len - 1] = '\0';
- }
- for (i = 0; to_r[i]; i++) {
+ if (to_len > 0) {
+ to_r = estrndup(to, to_len);
+ for (; to_len; to_len--) {
+ if (!isspace((unsigned char) to_r[to_len - 1])) {
+ break;
+ }
+ to_r[to_len - 1] = '\0';
+ }
+ for (i = 0; to_r[i]; i++) {
if (iscntrl((unsigned char) to_r[i])) {
/* According to RFC 822, section 3.1.1 long headers may be separated into
* parts using CRLF followed at least one linear-white-space character ('\t' or ' ').
@@ -3984,11 +4167,11 @@ PHP_FUNCTION(mb_send_mail)
SKIP_LONG_HEADER_SEP_MBSTRING(to_r, i);
to_r[i] = ' ';
}
- }
- } else {
- to_r = to;
- }
- } else {
+ }
+ } else {
+ to_r = to;
+ }
+ } else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing To: field");
err = 1;
}
@@ -3998,10 +4181,10 @@ PHP_FUNCTION(mb_send_mail)
orig_str.no_language = MBSTRG(language);
orig_str.val = (unsigned char *)subject;
orig_str.len = subject_len;
- orig_str.no_encoding = MBSTRG(current_internal_encoding);
- if (orig_str.no_encoding == mbfl_no_encoding_invalid
- || orig_str.no_encoding == mbfl_no_encoding_pass) {
- orig_str.no_encoding = mbfl_identify_encoding_no(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
+ orig_str.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
+ if (orig_str.no_encoding == mbfl_no_encoding_invalid || orig_str.no_encoding == mbfl_no_encoding_pass) {
+ const mbfl_encoding *encoding = mbfl_identify_encoding2(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
+ orig_str.no_encoding = encoding ? encoding->no_encoding: mbfl_no_encoding_invalid;
}
pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]"));
if (pstr != NULL) {
@@ -4017,11 +4200,11 @@ PHP_FUNCTION(mb_send_mail)
orig_str.no_language = MBSTRG(language);
orig_str.val = (unsigned char *)message;
orig_str.len = (unsigned int)message_len;
- orig_str.no_encoding = MBSTRG(current_internal_encoding);
+ orig_str.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (orig_str.no_encoding == mbfl_no_encoding_invalid
- || orig_str.no_encoding == mbfl_no_encoding_pass) {
- orig_str.no_encoding = mbfl_identify_encoding_no(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
+ if (orig_str.no_encoding == mbfl_no_encoding_invalid || orig_str.no_encoding == mbfl_no_encoding_pass) {
+ const mbfl_encoding *encoding = mbfl_identify_encoding2(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
+ orig_str.no_encoding = encoding ? encoding->no_encoding: mbfl_no_encoding_invalid;
}
pstr = NULL;
@@ -4129,15 +4312,13 @@ PHP_FUNCTION(mb_send_mail)
PHP_FUNCTION(mb_get_info)
{
char *typ = NULL;
- int typ_len, n;
+ int typ_len;
+ size_t n;
char *name;
const struct mb_overload_def *over_func;
zval *row1, *row2;
const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
- enum mbfl_no_encoding *entry;
-#ifdef ZEND_MULTIBYTE
- zval *row3;
-#endif /* ZEND_MULTIBYTE */
+ const mbfl_encoding **entry;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
RETURN_FALSE;
@@ -4145,14 +4326,14 @@ PHP_FUNCTION(mb_get_info)
if (!typ || !strcasecmp("all", typ)) {
array_init(return_value);
- if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding))) != NULL) {
- add_assoc_string(return_value, "internal_encoding", name, 1);
+ if (MBSTRG(current_internal_encoding)) {
+ add_assoc_string(return_value, "internal_encoding", (char *)MBSTRG(current_internal_encoding)->name, 1);
}
- if ((name = (char *)mbfl_no_encoding2name(MBSTRG(http_input_identify))) != NULL) {
- add_assoc_string(return_value, "http_input", name, 1);
+ if (MBSTRG(http_input_identify)) {
+ add_assoc_string(return_value, "http_input", (char *)MBSTRG(http_input_identify)->name, 1);
}
- if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_http_output_encoding))) != NULL) {
- add_assoc_string(return_value, "http_output", name, 1);
+ if (MBSTRG(current_http_output_encoding)) {
+ add_assoc_string(return_value, "http_output", (char *)MBSTRG(current_http_output_encoding)->name, 1);
}
if ((name = (char *)zend_ini_string("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes"), 0)) != NULL) {
add_assoc_string(return_value, "http_output_conv_mimetypes", name, 1);
@@ -4194,15 +4375,13 @@ PHP_FUNCTION(mb_get_info)
}
n = MBSTRG(current_detect_order_list_size);
entry = MBSTRG(current_detect_order_list);
- if(n > 0) {
+ if (n > 0) {
+ size_t i;
MAKE_STD_ZVAL(row2);
array_init(row2);
- while (n > 0) {
- if ((name = (char *)mbfl_no_encoding2name(*entry)) != NULL) {
- add_next_index_string(row2, name, 1);
- }
+ for (i = 0; i < n; i++) {
+ add_next_index_string(row2, (*entry)->name, 1);
entry++;
- n--;
}
add_assoc_zval(return_value, "detect_order", row2);
}
@@ -4220,33 +4399,17 @@ PHP_FUNCTION(mb_get_info)
} else {
add_assoc_string(return_value, "strict_detection", "Off", 1);
}
-#ifdef ZEND_MULTIBYTE
- entry = MBSTRG(script_encoding_list);
- n = MBSTRG(script_encoding_list_size);
- if(n > 0) {
- MAKE_STD_ZVAL(row3);
- array_init(row3);
- while (n > 0) {
- if ((name = (char *)mbfl_no_encoding2name(*entry)) != NULL) {
- add_next_index_string(row3, name, 1);
- }
- entry++;
- n--;
- }
- add_assoc_zval(return_value, "script_encoding", row3);
- }
-#endif /* ZEND_MULTIBYTE */
} else if (!strcasecmp("internal_encoding", typ)) {
- if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding))) != NULL) {
- RETVAL_STRING(name, 1);
+ if (MBSTRG(current_internal_encoding)) {
+ RETVAL_STRING((char *)MBSTRG(current_internal_encoding)->name, 1);
}
} else if (!strcasecmp("http_input", typ)) {
- if ((name = (char *)mbfl_no_encoding2name(MBSTRG(http_input_identify))) != NULL) {
- RETVAL_STRING(name, 1);
+ if (MBSTRG(http_input_identify)) {
+ RETVAL_STRING((char *)MBSTRG(http_input_identify)->name, 1);
}
} else if (!strcasecmp("http_output", typ)) {
- if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_http_output_encoding))) != NULL) {
- RETVAL_STRING(name, 1);
+ if (MBSTRG(current_http_output_encoding)) {
+ RETVAL_STRING((char *)MBSTRG(current_http_output_encoding)->name, 1);
}
} else if (!strcasecmp("http_output_conv_mimetypes", typ)) {
if ((name = (char *)zend_ini_string("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes"), 0)) != NULL) {
@@ -4294,15 +4457,12 @@ PHP_FUNCTION(mb_get_info)
} else if (!strcasecmp("detect_order", typ)) {
n = MBSTRG(current_detect_order_list_size);
entry = MBSTRG(current_detect_order_list);
- if(n > 0) {
+ if (n > 0) {
+ size_t i;
array_init(return_value);
- while (n > 0) {
- name = (char *)mbfl_no_encoding2name(*entry);
- if (name) {
- add_next_index_string(return_value, name, 1);
- }
+ for (i = 0; i < n; i++) {
+ add_next_index_string(return_value, (*entry)->name, 1);
entry++;
- n--;
}
}
} else if (!strcasecmp("substitute_character", typ)) {
@@ -4322,24 +4482,6 @@ PHP_FUNCTION(mb_get_info)
RETVAL_STRING("Off", 1);
}
} else {
-#ifdef ZEND_MULTIBYTE
- if (!strcasecmp("script_encoding", typ)) {
- entry = MBSTRG(script_encoding_list);
- n = MBSTRG(script_encoding_list_size);
- if(n > 0) {
- array_init(return_value);
- while (n > 0) {
- name = (char *)mbfl_no_encoding2name(*entry);
- if (name) {
- add_next_index_string(return_value, name, 1);
- }
- entry++;
- n--;
- }
- }
- return;
- }
-#endif /* ZEND_MULTIBYTE */
RETURN_FALSE;
}
}
@@ -4354,7 +4496,7 @@ PHP_FUNCTION(mb_check_encoding)
char *enc = NULL;
int enc_len;
mbfl_buffer_converter *convd;
- enum mbfl_no_encoding no_encoding = MBSTRG(current_internal_encoding);
+ const mbfl_encoding *encoding = MBSTRG(current_internal_encoding);
mbfl_string string, result, *ret = NULL;
long illegalchars = 0;
@@ -4367,23 +4509,23 @@ PHP_FUNCTION(mb_check_encoding)
}
if (enc != NULL) {
- no_encoding = mbfl_name2no_encoding(enc);
- if (no_encoding == mbfl_no_encoding_invalid || no_encoding == mbfl_no_encoding_pass) {
+ encoding = mbfl_name2encoding(enc);
+ if (!encoding || encoding == &mbfl_encoding_pass) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid encoding \"%s\"", enc);
RETURN_FALSE;
}
}
-
- convd = mbfl_buffer_converter_new(no_encoding, no_encoding, 0);
+
+ convd = mbfl_buffer_converter_new2(encoding, encoding, 0);
if (convd == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
RETURN_FALSE;
}
mbfl_buffer_converter_illegal_mode(convd, MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE);
mbfl_buffer_converter_illegal_substchar(convd, 0);
-
+
/* initialize string */
- mbfl_string_init_set(&string, mbfl_no_language_neutral, no_encoding);
+ mbfl_string_init_set(&string, mbfl_no_language_neutral, encoding->no_encoding);
mbfl_string_init(&result);
string.val = (unsigned char *)var;
@@ -4402,8 +4544,36 @@ PHP_FUNCTION(mb_check_encoding)
}
/* }}} */
-/* {{{ MBSTRING_API int php_mb_encoding_translation() */
-MBSTRING_API int php_mb_encoding_translation(TSRMLS_D)
+
+/* {{{ php_mb_populate_current_detect_order_list */
+static void php_mb_populate_current_detect_order_list(TSRMLS_D)
+{
+ const mbfl_encoding **entry = 0;
+ size_t nentries;
+
+ if (MBSTRG(current_detect_order_list)) {
+ return;
+ }
+
+ if (MBSTRG(detect_order_list) && MBSTRG(detect_order_list_size)) {
+ nentries = MBSTRG(detect_order_list_size);
+ entry = (const mbfl_encoding **)safe_emalloc(nentries, sizeof(mbfl_encoding*), 0);
+ memcpy(entry, MBSTRG(detect_order_list), sizeof(mbfl_encoding*) * nentries);
+ } else {
+ const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
+ size_t i;
+ nentries = MBSTRG(default_detect_order_list_size);
+ entry = (const mbfl_encoding **)safe_emalloc(nentries, sizeof(mbfl_encoding*), 0);
+ for (i = 0; i < nentries; i++) {
+ entry[i] = mbfl_no2encoding(src[i]);
+ }
+ }
+ MBSTRG(current_detect_order_list) = entry;
+ MBSTRG(current_detect_order_list_size) = nentries;
+}
+
+/* {{{ static int php_mb_encoding_translation() */
+static int php_mb_encoding_translation(TSRMLS_D)
{
return MBSTRG(encoding_translation);
}
@@ -4430,8 +4600,7 @@ MBSTRING_API size_t php_mb_mbchar_bytes_ex(const char *s, const mbfl_encoding *e
/* {{{ MBSTRING_API size_t php_mb_mbchar_bytes() */
MBSTRING_API size_t php_mb_mbchar_bytes(const char *s TSRMLS_DC)
{
- return php_mb_mbchar_bytes_ex(s,
- mbfl_no2encoding(MBSTRG(internal_encoding)));
+ return php_mb_mbchar_bytes_ex(s, MBSTRG(internal_encoding));
}
/* }}} */
@@ -4479,172 +4648,7 @@ MBSTRING_API char *php_mb_safe_strrchr_ex(const char *s, unsigned int c, size_t
/* {{{ MBSTRING_API char *php_mb_safe_strrchr() */
MBSTRING_API char *php_mb_safe_strrchr(const char *s, unsigned int c, size_t nbytes TSRMLS_DC)
{
- return php_mb_safe_strrchr_ex(s, c, nbytes,
- mbfl_no2encoding(MBSTRG(internal_encoding)));
-}
-/* }}} */
-
-/* {{{ MBSTRING_API char *php_mb_strrchr() */
-MBSTRING_API char *php_mb_strrchr(const char *s, char c TSRMLS_DC)
-{
- return php_mb_safe_strrchr(s, c, -1 TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ MBSTRING_API size_t php_mb_gpc_mbchar_bytes() */
-MBSTRING_API size_t php_mb_gpc_mbchar_bytes(const char *s TSRMLS_DC)
-{
-
- if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid){
- return php_mb_mbchar_bytes_ex(s,
- mbfl_no2encoding(MBSTRG(http_input_identify)));
- } else {
- return php_mb_mbchar_bytes_ex(s,
- mbfl_no2encoding(MBSTRG(internal_encoding)));
- }
-}
-/* }}} */
-
-/* {{{ MBSTRING_API int php_mb_gpc_encoding_converter() */
-MBSTRING_API int php_mb_gpc_encoding_converter(char **str, int *len, int num, const char *encoding_to, const char *encoding_from TSRMLS_DC)
-{
- int i;
- mbfl_string string, result, *ret = NULL;
- enum mbfl_no_encoding from_encoding, to_encoding;
- mbfl_buffer_converter *convd;
-
- if (encoding_to) {
- /* new encoding */
- to_encoding = mbfl_name2no_encoding(encoding_to);
- if (to_encoding == mbfl_no_encoding_invalid) {
- return -1;
- }
- } else {
- to_encoding = MBSTRG(current_internal_encoding);
- }
- if (encoding_from) {
- /* old encoding */
- from_encoding = mbfl_name2no_encoding(encoding_from);
- if (from_encoding == mbfl_no_encoding_invalid) {
- return -1;
- }
- } else {
- from_encoding = MBSTRG(http_input_identify);
- }
-
- if (from_encoding == mbfl_no_encoding_pass) {
- return 0;
- }
-
- /* initialize string */
- mbfl_string_init(&string);
- mbfl_string_init(&result);
- string.no_encoding = from_encoding;
- string.no_language = MBSTRG(language);
-
- for (i=0; i<num; i++){
- string.val = (unsigned char *)str[i];
- string.len = len[i];
-
- /* initialize converter */
- convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len);
- if (convd == NULL) {
- return -1;
- }
- mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
- mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
-
- /* do it */
- ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
- if (ret != NULL) {
- efree(str[i]);
- str[i] = (char *)ret->val;
- len[i] = (int)ret->len;
- }
-
- MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
- mbfl_buffer_converter_delete(convd);
- }
-
- return ret ? 0 : -1;
-}
-/* }}} */
-
-/* {{{ MBSTRING_API int php_mb_gpc_encoding_detector()
- */
-MBSTRING_API int php_mb_gpc_encoding_detector(char **arg_string, int *arg_length, int num, char *arg_list TSRMLS_DC)
-{
- mbfl_string string;
- enum mbfl_no_encoding *elist;
- enum mbfl_no_encoding encoding = mbfl_no_encoding_invalid;
- mbfl_encoding_detector *identd = NULL;
-
- int size;
- enum mbfl_no_encoding *list;
-
- if (MBSTRG(http_input_list_size) == 1 &&
- MBSTRG(http_input_list)[0] == mbfl_no_encoding_pass) {
- MBSTRG(http_input_identify) = mbfl_no_encoding_pass;
- return SUCCESS;
- }
-
- if (MBSTRG(http_input_list_size) == 1 &&
- MBSTRG(http_input_list)[0] != mbfl_no_encoding_auto &&
- mbfl_no_encoding2name(MBSTRG(http_input_list)[0]) != NULL) {
- MBSTRG(http_input_identify) = MBSTRG(http_input_list)[0];
- return SUCCESS;
- }
-
- if (arg_list && strlen(arg_list)>0) {
- /* make encoding list */
- list = NULL;
- size = 0;
- php_mb_parse_encoding_list(arg_list, strlen(arg_list), &list, &size, 0 TSRMLS_CC);
-
- if (size > 0 && list != NULL) {
- elist = list;
- } else {
- elist = MBSTRG(current_detect_order_list);
- size = MBSTRG(current_detect_order_list_size);
- if (size <= 0){
- elist = MBSTRG(default_detect_order_list);
- size = MBSTRG(default_detect_order_list_size);
- }
- }
- } else {
- elist = MBSTRG(current_detect_order_list);
- size = MBSTRG(current_detect_order_list_size);
- if (size <= 0){
- elist = MBSTRG(default_detect_order_list);
- size = MBSTRG(default_detect_order_list_size);
- }
- }
-
- mbfl_string_init(&string);
- string.no_language = MBSTRG(language);
-
- identd = mbfl_encoding_detector_new(elist, size, MBSTRG(strict_detection));
-
- if (identd) {
- int n = 0;
- while(n < num){
- string.val = (unsigned char *)arg_string[n];
- string.len = arg_length[n];
- if (mbfl_encoding_detector_feed(identd, &string)) {
- break;
- }
- n++;
- }
- encoding = mbfl_encoding_detector_judge(identd);
- mbfl_encoding_detector_delete(identd);
- }
-
- if (encoding != mbfl_no_encoding_invalid) {
- MBSTRG(http_input_identify) = encoding;
- return SUCCESS;
- } else {
- return FAILURE;
- }
+ return php_mb_safe_strrchr_ex(s, c, nbytes, MBSTRG(internal_encoding));
}
/* }}} */
@@ -4659,9 +4663,9 @@ MBSTRING_API int php_mb_stripos(int mode, const char *old_haystack, unsigned int
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
haystack.no_language = MBSTRG(language);
- haystack.no_encoding = MBSTRG(current_internal_encoding);
+ haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
- needle.no_encoding = MBSTRG(current_internal_encoding);
+ needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
do {
size_t len = 0;
@@ -4725,165 +4729,18 @@ MBSTRING_API int php_mb_stripos(int mode, const char *old_haystack, unsigned int
}
/* }}} */
-#ifdef ZEND_MULTIBYTE
-/* {{{ php_mb_set_zend_encoding() */
-static int php_mb_set_zend_encoding(TSRMLS_D)
+static void php_mb_gpc_get_detect_order(const zend_encoding ***list, size_t *list_size TSRMLS_DC) /* {{{ */
{
- /* 'd better use mbfl_memory_device? */
- char *name, *list = NULL;
- int n, *entry, list_size = 0;
- zend_encoding_detector encoding_detector;
- zend_encoding_converter encoding_converter;
- zend_encoding_oddlen encoding_oddlen;
-
- /* notify script encoding to Zend Engine */
- entry = MBSTRG(script_encoding_list);
- n = MBSTRG(script_encoding_list_size);
- while (n > 0) {
- name = (char *)mbfl_no_encoding2name(*entry);
- if (name) {
- list_size += strlen(name) + 1;
- if (!list) {
- list = (char*)emalloc(list_size);
- *list = '\0';
- } else {
- list = (char*)erealloc(list, list_size);
- strcat(list, ",");
- }
- strcat(list, name);
- }
- entry++;
- n--;
- }
- zend_multibyte_set_script_encoding(list, (list ? strlen(list) : 0) TSRMLS_CC);
- if (list) {
- efree(list);
- }
- encoding_detector = php_mb_encoding_detector;
- encoding_converter = php_mb_encoding_converter;
- encoding_oddlen = php_mb_oddlen;
-
- /* TODO: make independent from mbstring.encoding_translation? */
- if (MBSTRG(encoding_translation)) {
- /* notify internal encoding to Zend Engine */
- name = (char*)mbfl_no_encoding2name(MBSTRG(current_internal_encoding));
- zend_multibyte_set_internal_encoding(name TSRMLS_CC);
- }
-
- zend_multibyte_set_functions(encoding_detector, encoding_converter, encoding_oddlen TSRMLS_CC);
-
- return 0;
+ *list = (const zend_encoding **)MBSTRG(http_input_list);
+ *list_size = MBSTRG(http_input_list_size);
}
/* }}} */
-/* {{{ char *php_mb_encoding_detector()
- * Interface for Zend Engine
- */
-static char* php_mb_encoding_detector(const unsigned char *arg_string, size_t arg_length, char *arg_list TSRMLS_DC)
+static void php_mb_gpc_set_input_encoding(const zend_encoding *encoding TSRMLS_DC) /* {{{ */
{
- mbfl_string string;
- const char *ret;
- enum mbfl_no_encoding *elist;
- int size, *list;
-
- /* make encoding list */
- list = NULL;
- size = 0;
- php_mb_parse_encoding_list(arg_list, strlen(arg_list), &list, &size, 0 TSRMLS_CC);
- if (size <= 0) {
- return NULL;
- }
- if (size > 0 && list != NULL) {
- elist = list;
- } else {
- elist = MBSTRG(current_detect_order_list);
- size = MBSTRG(current_detect_order_list_size);
- }
-
- mbfl_string_init(&string);
- string.no_language = MBSTRG(language);
- string.val = (unsigned char *)arg_string;
- string.len = arg_length;
- ret = mbfl_identify_encoding_name(&string, elist, size, 0);
- if (list != NULL) {
- efree((void *)list);
- }
- if (ret != NULL) {
- return estrdup(ret);
- } else {
- return NULL;
- }
-}
-/* }}} */
-
-/* {{{ int php_mb_encoding_converter() */
-static int php_mb_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const char *encoding_to, const char *encoding_from TSRMLS_DC)
-{
- mbfl_string string, result, *ret;
- enum mbfl_no_encoding from_encoding, to_encoding;
- mbfl_buffer_converter *convd;
-
- /* new encoding */
- to_encoding = mbfl_name2no_encoding(encoding_to);
- if (to_encoding == mbfl_no_encoding_invalid) {
- return -1;
- }
- /* old encoding */
- from_encoding = mbfl_name2no_encoding(encoding_from);
- if (from_encoding == mbfl_no_encoding_invalid) {
- return -1;
- }
- /* initialize string */
- mbfl_string_init(&string);
- mbfl_string_init(&result);
- string.no_encoding = from_encoding;
- string.no_language = MBSTRG(language);
- string.val = (unsigned char*)from;
- string.len = from_length;
-
- /* initialize converter */
- convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len);
- if (convd == NULL) {
- return -1;
- }
- mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
- mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
-
- /* do it */
- ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
- if (ret != NULL) {
- *to = ret->val;
- *to_length = ret->len;
- }
-
- MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
- mbfl_buffer_converter_delete(convd);
-
- return ret ? 0 : -1;
-}
-/* }}} */
-
-/* {{{ int php_mb_oddlen()
- * returns number of odd (e.g. appears only first byte of multibyte
- * character) chars
- */
-static size_t php_mb_oddlen(const unsigned char *string, size_t length, const char *encoding TSRMLS_DC)
-{
- mbfl_string mb_string;
-
- mbfl_string_init(&mb_string);
- mb_string.no_language = MBSTRG(language);
- mb_string.no_encoding = mbfl_name2no_encoding(encoding);
- mb_string.val = (unsigned char *)string;
- mb_string.len = length;
-
- if (mb_string.no_encoding == mbfl_no_encoding_invalid) {
- return 0;
- }
- return mbfl_oddlen(&mb_string);
+ MBSTRG(http_input_identify) = (const mbfl_encoding*)encoding;
}
/* }}} */
-#endif /* ZEND_MULTIBYTE */
#endif /* HAVE_MBSTRING */
diff --git a/ext/mbstring/mbstring.h b/ext/mbstring/mbstring.h
index 5a407ac4b5..15f5d79190 100644
--- a/ext/mbstring/mbstring.h
+++ b/ext/mbstring/mbstring.h
@@ -128,13 +128,10 @@ PHP_FUNCTION(mb_send_mail);
PHP_FUNCTION(mb_get_info);
PHP_FUNCTION(mb_check_encoding);
-MBSTRING_API int php_mb_encoding_translation(TSRMLS_D);
-
MBSTRING_API char *php_mb_safe_strrchr_ex(const char *s, unsigned int c,
size_t nbytes, const mbfl_encoding *enc);
MBSTRING_API char *php_mb_safe_strrchr(const char *s, unsigned int c,
size_t nbytes TSRMLS_DC);
-MBSTRING_API char *php_mb_strrchr(const char *s, char c TSRMLS_DC);
MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length,
const char *_to_encoding,
@@ -146,45 +143,36 @@ MBSTRING_API int php_mb_check_encoding_list(const char *encoding_list TSRMLS_DC)
MBSTRING_API size_t php_mb_mbchar_bytes_ex(const char *s, const mbfl_encoding *enc);
MBSTRING_API size_t php_mb_mbchar_bytes(const char *s TSRMLS_DC);
-MBSTRING_API size_t php_mb_gpc_mbchar_bytes(const char *s TSRMLS_DC);
-
MBSTRING_API int php_mb_encoding_detector_ex(const char *arg_string, int arg_length,
char *arg_list TSRMLS_DC);
MBSTRING_API int php_mb_encoding_converter_ex(char **str, int *len, const char *encoding_to,
const char *encoding_from TSRMLS_DC);
-MBSTRING_API int php_mb_gpc_encoding_converter(char **str, int *len, int num, const char *encoding_to, const char *encoding_from TSRMLS_DC);
-
-MBSTRING_API int php_mb_gpc_encoding_detector(char **arg_string, int *arg_length, int num, char *arg_list TSRMLS_DC);
-
MBSTRING_API int php_mb_stripos(int mode, const char *old_haystack, unsigned int old_haystack_len, const char *old_needle, unsigned int old_needle_len, long offset, const char *from_encoding TSRMLS_DC);
/* internal use only */
int _php_mb_ini_mbstring_internal_encoding_set(const char *new_value, uint new_value_length TSRMLS_DC);
ZEND_BEGIN_MODULE_GLOBALS(mbstring)
+ char *internal_encoding_name;
enum mbfl_no_language language;
- enum mbfl_no_encoding internal_encoding;
- enum mbfl_no_encoding current_internal_encoding;
-#ifdef ZEND_MULTIBYTE
- enum mbfl_no_encoding *script_encoding_list;
- int script_encoding_list_size;
-#endif /* ZEND_MULTIBYTE */
- enum mbfl_no_encoding http_output_encoding;
- enum mbfl_no_encoding current_http_output_encoding;
- enum mbfl_no_encoding http_input_identify;
- enum mbfl_no_encoding http_input_identify_get;
- enum mbfl_no_encoding http_input_identify_post;
- enum mbfl_no_encoding http_input_identify_cookie;
- enum mbfl_no_encoding http_input_identify_string;
- enum mbfl_no_encoding *http_input_list;
- int http_input_list_size;
- enum mbfl_no_encoding *detect_order_list;
- int detect_order_list_size;
- enum mbfl_no_encoding *current_detect_order_list;
- int current_detect_order_list_size;
+ const mbfl_encoding *internal_encoding;
+ const mbfl_encoding *current_internal_encoding;
+ const mbfl_encoding *http_output_encoding;
+ const mbfl_encoding *current_http_output_encoding;
+ const mbfl_encoding *http_input_identify;
+ const mbfl_encoding *http_input_identify_get;
+ const mbfl_encoding *http_input_identify_post;
+ const mbfl_encoding *http_input_identify_cookie;
+ const mbfl_encoding *http_input_identify_string;
+ const mbfl_encoding **http_input_list;
+ size_t http_input_list_size;
+ const mbfl_encoding **detect_order_list;
+ size_t detect_order_list_size;
+ const mbfl_encoding **current_detect_order_list;
+ size_t current_detect_order_list_size;
enum mbfl_no_encoding *default_detect_order_list;
- int default_detect_order_list_size;
+ size_t default_detect_order_list_size;
int filter_illegal_mode;
int filter_illegal_substchar;
int current_filter_illegal_mode;
diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c
index df0e148d86..863eebead3 100644
--- a/ext/mbstring/php_mbregex.c
+++ b/ext/mbstring/php_mbregex.c
@@ -372,7 +372,7 @@ static OnigEncoding _php_mb_regex_name2mbctype(const char *pname)
const char *p;
php_mb_regex_enc_name_map_t *mapping;
- if (pname == NULL) {
+ if (pname == NULL || !*pname) {
return ONIG_ENCODING_UNDEF;
}
@@ -784,7 +784,7 @@ PHP_FUNCTION(mb_eregi)
/* }}} */
/* {{{ _php_mb_regex_ereg_replace_exec */
-static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options)
+static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable)
{
zval **arg_pattern_zval;
@@ -794,6 +794,9 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
char *replace;
int replace_len;
+ zend_fcall_info arg_replace_fci;
+ zend_fcall_info_cache arg_replace_fci_cache;
+
char *string;
int string_len;
@@ -826,12 +829,22 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
char *option_str = NULL;
int option_str_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zss|s",
- &arg_pattern_zval,
- &replace, &replace_len,
- &string, &string_len,
- &option_str, &option_str_len) == FAILURE) {
- RETURN_FALSE;
+ if (!is_callable) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zss|s",
+ &arg_pattern_zval,
+ &replace, &replace_len,
+ &string, &string_len,
+ &option_str, &option_str_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zfs|s",
+ &arg_pattern_zval,
+ &arg_replace_fci, &arg_replace_fci_cache,
+ &string, &string_len,
+ &option_str, &option_str_len) == FAILURE) {
+ RETURN_FALSE;
+ }
}
if (option_str != NULL) {
@@ -859,7 +872,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
RETURN_FALSE;
}
- if (eval) {
+ if (eval || is_callable) {
pbuf = &eval_buf;
description = zend_make_compiled_string_description("mbregex replace" TSRMLS_CC);
} else {
@@ -867,6 +880,13 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
description = NULL;
}
+ if (is_callable) {
+ if (eval) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option 'e' cannot be used with replacement callback");
+ RETURN_FALSE;
+ }
+ }
+
/* do the actual work */
err = 0;
pos = (OnigUChar *)string;
@@ -889,28 +909,32 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
#endif
/* copy the part of the string before the match */
smart_str_appendl(&out_buf, pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos));
- /* copy replacement and backrefs */
- i = 0;
- p = replace;
- while (i < replace_len) {
- int fwd = (int) php_mb_mbchar_bytes_ex(p, enc);
- n = -1;
- if ((replace_len - i) >= 2 && fwd == 1 &&
+
+ if (!is_callable) {
+ /* copy replacement and backrefs */
+ i = 0;
+ p = replace;
+ while (i < replace_len) {
+ int fwd = (int) php_mb_mbchar_bytes_ex(p, enc);
+ n = -1;
+ if ((replace_len - i) >= 2 && fwd == 1 &&
p[0] == '\\' && p[1] >= '0' && p[1] <= '9') {
- n = p[1] - '0';
- }
- if (n >= 0 && n < regs->num_regs) {
- if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && regs->end[n] <= string_len) {
- smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]);
+ n = p[1] - '0';
+ }
+ if (n >= 0 && n < regs->num_regs) {
+ if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && regs->end[n] <= string_len) {
+ smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]);
+ }
+ p += 2;
+ i += 2;
+ } else {
+ smart_str_appendl(pbuf, p, fwd);
+ p += fwd;
+ i += fwd;
}
- p += 2;
- i += 2;
- } else {
- smart_str_appendl(pbuf, p, fwd);
- p += fwd;
- i += fwd;
}
}
+
if (eval) {
zval v;
/* null terminate buffer */
@@ -928,7 +952,40 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
/* Clean up */
eval_buf.len = 0;
zval_dtor(&v);
+ } else if (is_callable) {
+ zval *retval_ptr;
+ zval **args[1];
+ zval *subpats;
+ int i;
+
+ MAKE_STD_ZVAL(subpats);
+ array_init(subpats);
+
+ for (i = 0; i < regs->num_regs; i++) {
+ add_next_index_stringl(subpats, string + regs->beg[i], regs->end[i] - regs->beg[i], 1);
+ }
+
+ args[0] = &subpats;
+ /* null terminate buffer */
+ smart_str_0(&eval_buf);
+
+ arg_replace_fci.param_count = 1;
+ arg_replace_fci.params = args;
+ arg_replace_fci.retval_ptr_ptr = &retval_ptr;
+ if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr) {
+ convert_to_string_ex(&retval_ptr);
+ smart_str_appendl(&out_buf, Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr));
+ eval_buf.len = 0;
+ zval_ptr_dtor(&retval_ptr);
+ } else {
+ efree(description);
+ if (!EG(exception)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call custom replacement function");
+ }
+ }
+ zval_ptr_dtor(&subpats);
}
+
n = regs->end[0];
if ((pos - (OnigUChar *)string) < n) {
pos = (OnigUChar *)string + n;
@@ -969,7 +1026,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
Replace regular expression for multibyte string */
PHP_FUNCTION(mb_ereg_replace)
{
- _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
}
/* }}} */
@@ -977,7 +1034,15 @@ PHP_FUNCTION(mb_ereg_replace)
Case insensitive replace regular expression for multibyte string */
PHP_FUNCTION(mb_eregi_replace)
{
- _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, ONIG_OPTION_IGNORECASE);
+ _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, ONIG_OPTION_IGNORECASE, 0);
+}
+/* }}} */
+
+/* {{{ proto string mb_ereg_replace_callback(string pattern, string callback, string string [, string option])
+ regular expression for multibyte string using replacement callback */
+PHP_FUNCTION(mb_ereg_replace_callback)
+{
+ _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
}
/* }}} */
diff --git a/ext/mbstring/php_mbregex.h b/ext/mbstring/php_mbregex.h
index 37b65091dd..2464c1b1c8 100644
--- a/ext/mbstring/php_mbregex.h
+++ b/ext/mbstring/php_mbregex.h
@@ -34,6 +34,7 @@
PHP_FE(mb_eregi, arginfo_mb_eregi) \
PHP_FE(mb_ereg_replace, arginfo_mb_ereg_replace) \
PHP_FE(mb_eregi_replace, arginfo_mb_eregi_replace) \
+ PHP_FE(mb_ereg_replace_callback, arginfo_mb_ereg_replace_callback) \
PHP_FE(mb_split, arginfo_mb_split) \
PHP_FE(mb_ereg_match, arginfo_mb_ereg_match) \
PHP_FE(mb_ereg_search, arginfo_mb_ereg_search) \
@@ -81,6 +82,7 @@ PHP_FUNCTION(mb_ereg);
PHP_FUNCTION(mb_eregi);
PHP_FUNCTION(mb_ereg_replace);
PHP_FUNCTION(mb_eregi_replace);
+PHP_FUNCTION(mb_ereg_replace_callback);
PHP_FUNCTION(mb_split);
PHP_FUNCTION(mb_ereg_match);
PHP_FUNCTION(mb_ereg_search);
diff --git a/ext/mbstring/tests/bug20087.phpt b/ext/mbstring/tests/bug20087.phpt
index d2530fa22e..01bcc90388 100644
--- a/ext/mbstring/tests/bug20087.phpt
+++ b/ext/mbstring/tests/bug20087.phpt
@@ -2,6 +2,8 @@
Bug #20087 (Assertion failure)
--SKIPIF--
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FAIL--
+register_globals calls killed the ability for mb_parse_str() to register into the global scope
--FILE--
<?php
ini_set('include_path', dirname(__FILE__));
diff --git a/ext/mbstring/tests/bug28220.phpt b/ext/mbstring/tests/bug28220.phpt
index f195606a15..527fdc6fe3 100644
--- a/ext/mbstring/tests/bug28220.phpt
+++ b/ext/mbstring/tests/bug28220.phpt
@@ -21,5 +21,5 @@ foreach ($coderange as $r) {
}
?>
--EXPECT--
-8101
+8085
63
diff --git a/ext/mbstring/tests/bug40685.phpt b/ext/mbstring/tests/bug40685.phpt
index 420b916bc5..1a673e5d15 100644
--- a/ext/mbstring/tests/bug40685.phpt
+++ b/ext/mbstring/tests/bug40685.phpt
@@ -8,13 +8,18 @@ $map = array(0, 0x10FFFF, 0, 0xFFFFFF);
var_dump(mb_decode_numericentity('&', $map, 'UTF-8'));
var_dump(mb_decode_numericentity('&&&', $map, 'UTF-8'));
var_dump(mb_decode_numericentity('&#', $map, 'UTF-8'));
+var_dump(mb_decode_numericentity('&#x', $map, 'UTF-8'));
var_dump(mb_decode_numericentity('&#61', $map, 'UTF-8'));
+var_dump(mb_decode_numericentity('&#x3d', $map, 'UTF-8'));
var_dump(mb_decode_numericentity('&#61;', $map, 'UTF-8'));
+var_dump(mb_decode_numericentity('&#x3d;', $map, 'UTF-8'));
?>
--EXPECTF--
string(1) "&"
string(3) "&&&"
string(2) "&#"
+string(3) "&#x"
string(4) "&#61"
+string(5) "&#x3D"
+string(1) "="
string(1) "="
-
diff --git a/ext/mbstring/tests/bug43301.phpt b/ext/mbstring/tests/bug43301.phpt
index 310426a142..2a5f748c5b 100644
--- a/ext/mbstring/tests/bug43301.phpt
+++ b/ext/mbstring/tests/bug43301.phpt
@@ -15,7 +15,7 @@ echo mb_ereg_replace($ptr,'$1',$txt,'e');
?>
--EXPECTF--
-Parse error: syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in %sbug43301.php(%d) : mbregex replace on line 1
+Parse error: syntax error, unexpected %s, expecting %s or '$' in %sbug43301.php(%d) : mbregex replace on line %d
Fatal error: mb_ereg_replace(): Failed evaluating code:
$1 in %sbug43301.php on line %d
diff --git a/ext/mbstring/tests/bug49536.phpt b/ext/mbstring/tests/bug49536.phpt
index 32685d2267..40328f79f0 100644
--- a/ext/mbstring/tests/bug49536.phpt
+++ b/ext/mbstring/tests/bug49536.phpt
@@ -16,5 +16,5 @@ var_dump(mb_detect_encoding("\xc0\x00", "UTF-8", true));
--EXPECT--
string(4) "SJIS"
bool(false)
-string(5) "UTF-8"
+bool(false)
bool(false)
diff --git a/ext/mbstring/tests/bug60306.phpt b/ext/mbstring/tests/bug60306.phpt
new file mode 100644
index 0000000000..f7969e1952
--- /dev/null
+++ b/ext/mbstring/tests/bug60306.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #60306 (Characters lost while converting from cp936 to utf8)
+--SKIPIF--
+<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FILE--
+<?php
+$s = "æ´ªä»çŽ•";
+var_dump($s === mb_convert_encoding(mb_convert_encoding($s, "cp936", "utf8"), "utf8", "cp936"));
+?>
+--EXPECT--
+bool(true)
diff --git a/ext/mbstring/tests/htmlent.phpt b/ext/mbstring/tests/htmlent.phpt
index 33c3a5be52..5af96c7c41 100644
--- a/ext/mbstring/tests/htmlent.phpt
+++ b/ext/mbstring/tests/htmlent.phpt
@@ -15,6 +15,7 @@ mbstring.http_input=HTML-ENTITIES
mbstring.internal_encoding=UTF-8
mbstring.http_output=HTML-ENTITIES
mbstring.encoding_translation=1
+filter.default=unsafe_raw
--FILE--
<?php
// enable output encoding through output handler
diff --git a/ext/mbstring/tests/illformed_utf_sequences.phpt b/ext/mbstring/tests/illformed_utf_sequences.phpt
index a462cd0745..b5b9d94db8 100644
--- a/ext/mbstring/tests/illformed_utf_sequences.phpt
+++ b/ext/mbstring/tests/illformed_utf_sequences.phpt
@@ -4,145 +4,214 @@ Unicode standard conformance test (ill-formed UTF sequences.)
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
--FILE--
<?php
+function chk_enc($str, $n, $enc = "UTF-8", $with_bom = false) {
+ $src = bin2hex(mb_convert_encoding($str, "UCS-4BE", $enc));
+ $dst = str_repeat("0000fffd", $n);
+ if ($with_bom) {
+ $dst = "0000feff" . $dst;
+ }
+ if ($dst == $src) {
+ return false;
+ } else {
+ return $src;
+ }
+}
+
+mb_substitute_character(0xfffd);
+
+
echo "UTF-8 redundancy\n";
-var_dump(bin2hex(mb_convert_encoding("\x31\x32\x33", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\x41\x42\x43", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xc0\xb1\xc0\xb2\xc0\xb3", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xc1\x81\xc1\x82\xc1\x83", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf8\x80\x80\x80\xb1\xf8\x80\x80\x80\xb2\xf8\x80\x80\x80\xb3", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf8\x80\x80\x81\x81\xf8\x80\x80\x81\x82\xf8\x80\x80\x81\x83", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfc\x80\x80\x80\x80\xb1\xfc\x80\x80\x80\x80\xb2\xfc\x80\x80\x80\x80\xb3", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfc\x80\x80\x80\x81\x81\xfc\x80\x80\x80\x81\x82\xfc\x80\x80\x80\x81\x83", "UCS-4BE", "UTF-8")));
+var_dump(chk_enc("\x31\x32\x33", 0));
+var_dump(chk_enc("\x41\x42\x43", 0));
+var_dump(chk_enc("\xc0\xb1\xc0\xb2\xc0\xb3", 6));
+var_dump(chk_enc("\xc1\x81\xc1\x82\xc1\x83", 6));
+var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 6));
+var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 6));
+var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 9));
+var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 8));
+var_dump(chk_enc("\xf8\x80\x80\x80\xb1\xf8\x80\x80\x80\xb2\xf8\x80\x80\x80\xb3", 15));
+var_dump(chk_enc("\xf8\x80\x80\x81\x81\xf8\x80\x80\x81\x82\xf8\x80\x80\x81\x83", 15));
+var_dump(chk_enc("\xfc\x80\x80\x80\x80\xb1\xfc\x80\x80\x80\x80\xb2\xfc\x80\x80\x80\x80\xb3", 18));
+var_dump(chk_enc("\xfc\x80\x80\x80\x81\x81\xfc\x80\x80\x80\x81\x82\xfc\x80\x80\x80\x81\x83", 18));
-var_dump(bin2hex(mb_convert_encoding("\xc2\xa2\xc2\xa3\xc2\xa5", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf8\x80\x80\x82\xa2\xf8\x80\x80\x82\xa3\xf8\x80\x80\x82\xa5", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfc\x80\x80\x80\x82\xa2\xfc\x80\x80\x80\x82\xa3\xfc\x80\x80\x80\x82\xa5", "UCS-4BE", "UTF-8")));
+var_dump(chk_enc("\xc2\xa2\xc2\xa3\xc2\xa5", 0));
+var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 6));
+var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 9));
+var_dump(chk_enc("\xf8\x80\x80\x82\xa2\xf8\x80\x80\x82\xa3\xf8\x80\x80\x82\xa5", 15));
+var_dump(chk_enc("\xfc\x80\x80\x80\x82\xa2\xfc\x80\x80\x80\x82\xa3\xfc\x80\x80\x80\x82\xa5", 18));
-var_dump(bin2hex(mb_convert_encoding("\xc1\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xc2\x80", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xdf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xe0\x9f\xff", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xe0\xa0\x80", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xef\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf0\x8f\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf0\x90\x80\x80", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf7\xbf\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf8\x87\xbf\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xf8\x88\x80\x80\x80", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfb\xbf\xbf\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfc\x83\xbf\xbf\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfc\x84\x80\x80\x80\x80", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfd\xaf\xbf\xbf\xbf\xbf", "UCS-4BE", "UTF-8")));
-var_dump(bin2hex(mb_convert_encoding("\xfd\xbf\xbf\xbf\xbf\xbf", "UCS-4BE", "UTF-8")));
+var_dump(chk_enc("\xc1\xbf", 2));
+var_dump(chk_enc("\xc2\x80", 0));
+var_dump(chk_enc("\xdf\xbf", 0));
+var_dump(chk_enc("\xe0\x9f\xff", 2));
+var_dump(chk_enc("\xe0\xa0\x80", 2));
+var_dump(chk_enc("\xef\xbf\xbf", 0));
+var_dump(chk_enc("\xf0\x8f\xbf\xbf", 3));
+var_dump(chk_enc("\xf0\x90\x80\x80", 0));
+var_dump(chk_enc("\xf7\xbf\xbf\xbf", 4));
+var_dump(chk_enc("\xf8\x87\xbf\xbf\xbf", 5));
+var_dump(chk_enc("\xf8\x88\x80\x80\x80", 5));
+var_dump(chk_enc("\xfb\xbf\xbf\xbf\xbf", 5));
+var_dump(chk_enc("\xfc\x83\xbf\xbf\xbf\xbf", 6));
+var_dump(chk_enc("\xfc\x84\x80\x80\x80\x80", 6));
+var_dump(chk_enc("\xfd\xaf\xbf\xbf\xbf\xbf", 6));
+var_dump(chk_enc("\xfd\xbf\xbf\xbf\xbf\xbf", 6));
echo "UTF-8 and surrogates area\n";
$out = '';
+$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
- $out .= mb_convert_encoding(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), "UCS-4BE", "UTF-8");
+ $s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 2);
+ if ($s === false) {
+ $cnt++;
+ } else {
+ $out .= $s;
+ }
}
-var_dump(bin2hex($out));
+var_dump($cnt);
+var_dump($out);
echo "UTF-32 code range\n";
-var_dump(bin2hex(mb_convert_encoding("\x00\x11\x00\x00", "UCS-4BE", "UTF-32BE")));
-var_dump(bin2hex(mb_convert_encoding("\x00\x10\xff\xff", "UCS-4BE", "UTF-32BE")));
-var_dump(bin2hex(mb_convert_encoding("\x00\x00\x11\x00", "UCS-4BE", "UTF-32LE")));
-var_dump(bin2hex(mb_convert_encoding("\xff\xff\x10\x00", "UCS-4BE", "UTF-32LE")));
-var_dump(bin2hex(mb_convert_encoding("\x00\x11\x00\x00", "UCS-4BE", "UTF-32")));
-var_dump(bin2hex(mb_convert_encoding("\x00\x10\xff\xff", "UCS-4BE", "UTF-32")));
-var_dump(bin2hex(mb_convert_encoding("\x00\x00\xfe\xff\x00\x11\x00\x00", "UCS-4BE", "UTF-32")));
-var_dump(bin2hex(mb_convert_encoding("\x00\x00\xfe\xff\x00\x10\xff\xff", "UCS-4BE", "UTF-32")));
-var_dump(bin2hex(mb_convert_encoding("\xff\xfe\x00\x00\x00\x00\x11\x00", "UCS-4BE", "UTF-32")));
-var_dump(bin2hex(mb_convert_encoding("\xff\xfe\x00\x00\xff\xff\x10\x00", "UCS-4BE", "UTF-32")));
+var_dump(chk_enc("\x00\x11\x00\x00", 1, "UTF-32BE"));
+var_dump(chk_enc("\x00\x10\xff\xff", 0, "UTF-32BE"));
+var_dump(chk_enc("\x00\x00\x11\x00", 1, "UTF-32LE"));
+var_dump(chk_enc("\xff\xff\x10\x00", 0, "UTF-32LE"));
+var_dump(chk_enc("\x00\x11\x00\x00", 1, "UTF-32"));
+var_dump(chk_enc("\x00\x10\xff\xff", 0, "UTF-32"));
+var_dump(chk_enc("\x00\x00\xfe\xff\x00\x11\x00\x00", 0, "UTF-32"));
+var_dump(chk_enc("\x00\x00\xfe\xff\x00\x10\xff\xff", 0, "UTF-32"));
+var_dump(chk_enc("\xff\xfe\x00\x00\x00\x00\x11\x00", 0, "UTF-32"));
+var_dump(chk_enc("\xff\xfe\x00\x00\xff\xff\x10\x00", 0, "UTF-32"));
echo "UTF-32 and surrogates area\n";
$out = '';
+$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
- $out .= mb_convert_encoding(pack('C4', $i >> 24, ($i >> 16) & 0xff, ($i >> 8) & 0xff, $i & 0xff), "UCS-4BE", "UTF-32BE");
+ $s = chk_enc(pack('C4', $i >> 24, ($i >> 16) & 0xff, ($i >> 8) & 0xff, $i & 0xff), 1, "UTF-32BE");
+ if ($s === false) {
+ $cnt++;
+ } else {
+ $out .= $s;
+ }
}
-var_dump(bin2hex($out));
+var_dump($cnt);
+var_dump($out);
$out = '';
+$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
- $out .= mb_convert_encoding(pack('C4', $i & 0xff, ($i >> 8) & 0xff, ($i >> 16) & 0xff, ($i >> 24) & 0xff), "UCS-4BE", "UTF-32LE");
+ $s = chk_enc(pack('C4', $i & 0xff, ($i >> 8) & 0xff, ($i >> 16) & 0xff, ($i >> 24) & 0xff), 1, "UTF-32LE");
+ if ($s === false) {
+ $cnt++;
+ } else {
+ $out .= $s;
+ }
}
-var_dump(bin2hex($out));
+var_dump($cnt);
+var_dump($out);
$out = '';
+$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
- $out .= mb_convert_encoding(pack('C4', $i >> 24, ($i >> 16) & 0xff, ($i >> 8) & 0xff, $i & 0xff), "UCS-4BE", "UTF-32");
+ $s = chk_enc(pack('C4', $i >> 24, ($i >> 16) & 0xff, ($i >> 8) & 0xff, $i & 0xff), 1, "UTF-32");
+ if ($s === false) {
+ $cnt++;
+ } else {
+ $out .= $s;
+ }
}
-var_dump(bin2hex($out));
+var_dump($cnt);
+var_dump($out);
+
+echo "UTF-32 and surrogates area with BOM\n";
$out = '';
+$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
- $out .= mb_convert_encoding("\x00\x00\xfe\xff". pack('C4', $i >> 24, ($i >> 16) & 0xff, ($i >> 8) & 0xff, $i & 0xff), "UCS-4BE", "UTF-32");
+ $s = chk_enc("\x00\x00\xfe\xff". pack('C4', $i >> 24, ($i >> 16) & 0xff, ($i >> 8) & 0xff, $i & 0xff),
+ 1, "UTF-32", true);
+ if ($s === false) {
+ $cnt++;
+ } else {
+ $out .= $s;
+ }
}
-var_dump(bin2hex(str_replace("\x00\x00\xfe\xff", "", $out)));
-
+var_dump($cnt);
+var_dump(str_replace("0000feff","",$out));
$out = '';
+$cnt = 0;
for ($i = 0xd7ff; $i <= 0xe000; ++$i) {
- $out .= mb_convert_encoding("\xff\xfe\x00\x00". pack('C4', $i & 0xff, ($i >> 8) & 0xff, ($i >> 16) & 0xff, ($i >> 24) & 0xff), "UCS-4BE", "UTF-32");
+ $s = chk_enc("\xff\xfe\x00\x00". pack('C4', $i & 0xff, ($i >> 8) & 0xff, ($i >> 16) & 0xff, ($i >> 24) & 0xff),
+ 1, "UTF-32", true);
+ if ($s === false) {
+ $cnt++;
+ } else {
+ $out .= $s;
+ }
}
-var_dump(bin2hex(str_replace("\x00\x00\xfe\xff", "", $out)));
+var_dump($cnt);
+var_dump(str_replace("0000feff","",$out));
+
?>
--EXPECT--
UTF-8 redundancy
string(24) "000000310000003200000033"
string(24) "000000410000004200000043"
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
string(24) "000000a2000000a3000000a5"
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
-string(0) ""
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
string(8) "00000080"
string(8) "000007ff"
-string(0) ""
+bool(false)
string(8) "00000800"
string(8) "0000ffff"
-string(0) ""
+bool(false)
string(8) "00010000"
-string(8) "001fffff"
-string(0) ""
-string(8) "00200000"
-string(8) "03ffffff"
-string(0) ""
-string(8) "04000000"
-string(8) "6fffffff"
-string(0) ""
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
UTF-8 and surrogates area
+int(2048)
string(16) "0000d7ff0000e000"
UTF-32 code range
-string(0) ""
+bool(false)
string(8) "0010ffff"
-string(0) ""
+bool(false)
string(8) "0010ffff"
-string(0) ""
+bool(false)
string(8) "0010ffff"
-string(8) "0000feff"
+string(16) "0000feff0000fffd"
string(16) "0000feff0010ffff"
-string(8) "0000feff"
+string(16) "0000feff0000fffd"
string(16) "0000feff0010ffff"
UTF-32 and surrogates area
+int(2048)
string(16) "0000d7ff0000e000"
+int(2048)
string(16) "0000d7ff0000e000"
+int(2048)
string(16) "0000d7ff0000e000"
+UTF-32 and surrogates area with BOM
+int(2048)
string(16) "0000d7ff0000e000"
+int(2048)
string(16) "0000d7ff0000e000"
diff --git a/ext/mbstring/tests/mb_encoding_aliases.phpt b/ext/mbstring/tests/mb_encoding_aliases.phpt
index 2159481efe..8ef299425a 100644
--- a/ext/mbstring/tests/mb_encoding_aliases.phpt
+++ b/ext/mbstring/tests/mb_encoding_aliases.phpt
@@ -13,26 +13,28 @@ var_dump(mb_encoding_aliases("8bit"));
?>
--EXPECTF--
Warning: mb_encoding_aliases() expects exactly 1 parameter, 0 given in %s on line 2
-array(10) {
+array(11) {
[0]=>
string(14) "ANSI_X3.4-1968"
[1]=>
string(14) "ANSI_X3.4-1986"
[2]=>
- string(6) "IBM367"
+ string(7) "IBM-367"
[3]=>
- string(9) "ISO646-US"
+ string(6) "IBM367"
[4]=>
- string(16) "ISO_646.irv:1991"
+ string(9) "ISO646-US"
[5]=>
- string(8) "US-ASCII"
+ string(16) "ISO_646.irv:1991"
[6]=>
- string(5) "cp367"
+ string(8) "US-ASCII"
[7]=>
- string(7) "csASCII"
+ string(5) "cp367"
[8]=>
- string(8) "iso-ir-6"
+ string(7) "csASCII"
[9]=>
+ string(8) "iso-ir-6"
+ [10]=>
string(2) "us"
}
array(0) {
diff --git a/ext/mbstring/tests/mb_ereg_replace_callback.phpt b/ext/mbstring/tests/mb_ereg_replace_callback.phpt
new file mode 100644
index 0000000000..98a3809574
--- /dev/null
+++ b/ext/mbstring/tests/mb_ereg_replace_callback.phpt
@@ -0,0 +1,15 @@
+--TEST--
+mb_ereg_replace_callback()
+--SKIPIF--
+<?php
+extension_loaded('mbstring') or die('skip mbstring not available');
+function_exists('mb_ereg_replace_callback') or die("skip mb_ereg_replace_callback() is not available in this build");
+?>
+--FILE--
+<?php
+$str = 'abc 123 #",; $foo';
+echo mb_ereg_replace_callback('(\S+)', function($m){return $m[1].'('.strlen($m[1]).')';}, $str);
+?>
+--EXPECT--
+abc(3) 123(3) #",;(4) $foo(4)
+
diff --git a/ext/mbstring/tests/mb_internal_encoding_variation2.phpt b/ext/mbstring/tests/mb_internal_encoding_variation2.phpt
index 3d2c547313..914041c914 100644
--- a/ext/mbstring/tests/mb_internal_encoding_variation2.phpt
+++ b/ext/mbstring/tests/mb_internal_encoding_variation2.phpt
@@ -330,10 +330,10 @@ string(6) "EUC-TW"
-- Iteration 48 --
string(6) "EUC-TW"
bool(true)
-string(5) "BIG-5"
+string(5) "CP950"
-- Iteration 49 --
-string(5) "BIG-5"
+string(5) "CP950"
bool(true)
string(5) "BIG-5"
diff --git a/ext/mbstring/tests/mb_parse_str.phpt b/ext/mbstring/tests/mb_parse_str.phpt
index 8b320b0845..59d187bd05 100644
--- a/ext/mbstring/tests/mb_parse_str.phpt
+++ b/ext/mbstring/tests/mb_parse_str.phpt
@@ -2,9 +2,10 @@
mb_parse_str()
--SKIPIF--
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FAIL--
+register_globals calls killed the ability for mb_parse_str() to register into the global scope
--INI--
arg_separator.input=&
-register_globals=0
--FILE--
<?php
$queries = array(
diff --git a/ext/mbstring/tests/mb_parse_str02.phpt b/ext/mbstring/tests/mb_parse_str02.phpt
index 51cfb63cb9..f35699928e 100644
--- a/ext/mbstring/tests/mb_parse_str02.phpt
+++ b/ext/mbstring/tests/mb_parse_str02.phpt
@@ -2,9 +2,10 @@
mb_parse_str() test 2
--SKIPIF--
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FAIL--
+register_globals calls killed the ability for mb_parse_str() to register into the global scope
--INI--
arg_separator.input=&#
-register_globals=0
--FILE--
<?php
$queries = array(
diff --git a/ext/mbstring/tests/mb_str_functions_opt-parameter.phpt b/ext/mbstring/tests/mb_str_functions_opt-parameter.phpt
new file mode 100644
index 0000000000..5fb642f9b2
--- /dev/null
+++ b/ext/mbstring/tests/mb_str_functions_opt-parameter.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Optional long parameter might be null
+--FILE--
+<?php
+echo mb_strpos('abb', 'b', null, 'UTF-8') . "\n";
+echo mb_strrpos('abb', 'b', null, 'UTF-8') . "\n";
+echo mb_stripos('abb', 'B', null, 'UTF-8') . "\n";
+echo mb_strripos('abb', 'B', null, 'UTF-8') . "\n";
+echo mb_strstr('foobarbaz', 'ba', null, 'UTF-8') . "\n";
+echo mb_strrchr('foobarbaz', 'ba', null, 'UTF-8') . "\n";
+echo mb_stristr('foobarbaz', 'BA', null, 'UTF-8') . "\n";
+echo mb_strrichr('foobarbaz', 'BA', null, 'UTF-8') . "\n";
+echo mb_substr('foobarbaz', 6, null, 'UTF-8') . "\n";
+echo mb_strcut('foobarbaz', 6, null, 'UTF-8') . "\n";
+echo mb_strimwidth('foobar', 0, 3, null, 'UTF-8') . "\n";
+?>
+==DONE==
+--EXPECT--
+1
+2
+1
+2
+barbaz
+baz
+barbaz
+baz
+baz
+baz
+foo
+==DONE==
diff --git a/ext/mbstring/tests/pictogram1.phpt b/ext/mbstring/tests/pictogram1.phpt
new file mode 100644
index 0000000000..2c9609939a
--- /dev/null
+++ b/ext/mbstring/tests/pictogram1.phpt
@@ -0,0 +1,172 @@
+--TEST--
+Emoji (Pictogram characters for cellular phone in Japan) test based on Unicode 6.0
+--SKIPIF--
+<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FILE--
+<?php
+mb_substitute_character(0x3f);
+
+echo "SJIS-Mobile to Unicode\n";
+var_dump(bin2hex(mb_convert_encoding("\xf8\x9f", "UCS-4BE", "SJIS-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xf6\x60", "UCS-4BE", "SJIS-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xf9\x8b", "UCS-4BE", "SJIS-Mobile#SOFTBANK")));
+
+var_dump(bin2hex(mb_convert_encoding("\xf9\xe6", "UCS-4BE", "SJIS-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xf6\xec", "UCS-4BE", "SJIS-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xf7\x50", "UCS-4BE", "SJIS-Mobile#SOFTBANK")));
+
+var_dump(bin2hex(mb_convert_encoding("\xf9\x85", "UCS-4BE", "SJIS-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xf4\x89", "UCS-4BE", "SJIS-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xf7\xb0", "UCS-4BE", "SJIS-Mobile#SOFTBANK")));
+
+var_dump(bin2hex(mb_convert_encoding("\xf3\xd2", "UCS-4BE", "SJIS-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xfb\xb3", "UCS-4BE", "SJIS-Mobile#SOFTBANK")));
+
+echo "Unicode to SJIS-Mobile\n";
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "SJIS-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "SJIS-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "SJIS-Mobile#SOFTBANK", "UCS-4BE")));
+
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf3\x40", "SJIS-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf3\x40", "SJIS-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf3\x40", "SJIS-Mobile#SOFTBANK", "UCS-4BE")));
+
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x00\x23\x00\x00\x20\xe3", "SJIS-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x00\x23\x00\x00\x20\xe3", "SJIS-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x00\x23\x00\x00\x20\xe3", "SJIS-Mobile#SOFTBANK", "UCS-4BE")));
+
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf1\xe8\x00\x01\xf1\xf3", "SJIS-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf1\xe8\x00\x01\xf1\xf3", "SJIS-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf1\xe8\x00\x01\xf1\xf3", "SJIS-Mobile#SOFTBANK", "UCS-4BE")));
+
+echo "UTF-8-Mobile to Unicode\n";
+var_dump(bin2hex(mb_convert_encoding("\xee\x98\xbe", "UCS-4BE", "UTF-8-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xee\xbd\xa0", "UCS-4BE", "UTF-8-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xee\x81\x8a", "UCS-4BE", "UTF-8-Mobile#SOFTBANK")));
+
+var_dump(bin2hex(mb_convert_encoding("\xee\x9d\x81", "UCS-4BE", "UTF-8-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xee\xbf\xac", "UCS-4BE", "UTF-8-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xee\x84\x90", "UCS-4BE", "UTF-8-Mobile#SOFTBANK")));
+
+var_dump(bin2hex(mb_convert_encoding("\xee\x9b\xa0", "UCS-4BE", "UTF-8-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xee\xb6\x89", "UCS-4BE", "UTF-8-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xee\x88\x90", "UCS-4BE", "UTF-8-Mobile#SOFTBANK")));
+
+var_dump(bin2hex(mb_convert_encoding("\xee\xb3\x92", "UCS-4BE", "UTF-8-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xee\x94\x93", "UCS-4BE", "UTF-8-Mobile#SOFTBANK")));
+
+echo "Unicode to UTF8-Mobile\n";
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "UTF-8-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "UTF-8-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "UTF-8-Mobile#SOFTBANK", "UCS-4BE")));
+
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf3\x40", "UTF-8-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf3\x40", "UTF-8-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf3\x40", "UTF-8-Mobile#SOFTBANK", "UCS-4BE")));
+
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x00\x23\x00\x00\x20\xe3", "UTF-8-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x00\x23\x00\x00\x20\xe3", "UTF-8-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x00\x23\x00\x00\x20\xe3", "UTF-8-Mobile#SOFTBANK", "UCS-4BE")));
+
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf1\xe8\x00\x01\xf1\xf3", "UTF-8-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf1\xe8\x00\x01\xf1\xf3", "UTF-8-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x01\xf1\xe8\x00\x01\xf1\xf3", "UTF-8-Mobile#SOFTBANK", "UCS-4BE")));
+
+echo "Unicode to ISO-2022-JP-MOBILE#KDDI\n";
+var_dump(bin2hex(mb_convert_encoding("\x00\x00\x26\x00", "ISO-2022-JP-MOBILE#KDDI", "UCS-4BE")));
+
+echo "ISO-2022-JP-MOBILE#KDDI to Unicode\n";
+var_dump(bin2hex(mb_convert_encoding("\x1b\x24\x42\x75\x41\x1b\x28\x42", "UCS-4BE", "ISO-2022-JP-MOBILE#KDDI")));
+
+echo "SJIS-Mobile to Unicode (Google) \n";
+var_dump(bin2hex(mb_convert_encoding("\xf9\x86", "UCS-4BE", "SJIS-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xf7\x48", "UCS-4BE", "SJIS-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xfb\xd8", "UCS-4BE", "SJIS-Mobile#SOFTBANK")));
+
+echo "Unicode (Google) to SJIS-Mobile\n";
+var_dump(bin2hex(mb_convert_encoding("\x00\x0f\xe8\x2d", "SJIS-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x0f\xe8\x2d", "SJIS-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x0f\xee\x70", "SJIS-Mobile#SOFTBANK", "UCS-4BE")));
+
+echo "UTF-8-Mobile to Unicode (Google) \n";
+var_dump(bin2hex(mb_convert_encoding("\xee\x9b\xa1", "UCS-4BE", "UTF-8-Mobile#DOCOMO")));
+var_dump(bin2hex(mb_convert_encoding("\xef\x81\x88", "UCS-4BE", "UTF-8-Mobile#KDDI")));
+var_dump(bin2hex(mb_convert_encoding("\xee\x94\xb8", "UCS-4BE", "UTF-8-Mobile#SOFTBANK")));//
+
+echo "Unicode (Google) to UTF-8-Mobile\n";
+var_dump(bin2hex(mb_convert_encoding("\x00\x0f\xe8\x2d", "UTF-8-Mobile#DOCOMO", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x0f\xe8\x2d", "UTF-8-Mobile#KDDI", "UCS-4BE")));
+var_dump(bin2hex(mb_convert_encoding("\x00\x0f\xee\x70", "UTF-8-Mobile#SOFTBANK", "UCS-4BE")));//
+
+?>
+--EXPECT--
+SJIS-Mobile to Unicode
+string(8) "00002600"
+string(8) "00002600"
+string(8) "00002600"
+string(8) "0001f340"
+string(8) "0001f340"
+string(8) "0001f340"
+string(16) "00000023000020e3"
+string(16) "00000023000020e3"
+string(16) "00000023000020e3"
+string(16) "0001f1e80001f1f3"
+string(16) "0001f1e80001f1f3"
+Unicode to SJIS-Mobile
+string(4) "f89f"
+string(4) "f660"
+string(4) "f98b"
+string(4) "f9e6"
+string(4) "f6ec"
+string(4) "f750"
+string(4) "f985"
+string(4) "f489"
+string(4) "f7b0"
+string(4) "3f3f"
+string(4) "f3d2"
+string(4) "fbb3"
+UTF-8-Mobile to Unicode
+string(8) "00002600"
+string(8) "00002600"
+string(8) "00002600"
+string(8) "0001f340"
+string(8) "0001f340"
+string(8) "0001f340"
+string(16) "00000023000020e3"
+string(16) "00000023000020e3"
+string(16) "00000023000020e3"
+string(16) "0001f1e80001f1f3"
+string(16) "0001f1e80001f1f3"
+Unicode to UTF8-Mobile
+string(6) "ee98be"
+string(6) "eebda0"
+string(6) "ee818a"
+string(6) "ee9d81"
+string(6) "eebfac"
+string(6) "ee8490"
+string(6) "ee9ba0"
+string(6) "eeb689"
+string(6) "ee8890"
+string(16) "f09f87a8f09f87b3"
+string(6) "eeb392"
+string(6) "ee9493"
+Unicode to ISO-2022-JP-MOBILE#KDDI
+string(16) "1b244275411b2842"
+ISO-2022-JP-MOBILE#KDDI to Unicode
+string(8) "00002600"
+SJIS-Mobile to Unicode (Google)
+string(8) "000fe82d"
+string(8) "000fe82d"
+string(8) "000fee70"
+Unicode (Google) to SJIS-Mobile
+string(4) "f986"
+string(4) "f748"
+string(4) "fbd8"
+UTF-8-Mobile to Unicode (Google)
+string(8) "000fe82d"
+string(8) "000fe82d"
+string(8) "000fee70"
+Unicode (Google) to UTF-8-Mobile
+string(6) "ee9ba1"
+string(6) "ef8188"
+string(6) "ee94b8"
diff --git a/ext/mbstring/tests/zend_multibyte-10.phpt b/ext/mbstring/tests/zend_multibyte-10.phpt
index 89c7c1c26c..435c339752 100644
--- a/ext/mbstring/tests/zend_multibyte-10.phpt
+++ b/ext/mbstring/tests/zend_multibyte-10.phpt
@@ -15,4 +15,3 @@ echo "ok\n";
?>
--EXPECTF--
ok
-
diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c
index c573939589..05f13cf59b 100644
--- a/ext/mcrypt/mcrypt.c
+++ b/ext/mcrypt/mcrypt.c
@@ -1387,7 +1387,7 @@ PHP_FUNCTION(mcrypt_create_iv)
}
iv = ecalloc(size + 1, 1);
-
+
if (source == RANDOM || source == URANDOM) {
#if PHP_WIN32
/* random/urandom equivalent on Windows */
diff --git a/ext/mcrypt/tests/blowfish.phpt b/ext/mcrypt/tests/blowfish.phpt
index bd8df9d14d..a133091d78 100644
--- a/ext/mcrypt/tests/blowfish.phpt
+++ b/ext/mcrypt/tests/blowfish.phpt
@@ -4,10 +4,12 @@ Test for blowfish compatibility
<?php if (!extension_loaded("mcrypt")) print "skip"; ?>
--FILE--
<?php
-function hex2bin($data) {
- $len = strlen($data);
- return pack("H" . $len, $data);
-}
+if(!function_exists("hex2bin")) {
+ function hex2bin($data) {
+ $len = strlen($data);
+ return pack("H" . $len, $data);
+ }
+}
print "key plain crypt guess stat\n";
$null = "\0\0\0\0\0\0\0\0";
diff --git a/ext/mssql/php_mssql.c b/ext/mssql/php_mssql.c
index 591e7f3759..a1c797c7b7 100644
--- a/ext/mssql/php_mssql.c
+++ b/ext/mssql/php_mssql.c
@@ -1527,27 +1527,17 @@ static void php_mssql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
if (Z_TYPE(result->data[result->cur_row][i]) != IS_NULL) {
char *data;
int data_len;
- int should_copy;
if (Z_TYPE(result->data[result->cur_row][i]) == IS_STRING) {
- if (PG(magic_quotes_runtime)) {
- data = php_addslashes(Z_STRVAL(result->data[result->cur_row][i]), Z_STRLEN(result->data[result->cur_row][i]), &data_len, 0 TSRMLS_CC);
- should_copy = 0;
- }
- else
- {
- data = Z_STRVAL(result->data[result->cur_row][i]);
- data_len = Z_STRLEN(result->data[result->cur_row][i]);
- should_copy = 1;
- }
+ data = Z_STRVAL(result->data[result->cur_row][i]);
+ data_len = Z_STRLEN(result->data[result->cur_row][i]);
if (result_type & MSSQL_NUM) {
- add_index_stringl(return_value, i, data, data_len, should_copy);
- should_copy = 1;
+ add_index_stringl(return_value, i, data, data_len, 1);
}
if (result_type & MSSQL_ASSOC) {
- add_assoc_stringl(return_value, result->fields[i].name, data, data_len, should_copy);
+ add_assoc_stringl(return_value, result->fields[i].name, data, data_len, 1);
}
}
else if (Z_TYPE(result->data[result->cur_row][i]) == IS_LONG) {
@@ -2005,7 +1995,7 @@ PHP_FUNCTION(mssql_init)
statement->link = mssql_ptr;
statement->executed=FALSE;
- statement->id = zend_list_insert(statement,le_statement);
+ statement->id = zend_list_insert(statement,le_statement TSRMLS_CC);
RETURN_RESOURCE(statement->id);
}
diff --git a/ext/mysql/config.m4 b/ext/mysql/config.m4
index e7d598fe05..5968c43346 100644
--- a/ext/mysql/config.m4
+++ b/ext/mysql/config.m4
@@ -41,8 +41,8 @@ AC_DEFUN([PHP_MYSQL_SOCKET_SEARCH], [
PHP_ARG_WITH(mysql, for MySQL support,
[ --with-mysql[=DIR] Include MySQL support. DIR is the MySQL base
- directory. If mysqlnd is passed as DIR,
- the MySQL native driver will be used [/usr/local]])
+ directory, if no DIR is passed or the value is
+ mysqlnd the MySQL native driver will be used])
PHP_ARG_WITH(mysql-sock, for specified location of the MySQL UNIX socket,
[ --with-mysql-sock[=DIR] MySQL/MySQLi/PDO_MYSQL: Location of the MySQL unix socket pointer.
@@ -53,7 +53,7 @@ if test -z "$PHP_ZLIB_DIR"; then
[ --with-zlib-dir[=DIR] MySQL: Set the path to libz install prefix], no, no)
fi
-if test "$PHP_MYSQL" = "mysqlnd"; then
+if test "$PHP_MYSQL" = "yes" || test "$PHP_MYSQL" = "mysqlnd"; then
dnl enables build of mysqnd library
PHP_MYSQLND_ENABLED=yes
@@ -61,17 +61,15 @@ elif test "$PHP_MYSQL" != "no"; then
MYSQL_DIR=
MYSQL_INC_DIR=
- for i in $PHP_MYSQL /usr/local /usr; do
- if test -r $i/include/mysql/mysql.h; then
- MYSQL_DIR=$i
- MYSQL_INC_DIR=$i/include/mysql
- break
- elif test -r $i/include/mysql.h; then
- MYSQL_DIR=$i
- MYSQL_INC_DIR=$i/include
- break
- fi
- done
+ if test -r $PHP_MYSQL/include/mysql/mysql.h; then
+ MYSQL_DIR=$PHP_MYSQL
+ MYSQL_INC_DIR=$PHP_MYSQL/include/mysql
+ break
+ elif test -r $PHP_MYSQL/include/mysql.h; then
+ MYSQL_DIR=$PHP_MYSQL
+ MYSQL_INC_DIR=$PHP_MYSQL/include
+ break
+ fi
if test -z "$MYSQL_DIR"; then
AC_MSG_ERROR([Cannot find MySQL header files under $PHP_MYSQL.
@@ -162,7 +160,7 @@ if test "$PHP_MYSQL" != "no"; then
PHP_NEW_EXTENSION(mysql, php_mysql.c, $ext_shared)
PHP_SUBST(MYSQL_SHARED_LIBADD)
- if test "$PHP_MYSQL" = "mysqlnd"; then
+ if test "$PHP_MYSQL" = "yes" || test "$PHP_MYSQL" = "mysqlnd"; then
PHP_ADD_EXTENSION_DEP(mysql, mysqlnd)
AC_DEFINE([MYSQL_USE_MYSQLND], 1, [Whether mysqlnd is enabled])
fi
diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c
index f862642a05..d6a0c94677 100644
--- a/ext/mysql/php_mysql.c
+++ b/ext/mysql/php_mysql.c
@@ -252,7 +252,7 @@ static const zend_function_entry mysql_functions[] = {
PHP_FE(mysql_query, arginfo_mysql_query)
PHP_FE(mysql_unbuffered_query, arginfo_mysql_query)
PHP_DEP_FE(mysql_db_query, arginfo_mysql_db_query)
- PHP_FE(mysql_list_dbs, arginfo__optional_mysql_link)
+ PHP_DEP_FE(mysql_list_dbs, arginfo__optional_mysql_link)
PHP_DEP_FE(mysql_list_tables, arginfo_mysql_select_db)
PHP_FE(mysql_list_fields, arginfo_mysql_list_fields)
PHP_FE(mysql_list_processes, arginfo__optional_mysql_link)
@@ -529,6 +529,32 @@ static PHP_GINIT_FUNCTION(mysql)
}
/* }}} */
+#ifdef MYSQL_USE_MYSQLND
+#include "ext/mysqlnd/mysqlnd_reverse_api.h"
+static MYSQLND * mysql_convert_zv_to_mysqlnd(zval * zv TSRMLS_DC)
+{
+ php_mysql_conn *mysql;
+
+ if (Z_TYPE_P(zv) != IS_RESOURCE) {
+ /* Might be nicer to check resource type, too, but ext/mysql is the only one using resources so emitting an error is not to bad, while usually this hook should be silent */
+ return NULL;
+ }
+
+ mysql = (php_mysql_conn *)zend_fetch_resource(&zv TSRMLS_CC, -1, "MySQL-Link", NULL, 2, le_link, le_plink);
+
+ if (!mysql) {
+ return NULL;
+ }
+
+ return mysql->conn;
+}
+
+static MYSQLND_REVERSE_API mysql_reverse_api = {
+ &mysql_module_entry,
+ mysql_convert_zv_to_mysqlnd
+};
+#endif
+
/* {{{ PHP_MINIT_FUNCTION
*/
ZEND_MODULE_STARTUP_D(mysql)
@@ -557,6 +583,10 @@ ZEND_MODULE_STARTUP_D(mysql)
#endif
#endif
+#ifdef MYSQL_USE_MYSQLND
+ mysqlnd_reverse_api_register_api(&mysql_reverse_api TSRMLS_CC);
+#endif
+
return SUCCESS;
}
/* }}} */
@@ -735,7 +765,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "SQL safe mode in effect - ignoring host/user/password information");
}
host_and_port=passwd=NULL;
- user=php_get_current_user();
+ user=php_get_current_user(TSRMLS_C);
hashed_details_length = spprintf(&hashed_details, 0, "mysql__%s_", user);
client_flags = CLIENT_INTERACTIVE;
} else {
@@ -1579,11 +1609,13 @@ PHP_FUNCTION(mysql_list_dbs)
id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
CHECK_LINK(id);
}
+ php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "This function is deprecated; use mysql_query() with SHOW DATABASES instead");
ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);
PHPMY_UNBUFFERED_QUERY_CHECK();
+
if ((mysql_result=mysql_list_dbs(mysql->conn, NULL))==NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to save MySQL query result");
RETURN_FALSE;
@@ -1811,9 +1843,7 @@ PHP_FUNCTION(mysql_escape_string)
Z_STRLEN_P(return_value) = mysql_escape_string(Z_STRVAL_P(return_value), str, str_len);
Z_TYPE_P(return_value) = IS_STRING;
- if (MySG(trace_mode)){
- php_error_docref("function.mysql-real-escape-string" TSRMLS_CC, E_DEPRECATED, "This function is deprecated; use mysql_real_escape_string() instead.");
- }
+ php_error_docref("function.mysql-real-escape-string" TSRMLS_CC, E_DEPRECATED, "This function is deprecated; use mysql_real_escape_string() instead.");
}
/* }}} */
@@ -1959,12 +1989,16 @@ Q: String or long first?
if (sql_row[field_offset]) {
Z_TYPE_P(return_value) = IS_STRING;
+#if PHP_API_VERSION < 20100412
if (PG(magic_quotes_runtime)) {
Z_STRVAL_P(return_value) = php_addslashes(sql_row[field_offset], sql_row_lengths[field_offset],&Z_STRLEN_P(return_value), 0 TSRMLS_CC);
} else {
+#endif
Z_STRLEN_P(return_value) = sql_row_lengths[field_offset];
Z_STRVAL_P(return_value) = (char *) safe_estrndup(sql_row[field_offset], Z_STRLEN_P(return_value));
+#if PHP_API_VERSION < 20100412
}
+#endif
} else {
Z_TYPE_P(return_value) = IS_NULL;
}
@@ -2082,12 +2116,16 @@ static void php_mysql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type,
MAKE_STD_ZVAL(data);
+#if PHP_API_VERSION < 20100412
if (PG(magic_quotes_runtime)) {
Z_TYPE_P(data) = IS_STRING;
Z_STRVAL_P(data) = php_addslashes(mysql_row[i], mysql_row_lengths[i], &Z_STRLEN_P(data), 0 TSRMLS_CC);
} else {
+#endif
ZVAL_STRINGL(data, mysql_row[i], mysql_row_lengths[i], 1);
+#if PHP_API_VERSION < 20100412
}
+#endif
if (result_type & MYSQL_NUM) {
add_index_zval(return_value, i, data);
@@ -2378,8 +2416,8 @@ PHP_FUNCTION(mysql_fetch_field)
}
object_init(return_value);
- add_property_string(return_value, "name", (char *) (mysql_field->name?mysql_field->name:""), 1);
- add_property_string(return_value, "table",(char *) (mysql_field->table?mysql_field->table:""), 1);
+ add_property_string(return_value, "name",(mysql_field->name?mysql_field->name:""), 1);
+ add_property_string(return_value, "table",(mysql_field->table?mysql_field->table:""), 1);
add_property_string(return_value, "def",(mysql_field->def?mysql_field->def:""), 1);
add_property_long(return_value, "max_length", mysql_field->max_length);
add_property_long(return_value, "not_null", IS_NOT_NULL(mysql_field->flags)?1:0);
diff --git a/ext/mysql/tests/bug55473.phpt b/ext/mysql/tests/bug55473.phpt
index df584bdef9..befecef192 100644
--- a/ext/mysql/tests/bug55473.phpt
+++ b/ext/mysql/tests/bug55473.phpt
@@ -1,5 +1,5 @@
--TEST--
-Bug #5547 (mysql_pconnect leaks file descriptors on reconnect)
+Bug #55473 (mysql_pconnect leaks file descriptors on reconnect)
--SKIPIF--
<?php
require_once('skipif.inc');
@@ -8,7 +8,7 @@ if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
die("skip Test doesn't work on Windows");
}
-if (!($output = @exec("lsof -np " . getmypid())))
+if (!($output = @exec("lsof -nwp " . getmypid())))
die("skip Test can't find command line tool lsof");
?>
--INI--
@@ -56,9 +56,9 @@ mysql.allow_persistent=1
if ($opened_files == -1) {
- $opened_files = trim(exec("lsof -np " . getmypid() . " | wc -l"));
+ $opened_files = trim(exec("lsof -nwp " . getmypid() . " | wc -l"));
printf("[005] Setting openened files...\n");
- } else if (($tmp = trim(exec("lsof -np " . getmypid() . " | wc -l"))) != $opened_files) {
+ } else if (($tmp = trim(exec("lsof -nwp " . getmypid() . " | wc -l"))) != $opened_files) {
printf("[006] [%d] different number of opened_files : expected %d, got %d", $i, $opened_files, $tmp);
} else {
printf("[007] Opened files as expected\n");
@@ -76,4 +76,4 @@ mysql.allow_persistent=1
[007] Opened files as expected
[003] reconnect 3
[007] Opened files as expected
-done! \ No newline at end of file
+done!
diff --git a/ext/mysql/tests/mysql_pconn_kill.phpt b/ext/mysql/tests/mysql_pconn_kill.phpt
index 20dfbe9a15..efef421604 100644
--- a/ext/mysql/tests/mysql_pconn_kill.phpt
+++ b/ext/mysql/tests/mysql_pconn_kill.phpt
@@ -64,8 +64,6 @@ mysql.max_persistent=2
mysql_close($plink);
- /* mysql_pconnect cound generate a warning when linked against mysqlnd
- PHP Warning: mysql_pconnect(): MySQL server has gone away */
if (!($plink = @mysql_pconnect($myhost, $user, $passwd)))
printf("[009] Cannot create new persistent connection, [%d] %s\n", mysql_errno(), mysql_error());
mysql_select_db($db, $plink);
diff --git a/ext/mysql/tests/mysql_phpinfo.phpt b/ext/mysql/tests/mysql_phpinfo.phpt
index 46600ab2d2..79de939167 100644
--- a/ext/mysql/tests/mysql_phpinfo.phpt
+++ b/ext/mysql/tests/mysql_phpinfo.phpt
@@ -51,7 +51,7 @@ if (!stristr($phpinfo, "mysql.allow_persistent"))
if ($IS_MYSQLND) {
$expected = array(
- 'client statistics',
+ 'mysqlnd statistics',
'bytes_sent', 'bytes_received', 'packets_sent', 'packets_received',
'protocol_overhead_in', 'protocol_overhead_out', 'result_set_queries',
'non_result_set_queries', 'no_index_used', 'bad_index_used',
diff --git a/ext/mysql/tests/mysql_query_load_data_openbasedir.phpt b/ext/mysql/tests/mysql_query_load_data_openbasedir.phpt
index 474065faf1..aa15f5ca12 100644
--- a/ext/mysql/tests/mysql_query_load_data_openbasedir.phpt
+++ b/ext/mysql/tests/mysql_query_load_data_openbasedir.phpt
@@ -3,11 +3,6 @@ LOAD DATA INFILE - open_basedir
--SKIPIF--
<?php
include_once('skipif.inc');
-
-if (!isset($db)) {
- die("skip open_basedir setting prevents inclusing of required files");
-}
-
include_once('skipifconnectfailure.inc');
@@ -30,12 +25,11 @@ if ($socket == "" && $host != NULL && $host != 'localhost' && $host != '.') {
}
}
?>
---INI--
-open_basedir="."
--FILE--
<?php
@include_once("connect.inc");
-
+ini_set("open_basedir", __DIR__);
+chdir(__DIR__);
if (!isset($db)) {
// run-tests, I love you for not allowing me to set ini settings dynamically
print "[006] [1148] The used command is not allowed with this MySQL version
diff --git a/ext/mysqli/config.m4 b/ext/mysqli/config.m4
index 59efaaaff2..6ec9334639 100644
--- a/ext/mysqli/config.m4
+++ b/ext/mysqli/config.m4
@@ -4,24 +4,20 @@ dnl config.m4 for extension mysqli
PHP_ARG_WITH(mysqli, for MySQLi support,
[ --with-mysqli[=FILE] Include MySQLi support. FILE is the path
- to mysql_config. If mysqlnd is passed as FILE,
- the MySQL native driver will be used [mysql_config]])
+ to mysql_config. If no value or mysqlnd is passed
+ as FILE, the MySQL native driver will be used])
PHP_ARG_ENABLE(embedded_mysqli, whether to enable embedded MySQLi support,
[ --enable-embedded-mysqli MYSQLi: Enable embedded support
Note: Does not work with MySQL native driver!], no, no)
-if test "$PHP_MYSQLI" = "mysqlnd"; then
+if test "$PHP_MYSQLI" = "yes" || test "$PHP_MYSQLI" = "mysqlnd"; then
dnl This needs to be set in any extension which wishes to use mysqlnd
PHP_MYSQLND_ENABLED=yes
elif test "$PHP_MYSQLI" != "no"; then
- if test "$PHP_MYSQLI" = "yes"; then
- MYSQL_CONFIG=`$php_shtool path mysql_config`
- else
- MYSQL_CONFIG=$PHP_MYSQLI
- fi
+ MYSQL_CONFIG=$PHP_MYSQLI
MYSQL_LIB_NAME='mysqlclient'
if test "$PHP_EMBEDDED_MYSQLI" = "yes"; then
@@ -77,12 +73,12 @@ dnl Build extension
if test "$PHP_MYSQLI" != "no"; then
mysqli_sources="mysqli.c mysqli_api.c mysqli_prop.c mysqli_nonapi.c \
mysqli_fe.c mysqli_report.c mysqli_driver.c mysqli_warning.c \
- mysqli_exception.c $mysqli_extra_sources"
+ mysqli_exception.c mysqli_result_iterator.c $mysqli_extra_sources"
PHP_NEW_EXTENSION(mysqli, $mysqli_sources, $ext_shared)
PHP_SUBST(MYSQLI_SHARED_LIBADD)
PHP_INSTALL_HEADERS([ext/mysqli/php_mysqli_structs.h])
- if test "$PHP_MYSQLI" = "mysqlnd"; then
+ if test "$PHP_MYSQLI" = "yes" || test "$PHP_MYSQLI" = "mysqlnd"; then
PHP_ADD_EXTENSION_DEP(mysqli, mysqlnd)
AC_DEFINE([MYSQLI_USE_MYSQLND], 1, [Whether mysqlnd is enabled])
fi
diff --git a/ext/mysqli/config.w32 b/ext/mysqli/config.w32
index ab3321ae44..ab8bcd0087 100644
--- a/ext/mysqli/config.w32
+++ b/ext/mysqli/config.w32
@@ -18,6 +18,7 @@ if (PHP_MYSQLI != "no") {
"mysqli_fe.c " +
"mysqli_nonapi.c " +
"mysqli_prop.c " +
+ "mysqli_result_iterator.c " +
"mysqli_report.c " +
"mysqli_warning.c";
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 08fcf1e75b..6d283aa9ca 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -30,9 +30,11 @@
#include "php_ini.h"
#include "ext/standard/info.h"
#include "ext/standard/php_string.h"
+#include "php_mysqli.h"
#include "php_mysqli_structs.h"
#include "mysqli_priv.h"
#include "zend_exceptions.h"
+#include "zend_interfaces.h"
ZEND_DECLARE_MODULE_GLOBALS(mysqli)
static PHP_GINIT_FUNCTION(mysqli);
@@ -160,7 +162,7 @@ void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC)
{
if (stmt->stmt) {
if (mysqli_stmt_close(stmt->stmt, TRUE)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error occured while closing statement");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error occurred while closing statement");
return;
}
}
@@ -313,7 +315,7 @@ static int mysqli_write_na(mysqli_object *obj, zval *newval TSRMLS_DC)
/* {{{ mysqli_read_property */
-zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC)
+zval *mysqli_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
zval tmp_member;
zval *retval;
@@ -345,7 +347,7 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC)
}
} else {
zend_object_handlers * std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->read_property(object, member, type TSRMLS_CC);
+ retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -356,7 +358,7 @@ zval *mysqli_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* }}} */
/* {{{ mysqli_write_property */
-void mysqli_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+void mysqli_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
zval tmp_member;
mysqli_object *obj;
@@ -384,7 +386,7 @@ void mysqli_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
}
} else {
zend_object_handlers * std_hnd = zend_get_std_object_handlers();
- std_hnd->write_property(object, member, value TSRMLS_CC);
+ std_hnd->write_property(object, member, value, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -405,7 +407,7 @@ void mysqli_add_property(HashTable *h, const char *pname, size_t pname_len, mysq
}
/* }}} */
-static int mysqli_object_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */
+static int mysqli_object_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
{
mysqli_object *obj = (mysqli_object *)zend_objects_get_address(object TSRMLS_CC);
mysqli_prop_handler p;
@@ -417,7 +419,7 @@ static int mysqli_object_has_property(zval *object, zval *member, int has_set_ex
ret = 1;
break;
case 1: {
- zval *value = mysqli_read_property(object, member, BP_VAR_IS TSRMLS_CC);
+ zval *value = mysqli_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
if (value != EG(uninitialized_zval_ptr)) {
convert_to_boolean(value);
ret = Z_BVAL_P(value)? 1:0;
@@ -428,7 +430,7 @@ static int mysqli_object_has_property(zval *object, zval *member, int has_set_ex
break;
}
case 0:{
- zval *value = mysqli_read_property(object, member, BP_VAR_IS TSRMLS_CC);
+ zval *value = mysqli_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
if (value != EG(uninitialized_zval_ptr)) {
ret = Z_TYPE_P(value) != IS_NULL? 1:0;
/* refcount is 0 */
@@ -442,7 +444,7 @@ static int mysqli_object_has_property(zval *object, zval *member, int has_set_ex
}
} else {
zend_object_handlers * std_hnd = zend_get_std_object_handlers();
- ret = std_hnd->has_property(object, member, has_set_exists TSRMLS_CC);
+ ret = std_hnd->has_property(object, member, has_set_exists, key TSRMLS_CC);
}
return ret;
} /* }}} */
@@ -465,7 +467,7 @@ HashTable * mysqli_object_get_debug_info(zval *object, int *is_temp TSRMLS_DC)
zval *value;
INIT_ZVAL(member);
ZVAL_STRINGL(&member, entry->name, entry->name_len, 0);
- value = mysqli_read_property(object, &member, BP_VAR_IS TSRMLS_CC);
+ value = mysqli_read_property(object, &member, BP_VAR_IS, 0 TSRMLS_CC);
if (value != EG(uninitialized_zval_ptr)) {
Z_ADDREF_P(value);
zend_hash_add(retval, entry->name, entry->name_len + 1, &value, sizeof(zval *), NULL);
@@ -484,7 +486,6 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
{
zend_object_value retval;
mysqli_object *intern;
- zval *tmp;
zend_class_entry *mysqli_base_class;
zend_objects_free_object_storage_t free_storage;
@@ -502,8 +503,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
(void **) &intern->prop_handler);
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,
- (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
/* link object */
if (instanceof_function(class_type, mysqli_link_class_entry TSRMLS_CC)) {
@@ -527,6 +527,30 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
}
/* }}} */
+#ifdef MYSQLI_USE_MYSQLND
+#include "ext/mysqlnd/mysqlnd_reverse_api.h"
+static MYSQLND *mysqli_convert_zv_to_mysqlnd(zval * zv TSRMLS_DC)
+{
+ if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == mysqli_link_class_entry) {
+ MY_MYSQL * mysql;
+ MYSQLI_RESOURCE * my_res;
+ mysqli_object * intern = (mysqli_object *)zend_object_store_get_object(zv TSRMLS_CC);
+ if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
+ /* We know that we have a mysqli object, so this failure should be emitted */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name);
+ return NULL;
+ }
+ mysql = (MY_MYSQL *)(my_res->ptr);
+ return mysql ? mysql->mysql : NULL;
+ }
+ return NULL;
+}
+
+static MYSQLND_REVERSE_API mysqli_reverse_api = {
+ &mysqli_module_entry,
+ mysqli_convert_zv_to_mysqlnd
+};
+#endif
/* {{{ PHP_INI_BEGIN
*/
@@ -646,6 +670,9 @@ PHP_MINIT_FUNCTION(mysqli)
zend_hash_init(&mysqli_result_properties, 0, NULL, NULL, 1);
MYSQLI_ADD_PROPERTIES(&mysqli_result_properties, mysqli_result_property_entries);
MYSQLI_ADD_PROPERTIES_INFO(ce, mysqli_result_property_info_entries);
+ mysqli_result_class_entry->get_iterator = php_mysqli_result_get_iterator;
+ mysqli_result_class_entry->iterator_funcs.funcs = &php_mysqli_result_iterator_funcs;
+ zend_class_implements(mysqli_result_class_entry TSRMLS_CC, 1, zend_ce_traversable);
zend_hash_add(&classes, ce->name, ce->name_length+1, &mysqli_result_properties, sizeof(mysqli_result_properties), NULL);
REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, mysqli_stmt_methods);
@@ -783,10 +810,10 @@ PHP_MINIT_FUNCTION(mysqli)
#ifdef MYSQLI_USE_MYSQLND
REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", MYSQLND_DBG_ENABLED, CONST_CS | CONST_PERSISTENT);
#else
-#ifndef DBUG_OFF
- REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 0, CONST_CS | CONST_PERSISTENT);
-#else
+#ifdef DBUG_ON
REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 1, CONST_CS | CONST_PERSISTENT);
+#else
+ REGISTER_LONG_CONSTANT("MYSQLI_DEBUG_TRACE_ENABLED", 0, CONST_CS | CONST_PERSISTENT);
#endif
#endif
@@ -811,6 +838,11 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_REFRESH_BACKUP_LOG", REFRESH_BACKUP_LOG, CONST_CS | CONST_PERSISTENT);
#endif
+
+#ifdef MYSQLI_USE_MYSQLND
+ mysqlnd_reverse_api_register_api(&mysqli_reverse_api TSRMLS_CC);
+#endif
+
return SUCCESS;
}
/* }}} */
@@ -1083,61 +1115,17 @@ PHP_FUNCTION(mysqli_result_construct)
}
/* }}} */
-/* {{{ php_mysqli_fetch_into_hash
+
+/* {{{ php_mysqli_fetch_into_hash_aux
*/
-void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
+void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, long fetchtype TSRMLS_DC)
{
- MYSQL_RES *result;
- zval *mysql_result;
- long fetchtype;
- zval *ctor_params = NULL;
- zend_class_entry *ce = NULL;
#if !defined(MYSQLI_USE_MYSQLND)
+ MYSQL_ROW row;
unsigned int i;
MYSQL_FIELD *fields;
- MYSQL_ROW row;
unsigned long *field_len;
- zend_bool magic_quotes_warning_sent = FALSE;
-#endif
-
- if (into_object) {
- char *class_name;
- int class_name_len;
-
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|sz", &mysql_result, mysqli_result_class_entry, &class_name, &class_name_len, &ctor_params) == FAILURE) {
- return;
- }
- if (ZEND_NUM_ARGS() < (getThis() ? 1 : 2)) {
- ce = zend_standard_class_def;
- } else {
- ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
- }
- if (!ce) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
- return;
- }
- fetchtype = MYSQLI_ASSOC;
- } else {
- if (override_flags) {
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
- return;
- }
- fetchtype = override_flags;
- } else {
- fetchtype = MYSQLI_BOTH;
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
- return;
- }
- }
- }
- MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
-
- if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH");
- RETURN_FALSE;
- }
-
-#if !defined(MYSQLI_USE_MYSQLND)
+
if (!(row = mysql_fetch_row(result))) {
RETURN_NULL();
}
@@ -1179,17 +1167,17 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
#endif
{
+#if PHP_API_VERSION < 20100412
/* check if we need magic quotes */
if (PG(magic_quotes_runtime)) {
- if (magic_quotes_warning_sent == FALSE) {
- magic_quotes_warning_sent = TRUE;
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "magic_quotes_runtime are deprecated since PHP 5.3");
- }
Z_TYPE_P(res) = IS_STRING;
Z_STRVAL_P(res) = php_addslashes(row[i], field_len[i], &Z_STRLEN_P(res), 0 TSRMLS_CC);
} else {
+#endif
ZVAL_STRINGL(res, row[i], field_len[i], 1);
+#if PHP_API_VERSION < 20100412
}
+#endif
}
if (fetchtype & MYSQLI_NUM) {
@@ -1211,53 +1199,60 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
}
}
#else
- if (PG(magic_quotes_runtime)) {
- HashPosition pos_values;
- zval **entry_values;
- zval new_return_value;
- char * string_key;
- uint string_key_len;
- ulong num_key;
-
- mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), &new_return_value, MYSQLND_MYSQLI);
- if (Z_TYPE(new_return_value) == IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "magic_quotes_runtime are deprecated since PHP 5.3");
- array_init(return_value);
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL(new_return_value), &pos_values);
- while (zend_hash_get_current_data_ex(Z_ARRVAL(new_return_value), (void **)&entry_values, &pos_values) == SUCCESS) {
- if (Z_TYPE_PP(entry_values) == IS_STRING) {
- int new_str_len;
- char * new_str = php_addslashes(Z_STRVAL_PP(entry_values), Z_STRLEN_PP(entry_values), &new_str_len, 0 TSRMLS_CC);
- switch (zend_hash_get_current_key_ex(Z_ARRVAL(new_return_value), &string_key, &string_key_len, &num_key, 0, &pos_values)) {
- case HASH_KEY_IS_LONG:
- add_index_stringl(return_value, num_key, new_str, new_str_len, 0);
- break;
- case HASH_KEY_IS_STRING:
- add_assoc_stringl_ex(return_value, string_key, string_key_len, new_str, new_str_len, 0);
- break;
- }
- } else {
- zval_add_ref(entry_values);
- switch (zend_hash_get_current_key_ex(Z_ARRVAL(new_return_value), &string_key, &string_key_len, &num_key, 0, &pos_values)) {
- case HASH_KEY_IS_LONG:
- add_index_zval(return_value, num_key, *entry_values);
- break;
- case HASH_KEY_IS_STRING:
- add_assoc_zval_ex(return_value, string_key, string_key_len, *entry_values);
- break;
- }
- }
- zend_hash_move_forward_ex(Z_ARRVAL(new_return_value), &pos_values);
- }
+ mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value, MYSQLND_MYSQLI);
+#endif
+}
+/* }}} */
+
+
+/* {{{ php_mysqli_fetch_into_hash
+ */
+void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
+{
+ MYSQL_RES *result;
+ zval *mysql_result;
+ long fetchtype;
+ zval *ctor_params = NULL;
+ zend_class_entry *ce = NULL;
+
+ if (into_object) {
+ char *class_name;
+ int class_name_len;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|sz", &mysql_result, mysqli_result_class_entry, &class_name, &class_name_len, &ctor_params) == FAILURE) {
+ return;
+ }
+ if (ZEND_NUM_ARGS() < (getThis() ? 1 : 2)) {
+ ce = zend_standard_class_def;
} else {
- RETVAL_NULL();
+ ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
}
- zval_dtor(&new_return_value);
+ if (!ce) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
+ return;
+ }
+ fetchtype = MYSQLI_ASSOC;
} else {
- mysqlnd_fetch_into(result, ((fetchtype & MYSQLI_NUM)? MYSQLND_FETCH_NUM:0) | ((fetchtype & MYSQLI_ASSOC)? MYSQLND_FETCH_ASSOC:0), return_value, MYSQLND_MYSQLI);
+ if (override_flags) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
+ return;
+ }
+ fetchtype = override_flags;
+ } else {
+ fetchtype = MYSQLI_BOTH;
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
+ return;
+ }
+ }
}
+ MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
-#endif
+ if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH");
+ RETURN_FALSE;
+ }
+
+ php_mysqli_fetch_into_hash_aux(return_value, result, fetchtype TSRMLS_CC);
if (into_object && Z_TYPE_P(return_value) != IS_NULL) {
zval dataset = *return_value;
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index aa6b6ab98e..ce7588ecbf 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -535,7 +535,11 @@ PHP_FUNCTION(mysqli_change_user)
old_charset = mysql->mysql->charset;
#endif
+#if defined(MYSQLI_USE_MYSQLND)
+ rc = mysqlnd_change_user_ex(mysql->mysql, user, password, dbname, FALSE, (size_t) password_len);
+#else
rc = mysql_change_user(mysql->mysql, user, password, dbname);
+#endif
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
if (rc) {
@@ -883,7 +887,7 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
*/
/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
if (Z_TYPE_P(stmt->result.vars[i]) == IS_STRING) {
- efree(stmt->result.vars[i]->value.str.val);
+ STR_FREE(stmt->result.vars[i]->value.str.val);
}
if (!stmt->result.is_null[i]) {
switch (stmt->result.buf[i].type) {
@@ -1047,12 +1051,12 @@ PHP_FUNCTION(mysqli_stmt_fetch)
/* {{{ php_add_field_properties */
static void php_add_field_properties(zval *value, const MYSQL_FIELD *field TSRMLS_DC)
{
- add_property_string(value, "name", (char *) (field->name ? field->name : ""), 1);
- add_property_string(value, "orgname", (char *) (field->org_name ? field->org_name : ""), 1);
- add_property_string(value, "table", (char *) (field->table ? field->table : ""), 1);
- add_property_string(value, "orgtable", (char *) (field->org_table ? field->org_table : ""), 1);
- add_property_string(value, "def", (field->def ? field->def : ""), 1);
- add_property_string(value, "db", (field->db ? field->db : ""), 1);
+ add_property_string(value, "name",(field->name ? field->name : ""), 1);
+ add_property_string(value, "orgname",(field->org_name ? field->org_name : ""), 1);
+ add_property_string(value, "table",(field->table ? field->table : ""), 1);
+ add_property_string(value, "orgtable",(field->org_table ? field->org_table : ""), 1);
+ add_property_string(value, "def",(field->def ? field->def : ""), 1);
+ add_property_string(value, "db",(field->db ? field->db : ""), 1);
/* FIXME: manually set the catalog to "def" due to bug in
* libmysqlclient which does not initialize field->catalog
@@ -1287,8 +1291,11 @@ PHP_FUNCTION(mysqli_get_host_info)
return;
}
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
-
+#if !defined(MYSQLI_USE_MYSQLND)
RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "", 1);
+#else
+ RETURN_STRING((mysql->mysql->data->host_info) ? mysql->mysql->data->host_info : "", 1);
+#endif
}
/* }}} */
@@ -1800,7 +1807,7 @@ PHP_FUNCTION(mysqli_prepare)
memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
#else
- MYSQLND_ERROR_INFO error_info = mysql->mysql->error_info;
+ MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
#endif
mysqli_stmt_close(stmt->stmt, FALSE);
stmt->stmt = NULL;
@@ -1811,7 +1818,7 @@ PHP_FUNCTION(mysqli_prepare)
memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
#else
- mysql->mysql->error_info = error_info;
+ *mysql->mysql->data->error_info = error_info;
#endif
}
}
diff --git a/ext/mysqli/mysqli_driver.c b/ext/mysqli/mysqli_driver.c
index b7227bb3c2..67e2b43e76 100644
--- a/ext/mysqli/mysqli_driver.c
+++ b/ext/mysqli/mysqli_driver.c
@@ -151,14 +151,14 @@ const mysqli_property_entry mysqli_driver_property_entries[] = {
};
/* {{{ mysqli_warning_property_info_entries */
-zend_property_info mysqli_driver_property_info_entries[] = {
- {ZEND_ACC_PUBLIC, "client_info", sizeof("client_info") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "client_version", sizeof("client_version") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "driver_version", sizeof("driver_version") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "embedded", sizeof("embedded") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "reconnect", sizeof("reconnect") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "report_mode", sizeof("report_mode") - 1, 0, NULL, 0, NULL},
- {0, NULL, 0, 0, NULL, 0, NULL},
+const zend_property_info mysqli_driver_property_info_entries[] = {
+ {ZEND_ACC_PUBLIC, "client_info", sizeof("client_info") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "client_version", sizeof("client_version") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "driver_version", sizeof("driver_version") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "embedded", sizeof("embedded") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "reconnect", sizeof("reconnect") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "report_mode", sizeof("report_mode") - 1, -1, 0, NULL, 0, NULL},
+ {0, NULL, 0, -1, 0, NULL, 0, NULL},
};
/* }}} */
diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c
index bb4e7cab8c..9ebb9352fe 100644
--- a/ext/mysqli/mysqli_fe.c
+++ b/ext/mysqli/mysqli_fe.c
@@ -33,7 +33,7 @@
#include "mysqli_fe.h"
#include "mysqli_priv.h"
-#if PHP_VERSION_ID >= 50399
+#ifdef MYSQLI_USE_FULL_TYPED_ARGINFO_0
#define MYSQLI_ZEND_ARG_OBJ_INFO_LINK() ZEND_ARG_OBJ_INFO(0, link, mysqli, 0)
#define MYSQLI_ZEND_ARG_OBJ_INFO_RESULT() ZEND_ARG_OBJ_INFO(0, result, mysqli_result, 0)
#define MYSQLI_ZEND_ARG_OBJ_INFO_STMT() ZEND_ARG_OBJ_INFO(0, stmt, mysqli_stmt, 0)
@@ -352,6 +352,7 @@ const zend_function_entry mysqli_functions[] = {
#endif
PHP_FE(mysqli_errno, arginfo_mysqli_only_link)
PHP_FE(mysqli_error, arginfo_mysqli_only_link)
+ PHP_FE(mysqli_error_list, arginfo_mysqli_only_link)
PHP_FE(mysqli_stmt_execute, arginfo_mysqli_only_statement)
PHP_FALIAS(mysqli_execute, mysqli_stmt_execute, arginfo_mysqli_only_statement)
PHP_FE(mysqli_fetch_field, arginfo_mysqli_only_result)
@@ -370,7 +371,6 @@ const zend_function_entry mysqli_functions[] = {
PHP_FE(mysqli_field_tell, arginfo_mysqli_only_result)
PHP_FE(mysqli_free_result, arginfo_mysqli_only_result)
#if defined(MYSQLI_USE_MYSQLND)
- PHP_FE(mysqli_get_cache_stats, arginfo_mysqli_no_params)
PHP_FE(mysqli_get_connection_stats, arginfo_mysqli_only_link)
PHP_FE(mysqli_get_client_stats, arginfo_mysqli_no_params)
#endif
@@ -425,6 +425,7 @@ const zend_function_entry mysqli_functions[] = {
PHP_FE(mysqli_stmt_data_seek, arginfo_mysqli_stmt_data_seek)
PHP_FE(mysqli_stmt_errno, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_error, arginfo_mysqli_only_statement)
+ PHP_FE(mysqli_stmt_error_list, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_fetch, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_field_count, arginfo_mysqli_only_statement)
PHP_FE(mysqli_stmt_free_result, arginfo_mysqli_only_statement)
@@ -458,14 +459,7 @@ const zend_function_entry mysqli_functions[] = {
PHP_FE(mysqli_refresh, arginfo_mysqli_refresh)
/* Aliases */
- PHP_FALIAS(mysqli_bind_param, mysqli_stmt_bind_param, arginfo_mysqli_stmt_bind_param)
- PHP_FALIAS(mysqli_bind_result, mysqli_stmt_bind_result, arginfo_mysqli_stmt_bind_result)
- PHP_FALIAS(mysqli_client_encoding, mysqli_character_set_name, NULL)
PHP_FALIAS(mysqli_escape_string, mysqli_real_escape_string, arginfo_mysqli_query)
- PHP_FALIAS(mysqli_fetch, mysqli_stmt_fetch, NULL)
- PHP_FALIAS(mysqli_param_count, mysqli_stmt_param_count, NULL)
- PHP_FALIAS(mysqli_get_metadata, mysqli_stmt_result_metadata,NULL)
- PHP_FALIAS(mysqli_send_long_data, mysqli_stmt_send_long_data, NULL)
PHP_FALIAS(mysqli_set_opt, mysqli_options, NULL)
PHP_FE_END
@@ -480,7 +474,6 @@ const zend_function_entry mysqli_link_methods[] = {
PHP_FALIAS(autocommit, mysqli_autocommit, arginfo_class_mysqli_autocommit)
PHP_FALIAS(change_user,mysqli_change_user, arginfo_class_mysqli_change_user)
PHP_FALIAS(character_set_name, mysqli_character_set_name, arginfo_mysqli_no_params)
- PHP_FALIAS(client_encoding, mysqli_character_set_name, arginfo_mysqli_no_params) /* deprecated */
PHP_FALIAS(close, mysqli_close, arginfo_mysqli_no_params)
PHP_FALIAS(commit, mysqli_commit, arginfo_mysqli_no_params)
PHP_FALIAS(connect, mysqli_connect, arginfo_mysqli_connect)
diff --git a/ext/mysqli/mysqli_fe.h b/ext/mysqli/mysqli_fe.h
index ad73eb73e5..7b55ad1c12 100644
--- a/ext/mysqli/mysqli_fe.h
+++ b/ext/mysqli/mysqli_fe.h
@@ -38,6 +38,7 @@ PHP_FUNCTION(mysqli_debug);
PHP_FUNCTION(mysqli_dump_debug_info);
PHP_FUNCTION(mysqli_errno);
PHP_FUNCTION(mysqli_error);
+PHP_FUNCTION(mysqli_error_list);
PHP_FUNCTION(mysqli_fetch_all);
PHP_FUNCTION(mysqli_fetch_array);
PHP_FUNCTION(mysqli_fetch_assoc);
@@ -111,6 +112,7 @@ PHP_FUNCTION(mysqli_stmt_close);
PHP_FUNCTION(mysqli_stmt_data_seek);
PHP_FUNCTION(mysqli_stmt_errno);
PHP_FUNCTION(mysqli_stmt_error);
+PHP_FUNCTION(mysqli_stmt_error_list);
PHP_FUNCTION(mysqli_stmt_free_result);
PHP_FUNCTION(mysqli_stmt_get_result);
PHP_FUNCTION(mysqli_stmt_get_warnings);
@@ -133,3 +135,5 @@ PHP_FUNCTION(mysqli_driver_construct);
PHP_METHOD(mysqli_warning,__construct);
#endif /* MYSQLI_FE_H */
+
+
diff --git a/ext/mysqli/mysqli_libmysql.h b/ext/mysqli/mysqli_libmysql.h
index 228cde279e..a61f7e87b9 100644
--- a/ext/mysqli/mysqli_libmysql.h
+++ b/ext/mysqli/mysqli_libmysql.h
@@ -1,9 +1,9 @@
/*
- ----------------------------------------------------------------------
+ +----------------------------------------------------------------------+
| PHP Version 5 |
- ----------------------------------------------------------------------
- | Copyright (c) 2007 The PHP Group |
- ----------------------------------------------------------------------
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
@@ -11,12 +11,11 @@
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
- ----------------------------------------------------------------------
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
- | Ulf Wendel <uwendel@mysql.com> |
- ----------------------------------------------------------------------
-
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@php.net> |
+ | Andrey Hristov <andrey@php.net> |
+ | Ulf Wendel <uw@php.net> |
+ +----------------------------------------------------------------------+
*/
#ifndef MYSQLI_LIBMYSQL_H
@@ -29,8 +28,9 @@
#define MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE 200
#define MYSQLND_OPT_INT_AND_YEAR_AS_INT 201
+/* r->data should be always NULL, at least in recent libmysql versions, the status changes once data is read*/
#define mysqli_result_is_unbuffered(r) ((r)->handle && (r)->handle->status == MYSQL_STATUS_USE_RESULT && (r)->data == NULL)
-#define mysqli_result_is_unbuffered_and_not_everything_is_fetched(r) mysqli_result_is_unbuffered(r)
+#define mysqli_result_is_unbuffered_and_not_everything_is_fetched(r) mysqli_result_is_unbuffered(r)
#define mysqli_server_status(c) (c)->server_status
#define mysqli_stmt_get_id(s) ((s)->stmt_id)
#define mysqli_stmt_warning_count(s) mysql_warning_count((s)->mysql)
@@ -39,7 +39,7 @@
#define mysqli_close(c, is_forced) mysql_close((c))
#define mysqli_stmt_close(c, implicit) mysql_stmt_close((c))
#define mysqli_free_result(r, is_forced) mysql_free_result((r))
-#define mysqli_change_user_silent(c, u, p, d) mysql_change_user((c), (u), (p), (d))
+#define mysqli_change_user_silent(c, u, p, d, p_len) mysql_change_user((c), (u), (p), (d))
/*
diff --git a/ext/mysqli/mysqli_mysqlnd.h b/ext/mysqli/mysqli_mysqlnd.h
index ce0be63e5b..b6d23d9ef1 100644
--- a/ext/mysqli/mysqli_mysqlnd.h
+++ b/ext/mysqli/mysqli_mysqlnd.h
@@ -32,7 +32,7 @@
#define mysqli_result_is_unbuffered(r) ((r)->unbuf)
#define mysqli_result_is_unbuffered_and_not_everything_is_fetched(r) ((r)->unbuf && !(r)->unbuf->eof_reached)
-#define mysqli_server_status(c) (c)->upsert_status.server_status
+#define mysqli_server_status(c) mysqlnd_get_server_status((c))
#define mysqli_stmt_get_id(s) ((s)->data->stmt_id)
#define mysqli_stmt_warning_count(s) mysqlnd_stmt_warning_count((s))
#define mysqli_stmt_server_status(s) mysqlnd_stmt_server_status((s))
@@ -41,7 +41,7 @@
#define mysqli_stmt_close(c, implicit) mysqlnd_stmt_close((c), (implicit))
#define mysqli_free_result(r, implicit) mysqlnd_free_result((r), (implicit))
#define mysqli_async_query(c, q, l) mysqlnd_async_query((c), (q), (l))
-#define mysqli_change_user_silent(c, u, p, d) mysqlnd_change_user((c), (u), (p), (d), TRUE)
+#define mysqli_change_user_silent(c, u, p, d, p_len) mysqlnd_change_user_ex((c), (u), (p), (d), TRUE, (size_t)(p_len))
#define HAVE_STMT_NEXT_RESULT
diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c
index 0ef67a2c44..7e1b9355d0 100644
--- a/ext/mysqli/mysqli_nonapi.c
+++ b/ext/mysqli/mysqli_nonapi.c
@@ -174,7 +174,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
/* reset variables */
#ifndef MYSQLI_NO_CHANGE_USER_ON_PCONNECT
- if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname)) {
+ if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname, passwd_len)) {
#else
if (!mysql_ping(mysql->mysql)) {
#endif
@@ -387,17 +387,6 @@ PHP_FUNCTION(mysqli_fetch_all)
/* }}} */
-/* {{{ proto array mysqli_cache_stats(void) U
- Returns statistics about the zval cache */
-PHP_FUNCTION(mysqli_get_cache_stats)
-{
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- array_init(return_value);
-}
-/* }}} */
-
/* {{{ proto array mysqli_get_client_stats(void)
Returns statistics about the zval cache */
@@ -429,6 +418,93 @@ PHP_FUNCTION(mysqli_get_connection_stats)
#endif
/* }}} */
+/* {{{ proto mixed mysqli_error_list (object connection)
+ Fetches all client errors */
+PHP_FUNCTION(mysqli_error_list)
+{
+ MY_MYSQL *mysql;
+ zval *mysql_link;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
+ return;
+ }
+ MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
+ array_init(return_value);
+#if defined(MYSQLI_USE_MYSQLND)
+ if (mysql->mysql->data->error_info->error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->data->error_info->error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->data->error_info->error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(return_value, single_error);
+ }
+ }
+#else
+ if (mysql_errno(mysql->mysql)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_errno(mysql->mysql));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_sqlstate(mysql->mysql), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_error(mysql->mysql), 1);
+ add_next_index_zval(return_value, single_error);
+ }
+#endif
+}
+/* }}} */
+
+
+/* {{{ proto string mysqli_stmt_error_list(object stmt)
+*/
+PHP_FUNCTION(mysqli_stmt_error_list)
+{
+ MY_STMT *stmt;
+ zval *mysql_stmt;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
+ return;
+ }
+ MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_INITIALIZED);
+ array_init(return_value);
+#if defined(MYSQLI_USE_MYSQLND)
+ if (stmt->stmt && stmt->stmt->data && stmt->stmt->data->error_info->error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info->error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info->error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(return_value, single_error);
+ }
+ }
+#else
+ if (mysql_stmt_errno(stmt->stmt)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_stmt_errno(stmt->stmt));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_stmt_sqlstate(stmt->stmt), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_stmt_error(stmt->stmt), 1);
+ add_next_index_zval(return_value, single_error);
+ }
+#endif
+}
+/* }}} */
+
/* {{{ proto mixed mysqli_fetch_object (object result [, string class_name [, NULL|array ctor_params]])
Fetch a result row as an object */
@@ -463,7 +539,7 @@ PHP_FUNCTION(mysqli_multi_query)
strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql));
s_errno = mysql_errno(mysql->mysql);
#else
- MYSQLND_ERROR_INFO error_info = mysql->mysql->error_info;
+ MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
#endif
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
MYSQLI_DISABLE_MQ;
@@ -474,7 +550,7 @@ PHP_FUNCTION(mysqli_multi_query)
strcpy(mysql->mysql->net.sqlstate, s_sqlstate);
mysql->mysql->net.last_errno = s_errno;
#else
- mysql->mysql->error_info = error_info;
+ *mysql->mysql->data->error_info = error_info;
#endif
RETURN_FALSE;
}
@@ -842,7 +918,11 @@ PHP_FUNCTION(mysqli_get_warnings)
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
if (mysql_warning_count(mysql->mysql)) {
+#ifdef MYSQLI_USE_MYSQLND
+ w = php_get_warnings(mysql->mysql->data TSRMLS_CC);
+#else
w = php_get_warnings(mysql->mysql TSRMLS_CC);
+#endif
} else {
RETURN_FALSE;
}
@@ -853,6 +933,7 @@ PHP_FUNCTION(mysqli_get_warnings)
}
/* }}} */
+
/* {{{ proto object mysqli_stmt_get_warnings(object link) */
PHP_FUNCTION(mysqli_stmt_get_warnings)
{
@@ -878,6 +959,7 @@ PHP_FUNCTION(mysqli_stmt_get_warnings)
}
/* }}} */
+
#ifdef HAVE_MYSQLI_SET_CHARSET
/* {{{ proto bool mysqli_set_charset(object link, string csname)
sets client character set */
@@ -933,7 +1015,7 @@ PHP_FUNCTION(mysqli_get_charset)
state = cs.state;
comment = cs.comment;
#else
- cs = mysql->mysql->charset;
+ cs = mysql->mysql->data->charset;
if (!cs) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The connection has no charset associated");
RETURN_NULL();
diff --git a/ext/mysqli/mysqli_priv.h b/ext/mysqli/mysqli_priv.h
index 3a7788dba7..9dd11117d1 100644
--- a/ext/mysqli/mysqli_priv.h
+++ b/ext/mysqli/mysqli_priv.h
@@ -52,11 +52,11 @@ extern const mysqli_property_entry mysqli_stmt_property_entries[];
extern const mysqli_property_entry mysqli_driver_property_entries[];
extern const mysqli_property_entry mysqli_warning_property_entries[];
-extern zend_property_info mysqli_link_property_info_entries[];
-extern zend_property_info mysqli_result_property_info_entries[];
-extern zend_property_info mysqli_stmt_property_info_entries[];
-extern zend_property_info mysqli_driver_property_info_entries[];
-extern zend_property_info mysqli_warning_property_info_entries[];
+extern const zend_property_info mysqli_link_property_info_entries[];
+extern const zend_property_info mysqli_result_property_info_entries[];
+extern const zend_property_info mysqli_stmt_property_info_entries[];
+extern const zend_property_info mysqli_driver_property_info_entries[];
+extern const zend_property_info mysqli_warning_property_info_entries[];
extern int php_le_pmysqli(void);
extern void php_mysqli_dtor_p_elements(void *data);
@@ -66,7 +66,12 @@ extern void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_stat
extern void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flag, int into_object);
extern void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC);
extern void php_clear_mysql(MY_MYSQL *);
-extern MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC);
+#ifdef MYSQLI_USE_MYSQLND
+extern MYSQLI_WARNING *php_get_warnings(MYSQLND_CONN_DATA * mysql TSRMLS_DC);
+#else
+extern MYSQLI_WARNING *php_get_warnings(MYSQL * mysql TSRMLS_DC);
+#endif
+
extern void php_clear_warnings(MYSQLI_WARNING *w);
extern void php_free_stmt_bind_buffer(BIND_BUFFER bbuf, int type);
extern void php_mysqli_report_error(const char *sqlstate, int errorno, const char *error TSRMLS_DC);
@@ -78,13 +83,6 @@ extern void php_mysqli_throw_sql_exception(char *sqlstate, int errorno TSRMLS_DC
extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
#endif
-#define REGISTER_MYSQLI_CLASS_ENTRY(name, mysqli_entry, class_functions) { \
- zend_class_entry tmp_ce; \
- INIT_CLASS_ENTRY(tmp_ce, name,class_functions); \
- tmp_ce.create_object = mysqli_objects_new; \
- mysqli_entry = zend_register_internal_class(&tmp_ce TSRMLS_CC); \
-} \
-
#define PHP_MYSQLI_EXPORT(__type) PHP_MYSQLI_API __type
PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRMLS_DC);
diff --git a/ext/mysqli/mysqli_prop.c b/ext/mysqli/mysqli_prop.c
index a9155702a6..908de63d23 100644
--- a/ext/mysqli/mysqli_prop.c
+++ b/ext/mysqli/mysqli_prop.c
@@ -13,6 +13,7 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Georg Richter <georg@php.net> |
+ | Andrey Hristov <andrey@php.net> |
+----------------------------------------------------------------------+
$Id$
@@ -189,6 +190,54 @@ static int link_affected_rows_read(mysqli_object *obj, zval **retval TSRMLS_DC)
}
/* }}} */
+
+/* {{{ property link_error_list_read */
+static int link_error_list_read(mysqli_object *obj, zval **retval TSRMLS_DC)
+{
+ MY_MYSQL *mysql;
+
+ MAKE_STD_ZVAL(*retval);
+
+ CHECK_STATUS(MYSQLI_STATUS_VALID);
+
+ mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
+
+ array_init(*retval);
+ if (mysql) {
+#if defined(MYSQLI_USE_MYSQLND)
+ if (mysql->mysql->data->error_info->error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->data->error_info->error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->data->error_info->error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(*retval, single_error);
+ }
+ }
+#else
+ if (mysql_errno(mysql->mysql)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_errno(mysql->mysql));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_sqlstate(mysql->mysql), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_error(mysql->mysql), 1);
+ add_next_index_zval(*retval, single_error);
+ }
+#endif
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+
/* link properties */
MYSQLI_MAP_PROPERTY_FUNC_LONG(link_errno_read, mysql_errno, MYSQLI_GET_MYSQL(MYSQLI_STATUS_INITIALIZED), ulong, "%lu")
MYSQLI_MAP_PROPERTY_FUNC_STRING(link_error_read, mysql_error, MYSQLI_GET_MYSQL(MYSQLI_STATUS_INITIALIZED))
@@ -236,6 +285,7 @@ static int link_stat_read(mysqli_object *obj, zval **retval TSRMLS_DC)\
}
/* }}} */
+
/* result properties */
/* {{{ property result_type_read */
@@ -340,6 +390,51 @@ static int stmt_affected_rows_read(mysqli_object *obj, zval **retval TSRMLS_DC)
}
/* }}} */
+/* {{{ property stmt_error_list_read */
+static int stmt_error_list_read(mysqli_object *obj, zval **retval TSRMLS_DC)
+{
+ MY_STMT * stmt;
+
+ MAKE_STD_ZVAL(*retval);
+ CHECK_STATUS(MYSQLI_STATUS_INITIALIZED);
+
+ stmt = (MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
+ array_init(*retval);
+ if (stmt && stmt->stmt) {
+#if defined(MYSQLI_USE_MYSQLND)
+ if (stmt->stmt->data && stmt->stmt->data->error_info->error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT * message;
+ zend_llist_position pos;
+ for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info->error_list, &pos);
+ message;
+ message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info->error_list, &pos))
+ {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), message->error_no);
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), message->sqlstate, 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), message->error, 1);
+ add_next_index_zval(*retval, single_error);
+ }
+ }
+#else
+ if (mysql_stmt_errno(stmt->stmt)) {
+ zval * single_error;
+ MAKE_STD_ZVAL(single_error);
+ array_init(single_error);
+ add_assoc_long_ex(single_error, "errno", sizeof("errno"), mysql_stmt_errno(stmt->stmt));
+ add_assoc_string_ex(single_error, "sqlstate", sizeof("sqlstate"), mysql_stmt_sqlstate(stmt->stmt), 1);
+ add_assoc_string_ex(single_error, "error", sizeof("error"), mysql_stmt_error(stmt->stmt), 1);
+ add_next_index_zval(*retval, single_error);
+ }
+#endif
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+
MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_insert_id_read, mysql_stmt_insert_id, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_num_rows_read, mysql_stmt_num_rows, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_param_count_read, mysql_stmt_param_count, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), ulong, "%lu")
@@ -357,6 +452,7 @@ const mysqli_property_entry mysqli_link_property_entries[] = {
{"connect_error", sizeof("connect_error") - 1, link_connect_error_read, NULL},
{"errno", sizeof("errno") - 1, link_errno_read, NULL},
{"error", sizeof("error") - 1, link_error_read, NULL},
+ {"error_list", sizeof("error_list") - 1, link_error_list_read, NULL},
{"field_count", sizeof("field_count") - 1, link_field_count_read, NULL},
{"host_info", sizeof("host_info") - 1, link_host_info_read, NULL},
{"info", sizeof("info") - 1, link_info_read, NULL},
@@ -371,27 +467,28 @@ const mysqli_property_entry mysqli_link_property_entries[] = {
{NULL, 0, NULL, NULL}
};
-/* should not be const, as it is patched during runtime */
-zend_property_info mysqli_link_property_info_entries[] = {
- {ZEND_ACC_PUBLIC, "affected_rows", sizeof("affected_rows") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "client_info", sizeof("client_info") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "client_version", sizeof("client_version") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "connect_errno", sizeof("connect_errno") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "connect_error", sizeof("connect_error") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "error", sizeof("error") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "field_count", sizeof("field_count") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "host_info", sizeof("host_info") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "info", sizeof("info") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "insert_id", sizeof("insert_id") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "server_info", sizeof("server_info") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "server_version", sizeof("server_version") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "stat", sizeof("stat") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "protocol_version", sizeof("protocol_version")-1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "thread_id", sizeof("thread_id") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "warning_count", sizeof("warning_count") - 1, 0, NULL, 0, NULL},
- {0, NULL, 0, 0, NULL, 0, NULL}
+
+const zend_property_info mysqli_link_property_info_entries[] = {
+ {ZEND_ACC_PUBLIC, "affected_rows", sizeof("affected_rows") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "client_info", sizeof("client_info") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "client_version", sizeof("client_version") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "connect_errno", sizeof("connect_errno") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "connect_error", sizeof("connect_error") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "error", sizeof("error") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "error_list", sizeof("error_list") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "field_count", sizeof("field_count") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "host_info", sizeof("host_info") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "info", sizeof("info") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "insert_id", sizeof("insert_id") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "server_info", sizeof("server_info") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "server_version", sizeof("server_version") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "stat", sizeof("stat") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "protocol_version", sizeof("protocol_version")-1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "thread_id", sizeof("thread_id") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "warning_count", sizeof("warning_count") - 1, -1, 0, NULL, 0, NULL},
+ {0, NULL, 0, -1, 0, NULL, 0, NULL}
};
@@ -404,13 +501,13 @@ const mysqli_property_entry mysqli_result_property_entries[] = {
{NULL, 0, NULL, NULL}
};
-zend_property_info mysqli_result_property_info_entries[] = {
- {ZEND_ACC_PUBLIC, "current_field", sizeof("current_field")-1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "field_count", sizeof("field_count") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "lengths", sizeof("lengths") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "num_rows", sizeof("num_rows") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "type", sizeof("type") - 1, 0, NULL, 0, NULL},
- {0, NULL, 0, 0, NULL, 0, NULL}
+const zend_property_info mysqli_result_property_info_entries[] = {
+ {ZEND_ACC_PUBLIC, "current_field", sizeof("current_field")-1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "field_count", sizeof("field_count") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "lengths", sizeof("lengths") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "num_rows", sizeof("num_rows") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "type", sizeof("type") - 1, -1, 0, NULL, 0, NULL},
+ {0, NULL, 0, -1, 0, NULL, 0, NULL}
};
const mysqli_property_entry mysqli_stmt_property_entries[] = {
@@ -421,23 +518,25 @@ const mysqli_property_entry mysqli_stmt_property_entries[] = {
{"field_count", sizeof("field_count") - 1, stmt_field_count_read, NULL},
{"errno", sizeof("errno") - 1, stmt_errno_read, NULL},
{"error", sizeof("error") - 1, stmt_error_read, NULL},
+ {"error_list", sizeof("error_list") - 1, stmt_error_list_read, NULL},
{"sqlstate", sizeof("sqlstate") - 1, stmt_sqlstate_read, NULL},
{"id", sizeof("id") - 1, stmt_id_read, NULL},
{NULL, 0, NULL, NULL}
};
-zend_property_info mysqli_stmt_property_info_entries[] = {
- {ZEND_ACC_PUBLIC, "affected_rows", sizeof("affected_rows") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "insert_id", sizeof("insert_id") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "num_rows", sizeof("num_rows") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "param_count",sizeof("param_count") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "field_count",sizeof("field_count") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "error", sizeof("error") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "id", sizeof("id") - 1, 0, NULL, 0, NULL},
- {0, NULL, 0, 0, NULL, 0, NULL}
+const zend_property_info mysqli_stmt_property_info_entries[] = {
+ {ZEND_ACC_PUBLIC, "affected_rows", sizeof("affected_rows") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "insert_id", sizeof("insert_id") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "num_rows", sizeof("num_rows") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "param_count",sizeof("param_count") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "field_count",sizeof("field_count") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "error", sizeof("error") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "error_list", sizeof("error_list") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "id", sizeof("id") - 1, -1, 0, NULL, 0, NULL},
+ {0, NULL, 0, -1, 0, NULL, 0, NULL}
};
/*
diff --git a/ext/mysqli/mysqli_report.h b/ext/mysqli/mysqli_report.h
index 1675439f34..4035a4b917 100644
--- a/ext/mysqli/mysqli_report.h
+++ b/ext/mysqli/mysqli_report.h
@@ -34,7 +34,7 @@
#endif
typedef struct {
- struct timeval starttime,
+ struct timeval starttime,
endtime; /* execution time */
} PR_TIME_INFO;
diff --git a/ext/mysqli/mysqli_result_iterator.c b/ext/mysqli/mysqli_result_iterator.c
new file mode 100644
index 0000000000..9a2e2634e6
--- /dev/null
+++ b/ext/mysqli/mysqli_result_iterator.c
@@ -0,0 +1,182 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@php.net> |
+ | Andrey Hristov <andrey@php.net> |
+ | Ulf Wendel <uw@php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: mysqli.c 299335 2010-05-13 11:05:09Z andrey $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <signal.h>
+
+#include "php.h"
+#include "php_ini.h"
+#include "php_mysqli_structs.h"
+#include "mysqli_priv.h"
+#include "zend_interfaces.h"
+
+
+extern zend_object_iterator_funcs php_mysqli_result_iterator_funcs;
+
+typedef struct {
+ zend_object_iterator intern;
+ mysqli_object *result;
+ zval *current_row;
+ my_longlong row_num;
+} php_mysqli_result_iterator;
+
+
+/* {{{ */
+zend_object_iterator *php_mysqli_result_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
+{
+ php_mysqli_result_iterator *iterator;
+
+ if (by_ref) {
+ zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
+ }
+ iterator = ecalloc(1, sizeof(php_mysqli_result_iterator));
+
+ Z_ADDREF_P(object);
+ iterator->intern.data = (void*)object;
+ iterator->intern.funcs = &php_mysqli_result_iterator_funcs;
+ iterator->result = (mysqli_object *) zend_object_store_get_object(object TSRMLS_CC);
+ iterator->row_num = -1;
+
+ return (zend_object_iterator*)iterator;
+}
+/* }}} */
+
+
+/* {{{ */
+static void php_mysqli_result_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
+{
+ php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
+
+ /* cleanup handled in sxe_object_dtor as we dont always have an iterator wrapper */
+ if (iterator->intern.data) {
+ zval_ptr_dtor((zval**)&iterator->intern.data);
+ }
+ if (iterator->current_row) {
+ zval_ptr_dtor(&iterator->current_row);
+ }
+ efree(iterator);
+}
+/* }}} */
+
+
+/* {{{ */
+static int php_mysqli_result_iterator_valid(zend_object_iterator *iter TSRMLS_DC)
+{
+ php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
+
+ return iterator->current_row && Z_TYPE_P(iterator->current_row) == IS_ARRAY ? SUCCESS : FAILURE;
+}
+/* }}} */
+
+
+/* {{{ */
+static void php_mysqli_result_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
+{
+ php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
+
+ *data = &iterator->current_row;
+}
+/* }}} */
+
+
+/* {{{ */
+static void php_mysqli_result_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
+{
+
+ php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
+ mysqli_object *intern = iterator->result;
+ MYSQL_RES *result;
+
+ MYSQLI_FETCH_RESOURCE_BY_OBJ(result, MYSQL_RES *, intern, "mysqli_result", MYSQLI_STATUS_VALID);
+ if (iterator->current_row) {
+ zval_ptr_dtor(&iterator->current_row);
+ }
+ MAKE_STD_ZVAL(iterator->current_row);
+ php_mysqli_fetch_into_hash_aux(iterator->current_row, result, MYSQLI_ASSOC TSRMLS_CC);
+ if (Z_TYPE_P(iterator->current_row) == IS_ARRAY) {
+ iterator->row_num++;
+ }
+}
+/* }}} */
+
+
+/* {{{ */
+static void php_mysqli_result_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
+{
+ php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
+ mysqli_object *intern = iterator->result;
+ MYSQL_RES *result;
+
+ MYSQLI_FETCH_RESOURCE_BY_OBJ(result, MYSQL_RES *, intern, "mysqli_result", MYSQLI_STATUS_VALID);
+
+ if (mysqli_result_is_unbuffered(result)) {
+#if MYSQLI_USE_MYSQLND
+ if (result->unbuf->eof_reached) {
+#else
+ if (result->eof) {
+#endif
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data fetched with MYSQLI_USE_RESULT can be iterated only once");
+ return;
+ }
+ } else {
+ mysql_data_seek(result, 0);
+ }
+ iterator->row_num = -1;
+ php_mysqli_result_iterator_move_forward(iter TSRMLS_CC);
+}
+/* }}} */
+
+
+/* {{{ php_mysqli_result_iterator_current_key */
+static int php_mysqli_result_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+{
+ php_mysqli_result_iterator *iterator = (php_mysqli_result_iterator*) iter;
+
+ *int_key = (ulong) iterator->row_num;
+ return HASH_KEY_IS_LONG;
+}
+/* }}} */
+
+
+/* {{{ php_mysqli_result_iterator_funcs */
+zend_object_iterator_funcs php_mysqli_result_iterator_funcs = {
+ php_mysqli_result_iterator_dtor,
+ php_mysqli_result_iterator_valid,
+ php_mysqli_result_iterator_current_data,
+ php_mysqli_result_iterator_current_key,
+ php_mysqli_result_iterator_move_forward,
+ php_mysqli_result_iterator_rewind,
+};
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqli/mysqli_warning.c b/ext/mysqli/mysqli_warning.c
index d897a82b8f..33e2b85a2c 100644
--- a/ext/mysqli/mysqli_warning.c
+++ b/ext/mysqli/mysqli_warning.c
@@ -102,7 +102,7 @@ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
#else
/* {{{ MYSQLI_WARNING *php_new_warning */
static
-MYSQLI_WARNING *php_new_warning(const zval *reason, int errorno TSRMLS_DC)
+MYSQLI_WARNING *php_new_warning(const zval * reason, int errorno TSRMLS_DC)
{
MYSQLI_WARNING *w;
@@ -123,17 +123,17 @@ MYSQLI_WARNING *php_new_warning(const zval *reason, int errorno TSRMLS_DC)
/* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
-MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
+MYSQLI_WARNING * php_get_warnings(MYSQLND_CONN_DATA * mysql TSRMLS_DC)
{
MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
MYSQL_RES *result;
zval *row;
- if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
+ if (mysql->m->query(mysql, "SHOW WARNINGS", 13 TSRMLS_CC)) {
return NULL;
}
- result = mysql_use_result(mysql);
+ result = mysql->m->use_result(mysql TSRMLS_CC);
for (;;) {
zval **entry;
@@ -267,7 +267,9 @@ PHP_METHOD(mysqli_warning, __construct)
{
zval *z;
mysqli_object *obj;
+#ifndef MYSQLI_USE_MYSQLND
MYSQL *hdl;
+#endif
MYSQLI_WARNING *w;
MYSQLI_RESOURCE *mysqli_resource;
@@ -282,23 +284,36 @@ PHP_METHOD(mysqli_warning, __construct)
if (obj->zo.ce == mysqli_link_class_entry) {
MY_MYSQL *mysql;
MYSQLI_FETCH_RESOURCE_CONN(mysql, &z, MYSQLI_STATUS_VALID);
- hdl = mysql->mysql;
+ if (mysql_warning_count(mysql->mysql)) {
+#ifndef MYSQLI_USE_MYSQLND
+ w = php_get_warnings(mysql->mysql TSRMLS_CC);
+#else
+ w = php_get_warnings(mysql->mysql->data TSRMLS_CC);
+#endif
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No warnings found");
+ RETURN_FALSE;
+ }
} else if (obj->zo.ce == mysqli_stmt_class_entry) {
MY_STMT *stmt;
MYSQLI_FETCH_RESOURCE_STMT(stmt, &z, MYSQLI_STATUS_VALID);
+#ifndef MYSQLI_USE_MYSQLND
hdl = mysqli_stmt_get_connection(stmt->stmt);
+ if (mysql_warning_count(hdl)) {
+ w = php_get_warnings(hdl TSRMLS_CC);
+#else
+ if (mysqlnd_stmt_warning_count(stmt->stmt)) {
+ w = php_get_warnings(mysqli_stmt_get_connection(stmt->stmt) TSRMLS_CC);
+#endif
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No warnings found");
+ RETURN_FALSE;
+ }
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid class argument");
RETURN_FALSE;
}
- if (mysql_warning_count(hdl)) {
- w = php_get_warnings(hdl TSRMLS_CC);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No warnings found");
- RETURN_FALSE;
- }
-
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = mysqli_resource->info = (void *)w;
mysqli_resource->status = MYSQLI_STATUS_VALID;
@@ -330,11 +345,11 @@ const mysqli_property_entry mysqli_warning_property_entries[] = {
/* }}} */
/* {{{ mysqli_warning_property_info_entries */
-zend_property_info mysqli_warning_property_info_entries[] = {
- {ZEND_ACC_PUBLIC, "message", sizeof("message") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, 0, NULL, 0, NULL},
- {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, 0, NULL, 0, NULL},
- {0, NULL, 0, 0, NULL, 0, NULL}
+const zend_property_info mysqli_warning_property_info_entries[] = {
+ {ZEND_ACC_PUBLIC, "message", sizeof("message") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "sqlstate", sizeof("sqlstate") - 1, -1, 0, NULL, 0, NULL},
+ {ZEND_ACC_PUBLIC, "errno", sizeof("errno") - 1, -1, 0, NULL, 0, NULL},
+ {0, NULL, 0, -1, 0, NULL, 0, NULL}
};
/* }}} */
diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h
index 3ef47ef0f1..ed468e2823 100644
--- a/ext/mysqli/php_mysqli_structs.h
+++ b/ext/mysqli/php_mysqli_structs.h
@@ -12,7 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Georg Richter <georg@php.net> |
+ | Authors: Georg Richter <georg@php.net> |
+ | Andrey Hristov <andrey@php.net> |
+ | Ulf Wendel <uw@php.net> |
+----------------------------------------------------------------------+
$Id$
@@ -207,6 +209,36 @@ extern zend_class_entry *mysqli_result_class_entry;
extern zend_class_entry *mysqli_driver_class_entry;
extern zend_class_entry *mysqli_warning_class_entry;
extern zend_class_entry *mysqli_exception_class_entry;
+extern int php_le_pmysqli(void);
+extern void php_mysqli_dtor_p_elements(void *data);
+
+extern void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status TSRMLS_DC);
+
+extern zend_object_iterator_funcs php_mysqli_result_iterator_funcs;
+extern zend_object_iterator *php_mysqli_result_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
+
+extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, long fetchtype TSRMLS_DC);
+
+#ifdef HAVE_SPL
+extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
+#endif
+
+#define MYSQLI_DISABLE_MQ if (mysql->multi_query) { \
+ mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \
+ mysql->multi_query = 0; \
+}
+
+#define MYSQLI_ENABLE_MQ if (!mysql->multi_query) { \
+ mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON); \
+ mysql->multi_query = 1; \
+}
+
+#define REGISTER_MYSQLI_CLASS_ENTRY(name, mysqli_entry, class_functions) { \
+ zend_class_entry ce; \
+ INIT_CLASS_ENTRY(ce, name,class_functions); \
+ ce.create_object = mysqli_objects_new; \
+ mysqli_entry = zend_register_internal_class(&ce TSRMLS_CC); \
+} \
#define MYSQLI_REGISTER_RESOURCE_EX(__ptr, __zval) \
((mysqli_object *) zend_object_store_get_object(__zval TSRMLS_CC))->ptr = __ptr;
@@ -242,6 +274,21 @@ extern zend_class_entry *mysqli_exception_class_entry;
}\
}
+#define MYSQLI_FETCH_RESOURCE_BY_OBJ(__ptr, __type, __obj, __name, __check) \
+{ \
+ MYSQLI_RESOURCE *my_res; \
+ if (!(my_res = (MYSQLI_RESOURCE *)(__obj->ptr))) {\
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't fetch %s", intern->zo.ce->name);\
+ return;\
+ }\
+ __ptr = (__type)my_res->ptr; \
+ if (__check && my_res->status < __check) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object or resource %s\n", intern->zo.ce->name); \
+ return;\
+ }\
+}
+
+
#define MYSQLI_FETCH_RESOURCE_CONN(__ptr, __id, __check) \
{ \
MYSQLI_FETCH_RESOURCE((__ptr), MY_MYSQL *, (__id), "mysqli_link", (__check)); \
@@ -285,7 +332,6 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqli)
long num_inactive_persistent;
long max_persistent;
long allow_persistent;
- long cache_size;
unsigned long default_port;
char *default_host;
char *default_user;
diff --git a/ext/mysqli/tests/057.phpt b/ext/mysqli/tests/057.phpt
index 8c8b3eeed7..2cb887506a 100644
--- a/ext/mysqli/tests/057.phpt
+++ b/ext/mysqli/tests/057.phpt
@@ -91,6 +91,9 @@ object(mysqli_stmt)#%d (%d) {
int(0)
[%u|b%"error"]=>
%unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ array(0) {
+ }
[%u|b%"sqlstate"]=>
%unicode|string%(5) "00000"
[%u|b%"id"]=>
diff --git a/ext/mysqli/tests/bug34810.phpt b/ext/mysqli/tests/bug34810.phpt
index f975506187..1ea89d9bee 100644
--- a/ext/mysqli/tests/bug34810.phpt
+++ b/ext/mysqli/tests/bug34810.phpt
@@ -77,6 +77,9 @@ object(mysqli)#%d (%d) {
int(0)
[%u|b%"error"]=>
%unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ array(0) {
+ }
[%u|b%"field_count"]=>
int(0)
[%u|b%"host_info"]=>
@@ -89,8 +92,8 @@ object(mysqli)#%d (%d) {
%unicode|string%(%d) "%s"
[%u|b%"server_version"]=>
int(%d)
- ["stat"]=>
- %s
+ [%u|b%"stat"]=>
+ string(%d) "Uptime: %d Threads: %d Questions: %d Slow queries: %d Opens: %d Flush tables: %d Open tables: %d Queries per second avg: %d.%d"
[%u|b%"sqlstate"]=>
%unicode|string%(5) "00000"
[%u|b%"protocol_version"]=>
@@ -115,6 +118,8 @@ object(mysqli)#%d (%d) {
int(0)
[%u|b%"error"]=>
%unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ NULL
[%u|b%"field_count"]=>
NULL
[%u|b%"host_info"]=>
@@ -127,7 +132,7 @@ object(mysqli)#%d (%d) {
NULL
[%u|b%"server_version"]=>
NULL
- ["stat"]=>
+ [%u|b%"stat"]=>
NULL
[%u|b%"sqlstate"]=>
NULL
diff --git a/ext/mysqli/tests/bug55582.phpt b/ext/mysqli/tests/bug55582.phpt
index 85fc7f6ce8..3933845147 100644
--- a/ext/mysqli/tests/bug55582.phpt
+++ b/ext/mysqli/tests/bug55582.phpt
@@ -38,4 +38,4 @@ Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s
int(0)
NULL
int(1)
-done \ No newline at end of file
+done
diff --git a/ext/mysqli/tests/mysqli_auth_pam.phpt b/ext/mysqli/tests/mysqli_auth_pam.phpt
new file mode 100644
index 0000000000..fe1552954a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_auth_pam.phpt
@@ -0,0 +1,98 @@
+--TEST--
+PAM auth plugin
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (version_compare(PHP_VERSION, '5.3.99') >= 0) {
+ die("SKIP Available as of PHP 5.3.99");
+}
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+}
+
+if ($link->server_version < 50500)
+ die(sprintf("SKIP Needs MySQL 5.5 or newer, found MySQL %s\n", $link->server_info));
+
+if (!$res = $link->query("SHOW PLUGINS"))
+ die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error));
+
+$have_pam = false;
+while ($row = $res->fetch_assoc()) {
+ if (isset($row['Name']) && ('mysql_clear_password' == $row['Name'])) {
+ $have_pam = true;
+ break;
+ }
+}
+$res->close();
+
+if (!$have_pam)
+ die("SKIP Server PAM plugin not installed");
+
+
+mysqli_query($link, 'DROP USER pamtest');
+mysqli_query($link, 'DROP USER pamtest@localhost');
+
+if (!mysqli_query($link, 'CREATE USER pamtest@"%" IDENTIFIED WITH mysql_clear_password') ||
+ !mysqli_query($link, 'CREATE USER pamtest@"localhost" IDENTIFIED WITH mysql_clear_password')) {
+ printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip CREATE USER failed");
+}
+
+if (!$link->query("CREATE TABLE test (id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)"))
+ die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error));
+
+
+
+if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pamtest@'%%'", $db)) ||
+ !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pamtest@'localhost'", $db))) {
+ printf("skip Cannot grant SELECT to user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip GRANT failed");
+}
+?>
+--INI--
+max_execution_time=240
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!$link = my_mysqli_connect($host, 'pamtest', 'pamtest', $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ } else {
+
+ if (!$res = $link->query("SELECT id FROM test WHERE id = 1"))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ if ($row['id'] != 1) {
+ printf("[004] Expecting 1 got %s/'%s'", gettype($row['id']), $row['id']);
+ }
+
+ $res->close();
+ $link->close();
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+ mysqli_query($link, 'DROP USER pamtest');
+ mysqli_query($link, 'DROP USER pamtest@localhost');
+?>
+--EXPECTF--
+
+Warning: mysqli_real_connect(): (28000/1045): Access denied for user %s
+[001] Cannot connect to the server using host=%s
+done!
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt b/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt
index 530b4647c4..e4d0b08a85 100644
--- a/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt
+++ b/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt
@@ -68,11 +68,6 @@ require_once('skipifconnectfailure.inc');
@$mysqli->sqlstate, gettype(@$mysqli->sqlstate),
@mysqli_sqlstate($mysqli), gettype(@mysqli_sqlstate($mysqli)));
- assert(@mysqli_stat($mysqli) === @$mysqli->sstat);
- printf("mysqli->stat = '%s'/%s ('%s'/%s)\n",
- @$mysqli->stat, gettype(@$mysqli->stat),
- @mysqli_stat($mysqli), gettype(@mysqli_stat($mysqli)));
-
assert(@mysqli_get_host_info($mysqli) === @$mysqli->host_info);
printf("mysqli->host_info = '%s'/%s ('%s'/%s)\n",
@$mysqli->host_info, gettype(@$mysqli->host_info),
@@ -151,11 +146,12 @@ Without RS
Class variables:
affected_rows = 'NULL'
client_info = 'NULL'
-client_version = '%d'
-connect_errno = '%d'
-connect_error = '%s'
+client_version = '%s'
+connect_errno = '%s'
+connect_error = ''%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
@@ -171,11 +167,12 @@ warning_count = 'NULL'
Object variables:
affected_rows = 'NULL'
client_info = 'NULL'
-client_version = '%d'
-connect_errno = '%d'
+client_version = '%s'
+connect_errno = '%s'
connect_error = '%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
@@ -192,18 +189,17 @@ Magic, magic properties:
mysqli->affected_rows = ''/NULL (''/NULL)
Warning: assert(): Assertion failed in %s on line %d
-mysqli->client_info = ''/NULL ('%s'/string)
-mysqli->client_version = '%d'/integer ('%d'/integer)
+mysqli->client_info = ''/NULL ('%s'/%s)
+mysqli->client_version = '%s'/integer ('%s'/integer)
mysqli->errno = ''/NULL (''/NULL)
mysqli->error = ''/NULL (''/NULL)
mysqli->field_count = ''/NULL (''/NULL)
mysqli->insert_id = ''/NULL (''/NULL)
mysqli->sqlstate = ''/NULL (''/NULL)
-mysqli->stat = ''/NULL (''/NULL)
mysqli->host_info = ''/NULL (''/NULL)
mysqli->info = ''/NULL (''/NULL)
-Warning: assert(): Assertion failed in %s on line 78
+Warning: assert(): Assertion failed in %s on line %d
mysqli->thread_id = ''/NULL (''/NULL)
mysqli->protocol_version = ''/NULL (''/NULL)
mysqli->server_info = ''/NULL (''/NULL)
@@ -216,18 +212,19 @@ setting mysqli->unknown, @mysqli_unknown = '13'
setting mysqli->unknown, @mysqli_unknown = 'friday'
Access hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):
-mysqli->connect_error = '%s'/string ('%s'/string)
-mysqli->connect_errno = '%d'/integer ('%d'/integer)
+mysqli->connect_error = '%s'/%s)
+mysqli->connect_errno = '%s'/integer ('%s'/integer)
With RS
Class variables:
affected_rows = 'NULL'
client_info = 'NULL'
-client_version = '%d'
-connect_errno = '%d'
+client_version = '%s'
+connect_errno = '%s'
connect_error = '%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
@@ -243,11 +240,12 @@ warning_count = 'NULL'
Object variables:
affected_rows = 'NULL'
client_info = 'NULL'
-client_version = '%d'
-connect_errno = '%d'
+client_version = '%s'
+connect_errno = '%s'
connect_error = '%s'
errno = 'NULL'
error = 'NULL'
+error_list = 'NULL'
field_count = 'NULL'
host_info = 'NULL'
info = 'NULL'
@@ -263,15 +261,14 @@ warning_count = 'NULL'
Magic, magic properties:
mysqli->affected_rows = ''/NULL (''/NULL)
-Warning: assert(): Assertion failed in %s on line %s
-mysqli->client_info = ''/NULL ('%s'/string)
-mysqli->client_version = '%d'/integer ('%d'/integer)
+Warning: assert(): Assertion failed in %s on line %d
+mysqli->client_info = ''/NULL ('%s'/%s)
+mysqli->client_version = '%s'/integer ('%s'/integer)
mysqli->errno = ''/NULL (''/NULL)
mysqli->error = ''/NULL (''/NULL)
mysqli->field_count = ''/NULL (''/NULL)
mysqli->insert_id = ''/NULL (''/NULL)
mysqli->sqlstate = ''/NULL (''/NULL)
-mysqli->stat = ''/NULL (''/NULL)
mysqli->host_info = ''/NULL (''/NULL)
mysqli->info = ''/NULL (''/NULL)
@@ -288,6 +285,6 @@ setting mysqli->unknown, @mysqli_unknown = '13'
setting mysqli->unknown, @mysqli_unknown = 'friday'
Access hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):
-mysqli->connect_error = '%s'/string ('%s'/string)
-mysqli->connect_errno = '%d'/integer ('%d'/integer)
+mysqli->connect_error = '%s'/%s)
+mysqli->connect_errno = '%s'/integer ('%s'/integer)
done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
index 0e0fe6cf57..5fd4b6f45c 100644
--- a/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
+++ b/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
@@ -173,22 +173,6 @@ Modifiers: 256
Number of Parameters: 0
Number of Required Parameters: 0
-Inspecting method 'client_encoding'
-isFinal: no
-isAbstract: no
-isPublic: yes
-isPrivate: no
-isProtected: no
-isStatic: no
-isConstructor: no
-isDestructor: no
-isInternal: yes
-isUserDefined: no
-returnsReference: no
-Modifiers: 256
-Number of Parameters: 0
-Number of Required Parameters: 0
-
Inspecting method 'close'
isFinal: no
isAbstract: no
@@ -1145,6 +1129,14 @@ isStatic: no
isDefault: yes
Modifiers: 256
+Inspecting property 'error_list'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
Inspecting property 'field_count'
isPublic: yes
isPrivate: no
@@ -1239,6 +1231,7 @@ Default property 'connect_errno'
Default property 'connect_error'
Default property 'errno'
Default property 'error'
+Default property 'error_list'
Default property 'field_count'
Default property 'host_info'
Default property 'info'
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
index b86129c57e..988b82732a 100644
--- a/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
+++ b/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
@@ -35,7 +35,7 @@ isInstantiable: yes
isInterface: no
isAbstract: no
isFinal: no
-isIteratable: no
+isIteratable: yes
Modifiers: '0'
Parent Class: ''
Extension: 'mysqli'
@@ -234,9 +234,23 @@ isInternal: yes
isUserDefined: no
returnsReference: no
Modifiers: 256
-Number of Parameters: 0
+Number of Parameters: 2
Number of Required Parameters: 0
+Inspecting parameter 'class_name' of method 'fetch_object'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'params' of method 'fetch_object'
+isArray: yes
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
Inspecting method 'fetch_row'
isFinal: no
isAbstract: no
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt b/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt
index 7cbb127212..acf7379198 100644
--- a/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt
+++ b/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt
@@ -97,6 +97,9 @@ printf("stmt->errno = '%s'\n", $stmt->errno);
assert(mysqli_stmt_error($stmt) === $stmt->error);
printf("stmt->error = '%s'\n", $stmt->error);
+assert(mysqli_stmt_error_list($stmt) === $stmt->error_list);
+var_dump("stmt->error = ", $stmt->error_list);
+
assert(mysqli_stmt_field_count($stmt) === $stmt->field_count);
printf("stmt->field_count = '%s'\n", $stmt->field_count);
@@ -143,6 +146,7 @@ Class variables:
affected_rows
errno
error
+error_list
field_count
id
insert_id
@@ -158,6 +162,7 @@ param_count
field_count
errno
error
+error_list
sqlstate
id
@@ -173,6 +178,9 @@ stmt->affected_rows = ''
stmt->affected_rows = '1'
stmt->errno = '0'
stmt->error = ''
+string(14) "stmt->error = "
+array(0) {
+}
stmt->field_count = '0'
stmt->id = '%d'
stmt->insert_id = '0'
diff --git a/ext/mysqli/tests/mysqli_fetch_array_large.phpt b/ext/mysqli/tests/mysqli_fetch_array_large.phpt
index ae83b3f8b1..3c6a0f03f3 100644
--- a/ext/mysqli/tests/mysqli_fetch_array_large.phpt
+++ b/ext/mysqli/tests/mysqli_fetch_array_large.phpt
@@ -5,6 +5,8 @@ mysqli_fetch_array() - large packages (to test compression)
require_once('skipif.inc');
require_once('skipifconnectfailure.inc');
?>
+--INI--
+memory_limit=-1
--FILE--
<?php
require_once("connect.inc");
@@ -164,4 +166,4 @@ require_once('skipifconnectfailure.inc');
--EXPECTF--
stop: %s
stop: %s
-done! \ No newline at end of file
+done!
diff --git a/ext/mysqli/tests/mysqli_fetch_object.phpt b/ext/mysqli/tests/mysqli_fetch_object.phpt
index f164c4e19b..c70871e6ea 100644
--- a/ext/mysqli/tests/mysqli_fetch_object.phpt
+++ b/ext/mysqli/tests/mysqli_fetch_object.phpt
@@ -10,6 +10,8 @@ require_once('skipifconnectfailure.inc');
<?php
include_once("connect.inc");
+ set_error_handler('handle_catchable_fatal');
+
$tmp = NULL;
$link = NULL;
@@ -57,7 +59,7 @@ require_once('skipifconnectfailure.inc');
}
- $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_construct', null);
+ $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_construct', array());
if (($obj->ID !== "3") || ($obj->label !== "c") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) {
printf("[006] Object seems wrong. [%d] %s\n", mysqli_errno($link), mysqli_error($link));
@@ -97,7 +99,7 @@ require_once('skipifconnectfailure.inc');
Also, I did not ask to get exceptions using the mysqli_options()
*/
try {
- if (false !== ($obj = mysqli_fetch_object($res, 'mysqli_fetch_object_construct', 'a')))
+ if (false !== ($obj = @mysqli_fetch_object($res, 'mysqli_fetch_object_construct', 'a')))
printf("[011] Should have failed\n");
} catch (Exception $e) {
printf("%s\n", $e->getMessage());
@@ -136,22 +138,19 @@ require_once('skipifconnectfailure.inc');
require_once("clean_table.inc");
?>
--EXPECTF--
-Warning: Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d
-
-Warning: Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
-
-Notice: Undefined variable: a in %s on line %d
-
-Notice: Undefined variable: b in %s on line %d
-
-Warning: Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
-
-Notice: Undefined variable: b in %s on line %d
+[E_WARNING] mysqli_fetch_object() expects at least 1 parameter, 0 given in %s on line %d
+[E_WARNING] mysqli_fetch_object() expects parameter 1 to be mysqli_result, null given in %s on line %d
+[E_WARNING] Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: a in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
NULL
NULL
-
-Warning: mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
+[E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
NULL
+[E_RECOVERABLE_ERROR] Argument 3 passed to mysqli_fetch_object() must be of the type array, string given in %s on line %d
Parameter ctor_params must be an array
Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_object_oo.phpt b/ext/mysqli/tests/mysqli_fetch_object_oo.phpt
index 3b263e49e4..1d62c6dd4f 100644
--- a/ext/mysqli/tests/mysqli_fetch_object_oo.phpt
+++ b/ext/mysqli/tests/mysqli_fetch_object_oo.phpt
@@ -9,6 +9,7 @@ require_once('skipifconnectfailure.inc');
--FILE--
<?php
require_once("connect.inc");
+ set_error_handler('handle_catchable_fatal');
$tmp = NULL;
$link = NULL;
@@ -110,21 +111,24 @@ require_once('skipifconnectfailure.inc');
require_once("clean_table.inc");
?>
--EXPECTF--
-Warning: Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d
-
-Warning: Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
-
-Notice: Undefined variable: a in %s on line %d
-
-Notice: Undefined variable: b in %s on line %d
-
-Warning: Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
-
-Notice: Undefined variable: b in %s on line %d
+[E_WARNING] mysqli_result::__construct(): invalid object or resource mysql%s
+%s on line %d
+[E_WARNING] mysqli_result::fetch_object(): Couldn't fetch mysqli_result in %s on line %d
+[E_WARNING] mysqli_result::fetch_object() expects parameter 1 to be string, object given in %s on line %d
+[E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, object given in %s on line %d
+[E_WARNING] mysqli_result::fetch_object() expects parameter 1 to be string, object given in %s on line %d
+[E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, object given in %s on line %d
+[E_WARNING] mysqli_result::fetch_object() expects at most 2 parameters, 3 given in %s on line %d
+[E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, null given in %s on line %d
+[E_WARNING] Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: a in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
NULL
NULL
-
-Warning: mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
+[E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
NULL
Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_free_result.phpt b/ext/mysqli/tests/mysqli_free_result.phpt
index a065e14821..28f338ac6d 100644
--- a/ext/mysqli/tests/mysqli_free_result.phpt
+++ b/ext/mysqli/tests/mysqli_free_result.phpt
@@ -10,7 +10,6 @@ require_once('skipifconnectfailure.inc');
<?php
require_once("connect.inc");
- $db = 'test';
$tmp = NULL;
$link = NULL;
@@ -76,4 +75,4 @@ bool(false)
Warning: mysqli_free_result() expects parameter 1 to be mysqli_result, boolean given in %s on line %d
NULL
-done! \ No newline at end of file
+done!
diff --git a/ext/mysqli/tests/mysqli_get_cache_stats_off.phpt b/ext/mysqli/tests/mysqli_get_cache_stats_off.phpt
deleted file mode 100644
index bbfe503b2b..0000000000
--- a/ext/mysqli/tests/mysqli_get_cache_stats_off.phpt
+++ /dev/null
@@ -1,56 +0,0 @@
---TEST--
-mysqli_get_cache_stats() - disabled via php.ini
---INI--
-mysqlnd.collect_statistics="0"
-mysqlnd.collect_memory_statistics="0"
---SKIPIF--
-<?PHP
-require_once('skipif.inc');
-require_once('skipifemb.inc');
-require_once('skipifconnectfailure.inc');
-if (!function_exists('mysqli_get_cache_stats')) {
- die("skip only available with mysqlnd");
-}
-?>
---FILE--
-<?php
- $before = mysqli_get_cache_stats();
- /*
- NOTE: the function belongs to the mysqnd zval cache. The
- mysqlnd zval cache was part of PHP from PHP 5.3.0(-dev) to
- PHP 5.3.0RC3 or something. And it was turned off by default.
- The function never returned anything meaningful in any released version of PHP.
- */
- if (!is_array($before)) {
- printf("[001] Expecting array, got %s.\n", gettype($before));
- var_dump($before);
- }
-
- require_once('table.inc');
- if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
- printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
- while ($row = mysqli_fetch_assoc($res))
- ;
- if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
- printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
- while ($row = mysqli_fetch_assoc($res))
- ;
-
- $after = mysqli_get_cache_stats();
- if ($before !== $after) {
- printf("[002] Statistics have changed\n");
- var_dump($before);
- var_dump($after);
- }
- mysqli_close($link);
-
- print "done!";
-?>
---CLEAN--
-<?php
- require_once("clean_table.inc");
-?>
---EXPECTF--
-done!
diff --git a/ext/mysqli/tests/mysqli_kill.phpt b/ext/mysqli/tests/mysqli_kill.phpt
index 3606fda0b1..94e4e8f2e0 100644
--- a/ext/mysqli/tests/mysqli_kill.phpt
+++ b/ext/mysqli/tests/mysqli_kill.phpt
@@ -42,33 +42,33 @@ require_once('skipifconnectfailure.inc');
var_dump($link);
if ($IS_MYSQLND) {
if ($link->info != 'Records: 6 Duplicates: 0 Warnings: 0') {
- printf("[008] mysqlnd used to be more verbose and used to support SELECT");
+ printf("[008] mysqlnd used to be more verbose and used to support SELECT\n");
}
if ($link->stat != NULL) {
printf("[009] NULL expected because of error.\n");
}
} else {
if ($link->info != NULL) {
- printf("[010] Time for wonders - libmysql has started to support SELECT, change test");
+ printf("[008] Time for wonders - libmysql has started to support SELECT, change test\n");
}
}
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
- printf("[011] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ printf("[010] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
mysqli_kill($link, -1);
if ((!$res = mysqli_query($link, "SELECT id FROM test LIMIT 1")) ||
(!$tmp = mysqli_fetch_assoc($res))) {
- printf("[012] Connection should not be gone, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ printf("[011] Connection should not be gone, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
}
var_dump($tmp);
mysqli_free_result($res);
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
- printf("[013] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ printf("[012] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db); mysqli_kill($link, -1);
@@ -99,6 +99,18 @@ object(mysqli)#%d (%d) {
int(2006)
[%u|b%"error"]=>
%unicode|string%(%d) "%s"
+ [%u|b%"error_list"]=>
+ array(1) {
+ [0]=>
+ array(3) {
+ [%u|b%"errno"]=>
+ int(2006)
+ [%u|b%"sqlstate"]=>
+ %unicode|string%(5) "%s"
+ [%u|b%"error"]=>
+ %unicode|string%(%d) "%s"
+ }
+ }
[%u|b%"field_count"]=>
int(0)
[%u|b%"host_info"]=>
@@ -111,7 +123,7 @@ object(mysqli)#%d (%d) {
%unicode|string%(%d) "%s"
[%u|b%"server_version"]=>
int(%d)
- ["stat"]=>
+ [%u|b%"stat"]=>
%s
[%u|b%"sqlstate"]=>
%unicode|string%(5) "HY000"
@@ -130,4 +142,4 @@ array(1) {
}
Warning: mysqli_kill(): processid should have positive value in %s on line %d
-done!
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_magic_quotes.phpt b/ext/mysqli/tests/mysqli_magic_quotes.phpt
deleted file mode 100644
index 16848a8e8f..0000000000
--- a/ext/mysqli/tests/mysqli_magic_quotes.phpt
+++ /dev/null
@@ -1,128 +0,0 @@
---TEST--
-magic_quotes_runtime (DEPRECATED)
---SKIPIF--
-<?php
-require_once('skipif.inc');
-require_once('skipifemb.inc');
-require_once('skipifconnectfailure.inc');
-
-if (version_compare(PHP_VERSION, '5.3.98') >= 0) {
- die("skip: PHP 5.3 test");
-}
-?>
---INI--
-magic_quotes_runtime=1
---FILE--
-<?php
- require('connect.inc');
-
- if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
- printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
-
- $query = sprintf("SELECT '%s', '%s', '%s', '%s' FROM DUAL",
- mysqli_real_escape_string($link, "'"),
- mysqli_real_escape_string($link, '"'),
- mysqli_real_escape_string($link, '\0'),
- mysqli_real_escape_string($link, '\\'));
-
- if (!$res = mysqli_query($link, $query)) {
- printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
-
- while ($row = $res->fetch_assoc()) {
- var_dump($row);
- }
-
- $res->free();
-
- $expected = array(
- "'" => "\\'",
- '"' => "\\\"",
- "\\0" => "\\\\0",
- "\\" => "\\\\",
- );
- $expectedBoth = array(
- 0 => "\\'",
- "'" => "\\'",
- 1 => "\\\"",
- '"' => "\\\"",
- 2 => "\\\\0",
- "\\0" => "\\\\0",
- 3 => "\\\\",
- "\\" => "\\\\",
- );
-
- if (!$res = mysqli_query($link, $query)) {
- printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
- $row = mysqli_fetch_row($res);
- echo "Equal:";var_dump($row === array_values($expected));
- if ($row !== array_values($expected)) {
- var_dump($row, array_values($expected));
- }
- $res->free();
-
- if (!$res = mysqli_query($link, $query)) {
- printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
- $row = mysqli_fetch_array($res, MYSQLI_BOTH);
- echo "Equal:";var_dump($row === $expectedBoth);
- if ($row !== $expectedBoth) {
- var_dump($row, $expectedBoth);
- }
- $res->free();
-
- class fetch_object {
- public function __set($key, $value) {
- printf(">%s< => >%s<\n", $key, $value);
- }
- }
-
- if (!$res = mysqli_query($link, $query)) {
- printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
- $obj = mysqli_fetch_object($res, "fetch_object");
- $res->free();
-
- if (false && $IS_MYSQLND) {
- if (!$res = mysqli_query($link, $query)) {
- printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- }
- $row = @mysqli_fetch_all($res, MYSQLI_ASSOC);
- if ($row[0] !== $expected) {
- printf("[015] Wrong data, dumping\n");
- var_dump($row);
- }
- }
-
- $link->close();
-
- print "done!";
-?>
---EXPECTF--
-Deprecated: Directive 'magic_quotes_runtime' is deprecated in PHP 5.3 and greater in Unknown on line %d
-
-Warning: mysqli_result::fetch_assoc(): magic_quotes_runtime are deprecated since PHP 5.3 in %s on line %d
-array(4) {
- ["'"]=>
- string(2) "\'"
- ["""]=>
- string(2) "\""
- ["\0"]=>
- string(3) "\\0"
- ["\"]=>
- string(2) "\\"
-}
-
-Warning: mysqli_fetch_row(): magic_quotes_runtime are deprecated since PHP 5.3 in %s on line %d
-Equal:bool(true)
-
-Warning: mysqli_fetch_array(): magic_quotes_runtime are deprecated since PHP 5.3 in %s on line %d
-Equal:bool(true)
-
-Warning: mysqli_fetch_object(): magic_quotes_runtime are deprecated since PHP 5.3 in %s on line %d
->'< => >\'<
->"< => >\"<
->\0< => >\\0<
->\< => >\\<
-done!
diff --git a/ext/mysqli/tests/mysqli_options_openbasedir.phpt b/ext/mysqli/tests/mysqli_options_openbasedir.phpt
index 81d8ffef64..4c13ec1ef0 100644
--- a/ext/mysqli/tests/mysqli_options_openbasedir.phpt
+++ b/ext/mysqli/tests/mysqli_options_openbasedir.phpt
@@ -6,11 +6,10 @@ require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
?>
---INI--
-open_basedir="."
--FILE--
<?php
require_once('connect.inc');
+ ini_set("open_basedir", __DIR__);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
printf("[001] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
diff --git a/ext/mysqli/tests/mysqli_phpinfo.phpt b/ext/mysqli/tests/mysqli_phpinfo.phpt
index d60636ae40..e23a5f696f 100644
--- a/ext/mysqli/tests/mysqli_phpinfo.phpt
+++ b/ext/mysqli/tests/mysqli_phpinfo.phpt
@@ -46,7 +46,7 @@ require_once('skipifconnectfailure.inc');
if ($IS_MYSQLND) {
$expected = array(
- 'client statistics',
+ 'mysqlnd statistics',
'bytes_sent', 'bytes_received', 'packets_sent', 'packets_received',
'protocol_overhead_in', 'protocol_overhead_out', 'result_set_queries',
'non_result_set_queries', 'no_index_used', 'bad_index_used',
diff --git a/ext/mysqli/tests/mysqli_query_iterators.phpt b/ext/mysqli/tests/mysqli_query_iterators.phpt
new file mode 100644
index 0000000000..2577aa76ee
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_query_iterators.phpt
@@ -0,0 +1,201 @@
+--TEST--
+mysqli iterators
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+
+ echo "--- Testing default ---\n";
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id")))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else {
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ echo "======\n";
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ }
+ echo "--- Testing USE_RESULT ---\n";
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id", MYSQLI_USE_RESULT)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else {
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ echo "======\n";
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+ }
+
+ echo "--- Testing STORE_RESULT ---\n";
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id", MYSQLI_STORE_RESULT)))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else {
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ echo "======\n";
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+ }
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+--- Testing default ---
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+======
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+
+Warning: main(): Couldn't fetch mysqli_result in %s on line %d
+--- Testing USE_RESULT ---
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+======
+
+Warning: main(): Data fetched with MYSQLI_USE_RESULT can be iterated only once in %s on line %d
+--- Testing STORE_RESULT ---
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+======
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_connect.phpt b/ext/mysqli/tests/mysqli_real_connect.phpt
index b9ba98693f..5477ea1745 100644
--- a/ext/mysqli/tests/mysqli_real_connect.phpt
+++ b/ext/mysqli/tests/mysqli_real_connect.phpt
@@ -175,43 +175,45 @@ require_once('skipifconnectfailure.inc');
require_once("clean_table.inc");
?>
--EXPECTF--
-Warning: mysqli_real_connect(): (%d/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
-object(mysqli)#%d (18) {
- ["affected_rows"]=>
+Warning: mysqli_real_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+object(mysqli)#%d (%d) {
+ [%u|b%"affected_rows"]=>
NULL
- ["client_info"]=>
+ [%u|b%"client_info"]=>
%s
- ["client_version"]=>
+ [%u|b%"client_version"]=>
int(%d)
- ["connect_errno"]=>
- int(0)
- ["connect_error"]=>
- %s
- ["errno"]=>
+ [%u|b%"connect_errno"]=>
+ int(%d)
+ [%u|b%"connect_error"]=>
+ NULL
+ [%u|b%"errno"]=>
%s
- ["error"]=>
+ [%u|b%"error"]=>
%s
- ["field_count"]=>
+ [%u|b%"error_list"]=>
NULL
- ["host_info"]=>
- %s
- ["info"]=>
+ [%u|b%"field_count"]=>
+ NULL
+ [%u|b%"host_info"]=>
+ NULL
+ [%u|b%"info"]=>
NULL
- ["insert_id"]=>
+ [%u|b%"insert_id"]=>
NULL
- ["server_info"]=>
+ [%u|b%"server_info"]=>
NULL
- ["server_version"]=>
+ [%u|b%"server_version"]=>
NULL
- ["stat"]=>
+ [%u|b%"stat"]=>
NULL
- ["sqlstate"]=>
+ [%u|b%"sqlstate"]=>
NULL
- ["protocol_version"]=>
+ [%u|b%"protocol_version"]=>
NULL
- ["thread_id"]=>
+ [%u|b%"thread_id"]=>
NULL
- ["warning_count"]=>
+ [%u|b%"warning_count"]=>
NULL
}
diff --git a/ext/mysqli/tests/mysqli_real_connect_pconn.phpt b/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
index 5dedd47c96..4cc18198c6 100644
--- a/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
+++ b/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
@@ -151,5 +151,5 @@ mysqli.max_persistent=10
require_once("clean_table.inc");
?>
--EXPECTF--
-Warning: mysqli_real_connect(): (%d/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+Warning: mysqli_real_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
done!
diff --git a/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
index b8dd11a699..7fc32f7e61 100644
--- a/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
+++ b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
@@ -63,7 +63,7 @@ require_once('skipifconnectfailure.inc');
// NOTE: the error message varies with the MySQL Server version, dump only the error code!
printf("[009] [%d] (error message varies with the MySQL Server version, check the error code)\n", mysqli_stmt_errno($stmt));
- /* an error occured: affected rows should return -1 */
+ /* an error occurred: affected rows should return -1 */
if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
printf("[010] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
diff --git a/ext/mysqlnd/CREDITS b/ext/mysqlnd/CREDITS
index bac8d1a4a2..5aed316e89 100644
--- a/ext/mysqlnd/CREDITS
+++ b/ext/mysqlnd/CREDITS
@@ -1,2 +1,2 @@
MySQLnd
-Georg Richter, Andrey Hristov, Ulf Wendel
+Andrey Hristov, Ulf Wendel, Georg Richter
diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32
index 9f6ccc5e38..a910a0e509 100644
--- a/ext/mysqlnd/config.w32
+++ b/ext/mysqlnd/config.w32
@@ -7,18 +7,25 @@ if (PHP_MYSQLND != "no") {
if (CHECK_LIB("ws2_32.lib", "mysqlnd")) {
mysqlnd_source =
"mysqlnd.c " +
+ "mysqlnd_alloc.c " +
+ "mysqlnd_auth.c " +
"mysqlnd_block_alloc.c " +
+ "mysqlnd_bt.c " +
"mysqlnd_charset.c " +
"mysqlnd_debug.c " +
+ "mysqlnd_driver.c " +
+ "mysqlnd_ext_plugin.c " +
"mysqlnd_loaddata.c " +
+ "mysqlnd_reverse_api.c " +
"mysqlnd_net.c " +
+ "mysqlnd_plugin.c " +
"mysqlnd_ps.c " +
"mysqlnd_ps_codec.c " +
"mysqlnd_result.c " +
"mysqlnd_result_meta.c " +
"mysqlnd_statistics.c " +
"mysqlnd_wireprotocol.c " +
- "php_mysqlnd.c";
+ "php_mysqlnd.c ";
EXTENSION("mysqlnd", mysqlnd_source, false);
if (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "mysqlnd", PHP_MYSQLND))) ||
(PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "mysqlnd", PHP_MYSQLND)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED)))
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 73101eb50e..2c15c34e8d 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -18,10 +18,11 @@ fi
dnl If some extension uses mysqlnd it will get compiled in PHP core
if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes"; then
mysqlnd_ps_sources="mysqlnd_ps.c mysqlnd_ps_codec.c"
- mysqlnd_base_sources="mysqlnd.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
- mysqlnd_loaddata.c mysqlnd_net.c mysqlnd_statistics.c \
+ mysqlnd_base_sources="mysqlnd.c mysqlnd_alloc.c mysqlnd_bt.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
+ mysqlnd_loaddata.c mysqlnd_reverse_api.c mysqlnd_net.c \
+ mysqlnd_statistics.c mysqlnd_driver.c mysqlnd_ext_plugin.c mysqlnd_auth.c \
mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c\
- mysqlnd_block_alloc.c php_mysqlnd.c"
+ mysqlnd_block_alloc.c mysqlnd_plugin.c php_mysqlnd.c"
if test "$PHP_MYSQLND_COMPRESSION_SUPPORT" != "no"; then
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index b539c5180c..900f8207b4 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -27,8 +27,6 @@
#include "mysqlnd_statistics.h"
#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
-/* for php_get_current_user() */
-#include "ext/standard/basic_functions.h"
/*
TODO :
@@ -64,60 +62,50 @@ PHPAPI const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't
PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
-static zend_bool mysqlnd_library_initted = FALSE;
-static struct st_mysqlnd_conn_methods *mysqlnd_conn_methods;
-/* {{{ mysqlnd_library_end */
-PHPAPI void mysqlnd_library_end(TSRMLS_D)
-{
- if (mysqlnd_library_initted == TRUE) {
- mysqlnd_stats_end(mysqlnd_global_stats);
- mysqlnd_global_stats = NULL;
- mysqlnd_library_initted = FALSE;
- }
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn::free_options */
+/* {{{ mysqlnd_conn_data::free_options */
static void
-MYSQLND_METHOD(mysqlnd_conn, free_options)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_bool pers = conn->persistent;
- if (conn->options.charset_name) {
- mnd_pefree(conn->options.charset_name, pers);
- conn->options.charset_name = NULL;
+ if (conn->options->charset_name) {
+ mnd_pefree(conn->options->charset_name, pers);
+ conn->options->charset_name = NULL;
+ }
+ if (conn->options->auth_protocol) {
+ mnd_pefree(conn->options->auth_protocol, pers);
+ conn->options->auth_protocol = NULL;
}
- if (conn->options.num_commands) {
+ if (conn->options->num_commands) {
unsigned int i;
- for (i = 0; i < conn->options.num_commands; i++) {
+ for (i = 0; i < conn->options->num_commands; i++) {
/* allocated with pestrdup */
- mnd_pefree(conn->options.init_commands[i], pers);
+ mnd_pefree(conn->options->init_commands[i], pers);
}
- mnd_pefree(conn->options.init_commands, pers);
- conn->options.init_commands = NULL;
+ mnd_pefree(conn->options->init_commands, pers);
+ conn->options->init_commands = NULL;
}
- if (conn->options.cfg_file) {
- mnd_pefree(conn->options.cfg_file, pers);
- conn->options.cfg_file = NULL;
+ if (conn->options->cfg_file) {
+ mnd_pefree(conn->options->cfg_file, pers);
+ conn->options->cfg_file = NULL;
}
- if (conn->options.cfg_section) {
- mnd_pefree(conn->options.cfg_section, pers);
- conn->options.cfg_section = NULL;
+ if (conn->options->cfg_section) {
+ mnd_pefree(conn->options->cfg_section, pers);
+ conn->options->cfg_section = NULL;
}
}
/* }}} */
-/* {{{ mysqlnd_conn::free_contents */
+/* {{{ mysqlnd_conn_data::free_contents */
static void
-MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_bool pers = conn->persistent;
- DBG_ENTER("mysqlnd_conn::free_contents");
+ DBG_ENTER("mysqlnd_conn_data::free_contents");
mysqlnd_local_infile_default(conn);
if (conn->current_result) {
@@ -132,55 +120,51 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
DBG_INF("Freeing memory of members");
if (conn->host) {
- DBG_INF("Freeing host");
mnd_pefree(conn->host, pers);
conn->host = NULL;
}
if (conn->user) {
- DBG_INF("Freeing user");
mnd_pefree(conn->user, pers);
conn->user = NULL;
}
if (conn->passwd) {
- DBG_INF("Freeing passwd");
mnd_pefree(conn->passwd, pers);
conn->passwd = NULL;
}
if (conn->connect_or_select_db) {
- DBG_INF("Freeing connect_or_select_db");
mnd_pefree(conn->connect_or_select_db, pers);
conn->connect_or_select_db = NULL;
}
if (conn->unix_socket) {
- DBG_INF("Freeing unix_socket");
mnd_pefree(conn->unix_socket, pers);
conn->unix_socket = NULL;
}
DBG_INF_FMT("scheme=%s", conn->scheme);
if (conn->scheme) {
- DBG_INF("Freeing scheme");
mnd_pefree(conn->scheme, pers);
conn->scheme = NULL;
}
if (conn->server_version) {
- DBG_INF("Freeing server_version");
mnd_pefree(conn->server_version, pers);
conn->server_version = NULL;
}
if (conn->host_info) {
- DBG_INF("Freeing host_info");
mnd_pefree(conn->host_info, pers);
conn->host_info = NULL;
}
- if (conn->scramble) {
- DBG_INF("Freeing scramble");
- mnd_pefree(conn->scramble, pers);
- conn->scramble = NULL;
+ if (conn->auth_plugin_data) {
+ mnd_pefree(conn->auth_plugin_data, pers);
+ conn->auth_plugin_data = NULL;
}
if (conn->last_message) {
mnd_pefree(conn->last_message, pers);
conn->last_message = NULL;
}
+ if (conn->error_info->error_list) {
+ zend_llist_clean(conn->error_info->error_list);
+ mnd_pefree(conn->error_info->error_list, pers);
+ conn->error_info->error_list = NULL;
+ }
conn->charset = NULL;
conn->greet_charset = NULL;
@@ -189,24 +173,22 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::dtor */
+/* {{{ mysqlnd_conn_data::dtor */
static void
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::dtor");
+ DBG_ENTER("mysqlnd_conn_data::dtor");
DBG_INF_FMT("conn=%llu", conn->thread_id);
conn->m->free_contents(conn TSRMLS_CC);
conn->m->free_options(conn TSRMLS_CC);
if (conn->net) {
- DBG_INF("Freeing net");
- mysqlnd_net_free(conn->net TSRMLS_CC);
+ mysqlnd_net_free(conn->net, conn->stats, conn->error_info TSRMLS_CC);
conn->net = NULL;
}
if (conn->protocol) {
- DBG_INF("Freeing protocol");
mysqlnd_protocol_free(conn->protocol TSRMLS_CC);
conn->protocol = NULL;
}
@@ -222,22 +204,22 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::simple_command_handle_response */
+/* {{{ mysqlnd_conn_data::simple_command_handle_response */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enum mysqlnd_packet_type ok_packet,
+MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet,
zend_bool silent, enum php_mysqlnd_server_command command,
zend_bool ignore_upsert_status TSRMLS_DC)
{
enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::simple_command_handle_response");
+ DBG_ENTER("mysqlnd_conn_data::simple_command_handle_response");
DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
switch (ok_packet) {
case PROT_OK_PACKET:{
MYSQLND_PACKET_OK * ok_response = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
if (!ok_response) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
if (FAIL == (ret = PACKET_READ(ok_response, conn))) {
@@ -250,7 +232,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
DBG_INF_FMT("OK from server");
if (0xFF == ok_response->field_count) {
/* The server signalled error. Set the error */
- SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+ SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
ret = FAIL;
/*
Cover a protocol design error: error packet does not
@@ -261,7 +243,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
a multi-statement or a stored procedure, so it should be
safe to unconditionally turn off the flag here.
*/
- conn->upsert_status.server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
SET_ERROR_AFF_ROWS(conn);
} else {
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
@@ -269,10 +251,10 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
conn->persistent);
if (!ignore_upsert_status) {
- conn->upsert_status.warning_count = ok_response->warning_count;
- conn->upsert_status.server_status = ok_response->server_status;
- conn->upsert_status.affected_rows = ok_response->affected_rows;
- conn->upsert_status.last_insert_id = ok_response->last_insert_id;
+ conn->upsert_status->warning_count = ok_response->warning_count;
+ conn->upsert_status->server_status = ok_response->server_status;
+ conn->upsert_status->affected_rows = ok_response->affected_rows;
+ conn->upsert_status->last_insert_id = ok_response->last_insert_id;
}
}
}
@@ -282,11 +264,11 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
case PROT_EOF_PACKET:{
MYSQLND_PACKET_EOF * ok_response = conn->protocol->m.get_eof_packet(conn->protocol, FALSE TSRMLS_CC);
if (!ok_response) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
if (FAIL == (ret = PACKET_READ(ok_response, conn))) {
- SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
"Malformed packet");
if (!silent) {
DBG_ERR_FMT("Error while reading %s's EOF packet", mysqlnd_command_to_text[command]);
@@ -295,10 +277,10 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
}
} else if (0xFF == ok_response->field_count) {
/* The server signalled error. Set the error */
- SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+ SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
SET_ERROR_AFF_ROWS(conn);
} else if (0xFE != ok_response->field_count) {
- SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
if (!silent) {
DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X",
@@ -311,7 +293,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
break;
}
default:
- SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
break;
}
@@ -321,41 +303,41 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
/* }}} */
-/* {{{ mysqlnd_conn::simple_command */
+/* {{{ mysqlnd_conn_data::simple_command */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND * conn, enum php_mysqlnd_server_command command,
- const char * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent,
+MYSQLND_METHOD(mysqlnd_conn_data, simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command,
+ const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent,
zend_bool ignore_upsert_status TSRMLS_DC)
{
enum_func_status ret = PASS;
MYSQLND_PACKET_COMMAND * cmd_packet;
- DBG_ENTER("mysqlnd_conn::simple_command");
+ DBG_ENTER("mysqlnd_conn_data::simple_command");
DBG_INF_FMT("command=%s ok_packet=%u silent=%u", mysqlnd_command_to_text[command], ok_packet, silent);
switch (CONN_GET_STATE(conn)) {
case CONN_READY:
break;
case CONN_QUIT_SENT:
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
DBG_ERR("Server is gone");
DBG_RETURN(FAIL);
default:
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR_FMT("Command out of sync. State=%u", CONN_GET_STATE(conn));
DBG_RETURN(FAIL);
}
/* clean UPSERT info */
if (!ignore_upsert_status) {
- memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
+ memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
}
SET_ERROR_AFF_ROWS(conn);
- SET_EMPTY_ERROR(conn->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
cmd_packet = conn->protocol->m.get_command_packet(conn->protocol, FALSE TSRMLS_CC);
if (!cmd_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(FAIL);
}
@@ -372,6 +354,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND * conn, enum php_mysqlnd_se
DBG_ERR_FMT("Error while sending %s packet", mysqlnd_command_to_text[command]);
php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid());
}
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
DBG_ERR("Server is gone");
ret = FAIL;
} else if (ok_packet != PROT_LAST) {
@@ -385,26 +368,31 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND * conn, enum php_mysqlnd_se
/* }}} */
-/* {{{ mysqlnd_conn::set_server_option */
+/* {{{ mysqlnd_conn_data::set_server_option */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_server_option)(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option TSRMLS_DC)
{
- enum_func_status ret;
- char buffer[2];
- DBG_ENTER("mysqlnd_conn::set_server_option");
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_server_option);
+ zend_uchar buffer[2];
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::set_server_option");
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
- int2store(buffer, (unsigned int) option);
- ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
+ int2store(buffer, (unsigned int) option);
+ ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::restart_psession */
+/* {{{ mysqlnd_conn_data::restart_psession */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, restart_psession)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, restart_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::restart_psession");
+ DBG_ENTER("mysqlnd_conn_data::restart_psession");
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_REUSED);
/* Free here what should not be seen by the next script */
if (conn->last_message) {
@@ -416,49 +404,38 @@ MYSQLND_METHOD(mysqlnd_conn, restart_psession)(MYSQLND * conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::end_psession */
+/* {{{ mysqlnd_conn_data::end_psession */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, end_psession)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, end_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::end_psession");
+ DBG_ENTER("mysqlnd_conn_data::end_psession");
DBG_RETURN(PASS);
}
/* }}} */
-#define MYSQLND_ASSEBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
-/* {{{ mysqlnd_connect_run_authentication */
+/* {{{ mysqlnd_switch_to_ssl_if_needed */
static enum_func_status
-mysqlnd_connect_run_authentication(
- MYSQLND * conn,
- const char * const user,
- const char * const passwd,
- const char * const db,
- size_t db_len,
+mysqlnd_switch_to_ssl_if_needed(
+ MYSQLND_CONN_DATA * conn,
const MYSQLND_PACKET_GREET * const greet_packet,
const MYSQLND_OPTIONS * const options,
unsigned long mysql_flags
- TSRMLS_DC)
+ TSRMLS_DC
+ )
{
- const MYSQLND_CHARSET * charset = NULL;
enum_func_status ret = FAIL;
- MYSQLND_PACKET_AUTH * auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
- MYSQLND_PACKET_OK * ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
-
- DBG_ENTER("mysqlnd_connect_run_authentication");
-
- if (!auth_packet || !ok_packet) {
- SET_OOM_ERROR(conn->error_info);
- goto err;
- }
+ const MYSQLND_CHARSET * charset;
+ MYSQLND_PACKET_AUTH * auth_packet;
+ DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
-#ifdef MYSQLND_SSL_SUPPORTED
- if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
- auth_packet->send_half_packet = TRUE;
+ auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!auth_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
}
-#endif
- auth_packet->user = user;
- auth_packet->password = passwd;
+ auth_packet->client_flags = mysql_flags;
+ auth_packet->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
auth_packet->charset_no = charset->nr;
@@ -469,106 +446,201 @@ mysqlnd_connect_run_authentication(
auth_packet->charset_no = greet_packet->charset_no;
#endif
}
- auth_packet->db = db;
- auth_packet->db_len = db_len;
- auth_packet->max_packet_size= MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
- auth_packet->client_flags= mysql_flags;
-
- conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
- if (!conn->scramble) {
- SET_OOM_ERROR(conn->error_info);
- goto err;
- }
- memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
-
- if (!PACKET_WRITE(auth_packet, conn)) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- goto err;
- }
#ifdef MYSQLND_SSL_SUPPORTED
- if (auth_packet->send_half_packet) {
+ if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
DBG_INF("Switching to SSL");
-
- conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
-
- if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
- goto err;
- }
-
- auth_packet->send_half_packet = FALSE;
if (!PACKET_WRITE(auth_packet, conn)) {
CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- goto err;
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
}
- }
-#endif
+ conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
- if (FAIL == PACKET_READ(ok_packet, conn) || ok_packet->field_count >= 0xFE) {
- if (ok_packet->field_count == 0xFE) {
- /* old authentication with new server !*/
- DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
- } else if (ok_packet->field_count == 0xFF) {
- if (ok_packet->sqlstate[0]) {
- strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate));
- DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error);
- }
- conn->error_info.error_no = ok_packet->error_no;
- strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error));
+ if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
+ goto end;
}
- goto err;
}
-
- SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
- ok_packet->message, ok_packet->message_len,
- conn->persistent);
- conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
+#endif
ret = PASS;
-err:
+end:
PACKET_FREE(auth_packet);
- PACKET_FREE(ok_packet);
DBG_RETURN(ret);
}
/* }}} */
-#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
- CLIENT_MULTI_RESULTS)
+/* {{{ mysqlnd_connect_run_authentication */
+static enum_func_status
+mysqlnd_connect_run_authentication(
+ MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const char * const db,
+ size_t db_len,
+ size_t passwd_len,
+ const MYSQLND_PACKET_GREET * const greet_packet,
+ const MYSQLND_OPTIONS * const options,
+ unsigned long mysql_flags
+ TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_connect_run_authentication");
+ ret = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, options, mysql_flags TSRMLS_CC);
+ if (PASS == ret) {
+ zend_bool first_call = TRUE;
+ char * switch_to_auth_protocol = NULL;
+ size_t switch_to_auth_protocol_len = 0;
+ char * requested_protocol = NULL;
+ zend_uchar * plugin_data;
+ size_t plugin_data_len;
-/* {{{ mysqlnd_conn::connect */
+ plugin_data_len = greet_packet->auth_plugin_data_len;
+ plugin_data = mnd_emalloc(plugin_data_len + 1);
+ if (!plugin_data) {
+ ret = FAIL;
+ goto end;
+ }
+ memcpy(plugin_data, greet_packet->auth_plugin_data, plugin_data_len);
+ plugin_data[plugin_data_len] = '\0';
+
+ requested_protocol = mnd_pestrdup(greet_packet->auth_protocol? greet_packet->auth_protocol: "mysql_native_password", FALSE);
+ if (!requested_protocol) {
+ ret = FAIL;
+ goto end;
+ }
+
+ do {
+ struct st_mysqlnd_authentication_plugin * auth_plugin;
+ {
+ char * plugin_name = NULL;
+
+ mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol);
+
+ DBG_INF_FMT("looking for %s auth plugin", plugin_name);
+ auth_plugin = mysqlnd_plugin_find(plugin_name);
+ mnd_sprintf_free(plugin_name);
+
+ if (!auth_plugin) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol);
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client");
+ break;
+ }
+ }
+ DBG_INF("plugin found");
+
+ {
+ zend_uchar * switch_to_auth_protocol_data = NULL;
+ size_t switch_to_auth_protocol_data_len = 0;
+ zend_uchar * scrambled_data = NULL;
+ size_t scrambled_data_len = 0;
+
+ switch_to_auth_protocol = NULL;
+ switch_to_auth_protocol_len = 0;
+
+ if (conn->auth_plugin_data) {
+ mnd_pefree(conn->auth_plugin_data, conn->persistent);
+ conn->auth_plugin_data = NULL;
+ }
+ conn->auth_plugin_data_len = plugin_data_len;
+ conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
+ if (!conn->auth_plugin_data) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+ memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
+
+ DBG_INF_FMT("salt=[%*s]", plugin_data_len - 1, plugin_data);
+ /* The data should be allocated with malloc() */
+ scrambled_data =
+ auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
+ plugin_data, plugin_data_len, options, mysql_flags TSRMLS_CC);
+
+
+ ret = mysqlnd_auth_handshake(conn, user, passwd, passwd_len, db, db_len, options, mysql_flags,
+ greet_packet->charset_no,
+ first_call,
+ requested_protocol,
+ scrambled_data, scrambled_data_len,
+ &switch_to_auth_protocol, &switch_to_auth_protocol_len,
+ &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
+ TSRMLS_CC);
+ first_call = FALSE;
+ free(scrambled_data);
+
+ DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
+ if (requested_protocol && switch_to_auth_protocol) {
+ mnd_efree(requested_protocol);
+ requested_protocol = switch_to_auth_protocol;
+ }
+
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ plugin_data_len = switch_to_auth_protocol_data_len;
+ plugin_data = switch_to_auth_protocol_data;
+ }
+ DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no);
+ } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL);
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+
+ if (ret == PASS) {
+ DBG_INF_FMT("saving requested_protocol=%s", requested_protocol);
+ conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC);
+ }
+
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+ }
+end:
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::connect */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
+MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
const char *host, const char *user,
const char *passwd, unsigned int passwd_len,
const char *db, unsigned int db_len,
unsigned int port,
- const char * socket_or_pipe,
+ const char *socket_or_pipe,
unsigned int mysql_flags
TSRMLS_DC)
{
- char *errstr = NULL;
- int errcode = 0, host_len;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, connect);
+ size_t host_len;
zend_bool unix_socket = FALSE;
+ zend_bool named_pipe = FALSE;
zend_bool reconnect = FALSE;
zend_bool saved_compression = FALSE;
+ zend_bool local_tx_started = FALSE;
MYSQLND_PACKET_GREET * greet_packet = NULL;
- DBG_ENTER("mysqlnd_conn::connect");
+ DBG_ENTER("mysqlnd_conn_data::connect");
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto err;
+ }
+ local_tx_started = TRUE;
+
+ SET_EMPTY_ERROR(*conn->error_info);
+ SET_ERROR_AFF_ROWS(conn);
DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u persistent=%u state=%u",
host?host:"", user?user:"", db?db:"", port, mysql_flags,
conn? conn->persistent:0, conn? CONN_GET_STATE(conn):-1);
- if (conn && CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) ) {
+ if (CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) ) {
DBG_INF("Connecting on a connected handle.");
if (CONN_GET_STATE(conn) < CONN_QUIT_SENT) {
@@ -592,6 +664,9 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
saved_compression = TRUE;
conn->net->compressed = FALSE;
}
+ } else {
+ unsigned int max_allowed_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
+ conn->m->set_client_option(conn, MYSQLND_OPT_MAX_ALLOWED_PACKET, (char *)&max_allowed_size TSRMLS_CC);
}
if (!host || !host[0]) {
@@ -622,24 +697,31 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
if (!socket_or_pipe) {
socket_or_pipe = "/tmp/mysql.sock";
}
- transport_len = spprintf(&transport, 0, "unix://%s", socket_or_pipe);
+ transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe);
unix_socket = TRUE;
- } else
+#else
+ if (host_len == sizeof(".") - 1 && host[0] == '.') {
+ /* named pipe in socket */
+ if (!socket_or_pipe) {
+ socket_or_pipe = "\\\\.\\pipe\\MySQL";
+ }
+ transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe);
+ named_pipe = TRUE;
#endif
- {
+ } else {
if (!port) {
port = 3306;
}
- transport_len = spprintf(&transport, 0, "tcp://%s:%u", host, port);
+ transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", host, port);
}
if (!transport) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
DBG_INF_FMT("transport=%s conn->scheme=%s", transport, conn->scheme);
conn->scheme = mnd_pestrndup(transport, transport_len, conn->persistent);
conn->scheme_len = transport_len;
- efree(transport); /* allocated by spprintf */
+ mnd_sprintf_free(transport);
transport = NULL;
if (!conn->scheme) {
goto err; /* OOM */
@@ -648,11 +730,13 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC);
if (!greet_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
- if (FAIL == conn->net->m.connect(conn->net, conn->scheme, conn->scheme_len, conn->persistent, &errstr, &errcode TSRMLS_CC)) {
+ if (FAIL == conn->net->m.connect_ex(conn->net, conn->scheme, conn->scheme_len, conn->persistent,
+ conn->stats, conn->error_info TSRMLS_CC))
+ {
goto err;
}
@@ -664,13 +748,13 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
goto err;
} else if (greet_packet->error_no) {
DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
- SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
+ SET_CLIENT_ERROR(*conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
goto err;
} else if (greet_packet->pre41) {
DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
" is not supported. Server is %-.32s", greet_packet->server_version);
- SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
"Connecting to 3.22, 3.23 & 4.0 servers is not supported");
goto err;
}
@@ -683,12 +767,11 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
if (!conn->greet_charset) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
- SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
"Server sent charset unknown to the client. Please, report to the developers");
goto err;
}
/* we allow load data local infile by default */
- mysql_flags |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS;
mysql_flags |= MYSQLND_CAPABILITIES;
if (db) {
@@ -720,7 +803,9 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
}
#endif
- if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, greet_packet, &conn->options, mysql_flags TSRMLS_CC)) {
+ if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
+ greet_packet, conn->options, mysql_flags TSRMLS_CC))
+ {
goto err;
}
@@ -746,49 +831,66 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
conn->connect_or_select_db_len = db_len;
if (!conn->user || !conn->passwd || !conn->connect_or_select_db) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
- if (!unix_socket) {
+ if (!unix_socket && !named_pipe) {
conn->host = mnd_pestrdup(host, conn->persistent);
if (!conn->host) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
conn->host_len = strlen(conn->host);
{
char *p;
- spprintf(&p, 0, "%s via TCP/IP", conn->host);
+ mnd_sprintf(&p, 0, "%s via TCP/IP", conn->host);
if (!p) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
conn->host_info = mnd_pestrdup(p, conn->persistent);
- efree(p); /* allocated by spprintf */
+ mnd_sprintf_free(p);
if (!conn->host_info) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
}
} else {
- conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
- conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
+ conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
+ if (unix_socket) {
+ conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
+ } else if (named_pipe) {
+ char *p;
+ mnd_sprintf(&p, 0, "%s via named pipe", conn->unix_socket);
+ if (!p) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto err; /* OOM */
+ }
+ conn->host_info = mnd_pestrdup(p, conn->persistent);
+ mnd_sprintf_free(p);
+ if (!conn->host_info) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto err; /* OOM */
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Impossible. Should be either socket or a pipe. Report a bug!");
+ }
if (!conn->unix_socket || !conn->host_info) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
conn->unix_socket_len = strlen(conn->unix_socket);
}
conn->client_flag = mysql_flags;
- conn->max_packet_size = MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
+ conn->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
/* todo: check if charset is available */
conn->server_capabilities = greet_packet->server_capabilities;
- conn->upsert_status.warning_count = 0;
- conn->upsert_status.server_status = greet_packet->server_status;
- conn->upsert_status.affected_rows = 0;
+ conn->upsert_status->warning_count = 0;
+ conn->upsert_status->server_status = greet_packet->server_status;
+ conn->upsert_status->affected_rows = 0;
- SET_EMPTY_ERROR(conn->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
mysqlnd_local_infile_default(conn);
@@ -799,10 +901,10 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
DBG_INF("unicode set");
}
#endif
- if (conn->options.init_commands) {
+ if (conn->options->init_commands) {
unsigned int current_command = 0;
- for (; current_command < conn->options.num_commands; ++current_command) {
- const char * const command = conn->options.init_commands[current_command];
+ for (; current_command < conn->options->num_commands; ++current_command) {
+ const char * const command = conn->options->init_commands[current_command];
if (command) {
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
@@ -832,33 +934,63 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
PACKET_FREE(greet_packet);
+ conn->m->local_tx_end(conn, this_func, PASS TSRMLS_CC);
DBG_RETURN(PASS);
}
err:
PACKET_FREE(greet_packet);
- if (errstr) {
- DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", errcode, errstr, conn->scheme);
- SET_CLIENT_ERROR(conn->error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%u] %.128s (trying to connect via %s)", errcode, errstr, conn->scheme);
- /* no mnd_ since we don't allocate it */
- efree(errstr);
+ DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme);
+ if (!conn->error_info->error_no) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, conn->error_info->error? conn->error_info->error:"Unknown error");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%u] %.128s (trying to connect via %s)",
+ conn->error_info->error_no, conn->error_info->error, conn->scheme);
}
+
conn->m->free_contents(conn TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_FAILURE);
+ if (TRUE == local_tx_started) {
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+ }
DBG_RETURN(FAIL);
}
/* }}} */
+/* {{{ mysqlnd_conn::connect */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
+ const char * host, const char * user,
+ const char * passwd, unsigned int passwd_len,
+ const char * db, unsigned int db_len,
+ unsigned int port,
+ const char * socket_or_pipe,
+ unsigned int mysql_flags
+ TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, connect);
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = conn_handle->data;
+
+ DBG_ENTER("mysqlnd_conn::connect");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
/* {{{ mysqlnd_connect */
-PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
- const char *host, const char *user,
- const char *passwd, unsigned int passwd_len,
- const char *db, unsigned int db_len,
+PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
+ const char * host, const char * user,
+ const char * passwd, unsigned int passwd_len,
+ const char * db, unsigned int db_len,
unsigned int port,
- const char *socket_or_pipe,
+ const char * socket_or_pipe,
unsigned int mysql_flags
TSRMLS_DC)
{
@@ -868,15 +1000,15 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
DBG_ENTER("mysqlnd_connect");
DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host?host:"", user?user:"", db?db:"", port, mysql_flags);
- if (!conn) {
+ if (!conn_handle) {
self_alloced = TRUE;
- if (!(conn = mysqlnd_init(FALSE))) {
+ if (!(conn_handle = mysqlnd_init(FALSE))) {
/* OOM */
DBG_RETURN(NULL);
}
}
- ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
+ ret = conn_handle->m->connect(conn_handle, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
if (ret == FAIL) {
if (self_alloced) {
@@ -884,215 +1016,88 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
We have alloced, thus there are no references to this
object - we are free to kill it!
*/
- conn->m->dtor(conn TSRMLS_CC);
+ conn_handle->m->dtor(conn_handle TSRMLS_CC);
}
DBG_RETURN(NULL);
}
- DBG_RETURN(conn);
+ DBG_RETURN(conn_handle);
}
/* }}} */
-/* {{{ mysqlnd_conn::change_user */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn,
- const char *user,
- const char *passwd,
- const char *db,
- zend_bool silent TSRMLS_DC)
-{
- size_t user_len;
- enum_func_status ret = FAIL;
- MYSQLND_PACKET_CHG_USER_RESPONSE * chg_user_resp;
- char buffer[MYSQLND_MAX_ALLOWED_USER_LEN + 1 + 1 + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 2 /* charset*/ + 2];
- char *p = buffer;
- const MYSQLND_CHARSET * old_cs = conn->charset;
-
- DBG_ENTER("mysqlnd_conn::change_user");
- DBG_INF_FMT("conn=%llu user=%s passwd=%s db=%s silent=%u",
- conn->thread_id, user?user:"", passwd?"***":"null", db?db:"", (silent == TRUE)?1:0 );
-
- SET_ERROR_AFF_ROWS(conn);
-
- if (!user) {
- user = "";
- }
- if (!passwd) {
- passwd = "";
- }
- if (!db) {
- db = "";
- }
-
- /* 1. user ASCIIZ */
- user_len = MIN(strlen(user), MYSQLND_MAX_ALLOWED_USER_LEN);
- memcpy(p, user, user_len);
- p += user_len;
- *p++ = '\0';
-
- /* 2. password SCRAMBLE_LENGTH followed by the scramble or \0 */
- if (passwd[0]) {
- *p++ = SCRAMBLE_LENGTH;
- php_mysqlnd_scramble((unsigned char *)p, conn->scramble, (unsigned char *)passwd);
- p += SCRAMBLE_LENGTH;
- } else {
- *p++ = '\0';
- }
-
- /* 3. db ASCIIZ */
- if (db[0]) {
- size_t db_len = MIN(strlen(db), MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, db, db_len);
- p += db_len;
- }
- *p++ = '\0';
-
- /*
- 4. request the current charset, or it will be reset to the system one.
- 5.0 doesn't support it. Support added in 5.1.23 by fixing the following bug :
- Bug #30472 libmysql doesn't reset charset, insert_id after succ. mysql_change_user() call
- */
- if (mysqlnd_get_server_version(conn) >= 50123) {
- int2store(p, conn->charset->nr);
- p+=2;
- }
-
- if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer, p - buffer,
- PROT_LAST /* we will handle the OK packet*/,
- silent, TRUE TSRMLS_CC)) {
- DBG_RETURN(FAIL);
- }
-
- chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE TSRMLS_CC);
- if (!chg_user_resp) {
- SET_OOM_ERROR(conn->error_info);
- goto end;
- }
- ret = PACKET_READ(chg_user_resp, conn);
- conn->error_info = chg_user_resp->error_info;
-
- if (conn->error_info.error_no) {
- ret = FAIL;
- /*
- COM_CHANGE_USER is broken in 5.1. At least in 5.1.15 and 5.1.14, 5.1.11 is immune.
- bug#25371 mysql_change_user() triggers "packets out of sync"
- When it gets fixed, there should be one more check here
- */
- if (mysqlnd_get_server_version(conn) > 50113L && mysqlnd_get_server_version(conn) < 50118L) {
- MYSQLND_PACKET_OK * redundant_error_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
- if (redundant_error_packet) {
- PACKET_READ(redundant_error_packet, conn);
- PACKET_FREE(redundant_error_packet);
- DBG_INF_FMT("Server is %u, buggy, sends two ERR messages", mysqlnd_get_server_version(conn));
- } else {
- SET_OOM_ERROR(conn->error_info);
- }
- }
- }
- if (ret == PASS) {
- char * tmp = NULL;
- /* if we get conn->user as parameter and then we first free it, then estrndup it, we will crash */
- tmp = mnd_pestrndup(user, user_len, conn->persistent);
- if (conn->user) {
- mnd_pefree(conn->user, conn->persistent);
- }
- conn->user = tmp;
-
- tmp = mnd_pestrdup(passwd, conn->persistent);
- if (conn->passwd) {
- mnd_pefree(conn->passwd, conn->persistent);
- }
- conn->passwd = tmp;
-
- if (conn->last_message) {
- mnd_pefree(conn->last_message, conn->persistent);
- conn->last_message = NULL;
- }
- memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
- /* set charset for old servers */
- if (mysqlnd_get_server_version(conn) < 50123) {
- ret = conn->m->set_charset(conn, old_cs->name TSRMLS_CC);
- }
- } else if (ret == FAIL && chg_user_resp->server_asked_323_auth == TRUE) {
- /* old authentication with new server !*/
- DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
- }
-end:
- PACKET_FREE(chg_user_resp);
-
- /*
- Here we should close all statements. Unbuffered queries should not be a
- problem as we won't allow sending COM_CHANGE_USER.
- */
- DBG_INF(ret == PASS? "PASS":"FAIL");
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn::query */
+/* {{{ mysqlnd_conn_data::query */
/*
- If conn->error_info.error_no is not zero, then we had an error.
+ If conn->error_info->error_no is not zero, then we had an error.
Still the result from the query is PASS
*/
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, query)(MYSQLND * conn, const char * query, unsigned int query_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, query);
enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::query");
+ DBG_ENTER("mysqlnd_conn_data::query");
DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query);
- if (PASS == conn->m->send_query(conn, query, query_len TSRMLS_CC) &&
- PASS == conn->m->reap_query(conn TSRMLS_CC))
- {
- ret = PASS;
- if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status.affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status.affected_rows);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (PASS == conn->m->send_query(conn, query, query_len TSRMLS_CC) &&
+ PASS == conn->m->reap_query(conn TSRMLS_CC))
+ {
+ ret = PASS;
+ if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status->affected_rows) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status->affected_rows);
+ }
}
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::send_query */
+/* {{{ mysqlnd_conn_data::send_query */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, send_query)(MYSQLND * conn, const char * query, unsigned int query_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, send_query);
enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::send_query");
+ DBG_ENTER("mysqlnd_conn_data::send_query");
DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query);
- ret = conn->m->simple_command(conn, COM_QUERY, query, query_len,
- PROT_LAST /* we will handle the OK packet*/,
- FALSE, FALSE TSRMLS_CC);
- if (PASS == ret) {
- CONN_SET_STATE(conn, CONN_QUERY_SENT);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_QUERY, (zend_uchar *) query, query_len,
+ PROT_LAST /* we will handle the OK packet*/,
+ FALSE, FALSE TSRMLS_CC);
+ if (PASS == ret) {
+ CONN_SET_STATE(conn, CONN_QUERY_SENT);
+ }
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::reap_query */
+/* {{{ mysqlnd_conn_data::reap_query */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, reap_query);
enum_mysqlnd_connection_state state = CONN_GET_STATE(conn);
- DBG_ENTER("mysqlnd_conn::reap_query");
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::reap_query");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (state <= CONN_READY || state == CONN_QUIT_SENT) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed");
- DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
- DBG_RETURN(FAIL);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (state <= CONN_READY || state == CONN_QUIT_SENT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed");
+ DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
+ DBG_RETURN(ret);
+ }
+ ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
- /*
- Here read the result set. We don't do it in simple_command because it need
- information from the ok packet. We will fetch it ourselves.
- */
- DBG_RETURN(conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC));
+ DBG_RETURN(ret);
}
/* }}} */
@@ -1106,7 +1111,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
MYSQLND **ret = NULL;
while (*p) {
- if (CONN_GET_STATE(*p) <= CONN_READY || CONN_GET_STATE(*p) == CONN_QUIT_SENT) {
+ if (CONN_GET_STATE((*p)->data) <= CONN_READY || CONN_GET_STATE((*p)->data) == CONN_QUIT_SENT) {
cnt++;
}
p++;
@@ -1115,7 +1120,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *));
p_p = p = conn_array;
while (*p) {
- if (CONN_GET_STATE(*p) <= CONN_READY || CONN_GET_STATE(*p) == CONN_QUIT_SENT) {
+ if (CONN_GET_STATE((*p)->data) <= CONN_READY || CONN_GET_STATE((*p)->data) == CONN_QUIT_SENT) {
*ret_p = *p;
*p = NULL;
ret_p++;
@@ -1132,7 +1137,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
/* {{{ stream_select mysqlnd_stream_array_to_fd_set functions */
-static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php_socket_t *max_fd TSRMLS_DC)
+static int mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, php_socket_t * max_fd TSRMLS_DC)
{
php_socket_t this_fd;
int cnt = 0;
@@ -1144,7 +1149,7 @@ static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php
* when casting. It is only used here so that the buffered data warning
* is not displayed.
* */
- if (SUCCESS == php_stream_cast((*p)->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
+ if (SUCCESS == php_stream_cast((*p)->data->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
(void*)&this_fd, 1) && this_fd >= 0) {
PHP_SAFE_FD_SET(this_fd, fds);
@@ -1159,7 +1164,7 @@ static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php
return cnt ? 1 : 0;
}
-static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TSRMLS_DC)
+static int mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds TSRMLS_DC)
{
php_socket_t this_fd;
int ret = 0;
@@ -1169,7 +1174,7 @@ static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TS
MYSQLND **fwd = conn_array, **bckwd = conn_array;
while (*fwd) {
- if (SUCCESS == php_stream_cast((*fwd)->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
+ if (SUCCESS == php_stream_cast((*fwd)->data->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
(void*)&this_fd, 1) && this_fd >= 0) {
if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
if (disproportion) {
@@ -1190,25 +1195,26 @@ static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TS
}
/* }}} */
+
#ifndef PHP_WIN32
#define php_select(m, r, w, e, t) select(m, r, w, e, t)
#else
#include "win32/select.h"
#endif
+
/* {{{ _mysqlnd_poll */
PHPAPI enum_func_status
_mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, uint * desc_num TSRMLS_DC)
{
-
struct timeval tv;
struct timeval *tv_p = NULL;
fd_set rfds, wfds, efds;
php_socket_t max_fd = 0;
int retval, sets = 0;
int set_count, max_set_count = 0;
- DBG_ENTER("mysqlnd_poll");
+ DBG_ENTER("_mysqlnd_poll");
if (sec < 0 || usec < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative values passed for sec and/or usec");
DBG_RETURN(FAIL);
@@ -1271,7 +1277,6 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s
}
*desc_num = retval;
-
DBG_RETURN(PASS);
}
/* }}} */
@@ -1284,322 +1289,385 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s
- The EOF packet is consumed by the metadata packet reader.
*/
-/* {{{ mysqlnd_conn::list_fields */
+/* {{{ mysqlnd_conn_data::list_fields */
MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, list_fields)(MYSQLND * conn, const char *table, const char *achtung_wild TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, list_fields)(MYSQLND_CONN_DATA * conn, const char *table, const char *achtung_wild TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, list_fields);
/* db + \0 + wild + \0 (for wild) */
- char buff[MYSQLND_MAX_ALLOWED_DB_LEN * 2 + 1 + 1], *p;
+ zend_uchar buff[MYSQLND_MAX_ALLOWED_DB_LEN * 2 + 1 + 1], *p;
size_t table_len, wild_len;
- MYSQLND_RES *result = NULL;
- DBG_ENTER("mysqlnd_conn::list_fields");
+ MYSQLND_RES * result = NULL;
+ DBG_ENTER("mysqlnd_conn_data::list_fields");
DBG_INF_FMT("conn=%llu table=%s wild=%s", conn->thread_id, table? table:"",achtung_wild? achtung_wild:"");
- p = buff;
- if (table && (table_len = strlen(table))) {
- size_t to_copy = MIN(table_len, MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, table, to_copy);
- p += to_copy;
- *p++ = '\0';
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ p = buff;
+ if (table && (table_len = strlen(table))) {
+ size_t to_copy = MIN(table_len, MYSQLND_MAX_ALLOWED_DB_LEN);
+ memcpy(p, table, to_copy);
+ p += to_copy;
+ *p++ = '\0';
+ }
- if (achtung_wild && (wild_len = strlen(achtung_wild))) {
- size_t to_copy = MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, achtung_wild, to_copy);
- p += to_copy;
- *p++ = '\0';
- }
+ if (achtung_wild && (wild_len = strlen(achtung_wild))) {
+ size_t to_copy = MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN);
+ memcpy(p, achtung_wild, to_copy);
+ p += to_copy;
+ *p++ = '\0';
+ }
- if (PASS != conn->m->simple_command(conn, COM_FIELD_LIST, buff, p - buff,
- PROT_LAST /* we will handle the OK packet*/,
- FALSE, TRUE TSRMLS_CC)) {
- DBG_RETURN(NULL);
- }
+ if (PASS != conn->m->simple_command(conn, COM_FIELD_LIST, buff, p - buff,
+ PROT_LAST /* we will handle the OK packet*/,
+ FALSE, TRUE TSRMLS_CC)) {
+ conn->m->local_tx_end(conn, 0, FAIL TSRMLS_CC);
+ break;
+ }
- /*
- Prepare for the worst case.
- MyISAM goes to 2500 BIT columns, double it for safety.
- */
- result = conn->m->result_init(5000, conn->persistent TSRMLS_CC);
- if (!result) {
- DBG_RETURN(NULL);
- }
+ /*
+ Prepare for the worst case.
+ MyISAM goes to 2500 BIT columns, double it for safety.
+ */
+ result = conn->m->result_init(5000, conn->persistent TSRMLS_CC);
+ if (!result) {
+ break;
+ }
- if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) {
- DBG_ERR("Error ocurred while reading metadata");
- result->m.free_result(result, TRUE TSRMLS_CC);
- DBG_RETURN(NULL);
- }
+ if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) {
+ DBG_ERR("Error ocurred while reading metadata");
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ result = NULL;
+ break;
+ }
- result->type = MYSQLND_RES_NORMAL;
- result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
- result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
- if (!result->unbuf) {
- /* OOM */
- SET_OOM_ERROR(conn->error_info);
- result->m.free_result(result, TRUE TSRMLS_CC);
- DBG_RETURN(NULL);
+ result->type = MYSQLND_RES_NORMAL;
+ result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
+ result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+ if (!result->unbuf) {
+ /* OOM */
+ SET_OOM_ERROR(*conn->error_info);
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ result = NULL;
+ break;
+ }
+ result->unbuf->eof_reached = TRUE;
+ } while (0);
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
- result->unbuf->eof_reached = TRUE;
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::list_method */
+/* {{{ mysqlnd_conn_data::list_method */
MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, list_method)(MYSQLND * conn, const char * query, const char *achtung_wild, char *par1 TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, list_method)(MYSQLND_CONN_DATA * conn, const char * query, const char *achtung_wild, char *par1 TSRMLS_DC)
{
- char *show_query = NULL;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, list_method);
+ char * show_query = NULL;
size_t show_query_len;
- MYSQLND_RES *result = NULL;
+ MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn::list_method");
+ DBG_ENTER("mysqlnd_conn_data::list_method");
DBG_INF_FMT("conn=%llu query=%s wild=%u", conn->thread_id, query, achtung_wild);
- if (par1) {
- if (achtung_wild) {
- show_query_len = spprintf(&show_query, 0, query, par1, achtung_wild);
- } else {
- show_query_len = spprintf(&show_query, 0, query, par1);
- }
- } else {
- if (achtung_wild) {
- show_query_len = spprintf(&show_query, 0, query, achtung_wild);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (par1) {
+ if (achtung_wild) {
+ show_query_len = mnd_sprintf(&show_query, 0, query, par1, achtung_wild);
+ } else {
+ show_query_len = mnd_sprintf(&show_query, 0, query, par1);
+ }
} else {
- show_query_len = strlen(show_query = (char *)query);
+ if (achtung_wild) {
+ show_query_len = mnd_sprintf(&show_query, 0, query, achtung_wild);
+ } else {
+ show_query_len = strlen(show_query = (char *)query);
+ }
}
- }
- if (PASS == conn->m->query(conn, show_query, show_query_len TSRMLS_CC)) {
- result = conn->m->store_result(conn TSRMLS_CC);
- }
- if (show_query != query) {
- efree(show_query); /* allocated by spprintf */
+ if (PASS == conn->m->query(conn, show_query, show_query_len TSRMLS_CC)) {
+ result = conn->m->store_result(conn TSRMLS_CC);
+ }
+ if (show_query != query) {
+ mnd_sprintf_free(show_query);
+ }
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::errno */
+/* {{{ mysqlnd_conn_data::errno */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, errno)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, errno)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->error_info.error_no;
+ return conn->error_info->error_no;
}
/* }}} */
-/* {{{ mysqlnd_conn::error */
+/* {{{ mysqlnd_conn_data::error */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, error)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, error)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->error_info.error;
+ return conn->error_info->error;
}
/* }}} */
-/* {{{ mysqlnd_conn::sqlstate */
+/* {{{ mysqlnd_conn_data::sqlstate */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, sqlstate)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, sqlstate)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->error_info.sqlstate[0] ? conn->error_info.sqlstate:MYSQLND_SQLSTATE_NULL;
+ return conn->error_info->sqlstate[0] ? conn->error_info->sqlstate:MYSQLND_SQLSTATE_NULL;
}
/* }}} */
/* {{{ mysqlnd_old_escape_string */
-PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC)
+PHPAPI ulong
+mysqlnd_old_escape_string(char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
DBG_ENTER("mysqlnd_old_escape_string");
DBG_RETURN(mysqlnd_cset_escape_slashes(mysqlnd_find_charset_name("latin1"), newstr, escapestr, escapestr_len TSRMLS_CC));
}
/* }}} */
-/* {{{ mysqlnd_conn::ssl_set */
+
+/* {{{ mysqlnd_conn_data::ssl_set */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, ssl_set)(MYSQLND * const conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, ssl_set)(MYSQLND_CONN_DATA * const conn, const char * key, const char * const cert,
+ const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC)
{
- return (PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_KEY, key TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CERT, cert TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CA, ca TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CAPATH, capath TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CIPHER, cipher TSRMLS_CC)) ? PASS : FAIL;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ssl_set);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::ssl_set");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = (PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_KEY, key TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CERT, cert TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CA, ca TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CAPATH, capath TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CIPHER, cipher TSRMLS_CC)) ? PASS : FAIL;
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::escape_string */
+/* {{{ mysqlnd_conn_data::escape_string */
static ulong
-MYSQLND_METHOD(mysqlnd_conn, escape_string)(MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, escape_string)(MYSQLND_CONN_DATA * const conn, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::escape_string");
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, escape_string);
+ ulong ret;
+ DBG_ENTER("mysqlnd_conn_data::escape_string");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (conn->upsert_status.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
- DBG_RETURN(mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC));
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (conn->upsert_status->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
+ ret = mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC);
+ } else {
+ ret = mysqlnd_cset_escape_slashes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC);
+ }
+ conn->m->local_tx_end(conn, this_func, PASS TSRMLS_CC);
}
- DBG_RETURN(mysqlnd_cset_escape_slashes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC));
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::dump_debug_info */
+/* {{{ mysqlnd_conn_data::dump_debug_info */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, dump_debug_info)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::dump_debug_info");
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, server_dump_debug_information);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::dump_debug_info");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- DBG_RETURN(conn->m->simple_command(conn, COM_DEBUG, NULL, 0, PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC));
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_DEBUG, NULL, 0, PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::select_db */
+/* {{{ mysqlnd_conn_data::select_db */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, select_db)(MYSQLND * const conn, const char * const db, unsigned int db_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, unsigned int db_len TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, select_db);
+ enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::select_db");
+ DBG_ENTER("mysqlnd_conn_data::select_db");
DBG_INF_FMT("conn=%llu db=%s", conn->thread_id, db);
- ret = conn->m->simple_command(conn, COM_INIT_DB, db, db_len, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
- if (ret == PASS) {
- if (conn->connect_or_select_db) {
- mnd_pefree(conn->connect_or_select_db, conn->persistent);
- }
- conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
- conn->connect_or_select_db_len = db_len;
- if (!conn->connect_or_select_db) {
- /* OOM */
- SET_OOM_ERROR(conn->error_info);
- ret = FAIL;
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_INIT_DB, (zend_uchar*) db, db_len, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ SET_ERROR_AFF_ROWS(conn);
+ if (ret == PASS) {
+ if (conn->connect_or_select_db) {
+ mnd_pefree(conn->connect_or_select_db, conn->persistent);
+ }
+ conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
+ conn->connect_or_select_db_len = db_len;
+ if (!conn->connect_or_select_db) {
+ /* OOM */
+ SET_OOM_ERROR(*conn->error_info);
+ ret = FAIL;
+ }
}
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::ping */
+/* {{{ mysqlnd_conn_data::ping */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, ping)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ping);
+ enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::ping");
+ DBG_ENTER("mysqlnd_conn_data::ping");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- ret = conn->m->simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, TRUE, TRUE TSRMLS_CC);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, TRUE, TRUE TSRMLS_CC);
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ SET_ERROR_AFF_ROWS(conn);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
DBG_INF_FMT("ret=%u", ret);
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::statistic */
+/* {{{ mysqlnd_conn_data::statistic */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, statistic)(MYSQLND * conn, char **message, unsigned int * message_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, char **message, unsigned int * message_len TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, get_server_statistics);
+ enum_func_status ret = FAIL;
MYSQLND_PACKET_STATS * stats_header;
- DBG_ENTER("mysqlnd_conn::statistic");
+ DBG_ENTER("mysqlnd_conn_data::statistic");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- ret = conn->m->simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, FALSE, TRUE TSRMLS_CC);
- if (FAIL == ret) {
- DBG_RETURN(FAIL);
- }
- stats_header = conn->protocol->m.get_stats_packet(conn->protocol, FALSE TSRMLS_CC);
- if (!stats_header) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ ret = conn->m->simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, FALSE, TRUE TSRMLS_CC);
+ if (FAIL == ret) {
+ break;
+ }
+ stats_header = conn->protocol->m.get_stats_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!stats_header) {
+ SET_OOM_ERROR(*conn->error_info);
+ break;
+ }
- if (FAIL == (ret = PACKET_READ(stats_header, conn))) {
- DBG_RETURN(FAIL);
- }
- /* will be freed by Zend, thus don't use the mnd_ allocator */
- *message = estrndup(stats_header->message, stats_header->message_len);
- *message_len = stats_header->message_len;
- PACKET_FREE(stats_header);
+ if (PASS == (ret = PACKET_READ(stats_header, conn))) {
+ /* will be freed by Zend, thus don't use the mnd_ allocator */
+ *message = estrndup(stats_header->message, stats_header->message_len);
+ *message_len = stats_header->message_len;
+ DBG_INF(*message);
+ }
+ PACKET_FREE(stats_header);
+ } while (0);
- DBG_INF(*message);
- DBG_RETURN(PASS);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::kill */
+/* {{{ mysqlnd_conn_data::kill */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, kill)(MYSQLND * conn, unsigned int pid TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int pid TSRMLS_DC)
{
- enum_func_status ret;
- char buff[4];
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, kill_connection);
+ enum_func_status ret = FAIL;
+ zend_uchar buff[4];
- DBG_ENTER("mysqlnd_conn::kill");
+ DBG_ENTER("mysqlnd_conn_data::kill");
DBG_INF_FMT("conn=%llu pid=%u", conn->thread_id, pid);
- int4store(buff, pid);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ int4store(buff, pid);
- /* If we kill ourselves don't expect OK packet, PROT_LAST will skip it */
- if (pid != conn->thread_id) {
- ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
- } else if (PASS == (ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE, TRUE TSRMLS_CC))) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ /* If we kill ourselves don't expect OK packet, PROT_LAST will skip it */
+ if (pid != conn->thread_id) {
+ ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ SET_ERROR_AFF_ROWS(conn);
+ } else if (PASS == (ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE, TRUE TSRMLS_CC))) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::set_charset */
+/* {{{ mysqlnd_conn_data::set_charset */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_charset)(MYSQLND * const conn, const char * const csname TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, set_charset)(MYSQLND_CONN_DATA * const conn, const char * const csname TSRMLS_DC)
{
- enum_func_status ret = PASS;
- char * query;
- size_t query_len;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_charset);
+ enum_func_status ret = FAIL;
const MYSQLND_CHARSET * const charset = mysqlnd_find_charset_name(csname);
- DBG_ENTER("mysqlnd_conn::set_charset");
+ DBG_ENTER("mysqlnd_conn_data::set_charset");
DBG_INF_FMT("conn=%llu cs=%s", conn->thread_id, csname);
if (!charset) {
- SET_CLIENT_ERROR(conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE,
"Invalid characterset or character set not supported");
- DBG_RETURN(FAIL);
+ DBG_RETURN(ret);
}
- query_len = spprintf(&query, 0, "SET NAMES %s", csname);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ char * query;
+ size_t query_len = mnd_sprintf(&query, 0, "SET NAMES %s", csname);
- if (FAIL == conn->m->query(conn, query, query_len TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error executing query");
- } else if (conn->error_info.error_no) {
- ret = FAIL;
- } else {
- conn->charset = charset;
+ if (FAIL == (ret = conn->m->query(conn, query, query_len TSRMLS_CC))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error executing query");
+ } else if (conn->error_info->error_no) {
+ ret = FAIL;
+ } else {
+ conn->charset = charset;
+ }
+ mnd_sprintf_free(query);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
- efree(query); /* allocated by spprintf */
DBG_INF(ret == PASS? "PASS":"FAIL");
DBG_RETURN(ret);
@@ -1607,39 +1675,53 @@ MYSQLND_METHOD(mysqlnd_conn, set_charset)(MYSQLND * const conn, const char * con
/* }}} */
-/* {{{ mysqlnd_conn::refresh */
+/* {{{ mysqlnd_conn_data::refresh */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, refresh)(MYSQLND * const conn, uint8_t options TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, refresh)(MYSQLND_CONN_DATA * const conn, uint8_t options TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, refresh_server);
+ enum_func_status ret = FAIL;
zend_uchar bits[1];
- DBG_ENTER("mysqlnd_conn::refresh");
+ DBG_ENTER("mysqlnd_conn_data::refresh");
DBG_INF_FMT("conn=%llu options=%lu", conn->thread_id, options);
- int1store(bits, options);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ int1store(bits, options);
+
+ ret = conn->m->simple_command(conn, COM_REFRESH, bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
- DBG_RETURN(conn->m->simple_command(conn, COM_REFRESH, (char *)bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC));
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::shutdown */
+/* {{{ mysqlnd_conn_data::shutdown */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, shutdown)(MYSQLND * const conn, uint8_t level TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, shutdown)(MYSQLND_CONN_DATA * const conn, uint8_t level TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, shutdown_server);
+ enum_func_status ret = FAIL;
zend_uchar bits[1];
- DBG_ENTER("mysqlnd_conn::shutdown");
+ DBG_ENTER("mysqlnd_conn_data::shutdown");
DBG_INF_FMT("conn=%llu level=%lu", conn->thread_id, level);
- int1store(bits, level);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ int1store(bits, level);
- DBG_RETURN(conn->m->simple_command(conn, COM_SHUTDOWN, (char *)bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC));
+ ret = conn->m->simple_command(conn, COM_SHUTDOWN, bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_send_close */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, send_close)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
enum_func_status ret = PASS;
@@ -1647,11 +1729,17 @@ MYSQLND_METHOD(mysqlnd_conn, send_close)(MYSQLND * const conn TSRMLS_DC)
DBG_INF_FMT("conn=%llu conn->net->stream->abstract=%p",
conn->thread_id, conn->net->stream? conn->net->stream->abstract:NULL);
+ if (CONN_GET_STATE(conn) >= CONN_READY) {
+ MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS);
+ if (conn->persistent) {
+ MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
+ }
+ }
switch (CONN_GET_STATE(conn)) {
case CONN_READY:
DBG_INF("Connection clean, sending COM_QUIT");
if (conn->net->stream) {
- ret = conn->m->simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE TSRMLS_CC);
+ ret = conn->m->simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE TSRMLS_CC);
}
/* Do nothing */
break;
@@ -1691,48 +1779,11 @@ MYSQLND_METHOD(mysqlnd_conn, send_close)(MYSQLND * const conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::close */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn, enum_connection_close_type close_type TSRMLS_DC)
+/* {{{ mysqlnd_conn_data::get_reference */
+static MYSQLND_CONN_DATA *
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- enum_func_status ret = PASS;
- static enum_mysqlnd_collected_stats
- close_type_to_stat_map[MYSQLND_CLOSE_LAST] = {
- STAT_CLOSE_EXPLICIT,
- STAT_CLOSE_IMPLICIT,
- STAT_CLOSE_DISCONNECT
- };
- enum_mysqlnd_collected_stats statistic = close_type_to_stat_map[close_type];
-
- DBG_ENTER("mysqlnd_conn::close");
- DBG_INF_FMT("conn=%llu", conn->thread_id);
-
- if (conn->state >= CONN_READY) {
- MYSQLND_INC_CONN_STATISTIC(conn->stats, statistic);
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS);
- if (conn->persistent) {
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
- }
- }
-
- /*
- Close now, free_reference will try,
- if we are last, but that's not a problem.
- */
- ret = conn->m->send_close(conn TSRMLS_CC);
-
- ret = conn->m->free_reference(conn TSRMLS_CC);
-
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn::get_reference */
-static MYSQLND *
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference)(MYSQLND * const conn TSRMLS_DC)
-{
- DBG_ENTER("mysqlnd_conn::get_reference");
+ DBG_ENTER("mysqlnd_conn_data::get_reference");
++conn->refcount;
DBG_INF_FMT("conn=%llu new_refcount=%u", conn->thread_id, conn->refcount);
DBG_RETURN(conn);
@@ -1740,12 +1791,12 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference)(MYSQLND * const conn TSRMLS_
/* }}} */
-/* {{{ mysqlnd_conn::free_reference */
+/* {{{ mysqlnd_conn_data::free_reference */
static enum_func_status
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
enum_func_status ret = PASS;
- DBG_ENTER("mysqlnd_conn::free_reference");
+ DBG_ENTER("mysqlnd_conn_data::free_reference");
DBG_INF_FMT("conn=%llu old_refcount=%u", conn->thread_id, conn->refcount);
if (!(--conn->refcount)) {
/*
@@ -1761,21 +1812,21 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS
/* }}} */
-/* {{{ mysqlnd_conn::get_state */
+/* {{{ mysqlnd_conn_data::get_state */
static enum mysqlnd_connection_state
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::get_state");
+ DBG_ENTER("mysqlnd_conn_data::get_state");
DBG_RETURN(conn->state);
}
/* }}} */
-/* {{{ mysqlnd_conn::set_state */
+/* {{{ mysqlnd_conn_data::set_state */
static void
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::set_state");
+ DBG_ENTER("mysqlnd_conn_data::set_state");
DBG_INF_FMT("New state=%u", new_state);
conn->state = new_state;
DBG_VOID_RETURN;
@@ -1783,51 +1834,59 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysql
/* }}} */
-/* {{{ mysqlnd_conn::field_count */
+/* {{{ mysqlnd_conn_data::field_count */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, field_count)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, field_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->field_count;
}
/* }}} */
-/* {{{ mysqlnd_conn::insert_id */
+/* {{{ mysqlnd_conn_data::server_status */
+static unsigned int
+MYSQLND_METHOD(mysqlnd_conn_data, server_status)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
+{
+ return conn->upsert_status->server_status;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::insert_id */
static uint64_t
-MYSQLND_METHOD(mysqlnd_conn, insert_id)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, insert_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->upsert_status.last_insert_id;
+ return conn->upsert_status->last_insert_id;
}
/* }}} */
-/* {{{ mysqlnd_conn::affected_rows */
+/* {{{ mysqlnd_conn_data::affected_rows */
static uint64_t
-MYSQLND_METHOD(mysqlnd_conn, affected_rows)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, affected_rows)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->upsert_status.affected_rows;
+ return conn->upsert_status->affected_rows;
}
/* }}} */
-/* {{{ mysqlnd_conn::warning_count */
+/* {{{ mysqlnd_conn_data::warning_count */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, warning_count)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, warning_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->upsert_status.warning_count;
+ return conn->upsert_status->warning_count;
}
/* }}} */
-/* {{{ mysqlnd_conn::info */
+/* {{{ mysqlnd_conn_data::info */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, info)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->last_message;
}
/* }}} */
-#if !defined(MYSQLND_USE_OPTIMISATIONS) || MYSQLND_USE_OPTIMISATIONS == 0
/* {{{ mysqlnd_get_client_info */
PHPAPI const char * mysqlnd_get_client_info()
{
@@ -1842,56 +1901,56 @@ PHPAPI unsigned int mysqlnd_get_client_version()
return MYSQLND_VERSION_ID;
}
/* }}} */
-#endif
-/* {{{ mysqlnd_conn::get_server_info */
+
+/* {{{ mysqlnd_conn_data::get_server_info */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, get_server_info)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_server_info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->server_version;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_host_info */
+/* {{{ mysqlnd_conn_data::get_host_info */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, get_host_info)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_host_info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->host_info;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_proto_info */
+/* {{{ mysqlnd_conn_data::get_proto_info */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, get_proto_info)(const MYSQLND *const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_proto_info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->protocol_version;
}
/* }}} */
-/* {{{ mysqlnd_conn::charset_name */
+/* {{{ mysqlnd_conn_data::charset_name */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, charset_name)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, charset_name)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->charset->name;
}
/* }}} */
-/* {{{ mysqlnd_conn::thread_id */
+/* {{{ mysqlnd_conn_data::thread_id */
static uint64_t
-MYSQLND_METHOD(mysqlnd_conn, thread_id)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, thread_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->thread_id;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_server_version */
+/* {{{ mysqlnd_conn_data::get_server_version */
static unsigned long
-MYSQLND_METHOD(mysqlnd_conn, get_server_version)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_server_version)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
long major, minor, patch;
char *p;
@@ -1911,51 +1970,58 @@ MYSQLND_METHOD(mysqlnd_conn, get_server_version)(const MYSQLND * const conn TSRM
/* }}} */
-/* {{{ mysqlnd_conn::more_results */
+/* {{{ mysqlnd_conn_data::more_results */
static zend_bool
-MYSQLND_METHOD(mysqlnd_conn, more_results)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, more_results)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::more_results");
+ DBG_ENTER("mysqlnd_conn_data::more_results");
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
- DBG_RETURN(conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
+ DBG_RETURN(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
}
/* }}} */
-/* {{{ mysqlnd_conn::next_result */
+/* {{{ mysqlnd_conn_data::next_result */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, next_result)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, next_result);
+ enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::next_result");
+ DBG_ENTER("mysqlnd_conn_data::next_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING) {
- DBG_RETURN(FAIL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING) {
+ break;
+ }
- SET_EMPTY_ERROR(conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
- /*
- We are sure that there is a result set, since conn->state is set accordingly
- in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
- */
- if (FAIL == (ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC))) {
- /*
- There can be an error in the middle of a multi-statement, which will cancel the multi-statement.
- So there are no more results and we should just return FALSE, error_no has been set
- */
- if (!conn->error_info.error_no) {
- DBG_ERR_FMT("Serious error. %s::%u", __FILE__, __LINE__);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. PID=%d", getpid());
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- } else {
- DBG_INF_FMT("Error from the server : (%u) %s", conn->error_info.error_no, conn->error_info.error);
- }
- }
- if (ret == PASS && conn->last_query_type == QUERY_UPSERT && conn->upsert_status.affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status.affected_rows);
+ SET_EMPTY_ERROR(*conn->error_info);
+ SET_ERROR_AFF_ROWS(conn);
+ /*
+ We are sure that there is a result set, since conn->state is set accordingly
+ in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
+ */
+ if (FAIL == (ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC))) {
+ /*
+ There can be an error in the middle of a multi-statement, which will cancel the multi-statement.
+ So there are no more results and we should just return FALSE, error_no has been set
+ */
+ if (!conn->error_info->error_no) {
+ DBG_ERR_FMT("Serious error. %s::%u", __FILE__, __LINE__);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. PID=%d", getpid());
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ } else {
+ DBG_INF_FMT("Error from the server : (%u) %s", conn->error_info->error_no, conn->error_info->error);
+ }
+ break;
+ }
+ if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status->affected_rows) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status->affected_rows);
+ }
+ } while (0);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
@@ -2014,16 +2080,182 @@ PHPAPI const char *mysqlnd_field_type_name(enum mysqlnd_field_types field_type)
/* }}} */
-/* {{{ mysqlnd_conn::set_client_option */
+/* {{{ mysqlnd_conn_data::change_user */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
+MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
+ const char * user,
+ const char * passwd,
+ const char * db,
+ zend_bool silent,
+ size_t passwd_len
+ TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, change_user);
+ /*
+ User could be max 16 * 3 (utf8), pass is 20 usually, db is up to 64*3
+ Stack space is not that expensive, so use a bit more to be protected against
+ buffer overflows.
+ */
+ enum_func_status ret = FAIL;
+ zend_bool local_tx_started = FALSE;
+
+ DBG_ENTER("mysqlnd_conn_data::change_user");
+ DBG_INF_FMT("conn=%llu user=%s passwd=%s db=%s silent=%u",
+ conn->thread_id, user?user:"", passwd?"***":"null", db?db:"", (silent == TRUE)?1:0 );
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto end;
+ }
+ local_tx_started = TRUE;
+
+ SET_EMPTY_ERROR(*conn->error_info);
+ SET_ERROR_AFF_ROWS(conn);
+
+ if (!user) {
+ user = "";
+ }
+ if (!passwd) {
+ passwd = "";
+ }
+ if (!db) {
+ db = "";
+ }
+
+ {
+ zend_bool first_call = TRUE;
+ char * switch_to_auth_protocol = NULL;
+ size_t switch_to_auth_protocol_len = 0;
+ char * requested_protocol = NULL;
+ zend_uchar * plugin_data;
+ size_t plugin_data_len;
+
+ plugin_data_len = conn->auth_plugin_data_len;
+ plugin_data = mnd_emalloc(plugin_data_len);
+ if (!plugin_data) {
+ ret = FAIL;
+ goto end;
+ }
+ memcpy(plugin_data, conn->auth_plugin_data, plugin_data_len);
+
+ requested_protocol = mnd_pestrdup(conn->options->auth_protocol? conn->options->auth_protocol:"mysql_native_password", FALSE);
+ if (!requested_protocol) {
+ ret = FAIL;
+ goto end;
+ }
+
+ do {
+ struct st_mysqlnd_authentication_plugin * auth_plugin;
+ {
+ char * plugin_name = NULL;
+
+ mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol);
+
+ DBG_INF_FMT("looking for %s auth plugin", plugin_name);
+ auth_plugin = mysqlnd_plugin_find(plugin_name);
+ mnd_sprintf_free(plugin_name);
+
+ if (!auth_plugin) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol);
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client");
+ break;
+ }
+ }
+ DBG_INF("plugin found");
+
+ {
+ zend_uchar * switch_to_auth_protocol_data = NULL;
+ size_t switch_to_auth_protocol_data_len = 0;
+ zend_uchar * scrambled_data = NULL;
+ size_t scrambled_data_len = 0;
+
+ switch_to_auth_protocol = NULL;
+ switch_to_auth_protocol_len = 0;
+
+ if (conn->auth_plugin_data) {
+ mnd_pefree(conn->auth_plugin_data, conn->persistent);
+ conn->auth_plugin_data = NULL;
+ }
+ conn->auth_plugin_data_len = plugin_data_len;
+ conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
+ if (!conn->auth_plugin_data) {
+ SET_OOM_ERROR(*conn->error_info);
+ ret = FAIL;
+ goto end;
+ }
+ memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
+
+ DBG_INF_FMT("salt=[%*.s]", plugin_data_len - 1, plugin_data);
+
+ /* The data should be allocated with malloc() */
+ scrambled_data =
+ auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
+ plugin_data, plugin_data_len, 0, conn->server_capabilities TSRMLS_CC);
+
+
+ ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, passwd_len, db, strlen(db), silent,
+ first_call,
+ requested_protocol,
+ scrambled_data, scrambled_data_len,
+ &switch_to_auth_protocol, &switch_to_auth_protocol_len,
+ &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
+ TSRMLS_CC);
+
+ first_call = FALSE;
+ free(scrambled_data);
+
+ DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+ requested_protocol = switch_to_auth_protocol;
+
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ plugin_data_len = switch_to_auth_protocol_data_len;
+ plugin_data = switch_to_auth_protocol_data;
+ }
+ DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no);
+ } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL);
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ if (ret == PASS) {
+ conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC);
+ }
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+ }
+ /*
+ Here we should close all statements. Unbuffered queries should not be a
+ problem as we won't allow sending COM_CHANGE_USER.
+ */
+end:
+ if (TRUE == local_tx_started) {
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_INF(ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::set_client_option */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const conn,
enum mysqlnd_option option,
const char * const value
TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_client_option);
enum_func_status ret = PASS;
- DBG_ENTER("mysqlnd_conn::set_client_option");
+ DBG_ENTER("mysqlnd_conn_data::set_client_option");
DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto end;
+ }
switch (option) {
case MYSQL_OPT_COMPRESS:
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@@ -2043,42 +2275,38 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
break;
#if MYSQLND_UNICODE
case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE:
- conn->options.numeric_and_datetime_as_unicode = *(unsigned int*) value;
+ conn->options->numeric_and_datetime_as_unicode = *(unsigned int*) value;
break;
#endif
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
- DBG_INF("MYSQLND_OPT_INT_AND_FLOAT_NATIVE");
- conn->options.int_and_float_native = *(unsigned int*) value;
+ conn->options->int_and_float_native = *(unsigned int*) value;
break;
#endif
case MYSQL_OPT_LOCAL_INFILE:
- DBG_INF("MYSQL_OPT_LOCAL_INFILE");
if (!value || (*(unsigned int*) value) ? 1 : 0) {
- conn->options.flags |= CLIENT_LOCAL_FILES;
+ conn->options->flags |= CLIENT_LOCAL_FILES;
} else {
- conn->options.flags &= ~CLIENT_LOCAL_FILES;
+ conn->options->flags &= ~CLIENT_LOCAL_FILES;
}
break;
case MYSQL_INIT_COMMAND:
{
char ** new_init_commands;
char * new_command;
- DBG_INF("MYSQL_INIT_COMMAND");
- DBG_INF_FMT("command=%s", value);
/* when num_commands is 0, then realloc will be effectively a malloc call, internally */
- /* Don't assign to conn->options.init_commands because in case of OOM we will lose the pointer and leak */
- new_init_commands = mnd_perealloc(conn->options.init_commands, sizeof(char *) * (conn->options.num_commands + 1), conn->persistent);
+ /* Don't assign to conn->options->init_commands because in case of OOM we will lose the pointer and leak */
+ new_init_commands = mnd_perealloc(conn->options->init_commands, sizeof(char *) * (conn->options->num_commands + 1), conn->persistent);
if (!new_init_commands) {
goto oom;
}
- conn->options.init_commands = new_init_commands;
+ conn->options->init_commands = new_init_commands;
new_command = mnd_pestrdup(value, conn->persistent);
if (!new_command) {
goto oom;
}
- conn->options.init_commands[conn->options.num_commands] = new_command;
- ++conn->options.num_commands;
+ conn->options->init_commands[conn->options->num_commands] = new_command;
+ ++conn->options->num_commands;
break;
}
case MYSQL_READ_DEFAULT_FILE:
@@ -2092,23 +2320,22 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
case MYSQL_SET_CHARSET_NAME:
{
char * new_charset_name = mnd_pestrdup(value, conn->persistent);
- DBG_INF("MYSQL_SET_CHARSET_NAME");
if (!new_charset_name) {
goto oom;
}
- if (conn->options.charset_name) {
- mnd_pefree(conn->options.charset_name, conn->persistent);
+ if (conn->options->charset_name) {
+ mnd_pefree(conn->options->charset_name, conn->persistent);
}
- conn->options.charset_name = new_charset_name;
- DBG_INF_FMT("charset=%s", conn->options.charset_name);
+ conn->options->charset_name = new_charset_name;
+ DBG_INF_FMT("charset=%s", conn->options->charset_name);
break;
}
case MYSQL_OPT_NAMED_PIPE:
- conn->options.protocol = MYSQL_PROTOCOL_PIPE;
+ conn->options->protocol = MYSQL_PROTOCOL_PIPE;
break;
case MYSQL_OPT_PROTOCOL:
if (*(unsigned int*) value < MYSQL_PROTOCOL_LAST) {
- conn->options.protocol = *(unsigned int*) value;
+ conn->options->protocol = *(unsigned int*) value;
}
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@@ -2123,7 +2350,24 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
/* todo: throw an error, we don't support embedded */
break;
#endif
-
+ case MYSQLND_OPT_MAX_ALLOWED_PACKET:
+ if (*(unsigned int*) value > (1<<16)) {
+ conn->options->max_allowed_packet = *(unsigned int*) value;
+ }
+ break;
+ case MYSQLND_OPT_AUTH_PROTOCOL:
+ {
+ char * new_auth_protocol = value? mnd_pestrdup(value, conn->persistent) : NULL;
+ if (value && !new_auth_protocol) {
+ goto oom;
+ }
+ if (conn->options->auth_protocol) {
+ mnd_pefree(conn->options->auth_protocol, conn->persistent);
+ }
+ conn->options->auth_protocol = new_auth_protocol;
+ DBG_INF_FMT("auth_protocol=%s", conn->options->auth_protocol);
+ break;
+ }
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_SHARED_MEMORY_BASE_NAME:
case MYSQL_OPT_USE_RESULT:
@@ -2133,315 +2377,364 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
default:
ret = FAIL;
}
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
DBG_RETURN(ret);
oom:
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+end:
DBG_RETURN(FAIL);
}
/* }}} */
-/* {{{ mysqlnd_conn::use_result */
+/* {{{ mysqlnd_conn_data::use_result */
static MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- MYSQLND_RES * result;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, use_result);
+ MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn::use_result");
+ DBG_ENTER("mysqlnd_conn_data::use_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (!conn->current_result) {
- DBG_RETURN(NULL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ if (!conn->current_result) {
+ break;
+ }
- /* Nothing to store for UPSERT/LOAD DATA */
- if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
- mysqlnd_out_of_sync);
- DBG_ERR("Command out of sync");
- DBG_RETURN(NULL);
- }
+ /* Nothing to store for UPSERT/LOAD DATA */
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ DBG_ERR("Command out of sync");
+ break;
+ }
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);
- conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
- result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
+ conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
+ result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
- if (!result) {
- conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ if (!result) {
+ conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ }
+ conn->current_result = NULL;
+ } while (0);
+
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
- conn->current_result = NULL;
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::store_result */
+/* {{{ mysqlnd_conn_data::store_result */
static MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, store_result)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- MYSQLND_RES *result;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, store_result);
+ MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn::store_result");
+ DBG_ENTER("mysqlnd_conn_data::store_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (!conn->current_result) {
- DBG_RETURN(NULL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ if (!conn->current_result) {
+ break;
+ }
- /* Nothing to store for UPSERT/LOAD DATA*/
- if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
- mysqlnd_out_of_sync);
- DBG_ERR("Command out of sync");
- DBG_RETURN(NULL);
- }
+ /* Nothing to store for UPSERT/LOAD DATA*/
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ DBG_ERR("Command out of sync");
+ break;
+ }
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
- result = conn->current_result->m.store_result(conn->current_result, conn, FALSE TSRMLS_CC);
- if (!result) {
- conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ result = conn->current_result->m.store_result(conn->current_result, conn, FALSE TSRMLS_CC);
+ if (!result) {
+ conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ }
+ conn->current_result = NULL;
+ } while (0);
+
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
- conn->current_result = NULL;
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::get_connection_stats */
+/* {{{ mysqlnd_conn_data::get_connection_stats */
static void
-MYSQLND_METHOD(mysqlnd_conn, get_connection_stats)(const MYSQLND * const conn,
- zval *return_value
- TSRMLS_DC ZEND_FILE_LINE_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats)(const MYSQLND_CONN_DATA * const conn,
+ zval * return_value TSRMLS_DC ZEND_FILE_LINE_DC)
{
- DBG_ENTER("mysqlnd_conn::get_connection_stats");
- DBG_INF_FMT("conn=%llu", conn->thread_id);
+ DBG_ENTER("mysqlnd_conn_data::get_connection_stats");
mysqlnd_fill_stats_hash(conn->stats, mysqlnd_stats_values_names, return_value TSRMLS_CC ZEND_FILE_LINE_CC);
DBG_VOID_RETURN;
}
/* }}} */
-/* {{{ mysqlnd_conn::set_autocommit */
+/* {{{ mysqlnd_conn_data::set_autocommit */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_autocommit)(MYSQLND * conn, unsigned int mode TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit)(MYSQLND_CONN_DATA * conn, unsigned int mode TSRMLS_DC)
{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::set_autocommit");
- ret = conn->m->query(conn, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=1") - 1 TSRMLS_CC);
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_autocommit);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::set_autocommit");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->query(conn, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=1") - 1 TSRMLS_CC);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::tx_commit */
+/* {{{ mysqlnd_conn_data::tx_commit */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, tx_commit)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::tx_commit");
- ret = conn->m->query(conn, "COMMIT", sizeof("COMMIT") - 1 TSRMLS_CC);
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_commit);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::tx_commit");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->query(conn, "COMMIT", sizeof("COMMIT") - 1 TSRMLS_CC);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::tx_rollback */
+/* {{{ mysqlnd_conn_data::tx_rollback */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, tx_rollback)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::tx_rollback");
- ret = conn->m->query(conn, "ROLLBACK", sizeof("ROLLBACK") - 1 TSRMLS_CC);
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_rollback);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::tx_rollback");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->query(conn, "ROLLBACK", sizeof("ROLLBACK") - 1 TSRMLS_CC);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
+/* {{{ mysqlnd_conn_data::local_tx_start */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC)
+{
+ enum_func_status ret = PASS;
+ DBG_ENTER("mysqlnd_conn_data::local_tx_start");
+ DBG_RETURN(ret);
+}
+/* }}} */
-MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC);
-static enum_func_status MYSQLND_METHOD(mysqlnd_conn, init)(MYSQLND * conn TSRMLS_DC);
-
-static
-MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
- MYSQLND_METHOD(mysqlnd_conn, init),
- MYSQLND_METHOD(mysqlnd_conn, connect),
-
- MYSQLND_METHOD(mysqlnd_conn, escape_string),
- MYSQLND_METHOD(mysqlnd_conn, set_charset),
- MYSQLND_METHOD(mysqlnd_conn, query),
- MYSQLND_METHOD(mysqlnd_conn, send_query),
- MYSQLND_METHOD(mysqlnd_conn, reap_query),
- MYSQLND_METHOD(mysqlnd_conn, use_result),
- MYSQLND_METHOD(mysqlnd_conn, store_result),
- MYSQLND_METHOD(mysqlnd_conn, next_result),
- MYSQLND_METHOD(mysqlnd_conn, more_results),
-
- _mysqlnd_stmt_init,
-
- MYSQLND_METHOD(mysqlnd_conn, shutdown),
- MYSQLND_METHOD(mysqlnd_conn, refresh),
-
- MYSQLND_METHOD(mysqlnd_conn, ping),
- MYSQLND_METHOD(mysqlnd_conn, kill),
- MYSQLND_METHOD(mysqlnd_conn, select_db),
- MYSQLND_METHOD(mysqlnd_conn, dump_debug_info),
- MYSQLND_METHOD(mysqlnd_conn, change_user),
-
- MYSQLND_METHOD(mysqlnd_conn, errno),
- MYSQLND_METHOD(mysqlnd_conn, error),
- MYSQLND_METHOD(mysqlnd_conn, sqlstate),
- MYSQLND_METHOD(mysqlnd_conn, thread_id),
-
- MYSQLND_METHOD(mysqlnd_conn, get_connection_stats),
-
- MYSQLND_METHOD(mysqlnd_conn, get_server_version),
- MYSQLND_METHOD(mysqlnd_conn, get_server_info),
- MYSQLND_METHOD(mysqlnd_conn, statistic),
- MYSQLND_METHOD(mysqlnd_conn, get_host_info),
- MYSQLND_METHOD(mysqlnd_conn, get_proto_info),
- MYSQLND_METHOD(mysqlnd_conn, info),
- MYSQLND_METHOD(mysqlnd_conn, charset_name),
- MYSQLND_METHOD(mysqlnd_conn, list_fields),
- MYSQLND_METHOD(mysqlnd_conn, list_method),
-
- MYSQLND_METHOD(mysqlnd_conn, insert_id),
- MYSQLND_METHOD(mysqlnd_conn, affected_rows),
- MYSQLND_METHOD(mysqlnd_conn, warning_count),
- MYSQLND_METHOD(mysqlnd_conn, field_count),
-
- MYSQLND_METHOD(mysqlnd_conn, set_server_option),
- MYSQLND_METHOD(mysqlnd_conn, set_client_option),
- MYSQLND_METHOD(mysqlnd_conn, free_contents),
- MYSQLND_METHOD(mysqlnd_conn, free_options),
- MYSQLND_METHOD(mysqlnd_conn, close),
-
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor),
-
- mysqlnd_query_read_result_set_header,
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state),
-
- MYSQLND_METHOD(mysqlnd_conn, simple_command),
- MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response),
- MYSQLND_METHOD(mysqlnd_conn, restart_psession),
- MYSQLND_METHOD(mysqlnd_conn, end_psession),
- MYSQLND_METHOD(mysqlnd_conn, send_close),
-
- MYSQLND_METHOD(mysqlnd_conn, ssl_set),
- mysqlnd_result_init
-#ifdef AUTOCOMMIT_TX_COMMIT_ROLLBACK
- ,MYSQLND_METHOD(mysqlnd_conn, set_autocommit),
- MYSQLND_METHOD(mysqlnd_conn, tx_commit),
- MYSQLND_METHOD(mysqlnd_conn, tx_rollback)
-#endif
-MYSQLND_CLASS_METHODS_END;
+/* {{{ mysqlnd_conn_data::local_tx_end */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_conn_data::local_tx_end");
+ DBG_RETURN(status);
+}
+/* }}} */
-/* {{{ mysqlnd_conn::init */
+/* {{{ mysqlnd_conn_data::init */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, init)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, init)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::init");
+ DBG_ENTER("mysqlnd_conn_data::init");
mysqlnd_stats_init(&conn->stats, STAT_LAST);
SET_ERROR_AFF_ROWS(conn);
- conn->net = mysqlnd_net_init(conn->persistent TSRMLS_CC);
+ conn->net = mysqlnd_net_init(conn->persistent, conn->stats, conn->error_info TSRMLS_CC);
conn->protocol = mysqlnd_protocol_init(conn->persistent TSRMLS_CC);
- DBG_RETURN(conn->net && conn->protocol? PASS:FAIL);
+ DBG_RETURN(conn->stats && conn->net && conn->protocol? PASS:FAIL);
}
/* }}} */
-/* {{{ mysqlnd_init */
-PHPAPI MYSQLND * _mysqlnd_init(zend_bool persistent TSRMLS_DC)
-{
- size_t alloc_size = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND *ret;
+MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
- DBG_ENTER("mysqlnd_init");
- DBG_INF_FMT("persistent=%u", persistent);
- ret = mnd_pecalloc(1, alloc_size, persistent);
- if (!ret) {
- DBG_RETURN(NULL);
- }
- ret->persistent = persistent;
- ret->m = mysqlnd_conn_methods;
- CONN_SET_STATE(ret, CONN_ALLOCED);
- ret->m->get_reference(ret TSRMLS_CC);
+MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
+ MYSQLND_METHOD(mysqlnd_conn_data, init),
+ MYSQLND_METHOD(mysqlnd_conn_data, connect),
- if (PASS != ret->m->init(ret TSRMLS_CC)) {
- ret->m->dtor(ret TSRMLS_CC);
- ret = NULL;
- }
+ MYSQLND_METHOD(mysqlnd_conn_data, escape_string),
+ MYSQLND_METHOD(mysqlnd_conn_data, set_charset),
+ MYSQLND_METHOD(mysqlnd_conn_data, query),
+ MYSQLND_METHOD(mysqlnd_conn_data, send_query),
+ MYSQLND_METHOD(mysqlnd_conn_data, reap_query),
+ MYSQLND_METHOD(mysqlnd_conn_data, use_result),
+ MYSQLND_METHOD(mysqlnd_conn_data, store_result),
+ MYSQLND_METHOD(mysqlnd_conn_data, next_result),
+ MYSQLND_METHOD(mysqlnd_conn_data, more_results),
- DBG_RETURN(ret);
-}
-/* }}} */
+ _mysqlnd_stmt_init,
+ MYSQLND_METHOD(mysqlnd_conn_data, shutdown),
+ MYSQLND_METHOD(mysqlnd_conn_data, refresh),
-/* {{{ mysqlnd_library_init */
-PHPAPI void mysqlnd_library_init(TSRMLS_D)
-{
- if (mysqlnd_library_initted == FALSE) {
- mysqlnd_library_initted = TRUE;
- mysqlnd_conn_methods = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_conn);
- _mysqlnd_init_ps_subsystem();
- /* Should be calloc, as mnd_calloc will reference LOCK_access*/
- mysqlnd_stats_init(&mysqlnd_global_stats, STAT_LAST);
- }
-}
-/* }}} */
+ MYSQLND_METHOD(mysqlnd_conn_data, ping),
+ MYSQLND_METHOD(mysqlnd_conn_data, kill),
+ MYSQLND_METHOD(mysqlnd_conn_data, select_db),
+ MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, change_user),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, errno),
+ MYSQLND_METHOD(mysqlnd_conn_data, error),
+ MYSQLND_METHOD(mysqlnd_conn_data, sqlstate),
+ MYSQLND_METHOD(mysqlnd_conn_data, thread_id),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, get_server_version),
+ MYSQLND_METHOD(mysqlnd_conn_data, get_server_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, statistic),
+ MYSQLND_METHOD(mysqlnd_conn_data, get_host_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, get_proto_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, info),
+ MYSQLND_METHOD(mysqlnd_conn_data, charset_name),
+ MYSQLND_METHOD(mysqlnd_conn_data, list_fields),
+ MYSQLND_METHOD(mysqlnd_conn_data, list_method),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, insert_id),
+ MYSQLND_METHOD(mysqlnd_conn_data, affected_rows),
+ MYSQLND_METHOD(mysqlnd_conn_data, warning_count),
+ MYSQLND_METHOD(mysqlnd_conn_data, field_count),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, server_status),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, set_server_option),
+ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option),
+ MYSQLND_METHOD(mysqlnd_conn_data, free_contents),
+ MYSQLND_METHOD(mysqlnd_conn_data, free_options),
+
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor),
+
+ mysqlnd_query_read_result_set_header,
+
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_reference),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, simple_command),
+ MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response),
+ MYSQLND_METHOD(mysqlnd_conn_data, restart_psession),
+ MYSQLND_METHOD(mysqlnd_conn_data, end_psession),
+ MYSQLND_METHOD(mysqlnd_conn_data, send_close),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, ssl_set),
+ mysqlnd_result_init,
+ MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit),
+ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit),
+ MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback),
+ MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start),
+ MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)
+MYSQLND_CLASS_METHODS_END;
-/* {{{ mysqlnd_conn_get_methods */
-PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods()
+
+/* {{{ mysqlnd_conn::get_reference */
+static MYSQLND *
+MYSQLND_METHOD(mysqlnd_conn, clone_object)(MYSQLND * const conn TSRMLS_DC)
{
- return mysqlnd_conn_methods;
+ MYSQLND * ret;
+ DBG_ENTER("mysqlnd_conn::get_reference");
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).clone_connection_object(conn TSRMLS_CC);
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn_set_methods */
-PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods)
+
+/* {{{ mysqlnd_conn_data::dtor */
+static void
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn TSRMLS_DC)
{
- mysqlnd_conn_methods = methods;
-}
-/* }}} */
+ DBG_ENTER("mysqlnd_conn::dtor");
+ DBG_INF_FMT("conn=%llu", conn->data->thread_id);
+ conn->data->m->free_reference(conn->data TSRMLS_CC);
-static unsigned int mysqlnd_plugins_counter = 0;
+ mnd_pefree(conn, conn->persistent);
-/* {{{ mysqlnd_plugin_register */
-PHPAPI unsigned int mysqlnd_plugin_register()
-{
- return mysqlnd_plugins_counter++;
+ DBG_VOID_RETURN;
}
/* }}} */
-/* {{{ mysqlnd_plugin_count */
-PHPAPI unsigned int mysqlnd_plugin_count()
+/* {{{ mysqlnd_conn_data::close */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, enum_connection_close_type close_type TSRMLS_DC)
{
- return mysqlnd_plugins_counter;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_methods, close);
+ MYSQLND_CONN_DATA * conn = conn_handle->data;
+ enum_func_status ret = FAIL;
+
+ DBG_ENTER("mysqlnd_conn::close");
+ DBG_INF_FMT("conn=%llu", conn->thread_id);
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (CONN_GET_STATE(conn) >= CONN_READY) {
+ static enum_mysqlnd_collected_stats close_type_to_stat_map[MYSQLND_CLOSE_LAST] = {
+ STAT_CLOSE_EXPLICIT,
+ STAT_CLOSE_IMPLICIT,
+ STAT_CLOSE_DISCONNECT
+ };
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, close_type_to_stat_map[close_type]);
+ }
+
+ /*
+ Close now, free_reference will try,
+ if we are last, but that's not a problem.
+ */
+ ret = conn->m->send_close(conn TSRMLS_CC);
+
+ /* do it after free_reference/dtor and we might crash */
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+
+ conn_handle->m->dtor(conn_handle TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_connection_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC)
+MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
+ MYSQLND_METHOD(mysqlnd_conn, connect),
+ MYSQLND_METHOD(mysqlnd_conn, clone_object),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor),
+ MYSQLND_METHOD(mysqlnd_conn, close)
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ _mysqlnd_init */
+PHPAPI MYSQLND *
+_mysqlnd_init(zend_bool persistent TSRMLS_DC)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!conn || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)conn + sizeof(MYSQLND) + plugin_id * sizeof(void *)));
+ MYSQLND * ret;
+ DBG_ENTER("mysqlnd_init");
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_connection(persistent TSRMLS_CC);
+ DBG_RETURN(ret);
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index 65fe78e70c..b0b3b15c69 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
@@ -22,12 +22,10 @@
#ifndef MYSQLND_H
#define MYSQLND_H
-#define MYSQLND_VERSION "mysqlnd 5.0.8-dev - 20102224 - $Id$"
-#define MYSQLND_VERSION_ID 50008
+#define MYSQLND_VERSION "mysqlnd 5.0.10 - 20111026 - $Id$"
+#define MYSQLND_VERSION_ID 50010
-/* This forces inlining of some accessor functions */
-#define MYSQLND_USE_OPTIMISATIONS 0
-#define AUTOCOMMIT_TX_COMMIT_ROLLBACK
+#define MYSQLND_PLUGIN_API_VERSION 1
#define MYSQLND_STRING_TO_INT_CONVERSION
/*
@@ -69,29 +67,16 @@ PHPAPI void mysqlnd_library_init(TSRMLS_D);
PHPAPI void mysqlnd_library_end(TSRMLS_D);
PHPAPI unsigned int mysqlnd_plugin_register();
+PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header * plugin TSRMLS_DC);
PHPAPI unsigned int mysqlnd_plugin_count();
-PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data((c), (p_id) TSRMLS_CC)
+PHPAPI void * _mysqlnd_plugin_find(const char * const name TSRMLS_DC);
+#define mysqlnd_plugin_find(name) _mysqlnd_plugin_find((name) TSRMLS_CC);
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_result_data(r, p_id) _mysqlnd_plugin_get_plugin_result_data((r), (p_id) TSRMLS_CC)
+PHPAPI void _mysqlnd_plugin_apply_with_argument(apply_func_arg_t apply_func, void * argument TSRMLS_DC);
+#define mysqlnd_plugin_apply_with_argument(func, argument) _mysqlnd_plugin_apply_with_argument((func), (argument) TSRMLS_CC);
-PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_stmt_data(s, p_id) _mysqlnd_plugin_get_plugin_stmt_data((s), (p_id) TSRMLS_CC)
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_protocol_data(p, p_id) _mysqlnd_plugin_get_plugin_protocol_data((p), (p_id) TSRMLS_CC)
-
-
-PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods();
-PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods);
-
-PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods();
-PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods);
-
-
-#define mysqlnd_restart_psession(conn) (conn)->m->restart_psession((conn) TSRMLS_CC)
-#define mysqlnd_end_psession(conn) (conn)->m->end_psession((conn) TSRMLS_CC)
+#define mysqlnd_restart_psession(conn) ((conn)->data)->m->restart_psession((conn)->data TSRMLS_CC)
+#define mysqlnd_end_psession(conn) ((conn)->data)->m->end_psession((conn)->data TSRMLS_CC)
PHPAPI void mysqlnd_minfo_print_hash(zval *values);
#define mysqlnd_thread_safe() TRUE
@@ -102,16 +87,17 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const char
/* Connect */
#define mysqlnd_init(persistent) _mysqlnd_init((persistent) TSRMLS_CC)
PHPAPI MYSQLND * _mysqlnd_init(zend_bool persistent TSRMLS_DC);
-PHPAPI MYSQLND * mysqlnd_connect(MYSQLND *conn,
- const char *host, const char *user,
- const char *passwd, unsigned int passwd_len,
- const char *db, unsigned int db_len,
+PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
+ const char * host, const char * user,
+ const char * passwd, unsigned int passwd_len,
+ const char * db, unsigned int db_len,
unsigned int port,
- const char *socket_or_pipe,
+ const char * socket_or_pipe,
unsigned int mysql_flags
TSRMLS_DC);
-#define mysqlnd_change_user(conn, user, passwd, db, silent) (conn)->m->change_user((conn), (user), (passwd), (db), (silent) TSRMLS_CC)
+#define mysqlnd_change_user(conn, user, passwd, db, silent) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), strlen((passwd)) TSRMLS_CC)
+#define mysqlnd_change_user_ex(conn, user, passwd, db, silent, passwd_len) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), (passwd_len) TSRMLS_CC)
#define mysqlnd_debug(x) _mysqlnd_debug((x) TSRMLS_CC)
PHPAPI void _mysqlnd_debug(const char *mode TSRMLS_DC);
@@ -121,43 +107,45 @@ PHPAPI void _mysqlnd_debug(const char *mode TSRMLS_DC);
#define mysqlnd_fetch_row_c(result) (result)->m.fetch_row_c((result) TSRMLS_CC)
#define mysqlnd_fetch_all(result, flags, return_value) (result)->m.fetch_all((result), (flags), (return_value) TSRMLS_CC ZEND_FILE_LINE_CC)
#define mysqlnd_result_fetch_field_data(res,offset,ret) (res)->m.fetch_field_data((res), (offset), (ret) TSRMLS_CC)
-#define mysqlnd_get_connection_stats(conn, values) (conn)->m->get_statistics((conn), (values) TSRMLS_CC ZEND_FILE_LINE_CC)
+#define mysqlnd_get_connection_stats(conn, values) ((conn)->data)->m->get_statistics((conn)->data, (values) TSRMLS_CC ZEND_FILE_LINE_CC)
#define mysqlnd_get_client_stats(values) _mysqlnd_get_client_stats((values) TSRMLS_CC ZEND_FILE_LINE_CC)
#define mysqlnd_close(conn,is_forced) (conn)->m->close((conn), (is_forced) TSRMLS_CC)
-#define mysqlnd_query(conn, query_str, query_len) (conn)->m->query((conn), (query_str), (query_len) TSRMLS_CC)
-#define mysqlnd_async_query(conn, query_str, query_len) (conn)->m->send_query((conn), (query_str), (query_len) TSRMLS_CC)
+#define mysqlnd_query(conn, query_str, query_len) ((conn)->data)->m->query((conn)->data, (query_str), (query_len) TSRMLS_CC)
+#define mysqlnd_async_query(conn, query_str, query_len) ((conn)->data)->m->send_query((conn)->data, (query_str), (query_len) TSRMLS_CC)
#define mysqlnd_poll(r, err, d_pull,sec,usec,desc_num) _mysqlnd_poll((r), (err), (d_pull), (sec), (usec), (desc_num) TSRMLS_CC)
-#define mysqlnd_reap_async_query(conn) (conn)->m->reap_query((conn) TSRMLS_CC)
+#define mysqlnd_reap_async_query(conn) ((conn)->data)->m->reap_query((conn)->data TSRMLS_CC)
#define mysqlnd_unbuffered_skip_result(result) (result)->m.skip_result((result) TSRMLS_CC)
PHPAPI enum_func_status _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, uint * desc_num TSRMLS_DC);
-#define mysqlnd_use_result(conn) (conn)->m->use_result((conn) TSRMLS_CC)
-#define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC)
-#define mysqlnd_next_result(conn) (conn)->m->next_result((conn) TSRMLS_CC)
-#define mysqlnd_more_results(conn) (conn)->m->more_results((conn) TSRMLS_CC)
+#define mysqlnd_use_result(conn) ((conn)->data)->m->use_result((conn)->data TSRMLS_CC)
+#define mysqlnd_store_result(conn) ((conn)->data)->m->store_result((conn)->data TSRMLS_CC)
+#define mysqlnd_next_result(conn) ((conn)->data)->m->next_result((conn)->data TSRMLS_CC)
+#define mysqlnd_more_results(conn) ((conn)->data)->m->more_results((conn)->data TSRMLS_CC)
#define mysqlnd_free_result(r,e_or_i) ((MYSQLND_RES*)r)->m.free_result(((MYSQLND_RES*)(r)), (e_or_i) TSRMLS_CC)
#define mysqlnd_data_seek(result, row) (result)->m.seek_data((result), (row) TSRMLS_CC)
/* Errors */
-#define mysqlnd_errno(conn) (conn)->m->get_error_no((conn) TSRMLS_CC)
-#define mysqlnd_error(conn) (conn)->m->get_error_str((conn) TSRMLS_CC)
-#define mysqlnd_sqlstate(conn) (conn)->m->get_sqlstate((conn) TSRMLS_CC)
+#define mysqlnd_errno(conn) ((conn)->data)->m->get_error_no((conn)->data TSRMLS_CC)
+#define mysqlnd_error(conn) ((conn)->data)->m->get_error_str((conn)->data TSRMLS_CC)
+#define mysqlnd_sqlstate(conn) ((conn)->data)->m->get_sqlstate((conn)->data TSRMLS_CC)
/* Charset */
-#define mysqlnd_character_set_name(conn) (conn)->m->charset_name((conn) TSRMLS_CC)
+#define mysqlnd_character_set_name(conn) ((conn)->data)->m->charset_name((conn)->data TSRMLS_CC)
/* Simple metadata */
-#define mysqlnd_field_count(conn) (conn)->m->get_field_count((conn) TSRMLS_CC)
-#define mysqlnd_insert_id(conn) (conn)->m->get_last_insert_id((conn) TSRMLS_CC)
-#define mysqlnd_affected_rows(conn) (conn)->m->get_affected_rows((conn) TSRMLS_CC)
-#define mysqlnd_warning_count(conn) (conn)->m->get_warning_count((conn) TSRMLS_CC)
-#define mysqlnd_info(conn) (conn)->m->get_last_message((conn) TSRMLS_CC)
-#define mysqlnd_get_server_info(conn) (conn)->m->get_server_information((conn) TSRMLS_CC)
-#define mysqlnd_get_host_info(conn) (conn)->m->get_host_information((conn) TSRMLS_CC)
-#define mysqlnd_get_proto_info(conn) (conn)->m->get_protocol_information((conn) TSRMLS_CC)
-#define mysqlnd_thread_id(conn) (conn)->m->get_thread_id((conn) TSRMLS_CC)
+#define mysqlnd_field_count(conn) ((conn)->data)->m->get_field_count((conn)->data TSRMLS_CC)
+#define mysqlnd_insert_id(conn) ((conn)->data)->m->get_last_insert_id((conn)->data TSRMLS_CC)
+#define mysqlnd_affected_rows(conn) ((conn)->data)->m->get_affected_rows((conn)->data TSRMLS_CC)
+#define mysqlnd_warning_count(conn) ((conn)->data)->m->get_warning_count((conn)->data TSRMLS_CC)
+#define mysqlnd_info(conn) ((conn)->data)->m->get_last_message((conn)->data TSRMLS_CC)
+#define mysqlnd_get_server_info(conn) ((conn)->data)->m->get_server_information((conn)->data TSRMLS_CC)
+#define mysqlnd_get_server_version(conn) ((conn)->data)->m->get_server_version((conn)->data TSRMLS_CC)
+#define mysqlnd_get_host_info(conn) ((conn)->data)->m->get_host_information((conn)->data TSRMLS_CC)
+#define mysqlnd_get_proto_info(conn) ((conn)->data)->m->get_protocol_information((conn)->data TSRMLS_CC)
+#define mysqlnd_thread_id(conn) ((conn)->data)->m->get_thread_id((conn)->data TSRMLS_CC)
+#define mysqlnd_get_server_status(conn) ((conn)->data)->m->get_server_status((conn)->data TSRMLS_CC)
#define mysqlnd_num_rows(result) (result)->m.num_rows((result) TSRMLS_CC)
#define mysqlnd_num_fields(result) (result)->m.num_fields((result) TSRMLS_CC)
@@ -175,7 +163,7 @@ PHPAPI unsigned long * _mysqlnd_fetch_lengths(MYSQLND_RES * const result TSRMLS
PHPAPI const char * mysqlnd_get_client_info();
PHPAPI unsigned int mysqlnd_get_client_version();
-#define mysqlnd_ssl_set(conn, key, cert, ca, capath, cipher) (conn)->m->ssl_set((conn), (key), (cert), (ca), (capath), (cipher) TSRMLS_CC)
+#define mysqlnd_ssl_set(conn, key, cert, ca, capath, cipher) ((conn)->data)->m->ssl_set((conn)->data, (key), (cert), (ca), (capath), (cipher) TSRMLS_CC)
/* PS */
#define mysqlnd_stmt_insert_id(stmt) (stmt)->m->get_last_insert_id((stmt) TSRMLS_CC)
@@ -199,46 +187,39 @@ PHPAPI void mysqlnd_free_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind TSRM
PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
/* LOAD DATA LOCAL */
-PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn);
-PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname);
+PHPAPI void mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn);
+PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, const char * const funcname);
/* Simple commands */
-#ifdef AUTOCOMMIT_TX_COMMIT_ROLLBACK
-#define mysqlnd_autocommit(conn, mode) (conn)->m->set_autocommit((conn), (mode) TSRMLS_CC)
-#define mysqlnd_commit(conn) (conn)->m->tx_commit((conn) TSRMLS_CC)
-#define mysqlnd_rollback(conn) (conn)->m->tx_rollback((conn) TSRMLS_CC)
-#else
-#define mysqlnd_autocommit(conn, mode) (conn)->m->query((conn),(mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", 16 TSRMLS_CC)
-#define mysqlnd_commit(conn) (conn)->m->query((conn), "COMMIT", sizeof("COMMIT")-1 TSRMLS_CC)
-#define mysqlnd_rollback(conn) (conn)->m->query((conn), "ROLLBACK", sizeof("ROLLBACK")-1 TSRMLS_CC)
-#endif
-#define mysqlnd_list_dbs(conn, wild) (conn)->m->list_method((conn), wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
-#define mysqlnd_list_fields(conn, tab,wild) (conn)->m->list_fields((conn), (tab), (wild) TSRMLS_CC)
-#define mysqlnd_list_processes(conn) (conn)->m->list_method((conn), "SHOW PROCESSLIST", NULL, NULL TSRMLS_CC)
-#define mysqlnd_list_tables(conn, wild) (conn)->m->list_method((conn), wild? "SHOW TABLES LIKE %s":"SHOW TABLES", (wild), NULL TSRMLS_CC)
-#define mysqlnd_dump_debug_info(conn) (conn)->m->server_dump_debug_information((conn) TSRMLS_CC)
-#define mysqlnd_select_db(conn, db, db_len) (conn)->m->select_db((conn), (db), (db_len) TSRMLS_CC)
-#define mysqlnd_ping(conn) (conn)->m->ping((conn) TSRMLS_CC)
-#define mysqlnd_kill(conn, pid) (conn)->m->kill_connection((conn), (pid) TSRMLS_CC)
-#define mysqlnd_refresh(conn, options) (conn)->m->refresh_server((conn), (options) TSRMLS_CC)
-#define mysqlnd_shutdown(conn, level) (conn)->m->shutdown_server((conn), (level) TSRMLS_CC)
-#define mysqlnd_get_server_version(conn) (conn)->m->get_server_version((conn) TSRMLS_CC)
-#define mysqlnd_set_character_set(conn, cs) (conn)->m->set_charset((conn), (cs) TSRMLS_CC)
-#define mysqlnd_stat(conn, msg, msg_len) (conn)->m->get_server_statistics((conn), (msg), (msg_len) TSRMLS_CC)
-#define mysqlnd_options(conn, opt, value) (conn)->m->set_client_option((conn), (opt), (value) TSRMLS_CC)
-#define mysqlnd_set_server_option(conn, op) (conn)->m->set_server_option((conn), (op) TSRMLS_CC)
+#define mysqlnd_autocommit(conn, mode) ((conn)->data)->m->set_autocommit((conn)->data, (mode) TSRMLS_CC)
+#define mysqlnd_commit(conn) ((conn)->data)->m->tx_commit((conn)->data TSRMLS_CC)
+#define mysqlnd_rollback(conn) ((conn)->data)->m->tx_rollback((conn)->data TSRMLS_CC)
+#define mysqlnd_list_dbs(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
+#define mysqlnd_list_fields(conn, tab,wild) ((conn)->data)->m->list_fields((conn)->data, (tab), (wild) TSRMLS_CC)
+#define mysqlnd_list_processes(conn) ((conn)->data)->m->list_method((conn)->data, "SHOW PROCESSLIST", NULL, NULL TSRMLS_CC)
+#define mysqlnd_list_tables(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW TABLES LIKE %s":"SHOW TABLES", (wild), NULL TSRMLS_CC)
+#define mysqlnd_dump_debug_info(conn) ((conn)->data)->m->server_dump_debug_information((conn)->data TSRMLS_CC)
+#define mysqlnd_select_db(conn, db, db_len) ((conn)->data)->m->select_db((conn)->data, (db), (db_len) TSRMLS_CC)
+#define mysqlnd_ping(conn) ((conn)->data)->m->ping((conn)->data TSRMLS_CC)
+#define mysqlnd_kill(conn, pid) ((conn)->data)->m->kill_connection((conn)->data, (pid) TSRMLS_CC)
+#define mysqlnd_refresh(conn, options) ((conn)->data)->m->refresh_server((conn)->data, (options) TSRMLS_CC)
+#define mysqlnd_shutdown(conn, level) ((conn)->data)->m->shutdown_server((conn)->data, (level) TSRMLS_CC)
+#define mysqlnd_set_character_set(conn, cs) ((conn)->data)->m->set_charset((conn)->data, (cs) TSRMLS_CC)
+#define mysqlnd_stat(conn, msg, msg_len) ((conn)->data)->m->get_server_statistics(((conn)->data), (msg), (msg_len) TSRMLS_CC)
+#define mysqlnd_options(conn, opt, value) ((conn)->data)->m->set_client_option((conn)->data, (opt), (value) TSRMLS_CC)
+#define mysqlnd_set_server_option(conn, op) ((conn)->data)->m->set_server_option((conn)->data, (op) TSRMLS_CC)
/* Escaping */
#define mysqlnd_real_escape_string(conn, newstr, escapestr, escapestr_len) \
- (conn)->m->escape_string((conn), (newstr), (escapestr), (escapestr_len) TSRMLS_CC)
+ ((conn)->data)->m->escape_string((conn)->data, (newstr), (escapestr), (escapestr_len) TSRMLS_CC)
#define mysqlnd_escape_string(newstr, escapestr, escapestr_len) \
mysqlnd_old_escape_string((newstr), (escapestr), (escapestr_len) TSRMLS_CC)
-PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
+PHPAPI ulong mysqlnd_old_escape_string(char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC);
/* PS */
-#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn) TSRMLS_CC)
+#define mysqlnd_stmt_init(conn) ((conn)->data)->m->stmt_init(((conn)->data) TSRMLS_CC)
#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt) TSRMLS_CC)? PASS:FAIL))
#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt) TSRMLS_CC)
#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt) TSRMLS_CC)
@@ -262,6 +243,7 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size
#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt) TSRMLS_CC)
#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit) TSRMLS_CC)
#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt) TSRMLS_CC)
+#define mysqlnd_stmt_flush(stmt) (stmt)->m->flush((stmt) TSRMLS_CC)
#define mysqlnd_stmt_attr_get(stmt, attr, value) (stmt)->m->get_attribute((stmt), (attr), (value) TSRMLS_CC)
diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c
new file mode 100644
index 0000000000..06e979a6e1
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_alloc.c
@@ -0,0 +1,726 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_statistics.h"
+
+
+static const char mysqlnd_emalloc_name[] = "_mysqlnd_emalloc";
+static const char mysqlnd_pemalloc_name[] = "_mysqlnd_pemalloc";
+static const char mysqlnd_ecalloc_name[] = "_mysqlnd_ecalloc";
+static const char mysqlnd_pecalloc_name[] = "_mysqlnd_pecalloc";
+static const char mysqlnd_erealloc_name[] = "_mysqlnd_erealloc";
+static const char mysqlnd_perealloc_name[] = "_mysqlnd_perealloc";
+static const char mysqlnd_efree_name[] = "_mysqlnd_efree";
+static const char mysqlnd_pefree_name[] = "_mysqlnd_pefree";
+static const char mysqlnd_malloc_name[] = "_mysqlnd_malloc";
+static const char mysqlnd_calloc_name[] = "_mysqlnd_calloc";
+static const char mysqlnd_realloc_name[] = "_mysqlnd_realloc";
+static const char mysqlnd_free_name[] = "_mysqlnd_free";
+static const char mysqlnd_pestrndup_name[] = "_mysqlnd_pestrndup";
+static const char mysqlnd_pestrdup_name[] = "_mysqlnd_pestrdup";
+
+const char * mysqlnd_debug_std_no_trace_funcs[] =
+{
+ mysqlnd_emalloc_name,
+ mysqlnd_ecalloc_name,
+ mysqlnd_efree_name,
+ mysqlnd_erealloc_name,
+ mysqlnd_pemalloc_name,
+ mysqlnd_pecalloc_name,
+ mysqlnd_pefree_name,
+ mysqlnd_perealloc_name,
+ mysqlnd_malloc_name,
+ mysqlnd_calloc_name,
+ mysqlnd_realloc_name,
+ mysqlnd_free_name,
+ mysqlnd_pestrndup_name,
+ mysqlnd_read_header_name,
+ mysqlnd_read_body_name,
+ NULL /* must be always last */
+};
+
+
+#if ZEND_DEBUG
+#else
+#define __zend_filename "/unknown/unknown"
+#define __zend_lineno 0
+#endif
+
+#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
+#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
+#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
+
+/* {{{ _mysqlnd_emalloc */
+void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_emalloc_name);
+
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = emalloc(REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pemalloc */
+void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_pemalloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = pemalloc(REAL_SIZE(size), persistent);
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
+
+ if (ret && collect_memory_statistics) {
+ enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
+ enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
+ }
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_ecalloc */
+void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_ecalloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = ecalloc(nmemb, REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pecalloc */
+void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_pecalloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+
+ if (ret && collect_memory_statistics) {
+ enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
+ enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
+ }
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_erealloc */
+void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_erealloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("new_ptr=%p", (char*)ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = new_size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_perealloc */
+void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
+#if PHP_DEBUG
+ long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_perealloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("new_ptr=%p", (char*)ret);
+
+ if (ret && collect_memory_statistics) {
+ enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
+ enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
+ *(size_t *) ret = new_size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_efree */
+void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
+{
+ size_t free_amount = 0;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_efree_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p", ptr);
+
+ if (ptr) {
+ if (collect_memory_statistics) {
+ free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+ DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+ }
+ efree(REAL_PTR(ptr));
+ }
+
+ if (collect_memory_statistics) {
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pefree */
+void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ size_t free_amount = 0;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_pefree_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
+
+ if (ptr) {
+ if (collect_memory_statistics) {
+ free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+ DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+ }
+ pefree(REAL_PTR(ptr), persistent);
+ }
+
+ if (collect_memory_statistics) {
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
+ persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
+ }
+ DBG_VOID_RETURN;
+}
+
+
+/* {{{ _mysqlnd_malloc */
+void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_malloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = malloc(REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_calloc */
+void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_calloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = calloc(nmemb, REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_realloc */
+void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_realloc_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
+ DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("new_ptr=%p", (char*)ret);
+
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = new_size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_free */
+void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
+{
+ size_t free_amount = 0;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_free_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p", ptr);
+
+ if (ptr) {
+ if (collect_memory_statistics) {
+ free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+ DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+ }
+ free(REAL_PTR(ptr));
+ }
+
+ if (collect_memory_statistics) {
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+#define SMART_STR_START_SIZE 2048
+#define SMART_STR_PREALLOC 512
+#include "ext/standard/php_smart_str.h"
+
+
+/* {{{ _mysqlnd_pestrndup */
+char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+{
+ char * ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_pestrndup_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p", ptr);
+
+ ret = pemalloc(REAL_SIZE(length) + 1, persistent);
+ {
+ size_t l = length;
+ char * p = (char *) ptr;
+ char * dest = (char *) FAKE_PTR(ret);
+ while (*p && l--) {
+ *dest++ = *p++;
+ }
+ *dest = '\0';
+ }
+
+ if (collect_memory_statistics) {
+ *(size_t *) ret = length;
+ MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
+ }
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pestrdup */
+char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ char * ret;
+ smart_str tmp_str = {0, 0, 0};
+ const char * p = ptr;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_pestrdup_name);
+ DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+ DBG_INF_FMT("ptr=%p", ptr);
+ do {
+ smart_str_appendc(&tmp_str, *p);
+ } while (*p++);
+
+ ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
+ memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
+
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = tmp_str.len;
+ MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
+ }
+ smart_str_free(&tmp_str);
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_sprintf */
+PHPAPI int _mysqlnd_sprintf(char ** pbuf, size_t max_len, const char *format, ...)
+{
+ int len;
+ va_list ap;
+ va_start(ap, format);
+ len = vspprintf(pbuf, max_len, format, ap);
+ va_end(ap);
+ return len;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_sprintf_free */
+PHPAPI void _mysqlnd_sprintf_free(char * p)
+{
+ efree(p);
+}
+/* }}} */
+
+
+PHPAPI int _mysqlnd_vsprintf(char ** pbuf, size_t max_len, const char * format, va_list ap)
+{
+ return vspprintf(pbuf, max_len, format, ap);
+}
+/* }}} */
+
+
+#define MYSQLND_DEBUG_MEMORY 1
+
+#if MYSQLND_DEBUG_MEMORY == 0
+
+/* {{{ mysqlnd_zend_mm_emalloc */
+static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
+{
+ return emalloc(size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pemalloc */
+static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pemalloc(size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_ecalloc */
+static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ return ecalloc(nmemb, size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pecalloc */
+static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pecalloc(nmemb, size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_erealloc */
+static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+ return erealloc(ptr, new_size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_perealloc */
+static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
+{
+ return perealloc(ptr, new_size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_efree */
+static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
+{
+ efree(ptr);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pefree */
+static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ pefree(ptr, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_malloc */
+static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
+{
+ return malloc(size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_calloc */
+static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ return calloc(nmemb, size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_realloc */
+static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
+{
+ return realloc(ptr, new_size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_free */
+static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
+{
+ free(ptr);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pestrndup */
+static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pestrndup(ptr, length, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pestrdup */
+static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pestrdup(ptr, persistent);
+}
+/* }}} */
+
+#endif
+
+
+PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator =
+{
+#if MYSQLND_DEBUG_MEMORY
+ _mysqlnd_emalloc,
+ _mysqlnd_pemalloc,
+ _mysqlnd_ecalloc,
+ _mysqlnd_pecalloc,
+ _mysqlnd_erealloc,
+ _mysqlnd_perealloc,
+ _mysqlnd_efree,
+ _mysqlnd_pefree,
+ _mysqlnd_malloc,
+ _mysqlnd_calloc,
+ _mysqlnd_realloc,
+ _mysqlnd_free,
+ _mysqlnd_pestrndup,
+ _mysqlnd_pestrdup,
+ _mysqlnd_sprintf,
+ _mysqlnd_vsprintf,
+ _mysqlnd_sprintf_free
+#else
+ mysqlnd_zend_mm_emalloc,
+ mysqlnd_zend_mm_pemalloc,
+ mysqlnd_zend_mm_ecalloc,
+ mysqlnd_zend_mm_pecalloc,
+ mysqlnd_zend_mm_erealloc,
+ mysqlnd_zend_mm_perealloc,
+ mysqlnd_zend_mm_efree,
+ mysqlnd_zend_mm_pefree,
+ mysqlnd_zend_mm_malloc,
+ mysqlnd_zend_mm_calloc,
+ mysqlnd_zend_mm_realloc,
+ mysqlnd_zend_mm_free,
+ mysqlnd_zend_mm_pestrndup,
+ mysqlnd_zend_mm_pestrdup
+ sprintf,
+ mysqlnd_zend_mm_efree,
+#endif
+};
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_alloc.h b/ext/mysqlnd/mysqlnd_alloc.h
new file mode 100644
index 0000000000..673d4f6dae
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_alloc.h
@@ -0,0 +1,100 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
+/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
+
+#ifndef MYSQLND_ALLOC_H
+#define MYSQLND_ALLOC_H
+
+extern const char * mysqlnd_debug_std_no_trace_funcs[];
+
+#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
+#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
+
+struct st_mysqlnd_allocator_methods
+{
+ void * (*m_emalloc)(size_t size MYSQLND_MEM_D);
+ void * (*m_pemalloc)(size_t size, zend_bool persistent MYSQLND_MEM_D);
+ void * (*m_ecalloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+ void * (*m_pecalloc)(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
+ void * (*m_erealloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
+ void * (*m_perealloc)(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
+ void (*m_efree)(void *ptr MYSQLND_MEM_D);
+ void (*m_pefree)(void *ptr, zend_bool persistent MYSQLND_MEM_D);
+ void * (*m_malloc)(size_t size MYSQLND_MEM_D);
+ void * (*m_calloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+ void * (*m_realloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
+ void (*m_free)(void *ptr MYSQLND_MEM_D);
+ char * (*m_pestrndup)(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
+ char * (*m_pestrdup)(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
+ int (*m_sprintf)(char **pbuf, size_t max_len, const char *format, ...);
+ int (*m_vsprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
+ void (*m_sprintf_free)(char * p);
+};
+
+PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator;
+
+PHPAPI void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
+PHPAPI void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
+PHPAPI void _mysqlnd_free(void *ptr MYSQLND_MEM_D);
+PHPAPI char * _mysqlnd_pestrndup(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI int _mysqlnd_sprintf(char **pbuf, size_t max_len, const char *format, ...);
+PHPAPI void _mysqlnd_sprintf_free(char * p);
+PHPAPI int _mysqlnd_vsprintf(char **pbuf, size_t max_len, const char *format, va_list ap);
+
+#define mnd_emalloc(size) mysqlnd_allocator.m_emalloc((size) MYSQLND_MEM_C)
+#define mnd_pemalloc(size, pers) mysqlnd_allocator.m_pemalloc((size), (pers) MYSQLND_MEM_C)
+#define mnd_ecalloc(nmemb, size) mysqlnd_allocator.m_ecalloc((nmemb), (size) MYSQLND_MEM_C)
+#define mnd_pecalloc(nmemb, size, p) mysqlnd_allocator.m_pecalloc((nmemb), (size), (p) MYSQLND_MEM_C)
+#define mnd_erealloc(ptr, new_size) mysqlnd_allocator.m_erealloc((ptr), (new_size) MYSQLND_MEM_C)
+#define mnd_perealloc(ptr, new_size, p) mysqlnd_allocator.m_perealloc((ptr), (new_size), (p) MYSQLND_MEM_C)
+#define mnd_efree(ptr) mysqlnd_allocator.m_efree((ptr) MYSQLND_MEM_C)
+#define mnd_pefree(ptr, pers) mysqlnd_allocator.m_pefree((ptr), (pers) MYSQLND_MEM_C)
+#define mnd_malloc(size) mysqlnd_allocator.m_malloc((size) MYSQLND_MEM_C)
+#define mnd_calloc(nmemb, size) mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C)
+#define mnd_realloc(ptr, new_size) mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C)
+#define mnd_free(ptr) mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C)
+#define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C)
+#define mnd_pestrdup(ptr, pers) mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C)
+#define mnd_sprintf(p, mx_len, fmt,...) mysqlnd_allocator.m_sprintf((p), (mx_len), (fmt), __VA_ARGS__)
+#define mnd_vsprintf(p, mx_len, fmt,ap) mysqlnd_allocator.m_vsprintf((p), (mx_len), (fmt), (ap))
+#define mnd_sprintf_free(p) mysqlnd_allocator.m_sprintf_free((p))
+
+#endif /* MYSQLND_ALLOC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
new file mode 100644
index 0000000000..10c932a968
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -0,0 +1,477 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 307377 2011-01-11 13:02:57Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_structs.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_result.h"
+#include "mysqlnd_charset.h"
+#include "mysqlnd_debug.h"
+
+
+/* {{{ mysqlnd_auth_handshake */
+enum_func_status
+mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_OPTIONS * const options,
+ unsigned long mysql_flags,
+ unsigned int server_charset_no,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ const zend_uchar * const auth_plugin_data,
+ const size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ const MYSQLND_CHARSET * charset = NULL;
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * change_auth_resp_packet = NULL;
+ MYSQLND_PACKET_AUTH_RESPONSE * auth_resp_packet = NULL;
+ MYSQLND_PACKET_AUTH * auth_packet = NULL;
+
+ DBG_ENTER("mysqlnd_auth_handshake");
+
+ auth_resp_packet = conn->protocol->m.get_auth_response_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ if (!auth_resp_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ if (use_full_blown_auth_packet != TRUE) {
+ change_auth_resp_packet = conn->protocol->m.get_change_auth_response_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!change_auth_resp_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ change_auth_resp_packet->auth_data = auth_plugin_data;
+ change_auth_resp_packet->auth_data_len = auth_plugin_data_len;
+
+ if (!PACKET_WRITE(change_auth_resp_packet, conn)) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
+ }
+ } else {
+ auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ auth_packet->client_flags = mysql_flags;
+ auth_packet->max_packet_size = options->max_allowed_packet;
+ if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
+ auth_packet->charset_no = charset->nr;
+ } else {
+#if MYSQLND_UNICODE
+ auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
+#else
+ auth_packet->charset_no = server_charset_no;
+#endif
+ }
+
+ auth_packet->send_auth_data = TRUE;
+ auth_packet->user = user;
+ auth_packet->db = db;
+ auth_packet->db_len = db_len;
+
+ auth_packet->auth_data = auth_plugin_data;
+ auth_packet->auth_data_len = auth_plugin_data_len;
+ auth_packet->auth_plugin_name = auth_protocol;
+
+ if (!PACKET_WRITE(auth_packet, conn)) {
+ goto end;
+ }
+ }
+ if (use_full_blown_auth_packet == TRUE) {
+ conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
+ }
+
+ if (FAIL == PACKET_READ(auth_resp_packet, conn) || auth_resp_packet->response_code >= 0xFE) {
+ if (auth_resp_packet->response_code == 0xFE) {
+ /* old authentication with new server !*/
+ if (!auth_resp_packet->new_auth_protocol) {
+ DBG_ERR(mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ } else {
+ *switch_to_auth_protocol = mnd_pestrndup(auth_resp_packet->new_auth_protocol, auth_resp_packet->new_auth_protocol_len, FALSE);
+ *switch_to_auth_protocol_len = auth_resp_packet->new_auth_protocol_len;
+ if (auth_resp_packet->new_auth_protocol_data) {
+ *switch_to_auth_protocol_data_len = auth_resp_packet->new_auth_protocol_data_len;
+ *switch_to_auth_protocol_data = mnd_emalloc(*switch_to_auth_protocol_data_len);
+ memcpy(*switch_to_auth_protocol_data, auth_resp_packet->new_auth_protocol_data, *switch_to_auth_protocol_data_len);
+ } else {
+ *switch_to_auth_protocol_data = NULL;
+ *switch_to_auth_protocol_data_len = 0;
+ }
+ }
+ } else if (auth_resp_packet->response_code == 0xFF) {
+ if (auth_resp_packet->sqlstate[0]) {
+ strlcpy(conn->error_info->sqlstate, auth_resp_packet->sqlstate, sizeof(conn->error_info->sqlstate));
+ DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", auth_resp_packet->error_no, auth_resp_packet->sqlstate, auth_resp_packet->error);
+ }
+ SET_CLIENT_ERROR(*conn->error_info, auth_resp_packet->error_no, UNKNOWN_SQLSTATE, auth_resp_packet->error);
+ }
+ goto end;
+ }
+
+ SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, auth_resp_packet->message, auth_resp_packet->message_len, conn->persistent);
+ ret = PASS;
+end:
+ PACKET_FREE(change_auth_resp_packet);
+ PACKET_FREE(auth_packet);
+ PACKET_FREE(auth_resp_packet);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_auth_change_user */
+enum_func_status
+mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
+ const char * const user,
+ const size_t user_len,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const zend_bool silent,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ zend_uchar * auth_plugin_data,
+ size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ const MYSQLND_CHARSET * old_cs = conn->charset;
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * change_auth_resp_packet = NULL;
+ MYSQLND_PACKET_CHG_USER_RESPONSE * chg_user_resp = NULL;
+ MYSQLND_PACKET_AUTH * auth_packet = NULL;
+
+ DBG_ENTER("mysqlnd_auth_change_user");
+
+ chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ if (!chg_user_resp) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ if (use_full_blown_auth_packet != TRUE) {
+ change_auth_resp_packet = conn->protocol->m.get_change_auth_response_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!change_auth_resp_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ change_auth_resp_packet->auth_data = auth_plugin_data;
+ change_auth_resp_packet->auth_data_len = auth_plugin_data_len;
+
+ if (!PACKET_WRITE(change_auth_resp_packet, conn)) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
+ }
+ } else {
+ auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ if (!auth_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ auth_packet->is_change_user_packet = TRUE;
+ auth_packet->user = user;
+ auth_packet->db = db;
+ auth_packet->db_len = db_len;
+ auth_packet->silent = silent;
+
+ auth_packet->auth_data = auth_plugin_data;
+ auth_packet->auth_data_len = auth_plugin_data_len;
+ auth_packet->auth_plugin_name = auth_protocol;
+
+
+ if (conn->m->get_server_version(conn TSRMLS_CC) >= 50123) {
+ auth_packet->charset_no = conn->charset->nr;
+ }
+
+ if (!PACKET_WRITE(auth_packet, conn)) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
+ }
+ }
+
+ ret = PACKET_READ(chg_user_resp, conn);
+ COPY_CLIENT_ERROR(*conn->error_info, chg_user_resp->error_info);
+
+ if (0xFE == chg_user_resp->response_code) {
+ ret = FAIL;
+ if (!chg_user_resp->new_auth_protocol) {
+ DBG_ERR(mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ } else {
+ *switch_to_auth_protocol = mnd_pestrndup(chg_user_resp->new_auth_protocol, chg_user_resp->new_auth_protocol_len, FALSE);
+ *switch_to_auth_protocol_len = chg_user_resp->new_auth_protocol_len;
+ if (chg_user_resp->new_auth_protocol_data) {
+ *switch_to_auth_protocol_data_len = chg_user_resp->new_auth_protocol_data_len;
+ *switch_to_auth_protocol_data = mnd_emalloc(*switch_to_auth_protocol_data_len);
+ memcpy(*switch_to_auth_protocol_data, chg_user_resp->new_auth_protocol_data, *switch_to_auth_protocol_data_len);
+ } else {
+ *switch_to_auth_protocol_data = NULL;
+ *switch_to_auth_protocol_data_len = 0;
+ }
+ }
+ }
+
+ if (conn->error_info->error_no) {
+ ret = FAIL;
+ /*
+ COM_CHANGE_USER is broken in 5.1. At least in 5.1.15 and 5.1.14, 5.1.11 is immune.
+ bug#25371 mysql_change_user() triggers "packets out of sync"
+ When it gets fixed, there should be one more check here
+ */
+ if (conn->m->get_server_version(conn TSRMLS_CC) > 50113L &&conn->m->get_server_version(conn TSRMLS_CC) < 50118L) {
+ MYSQLND_PACKET_OK * redundant_error_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (redundant_error_packet) {
+ PACKET_READ(redundant_error_packet, conn);
+ PACKET_FREE(redundant_error_packet);
+ DBG_INF_FMT("Server is %u, buggy, sends two ERR messages", conn->m->get_server_version(conn TSRMLS_CC));
+ } else {
+ SET_OOM_ERROR(*conn->error_info);
+ }
+ }
+ }
+ if (ret == PASS) {
+ char * tmp = NULL;
+ /* if we get conn->user as parameter and then we first free it, then estrndup it, we will crash */
+ tmp = mnd_pestrndup(user, user_len, conn->persistent);
+ if (conn->user) {
+ mnd_pefree(conn->user, conn->persistent);
+ }
+ conn->user = tmp;
+
+ tmp = mnd_pestrdup(passwd, conn->persistent);
+ if (conn->passwd) {
+ mnd_pefree(conn->passwd, conn->persistent);
+ }
+ conn->passwd = tmp;
+
+ if (conn->last_message) {
+ mnd_pefree(conn->last_message, conn->persistent);
+ conn->last_message = NULL;
+ }
+ memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ /* set charset for old servers */
+ if (conn->m->get_server_version(conn TSRMLS_CC) < 50123) {
+ ret = conn->m->set_charset(conn, old_cs->name TSRMLS_CC);
+ }
+ } else if (ret == FAIL && chg_user_resp->server_asked_323_auth == TRUE) {
+ /* old authentication with new server !*/
+ DBG_ERR(mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ }
+end:
+ PACKET_FREE(change_auth_resp_packet);
+ PACKET_FREE(auth_packet);
+ PACKET_FREE(chg_user_resp);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/******************************************* MySQL Native Password ***********************************/
+
+#include "ext/standard/sha1.h"
+
+/* {{{ php_mysqlnd_crypt */
+static void
+php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
+{
+ const zend_uchar *s1_end = s1 + len;
+ while (s1 < s1_end) {
+ *buffer++= *s1++ ^ *s2++;
+ }
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_scramble */
+void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password, size_t password_len)
+{
+ PHP_SHA1_CTX context;
+ zend_uchar sha1[SHA1_MAX_LENGTH];
+ zend_uchar sha2[SHA1_MAX_LENGTH];
+
+ /* Phase 1: hash password */
+ PHP_SHA1Init(&context);
+ PHP_SHA1Update(&context, password, password_len);
+ PHP_SHA1Final(sha1, &context);
+
+ /* Phase 2: hash sha1 */
+ PHP_SHA1Init(&context);
+ PHP_SHA1Update(&context, (zend_uchar*)sha1, SHA1_MAX_LENGTH);
+ PHP_SHA1Final(sha2, &context);
+
+ /* Phase 3: hash scramble + sha2 */
+ PHP_SHA1Init(&context);
+ PHP_SHA1Update(&context, scramble, SCRAMBLE_LENGTH);
+ PHP_SHA1Update(&context, (zend_uchar*)sha2, SHA1_MAX_LENGTH);
+ PHP_SHA1Final(buffer, &context);
+
+ /* let's crypt buffer now */
+ php_mysqlnd_crypt(buffer, (const zend_uchar *)buffer, (const zend_uchar *)sha1, SHA1_MAX_LENGTH);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_native_auth_get_auth_data */
+static zend_uchar *
+mysqlnd_native_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
+ size_t * auth_data_len,
+ MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
+ const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
+ const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
+ TSRMLS_DC)
+{
+ zend_uchar * ret = NULL;
+ DBG_ENTER("mysqlnd_native_auth_get_auth_data");
+ *auth_data_len = 0;
+
+ /* 5.5.x reports 21 as scramble length because it needs to show the length of the data before the plugin name */
+ if (auth_plugin_data_len < SCRAMBLE_LENGTH) {
+ /* mysql_native_password only works with SCRAMBLE_LENGTH scramble */
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
+ DBG_ERR_FMT("The server sent wrong length for scramble %u. Expected %u", auth_plugin_data_len, SCRAMBLE_LENGTH);
+ DBG_RETURN(NULL);
+ }
+
+ /* copy scrambled pass*/
+ if (passwd && passwd_len) {
+ ret = malloc(SCRAMBLE_LENGTH);
+ *auth_data_len = SCRAMBLE_LENGTH;
+ /* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
+ php_mysqlnd_scramble((zend_uchar*)ret, auth_plugin_data, (zend_uchar*)passwd, passwd_len);
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+static struct st_mysqlnd_authentication_plugin mysqlnd_native_auth_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "auth_plugin_mysql_native_password",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ },
+ {/* methods */
+ mysqlnd_native_auth_get_auth_data
+ }
+};
+
+
+/******************************************* PAM Authentication ***********************************/
+
+/* {{{ mysqlnd_pam_auth_get_auth_data */
+static zend_uchar *
+mysqlnd_pam_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
+ size_t * auth_data_len,
+ MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
+ const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
+ const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
+ TSRMLS_DC)
+{
+ zend_uchar * ret = NULL;
+
+ /* copy pass*/
+ if (passwd && passwd_len) {
+ ret = (zend_uchar*) zend_strndup(passwd, passwd_len);
+ }
+ *auth_data_len = passwd_len;
+
+ return ret;
+}
+/* }}} */
+
+
+static struct st_mysqlnd_authentication_plugin mysqlnd_pam_authentication_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "auth_plugin_mysql_clear_password",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ },
+ {/* methods */
+ mysqlnd_pam_auth_get_auth_data
+ }
+};
+
+
+/* {{{ mysqlnd_register_builtin_authentication_plugins */
+void
+mysqlnd_register_builtin_authentication_plugins(TSRMLS_D)
+{
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_native_auth_plugin TSRMLS_CC);
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_pam_authentication_plugin TSRMLS_CC);
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_bt.c b/ext/mysqlnd/mysqlnd_bt.c
new file mode 100644
index 0000000000..937518405a
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_bt.c
@@ -0,0 +1,484 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
+
+#include "php.h"
+#include "Zend/zend_builtin_functions.h"
+
+/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
+
+#if MYSQLND_UNICODE
+/* {{{ gettraceasstring() macros */
+#define TRACE_APPEND_CHR(chr) \
+ *str = (char*)erealloc(*str, *len + 1 + 1); \
+ (*str)[(*len)++] = chr
+
+#define TRACE_APPEND_STRL(val, vallen) \
+ { \
+ int l = vallen; \
+ *str = (char*)erealloc(*str, *len + l + 1); \
+ memcpy((*str) + *len, val, l); \
+ *len += l; \
+ }
+
+#define TRACE_APPEND_USTRL(val, vallen) \
+ { \
+ zval tmp, copy; \
+ int use_copy; \
+ ZVAL_UNICODEL(&tmp, val, vallen, 1); \
+ zend_make_printable_zval(&tmp, &copy, &use_copy); \
+ TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+ zval_dtor(&copy); \
+ zval_dtor(&tmp); \
+ }
+
+#define TRACE_APPEND_ZVAL(zv) \
+ if (Z_TYPE_P((zv)) == IS_UNICODE) { \
+ zval copy; \
+ int use_copy; \
+ zend_make_printable_zval((zv), &copy, &use_copy); \
+ TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+ zval_dtor(&copy); \
+ } else { \
+ TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
+ }
+
+#define TRACE_APPEND_STR(val) \
+ TRACE_APPEND_STRL(val, sizeof(val)-1)
+
+#define TRACE_APPEND_KEY(key) \
+ if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
+ if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
+ zval copy; \
+ int use_copy; \
+ zend_make_printable_zval(*tmp, &copy, &use_copy); \
+ TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+ zval_dtor(&copy); \
+ } else { \
+ TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
+ } \
+ }
+/* }}} */
+
+
+/* {{{ mysqlnd_build_trace_args */
+static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+{
+ char **str;
+ int *len;
+
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+
+ /* the trivial way would be to do:
+ * conver_to_string_ex(arg);
+ * append it and kill the now tmp arg.
+ * but that could cause some E_NOTICE and also damn long lines.
+ */
+
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ TRACE_APPEND_STR("NULL, ");
+ break;
+ case IS_STRING: {
+ int l_added;
+ TRACE_APPEND_CHR('\'');
+ if (Z_STRLEN_PP(arg) > 15) {
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
+ TRACE_APPEND_STR("...', ");
+ l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+ } else {
+ l_added = Z_STRLEN_PP(arg);
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
+ TRACE_APPEND_STR("', ");
+ l_added += 3 + 1;
+ }
+ while (--l_added) {
+ if ((unsigned char)(*str)[*len - l_added] < 32) {
+ (*str)[*len - l_added] = '?';
+ }
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ int l_added;
+
+ /*
+ * We do not want to apply current error mode here, since
+ * zend_make_printable_zval() uses output encoding converter.
+ * Temporarily set output encoding converter to escape offending
+ * chars with \uXXXX notation.
+ */
+ zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
+ TRACE_APPEND_CHR('\'');
+ if (Z_USTRLEN_PP(arg) > 15) {
+ TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
+ TRACE_APPEND_STR("...', ");
+ l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+ } else {
+ l_added = Z_USTRLEN_PP(arg);
+ TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
+ TRACE_APPEND_STR("', ");
+ l_added += 3 + 1;
+ }
+ /*
+ * Reset output encoding converter error mode.
+ */
+ zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
+ while (--l_added) {
+ if ((unsigned char)(*str)[*len - l_added] < 32) {
+ (*str)[*len - l_added] = '?';
+ }
+ }
+ break;
+ }
+ case IS_BOOL:
+ if (Z_LVAL_PP(arg)) {
+ TRACE_APPEND_STR("true, ");
+ } else {
+ TRACE_APPEND_STR("false, ");
+ }
+ break;
+ case IS_RESOURCE:
+ TRACE_APPEND_STR("Resource id #");
+ /* break; */
+ case IS_LONG: {
+ long lval = Z_LVAL_PP(arg);
+ char s_tmp[MAX_LENGTH_OF_LONG + 1];
+ int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_DOUBLE: {
+ double dval = Z_DVAL_PP(arg);
+ char *s_tmp;
+ int l_tmp;
+
+ s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
+ l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ /* %G already handles removing trailing zeros from the fractional part, yay */
+ efree(s_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_ARRAY:
+ TRACE_APPEND_STR("Array, ");
+ break;
+ case IS_OBJECT: {
+ zval tmp;
+ zstr class_name;
+ zend_uint class_name_len;
+ int dup;
+
+ TRACE_APPEND_STR("Object(");
+
+ dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
+
+ ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
+ convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
+ TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
+ zval_dtor(&tmp);
+
+ if(!dup) {
+ efree(class_name.v);
+ }
+
+ TRACE_APPEND_STR("), ");
+ break;
+ }
+ default:
+ break;
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ char *s_tmp, **str;
+ int *len, *num;
+ long line;
+ HashTable *ht = Z_ARRVAL_PP(frame);
+ zval **file, **tmp;
+ uint * level;
+
+ level = va_arg(args, uint *);
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+ num = va_arg(args, int*);
+
+ if (!*level) {
+ return ZEND_HASH_APPLY_KEEP;
+ }
+ --*level;
+
+ s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
+ sprintf(s_tmp, "#%d ", (*num)++);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
+ if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
+ line = Z_LVAL_PP(tmp);
+ } else {
+ line = 0;
+ }
+ TRACE_APPEND_ZVAL(*file);
+ s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
+ sprintf(s_tmp, "(%ld): ", line);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ } else {
+ TRACE_APPEND_STR("[internal function]: ");
+ }
+ TRACE_APPEND_KEY("class");
+ TRACE_APPEND_KEY("type");
+ TRACE_APPEND_KEY("function");
+ TRACE_APPEND_CHR('(');
+ if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
+ int last_len = *len;
+ zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
+ if (last_len != *len) {
+ *len -= 2; /* remove last ', ' */
+ }
+ }
+ TRACE_APPEND_STR(")\n");
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+#else /* PHP 5*/
+
+
+/* {{{ gettraceasstring() macros */
+#define TRACE_APPEND_CHR(chr) \
+ *str = (char*)erealloc(*str, *len + 1 + 1); \
+ (*str)[(*len)++] = chr
+
+#define TRACE_APPEND_STRL(val, vallen) \
+ { \
+ int l = vallen; \
+ *str = (char*)erealloc(*str, *len + l + 1); \
+ memcpy((*str) + *len, val, l); \
+ *len += l; \
+ }
+
+#define TRACE_APPEND_STR(val) \
+ TRACE_APPEND_STRL(val, sizeof(val)-1)
+
+#define TRACE_APPEND_KEY(key) \
+ if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
+ TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
+ }
+
+/* }}} */
+
+
+static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ char **str;
+ int *len;
+
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+
+ /* the trivial way would be to do:
+ * conver_to_string_ex(arg);
+ * append it and kill the now tmp arg.
+ * but that could cause some E_NOTICE and also damn long lines.
+ */
+
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ TRACE_APPEND_STR("NULL, ");
+ break;
+ case IS_STRING: {
+ int l_added;
+ TRACE_APPEND_CHR('\'');
+ if (Z_STRLEN_PP(arg) > 15) {
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
+ TRACE_APPEND_STR("...', ");
+ l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+ } else {
+ l_added = Z_STRLEN_PP(arg);
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
+ TRACE_APPEND_STR("', ");
+ l_added += 3 + 1;
+ }
+ while (--l_added) {
+ if ((*str)[*len - l_added] < 32) {
+ (*str)[*len - l_added] = '?';
+ }
+ }
+ break;
+ }
+ case IS_BOOL:
+ if (Z_LVAL_PP(arg)) {
+ TRACE_APPEND_STR("true, ");
+ } else {
+ TRACE_APPEND_STR("false, ");
+ }
+ break;
+ case IS_RESOURCE:
+ TRACE_APPEND_STR("Resource id #");
+ /* break; */
+ case IS_LONG: {
+ long lval = Z_LVAL_PP(arg);
+ char s_tmp[MAX_LENGTH_OF_LONG + 1];
+ int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_DOUBLE: {
+ double dval = Z_DVAL_PP(arg);
+ char *s_tmp;
+ int l_tmp;
+
+ s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
+ l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ /* %G already handles removing trailing zeros from the fractional part, yay */
+ efree(s_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_ARRAY:
+ TRACE_APPEND_STR("Array, ");
+ break;
+ case IS_OBJECT: {
+ char *class_name;
+ zend_uint class_name_len;
+ int dupl;
+
+ TRACE_APPEND_STR("Object(");
+
+ dupl = zend_get_object_classname(*arg, (const char **)&class_name, &class_name_len TSRMLS_CC);
+
+ TRACE_APPEND_STRL(class_name, class_name_len);
+ if (!dupl) {
+ efree(class_name);
+ }
+
+ TRACE_APPEND_STR("), ");
+ break;
+ }
+ default:
+ break;
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ char *s_tmp, **str;
+ int *len, *num;
+ long line;
+ HashTable *ht = Z_ARRVAL_PP(frame);
+ zval **file, **tmp;
+ uint * level;
+
+ level = va_arg(args, uint *);
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+ num = va_arg(args, int*);
+
+ if (!*level) {
+ return ZEND_HASH_APPLY_KEEP;
+ }
+ --*level;
+
+ s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
+ sprintf(s_tmp, "#%d ", (*num)++);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
+ if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
+ line = Z_LVAL_PP(tmp);
+ } else {
+ line = 0;
+ }
+ s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
+ sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ } else {
+ TRACE_APPEND_STR("[internal function]: ");
+ }
+ TRACE_APPEND_KEY("class");
+ TRACE_APPEND_KEY("type");
+ TRACE_APPEND_KEY("function");
+ TRACE_APPEND_CHR('(');
+ if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
+ int last_len = *len;
+ zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
+ if (last_len != *len) {
+ *len -= 2; /* remove last ', ' */
+ }
+ }
+ TRACE_APPEND_STR(")\n");
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+#endif
+
+
+PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
+{
+ zval *trace;
+ char *res = estrdup(""), **str = &res, *s_tmp;
+ int res_len = 0, *len = &res_len, num = 0;
+ if (max_levels == 0) {
+ max_levels = 99999;
+ }
+
+ MAKE_STD_ZVAL(trace);
+ zend_fetch_debug_backtrace(trace, 0, 0, 0 TSRMLS_CC);
+
+ zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);
+ zval_ptr_dtor(&trace);
+
+ if (max_levels) {
+ s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
+ sprintf(s_tmp, "#%d {main}", num);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ }
+
+ res[res_len] = '\0';
+ *length = res_len;
+
+ return res;
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_charset.c b/ext/mysqlnd/mysqlnd_charset.c
index 704c119026..25b9877078 100644
--- a/ext/mysqlnd/mysqlnd_charset.c
+++ b/ext/mysqlnd/mysqlnd_charset.c
@@ -22,6 +22,7 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_charset.h"
/* {{{ utf8 functions */
static unsigned int check_mb_utf8mb3_sequence(const char *start, const char *end)
@@ -325,7 +326,7 @@ static unsigned int mysqlnd_mbcharlen_gbk(unsigned int gbk)
/* }}} */
-/* {{{ functions */
+/* {{{ sjis functions */
#define valid_sjis_head(c) ((0x81 <= (c) && (c) <= 0x9F) || (0xE0 <= (c) && (c) <= 0xFC))
#define valid_sjis_tail(c) ((0x40 <= (c) && (c) <= 0x7E) || (0x80 <= (c) && (c) <= 0xFC))
@@ -490,8 +491,8 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 42, "latin7", "latin7_general_cs", 1, 1, "", NULL, NULL},
{ 43, "macce", "macce_bin", 1, 1, "", NULL, NULL},
{ 44, "cp1250", "cp1250_croatian_ci", 1, 1, "", NULL, NULL},
- { 45, UTF8_MB4, UTF8_MB4"_general_ci", 1, 3, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
- { 46, UTF8_MB4, UTF8_MB4"_bin", 1, 3, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
+ { 45, UTF8_MB4, UTF8_MB4"_general_ci", 1, 4, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
+ { 46, UTF8_MB4, UTF8_MB4"_bin", 1, 4, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 47, "latin1", "latin1_bin", 1, 1, "", NULL, NULL},
{ 48, "latin1", "latin1_general_ci", 1, 1, "", NULL, NULL},
{ 49, "latin1", "latin1_general_cs", 1, 1, "", NULL, NULL},
@@ -668,7 +669,7 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_nr(unsigned int charsetnr)
/* {{{ mysqlnd_find_charset_name */
PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const name)
{
- const MYSQLND_CHARSET *c = mysqlnd_charsets;
+ const MYSQLND_CHARSET * c = mysqlnd_charsets;
do {
if (!strcasecmp(c->name, name)) {
@@ -814,6 +815,42 @@ PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, cha
}
/* }}} */
+
+static struct st_mysqlnd_plugin_charsets mysqlnd_plugin_charsets_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "charsets",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ },
+ {/* methods */
+ mysqlnd_find_charset_nr,
+ mysqlnd_find_charset_name,
+ mysqlnd_cset_escape_quotes,
+ mysqlnd_cset_escape_slashes
+ }
+};
+
+
+/* {{{ mysqlnd_charsets_plugin_register */
+void
+mysqlnd_charsets_plugin_register(TSRMLS_D)
+{
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_charsets_plugin TSRMLS_CC);
+}
+/* }}} */
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_charset.h b/ext/mysqlnd/mysqlnd_charset.h
index 2f5d1db278..418d5dd9b1 100644
--- a/ext/mysqlnd/mysqlnd_charset.h
+++ b/ext/mysqlnd/mysqlnd_charset.h
@@ -27,6 +27,20 @@ PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const charset, c
PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, char *newstr,
const char *escapestr, size_t escapestr_len TSRMLS_DC);
+struct st_mysqlnd_plugin_charsets
+{
+ const struct st_mysqlnd_plugin_header plugin_header;
+ struct
+ {
+ const MYSQLND_CHARSET * (*const find_charset_by_nr)(unsigned int charsetnr);
+ const MYSQLND_CHARSET * (*const find_charset_by_name)(const char * const name);
+ unsigned long (*const escape_quotes)(const MYSQLND_CHARSET * const cset, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC);
+ unsigned long (*const escape_slashes)(const MYSQLND_CHARSET * const cset, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC);
+ } methods;
+};
+
+void mysqlnd_charsets_plugin_register(TSRMLS_D);
+
#endif /* MYSQLND_CHARSET_H */
/*
diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c
index 66f6466f6a..044a7d6807 100644
--- a/ext/mysqlnd/mysqlnd_debug.c
+++ b/ext/mysqlnd/mysqlnd_debug.c
@@ -24,9 +24,6 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
-#include "mysqlnd_wireprotocol.h"
-#include "mysqlnd_statistics.h"
-#include "zend_builtin_functions.h"
static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
@@ -36,41 +33,6 @@ static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace
#define MYSQLND_ZTS(self)
#endif
-static const char mysqlnd_emalloc_name[] = "_mysqlnd_emalloc";
-static const char mysqlnd_pemalloc_name[] = "_mysqlnd_pemalloc";
-static const char mysqlnd_ecalloc_name[] = "_mysqlnd_ecalloc";
-static const char mysqlnd_pecalloc_name[] = "_mysqlnd_pecalloc";
-static const char mysqlnd_erealloc_name[] = "_mysqlnd_erealloc";
-static const char mysqlnd_perealloc_name[] = "_mysqlnd_perealloc";
-static const char mysqlnd_efree_name[] = "_mysqlnd_efree";
-static const char mysqlnd_pefree_name[] = "_mysqlnd_pefree";
-static const char mysqlnd_malloc_name[] = "_mysqlnd_malloc";
-static const char mysqlnd_calloc_name[] = "_mysqlnd_calloc";
-static const char mysqlnd_realloc_name[] = "_mysqlnd_realloc";
-static const char mysqlnd_free_name[] = "_mysqlnd_free";
-static const char mysqlnd_pestrndup_name[] = "_mysqlnd_pestrndup";
-static const char mysqlnd_pestrdup_name[] = "_mysqlnd_pestrdup";
-
-const char * mysqlnd_debug_std_no_trace_funcs[] =
-{
- mysqlnd_emalloc_name,
- mysqlnd_ecalloc_name,
- mysqlnd_efree_name,
- mysqlnd_erealloc_name,
- mysqlnd_pemalloc_name,
- mysqlnd_pecalloc_name,
- mysqlnd_pefree_name,
- mysqlnd_perealloc_name,
- mysqlnd_malloc_name,
- mysqlnd_calloc_name,
- mysqlnd_realloc_name,
- mysqlnd_free_name,
- mysqlnd_pestrndup_name,
- mysqlnd_read_header_name,
- mysqlnd_read_body_name,
- NULL /* must be always last */
-};
-
/* {{{ mysqlnd_debug::open */
static enum_func_status
@@ -167,7 +129,7 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
level_buffer[sizeof(level_buffer) - 1 ] = '\0';
}
- message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
+ message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
@@ -176,7 +138,7 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
pipe_buffer, type? type:"", message);
ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
- efree(message_line); /* allocated by spprintf */
+ mnd_sprintf_free(message_line);
if (flags & MYSQLND_DEBUG_FLUSH) {
self->m->close(self);
self->m->open(self, TRUE);
@@ -265,21 +227,20 @@ MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *self,
level_buffer[sizeof(level_buffer) - 1 ] = '\0';
}
-
va_start(args, format);
- vspprintf(&buffer, 0, format, args);
+ mnd_vsprintf(&buffer, 0, format, args);
va_end(args);
- message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
+ message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
pipe_buffer, type? type:"", buffer);
- efree(buffer);
+ mnd_sprintf_free(buffer);
ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
- efree(message_line); /* allocated by spprintf */
+ mnd_sprintf_free(message_line);
if (flags & MYSQLND_DEBUG_FLUSH) {
self->m->close(self);
@@ -538,7 +499,7 @@ MYSQLND_METHOD(mysqlnd_debug, free)(MYSQLND_DEBUG * self)
zend_stack_destroy(&self->call_time_stack);
zend_hash_destroy(&self->not_filtered_functions);
zend_hash_destroy(&self->function_profiles);
- efree(self);
+ free(self);
return PASS;
}
/* }}} */
@@ -555,9 +516,11 @@ enum mysqlnd_debug_parser_state
static void
MYSQLND_METHOD(mysqlnd_debug, set_mode)(MYSQLND_DEBUG * self, const char * const mode)
{
- unsigned int mode_len = strlen(mode), i;
+ unsigned int mode_len, i;
enum mysqlnd_debug_parser_state state = PARSER_WAIT_MODIFIER;
+ mode_len = mode? strlen(mode) : 0;
+
self->flags = 0;
self->nest_level_limit = 0;
if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
@@ -761,7 +724,7 @@ MYSQLND_CLASS_METHODS_END;
PHPAPI MYSQLND_DEBUG *
mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
{
- MYSQLND_DEBUG *ret = ecalloc(1, sizeof(MYSQLND_DEBUG));
+ MYSQLND_DEBUG *ret = calloc(1, sizeof(MYSQLND_DEBUG));
#ifdef ZTS
ret->TSRMLS_C = TSRMLS_C;
#endif
@@ -783,7 +746,7 @@ mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
/* {{{ _mysqlnd_debug */
PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
{
-#ifdef PHP_DEBUG
+#if PHP_DEBUG
MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);
if (!dbg) {
MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
@@ -805,1057 +768,39 @@ PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
/* }}} */
-#if ZEND_DEBUG
-#else
-#define __zend_filename "/unknown/unknown"
-#define __zend_lineno 0
-#endif
-
-#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
-#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
-#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
-
-/* {{{ _mysqlnd_emalloc */
-void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
- DBG_ENTER(mysqlnd_emalloc_name);
-
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = emalloc(REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pemalloc */
-void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
- DBG_ENTER(mysqlnd_pemalloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = pemalloc(REAL_SIZE(size), persistent);
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
-
- if (ret && collect_memory_statistics) {
- enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
- enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
- }
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_ecalloc */
-void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
- DBG_ENTER(mysqlnd_ecalloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = ecalloc(nmemb, REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pecalloc */
-void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
- DBG_ENTER(mysqlnd_pecalloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-
- if (ret && collect_memory_statistics) {
- enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
- enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
- }
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_erealloc */
-void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
- long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
- DBG_ENTER(mysqlnd_erealloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("new_ptr=%p", (char*)ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = new_size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_perealloc */
-void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
- long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
- DBG_ENTER(mysqlnd_perealloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("new_ptr=%p", (char*)ret);
-
- if (ret && collect_memory_statistics) {
- enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
- enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
- *(size_t *) ret = new_size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_efree */
-void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
-{
- size_t free_amount = 0;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_efree_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
-
- if (ptr) {
- if (collect_memory_statistics) {
- free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
- DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
- }
- efree(REAL_PTR(ptr));
- }
-
- if (collect_memory_statistics) {
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pefree */
-void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- size_t free_amount = 0;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_pefree_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
-
- if (ptr) {
- if (collect_memory_statistics) {
- free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
- DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
- }
- pefree(REAL_PTR(ptr), persistent);
- }
-
- if (collect_memory_statistics) {
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
- persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
- }
- DBG_VOID_RETURN;
-}
-
-
-/* {{{ _mysqlnd_malloc */
-void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
- DBG_ENTER(mysqlnd_malloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = malloc(REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_calloc */
-void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
- DBG_ENTER(mysqlnd_calloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = calloc(nmemb, REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_realloc */
-void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
- DBG_ENTER(mysqlnd_realloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
- DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("new_ptr=%p", (char*)ret);
-
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = new_size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_free */
-void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
-{
- size_t free_amount = 0;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_free_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
-
- if (ptr) {
- if (collect_memory_statistics) {
- free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
- DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
- }
- free(REAL_PTR(ptr));
- }
-
- if (collect_memory_statistics) {
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-#define SMART_STR_START_SIZE 2048
-#define SMART_STR_PREALLOC 512
-#include "ext/standard/php_smart_str.h"
-
-
-/* {{{ _mysqlnd_pestrndup */
-char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+static struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
{
- char * ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_pestrndup_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
-
- ret = pemalloc(REAL_SIZE(length) + 1, persistent);
{
- size_t l = length;
- char * p = (char *) ptr;
- char * dest = (char *) FAKE_PTR(ret);
- while (*p && l--) {
- *dest++ = *p++;
+ MYSQLND_PLUGIN_API_VERSION,
+ "debug_trace",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
}
- *dest = '\0';
- }
-
- if (collect_memory_statistics) {
- *(size_t *) ret = length;
- MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
- }
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pestrdup */
-char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- char * ret;
- smart_str tmp_str = {0, 0, 0};
- const char * p = ptr;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_pestrdup_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
- do {
- smart_str_appendc(&tmp_str, *p);
- } while (*p++);
-
- ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
- memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
-
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = tmp_str.len;
- MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
+ },
+ {/* methods */
+ mysqlnd_debug_init,
+ mysqlnd_get_backtrace
}
- smart_str_free(&tmp_str);
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-#define MYSQLND_DEBUG_MEMORY 1
-
-#if MYSQLND_DEBUG_MEMORY == 0
-
-/* {{{ mysqlnd_zend_mm_emalloc */
-static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
-{
- return emalloc(size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pemalloc */
-static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- return pemalloc(size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_ecalloc */
-static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- return ecalloc(nmemb, size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pecalloc */
-static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- return pecalloc(nmemb, size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_erealloc */
-static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
- return erealloc(ptr, new_size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_perealloc */
-static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
-{
- return perealloc(ptr, new_size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_efree */
-static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
-{
- efree(ptr);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pefree */
-static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- pefree(ptr, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_malloc */
-static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
-{
- return malloc(size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_calloc */
-static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- return calloc(nmemb, size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_realloc */
-static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
-{
- return realloc(ptr, new_size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_free */
-static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
-{
- free(ptr);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pestrndup */
-static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
-{
- return pestrndup(ptr, length, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pestrdup */
-static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- return pestrdup(ptr, persistent);
-}
-/* }}} */
-
-#endif
-
-
-PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator =
-{
-#if MYSQLND_DEBUG_MEMORY
- _mysqlnd_emalloc,
- _mysqlnd_pemalloc,
- _mysqlnd_ecalloc,
- _mysqlnd_pecalloc,
- _mysqlnd_erealloc,
- _mysqlnd_perealloc,
- _mysqlnd_efree,
- _mysqlnd_pefree,
- _mysqlnd_malloc,
- _mysqlnd_calloc,
- _mysqlnd_realloc,
- _mysqlnd_free,
- _mysqlnd_pestrndup,
- _mysqlnd_pestrdup
-#else
- mysqlnd_zend_mm_emalloc,
- mysqlnd_zend_mm_pemalloc,
- mysqlnd_zend_mm_ecalloc,
- mysqlnd_zend_mm_pecalloc,
- mysqlnd_zend_mm_erealloc,
- mysqlnd_zend_mm_perealloc,
- mysqlnd_zend_mm_efree,
- mysqlnd_zend_mm_pefree,
- mysqlnd_zend_mm_malloc,
- mysqlnd_zend_mm_calloc,
- mysqlnd_zend_mm_realloc,
- mysqlnd_zend_mm_free,
- mysqlnd_zend_mm_pestrndup,
- mysqlnd_zend_mm_pestrdup
-#endif
};
-
-/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
-
-#if MYSQLND_UNICODE
-/* {{{ gettraceasstring() macros */
-#define TRACE_APPEND_CHR(chr) \
- *str = (char*)erealloc(*str, *len + 1 + 1); \
- (*str)[(*len)++] = chr
-
-#define TRACE_APPEND_STRL(val, vallen) \
- { \
- int l = vallen; \
- *str = (char*)erealloc(*str, *len + l + 1); \
- memcpy((*str) + *len, val, l); \
- *len += l; \
- }
-
-#define TRACE_APPEND_USTRL(val, vallen) \
- { \
- zval tmp, copy; \
- int use_copy; \
- ZVAL_UNICODEL(&tmp, val, vallen, 1); \
- zend_make_printable_zval(&tmp, &copy, &use_copy); \
- TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
- zval_dtor(&copy); \
- zval_dtor(&tmp); \
- }
-
-#define TRACE_APPEND_ZVAL(zv) \
- if (Z_TYPE_P((zv)) == IS_UNICODE) { \
- zval copy; \
- int use_copy; \
- zend_make_printable_zval((zv), &copy, &use_copy); \
- TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
- zval_dtor(&copy); \
- } else { \
- TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
- }
-
-#define TRACE_APPEND_STR(val) \
- TRACE_APPEND_STRL(val, sizeof(val)-1)
-
-#define TRACE_APPEND_KEY(key) \
- if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
- if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
- zval copy; \
- int use_copy; \
- zend_make_printable_zval(*tmp, &copy, &use_copy); \
- TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
- zval_dtor(&copy); \
- } else { \
- TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
- } \
- }
-/* }}} */
-
-/* {{{ mysqlnd_build_trace_args */
-static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
-{
- char **str;
- int *len;
-
- str = va_arg(args, char**);
- len = va_arg(args, int*);
-
- /* the trivial way would be to do:
- * conver_to_string_ex(arg);
- * append it and kill the now tmp arg.
- * but that could cause some E_NOTICE and also damn long lines.
- */
-
- switch (Z_TYPE_PP(arg)) {
- case IS_NULL:
- TRACE_APPEND_STR("NULL, ");
- break;
- case IS_STRING: {
- int l_added;
- TRACE_APPEND_CHR('\'');
- if (Z_STRLEN_PP(arg) > 15) {
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
- } else {
- l_added = Z_STRLEN_PP(arg);
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- while (--l_added) {
- if ((unsigned char)(*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_UNICODE: {
- int l_added;
-
- /*
- * We do not want to apply current error mode here, since
- * zend_make_printable_zval() uses output encoding converter.
- * Temporarily set output encoding converter to escape offending
- * chars with \uXXXX notation.
- */
- zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
- TRACE_APPEND_CHR('\'');
- if (Z_USTRLEN_PP(arg) > 15) {
- TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
- } else {
- l_added = Z_USTRLEN_PP(arg);
- TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- /*
- * Reset output encoding converter error mode.
- */
- zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
- while (--l_added) {
- if ((unsigned char)(*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_BOOL:
- if (Z_LVAL_PP(arg)) {
- TRACE_APPEND_STR("true, ");
- } else {
- TRACE_APPEND_STR("false, ");
- }
- break;
- case IS_RESOURCE:
- TRACE_APPEND_STR("Resource id #");
- /* break; */
- case IS_LONG: {
- long lval = Z_LVAL_PP(arg);
- char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_DOUBLE: {
- double dval = Z_DVAL_PP(arg);
- char *s_tmp;
- int l_tmp;
-
- s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
- l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- /* %G already handles removing trailing zeros from the fractional part, yay */
- efree(s_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_ARRAY:
- TRACE_APPEND_STR("Array, ");
- break;
- case IS_OBJECT: {
- zval tmp;
- zstr class_name;
- zend_uint class_name_len;
- int dup;
-
- TRACE_APPEND_STR("Object(");
-
- dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
-
- ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
- convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
- TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
- zval_dtor(&tmp);
-
- if(!dup) {
- efree(class_name.v);
- }
-
- TRACE_APPEND_STR("), ");
- break;
- }
- default:
- break;
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-
-static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
-{
- char *s_tmp, **str;
- int *len, *num;
- long line;
- HashTable *ht = Z_ARRVAL_PP(frame);
- zval **file, **tmp;
- uint * level;
-
- level = va_arg(args, uint *);
- str = va_arg(args, char**);
- len = va_arg(args, int*);
- num = va_arg(args, int*);
-
- if (!*level) {
- return ZEND_HASH_APPLY_KEEP;
- }
- --*level;
-
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
- sprintf(s_tmp, "#%d ", (*num)++);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
- if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
- line = Z_LVAL_PP(tmp);
- } else {
- line = 0;
- }
- TRACE_APPEND_ZVAL(*file);
- s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
- sprintf(s_tmp, "(%ld): ", line);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- } else {
- TRACE_APPEND_STR("[internal function]: ");
- }
- TRACE_APPEND_KEY("class");
- TRACE_APPEND_KEY("type");
- TRACE_APPEND_KEY("function");
- TRACE_APPEND_CHR('(');
- if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
- int last_len = *len;
- zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
- if (last_len != *len) {
- *len -= 2; /* remove last ', ' */
- }
- }
- TRACE_APPEND_STR(")\n");
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-
-#else /* PHP 5*/
-
-
-/* {{{ gettraceasstring() macros */
-#define TRACE_APPEND_CHR(chr) \
- *str = (char*)erealloc(*str, *len + 1 + 1); \
- (*str)[(*len)++] = chr
-
-#define TRACE_APPEND_STRL(val, vallen) \
- { \
- int l = vallen; \
- *str = (char*)erealloc(*str, *len + l + 1); \
- memcpy((*str) + *len, val, l); \
- *len += l; \
- }
-
-#define TRACE_APPEND_STR(val) \
- TRACE_APPEND_STRL(val, sizeof(val)-1)
-
-#define TRACE_APPEND_KEY(key) \
- if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
- TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
- }
-
-/* }}} */
-
-
-static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
-{
- char **str;
- int *len;
-
- str = va_arg(args, char**);
- len = va_arg(args, int*);
-
- /* the trivial way would be to do:
- * conver_to_string_ex(arg);
- * append it and kill the now tmp arg.
- * but that could cause some E_NOTICE and also damn long lines.
- */
-
- switch (Z_TYPE_PP(arg)) {
- case IS_NULL:
- TRACE_APPEND_STR("NULL, ");
- break;
- case IS_STRING: {
- int l_added;
- TRACE_APPEND_CHR('\'');
- if (Z_STRLEN_PP(arg) > 15) {
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
- } else {
- l_added = Z_STRLEN_PP(arg);
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- while (--l_added) {
- if ((*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_BOOL:
- if (Z_LVAL_PP(arg)) {
- TRACE_APPEND_STR("true, ");
- } else {
- TRACE_APPEND_STR("false, ");
- }
- break;
- case IS_RESOURCE:
- TRACE_APPEND_STR("Resource id #");
- /* break; */
- case IS_LONG: {
- long lval = Z_LVAL_PP(arg);
- char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_DOUBLE: {
- double dval = Z_DVAL_PP(arg);
- char *s_tmp;
- int l_tmp;
-
- s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
- l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- /* %G already handles removing trailing zeros from the fractional part, yay */
- efree(s_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_ARRAY:
- TRACE_APPEND_STR("Array, ");
- break;
- case IS_OBJECT: {
- char *class_name;
- zend_uint class_name_len;
- int dupl;
-
- TRACE_APPEND_STR("Object(");
-
- dupl = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
-
- TRACE_APPEND_STRL(class_name, class_name_len);
- if (!dupl) {
- efree(class_name);
- }
-
- TRACE_APPEND_STR("), ");
- break;
- }
- default:
- break;
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+/* {{{ mysqlnd_debug_trace_plugin_register */
+void
+mysqlnd_debug_trace_plugin_register(TSRMLS_D)
{
- char *s_tmp, **str;
- int *len, *num;
- long line;
- HashTable *ht = Z_ARRVAL_PP(frame);
- zval **file, **tmp;
- uint * level;
-
- level = va_arg(args, uint *);
- str = va_arg(args, char**);
- len = va_arg(args, int*);
- num = va_arg(args, int*);
-
- if (!*level) {
- return ZEND_HASH_APPLY_KEEP;
- }
- --*level;
-
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
- sprintf(s_tmp, "#%d ", (*num)++);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
- if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
- line = Z_LVAL_PP(tmp);
- } else {
- line = 0;
- }
- s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
- sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- } else {
- TRACE_APPEND_STR("[internal function]: ");
- }
- TRACE_APPEND_KEY("class");
- TRACE_APPEND_KEY("type");
- TRACE_APPEND_KEY("function");
- TRACE_APPEND_CHR('(');
- if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
- int last_len = *len;
- zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
- if (last_len != *len) {
- *len -= 2; /* remove last ', ' */
- }
- }
- TRACE_APPEND_STR(")\n");
- return ZEND_HASH_APPLY_KEEP;
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_trace_log_plugin TSRMLS_CC);
}
/* }}} */
-#endif
-PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
-{
- zval *trace;
- char *res = estrdup(""), **str = &res, *s_tmp;
- int res_len = 0, *len = &res_len, num = 0;
- if (max_levels == 0) {
- max_levels = 99999;
- }
-
- MAKE_STD_ZVAL(trace);
- zend_fetch_debug_backtrace(trace, 0, 0 TSRMLS_CC);
-
- zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);
- zval_ptr_dtor(&trace);
-
- if (max_levels) {
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
- sprintf(s_tmp, "#%d {main}", num);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- }
-
- res[res_len] = '\0';
- *length = res_len;
-
- return res;
-}
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_debug.h b/ext/mysqlnd/mysqlnd_debug.h
index 01d9e8968a..d805178e26 100644
--- a/ext/mysqlnd/mysqlnd_debug.h
+++ b/ext/mysqlnd/mysqlnd_debug.h
@@ -23,6 +23,7 @@
#ifndef MYSQLND_DEBUG_H
#define MYSQLND_DEBUG_H
+#include "mysqlnd_alloc.h"
#include "zend_stack.h"
struct st_mysqlnd_debug_methods
@@ -59,11 +60,21 @@ struct st_mysqlnd_debug
const char ** skip_functions;
};
-PHPAPI extern const char * mysqlnd_debug_std_no_trace_funcs[];
+struct st_mysqlnd_plugin_trace_log
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+ struct
+ {
+ MYSQLND_DEBUG * (*trace_instance_init)(const char * skip_functions[] TSRMLS_DC);
+ char * (*get_backtrace)(uint max_levels, size_t * length TSRMLS_DC);
+ } methods;
+};
+
+void mysqlnd_debug_trace_plugin_register(TSRMLS_D);
PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC);
-PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
+PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
#if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400))
#ifdef PHP_WIN32
@@ -141,7 +152,7 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func
#define DBG_VOID_RETURN_EX(dbg_obj) return
#define DBG_BLOCK_LEAVE_EX(dbg_obj) }
-#endif /* defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400)) */
+#endif
#if MYSQLND_DBG_ENABLED == 1
@@ -158,8 +169,6 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func
#elif MYSQLND_DBG_ENABLED == 0
-
-
static inline void DBG_INF(const char * const msg) {}
static inline void DBG_ERR(const char * const msg) {}
static inline void DBG_INF_FMT(const char * const format, ...) {}
@@ -172,62 +181,6 @@ static inline void DBG_ENTER(const char * const func_name) {}
#endif
-
-#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
-#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
-
-struct st_mysqlnd_allocator_methods
-{
- void * (*m_emalloc)(size_t size MYSQLND_MEM_D);
- void * (*m_pemalloc)(size_t size, zend_bool persistent MYSQLND_MEM_D);
- void * (*m_ecalloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
- void * (*m_pecalloc)(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
- void * (*m_erealloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
- void * (*m_perealloc)(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
- void (*m_efree)(void *ptr MYSQLND_MEM_D);
- void (*m_pefree)(void *ptr, zend_bool persistent MYSQLND_MEM_D);
- void * (*m_malloc)(size_t size MYSQLND_MEM_D);
- void * (*m_calloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
- void * (*m_realloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
- void (*m_free)(void *ptr MYSQLND_MEM_D);
- char * (*m_pestrndup)(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
- char * (*m_pestrdup)(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
-};
-
-PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator;
-
-
-PHPAPI void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
-PHPAPI void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
-PHPAPI void _mysqlnd_free(void *ptr MYSQLND_MEM_D);
-PHPAPI char * _mysqlnd_pestrndup(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
-
-
-#define mnd_emalloc(size) mysqlnd_allocator.m_emalloc((size) MYSQLND_MEM_C)
-#define mnd_pemalloc(size, pers) mysqlnd_allocator.m_pemalloc((size), (pers) MYSQLND_MEM_C)
-#define mnd_ecalloc(nmemb, size) mysqlnd_allocator.m_ecalloc((nmemb), (size) MYSQLND_MEM_C)
-#define mnd_pecalloc(nmemb, size, p) mysqlnd_allocator.m_pecalloc((nmemb), (size), (p) MYSQLND_MEM_C)
-#define mnd_erealloc(ptr, new_size) mysqlnd_allocator.m_erealloc((ptr), (new_size) MYSQLND_MEM_C)
-#define mnd_perealloc(ptr, new_size, p) mysqlnd_allocator.m_perealloc((ptr), (new_size), (p) MYSQLND_MEM_C)
-#define mnd_efree(ptr) mysqlnd_allocator.m_efree((ptr) MYSQLND_MEM_C)
-#define mnd_pefree(ptr, pers) mysqlnd_allocator.m_pefree((ptr), (pers) MYSQLND_MEM_C)
-#define mnd_malloc(size) mysqlnd_allocator.m_malloc((size) MYSQLND_MEM_C)
-#define mnd_calloc(nmemb, size) mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C)
-#define mnd_realloc(ptr, new_size) mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C)
-#define mnd_free(ptr) mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C)
-#define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C)
-#define mnd_pestrdup(ptr, pers) mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C)
-
#endif /* MYSQLND_DEBUG_H */
/*
diff --git a/ext/mysqlnd/mysqlnd_driver.c b/ext/mysqlnd/mysqlnd_driver.c
new file mode 100644
index 0000000000..aeb34a66ef
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_driver.c
@@ -0,0 +1,304 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 317989 2011-10-10 20:49:28Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_result.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_charset.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_reverse_api.h"
+#include "mysqlnd_ext_plugin.h"
+
+static zend_bool mysqlnd_library_initted = FALSE;
+
+static struct st_mysqlnd_plugin_core mysqlnd_plugin_core =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "mysqlnd",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* will be filled later */
+ mysqlnd_stats_values_names,
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ }
+};
+
+
+/* {{{ mysqlnd_library_end */
+PHPAPI void mysqlnd_library_end(TSRMLS_D)
+{
+ if (mysqlnd_library_initted == TRUE) {
+ mysqlnd_plugin_subsystem_end(TSRMLS_C);
+ mysqlnd_stats_end(mysqlnd_global_stats);
+ mysqlnd_global_stats = NULL;
+ mysqlnd_library_initted = FALSE;
+ mysqlnd_reverse_api_end(TSRMLS_C);
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_library_init */
+PHPAPI void mysqlnd_library_init(TSRMLS_D)
+{
+ if (mysqlnd_library_initted == FALSE) {
+ mysqlnd_library_initted = TRUE;
+ mysqlnd_conn_set_methods(&MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_conn));
+ mysqlnd_conn_data_set_methods(&MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_conn_data));
+ _mysqlnd_init_ps_subsystem();
+ /* Should be calloc, as mnd_calloc will reference LOCK_access*/
+ mysqlnd_stats_init(&mysqlnd_global_stats, STAT_LAST);
+ mysqlnd_plugin_subsystem_init(TSRMLS_C);
+ {
+ mysqlnd_plugin_core.plugin_header.plugin_stats.values = mysqlnd_global_stats;
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_core TSRMLS_CC);
+ }
+ mysqlnd_example_plugin_register(TSRMLS_C);
+ mysqlnd_debug_trace_plugin_register(TSRMLS_C);
+ mysqlnd_register_builtin_authentication_plugins(TSRMLS_C);
+
+ mysqlnd_reverse_api_init(TSRMLS_C);
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_error_list_pdtor */
+static void
+mysqlnd_error_list_pdtor(void * pDest)
+{
+ MYSQLND_ERROR_LIST_ELEMENT * element = (MYSQLND_ERROR_LIST_ELEMENT *) pDest;
+ TSRMLS_FETCH();
+ DBG_ENTER("mysqlnd_error_list_pdtor");
+ if (element->error) {
+ mnd_pefree(element->error, TRUE);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_connection */
+static MYSQLND *
+MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(zend_bool persistent TSRMLS_DC)
+{
+ size_t alloc_size_ret = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
+ size_t alloc_size_ret_data = sizeof(MYSQLND_CONN_DATA) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND * new_object;
+ MYSQLND_CONN_DATA * data;
+
+ DBG_ENTER("mysqlnd_driver::get_connection");
+ DBG_INF_FMT("persistent=%u", persistent);
+ new_object = mnd_pecalloc(1, alloc_size_ret, persistent);
+ if (!new_object) {
+ DBG_RETURN(NULL);
+ }
+ new_object->data = mnd_pecalloc(1, alloc_size_ret_data, persistent);
+ if (!new_object->data) {
+ mnd_pefree(new_object, persistent);
+ DBG_RETURN(NULL);
+ }
+ new_object->persistent = persistent;
+ new_object->m = mysqlnd_conn_get_methods();
+ data = new_object->data;
+
+ data->error_info = &(data->error_info_impl);
+ data->options = &(data->options_impl);
+ data->upsert_status = &(data->upsert_status_impl);
+
+ data->persistent = persistent;
+ data->m = mysqlnd_conn_data_get_methods();
+ CONN_SET_STATE(data, CONN_ALLOCED);
+ data->m->get_reference(data TSRMLS_CC);
+
+ if (PASS != data->m->init(data TSRMLS_CC)) {
+ new_object->m->dtor(new_object TSRMLS_CC);
+ DBG_RETURN(NULL);
+ }
+
+ data->error_info->error_list = mnd_pecalloc(1, sizeof(zend_llist), persistent);
+ if (!data->error_info->error_list) {
+ new_object->m->dtor(new_object TSRMLS_CC);
+ DBG_RETURN(NULL);
+ } else {
+ zend_llist_init(data->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t)mysqlnd_error_list_pdtor, persistent);
+ }
+
+ DBG_RETURN(new_object);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::clone_connection_object */
+static MYSQLND *
+MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object)(MYSQLND * to_be_cloned TSRMLS_DC)
+{
+ size_t alloc_size_ret = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND * new_object;
+
+ DBG_ENTER("mysqlnd_driver::clone_connection_object");
+ DBG_INF_FMT("persistent=%u", to_be_cloned->persistent);
+ if (!to_be_cloned || !to_be_cloned->data) {
+ DBG_RETURN(NULL);
+ }
+ new_object = mnd_pecalloc(1, alloc_size_ret, to_be_cloned->persistent);
+ if (!new_object) {
+ DBG_RETURN(NULL);
+ }
+ new_object->persistent = to_be_cloned->persistent;
+ new_object->m = to_be_cloned->m;
+
+ new_object->data = to_be_cloned->data->m->get_reference(to_be_cloned->data TSRMLS_CC);
+ if (!new_object->data) {
+ new_object->m->dtor(new_object TSRMLS_CC);
+ new_object = NULL;
+ }
+ DBG_RETURN(new_object);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_prepared_statement */
+static MYSQLND_STMT *
+MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
+{
+ size_t alloc_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_STMT * ret = mnd_pecalloc(1, alloc_size, conn->persistent);
+ MYSQLND_STMT_DATA * stmt = NULL;
+
+ DBG_ENTER("mysqlnd_object_factory::get_prepared_statement");
+ do {
+ if (!ret) {
+ break;
+ }
+ ret->m = mysqlnd_stmt_get_methods();
+ ret->persistent = conn->persistent;
+
+ stmt = ret->data = mnd_pecalloc(1, sizeof(MYSQLND_STMT_DATA), conn->persistent);
+ DBG_INF_FMT("stmt=%p", stmt);
+ if (!stmt) {
+ break;
+ }
+ stmt->persistent = conn->persistent;
+ stmt->error_info = &(stmt->error_info_impl);
+ stmt->upsert_status = &(stmt->upsert_status_impl);
+ stmt->state = MYSQLND_STMT_INITTED;
+ stmt->execute_cmd_buffer.length = 4096;
+ stmt->execute_cmd_buffer.buffer = mnd_pemalloc(stmt->execute_cmd_buffer.length, stmt->persistent);
+ if (!stmt->execute_cmd_buffer.buffer) {
+ break;
+ }
+
+ stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS;
+ /*
+ Mark that we reference the connection, thus it won't be
+ be destructed till there is open statements. The last statement
+ or normal query result will close it then.
+ */
+ stmt->conn = conn->m->get_reference(conn TSRMLS_CC);
+ stmt->error_info->error_list = mnd_pecalloc(1, sizeof(zend_llist), ret->persistent);
+ if (!stmt->error_info->error_list) {
+ break;
+ }
+
+ zend_llist_init(stmt->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t) mysqlnd_error_list_pdtor, conn->persistent);
+
+ DBG_RETURN(ret);
+ } while (0);
+
+ SET_OOM_ERROR(*conn->error_info);
+ if (ret) {
+ ret->m->dtor(ret, TRUE TSRMLS_CC);
+ ret = NULL;
+ }
+ DBG_RETURN(NULL);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_io_channel */
+PHPAPI MYSQLND_NET *
+MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
+{
+ size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent);
+
+ DBG_ENTER("mysqlnd_object_factory::get_io_channel");
+ DBG_INF_FMT("persistent=%u", persistent);
+ if (net) {
+ net->persistent = persistent;
+ net->m = *mysqlnd_net_get_methods();
+
+ if (PASS != net->m.init(net, stats, error_info TSRMLS_CC)) {
+ net->m.dtor(net, stats, error_info TSRMLS_CC);
+ net = NULL;
+ }
+ }
+ DBG_RETURN(net);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_protocol_decoder */
+PHPAPI MYSQLND_PROTOCOL *
+MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)(zend_bool persistent TSRMLS_DC)
+{
+ size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_PROTOCOL *ret = mnd_pecalloc(1, alloc_size, persistent);
+
+ DBG_ENTER("mysqlnd_object_factory::get_protocol_decoder");
+ DBG_INF_FMT("persistent=%u", persistent);
+ if (ret) {
+ ret->persistent = persistent;
+ ret->m = mysqlnd_mysqlnd_protocol_methods;
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_object_factory)
+ MYSQLND_METHOD(mysqlnd_object_factory, get_connection),
+ MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)
+MYSQLND_CLASS_METHODS_END;
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h
index 6dfb0aaaa6..b0fe88648e 100644
--- a/ext/mysqlnd/mysqlnd_enum_n_def.h
+++ b/ext/mysqlnd/mysqlnd_enum_n_def.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -35,6 +35,8 @@
#define MYSQLND_MAX_PACKET_SIZE (256L*256L*256L-1)
+#define MYSQLND_ASSEMBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
+
#define MYSQLND_ERRMSG_SIZE 512
#define MYSQLND_SQLSTATE_LENGTH 5
#define MYSQLND_SQLSTATE_NULL "00000"
@@ -96,6 +98,9 @@
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
+#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
+ CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_LOCAL_FILES | CLIENT_PLUGIN_AUTH)
#define MYSQLND_NET_FLAG_USE_COMPRESSION 1
@@ -172,7 +177,9 @@ typedef enum mysqlnd_option
MYSQLND_OPT_SSL_CA = 206,
MYSQLND_OPT_SSL_CAPATH = 207,
MYSQLND_OPT_SSL_CIPHER = 208,
- MYSQLND_OPT_SSL_PASSPHRASE = 209
+ MYSQLND_OPT_SSL_PASSPHRASE = 209,
+ MYSQLND_OPT_MAX_ALLOWED_PACKET = 210,
+ MYSQLND_OPT_AUTH_PROTOCOL = 211
} enum_mysqlnd_option;
typedef enum mysqlnd_protocol_type
@@ -517,6 +524,8 @@ enum mysqlnd_packet_type
{
PROT_GREET_PACKET= 0,
PROT_AUTH_PACKET,
+ PROT_AUTH_RESP_PACKET,
+ PROT_CHANGE_AUTH_RESP_PACKET,
PROT_OK_PACKET,
PROT_EOF_PACKET,
PROT_CMD_PACKET,
diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.c b/ext/mysqlnd/mysqlnd_ext_plugin.c
new file mode 100644
index 0000000000..02cd9a891f
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_ext_plugin.c
@@ -0,0 +1,226 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 318221 2011-10-19 15:04:12Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_result.h"
+#include "mysqlnd_debug.h"
+
+static struct st_mysqlnd_conn_methods * mysqlnd_conn_methods;
+static struct st_mysqlnd_conn_data_methods * mysqlnd_conn_data_methods;
+static struct st_mysqlnd_stmt_methods * mysqlnd_stmt_methods;
+
+/* {{{ _mysqlnd_plugin_get_plugin_connection_data */
+PHPAPI void **
+_mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!conn || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)conn + sizeof(MYSQLND) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_connection_data_data */
+PHPAPI void **
+_mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!conn || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)conn + sizeof(MYSQLND_CONN_DATA) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_result_data */
+PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!result || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_protocol_data */
+PHPAPI void **
+_mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_protocol_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!protocol || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)protocol + sizeof(MYSQLND_PROTOCOL) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_stmt_data */
+PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_stmt_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!stmt || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)stmt + sizeof(MYSQLND_STMT) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_net_data */
+PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!net || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+
+/* {{{ mysqlnd_conn_get_methods */
+PHPAPI struct st_mysqlnd_conn_methods *
+mysqlnd_conn_get_methods()
+{
+ return mysqlnd_conn_methods;
+}
+/* }}} */
+
+/* {{{ mysqlnd_conn_set_methods */
+PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods)
+{
+ mysqlnd_conn_methods = methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_get_methods */
+PHPAPI struct st_mysqlnd_conn_data_methods *
+mysqlnd_conn_data_get_methods()
+{
+ return mysqlnd_conn_data_methods;
+}
+/* }}} */
+
+/* {{{ mysqlnd_conn_set_methods */
+PHPAPI void mysqlnd_conn_data_set_methods(struct st_mysqlnd_conn_data_methods * methods)
+{
+ mysqlnd_conn_data_methods = methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_result_get_methods */
+PHPAPI struct st_mysqlnd_res_methods *
+mysqlnd_result_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_res);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_result_set_methods */
+PHPAPI void
+mysqlnd_result_set_methods(struct st_mysqlnd_res_methods * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_res) = *methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stmt_get_methods */
+PHPAPI struct st_mysqlnd_stmt_methods *
+mysqlnd_stmt_get_methods()
+{
+ return mysqlnd_stmt_methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stmt_set_methods */
+PHPAPI void
+mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods)
+{
+ mysqlnd_stmt_methods = methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol_get_methods */
+PHPAPI struct st_mysqlnd_protocol_methods *
+mysqlnd_protocol_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol_set_methods */
+PHPAPI void
+mysqlnd_protocol_set_methods(struct st_mysqlnd_protocol_methods * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol) = *methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net_get_methods */
+PHPAPI struct st_mysqlnd_net_methods *
+mysqlnd_net_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_net);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net_set_methods */
+PHPAPI void
+mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_net) = *methods;
+}
+/* }}} */
+
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.h b/ext/mysqlnd/mysqlnd_ext_plugin.h
new file mode 100644
index 0000000000..f980f13478
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_ext_plugin.h
@@ -0,0 +1,72 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+/* $Id: mysqlnd.h 318221 2011-10-19 15:04:12Z andrey $ */
+
+#ifndef MYSQLND_EXT_PLUGIN_H
+#define MYSQLND_EXT_PLUGIN_H
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data((c), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_connection_data_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data_data((c), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_result_data(r, p_id) _mysqlnd_plugin_get_plugin_result_data((r), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_stmt_data(s, p_id) _mysqlnd_plugin_get_plugin_stmt_data((s), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_protocol_data(p, p_id) _mysqlnd_plugin_get_plugin_protocol_data((p), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_net_data(n, p_id) _mysqlnd_plugin_get_plugin_net_data((n), (p_id) TSRMLS_CC)
+
+
+PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods();
+PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods * methods);
+
+PHPAPI struct st_mysqlnd_conn_data_methods * mysqlnd_conn_data_get_methods();
+PHPAPI void mysqlnd_conn_data_set_methods(struct st_mysqlnd_conn_data_methods * methods);
+
+PHPAPI struct st_mysqlnd_res_methods * mysqlnd_result_get_methods();
+PHPAPI void mysqlnd_result_set_methods(struct st_mysqlnd_res_methods * methods);
+
+PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods();
+PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods * methods);
+
+PHPAPI struct st_mysqlnd_protocol_methods * mysqlnd_protocol_get_methods();
+PHPAPI void mysqlnd_protocol_set_methods(struct st_mysqlnd_protocol_methods * methods);
+
+PHPAPI struct st_mysqlnd_net_methods * mysqlnd_net_get_methods();
+PHPAPI void mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods);
+
+
+#endif /* MYSQLND_EXT_PLUGIN_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_loaddata.c b/ext/mysqlnd/mysqlnd_loaddata.c
index 557caa2941..82ee63458e 100644
--- a/ext/mysqlnd/mysqlnd_loaddata.c
+++ b/ext/mysqlnd/mysqlnd_loaddata.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -25,28 +25,9 @@
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
-
-#define ALLOC_CALLBACK_ARGS(a, b, c)\
-if (c) {\
- a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
- for (i = b; i < c; i++) {\
- a[i] = mnd_emalloc(sizeof(zval *));\
- MAKE_STD_ZVAL(*a[i]);\
- }\
-}
-
-#define FREE_CALLBACK_ARGS(a, b, c)\
-if (a) {\
- for (i = b; i < c; i++) {\
- zval_ptr_dtor(a[i]);\
- mnd_efree(a[i]);\
- }\
- mnd_efree(a);\
-}
-
/* {{{ mysqlnd_local_infile_init */
static
-int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS_DC)
+int mysqlnd_local_infile_init(void ** ptr, char * filename, void ** userdata TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info;
php_stream_context *context = NULL;
@@ -85,14 +66,14 @@ int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS
/* {{{ mysqlnd_local_infile_read */
static
-int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC)
+int mysqlnd_local_infile_read(void * ptr, zend_uchar * buf, unsigned int buf_len TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
int count;
DBG_ENTER("mysqlnd_local_infile_read");
- count = (int)php_stream_read(info->fd, buf, buf_len);
+ count = (int)php_stream_read(info->fd, (char *) buf, buf_len);
if (count < 0) {
strcpy(info->error_msg, "Error reading file");
@@ -106,7 +87,7 @@ int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_
/* {{{ mysqlnd_local_infile_error */
static
-int mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
+int mysqlnd_local_infile_error(void * ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
@@ -127,7 +108,7 @@ int mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_bu
/* {{{ mysqlnd_local_infile_end */
static
-void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
+void mysqlnd_local_infile_end(void * ptr TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
@@ -144,7 +125,8 @@ void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
/* {{{ mysqlnd_local_infile_default */
-PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
+PHPAPI void
+mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
{
conn->infile.local_infile_init = mysqlnd_local_infile_init;
conn->infile.local_infile_read = mysqlnd_local_infile_read;
@@ -153,8 +135,10 @@ PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
}
/* }}} */
+
/* {{{ mysqlnd_set_local_infile_handler */
-PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname)
+PHPAPI void
+mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, const char * const funcname)
{
if (!conn->infile.callback) {
MAKE_STD_ZVAL(conn->infile.callback);
@@ -171,67 +155,70 @@ static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA
/* {{{ mysqlnd_handle_local_infile */
enum_func_status
-mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC)
+mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning TSRMLS_DC)
{
- char *buf = NULL;
- char empty_packet[MYSQLND_HEADER_SIZE];
+ zend_uchar *buf = NULL;
+ zend_uchar empty_packet[MYSQLND_HEADER_SIZE];
enum_func_status result = FAIL;
unsigned int buflen = 4096;
void *info = NULL;
int bufsize;
size_t ret;
MYSQLND_INFILE infile;
+ MYSQLND_NET * net = conn->net;
DBG_ENTER("mysqlnd_handle_local_infile");
- if (!(conn->options.flags & CLIENT_LOCAL_FILES)) {
+ if (!(conn->options->flags & CLIENT_LOCAL_FILES)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
/* write empty packet to server */
- ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
+ ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC);
*is_warning = TRUE;
goto infile_error;
}
infile = conn->infile;
/* allocate buffer for reading data */
- buf = (char *)mnd_ecalloc(1, buflen);
+ buf = (zend_uchar *) mnd_ecalloc(1, buflen);
*is_warning = FALSE;
/* init handler: allocate read buffer and open file */
if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
+ char tmp_buf[sizeof(conn->error_info->error)];
+ int tmp_error_no;
*is_warning = TRUE;
- /* error occured */
- strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
- conn->error_info.error_no =
- infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
+ /* error occurred */
+ tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
+ SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
/* write empty packet to server */
- ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
+ ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC);
goto infile_error;
}
/* read data */
while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
- if ((ret = conn->net->m.send(conn, buf, bufsize TSRMLS_CC)) == 0) {
+ if ((ret = net->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info TSRMLS_CC)) == 0) {
DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
}
/* send empty packet for eof */
- if ((ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC)) == 0) {
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
+ if ((ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC)) == 0) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
- /* error during read occured */
+ /* error during read occurred */
if (bufsize < 0) {
+ char tmp_buf[sizeof(conn->error_info->error)];
+ int tmp_error_no;
*is_warning = TRUE;
DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
- strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
- conn->error_info.error_no =
- infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
+ tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
+ SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
goto infile_error;
}
diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c
index e801928505..800f577332 100644
--- a/ext/mysqlnd/mysqlnd_net.c
+++ b/ext/mysqlnd/mysqlnd_net.c
@@ -12,11 +12,13 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
+
+/* $Id: mysqlnd_ps.c 316906 2011-09-17 10:24:18Z pajoye $ */
#include "php.h"
#include "php_globals.h"
#include "mysqlnd.h"
@@ -24,7 +26,7 @@
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
-#include "ext/standard/sha1.h"
+#include "mysqlnd_ext_plugin.h"
#include "php_network.h"
#include "zend_ini.h"
#ifdef MYSQLND_COMPRESSION_ENABLED
@@ -59,48 +61,88 @@ mysqlnd_set_sock_no_delay(php_stream * stream TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_net::network_read */
+/* {{{ mysqlnd_net::network_read_ex */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, network_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
enum_func_status return_value = PASS;
size_t to_read = count, ret;
- size_t old_chunk_size = conn->net->stream->chunk_size;
- DBG_ENTER("mysqlnd_net::network_read");
- DBG_INF_FMT("count=%u", count);
- conn->net->stream->chunk_size = MIN(to_read, conn->net->options.net_read_buffer_size);
+ size_t old_chunk_size = net->stream->chunk_size;
+ zend_uchar * p = buffer;
+
+ DBG_ENTER("mysqlnd_net::network_read_ex");
+ DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count);
+
+ net->stream->chunk_size = MIN(to_read, net->options.net_read_buffer_size);
while (to_read) {
- if (!(ret = php_stream_read(conn->net->stream, (char *) buffer, to_read))) {
+ if (!(ret = php_stream_read(net->stream, (char *) p, to_read))) {
DBG_ERR_FMT("Error while reading header from socket");
return_value = FAIL;
break;
}
- buffer += ret;
+ p += ret;
to_read -= ret;
}
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_BYTES_RECEIVED, count - to_read);
- conn->net->stream->chunk_size = old_chunk_size;
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(stats, STAT_BYTES_RECEIVED, count - to_read);
+ net->stream->chunk_size = old_chunk_size;
DBG_RETURN(return_value);
}
/* }}} */
-/* {{{ mysqlnd_net::network_write */
+/* {{{ mysqlnd_net::network_write_ex */
static size_t
-MYSQLND_METHOD(mysqlnd_net, network_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
size_t ret;
- DBG_ENTER("mysqlnd_net::network_write");
- ret = php_stream_write(conn->net->stream, (char *)buf, count);
+ DBG_ENTER("mysqlnd_net::network_write_ex");
+ ret = php_stream_write(net->stream, (char *)buffer, count);
DBG_RETURN(ret);
}
/* }}} */
+/* {{{ mysqlnd_net::open_pipe */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
+ const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+#if PHP_API_VERSION < 20100412
+ unsigned int streams_options = ENFORCE_SAFE_MODE;
+#else
+ unsigned int streams_options = 0;
+#endif
+ DBG_ENTER("mysqlnd_net::open_pipe");
+ if (persistent) {
+ streams_options |= STREAM_OPEN_PERSISTENT;
+ }
+ streams_options |= IGNORE_URL;
+ net->stream = php_stream_open_wrapper((char*) scheme + sizeof("pipe://") - 1, "r+", streams_options, NULL);
+ if (!net->stream) {
+ SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown errror while connecting");
+ DBG_RETURN(FAIL);
+ }
+ /*
+ Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
+ be registered as resource (in EG(regular_list). So far, so good. However, it won't be
+ unregistered yntil the script ends. So, we need to take care of that.
+ */
+ net->stream->in_free = 1;
+ zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
+ net->stream->in_free = 0;
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
-/* {{{ mysqlnd_net::connect */
+/* {{{ mysqlnd_net::open_tcp_or_unix */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
+ const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
#if PHP_API_VERSION < 20100412
unsigned int streams_options = ENFORCE_SAFE_MODE;
@@ -110,27 +152,17 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
char * hashed_details = NULL;
int hashed_details_len = 0;
+ char * errstr = NULL;
+ int errcode = 0;
struct timeval tv;
- DBG_ENTER("mysqlnd_net::connect");
+
+ DBG_ENTER("mysqlnd_net::open_tcp_or_unix");
if (persistent) {
- hashed_details_len = spprintf(&hashed_details, 0, "%p", net);
+ hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", net);
DBG_INF_FMT("hashed_details=%s", hashed_details);
}
- net->packet_no = net->compressed_envelope_packet_no = 0;
-
- if (net->stream) {
- /* close before opening a new one */
- DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
- if (net->persistent) {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
- } else {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
- }
- net->stream = NULL;
- }
-
if (net->options.timeout_connect) {
tv.tv_sec = net->options.timeout_connect;
tv.tv_usec = 0;
@@ -139,16 +171,20 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
DBG_INF_FMT("calling php_stream_xport_create");
net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags,
hashed_details, (net->options.timeout_connect) ? &tv : NULL,
- NULL /*ctx*/, errstr, errcode);
-
- if (*errstr || !net->stream) {
+ NULL /*ctx*/, &errstr, &errcode);
+ if (errstr || !net->stream) {
+ DBG_ERR("Error");
if (hashed_details) {
- efree(hashed_details); /* allocated by spprintf */
+ mnd_sprintf_free(hashed_details);
+ }
+ errcode = CR_CONNECTION_ERROR;
+ SET_CLIENT_ERROR(*error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr);
+ if (errstr) {
+ /* no mnd_ since we don't allocate it */
+ efree(errstr);
}
- *errcode = CR_CONNECTION_ERROR;
DBG_RETURN(FAIL);
}
-
if (hashed_details) {
/*
If persistent, the streams register it in EG(persistent_list).
@@ -171,22 +207,32 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
/* Shut-up the streams, they don't know what they are doing */
net->stream->__exposed = 1;
#endif
- efree(hashed_details);
+ mnd_sprintf_free(hashed_details);
}
+
/*
Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
be registered as resource (in EG(regular_list). So far, so good. However, it won't be
- unregistered till the script ends. So, we need to take care of that.
+ unregistered yntil the script ends. So, we need to take care of that.
*/
net->stream->in_free = 1;
zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
net->stream->in_free = 0;
- if (!net->options.timeout_read) {
- /* should always happen because read_timeout cannot be set via API */
- net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout);
- }
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net::connect_ex */
+static void
+MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt)(MYSQLND_NET * const net,
+ const char * const scheme, const size_t scheme_len,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_net::post_connect_set_opt");
if (net->options.timeout_read) {
+ struct timeval tv;
DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
tv.tv_sec = net->options.timeout_read;
tv.tv_usec = 0;
@@ -198,13 +244,33 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
mysqlnd_set_sock_no_delay(net->stream TSRMLS_CC);
}
- {
- unsigned int buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
- net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
- }
+ DBG_VOID_RETURN;
+}
+/* }}} */
- DBG_RETURN(PASS);
+/* {{{ mysqlnd_net::connect_ex */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
+ const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ func_mysqlnd_net__open_stream open_stream = NULL;
+ DBG_ENTER("mysqlnd_net::connect_ex");
+
+ net->packet_no = net->compressed_envelope_packet_no = 0;
+
+ net->m.close_stream(net, conn_stats, error_info TSRMLS_CC);
+
+ open_stream = (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", sizeof("pipe://") - 1))? net->m.open_pipe:
+ net->m.open_tcp_or_unix;
+
+ if (PASS == (ret = open_stream(net, scheme, scheme_len, persistent, conn_stats, error_info TSRMLS_CC))) {
+ net->m.post_connect_set_opt(net, scheme, scheme_len, conn_stats, error_info TSRMLS_CC);
+ }
+
+ DBG_RETURN(ret);
}
/* }}} */
@@ -218,34 +284,32 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
#define STORE_HEADER_SIZE(safe_storage, buffer) COPY_HEADER((safe_storage), (buffer))
#define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
-/* {{{ mysqlnd_net::send */
+
+/* {{{ mysqlnd_net::send_ex */
/*
- IMPORTANT : It's expected that buf has place in the beginning for MYSQLND_HEADER_SIZE !!!!
+ IMPORTANT : It's expected that buffer has place in the beginning for MYSQLND_HEADER_SIZE !!!!
This is done for performance reasons in the caller of this function.
Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.
Neither are quick, thus the clients of this function are obligated to do
what they are asked for.
`count` is actually the length of the payload data. Thus :
- count + MYSQLND_HEADER_SIZE = sizeof(buf) (not the pointer but the actual buffer)
+ count + MYSQLND_HEADER_SIZE = sizeof(buffer) (not the pointer but the actual buffer)
*/
-size_t
-MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC)
+static size_t
+MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
- zend_uchar *safe_storage = safe_buf;
- MYSQLND_NET *net = conn->net;
- size_t old_chunk_size = net->stream->chunk_size;
- size_t ret, packets_sent = 1;
+ zend_uchar * safe_storage = safe_buf;
+ size_t bytes_sent, packets_sent = 1;
size_t left = count;
- zend_uchar *p = (zend_uchar *) buf;
+ zend_uchar * p = (zend_uchar *) buffer;
zend_uchar * compress_buf = NULL;
size_t to_be_sent;
- DBG_ENTER("mysqlnd_net::send");
- DBG_INF_FMT("conn=%llu count=%lu compression=%u", conn->thread_id, count, net->compressed);
-
- net->stream->chunk_size = MYSQLND_MAX_PACKET_SIZE;
+ DBG_ENTER("mysqlnd_net::send_ex");
+ DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, net->compressed);
if (net->compressed == TRUE) {
size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
@@ -280,7 +344,8 @@ MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t
int3store(compress_buf, payload_size);
int1store(compress_buf + 3, net->packet_no);
DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
- ret = conn->net->m.network_write(conn, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE TSRMLS_CC);
+ bytes_sent = net->m.network_write_ex(net, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE,
+ conn_stats, error_info TSRMLS_CC);
net->compressed_envelope_packet_no++;
#if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
if (res == Z_OK) {
@@ -311,7 +376,7 @@ MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t
STORE_HEADER_SIZE(safe_storage, p);
int3store(p, to_be_sent);
int1store(p + 3, net->packet_no);
- ret = conn->net->m.network_write(conn, p, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC);
+ bytes_sent = net->m.network_write_ex(net, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC);
RESTORE_HEADER_SIZE(p, safe_storage);
net->compressed_envelope_packet_no++;
}
@@ -327,26 +392,25 @@ MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t
indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty
packet will be sent and this loop will end.
*/
- } while (ret && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
+ } while (bytes_sent && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, net->packet_no);
- /* Even for zero size payload we have to send a packet */
- if (!ret) {
- DBG_ERR_FMT("Can't %u send bytes", count);
- conn->state = CONN_QUIT_SENT;
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- }
- MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn->stats,
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats,
STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
STAT_PACKETS_SENT, packets_sent);
- net->stream->chunk_size = old_chunk_size;
if (compress_buf) {
mnd_efree(compress_buf);
}
- DBG_RETURN(ret);
+
+ /* Even for zero size payload we have to send a packet */
+ if (!bytes_sent) {
+ DBG_ERR_FMT("Can't %u send bytes", count);
+ SET_CLIENT_ERROR(*error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ }
+ DBG_RETURN(bytes_sent);
}
/* }}} */
@@ -416,19 +480,19 @@ mysqlnd_create_read_buffer(size_t count TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer */
+/* {{{ mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffer */
static enum_func_status
-mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn, size_t net_payload_size TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
+ (MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- MYSQLND_NET * net = conn->net;
size_t decompressed_size;
enum_func_status ret = PASS;
zend_uchar * compressed_data = NULL;
zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
- DBG_ENTER("mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer");
+ DBG_ENTER("mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffe");
/* Read the compressed header */
- if (FAIL == conn->net->m.network_read(conn, comp_header, COMPRESSED_HEADER_SIZE TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
DBG_RETURN(FAIL);
}
decompressed_size = uint3korr(comp_header);
@@ -438,7 +502,7 @@ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn,
if (decompressed_size) {
compressed_data = mnd_emalloc(net_payload_size);
- if (FAIL == conn->net->m.network_read(conn, compressed_data, net_payload_size TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, compressed_data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
ret = FAIL;
goto end;
}
@@ -450,7 +514,7 @@ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn,
} else {
DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC);
- if (FAIL == conn->net->m.network_read(conn, net->uncompressed_data->data, net_payload_size TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, net->uncompressed_data->data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
ret = FAIL;
goto end;
}
@@ -467,8 +531,8 @@ end:
/* {{{ mysqlnd_net::decode */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, size_t uncompressed_data_len,
- const zend_uchar * const compressed_data, size_t compressed_data_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len,
+ const zend_uchar * const compressed_data, const size_t compressed_data_len TSRMLS_DC)
{
#ifdef MYSQLND_COMPRESSION_ENABLED
int error;
@@ -492,7 +556,7 @@ MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, size_t uncom
/* {{{ mysqlnd_net::encode */
static enum_func_status
MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
- const zend_uchar * const uncompressed_data, size_t uncompressed_data_len TSRMLS_DC)
+ const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len TSRMLS_DC)
{
#ifdef MYSQLND_COMPRESSION_ENABLED
int error;
@@ -516,15 +580,15 @@ MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compr
/* }}} */
-/* {{{ mysqlnd_net::receive */
+/* {{{ mysqlnd_net::receive_ex */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
size_t to_read = count;
zend_uchar * p = buffer;
- MYSQLND_NET * net = conn->net;
- DBG_ENTER("mysqlnd_net::receive");
+ DBG_ENTER("mysqlnd_net::receive_ex");
#ifdef MYSQLND_COMPRESSION_ENABLED
if (net->compressed) {
if (net->uncompressed_data) {
@@ -546,7 +610,7 @@ MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t
size_t net_payload_size;
zend_uchar packet_no;
- if (FAIL == net->m.network_read(conn, net_header, MYSQLND_HEADER_SIZE TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
DBG_RETURN(FAIL);
}
net_payload_size = uint3korr(net_header);
@@ -564,7 +628,7 @@ MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t
DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size);
#endif
/* Now let's read from the wire, decompress it and fill the read buffer */
- mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(conn, net_payload_size TSRMLS_CC);
+ net->m.read_compressed_packet_from_stream_and_fill_read_buffer(net, net_payload_size, conn_stats, error_info TSRMLS_CC);
/*
Now a bit of recursion - read from the read buffer,
@@ -572,12 +636,12 @@ MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t
is not enough, then the recursive call will try to
satisfy it until it is satisfied.
*/
- DBG_RETURN(net->m.receive(conn, p, to_read TSRMLS_CC));
+ DBG_RETURN(net->m.receive_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
}
DBG_RETURN(PASS);
}
#endif /* MYSQLND_COMPRESSION_ENABLED */
- DBG_RETURN(net->m.network_read(conn, p, to_read TSRMLS_CC));
+ DBG_RETURN(net->m.network_read_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
}
/* }}} */
@@ -668,13 +732,11 @@ MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mys
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE;
break;
-#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_READ_TIMEOUT:
- DBG_INF("MYSQL_OPT_READ_TIMEOUT");
net->options.timeout_read = *(unsigned int*) value;
break;
+#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_WRITE_TIMEOUT:
- DBG_INF("MYSQL_OPT_WRITE_TIMEOUT");
net->options.timeout_write = *(unsigned int*) value;
break;
#endif
@@ -744,7 +806,7 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
{
#ifdef MYSQLND_SSL_SUPPORTED
- php_stream_context *context = php_stream_context_alloc();
+ php_stream_context *context = php_stream_context_alloc(TSRMLS_C);
DBG_ENTER("mysqlnd_net::enable_ssl");
if (!context) {
DBG_RETURN(FAIL);
@@ -753,19 +815,16 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->options.ssl_key) {
zval key_zval;
ZVAL_STRING(&key_zval, net->options.ssl_key, 0);
- DBG_INF("key");
php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
}
if (net->options.ssl_verify_peer) {
zval verify_peer_zval;
ZVAL_TRUE(&verify_peer_zval);
- DBG_INF("verify peer");
php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
}
if (net->options.ssl_cert) {
zval cert_zval;
ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0);
- DBG_INF_FMT("local_cert=%s", net->options.ssl_cert);
php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
if (!net->options.ssl_key) {
php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
@@ -774,13 +833,11 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->options.ssl_ca) {
zval cafile_zval;
ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0);
- DBG_INF_FMT("cafile=%s", net->options.ssl_ca);
php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
}
if (net->options.ssl_capath) {
zval capath_zval;
ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0);
- DBG_INF_FMT("capath=%s", net->options.ssl_capath);
php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);
}
if (net->options.ssl_passphrase) {
@@ -791,7 +848,6 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->options.ssl_cipher) {
zval cipher_zval;
ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0);
- DBG_INF_FMT("ciphers=%s", net->options.ssl_cipher);
php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
}
php_stream_context_set(net->stream, context);
@@ -838,7 +894,7 @@ MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_net::set_client_option */
+/* {{{ mysqlnd_net::free_contents */
static void
MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
{
@@ -875,70 +931,72 @@ MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
}
/* }}} */
-static
-MYSQLND_CLASS_METHODS_START(mysqlnd_net)
- MYSQLND_METHOD(mysqlnd_net, connect),
- MYSQLND_METHOD(mysqlnd_net, send),
- MYSQLND_METHOD(mysqlnd_net, receive),
- MYSQLND_METHOD(mysqlnd_net, set_client_option),
- MYSQLND_METHOD(mysqlnd_net, network_read),
- MYSQLND_METHOD(mysqlnd_net, network_write),
- MYSQLND_METHOD(mysqlnd_net, decode),
- MYSQLND_METHOD(mysqlnd_net, encode),
- MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
- MYSQLND_METHOD(mysqlnd_net, free_contents),
- MYSQLND_METHOD(mysqlnd_net, enable_ssl),
- MYSQLND_METHOD(mysqlnd_net, disable_ssl)
-MYSQLND_CLASS_METHODS_END;
-
-/* {{{ mysqlnd_net_init */
-PHPAPI MYSQLND_NET *
-mysqlnd_net_init(zend_bool persistent TSRMLS_DC)
+/* {{{ mysqlnd_net::close_stream */
+static void
+MYSQLND_METHOD(mysqlnd_net, close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
- size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent);
-
- DBG_ENTER("mysqlnd_net_init");
- DBG_INF_FMT("persistent=%u", persistent);
- if (net) {
- net->persistent = persistent;
- net->m = mysqlnd_mysqlnd_net_methods;
-
- {
- unsigned int buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
- net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
+ DBG_ENTER("mysqlnd_net::close_stream");
+ if (net && net->stream) {
+ zend_bool pers = net->persistent;
+ DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
+ if (pers) {
+ if (EG(active)) {
+ php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
+ } else {
+ /*
+ otherwise we will crash because the EG(persistent_list) has been freed already,
+ before the modules are shut down
+ */
+ php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
+ }
+ } else {
+ php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
}
+ net->stream = NULL;
}
- DBG_RETURN(net);
+
+ DBG_VOID_RETURN;
}
/* }}} */
-/* {{{ mysqlnd_net_free */
-PHPAPI void
-mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)
+/* {{{ mysqlnd_net::init */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_net_free");
+ unsigned int buf_size;
+ DBG_ENTER("mysqlnd_net::init");
+
+ buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
+ net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
+
+ buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
+ net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
+ buf_size = MYSQLND_G(net_read_timeout); /* this is long, cast to unsigned int*/
+ net->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size TSRMLS_CC);
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net::dtor */
+static void
+MYSQLND_METHOD(mysqlnd_net, dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_net::dtor");
if (net) {
zend_bool pers = net->persistent;
-
+
net->m.free_contents(net TSRMLS_CC);
+ net->m.close_stream(net, stats, error_info TSRMLS_CC);
if (net->cmd_buffer.buffer) {
DBG_INF("Freeing cmd buffer");
mnd_pefree(net->cmd_buffer.buffer, pers);
net->cmd_buffer.buffer = NULL;
}
- if (net->stream) {
- DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
- if (pers) {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
- } else {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
- }
- net->stream = NULL;
- }
mnd_pefree(net, pers);
}
DBG_VOID_RETURN;
@@ -946,28 +1004,61 @@ mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_net_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC)
+MYSQLND_CLASS_METHODS_START(mysqlnd_net)
+ MYSQLND_METHOD(mysqlnd_net, init),
+ MYSQLND_METHOD(mysqlnd_net, dtor),
+ MYSQLND_METHOD(mysqlnd_net, connect_ex),
+ MYSQLND_METHOD(mysqlnd_net, close_stream),
+ MYSQLND_METHOD(mysqlnd_net, open_pipe),
+ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix),
+ NULL, /* unused 1 */
+ NULL, /* unused 2 */
+ MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt),
+ MYSQLND_METHOD(mysqlnd_net, set_client_option),
+ MYSQLND_METHOD(mysqlnd_net, decode),
+ MYSQLND_METHOD(mysqlnd_net, encode),
+ MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
+ MYSQLND_METHOD(mysqlnd_net, free_contents),
+ MYSQLND_METHOD(mysqlnd_net, enable_ssl),
+ MYSQLND_METHOD(mysqlnd_net, disable_ssl),
+ MYSQLND_METHOD(mysqlnd_net, network_read_ex),
+ MYSQLND_METHOD(mysqlnd_net, network_write_ex),
+ MYSQLND_METHOD(mysqlnd_net, send_ex),
+ MYSQLND_METHOD(mysqlnd_net, receive_ex),
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
+#else
+ NULL
+#endif
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ mysqlnd_net_init */
+PHPAPI MYSQLND_NET *
+mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!net || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *)));
+ MYSQLND_NET * net;
+ DBG_ENTER("mysqlnd_net_init");
+ net = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_io_channel(persistent, stats, error_info TSRMLS_CC);
+ DBG_RETURN(net);
}
/* }}} */
-/* {{{ mysqlnd_net_get_methods */
-PHPAPI struct st_mysqlnd_net_methods *
-mysqlnd_net_get_methods()
+/* {{{ mysqlnd_net_free */
+PHPAPI void
+mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- return &mysqlnd_mysqlnd_net_methods;
+ DBG_ENTER("mysqlnd_net_free");
+ if (net) {
+ net->m.dtor(net, stats, error_info TSRMLS_CC);
+ }
+ DBG_VOID_RETURN;
}
/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_net.h b/ext/mysqlnd/mysqlnd_net.h
index d4077aea0b..29280ee407 100644
--- a/ext/mysqlnd/mysqlnd_net.h
+++ b/ext/mysqlnd/mysqlnd_net.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -23,10 +23,8 @@
#ifndef MYSQLND_NET_H
#define MYSQLND_NET_H
-PHPAPI MYSQLND_NET * mysqlnd_net_init(zend_bool persistent TSRMLS_DC);
-PHPAPI void mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC);
-
-PHPAPI struct st_mysqlnd_net_methods * mysqlnd_net_get_methods();
+PHPAPI MYSQLND_NET * mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
+PHPAPI void mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
#endif /* MYSQLND_NET_H */
diff --git a/ext/mysqlnd/mysqlnd_plugin.c b/ext/mysqlnd/mysqlnd_plugin.c
new file mode 100644
index 0000000000..2dbb57d1c8
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_plugin.c
@@ -0,0 +1,209 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 306407 2010-12-16 12:56:19Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_debug.h"
+
+/*--------------------------------------------------------------------*/
+
+static enum_func_status mysqlnd_example_plugin_end(void * p TSRMLS_DC);
+
+static MYSQLND_STATS * mysqlnd_plugin_example_stats = NULL;
+
+enum mysqlnd_plugin_example_collected_stats
+{
+ EXAMPLE_STAT1,
+ EXAMPLE_STAT2,
+ EXAMPLE_STAT_LAST
+};
+
+static const MYSQLND_STRING mysqlnd_plugin_example_stats_values_names[EXAMPLE_STAT_LAST] =
+{
+ { MYSQLND_STR_W_LEN("stat1") },
+ { MYSQLND_STR_W_LEN("stat2") }
+};
+
+static struct st_mysqlnd_typeii_plugin_example mysqlnd_example_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "example",
+ 10001L,
+ "1.00.01",
+ "PHP License",
+ "Andrey Hristov <andrey@php.net>",
+ {
+ NULL, /* will be filled later */
+ mysqlnd_plugin_example_stats_values_names,
+ },
+ {
+ mysqlnd_example_plugin_end
+ }
+ },
+ NULL, /* methods */
+};
+
+
+/* {{{ mysqlnd_example_plugin_end */
+static
+enum_func_status mysqlnd_example_plugin_end(void * p TSRMLS_DC)
+{
+ struct st_mysqlnd_typeii_plugin_example * plugin = (struct st_mysqlnd_typeii_plugin_example *) p;
+ DBG_ENTER("mysqlnd_example_plugin_end");
+ mysqlnd_stats_end(plugin->plugin_header.plugin_stats.values);
+ plugin->plugin_header.plugin_stats.values = NULL;
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_example_plugin_register */
+void
+mysqlnd_example_plugin_register(TSRMLS_D)
+{
+ mysqlnd_stats_init(&mysqlnd_plugin_example_stats, EXAMPLE_STAT_LAST);
+ mysqlnd_example_plugin.plugin_header.plugin_stats.values = mysqlnd_plugin_example_stats;
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_example_plugin TSRMLS_CC);
+}
+/* }}} */
+
+/*--------------------------------------------------------------------*/
+
+static HashTable mysqlnd_registered_plugins;
+
+static unsigned int mysqlnd_plugins_counter = 0;
+
+
+/* {{{ mysqlnd_plugin_subsystem_init */
+void
+mysqlnd_plugin_subsystem_init(TSRMLS_D)
+{
+ zend_hash_init(&mysqlnd_registered_plugins, 4 /* initial hash size */, NULL /* hash_func */, NULL /* dtor */, TRUE /* pers */);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_end_apply_func */
+int
+mysqlnd_plugin_end_apply_func(void *pDest TSRMLS_DC)
+{
+ struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ if (plugin_header->m.plugin_shutdown) {
+ plugin_header->m.plugin_shutdown(plugin_header TSRMLS_CC);
+ }
+ return ZEND_HASH_APPLY_REMOVE;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_subsystem_end */
+void
+mysqlnd_plugin_subsystem_end(TSRMLS_D)
+{
+ zend_hash_apply(&mysqlnd_registered_plugins, mysqlnd_plugin_end_apply_func TSRMLS_CC);
+ zend_hash_destroy(&mysqlnd_registered_plugins);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_register */
+PHPAPI unsigned int mysqlnd_plugin_register()
+{
+ TSRMLS_FETCH();
+ return mysqlnd_plugin_register_ex(NULL TSRMLS_CC);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_register_ex */
+PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header * plugin TSRMLS_DC)
+{
+ if (plugin) {
+ if (plugin->plugin_api_version == MYSQLND_PLUGIN_API_VERSION) {
+ zend_hash_update(&mysqlnd_registered_plugins, plugin->plugin_name, strlen(plugin->plugin_name) + 1, &plugin, sizeof(void *), NULL);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Plugin API version mismatch while loading plugin %s. Expected %d, got %d",
+ plugin->plugin_name, MYSQLND_PLUGIN_API_VERSION, plugin->plugin_api_version);
+ return 0xCAFE;
+ }
+ }
+ return mysqlnd_plugins_counter++;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_find */
+PHPAPI void * _mysqlnd_plugin_find(const char * const name TSRMLS_DC)
+{
+ void * plugin;
+ if (SUCCESS == zend_hash_find(&mysqlnd_registered_plugins, name, strlen(name) + 1, (void **) &plugin)) {
+ return (void *)*(char **) plugin;
+ }
+ return NULL;
+
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_apply_with_argument */
+PHPAPI void _mysqlnd_plugin_apply_with_argument(apply_func_arg_t apply_func, void * argument TSRMLS_DC)
+{
+ /* Note: We want to be thread-safe (read-only), so we can use neither
+ * zend_hash_apply_with_argument nor zend_hash_internal_pointer_reset and
+ * friends
+ */
+ Bucket *p;
+
+ p = mysqlnd_registered_plugins.pListHead;
+ while (p != NULL) {
+ int result = apply_func(p->pData, argument TSRMLS_CC);
+
+ if (result & ZEND_HASH_APPLY_REMOVE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "mysqlnd_plugin_apply_with_argument must not remove table entries");
+ }
+ p = p->pListNext;
+ if (result & ZEND_HASH_APPLY_STOP) {
+ break;
+ }
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_count */
+PHPAPI unsigned int mysqlnd_plugin_count()
+{
+ return mysqlnd_plugins_counter;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h
index 52600a4830..addce670d4 100644
--- a/ext/mysqlnd/mysqlnd_priv.h
+++ b/ext/mysqlnd/mysqlnd_priv.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -47,10 +47,6 @@
#define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
#endif
-#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
-#define MYSQLND_CLASS_METHODS_START(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class) = {
-#define MYSQLND_CLASS_METHODS_END }
-
#if MYSQLND_UNICODE
#define mysqlnd_array_init(arg, field_count) \
{ \
@@ -67,6 +63,7 @@
}
#endif
+#define MYSQLND_STR_W_LEN(str) str, (sizeof(str) - 1)
#define MYSQLND_DEBUG_DUMP_TIME 1
#define MYSQLND_DEBUG_DUMP_TRACE 2
@@ -102,7 +99,7 @@
#define MAX_CHARSET_LEN 32
-#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status.affected_rows = (uint64_t) ~0
+#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status->affected_rows = (uint64_t) ~0
/* Error handling */
#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \
@@ -133,19 +130,45 @@
(error_info).error_no = 0; \
(error_info).error[0] = '\0'; \
strlcpy((error_info).sqlstate, "00000", sizeof((error_info).sqlstate)); \
+ if ((error_info).error_list) { \
+ zend_llist_clean((error_info).error_list); \
+ } \
}
+
#define SET_CLIENT_ERROR(error_info, a, b, c) \
- { \
+{ \
+ if (0 == (a)) { \
+ SET_EMPTY_ERROR((error_info)); \
+ } else { \
(error_info).error_no = (a); \
strlcpy((error_info).sqlstate, (b), sizeof((error_info).sqlstate)); \
strlcpy((error_info).error, (c), sizeof((error_info).error)); \
+ if ((error_info).error_list) {\
+ MYSQLND_ERROR_LIST_ELEMENT error_for_the_list = {0}; \
+ \
+ error_for_the_list.error_no = (a); \
+ strlcpy(error_for_the_list.sqlstate, (b), sizeof(error_for_the_list.sqlstate)); \
+ error_for_the_list.error = mnd_pestrdup((c), TRUE); \
+ if (error_for_the_list.error) { \
+ DBG_INF_FMT("adding error [%s] to the list", error_for_the_list.error); \
+ zend_llist_add_element((error_info).error_list, &error_for_the_list); \
+ } \
+ } \
+ } \
+}
+
+
+#define COPY_CLIENT_ERROR(error_info_to, error_info_from) \
+ { \
+ SET_CLIENT_ERROR((error_info_to), (error_info_from).error_no, (error_info_from).sqlstate, (error_info_from).error); \
}
+
#define SET_OOM_ERROR(error_info) SET_CLIENT_ERROR((error_info), CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
-#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR((stmt)->error_info, a, b, c)
+#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR(*(stmt)->error_info, a, b, c)
#define CONN_GET_STATE(c) (c)->m->get_state((c) TSRMLS_CC)
#define CONN_SET_STATE(c, s) (c)->m->set_state((c), (s) TSRMLS_CC)
@@ -170,7 +193,14 @@ PHPAPI extern const char * const mysqlnd_out_of_sync;
PHPAPI extern const char * const mysqlnd_server_gone;
PHPAPI extern const char * const mysqlnd_out_of_memory;
-enum_func_status mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_object_factory);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn_data);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_res);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net);
+
+enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
@@ -181,6 +211,55 @@ void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
unsigned int pack_len, zend_uchar **row, zend_bool as_unicode,
unsigned int byte_count TSRMLS_DC);
+void mysqlnd_plugin_subsystem_init(TSRMLS_D);
+void mysqlnd_plugin_subsystem_end(TSRMLS_D);
+
+void mysqlnd_register_builtin_authentication_plugins(TSRMLS_D);
+
+void mysqlnd_example_plugin_register(TSRMLS_D);
+
+struct st_mysqlnd_packet_greet;
+struct st_mysqlnd_authentication_plugin;
+
+enum_func_status
+mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_OPTIONS * const options,
+ unsigned long mysql_flags,
+ unsigned int server_charset_no,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ const zend_uchar * const auth_plugin_data,
+ const size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC);
+
+enum_func_status
+mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
+ const char * const user,
+ const size_t user_len,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const zend_bool silent,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ zend_uchar * auth_plugin_data,
+ size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC);
+
#endif /* MYSQLND_PRIV_H */
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index d762689a92..1b48ba1d7b 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -28,7 +28,7 @@
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
#include "mysqlnd_block_alloc.h"
-
+#include "mysqlnd_ext_plugin.h"
#define MYSQLND_SILENT
@@ -36,8 +36,6 @@
const char * const mysqlnd_not_bound_as_blob = "Can't send long data for non-string/non-binary data types";
const char * const mysqlnd_stmt_not_prepared = "Statement not prepared";
-static struct st_mysqlnd_stmt_methods *mysqlnd_stmt_methods;
-
/* Exported by mysqlnd_ps_codec.c */
enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
@@ -52,15 +50,15 @@ enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param,
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC);
+
/* {{{ mysqlnd_stmt::store_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
MYSQLND_RES * result;
- zend_bool to_cache = FALSE;
DBG_ENTER("mysqlnd_stmt::store_result");
if (!stmt || !stmt->conn || !stmt->result) {
@@ -84,33 +82,34 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA ||
stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
{
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
stmt->default_rset_handler = s->m->store_result;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_BUFFERED_SETS);
result = stmt->result;
result->type = MYSQLND_RES_PS_BUF;
result->m.fetch_row = mysqlnd_stmt_fetch_row_buffered;
result->m.fetch_lengths = NULL;/* makes no sense */
+ result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
- ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE, to_cache TSRMLS_CC);
+ ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE TSRMLS_CC);
if (PASS == ret) {
/* libmysql API docs say it should be so for SELECT statements */
- stmt->upsert_status.affected_rows = stmt->result->stored_data->row_count;
+ stmt->upsert_status->affected_rows = stmt->result->stored_data->row_count;
stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;
} else {
- conn->error_info = result->stored_data->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
stmt->result->m.free_result_contents(stmt->result TSRMLS_CC);
mnd_efree(stmt->result);
stmt->result = NULL;
@@ -127,7 +126,7 @@ static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
MYSQLND_RES *result;
DBG_ENTER("mysqlnd_stmt::get_result");
@@ -150,34 +149,34 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC)
/* Nothing to store for UPSERT/LOAD DATA*/
if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
do {
result = conn->m->result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC);
if (!result) {
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC);
if (!result->meta) {
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) {
- stmt->upsert_status.affected_rows = result->stored_data->row_count;
+ stmt->upsert_status->affected_rows = result->stored_data->row_count;
stmt->state = MYSQLND_STMT_PREPARED;
result->type = MYSQLND_RES_PS_BUF;
} else {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
stmt->state = MYSQLND_STMT_PREPARED;
break;
}
@@ -199,8 +198,7 @@ MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * s TSRMLS_DC)
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
DBG_ENTER("mysqlnd_stmt::more_results");
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
- DBG_RETURN((stmt && stmt->conn && (stmt->conn->upsert_status.server_status &
- SERVER_MORE_RESULTS_EXISTS))?
+ DBG_RETURN((stmt && stmt->conn && (stmt->conn->m->get_server_status(stmt->conn TSRMLS_CC) & SERVER_MORE_RESULTS_EXISTS))?
TRUE:
FALSE);
}
@@ -212,7 +210,7 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt::next_result");
if (!stmt || !stmt->conn || !stmt->result) {
@@ -221,12 +219,11 @@ MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s TSRMLS_DC)
conn = stmt->conn;
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING || !(conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS)) {
+ if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING || !(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS)) {
DBG_RETURN(FAIL);
}
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status.server_status, stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
- DBG_INF_FMT("server_status=%u cursor=%u", conn->upsert_status.server_status, conn->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
/* Free space for next result */
s->m->free_stmt_content(s TSRMLS_CC);
@@ -256,8 +253,8 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s TSRMLS_DC)
field_packet = stmt->conn->protocol->m.get_result_field_packet(stmt->conn->protocol, FALSE TSRMLS_CC);
if (!field_packet) {
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
} else {
ret = PASS;
field_packet->skip_parsing = TRUE;
@@ -291,8 +288,8 @@ mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s TSRMLS_DC)
prepare_resp = stmt->conn->protocol->m.get_prepare_response_packet(stmt->conn->protocol, FALSE TSRMLS_CC);
if (!prepare_resp) {
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
goto done;
}
@@ -301,12 +298,13 @@ mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s TSRMLS_DC)
}
if (0xFF == prepare_resp->error_code) {
- stmt->error_info = stmt->conn->error_info = prepare_resp->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, prepare_resp->error_info);
+ COPY_CLIENT_ERROR(*stmt->conn->error_info, prepare_resp->error_info);
goto done;
}
ret = PASS;
stmt->stmt_id = prepare_resp->stmt_id;
- stmt->warning_count = stmt->conn->upsert_status.warning_count = prepare_resp->warning_count;
+ stmt->warning_count = stmt->conn->upsert_status->warning_count = prepare_resp->warning_count;
stmt->field_count = stmt->conn->field_count = prepare_resp->field_count;
stmt->param_count = prepare_resp->param_count;
done:
@@ -333,8 +331,8 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s TSRMLS_DC)
fields_eof = stmt->conn->protocol->m.get_eof_packet(stmt->conn->protocol, FALSE TSRMLS_CC);
if (!fields_eof) {
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
} else {
if (FAIL == (ret = PACKET_READ(fields_eof, stmt->conn))) {
if (stmt->result) {
@@ -344,8 +342,8 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s TSRMLS_DC)
stmt->state = MYSQLND_STMT_INITTED;
}
} else {
- stmt->upsert_status.server_status = fields_eof->server_status;
- stmt->upsert_status.warning_count = fields_eof->warning_count;
+ stmt->upsert_status->server_status = fields_eof->server_status;
+ stmt->upsert_status->warning_count = fields_eof->warning_count;
stmt->state = MYSQLND_STMT_PREPARED;
}
PACKET_FREE(fields_eof);
@@ -369,12 +367,13 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
+ DBG_INF_FMT("query=%s", query);
SET_ERROR_AFF_ROWS(stmt);
SET_ERROR_AFF_ROWS(stmt->conn);
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->state > MYSQLND_STMT_INITTED) {
/* See if we have to clean the wire */
@@ -398,7 +397,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
stmt_to_prepare = s_to_prepare->data;
}
- if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, query, query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) ||
+ if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, (const zend_uchar *) query, query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) ||
FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare TSRMLS_CC))
{
goto fail;
@@ -420,7 +419,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
if (stmt_to_prepare->field_count) {
MYSQLND_RES * result = stmt->conn->m->result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC);
if (!result) {
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
goto fail;
}
/* Allocate the result now as it is needed for the reading of metadata */
@@ -474,7 +473,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt_execute_parse_response");
if (!stmt || !stmt->conn) {
@@ -485,8 +484,8 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
ret = mysqlnd_query_read_result_set_header(stmt->conn, s TSRMLS_CC);
if (ret == FAIL) {
- stmt->error_info = conn->error_info;
- stmt->upsert_status.affected_rows = conn->upsert_status.affected_rows;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ stmt->upsert_status->affected_rows = conn->upsert_status->affected_rows;
if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
/* close the statement here, the connection has been closed */
}
@@ -500,9 +499,9 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
value is > LONG_MAX or < LONG_MIN, there is string conversion and we have
to resend the types. Next execution will also need to resend the type.
*/
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
- stmt->upsert_status = conn->upsert_status;
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
+ *stmt->upsert_status = *conn->upsert_status; /* copy status */
stmt->state = MYSQLND_STMT_EXECUTED;
if (conn->last_query_type == QUERY_UPSERT || conn->last_query_type == QUERY_LOAD_LOCAL) {
DBG_INF("PASS");
@@ -528,10 +527,10 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
use_result() or store_result() and we should be able to scrap the
data on the line, if he just decides to close the statement.
*/
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status.server_status,
- stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status,
+ stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
- if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) {
+ if (stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS) {
DBG_INF("cursor exists");
stmt->cursor_exists = TRUE;
CONN_SET_STATE(conn, CONN_READY);
@@ -562,7 +561,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
}
}
#ifndef MYSQLND_DONT_SKIP_OUT_PARAMS_RESULTSET
- if (stmt->upsert_status.server_status & SERVER_PS_OUT_PARAMS) {
+ if (stmt->upsert_status->server_status & SERVER_PS_OUT_PARAMS) {
s->m->free_stmt_content(s TSRMLS_CC);
DBG_INF("PS OUT Variable RSet, skipping");
/* OUT params result set. Skip for now to retain compatibility */
@@ -582,7 +581,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
zend_uchar *request = NULL;
size_t request_len;
zend_bool free_request;
@@ -629,27 +628,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
}
#endif
- /*
- If right after execute() we have to call the appropriate
- use_result() or store_result() and clean.
- */
- if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
- DBG_INF("fetching result set header");
- /* Do implicit use_result and then flush the result */
- stmt->default_rset_handler = s->m->use_result;
- stmt->default_rset_handler(s TSRMLS_CC);
- }
-
- if (stmt->state > MYSQLND_STMT_WAITING_USE_OR_STORE) {
- DBG_INF("skipping result");
- /* Flush if anything is left and unbuffered set */
- stmt->result->m.skip_result(stmt->result TSRMLS_CC);
- }
-
- if (stmt->state > MYSQLND_STMT_PREPARED) {
- /* As the buffers have been freed, we should go back to PREPARED */
- stmt->state = MYSQLND_STMT_PREPARED;
- }
+ s->m->flush(s TSRMLS_CC);
/*
Executed, but the user hasn't started to fetch
@@ -657,9 +636,11 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
have it again.
*/
stmt->result->m.free_result_buffers(stmt->result TSRMLS_CC);
+
+ stmt->state = MYSQLND_STMT_PREPARED;
} else if (stmt->state < MYSQLND_STMT_PREPARED) {
/* Only initted - error */
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
mysqlnd_out_of_sync);
SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_INF("FAIL");
@@ -681,11 +662,11 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
}
if (not_bound) {
char * msg;
- spprintf(&msg, 0, "No data supplied for %u parameter%s in prepared statement",
- not_bound, not_bound>1 ?"s":"");
+ mnd_sprintf(&msg, 0, "No data supplied for %u parameter%s in prepared statement",
+ not_bound, not_bound>1 ?"s":"");
SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg);
if (msg) {
- efree(msg); /* allocated by spprintf */
+ mnd_sprintf_free(msg);
}
DBG_INF("FAIL");
DBG_RETURN(FAIL);
@@ -694,7 +675,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
ret = s->m->generate_execute_request(s, &request, &request_len, &free_request TSRMLS_CC);
if (ret == PASS) {
/* support for buffer types should be added here ! */
- ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, (char *)request, request_len,
+ ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, request, request_len,
PROT_LAST /* we will handle the response packet*/,
FALSE, FALSE TSRMLS_CC);
} else {
@@ -706,7 +687,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
}
if (ret == FAIL) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -714,10 +695,10 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
ret = s->m->parse_execute_response(s TSRMLS_CC);
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status.server_status, stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
- if (ret == PASS && conn->last_query_type == QUERY_UPSERT && stmt->upsert_status.affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, stmt->upsert_status.affected_rows);
+ if (ret == PASS && conn->last_query_type == QUERY_UPSERT && stmt->upsert_status->affected_rows) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, stmt->upsert_status->affected_rows);
}
DBG_RETURN(ret);
}
@@ -753,9 +734,8 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
current_row,
meta->field_count,
meta->fields,
- result->stored_data->persistent,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(FAIL);
@@ -838,11 +818,11 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
if (result->unbuf->eof_reached) {
/* No more rows obviously */
- DBG_INF("eof reached");
+ DBG_INF("EOF already reached");
DBG_RETURN(PASS);
}
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
@@ -864,7 +844,6 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
if (!row_packet->skip_extraction) {
result->m.unbuffered_free_last_data(result TSRMLS_CC);
- DBG_INF("extracting data");
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
row_packet->fields = NULL;
@@ -874,9 +853,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC))
{
DBG_RETURN(FAIL);
@@ -926,8 +904,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
*fetched_anything = TRUE;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- stmt->conn->error_info = row_packet->error_info;
- stmt->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(*stmt->conn->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(*stmt->error_info, row_packet->error_info);
}
CONN_SET_STATE(result->conn, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
@@ -935,13 +913,13 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
DBG_INF("EOF");
/* Mark the connection as usable again */
result->unbuf->eof_reached = TRUE;
- result->conn->upsert_status.warning_count = row_packet->warning_count;
- result->conn->upsert_status.server_status = row_packet->server_status;
+ result->conn->upsert_status->warning_count = row_packet->warning_count;
+ result->conn->upsert_status->server_status = row_packet->server_status;
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(result->conn, CONN_READY);
@@ -959,8 +937,8 @@ static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND_RES *result;
- MYSQLND * conn;
+ MYSQLND_RES * result;
+ MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt::use_result");
if (!stmt || !stmt->conn || !stmt->result) {
@@ -975,18 +953,17 @@ MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s TSRMLS_DC)
(stmt->cursor_exists && CONN_GET_STATE(conn) != CONN_READY) ||
(stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE))
{
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(NULL);
}
- SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_PS_UNBUFFERED_SETS);
result = stmt->result;
- DBG_INF_FMT("%scursor exists", stmt->cursor_exists? "":"no ");
result->m.use_result(stmt->result, TRUE TSRMLS_CC);
result->m.fetch_row = stmt->cursor_exists? mysqlnd_fetch_stmt_row_cursor:
mysqlnd_stmt_fetch_row_unbuffered;
@@ -1021,7 +998,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
if (stmt->state < MYSQLND_STMT_USER_FETCHING) {
/* Only initted - error */
- SET_CLIENT_ERROR(stmt->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*stmt->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
@@ -1030,16 +1007,16 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
int4store(buf, stmt->stmt_id);
int4store(buf + STMT_ID_LENGTH, 1); /* for now fetch only one row */
- if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, (char *)buf, sizeof(buf),
+ if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, buf, sizeof(buf),
PROT_LAST /* we will handle the response packet*/,
FALSE, TRUE TSRMLS_CC)) {
- stmt->error_info = stmt->conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *stmt->conn->error_info);
DBG_RETURN(FAIL);
}
@@ -1048,11 +1025,9 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
unsigned int i, field_count = result->field_count;
- DBG_INF_FMT("skip_extraction=%u", row_packet->skip_extraction);
if (!row_packet->skip_extraction) {
result->m.unbuffered_free_last_data(result TSRMLS_CC);
- DBG_INF("extracting data");
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
row_packet->fields = NULL;
@@ -1062,9 +1037,8 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC))
{
DBG_RETURN(FAIL);
@@ -1123,21 +1097,21 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
} else {
*fetched_anything = FALSE;
- stmt->upsert_status.warning_count =
- stmt->conn->upsert_status.warning_count =
+ stmt->upsert_status->warning_count =
+ stmt->conn->upsert_status->warning_count =
row_packet->warning_count;
- stmt->upsert_status.server_status =
- stmt->conn->upsert_status.server_status =
+ stmt->upsert_status->server_status =
+ stmt->conn->upsert_status->server_status =
row_packet->server_status;
result->unbuf->eof_reached = row_packet->eof;
}
- stmt->upsert_status.warning_count =
- stmt->conn->upsert_status.warning_count =
+ stmt->upsert_status->warning_count =
+ stmt->conn->upsert_status->warning_count =
row_packet->warning_count;
- stmt->upsert_status.server_status =
- stmt->conn->upsert_status.server_status =
+ stmt->upsert_status->server_status =
+ stmt->conn->upsert_status->server_status =
row_packet->server_status;
DBG_INF_FMT("ret=%s fetched=%u server_status=%u warnings=%u eof=%u",
@@ -1174,8 +1148,8 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
}
stmt->state = MYSQLND_STMT_USER_FETCHING;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
DBG_INF_FMT("result_bind=%p separated_once=%u", stmt->result_bind, stmt->result_zvals_separated_once);
/*
@@ -1217,11 +1191,11 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s TSRMLS_DC)
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->stmt_id) {
- MYSQLND * conn = stmt->conn;
+ MYSQLND_CONN_DATA * conn = stmt->conn;
if (stmt->param_bind) {
unsigned int i;
DBG_INF("resetting long data");
@@ -1233,6 +1207,43 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s TSRMLS_DC)
}
}
+ s->m->flush(s TSRMLS_CC);
+
+ /*
+ Don't free now, let the result be usable. When the stmt will again be
+ executed then the result set will be cleaned, the bound variables will
+ be separated before that.
+ */
+
+ int4store(cmd_buf, stmt->stmt_id);
+ if (CONN_GET_STATE(conn) == CONN_READY &&
+ FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, cmd_buf,
+ sizeof(cmd_buf), PROT_OK_PACKET,
+ FALSE, TRUE TSRMLS_CC))) {
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ }
+ *stmt->upsert_status = *conn->upsert_status;
+ }
+ DBG_INF(ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stmt::flush */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_stmt, flush)(MYSQLND_STMT * const s TSRMLS_DC)
+{
+ MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ enum_func_status ret = PASS;
+
+ DBG_ENTER("mysqlnd_stmt::flush");
+ if (!stmt || !stmt->conn) {
+ DBG_RETURN(FAIL);
+ }
+ DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
+
+ if (stmt->stmt_id) {
/*
If the user decided to close the statement right after execute()
We have to call the appropriate use_result() or store_result() and
@@ -1250,21 +1261,6 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s TSRMLS_DC)
stmt->result->m.skip_result(stmt->result TSRMLS_CC);
}
} while (mysqlnd_stmt_more_results(s) && mysqlnd_stmt_next_result(s) == PASS);
-
- /*
- Don't free now, let the result be usable. When the stmt will again be
- executed then the result set will be cleaned, the bound variables will
- be separated before that.
- */
-
- int4store(cmd_buf, stmt->stmt_id);
- if (CONN_GET_STATE(conn) == CONN_READY &&
- FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, (char *)cmd_buf,
- sizeof(cmd_buf), PROT_OK_PACKET,
- FALSE, TRUE TSRMLS_CC))) {
- stmt->error_info = conn->error_info;
- }
- stmt->upsert_status = conn->upsert_status;
}
DBG_INF(ret == PASS? "PASS":"FAIL");
DBG_RETURN(ret);
@@ -1279,8 +1275,8 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret = FAIL;
- MYSQLND * conn;
- zend_uchar *cmd_buf;
+ MYSQLND_CONN_DATA * conn;
+ zend_uchar * cmd_buf;
enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA;
DBG_ENTER("mysqlnd_stmt::send_long_data");
@@ -1291,8 +1287,8 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
conn = stmt->conn;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
@@ -1304,7 +1300,6 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
}
-
if (param_no >= stmt->param_count) {
SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
DBG_ERR("invalid param_no");
@@ -1337,15 +1332,15 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length);
/* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/
- ret = conn->m->simple_command(conn, cmd, (char *)cmd_buf, packet_len, PROT_LAST , FALSE, TRUE TSRMLS_CC);
+ ret = conn->m->simple_command(conn, cmd, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE TSRMLS_CC);
mnd_efree(cmd_buf);
if (FAIL == ret) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
}
} else {
ret = FAIL;
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*conn->error_info);
}
/*
Cover protocol error: COM_STMT_SEND_LONG_DATA was designed to be quick and not
@@ -1405,8 +1400,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->param_count) {
unsigned int i = 0;
@@ -1423,8 +1418,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
*/
for (i = 0; i < stmt->param_count; i++) {
/*
- We may have the last reference, then call zval_ptr_dtor()
- or we may leak memory.
+ We may have the last reference, then call zval_ptr_dtor() or we may leak memory.
Switching from bind_one_parameter to bind_parameters may result in zv being NULL
*/
if (stmt->param_bind[i].zv) {
@@ -1466,8 +1460,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
if (!stmt || !stmt->conn) {
DBG_RETURN(FAIL);
}
- DBG_INF_FMT("stmt=%lu param_no=%u param_count=%u type=%u",
- stmt->stmt_id, param_no, stmt->param_count, type);
+ DBG_INF_FMT("stmt=%lu param_no=%u param_count=%u type=%u", stmt->stmt_id, param_no, stmt->param_count, type);
if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
@@ -1480,8 +1473,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
DBG_ERR("invalid param_no");
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->param_count) {
if (!stmt->param_bind) {
@@ -1531,13 +1524,12 @@ MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const s TSRMLS_D
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->param_count) {
stmt->send_types_to_server = 1;
}
- DBG_INF("PASS");
DBG_RETURN(PASS);
}
/* }}} */
@@ -1564,8 +1556,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->field_count) {
unsigned int i = 0;
@@ -1621,8 +1613,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned i
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->field_count) {
mysqlnd_stmt_separate_one_result_bind(s, param_no TSRMLS_CC);
@@ -1654,7 +1646,7 @@ static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.last_insert_id : 0;
+ return stmt? stmt->upsert_status->last_insert_id : 0;
}
/* }}} */
@@ -1664,7 +1656,7 @@ static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, affected_rows)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.affected_rows : 0;
+ return stmt? stmt->upsert_status->affected_rows : 0;
}
/* }}} */
@@ -1684,7 +1676,7 @@ static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, warning_count)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.warning_count : 0;
+ return stmt? stmt->upsert_status->warning_count : 0;
}
/* }}} */
@@ -1694,7 +1686,7 @@ static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, server_status)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.server_status : 0;
+ return stmt? stmt->upsert_status->server_status : 0;
}
/* }}} */
@@ -1724,7 +1716,7 @@ static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, errno)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->error_info.error_no : 0;
+ return stmt? stmt->error_info->error_no : 0;
}
/* }}} */
@@ -1734,7 +1726,7 @@ static const char *
MYSQLND_METHOD(mysqlnd_stmt, error)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->error_info.error : 0;
+ return stmt? stmt->error_info->error : 0;
}
/* }}} */
@@ -1744,7 +1736,7 @@ static const char *
MYSQLND_METHOD(mysqlnd_stmt, sqlstate)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt && stmt->error_info.sqlstate[0] ? stmt->error_info.sqlstate:MYSQLND_SQLSTATE_NULL;
+ return stmt && stmt->error_info->sqlstate[0] ? stmt->error_info->sqlstate:MYSQLND_SQLSTATE_NULL;
}
/* }}} */
@@ -1824,7 +1816,7 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s TSRMLS_DC)
DBG_RETURN(result);
} while (0);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
if (result) {
result->m.free_result(result, TRUE TSRMLS_CC);
}
@@ -1919,6 +1911,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const s,
}
/* }}} */
+
/* free_result() doesn't actually free stmt->result but only the buffers */
/* {{{ mysqlnd_stmt::free_result */
static enum_func_status
@@ -1985,8 +1978,7 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s TSRMLS_DC)
if (!stmt) {
DBG_VOID_RETURN;
}
- DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u",
- stmt->stmt_id, stmt->result_bind, stmt->field_count);
+ DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u", stmt->stmt_id, stmt->result_bind, stmt->field_count);
if (!stmt->result_bind) {
DBG_VOID_RETURN;
@@ -2040,8 +2032,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param
if (!stmt) {
DBG_VOID_RETURN;
}
- DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u param_no=%u",
- stmt->stmt_id, stmt->result_bind, stmt->field_count, param_no);
+ DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u param_no=%u", stmt->stmt_id, stmt->result_bind, stmt->field_count, param_no);
if (!stmt->result_bind) {
DBG_VOID_RETURN;
@@ -2091,8 +2082,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC
if (!stmt) {
DBG_VOID_RETURN;
}
- DBG_INF_FMT("stmt=%lu param_bind=%p param_count=%u",
- stmt->stmt_id, stmt->param_bind, stmt->param_count);
+ DBG_INF_FMT("stmt=%lu param_bind=%p param_count=%u", stmt->stmt_id, stmt->param_bind, stmt->param_count);
/* Destroy the input bind */
if (stmt->param_bind) {
@@ -2125,6 +2115,11 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC
stmt->result->m.free_result_internal(stmt->result TSRMLS_CC);
stmt->result = NULL;
}
+ if (stmt->error_info->error_list) {
+ zend_llist_clean(stmt->error_info->error_list);
+ mnd_pefree(stmt->error_info->error_list, s->persistent);
+ stmt->error_info->error_list = NULL;
+ }
DBG_VOID_RETURN;
}
@@ -2136,7 +2131,7 @@ static enum_func_status
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_bool implicit TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */];
enum_mysqlnd_collected_stats statistic = STAT_LAST;
@@ -2148,8 +2143,8 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
conn = stmt->conn;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
/*
If the user decided to close the statement right after execute()
@@ -2157,7 +2152,6 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
clean.
*/
do {
- DBG_INF_FMT("stmt->state=%u", stmt->state);
if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
DBG_INF("fetching result set header");
stmt->default_rset_handler(s TSRMLS_CC);
@@ -2180,10 +2174,10 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
int4store(cmd_buf, stmt->stmt_id);
if (CONN_GET_STATE(conn) == CONN_READY &&
- FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, (char *)cmd_buf, sizeof(cmd_buf),
+ FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf),
PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/,
FALSE, TRUE TSRMLS_CC)) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
DBG_RETURN(FAIL);
}
}
@@ -2227,7 +2221,6 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const s, zend_bool implicit TS
DBG_ENTER("mysqlnd_stmt::dtor");
if (stmt) {
-
DBG_INF_FMT("stmt=%p", stmt);
MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_STMT_CLOSE_IMPLICIT:
@@ -2345,68 +2338,19 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt)
MYSQLND_METHOD(mysqlnd_stmt, server_status),
mysqlnd_stmt_execute_generate_request,
mysqlnd_stmt_execute_parse_response,
- MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)
+ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content),
+ MYSQLND_METHOD(mysqlnd_stmt, flush)
MYSQLND_CLASS_METHODS_END;
/* {{{ _mysqlnd_stmt_init */
-MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_STMT *
+_mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- size_t alloc_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_STMT * ret = mnd_pecalloc(1, alloc_size, conn->persistent);
- MYSQLND_STMT_DATA * stmt = NULL;
-
+ MYSQLND_STMT * ret;
DBG_ENTER("_mysqlnd_stmt_init");
- do {
- if (!ret) {
- break;
- }
- ret->m = mysqlnd_stmt_methods;
- ret->persistent = conn->persistent;
-
- stmt = ret->data = mnd_pecalloc(1, sizeof(MYSQLND_STMT_DATA), conn->persistent);
- DBG_INF_FMT("stmt=%p", stmt);
- if (!stmt) {
- break;
- }
- stmt->persistent = conn->persistent;
- stmt->state = MYSQLND_STMT_INITTED;
- stmt->execute_cmd_buffer.length = 4096;
- stmt->execute_cmd_buffer.buffer = mnd_pemalloc(stmt->execute_cmd_buffer.length, stmt->persistent);
- if (!stmt->execute_cmd_buffer.buffer) {
- break;
- }
-
- stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS;
- /*
- Mark that we reference the connection, thus it won't be
- be destructed till there is open statements. The last statement
- or normal query result will close it then.
- */
- stmt->conn = conn->m->get_reference(conn TSRMLS_CC);
-
- DBG_RETURN(ret);
- } while (0);
-
- SET_OOM_ERROR(conn->error_info);
- if (ret) {
- ret->m->dtor(ret, TRUE TSRMLS_CC);
- ret = NULL;
- }
- DBG_RETURN(NULL);
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_plugin_get_plugin_stmt_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_stmt_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!stmt || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)stmt + sizeof(MYSQLND_STMT) + plugin_id * sizeof(void *)));
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_prepared_statement(conn TSRMLS_CC);
+ DBG_RETURN(ret);
}
/* }}} */
@@ -2414,28 +2358,12 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, u
/* {{{ _mysqlnd_init_ps_subsystem */
void _mysqlnd_init_ps_subsystem()
{
- mysqlnd_stmt_methods = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_stmt);
+ mysqlnd_stmt_set_methods(&MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_stmt));
_mysqlnd_init_ps_fetch_subsystem();
}
/* }}} */
-/* {{{ mysqlnd_conn_get_methods */
-PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods()
-{
- return mysqlnd_stmt_methods;
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn_set_methods */
-PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods)
-{
- mysqlnd_stmt_methods = methods;
-}
-/* }}} */
-
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index 8e1db9b57b..ce0736fdff 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -258,18 +258,14 @@ void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
t.time_type = MYSQLND_TIMESTAMP_TIME;
}
- /*
- QQ : How to make this unicode without copying two times the buffer -
- Unicode equivalent of spprintf?
- */
- length = spprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
+ length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, value, length, 1);
- efree(value); /* allocated by spprintf */
+ mnd_sprintf_free(value);
#if MYSQLND_UNICODE
} else {
ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
@@ -309,18 +305,14 @@ void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field,
t.time_type = MYSQLND_TIMESTAMP_DATE;
}
- /*
- QQ : How to make this unicode without copying two times the buffer -
- Unicode equivalent of spprintf?
- */
- length = spprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
+ length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, value, length, 1);
- efree(value); /* allocated by spprintf */
+ mnd_sprintf_free(value);
#if MYSQLND_UNICODE
} else {
ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
@@ -367,19 +359,14 @@ void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field,
t.time_type = MYSQLND_TIMESTAMP_DATETIME;
}
- /*
- QQ : How to make this unicode without copying two times the buffer -
- Unicode equivalent of spprintf?
- */
- length = spprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u",
- t.year, t.month, t.day, t.hour, t.minute, t.second);
+ length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second);
DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, value, length, 1);
- efree(value); /* allocated by spprintf */
+ mnd_sprintf_free(value);
#if MYSQLND_UNICODE
} else {
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
@@ -621,7 +608,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
*buf_len = offset + null_count + 20;
tmp_buf = mnd_emalloc(*buf_len);
if (!tmp_buf) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
memcpy(tmp_buf, *buf, offset);
@@ -655,7 +642,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
PASS != mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
{
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
/*
@@ -683,7 +670,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
*buf_len = offset + stmt->param_count * 2 + 20;
tmp_buf = mnd_emalloc(*buf_len);
if (!tmp_buf) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
memcpy(tmp_buf, *buf, offset);
@@ -746,7 +733,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
/* Double binding of the same zval, make a copy */
if (!copies || !copies[i]) {
if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
@@ -760,7 +747,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
if (!copies || !copies[i]) {
if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
@@ -807,7 +794,7 @@ use_string:
{
if (!copies || !copies[i]) {
if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
@@ -832,7 +819,7 @@ use_string:
*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
tmp_buf = mnd_emalloc(*buf_len);
if (!tmp_buf) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
memcpy(tmp_buf, *buf, offset);
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index f238cc49ad..8ae2665ba7 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -28,6 +28,7 @@
#include "mysqlnd_result_meta.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_ext_plugin.h"
#define MYSQLND_SILENT
@@ -54,9 +55,8 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu
data_cursor,
result->meta->field_count,
result->meta->fields,
- result->stored_data->persistent,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
ret = FAIL;
@@ -150,13 +150,11 @@ MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRM
DBG_VOID_RETURN;
}
- DBG_INF_FMT("last_row_data=%p", unbuf->last_row_data);
if (unbuf->last_row_data) {
unsigned int i, ctor_called_count = 0;
zend_bool copy_ctor_called;
MYSQLND_STATS *global_stats = result->conn? result->conn->stats:NULL;
- DBG_INF_FMT("%u columns to free", result->field_count);
for (i = 0; i < result->field_count; i++) {
mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, &copy_ctor_called TSRMLS_CC);
if (copy_ctor_called) {
@@ -197,12 +195,10 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC)
DBG_ENTER("mysqlnd_res::free_buffered_data");
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
- DBG_INF("Freeing data & row_buffer");
if (set->data) {
unsigned int copy_on_write_performed = 0;
unsigned int copy_on_write_saved = 0;
- DBG_INF_FMT("before: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
for (row = set->row_count - 1; row >= 0; row--) {
zval **current_row = set->data + row * field_count;
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
@@ -213,9 +209,6 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC)
if (current_row[col]) {
zend_bool copy_ctor_called;
mysqlnd_rset_zval_ptr_dtor(&(current_row[col]), result->type, &copy_ctor_called TSRMLS_CC);
-#if MYSQLND_DEBUG_MEMORY
- DBG_INF_FMT("Copy_ctor_called=%u", copy_ctor_called);
-#endif
if (copy_ctor_called) {
++copy_on_write_performed;
} else {
@@ -224,29 +217,24 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC)
}
}
}
-#if MYSQLND_DEBUG_MEMORY
- DBG_INF("Freeing current_row & current_buffer");
-#endif
current_buffer->free_chunk(current_buffer TSRMLS_CC);
}
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_COPY_ON_WRITE_PERFORMED, copy_on_write_performed,
STAT_COPY_ON_WRITE_SAVED, copy_on_write_saved);
- mnd_pefree(set->data, set->persistent);
+ mnd_efree(set->data);
set->data = NULL;
}
if (set->row_buffers) {
- mnd_pefree(set->row_buffers, set->persistent);
+ mnd_efree(set->row_buffers);
set->row_buffers = NULL;
}
set->data_cursor = NULL;
set->row_count = 0;
- DBG_INF("Freeing set");
- mnd_pefree(set, set->persistent);
+ mnd_efree(set);
- DBG_INF_FMT("after: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
DBG_VOID_RETURN;
}
/* }}} */
@@ -274,13 +262,11 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result TSRMLS_DC)
}
if (result->row_packet) {
- DBG_INF("Freeing packet");
PACKET_FREE(result->row_packet);
result->row_packet = NULL;
}
if (result->result_set_memory_pool) {
- DBG_INF("Freeing memory pool");
mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC);
result->result_set_memory_pool = NULL;
}
@@ -329,7 +315,7 @@ void mysqlnd_internal_free_result(MYSQLND_RES * result TSRMLS_DC)
/* {{{ mysqlnd_res::read_result_metadata */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND *conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::read_result_metadata");
@@ -346,7 +332,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND
result->meta = result->m.result_meta_init(result->field_count, result->persistent TSRMLS_CC);
if (!result->meta) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(FAIL);
}
@@ -374,7 +360,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND
/* {{{ mysqlnd_query_read_result_set_header */
enum_func_status
-mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
+mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s ? s->data:NULL;
enum_func_status ret;
@@ -388,7 +374,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
do {
rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE TSRMLS_CC);
if (!rset_header) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -410,19 +396,19 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
a multi-statement or a stored procedure, so it should be
safe to unconditionally turn off the flag here.
*/
- conn->upsert_status.server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
/*
This will copy the error code and the messages, as they
are buffers in the struct
*/
- conn->error_info = rset_header->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, rset_header->error_info);
ret = FAIL;
DBG_ERR_FMT("error=%s", rset_header->error_info.error);
/* Return back from CONN_QUERY_SENT */
CONN_SET_STATE(conn, CONN_READY);
break;
}
- conn->error_info.error_no = 0;
+ conn->error_info->error_no = 0;
switch (rset_header->field_count) {
case MYSQLND_NULL_LENGTH: { /* LOAD DATA LOCAL INFILE */
@@ -440,15 +426,15 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
DBG_INF("UPSERT");
conn->last_query_type = QUERY_UPSERT;
conn->field_count = rset_header->field_count;
- conn->upsert_status.warning_count = rset_header->warning_count;
- conn->upsert_status.server_status = rset_header->server_status;
- conn->upsert_status.affected_rows = rset_header->affected_rows;
- conn->upsert_status.last_insert_id = rset_header->last_insert_id;
+ conn->upsert_status->warning_count = rset_header->warning_count;
+ conn->upsert_status->server_status = rset_header->server_status;
+ conn->upsert_status->affected_rows = rset_header->affected_rows;
+ conn->upsert_status->last_insert_id = rset_header->last_insert_id;
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
rset_header->info_or_local_file, rset_header->info_or_local_file_len,
conn->persistent);
/* Result set can follow UPSERT statement, check server_status */
- if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(conn, CONN_READY);
@@ -464,7 +450,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_RSET_QUERY);
- memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
+ memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
/* restore after zeroing */
SET_ERROR_AFF_ROWS(conn);
@@ -500,7 +486,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
result = stmt->result;
}
if (!result) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -518,7 +504,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
/* Check for SERVER_STATUS_MORE_RESULTS if needed */
fields_eof = conn->protocol->m.get_eof_packet(conn->protocol, FALSE TSRMLS_CC);
if (!fields_eof) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -537,7 +523,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
unsigned int to_log = MYSQLND_G(log_mask);
to_log &= fields_eof->server_status;
DBG_INF_FMT("warnings=%u server_status=%u", fields_eof->warning_count, fields_eof->server_status);
- conn->upsert_status.warning_count = fields_eof->warning_count;
+ conn->upsert_status->warning_count = fields_eof->warning_count;
/*
If SERVER_MORE_RESULTS_EXISTS is set then this is either MULTI_QUERY or a CALL()
The first packet after sending the query/com_execute has the bit set only
@@ -545,7 +531,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
will include many result sets. What actually matters are the bits set at the end
of every result set (the EOF packet).
*/
- conn->upsert_status.server_status = fields_eof->server_status;
+ conn->upsert_status->server_status = fields_eof->server_status;
if (fields_eof->server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) {
statistic = STAT_BAD_INDEX_USED;
} else if (fields_eof->server_status & SERVER_QUERY_NO_INDEX_USED) {
@@ -648,7 +634,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
DBG_RETURN(retrow);
}
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(retrow);
}
@@ -683,9 +669,8 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(retrow);
@@ -715,27 +700,27 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
}
}
} else {
- SET_OOM_ERROR(result->conn->error_info);
+ SET_OOM_ERROR(*result->conn->error_info);
}
}
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- result->conn->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
CONN_SET_STATE(result->conn, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
/* Mark the connection as usable again */
- DBG_INF_FMT("warningss=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
+ DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- result->conn->upsert_status.warning_count = row_packet->warning_count;
- result->conn->upsert_status.server_status = row_packet->server_status;
+ result->conn->upsert_status->warning_count = row_packet->warning_count;
+ result->conn->upsert_status->server_status = row_packet->server_status;
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(result->conn, CONN_READY);
@@ -757,7 +742,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
MYSQLND_PACKET_ROW *row_packet = result->row_packet;
DBG_ENTER("mysqlnd_fetch_row_unbuffered");
- DBG_INF_FMT("flags=%u", flags);
*fetched_anything = FALSE;
if (result->unbuf->eof_reached) {
@@ -765,7 +749,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
DBG_RETURN(PASS);
}
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(FAIL);
}
if (!row_packet) {
@@ -800,9 +784,8 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
result->unbuf->last_row_data,
field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(FAIL);
@@ -857,7 +840,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
result->unbuf->row_count++;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- result->conn->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
CONN_SET_STATE(result->conn, CONN_READY);
@@ -866,13 +849,13 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
/* Mark the connection as usable again */
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- result->conn->upsert_status.warning_count = row_packet->warning_count;
- result->conn->upsert_status.server_status = row_packet->server_status;
+ result->conn->upsert_status->warning_count = row_packet->warning_count;
+ result->conn->upsert_status->server_status = row_packet->server_status;
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(result->conn, CONN_READY);
@@ -891,10 +874,8 @@ static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::use_result");
- DBG_INF_FMT("ps=%u", ps);
-
- SET_EMPTY_ERROR(result->conn->error_info);
+ SET_EMPTY_ERROR(*result->conn->error_info);
if (ps == FALSE) {
result->type = MYSQLND_RES_NORMAL;
@@ -939,7 +920,7 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
DBG_RETURN(result);
oom:
- SET_OOM_ERROR(result->conn->error_info);
+ SET_OOM_ERROR(*result->conn->error_info);
DBG_RETURN(NULL);
}
/* }}} */
@@ -969,9 +950,8 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC)
current_row,
result->meta->field_count,
result->meta->fields,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(ret);
@@ -1028,7 +1008,6 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_fetch_row_buffered");
- DBG_INF_FMT("flags=%u row=%p", flags, row);
/* If we haven't read everything */
if (set->data_cursor &&
@@ -1044,9 +1023,8 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
current_row,
result->meta->field_count,
result->meta->fields,
- result->stored_data->persistent,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(FAIL);
@@ -1124,10 +1102,9 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
/* {{{ mysqlnd_res::store_result_fetch_data */
enum_func_status
-MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQLND_RES * result,
+MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result,
MYSQLND_RES_METADATA *meta,
- zend_bool binary_protocol,
- zend_bool to_cache TSRMLS_DC)
+ zend_bool binary_protocol TSRMLS_DC)
{
enum_func_status ret;
MYSQLND_PACKET_ROW *row_packet = NULL;
@@ -1135,33 +1112,27 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
MYSQLND_RES_BUFFERED *set;
DBG_ENTER("mysqlnd_res::store_result_fetch_data");
- DBG_INF_FMT("conn=%llu binary_proto=%u to_cache=%u",
- conn->thread_id, binary_protocol, to_cache);
- result->stored_data = set = mnd_pecalloc(1, sizeof(MYSQLND_RES_BUFFERED), to_cache);
+ result->stored_data = set = mnd_ecalloc(1, sizeof(MYSQLND_RES_BUFFERED));
if (!set) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
if (free_rows) {
- set->row_buffers = mnd_pemalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), to_cache);
+ set->row_buffers = mnd_emalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
if (!set->row_buffers) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
}
- set->persistent = to_cache;
set->references = 1;
- result->m.row_decoder = binary_protocol? php_mysqlnd_rowp_read_binary_protocol:
- php_mysqlnd_rowp_read_text_protocol;
-
/* non-persistent */
row_packet = conn->protocol->m.get_row_packet(conn->protocol, FALSE TSRMLS_CC);
if (!row_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
@@ -1182,15 +1153,13 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
- new_row_buffers = mnd_perealloc(set->row_buffers,
- (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)),
- set->persistent);
+ new_row_buffers = mnd_erealloc(set->row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
if (!new_row_buffers) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
@@ -1216,14 +1185,14 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
if (set->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
- set->data = mnd_pemalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)), to_cache);
+ set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)));
if (!set->data) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
@@ -1237,39 +1206,37 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
/* Finally clean */
if (row_packet->eof) {
- conn->upsert_status.warning_count = row_packet->warning_count;
- conn->upsert_status.server_status = row_packet->server_status;
+ conn->upsert_status->warning_count = row_packet->warning_count;
+ conn->upsert_status->server_status = row_packet->server_status;
}
/* save some memory */
if (free_rows) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
- set->row_buffers = mnd_perealloc(set->row_buffers,
- (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)),
- set->persistent);
+ set->row_buffers = mnd_erealloc(set->row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
}
- if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(conn, CONN_READY);
}
if (ret == FAIL) {
- set->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(set->error_info, row_packet->error_info);
} else {
/* Position at the first row */
set->data_cursor = set->data;
/* libmysql's documentation says it should be so for SELECT statements */
- conn->upsert_status.affected_rows = set->row_count;
+ conn->upsert_status->affected_rows = set->row_count;
}
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u",
- ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
+ ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status->warning_count, conn->upsert_status->server_status);
end:
PACKET_FREE(row_packet);
@@ -1281,41 +1248,42 @@ end:
/* {{{ mysqlnd_res::store_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
- MYSQLND * const conn,
+ MYSQLND_CONN_DATA * const conn,
zend_bool ps_protocol TSRMLS_DC)
{
enum_func_status ret;
- zend_bool to_cache = FALSE;
DBG_ENTER("mysqlnd_res::store_result");
- DBG_INF_FMT("conn=%u ps_protocol=%u", conn->thread_id, ps_protocol);
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
result->conn = conn->m->get_reference(conn TSRMLS_CC);
result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_buffered;
result->m.fetch_lengths = mysqlnd_fetch_lengths_buffered;
+ result->m.row_decoder = ps_protocol? php_mysqlnd_rowp_read_binary_protocol:
+ php_mysqlnd_rowp_read_text_protocol;
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
+
if (!result->result_set_memory_pool || !result->lengths) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
- ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol, to_cache TSRMLS_CC);
+ ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol TSRMLS_CC);
if (FAIL == ret) {
if (result->stored_data) {
- conn->error_info = result->stored_data->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
} else {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
}
DBG_RETURN(NULL);
}
/* libmysql's documentation says it should be so for SELECT statements */
- conn->upsert_status.affected_rows = result->stored_data->row_count;
+ conn->upsert_status->affected_rows = result->stored_data->row_count;
DBG_RETURN(result);
}
@@ -1357,7 +1325,6 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::free_result");
- DBG_INF_FMT("implicit=%u", implicit);
result->m.skip_result(result TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(result->conn? result->conn->stats : NULL,
@@ -1522,9 +1489,6 @@ MYSQLND_METHOD(mysqlnd_res, field_tell)(const MYSQLND_RES * const result TSRMLS_
/* }}} */
-/* for php_addslashes */
-#include "ext/standard/php_string.h"
-
/* {{{ mysqlnd_res::fetch_into */
static void
MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags,
@@ -1534,7 +1498,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags
zend_bool fetched_anything;
DBG_ENTER("mysqlnd_res::fetch_into");
- DBG_INF_FMT("flags=%u mysqlnd_extension=%u", flags, extension);
if (!result->m.fetch_row) {
RETVAL_NULL();
@@ -1559,7 +1522,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags
break;
default:exit(0);
}
- }
+ }
/*
return_value is IS_NULL for no more data and an array for data. Thus it's ok
to return here.
@@ -1599,12 +1562,11 @@ MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, unsigned int flags,
MYSQLND_RES_BUFFERED *set = result->stored_data;
DBG_ENTER("mysqlnd_res::fetch_all");
- DBG_INF_FMT("flags=%u", flags);
if ((!result->unbuf && !set)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "fetch_all can be used only with buffered sets");
if (result->conn) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
}
RETVAL_NULL();
DBG_VOID_RETURN;
@@ -1672,7 +1634,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int
/* }}} */
-static
MYSQLND_CLASS_METHODS_START(mysqlnd_res)
NULL, /* fetch_row */
mysqlnd_fetch_row_buffered,
@@ -1717,7 +1678,6 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC)
MYSQLND_RES *ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_init");
- DBG_INF_FMT("field_count=%u", field_count);
if (!ret) {
DBG_RETURN(NULL);
@@ -1725,34 +1685,13 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC)
ret->persistent = persistent;
ret->field_count = field_count;
- ret->m = mysqlnd_mysqlnd_res_methods;
+ ret->m = *mysqlnd_result_get_methods();
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_result_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!result || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES) + plugin_id * sizeof(void *)));
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_result_get_methods */
-PHPAPI struct st_mysqlnd_res_methods *
-mysqlnd_result_get_methods()
-{
- return &mysqlnd_mysqlnd_res_methods;
-}
-/* }}} */
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_result.h b/ext/mysqlnd/mysqlnd_result.h
index 658db741ea..f5ee79174a 100644
--- a/ext/mysqlnd/mysqlnd_result.h
+++ b/ext/mysqlnd/mysqlnd_result.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -24,9 +24,8 @@
#define MYSQLND_RESULT_H
PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC);
-PHPAPI struct st_mysqlnd_res_methods * mysqlnd_result_get_methods();
-enum_func_status mysqlnd_query_read_result_set_header(MYSQLND * conn, MYSQLND_STMT * stmt TSRMLS_DC);
+enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC);
#endif /* MYSQLND_RESULT_H */
diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c
index f19bc02910..9469ceaf11 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.c
+++ b/ext/mysqlnd/mysqlnd_result_meta.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -138,7 +138,7 @@ mysqlnd_unicode_is_key_numeric(UChar *key, size_t length, long *idx)
/* {{{ mysqlnd_res_meta::read_metadata */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
unsigned int i = 0;
MYSQLND_PACKET_RES_FIELD * field_packet;
@@ -151,7 +151,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
field_packet = conn->protocol->m.get_result_field_packet(conn->protocol, FALSE TSRMLS_CC);
if (!field_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(FAIL);
}
field_packet->persistent_alloc = meta->persistent;
@@ -170,7 +170,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
DBG_RETURN(FAIL);
}
if (field_packet->error_info.error_no) {
- conn->error_info = field_packet->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, field_packet->error_info);
/* Return back from CONN_QUERY_SENT */
PACKET_FREE(field_packet);
DBG_RETURN(FAIL);
diff --git a/ext/mysqlnd/mysqlnd_result_meta.h b/ext/mysqlnd/mysqlnd_result_meta.h
index cf45b88556..e81e0db83b 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.h
+++ b/ext/mysqlnd/mysqlnd_result_meta.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.c b/ext/mysqlnd/mysqlnd_reverse_api.c
new file mode 100644
index 0000000000..0b77b5a949
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_reverse_api.c
@@ -0,0 +1,100 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 317989 2011-10-10 20:49:28Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_reverse_api.h"
+
+
+static HashTable mysqlnd_api_ext_ht;
+
+
+/* {{{ mysqlnd_reverse_api_init */
+PHPAPI void
+mysqlnd_reverse_api_init(TSRMLS_D)
+{
+ zend_hash_init(&mysqlnd_api_ext_ht, 3, NULL, NULL, 1);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_reverse_api_end */
+PHPAPI void
+mysqlnd_reverse_api_end(TSRMLS_D)
+{
+ zend_hash_destroy(&mysqlnd_api_ext_ht);
+}
+/* }}} */
+
+
+/* {{{ myslqnd_get_api_extensions */
+PHPAPI HashTable *
+mysqlnd_reverse_api_get_api_list(TSRMLS_D)
+{
+ return &mysqlnd_api_ext_ht;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_reverse_api_register_api */
+PHPAPI void
+mysqlnd_reverse_api_register_api(MYSQLND_REVERSE_API * apiext TSRMLS_DC)
+{
+ zend_hash_add(&mysqlnd_api_ext_ht, apiext->module->name, strlen(apiext->module->name) + 1, &apiext,
+ sizeof(MYSQLND_REVERSE_API), NULL);
+}
+/* }}} */
+
+
+/* {{{ zval_to_mysqlnd */
+PHPAPI MYSQLND *
+zval_to_mysqlnd(zval * zv TSRMLS_DC)
+{
+ MYSQLND * retval;
+ MYSQLND_REVERSE_API ** elem;
+
+ for (zend_hash_internal_pointer_reset(&mysqlnd_api_ext_ht);
+ zend_hash_get_current_data(&mysqlnd_api_ext_ht, (void **)&elem) == SUCCESS;
+ zend_hash_move_forward(&mysqlnd_api_ext_ht))
+ {
+ if ((*elem)->conversion_cb) {
+ retval = (*elem)->conversion_cb(zv TSRMLS_CC);
+ if (retval) {
+ return retval;
+ }
+ }
+ }
+
+ return NULL;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.h b/ext/mysqlnd/mysqlnd_reverse_api.h
new file mode 100644
index 0000000000..005df5a1ab
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_reverse_api.h
@@ -0,0 +1,50 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+/* $Id: mysqlnd.h 318051 2011-10-12 16:18:02Z andrey $ */
+
+#ifndef MYSQLND_REVERSE_API_H
+#define MYSQLND_REVERSE_API_H
+typedef struct st_mysqlnd_reverse_api
+{
+ zend_module_entry * module;
+ MYSQLND *(*conversion_cb)(zval * zv TSRMLS_DC);
+} MYSQLND_REVERSE_API;
+
+
+PHPAPI void mysqlnd_reverse_api_init(TSRMLS_D);
+PHPAPI void mysqlnd_reverse_api_end(TSRMLS_D);
+
+PHPAPI HashTable * mysqlnd_reverse_api_get_api_list(TSRMLS_D);
+
+PHPAPI void mysqlnd_reverse_api_register_api(MYSQLND_REVERSE_API * apiext TSRMLS_DC);
+
+PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv TSRMLS_DC);
+
+#endif /* MYSQLND_REVERSE_API_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
diff --git a/ext/mysqlnd/mysqlnd_statistics.c b/ext/mysqlnd/mysqlnd_statistics.c
index 55eb0d1acd..bb00a9192d 100644
--- a/ext/mysqlnd/mysqlnd_statistics.c
+++ b/ext/mysqlnd/mysqlnd_statistics.c
@@ -26,173 +26,171 @@
#include "mysqlnd_debug.h"
-#define STR_W_LEN(str) str, (sizeof(str) - 1)
-
/* {{{ mysqlnd_stats_values_names
*/
const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{
- { STR_W_LEN("bytes_sent") },
- { STR_W_LEN("bytes_received") },
- { STR_W_LEN("packets_sent") },
- { STR_W_LEN("packets_received") },
- { STR_W_LEN("protocol_overhead_in") },
- { STR_W_LEN("protocol_overhead_out") },
- { STR_W_LEN("bytes_received_ok_packet") },
- { STR_W_LEN("bytes_received_eof_packet") },
- { STR_W_LEN("bytes_received_rset_header_packet") },
- { STR_W_LEN("bytes_received_rset_field_meta_packet") },
- { STR_W_LEN("bytes_received_rset_row_packet") },
- { STR_W_LEN("bytes_received_prepare_response_packet") },
- { STR_W_LEN("bytes_received_change_user_packet") },
- { STR_W_LEN("packets_sent_command") },
- { STR_W_LEN("packets_received_ok") },
- { STR_W_LEN("packets_received_eof") },
- { STR_W_LEN("packets_received_rset_header") },
- { STR_W_LEN("packets_received_rset_field_meta") },
- { STR_W_LEN("packets_received_rset_row") },
- { STR_W_LEN("packets_received_prepare_response") },
- { STR_W_LEN("packets_received_change_user") },
- { STR_W_LEN("result_set_queries") },
- { STR_W_LEN("non_result_set_queries") },
- { STR_W_LEN("no_index_used") },
- { STR_W_LEN("bad_index_used") },
- { STR_W_LEN("slow_queries") },
- { STR_W_LEN("buffered_sets") },
- { STR_W_LEN("unbuffered_sets") },
- { STR_W_LEN("ps_buffered_sets") },
- { STR_W_LEN("ps_unbuffered_sets") },
- { STR_W_LEN("flushed_normal_sets") },
- { STR_W_LEN("flushed_ps_sets") },
- { STR_W_LEN("ps_prepared_never_executed") },
- { STR_W_LEN("ps_prepared_once_executed") },
- { STR_W_LEN("rows_fetched_from_server_normal") },
- { STR_W_LEN("rows_fetched_from_server_ps") },
- { STR_W_LEN("rows_buffered_from_client_normal") },
- { STR_W_LEN("rows_buffered_from_client_ps") },
- { STR_W_LEN("rows_fetched_from_client_normal_buffered") },
- { STR_W_LEN("rows_fetched_from_client_normal_unbuffered") },
- { STR_W_LEN("rows_fetched_from_client_ps_buffered") },
- { STR_W_LEN("rows_fetched_from_client_ps_unbuffered") },
- { STR_W_LEN("rows_fetched_from_client_ps_cursor") },
- { STR_W_LEN("rows_affected_normal") },
- { STR_W_LEN("rows_affected_ps") },
- { STR_W_LEN("rows_skipped_normal") },
- { STR_W_LEN("rows_skipped_ps") },
- { STR_W_LEN("copy_on_write_saved") },
- { STR_W_LEN("copy_on_write_performed") },
- { STR_W_LEN("command_buffer_too_small") },
- { STR_W_LEN("connect_success") },
- { STR_W_LEN("connect_failure") },
- { STR_W_LEN("connection_reused") },
- { STR_W_LEN("reconnect") },
- { STR_W_LEN("pconnect_success") },
- { STR_W_LEN("active_connections") },
- { STR_W_LEN("active_persistent_connections") },
- { STR_W_LEN("explicit_close") },
- { STR_W_LEN("implicit_close") },
- { STR_W_LEN("disconnect_close") },
- { STR_W_LEN("in_middle_of_command_close") },
- { STR_W_LEN("explicit_free_result") },
- { STR_W_LEN("implicit_free_result") },
- { STR_W_LEN("explicit_stmt_close") },
- { STR_W_LEN("implicit_stmt_close") },
- { STR_W_LEN("mem_emalloc_count") },
- { STR_W_LEN("mem_emalloc_amount") },
- { STR_W_LEN("mem_ecalloc_count") },
- { STR_W_LEN("mem_ecalloc_amount") },
- { STR_W_LEN("mem_erealloc_count") },
- { STR_W_LEN("mem_erealloc_amount") },
- { STR_W_LEN("mem_efree_count") },
- { STR_W_LEN("mem_efree_amount") },
- { STR_W_LEN("mem_malloc_count") },
- { STR_W_LEN("mem_malloc_amount") },
- { STR_W_LEN("mem_calloc_count") },
- { STR_W_LEN("mem_calloc_amount") },
- { STR_W_LEN("mem_realloc_count") },
- { STR_W_LEN("mem_realloc_amount") },
- { STR_W_LEN("mem_free_count") },
- { STR_W_LEN("mem_free_amount") },
- { STR_W_LEN("mem_estrndup_count") },
- { STR_W_LEN("mem_strndup_count") },
- { STR_W_LEN("mem_estndup_count") },
- { STR_W_LEN("mem_strdup_count") },
- { STR_W_LEN("proto_text_fetched_null") },
- { STR_W_LEN("proto_text_fetched_bit") },
- { STR_W_LEN("proto_text_fetched_tinyint") },
- { STR_W_LEN("proto_text_fetched_short") },
- { STR_W_LEN("proto_text_fetched_int24") },
- { STR_W_LEN("proto_text_fetched_int") },
- { STR_W_LEN("proto_text_fetched_bigint") },
- { STR_W_LEN("proto_text_fetched_decimal") },
- { STR_W_LEN("proto_text_fetched_float") },
- { STR_W_LEN("proto_text_fetched_double") },
- { STR_W_LEN("proto_text_fetched_date") },
- { STR_W_LEN("proto_text_fetched_year") },
- { STR_W_LEN("proto_text_fetched_time") },
- { STR_W_LEN("proto_text_fetched_datetime") },
- { STR_W_LEN("proto_text_fetched_timestamp") },
- { STR_W_LEN("proto_text_fetched_string") },
- { STR_W_LEN("proto_text_fetched_blob") },
- { STR_W_LEN("proto_text_fetched_enum") },
- { STR_W_LEN("proto_text_fetched_set") },
- { STR_W_LEN("proto_text_fetched_geometry") },
- { STR_W_LEN("proto_text_fetched_other") },
- { STR_W_LEN("proto_binary_fetched_null") },
- { STR_W_LEN("proto_binary_fetched_bit") },
- { STR_W_LEN("proto_binary_fetched_tinyint") },
- { STR_W_LEN("proto_binary_fetched_short") },
- { STR_W_LEN("proto_binary_fetched_int24") },
- { STR_W_LEN("proto_binary_fetched_int") },
- { STR_W_LEN("proto_binary_fetched_bigint") },
- { STR_W_LEN("proto_binary_fetched_decimal") },
- { STR_W_LEN("proto_binary_fetched_float") },
- { STR_W_LEN("proto_binary_fetched_double") },
- { STR_W_LEN("proto_binary_fetched_date") },
- { STR_W_LEN("proto_binary_fetched_year") },
- { STR_W_LEN("proto_binary_fetched_time") },
- { STR_W_LEN("proto_binary_fetched_datetime") },
- { STR_W_LEN("proto_binary_fetched_timestamp") },
- { STR_W_LEN("proto_binary_fetched_string") },
- { STR_W_LEN("proto_binary_fetched_blob") },
- { STR_W_LEN("proto_binary_fetched_enum") },
- { STR_W_LEN("proto_binary_fetched_set") },
- { STR_W_LEN("proto_binary_fetched_geometry") },
- { STR_W_LEN("proto_binary_fetched_other") },
- { STR_W_LEN("init_command_executed_count") },
- { STR_W_LEN("init_command_failed_count") },
- { STR_W_LEN("com_quit") },
- { STR_W_LEN("com_init_db") },
- { STR_W_LEN("com_query") },
- { STR_W_LEN("com_field_list") },
- { STR_W_LEN("com_create_db") },
- { STR_W_LEN("com_drop_db") },
- { STR_W_LEN("com_refresh") },
- { STR_W_LEN("com_shutdown") },
- { STR_W_LEN("com_statistics") },
- { STR_W_LEN("com_process_info") },
- { STR_W_LEN("com_connect") },
- { STR_W_LEN("com_process_kill") },
- { STR_W_LEN("com_debug") },
- { STR_W_LEN("com_ping") },
- { STR_W_LEN("com_time") },
- { STR_W_LEN("com_delayed_insert") },
- { STR_W_LEN("com_change_user") },
- { STR_W_LEN("com_binlog_dump") },
- { STR_W_LEN("com_table_dump") },
- { STR_W_LEN("com_connect_out") },
- { STR_W_LEN("com_register_slave") },
- { STR_W_LEN("com_stmt_prepare") },
- { STR_W_LEN("com_stmt_execute") },
- { STR_W_LEN("com_stmt_send_long_data") },
- { STR_W_LEN("com_stmt_close") },
- { STR_W_LEN("com_stmt_reset") },
- { STR_W_LEN("com_stmt_set_option") },
- { STR_W_LEN("com_stmt_fetch") },
- { STR_W_LEN("com_deamon") },
- { STR_W_LEN("bytes_received_real_data_normal") },
- { STR_W_LEN("bytes_received_real_data_ps") }
+ { MYSQLND_STR_W_LEN("bytes_sent") },
+ { MYSQLND_STR_W_LEN("bytes_received") },
+ { MYSQLND_STR_W_LEN("packets_sent") },
+ { MYSQLND_STR_W_LEN("packets_received") },
+ { MYSQLND_STR_W_LEN("protocol_overhead_in") },
+ { MYSQLND_STR_W_LEN("protocol_overhead_out") },
+ { MYSQLND_STR_W_LEN("bytes_received_ok_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_eof_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_rset_header_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_rset_field_meta_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_rset_row_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_prepare_response_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_change_user_packet") },
+ { MYSQLND_STR_W_LEN("packets_sent_command") },
+ { MYSQLND_STR_W_LEN("packets_received_ok") },
+ { MYSQLND_STR_W_LEN("packets_received_eof") },
+ { MYSQLND_STR_W_LEN("packets_received_rset_header") },
+ { MYSQLND_STR_W_LEN("packets_received_rset_field_meta") },
+ { MYSQLND_STR_W_LEN("packets_received_rset_row") },
+ { MYSQLND_STR_W_LEN("packets_received_prepare_response") },
+ { MYSQLND_STR_W_LEN("packets_received_change_user") },
+ { MYSQLND_STR_W_LEN("result_set_queries") },
+ { MYSQLND_STR_W_LEN("non_result_set_queries") },
+ { MYSQLND_STR_W_LEN("no_index_used") },
+ { MYSQLND_STR_W_LEN("bad_index_used") },
+ { MYSQLND_STR_W_LEN("slow_queries") },
+ { MYSQLND_STR_W_LEN("buffered_sets") },
+ { MYSQLND_STR_W_LEN("unbuffered_sets") },
+ { MYSQLND_STR_W_LEN("ps_buffered_sets") },
+ { MYSQLND_STR_W_LEN("ps_unbuffered_sets") },
+ { MYSQLND_STR_W_LEN("flushed_normal_sets") },
+ { MYSQLND_STR_W_LEN("flushed_ps_sets") },
+ { MYSQLND_STR_W_LEN("ps_prepared_never_executed") },
+ { MYSQLND_STR_W_LEN("ps_prepared_once_executed") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_server_normal") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_server_ps") },
+ { MYSQLND_STR_W_LEN("rows_buffered_from_client_normal") },
+ { MYSQLND_STR_W_LEN("rows_buffered_from_client_ps") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_normal_buffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_normal_unbuffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_ps_buffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_ps_unbuffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_ps_cursor") },
+ { MYSQLND_STR_W_LEN("rows_affected_normal") },
+ { MYSQLND_STR_W_LEN("rows_affected_ps") },
+ { MYSQLND_STR_W_LEN("rows_skipped_normal") },
+ { MYSQLND_STR_W_LEN("rows_skipped_ps") },
+ { MYSQLND_STR_W_LEN("copy_on_write_saved") },
+ { MYSQLND_STR_W_LEN("copy_on_write_performed") },
+ { MYSQLND_STR_W_LEN("command_buffer_too_small") },
+ { MYSQLND_STR_W_LEN("connect_success") },
+ { MYSQLND_STR_W_LEN("connect_failure") },
+ { MYSQLND_STR_W_LEN("connection_reused") },
+ { MYSQLND_STR_W_LEN("reconnect") },
+ { MYSQLND_STR_W_LEN("pconnect_success") },
+ { MYSQLND_STR_W_LEN("active_connections") },
+ { MYSQLND_STR_W_LEN("active_persistent_connections") },
+ { MYSQLND_STR_W_LEN("explicit_close") },
+ { MYSQLND_STR_W_LEN("implicit_close") },
+ { MYSQLND_STR_W_LEN("disconnect_close") },
+ { MYSQLND_STR_W_LEN("in_middle_of_command_close") },
+ { MYSQLND_STR_W_LEN("explicit_free_result") },
+ { MYSQLND_STR_W_LEN("implicit_free_result") },
+ { MYSQLND_STR_W_LEN("explicit_stmt_close") },
+ { MYSQLND_STR_W_LEN("implicit_stmt_close") },
+ { MYSQLND_STR_W_LEN("mem_emalloc_count") },
+ { MYSQLND_STR_W_LEN("mem_emalloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_ecalloc_count") },
+ { MYSQLND_STR_W_LEN("mem_ecalloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_erealloc_count") },
+ { MYSQLND_STR_W_LEN("mem_erealloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_efree_count") },
+ { MYSQLND_STR_W_LEN("mem_efree_amount") },
+ { MYSQLND_STR_W_LEN("mem_malloc_count") },
+ { MYSQLND_STR_W_LEN("mem_malloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_calloc_count") },
+ { MYSQLND_STR_W_LEN("mem_calloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_realloc_count") },
+ { MYSQLND_STR_W_LEN("mem_realloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_free_count") },
+ { MYSQLND_STR_W_LEN("mem_free_amount") },
+ { MYSQLND_STR_W_LEN("mem_estrndup_count") },
+ { MYSQLND_STR_W_LEN("mem_strndup_count") },
+ { MYSQLND_STR_W_LEN("mem_estndup_count") },
+ { MYSQLND_STR_W_LEN("mem_strdup_count") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_null") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_bit") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_tinyint") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_short") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_int24") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_int") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_bigint") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_decimal") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_float") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_double") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_date") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_year") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_time") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_datetime") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_timestamp") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_string") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_blob") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_enum") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_set") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_geometry") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_other") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_null") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_bit") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_tinyint") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_short") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_int24") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_int") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_bigint") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_decimal") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_float") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_double") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_date") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_year") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_time") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_datetime") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_timestamp") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_string") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_blob") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_enum") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_set") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_geometry") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_other") },
+ { MYSQLND_STR_W_LEN("init_command_executed_count") },
+ { MYSQLND_STR_W_LEN("init_command_failed_count") },
+ { MYSQLND_STR_W_LEN("com_quit") },
+ { MYSQLND_STR_W_LEN("com_init_db") },
+ { MYSQLND_STR_W_LEN("com_query") },
+ { MYSQLND_STR_W_LEN("com_field_list") },
+ { MYSQLND_STR_W_LEN("com_create_db") },
+ { MYSQLND_STR_W_LEN("com_drop_db") },
+ { MYSQLND_STR_W_LEN("com_refresh") },
+ { MYSQLND_STR_W_LEN("com_shutdown") },
+ { MYSQLND_STR_W_LEN("com_statistics") },
+ { MYSQLND_STR_W_LEN("com_process_info") },
+ { MYSQLND_STR_W_LEN("com_connect") },
+ { MYSQLND_STR_W_LEN("com_process_kill") },
+ { MYSQLND_STR_W_LEN("com_debug") },
+ { MYSQLND_STR_W_LEN("com_ping") },
+ { MYSQLND_STR_W_LEN("com_time") },
+ { MYSQLND_STR_W_LEN("com_delayed_insert") },
+ { MYSQLND_STR_W_LEN("com_change_user") },
+ { MYSQLND_STR_W_LEN("com_binlog_dump") },
+ { MYSQLND_STR_W_LEN("com_table_dump") },
+ { MYSQLND_STR_W_LEN("com_connect_out") },
+ { MYSQLND_STR_W_LEN("com_register_slave") },
+ { MYSQLND_STR_W_LEN("com_stmt_prepare") },
+ { MYSQLND_STR_W_LEN("com_stmt_execute") },
+ { MYSQLND_STR_W_LEN("com_stmt_send_long_data") },
+ { MYSQLND_STR_W_LEN("com_stmt_close") },
+ { MYSQLND_STR_W_LEN("com_stmt_reset") },
+ { MYSQLND_STR_W_LEN("com_stmt_set_option") },
+ { MYSQLND_STR_W_LEN("com_stmt_fetch") },
+ { MYSQLND_STR_W_LEN("com_deamon") },
+ { MYSQLND_STR_W_LEN("bytes_received_real_data_normal") },
+ { MYSQLND_STR_W_LEN("bytes_received_real_data_ps") }
};
/* }}} */
@@ -257,7 +255,6 @@ mysqlnd_stats_init(MYSQLND_STATS ** stats, size_t statistic_count)
#ifdef ZTS
(*stats)->LOCK_access = tsrm_mutex_alloc();
#endif
-
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_statistics.h b/ext/mysqlnd/mysqlnd_statistics.h
index 9a5e31cf28..7a1a1cec27 100644
--- a/ext/mysqlnd/mysqlnd_statistics.h
+++ b/ext/mysqlnd/mysqlnd_statistics.h
@@ -26,12 +26,6 @@
PHPAPI extern MYSQLND_STATS * mysqlnd_global_stats;
-typedef struct st_mysqlnd_string
-{
- char *s;
- size_t l;
-} MYSQLND_STRING;
-
extern const MYSQLND_STRING mysqlnd_stats_values_names[];
#ifdef ZTS
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 1a6b790d9f..43eba40a20 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -25,6 +25,12 @@
#define MYSQLND_TYPEDEFED_METHODS
+#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
+#define MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class)
+
+#define MYSQLND_CLASS_METHODS_START(class) MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) = {
+#define MYSQLND_CLASS_METHODS_END }
+
typedef struct st_mysqlnd_memory_pool MYSQLND_MEMORY_POOL;
typedef struct st_mysqlnd_memory_pool_chunk MYSQLND_MEMORY_POOL_CHUNK;
typedef struct st_mysqlnd_memory_pool_chunk_llist MYSQLND_MEMORY_POOL_CHUNK_LLIST;
@@ -102,9 +108,18 @@ typedef struct st_mysqlnd_error_info
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
+ zend_llist * error_list;
} MYSQLND_ERROR_INFO;
+typedef struct st_mysqlnd_error_list_element
+{
+ char * error;
+ char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
+ unsigned int error_no;
+} MYSQLND_ERROR_LIST_ELEMENT;
+
+
typedef struct st_mysqlnd_infile_info
{
php_stream *fd;
@@ -132,7 +147,7 @@ typedef struct st_mysqlnd_charset
typedef struct st_mysqlnd_infile
{
int (*local_infile_init)(void **ptr, char *filename, void **userdata TSRMLS_DC);
- int (*local_infile_read)(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC);
+ int (*local_infile_read)(void *ptr, zend_uchar * buf, unsigned int buf_len TSRMLS_DC);
int (*local_infile_error)(void *ptr, char *error_msg, unsigned int error_msg_len TSRMLS_DC);
void (*local_infile_end)(void *ptr TSRMLS_DC);
zval *callback;
@@ -151,12 +166,12 @@ typedef struct st_mysqlnd_options
char *cfg_file;
char *cfg_section;
+ char *auth_protocol;
/*
We need to keep these because otherwise st_mysqlnd_conn will be changed.
The ABI will be broken and the methods structure will be somewhere else
in the memory which can crash external code. Feel free to reuse these.
*/
- char * unused1;
char * unused2;
char * unused3;
char * unused4;
@@ -196,6 +211,7 @@ typedef struct st_mysqlnd_net_options
typedef struct st_mysqlnd_connection MYSQLND;
+typedef struct st_mysqlnd_connection_data MYSQLND_CONN_DATA;
typedef struct st_mysqlnd_net MYSQLND_NET;
typedef struct st_mysqlnd_protocol MYSQLND_PROTOCOL;
typedef struct st_mysqlnd_res MYSQLND_RES;
@@ -251,28 +267,39 @@ typedef struct st_mysqlnd_read_buffer {
-typedef enum_func_status (*func_mysqlnd_net__connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC);
-typedef size_t (*func_mysqlnd_net__send)(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__receive)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_net__set_client_option)(MYSQLND_NET * const net, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__network_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);
-typedef size_t (*func_mysqlnd_net__network_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__decode)(zend_uchar * uncompressed_data, size_t uncompressed_data_len, const zend_uchar * const compressed_data, size_t compressed_data_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len, const zend_uchar * const uncompressed_data, size_t uncompressed_data_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len, const zend_uchar * const compressed_data, const size_t compressed_data_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len, const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len TSRMLS_DC);
typedef size_t (*func_mysqlnd_net__consume_uneaten_data)(MYSQLND_NET * const net, enum php_mysqlnd_server_command cmd TSRMLS_DC);
typedef void (*func_mysqlnd_net__free_contents)(MYSQLND_NET * net TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_net__enable_ssl)(MYSQLND_NET * const net TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_net__disable_ssl)(MYSQLND_NET * const net TSRMLS_DC);
-
+typedef enum_func_status (*func_mysqlnd_net__network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef size_t (*func_mysqlnd_net__network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buf, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef size_t (*func_mysqlnd_net__send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef void (*func_mysqlnd_net__dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef void (*func_mysqlnd_net__close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef void (*func_mysqlnd_net__post_connect_set_opt)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer)(MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
struct st_mysqlnd_net_methods
{
- func_mysqlnd_net__connect connect;
- func_mysqlnd_net__send send;
- func_mysqlnd_net__receive receive;
+ func_mysqlnd_net__init init;
+ func_mysqlnd_net__dtor dtor;
+ func_mysqlnd_net__connect_ex connect_ex;
+ func_mysqlnd_net__close_stream close_stream;
+ func_mysqlnd_net__open_stream open_pipe;
+ func_mysqlnd_net__open_stream open_tcp_or_unix;
+
+ void * unused1;
+ void * unused2;
+ func_mysqlnd_net__post_connect_set_opt post_connect_set_opt;
+
func_mysqlnd_net__set_client_option set_client_option;
- func_mysqlnd_net__network_read network_read;
- func_mysqlnd_net__network_write network_write;
func_mysqlnd_net__decode decode;
func_mysqlnd_net__encode encode;
func_mysqlnd_net__consume_uneaten_data consume_uneaten_data;
@@ -280,11 +307,18 @@ struct st_mysqlnd_net_methods
func_mysqlnd_net__enable_ssl enable_ssl;
func_mysqlnd_net__disable_ssl disable_ssl;
- void * unused1;
- void * unused2;
+ func_mysqlnd_net__network_read_ex network_read_ex;
+ func_mysqlnd_net__network_write_ex network_write_ex;
+ func_mysqlnd_net__send_ex send_ex;
+ func_mysqlnd_net__receive_ex receive_ex;
+
+ func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer read_compressed_packet_from_stream_and_fill_read_buffer;
+
void * unused3;
void * unused4;
void * unused5;
+ void * unused6;
+ void * unused7;
};
@@ -300,9 +334,12 @@ struct st_mysqlnd_packet_row;
struct st_mysqlnd_packet_stats;
struct st_mysqlnd_packet_prepare_response;
struct st_mysqlnd_packet_chg_user_resp;
+struct st_mysqlnd_packet_auth_pam;
typedef struct st_mysqlnd_packet_greet * (*func_mysqlnd_protocol__get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_auth * (*func_mysqlnd_protocol__get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
+typedef struct st_mysqlnd_packet_auth_response *(*func_mysqlnd_protocol__get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
+typedef struct st_mysqlnd_packet_change_auth_response * (*func_mysqlnd_protocol__get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_ok * (*func_mysqlnd_protocol__get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_command * (*func_mysqlnd_protocol__get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_eof * (*func_mysqlnd_protocol__get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
@@ -317,6 +354,8 @@ struct st_mysqlnd_protocol_methods
{
func_mysqlnd_protocol__get_greet_packet get_greet_packet;
func_mysqlnd_protocol__get_auth_packet get_auth_packet;
+ func_mysqlnd_protocol__get_auth_response_packet get_auth_response_packet;
+ func_mysqlnd_protocol__get_change_auth_response_packet get_change_auth_response_packet;
func_mysqlnd_protocol__get_ok_packet get_ok_packet;
func_mysqlnd_protocol__get_command_packet get_command_packet;
func_mysqlnd_protocol__get_eof_packet get_eof_packet;
@@ -335,161 +374,194 @@ struct st_mysqlnd_protocol_methods
};
+typedef MYSQLND * (*func_mysqlnd_object_factory__get_connection)(zend_bool persistent TSRMLS_DC);
+typedef MYSQLND * (*func_mysqlnd_object_factory__clone_connection_object)(MYSQLND * conn TSRMLS_DC);
+typedef MYSQLND_STMT * (*func_mysqlnd_object_factory__get_prepared_statement)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef MYSQLND_NET * (*func_mysqlnd_object_factory__get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
+typedef MYSQLND_PROTOCOL * (*func_mysqlnd_object_factory__get_protocol_decoder)(zend_bool persistent TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__init)(MYSQLND * conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__connect)(MYSQLND *conn, const char *host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags TSRMLS_DC);
-typedef ulong (*func_mysqlnd_conn__escape_string)(MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_charset)(MYSQLND * const conn, const char * const charset TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__send_query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__reap_query)(MYSQLND *conn TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__use_result)(MYSQLND * const conn TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__store_result)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__next_result)(MYSQLND * const conn TSRMLS_DC);
-typedef zend_bool (*func_mysqlnd_conn__more_results)(const MYSQLND * const conn TSRMLS_DC);
-
-typedef MYSQLND_STMT * (*func_mysqlnd_conn__stmt_init)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__shutdown_server)(MYSQLND * const conn, uint8_t level TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__refresh_server)(MYSQLND * const conn, uint8_t options TSRMLS_DC);
-
-typedef enum_func_status (*func_mysqlnd_conn__ping)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__kill_connection)(MYSQLND *conn, unsigned int pid TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__select_db)(MYSQLND * const conn, const char * const db, unsigned int db_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__server_dump_debug_information)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__change_user)(MYSQLND * const conn, const char * user, const char * passwd, const char * db, zend_bool silent TSRMLS_DC);
+struct st_mysqlnd_object_factory_methods
+{
+ func_mysqlnd_object_factory__get_connection get_connection;
+ func_mysqlnd_object_factory__clone_connection_object clone_connection_object;
+ func_mysqlnd_object_factory__get_prepared_statement get_prepared_statement;
+ func_mysqlnd_object_factory__get_io_channel get_io_channel;
+ func_mysqlnd_object_factory__get_protocol_decoder get_protocol_decoder;
+};
-typedef unsigned int (*func_mysqlnd_conn__get_error_no)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_error_str)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_sqlstate)(const MYSQLND * const conn TSRMLS_DC);
-typedef uint64_t (*func_mysqlnd_conn__get_thread_id)(const MYSQLND * const conn TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__get_statistics)(const MYSQLND * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
-typedef unsigned long (*func_mysqlnd_conn__get_server_version)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_server_information)(const MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__get_server_statistics)(MYSQLND *conn, char **message, unsigned int * message_len TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_host_information)(const MYSQLND * const conn TSRMLS_DC);
-typedef unsigned int (*func_mysqlnd_conn__get_protocol_information)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_last_message)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__charset_name)(const MYSQLND * const conn TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__list_fields)(MYSQLND *conn, const char *table, const char *achtung_wild TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__list_method)(MYSQLND *conn, const char *query, const char *achtung_wild, char *par1 TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__init)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__connect)(MYSQLND_CONN_DATA * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags TSRMLS_DC);
+typedef ulong (*func_mysqlnd_conn_data__escape_string)(MYSQLND_CONN_DATA * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_charset)(MYSQLND_CONN_DATA * const conn, const char * const charset TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_query)(MYSQLND_CONN_DATA * conn, const char *query, unsigned int query_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__reap_query)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__use_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__store_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__next_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef zend_bool (*func_mysqlnd_conn_data__more_results)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef uint64_t (*func_mysqlnd_conn__get_last_insert_id)(const MYSQLND * const conn TSRMLS_DC);
-typedef uint64_t (*func_mysqlnd_conn__get_affected_rows)(const MYSQLND * const conn TSRMLS_DC);
-typedef unsigned int (*func_mysqlnd_conn__get_warning_count)(const MYSQLND * const conn TSRMLS_DC);
+typedef MYSQLND_STMT * (*func_mysqlnd_conn_data__stmt_init)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef unsigned int (*func_mysqlnd_conn__get_field_count)(const MYSQLND * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__shutdown_server)(MYSQLND_CONN_DATA * const conn, uint8_t level TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__refresh_server)(MYSQLND_CONN_DATA * const conn, uint8_t options TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_server_option)(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_client_option)(MYSQLND * const conn, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__free_contents)(MYSQLND *conn TSRMLS_DC); /* private */
-typedef void (*func_mysqlnd_conn__free_options)(MYSQLND * conn TSRMLS_DC); /* private */
-typedef enum_func_status (*func_mysqlnd_conn__close)(MYSQLND *conn, enum_connection_close_type close_type TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__dtor)(MYSQLND *conn TSRMLS_DC); /* private */
+typedef enum_func_status (*func_mysqlnd_conn_data__ping)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__kill_connection)(MYSQLND_CONN_DATA * conn, unsigned int pid TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, unsigned int db_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__server_dump_debug_information)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__change_user)(MYSQLND_CONN_DATA * const conn, const char * user, const char * passwd, const char * db, zend_bool silent, size_t passwd_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__query_read_result_set_header)(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_error_no)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_error_str)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_sqlstate)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef uint64_t (*func_mysqlnd_conn_data__get_thread_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef void (*func_mysqlnd_conn_data__get_statistics)(const MYSQLND_CONN_DATA * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
-typedef MYSQLND * (*func_mysqlnd_conn__get_reference)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__free_reference)(MYSQLND * const conn TSRMLS_DC);
-typedef enum mysqlnd_connection_state (*func_mysqlnd_conn__get_state)(MYSQLND * const conn TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC);
+typedef unsigned long (*func_mysqlnd_conn_data__get_server_version)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_server_information)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__get_server_statistics)(MYSQLND_CONN_DATA * conn, char **message, unsigned int * message_len TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_host_information)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_protocol_information)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_last_message)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__charset_name)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_fields)(MYSQLND_CONN_DATA * conn, const char * table, const char * achtung_wild TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_method)(MYSQLND_CONN_DATA * conn, const char * query, const char * achtung_wild, char *par1 TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__simple_command)(MYSQLND *conn, enum php_mysqlnd_server_command command, const char * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__simple_command_handle_response)(MYSQLND *conn, enum mysqlnd_packet_type ok_packet, zend_bool silent, enum php_mysqlnd_server_command command, zend_bool ignore_upsert_status TSRMLS_DC);
+typedef uint64_t (*func_mysqlnd_conn_data__get_last_insert_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef uint64_t (*func_mysqlnd_conn_data__get_affected_rows)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_warning_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__restart_psession)(MYSQLND *conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__end_psession)(MYSQLND *conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__send_close)(MYSQLND * conn TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_field_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__ssl_set)(MYSQLND * const conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_server_status)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
+typedef void (*func_mysqlnd_conn_data__free_contents)(MYSQLND_CONN_DATA * conn TSRMLS_DC);/* private */
+typedef void (*func_mysqlnd_conn_data__free_options)(MYSQLND_CONN_DATA * conn TSRMLS_DC); /* private */
+typedef void (*func_mysqlnd_conn_data__dtor)(MYSQLND_CONN_DATA * conn TSRMLS_DC); /* private */
-typedef MYSQLND_RES * (*func_mysqlnd_conn__result_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__query_read_result_set_header)(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_autocommit)(MYSQLND * conn, unsigned int mode TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__tx_commit)(MYSQLND * conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__tx_rollback)(MYSQLND * conn TSRMLS_DC);
+typedef MYSQLND_CONN_DATA * (*func_mysqlnd_conn_data__get_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__free_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum mysqlnd_connection_state (*func_mysqlnd_conn_data__get_state)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef void (*func_mysqlnd_conn_data__set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet, zend_bool silent, enum php_mysqlnd_server_command command, zend_bool ignore_upsert_status TSRMLS_DC);
-struct st_mysqlnd_conn_methods
-{
- func_mysqlnd_conn__init init;
- func_mysqlnd_conn__connect connect;
- func_mysqlnd_conn__escape_string escape_string;
- func_mysqlnd_conn__set_charset set_charset;
- func_mysqlnd_conn__query query;
- func_mysqlnd_conn__send_query send_query;
- func_mysqlnd_conn__reap_query reap_query;
- func_mysqlnd_conn__use_result use_result;
- func_mysqlnd_conn__store_result store_result;
- func_mysqlnd_conn__next_result next_result;
- func_mysqlnd_conn__more_results more_results;
-
- func_mysqlnd_conn__stmt_init stmt_init;
-
- func_mysqlnd_conn__shutdown_server shutdown_server;
- func_mysqlnd_conn__refresh_server refresh_server;
-
- func_mysqlnd_conn__ping ping;
- func_mysqlnd_conn__kill_connection kill_connection;
- func_mysqlnd_conn__select_db select_db;
- func_mysqlnd_conn__server_dump_debug_information server_dump_debug_information;
- func_mysqlnd_conn__change_user change_user;
-
- func_mysqlnd_conn__get_error_no get_error_no;
- func_mysqlnd_conn__get_error_str get_error_str;
- func_mysqlnd_conn__get_sqlstate get_sqlstate;
- func_mysqlnd_conn__get_thread_id get_thread_id;
- func_mysqlnd_conn__get_statistics get_statistics;
-
- func_mysqlnd_conn__get_server_version get_server_version;
- func_mysqlnd_conn__get_server_information get_server_information;
- func_mysqlnd_conn__get_server_statistics get_server_statistics;
- func_mysqlnd_conn__get_host_information get_host_information;
- func_mysqlnd_conn__get_protocol_information get_protocol_information;
- func_mysqlnd_conn__get_last_message get_last_message;
- func_mysqlnd_conn__charset_name charset_name;
- func_mysqlnd_conn__list_fields list_fields;
- func_mysqlnd_conn__list_method list_method;
-
- func_mysqlnd_conn__get_last_insert_id get_last_insert_id;
- func_mysqlnd_conn__get_affected_rows get_affected_rows;
- func_mysqlnd_conn__get_warning_count get_warning_count;
-
- func_mysqlnd_conn__get_field_count get_field_count;
-
- func_mysqlnd_conn__set_server_option set_server_option;
- func_mysqlnd_conn__set_client_option set_client_option;
- func_mysqlnd_conn__free_contents free_contents;
- func_mysqlnd_conn__free_options free_options;
- func_mysqlnd_conn__close close;
- func_mysqlnd_conn__dtor dtor;
+typedef enum_func_status (*func_mysqlnd_conn_data__restart_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__end_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_close)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
- func_mysqlnd_conn__query_read_result_set_header query_read_result_set_header;
+typedef enum_func_status (*func_mysqlnd_conn_data__ssl_set)(MYSQLND_CONN_DATA * const conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC);
- func_mysqlnd_conn__get_reference get_reference;
- func_mysqlnd_conn__free_reference free_reference;
- func_mysqlnd_conn__get_state get_state;
- func_mysqlnd_conn__set_state set_state;
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__result_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC);
- func_mysqlnd_conn__simple_command simple_command;
- func_mysqlnd_conn__simple_command_handle_response simple_command_handle_response;
+typedef enum_func_status (*func_mysqlnd_conn_data__set_autocommit)(MYSQLND_CONN_DATA * conn, unsigned int mode TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
- func_mysqlnd_conn__restart_psession restart_psession;
- func_mysqlnd_conn__end_psession end_psession;
- func_mysqlnd_conn__send_close send_close;
+typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status TSRMLS_DC);
- func_mysqlnd_conn__ssl_set ssl_set;
- func_mysqlnd_conn__result_init result_init;
-#ifdef AUTOCOMMIT_TX_COMMIT_ROLLBACK
- func_mysqlnd_conn__set_autocommit set_autocommit;
- func_mysqlnd_conn__tx_commit tx_commit;
- func_mysqlnd_conn__tx_rollback tx_rollback;
-#endif
+struct st_mysqlnd_conn_data_methods
+{
+ func_mysqlnd_conn_data__init init;
+ func_mysqlnd_conn_data__connect connect;
+ func_mysqlnd_conn_data__escape_string escape_string;
+ func_mysqlnd_conn_data__set_charset set_charset;
+ func_mysqlnd_conn_data__query query;
+ func_mysqlnd_conn_data__send_query send_query;
+ func_mysqlnd_conn_data__reap_query reap_query;
+ func_mysqlnd_conn_data__use_result use_result;
+ func_mysqlnd_conn_data__store_result store_result;
+ func_mysqlnd_conn_data__next_result next_result;
+ func_mysqlnd_conn_data__more_results more_results;
+
+ func_mysqlnd_conn_data__stmt_init stmt_init;
+
+ func_mysqlnd_conn_data__shutdown_server shutdown_server;
+ func_mysqlnd_conn_data__refresh_server refresh_server;
+
+ func_mysqlnd_conn_data__ping ping;
+ func_mysqlnd_conn_data__kill_connection kill_connection;
+ func_mysqlnd_conn_data__select_db select_db;
+ func_mysqlnd_conn_data__server_dump_debug_information server_dump_debug_information;
+ func_mysqlnd_conn_data__change_user change_user;
+
+ func_mysqlnd_conn_data__get_error_no get_error_no;
+ func_mysqlnd_conn_data__get_error_str get_error_str;
+ func_mysqlnd_conn_data__get_sqlstate get_sqlstate;
+ func_mysqlnd_conn_data__get_thread_id get_thread_id;
+ func_mysqlnd_conn_data__get_statistics get_statistics;
+
+ func_mysqlnd_conn_data__get_server_version get_server_version;
+ func_mysqlnd_conn_data__get_server_information get_server_information;
+ func_mysqlnd_conn_data__get_server_statistics get_server_statistics;
+ func_mysqlnd_conn_data__get_host_information get_host_information;
+ func_mysqlnd_conn_data__get_protocol_information get_protocol_information;
+ func_mysqlnd_conn_data__get_last_message get_last_message;
+ func_mysqlnd_conn_data__charset_name charset_name;
+ func_mysqlnd_conn_data__list_fields list_fields;
+ func_mysqlnd_conn_data__list_method list_method;
+
+ func_mysqlnd_conn_data__get_last_insert_id get_last_insert_id;
+ func_mysqlnd_conn_data__get_affected_rows get_affected_rows;
+ func_mysqlnd_conn_data__get_warning_count get_warning_count;
+
+ func_mysqlnd_conn_data__get_field_count get_field_count;
+
+ func_mysqlnd_conn_data__get_server_status get_server_status;
+
+ func_mysqlnd_conn_data__set_server_option set_server_option;
+ func_mysqlnd_conn_data__set_client_option set_client_option;
+ func_mysqlnd_conn_data__free_contents free_contents;
+ func_mysqlnd_conn_data__free_options free_options;
+ func_mysqlnd_conn_data__dtor dtor;
+
+ func_mysqlnd_conn_data__query_read_result_set_header query_read_result_set_header;
+
+ func_mysqlnd_conn_data__get_reference get_reference;
+ func_mysqlnd_conn_data__free_reference free_reference;
+ func_mysqlnd_conn_data__get_state get_state;
+ func_mysqlnd_conn_data__set_state set_state;
+
+ func_mysqlnd_conn_data__simple_command simple_command;
+ func_mysqlnd_conn_data__simple_command_handle_response simple_command_handle_response;
+
+ func_mysqlnd_conn_data__restart_psession restart_psession;
+ func_mysqlnd_conn_data__end_psession end_psession;
+ func_mysqlnd_conn_data__send_close send_close;
+
+ func_mysqlnd_conn_data__ssl_set ssl_set;
+
+ func_mysqlnd_conn_data__result_init result_init;
+ func_mysqlnd_conn_data__set_autocommit set_autocommit;
+ func_mysqlnd_conn_data__tx_commit tx_commit;
+ func_mysqlnd_conn_data__tx_rollback tx_rollback;
+
+ func_mysqlnd_conn_data__local_tx_start local_tx_start;
+ func_mysqlnd_conn_data__local_tx_end local_tx_end;
};
+typedef enum_func_status (*func_mysqlnd_data__connect)(MYSQLND * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags TSRMLS_DC);
+typedef MYSQLND * (*func_mysqlnd_conn__clone_object)(MYSQLND * const conn TSRMLS_DC);
+typedef void (*func_mysqlnd_conn__dtor)(MYSQLND * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn__close)(MYSQLND * conn, enum_connection_close_type close_type TSRMLS_DC);
+
+struct st_mysqlnd_conn_methods
+{
+ func_mysqlnd_data__connect connect;
+ func_mysqlnd_conn__clone_object clone_object;
+ func_mysqlnd_conn__dtor dtor;
+ func_mysqlnd_conn__close close;
+};
typedef mysqlnd_fetch_row_func fetch_row;
@@ -497,7 +569,7 @@ typedef mysqlnd_fetch_row_func fetch_row_normal_buffered; /* private */
typedef mysqlnd_fetch_row_func fetch_row_normal_unbuffered; /* private */
typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, zend_bool ps_protocol TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, zend_bool ps TSRMLS_DC);
typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, unsigned int flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
typedef MYSQLND_ROW_C (*func_mysqlnd_res__fetch_row_c)(MYSQLND_RES *result TSRMLS_DC);
typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
@@ -512,9 +584,9 @@ typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field)(MYSQLND_RES * cons
typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * const result TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES *result, MYSQLND * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC);
typedef unsigned long * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND * const conn, MYSQLND_RES *result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol, zend_bool to_cache TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_res__initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC);
typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */
@@ -527,7 +599,6 @@ typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *resu
/* for decoding - binary or text protocol */
typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC);
@@ -582,7 +653,7 @@ typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field)(MYSQLND_RES_
typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_fields)(MYSQLND_RES_METADATA * const meta TSRMLS_DC);
typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_tell)(const MYSQLND_RES_METADATA * const meta TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn TSRMLS_DC);
typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent TSRMLS_DC);
typedef void (*func_mysqlnd_res_meta__free_metadata)(MYSQLND_RES_METADATA * meta TSRMLS_DC);
@@ -638,6 +709,7 @@ typedef unsigned int (*func_mysqlnd_stmt__server_status)(const MYSQLND_STMT * c
typedef enum_func_status (*func_mysqlnd_stmt__generate_execute_request)(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_stmt__parse_execute_response)(MYSQLND_STMT * const s TSRMLS_DC);
typedef void (*func_mysqlnd_stmt__free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_stmt__flush)(MYSQLND_STMT * const stmt TSRMLS_DC);
struct st_mysqlnd_stmt_methods
{
@@ -691,23 +763,27 @@ struct st_mysqlnd_stmt_methods
func_mysqlnd_stmt__parse_execute_response parse_execute_response;
func_mysqlnd_stmt__free_stmt_content free_stmt_content;
+
+ func_mysqlnd_stmt__flush flush;
};
struct st_mysqlnd_net
{
php_stream *stream;
- struct st_mysqlnd_net_methods m;
-
/* sequence for simple checking of correct packets */
zend_uchar packet_no;
zend_bool compressed;
zend_uchar compressed_envelope_packet_no;
#ifdef MYSQLND_COMPRESSION_ENABLED
MYSQLND_READ_BUFFER * uncompressed_data;
+#else
+ void * unused_pad1;
#endif
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
zend_uchar last_command;
+#else
+ zend_uchar unused_pad2;
#endif
/* cmd buffer */
MYSQLND_CMD_BUFFER cmd_buffer;
@@ -715,17 +791,19 @@ struct st_mysqlnd_net
MYSQLND_NET_OPTIONS options;
zend_bool persistent;
+
+ struct st_mysqlnd_net_methods m;
};
struct st_mysqlnd_protocol
{
- struct st_mysqlnd_protocol_methods m;
zend_bool persistent;
+ struct st_mysqlnd_protocol_methods m;
};
-struct st_mysqlnd_connection
+struct st_mysqlnd_connection_data
{
/* Operation related */
MYSQLND_NET * net;
@@ -745,7 +823,8 @@ struct st_mysqlnd_connection
uint64_t thread_id;
char *server_version;
char *host_info;
- unsigned char *scramble;
+ zend_uchar *auth_plugin_data;
+ size_t auth_plugin_data_len;
const MYSQLND_CHARSET *charset;
const MYSQLND_CHARSET *greet_charset;
char *connect_or_select_db;
@@ -758,12 +837,14 @@ struct st_mysqlnd_connection
unsigned long server_capabilities;
/* For UPSERT queries */
- MYSQLND_UPSERT_STATUS upsert_status;
+ MYSQLND_UPSERT_STATUS * upsert_status;
+ MYSQLND_UPSERT_STATUS upsert_status_impl;
char *last_message;
unsigned int last_message_len;
/* If error packet, we use these */
- MYSQLND_ERROR_INFO error_info;
+ MYSQLND_ERROR_INFO * error_info;
+ MYSQLND_ERROR_INFO error_info_impl;
/*
To prevent queries during unbuffered fetches. Also to
@@ -790,12 +871,21 @@ struct st_mysqlnd_connection
zend_bool persistent;
/* options */
- MYSQLND_OPTIONS options;
+ MYSQLND_OPTIONS * options;
+ MYSQLND_OPTIONS options_impl;
/* stats */
MYSQLND_STATS * stats;
- struct st_mysqlnd_conn_methods *m;
+ struct st_mysqlnd_conn_data_methods * m;
+};
+
+
+struct st_mysqlnd_connection
+{
+ MYSQLND_CONN_DATA * data;
+ zend_bool persistent;
+ struct st_mysqlnd_conn_methods * m;
};
@@ -832,7 +922,6 @@ struct st_mysqlnd_buffered_result
MYSQLND_MEMORY_POOL_CHUNK **row_buffers;
uint64_t row_count;
uint64_t initialized_rows;
- zend_bool persistent;
unsigned int references;
@@ -853,9 +942,7 @@ struct st_mysqlnd_unbuffered_result
struct st_mysqlnd_res
{
- struct st_mysqlnd_res_methods m;
-
- MYSQLND *conn;
+ MYSQLND_CONN_DATA *conn;
enum_mysqlnd_res_type type;
unsigned int field_count;
@@ -876,6 +963,8 @@ struct st_mysqlnd_res
MYSQLND_MEMORY_POOL * result_set_memory_pool;
zend_bool persistent;
+
+ struct st_mysqlnd_res_methods m;
};
@@ -895,7 +984,7 @@ struct st_mysqlnd_result_bind
struct st_mysqlnd_stmt_data
{
- MYSQLND *conn;
+ MYSQLND_CONN_DATA *conn;
unsigned long stmt_id;
unsigned long flags;/* cursor is set here */
enum_mysqlnd_stmt_state state;
@@ -909,9 +998,11 @@ struct st_mysqlnd_stmt_data
zend_bool result_zvals_separated_once;
zend_bool persistent;
- MYSQLND_UPSERT_STATUS upsert_status;
+ MYSQLND_UPSERT_STATUS * upsert_status;
+ MYSQLND_UPSERT_STATUS upsert_status_impl;
- MYSQLND_ERROR_INFO error_info;
+ MYSQLND_ERROR_INFO * error_info;
+ MYSQLND_ERROR_INFO error_info_impl;
zend_bool update_max_length;
unsigned long prefetch_rows;
@@ -931,4 +1022,64 @@ struct st_mysqlnd_stmt
zend_bool persistent;
};
+
+typedef struct st_mysqlnd_string
+{
+ char *s;
+ size_t l;
+} MYSQLND_STRING;
+
+
+struct st_mysqlnd_plugin_header
+{
+ unsigned int plugin_api_version;
+ const char * plugin_name;
+ unsigned long plugin_version;
+ const char * plugin_string_version;
+ const char * plugin_license;
+ const char * plugin_author;
+ struct
+ {
+ MYSQLND_STATS * values;
+ const MYSQLND_STRING * names;
+ } plugin_stats;
+
+ struct
+ {
+ enum_func_status (*plugin_shutdown)(void * plugin TSRMLS_DC);
+ } m;
+};
+
+
+struct st_mysqlnd_plugin_core
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+};
+
+
+struct st_mysqlnd_typeii_plugin_example
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+ void * methods;
+ unsigned int counter;
+};
+
+struct st_mysqlnd_authentication_plugin;
+
+typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authentication_plugin * self,
+ size_t * auth_data_len,
+ MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
+ const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
+ const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
+ TSRMLS_DC);
+
+struct st_mysqlnd_authentication_plugin
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+ struct {
+ func_auth_plugin__get_auth_data get_auth_data;
+ } methods;
+};
+
+
#endif /* MYSQLND_STRUCTS_H */
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 1318c37a73..ce94ad8d8e 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -12,11 +12,13 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
+
+/* $Id$ */
#include "php.h"
#include "php_globals.h"
#include "mysqlnd.h"
@@ -24,7 +26,6 @@
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
-#include "ext/standard/sha1.h"
#include "zend_ini.h"
#define MYSQLND_SILENT 1
@@ -34,9 +35,9 @@
#define PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_size, packet_type_as_text, packet_type) \
{ \
DBG_INF_FMT("buf=%p size=%u", (buf), (buf_size)); \
- if (FAIL == mysqlnd_read_header((conn), &((packet)->header) TSRMLS_CC)) {\
+ if (FAIL == mysqlnd_read_header((conn)->net, &((packet)->header), (conn)->stats, ((conn)->error_info) TSRMLS_CC)) {\
CONN_SET_STATE(conn, CONN_QUIT_SENT); \
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mysqlnd_server_gone); \
DBG_ERR_FMT("Can't read %s's header", (packet_type_as_text)); \
DBG_RETURN(FAIL);\
@@ -46,9 +47,9 @@
(buf_size), (packet)->header.size, (packet)->header.size - (buf_size)); \
DBG_RETURN(FAIL); \
}\
- if (FAIL == conn->net->m.receive((conn), (buf), (packet)->header.size TSRMLS_CC)) { \
+ if (FAIL == conn->net->m.receive_ex((conn)->net, (buf), (packet)->header.size, (conn)->stats, ((conn)->error_info) TSRMLS_CC)) { \
CONN_SET_STATE(conn, CONN_QUIT_SENT); \
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mysqlnd_server_gone); \
DBG_ERR_FMT("Empty '%s' packet body", (packet_type_as_text)); \
DBG_RETURN(FAIL);\
@@ -257,14 +258,14 @@ end:
/* {{{ mysqlnd_read_header */
static enum_func_status
-mysqlnd_read_header(MYSQLND * conn, MYSQLND_PACKET_HEADER * header TSRMLS_DC)
+mysqlnd_read_header(MYSQLND_NET * net, MYSQLND_PACKET_HEADER * header,
+ MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- MYSQLND_NET * net = conn->net;
zend_uchar buffer[MYSQLND_HEADER_SIZE];
- DBG_ENTER("mysqlnd_read_header_name");
- DBG_INF_FMT("compressed=%u conn_id=%u", net->compressed, conn->thread_id);
- if (FAIL == net->m.receive(conn, buffer, MYSQLND_HEADER_SIZE TSRMLS_CC)) {
+ DBG_ENTER(mysqlnd_read_header_name);
+ DBG_INF_FMT("compressed=%u", net->compressed);
+ if (FAIL == net->m.receive_ex(net, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
DBG_RETURN(FAIL);
}
@@ -274,7 +275,7 @@ mysqlnd_read_header(MYSQLND * conn, MYSQLND_PACKET_HEADER * header TSRMLS_DC)
#ifdef MYSQLND_DUMP_HEADER_N_BODY
DBG_INF_FMT("HEADER: prot_packet_no=%u size=%3u", header->packet_no, header->size);
#endif
- MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats,
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats,
STAT_PROTOCOL_OVERHEAD_IN, MYSQLND_HEADER_SIZE,
STAT_PACKETS_RECEIVED, 1);
@@ -300,11 +301,12 @@ mysqlnd_read_header(MYSQLND * conn, MYSQLND_PACKET_HEADER * header TSRMLS_DC)
/* {{{ php_mysqlnd_greet_read */
static enum_func_status
-php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_uchar buf[2048];
zend_uchar *p = buf;
zend_uchar *begin = buf;
+ zend_uchar *pad_start = NULL;
MYSQLND_PACKET_GREET *packet= (MYSQLND_PACKET_GREET *) _packet;
DBG_ENTER("php_mysqlnd_greet_read");
@@ -312,6 +314,17 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "greeting", PROT_GREET_PACKET);
BAIL_IF_NO_MORE_DATA;
+ packet->auth_plugin_data = packet->intern_auth_plugin_data;
+ packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
+
+ if (packet->header.size < sizeof(buf)) {
+ /*
+ Null-terminate the string, so strdup can work even if the packets have a string at the end,
+ which is not ASCIIZ
+ */
+ buf[packet->header.size] = '\0';
+ }
+
packet->protocol_version = uint1korr(p);
p++;
BAIL_IF_NO_MORE_DATA;
@@ -340,8 +353,8 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
p+=4;
BAIL_IF_NO_MORE_DATA;
- memcpy(packet->scramble_buf, p, SCRAMBLE_LENGTH_323);
- p+= 8;
+ memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
+ p+= SCRAMBLE_LENGTH_323;
BAIL_IF_NO_MORE_DATA;
/* pad1 */
@@ -361,22 +374,56 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
BAIL_IF_NO_MORE_DATA;
/* pad2 */
+ pad_start = p;
p+= 13;
BAIL_IF_NO_MORE_DATA;
if ((size_t) (p - buf) < packet->header.size) {
- /* scramble_buf is split into two parts */
- memcpy(packet->scramble_buf + SCRAMBLE_LENGTH_323,
- p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+ /* auth_plugin_data is split into two parts */
+ memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+ p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
+ p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
} else {
packet->pre41 = TRUE;
}
+ /* Is this a 5.5+ server ? */
+ if ((size_t) (p - buf) < packet->header.size) {
+ /* backtrack one byte, the 0x0 at the end of the scramble in 5.1 and previous */
+ p--;
+
+ /* Additional 16 bits for server capabilities */
+ packet->server_capabilities |= uint2korr(pad_start) << 16;
+ /* And a length of the server scramble in one byte */
+ packet->auth_plugin_data_len = uint1korr(pad_start + 2);
+ if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
+ /* more data*/
+ zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
+ if (!new_auth_plugin_data) {
+ goto premature_end;
+ }
+ /* copy what we already have */
+ memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
+ /* add additional scramble data 5.5+ sent us */
+ memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
+ p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
+ packet->auth_plugin_data = new_auth_plugin_data;
+ }
+ }
+
+ if (packet->server_capabilities & CLIENT_PLUGIN_AUTH) {
+ BAIL_IF_NO_MORE_DATA;
+ /* The server is 5.5.x and supports authentication plugins */
+ packet->auth_protocol = estrdup((char *)p);
+ p+= strlen(packet->auth_protocol) + 1; /* eat the '\0' */
+ }
+
DBG_INF_FMT("proto=%u server=%s thread_id=%u",
packet->protocol_version, packet->server_version, packet->thread_id);
- DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i",
- packet->server_capabilities, packet->charset_no, packet->server_status);
+ DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
+ packet->server_capabilities, packet->charset_no, packet->server_status,
+ packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
DBG_RETURN(PASS);
premature_end:
@@ -390,13 +437,21 @@ premature_end:
/* {{{ php_mysqlnd_greet_free_mem */
static
-void php_mysqlnd_greet_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_GREET *p= (MYSQLND_PACKET_GREET *) _packet;
if (p->server_version) {
efree(p->server_version);
p->server_version = NULL;
}
+ if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
+ efree(p->auth_plugin_data);
+ p->auth_plugin_data = NULL;
+ }
+ if (p->auth_protocol) {
+ efree(p->auth_protocol);
+ p->auth_protocol = NULL;
+ }
if (!stack_allocation) {
mnd_pefree(p, p->header.persistent);
}
@@ -404,110 +459,109 @@ void php_mysqlnd_greet_free_mem(void *_packet, zend_bool stack_allocation TSRMLS
/* }}} */
-/* {{{ php_mysqlnd_crypt */
-static void
-php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
-{
- const zend_uchar *s1_end = s1 + len;
- while (s1 < s1_end) {
- *buffer++= *s1++ ^ *s2++;
- }
-}
-/* }}} */
-
-
-/* {{{ php_mysqlnd_scramble */
-void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password)
-{
- PHP_SHA1_CTX context;
- zend_uchar sha1[SHA1_MAX_LENGTH];
- zend_uchar sha2[SHA1_MAX_LENGTH];
-
-
- /* Phase 1: hash password */
- PHP_SHA1Init(&context);
- PHP_SHA1Update(&context, password, strlen((char *)password));
- PHP_SHA1Final(sha1, &context);
-
- /* Phase 2: hash sha1 */
- PHP_SHA1Init(&context);
- PHP_SHA1Update(&context, (zend_uchar*)sha1, SHA1_MAX_LENGTH);
- PHP_SHA1Final(sha2, &context);
-
- /* Phase 3: hash scramble + sha2 */
- PHP_SHA1Init(&context);
- PHP_SHA1Update(&context, scramble, SCRAMBLE_LENGTH);
- PHP_SHA1Update(&context, (zend_uchar*)sha2, SHA1_MAX_LENGTH);
- PHP_SHA1Final(buffer, &context);
-
- /* let's crypt buffer now */
- php_mysqlnd_crypt(buffer, (const zend_uchar *)buffer, (const zend_uchar *)sha1, SHA1_MAX_LENGTH);
-}
-/* }}} */
-
-
-#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SHA1_MAX_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 128)
+#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 1024)
/* {{{ php_mysqlnd_auth_write */
static
-size_t php_mysqlnd_auth_write(void *_packet, MYSQLND * conn TSRMLS_DC)
+size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- char buffer[AUTH_WRITE_BUFFER_LEN];
- register char *p= buffer + MYSQLND_HEADER_SIZE; /* start after the header */
+ zend_uchar buffer[AUTH_WRITE_BUFFER_LEN];
+ zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
int len;
- register MYSQLND_PACKET_AUTH *packet= (MYSQLND_PACKET_AUTH *) _packet;
+ MYSQLND_PACKET_AUTH * packet= (MYSQLND_PACKET_AUTH *) _packet;
DBG_ENTER("php_mysqlnd_auth_write");
- int4store(p, packet->client_flags);
- p+= 4;
+ if (!packet->is_change_user_packet) {
+ int4store(p, packet->client_flags);
+ p+= 4;
- int4store(p, packet->max_packet_size);
- p+= 4;
+ int4store(p, packet->max_packet_size);
+ p+= 4;
- int1store(p, packet->charset_no);
- p++;
+ int1store(p, packet->charset_no);
+ p++;
- memset(p, 0, 23); /* filler */
- p+= 23;
+ memset(p, 0, 23); /* filler */
+ p+= 23;
+ }
- if (!packet->send_half_packet) {
+ if (packet->send_auth_data || packet->is_change_user_packet) {
len = MIN(strlen(packet->user), MYSQLND_MAX_ALLOWED_USER_LEN);
memcpy(p, packet->user, len);
p+= len;
*p++ = '\0';
- /* copy scrambled pass*/
- if (packet->password && packet->password[0]) {
- /* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
- int1store(p, SHA1_MAX_LENGTH);
- p++;
- php_mysqlnd_scramble((zend_uchar*)p, packet->server_scramble_buf, (zend_uchar*)packet->password);
- p+= SHA1_MAX_LENGTH;
- } else {
- /* Zero length */
- int1store(p, 0);
- p++;
+ /* defensive coding */
+ if (packet->auth_data == NULL) {
+ packet->auth_data_len = 0;
+ }
+ if (packet->auth_data_len > 0xFF) {
+ const char * const msg = "Authentication data too long. "
+ "Won't fit into the buffer and will be truncated. Authentication will thus fail";
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, msg);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", msg);
+ DBG_RETURN(0);
+ }
+
+ int1store(p, packet->auth_data_len);
+ ++p;
+/*!!!!! is the buffer big enough ??? */
+ if ((sizeof(buffer) - (p - buffer)) < packet->auth_data_len) {
+ DBG_ERR("the stack buffer was not enough!!");
+ DBG_RETURN(0);
+ }
+ if (packet->auth_data_len) {
+ memcpy(p, packet->auth_data, packet->auth_data_len);
+ p+= packet->auth_data_len;
}
if (packet->db) {
+ /* CLIENT_CONNECT_WITH_DB should have been set */
size_t real_db_len = MIN(MYSQLND_MAX_ALLOWED_DB_LEN, packet->db_len);
memcpy(p, packet->db, real_db_len);
p+= real_db_len;
*p++= '\0';
+ } else if (packet->is_change_user_packet) {
+ *p++= '\0';
}
- /* Handle CLIENT_CONNECT_WITH_DB */
/* no \0 for no DB */
- }
- DBG_RETURN(conn->net->m.send(conn, buffer, p - buffer - MYSQLND_HEADER_SIZE TSRMLS_CC));
+ if (packet->is_change_user_packet) {
+ if (packet->charset_no) {
+ int2store(p, packet->charset_no);
+ p+= 2;
+ }
+ }
+
+ if (packet->auth_plugin_name) {
+ size_t len = MIN(strlen(packet->auth_plugin_name), sizeof(buffer) - (p - buffer) - 1);
+ memcpy(p, packet->auth_plugin_name, len);
+ p+= len;
+ *p++= '\0';
+ }
+ }
+ if (packet->is_change_user_packet) {
+ if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
+ PROT_LAST /* the caller will handle the OK packet */,
+ packet->silent, TRUE TSRMLS_CC)) {
+ DBG_RETURN(0);
+ }
+ DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE);
+ } else {
+ size_t sent = conn->net->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC);
+ if (!sent) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+ DBG_RETURN(sent);
+ }
}
/* }}} */
/* {{{ php_mysqlnd_auth_free_mem */
static
-void php_mysqlnd_auth_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_auth_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
if (!stack_allocation) {
MYSQLND_PACKET_AUTH * p = (MYSQLND_PACKET_AUTH *) _packet;
@@ -517,11 +571,174 @@ void php_mysqlnd_auth_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_
/* }}} */
+#define AUTH_RESP_BUFFER_SIZE 2048
+
+/* {{{ php_mysqlnd_auth_response_read */
+static enum_func_status
+php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
+{
+ zend_uchar local_buf[AUTH_RESP_BUFFER_SIZE];
+ size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length: AUTH_RESP_BUFFER_SIZE;
+ zend_uchar *buf = conn->net->cmd_buffer.buffer? (zend_uchar *) conn->net->cmd_buffer.buffer : local_buf;
+ zend_uchar *p = buf;
+ zend_uchar *begin = buf;
+ unsigned long i;
+ register MYSQLND_PACKET_AUTH_RESPONSE * packet= (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
+
+ DBG_ENTER("php_mysqlnd_auth_response_read");
+
+ /* leave space for terminating safety \0 */
+ buf_len--;
+ PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "OK", PROT_OK_PACKET);
+ BAIL_IF_NO_MORE_DATA;
+
+ /*
+ zero-terminate the buffer for safety. We are sure there is place for the \0
+ because buf_len is -1 the size of the buffer pointed
+ */
+ buf[packet->header.size] = '\0';
+
+ /* Should be always 0x0 or ERROR_MARKER for error */
+ packet->response_code = uint1korr(p);
+ p++;
+ BAIL_IF_NO_MORE_DATA;
+
+ if (ERROR_MARKER == packet->response_code) {
+ php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
+ packet->error, sizeof(packet->error),
+ &packet->error_no, packet->sqlstate
+ TSRMLS_CC);
+ DBG_RETURN(PASS);
+ }
+ if (0xFE == packet->response_code) {
+ /* Authentication Switch Response */
+ if (packet->header.size > (size_t) (p - buf)) {
+ packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
+ packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
+ p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
+
+ packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
+ if (packet->new_auth_protocol_data_len) {
+ packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
+ memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
+ }
+ DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
+ DBG_INF_FMT("Server salt : [%*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
+ }
+ } else {
+ /* Everything was fine! */
+ packet->affected_rows = php_mysqlnd_net_field_length_ll(&p);
+ BAIL_IF_NO_MORE_DATA;
+
+ packet->last_insert_id = php_mysqlnd_net_field_length_ll(&p);
+ BAIL_IF_NO_MORE_DATA;
+
+ packet->server_status = uint2korr(p);
+ p+= 2;
+ BAIL_IF_NO_MORE_DATA;
+
+ packet->warning_count = uint2korr(p);
+ p+= 2;
+ BAIL_IF_NO_MORE_DATA;
+
+ /* There is a message */
+ if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
+ packet->message_len = MIN(i, buf_len - (p - begin));
+ packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
+ } else {
+ packet->message = NULL;
+ packet->message_len = 0;
+ }
+
+ DBG_INF_FMT("OK packet: aff_rows=%lld last_ins_id=%ld server_status=%u warnings=%u",
+ packet->affected_rows, packet->last_insert_id, packet->server_status,
+ packet->warning_count);
+ }
+
+ DBG_RETURN(PASS);
+premature_end:
+ DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "AUTH_RESPONSE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
+ p - begin - packet->header.size);
+ DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_auth_response_free_mem */
+static void
+php_mysqlnd_auth_response_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
+{
+ MYSQLND_PACKET_AUTH_RESPONSE * p = (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
+ if (p->message) {
+ mnd_efree(p->message);
+ p->message = NULL;
+ }
+ if (p->new_auth_protocol) {
+ mnd_efree(p->new_auth_protocol);
+ p->new_auth_protocol = NULL;
+ }
+ p->new_auth_protocol_len = 0;
+
+ if (p->new_auth_protocol_data) {
+ mnd_efree(p->new_auth_protocol_data);
+ p->new_auth_protocol_data = NULL;
+ }
+ p->new_auth_protocol_data_len = 0;
+
+ if (!stack_allocation) {
+ mnd_pefree(p, p->header.persistent);
+ }
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_change_auth_response_write */
+static size_t
+php_mysqlnd_change_auth_response_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
+{
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *packet= (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
+ zend_uchar * buffer = conn->net->cmd_buffer.length >= packet->auth_data_len? conn->net->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
+ zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
+
+ DBG_ENTER("php_mysqlnd_change_auth_response_write");
+
+ if (packet->auth_data_len) {
+ memcpy(p, packet->auth_data, packet->auth_data_len);
+ p+= packet->auth_data_len;
+ }
+
+ {
+ size_t sent = conn->net->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC);
+ if (buffer != conn->net->cmd_buffer.buffer) {
+ mnd_efree(buffer);
+ }
+ if (!sent) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+ DBG_RETURN(sent);
+ }
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_change_auth_response_free_mem */
+static void
+php_mysqlnd_change_auth_response_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
+{
+ if (!stack_allocation) {
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * p = (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
+ mnd_pefree(p, p->header.persistent);
+ }
+}
+/* }}} */
+
+
#define OK_BUFFER_SIZE 2048
/* {{{ php_mysqlnd_ok_read */
static enum_func_status
-php_mysqlnd_ok_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_uchar local_buf[OK_BUFFER_SIZE];
size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length : OK_BUFFER_SIZE;
@@ -590,7 +807,7 @@ premature_end:
/* {{{ php_mysqlnd_ok_free_mem */
static void
-php_mysqlnd_ok_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_ok_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_OK *p= (MYSQLND_PACKET_OK *) _packet;
if (p->message) {
@@ -606,7 +823,7 @@ php_mysqlnd_ok_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
/* {{{ php_mysqlnd_eof_read */
static enum_func_status
-php_mysqlnd_eof_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_eof_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/*
EOF packet is since 4.1 five bytes long,
@@ -673,7 +890,7 @@ premature_end:
/* {{{ php_mysqlnd_eof_free_mem */
static
-void php_mysqlnd_eof_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_eof_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
if (!stack_allocation) {
mnd_pefree(_packet, ((MYSQLND_PACKET_EOF *)_packet)->header.persistent);
@@ -683,13 +900,13 @@ void php_mysqlnd_eof_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_D
/* {{{ php_mysqlnd_cmd_write */
-size_t php_mysqlnd_cmd_write(void *_packet, MYSQLND *conn TSRMLS_DC)
+size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* Let's have some space, which we can use, if not enough, we will allocate new buffer */
- MYSQLND_PACKET_COMMAND *packet= (MYSQLND_PACKET_COMMAND *) _packet;
- MYSQLND_NET *net = conn->net;
+ MYSQLND_PACKET_COMMAND * packet= (MYSQLND_PACKET_COMMAND *) _packet;
+ MYSQLND_NET * net = conn->net;
unsigned int error_reporting = EG(error_reporting);
- size_t written = 0;
+ size_t sent = 0;
DBG_ENTER("php_mysqlnd_cmd_write");
/*
@@ -710,12 +927,12 @@ size_t php_mysqlnd_cmd_write(void *_packet, MYSQLND *conn TSRMLS_DC)
#endif
if (!packet->argument || !packet->arg_len) {
- char buffer[MYSQLND_HEADER_SIZE + 1];
+ zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
int1store(buffer + MYSQLND_HEADER_SIZE, packet->command);
- written = conn->net->m.send(conn, buffer, 1 TSRMLS_CC);
+ sent = net->m.send_ex(net, buffer, 1, conn->stats, conn->error_info TSRMLS_CC);
} else {
- size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE, ret;
+ size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE;
zend_uchar *tmp, *p;
tmp = (tmp_len > net->cmd_buffer.length)? mnd_emalloc(tmp_len):net->cmd_buffer.buffer;
if (!tmp) {
@@ -728,26 +945,28 @@ size_t php_mysqlnd_cmd_write(void *_packet, MYSQLND *conn TSRMLS_DC)
memcpy(p, packet->argument, packet->arg_len);
- ret = conn->net->m.send(conn, (char *)tmp, tmp_len - MYSQLND_HEADER_SIZE TSRMLS_CC);
+ sent = net->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC);
if (tmp != net->cmd_buffer.buffer) {
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CMD_BUFFER_TOO_SMALL);
mnd_efree(tmp);
}
- written = ret;
}
end:
if (error_reporting) {
/* restore error reporting */
EG(error_reporting) = error_reporting;
}
- DBG_RETURN(written);
+ if (!sent) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+ DBG_RETURN(sent);
}
/* }}} */
/* {{{ php_mysqlnd_cmd_free_mem */
static
-void php_mysqlnd_cmd_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_cmd_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
if (!stack_allocation) {
MYSQLND_PACKET_COMMAND * p = (MYSQLND_PACKET_COMMAND *) _packet;
@@ -759,7 +978,7 @@ void php_mysqlnd_cmd_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_D
/* {{{ php_mysqlnd_rset_header_read */
static enum_func_status
-php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
enum_func_status ret = PASS;
size_t buf_len = conn->net->cmd_buffer.length;
@@ -809,8 +1028,8 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
packet->info_or_local_file[len] = '\0';
packet->info_or_local_file_len = len;
} else {
- SET_OOM_ERROR(conn->error_info);
- ret = FAIL;
+ SET_OOM_ERROR(*conn->error_info);
+ ret = FAIL;
}
break;
case 0x00:
@@ -836,7 +1055,7 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
packet->info_or_local_file[len] = '\0';
packet->info_or_local_file_len = len;
} else {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
}
}
@@ -863,7 +1082,7 @@ premature_end:
/* {{{ php_mysqlnd_rset_header_free_mem */
static
-void php_mysqlnd_rset_header_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_rset_header_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_RSET_HEADER *p= (MYSQLND_PACKET_RSET_HEADER *) _packet;
DBG_ENTER("php_mysqlnd_rset_header_free_mem");
@@ -897,7 +1116,7 @@ static size_t rset_field_offsets[] =
/* {{{ php_mysqlnd_rset_field_read */
static enum_func_status
-php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* Should be enough for the metadata of a single row */
MYSQLND_PACKET_RES_FIELD *packet= (MYSQLND_PACKET_RES_FIELD *) _packet;
@@ -1013,8 +1232,8 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_INF_FMT("Def found, length %lu, persistent=%u", len, packet->persistent_alloc);
meta->def = mnd_pemalloc(len + 1, packet->persistent_alloc);
if (!meta->def) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL);
+ SET_OOM_ERROR(*conn->error_info);
+ DBG_RETURN(FAIL);
}
memcpy(meta->def, p, len);
meta->def[len] = '\0';
@@ -1025,10 +1244,10 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_INF_FMT("allocing root. persistent=%u", packet->persistent_alloc);
root_ptr = meta->root = mnd_pemalloc(total_len, packet->persistent_alloc);
if (!root_ptr) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL);
+ SET_OOM_ERROR(*conn->error_info);
+ DBG_RETURN(FAIL);
}
-
+
meta->root_len = total_len;
/* Now do allocs */
if (meta->catalog && meta->catalog != mysqlnd_empty_string) {
@@ -1094,7 +1313,7 @@ premature_end:
/* {{{ php_mysqlnd_rset_field_free_mem */
static
-void php_mysqlnd_rset_field_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_rset_field_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_RES_FIELD *p= (MYSQLND_PACKET_RES_FIELD *) _packet;
/* p->metadata was passed to us as temporal buffer */
@@ -1107,14 +1326,14 @@ void php_mysqlnd_rset_field_free_mem(void *_packet, zend_bool stack_allocation T
/* {{{ php_mysqlnd_read_row_ex */
static enum_func_status
-php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_pool,
- MYSQLND_MEMORY_POOL_CHUNK **buffer,
- size_t *data_size, zend_bool persistent_alloc,
+php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_set_memory_pool,
+ MYSQLND_MEMORY_POOL_CHUNK ** buffer,
+ size_t * data_size, zend_bool persistent_alloc,
unsigned int prealloc_more_bytes TSRMLS_DC)
{
enum_func_status ret = PASS;
MYSQLND_PACKET_HEADER header;
- zend_uchar *p = NULL;
+ zend_uchar * p = NULL;
zend_bool first_iteration = TRUE;
DBG_ENTER("php_mysqlnd_read_row_ex");
@@ -1129,7 +1348,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
*data_size = prealloc_more_bytes;
while (1) {
- if (FAIL == mysqlnd_read_header(conn , &header TSRMLS_CC)) {
+ if (FAIL == mysqlnd_read_header(conn->net, &header, conn->stats, conn->error_info TSRMLS_CC)) {
ret = FAIL;
break;
}
@@ -1161,7 +1380,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
to be able to implement read-only variables.
*/
if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size + 1 TSRMLS_CC)) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -1169,7 +1388,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
p = (*buffer)->ptr + (*data_size - header.size);
}
- if (PASS != (ret = conn->net->m.receive(conn, p, header.size TSRMLS_CC))) {
+ if (PASS != (ret = conn->net->m.receive_ex(conn->net, p, header.size, conn->stats, conn->error_info TSRMLS_CC))) {
DBG_ERR("Empty row packet body");
php_error(E_WARNING, "Empty row packet body");
break;
@@ -1193,13 +1412,12 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
enum_func_status
php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC)
{
unsigned int i;
- zend_uchar *p = row_buffer->ptr;
- zend_uchar *null_ptr, bit;
+ zend_uchar * p = row_buffer->ptr;
+ zend_uchar * null_ptr, bit;
zval **current_field, **end_field, **start_field;
DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");
@@ -1293,16 +1511,15 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
enum_func_status
php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC)
{
unsigned int i;
zend_bool last_field_was_string = FALSE;
zval **current_field, **end_field, **start_field;
- zend_uchar *p = row_buffer->ptr;
+ zend_uchar * p = row_buffer->ptr;
size_t data_size = row_buffer->app;
- zend_uchar *bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */
+ zend_uchar * bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol");
@@ -1525,9 +1742,9 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
if PS => packet->fields is passed from outside
*/
static enum_func_status
-php_mysqlnd_rowp_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- MYSQLND_NET *net = conn->net;
+ MYSQLND_NET * net = conn->net;
zend_uchar *p;
enum_func_status ret = PASS;
size_t old_chunk_size = net->stream->chunk_size;
@@ -1620,7 +1837,7 @@ end:
/* {{{ php_mysqlnd_rowp_free_mem */
static void
-php_mysqlnd_rowp_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_rowp_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_ROW *p;
@@ -1648,7 +1865,7 @@ php_mysqlnd_rowp_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
/* {{{ php_mysqlnd_stats_read */
static enum_func_status
-php_mysqlnd_stats_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_stats_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
MYSQLND_PACKET_STATS *packet= (MYSQLND_PACKET_STATS *) _packet;
size_t buf_len = conn->net->cmd_buffer.length;
@@ -1670,7 +1887,7 @@ php_mysqlnd_stats_read(void *_packet, MYSQLND *conn TSRMLS_DC)
/* {{{ php_mysqlnd_stats_free_mem */
static
-void php_mysqlnd_stats_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_stats_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_STATS *p= (MYSQLND_PACKET_STATS *) _packet;
if (p->message) {
@@ -1690,7 +1907,7 @@ void php_mysqlnd_stats_free_mem(void *_packet, zend_bool stack_allocation TSRMLS
/* {{{ php_mysqlnd_prepare_read */
static enum_func_status
-php_mysqlnd_prepare_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_prepare_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* In case of an error, we should have place to put it */
size_t buf_len = conn->net->cmd_buffer.length;
@@ -1766,7 +1983,7 @@ premature_end:
/* {{{ php_mysqlnd_prepare_free_mem */
static void
-php_mysqlnd_prepare_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_prepare_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_PREPARE_RESPONSE *p= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
if (!stack_allocation) {
@@ -1778,7 +1995,7 @@ php_mysqlnd_prepare_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC
/* {{{ php_mysqlnd_chg_user_read */
static enum_func_status
-php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_chg_user_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* There could be an error message */
size_t buf_len = conn->net->cmd_buffer.length;
@@ -1798,7 +2015,7 @@ php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
*/
/* Should be always 0x0 or ERROR_MARKER for error */
- packet->field_count= uint1korr(p);
+ packet->response_code = uint1korr(p);
p++;
if (packet->header.size == 1 && buf[0] == EODATA_MARKER && packet->server_capabilities & CLIENT_SECURE_CONNECTION) {
@@ -1807,7 +2024,7 @@ php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_RETURN(FAIL);
}
- if (ERROR_MARKER == packet->field_count) {
+ if (ERROR_MARKER == packet->response_code) {
php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
packet->error_info.error,
sizeof(packet->error_info.error),
@@ -1816,6 +2033,18 @@ php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
TSRMLS_CC);
}
BAIL_IF_NO_MORE_DATA;
+ if (packet->response_code == 0xFE && packet->header.size > (size_t) (p - buf)) {
+ packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
+ packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
+ p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
+ packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
+ if (packet->new_auth_protocol_data_len) {
+ packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
+ memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
+ }
+ DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
+ DBG_INF_FMT("Server salt : [%*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
+ }
DBG_RETURN(PASS);
premature_end:
@@ -1829,10 +2058,24 @@ premature_end:
/* {{{ php_mysqlnd_chg_user_free_mem */
static void
-php_mysqlnd_chg_user_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_chg_user_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
+ MYSQLND_PACKET_CHG_USER_RESPONSE * p = (MYSQLND_PACKET_CHG_USER_RESPONSE *) _packet;
+
+ if (p->new_auth_protocol) {
+ mnd_efree(p->new_auth_protocol);
+ p->new_auth_protocol = NULL;
+ }
+ p->new_auth_protocol_len = 0;
+
+ if (p->new_auth_protocol_data) {
+ mnd_efree(p->new_auth_protocol_data);
+ p->new_auth_protocol_data = NULL;
+ }
+ p->new_auth_protocol_data_len = 0;
+
if (!stack_allocation) {
- mnd_pefree(_packet, ((MYSQLND_PACKET_CHG_USER_RESPONSE *)_packet)->header.persistent);
+ mnd_pefree(p, p->header.persistent);
}
}
/* }}} */
@@ -1855,6 +2098,18 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] =
php_mysqlnd_auth_free_mem,
}, /* PROT_AUTH_PACKET */
{
+ sizeof(MYSQLND_PACKET_AUTH_RESPONSE),
+ php_mysqlnd_auth_response_read, /* read */
+ NULL, /* write */
+ php_mysqlnd_auth_response_free_mem,
+ }, /* PROT_AUTH_RESP_PACKET */
+ {
+ sizeof(MYSQLND_PACKET_CHANGE_AUTH_RESPONSE),
+ NULL, /* read */
+ php_mysqlnd_change_auth_response_write, /* write */
+ php_mysqlnd_change_auth_response_free_mem,
+ }, /* PROT_CHANGE_AUTH_RESP_PACKET */
+ {
sizeof(MYSQLND_PACKET_OK),
php_mysqlnd_ok_read, /* read */
NULL, /* write */
@@ -1942,6 +2197,36 @@ MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL * const proto
/* }}} */
+/* {{{ mysqlnd_protocol::get_auth_response_packet */
+static struct st_mysqlnd_packet_auth_response *
+MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC)
+{
+ struct st_mysqlnd_packet_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_AUTH_RESP_PACKET].struct_size, persistent);
+ DBG_ENTER("mysqlnd_protocol::get_auth_response_packet");
+ if (packet) {
+ packet->header.m = &packet_methods[PROT_AUTH_RESP_PACKET];
+ packet->header.persistent = persistent;
+ }
+ DBG_RETURN(packet);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol::get_change_auth_response_packet */
+static struct st_mysqlnd_packet_change_auth_response *
+MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC)
+{
+ struct st_mysqlnd_packet_change_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_CHANGE_AUTH_RESP_PACKET].struct_size, persistent);
+ DBG_ENTER("mysqlnd_protocol::get_change_auth_response_packet");
+ if (packet) {
+ packet->header.m = &packet_methods[PROT_CHANGE_AUTH_RESP_PACKET];
+ packet->header.persistent = persistent;
+ }
+ DBG_RETURN(packet);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_protocol::get_ok_packet */
static struct st_mysqlnd_packet_ok *
MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC)
@@ -2077,10 +2362,11 @@ MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOC
/* }}} */
-static
MYSQLND_CLASS_METHODS_START(mysqlnd_protocol)
MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet),
+ MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet),
+ MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_command_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet),
@@ -2097,16 +2383,9 @@ MYSQLND_CLASS_METHODS_END;
PHPAPI MYSQLND_PROTOCOL *
mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC)
{
- size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_PROTOCOL *ret = mnd_pecalloc(1, alloc_size, persistent);
-
+ MYSQLND_PROTOCOL * ret;
DBG_ENTER("mysqlnd_protocol_init");
- DBG_INF_FMT("persistent=%u", persistent);
- if (ret) {
- ret->persistent = persistent;
- ret->m = mysqlnd_mysqlnd_protocol_methods;
- }
-
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_protocol_decoder(persistent TSRMLS_CC);
DBG_RETURN(ret);
}
/* }}} */
@@ -2127,29 +2406,6 @@ mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol TSRMLS_DC)
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_protocol_data */
-PHPAPI void **
-_mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_protocol_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!protocol || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)protocol + sizeof(MYSQLND_PROTOCOL) + plugin_id * sizeof(void *)));
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_protocol_get_methods */
-PHPAPI struct st_mysqlnd_protocol_methods *
-mysqlnd_protocol_get_methods()
-{
- return &mysqlnd_mysqlnd_protocol_methods;
-}
-/* }}} */
-
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h
index be14e09e7e..96322d7060 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -51,8 +51,8 @@ PHPAPI extern const char * const mysqlnd_command_to_text[COM_END];
/* Low-level extraction functionality */
typedef struct st_mysqlnd_packet_methods {
size_t struct_size;
- enum_func_status (*read_from_net)(void *packet, MYSQLND *conn TSRMLS_DC);
- size_t (*write_to_net)(void *packet, MYSQLND *conn TSRMLS_DC);
+ enum_func_status (*read_from_net)(void * packet, MYSQLND_CONN_DATA * conn TSRMLS_DC);
+ size_t (*write_to_net)(void * packet, MYSQLND_CONN_DATA * conn TSRMLS_DC);
void (*free_mem)(void *packet, zend_bool stack_allocation TSRMLS_DC);
} mysqlnd_packet_methods;
@@ -70,17 +70,20 @@ typedef struct st_mysqlnd_packet_greet {
uint8_t protocol_version;
char *server_version;
uint32_t thread_id;
- zend_uchar scramble_buf[SCRAMBLE_LENGTH];
+ zend_uchar intern_auth_plugin_data[SCRAMBLE_LENGTH];
+ zend_uchar * auth_plugin_data;
+ size_t auth_plugin_data_len;
/* 1 byte pad */
- uint16_t server_capabilities;
+ uint32_t server_capabilities;
uint8_t charset_no;
uint16_t server_status;
- /* 13 byte pad*/
+ /* 13 byte pad, in 5.5 first 2 bytes are more capabilities followed by 1 byte scramble_length */
zend_bool pre41;
/* If error packet, we use these */
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
- unsigned int error_no;
+ unsigned int error_no;
+ char *auth_protocol;
} MYSQLND_PACKET_GREET;
@@ -89,21 +92,50 @@ typedef struct st_mysqlnd_packet_auth {
MYSQLND_PACKET_HEADER header;
uint32_t client_flags;
uint32_t max_packet_size;
- uint8_t charset_no;
- /* 23 byte pad */
+ uint8_t charset_no;
const char *user;
- /* 8 byte scramble */
+ const zend_uchar *auth_data;
+ size_t auth_data_len;
const char *db;
- /* 12 byte scramble */
-
+ const char *auth_plugin_name;
/* Here the packet ends. This is user supplied data */
- const char *password;
- /* +1 for \0 because of scramble() */
- unsigned char *server_scramble_buf;
- size_t db_len;
- zend_bool send_half_packet;
+ size_t db_len;
+ zend_bool send_auth_data;
+ zend_bool is_change_user_packet;
+ zend_bool silent;
+
} MYSQLND_PACKET_AUTH;
+/* Auth response packet */
+typedef struct st_mysqlnd_packet_auth_response {
+ MYSQLND_PACKET_HEADER header;
+ uint8_t response_code;
+ uint64_t affected_rows;
+ uint64_t last_insert_id;
+ uint16_t server_status;
+ uint16_t warning_count;
+ char *message;
+ size_t message_len;
+ /* If error packet, we use these */
+ char error[MYSQLND_ERRMSG_SIZE+1];
+ char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
+ unsigned int error_no;
+
+ char *new_auth_protocol;
+ size_t new_auth_protocol_len;
+ zend_uchar *new_auth_protocol_data;
+ size_t new_auth_protocol_data_len;
+} MYSQLND_PACKET_AUTH_RESPONSE;
+
+
+/* Auth response packet */
+typedef struct st_mysqlnd_packet_change_auth_response {
+ MYSQLND_PACKET_HEADER header;
+ const zend_uchar *auth_data;
+ size_t auth_data_len;
+} MYSQLND_PACKET_CHANGE_AUTH_RESPONSE;
+
+
/* OK packet */
typedef struct st_mysqlnd_packet_ok {
MYSQLND_PACKET_HEADER header;
@@ -125,7 +157,7 @@ typedef struct st_mysqlnd_packet_ok {
typedef struct st_mysqlnd_packet_command {
MYSQLND_PACKET_HEADER header;
enum php_mysqlnd_server_command command;
- const char *argument;
+ const zend_uchar *argument;
size_t arg_len;
} MYSQLND_PACKET_COMMAND;
@@ -239,17 +271,22 @@ typedef struct st_mysqlnd_packet_prepare_response {
/* Statistics packet */
typedef struct st_mysqlnd_packet_chg_user_resp {
MYSQLND_PACKET_HEADER header;
- uint32_t field_count;
+ uint32_t response_code;
/* message_len is not part of the packet*/
uint16_t server_capabilities;
/* If error packet, we use these */
MYSQLND_ERROR_INFO error_info;
zend_bool server_asked_323_auth;
+
+ char *new_auth_protocol;
+ size_t new_auth_protocol_len;
+ zend_uchar *new_auth_protocol_data;
+ size_t new_auth_protocol_data_len;
} MYSQLND_PACKET_CHG_USER_RESPONSE;
-PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass);
+PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len);
unsigned long php_mysqlnd_net_field_length(zend_uchar **packet);
zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);
@@ -259,21 +296,18 @@ PHPAPI const extern char * const mysqlnd_empty_string;
enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC);
PHPAPI MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC);
PHPAPI void mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol TSRMLS_DC);
-PHPAPI struct st_mysqlnd_protocol_methods * mysqlnd_protocol_get_methods();
#endif /* MYSQLND_WIREPROTOCOL_H */
diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c
index 58632443da..20fcc5e7ad 100644
--- a/ext/mysqlnd/php_mysqlnd.c
+++ b/ext/mysqlnd/php_mysqlnd.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -24,7 +24,10 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_reverse_api.h"
#include "ext/standard/info.h"
+#include "ext/standard/php_smart_str.h"
/* {{{ mysqlnd_functions[]
*
@@ -92,12 +95,71 @@ PHPAPI void mysqlnd_minfo_print_hash(zval *values)
/* }}} */
+/* {{{ mysqlnd_minfo_dump_plugin_stats */
+static int
+mysqlnd_minfo_dump_plugin_stats(void *pDest, void * argument TSRMLS_DC)
+{
+ struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ if (plugin_header->plugin_stats.values) {
+ char buf[64];
+ zval values;
+ snprintf(buf, sizeof(buf), "%s statistics", plugin_header->plugin_name);
+
+ mysqlnd_fill_stats_hash(plugin_header->plugin_stats.values, plugin_header->plugin_stats.names, &values TSRMLS_CC ZEND_FILE_LINE_CC);
+
+ php_info_print_table_start();
+ php_info_print_table_header(2, buf, "");
+ mysqlnd_minfo_print_hash(&values);
+ php_info_print_table_end();
+ zval_dtor(&values);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_minfo_dump_loaded_plugins */
+static int
+mysqlnd_minfo_dump_loaded_plugins(void *pDest, void * buf TSRMLS_DC)
+{
+ smart_str * buffer = (smart_str *) buf;
+ struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ if (plugin_header->plugin_name) {
+ if (buffer->len) {
+ smart_str_appendc(buffer, ',');
+ }
+ smart_str_appends(buffer, plugin_header->plugin_name);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+/* {{{ mysqlnd_minfo_dump_api_plugins */
+static void
+mysqlnd_minfo_dump_api_plugins(smart_str * buffer TSRMLS_DC)
+{
+ HashTable *ht = mysqlnd_reverse_api_get_api_list(TSRMLS_C);
+ Bucket *p;
+
+ p = ht->pListHead;
+ while(p != NULL) {
+ MYSQLND_REVERSE_API * ext = *(MYSQLND_REVERSE_API **) p->pData;
+ if (buffer->len) {
+ smart_str_appendc(buffer, ',');
+ }
+ smart_str_appends(buffer, ext->module->name);
+
+ p = p->pListNext;
+ }
+}
+/* }}} */
+
+
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(mysqlnd)
{
char buf[32];
- zval values;
php_info_print_table_start();
php_info_print_table_header(2, "mysqlnd", "enabled");
@@ -124,16 +186,26 @@ PHP_MINFO_FUNCTION(mysqlnd)
php_info_print_table_row(2, "Collecting memory statistics", MYSQLND_G(collect_memory_statistics)? "Yes":"No");
php_info_print_table_row(2, "Tracing", MYSQLND_G(debug)? MYSQLND_G(debug):"n/a");
- php_info_print_table_end();
- /* Print client stats */
- php_info_print_table_start();
- php_info_print_table_header(2, "Client statistics", "");
- mysqlnd_get_client_stats(&values);
- mysqlnd_minfo_print_hash(&values);
+ /* loaded plugins */
+ {
+ smart_str tmp_str = {0, 0, 0};
+ mysqlnd_plugin_apply_with_argument(mysqlnd_minfo_dump_loaded_plugins, &tmp_str);
+ smart_str_0(&tmp_str);
+ php_info_print_table_row(2, "Loaded plugins", tmp_str.c);
+ smart_str_free(&tmp_str);
+
+ mysqlnd_minfo_dump_api_plugins(&tmp_str TSRMLS_CC);
+ smart_str_0(&tmp_str);
+ php_info_print_table_row(2, "API Extensions", tmp_str.c);
+ smart_str_free(&tmp_str);
+ }
- zval_dtor(&values);
php_info_print_table_end();
+
+
+ /* Print client stats */
+ mysqlnd_plugin_apply_with_argument(mysqlnd_minfo_dump_plugin_stats, NULL);
}
/* }}} */
@@ -187,7 +259,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("mysqlnd.log_mask", "0", PHP_INI_ALL, OnUpdateLong, log_mask, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.mempool_default_size","16000", PHP_INI_ALL, OnUpdateLong, mempool_default_size, zend_mysqlnd_globals, mysqlnd_globals)
-#ifdef PHP_DEBUG
+#if PHP_DEBUG
STD_PHP_INI_ENTRY("mysqlnd.debug_emalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_emalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug_ecalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_ecalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug_erealloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_erealloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
@@ -224,28 +296,30 @@ static PHP_MSHUTDOWN_FUNCTION(mysqlnd)
/* }}} */
-#if defined(PHP_DEBUG)
+#if PHP_DEBUG
/* {{{ PHP_RINIT_FUNCTION
*/
static PHP_RINIT_FUNCTION(mysqlnd)
{
-#if defined(PHP_DEBUG)
if (MYSQLND_G(debug)) {
- MYSQLND_DEBUG *dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
- if (!dbg) {
- return FAILURE;
+ struct st_mysqlnd_plugin_trace_log * trace_log_plugin = mysqlnd_plugin_find("debug_trace");
+ MYSQLND_G(dbg) = NULL;
+ if (trace_log_plugin) {
+ MYSQLND_DEBUG * dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
+ if (!dbg) {
+ return FAILURE;
+ }
+ dbg->m->set_mode(dbg, MYSQLND_G(debug));
+ MYSQLND_G(dbg) = dbg;
}
- dbg->m->set_mode(dbg, MYSQLND_G(debug));
- MYSQLND_G(dbg) = dbg;
}
-#endif
return SUCCESS;
}
/* }}} */
#endif
-#if defined(PHP_DEBUG)
+#if PHP_DEBUG
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
static PHP_RSHUTDOWN_FUNCTION(mysqlnd)
@@ -279,12 +353,12 @@ zend_module_entry mysqlnd_module_entry = {
mysqlnd_functions,
PHP_MINIT(mysqlnd),
PHP_MSHUTDOWN(mysqlnd),
-#if defined(PHP_DEBUG)
+#if PHP_DEBUG
PHP_RINIT(mysqlnd),
#else
NULL,
#endif
-#ifdef PHP_DEBUG
+#if PHP_DEBUG
PHP_RSHUTDOWN(mysqlnd),
#else
NULL,
diff --git a/ext/mysqlnd/php_mysqlnd.h b/ext/mysqlnd/php_mysqlnd.h
index 5e7a5e538b..c8a749df6d 100644
--- a/ext/mysqlnd/php_mysqlnd.h
+++ b/ext/mysqlnd/php_mysqlnd.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@php.net> |
- | Andrey Hristov <andrey@php.net> |
- | Ulf Wendel <uw@php.net> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
$Id$
diff --git a/ext/oci8/tests/null_byte_1.phpt b/ext/oci8/tests/null_byte_1.phpt
index 1439bd5d66..0869d94123 100644
--- a/ext/oci8/tests/null_byte_1.phpt
+++ b/ext/oci8/tests/null_byte_1.phpt
@@ -1,13 +1,21 @@
--TEST--
-Protect against null bytes in LOB filenames (http://news.php.net/php.internals/50202)
+Protect against null bytes in LOB filenames
--SKIPIF--
-<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+<?php
+if (!extension_loaded('oci8'))
+ die ("skip no oci8 extension");
+if (PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4))
+ die ("skip Test only valid for PHP 5.4 onwards");
+?>
--INI--
display_errors = On
error_reporting = E_WARNING
--FILE--
<?php
+// See http://news.php.net/php.internals/50202
+// http://svn.php.net/viewvc?view=revision&revision=311870
+
require(dirname(__FILE__).'/connect.inc');
// Run Test
@@ -29,10 +37,10 @@ var_dump($r);
--EXPECTF--
Test 1: Import
-Warning: OCI-Lob::savefile(): Filename cannot contain null bytes in %snull_byte_1.php on line %d
-bool(false)
+Warning: OCI-Lob::savefile() expects parameter 1 to be a valid path, string given in %snull_byte_1.php on line %d
+NULL
Test 2: Export
-Warning: OCI-Lob::export(): Filename cannot contain null bytes in %snull_byte_1.php on line %d
-bool(false)
+Warning: OCI-Lob::export() expects parameter 1 to be a valid path, string given in %snull_byte_1.php on line %d
+NULL
===DONE===
diff --git a/ext/oci8/tests/oci8safemode.phpt b/ext/oci8/tests/oci8safemode.phpt
deleted file mode 100644
index 02e180e654..0000000000
--- a/ext/oci8/tests/oci8safemode.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Test functionality disabled in safe mode
---SKIPIF--
-<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
---INI--
-safe_mode=On
-oci8.privileged_connect=On
---FILE--
-<?php
-
-$c = oci_connect("hr", "hrpwd", "//localhost/XE", null, OCI_SYSDBA);
-
-$r = oci_password_change($c, "hr", "hrpwd", "hrpwd");
-
-echo "Done\n";
-?>
---EXPECTF--
-%s: Directive 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Warning: oci_connect(): Privileged connect is disabled in Safe Mode in %s on line %d
-
-Warning: oci_password_change(): is disabled in Safe Mode in %s on line %d
-Done
diff --git a/ext/odbc/birdstep.c b/ext/odbc/birdstep.c
index 111eb0a80c..63125fd836 100644
--- a/ext/odbc/birdstep.c
+++ b/ext/odbc/birdstep.c
@@ -224,11 +224,11 @@ PHP_MSHUTDOWN_FUNCTION(birdstep)
/* Some internal functions. Connections and result manupulate */
-static int birdstep_add_conn(HashTable *list,VConn *conn,HDBC hdbc)
+static int birdstep_add_conn(HashTable *list,VConn *conn,HDBC hdbc TSRMLS_DC)
{
int ind;
- ind = zend_list_insert(conn,php_birdstep_module.le_link);
+ ind = zend_list_insert(conn,php_birdstep_module.le_link TSRMLS_CC);
conn->hdbc = hdbc;
conn->index = ind;
@@ -314,7 +314,7 @@ PHP_FUNCTION(birdstep_connect)
RETURN_FALSE;
}
new = (VConn *)emalloc(sizeof(VConn));
- ind = birdstep_add_conn(list,new,hdbc);
+ ind = birdstep_add_conn(list,new,hdbc TSRMLS_CC);
php_birdstep_module.num_links++;
RETURN_LONG(ind);
}
diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
index 4044117c41..52d46b2fd0 100644
--- a/ext/odbc/php_odbc.c
+++ b/ext/odbc/php_odbc.c
@@ -1317,18 +1317,12 @@ PHP_FUNCTION(odbc_execute)
if (Z_STRLEN_PP(tmp) > 2 &&
Z_STRVAL_PP(tmp)[0] == '\'' &&
Z_STRVAL_PP(tmp)[Z_STRLEN_PP(tmp) - 1] == '\'') {
- if (strlen(tmp) != Z_STRLEN_PP(tmp)) {
+
+ if (CHECK_ZVAL_NULL_PATH(*tmp)) {
RETURN_FALSE;
}
-
filename = estrndup(&Z_STRVAL_PP(tmp)[1], Z_STRLEN_PP(tmp) - 2);
-
- /* Check for safe mode. */
- if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- efree(filename);
- efree(params);
- RETURN_FALSE;
- }
+ filename[strlen(filename)] = '\0';
/* Check the basedir */
if (php_check_open_basedir(filename TSRMLS_CC)) {
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 779a91db9c..2b8cfd571a 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -16,7 +16,7 @@
| Wez Furlong <wez@thebrainroom.com> |
| Sascha Kettler <kettler@gmx.net> |
| Pierre-Alain Joye <pierre@php.net> |
- | Marc Delling <delling@silpion.de> (PKCS12 functions) |
+ | Marc Delling <delling@silpion.de> (PKCS12 functions) |
+----------------------------------------------------------------------+
*/
@@ -36,6 +36,10 @@
#include "ext/standard/md5.h"
#include "ext/standard/base64.h"
+#if PHP_WIN32
+# include "win32/winutil.h"
+#endif
+
/* OpenSSL includes */
#include <openssl/evp.h>
#include <openssl/x509.h>
@@ -65,7 +69,13 @@
#define OPENSSL_ALGO_MD2 4
#endif
#define OPENSSL_ALGO_DSS1 5
-
+#if OPENSSL_VERSION_NUMBER >= 0x0090708fL
+#define OPENSSL_ALGO_SHA224 6
+#define OPENSSL_ALGO_SHA256 7
+#define OPENSSL_ALGO_SHA384 8
+#define OPENSSL_ALGO_SHA512 9
+#define OPENSSL_ALGO_RMD160 10
+#endif
#define DEBUG_SMIME 0
/* FIXME: Use the openssl constants instead of
@@ -89,6 +99,9 @@ enum php_openssl_cipher_type {
PHP_OPENSSL_CIPHER_RC2_64,
PHP_OPENSSL_CIPHER_DES,
PHP_OPENSSL_CIPHER_3DES,
+ PHP_OPENSSL_CIPHER_AES_128_CBC,
+ PHP_OPENSSL_CIPHER_AES_192_CBC,
+ PHP_OPENSSL_CIPHER_AES_256_CBC,
PHP_OPENSSL_CIPHER_DEFAULT = PHP_OPENSSL_CIPHER_RC2_40
};
@@ -347,7 +360,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_encrypt, 0, 0, 3)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, method)
ZEND_ARG_INFO(0, password)
- ZEND_ARG_INFO(0, raw_output)
+ ZEND_ARG_INFO(0, options)
ZEND_ARG_INFO(0, iv)
ZEND_END_ARG_INFO()
@@ -355,7 +368,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_decrypt, 0, 0, 3)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, method)
ZEND_ARG_INFO(0, password)
- ZEND_ARG_INFO(0, raw_input)
+ ZEND_ARG_INFO(0, options)
ZEND_ARG_INFO(0, iv)
ZEND_END_ARG_INFO()
@@ -497,16 +510,13 @@ static void php_csr_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
}
/* }}} */
-/* {{{ openssl safe_mode & open_basedir checks */
-inline static int php_openssl_safe_mode_chk(char *filename TSRMLS_DC)
+/* {{{ openssl open_basedir check */
+inline static int php_openssl_open_base_dir_chk(char *filename TSRMLS_DC)
{
- if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return -1;
- }
if (php_check_open_basedir(filename TSRMLS_CC)) {
return -1;
}
-
+
return 0;
}
/* }}} */
@@ -536,6 +546,8 @@ struct php_x509_request { /* {{{ */
int priv_key_encrypt;
EVP_PKEY * priv_key;
+
+ const EVP_CIPHER * priv_key_encrypt_cipher;
};
/* }}} */
@@ -563,7 +575,7 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s
} else {
subitem = val;
}
-
+
for (i = 0; i < X509_NAME_entry_count(name); i++) {
unsigned char *to_add;
int to_add_len;
@@ -606,7 +618,7 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s
last = j;
}
i = last;
-
+
if (obj_cnt > 1) {
add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries);
} else {
@@ -706,7 +718,7 @@ static inline int php_openssl_config_check_syntax(const char * section_label, co
#endif
{
X509V3_CTX ctx;
-
+
X509V3_set_ctx_test(&ctx);
X509V3_set_conf_lhash(&ctx, config);
if (!X509V3_EXT_add_conf(config, &ctx, (char *)section, NULL)) {
@@ -766,6 +778,9 @@ static int add_oid_section(struct php_x509_request * req TSRMLS_DC) /* {{{ */
else \
varname = defval
+static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo);
+
+
static int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args TSRMLS_DC) /* {{{ */
{
char * str;
@@ -782,7 +797,7 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
/* read in the oids */
str = CONF_get_string(req->req_config, NULL, "oid_file");
- if (str && !php_openssl_safe_mode_chk(str TSRMLS_CC)) {
+ if (str && !php_openssl_open_base_dir_chk(str TSRMLS_CC)) {
BIO *oid_bio = BIO_new_file(str, "r");
if (oid_bio) {
OBJ_create_objects(oid_bio);
@@ -816,7 +831,22 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
req->priv_key_encrypt = 1;
}
}
-
+
+ if (req->priv_key_encrypt && optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), "encrypt_key_cipher", sizeof("encrypt_key_cipher"), (void**)&item) == SUCCESS) {
+ long cipher_algo = Z_LVAL_PP(item);
+ const EVP_CIPHER* cipher = php_openssl_get_evp_cipher_from_algo(cipher_algo);
+ if (cipher == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown cipher algorithm for private key.");
+ return FAILURE;
+ } else {
+ req->priv_key_encrypt_cipher = cipher;
+ }
+ } else {
+ req->priv_key_encrypt_cipher = NULL;
+ }
+
+
+
/* digest alg */
if (req->digest_name == NULL) {
req->digest_name = CONF_get_string(req->req_config, req->section_name, "default_md");
@@ -838,7 +868,7 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
}
PHP_SSL_CONFIG_SYNTAX_CHECK(request_extensions_section);
-
+
return SUCCESS;
}
/* }}} */
@@ -860,12 +890,10 @@ static void php_openssl_dispose_config(struct php_x509_request * req TSRMLS_DC)
}
/* }}} */
-static int php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded) /* {{{ */
+static int php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded TSRMLS_DC) /* {{{ */
{
char buffer[MAXPATHLEN];
- TSRMLS_FETCH();
-
*egdsocket = 0;
*seeded = 0;
@@ -932,6 +960,23 @@ static EVP_MD * php_openssl_get_evp_md_from_algo(long algo) { /* {{{ */
case OPENSSL_ALGO_DSS1:
mdtype = (EVP_MD *) EVP_dss1();
break;
+#if OPENSSL_VERSION_NUMBER >= 0x0090708fL
+ case OPENSSL_ALGO_SHA224:
+ mdtype = (EVP_MD *) EVP_sha224();
+ break;
+ case OPENSSL_ALGO_SHA256:
+ mdtype = (EVP_MD *) EVP_sha256();
+ break;
+ case OPENSSL_ALGO_SHA384:
+ mdtype = (EVP_MD *) EVP_sha384();
+ break;
+ case OPENSSL_ALGO_SHA512:
+ mdtype = (EVP_MD *) EVP_sha512();
+ break;
+ case OPENSSL_ALGO_RMD160:
+ mdtype = (EVP_MD *) EVP_ripemd160();
+ break;
+#endif
default:
return NULL;
break;
@@ -962,6 +1007,20 @@ static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo) { /* {
return EVP_des_ede3_cbc();
break;
#endif
+
+#ifndef OPENSSL_NO_AES
+ case PHP_OPENSSL_CIPHER_AES_128_CBC:
+ return EVP_aes_128_cbc();
+ break;
+ case PHP_OPENSSL_CIPHER_AES_192_CBC:
+ return EVP_aes_192_cbc();
+ break;
+ case PHP_OPENSSL_CIPHER_AES_256_CBC:
+ return EVP_aes_256_cbc();
+ break;
+#endif
+
+
default:
return NULL;
break;
@@ -984,17 +1043,15 @@ PHP_MINIT_FUNCTION(openssl)
OpenSSL_add_all_digests();
OpenSSL_add_all_algorithms();
- ERR_load_ERR_strings();
- ERR_load_crypto_strings();
- ERR_load_EVP_strings();
+ SSL_load_error_strings();
/* register a resource id number with OpenSSL so that we can map SSL -> stream structures in
* OpenSSL callbacks */
ssl_stream_data_index = SSL_get_ex_new_index(0, "PHP stream index", NULL, NULL, NULL);
-
+
REGISTER_STRING_CONSTANT("OPENSSL_VERSION_TEXT", OPENSSL_VERSION_TEXT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER, CONST_CS|CONST_PERSISTENT);
-
+
/* purposes for cert purpose checking */
REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_CLIENT", X509_PURPOSE_SSL_CLIENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_SERVER", X509_PURPOSE_SSL_SERVER, CONST_CS|CONST_PERSISTENT);
@@ -1014,6 +1071,13 @@ PHP_MINIT_FUNCTION(openssl)
REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD2", OPENSSL_ALGO_MD2, CONST_CS|CONST_PERSISTENT);
#endif
REGISTER_LONG_CONSTANT("OPENSSL_ALGO_DSS1", OPENSSL_ALGO_DSS1, CONST_CS|CONST_PERSISTENT);
+#if OPENSSL_VERSION_NUMBER >= 0x0090708fL
+ REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA224", OPENSSL_ALGO_SHA224, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA256", OPENSSL_ALGO_SHA256, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA384", OPENSSL_ALGO_SHA384, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA512", OPENSSL_ALGO_SHA512, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_ALGO_RMD160", OPENSSL_ALGO_RMD160, CONST_CS|CONST_PERSISTENT);
+#endif
/* flags for S/MIME */
REGISTER_LONG_CONSTANT("PKCS7_DETACHED", PKCS7_DETACHED, CONST_CS|CONST_PERSISTENT);
@@ -1041,6 +1105,11 @@ PHP_MINIT_FUNCTION(openssl)
REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_DES", PHP_OPENSSL_CIPHER_DES, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_3DES", PHP_OPENSSL_CIPHER_3DES, CONST_CS|CONST_PERSISTENT);
#endif
+#ifndef OPENSSL_NO_AES
+ REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_128_CBC", PHP_OPENSSL_CIPHER_AES_128_CBC, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_192_CBC", PHP_OPENSSL_CIPHER_AES_192_CBC, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_256_CBC", PHP_OPENSSL_CIPHER_AES_256_CBC, CONST_CS|CONST_PERSISTENT);
+#endif
/* Values for key types */
REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_RSA", OPENSSL_KEYTYPE_RSA, CONST_CS|CONST_PERSISTENT);
@@ -1052,6 +1121,9 @@ PHP_MINIT_FUNCTION(openssl)
REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT);
#endif
+ REGISTER_LONG_CONSTANT("OPENSSL_RAW_DATA", OPENSSL_RAW_DATA, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_ZERO_PADDING", OPENSSL_ZERO_PADDING, CONST_CS|CONST_PERSISTENT);
+
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
/* SNI support included in OpenSSL >= 0.9.8j */
REGISTER_LONG_CONSTANT("OPENSSL_TLSEXT_SERVER_NAME", 1, CONST_CS|CONST_PERSISTENT);
@@ -1084,7 +1156,7 @@ PHP_MINIT_FUNCTION(openssl)
php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC);
php_register_url_stream_wrapper("ftps", &php_stream_ftp_wrapper TSRMLS_CC);
-
+
return SUCCESS;
}
/* }}} */
@@ -1174,7 +1246,7 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
/* read cert from the named file */
BIO *in;
- if (php_openssl_safe_mode_chk(Z_STRVAL_PP(val) + (sizeof("file://") - 1) TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(Z_STRVAL_PP(val) + (sizeof("file://") - 1) TSRMLS_CC)) {
return NULL;
}
@@ -1200,7 +1272,7 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
}
if (cert && makeresource && resourceval) {
- *resourceval = zend_list_insert(cert, le_x509);
+ *resourceval = zend_list_insert(cert, le_x509 TSRMLS_CC);
}
return cert;
}
@@ -1219,7 +1291,7 @@ PHP_FUNCTION(openssl_x509_export_to_file)
char * filename;
int filename_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|b", &zcert, &filename, &filename_len, &notext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zp|b", &zcert, &filename, &filename_len, &notext) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -1230,7 +1302,7 @@ PHP_FUNCTION(openssl_x509_export_to_file)
return;
}
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
return;
}
@@ -1304,14 +1376,14 @@ PHP_FUNCTION(openssl_x509_check_private_key)
long certresource = -1, keyresource = -1;
RETVAL_FALSE;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &zcert, &zkey) == FAILURE) {
return;
}
cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
if (cert == NULL) {
RETURN_FALSE;
- }
+ }
key = php_openssl_evp_from_zval(zkey, 0, "", 1, &keyresource TSRMLS_CC);
if (key) {
RETVAL_BOOL(X509_check_private_key(cert, key));
@@ -1364,11 +1436,11 @@ PHP_FUNCTION(openssl_x509_parse)
snprintf(buf, sizeof(buf), "%08lx", X509_subject_name_hash(cert));
add_assoc_string(return_value, "hash", buf, 1);
}
-
+
add_assoc_name_entry(return_value, "issuer", X509_get_issuer_name(cert), useshortnames TSRMLS_CC);
add_assoc_long(return_value, "version", X509_get_version(cert));
- add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1);
+ add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1);
add_assoc_asn1_string(return_value, "validFrom", X509_get_notBefore(cert));
add_assoc_asn1_string(return_value, "validTo", X509_get_notAfter(cert));
@@ -1460,7 +1532,7 @@ static STACK_OF(X509) * load_all_certs_from_file(char *certfile)
goto end;
}
- if (php_openssl_safe_mode_chk(certfile TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(certfile TSRMLS_CC)) {
sk_X509_free(stack);
goto end;
}
@@ -1570,8 +1642,8 @@ clean_exit:
if (certresource == 1 && cert) {
X509_free(cert);
}
- if (cainfo) {
- X509_STORE_free(cainfo);
+ if (cainfo) {
+ X509_STORE_free(cainfo);
}
if (untrustedchain) {
sk_X509_pop_free(untrustedchain, X509_free);
@@ -1624,7 +1696,7 @@ static X509_STORE * setup_verify(zval * calist TSRMLS_DC)
dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, Z_STRVAL_PP(item), X509_FILETYPE_PEM)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading directory %s", Z_STRVAL_PP(item));
- } else {
+ } else {
ndirs++;
}
dir_lookup = NULL;
@@ -1718,11 +1790,11 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval ** zcerts TSRMLS_DC) /* {{{ */
if (certresource != -1) {
cert = X509_dup(cert);
-
+
if (cert == NULL) {
goto clean_exit;
}
-
+
}
sk_X509_push(sk, cert);
@@ -1731,7 +1803,7 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval ** zcerts TSRMLS_DC) /* {{{ */
} else {
/* a single certificate */
cert = php_openssl_x509_from_zval(zcerts, 0, &certresource TSRMLS_CC);
-
+
if (cert == NULL) {
goto clean_exit;
}
@@ -1768,15 +1840,11 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
zval ** item;
STACK_OF(X509) *ca = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zszs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE)
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zpzs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE)
return;
RETVAL_FALSE;
- if (strlen(filename) != filename_len) {
- return;
- }
-
cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
if (cert == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1");
@@ -1791,7 +1859,7 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to cert");
goto cleanup;
}
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
goto cleanup;
}
@@ -1812,9 +1880,9 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0);
- bio_out = BIO_new_file(filename, "w");
+ bio_out = BIO_new_file(filename, "w");
if (bio_out) {
-
+
i2d_PKCS12_bio(bio_out, p12);
RETVAL_TRUE;
@@ -1825,13 +1893,13 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
BIO_free(bio_out);
PKCS12_free(p12);
php_sk_X509_free(ca);
-
+
cleanup:
if (keyresource == -1 && priv_key) {
EVP_PKEY_free(priv_key);
}
- if (certresource == -1 && cert) {
+ if (certresource == -1 && cert) {
X509_free(cert);
}
}
@@ -1857,7 +1925,7 @@ PHP_FUNCTION(openssl_pkcs12_export)
return;
RETVAL_FALSE;
-
+
cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC);
if (cert == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1");
@@ -1880,7 +1948,7 @@ PHP_FUNCTION(openssl_pkcs12_export)
if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS)
ca = php_array_to_X509_sk(item TSRMLS_CC);
/* end parse extra config */
-
+
p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0);
bio_out = BIO_new(BIO_s_mem());
@@ -1897,13 +1965,13 @@ PHP_FUNCTION(openssl_pkcs12_export)
BIO_free(bio_out);
PKCS12_free(p12);
php_sk_X509_free(ca);
-
+
cleanup:
if (keyresource == -1 && priv_key) {
EVP_PKEY_free(priv_key);
}
- if (certresource == -1 && cert) {
+ if (certresource == -1 && cert) {
X509_free(cert);
}
}
@@ -1927,12 +1995,12 @@ PHP_FUNCTION(openssl_pkcs12_read)
return;
RETVAL_FALSE;
-
+
bio_in = BIO_new(BIO_s_mem());
-
+
if(!BIO_write(bio_in, zp12, zp12_len))
goto cleanup;
-
+
if(d2i_PKCS12_bio(bio_in, &p12)) {
if(PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
BIO * bio_out;
@@ -1962,12 +2030,12 @@ PHP_FUNCTION(openssl_pkcs12_read)
MAKE_STD_ZVAL(zextracerts);
array_init(zextracerts);
-
+
for (i=0;;i++) {
zval * zextracert;
X509* aCA = sk_X509_pop(ca);
if (!aCA) break;
-
+
bio_out = BIO_new(BIO_s_mem());
if (PEM_write_bio_X509(bio_out, aCA)) {
BUF_MEM *bio_buf;
@@ -1975,7 +2043,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
MAKE_STD_ZVAL(zextracert);
ZVAL_STRINGL(zextracert, bio_buf->data, bio_buf->length, 1);
add_index_zval(zextracerts, i, zextracert);
-
+
}
BIO_free(bio_out);
@@ -1987,13 +2055,13 @@ PHP_FUNCTION(openssl_pkcs12_read)
} else {
zval_dtor(zextracerts);
}
-
+
RETVAL_TRUE;
-
+
PKCS12_free(p12);
}
}
-
+
cleanup:
if (bio_in) {
BIO_free(bio_in);
@@ -2001,7 +2069,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
if (pkey) {
EVP_PKEY_free(pkey);
}
- if (cert) {
+ if (cert) {
X509_free(cert);
}
}
@@ -2020,7 +2088,7 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
return FAILURE;
}
dn_sk = CONF_get_section(req->req_config, dn_sect);
- if (dn_sk == NULL) {
+ if (dn_sk == NULL) {
return FAILURE;
}
attr_sect = CONF_get_string(req->req_config, req->section_name, "attributes");
@@ -2040,15 +2108,15 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
X509_NAME * subj;
HashPosition hpos;
zval ** item;
-
+
subj = X509_REQ_get_subject_name(csr);
/* apply values from the dn hash */
zend_hash_internal_pointer_reset_ex(HASH_OF(dn), &hpos);
while(zend_hash_get_current_data_ex(HASH_OF(dn), (void**)&item, &hpos) == SUCCESS) {
- char * strindex = NULL;
+ char * strindex = NULL;
uint strindexlen = 0;
ulong intindex;
-
+
zend_hash_get_current_key_ex(HASH_OF(dn), &strindex, &strindexlen, &intindex, 0, &hpos);
convert_to_string_ex(item);
@@ -2058,10 +2126,14 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
nid = OBJ_txt2nid(strindex);
if (nid != NID_undef) {
- if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC,
+ if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8,
(unsigned char*)Z_STRVAL_PP(item), -1, -1, 0))
{
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_PP(item));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "dn: add_entry_by_NID %d -> %s (failed; check error"
+ " queue and value of string_mask OpenSSL option "
+ "if illegal characters are reported)",
+ nid, Z_STRVAL_PP(item));
return FAILURE;
}
} else {
@@ -2075,10 +2147,10 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
for(i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
int len;
char buffer[200 + 1]; /*200 + \0 !*/
-
+
v = sk_CONF_VALUE_value(dn_sk, i);
type = v->name;
-
+
len = strlen(type);
if (len < sizeof("_default")) {
continue;
@@ -2093,7 +2165,7 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
memcpy(buffer, type, len);
buffer[len] = '\0';
type = buffer;
-
+
/* Skip past any leading X. X: X, etc to allow for multiple
* instances */
for (str = type; *str; str++) {
@@ -2110,7 +2182,7 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
if (X509_NAME_get_index_by_NID(subj, nid, -1) >= 0) {
continue;
}
- if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_ASC, (unsigned char*)v->value, -1, -1, 0)) {
+ if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_UTF8, (unsigned char*)v->value, -1, -1, 0)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_entry_by_txt %s -> %s (failed)", type, v->value);
return FAILURE;
}
@@ -2134,7 +2206,7 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
nid = OBJ_txt2nid(strindex);
if (nid != NID_undef) {
- if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0)) {
+ if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_PP(item));
return FAILURE;
}
@@ -2151,8 +2223,12 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
if (X509_REQ_get_attr_by_NID(csr, nid, -1) >= 0) {
continue;
}
- if (!X509_REQ_add1_attr_by_txt(csr, v->name, MBSTRING_ASC, (unsigned char*)v->value, -1)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "add1_attr_by_txt %s -> %s (failed)", v->name, v->value);
+ if (!X509_REQ_add1_attr_by_txt(csr, v->name, MBSTRING_UTF8, (unsigned char*)v->value, -1)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "add1_attr_by_txt %s -> %s (failed; check error queue "
+ "and value of string_mask OpenSSL option if illegal "
+ "characters are reported)",
+ v->name, v->value);
return FAILURE;
}
}
@@ -2170,7 +2246,7 @@ static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long
X509_REQ * csr = NULL;
char * filename = NULL;
BIO * in;
-
+
if (resourceval) {
*resourceval = -1;
}
@@ -2194,7 +2270,7 @@ static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long
filename = Z_STRVAL_PP(val) + (sizeof("file://") - 1);
}
if (filename) {
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
return NULL;
}
in = BIO_new_file(filename, "r");
@@ -2219,22 +2295,18 @@ PHP_FUNCTION(openssl_csr_export_to_file)
BIO * bio_out;
long csr_resource;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|b", &zcsr, &filename, &filename_len, &notext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp|b", &zcsr, &filename, &filename_len, &notext) == FAILURE) {
return;
}
RETVAL_FALSE;
- if (strlen(filename) != filename_len) {
- return;
- }
-
csr = php_openssl_csr_from_zval(&zcsr, 0, &csr_resource TSRMLS_CC);
if (csr == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1");
return;
}
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
return;
}
@@ -2315,13 +2387,13 @@ PHP_FUNCTION(openssl_csr_sign)
long csr_resource, certresource = 0, keyresource = -1;
int i;
struct php_x509_request req;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ!Zl|a!l", &zcsr, &zcert, &zpkey, &num_days, &args, &serial) == FAILURE)
return;
RETVAL_FALSE;
PHP_SSL_REQ_INIT(&req);
-
+
csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource TSRMLS_CC);
if (csr == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1");
@@ -2343,7 +2415,7 @@ PHP_FUNCTION(openssl_csr_sign)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to signing cert");
goto cleanup;
}
-
+
if (PHP_SSL_REQ_PARSE(&req, args) == FAILURE) {
goto cleanup;
}
@@ -2363,9 +2435,9 @@ PHP_FUNCTION(openssl_csr_sign)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Signature did not match the certificate request");
goto cleanup;
}
-
+
/* Now we can get on with it */
-
+
new_cert = X509_new();
if (new_cert == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No memory");
@@ -2376,7 +2448,7 @@ PHP_FUNCTION(openssl_csr_sign)
goto cleanup;
ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial);
-
+
X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr));
if (cert == NULL) {
@@ -2393,7 +2465,7 @@ PHP_FUNCTION(openssl_csr_sign)
}
if (req.extensions_section) {
X509V3_CTX ctx;
-
+
X509V3_set_ctx(&ctx, cert, new_cert, csr, NULL, 0);
X509V3_set_conf_lhash(&ctx, req.req_config);
if (!X509V3_EXT_add_conf(req.req_config, &ctx, req.extensions_section, new_cert)) {
@@ -2406,11 +2478,11 @@ PHP_FUNCTION(openssl_csr_sign)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to sign it");
goto cleanup;
}
-
+
/* Succeeded; lets return the cert */
- RETVAL_RESOURCE(zend_list_insert(new_cert, le_x509));
+ RETVAL_RESOURCE(zend_list_insert(new_cert, le_x509 TSRMLS_CC));
new_cert = NULL;
-
+
cleanup:
if (cert == new_cert) {
@@ -2427,7 +2499,7 @@ cleanup:
if (csr_resource == -1 && csr) {
X509_REQ_free(csr);
}
- if (certresource == -1 && cert) {
+ if (certresource == -1 && cert) {
X509_free(cert);
}
if (new_cert) {
@@ -2446,12 +2518,12 @@ PHP_FUNCTION(openssl_csr_new)
X509_REQ * csr = NULL;
int we_made_the_key = 1;
long key_resource;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) {
return;
}
RETVAL_FALSE;
-
+
PHP_SSL_REQ_INIT(&req);
if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
@@ -2483,10 +2555,10 @@ PHP_FUNCTION(openssl_csr_new)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error loading extension section %s", req.request_extensions_section);
} else {
RETVAL_TRUE;
-
+
if (X509_REQ_sign(csr, req.priv_key, req.digest)) {
- RETVAL_RESOURCE(zend_list_insert(csr, le_csr));
- csr = NULL;
+ RETVAL_RESOURCE(zend_list_insert(csr, le_csr TSRMLS_CC));
+ csr = NULL;
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error signing request");
}
@@ -2494,7 +2566,7 @@ PHP_FUNCTION(openssl_csr_new)
if (we_made_the_key) {
/* and a resource for the private key */
zval_dtor(out_pkey);
- ZVAL_RESOURCE(out_pkey, zend_list_insert(req.priv_key, le_key));
+ ZVAL_RESOURCE(out_pkey, zend_list_insert(req.priv_key, le_key TSRMLS_CC));
req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */
} else if (key_resource != -1) {
req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */
@@ -2567,7 +2639,7 @@ PHP_FUNCTION(openssl_csr_get_public_key)
}
tpubkey=X509_REQ_get_pubkey(csr);
- RETVAL_RESOURCE(zend_list_insert(tpubkey, le_key));
+ RETVAL_RESOURCE(zend_list_insert(tpubkey, le_key TSRMLS_CC));
return;
}
/* }}} */
@@ -2611,14 +2683,14 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
}
if (Z_TYPE_PP(val) == IS_ARRAY) {
zval ** zphrase;
-
+
/* get passphrase */
if (zend_hash_index_find(HASH_OF(*val), 1, (void **)&zphrase) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)");
return NULL;
}
-
+
if (Z_TYPE_PP(zphrase) == IS_STRING) {
passphrase = Z_STRVAL_PP(zphrase);
} else {
@@ -2643,7 +2715,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
if (!what) {
TMP_CLEAN;
}
- if (resourceval) {
+ if (resourceval) {
*resourceval = Z_LVAL_PP(val);
}
if (type == le_x509) {
@@ -2677,8 +2749,8 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
}
} else {
/* force it to be a string and check if it refers to a file */
- /* passing non string values leaks, object uses toString, it returns NULL
- * See bug38255.phpt
+ /* passing non string values leaks, object uses toString, it returns NULL
+ * See bug38255.phpt
*/
if (!(Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_OBJECT)) {
TMP_CLEAN;
@@ -2712,7 +2784,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
BIO *in;
if (filename) {
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
TMP_CLEAN;
}
in = BIO_new_file(filename, "r");
@@ -2752,7 +2824,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
char * randfile = NULL;
int egdsocket, seeded;
EVP_PKEY * return_val = NULL;
-
+
if (req->priv_key_bits < MIN_KEY_LENGTH) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key length is too short; it needs to be at least %d bits, not %d",
MIN_KEY_LENGTH, req->priv_key_bits);
@@ -2760,8 +2832,8 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
}
randfile = CONF_get_string(req->req_config, req->section_name, "RANDFILE");
- php_openssl_load_rand_file(randfile, &egdsocket, &seeded);
-
+ php_openssl_load_rand_file(randfile, &egdsocket, &seeded TSRMLS_CC);
+
if ((req->priv_key = EVP_PKEY_new()) != NULL) {
switch(req->priv_key_type) {
case OPENSSL_KEYTYPE_RSA:
@@ -2811,13 +2883,13 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
}
php_openssl_write_rand_file(randfile, egdsocket, seeded);
-
+
if (return_val == NULL) {
EVP_PKEY_free(req->priv_key);
req->priv_key = NULL;
return NULL;
}
-
+
return return_val;
}
/* }}} */
@@ -2846,7 +2918,7 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC)
case EVP_PKEY_DSA4:
assert(pkey->pkey.dsa != NULL);
- if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){
+ if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){
return 0;
}
break;
@@ -2921,7 +2993,7 @@ PHP_FUNCTION(openssl_pkey_new)
OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, iqmp);
if (rsa->n && rsa->d) {
if (EVP_PKEY_assign_RSA(pkey, rsa)) {
- RETURN_RESOURCE(zend_list_insert(pkey, le_key));
+ RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
}
}
RSA_free(rsa);
@@ -2945,7 +3017,7 @@ PHP_FUNCTION(openssl_pkey_new)
DSA_generate_key(dsa);
}
if (EVP_PKEY_assign_DSA(pkey, dsa)) {
- RETURN_RESOURCE(zend_list_insert(pkey, le_key));
+ RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
}
}
DSA_free(dsa);
@@ -2968,7 +3040,7 @@ PHP_FUNCTION(openssl_pkey_new)
DH_generate_key(dh);
}
if (EVP_PKEY_assign_DH(pkey, dh)) {
- RETURN_RESOURCE(zend_list_insert(pkey, le_key));
+ RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
}
}
DH_free(dh);
@@ -2977,7 +3049,7 @@ PHP_FUNCTION(openssl_pkey_new)
}
RETURN_FALSE;
}
- }
+ }
PHP_SSL_REQ_INIT(&req);
@@ -2985,7 +3057,7 @@ PHP_FUNCTION(openssl_pkey_new)
{
if (php_openssl_generate_private_key(&req TSRMLS_CC)) {
/* pass back a key resource */
- RETVAL_RESOURCE(zend_list_insert(req.priv_key, le_key));
+ RETVAL_RESOURCE(zend_list_insert(req.priv_key, le_key TSRMLS_CC));
/* make sure the cleanup code doesn't zap it! */
req.priv_key = NULL;
}
@@ -3006,15 +3078,11 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
EVP_PKEY * key;
BIO * bio_out = NULL;
const EVP_CIPHER * cipher;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) {
- return;
- }
- RETVAL_FALSE;
- if (strlen(filename) != filename_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zp|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) {
return;
}
+ RETVAL_FALSE;
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource TSRMLS_CC);
@@ -3022,18 +3090,22 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1");
RETURN_FALSE;
}
-
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
RETURN_FALSE;
}
-
+
PHP_SSL_REQ_INIT(&req);
if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
bio_out = BIO_new_file(filename, "w");
if (passphrase && req.priv_key_encrypt) {
- cipher = (EVP_CIPHER *) EVP_des_ede3_cbc();
+ if (req.priv_key_encrypt_cipher) {
+ cipher = req.priv_key_encrypt_cipher;
+ } else {
+ cipher = (EVP_CIPHER *) EVP_des_ede3_cbc();
+ }
} else {
cipher = NULL;
}
@@ -3065,7 +3137,7 @@ PHP_FUNCTION(openssl_pkey_export)
EVP_PKEY * key;
BIO * bio_out = NULL;
const EVP_CIPHER * cipher;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
return;
}
@@ -3077,14 +3149,18 @@ PHP_FUNCTION(openssl_pkey_export)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1");
RETURN_FALSE;
}
-
+
PHP_SSL_REQ_INIT(&req);
if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
bio_out = BIO_new(BIO_s_mem());
if (passphrase && req.priv_key_encrypt) {
- cipher = (EVP_CIPHER *) EVP_des_ede3_cbc();
+ if (req.priv_key_encrypt_cipher) {
+ cipher = req.priv_key_encrypt_cipher;
+ } else {
+ cipher = (EVP_CIPHER *) EVP_des_ede3_cbc();
+ }
} else {
cipher = NULL;
}
@@ -3193,7 +3269,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
array_init(return_value);
add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey));
add_assoc_stringl(return_value, "key", pbio, pbio_len, 1);
- /*TODO: Use the real values once the openssl constants are used
+ /*TODO: Use the real values once the openssl constants are used
* See the enum at the top of this file
*/
switch (EVP_PKEY_type(pkey->type)) {
@@ -3217,7 +3293,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
add_assoc_zval(return_value, "rsa", rsa);
}
- break;
+ break;
case EVP_PKEY_DSA:
case EVP_PKEY_DSA2:
case EVP_PKEY_DSA3:
@@ -3238,7 +3314,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
}
break;
case EVP_PKEY_DH:
-
+
ktype = OPENSSL_KEYTYPE_DH;
if (pkey->pkey.dh != NULL) {
@@ -3254,7 +3330,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
}
break;
-#ifdef EVP_PKEY_EC
+#ifdef EVP_PKEY_EC
case EVP_PKEY_EC:
ktype = OPENSSL_KEYTYPE_EC;
break;
@@ -3288,15 +3364,15 @@ PHP_FUNCTION(openssl_pkcs7_verify)
char * extracerts = NULL; int extracerts_len = 0;
char * signersfilename = NULL; int signersfilename_len = 0;
char * datafilename = NULL; int datafilename_len = 0;
-
+
RETVAL_LONG(-1);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|sass", &filename, &filename_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl|papp", &filename, &filename_len,
&flags, &signersfilename, &signersfilename_len, &cainfo,
&extracerts, &extracerts_len, &datafilename, &datafilename_len) == FAILURE) {
return;
}
-
+
if (extracerts) {
others = load_all_certs_from_file(extracerts);
if (others == NULL) {
@@ -3311,7 +3387,7 @@ PHP_FUNCTION(openssl_pkcs7_verify)
if (!store) {
goto clean_exit;
}
- if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
goto clean_exit;
}
@@ -3329,7 +3405,7 @@ PHP_FUNCTION(openssl_pkcs7_verify)
if (datafilename) {
- if (php_openssl_safe_mode_chk(datafilename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(datafilename TSRMLS_CC)) {
goto clean_exit;
}
@@ -3348,11 +3424,11 @@ PHP_FUNCTION(openssl_pkcs7_verify)
if (signersfilename) {
BIO *certout;
-
- if (php_openssl_safe_mode_chk(signersfilename TSRMLS_CC)) {
+
+ if (php_openssl_open_base_dir_chk(signersfilename TSRMLS_CC)) {
goto clean_exit;
}
-
+
certout = BIO_new_file(signersfilename, "w");
if (certout) {
int i;
@@ -3401,22 +3477,15 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)
char * strindex;
char * infilename = NULL; int infilename_len;
char * outfilename = NULL; int outfilename_len;
-
+
RETVAL_FALSE;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZa!|ll", &infilename, &infilename_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZa!|ll", &infilename, &infilename_len,
&outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags, &cipherid) == FAILURE)
return;
- if (strlen(infilename) != infilename_len) {
- return;
- }
-
- if (strlen(outfilename) != outfilename_len) {
- return;
- }
- if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(infilename TSRMLS_CC) || php_openssl_open_base_dir_chk(outfilename TSRMLS_CC)) {
return;
}
@@ -3426,7 +3495,7 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)
}
outfile = BIO_new_file(outfilename, "w");
- if (outfile == NULL) {
+ if (outfile == NULL) {
goto clean_exit;
}
@@ -3547,25 +3616,18 @@ PHP_FUNCTION(openssl_pkcs7_sign)
char * outfilename; int outfilename_len;
char * extracertsfilename = NULL; int extracertsfilename_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZZa!|ls",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZZa!|lp",
&infilename, &infilename_len, &outfilename, &outfilename_len,
&zcert, &zprivkey, &zheaders, &flags, &extracertsfilename,
&extracertsfilename_len) == FAILURE) {
return;
}
- RETVAL_FALSE;
-
- if (strlen(infilename) != infilename_len) {
- return;
- }
- if (strlen(outfilename) != outfilename_len) {
- return;
- }
+ RETVAL_FALSE;
if (extracertsfilename) {
others = load_all_certs_from_file(extracertsfilename);
- if (others == NULL) {
+ if (others == NULL) {
goto clean_exit;
}
}
@@ -3582,7 +3644,7 @@ PHP_FUNCTION(openssl_pkcs7_sign)
goto clean_exit;
}
- if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) {
+ if (php_openssl_open_base_dir_chk(infilename TSRMLS_CC) || php_openssl_open_base_dir_chk(outfilename TSRMLS_CC)) {
goto clean_exit;
}
@@ -3658,20 +3720,12 @@ PHP_FUNCTION(openssl_pkcs7_decrypt)
char * infilename; int infilename_len;
char * outfilename; int outfilename_len;
- RETVAL_FALSE;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|Z", &infilename, &infilename_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZ|Z", &infilename, &infilename_len,
&outfilename, &outfilename_len, &recipcert, &recipkey) == FAILURE) {
return;
}
- if (strlen(infilename) != infilename_len) {
- return;
- }
-
- if (strlen(outfilename) != outfilename_len) {
- return;
- }
+ RETVAL_FALSE;
cert = php_openssl_x509_from_zval(recipcert, 0, &certresval TSRMLS_CC);
if (cert == NULL) {
@@ -3684,8 +3738,8 @@ PHP_FUNCTION(openssl_pkcs7_decrypt)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to get private key");
goto clean_exit;
}
-
- if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) {
+
+ if (php_openssl_open_base_dir_chk(infilename TSRMLS_CC) || php_openssl_open_base_dir_chk(outfilename TSRMLS_CC)) {
goto clean_exit;
}
@@ -3703,7 +3757,7 @@ PHP_FUNCTION(openssl_pkcs7_decrypt)
if (p7 == NULL) {
goto clean_exit;
}
- if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) {
+ if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) {
RETVAL_TRUE;
}
clean_exit:
@@ -3736,7 +3790,7 @@ PHP_FUNCTION(openssl_private_encrypt)
int data_len;
long padding = RSA_PKCS1_PADDING;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -3754,10 +3808,10 @@ PHP_FUNCTION(openssl_private_encrypt)
switch (pkey->type) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
- successful = (RSA_private_encrypt(data_len,
- (unsigned char *)data,
- cryptedbuf,
- pkey->pkey.rsa,
+ successful = (RSA_private_encrypt(data_len,
+ (unsigned char *)data,
+ cryptedbuf,
+ pkey->pkey.rsa,
padding) == cryptedlen);
break;
default:
@@ -3774,7 +3828,7 @@ PHP_FUNCTION(openssl_private_encrypt)
if (cryptedbuf) {
efree(cryptedbuf);
}
- if (keyresource == -1) {
+ if (keyresource == -1) {
EVP_PKEY_free(pkey);
}
}
@@ -3812,10 +3866,10 @@ PHP_FUNCTION(openssl_private_decrypt)
switch (pkey->type) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
- cryptedlen = RSA_private_decrypt(data_len,
- (unsigned char *)data,
- crypttemp,
- pkey->pkey.rsa,
+ cryptedlen = RSA_private_decrypt(data_len,
+ (unsigned char *)data,
+ crypttemp,
+ pkey->pkey.rsa,
padding);
if (cryptedlen != -1) {
cryptedbuf = emalloc(cryptedlen + 1);
@@ -3840,7 +3894,7 @@ PHP_FUNCTION(openssl_private_decrypt)
if (keyresource == -1) {
EVP_PKEY_free(pkey);
}
- if (cryptedbuf) {
+ if (cryptedbuf) {
efree(cryptedbuf);
}
}
@@ -3864,7 +3918,7 @@ PHP_FUNCTION(openssl_public_encrypt)
return;
RETVAL_FALSE;
-
+
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC);
if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is not a valid public key");
@@ -3877,10 +3931,10 @@ PHP_FUNCTION(openssl_public_encrypt)
switch (pkey->type) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
- successful = (RSA_public_encrypt(data_len,
- (unsigned char *)data,
- cryptedbuf,
- pkey->pkey.rsa,
+ successful = (RSA_public_encrypt(data_len,
+ (unsigned char *)data,
+ cryptedbuf,
+ pkey->pkey.rsa,
padding) == cryptedlen);
break;
default:
@@ -3923,7 +3977,7 @@ PHP_FUNCTION(openssl_public_decrypt)
return;
}
RETVAL_FALSE;
-
+
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC);
if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is not a valid public key");
@@ -3936,10 +3990,10 @@ PHP_FUNCTION(openssl_public_decrypt)
switch (pkey->type) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
- cryptedlen = RSA_public_decrypt(data_len,
- (unsigned char *)data,
- crypttemp,
- pkey->pkey.rsa,
+ cryptedlen = RSA_public_decrypt(data_len,
+ (unsigned char *)data,
+ crypttemp,
+ pkey->pkey.rsa,
padding);
if (cryptedlen != -1) {
cryptedbuf = emalloc(cryptedlen + 1);
@@ -3947,10 +4001,10 @@ PHP_FUNCTION(openssl_public_decrypt)
successful = 1;
}
break;
-
+
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!");
-
+
}
efree(crypttemp);
@@ -4068,7 +4122,7 @@ PHP_FUNCTION(openssl_verify)
char * signature; int signature_len;
zval *method = NULL;
long signature_algo = OPENSSL_ALGO_SHA1;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|z", &data, &data_len, &signature, &signature_len, &key, &method) == FAILURE) {
return;
}
@@ -4127,7 +4181,7 @@ PHP_FUNCTION(openssl_seal)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) {
return;
}
-
+
pubkeysht = HASH_OF(pubkeys);
nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0;
if (!nkeys) {
@@ -4222,7 +4276,7 @@ clean_exit:
if (key_resources[i] == -1) {
EVP_PKEY_free(pkeys[i]);
}
- if (eks[i]) {
+ if (eks[i]) {
efree(eks[i]);
}
}
@@ -4268,13 +4322,13 @@ PHP_FUNCTION(openssl_open)
} else {
cipher = EVP_rc4();
}
-
+
buf = emalloc(data_len + 1);
if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) {
efree(buf);
- if (keyresource == -1) {
+ if (keyresource == -1) {
EVP_PKEY_free(pkey);
}
RETURN_FALSE;
@@ -4511,7 +4565,7 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{
if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff);
return NULL;
- }
+ }
}
tmpssl = SSL_new(ctx);
@@ -4568,7 +4622,7 @@ PHP_FUNCTION(openssl_get_md_methods)
}
array_init(return_value);
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
- aliases ? openssl_add_method_or_alias: openssl_add_method,
+ aliases ? openssl_add_method_or_alias: openssl_add_method,
return_value);
}
/* }}} */
@@ -4584,7 +4638,7 @@ PHP_FUNCTION(openssl_get_cipher_methods)
}
array_init(return_value);
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
- aliases ? openssl_add_method_or_alias: openssl_add_method,
+ aliases ? openssl_add_method_or_alias: openssl_add_method,
return_value);
}
/* }}} */
@@ -4668,20 +4722,20 @@ static zend_bool php_openssl_validate_iv(char **piv, int *piv_len, int iv_requir
}
-/* {{{ proto string openssl_encrypt(string data, string method, string password [, bool raw_output=false [, string $iv='']])
+/* {{{ proto string openssl_encrypt(string data, string method, string password [, long options=0 [, string $iv='']])
Encrypts given data with given method and key, returns raw or base64 encoded string */
PHP_FUNCTION(openssl_encrypt)
{
- zend_bool raw_output = 0;
+ long options = 0;
char *data, *method, *password, *iv = "";
int data_len, method_len, password_len, iv_len = 0, max_iv_len;
const EVP_CIPHER *cipher_type;
EVP_CIPHER_CTX cipher_ctx;
- int i = 0, outlen, keylen;
+ int i=0, outlen, keylen;
unsigned char *outbuf, *key;
zend_bool free_iv;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|bs", &data, &data_len, &method, &method_len, &password, &password_len, &raw_output, &iv, &iv_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) {
return;
}
cipher_type = EVP_get_cipherbyname(method);
@@ -4713,13 +4767,16 @@ PHP_FUNCTION(openssl_encrypt)
EVP_CIPHER_CTX_set_key_length(&cipher_ctx, password_len);
}
EVP_EncryptInit_ex(&cipher_ctx, NULL, NULL, key, (unsigned char *)iv);
+ if (options & OPENSSL_ZERO_PADDING) {
+ EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0);
+ }
if (data_len > 0) {
EVP_EncryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len);
}
outlen = i;
if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {
outlen += i;
- if (raw_output) {
+ if (options & OPENSSL_RAW_DATA) {
outbuf[outlen] = '\0';
RETVAL_STRINGL((char *)outbuf, outlen, 0);
} else {
@@ -4744,11 +4801,11 @@ PHP_FUNCTION(openssl_encrypt)
}
/* }}} */
-/* {{{ proto string openssl_decrypt(string data, string method, string password [, bool raw_input=false [, string $iv = '']])
+/* {{{ proto string openssl_decrypt(string data, string method, string password [, long options=0 [, string $iv = '']])
Takes raw or base64 encoded string and dectupt it using given method and key */
PHP_FUNCTION(openssl_decrypt)
{
- zend_bool raw_input = 0;
+ long options = 0;
char *data, *method, *password, *iv = "";
int data_len, method_len, password_len, iv_len = 0;
const EVP_CIPHER *cipher_type;
@@ -4759,7 +4816,7 @@ PHP_FUNCTION(openssl_decrypt)
char *base64_str = NULL;
zend_bool free_iv;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|bs", &data, &data_len, &method, &method_len, &password, &password_len, &raw_input, &iv, &iv_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) {
return;
}
@@ -4774,7 +4831,7 @@ PHP_FUNCTION(openssl_decrypt)
RETURN_FALSE;
}
- if (!raw_input) {
+ if (!(options & OPENSSL_RAW_DATA)) {
base64_str = (char*)php_base64_decode((unsigned char*)data, data_len, &base64_str_len);
if (!base64_str) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to base64 decode the input");
@@ -4803,6 +4860,9 @@ PHP_FUNCTION(openssl_decrypt)
EVP_CIPHER_CTX_set_key_length(&cipher_ctx, password_len);
}
EVP_DecryptInit_ex(&cipher_ctx, NULL, NULL, key, (unsigned char *)iv);
+ if (options & OPENSSL_ZERO_PADDING) {
+ EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0);
+ }
EVP_DecryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len);
outlen = i;
if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {
@@ -4914,10 +4974,25 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
buffer = emalloc(buffer_length + 1);
+#ifdef PHP_WIN32
+ strong_result = 1;
+ /* random/urandom equivalent on Windows */
+ if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE) {
+ efree(buffer);
+ if (zstrong_result_returned) {
+ ZVAL_BOOL(zstrong_result_returned, 0);
+ }
+ RETURN_FALSE;
+ }
+#else
if ((strong_result = RAND_pseudo_bytes(buffer, buffer_length)) < 0) {
efree(buffer);
+ if (zstrong_result_returned) {
+ ZVAL_BOOL(zstrong_result_returned, 0);
+ }
RETURN_FALSE;
}
+#endif
buffer[buffer_length] = 0;
RETVAL_STRINGL((char *)buffer, buffer_length, 0);
diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h
index 74f8a80e71..fc118dba1e 100644
--- a/ext/openssl/php_openssl.h
+++ b/ext/openssl/php_openssl.h
@@ -26,6 +26,9 @@
extern zend_module_entry openssl_module_entry;
#define phpext_openssl_ptr &openssl_module_entry
+#define OPENSSL_RAW_DATA 1
+#define OPENSSL_ZERO_PADDING 2
+
php_stream_transport_factory_func php_openssl_ssl_socket_factory;
PHP_MINIT_FUNCTION(openssl);
diff --git a/ext/openssl/tests/004.phpt b/ext/openssl/tests/004.phpt
index aca9818ad1..508ccabc85 100644
--- a/ext/openssl/tests/004.phpt
+++ b/ext/openssl/tests/004.phpt
@@ -28,7 +28,7 @@ NULL
Warning: openssl_csr_new(): key array must be of the form array(0 => key, 1 => phrase) in %s on line %d
-Warning: openssl_csr_new(): add1_attr_by_txt challengePassword_min -> 4 (failed) in %s on line %d
+Warning: openssl_csr_new(): add1_attr_by_txt challengePassword_min -> 4 (failed; check error queue and value of string_mask OpenSSL option if illegal characters are reported) in %s on line %d
bool(false)
resource(%d) of type (OpenSSL X.509 CSR)
Done
diff --git a/ext/openssl/tests/011.phpt b/ext/openssl/tests/011.phpt
index fdcc5e296a..118e952a51 100644
--- a/ext/openssl/tests/011.phpt
+++ b/ext/openssl/tests/011.phpt
@@ -13,14 +13,19 @@ $iv = '';
srand(time() + ((microtime(true) * 1000000) % 1000000));
while(strlen($iv) < $ivlen) $iv .= chr(rand(0,255));
-$encrypted = openssl_encrypt($data, $method, $password, false, $iv);
-$output = openssl_decrypt($encrypted, $method, $password, false, $iv);
+$encrypted = openssl_encrypt($data, $method, $password, 0, $iv);
+$output = openssl_decrypt($encrypted, $method, $password, 0, $iv);
var_dump($output);
-$encrypted = openssl_encrypt($data, $method, $password, true, $iv);
-$output = openssl_decrypt($encrypted, $method, $password, true, $iv);
+$encrypted = openssl_encrypt($data, $method, $password, OPENSSL_RAW_DATA, $iv);
+$output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA, $iv);
var_dump($output);
+// if we want to manage our own padding
+$padded_data = $data . str_repeat(' ', 16 - (strlen($data) % 16));
+$encrypted = openssl_encrypt($padded_data, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
+$output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
+var_dump(rtrim($output));
?>
--EXPECT--
string(45) "openssl_encrypt() and openssl_decrypt() tests"
string(45) "openssl_encrypt() and openssl_decrypt() tests"
-
+string(45) "openssl_encrypt() and openssl_decrypt() tests"
diff --git a/ext/openssl/tests/bug54060.phpt b/ext/openssl/tests/bug54060.phpt
index fe8ca94a5f..88f1f944df 100644
--- a/ext/openssl/tests/bug54060.phpt
+++ b/ext/openssl/tests/bug54060.phpt
@@ -10,7 +10,7 @@ r7-89437 r892374 r894372 r894 7289r7 f frwerfh i iurf iuryw uyrfouiwy ruy
972439 8478942 yrhfjkdhls";
$pass = "r23498rui324hjbnkj";
-openssl_encrypt($data, 'des3', $pass, false, '1qazxsw2');
+openssl_encrypt($data, 'des3', $pass, 0, '1qazxsw2');
echo "Done";
?>
--EXPECT--
diff --git a/ext/openssl/tests/bug54061.phpt b/ext/openssl/tests/bug54061.phpt
index cef3944119..f1d2e24a28 100644
--- a/ext/openssl/tests/bug54061.phpt
+++ b/ext/openssl/tests/bug54061.phpt
@@ -9,8 +9,8 @@ r7-89437 r892374 r894372 r894 7289r7 f frwerfh i iurf iuryw uyrfouiwy ruy
972439 8478942 yrhfjkdhls";
$pass = "r23498rui324hjbnkj";
-$cr = openssl_encrypt($data, 'des3', $pass, false, '1qazxsw2');
-$dcr = openssl_decrypt($cr, 'des3', $pass, false, '1qazxsw2');
+$cr = openssl_encrypt($data, 'des3', $pass, 0, '1qazxsw2');
+$dcr = openssl_decrypt($cr, 'des3', $pass, 0, '1qazxsw2');
echo "Done";
?>
--EXPECT--
diff --git a/ext/openssl/tests/bug55646.phpt b/ext/openssl/tests/bug55646.phpt
new file mode 100644
index 0000000000..c11284d72d
--- /dev/null
+++ b/ext/openssl/tests/bug55646.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #55646: textual input in openssl_csr_new() is not expected in UTF-8
+--SKIPIF--
+<?php
+if (!function_exists('openssl_csr_new'))
+ die('skip no openssl extension');
+--FILE--
+<?php
+function stringAsHex($string){$unpacked = unpack("H*", $string);return implode(" ", str_split($unpacked[1],2));}
+
+$config = array("digest_alg" => "sha1","x509_extensions" => "v3_ca","req_extensions" => "v3_req","private_key_bits" => 2048,"private_key_type" => OPENSSL_KEYTYPE_RSA,"encrypt_key" => false,);
+$csr_info = array(
+ "countryName" => "US",
+ "stateOrProvinceName" => "Utah",
+ "localityName" => "Lindon",
+ "organizationName" => "Chinese",
+ "organizationalUnitName" => "IT \xe4\xba\x92",
+ "commonName" => "www.example.com",);
+$private = openssl_pkey_new($config);
+while (openssl_error_string()) {}
+$csr_res = openssl_csr_new($csr_info, $private,
+ ['config' => __DIR__."/openssl.cnf"]);
+if (!$csr_res) {
+ while ($e = openssl_error_string()) { $err = $e; }
+ die("Failed; last error: $err");
+}
+openssl_csr_export($csr_res, $csr);
+$output = openssl_csr_get_subject($csr);
+
+echo "A: ".$csr_info["organizationalUnitName"]."\n";
+echo "B: ".stringAsHex($csr_info["organizationalUnitName"])."\n";
+echo "C: ".$output['OU']."\n";
+echo "D: ".stringAsHex($output['OU'])."\n";
+--EXPECT--
+A: IT 互
+B: 49 54 20 e4 ba 92
+C: IT 互
+D: 49 54 20 e4 ba 92
diff --git a/ext/openssl/tests/openssl_decrypt_error.phpt b/ext/openssl/tests/openssl_decrypt_error.phpt
index 233fa0c5bd..40debbd04f 100644
--- a/ext/openssl/tests/openssl_decrypt_error.phpt
+++ b/ext/openssl/tests/openssl_decrypt_error.phpt
@@ -12,7 +12,7 @@ $iv = str_repeat("\0", openssl_cipher_iv_length($method));
$encrypted = openssl_encrypt($data, $method, $password);
var_dump($encrypted); /* Not passing $iv should be the same as all-NULL iv, but with a warning */
-var_dump(openssl_encrypt($data, $method, $password, false, $iv));
+var_dump(openssl_encrypt($data, $method, $password, 0, $iv));
var_dump(openssl_decrypt($encrypted, $method, $wrong));
var_dump(openssl_decrypt($encrypted, $wrong, $password));
var_dump(openssl_decrypt($wrong, $method, $password));
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index c502abd72c..d03eb3ee87 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -310,6 +310,7 @@ static inline int php_openssl_setup_crypto(php_stream *stream,
TSRMLS_DC)
{
SSL_METHOD *method;
+ long ssl_ctx_options = SSL_OP_ALL;
if (sslsock->ssl_handle) {
if (sslsock->s.is_blocked) {
@@ -377,7 +378,10 @@ static inline int php_openssl_setup_crypto(php_stream *stream,
return -1;
}
- SSL_CTX_set_options(sslsock->ctx, SSL_OP_ALL);
+#if OPENSSL_VERSION_NUMBER >= 0x0090605fL
+ ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+#endif
+ SSL_CTX_set_options(sslsock->ctx, ssl_ctx_options);
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL
{
@@ -532,7 +536,7 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
zval_is_true(*val)) {
MAKE_STD_ZVAL(zcert);
ZVAL_RESOURCE(zcert, zend_list_insert(peer_cert,
- php_openssl_get_x509_list_id()));
+ php_openssl_get_x509_list_id() TSRMLS_CC));
php_stream_context_set_option(stream->context,
"ssl", "peer_certificate",
zcert);
@@ -561,7 +565,7 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
MAKE_STD_ZVAL(zcert);
ZVAL_RESOURCE(zcert,
zend_list_insert(mycert,
- php_openssl_get_x509_list_id()));
+ php_openssl_get_x509_list_id() TSRMLS_CC));
add_next_index_zval(arr, zcert);
}
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index b840066d99..8647e105ef 100644
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -816,7 +816,7 @@ PHP_FUNCTION(pcntl_exec)
if (execve(path, argv, envp) == -1) {
PCNTL_G(last_error) = errno;
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
}
/* Cleanup */
@@ -826,7 +826,7 @@ PHP_FUNCTION(pcntl_exec)
if (execv(path, argv) == -1) {
PCNTL_G(last_error) = errno;
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
}
}
@@ -849,6 +849,11 @@ PHP_FUNCTION(pcntl_signal)
return;
}
+ if (signo < 1 || signo > 32) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid signal");
+ RETURN_FALSE;
+ }
+
if (!PCNTL_G(spares)) {
/* since calling malloc() from within a signal handler is not portable,
* pre-allocate a few records for recording signals */
@@ -864,8 +869,9 @@ PHP_FUNCTION(pcntl_signal)
/* Special long value case for SIG_DFL and SIG_IGN */
if (Z_TYPE_P(handle)==IS_LONG) {
- if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
+ if (Z_LVAL_P(handle) != (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified");
+ RETURN_FALSE;
}
if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) {
PCNTL_G(last_error) = errno;
@@ -1121,7 +1127,7 @@ PHP_FUNCTION(pcntl_getpriority)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
break;
default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
break;
}
RETURN_FALSE;
@@ -1161,7 +1167,7 @@ PHP_FUNCTION(pcntl_setpriority)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
break;
default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
break;
}
RETURN_FALSE;
diff --git a/ext/pcntl/php_signal.c b/ext/pcntl/php_signal.c
index 167363c16e..35a2df1741 100644
--- a/ext/pcntl/php_signal.c
+++ b/ext/pcntl/php_signal.c
@@ -18,14 +18,21 @@
/* $Id$ */
+#include "TSRM.h"
#include "php_signal.h"
+#include "Zend/zend.h"
+#include "Zend/zend_signal.h"
/* php_signal using sigaction is derrived from Advanced Programing
* in the Unix Environment by W. Richard Stevens p 298. */
Sigfunc *php_signal4(int signo, Sigfunc *func, int restart, int mask_all)
{
struct sigaction act,oact;
+#ifdef ZEND_SIGNALS
+ TSRMLS_FETCH();
+#endif
act.sa_handler = func;
+
if (mask_all) {
sigfillset(&act.sa_mask);
} else {
@@ -41,9 +48,15 @@ Sigfunc *php_signal4(int signo, Sigfunc *func, int restart, int mask_all)
act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
#endif
}
+#ifdef ZEND_SIGNALS
+ if (zend_sigaction(signo, &act, &oact TSRMLS_CC) < 0)
+#else
if (sigaction(signo, &act, &oact) < 0)
+#endif
+ {
return SIG_ERR;
-
+ }
+
return oact.sa_handler;
}
diff --git a/ext/pcntl/tests/pcntl_exec_3.phpt b/ext/pcntl/tests/pcntl_exec_3.phpt
index d27c1c9962..5349381d92 100644
--- a/ext/pcntl/tests/pcntl_exec_3.phpt
+++ b/ext/pcntl/tests/pcntl_exec_3.phpt
@@ -13,5 +13,5 @@ unlink($file);
Warning: pcntl_exec() expects at least 1 parameter, 0 given %s
NULL
-Warning: pcntl_exec(): Error has occured: (errno %d) %s
+Warning: pcntl_exec(): Error has occurred: (errno %d) %s
bool(false)
diff --git a/ext/pcntl/tests/pcntl_signal.phpt b/ext/pcntl/tests/pcntl_signal.phpt
index 3f894fa3f2..2db01305b5 100644
--- a/ext/pcntl/tests/pcntl_signal.phpt
+++ b/ext/pcntl/tests/pcntl_signal.phpt
@@ -29,12 +29,10 @@ Warning: pcntl_signal() expects at least 2 parameters, 0 given in %s
NULL
bool(true)
-Warning: pcntl_signal(): Invalid value for handle argument specified in %s
-
-Warning: pcntl_signal(): Error assigning signal %s
+Warning: pcntl_signal(): Invalid signal %s
bool(false)
-Warning: pcntl_signal(): Error assigning signal %s
+Warning: pcntl_signal(): Invalid signal %s
bool(false)
Warning: pcntl_signal(): not callable is not a callable function name error in %s
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index b1b9e66e9a..2f892c8e94 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -248,6 +248,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
#endif
pcre_cache_entry *pce;
pcre_cache_entry new_entry;
+ char *tmp = NULL;
/* Try to lookup the cached regex entry, and if successful, just pass
back the compiled pattern, otherwise go on and compile it. */
@@ -275,7 +276,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
get to the end without encountering a delimiter. */
while (isspace((int)*(unsigned char *)p)) p++;
if (*p == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty regular expression");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ p < regex + regex_len ? "Null byte in regex" : "Empty regular expression");
return NULL;
}
@@ -292,21 +294,18 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
delimiter = pp[5];
end_delimiter = delimiter;
+ pp = p;
+
if (start_delimiter == end_delimiter) {
/* We need to iterate through the pattern, searching for the ending delimiter,
but skipping the backslashed delimiters. If the ending delimiter is not
found, display a warning. */
- pp = p;
while (*pp != 0) {
if (*pp == '\\' && pp[1] != 0) pp++;
else if (*pp == delimiter)
break;
pp++;
}
- if (*pp == 0) {
- php_error_docref(NULL TSRMLS_CC,E_WARNING, "No ending delimiter '%c' found", delimiter);
- return NULL;
- }
} else {
/* We iterate through the pattern, searching for the matching ending
* delimiter. For each matching starting delimiter, we increment nesting
@@ -314,7 +313,6 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
* reach the end of the pattern without matching, display a warning.
*/
int brackets = 1; /* brackets nesting level */
- pp = p;
while (*pp != 0) {
if (*pp == '\\' && pp[1] != 0) pp++;
else if (*pp == end_delimiter && --brackets <= 0)
@@ -323,10 +321,17 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
brackets++;
pp++;
}
- if (*pp == 0) {
- php_error_docref(NULL TSRMLS_CC,E_WARNING, "No ending matching delimiter '%c' found", end_delimiter);
- return NULL;
+ }
+
+ if (*pp == 0) {
+ if (pp < regex + regex_len) {
+ php_error_docref(NULL TSRMLS_CC,E_WARNING, "Null byte in regex");
+ } else if (start_delimiter == end_delimiter) {
+ php_error_docref(NULL TSRMLS_CC,E_WARNING, "No ending delimiter '%c' found", delimiter);
+ } else {
+ php_error_docref(NULL TSRMLS_CC,E_WARNING, "No ending matching delimiter '%c' found", delimiter);
}
+ return NULL;
}
/* Make a copy of the actual pattern. */
@@ -337,7 +342,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
/* Parse through the options, setting appropriate flags. Display
a warning if we encounter an unknown modifier. */
- while (*pp != 0) {
+ while (pp < regex + regex_len) {
switch (*pp++) {
/* Perl compatible options */
case 'i': coptions |= PCRE_CASELESS; break;
@@ -368,7 +373,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
break;
default:
- php_error_docref(NULL TSRMLS_CC,E_WARNING, "Unknown modifier '%c'", pp[-1]);
+ if (pp[-1]) {
+ php_error_docref(NULL TSRMLS_CC,E_WARNING, "Unknown modifier '%c'", pp[-1]);
+ } else {
+ php_error_docref(NULL TSRMLS_CC,E_WARNING, "Null byte in regex");
+ }
efree(pattern);
return NULL;
}
@@ -430,9 +439,26 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
new_entry.locale = pestrdup(locale, 1);
new_entry.tables = tables;
#endif
+
+ /*
+ * Interned strings are not duplicated when stored in HashTable,
+ * but all the interned strings created during HTTP request are removed
+ * at end of request. However PCRE_G(pcre_cache) must be consistent
+ * on the next request as well. So we disable usage of interned strings
+ * as hash keys especually for this table.
+ * See bug #63180
+ */
+ if (IS_INTERNED(regex)) {
+ regex = tmp = estrndup(regex, regex_len);
+ }
+
zend_hash_update(&PCRE_G(pcre_cache), regex, regex_len+1, (void *)&new_entry,
sizeof(pcre_cache_entry), (void**)&pce);
+ if (tmp) {
+ efree(tmp);
+ }
+
return pce;
}
/* }}} */
@@ -507,7 +533,7 @@ static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ *
long flags = 0; /* Match control flags */
long start_offset = 0; /* Where the new search starts */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ((global) ? "ssz|ll" : "ss|zll"), &regex, &regex_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|zll", &regex, &regex_len,
&subject, &subject_len, &subpats, &flags, &start_offset) == FAILURE) {
RETURN_FALSE;
}
@@ -609,7 +635,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
offsets = (int *)safe_emalloc(size_offsets, sizeof(int), 0);
/* Allocate match sets array and initialize the values. */
- if (global && subpats_order == PREG_PATTERN_ORDER) {
+ if (global && subpats && subpats_order == PREG_PATTERN_ORDER) {
match_sets = (zval **)safe_emalloc(num_subpats, sizeof(zval *), 0);
for (i=0; i<num_subpats; i++) {
ALLOC_ZVAL(match_sets[i]);
@@ -651,7 +677,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
}
if (global) { /* global pattern matching */
- if (subpats_order == PREG_PATTERN_ORDER) {
+ if (subpats && subpats_order == PREG_PATTERN_ORDER) {
/* For each subpattern, insert it into the appropriate array. */
for (i = 0; i < count; i++) {
if (offset_capture) {
@@ -741,7 +767,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
} while (global);
/* Add the match sets to the output array and clean up */
- if (global && subpats_order == PREG_PATTERN_ORDER) {
+ if (global && subpats && subpats_order == PREG_PATTERN_ORDER) {
for (i = 0; i < num_subpats; i++) {
if (subpat_names[i]) {
zend_hash_update(Z_ARRVAL_P(subpats), subpat_names[i],
@@ -773,7 +799,7 @@ static PHP_FUNCTION(preg_match)
}
/* }}} */
-/* {{{ proto int preg_match_all(string pattern, string subject, array &subpatterns [, int flags [, int offset]])
+/* {{{ proto int preg_match_all(string pattern, string subject [, array &subpatterns [, int flags [, int offset]]])
Perform a Perl-style global regular expression match */
static PHP_FUNCTION(preg_match_all)
{
@@ -900,7 +926,7 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,
match = subject + offsets[backref<<1];
match_len = offsets[(backref<<1)+1] - offsets[backref<<1];
if (match_len) {
- esc_match = php_addslashes_ex(match, match_len, &esc_match_len, 0, 1 TSRMLS_CC);
+ esc_match = php_addslashes(match, match_len, &esc_match_len, 0 TSRMLS_CC);
} else {
esc_match = match;
esc_match_len = 0;
diff --git a/ext/pcre/tests/002.phpt b/ext/pcre/tests/002.phpt
index 726390c77e..00f68f3651 100644
--- a/ext/pcre/tests/002.phpt
+++ b/ext/pcre/tests/002.phpt
@@ -20,7 +20,7 @@ var_dump(preg_replace('/(.)/e', 'for ($', 'abc'));
Warning: preg_match() expects at least 2 parameters, 0 given in %s002.php on line 3
bool(false)
-Warning: preg_match_all() expects at least 3 parameters, 0 given in %s002.php on line 4
+Warning: preg_match_all() expects at least 2 parameters, 0 given in %s002.php on line 4
bool(false)
Warning: preg_match_all(): Invalid flags specified in %s002.php on line 5
diff --git a/ext/pcre/tests/bug33200.phpt b/ext/pcre/tests/bug33200.phpt
deleted file mode 100644
index ddbb06519b..0000000000
--- a/ext/pcre/tests/bug33200.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Bug #33200 (magic_quotes_sybase = On makes 'e' modifier misbehave)
---INI--
-magic_quotes_sybase=1
---FILE--
-<?php
-$str = 'some \'$sample\' text';
-$str = preg_replace("/(some.*text)/e", "strtoupper('\\1')", $str);
-echo $str . "\r\n";
-?>
---EXPECT--
-Deprecated: Directive 'magic_quotes_sybase' is deprecated in PHP 5.3 and greater in Unknown on line 0
-SOME '$SAMPLE' TEXT
diff --git a/ext/pcre/tests/null_bytes.phpt b/ext/pcre/tests/null_bytes.phpt
new file mode 100644
index 0000000000..9a3f433ffb
--- /dev/null
+++ b/ext/pcre/tests/null_bytes.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Zero byte test
+--FILE--
+<?php
+
+preg_match("\0//i", "");
+preg_match("/\0/i", "");
+preg_match("//\0i", "");
+preg_match("//i\0", "");
+preg_match("/\\\0/i", "");
+
+preg_match("\0[]i", "");
+preg_match("[\0]i", "");
+preg_match("[]\0i", "");
+preg_match("[]i\0", "");
+preg_match("[\\\0]i", "");
+
+preg_replace("/foo/e\0/i", "echo('Eek');", "");
+
+?>
+--EXPECTF--
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 3
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 4
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 5
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 6
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 7
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 9
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 10
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 11
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 12
+
+Warning: preg_match(): Null byte in regex in %snull_bytes.php on line 13
+
+Warning: preg_replace(): Null byte in regex in %snull_bytes.php on line 15
diff --git a/ext/pcre/tests/preg_match_all_basic.phpt b/ext/pcre/tests/preg_match_all_basic.phpt
index 06dec1cb45..20c4a96be4 100644
--- a/ext/pcre/tests/preg_match_all_basic.phpt
+++ b/ext/pcre/tests/preg_match_all_basic.phpt
@@ -3,7 +3,7 @@ Test preg_match_all() function : basic functionality
--FILE--
<?php
/*
-* proto int preg_match_all(string pattern, string subject, array subpatterns [, int flags [, int offset]])
+* proto int preg_match_all(string pattern, string subject, [array subpatterns [, int flags [, int offset]]])
* Function is implemented in ext/pcre/php_pcre.c
*/
$string = 'Hello, world! This is a test. This is another test. \[4]. 34534 string.';
@@ -17,6 +17,12 @@ var_dump(preg_match_all('/\d{2}$/', $string, $match4)); //tries to find 2 digits
var_dump($match4);
var_dump(preg_match_all('/(This is a ){2}(.*)\stest/', $string, $match5)); //tries to find "This is aThis is a [...] test" (0 matches)
var_dump($match5);
+
+// Test not passing in a subpatterns array.
+var_dump(preg_match_all('/test/', $string));
+var_dump(preg_match_all('/this isn\'t in the string/', $string));
+var_dump(preg_match_all('/world/', $string));
+var_dump(preg_match_all('/[0-9]/', $string));
?>
--EXPECTF--
int(1)
@@ -80,3 +86,7 @@ array(3) {
array(0) {
}
}
+int(2)
+int(0)
+int(1)
+int(6)
diff --git a/ext/pcre/tests/preg_match_all_error.phpt b/ext/pcre/tests/preg_match_all_error.phpt
index 2371ccfef1..f6e89284bb 100644
--- a/ext/pcre/tests/preg_match_all_error.phpt
+++ b/ext/pcre/tests/preg_match_all_error.phpt
@@ -21,8 +21,7 @@ var_dump(preg_match_all($pattern, $subject, $matches, $flags, $offset, $extra_ar
// Testing preg_match_all withone less than the expected number of arguments
echo "\n-- Testing preg_match_all() function with less than expected no. of arguments --\n";
$pattern = '/\w/';
-$subject = 'string_val';
-var_dump(preg_match_all($pattern, $subject));
+var_dump(preg_match_all($pattern));
echo "Done"
?>
--EXPECTF--
@@ -30,7 +29,7 @@ echo "Done"
-- Testing preg_match_all() function with Zero arguments --
-Warning: preg_match_all() expects at least 3 parameters, 0 given in %spreg_match_all_error.php on line %d
+Warning: preg_match_all() expects at least 2 parameters, 0 given in %spreg_match_all_error.php on line %d
bool(false)
-- Testing preg_match_all() function with more than expected no. of arguments --
@@ -40,6 +39,6 @@ bool(false)
-- Testing preg_match_all() function with less than expected no. of arguments --
-Warning: preg_match_all() expects at least 3 parameters, 2 given in %spreg_match_all_error.php on line %d
+Warning: preg_match_all() expects at least 2 parameters, 1 given in %spreg_match_all_error.php on line %d
bool(false)
Done
diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c
index e1d8235b0b..e0a1c3ce2f 100644
--- a/ext/pdo/pdo.c
+++ b/ext/pdo/pdo.c
@@ -277,7 +277,7 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
parsed[j].optval = estrndup(data_source + valstart, semi - valstart - n_semicolumns);
} else {
int vlen = semi - valstart;
- char *orig_val = data_source + valstart;
+ const char *orig_val = data_source + valstart;
char *new_val = (char *) emalloc(vlen - n_semicolumns + 1);
parsed[j].optval = new_val;
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 4035b2b910..acdc0dd90d 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -187,7 +187,7 @@ static char *dsn_from_uri(char *uri, char *buf, size_t buflen TSRMLS_DC) /* {{{
php_stream *stream;
char *dsn = NULL;
- stream = php_stream_open_wrapper(uri, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(uri, "rb", REPORT_ERRORS, NULL);
if (stream) {
dsn = php_stream_get_line(stream, buf, buflen, NULL);
php_stream_close(stream);
@@ -229,6 +229,7 @@ static PHP_METHOD(PDO, dbh_constructor)
snprintf(alt_dsn, sizeof(alt_dsn), "pdo.dsn.%s", data_source);
if (FAILURE == cfg_get_string(alt_dsn, &ini_dsn)) {
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name");
+ zval_dtor(object);
ZVAL_NULL(object);
return;
}
@@ -328,20 +329,21 @@ static PHP_METHOD(PDO, dbh_constructor)
memcpy((char *)pdbh->persistent_id, hashkey, plen+1);
pdbh->persistent_id_len = plen+1;
pdbh->refcount = 1;
- pdbh->properties = NULL;
+ pdbh->std.properties = NULL;
}
}
if (pdbh) {
/* let's copy the emalloc bits over from the other handle */
- if (pdbh->properties) {
- zend_hash_destroy(dbh->properties);
- efree(dbh->properties);
+ if (pdbh->std.properties) {
+ zend_hash_destroy(dbh->std.properties);
+ efree(dbh->std.properties);
} else {
- pdbh->ce = dbh->ce;
+ pdbh->std.ce = dbh->std.ce;
pdbh->def_stmt_ce = dbh->def_stmt_ce;
pdbh->def_stmt_ctor_args = dbh->def_stmt_ctor_args;
- pdbh->properties = dbh->properties;
+ pdbh->std.properties = dbh->std.properties;
+ pdbh->std.properties_table = dbh->std.properties_table;
}
/* kill the non-persistent thingamy */
efree(dbh);
@@ -400,7 +402,7 @@ options:
if (options) {
zval **attr_value;
char *str_key;
- long long_key;
+ ulong long_key;
zend_hash_internal_pointer_reset(Z_ARRVAL_P(options));
while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(options), (void**)&attr_value)
@@ -449,7 +451,7 @@ static void pdo_stmt_construct(pdo_stmt_t *stmt, zval *object, zend_class_entry
MAKE_STD_ZVAL(query_string);
ZVAL_STRINGL(query_string, stmt->query_string, stmt->query_stringlen, 1);
ZVAL_STRINGL(&z_key, "queryString", sizeof("queryString")-1, 0);
- std_object_handlers.write_property(object, &z_key, query_string TSRMLS_CC);
+ std_object_handlers.write_property(object, &z_key, query_string, 0 TSRMLS_CC);
zval_ptr_dtor(&query_string);
if (dbstmt_ce->constructor) {
@@ -694,7 +696,11 @@ static PHP_METHOD(PDO, inTransaction)
}
PDO_CONSTRUCT_CHECK;
- RETURN_BOOL(dbh->in_txn);
+ if (!dbh->methods->in_transaction) {
+ RETURN_BOOL(dbh->in_txn);
+ }
+
+ RETURN_BOOL(dbh->methods->in_transaction(dbh TSRMLS_CC));
}
/* }}} */
@@ -1225,7 +1231,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo___construct, 0, 0, 3)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_prepare, 0, 0, 1)
- ZEND_ARG_INFO(0, statment)
+ ZEND_ARG_INFO(0, statement)
ZEND_ARG_INFO(0, options) /* array */
ZEND_END_ARG_INFO()
@@ -1302,29 +1308,37 @@ int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
ifunc->type = ZEND_INTERNAL_FUNCTION;
ifunc->handler = funcs->handler;
ifunc->function_name = (char*)funcs->fname;
- ifunc->scope = dbh->ce;
+ ifunc->scope = dbh->std.ce;
ifunc->prototype = NULL;
+ if (funcs->flags) {
+ ifunc->fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE;
+ } else {
+ ifunc->fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE;
+ }
if (funcs->arg_info) {
+ zend_internal_function_info *info = (zend_internal_function_info*)funcs->arg_info;
+
ifunc->arg_info = (zend_arg_info*)funcs->arg_info + 1;
ifunc->num_args = funcs->num_args;
- if (funcs->arg_info[0].required_num_args == -1) {
+ if (info->required_num_args == -1) {
ifunc->required_num_args = funcs->num_args;
} else {
- ifunc->required_num_args = funcs->arg_info[0].required_num_args;
+ ifunc->required_num_args = info->required_num_args;
+ }
+ if (info->pass_rest_by_reference) {
+ if (info->pass_rest_by_reference == ZEND_SEND_PREFER_REF) {
+ ifunc->fn_flags |= ZEND_ACC_PASS_REST_PREFER_REF;
+ } else {
+ ifunc->fn_flags |= ZEND_ACC_PASS_REST_BY_REFERENCE;
+ }
+ }
+ if (info->return_reference) {
+ ifunc->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
}
- ifunc->pass_rest_by_reference = funcs->arg_info[0].pass_by_reference;
- ifunc->return_reference = funcs->arg_info[0].return_reference;
} else {
ifunc->arg_info = NULL;
ifunc->num_args = 0;
ifunc->required_num_args = 0;
- ifunc->pass_rest_by_reference = 0;
- ifunc->return_reference = 0;
- }
- if (funcs->flags) {
- ifunc->fn_flags = funcs->flags;
- } else {
- ifunc->fn_flags = ZEND_ACC_PUBLIC;
}
namelen = strlen(funcs->fname);
lc_name = emalloc(namelen+1);
@@ -1343,7 +1357,7 @@ static union _zend_function *dbh_method_get(
#else
zval *object,
#endif
- char *method_name, int method_len TSRMLS_DC)
+ char *method_name, int method_len, const zend_literal *key TSRMLS_DC)
{
zend_function *fbc = NULL;
char *lc_method_name;
@@ -1355,7 +1369,7 @@ static union _zend_function *dbh_method_get(
lc_method_name = emalloc(method_len + 1);
zend_str_tolower_copy(lc_method_name, method_name, method_len);
- if ((fbc = std_object_handlers.get_method(object_pp, method_name, method_len TSRMLS_CC)) == NULL) {
+ if ((fbc = std_object_handlers.get_method(object_pp, method_name, method_len, key TSRMLS_CC)) == NULL) {
/* not a pre-defined method, nor a user-defined method; check
* the driver specific methods */
if (!dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
@@ -1555,16 +1569,12 @@ static void pdo_dbh_free_storage(pdo_dbh_t *dbh TSRMLS_DC)
dbh->methods->rollback(dbh TSRMLS_CC);
dbh->in_txn = 0;
}
-
- if (dbh->properties) {
- zend_hash_destroy(dbh->properties);
- efree(dbh->properties);
- dbh->properties = NULL;
- }
if (dbh->is_persistent && dbh->methods && dbh->methods->persistent_shutdown) {
dbh->methods->persistent_shutdown(dbh TSRMLS_CC);
}
+ zend_object_std_dtor(&dbh->std TSRMLS_CC);
+ dbh->std.properties = NULL;
dbh_free(dbh TSRMLS_CC);
}
@@ -1572,15 +1582,13 @@ zend_object_value pdo_dbh_new(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
pdo_dbh_t *dbh;
- zval *tmp;
dbh = emalloc(sizeof(*dbh));
memset(dbh, 0, sizeof(*dbh));
- dbh->ce = ce;
+ zend_object_std_init(&dbh->std, ce TSRMLS_CC);
+ object_properties_init(&dbh->std, ce);
+ rebuild_object_properties(&dbh->std);
dbh->refcount = 1;
- ALLOC_HASHTABLE(dbh->properties);
- zend_hash_init(dbh->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(dbh->properties, &ce->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
dbh->def_stmt_ce = pdo_dbstmt_ce;
retval.handle = zend_objects_store_put(dbh, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbh_free_storage, NULL TSRMLS_CC);
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index 0cf0cf852a..31932eb3c2 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -1333,16 +1333,15 @@ static PHP_METHOD(PDOStatement, fetchObject)
long how = PDO_FETCH_CLASS;
long ori = PDO_FETCH_ORI_NEXT;
long off = 0;
- char *class_name;
+ char *class_name = NULL;
int class_name_len;
zend_class_entry *old_ce;
- zval *old_ctor_args, *ctor_args;
+ zval *old_ctor_args, *ctor_args = NULL;
int error = 0, old_arg_count;
PHP_STMT_GET_OBJ;
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sz",
- &class_name, &class_name_len, &ctor_args)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!a", &class_name, &class_name_len, &ctor_args)) {
RETURN_FALSE;
}
@@ -1357,17 +1356,8 @@ static PHP_METHOD(PDOStatement, fetchObject)
old_arg_count = stmt->fetch.cls.fci.param_count;
do_fetch_opt_finish(stmt, 0 TSRMLS_CC);
-
- switch(ZEND_NUM_ARGS()) {
- case 0:
- stmt->fetch.cls.ce = zend_standard_class_def;
- break;
- case 2:
- if (Z_TYPE_P(ctor_args) != IS_NULL && Z_TYPE_P(ctor_args) != IS_ARRAY) {
- pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array" TSRMLS_CC);
- error = 1;
- break;
- }
+
+ if (ctor_args) {
if (Z_TYPE_P(ctor_args) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
ALLOC_ZVAL(stmt->fetch.cls.ctor_args);
*stmt->fetch.cls.ctor_args = *ctor_args;
@@ -1375,15 +1365,16 @@ static PHP_METHOD(PDOStatement, fetchObject)
} else {
stmt->fetch.cls.ctor_args = NULL;
}
- /* no break */
- case 1:
+ }
+ if (class_name && !error) {
stmt->fetch.cls.ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
if (!stmt->fetch.cls.ce) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Could not find user-supplied class" TSRMLS_CC);
error = 1;
- break;
}
+ } else if (!error) {
+ stmt->fetch.cls.ce = zend_standard_class_def;
}
if (!error && !do_fetch(stmt, TRUE, return_value, how, ori, off, 0 TSRMLS_CC)) {
@@ -2244,7 +2235,7 @@ const zend_function_entry pdo_dbstmt_functions[] = {
};
/* {{{ overloaded handlers for PDOStatement class */
-static void dbstmt_prop_write(zval *object, zval *member, zval *value TSRMLS_DC)
+static void dbstmt_prop_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
@@ -2253,11 +2244,11 @@ static void dbstmt_prop_write(zval *object, zval *member, zval *value TSRMLS_DC)
if(strcmp(Z_STRVAL_P(member), "queryString") == 0) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
} else {
- std_object_handlers.write_property(object, member, value TSRMLS_CC);
+ std_object_handlers.write_property(object, member, value, key TSRMLS_CC);
}
}
-static void dbstmt_prop_delete(zval *object, zval *member TSRMLS_DC)
+static void dbstmt_prop_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
{
pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
@@ -2266,7 +2257,7 @@ static void dbstmt_prop_delete(zval *object, zval *member TSRMLS_DC)
if(strcmp(Z_STRVAL_P(member), "queryString") == 0) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
} else {
- std_object_handlers.unset_property(object, member TSRMLS_CC);
+ std_object_handlers.unset_property(object, member, key TSRMLS_CC);
}
}
@@ -2276,7 +2267,7 @@ static union _zend_function *dbstmt_method_get(
#else
zval *object,
#endif
- char *method_name, int method_len TSRMLS_DC)
+ char *method_name, int method_len, const zend_literal *key TSRMLS_DC)
{
zend_function *fbc = NULL;
char *lc_method_name;
@@ -2325,17 +2316,14 @@ static int dbstmt_compare(zval *object1, zval *object2 TSRMLS_DC)
static zend_object_value dbstmt_clone_obj(zval *zobject TSRMLS_DC)
{
zend_object_value retval;
- zval *tmp;
pdo_stmt_t *stmt;
pdo_stmt_t *old_stmt;
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
stmt = ecalloc(1, sizeof(*stmt));
- stmt->ce = Z_OBJCE_P(zobject);
+ zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject) TSRMLS_CC);
+ object_properties_init(&stmt->std, Z_OBJCE_P(zobject));
stmt->refcount = 1;
- ALLOC_HASHTABLE(stmt->properties);
- zend_hash_init(stmt->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(stmt->properties, &stmt->ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
old_stmt = (pdo_stmt_t *)zend_object_store_get_object(zobject TSRMLS_CC);
@@ -2380,12 +2368,6 @@ void pdo_stmt_init(TSRMLS_D)
static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
{
- if (stmt->properties) {
- zend_hash_destroy(stmt->properties);
- efree(stmt->properties);
- stmt->properties = NULL;
- }
-
if (stmt->bound_params) {
zend_hash_destroy(stmt->bound_params);
FREE_HASHTABLE(stmt->bound_params);
@@ -2434,6 +2416,7 @@ static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
if (stmt->dbh) {
php_pdo_dbh_delref(stmt->dbh TSRMLS_CC);
}
+ zend_object_std_dtor(&stmt->std TSRMLS_CC);
efree(stmt);
}
@@ -2457,16 +2440,13 @@ void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
- zval *tmp;
pdo_stmt_t *stmt;
stmt = emalloc(sizeof(*stmt));
memset(stmt, 0, sizeof(*stmt));
- stmt->ce = ce;
+ zend_object_std_init(&stmt->std, ce TSRMLS_CC);
+ object_properties_init(&stmt->std, ce);
stmt->refcount = 1;
- ALLOC_HASHTABLE(stmt->properties);
- zend_hash_init(stmt->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(stmt->properties, &ce->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbstmt_free_storage, (zend_objects_store_clone_t)dbstmt_clone_obj TSRMLS_CC);
retval.handlers = &pdo_dbstmt_object_handlers;
@@ -2601,7 +2581,7 @@ const zend_function_entry pdo_row_functions[] = {
{NULL, NULL, NULL}
};
-static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC)
+static zval *row_prop_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
zval *return_value;
pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
@@ -2629,7 +2609,7 @@ static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC
}
if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
zval_ptr_dtor(&return_value);
- return std_object_handlers.read_property(object, member, type TSRMLS_CC);
+ return std_object_handlers.read_property(object, member, type, key TSRMLS_CC);
}
}
}
@@ -2640,12 +2620,22 @@ static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC
return return_value;
}
-static void row_prop_or_dim_write(zval *object, zval *member, zval *value TSRMLS_DC)
+static zval *row_dim_read(zval *object, zval *member, int type TSRMLS_DC)
+{
+ return row_prop_read(object, member, type, NULL TSRMLS_CC);
+}
+
+static void row_prop_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "This PDORow is not from a writable result set");
}
-static int row_prop_or_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+static void row_dim_write(zval *object, zval *member, zval *value TSRMLS_DC)
+{
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "This PDORow is not from a writable result set");
+}
+
+static int row_prop_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
{
pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC);
int colno = -1;
@@ -2669,7 +2659,17 @@ static int row_prop_or_dim_exists(zval *object, zval *member, int check_empty TS
return 0;
}
-static void row_prop_or_dim_delete(zval *object, zval *offset TSRMLS_DC)
+static int row_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+{
+ return row_prop_exists(object, member, check_empty, NULL TSRMLS_CC);
+}
+
+static void row_prop_delete(zval *object, zval *offset, const zend_literal *key TSRMLS_DC)
+{
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDORow");
+}
+
+static void row_dim_delete(zval *object, zval *offset TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a PDORow");
}
@@ -2683,15 +2683,18 @@ static HashTable *row_get_properties(zval *object TSRMLS_DC)
return NULL;
}
+ if (!stmt->std.properties) {
+ rebuild_object_properties(&stmt->std);
+ }
for (i = 0; i < stmt->column_count; i++) {
zval *val;
MAKE_STD_ZVAL(val);
fetch_value(stmt, val, i, NULL TSRMLS_CC);
- zend_hash_update(stmt->properties, stmt->columns[i].name, stmt->columns[i].namelen + 1, (void *)&val, sizeof(zval *), NULL);
+ zend_hash_update(stmt->std.properties, stmt->columns[i].name, stmt->columns[i].namelen + 1, (void *)&val, sizeof(zval *), NULL);
}
- return stmt->properties;
+ return stmt->std.properties;
}
static union _zend_function *row_method_get(
@@ -2700,7 +2703,7 @@ static union _zend_function *row_method_get(
#else
zval *object,
#endif
- char *method_name, int method_len TSRMLS_DC)
+ char *method_name, int method_len, const zend_literal *key TSRMLS_DC)
{
zend_function *fbc;
char *lc_method_name;
@@ -2717,7 +2720,7 @@ static union _zend_function *row_method_get(
return fbc;
}
-static int row_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
+static int row_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
{
return FAILURE;
}
@@ -2739,7 +2742,7 @@ static zend_class_entry *row_get_ce(const zval *object TSRMLS_DC)
return pdo_row_ce;
}
-static int row_get_classname(const zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
+static int row_get_classname(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
{
if (parent) {
return FAILURE;
@@ -2756,18 +2759,20 @@ static int row_compare(zval *object1, zval *object2 TSRMLS_DC)
}
zend_object_handlers pdo_row_object_handlers = {
- ZEND_OBJECTS_STORE_HANDLERS,
- row_prop_or_dim_read,
- row_prop_or_dim_write,
- row_prop_or_dim_read,
- row_prop_or_dim_write,
+ zend_objects_store_add_ref,
+ zend_objects_store_del_ref,
+ NULL,
+ row_prop_read,
+ row_prop_write,
+ row_dim_read,
+ row_dim_write,
NULL,
NULL,
NULL,
- row_prop_or_dim_exists,
- row_prop_or_dim_delete,
- row_prop_or_dim_exists,
- row_prop_or_dim_delete,
+ row_prop_exists,
+ row_prop_delete,
+ row_dim_exists,
+ row_dim_delete,
row_get_properties,
row_method_get,
row_call_method,
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index 17b23a32ef..b9c46bae74 100644
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -310,6 +310,7 @@ struct pdo_dbh_methods {
pdo_dbh_check_liveness_func check_liveness;
pdo_dbh_get_driver_methods_func get_driver_methods;
pdo_dbh_request_shutdown persistent_shutdown;
+ pdo_dbh_txn_func in_transaction;
};
/* }}} */
@@ -430,10 +431,7 @@ struct _pdo_dbh_t {
to allow the extending class to escape all the custom handlers
that PDO declares.
*/
- zend_class_entry *ce;
- HashTable *properties;
- unsigned int in_get:1;
- unsigned int in_set:1;
+ zend_object std;
/* driver specific methods */
struct pdo_dbh_methods *methods;
@@ -548,10 +546,7 @@ struct _pdo_stmt_t {
to allow the extending class to escape all the custom handlers
that PDO declares.
*/
- zend_class_entry *ce;
- HashTable *properties;
- unsigned int in_get:1;
- unsigned int in_set:1;
+ zend_object std;
/* driver specifics */
struct pdo_stmt_methods *methods;
diff --git a/ext/pdo/tests/bug61292.phpt b/ext/pdo/tests/bug61292.phpt
new file mode 100644
index 0000000000..2381fd1a23
--- /dev/null
+++ b/ext/pdo/tests/bug61292.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #61292 (Segfault while calling a method on an overloaded PDO object)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo')) die('skip');
+$dir = getenv('REDIR_TEST_DIR');
+if (false == $dir) die('skip no driver');
+require_once $dir . 'pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.dirname(__FILE__) . '/../../pdo/tests/');
+require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
+
+class Database_SQL extends PDO
+{
+ function __construct()
+ {
+ $options = array(PDO::ATTR_PERSISTENT => TRUE);
+ parent::__construct(getenv("PDOTEST_DSN"), getenv("PDOTEST_USER"), getenv("PDOTEST_PASS"), $options);
+ }
+
+ var $bar = array();
+
+ public function foo()
+ {
+ var_dump($this->bar);
+ }
+}
+
+(new Database_SQL)->foo();
+?>
+--EXPECTF--
+array(0) {
+}
diff --git a/ext/pdo/tests/pdo_test.inc b/ext/pdo/tests/pdo_test.inc
index a46e67d891..443c8dd822 100644
--- a/ext/pdo/tests/pdo_test.inc
+++ b/ext/pdo/tests/pdo_test.inc
@@ -11,7 +11,6 @@ if (getenv('PDOTEST_DSN') === false) {
$append = true;
}
}
- if (ini_get('magic_quotes_runtime')) $common = stripslashes($common);
$conf = eval($common);
foreach($conf['ENV'] as $n=>$v) putenv("$n=$v");
}
@@ -82,4 +81,4 @@ class PDOTest {
return $config;
}
}
-?> \ No newline at end of file
+?>
diff --git a/ext/pdo_dblib/config.m4 b/ext/pdo_dblib/config.m4
index 3410ba9c6b..ba8244c721 100644
--- a/ext/pdo_dblib/config.m4
+++ b/ext/pdo_dblib/config.m4
@@ -59,19 +59,19 @@ if test "$PHP_PDO_DBLIB" != "no"; then
],[
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
- AC_MSG_RESULT($pdo_inc_path)
+ AC_MSG_RESULT($pdo_cv_inc_path)
])
PDO_DBLIB_DEFS="-DPDO_DBLIB_FLAVOUR=\\\"freetds\\\""
- PHP_NEW_EXTENSION(pdo_dblib, pdo_dblib.c dblib_driver.c dblib_stmt.c, $ext_shared,,-I$pdo_inc_path $PDO_DBLIB_DEFS)
+ PHP_NEW_EXTENSION(pdo_dblib, pdo_dblib.c dblib_driver.c dblib_stmt.c, $ext_shared,,-I$pdo_cv_inc_path $PDO_DBLIB_DEFS)
AC_CHECK_LIB(dnet_stub, dnet_addr,
[ PHP_ADD_LIBRARY_WITH_PATH(dnet_stub,,PDO_DBLIB_SHARED_LIBADD)
AC_DEFINE(HAVE_LIBDNET_STUB,1,[ ])
diff --git a/ext/pdo_dblib/db.php b/ext/pdo_dblib/db.php
deleted file mode 100644
index f9bac04d29..0000000000
--- a/ext/pdo_dblib/db.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/* assumes that you have the freetds db.lib on windows */
-
-dl('php_pdo.dll');
-dl('php_pdo_sybase.dll');
-
-try {
-
-$db = new PDO('sybase:', 'pdo', 'pdo');
-$db->setAttribute(PDO_ATTR_ERRMODE, PDO_ERRMODE_EXCEPTION);
-debug_zval_dump($db);
-
-$stmt = $db->prepare('select 10');
-debug_zval_dump($stmt);
-
-$x = $stmt->execute();
-debug_zval_dump($x);
-
-while (($r = $stmt->fetch())) {
- print_r($r);
-}
-
-} catch (Exception $e) {
- print $e;
-}
-
-$stmt = null;
-$db = null;
-echo "All done\n";
-?>
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index 0fff3990db..baf1dcc670 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -166,19 +166,97 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote
return 1;
}
+static int pdo_dblib_transaction_cmd(const char *cmd, pdo_dbh_t *dbh TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+ RETCODE ret;
+
+ if (FAIL == dbcmd(H->link, cmd)) {
+ return 0;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int dblib_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ return pdo_dblib_transaction_cmd("BEGIN TRANSACTION", dbh TSRMLS_CC);
+}
+
+static int dblib_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ return pdo_dblib_transaction_cmd("COMMIT TRANSACTION", dbh TSRMLS_CC);
+}
+
+static int dblib_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ return pdo_dblib_transaction_cmd("ROLLBACK TRANSACTION", dbh TSRMLS_CC);
+}
+
+char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
+{
+ pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+
+ RETCODE ret;
+ char *id = NULL;
+
+ /*
+ * Would use scope_identity() but it's not implemented on Sybase
+ */
+
+ if (FAIL == dbcmd(H->link, "SELECT @@IDENTITY")) {
+ return NULL;
+ }
+
+ if (FAIL == dbsqlexec(H->link)) {
+ return NULL;
+ }
+
+ ret = dbresults(H->link);
+ if (ret == FAIL || ret == NO_MORE_RESULTS) {
+ dbcancel(H->link);
+ return NULL;
+ }
+
+ ret = dbnextrow(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_ROWS) {
+ dbcancel(H->link);
+ return NULL;
+ }
+
+ if (dbdatlen(H->link, 1) == 0) {
+ dbcancel(H->link);
+ return NULL;
+ }
+
+ id = emalloc(32);
+ *len = dbconvert(NULL, (dbcoltype(H->link, 1)) , (dbdata(H->link, 1)) , (dbdatlen(H->link, 1)), SQLCHAR, id, (DBINT)-1);
+
+ dbcancel(H->link);
+ return id;
+}
+
static struct pdo_dbh_methods dblib_methods = {
dblib_handle_closer,
dblib_handle_preparer,
dblib_handle_doer,
dblib_handle_quoter,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL, /* last insert */
+ dblib_handle_begin, /* begin */
+ dblib_handle_commit, /* commit */
+ dblib_handle_rollback, /* rollback */
+ NULL, /*set attr */
+ dblib_handle_last_id, /* last insert id */
dblib_fetch_error, /* fetch error */
NULL, /* get attr */
NULL, /* check liveness */
+ NULL, /* get driver methods */
+ NULL, /* request shutdown */
+ NULL /* in transaction */
};
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
@@ -232,10 +310,13 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
/* dblib do not return more than this length from text/image */
DBSETOPT(H->link, DBTEXTLIMIT, "2147483647");
-
+
/* limit text/image from network */
DBSETOPT(H->link, DBTEXTSIZE, "2147483647");
+ /* allow double quoted indentifiers */
+ DBSETOPT(H->link, DBQUOTEDIDENT, NULL);
+
if (vars[3].optval && FAIL == dbuse(H->link, vars[3].optval)) {
goto cleanup;
}
@@ -269,6 +350,7 @@ pdo_driver_t pdo_dblib_driver = {
#if PDO_DBLIB_IS_MSSQL
PDO_DRIVER_HEADER(mssql),
#elif defined(PHP_WIN32)
+#define PDO_DBLIB_IS_SYBASE
PDO_DRIVER_HEADER(sybase),
#else
PDO_DRIVER_HEADER(dblib),
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
index 34b051192e..3eacb4c5e2 100644
--- a/ext/pdo_dblib/dblib_stmt.c
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -33,234 +33,152 @@
#include "php_pdo_dblib_int.h"
#include "zend_exceptions.h"
-static void free_rows(pdo_dblib_stmt *S TSRMLS_DC)
+
+/* {{{ pdo_dblib_get_field_name
+ *
+ * Updated for MSSQL 2008 SR2 extended types
+ *
+ */
+static char *pdo_dblib_get_field_name(int type)
{
- int i, j;
-
- for (i = 0; i < S->nrows; i++) {
- for (j = 0; j < S->ncols; j++) {
- pdo_dblib_colval *val = &S->rows[i*S->ncols] + j;
- if (val->data) {
- efree(val->data);
- val->data = NULL;
- }
- }
+ switch (type) {
+ case 34: return "image";
+ case 35: return "text";
+ case 36: return "uniqueidentifier";
+ case 40: return "date";
+ case 41: return "time";
+ case 42: return "datetime2";
+ case 43: return "datetimeoffset";
+ case 48: return "tinyint";
+ case 52: return "smallint";
+ case 56: return "int";
+ case 58: return "smalldatetime";
+ case 59: return "real";
+ case 60: return "money";
+ case 61: return "datetime";
+ case 62: return "float";
+ case 98: return "sql_variant";
+ case 99: return "ntext";
+ case 104: return "bit";
+ case 106: return "decimal";
+ case 108: return "numeric";
+ case 122: return "smallmoney";
+ case 127: return "bigint";
+ case 240: return "geometry";
+ case 165: return "varbinary";
+ case 167: return "varchar";
+ case 173: return "binary";
+ case 175: return "char";
+ case 189: return "timestamp";
+ case 231: return "nvarchar";
+ case 239: return "nchar";
+ case 241: return "xml";
+ default:
+ return "unknown";
+ break;
}
- efree(S->rows);
- S->rows = NULL;
- S->nrows = 0;
+}
+/* }}} */
+
+static int dblib_dblib_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ /* Cancel any pending results */
+ dbcancel(H->link);
+
+ efree(stmt->columns);
+ stmt->columns = NULL;
+
+ return 1;
}
static int pdo_dblib_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
- if (S->rows) {
- free_rows(S TSRMLS_CC);
- }
- if (S->cols) {
- efree(S->cols);
- }
- efree(S);
+ dblib_dblib_stmt_cursor_closer(stmt TSRMLS_CC);
+ efree(S);
+
return 1;
}
-static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
+static int pdo_dblib_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
pdo_dblib_db_handle *H = S->H;
- RETCODE resret, ret;
- int i, j;
- int arows;
- unsigned int size;
+ RETCODE ret;
- dbsetuserdata(H->link, &S->err);
-
- if (S->rows) {
- /* clean them up */
- free_rows(S TSRMLS_CC);
+ ret = dbresults(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_RESULTS) {
+ return 0;
}
+
+ stmt->row_count = DBCOUNT(H->link);
+ stmt->column_count = dbnumcols(H->link);
+
+ return 1;
+}
+static int pdo_dblib_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
+{
+ pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+ RETCODE ret;
+
+ dbsetuserdata(H->link, (BYTE*) &S->err);
+
if (FAIL == dbcmd(H->link, stmt->active_query_string)) {
return 0;
}
+
if (FAIL == dbsqlexec(H->link)) {
return 0;
}
- resret = dbresults(H->link);
- if (resret == FAIL) {
+ ret = pdo_dblib_stmt_next_rowset(stmt TSRMLS_CC);
+
+ if (ret == 0) {
return 0;
}
-
- ret = dbnextrow(H->link);
-
+
stmt->row_count = DBCOUNT(H->link);
-
- if (ret == NO_MORE_ROWS) {
- return 1;
- }
-
- if (!S->cols) {
- S->ncols = dbnumcols(H->link);
-
- if (S->ncols <= 0) {
- return 1;
- }
-
- S->cols = ecalloc(S->ncols, sizeof(pdo_dblib_col));
- stmt->column_count = S->ncols;
+ stmt->column_count = dbnumcols(H->link);
- for (i = 0, j = 0; i < S->ncols; i++) {
- char *tmp = NULL;
-
- S->cols[i].coltype = dbcoltype(H->link, i+1);
- S->cols[i].name = (char*)dbcolname(H->link, i+1);
-
- if (!strlen(S->cols[i].name)) {
- if (j) {
- spprintf(&tmp, 0, "computed%d", j++);
- strlcpy(S->cols[i].name, tmp, strlen(tmp)+1);
- efree(tmp);
- } else {
- S->cols[i].name = "computed";
- j++;
- }
- }
-
- S->cols[i].source = (char*)dbcolsource(H->link, i+1);
- tmp = estrdup(S->cols[i].source ? S->cols[i].source : "");
- S->cols[i].source = tmp;
- efree(tmp);
-
- S->cols[i].maxlen = dbcollen(H->link, i+1);
- }
- }
-
- arows = 100;
- size = S->ncols * sizeof(pdo_dblib_colval);
- S->rows = safe_emalloc(arows, size, 0);
-
- /* let's fetch all the data */
- do {
- if (S->nrows >= arows) {
- arows *= 2;
- S->rows = erealloc(S->rows, arows * size);
- }
- for (i = 0; i < S->ncols; i++) {
- pdo_dblib_colval *val = &S->rows[S->nrows * S->ncols + i];
-
- if (dbdatlen(H->link, i+1) == 0 && dbdata(H->link, i+1) == NULL) {
- val->len = 0;
- val->data = NULL;
- } else {
- switch (S->cols[i].coltype) {
- case SQLCHAR:
- case SQLTEXT:
- case SQLVARBINARY:
- case SQLBINARY:
- case SQLIMAGE:
- val->len = dbdatlen(H->link, i+1);
- val->data = emalloc(val->len + 1);
- memcpy(val->data, dbdata(H->link, i+1), val->len);
- val->data[val->len] = '\0';
- break;
- case SQLMONEY:
- case SQLMONEY4:
- case SQLMONEYN: {
- DBFLT8 money_value;
- dbconvert(NULL, S->cols[i].coltype, dbdata(H->link, i+1), dbdatlen(H->link, i+1), SQLFLT8, (LPBYTE)&money_value, 8);
- val->len = spprintf(&val->data, 0, "%.4f", money_value);
- }
- break;
-#ifdef SQLUNIQUE
- case SQLUNIQUE: {
-#else
- case 36: { /* FreeTDS hack, also used by ext/mssql */
-#endif
- val->len = 36+1;
- val->data = emalloc(val->len + 1);
-
- /* uniqueidentifier is a 16-byte binary number, convert to 32 char hex string */
-#ifdef SQLUNIQUE
- val->len = dbconvert(NULL, SQLUNIQUE, dbdata(H->link, i+1), dbdatlen(H->link, i+1), SQLCHAR, val->data, val->len);
-#else
- val->len = dbconvert(NULL, 36, dbdata(H->link, i+1), dbdatlen(H->link, i+1), SQLCHAR, val->data, val->len);
-#endif
- php_strtoupper(val->data, val->len);
- break;
- }
- default:
- if (dbwillconvert(S->cols[i].coltype, SQLCHAR)) {
- val->len = 32 + (2 * dbdatlen(H->link, i+1));
- val->data = emalloc(val->len);
-
- val->len = dbconvert(NULL, S->cols[i].coltype, dbdata(H->link, i+1),
- dbdatlen(H->link, i+1), SQLCHAR, val->data, val->len);
-
- if (val->len >= 0) {
- val->data[val->len] = '\0';
- }
- } else {
- val->len = 0;
- val->data = NULL;
- }
- }
- }
- }
-
- S->nrows++;
-
- ret = dbnextrow(H->link);
-
- if (ret == BUF_FULL) {
- dbclrbuf(H->link, DBLASTROW(H->link)-1);
- }
- } while (ret != FAIL && ret != NO_MORE_ROWS);
-
- if (resret != NO_MORE_RESULTS) {
- /* there are additional result sets available */
- dbresults(H->link);
- /* cancel pending rows */
- dbcanquery(H->link);
-
- /* TODO: figure out a sane solution */
- }
-
- S->current = -1;
-
- return 1;
+ return 1;
}
static int pdo_dblib_stmt_fetch(pdo_stmt_t *stmt,
enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
{
+
+ RETCODE ret;
+
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
-
- if (!S->rows) {
+ pdo_dblib_db_handle *H = S->H;
+
+ ret = dbnextrow(H->link);
+
+ if (ret == FAIL || ret == NO_MORE_ROWS) {
return 0;
}
- if (++S->current < S->nrows) {
- return 1;
- }
-
- return 0;
+ return 1;
}
static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
struct pdo_column_data *col = &stmt->columns[colno];
-
- if (!S->rows) {
- return 0;
- }
-
- col->maxlen = S->cols[colno].maxlen;
- col->namelen = strlen(S->cols[colno].name);
- col->name = estrdup(S->cols[colno].name);
+
+ col->name = (char*)dbcolname(H->link, colno+1);
+ col->maxlen = dbcollen(H->link, colno+1);
+ col->namelen = strlen(col->name);
col->param_type = PDO_PARAM_STR;
return 1;
@@ -269,11 +187,76 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
unsigned long *len, int *caller_frees TSRMLS_DC)
{
+
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
- pdo_dblib_colval *val = &S->rows[S->current * S->ncols + colno];
+ pdo_dblib_db_handle *H = S->H;
+
+ int coltype;
+ unsigned int tmp_len;
+ char *tmp_ptr = NULL;
+
+ coltype = dbcoltype(H->link, colno+1);
+
+ *len = dbdatlen(H->link, colno+1);
+ *ptr = dbdata(H->link, colno+1);
+
+ if (*len == 0 && *ptr == NULL) {
+ return 1;
+ }
+
+ switch (coltype) {
+ case SQLCHAR:
+ case SQLTEXT:
+ case SQLVARBINARY:
+ case SQLBINARY:
+ case SQLIMAGE:
+ case SQLVARCHAR:
+ tmp_ptr = emalloc(*len + 1);
+ memcpy(tmp_ptr, *ptr, *len);
+ tmp_ptr[*len] = '\0';
+ *ptr = tmp_ptr;
+ break;
+ case SQLMONEY:
+ case SQLMONEY4:
+ case SQLMONEYN: {
+ DBFLT8 money_value;
+ dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
+ *len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
+ *ptr = tmp_ptr;
+ break;
+ }
+#ifdef SQLUNIQUE
+ case SQLUNIQUE: {
+#else
+ case 36: { /* FreeTDS hack, also used by ext/mssql */
+#endif
+ *len = 36+1;
+ tmp_ptr = emalloc(*len + 1);
+
+ /* uniqueidentifier is a 16-byte binary number, convert to 32 char hex string */
+#ifdef SQLUNIQUE
+ *len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
+#else
+ *len = dbconvert(NULL, 36, *ptr, *len, SQLCHAR, tmp_ptr, *len);
+#endif
+ php_strtoupper(tmp_ptr, *len);
+ *ptr = tmp_ptr;
+ break;
+ }
+ default:
+ if (dbwillconvert(coltype, SQLCHAR)) {
+ tmp_len = 32 + (2 * (*len));
+ tmp_ptr = emalloc(tmp_len);
+ *len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
+ *ptr = tmp_ptr;
+ } else {
+ *len = 0;
+ *ptr = NULL;
+ }
+ }
+
+ *caller_frees = 1;
- *ptr = val->data;
- *len = val->len;
return 1;
}
@@ -283,18 +266,26 @@ static int pdo_dblib_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
return 1;
}
-static int dblib_dblib_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
+static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
+ pdo_dblib_db_handle *H = S->H;
+
+ array_init(return_value);
- if (S->rows) {
- free_rows(S TSRMLS_CC);
- S->rows = NULL;
- }
+ DBTYPEINFO* dbtypeinfo;
+ dbtypeinfo = dbcoltypeinfo(H->link, colno+1);
+
+ add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
+ add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
+ add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
+ add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1), 1);
+ add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)), 1);
return 1;
}
+
struct pdo_stmt_methods dblib_stmt_methods = {
pdo_dblib_stmt_dtor,
pdo_dblib_stmt_execute,
@@ -304,8 +295,8 @@ struct pdo_stmt_methods dblib_stmt_methods = {
pdo_dblib_stmt_param_hook,
NULL, /* set attr */
NULL, /* get attr */
- NULL, /* meta */
- NULL, /* nextrow */
+ pdo_dblib_stmt_get_column_meta, /* meta */
+ pdo_dblib_stmt_next_rowset, /* nextrow */
dblib_dblib_stmt_cursor_closer
};
diff --git a/ext/pdo_dblib/php_pdo_dblib_int.h b/ext/pdo_dblib/php_pdo_dblib_int.h
index b839cb60f8..48d0eb318d 100644
--- a/ext/pdo_dblib/php_pdo_dblib_int.h
+++ b/ext/pdo_dblib/php_pdo_dblib_int.h
@@ -114,28 +114,7 @@ typedef struct {
} pdo_dblib_db_handle;
typedef struct {
- int coltype;
- char *name;
- int maxlen;
- char *source;
-} pdo_dblib_col;
-
-typedef struct {
- unsigned long len;
- char *data;
-} pdo_dblib_colval;
-
-typedef struct {
pdo_dblib_db_handle *H;
-
- int ncols;
- pdo_dblib_col *cols;
-
- pdo_dblib_colval *rows;
- int nrows;
-
- int current;
-
pdo_dblib_err err;
} pdo_dblib_stmt;
diff --git a/ext/pdo_dblib/tests/bug_38955.phpt b/ext/pdo_dblib/tests/bug_38955.phpt
new file mode 100644
index 0000000000..1954ed460b
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_38955.phpt
@@ -0,0 +1,57 @@
+--TEST--
+ PDO_DBLIB driver does not support transactions
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+/*We see these rows */
+$db->query("CREATE table php_test(val int)");
+$db->beginTransaction();
+$db->query("INSERT INTO php_test(val) values(1)");
+$db->query("INSERT INTO php_test(val) values(2)");
+$db->query("INSERT INTO php_test(val) values(3)");
+$db->query("INSERT INTO php_test(val) values(4)");
+$db->commit();
+
+/*We don't see these rows */
+$db->beginTransaction();
+$db->query("INSERT INTO php_test(val) values(5)");
+$db->query("INSERT INTO php_test(val) values(6)");
+$db->query("INSERT INTO php_test(val) values(7)");
+$db->query("INSERT INTO php_test(val) values(8)");
+$db->rollback();
+
+$rs = $db->query("SELECT * FROM php_test");
+$rows = $rs->fetchAll(PDO::FETCH_ASSOC);
+var_dump($rows);
+
+$db->query("DROP table php_test");
+?>
+--EXPECT--
+array(4) {
+ [0]=>
+ array(1) {
+ ["val"]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(1) {
+ ["val"]=>
+ string(1) "2"
+ }
+ [2]=>
+ array(1) {
+ ["val"]=>
+ string(1) "3"
+ }
+ [3]=>
+ array(1) {
+ ["val"]=>
+ string(1) "4"
+ }
+}
diff --git a/ext/pdo_dblib/tests/bug_45876.phpt b/ext/pdo_dblib/tests/bug_45876.phpt
new file mode 100644
index 0000000000..920905830a
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_45876.phpt
@@ -0,0 +1,35 @@
+--TEST--
+PDO_DBLIB: Does not support get column meta
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$stmt = $db->prepare("select ic1.* from information_schema.columns ic1");
+$stmt->execute();
+var_dump($stmt->getColumnMeta(0));
+$stmt = null;
+?>
+--EXPECT--
+array(8) {
+ ["max_length"]=>
+ int(255)
+ ["precision"]=>
+ int(0)
+ ["scale"]=>
+ int(0)
+ ["column_source"]=>
+ string(13) "TABLE_CATALOG"
+ ["native_type"]=>
+ string(4) "char"
+ ["name"]=>
+ string(13) "TABLE_CATALOG"
+ ["len"]=>
+ int(255)
+ ["pdo_type"]=>
+ int(2)
+}
diff --git a/ext/pdo_dblib/tests/bug_47588.phpt b/ext/pdo_dblib/tests/bug_47588.phpt
new file mode 100644
index 0000000000..d8f424e872
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_47588.phpt
@@ -0,0 +1,45 @@
+--TEST--
+PDO_DBLIB: Quoted field names
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$db->query('CREATE TABLE "Test Table" ("My Field" int, "Another Field" varchar(32) not null default \'test_string\')');
+$db->query('INSERT INTO "Test Table" ("My Field") values(1)');
+$db->query('INSERT INTO "Test Table" ("My Field") values(2)');
+$db->query('INSERT INTO "Test Table" ("My Field") values(3)');
+$rs = $db->query('SELECT * FROM "Test Table"');
+var_dump($rs->fetchAll(PDO::FETCH_ASSOC));
+$db->query('DROP TABLE "Test Table"');
+echo "Done.\n";
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ array(2) {
+ ["My Field"]=>
+ string(1) "1"
+ ["Another Field"]=>
+ string(11) "test_string"
+ }
+ [1]=>
+ array(2) {
+ ["My Field"]=>
+ string(1) "2"
+ ["Another Field"]=>
+ string(11) "test_string"
+ }
+ [2]=>
+ array(2) {
+ ["My Field"]=>
+ string(1) "3"
+ ["Another Field"]=>
+ string(11) "test_string"
+ }
+}
+Done.
diff --git a/ext/pdo_dblib/tests/bug_50755.phpt b/ext/pdo_dblib/tests/bug_50755.phpt
new file mode 100644
index 0000000000..95d1a8bc70
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_50755.phpt
@@ -0,0 +1,29 @@
+--TEST--
+PDO_DBLIB: Out of memory on large recordsets
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+/* This should be sufficient to overflow any buffers */
+$stmt = $db->prepare("select *
+from information_schema.columns ic1
+cross join information_schema.columns ic2
+cross join information_schema.columns ic3");
+
+$x = $stmt->execute();
+$n = 0;
+while (($r = $stmt->fetch())) {
+ $n++;
+}
+$stmt = null;
+
+echo "OK\n";
+
+?>
+--EXPECT--
+OK
diff --git a/ext/pdo_dblib/tests/config.inc b/ext/pdo_dblib/tests/config.inc
new file mode 100644
index 0000000000..5b7b4d4327
--- /dev/null
+++ b/ext/pdo_dblib/tests/config.inc
@@ -0,0 +1,26 @@
+<?php
+
+if (false !== getenv('PDO_DBLIB_TEST_DSN'))
+ $dsn = getenv('PDO_DBLIB_TEST_DSN');
+else
+ $dsn = 'dblib:host=localhost;dbname=test';
+
+if (false !== getenv('PDO_DBLIB_TEST_USER'))
+ $user = getenv('PDO_DBLIB_TEST_USER');
+else
+ $user = 'php';
+
+
+if (false !== getenv('PDO_DBLIB_TEST_PASS'))
+ $pass = getenv('PDO_DBLIB_TEST_PASS');
+else
+ $pass = 'password';
+
+try {
+ $db = new PDO($dsn, $user, $pass);
+ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+} catch (PDOException $e) {
+ die('skip ' . $e->getMessage());
+}
+?>
diff --git a/ext/pdo_firebird/EXPERIMENTAL b/ext/pdo_firebird/EXPERIMENTAL
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/pdo_firebird/EXPERIMENTAL
+++ /dev/null
diff --git a/ext/pdo_firebird/config.m4 b/ext/pdo_firebird/config.m4
index 94704d3adb..7b6f669a50 100644
--- a/ext/pdo_firebird/config.m4
+++ b/ext/pdo_firebird/config.m4
@@ -50,7 +50,7 @@ if test "$PHP_PDO_FIREBIRD" != "no"; then
PHP_ADD_LIBRARY_WITH_PATH($FIREBIRD_LIBNAME, $FIREBIRD_LIBDIR, PDO_FIREBIRD_SHARED_LIBADD)
PHP_ADD_INCLUDE($FIREBIRD_INCDIR)
AC_DEFINE(HAVE_PDO_FIREBIRD,1,[ ])
- PHP_NEW_EXTENSION(pdo_firebird, pdo_firebird.c firebird_driver.c firebird_statement.c, $ext_shared,,-I$pdo_inc_path)
+ PHP_NEW_EXTENSION(pdo_firebird, pdo_firebird.c firebird_driver.c firebird_statement.c, $ext_shared,,-I$pdo_cv_inc_path)
PHP_SUBST(PDO_FIREBIRD_SHARED_LIBADD)
PHP_ADD_EXTENSION_DEP(pdo_firebird, pdo)
fi
diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
index e39555fb97..9b0f596959 100644
--- a/ext/pdo_firebird/firebird_driver.c
+++ b/ext/pdo_firebird/firebird_driver.c
@@ -401,7 +401,7 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const char *sql, long sql
long l, pindex = -1;
/* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */
- if (sql_len > SHORT_MAX) {
+ if (sql_len > 65536) {
strcpy(dbh->error_code, "01004");
return 0;
}
diff --git a/ext/pdo_firebird/tests/bug_47415.phpt b/ext/pdo_firebird/tests/bug_47415.phpt
index cedc2c45b2..12cd782f26 100644
--- a/ext/pdo_firebird/tests/bug_47415.phpt
+++ b/ext/pdo_firebird/tests/bug_47415.phpt
@@ -2,6 +2,7 @@
Bug #47415 PDO_Firebird segfaults when passing lowercased column name to bindColumn()
--SKIPIF--
<?php extension_loaded("pdo_firebird") or die("skip"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--FILE--
<?php
diff --git a/ext/pdo_firebird/tests/bug_48877.phpt b/ext/pdo_firebird/tests/bug_48877.phpt
index 290cd7a3a0..cbab84b372 100644
--- a/ext/pdo_firebird/tests/bug_48877.phpt
+++ b/ext/pdo_firebird/tests/bug_48877.phpt
@@ -2,6 +2,7 @@
PDO_Firebird: bug 48877 The "bindValue" and "bindParam" do not work for PDO Firebird if we use named parameters (:parameter).
--SKIPIF--
<?php extension_loaded("pdo_firebird") or die("skip"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--FILE--
<?php
diff --git a/ext/pdo_firebird/tests/bug_53280.phpt b/ext/pdo_firebird/tests/bug_53280.phpt
index 1be4e8a826..3139867af1 100644
--- a/ext/pdo_firebird/tests/bug_53280.phpt
+++ b/ext/pdo_firebird/tests/bug_53280.phpt
@@ -2,6 +2,7 @@
PDO_Firebird: bug 53280 segfaults if query column count is less than param count
--SKIPIF--
<?php extension_loaded("pdo_firebird") or die("skip"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--FILE--
<?php
diff --git a/ext/pdo_firebird/tests/connect.phpt b/ext/pdo_firebird/tests/connect.phpt
index e4bb8ef54e..cbe76e6865 100644
--- a/ext/pdo_firebird/tests/connect.phpt
+++ b/ext/pdo_firebird/tests/connect.phpt
@@ -2,6 +2,7 @@
PDO_Firebird: connect/disconnect
--SKIPIF--
<?php include("skipif.inc"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--FILE--
<?php /* $Id$ */
diff --git a/ext/pdo_firebird/tests/ddl.phpt b/ext/pdo_firebird/tests/ddl.phpt
index 9a3ddd1002..9d2a0953ec 100644
--- a/ext/pdo_firebird/tests/ddl.phpt
+++ b/ext/pdo_firebird/tests/ddl.phpt
@@ -2,6 +2,7 @@
PDO_Firebird: DDL/transactions
--SKIPIF--
<?php include("skipif.inc"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--FILE--
<?php /* $Id$ */
diff --git a/ext/pdo_firebird/tests/execute.phpt b/ext/pdo_firebird/tests/execute.phpt
index 3a759fc51b..896347e935 100644
--- a/ext/pdo_firebird/tests/execute.phpt
+++ b/ext/pdo_firebird/tests/execute.phpt
@@ -2,6 +2,7 @@
PDO_Firebird: prepare/execute/binding
--SKIPIF--
<?php include("skipif.inc"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--INI--
ibase.timestampformat=%Y-%m-%d %H:%M:%S
--FILE--
diff --git a/ext/pdo_firebird/tests/rowCount.phpt b/ext/pdo_firebird/tests/rowCount.phpt
index 3d7f71c83b..1a009508e0 100644
--- a/ext/pdo_firebird/tests/rowCount.phpt
+++ b/ext/pdo_firebird/tests/rowCount.phpt
@@ -2,6 +2,7 @@
PDO_Firebird: rowCount
--SKIPIF--
<?php extension_loaded("pdo_firebird") or die("skip"); ?>
+<?php function_exists("ibase_query") or die("skip"); ?>
--FILE--
<?php /* $Id$ */
diff --git a/ext/pdo_mysql/config.m4 b/ext/pdo_mysql/config.m4
index d4c3745327..a2ba2fdbdd 100755
--- a/ext/pdo_mysql/config.m4
+++ b/ext/pdo_mysql/config.m4
@@ -4,8 +4,8 @@ dnl vim: se ts=2 sw=2 et:
PHP_ARG_WITH(pdo-mysql, for MySQL support for PDO,
[ --with-pdo-mysql[=DIR] PDO: MySQL support. DIR is the MySQL base directory
- If mysqlnd is passed as DIR, the MySQL native
- native driver will be used [/usr/local]])
+ If no value or mysqlnd is passed as DIR, the
+ MySQL native driver will be used])
if test -z "$PHP_ZLIB_DIR"; then
PHP_ARG_WITH(zlib-dir, for the location of libz,
@@ -28,30 +28,21 @@ if test "$PHP_PDO_MYSQL" != "no"; then
done
])
- if test -f $PHP_PDO_MYSQL && test -x $PHP_PDO_MYSQL ; then
- PDO_MYSQL_CONFIG=$PHP_PDO_MYSQL
- elif test "$PHP_PDO_MYSQL" != "yes"; then
- if test -d "$PHP_PDO_MYSQL" ; then
- if test -x "$PHP_PDO_MYSQL/bin/mysql_config" ; then
- PDO_MYSQL_CONFIG="$PHP_PDO_MYSQL/bin/mysql_config"
- else
- PDO_MYSQL_DIR="$PHP_PDO_MYSQL"
+ if test "$PHP_PDO_MYSQL" != "yes" && test "$PHP_PDO_MYSQL" != "mysqlnd"; then
+ if test -f $PHP_PDO_MYSQL && test -x $PHP_PDO_MYSQL ; then
+ PDO_MYSQL_CONFIG=$PHP_PDO_MYSQL
+ else
+ if test -d "$PHP_PDO_MYSQL" ; then
+ if test -x "$PHP_PDO_MYSQL/bin/mysql_config" ; then
+ PDO_MYSQL_CONFIG="$PHP_PDO_MYSQL/bin/mysql_config"
+ else
+ PDO_MYSQL_DIR="$PHP_PDO_MYSQL"
+ fi
fi
fi
- else
- for i in /usr/local /usr ; do
- if test -x "$i/bin/mysql_config" ; then
- PDO_MYSQL_CONFIG="$i/bin/mysql_config"
- break;
- fi
- if test -r $i/include/mysql/mysql.h || test -r $i/include/mysql.h ; then
- PDO_MYSQL_DIR="$i"
- break;
- fi
- done
fi
-
- if test "$PHP_PDO_MYSQL" = "mysqlnd"; then
+
+ if test "$PHP_PDO_MYSQL" = "yes" || test "$PHP_PDO_MYSQL" = "mysqlnd"; then
dnl enables build of mysqnd library
PHP_MYSQLND_ENABLED=yes
AC_DEFINE([PDO_USE_MYSQLND], 1, [Whether pdo_mysql uses mysqlnd])
@@ -100,15 +91,15 @@ if test "$PHP_PDO_MYSQL" != "no"; then
AC_MSG_ERROR([Unable to find your mysql installation])
fi
- PHP_CHECK_LIBRARY($PDO_MYSQL_LIBNAME, mysql_query,
+ PHP_CHECK_LIBRARY($PDO_MYSQL_LIBNAME, mysql_commit,
[
PHP_EVAL_INCLINE($PDO_MYSQL_INCLUDE)
PHP_EVAL_LIBLINE($PDO_MYSQL_LIBS, PDO_MYSQL_SHARED_LIBADD)
],[
if test "$PHP_ZLIB_DIR" != "no"; then
PHP_ADD_LIBRARY_WITH_PATH(z, $PHP_ZLIB_DIR, PDO_MYSQL_SHARED_LIBADD)
- PHP_CHECK_LIBRARY($PDO_MYSQL_LIBNAME, mysql_query, [], [
- AC_MSG_ERROR([PDO_MYSQL configure failed. Please check config.log for more information.])
+ PHP_CHECK_LIBRARY($PDO_MYSQL_LIBNAME, mysql_commit, [], [
+ AC_MSG_ERROR([PDO_MYSQL configure failed, MySQL 4.1 needed. Please check config.log for more information.])
], [
-L$PHP_ZLIB_DIR/$PHP_LIBDIR -L$PDO_MYSQL_LIB_DIR
])
@@ -128,11 +119,6 @@ if test "$PHP_PDO_MYSQL" != "no"; then
],[
$PDO_MYSQL_LIBS
])
-
- _SAVE_LIBS=$LIBS
- LIBS="$LIBS $PDO_MYSQL_LIBS"
- AC_CHECK_FUNCS([mysql_commit mysql_stmt_prepare mysql_next_result mysql_sqlstate])
- LIBS=$_SAVE_LIBS
fi
ifdef([PHP_CHECK_PDO_INCLUDES],
@@ -141,15 +127,15 @@ if test "$PHP_PDO_MYSQL" != "no"; then
],[
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
- AC_MSG_RESULT($pdo_inc_path)
+ AC_MSG_RESULT($pdo_cv_inc_path)
])
if test -n "$PDO_MYSQL_CONFIG"; then
@@ -158,7 +144,7 @@ if test "$PHP_PDO_MYSQL" != "no"; then
fi
dnl fix after renaming to pdo_mysql
- PHP_NEW_EXTENSION(pdo_mysql, pdo_mysql.c mysql_driver.c mysql_statement.c, $ext_shared,,-I$pdo_inc_path -I)
+ PHP_NEW_EXTENSION(pdo_mysql, pdo_mysql.c mysql_driver.c mysql_statement.c, $ext_shared,,-I$pdo_cv_inc_path -I)
ifdef([PHP_ADD_EXTENSION_DEP],
[
PHP_ADD_EXTENSION_DEP(pdo_mysql, pdo)
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c
index 727357a03a..5cf35b1680 100644
--- a/ext/pdo_mysql/mysql_driver.c
+++ b/ext/pdo_mysql/mysql_driver.c
@@ -36,23 +36,12 @@
#endif
#include "zend_exceptions.h"
-#if PDO_USE_MYSQLND
+#if defined(PDO_USE_MYSQLND)
# define pdo_mysql_init(persistent) mysqlnd_init(persistent)
#else
# define pdo_mysql_init(persistent) mysql_init(NULL)
#endif
-#if !defined(HAVE_MYSQL_SQLSTATE) && !defined(PDO_USE_MYSQLND)
-static const char *pdo_mysql_get_sqlstate(unsigned int my_errno) { /* {{{ */
- switch (my_errno) {
- /* import auto-generated case: code */
-#include "php_pdo_mysql_sqlstate.h"
- default: return "HY000";
- }
-}
-/* }}} */
-#endif
-
/* {{{ _pdo_mysql_error */
int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC)
{
@@ -72,13 +61,9 @@ int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int lin
einfo = &H->einfo;
}
-#if defined(HAVE_MYSQL_STMT_PREPARE) || defined(PDO_USE_MYSQLND)
if (S && S->stmt) {
einfo->errcode = mysql_stmt_errno(S->stmt);
- }
- else
-#endif
- {
+ } else {
einfo->errcode = mysql_errno(H->server);
}
@@ -112,18 +97,11 @@ int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int lin
PDO_DBG_RETURN(0);
}
-#if defined(HAVE_MYSQL_SQLSTATE) || defined(PDO_USE_MYSQLND)
-# if defined(HAVE_MYSQL_STMT_PREPARE) || defined(PDO_USE_MYSQLND)
if (S && S->stmt) {
strcpy(*pdo_err, mysql_stmt_sqlstate(S->stmt));
- } else
-# endif
- {
+ } else {
strcpy(*pdo_err, mysql_sqlstate(H->server));
}
-#else
- strcpy(*pdo_err, pdo_mysql_get_sqlstate(einfo->errcode));
-#endif
if (!dbh->methods) {
PDO_DBG_INF("Throwing exception");
@@ -187,12 +165,10 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
{
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt));
-#if defined(HAVE_MYSQL_STMT_PREPARE) || defined(PDO_USE_MYSQLND)
char *nsql = NULL;
int nsql_len = 0;
int ret;
int server_version;
-#endif
PDO_DBG_ENTER("mysql_handle_preparer");
PDO_DBG_INF_FMT("dbh=%p", dbh);
@@ -206,7 +182,6 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
goto end;
}
-#if defined(HAVE_MYSQL_STMT_PREPARE) || defined(PDO_USE_MYSQLND)
server_version = mysql_get_server_version(H->server);
if (server_version < 40100) {
goto fallback;
@@ -255,7 +230,7 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
if (S->num_params) {
S->params_given = 0;
-#ifdef PDO_USE_MYSQLND
+#if defined(PDO_USE_MYSQLND)
S->params = NULL;
#else
S->params = ecalloc(S->num_params, sizeof(MYSQL_BIND));
@@ -270,7 +245,6 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
PDO_DBG_RETURN(1);
fallback:
-#endif
end:
stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
@@ -296,7 +270,6 @@ static long mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRM
PDO_DBG_RETURN(H->einfo.errcode ? -1 : 0);
} else {
-#if defined(HAVE_MYSQL_NEXT_RESULT) || defined(PDO_USE_MYSQLND)
/* MULTI_QUERY support - eat up all unfetched result sets */
MYSQL_RES* result;
while (mysql_more_results(H->server)) {
@@ -308,7 +281,6 @@ static long mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRM
mysql_free_result(result);
}
}
-#endif
PDO_DBG_RETURN((int)c);
}
}
@@ -324,7 +296,7 @@ static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned
*len = strlen(id);
PDO_DBG_RETURN(id);
}
-/* }}} */
+/* }}} */
/* {{{ mysql_handle_quoter */
static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
@@ -463,7 +435,7 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value
break;
case PDO_ATTR_SERVER_INFO: {
char *tmp;
-#ifdef PDO_USE_MYSQLND
+#if defined(PDO_USE_MYSQLND)
unsigned int tmp_len;
if (mysqlnd_stat(H->server, &tmp, &tmp_len) == PASS) {
@@ -584,7 +556,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
#endif
;
-#ifdef PDO_USE_MYSQLND
+#if defined(PDO_USE_MYSQLND)
int dbname_len = 0;
int password_len = 0;
#endif
@@ -626,9 +598,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
char *default_file = NULL, *default_group = NULL;
#endif
long compress = 0;
-#if defined(HAVE_MYSQL_STMT_PREPARE) || defined(PDO_USE_MYSQLND)
char *ssl_key = NULL, *ssl_cert = NULL, *ssl_ca = NULL, *ssl_capath = NULL, *ssl_cipher = NULL;
-#endif
H->buffered = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_USE_BUFFERED_QUERY, 1 TSRMLS_CC);
H->emulate_prepare = pdo_attr_lval(driver_options,
@@ -714,7 +684,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
goto cleanup;
}
}
-#if defined(HAVE_MYSQL_STMT_PREPARE) || defined(PDO_USE_MYSQLND)
+
ssl_key = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_KEY, NULL TSRMLS_CC);
ssl_cert = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_CERT, NULL TSRMLS_CC);
ssl_ca = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_CA, NULL TSRMLS_CC);
@@ -739,7 +709,6 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
efree(ssl_cipher);
}
}
-#endif
}
#ifdef PDO_MYSQL_HAS_CHARSET
diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c
index 9884c85ae3..7bfbef015c 100644
--- a/ext/pdo_mysql/mysql_statement.c
+++ b/ext/pdo_mysql/mysql_statement.c
@@ -59,12 +59,10 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
pefree(S->einfo.errmsg, stmt->dbh->is_persistent);
S->einfo.errmsg = NULL;
}
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
if (S->stmt) {
pdo_mysql_stmt_close(S->stmt);
S->stmt = NULL;
}
-#endif /* HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND */
#ifndef PDO_USE_MYSQLND
if (S->params) {
@@ -77,9 +75,6 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
efree(S->in_length);
}
-#endif /* PDO_USE_MYSQLND */
-
-#ifdef HAVE_MYSQL_STMT_PREPARE
if (S->bound_result)
{
int i;
@@ -91,10 +86,9 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
efree(S->out_null);
efree(S->out_length);
}
-#endif /* HAVE_MYSQL_STMT_PREPARE */
+#endif
-#if HAVE_MYSQL_NEXT_RESULT || PDO_USE_MYSQLND
if (S->H->server) {
while (mysql_more_results(S->H->server)) {
MYSQL_RES *res;
@@ -108,7 +102,7 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
}
}
}
-#endif /* HAVE_MYSQL_NEXT_RESULT || PDO_USE_MYSQLND */
+
#if PDO_USE_MYSQLND
if (!S->stmt && S->current_data) {
mnd_free(S->current_data);
@@ -140,7 +134,7 @@ static int pdo_mysql_fill_stmt_from_result(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
row_count = mysql_affected_rows(H->server);
if (row_count == (my_ulonglong)-1) {
- /* we either have a query that returned a result set or an error occured
+ /* we either have a query that returned a result set or an error occurred
lets see if we have access to a result set */
if (!H->buffered) {
S->result = mysql_use_result(H->server);
@@ -164,7 +158,7 @@ static int pdo_mysql_fill_stmt_from_result(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
}
/* }}} */
-#ifdef HAVE_MYSQL_STMT_PREPARE
+#ifndef PDO_USE_MYSQLND
static int pdo_mysql_stmt_execute_prepared_libmysql(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
{
pdo_mysql_stmt *S = stmt->driver_data;
@@ -325,11 +319,9 @@ static int pdo_mysql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
PDO_DBG_ENTER("pdo_mysql_stmt_execute");
PDO_DBG_INF_FMT("stmt=%p", S->stmt);
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
if (S->stmt) {
PDO_DBG_RETURN(pdo_mysql_stmt_execute_prepared(stmt));
}
-#endif
/* ensure that we free any previous unfetched results */
if (S->result) {
@@ -348,7 +340,6 @@ static int pdo_mysql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
{
-#if HAVE_MYSQL_NEXT_RESULT || PDO_USE_MYSQLND
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
pdo_mysql_db_handle *H = S->H;
long row_count;
@@ -410,7 +401,7 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
#endif
/* ensure that we free any previous unfetched results */
-#if HAVE_MYSQL_STMT_PREPARE
+#ifndef PDO_USE_MYSQLND
if (S->stmt) {
stmt->column_count = (int)mysql_num_fields(S->result);
mysql_stmt_free_result(S->stmt);
@@ -445,11 +436,6 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
PDO_DBG_RETURN(pdo_mysql_fill_stmt_from_result(stmt TSRMLS_CC));
}
#endif
-
-#else
- strcpy(stmt->error_code, "HYC00");
- PDO_DBG_RETURN(0);
-#endif /* HAVE_MYSQL_STMT_PREPARE */
}
/* }}} */
@@ -471,7 +457,6 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
#ifndef PDO_USE_MYSQLND
PDO_MYSQL_PARAM_BIND *b;
#endif
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
PDO_DBG_ENTER("pdo_mysql_stmt_param_hook");
@@ -603,7 +588,7 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
break;
}
}
-#endif /* HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND */
+
PDO_DBG_RETURN(1);
}
/* }}} */
@@ -624,7 +609,6 @@ static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori
PDO_DBG_RETURN(1);
}
#else
-# if HAVE_MYSQL_STMT_PREPARE
int ret;
if (S->stmt) {
@@ -645,7 +629,6 @@ static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori
PDO_DBG_RETURN(1);
}
-# endif /* HAVE_MYSQL_STMT_PREPARE */
#endif /* PDO_USE_MYSQLND */
if (!S->result) {
@@ -736,15 +719,12 @@ static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsig
}
/* With mysqlnd data is stored inside mysqlnd, not S->current_data */
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
if (!S->stmt) {
-#endif
if (S->current_data == NULL || !S->result) {
PDO_DBG_RETURN(0);
}
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
}
-#endif
+
if (colno >= stmt->column_count) {
/* error invalid column */
PDO_DBG_RETURN(0);
@@ -756,7 +736,7 @@ static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsig
*len = sizeof(zval);
PDO_DBG_RETURN(1);
}
-#elif HAVE_MYSQL_STMT_PREPARE
+#else
if (S->stmt) {
if (S->out_null[colno]) {
*ptr = NULL;
@@ -774,7 +754,7 @@ static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsig
*len = S->out_length[colno];
PDO_DBG_RETURN(1);
}
-#endif /* PDO_USE_MYSQLND else HAVE_MYSQL_STMT_PREPARE */
+#endif
*ptr = S->current_data[colno];
*len = S->current_lengths[colno];
PDO_DBG_RETURN(1);
@@ -892,7 +872,7 @@ static int pdo_mysql_stmt_col_meta(pdo_stmt_t *stmt, long colno, zval *return_va
#endif
add_assoc_zval(return_value, "flags", flags);
- add_assoc_string(return_value, "table",(char *) (F->table?F->table:""), 1);
+ add_assoc_string(return_value, "table", (char *) (F->table?F->table:""), 1);
PDO_DBG_RETURN(SUCCESS);
} /* }}} */
@@ -906,15 +886,12 @@ static int pdo_mysql_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
mysql_free_result(S->result);
S->result = NULL;
}
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
if (S->stmt) {
int retval;
retval = mysql_stmt_free_result(S->stmt);
PDO_DBG_RETURN(retval ? 0 : 1);
}
-#endif
-#if HAVE_MYSQL_NEXT_RESULT || PDO_USE_MYSQLND
while (mysql_more_results(S->H->server)) {
MYSQL_RES *res;
if (mysql_next_result(S->H->server) != 0) {
@@ -925,7 +902,6 @@ static int pdo_mysql_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
mysql_free_result(res);
}
}
-#endif
PDO_DBG_RETURN(1);
}
/* }}} */
diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c
index e8e215fa39..ea69c3c11b 100644
--- a/ext/pdo_mysql/pdo_mysql.c
+++ b/ext/pdo_mysql/pdo_mysql.c
@@ -57,6 +57,30 @@ ZEND_DECLARE_MODULE_GLOBALS(pdo_mysql)
# endif
#endif
+#ifdef PDO_USE_MYSQLND
+#include "ext/mysqlnd/mysqlnd_reverse_api.h"
+static MYSQLND * pdo_mysql_convert_zv_to_mysqlnd(zval * zv TSRMLS_DC)
+{
+ if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) == php_pdo_get_dbh_ce()) {
+ pdo_dbh_t * dbh = zend_object_store_get_object(zv TSRMLS_CC);
+
+ if (!dbh || dbh->driver != &pdo_mysql_driver) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Provided PDO instance is not using MySQL but %s", dbh->driver->driver_name);
+ return NULL;
+ }
+
+ return ((pdo_mysql_db_handle *)dbh->driver_data)->server;
+ }
+ return NULL;
+}
+
+static MYSQLND_REVERSE_API pdo_mysql_reverse_api = {
+ &pdo_mysql_module_entry,
+ pdo_mysql_convert_zv_to_mysqlnd
+};
+#endif
+
+
/* {{{ PHP_INI_BEGIN
*/
PHP_INI_BEGIN()
@@ -94,6 +118,11 @@ static PHP_MINIT_FUNCTION(pdo_mysql)
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CA", (long)PDO_MYSQL_ATTR_SSL_CA);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CAPATH", (long)PDO_MYSQL_ATTR_SSL_CAPATH);
REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CIPHER", (long)PDO_MYSQL_ATTR_SSL_CIPHER);
+
+#ifdef PDO_USE_MYSQLND
+ mysqlnd_reverse_api_register_api(&pdo_mysql_reverse_api TSRMLS_CC);
+#endif
+
return php_pdo_register_driver(&pdo_mysql_driver);
}
/* }}} */
diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h
index f8caa9f6eb..0b6d7752d3 100644
--- a/ext/pdo_mysql/php_pdo_mysql_int.h
+++ b/ext/pdo_mysql/php_pdo_mysql_int.h
@@ -127,7 +127,6 @@ typedef struct {
long *current_lengths;
#endif
pdo_mysql_error_info einfo;
-#if HAVE_MYSQL_STMT_PREPARE || PDO_USE_MYSQLND
#if PDO_USE_MYSQLND
MYSQLND_STMT *stmt;
#else
@@ -144,7 +143,6 @@ typedef struct {
unsigned long *out_length;
unsigned int params_given;
unsigned max_length:1;
-#endif
} pdo_mysql_stmt;
extern pdo_driver_t pdo_mysql_driver;
diff --git a/ext/pdo_mysql/tests/bug_61207.phpt b/ext/pdo_mysql/tests/bug_61207.phpt
index 917b322180..411b39a70b 100644
--- a/ext/pdo_mysql/tests/bug_61207.phpt
+++ b/ext/pdo_mysql/tests/bug_61207.phpt
@@ -2,27 +2,27 @@
PDO MySQL Bug #61207 (PDO::nextRowset() after a multi-statement query doesn't always work)
--SKIPIF--
<?php
-if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) die('skip not loaded');
-require dirname(__FILE__) . '/config.inc';
-require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
-PDOTest::skip();
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+
?>
--FILE--
<?php
-require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+$db = MySQLPDOTest::factory();
-$link = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->query('DROP TABLE IF EXISTS test');
+$db->query('create table `test`( `id` int )');
-$link->query('create table `bug61207`( `id` int )');
+$handle1 = $db->prepare('insert into test(id) values(1);
+ select * from test where id = ?;
+ update test set id = 2 where id = ?;');
-$handle1 = $link->prepare('insert into bug61207(id) values(1);
- select * from bug61207 where id = ?;
- update bug61207 set id = 2 where id = ?;');
-
$handle1->bindValue('1', '1');
$handle1->bindValue('2', '1');
-
-$handle1->execute();
+
+$handle1->execute();
$i = 1;
print("Handle 1:\n");
do {
@@ -31,9 +31,9 @@ do {
print("Results detected\n");
} while($handle1->nextRowset());
-$handle2 = $link->prepare('select * from bug61207 where id = ?;
- update bug61207 set id = 1 where id = ?;');
-
+$handle2 = $db->prepare('select * from test where id = ?;
+ update test set id = 1 where id = ?;');
+
$handle2->bindValue('1', '2');
$handle2->bindValue('2', '2');
@@ -47,9 +47,9 @@ do {
print("Results detected\n");
} while($handle2->nextRowset());
-$handle3 = $link->prepare('update bug61207 set id = 2 where id = ?;
- select * from bug61207 where id = ?;');
-
+$handle3 = $db->prepare('update test set id = 2 where id = ?;
+ select * from test where id = ?;');
+
$handle3->bindValue('1', '1');
$handle3->bindValue('2', '2');
@@ -63,15 +63,15 @@ do {
print("Results detected\n");
} while($handle3->nextRowset());
-$handle4 = $link->prepare('insert into bug61207(id) values(3);
- update bug61207 set id = 2 where id = ?;
- select * from bug61207 where id = ?;');
-
+$handle4 = $db->prepare('insert into test(id) values(3);
+ update test set id = 2 where id = ?;
+ select * from test where id = ?;');
+
$handle4->bindValue('1', '3');
$handle4->bindValue('2', '2');
-
+
$handle4->execute();
-
+
$i = 1;
print("Handle 4:\n");
do {
@@ -80,7 +80,12 @@ do {
print("Results detected\n");
} while($handle1->nextRowset());
-$link->query("DROP TABLE bug61207");
+$db->query("DROP TABLE test");
+?>
+--CLEAN--
+<?php
+require dirname(__FILE__) . '/mysql_pdo_test.inc';
+MySQLPDOTest::dropTestTable();
?>
--EXPECT--
Handle 1:
diff --git a/ext/pdo_mysql/tests/common.phpt b/ext/pdo_mysql/tests/common.phpt
index 8179454cf7..f55d1f883b 100644
--- a/ext/pdo_mysql/tests/common.phpt
+++ b/ext/pdo_mysql/tests/common.phpt
@@ -8,7 +8,7 @@ if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) print 'skip not
# magic auto-configuration
$config = array(
- 'TESTS' => 'ext/pdo/tests'
+ 'TESTS' => __DIR__.'/ext/pdo/tests'
);
if (false !== getenv('PDO_MYSQL_TEST_DSN')) {
diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt
index 9092004fe5..c3f12df7a9 100644
--- a/ext/pdo_mysql/tests/pdo_mysql___construct.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql___construct.phpt
@@ -297,4 +297,4 @@ MySQLPDOTest::skip();
[009] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a
[010] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a
[017] DSN=%s, SQLSTATE[%s] [%d] %s
-[033] DSN = mysql:%s, character sets has not been set, @@character_set_connection reports 'latin1', expecting 'latin2'done!
+done!
diff --git a/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt b/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt
index 37de557527..b550cb8da3 100644
--- a/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt
+++ b/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt
@@ -69,7 +69,7 @@ if (($tmp[1] !== 'localhost') && ($tmp[1] !== '127.0.0.1'))
fwrite($fp, b"2;bar");
fclose($fp);
- $sql = sprintf("LOAD DATA INFILE %s INTO TABLE test FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n'", $db->quote($filename));
+ $sql = sprintf("LOAD DATA LOCAL INFILE %s INTO TABLE test FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n'", $db->quote($filename));
if (exec_and_count(4, $db, $sql, 2)) {
@@ -105,4 +105,4 @@ $db = MySQLPDOTest::factory();
$db->exec('DROP TABLE IF EXISTS test');
?>
--EXPECTF--
-done! \ No newline at end of file
+done!
diff --git a/ext/pdo_oci/config.m4 b/ext/pdo_oci/config.m4
index 214297073b..309bde8a5f 100755
--- a/ext/pdo_oci/config.m4
+++ b/ext/pdo_oci/config.m4
@@ -214,18 +214,18 @@ You need to tell me where to find your Oracle Instant Client SDK, or set ORACLE_
],[
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
- AC_MSG_RESULT($pdo_inc_path)
+ AC_MSG_RESULT($pdo_cv_inc_path)
])
- PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared,,-I$pdo_inc_path)
+ PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared,,-I$pdo_cv_inc_path)
PHP_SUBST_OLD(PDO_OCI_SHARED_LIBADD)
PHP_SUBST_OLD(PDO_OCI_DIR)
diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c
index b3aa7657ab..cb920ab14a 100644
--- a/ext/pdo_oci/oci_driver.c
+++ b/ext/pdo_oci/oci_driver.c
@@ -555,12 +555,12 @@ static int pdo_oci_check_liveness(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
/* use good old OCIServerVersion() */
H->last_err = OCIServerVersion (H->svc, H->err, (text *)version, sizeof(version), OCI_HTYPE_SVCCTX);
#endif
- if (H->last_err == OCI_SUCCESS) {
+ if (H->last_err == OCI_SUCCESS) {
return SUCCESS;
}
OCIErrorGet (H->err, (ub4)1, NULL, &error_code, NULL, 0, OCI_HTYPE_ERROR);
-
+
if (error_code == 1010) {
return SUCCESS;
}
diff --git a/ext/pdo_odbc/config.m4 b/ext/pdo_odbc/config.m4
index 36e506bd2c..b70dc9d539 100755
--- a/ext/pdo_odbc/config.m4
+++ b/ext/pdo_odbc/config.m4
@@ -47,15 +47,15 @@ if test "$PHP_PDO_ODBC" != "no"; then
],[
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
- AC_MSG_RESULT($pdo_inc_path)
+ AC_MSG_RESULT($pdo_cv_inc_path)
])
AC_MSG_CHECKING([for selected PDO ODBC flavour])
@@ -165,7 +165,7 @@ functions required for PDO support.
AC_MSG_ERROR([Your ODBC library does not exist or there was an error. Check config.log for more information])
], $PDO_ODBC_LDFLAGS)
- PHP_NEW_EXTENSION(pdo_odbc, pdo_odbc.c odbc_driver.c odbc_stmt.c, $ext_shared,,-I$pdo_inc_path $PDO_ODBC_INCLUDE)
+ PHP_NEW_EXTENSION(pdo_odbc, pdo_odbc.c odbc_driver.c odbc_stmt.c, $ext_shared,,-I$pdo_cv_inc_path $PDO_ODBC_INCLUDE)
PHP_SUBST(PDO_ODBC_SHARED_LIBADD)
ifdef([PHP_ADD_EXTENSION_DEP],
[
diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c
index 5c02f47a35..72553c421c 100644
--- a/ext/pdo_odbc/pdo_odbc.c
+++ b/ext/pdo_odbc/pdo_odbc.c
@@ -31,8 +31,8 @@
#include "php_pdo_odbc_int.h"
/* {{{ pdo_odbc_functions[] */
-const function_entry pdo_odbc_functions[] = {
- {NULL, NULL, NULL}
+const zend_function_entry pdo_odbc_functions[] = {
+ PHP_FE_END
};
/* }}} */
diff --git a/ext/pdo_pgsql/config.m4 b/ext/pdo_pgsql/config.m4
index 95d59a1b4a..f9254a8fd9 100644
--- a/ext/pdo_pgsql/config.m4
+++ b/ext/pdo_pgsql/config.m4
@@ -110,18 +110,18 @@ if test "$PHP_PDO_PGSQL" != "no"; then
],[
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
- AC_MSG_RESULT($pdo_inc_path)
+ AC_MSG_RESULT($pdo_cv_inc_path)
])
- PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_inc_path $PDO_PGSQL_CFLAGS)
+ PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_cv_inc_path $PDO_PGSQL_CFLAGS)
ifdef([PHP_ADD_EXTENSION_DEP],
[
PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo)
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index 1b8e4789d8..23ea5e58a2 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -497,6 +497,15 @@ static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
return pdo_pgsql_transaction_cmd("ROLLBACK", dbh TSRMLS_CC);
}
+static int pgsql_handle_in_transaction(pdo_dbh_t *dbh TSRMLS_DC)
+{
+ pdo_pgsql_db_handle *H;
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ return PQtransactionStatus(H->server);
+}
+
/* {{{ proto string PDO::pgsqlCopyFromArray(string $table_name , array $rows [, string $delimiter [, string $null_as ] [, string $fields])
Returns true if the copy worked fine or false if error */
static PHP_METHOD(PDO, pgsqlCopyFromArray)
@@ -619,7 +628,7 @@ static PHP_METHOD(PDO, pgsqlCopyFromFile)
ExecStatusType status;
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sss",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sp|sss",
&table_name, &table_name_len, &filename, &filename_len,
&pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
return;
@@ -713,7 +722,7 @@ static PHP_METHOD(PDO, pgsqlCopyToFile)
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sss",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sp|sss",
&table_name, &table_name_len, &filename, &filename_len,
&pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
return;
@@ -1022,6 +1031,7 @@ static struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_check_liveness, /* check_liveness */
pdo_pgsql_get_driver_methods, /* get_driver_methods */
NULL,
+ pgsql_handle_in_transaction,
};
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
diff --git a/ext/pdo_pgsql/tests/is_in_transaction.phpt b/ext/pdo_pgsql/tests/is_in_transaction.phpt
new file mode 100644
index 0000000000..99ff56162d
--- /dev/null
+++ b/ext/pdo_pgsql/tests/is_in_transaction.phpt
@@ -0,0 +1,66 @@
+--TEST--
+PDO PgSQL isInTransaction
+--SKIPIF--
+<?php # vim:se ft=php:
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+$db->exec('CREATE TABLE test (a integer not null primary key, b text)');
+
+$db->beginTransaction();
+try {
+echo "Test PDO::PGSQL_TRANSACTION_INTRANS\n";
+var_dump($db->inTransaction());
+
+$stmt = $db->prepare("INSERT INTO test (a, b) values (?, ?)");
+$stmt->bindValue(1, 1);
+$stmt->bindValue(2, "test insert");
+$stmt->execute();
+
+$db->commit();
+
+echo "Test PDO::PGSQL_TRANSACTION_IDLE\n";
+var_dump($db->inTransaction());
+
+$db->beginTransaction();
+
+try {
+$stmt = $db->prepare("INSERT INTO test (a, b) values (?, ?)");
+$stmt->bindValue(1, "error");
+$stmt->bindValue(2, "test insert");
+$stmt->execute();
+} catch (Exception $e) {
+ /* We catch the exception because the execute will give error and we must test the PDO::PGSQL_TRANSACTION_ERROR */
+ echo "Test PDO::PGSQL_TRANSACTION_INERROR\n";
+ var_dump($db->inTransaction());
+ $db->rollBack();
+}
+
+echo "Test PDO::PGSQL_TRANSACTION_IDLE\n";
+var_dump($db->inTransaction());
+
+} catch (Exception $e) {
+ /* catch exceptions so that we can show the relative error */
+ echo "Exception! at line ", $e->getLine(), "\n";
+ var_dump($e->getMessage());
+}
+
+?>
+--EXPECT--
+Test PDO::PGSQL_TRANSACTION_INTRANS
+int(2)
+Test PDO::PGSQL_TRANSACTION_IDLE
+int(0)
+Test PDO::PGSQL_TRANSACTION_INERROR
+int(3)
+Test PDO::PGSQL_TRANSACTION_IDLE
+int(0)
diff --git a/ext/pdo_sqlite/config.m4 b/ext/pdo_sqlite/config.m4
index 4e6dd2cb12..b2b70a5038 100644
--- a/ext/pdo_sqlite/config.m4
+++ b/ext/pdo_sqlite/config.m4
@@ -19,15 +19,15 @@ if test "$PHP_PDO_SQLITE" != "no"; then
],[
AC_MSG_CHECKING([for PDO includes])
if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$abs_srcdir/ext
+ pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then
- pdo_inc_path=$prefix/include/php/ext
+ pdo_cv_inc_path=$prefix/include/php/ext
else
AC_MSG_ERROR([Cannot find php_pdo_driver.h.])
fi
- AC_MSG_RESULT($pdo_inc_path)
+ AC_MSG_RESULT($pdo_cv_inc_path)
])
php_pdo_sqlite_sources_core="pdo_sqlite.c sqlite_driver.c sqlite_statement.c"
@@ -70,7 +70,7 @@ if test "$PHP_PDO_SQLITE" != "no"; then
])
PHP_SUBST(PDO_SQLITE_SHARED_LIBADD)
- PHP_NEW_EXTENSION(pdo_sqlite, $php_pdo_sqlite_sources_core, $ext_shared,,-I$pdo_inc_path)
+ PHP_NEW_EXTENSION(pdo_sqlite, $php_pdo_sqlite_sources_core, $ext_shared,,-I$pdo_cv_inc_path)
else
# use bundled libs
if test "$enable_maintainer_zts" = "yes"; then
@@ -92,7 +92,7 @@ if test "$PHP_PDO_SQLITE" != "no"; then
PHP_NEW_EXTENSION(pdo_sqlite,
$php_pdo_sqlite_sources_core,
- $ext_shared,,-DPDO_SQLITE_BUNDLED=1 $other_flags $threadsafe_flags -I$pdo_inc_path)
+ $ext_shared,,-DPDO_SQLITE_BUNDLED=1 $other_flags $threadsafe_flags -I$pdo_cv_inc_path)
PHP_SUBST(PDO_SQLITE_SHARED_LIBADD)
PHP_ADD_EXTENSION_DEP(pdo_sqlite, sqlite3)
diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
index 6d469d90c5..480c728d15 100644
--- a/ext/pdo_sqlite/sqlite_driver.c
+++ b/ext/pdo_sqlite/sqlite_driver.c
@@ -767,11 +767,6 @@ static char *make_filename_safe(const char *filename TSRMLS_DC)
return NULL;
}
- if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- efree(fullpath);
- return NULL;
- }
-
if (php_check_open_basedir(fullpath TSRMLS_CC)) {
efree(fullpath);
return NULL;
@@ -829,7 +824,7 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS
if (!filename) {
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
- "safe_mode/open_basedir prohibits opening %s",
+ "open_basedir prohibits opening %s",
dbh->data_source);
goto cleanup;
}
@@ -842,7 +837,7 @@ static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS
goto cleanup;
}
- if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
sqlite3_set_authorizer(H->db, authorizer, NULL);
}
diff --git a/ext/pdo_sqlite/tests/bug60104.phpt b/ext/pdo_sqlite/tests/bug60104.phpt
new file mode 100644
index 0000000000..fd36b57b76
--- /dev/null
+++ b/ext/pdo_sqlite/tests/bug60104.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #60104 (Segmentation Fault in pdo_sqlite when using sqliteCreateFunction())
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+function setUp()
+{
+ $handler = new PDO( "sqlite::memory:" );
+ $handler->sqliteCreateFunction( "md5", "md5", 1 );
+ unset( $handler );
+}
+
+setUp();
+setUp();
+echo "done";
+?>
+--EXPECTF--
+done
diff --git a/ext/pgsql/config.m4 b/ext/pgsql/config.m4
index 271079685c..bddb77a151 100644
--- a/ext/pgsql/config.m4
+++ b/ext/pgsql/config.m4
@@ -94,6 +94,7 @@ if test "$PHP_PGSQL" != "no"; then
AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibyte]))
AC_CHECK_LIB(pq, lo_create, AC_DEFINE(HAVE_PG_LO_CREATE,1,[PostgreSQL 8.1 or later]))
AC_CHECK_LIB(pq, lo_import_with_oid, AC_DEFINE(HAVE_PG_LO_IMPORT_WITH_OID,1,[PostgreSQL 8.4 or later]))
+ AC_CHECK_LIB(pq, PQescapeLiteral, AC_DEFINE(HAVE_PQESCAPELITERAL,1,[PostgreSQL 9.0 or later]))
LIBS=$old_LIBS
LDFLAGS=$old_LDFLAGS
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index 4a9294464a..ad66779606 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -422,6 +422,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_unescape_bytea, 0, 0, 1)
ZEND_END_ARG_INFO()
#endif
+#if HAVE_PQESCAPE
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_literal, 0, 0, 0)
+ ZEND_ARG_INFO(0, connection)
+ ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_identifier, 0, 0, 0)
+ ZEND_ARG_INFO(0, connection)
+ ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
ZEND_ARG_INFO(0, result)
ZEND_END_ARG_INFO()
@@ -652,6 +663,8 @@ const zend_function_entry pgsql_functions[] = {
PHP_FE(pg_escape_string, arginfo_pg_escape_string)
PHP_FE(pg_escape_bytea, arginfo_pg_escape_bytea)
PHP_FE(pg_unescape_bytea, arginfo_pg_unescape_bytea)
+ PHP_FE(pg_escape_literal, arginfo_pg_escape_literal)
+ PHP_FE(pg_escape_identifier, arginfo_pg_escape_identifier)
#endif
#if HAVE_PQSETERRORVERBOSITY
PHP_FE(pg_set_error_verbosity, arginfo_pg_set_error_verbosity)
@@ -815,7 +828,7 @@ static void _php_pgsql_notice_handler(void *resource_id, const char *message)
TSRMLS_FETCH();
if (! PGG(ignore_notices)) {
notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
- notice->message = _php_pgsql_trim_message(message, &notice->len);
+ notice->message = _php_pgsql_trim_message(message, (int *)&notice->len);
if (PGG(log_notices)) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", notice->message);
}
@@ -934,6 +947,11 @@ PHP_MINIT_FUNCTION(pgsql)
le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
le_string = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql string", module_number);
+#if HAVE_PG_CONFIG_H
+ /* PG_VERSION - libpq version */
+ REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION", PG_VERSION, CONST_CS | CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION_STR", PG_VERSION_STR, CONST_CS | CONST_PERSISTENT);
+#endif
/* For connection option */
REGISTER_LONG_CONSTANT("PGSQL_CONNECT_FORCE_NEW", PGSQL_CONNECT_FORCE_NEW, CONST_CS | CONST_PERSISTENT);
/* For pg_fetch_array() */
@@ -1048,6 +1066,7 @@ PHP_MINFO_FUNCTION(pgsql)
php_info_print_table_header(2, "PostgreSQL Support", "enabled");
#if HAVE_PG_CONFIG_H
php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
+ php_info_print_table_row(2, "PostgreSQL(libpq) ", PG_VERSION_STR);
#ifdef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
php_info_print_table_row(2, "Multibyte character support", "enabled");
#else
@@ -2503,12 +2522,8 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type,
int should_copy=0;
const uint element_len = strlen(element);
- if (PG(magic_quotes_runtime)) {
- data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
- } else {
- data = safe_estrndup(element, element_len);
- data_len = element_len;
- }
+ data = safe_estrndup(element, element_len);
+ data_len = element_len;
if (result_type & PGSQL_NUM) {
add_index_stringl(return_value, i, data, data_len, should_copy);
@@ -2883,7 +2898,7 @@ PHP_FUNCTION(pg_trace)
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
- stream = php_stream_open_wrapper(z_filename, mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(z_filename, mode, REPORT_ERRORS, NULL);
if (!stream) {
RETURN_FALSE;
@@ -3173,7 +3188,7 @@ PHP_FUNCTION(pg_lo_open)
} else {
pgsql_lofp->conn = pgsql;
pgsql_lofp->lofd = pgsql_lofd;
- Z_LVAL_P(return_value) = zend_list_insert(pgsql_lofp, le_lofp);
+ Z_LVAL_P(return_value) = zend_list_insert(pgsql_lofp, le_lofp TSRMLS_CC);
Z_TYPE_P(return_value) = IS_LONG;
}
}
@@ -3326,30 +3341,22 @@ PHP_FUNCTION(pg_lo_import)
Oid returned_oid;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "rs|z", &pgsql_link, &file_in, &name_len, &oid) == SUCCESS) {
+ "rp|z", &pgsql_link, &file_in, &name_len, &oid) == SUCCESS) {
;
}
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "s|z", &file_in, &name_len, &oid) == SUCCESS) {
+ "p|z", &file_in, &name_len, &oid) == SUCCESS) {
id = PGG(default_link);
CHECK_DEFAULT_LINK(id);
}
/* old calling convention, deprecated since PHP 4.2 */
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "sr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
+ "pr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
}
else {
WRONG_PARAM_COUNT;
}
-
- if (strlen(file_in) != name_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) &&(!php_checkuid(file_in, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
if (php_check_open_basedir(file_in TSRMLS_CC)) {
RETURN_FALSE;
@@ -3424,7 +3431,7 @@ PHP_FUNCTION(pg_lo_export)
/* allow string to handle large OID value correctly */
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "rls", &pgsql_link, &oid_long, &file_out, &name_len) == SUCCESS) {
+ "rlp", &pgsql_link, &oid_long, &file_out, &name_len) == SUCCESS) {
if (oid_long <= InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
RETURN_FALSE;
@@ -3441,7 +3448,7 @@ PHP_FUNCTION(pg_lo_export)
}
}
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "ls", &oid_long, &file_out, &name_len) == SUCCESS) {
+ "lp", &oid_long, &file_out, &name_len) == SUCCESS) {
if (oid_long <= InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
RETURN_FALSE;
@@ -3451,7 +3458,7 @@ PHP_FUNCTION(pg_lo_export)
CHECK_DEFAULT_LINK(id);
}
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "ss", &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
+ "sp", &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
if ((oid_string+oid_strlen) != end_ptr) {
/* wrong integer format */
@@ -3462,7 +3469,7 @@ PHP_FUNCTION(pg_lo_export)
CHECK_DEFAULT_LINK(id);
}
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "ssr", &oid_string, &oid_strlen, &file_out, &name_len, &pgsql_link) == SUCCESS) {
+ "spr", &oid_string, &oid_strlen, &file_out, &name_len, &pgsql_link) == SUCCESS) {
oid = (Oid)strtoul(oid_string, &end_ptr, 10);
if ((oid_string+oid_strlen) != end_ptr) {
/* wrong integer format */
@@ -3471,7 +3478,7 @@ PHP_FUNCTION(pg_lo_export)
}
}
else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
- "lsr", &oid_long, &file_out, &name_len, &pgsql_link) == SUCCESS) {
+ "lpr", &oid_long, &file_out, &name_len, &pgsql_link) == SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
if (oid_long <= InvalidOid) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
@@ -3483,14 +3490,6 @@ PHP_FUNCTION(pg_lo_export)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 2 or 3 arguments");
RETURN_FALSE;
}
-
- if (strlen(file_out) != name_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) &&(!php_checkuid(file_out, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
if (php_check_open_basedir(file_out TSRMLS_CC)) {
RETURN_FALSE;
@@ -4220,6 +4219,130 @@ PHP_FUNCTION(pg_unescape_bytea)
/* }}} */
#endif
+#ifdef HAVE_PQESCAPE
+#if !HAVE_PQESCAPELITERAL
+/* emulate libpq's PQescapeInternal() 9.0 or later */
+static char* php_pgsql_PQescapeInternal(PGconn *conn, const char *str, size_t len, int escape_literal) {
+ char *result, *rp;
+ const char *s;
+ size_t tmp_len;
+ int input_len = len;
+ char quote_char = escape_literal ? '\'' : '"';
+
+ if (!conn) {
+ return NULL;
+ }
+
+ /*
+ * NOTE: multibyte strings that could cointain slashes should be considered.
+ * (e.g. SJIS, BIG5) However, it cannot be done without valid PGconn and mbstring.
+ * Therefore, this function does not support such encodings currently.
+ * FIXME: add encoding check and skip multibyte char bytes if there is vaild PGconn.
+ */
+
+ /* allocate enough memory */
+ rp = result = (char *)emalloc(len*2 + 5); /* leading " E" needs extra 2 bytes + quote_chars on both end for 2 bytes + NULL */
+
+ if (escape_literal) {
+ /* check backslashes */
+ tmp_len = strspn(str, "\\");
+ if (tmp_len != len) {
+ /* add " E" for escaping slashes */
+ *rp++ = ' ';
+ *rp++ = 'E';
+ }
+ }
+ /* open quote */
+ *rp++ = quote_char;
+ for (s = str; s - str < input_len; ++s) {
+ if (*s == quote_char || (escape_literal && *s == '\\')) {
+ *rp++ = *s;
+ *rp++ = *s;
+ } else {
+ *rp++ = *s;
+ }
+ }
+ *rp++ = quote_char;
+ *rp = '\0';
+
+ return result;
+}
+#endif
+
+static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_literal) {
+ char *from = NULL, *to = NULL, *tmp = NULL;
+ zval *pgsql_link = NULL;
+ PGconn *pgsql;
+ int to_len;
+ int from_len;
+ int id = -1;
+
+ switch (ZEND_NUM_ARGS()) {
+ case 1:
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
+ return;
+ }
+ pgsql_link = NULL;
+ id = PGG(default_link);
+ break;
+
+ default:
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
+ return;
+ }
+ break;
+ }
+
+ if (pgsql_link == NULL && id == -1) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
+ if (pgsql == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get default pgsql link");
+ RETURN_FALSE;
+ }
+#ifdef HAVE_PQESCAPELITERAL
+ if (escape_literal) {
+ tmp = PQescapeLiteral(pgsql, from, (size_t)from_len);
+ } else {
+ tmp = PQescapeIdentifier(pgsql, from, (size_t)from_len);
+ }
+ if (!tmp) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Failed to escape");
+ RETURN_FALSE;
+ }
+ to = estrdup(tmp);
+ PQfreemem(tmp);
+#else
+ to = php_pgsql_PQescapeInternal(pgsql, from, (size_t)from_len, escape_literal);
+ if (!to) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Failed to escape");
+ RETURN_FALSE;
+ }
+#endif
+
+ RETURN_STRING(to, 0);
+}
+
+/* {{{ proto string pg_escape_literal([resource connection,] string data)
+ Escape parameter as string literal (i.e. parameter) */
+PHP_FUNCTION(pg_escape_literal)
+{
+ php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto string pg_escape_identifier([resource connection,] string data)
+ Escape identifier (i.e. table name, field name) */
+PHP_FUNCTION(pg_escape_identifier)
+{
+ php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+#endif
+
+
/* {{{ proto string pg_result_error(resource result)
Get error message associated with result */
PHP_FUNCTION(pg_result_error)
@@ -6237,12 +6360,9 @@ PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TS
size_t data_len;
const size_t element_len = strlen(element);
- if (PG(magic_quotes_runtime)) {
- data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
- } else {
- data = safe_estrndup(element, element_len);
- data_len = element_len;
- }
+ data = safe_estrndup(element, element_len);
+ data_len = element_len;
+
field_name = PQfname(pg_result, i);
add_assoc_stringl(row, field_name, data, data_len, 0);
}
diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h
index b24745699d..8b6abbf91c 100644
--- a/ext/pgsql/php_pgsql.h
+++ b/ext/pgsql/php_pgsql.h
@@ -172,6 +172,8 @@ PHP_FUNCTION(pg_set_error_verbosity);
PHP_FUNCTION(pg_escape_string);
PHP_FUNCTION(pg_escape_bytea);
PHP_FUNCTION(pg_unescape_bytea);
+PHP_FUNCTION(pg_escape_literal);
+PHP_FUNCTION(pg_escape_identifier);
#endif
/* misc functions */
diff --git a/ext/pgsql/tests/08escape.phpt b/ext/pgsql/tests/08escape.phpt
index cf23b50e3a..90b4ed8a9f 100644
--- a/ext/pgsql/tests/08escape.phpt
+++ b/ext/pgsql/tests/08escape.phpt
@@ -11,8 +11,9 @@ define('FILE_NAME', dirname(__FILE__) . '/php.gif');
// pg_escape_string() test
$before = "ABC\\ABC\'";
$expect = "ABC\\\\ABC\\'";
+$expect2 = "ABC\\\\ABC\\\\''"; //the way escape string differs from PostgreSQL 9.0
$after = pg_escape_string($before);
-if ($expect === $after) {
+if ($expect === $after || $expect2 === $after) {
echo "pg_escape_string() is Ok\n";
}
else {
@@ -58,11 +59,37 @@ else {
echo "pg_escape_bytea() is broken\n";
}
+// pg_escape_literal/pg_escape_identifier
+$before = "ABC\\ABC\'";
+$expect = " E'ABC\\\\ABC\\\\'''";
+$after = pg_escape_literal($before);
+if ($expect === $after) {
+ echo "pg_escape_literal() is Ok\n";
+}
+else {
+ echo "pg_escape_literal() is NOT Ok\n";
+ var_dump($before);
+ var_dump($after);
+ var_dump($expect);
+}
+
+$before = "ABC\\ABC\'";
+$expect = "\"ABC\ABC\'\"";
+$after = pg_escape_identifier($before);
+if ($expect === $after) {
+ echo "pg_escape_identifier() is Ok\n";
+}
+else {
+ echo "pg_escape_identifier() is NOT Ok\n";
+ var_dump($before);
+ var_dump($after);
+ var_dump($expect);
+}
+
?>
--EXPECT--
-pg_escape_string() is NOT Ok
-string(9) "ABC\ABC\'"
-string(12) "ABC\\ABC\\''"
-string(10) "ABC\\ABC\'"
+pg_escape_string() is Ok
pg_escape_bytea() is Ok
pg_escape_bytea() actually works with database
+pg_escape_literal() is Ok
+pg_escape_identifier() is Ok \ No newline at end of file
diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c
index 2e0739ea57..55f2548859 100644
--- a/ext/phar/func_interceptors.c
+++ b/ext/phar/func_interceptors.c
@@ -38,14 +38,14 @@ PHAR_FUNC(phar_opendir) /* {{{ */
goto skip_phar;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|z", &filename, &filename_len, &zcontext) == FAILURE) {
return;
}
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
char *arch, *entry, *fname;
int arch_len, entry_len, fname_len;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
/* we are checking for existence of a file within the relative path. Chances are good that this is
retrieving something from within the phar archive */
@@ -113,7 +113,7 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
}
/* Parse arguments */
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
goto skip_phar;
}
@@ -122,7 +122,7 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */
int arch_len, entry_len, fname_len;
php_stream_context *context = NULL;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
if (strncasecmp(fname, "phar://", 7)) {
goto skip_phar;
@@ -203,7 +203,7 @@ phar_it:
/* uses mmap if possible */
if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
-#if PHP_MAJOR_VERSION < 6
+#if PHP_API_VERSION < 20100412
if (PG(magic_quotes_runtime)) {
int newlen;
contents = php_addslashes(contents, len, &newlen, 1 TSRMLS_CC); /* 1 = free source string */
@@ -244,7 +244,7 @@ PHAR_FUNC(phar_readfile) /* {{{ */
&& !cached_phars.arBuckets) {
goto skip_phar;
}
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
goto skip_phar;
}
if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
@@ -253,7 +253,7 @@ PHAR_FUNC(phar_readfile) /* {{{ */
php_stream_context *context = NULL;
char *name;
phar_archive_data *phar;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
if (strncasecmp(fname, "phar://", 7)) {
goto skip_phar;
@@ -340,7 +340,7 @@ PHAR_FUNC(phar_fopen) /* {{{ */
/* no need to check, include_path not even specified in fopen/ no active phars */
goto skip_phar;
}
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
goto skip_phar;
}
if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
@@ -349,7 +349,7 @@ PHAR_FUNC(phar_fopen) /* {{{ */
php_stream_context *context = NULL;
char *name;
phar_archive_data *phar;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
if (strncasecmp(fname, "phar://", 7)) {
goto skip_phar;
@@ -621,7 +621,7 @@ static void phar_file_stat(const char *filename, php_stat_len filename_length, i
phar_entry_info *data = NULL;
phar_archive_data *phar;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
/* we are checking for existence of a file within the relative path. Chances are good that this is
retrieving something from within the phar archive */
@@ -813,7 +813,7 @@ void fname(INTERNAL_FUNCTION_PARAMETERS) { \
char *filename; \
int filename_len; \
\
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { \
return; \
} \
\
@@ -905,13 +905,13 @@ PHAR_FUNC(phar_is_file) /* {{{ */
&& !cached_phars.arBuckets) {
goto skip_phar;
}
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
goto skip_phar;
}
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
char *arch, *entry, *fname;
int arch_len, entry_len, fname_len;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
/* we are checking for existence of a file within the relative path. Chances are good that this is
retrieving something from within the phar archive */
@@ -972,13 +972,13 @@ PHAR_FUNC(phar_is_link) /* {{{ */
&& !cached_phars.arBuckets) {
goto skip_phar;
}
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
goto skip_phar;
}
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
char *arch, *entry, *fname;
int arch_len, entry_len, fname_len;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
/* we are checking for existence of a file within the relative path. Chances are good that this is
retrieving something from within the phar archive */
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 7b7d559811..cc7eac717d 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -1738,31 +1738,30 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a
static int phar_analyze_path(const char *fname, const char *ext, int ext_len, int for_create TSRMLS_DC) /* {{{ */
{
php_stream_statbuf ssb;
- char *realpath, old, *a = (char *)(ext + ext_len);
+ char *realpath;
+ char *filename = estrndup(fname, (ext - fname) + ext_len);
- old = *a;
- *a = '\0';
-
- if ((realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
+ if ((realpath = expand_filepath(filename, NULL TSRMLS_CC))) {
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
#endif
if (zend_hash_exists(&(PHAR_GLOBALS->phar_fname_map), realpath, strlen(realpath))) {
- *a = old;
efree(realpath);
+ efree(filename);
return SUCCESS;
}
if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_phars, realpath, strlen(realpath))) {
- *a = old;
efree(realpath);
+ efree(filename);
return SUCCESS;
}
efree(realpath);
}
- if (SUCCESS == php_stream_stat_path((char *) fname, &ssb)) {
- *a = old;
+ if (SUCCESS == php_stream_stat_path((char *) filename, &ssb)) {
+
+ efree(filename);
if (ssb.sb.st_mode & S_IFDIR) {
return FAILURE;
@@ -1777,61 +1776,56 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
char *slash;
if (!for_create) {
- *a = old;
+ efree(filename);
return FAILURE;
}
- slash = (char *) strrchr(fname, '/');
- *a = old;
+ slash = (char *) strrchr(filename, '/');
if (slash) {
- old = *slash;
*slash = '\0';
}
- if (SUCCESS != php_stream_stat_path((char *) fname, &ssb)) {
- if (slash) {
- *slash = old;
- } else {
- if (!(realpath = expand_filepath(fname, NULL TSRMLS_CC))) {
+ if (SUCCESS != php_stream_stat_path((char *) filename, &ssb)) {
+ if (!slash) {
+ if (!(realpath = expand_filepath(filename, NULL TSRMLS_CC))) {
+ efree(filename);
return FAILURE;
}
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
#endif
- if ((a = strstr(realpath, fname)) == NULL) {
- return FAILURE;
- }
-
- a += ((ext - fname) + ext_len);
- *a = '\0';
+ slash = strstr(realpath, filename) + ((ext - fname) + ext_len);
+ *slash = '\0';
slash = strrchr(realpath, '/');
if (slash) {
*slash = '\0';
} else {
efree(realpath);
+ efree(filename);
return FAILURE;
}
if (SUCCESS != php_stream_stat_path(realpath, &ssb)) {
efree(realpath);
+ efree(filename);
return FAILURE;
}
efree(realpath);
if (ssb.sb.st_mode & S_IFDIR) {
+ efree(filename);
return SUCCESS;
}
}
+ efree(filename);
return FAILURE;
}
- if (slash) {
- *slash = old;
- }
+ efree(filename);
if (ssb.sb.st_mode & S_IFDIR) {
return SUCCESS;
@@ -2339,7 +2333,7 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error TSRMLS_
*error = NULL;
}
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, 0, REPORT_ERRORS, NULL, 0 TSRMLS_CC) == SUCCESS) {
@@ -3341,7 +3335,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
return phar_orig_compile_file(file_handle, type TSRMLS_CC);
}
if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, "://")) {
- if (SUCCESS == phar_open_from_filename(file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
+ if (SUCCESS == phar_open_from_filename((char*)file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
if (phar->is_zip || phar->is_tar) {
zend_file_handle f = *file_handle;
@@ -3422,7 +3416,7 @@ int phar_zend_open(const char *filename, zend_file_handle *handle TSRMLS_DC) /*
char *fname;
int fname_len;
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (fname_len > 7 && !strncasecmp(fname, "phar://", 7)) {
diff --git a/ext/phar/phar/pharcommand.inc b/ext/phar/phar/pharcommand.inc
index 9e968694c3..cb343675b5 100644
--- a/ext/phar/phar/pharcommand.inc
+++ b/ext/phar/phar/pharcommand.inc
@@ -91,7 +91,7 @@ class PharCommand extends CLICommand
'h' => array(
'typ' => 'select',
'val' => NULL,
- 'inf' => '<method> Selects the hash algorithmn.',
+ 'inf' => '<method> Selects the hash algorithm.',
'select' => array('md5' => 'MD5','sha1' => 'SHA1')
),
'i' => array(
@@ -107,7 +107,7 @@ class PharCommand extends CLICommand
'l' => array(
'typ' => 'int',
'val' => 0,
- 'inf' => '<level> Number of preceeding subdirectories to strip from file entries',
+ 'inf' => '<level> Number of preceding subdirectories to strip from file entries',
),
'm' => array(
'typ' => 'any',
@@ -461,7 +461,7 @@ class PharCommand extends CLICommand
'typ' => 'any',
'val' => NULL,
'required' => 1,
- 'inf' => ' Any number of input files and directories. If -i is in use then ONLY files and matching thegiven regular expression are being packed. If -x is given then files matching that regular expression are NOT being packed.',
+ 'inf' => ' Any number of input files and directories. If -i is in use then ONLY files and matching the given regular expression are being packed. If -x is given then files matching that regular expression are NOT being packed.',
);
return $args;
@@ -981,7 +981,7 @@ class PharCommand extends CLICommand
'type' => 'any',
'val' => NULL,
'required' => 1,
- 'inf' => ' Any number of input files and directories. If -i is in use then ONLY files and matching thegiven regular expression are being packed. If -x is given then files matching that regular expression are NOT being packed.',
+ 'inf' => ' Any number of input files and directories. If -i is in use then ONLY files and matching the given regular expression are being packed. If -x is given then files matching that regular expression are NOT being packed.',
);
return $args;
}
diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h
index bd50bb9995..38342e3f7e 100644
--- a/ext/phar/phar_internal.h
+++ b/ext/phar/phar_internal.h
@@ -485,9 +485,9 @@ typedef struct _phar_entry_data {
off_t position;
/* for copies of the phar fp, defines where 0 is */
off_t zero;
- int for_write:1;
- int is_zip:1;
- int is_tar:1;
+ unsigned int for_write:1;
+ unsigned int is_zip:1;
+ unsigned int is_tar:1;
phar_entry_info *internal_file;
} phar_entry_data;
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index d19f30c612..561ba7bf24 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -164,7 +164,8 @@ static void phar_mung_server_vars(char *fname, char *entry, int entry_len, char
static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, int entry_len, char *arch, char *basename, char *ru, int ru_len TSRMLS_DC) /* {{{ */
{
- char *name = NULL, buf[8192], *cwd;
+ char *name = NULL, buf[8192];
+ const char *cwd;
zend_syntax_highlighter_ini syntax_highlighter_ini;
sapi_header_line ctr = {0};
size_t got;
@@ -447,7 +448,7 @@ PHP_METHOD(Phar, running)
return;
}
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
@@ -481,7 +482,7 @@ PHP_METHOD(Phar, mount)
return;
}
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
#ifdef PHP_WIN32
@@ -565,7 +566,8 @@ PHP_METHOD(Phar, webPhar)
zval *mimeoverride = NULL, *rewrite = NULL;
char *alias = NULL, *error, *index_php = NULL, *f404 = NULL, *ru = NULL;
int alias_len = 0, ret, f404_len = 0, free_pathinfo = 0, ru_len = 0;
- char *fname, *basename, *path_info, *mime_type = NULL, *entry, *pt;
+ char *fname, *path_info, *mime_type = NULL, *entry, *pt;
+ const char *basename;
int fname_len, entry_len, code, index_php_len = 0, not_cgi;
phar_archive_data *phar = NULL;
phar_entry_info *info = NULL;
@@ -575,7 +577,7 @@ PHP_METHOD(Phar, webPhar)
}
phar_request_initialize(TSRMLS_C);
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) != SUCCESS) {
@@ -841,7 +843,7 @@ PHP_METHOD(Phar, webPhar)
}
if (mimeoverride && zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) {
- char *ext = zend_memrchr(entry, '.', entry_len);
+ const char *ext = zend_memrchr(entry, '.', entry_len);
zval **val;
if (ext) {
@@ -1359,7 +1361,7 @@ PHP_METHOD(Phar, unlinkArchive)
return;
}
- zname = zend_get_executed_filename(TSRMLS_C);
+ zname = (char*)zend_get_executed_filename(TSRMLS_C);
zname_len = strlen(zname);
if (zname_len > 7 && !memcmp(zname, "phar://", 7) && SUCCESS == phar_split_fname(zname, zname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
@@ -2080,7 +2082,8 @@ static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp TSRMLS
static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool compress TSRMLS_DC) /* {{{ */
{
- char *oldname = NULL, *oldpath = NULL;
+ const char *oldname = NULL;
+ char *oldpath = NULL;
char *basename = NULL, *basepath = NULL;
char *newname = NULL, *newpath = NULL;
zval *ret, arg1;
@@ -4175,7 +4178,8 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
php_stream_statbuf ssb;
int len;
php_stream *fp;
- char *fullpath, *slash;
+ char *fullpath;
+ const char *slash;
mode_t mode;
if (entry->is_mounted) {
diff --git a/ext/phar/phar_path_check.c b/ext/phar/phar_path_check.c
index 01e8c79fe8..7ca339d269 100644
--- a/ext/phar/phar_path_check.c
+++ b/ext/phar/phar_path_check.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Fri Feb 25 04:29:05 2011 */
+/* Generated by re2c 0.13.5 on Fri Feb 25 04:35:39 2011 */
#line 1 "ext/phar/phar_path_check.re"
/*
+----------------------------------------------------------------------+
diff --git a/ext/phar/stream.c b/ext/phar/stream.c
index ccfe2a5886..bf0913d683 100644
--- a/ext/phar/stream.c
+++ b/ext/phar/stream.c
@@ -410,7 +410,7 @@ static int phar_stream_seek(php_stream *stream, off_t offset, int whence, off_t
case SEEK_SET :
temp = data->zero + offset;
break;
- default :
+ default:
temp = 0;
}
if (temp > data->zero + (off_t) entry->uncompressed_filesize) {
diff --git a/ext/phar/tests/008.phpt b/ext/phar/tests/008.phpt
index bede8ba1c1..664ffea5cb 100644
--- a/ext/phar/tests/008.phpt
+++ b/ext/phar/tests/008.phpt
@@ -2,8 +2,6 @@
Phar::mapPhar truncated manifest (not enough for manifest length)
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip");?>
---INI--
-detect_unicode=0
--FILE--
<?php
$file = "<?php
diff --git a/ext/phar/tests/009.phpt b/ext/phar/tests/009.phpt
index 55d13b353c..61933b3814 100644
--- a/ext/phar/tests/009.phpt
+++ b/ext/phar/tests/009.phpt
@@ -4,7 +4,6 @@ Phar::mapPhar too many manifest entries
<?php if (!extension_loaded("phar")) die("skip");?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$file = b"<?php
diff --git a/ext/phar/tests/010.phpt b/ext/phar/tests/010.phpt
index 441f13dc64..d1e2f40c9c 100644
--- a/ext/phar/tests/010.phpt
+++ b/ext/phar/tests/010.phpt
@@ -4,7 +4,6 @@ Phar::mapPhar buffer overrun
<?php if (!extension_loaded("phar")) die("skip");?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$file = b"<?php
diff --git a/ext/phar/tests/011.phpt b/ext/phar/tests/011.phpt
index 9923f853e4..4a1f0dd42c 100644
--- a/ext/phar/tests/011.phpt
+++ b/ext/phar/tests/011.phpt
@@ -4,7 +4,6 @@ Phar::mapPhar filesize too small in manifest
<?php if (!extension_loaded("phar")) die("skip");?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/012.phpt b/ext/phar/tests/012.phpt
index 37ff8bb19e..3246eff468 100644
--- a/ext/phar/tests/012.phpt
+++ b/ext/phar/tests/012.phpt
@@ -4,7 +4,6 @@ Phar::mapPhar valid file
<?php if (!extension_loaded("phar")) die("skip");?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
diff --git a/ext/phar/tests/018.phpt b/ext/phar/tests/018.phpt
index 71fa622402..2e2df470bf 100644
--- a/ext/phar/tests/018.phpt
+++ b/ext/phar/tests/018.phpt
@@ -7,7 +7,6 @@ if (version_compare(PHP_VERSION, "6.0", ">")) die("skip pre-unicode version of P
?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -34,4 +33,4 @@ while (false !== ($a = readdir($dir))) {
string(1) "a"
bool(false)
string(1) "b"
-bool(true)
+bool(true) \ No newline at end of file
diff --git a/ext/phar/tests/019b.phpt b/ext/phar/tests/019b.phpt
index 22d193efd6..5a0ef71335 100644
--- a/ext/phar/tests/019b.phpt
+++ b/ext/phar/tests/019b.phpt
@@ -7,7 +7,6 @@ if (version_compare(PHP_VERSION, "6.0", ">")) die("skip pre-unicode version of P
?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/019c.phpt b/ext/phar/tests/019c.phpt
index 23afa26190..2cb508c46c 100644
--- a/ext/phar/tests/019c.phpt
+++ b/ext/phar/tests/019c.phpt
@@ -7,7 +7,6 @@ if (version_compare(PHP_VERSION, "6.0", ">")) die("skip pre-unicode version of P
?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/020.phpt b/ext/phar/tests/020.phpt
index 334a16dbf1..7d01681b6f 100644
--- a/ext/phar/tests/020.phpt
+++ b/ext/phar/tests/020.phpt
@@ -4,7 +4,6 @@ Phar: url stat
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -134,4 +133,4 @@ array(26) {
int(-1)
[%sblocks"]=>
int(-1)
-}
+} \ No newline at end of file
diff --git a/ext/phar/tests/021.phpt b/ext/phar/tests/021.phpt
index af062dbcf1..bfd6576952 100644
--- a/ext/phar/tests/021.phpt
+++ b/ext/phar/tests/021.phpt
@@ -4,7 +4,6 @@ Phar: stream stat
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -83,4 +82,4 @@ array(26) {
int(-1)
[%sblocks"]=>
int(-1)
-}
+} \ No newline at end of file
diff --git a/ext/phar/tests/022.phpt b/ext/phar/tests/022.phpt
index 934add4721..20c24a0214 100644
--- a/ext/phar/tests/022.phpt
+++ b/ext/phar/tests/022.phpt
@@ -4,7 +4,6 @@ Phar: stream stat
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/028.phpt b/ext/phar/tests/028.phpt
index 8cead29ff4..087f822777 100644
--- a/ext/phar/tests/028.phpt
+++ b/ext/phar/tests/028.phpt
@@ -4,7 +4,6 @@ Phar::loadPhar
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/cache_list/copyonwrite1.phar.phpt b/ext/phar/tests/cache_list/copyonwrite1.phar.phpt
index f3105194eb..90b0a8fe46 100644
--- a/ext/phar/tests/cache_list/copyonwrite1.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite1.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 1 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite1.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write.phar
--EXPECT--
hi
changed
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite10.phar.phpt b/ext/phar/tests/cache_list/copyonwrite10.phar.phpt
index 959c6e0a94..3d5b7fe784 100644
--- a/ext/phar/tests/cache_list/copyonwrite10.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite10.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 10 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite10.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -22,4 +21,4 @@ __HALT_COMPILER(); ?>
"
<?php __HALT_COMPILER(); ?>
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite11.phar.phpt b/ext/phar/tests/cache_list/copyonwrite11.phar.phpt
index f48df3776d..65388163dc 100644
--- a/ext/phar/tests/cache_list/copyonwrite11.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite11.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 11 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite11.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -20,4 +19,4 @@ echo "ok\n";
__HALT_COMPILER(); ?>
"
6685
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite12.phar.phpt b/ext/phar/tests/cache_list/copyonwrite12.phar.phpt
index ef5d02ccc8..40b544191d 100644
--- a/ext/phar/tests/cache_list/copyonwrite12.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite12.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 12 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite12.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -22,4 +21,4 @@ array(2) {
["hash_type"]=>
string(3) "MD5"
}
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite13.phar.phpt b/ext/phar/tests/cache_list/copyonwrite13.phar.phpt
index bd49565c83..fc47174d2b 100644
--- a/ext/phar/tests/cache_list/copyonwrite13.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite13.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 13 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite13.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -13,4 +12,4 @@ files/write13.phar
--EXPECTF--
bool(false)
bool(true)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite14.phar.phpt b/ext/phar/tests/cache_list/copyonwrite14.phar.phpt
index 9b4a65c54c..11201ac989 100644
--- a/ext/phar/tests/cache_list/copyonwrite14.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite14.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 14 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite14.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -13,4 +12,4 @@ files/write14.phar
--EXPECTF--
bool(true)
bool(false)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite15.phar.phpt b/ext/phar/tests/cache_list/copyonwrite15.phar.phpt
index 545201e389..6e46289227 100644
--- a/ext/phar/tests/cache_list/copyonwrite15.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite15.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 15 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite15.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write15.phar
--EXPECTF--
bool(false)
bool(true)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite16.phar.phpt b/ext/phar/tests/cache_list/copyonwrite16.phar.phpt
index 5cc9cb415a..f17784c355 100644
--- a/ext/phar/tests/cache_list/copyonwrite16.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite16.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 16 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite16.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write16.phar
--EXPECTF--
bool(true)
bool(false)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite17.phar.phpt b/ext/phar/tests/cache_list/copyonwrite17.phar.phpt
index 74dc6619c1..158c049b14 100644
--- a/ext/phar/tests/cache_list/copyonwrite17.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite17.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 17 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite17.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write17.phar
--EXPECTF--
NULL
%string|unicode%(2) "hi"
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite18.phar.phpt b/ext/phar/tests/cache_list/copyonwrite18.phar.phpt
index 03112c18be..3e65f5a124 100644
--- a/ext/phar/tests/cache_list/copyonwrite18.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite18.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 18 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite18.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write18.phar
--EXPECTF--
100666
100444
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite19.phar.phpt b/ext/phar/tests/cache_list/copyonwrite19.phar.phpt
index 23fe5879a9..6e03554d96 100644
--- a/ext/phar/tests/cache_list/copyonwrite19.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite19.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 19 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite19.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write19.phar
--EXPECTF--
string(2) "hi"
%string|unicode%(3) "hi2"
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite2.phar.phpt b/ext/phar/tests/cache_list/copyonwrite2.phar.phpt
index 9246a630c6..8d21c813a4 100644
--- a/ext/phar/tests/cache_list/copyonwrite2.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite2.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 2 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite2.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -15,4 +14,4 @@ bool(true)
string(2) "hi"
bool(true)
bool(true)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite20.phar.phpt b/ext/phar/tests/cache_list/copyonwrite20.phar.phpt
index 10c56342e9..acce57415c 100644
--- a/ext/phar/tests/cache_list/copyonwrite20.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite20.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 20 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite20.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write20.phar
--EXPECTF--
string(2) "hi"
NULL
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite21.phar.phpt b/ext/phar/tests/cache_list/copyonwrite21.phar.phpt
index 409273db6c..8960ea7171 100644
--- a/ext/phar/tests/cache_list/copyonwrite21.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite21.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 21 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite21.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -13,4 +12,4 @@ files/write21.phar
--EXPECTF--
bool(false)
bool(true)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite22.phar.phpt b/ext/phar/tests/cache_list/copyonwrite22.phar.phpt
index 9e7ad6c741..7cba216395 100644
--- a/ext/phar/tests/cache_list/copyonwrite22.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite22.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 22 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite22.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -13,4 +12,4 @@ files/write22.phar
--EXPECTF--
bool(true)
bool(false)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite23.phar.phpt b/ext/phar/tests/cache_list/copyonwrite23.phar.phpt
index 28412928b6..292e5af668 100644
--- a/ext/phar/tests/cache_list/copyonwrite23.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite23.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 23 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite23.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -15,4 +14,4 @@ bool(true)
bool(false)
bool(false)
bool(true)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite24.phar.phpt b/ext/phar/tests/cache_list/copyonwrite24.phar.phpt
index 3aaba359f5..69197f2b4b 100644
--- a/ext/phar/tests/cache_list/copyonwrite24.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite24.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 24 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite24.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -13,4 +12,4 @@ files/write24.phar
--EXPECTF--
bool(false)
bool(true)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite25.phar.phpt b/ext/phar/tests/cache_list/copyonwrite25.phar.phpt
index 73a1d7648a..b661cb61c1 100644
--- a/ext/phar/tests/cache_list/copyonwrite25.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite25.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 25 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite25.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (!extension_loaded("zlib")) die("skip no zlib extension"); ?>
@@ -14,4 +13,4 @@ files/write25.phar
bool(false)
bool(true)
<?php __HALT_COMPILER();
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite3.phar.phpt b/ext/phar/tests/cache_list/copyonwrite3.phar.phpt
index 44815ef522..7e2c94c5b2 100644
--- a/ext/phar/tests/cache_list/copyonwrite3.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite3.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 3 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite3.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -14,4 +13,4 @@ bool(true)
bool(true)
bool(false)
bool(false)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite4.phar.phpt b/ext/phar/tests/cache_list/copyonwrite4.phar.phpt
index f29a8d6247..20ff78e282 100644
--- a/ext/phar/tests/cache_list/copyonwrite4.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite4.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 4 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite4.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -13,4 +12,4 @@ files/write4.phar
bool(false)
bool(true)
string(2) "hi"
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite4a.phpt b/ext/phar/tests/cache_list/copyonwrite4a.phpt
index 1b50c4204a..1945e31f16 100644
--- a/ext/phar/tests/cache_list/copyonwrite4a.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite4a.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 4a [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite4.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE--
@@ -18,4 +17,4 @@ var_dump(file_exists('phar://' . dirname(__FILE__) . '/files/write4.phar/testit.
bool(false)
bool(true)
string(2) "hi"
-===DONE===
+===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite5.phar.phpt b/ext/phar/tests/cache_list/copyonwrite5.phar.phpt
index 6f48dfa63d..89990a7af1 100644
--- a/ext/phar/tests/cache_list/copyonwrite5.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite5.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 5 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite5.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -25,4 +24,4 @@ array(2) {
phar://%scopyonwrite5.phar.php%cfile1 file1
phar://%scopyonwrite5.phar.php%cfile2 file2
phar://%scopyonwrite5.phar.php%chi hi
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite6.phar.phpt b/ext/phar/tests/cache_list/copyonwrite6.phar.phpt
index ceea8508bd..661fef42c1 100644
--- a/ext/phar/tests/cache_list/copyonwrite6.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite6.phar.phpt
@@ -5,7 +5,6 @@ default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite6.phar.php
phar.readonly=0
open_basedir=
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (version_compare(PHP_VERSION, "5.3", "<")) die("skip PHP 5.3+ required"); ?>
diff --git a/ext/phar/tests/cache_list/copyonwrite7.phar.phpt b/ext/phar/tests/cache_list/copyonwrite7.phar.phpt
index 57658dddd9..d6faded9cc 100644
--- a/ext/phar/tests/cache_list/copyonwrite7.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite7.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 7 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite7.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write7.phar
--EXPECT--
bool(true)
bool(false)
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite8.phar.phpt b/ext/phar/tests/cache_list/copyonwrite8.phar.phpt
index 71aa0b01be..7217d336e2 100644
--- a/ext/phar/tests/cache_list/copyonwrite8.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite8.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 8 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite8.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -12,4 +11,4 @@ files/write8.phar
--EXPECTF--
string(%s) "%scopyonwrite8.phar.php"
hi
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/copyonwrite9.phar.phpt b/ext/phar/tests/cache_list/copyonwrite9.phar.phpt
index b2437776a1..ffda9565bd 100644
--- a/ext/phar/tests/cache_list/copyonwrite9.phar.phpt
+++ b/ext/phar/tests/cache_list/copyonwrite9.phar.phpt
@@ -4,7 +4,6 @@ Phar: copy-on-write test 9 [cache_list]
default_charset=UTF-8
phar.cache_list={PWD}/copyonwrite9.phar.php
phar.readonly=0
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -21,4 +20,4 @@ __HALT_COMPILER(); ?>
"
<?php __HALT_COMPILER(); ?>
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller1.phpt b/ext/phar/tests/cache_list/frontcontroller1.phpt
index 91a5c9ea7d..d0d5552f16 100644
--- a/ext/phar/tests/cache_list/frontcontroller1.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller1.phpt
@@ -2,7 +2,6 @@
Phar front controller other
--INI--
phar.cache_list={PWD}/frontcontroller1.php [cache_list]
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller10.phpt b/ext/phar/tests/cache_list/frontcontroller10.phpt
index 7c94da116c..00177d4ff5 100644
--- a/ext/phar/tests/cache_list/frontcontroller10.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller10.phpt
@@ -3,7 +3,6 @@ Phar front controller rewrite access denied [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller10.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller11.phpt b/ext/phar/tests/cache_list/frontcontroller11.phpt
index e4912844de..25b147e194 100644
--- a/ext/phar/tests/cache_list/frontcontroller11.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller11.phpt
@@ -3,7 +3,6 @@ Phar front controller mime type extension is not a string [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller11.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php die("skip"); ?>
@@ -20,4 +19,4 @@ Fatal error: Uncaught exception 'PharException' with message 'Key of MIME type o
Stack trace:
#0 %sfrontcontroller11.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller11.php on line 2
+ thrown in %sfrontcontroller11.php on line 2 \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller12.phpt b/ext/phar/tests/cache_list/frontcontroller12.phpt
index c98a84027a..cfc7d0e43a 100644
--- a/ext/phar/tests/cache_list/frontcontroller12.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller12.phpt
@@ -3,7 +3,6 @@ Phar front controller mime type unknown int [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller12.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -19,4 +18,4 @@ Fatal error: Uncaught exception 'PharException' with message 'Unknown mime type
Stack trace:
#0 %sfrontcontroller12.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller12.php on line 2
+ thrown in %sfrontcontroller12.php on line 2 \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller13.phpt b/ext/phar/tests/cache_list/frontcontroller13.phpt
index deb02c25db..e6c9dee4ae 100644
--- a/ext/phar/tests/cache_list/frontcontroller13.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller13.phpt
@@ -3,7 +3,6 @@ Phar front controller mime type not string/int [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller13.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -19,4 +18,4 @@ Fatal error: Uncaught exception 'PharException' with message 'Unknown mime type
Stack trace:
#0 %sfrontcontroller13.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller13.php on line 2
+ thrown in %sfrontcontroller13.php on line 2 \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller14.phpt b/ext/phar/tests/cache_list/frontcontroller14.phpt
index bc214141f4..bbd9637d24 100644
--- a/ext/phar/tests/cache_list/frontcontroller14.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller14.phpt
@@ -2,7 +2,6 @@
Phar front controller mime type override, other [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller14.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller15.phpt b/ext/phar/tests/cache_list/frontcontroller15.phpt
index 22fed0af57..d142a5d742 100644
--- a/ext/phar/tests/cache_list/frontcontroller15.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller15.phpt
@@ -3,7 +3,6 @@ Phar front controller mime type override, Phar::PHPS [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller15.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller16.phpt b/ext/phar/tests/cache_list/frontcontroller16.phpt
index 4294c3d326..10bebdccef 100644
--- a/ext/phar/tests/cache_list/frontcontroller16.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller16.phpt
@@ -3,7 +3,6 @@ Phar front controller mime type override, Phar::PHP [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller16.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller17.phpt b/ext/phar/tests/cache_list/frontcontroller17.phpt
index 47688e7b6a..35d3ae4e9c 100644
--- a/ext/phar/tests/cache_list/frontcontroller17.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller17.phpt
@@ -2,7 +2,6 @@
Phar front controller mime type unknown [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller17.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller18.phpt b/ext/phar/tests/cache_list/frontcontroller18.phpt
index 8982706e5f..5e94bf6ff5 100644
--- a/ext/phar/tests/cache_list/frontcontroller18.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller18.phpt
@@ -2,7 +2,6 @@
Phar front controller $_SERVER munging failure [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller18.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller19.phpt b/ext/phar/tests/cache_list/frontcontroller19.phpt
index 0e5e8f1d07..bed0b1df31 100644
--- a/ext/phar/tests/cache_list/frontcontroller19.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller19.phpt
@@ -2,7 +2,6 @@
Phar front controller $_SERVER munging failure 2 [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller19.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller2.phpt b/ext/phar/tests/cache_list/frontcontroller2.phpt
index 2cf18f823c..67ccfc1e04 100644
--- a/ext/phar/tests/cache_list/frontcontroller2.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller2.phpt
@@ -3,7 +3,6 @@ Phar front controller PHP test [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list=frontcontroller2.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller20.phpt b/ext/phar/tests/cache_list/frontcontroller20.phpt
index b5499b1ef5..bf333c773c 100644
--- a/ext/phar/tests/cache_list/frontcontroller20.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller20.phpt
@@ -2,7 +2,6 @@
Phar front controller $_SERVER munging failure 3 [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller20.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller21.phpt b/ext/phar/tests/cache_list/frontcontroller21.phpt
index 6d514891df..829f2986e9 100644
--- a/ext/phar/tests/cache_list/frontcontroller21.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller21.phpt
@@ -3,7 +3,6 @@ Phar front controller $_SERVER munging success [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller21.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -23,4 +22,4 @@ string(18) "/index.php?test=hi"
string(32) "/frontcontroller21.php/index.php"
string(22) "/frontcontroller21.php"
string(%d) "%sfrontcontroller21.php"
-string(40) "/frontcontroller21.php/index.php?test=hi"
+string(40) "/frontcontroller21.php/index.php?test=hi" \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller22.phpt b/ext/phar/tests/cache_list/frontcontroller22.phpt
index 3454e16239..2769b01f2f 100644
--- a/ext/phar/tests/cache_list/frontcontroller22.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller22.phpt
@@ -3,7 +3,6 @@ Phar front controller include from cwd test 1 [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller22.phpt
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -20,4 +19,4 @@ Content-type: text/html; charset=UTF-8
Warning: include(./hi.php): failed to open stream: No such file or directory in phar://%s/oof/test.php on line %d
-Warning: include(): Failed opening './hi.php' for inclusion (include_path='%s') in phar://%soof/test.php on line %d
+Warning: include(): Failed opening './hi.php' for inclusion (include_path='%s') in phar://%soof/test.php on line %d \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller23.phpt b/ext/phar/tests/cache_list/frontcontroller23.phpt
index 6a053e694c..3da9631dfb 100644
--- a/ext/phar/tests/cache_list/frontcontroller23.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller23.phpt
@@ -3,7 +3,6 @@ Phar front controller with generic action router test [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller23.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -16,4 +15,4 @@ files/frontcontroller14.phar
Content-type: text/html; charset=UTF-8
--EXPECTF--
string(9) "/hi/there"
-string(%d) "phar://%sfrontcontroller23.php/html/index.php"
+string(%d) "phar://%sfrontcontroller23.php/html/index.php" \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller24.phpt b/ext/phar/tests/cache_list/frontcontroller24.phpt
index e8892a3dab..561826bd78 100644
--- a/ext/phar/tests/cache_list/frontcontroller24.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller24.phpt
@@ -3,7 +3,6 @@ Phar front controller with custom 404 php script [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller24.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -15,4 +14,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: text/html; charset=UTF-8
--EXPECTF--
-My 404 is rawesome
+My 404 is rawesome \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller25.phpt b/ext/phar/tests/cache_list/frontcontroller25.phpt
index 2fdc23daad..a8779392b6 100644
--- a/ext/phar/tests/cache_list/frontcontroller25.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller25.phpt
@@ -3,7 +3,6 @@ Phar front controller with extra path_info [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller25.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -16,4 +15,4 @@ files/frontcontroller8.phar
Content-type: text/html; charset=UTF-8
--EXPECTF--
string(42) "/frontcontroller25.php/a1.phps/extra/stuff"
-string(12) "/extra/stuff"
+string(12) "/extra/stuff" \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller26.phpt b/ext/phar/tests/cache_list/frontcontroller26.phpt
index dc3bdf8bc3..86a1c1444c 100644
--- a/ext/phar/tests/cache_list/frontcontroller26.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller26.phpt
@@ -2,7 +2,6 @@
Phar front controller with unknown extension mime type [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller26.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: application/octet-stream
--EXPECTF--
-<?php var_dump("hi");
+<?php var_dump("hi"); \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller27.phpt b/ext/phar/tests/cache_list/frontcontroller27.phpt
index 87e8050e2f..4a76e02eae 100644
--- a/ext/phar/tests/cache_list/frontcontroller27.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller27.phpt
@@ -3,7 +3,6 @@ Phar front controller with no extension [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller27.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -15,4 +14,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: text/plain;charset=UTF-8
--EXPECTF--
-hi
+hi \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller28.phpt b/ext/phar/tests/cache_list/frontcontroller28.phpt
index ea76bb21f6..80059a9da2 100644
--- a/ext/phar/tests/cache_list/frontcontroller28.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller28.phpt
@@ -3,7 +3,6 @@ Phar front controller with huge file [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller28.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller29.phpt b/ext/phar/tests/cache_list/frontcontroller29.phpt
index 5a5dacff52..1cd8f96f2d 100644
--- a/ext/phar/tests/cache_list/frontcontroller29.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller29.phpt
@@ -3,7 +3,6 @@ Phar front controller with fatal error in php file [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller29.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -15,4 +14,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: text/html; charset=UTF-8
--EXPECTF--
-Fatal error: Call to undefined function oopsie_daisy() in phar://%sfatalerror.phps on line 1
+Fatal error: Call to undefined function oopsie_daisy() in phar://%sfatalerror.phps on line 1 \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller3.phpt b/ext/phar/tests/cache_list/frontcontroller3.phpt
index f5651e2d78..1c1b479881 100644
--- a/ext/phar/tests/cache_list/frontcontroller3.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller3.phpt
@@ -3,7 +3,6 @@ Phar front controller phps [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller3.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller30.phpt b/ext/phar/tests/cache_list/frontcontroller30.phpt
index ca92c72880..5a63da874c 100644
--- a/ext/phar/tests/cache_list/frontcontroller30.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller30.phpt
@@ -2,7 +2,6 @@
Phar front controller with weird SCRIPT_NAME [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller30.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -12,4 +11,4 @@ REQUEST_URI=/huh?
files/frontcontroller8.phar
--EXPECTF--
oops did not run
-%a
+%a \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller31.phpt b/ext/phar/tests/cache_list/frontcontroller31.phpt
index 966ca1a40c..9ef1221a28 100644
--- a/ext/phar/tests/cache_list/frontcontroller31.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller31.phpt
@@ -3,7 +3,6 @@ Phar front controller with invalid callback for rewrites [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller31.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ Content-type: text/html; charset=UTF-8
--FILE_EXTERNAL--
files/frontcontroller16.phar
--EXPECT--
-phar error: invalid rewrite callback
+phar error: invalid rewrite callback \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller32.phpt b/ext/phar/tests/cache_list/frontcontroller32.phpt
index 49cb062e54..59116907a5 100644
--- a/ext/phar/tests/cache_list/frontcontroller32.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller32.phpt
@@ -3,7 +3,6 @@ Phar front controller with valid callback that is not good [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller32.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ Content-type: text/html; charset=UTF-8
--FILE_EXTERNAL--
files/frontcontroller17.phar
--EXPECTF--
-%ahar error: failed to call rewrite callback
+%ahar error: failed to call rewrite callback \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller33.phpt b/ext/phar/tests/cache_list/frontcontroller33.phpt
index 34244d844e..9573854823 100644
--- a/ext/phar/tests/cache_list/frontcontroller33.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller33.phpt
@@ -3,7 +3,6 @@ Phar front controller with valid callback that does not return any value [cache_
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller33.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ Content-type: text/html; charset=UTF-8
--FILE_EXTERNAL--
files/frontcontroller18.phar
--EXPECTF--
-phar error: rewrite callback must return a string or false
+phar error: rewrite callback must return a string or false \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller34.phpt b/ext/phar/tests/cache_list/frontcontroller34.phpt
index f6677cc04b..83c22f58f8 100644
--- a/ext/phar/tests/cache_list/frontcontroller34.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller34.phpt
@@ -3,7 +3,6 @@ Phar front controller with cwd [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller34.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller4.phpt b/ext/phar/tests/cache_list/frontcontroller4.phpt
index 16961a1e46..5cf3682277 100644
--- a/ext/phar/tests/cache_list/frontcontroller4.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller4.phpt
@@ -2,7 +2,6 @@
Phar front controller index.php relocate (no /) [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller4.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller5.phpt b/ext/phar/tests/cache_list/frontcontroller5.phpt
index 93ea37a9af..2c738d7bfb 100644
--- a/ext/phar/tests/cache_list/frontcontroller5.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller5.phpt
@@ -2,7 +2,6 @@
Phar front controller index.php relocate [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller5.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller6.phpt b/ext/phar/tests/cache_list/frontcontroller6.phpt
index d498072fa2..2480be4129 100644
--- a/ext/phar/tests/cache_list/frontcontroller6.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller6.phpt
@@ -2,7 +2,6 @@
Phar front controller 404 [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller6.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -21,4 +20,4 @@ Status: 404 Not Found
<body>
<h1>404 - File /notfound.php Not Found</h1>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller7.phpt b/ext/phar/tests/cache_list/frontcontroller7.phpt
index c4d5514ade..a8a88a95fe 100644
--- a/ext/phar/tests/cache_list/frontcontroller7.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller7.phpt
@@ -2,7 +2,6 @@
Phar front controller alternate index file [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller7.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/cache_list/frontcontroller8.phpt b/ext/phar/tests/cache_list/frontcontroller8.phpt
index bc6829cba5..bf9b390def 100644
--- a/ext/phar/tests/cache_list/frontcontroller8.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller8.phpt
@@ -2,7 +2,6 @@
Phar front controller no index file 404 [cache_list]
--INI--
phar.cache_list={PWD}/frontcontroller8.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -21,4 +20,4 @@ Status: 404 Not Found
<body>
<h1>404 - File /index.php Not Found</h1>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ext/phar/tests/cache_list/frontcontroller9.phpt b/ext/phar/tests/cache_list/frontcontroller9.phpt
index fb6f72ac22..1a8b9168cc 100644
--- a/ext/phar/tests/cache_list/frontcontroller9.phpt
+++ b/ext/phar/tests/cache_list/frontcontroller9.phpt
@@ -3,7 +3,6 @@ Phar front controller rewrite array [cache_list]
--INI--
default_charset=UTF-8
phar.cache_list={PWD}/frontcontroller9.php
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -18,4 +17,4 @@ Content-type: text/html; charset=UTF-8
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">hio</span><span style="color: #007700">(){}</span>
</span>
-</code>
+</code> \ No newline at end of file
diff --git a/ext/phar/tests/delete.phpt b/ext/phar/tests/delete.phpt
index f91b11b3d5..1d98509064 100644
--- a/ext/phar/tests/delete.phpt
+++ b/ext/phar/tests/delete.phpt
@@ -5,7 +5,6 @@ Phar: delete test
--INI--
phar.readonly=0
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -29,4 +28,4 @@ echo file_get_contents($pname . '/a') . "\n";
--EXPECTF--
a
-Warning: file_get_contents(phar://%sdelete.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%sdelete.phar.php" in %sdelete.php on line 16
+Warning: file_get_contents(phar://%sdelete.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%sdelete.phar.php" in %sdelete.php on line 16 \ No newline at end of file
diff --git a/ext/phar/tests/fatal_error_webphar.phpt b/ext/phar/tests/fatal_error_webphar.phpt
index 36b3fba122..dd6e0961a9 100644
--- a/ext/phar/tests/fatal_error_webphar.phpt
+++ b/ext/phar/tests/fatal_error_webphar.phpt
@@ -2,7 +2,6 @@
Phar web-based phar with fatal error
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -16,4 +15,4 @@ Content-type: text/html; charset=UTF-8
--EXPECTF--
string(9) "\Web\View"
-Parse error: syntax error, unexpected T_ECHO, expecting T_FUNCTION in phar://%sfatal_error_webphar.php/Web/View.php on line 380
+Parse error: syntax error, unexpected %s, expecting %s in phar://%r([A-Za-z]:)?%r/%sfatal_error_webphar.php/Web/View.php on line 380
diff --git a/ext/phar/tests/fgc_edgecases.phpt b/ext/phar/tests/fgc_edgecases.phpt
index 5b85d0dcf2..2699834eb0 100644
--- a/ext/phar/tests/fgc_edgecases.phpt
+++ b/ext/phar/tests/fgc_edgecases.phpt
@@ -33,7 +33,6 @@ echo file_get_contents("foob", true);
echo file_get_contents("./hi", 0, $context);
echo file_get_contents("../oops");
echo file_get_contents("./hi", 0, $context, 50000);
-ini_set("magic_quotes_runtime", 1);
echo file_get_contents("./hi");
echo file_get_contents("./hi", 0, $context, 0, 0);
?>
@@ -48,7 +47,7 @@ include $pname . '/foo/hi';
<?php rmdir(dirname(__FILE__) . '/poo'); ?>
<?php unlink(dirname(__FILE__) . '/foob'); ?>
--EXPECTF--
-Warning: file_get_contents() expects parameter 1 to be string, array given in %sfgc_edgecases.php on line %d
+Warning: file_get_contents() expects parameter 1 to be a valid path, array given in %sfgc_edgecases.php on line %d
blah
<?php
echo file_get_contents("foo/" . basename(__FILE__));
@@ -60,7 +59,6 @@ echo file_get_contents("foob", true);
echo file_get_contents("./hi", 0, $context);
echo file_get_contents("../oops");
echo file_get_contents("./hi", 0, $context, 50000);
-ini_set("magic_quotes_runtime", 1);
echo file_get_contents("./hi");
echo file_get_contents("./hi", 0, $context, 0, 0);
?>
@@ -78,7 +76,6 @@ echo file_get_contents("foob", true);
echo file_get_contents("./hi", 0, $context);
echo file_get_contents("../oops");
echo file_get_contents("./hi", 0, $context, 50000);
-ini_set("magic_quotes_runtime", 1);
echo file_get_contents("./hi");
echo file_get_contents("./hi", 0, $context, 0, 0);
?>
@@ -87,17 +84,16 @@ Warning: file_get_contents(phar://%sfgc_edgecases.phar.php/oops): failed to open
Warning: file_get_contents(): Failed to seek to position 50000 in the stream in phar://%sfgc_edgecases.phar.php/foo/hi on line %d
<?php
-echo file_get_contents(\"foo/\" . basename(__FILE__));
+echo file_get_contents("foo/" . basename(__FILE__));
$context = stream_context_create();
-file_get_contents(\"./hi\", 0, $context, 0, -1);
-echo file_get_contents(\"foob\");
-set_include_path(\"%stests\");
-echo file_get_contents(\"foob\", true);
-echo file_get_contents(\"./hi\", 0, $context);
-echo file_get_contents(\"../oops\");
-echo file_get_contents(\"./hi\", 0, $context, 50000);
-ini_set(\"magic_quotes_runtime\", 1);
-echo file_get_contents(\"./hi\");
-echo file_get_contents(\"./hi\", 0, $context, 0, 0);
+file_get_contents("./hi", 0, $context, 0, -1);
+echo file_get_contents("foob");
+set_include_path("%stests");
+echo file_get_contents("foob", true);
+echo file_get_contents("./hi", 0, $context);
+echo file_get_contents("../oops");
+echo file_get_contents("./hi", 0, $context, 50000);
+echo file_get_contents("./hi");
+echo file_get_contents("./hi", 0, $context, 0, 0);
?>
===DONE===
diff --git a/ext/phar/tests/file_get_contents.phpt b/ext/phar/tests/file_get_contents.phpt
index b931176e50..fcc9d64655 100644
--- a/ext/phar/tests/file_get_contents.phpt
+++ b/ext/phar/tests/file_get_contents.phpt
@@ -5,7 +5,6 @@ Phar: test file_get_contents() interception
--INI--
phar.require_hash=1
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -28,4 +27,4 @@ include $fname;
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECT--
-hihi===DONE===
+hihi===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/files/stuboflength1041.phar.inc b/ext/phar/tests/files/stuboflength1041.phar.inc
index 4a26a41a09..28ce8427f3 100644
--- a/ext/phar/tests/files/stuboflength1041.phar.inc
+++ b/ext/phar/tests/files/stuboflength1041.phar.inc
@@ -18,25 +18,4 @@ $phar->setStub('<?php
************************************************************************************************
************************************************************************************************
*********************************************/
-__HALT_COMPILER();');
-<?php
-
-@unlink(__DIR__ . '/stuboflength1041.phar');
-
-$phar = new Phar('./stuboflength1041.phar');
-$phar['a.php'] = 'hi1';
-$phar['b.php'] = 'hi2';
-
-$phar->setStub('<?php
-/***stub of length 1041 including the halt compiler*********************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-************************************************************************************************
-*********************************************/
__HALT_COMPILER();'); \ No newline at end of file
diff --git a/ext/phar/tests/fopen.phpt b/ext/phar/tests/fopen.phpt
index b10bcb3a53..5b694d6e2d 100644
--- a/ext/phar/tests/fopen.phpt
+++ b/ext/phar/tests/fopen.phpt
@@ -6,7 +6,6 @@ Phar: test fopen() interception
--INI--
phar.require_hash=1
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
Phar::interceptFileFuncs();
@@ -41,4 +40,4 @@ include $fname;
Warning: fopen() expects at least 2 parameters, 0 given in %sfopen.php on line %d
hihi
Warning: fopen(notfound.txt): failed to open stream: No such file or directory in phar://%sfopen.phar.php/index.php on line %d
-===DONE===
+===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/fopen_edgecases2.phpt b/ext/phar/tests/fopen_edgecases2.phpt
index c7ccd34afe..d55c97d228 100644
--- a/ext/phar/tests/fopen_edgecases2.phpt
+++ b/ext/phar/tests/fopen_edgecases2.phpt
@@ -36,7 +36,7 @@ include $pname . '/foo/hi';
<?php rmdir(dirname(__FILE__) . '/poo'); ?>
<?php unlink(dirname(__FILE__) . '/foob'); ?>
--EXPECTF--
-Warning: fopen() expects parameter 1 to be string, array given in %sfopen_edgecases2.php on line %d
+Warning: fopen() expects parameter 1 to be a valid path, array given in %sfopen_edgecases2.php on line %d
blah
test
diff --git a/ext/phar/tests/front.phar.phpt b/ext/phar/tests/front.phar.phpt
index 4009b491f5..bab8ada0fd 100644
--- a/ext/phar/tests/front.phar.phpt
+++ b/ext/phar/tests/front.phar.phpt
@@ -2,7 +2,6 @@
Phar front controller with mounted external file
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller1.phpt b/ext/phar/tests/frontcontroller1.phpt
index 0186b12529..7093323617 100644
--- a/ext/phar/tests/frontcontroller1.phpt
+++ b/ext/phar/tests/frontcontroller1.phpt
@@ -2,8 +2,6 @@
Phar front controller other
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller1.php
REQUEST_URI=/frontcontroller1.php/a.jpg
diff --git a/ext/phar/tests/frontcontroller10.phpt b/ext/phar/tests/frontcontroller10.phpt
index b6a0b488f6..667d5c243c 100644
--- a/ext/phar/tests/frontcontroller10.phpt
+++ b/ext/phar/tests/frontcontroller10.phpt
@@ -2,7 +2,6 @@
Phar front controller rewrite access denied
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller12.phpt b/ext/phar/tests/frontcontroller12.phpt
index b85b2f716b..956ea1c050 100644
--- a/ext/phar/tests/frontcontroller12.phpt
+++ b/ext/phar/tests/frontcontroller12.phpt
@@ -2,7 +2,6 @@
Phar front controller mime type unknown int
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -18,4 +17,4 @@ Fatal error: Uncaught exception 'PharException' with message 'Unknown mime type
Stack trace:
#0 %sfrontcontroller12.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller12.php on line 2
+ thrown in %sfrontcontroller12.php on line 2 \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller13.phpt b/ext/phar/tests/frontcontroller13.phpt
index cde41f7cdd..717e56996f 100644
--- a/ext/phar/tests/frontcontroller13.phpt
+++ b/ext/phar/tests/frontcontroller13.phpt
@@ -2,7 +2,6 @@
Phar front controller mime type not string/int
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -18,4 +17,4 @@ Fatal error: Uncaught exception 'PharException' with message 'Unknown mime type
Stack trace:
#0 %sfrontcontroller13.php(2): Phar::webPhar('whatever', 'index.php', '', Array)
#1 {main}
- thrown in %sfrontcontroller13.php on line 2
+ thrown in %sfrontcontroller13.php on line 2 \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller14.phpt b/ext/phar/tests/frontcontroller14.phpt
index 13de43f426..2bdb145c6e 100644
--- a/ext/phar/tests/frontcontroller14.phpt
+++ b/ext/phar/tests/frontcontroller14.phpt
@@ -2,8 +2,6 @@
Phar front controller mime type override, other
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller14.php
REQUEST_URI=/frontcontroller14.php/a.jpg
diff --git a/ext/phar/tests/frontcontroller15.phpt b/ext/phar/tests/frontcontroller15.phpt
index 8dbf144618..370098014d 100644
--- a/ext/phar/tests/frontcontroller15.phpt
+++ b/ext/phar/tests/frontcontroller15.phpt
@@ -2,7 +2,6 @@
Phar front controller mime type override, Phar::PHPS
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller16.phpt b/ext/phar/tests/frontcontroller16.phpt
index 8b0499b4b4..712af40bf3 100644
--- a/ext/phar/tests/frontcontroller16.phpt
+++ b/ext/phar/tests/frontcontroller16.phpt
@@ -2,7 +2,6 @@
Phar front controller mime type override, Phar::PHP
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller17.phpt b/ext/phar/tests/frontcontroller17.phpt
index ce8cda4642..233e2e2a49 100644
--- a/ext/phar/tests/frontcontroller17.phpt
+++ b/ext/phar/tests/frontcontroller17.phpt
@@ -2,8 +2,6 @@
Phar front controller mime type unknown
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller17.php
REQUEST_URI=/frontcontroller17.php/fronk.gronk
diff --git a/ext/phar/tests/frontcontroller18.phpt b/ext/phar/tests/frontcontroller18.phpt
index 3d867070ab..19aea45563 100644
--- a/ext/phar/tests/frontcontroller18.phpt
+++ b/ext/phar/tests/frontcontroller18.phpt
@@ -2,8 +2,6 @@
Phar front controller $_SERVER munging failure
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller18.php
REQUEST_URI=/frontcontroller18.php/fronk.gronk
diff --git a/ext/phar/tests/frontcontroller19.phpt b/ext/phar/tests/frontcontroller19.phpt
index 8c72e47056..9adafa2b30 100644
--- a/ext/phar/tests/frontcontroller19.phpt
+++ b/ext/phar/tests/frontcontroller19.phpt
@@ -2,8 +2,6 @@
Phar front controller $_SERVER munging failure 2
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller19.php
REQUEST_URI=/frontcontroller19.php/
diff --git a/ext/phar/tests/frontcontroller2.phpt b/ext/phar/tests/frontcontroller2.phpt
index 987a04ea99..d0744dea1d 100644
--- a/ext/phar/tests/frontcontroller2.phpt
+++ b/ext/phar/tests/frontcontroller2.phpt
@@ -2,7 +2,6 @@
Phar front controller PHP test
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller20.phpt b/ext/phar/tests/frontcontroller20.phpt
index bf87cd9688..45e2bfc25e 100644
--- a/ext/phar/tests/frontcontroller20.phpt
+++ b/ext/phar/tests/frontcontroller20.phpt
@@ -2,8 +2,6 @@
Phar front controller $_SERVER munging failure 3
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller20.php
REQUEST_URI=/frontcontroller20.php/
diff --git a/ext/phar/tests/frontcontroller21.phpt b/ext/phar/tests/frontcontroller21.phpt
index 1c61ceb602..bf50c6e801 100644
--- a/ext/phar/tests/frontcontroller21.phpt
+++ b/ext/phar/tests/frontcontroller21.phpt
@@ -2,7 +2,6 @@
Phar front controller $_SERVER munging success
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -22,4 +21,4 @@ string(18) "/index.php?test=hi"
string(32) "/frontcontroller21.php/index.php"
string(22) "/frontcontroller21.php"
string(%d) "%sfrontcontroller21.php"
-string(40) "/frontcontroller21.php/index.php?test=hi"
+string(40) "/frontcontroller21.php/index.php?test=hi" \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller22.phpt b/ext/phar/tests/frontcontroller22.phpt
index f19c88b595..b85c1eb497 100644
--- a/ext/phar/tests/frontcontroller22.phpt
+++ b/ext/phar/tests/frontcontroller22.phpt
@@ -2,7 +2,6 @@
Phar front controller include from cwd test 1
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -19,4 +18,4 @@ Content-type: text/html; charset=UTF-8
Warning: include(./hi.php): failed to open stream: No such file or directory in phar://%s/oof/test.php on line %d
-Warning: include(): Failed opening './hi.php' for inclusion (include_path='%s') in phar://%soof/test.php on line %d
+Warning: include(): Failed opening './hi.php' for inclusion (include_path='%s') in phar://%soof/test.php on line %d \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller23.phpt b/ext/phar/tests/frontcontroller23.phpt
index 4a676028b2..24464c9beb 100644
--- a/ext/phar/tests/frontcontroller23.phpt
+++ b/ext/phar/tests/frontcontroller23.phpt
@@ -2,7 +2,6 @@
Phar front controller with generic action router test
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -15,4 +14,4 @@ files/frontcontroller14.phar
Content-type: text/html; charset=UTF-8
--EXPECTF--
string(9) "/hi/there"
-string(%d) "phar://%sfrontcontroller23.php/html/index.php"
+string(%d) "phar://%sfrontcontroller23.php/html/index.php" \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller24.phpt b/ext/phar/tests/frontcontroller24.phpt
index 8d60ce2f7c..767971ee91 100644
--- a/ext/phar/tests/frontcontroller24.phpt
+++ b/ext/phar/tests/frontcontroller24.phpt
@@ -2,7 +2,6 @@
Phar front controller with custom 404 php script
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: text/html; charset=UTF-8
--EXPECTF--
-My 404 is rawesome
+My 404 is rawesome \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller25.phpt b/ext/phar/tests/frontcontroller25.phpt
index da4e58b49a..9b383de413 100644
--- a/ext/phar/tests/frontcontroller25.phpt
+++ b/ext/phar/tests/frontcontroller25.phpt
@@ -2,7 +2,6 @@
Phar front controller with extra path_info
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -15,4 +14,4 @@ files/frontcontroller8.phar
Content-type: text/html; charset=UTF-8
--EXPECTF--
string(42) "/frontcontroller25.php/a1.phps/extra/stuff"
-string(12) "/extra/stuff"
+string(12) "/extra/stuff" \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller26.phpt b/ext/phar/tests/frontcontroller26.phpt
index 9c5a14d512..a8097b0886 100644
--- a/ext/phar/tests/frontcontroller26.phpt
+++ b/ext/phar/tests/frontcontroller26.phpt
@@ -2,8 +2,6 @@
Phar front controller with unknown extension mime type
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller26.php
REQUEST_URI=/frontcontroller26.php/unknown.ext
@@ -13,4 +11,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: application/octet-stream
--EXPECTF--
-<?php var_dump("hi");
+<?php var_dump("hi"); \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller27.phpt b/ext/phar/tests/frontcontroller27.phpt
index f12d7f4538..16203f6feb 100644
--- a/ext/phar/tests/frontcontroller27.phpt
+++ b/ext/phar/tests/frontcontroller27.phpt
@@ -2,7 +2,6 @@
Phar front controller with no extension
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: text/plain;charset=UTF-8
--EXPECTF--
-hi
+hi \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller28.phpt b/ext/phar/tests/frontcontroller28.phpt
index 5871f327a2..577800885b 100644
--- a/ext/phar/tests/frontcontroller28.phpt
+++ b/ext/phar/tests/frontcontroller28.phpt
@@ -2,7 +2,6 @@
Phar front controller with huge file
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller29.phpt b/ext/phar/tests/frontcontroller29.phpt
index 61f9b1bfc1..0afc17929f 100644
--- a/ext/phar/tests/frontcontroller29.phpt
+++ b/ext/phar/tests/frontcontroller29.phpt
@@ -2,7 +2,6 @@
Phar front controller with fatal error in php file
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -14,4 +13,4 @@ files/frontcontroller8.phar
--EXPECTHEADERS--
Content-type: text/html; charset=UTF-8
--EXPECTF--
-Fatal error: Call to undefined function oopsie_daisy() in phar://%sfatalerror.phps on line 1
+Fatal error: Call to undefined function oopsie_daisy() in phar://%sfatalerror.phps on line 1 \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller3.phpt b/ext/phar/tests/frontcontroller3.phpt
index 6d025aec29..ac36485837 100644
--- a/ext/phar/tests/frontcontroller3.phpt
+++ b/ext/phar/tests/frontcontroller3.phpt
@@ -2,7 +2,6 @@
Phar front controller phps
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller30.phpt b/ext/phar/tests/frontcontroller30.phpt
index 9b38bccd4f..de6960c244 100644
--- a/ext/phar/tests/frontcontroller30.phpt
+++ b/ext/phar/tests/frontcontroller30.phpt
@@ -2,8 +2,6 @@
Phar front controller with weird SCRIPT_NAME
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/huh?
REQUEST_URI=/huh?
@@ -11,4 +9,4 @@ REQUEST_URI=/huh?
files/frontcontroller8.phar
--EXPECTF--
oops did not run
-%a
+%a \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller31.phpt b/ext/phar/tests/frontcontroller31.phpt
index 4995da74ef..13c305d2f3 100644
--- a/ext/phar/tests/frontcontroller31.phpt
+++ b/ext/phar/tests/frontcontroller31.phpt
@@ -2,7 +2,6 @@
Phar front controller with invalid callback for rewrites
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -13,4 +12,4 @@ Content-type: text/html; charset=UTF-8
--FILE_EXTERNAL--
files/frontcontroller16.phar
--EXPECT--
-phar error: invalid rewrite callback
+phar error: invalid rewrite callback \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller32.phpt b/ext/phar/tests/frontcontroller32.phpt
index 2459312dc5..58f6fffa00 100644
--- a/ext/phar/tests/frontcontroller32.phpt
+++ b/ext/phar/tests/frontcontroller32.phpt
@@ -2,7 +2,6 @@
Phar front controller with valid callback that is not good
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -13,4 +12,4 @@ Content-type: text/html; charset=UTF-8
--FILE_EXTERNAL--
files/frontcontroller17.phar
--EXPECTF--
-%ahar error: failed to call rewrite callback
+%ahar error: failed to call rewrite callback \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller33.phpt b/ext/phar/tests/frontcontroller33.phpt
index 58611080da..8593e31766 100644
--- a/ext/phar/tests/frontcontroller33.phpt
+++ b/ext/phar/tests/frontcontroller33.phpt
@@ -2,7 +2,6 @@
Phar front controller with valid callback that does not return any value
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -13,4 +12,4 @@ Content-type: text/html; charset=UTF-8
--FILE_EXTERNAL--
files/frontcontroller18.phar
--EXPECTF--
-phar error: rewrite callback must return a string or false
+phar error: rewrite callback must return a string or false \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller34.phpt b/ext/phar/tests/frontcontroller34.phpt
index bf1cf7f244..34a49ded4d 100644
--- a/ext/phar/tests/frontcontroller34.phpt
+++ b/ext/phar/tests/frontcontroller34.phpt
@@ -2,7 +2,6 @@
Phar front controller with cwd
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
diff --git a/ext/phar/tests/frontcontroller4.phpt b/ext/phar/tests/frontcontroller4.phpt
index d1cb2a4c63..f2482b9219 100644
--- a/ext/phar/tests/frontcontroller4.phpt
+++ b/ext/phar/tests/frontcontroller4.phpt
@@ -2,8 +2,6 @@
Phar front controller index.php relocate (no /)
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller4.php
REQUEST_URI=/frontcontroller4.php
diff --git a/ext/phar/tests/frontcontroller5.phpt b/ext/phar/tests/frontcontroller5.phpt
index 48771efc8f..1990a2b008 100644
--- a/ext/phar/tests/frontcontroller5.phpt
+++ b/ext/phar/tests/frontcontroller5.phpt
@@ -2,8 +2,6 @@
Phar front controller index.php relocate
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller5.php
REQUEST_URI=/frontcontroller5.php/
diff --git a/ext/phar/tests/frontcontroller6.phpt b/ext/phar/tests/frontcontroller6.phpt
index 1ab4e20032..1a2cc2cd23 100644
--- a/ext/phar/tests/frontcontroller6.phpt
+++ b/ext/phar/tests/frontcontroller6.phpt
@@ -2,8 +2,6 @@
Phar front controller 404
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller6.php
REQUEST_URI=/frontcontroller6.php/notfound.php
@@ -20,4 +18,4 @@ Status: 404 Not Found
<body>
<h1>404 - File /notfound.php Not Found</h1>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller7.phpt b/ext/phar/tests/frontcontroller7.phpt
index c30a366e37..aff2087522 100644
--- a/ext/phar/tests/frontcontroller7.phpt
+++ b/ext/phar/tests/frontcontroller7.phpt
@@ -2,8 +2,6 @@
Phar front controller alternate index file
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller7.php
REQUEST_URI=/frontcontroller7.php/
diff --git a/ext/phar/tests/frontcontroller8.phpt b/ext/phar/tests/frontcontroller8.phpt
index 88312c4061..36e3206d66 100644
--- a/ext/phar/tests/frontcontroller8.phpt
+++ b/ext/phar/tests/frontcontroller8.phpt
@@ -2,8 +2,6 @@
Phar front controller no index file 404
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--ENV--
SCRIPT_NAME=/frontcontroller8.php
REQUEST_URI=/frontcontroller8.php/
@@ -20,4 +18,4 @@ Status: 404 Not Found
<body>
<h1>404 - File /index.php Not Found</h1>
</body>
-</html>
+</html> \ No newline at end of file
diff --git a/ext/phar/tests/frontcontroller9.phpt b/ext/phar/tests/frontcontroller9.phpt
index 36cf2713cb..d47a2898e6 100644
--- a/ext/phar/tests/frontcontroller9.phpt
+++ b/ext/phar/tests/frontcontroller9.phpt
@@ -2,7 +2,6 @@
Phar front controller rewrite array
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--ENV--
@@ -17,4 +16,4 @@ Content-type: text/html; charset=UTF-8
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">hio</span><span style="color: #007700">(){}</span>
</span>
-</code>
+</code> \ No newline at end of file
diff --git a/ext/phar/tests/include_path_advanced.phpt b/ext/phar/tests/include_path_advanced.phpt
index 81e528130c..6feee422b4 100644
--- a/ext/phar/tests/include_path_advanced.phpt
+++ b/ext/phar/tests/include_path_advanced.phpt
@@ -2,7 +2,6 @@
Phar: include_path advanced code coverage test
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
--FILE_EXTERNAL--
@@ -10,4 +9,4 @@ files/include_path.phar
--EXPECT--
file1.php
test/file1.php
-ok
+ok \ No newline at end of file
diff --git a/ext/phar/tests/mounteddir.phpt b/ext/phar/tests/mounteddir.phpt
index b9bf58922f..e1308956fe 100644
--- a/ext/phar/tests/mounteddir.phpt
+++ b/ext/phar/tests/mounteddir.phpt
@@ -7,7 +7,6 @@ if (version_compare(PHP_VERSION, "6.0", ">")) die("skip pre-unicode version of P
?>
--INI--
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/tempmanifest1.phar.php';
diff --git a/ext/phar/tests/opendir.phpt b/ext/phar/tests/opendir.phpt
index e8253bbc33..ca6e391b06 100644
--- a/ext/phar/tests/opendir.phpt
+++ b/ext/phar/tests/opendir.phpt
@@ -5,7 +5,6 @@ Phar: test opendir() interception
--INI--
phar.require_hash=1
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -42,4 +41,4 @@ phar url "phar://" is unknown in %sopendir.php on line %d
Warning: opendir(phar://hi.phar): failed to open dir: phar error: invalid url or non-existent phar "phar://hi.phar"
phar url "phar://hi.phar" is unknown in %sopendir.php on line %d
-===DONE===
+===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/opendir_edgecases.phpt b/ext/phar/tests/opendir_edgecases.phpt
index c0f5ebc067..be899df81b 100644
--- a/ext/phar/tests/opendir_edgecases.phpt
+++ b/ext/phar/tests/opendir_edgecases.phpt
@@ -52,10 +52,10 @@ include $pname . '/foo';
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
<?php rmdir(dirname(__FILE__) . '/poo');
--EXPECTF--
-Warning: opendir() expects parameter 1 to be %string, array given in %sopendir_edgecases.php on line %d
+Warning: opendir() expects parameter 1 to be a valid path, array given in %sopendir_edgecases.php on line %d
.
..
foo
Warning: opendir(phar://%sopendir_edgecases.phar.php/oops): failed to open dir: %s in phar://%sopendir_edgecases.phar.php/foo on line %d
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/phar/tests/phar_gobyebye.phpt b/ext/phar/tests/phar_gobyebye.phpt
index 608e950768..93e153bdf2 100644
--- a/ext/phar/tests/phar_gobyebye.phpt
+++ b/ext/phar/tests/phar_gobyebye.phpt
@@ -44,4 +44,4 @@ bool(false)
bool(false)
Warning: opendir(foo/hi): failed to open dir: No such file or directory in phar://%sphar_gobyebye.phar.php/foo/hi on line %d
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/phar/tests/phar_gzip.phpt b/ext/phar/tests/phar_gzip.phpt
index 472a9a2d24..c722834ba6 100644
--- a/ext/phar/tests/phar_gzip.phpt
+++ b/ext/phar/tests/phar_gzip.phpt
@@ -11,7 +11,6 @@ if (version_compare(phpversion(), '5.2.6', '<')) die("skip zlib is buggy in PHP
--INI--
phar.readonly=0
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/phar_gzip.phar';
@@ -60,4 +59,4 @@ string(9) "it worked"
string(%d) "phar://%sphar_gzip.phar/tar_004.php"
bool(true)
bool(true)
-===DONE===
+===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/phar_magic.phpt b/ext/phar/tests/phar_magic.phpt
index 3663d6e635..7c60589f9f 100644
--- a/ext/phar/tests/phar_magic.phpt
+++ b/ext/phar/tests/phar_magic.phpt
@@ -5,7 +5,6 @@ Phar: include/fopen magic
--INI--
phar.require_hash=0
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/phar_mount.phpt b/ext/phar/tests/phar_mount.phpt
index 903e4a7bd6..73bd489a2d 100644
--- a/ext/phar/tests/phar_mount.phpt
+++ b/ext/phar/tests/phar_mount.phpt
@@ -4,7 +4,6 @@ Phar: Phar::mount
<?php if (!extension_loaded("phar")) die("skip"); ?>
--INI--
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/readfile.phpt b/ext/phar/tests/readfile.phpt
index ced02b1ae9..60fdad1792 100644
--- a/ext/phar/tests/readfile.phpt
+++ b/ext/phar/tests/readfile.phpt
@@ -5,7 +5,6 @@ Phar: test readfile() interception
--INI--
phar.require_hash=1
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -28,4 +27,4 @@ include $fname;
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECT--
-hihi===DONE===
+hihi===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/readfile_edgecases.phpt b/ext/phar/tests/readfile_edgecases.phpt
index 2c93c8b221..3cf69edb9a 100644
--- a/ext/phar/tests/readfile_edgecases.phpt
+++ b/ext/phar/tests/readfile_edgecases.phpt
@@ -36,7 +36,7 @@ include $pname . '/foo/hi';
<?php rmdir(dirname(__FILE__) . '/poo'); ?>
<?php unlink(dirname(__FILE__) . '/foob'); ?>
--EXPECTF--
-Warning: readfile() expects parameter 1 to be string, array given in %sreadfile_edgecases.php on line %d
+Warning: readfile() expects parameter 1 to be a valid path, array given in %sreadfile_edgecases.php on line %d
blah
<?php
readfile("foo/" . basename(__FILE__));
@@ -60,4 +60,4 @@ readfile("../oops");
?>
Warning: readfile(phar://%sreadfile_edgecases.phar.php/oops): failed to open stream: phar error: path "oops" is a directory in phar://%sreadfile_edgecases.phar.php/foo/hi on line %d
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/phar/tests/rename.phpt b/ext/phar/tests/rename.phpt
index 2f12540589..c73c98ec81 100644
--- a/ext/phar/tests/rename.phpt
+++ b/ext/phar/tests/rename.phpt
@@ -5,7 +5,6 @@ Phar: rename test
--INI--
phar.readonly=0
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -30,4 +29,4 @@ echo file_get_contents($pname . '/a') . "\n";
a
a
-Warning: file_get_contents(phar://%srename.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.php" in %srename.php on line %d
+Warning: file_get_contents(phar://%srename.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.php" in %srename.php on line %d \ No newline at end of file
diff --git a/ext/phar/tests/rename_dir.phpt b/ext/phar/tests/rename_dir.phpt
index f2d11dc947..d19a37f70f 100644
--- a/ext/phar/tests/rename_dir.phpt
+++ b/ext/phar/tests/rename_dir.phpt
@@ -5,7 +5,6 @@ Phar: rename_dir test
--INI--
phar.readonly=0
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
diff --git a/ext/phar/tests/rename_dir_and_mount.phpt b/ext/phar/tests/rename_dir_and_mount.phpt
index 3a4df6283b..b74f47b91d 100644
--- a/ext/phar/tests/rename_dir_and_mount.phpt
+++ b/ext/phar/tests/rename_dir_and_mount.phpt
@@ -5,7 +5,6 @@ Phar: rename_dir and mount test
--INI--
phar.readonly=0
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/rmdir.phpt b/ext/phar/tests/rmdir.phpt
index ffbe1563dc..726e2cfbac 100644
--- a/ext/phar/tests/rmdir.phpt
+++ b/ext/phar/tests/rmdir.phpt
@@ -5,7 +5,6 @@ Phar: rmdir test
--INI--
phar.readonly=0
phar.require_hash=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
diff --git a/ext/phar/tests/security.phpt b/ext/phar/tests/security.phpt
index 0867cb42f7..f2944da413 100644
--- a/ext/phar/tests/security.phpt
+++ b/ext/phar/tests/security.phpt
@@ -4,7 +4,6 @@ Phar: test to ensure phar.readonly cannot be circumvented
<?php if (!extension_loaded("phar")) die("skip");?>
--INI--
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
@@ -34,4 +33,4 @@ include $fname2;
--EXPECT--
bool(false)
Write operations disabled by the php.ini setting phar.readonly
-===DONE===
+===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/stat.phpt b/ext/phar/tests/stat.phpt
index a3c8491aee..184aa6d2ec 100644
--- a/ext/phar/tests/stat.phpt
+++ b/ext/phar/tests/stat.phpt
@@ -5,7 +5,6 @@ Phar: test stat function interceptions
--INI--
phar.require_hash=1
phar.readonly=0
-detect_unicode=0
--FILE--
<?php
Phar::interceptFileFuncs();
@@ -223,4 +222,4 @@ not found 2
Warning: fileperms(): stat failed for not/found in phar://%sstat.phar.php/my/index.php on line %d
bool(false)
-===DONE===
+===DONE=== \ No newline at end of file
diff --git a/ext/phar/tests/withphar.phpt b/ext/phar/tests/withphar.phpt
index b1af0eee51..c422fa9843 100644
--- a/ext/phar/tests/withphar.phpt
+++ b/ext/phar/tests/withphar.phpt
@@ -2,8 +2,6 @@
Phar: phar run with pecl/phar with default stub
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip"); ?>
---INI--
-detect_unicode=0
--FILE--
<?php
include dirname(__FILE__) . '/files/nophar.phar';
diff --git a/ext/phar/tests/withphar_web.phpt b/ext/phar/tests/withphar_web.phpt
index a3dbfd92e3..487873a134 100644
--- a/ext/phar/tests/withphar_web.phpt
+++ b/ext/phar/tests/withphar_web.phpt
@@ -2,10 +2,8 @@
Phar: default web stub, with phar extension
--INI--
default_charset=UTF-8
-detect_unicode=0
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip");?>
-detect_unicode=0
--ENV--
SCRIPT_NAME=/withphar_web.php
REQUEST_URI=/withphar_web.php/web.php
diff --git a/ext/phar/util.c b/ext/phar/util.c
index 08faaa65ef..f674bca4fb 100644
--- a/ext/phar/util.c
+++ b/ext/phar/util.c
@@ -156,7 +156,6 @@ int phar_seek_efp(phar_entry_info *entry, off_t offset, int whence, off_t positi
break;
default:
temp = 0;
- break;
}
if (temp > eoffset + (off_t) entry->uncompressed_filesize) {
@@ -272,7 +271,7 @@ char *phar_find_in_include_path(char *filename, int filename_len, phar_archive_d
return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
}
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
fname_len = strlen(fname);
if (PHAR_G(last_phar) && !memcmp(fname, "phar://", 7) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
@@ -364,7 +363,7 @@ splitted:
goto doit;
}
- fname = zend_get_executed_filename(TSRMLS_C);
+ fname = (char*)zend_get_executed_filename(TSRMLS_C);
if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
goto doit;
@@ -522,7 +521,7 @@ not_stream:
/* check in calling scripts' current working directory as a fall back case */
if (zend_is_executing(TSRMLS_C)) {
- char *exec_fname = zend_get_executed_filename(TSRMLS_C);
+ char *exec_fname = (char*)zend_get_executed_filename(TSRMLS_C);
int exec_fname_length = strlen(exec_fname);
const char *p;
int n = 0;
@@ -2230,7 +2229,7 @@ int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signat
void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC) /* {{{ */
{
- char *s;
+ const char *s;
while ((s = zend_memrchr(filename, '/', filename_len))) {
filename_len = s - filename;
diff --git a/ext/posix/posix.c b/ext/posix/posix.c
index c00b746500..967584c6fa 100644
--- a/ext/posix/posix.c
+++ b/ext/posix/posix.c
@@ -838,16 +838,11 @@ PHP_FUNCTION(posix_mkfifo)
long mode;
int result;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &path, &path_len, &mode) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl", &path, &path_len, &mode) == FAILURE) {
RETURN_FALSE;
}
- if (strlen(path) != path_len) {
- RETURN_FALSE;
- }
-
- if (php_check_open_basedir_ex(path, 0 TSRMLS_CC) ||
- (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_DIR)))) {
+ if (php_check_open_basedir_ex(path, 0 TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -876,17 +871,12 @@ PHP_FUNCTION(posix_mknod)
php_dev = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|ll", &path, &path_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl|ll", &path, &path_len,
&mode, &major, &minor) == FAILURE) {
RETURN_FALSE;
}
- if (strlen(path) != path_len) {
- RETURN_FALSE;
- }
-
- if (php_check_open_basedir_ex(path, 0 TSRMLS_CC) ||
- (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_DIR)))) {
+ if (php_check_open_basedir_ex(path, 0 TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -961,11 +951,7 @@ PHP_FUNCTION(posix_access)
int filename_len, ret;
char *filename, *path;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &mode) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &mode) == FAILURE) {
RETURN_FALSE;
}
@@ -975,8 +961,7 @@ PHP_FUNCTION(posix_access)
RETURN_FALSE;
}
- if (php_check_open_basedir_ex(path, 0 TSRMLS_CC) ||
- (PG(safe_mode) && (!php_checkuid_ex(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR, CHECKUID_NO_ERRORS)))) {
+ if (php_check_open_basedir_ex(path, 0 TSRMLS_CC)) {
efree(path);
POSIX_G(last_error) = EPERM;
RETURN_FALSE;
diff --git a/ext/posix/tests/posix_access.phpt b/ext/posix/tests/posix_access.phpt
index e585e67b47..47b5e15f0b 100644
--- a/ext/posix/tests/posix_access.phpt
+++ b/ext/posix/tests/posix_access.phpt
@@ -13,9 +13,10 @@ if (!extension_loaded('posix')) {
if (posix_geteuid() == 0) {
die('SKIP Cannot run test as root.');
}
+if (PHP_VERSION_ID < 503099) {
+ die('SKIP Safe mode is no longer available.');
+}
?>
---INI--
-safe_mode = 1
--FILE--
<?php
$filename = dirname(__FILE__) . '/foo.test';
diff --git a/ext/posix/tests/posix_access_error_modes.phpt b/ext/posix/tests/posix_access_error_modes.phpt
index 951ae01075..fb04e34683 100644
--- a/ext/posix/tests/posix_access_error_modes.phpt
+++ b/ext/posix/tests/posix_access_error_modes.phpt
@@ -13,9 +13,10 @@ if (!extension_loaded('posix')) {
if (posix_geteuid() == 0) {
die('SKIP Cannot run test as root.');
}
+if (PHP_VERSION_ID < 503099) {
+ die('SKIP Safe mode is no longer available.');
+}
?>
---INI--
-safe_mode = 1
--FILE--
<?php
$filename = dirname(__FILE__) . '/foo.test';
@@ -37,7 +38,7 @@ chmod ($filename, 0700);
unlink($filename);
?>
--EXPECTF--
-Deprecated: Directive 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line %d
+WDeprecated: Directive 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line %d
bool(false)
bool(false)
bool(false)
diff --git a/ext/posix/tests/posix_access_error_wrongparams.phpt b/ext/posix/tests/posix_access_error_wrongparams.phpt
index 111ec6c54d..35556a13af 100644
--- a/ext/posix/tests/posix_access_error_wrongparams.phpt
+++ b/ext/posix/tests/posix_access_error_wrongparams.phpt
@@ -13,9 +13,10 @@ if (!extension_loaded('posix')) {
if (posix_geteuid() == 0) {
die('SKIP Cannot run test as root.');
}
+if (PHP_VERSION_ID < 503099) {
+ die('SKIP Safe mode is no longer available.');
+}
?>
---INI--
-safe_mode = 1
--FILE--
<?php
diff --git a/ext/posix/tests/posix_access_safemode.phpt b/ext/posix/tests/posix_access_safemode.phpt
index ec0c3e8d8c..b726b4fdbb 100644
--- a/ext/posix/tests/posix_access_safemode.phpt
+++ b/ext/posix/tests/posix_access_safemode.phpt
@@ -11,8 +11,9 @@ if (!extension_loaded('posix')) {
if (posix_geteuid() == 0) {
die('SKIP Cannot run test as root.');
}
---INI--
-safe_mode = 1
+if (PHP_VERSION_ID < 503099) {
+ die('SKIP Safe mode is no longer available.');
+}
--FILE--
<?php
var_dump(posix_access('/tmp', POSIX_W_OK));
diff --git a/ext/posix/tests/posix_getgrgid_variation.phpt b/ext/posix/tests/posix_getgrgid_variation.phpt
index 13db73b791..5cce391d7b 100644
--- a/ext/posix/tests/posix_getgrgid_variation.phpt
+++ b/ext/posix/tests/posix_getgrgid_variation.phpt
@@ -103,26 +103,36 @@ valid output
Arg value 0.5
valid output
+Notice: Array to string conversion in %sposix_getgrgid_variation.php on line %d
+
Arg value Array
Warning: posix_getgrgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getgrgid_variation.php on line %d
+
Arg value Array
Warning: posix_getgrgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getgrgid_variation.php on line %d
+
Arg value Array
Warning: posix_getgrgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getgrgid_variation.php on line %d
+
Arg value Array
Warning: posix_getgrgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getgrgid_variation.php on line %d
+
Arg value Array
Warning: posix_getgrgid() expects parameter 1 to be long, array given in %s on line %d
diff --git a/ext/posix/tests/posix_getpgid_variation.phpt b/ext/posix/tests/posix_getpgid_variation.phpt
index e53d58f393..b9c92b539a 100644
--- a/ext/posix/tests/posix_getpgid_variation.phpt
+++ b/ext/posix/tests/posix_getpgid_variation.phpt
@@ -103,26 +103,36 @@ valid output
Arg value 0.5
valid output
+Notice: Array to string conversion in %sposix_getpgid_variation.php on line %d
+
Arg value Array
Warning: posix_getpgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpgid_variation.php on line %d
+
Arg value Array
Warning: posix_getpgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpgid_variation.php on line %d
+
Arg value Array
Warning: posix_getpgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpgid_variation.php on line %d
+
Arg value Array
Warning: posix_getpgid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpgid_variation.php on line %d
+
Arg value Array
Warning: posix_getpgid() expects parameter 1 to be long, array given in %s on line %d
diff --git a/ext/posix/tests/posix_getpwuid_variation.phpt b/ext/posix/tests/posix_getpwuid_variation.phpt
index 8e91d6c315..8b66f7f3d5 100644
--- a/ext/posix/tests/posix_getpwuid_variation.phpt
+++ b/ext/posix/tests/posix_getpwuid_variation.phpt
@@ -103,26 +103,36 @@ valid output
Arg value 0.5
valid output
+Notice: Array to string conversion in %sposix_getpwuid_variation.php on line %d
+
Arg value Array
Warning: posix_getpwuid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpwuid_variation.php on line %d
+
Arg value Array
Warning: posix_getpwuid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpwuid_variation.php on line %d
+
Arg value Array
Warning: posix_getpwuid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpwuid_variation.php on line %d
+
Arg value Array
Warning: posix_getpwuid() expects parameter 1 to be long, array given in %s on line %d
valid output
+Notice: Array to string conversion in %sposix_getpwuid_variation.php on line %d
+
Arg value Array
Warning: posix_getpwuid() expects parameter 1 to be long, array given in %s on line %d
diff --git a/ext/posix/tests/posix_kill_variation1.phpt b/ext/posix/tests/posix_kill_variation1.phpt
index 6fcf0fa98f..230977a9d0 100644
--- a/ext/posix/tests/posix_kill_variation1.phpt
+++ b/ext/posix/tests/posix_kill_variation1.phpt
@@ -97,26 +97,36 @@ bool(false)
Arg value 0.5
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation1.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 1 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation1.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 1 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation1.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 1 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation1.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 1 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation1.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 1 to be long, array given in %s on line %d
diff --git a/ext/posix/tests/posix_kill_variation2.phpt b/ext/posix/tests/posix_kill_variation2.phpt
index 240cfa57c1..c03ead9a4b 100644
--- a/ext/posix/tests/posix_kill_variation2.phpt
+++ b/ext/posix/tests/posix_kill_variation2.phpt
@@ -97,26 +97,36 @@ bool(false)
Arg value 0.5
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation2.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 2 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation2.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 2 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation2.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 2 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation2.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 2 to be long, array given in %s on line %d
bool(false)
+Notice: Array to string conversion in %sposix_kill_variation2.php on line %d
+
Arg value Array
Warning: posix_kill() expects parameter 2 to be long, array given in %s on line %d
diff --git a/ext/posix/tests/posix_mkfifo_safemode.phpt b/ext/posix/tests/posix_mkfifo_safemode.phpt
index 6f1f092497..1126c00df0 100644
--- a/ext/posix/tests/posix_mkfifo_safemode.phpt
+++ b/ext/posix/tests/posix_mkfifo_safemode.phpt
@@ -17,9 +17,10 @@ if (!extension_loaded('posix')) {
if (posix_geteuid() == 0) {
die('SKIP Cannot run test as root.');
}
+if (PHP_VERSION_ID < 503099) {
+ die('SKIP Safe mode is no longer available.');
+}
?>
---INI--
-safe_mode = 1
--FILE--
<?php
var_dump(posix_mkfifo('/tmp/foobar', 0644));
diff --git a/ext/posix/tests/posix_setgid_error.phpt b/ext/posix/tests/posix_setgid_error.phpt
index 247435d948..83d727c58a 100644
--- a/ext/posix/tests/posix_setgid_error.phpt
+++ b/ext/posix/tests/posix_setgid_error.phpt
@@ -1,6 +1,5 @@
--TEST--
Test function posix_setgid() by calling it more than or less than its expected arguments.
---CREDITS--
--SKIPIF--
<?php
if(!extension_loaded("posix")) print "skip - POSIX extension not loaded";
diff --git a/ext/posix/tests/posix_strerror_variation1.phpt b/ext/posix/tests/posix_strerror_variation1.phpt
index 5d6e354532..4d2b526716 100644
--- a/ext/posix/tests/posix_strerror_variation1.phpt
+++ b/ext/posix/tests/posix_strerror_variation1.phpt
@@ -96,26 +96,36 @@ string
Arg value 0.5
string
+Notice: Array to string conversion in %sposix_strerror_variation1.php on line %d
+
Arg value Array
Warning: posix_strerror() expects parameter 1 to be long, array given in %s on line %d
boolean
+Notice: Array to string conversion in %sposix_strerror_variation1.php on line %d
+
Arg value Array
Warning: posix_strerror() expects parameter 1 to be long, array given in %s on line %d
boolean
+Notice: Array to string conversion in %sposix_strerror_variation1.php on line %d
+
Arg value Array
Warning: posix_strerror() expects parameter 1 to be long, array given in %s on line %d
boolean
+Notice: Array to string conversion in %sposix_strerror_variation1.php on line %d
+
Arg value Array
Warning: posix_strerror() expects parameter 1 to be long, array given in %s on line %d
boolean
+Notice: Array to string conversion in %sposix_strerror_variation1.php on line %d
+
Arg value Array
Warning: posix_strerror() expects parameter 1 to be long, array given in %s on line %d
diff --git a/ext/posix/tests/posix_times_basic.phpt b/ext/posix/tests/posix_times_basic.phpt
index eb8af10df4..5da6434b14 100644
--- a/ext/posix/tests/posix_times_basic.phpt
+++ b/ext/posix/tests/posix_times_basic.phpt
@@ -24,14 +24,14 @@ Test posix_times() function : basic functionality
Basic test of POSIX times function
array(5) {
["ticks"]=>
- int(%d)
+ int(%i)
["utime"]=>
- int(%d)
+ int(%i)
["stime"]=>
- int(%d)
+ int(%i)
["cutime"]=>
- int(%d)
+ int(%i)
["cstime"]=>
- int(%d)
+ int(%i)
}
===DONE====
diff --git a/ext/pspell/pspell.c b/ext/pspell/pspell.c
index 962dba8ec6..f6c1ee074f 100644
--- a/ext/pspell/pspell.c
+++ b/ext/pspell/pspell.c
@@ -347,7 +347,7 @@ static PHP_FUNCTION(pspell_new)
}
manager = to_pspell_manager(ret);
- ind = zend_list_insert(manager, le_pspell);
+ ind = zend_list_insert(manager, le_pspell TSRMLS_CC);
RETURN_LONG(ind);
}
/* }}} */
@@ -374,7 +374,7 @@ static PHP_FUNCTION(pspell_new_personal)
PspellManager *manager;
PspellConfig *config;
- if (zend_parse_parameters(argc TSRMLS_CC, "ss|sssl", &personal, &personal_len, &language, &language_len,
+ if (zend_parse_parameters(argc TSRMLS_CC, "ps|sssl", &personal, &personal_len, &language, &language_len,
&spelling, &spelling_len, &jargon, &jargon_len, &encoding, &encoding_len, &mode) == FAILURE) {
return;
}
@@ -402,16 +402,6 @@ static PHP_FUNCTION(pspell_new_personal)
}
#endif
- if (strlen(personal) != personal_len) {
- delete_pspell_config(config);
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && (!php_checkuid(personal, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- delete_pspell_config(config);
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(personal TSRMLS_CC)) {
delete_pspell_config(config);
RETURN_FALSE;
@@ -462,7 +452,7 @@ static PHP_FUNCTION(pspell_new_personal)
}
manager = to_pspell_manager(ret);
- ind = zend_list_insert(manager, le_pspell);
+ ind = zend_list_insert(manager, le_pspell TSRMLS_CC);
RETURN_LONG(ind);
}
/* }}} */
@@ -492,7 +482,7 @@ static PHP_FUNCTION(pspell_new_config)
}
manager = to_pspell_manager(ret);
- ind = zend_list_insert(manager, le_pspell);
+ ind = zend_list_insert(manager, le_pspell TSRMLS_CC);
RETURN_LONG(ind);
}
/* }}} */
@@ -752,7 +742,7 @@ static PHP_FUNCTION(pspell_config_create)
which is not what we want */
pspell_config_replace(config, "save-repl", "false");
- ind = zend_list_insert(config, le_pspell_config);
+ ind = zend_list_insert(config, le_pspell_config TSRMLS_CC);
RETURN_LONG(ind);
}
/* }}} */
@@ -835,20 +825,12 @@ static void pspell_config_path(INTERNAL_FUNCTION_PARAMETERS, char *option)
int value_len;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &conf, &value, &value_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lp", &conf, &value, &value_len) == FAILURE) {
return;
}
- if (strlen(value) != value_len) {
- RETURN_FALSE;
- }
-
PSPELL_FETCH_CONFIG;
- if (PG(safe_mode) && (!php_checkuid(value, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(value TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -892,7 +874,7 @@ static PHP_FUNCTION(pspell_config_repl)
int repl_len;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &conf, &repl, &repl_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lp", &conf, &repl, &repl_len) == FAILURE) {
return;
}
@@ -900,14 +882,6 @@ static PHP_FUNCTION(pspell_config_repl)
pspell_config_replace(config, "save-repl", "true");
- if (strlen(repl) != repl_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && (!php_checkuid(repl, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(repl TSRMLS_CC)) {
RETURN_FALSE;
}
diff --git a/ext/readline/config.m4 b/ext/readline/config.m4
index a99262a659..b1cb0b67e8 100644
--- a/ext/readline/config.m4
+++ b/ext/readline/config.m4
@@ -60,6 +60,13 @@ if test "$PHP_READLINE" && test "$PHP_READLINE" != "no"; then
-L$READLINE_DIR/$PHP_LIBDIR $PHP_READLINE_LIBS
])
+ PHP_CHECK_LIBRARY(edit, rl_on_new_line,
+ [
+ AC_DEFINE(HAVE_RL_ON_NEW_LINE, 1, [ ])
+ ],[],[
+ -L$READLINE_DIR/$PHP_LIBDIR $PHP_READLINE_LIBS
+ ])
+
AC_DEFINE(HAVE_LIBREADLINE, 1, [ ])
elif test "$PHP_LIBEDIT" != "no"; then
@@ -93,11 +100,25 @@ elif test "$PHP_LIBEDIT" != "no"; then
-L$READLINE_DIR/$PHP_LIBDIR
])
+ PHP_CHECK_LIBRARY(edit, rl_callback_read_char,
+ [
+ AC_DEFINE(HAVE_RL_CALLBACK_READ_CHAR, 1, [ ])
+ ],[],[
+ -L$READLINE_DIR/$PHP_LIBDIR
+ ])
+
+ PHP_CHECK_LIBRARY(edit, rl_on_new_line,
+ [
+ AC_DEFINE(HAVE_RL_ON_NEW_LINE, 1, [ ])
+ ],[],[
+ -L$READLINE_DIR/$PHP_LIBDIR
+ ])
+
AC_DEFINE(HAVE_LIBEDIT, 1, [ ])
fi
if test "$PHP_READLINE" != "no" || test "$PHP_LIBEDIT" != "no"; then
AC_CHECK_FUNCS([rl_completion_matches])
- PHP_NEW_EXTENSION(readline, readline.c, $ext_shared, cli)
+ PHP_NEW_EXTENSION(readline, readline.c readline_cli.c, $ext_shared, cli)
PHP_SUBST(READLINE_SHARED_LIBADD)
fi
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 820e4b456a..92236a54f7 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -26,6 +26,7 @@
#include "php.h"
#include "php_readline.h"
+#include "readline_cli.h"
#if HAVE_LIBREADLINE || HAVE_LIBEDIT
@@ -66,7 +67,9 @@ static zval *_readline_completion = NULL;
static zval _readline_array;
PHP_MINIT_FUNCTION(readline);
+PHP_MSHUTDOWN_FUNCTION(readline);
PHP_RSHUTDOWN_FUNCTION(readline);
+PHP_MINFO_FUNCTION(readline);
/* }}} */
@@ -141,6 +144,8 @@ static const zend_function_entry php_readline_functions[] = {
PHP_FE(readline_callback_read_char, arginfo_readline_callback_read_char)
PHP_FE(readline_callback_handler_remove, arginfo_readline_callback_handler_remove)
PHP_FE(readline_redisplay, arginfo_readline_redisplay)
+#endif
+#if HAVE_RL_ON_NEW_LINE
PHP_FE(readline_on_new_line, arginfo_readline_on_new_line)
#endif
PHP_FE_END
@@ -151,11 +156,11 @@ zend_module_entry readline_module_entry = {
"readline",
php_readline_functions,
PHP_MINIT(readline),
- NULL,
+ PHP_MSHUTDOWN(readline),
NULL,
PHP_RSHUTDOWN(readline),
- NULL,
- NO_VERSION_YET,
+ PHP_MINFO(readline),
+ PHP_VERSION,
STANDARD_MODULE_PROPERTIES
};
@@ -166,7 +171,12 @@ ZEND_GET_MODULE(readline)
PHP_MINIT_FUNCTION(readline)
{
using_history();
- return SUCCESS;
+ return PHP_MINIT(cli_readline)(INIT_FUNC_ARGS_PASSTHRU);
+}
+
+PHP_MSHUTDOWN_FUNCTION(readline)
+{
+ return PHP_MSHUTDOWN(cli_readline)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
}
PHP_RSHUTDOWN_FUNCTION(readline)
@@ -186,6 +196,11 @@ PHP_RSHUTDOWN_FUNCTION(readline)
return SUCCESS;
}
+PHP_MINFO_FUNCTION(readline)
+{
+ PHP_MINFO(cli_readline)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
+}
+
/* }}} */
/* {{{ proto string readline([string prompt])
@@ -365,7 +380,7 @@ PHP_FUNCTION(readline_read_history)
char *arg = NULL;
int arg_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|p", &arg, &arg_len) == FAILURE) {
return;
}
@@ -389,7 +404,7 @@ PHP_FUNCTION(readline_write_history)
char *arg = NULL;
int arg_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|p", &arg, &arg_len) == FAILURE) {
return;
}
@@ -611,6 +626,9 @@ PHP_FUNCTION(readline_redisplay)
}
/* }}} */
+#endif
+
+#if HAVE_RL_ON_NEW_LINE
/* {{{ proto void readline_on_new_line(void)
Inform readline that the cursor has moved to a new line */
PHP_FUNCTION(readline_on_new_line)
diff --git a/sapi/cli/php_cli_readline.c b/ext/readline/readline_cli.c
index 2d6c7bb862..23e744e805 100644
--- a/sapi/cli/php_cli_readline.c
+++ b/ext/readline/readline_cli.c
@@ -21,8 +21,6 @@
#include "php.h"
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
-
#ifndef HAVE_RL_COMPLETION_MATCHES
#define rl_completion_matches completion_matches
#endif
@@ -44,6 +42,7 @@
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
+#include "ext/standard/php_smart_str.h"
#ifdef __riscos__
#include <unixlib/local.h>
@@ -60,6 +59,64 @@
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_indent.h"
+#include "zend_exceptions.h"
+
+#include "sapi/cli/cli.h"
+#include "readline_cli.h"
+
+#ifdef COMPILE_DL_READLINE
+#include <dlfcn.h>
+#endif
+
+#ifndef RTLD_DEFAULT
+#define RTLD_DEFAULT NULL
+#endif
+
+#define DEFAULT_PROMPT "\\b \\> "
+
+ZEND_DECLARE_MODULE_GLOBALS(cli_readline);
+
+static char php_last_char = '\0';
+static FILE *pager_pipe = NULL;
+
+static size_t readline_shell_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+{
+ if (CLIR_G(prompt_str)) {
+ smart_str_appendl(CLIR_G(prompt_str), str, str_length);
+ return str_length;
+ }
+
+ if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
+ pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
+ }
+ if (pager_pipe) {
+ return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
+ }
+
+ return -1;
+}
+/* }}} */
+
+static int readline_shell_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+{
+ php_last_char = str[str_length-1];
+ return -1;
+}
+/* }}} */
+
+static void cli_readline_init_globals(zend_cli_readline_globals *rg TSRMLS_DC)
+{
+ rg->pager = NULL;
+ rg->prompt = NULL;
+ rg->prompt_str = NULL;
+}
+
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("cli.pager", "", PHP_INI_ALL, OnUpdateString, pager, zend_cli_readline_globals, cli_readline_globals)
+ STD_PHP_INI_ENTRY("cli.prompt", DEFAULT_PROMPT, PHP_INI_ALL, OnUpdateString, prompt, zend_cli_readline_globals, cli_readline_globals)
+PHP_INI_END()
+
+
typedef enum {
body,
@@ -74,7 +131,77 @@ typedef enum {
outside,
} php_code_type;
-int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
+static char *cli_get_prompt(char *block, char prompt TSRMLS_DC) /* {{{ */
+{
+ smart_str retval = {0};
+ char *prompt_spec = CLIR_G(prompt) ? CLIR_G(prompt) : DEFAULT_PROMPT;
+
+ do {
+ if (*prompt_spec == '\\') {
+ switch (prompt_spec[1]) {
+ case '\\':
+ smart_str_appendc(&retval, '\\');
+ prompt_spec++;
+ break;
+ case 'n':
+ smart_str_appendc(&retval, '\n');
+ prompt_spec++;
+ break;
+ case 't':
+ smart_str_appendc(&retval, '\t');
+ prompt_spec++;
+ break;
+ case 'e':
+ smart_str_appendc(&retval, '\033');
+ prompt_spec++;
+ break;
+
+
+ case 'v':
+ smart_str_appends(&retval, PHP_VERSION);
+ prompt_spec++;
+ break;
+ case 'b':
+ smart_str_appends(&retval, block);
+ prompt_spec++;
+ break;
+ case '>':
+ smart_str_appendc(&retval, prompt);
+ prompt_spec++;
+ break;
+ case '`':
+ smart_str_appendc(&retval, '`');
+ prompt_spec++;
+ break;
+ default:
+ smart_str_appendc(&retval, '\\');
+ break;
+ }
+ } else if (*prompt_spec == '`') {
+ char *prompt_end = strstr(prompt_spec + 1, "`");
+ char *code;
+
+ if (prompt_end) {
+ code = estrndup(prompt_spec + 1, prompt_end - prompt_spec - 1);
+
+ CLIR_G(prompt_str) = &retval;
+ zend_try {
+ zend_eval_stringl(code, prompt_end - prompt_spec - 1, NULL, "php prompt code" TSRMLS_CC);
+ } zend_end_try();
+ CLIR_G(prompt_str) = NULL;
+ efree(code);
+ prompt_spec = prompt_end;
+ }
+ } else {
+ smart_str_appendc(&retval, *prompt_spec);
+ }
+ } while (++prompt_spec && *prompt_spec);
+ smart_str_0(&retval);
+ return retval.c;
+}
+/* }}} */
+
+static int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
{
int valid_end = 1, last_valid_end;
int brackets_count = 0;
@@ -206,6 +333,7 @@ int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
switch(code[i]) {
case ' ':
case '\t':
+ case '\'':
break;
case '\r':
case '\n':
@@ -241,29 +369,29 @@ int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
switch (code_type) {
default:
if (brace_count) {
- *prompt = "php ( ";
+ *prompt = cli_get_prompt("php", '(' TSRMLS_CC);
} else if (brackets_count) {
- *prompt = "php { ";
+ *prompt = cli_get_prompt("php", '{' TSRMLS_CC);
} else {
- *prompt = "php > ";
+ *prompt = cli_get_prompt("php", '>' TSRMLS_CC);
}
break;
case sstring:
case sstring_esc:
- *prompt = "php ' ";
+ *prompt = cli_get_prompt("php", '\'' TSRMLS_CC);
break;
case dstring:
case dstring_esc:
- *prompt = "php \" ";
+ *prompt = cli_get_prompt("php", '"' TSRMLS_CC);
break;
case comment_block:
- *prompt = "/* > ";
+ *prompt = cli_get_prompt("/* ", '>' TSRMLS_CC);
break;
case heredoc:
- *prompt = "<<< > ";
+ *prompt = cli_get_prompt("<<<", '>' TSRMLS_CC);
break;
case outside:
- *prompt = " > ";
+ *prompt = cli_get_prompt(" ", '>' TSRMLS_CC);
break;
}
@@ -315,6 +443,20 @@ static char *cli_completion_generator_var(const char *text, int textlen, int *st
return retval;
} /* }}} */
+static char *cli_completion_generator_ini(const char *text, int textlen, int *state TSRMLS_DC) /* {{{ */
+{
+ char *retval, *tmp;
+
+ tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, EG(ini_directives), NULL TSRMLS_CC);
+ if (retval) {
+ retval = malloc(strlen(tmp) + 2);
+ retval[0] = '#';
+ strcpy(&retval[1], tmp);
+ rl_completion_append_character = '=';
+ }
+ return retval;
+} /* }}} */
+
static char *cli_completion_generator_func(const char *text, int textlen, int *state, HashTable *ht TSRMLS_DC) /* {{{ */
{
zend_function *func;
@@ -373,6 +515,8 @@ TODO:
}
if (text[0] == '$') {
retval = cli_completion_generator_var(text, textlen, &cli_completion_state TSRMLS_CC);
+ } else if (text[0] == '#') {
+ retval = cli_completion_generator_ini(text, textlen, &cli_completion_state TSRMLS_CC);
} else {
char *lc_text, *class_name, *class_name_end;
int class_name_len;
@@ -430,13 +574,188 @@ TODO:
return retval;
} /* }}} */
-char **cli_code_completion(const char *text, int start, int end) /* {{{ */
+static char **cli_code_completion(const char *text, int start, int end) /* {{{ */
{
return rl_completion_matches(text, cli_completion_generator);
}
/* }}} */
-#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
+static int readline_shell_run(TSRMLS_D) /* {{{ */
+{
+ char *line;
+ size_t size = 4096, pos = 0, len;
+ char *code = emalloc(size);
+ char *prompt = cli_get_prompt("php", '>' TSRMLS_CC);
+ char *history_file;
+
+ if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
+ zend_file_handle *prepend_file_p;
+ zend_file_handle prepend_file = {0};
+
+ prepend_file.filename = PG(auto_prepend_file);
+ prepend_file.opened_path = NULL;
+ prepend_file.free_filename = 0;
+ prepend_file.type = ZEND_HANDLE_FILENAME;
+ prepend_file_p = &prepend_file;
+
+ zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, prepend_file_p);
+ }
+
+ history_file = tilde_expand("~/.php_history");
+ rl_attempted_completion_function = cli_code_completion;
+ rl_special_prefixes = "$";
+ read_history(history_file);
+
+ EG(exit_status) = 0;
+ while ((line = readline(prompt)) != NULL) {
+ if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
+ free(line);
+ break;
+ }
+
+ if (!pos && !*line) {
+ free(line);
+ continue;
+ }
+
+ len = strlen(line);
+
+ if (line[0] == '#') {
+ char *param = strstr(&line[1], "=");
+ if (param) {
+ char *cmd;
+ uint cmd_len;
+ param++;
+ cmd_len = param - &line[1] - 1;
+ cmd = estrndup(&line[1], cmd_len);
+
+ zend_alter_ini_entry_ex(cmd, cmd_len + 1, param, strlen(param), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
+ efree(cmd);
+ add_history(line);
+
+ efree(prompt);
+ /* TODO: This might be wrong! */
+ prompt = cli_get_prompt("php", '>' TSRMLS_CC);
+ continue;
+ }
+ }
+
+ if (pos + len + 2 > size) {
+ size = pos + len + 2;
+ code = erealloc(code, size);
+ }
+ memcpy(&code[pos], line, len);
+ pos += len;
+ code[pos] = '\n';
+ code[++pos] = '\0';
+
+ if (*line) {
+ add_history(line);
+ }
+
+ free(line);
+ efree(prompt);
+
+ if (!cli_is_valid_code(code, pos, &prompt TSRMLS_CC)) {
+ continue;
+ }
+
+ zend_try {
+ zend_eval_stringl(code, pos, NULL, "php shell code" TSRMLS_CC);
+ } zend_end_try();
+
+ pos = 0;
+
+ if (!pager_pipe && php_last_char != '\0' && php_last_char != '\n') {
+ readline_shell_write("\n", 1 TSRMLS_CC);
+ }
+
+ if (EG(exception)) {
+ zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
+ }
+
+ if (pager_pipe) {
+ fclose(pager_pipe);
+ pager_pipe = NULL;
+ }
+
+ php_last_char = '\0';
+ }
+ write_history(history_file);
+ free(history_file);
+ efree(code);
+ efree(prompt);
+ return EG(exit_status);
+}
+/* }}} */
+
+/*
+#ifdef COMPILE_DL_READLINE
+This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only
+extensions. If that is being changed dlsym() should only be used when building
+this extension sharedto offer compatibility.
+*/
+#define GET_SHELL_CB(cb) \
+ do { \
+ (cb) = NULL; \
+ cli_shell_callbacks_t *(*get_callbacks)(); \
+ get_callbacks = dlsym(RTLD_DEFAULT, "php_cli_get_shell_callbacks"); \
+ if (get_callbacks) { \
+ (cb) = get_callbacks(); \
+ } \
+ } while(0)
+/*#else
+#define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks()
+#endif*/
+
+PHP_MINIT_FUNCTION(cli_readline)
+{
+ cli_shell_callbacks_t *cb;
+
+ ZEND_INIT_MODULE_GLOBALS(cli_readline, cli_readline_init_globals, NULL);
+ REGISTER_INI_ENTRIES();
+
+#if HAVE_LIBEDIT
+ REGISTER_STRING_CONSTANT("READLINE_LIB", "libedit", CONST_CS|CONST_PERSISTENT);
+#else
+ REGISTER_STRING_CONSTANT("READLINE_LIB", "readline", CONST_CS|CONST_PERSISTENT);
+#endif
+
+ GET_SHELL_CB(cb);
+ if (cb) {
+ cb->cli_shell_write = readline_shell_write;
+ cb->cli_shell_ub_write = readline_shell_ub_write;
+ cb->cli_shell_run = readline_shell_run;
+ }
+
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(cli_readline)
+{
+ cli_shell_callbacks_t *cb;
+
+ UNREGISTER_INI_ENTRIES();
+
+ GET_SHELL_CB(cb);
+ if (cb) {
+ cb->cli_shell_write = NULL;
+ cb->cli_shell_ub_write = NULL;
+ cb->cli_shell_run = NULL;
+ }
+
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(cli_readline)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "Readline Support", "enabled");
+ php_info_print_table_row(2, "Readline library", (rl_library_version ? rl_library_version : "Unknown"));
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+}
/*
* Local variables:
diff --git a/ext/readline/readline_cli.h b/ext/readline/readline_cli.h
new file mode 100644
index 0000000000..d2925fe180
--- /dev/null
+++ b/ext/readline/readline_cli.h
@@ -0,0 +1,43 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ | Johannes Schlueter <johannes@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "php.h"
+#include "ext/standard/php_smart_str.h"
+
+ZEND_BEGIN_MODULE_GLOBALS(cli_readline)
+ char *pager;
+ char *prompt;
+ smart_str *prompt_str;
+ZEND_END_MODULE_GLOBALS(cli_readline)
+
+#ifdef ZTS
+# define CLIR_G(v) TSRMG(cli_readline_globals_id, zend_cli_readline_globals *, v)
+#else
+# define CLIR_G(v) (cli_readline_globals.v)
+#endif
+
+extern PHP_MINIT_FUNCTION(cli_readline);
+extern PHP_MSHUTDOWN_FUNCTION(cli_readline);
+extern PHP_MINFO_FUNCTION(cli_readline);
+
+ZEND_EXTERN_MODULE_GLOBALS(cli_readline)
+
+
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 593a0506b0..7c9981924d 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -39,11 +39,16 @@
#include "zend_ini.h"
#include "zend_interfaces.h"
#include "zend_closures.h"
+#include "zend_extensions.h"
-/* Undefine "getParameters" macro defined in "main/php3_compat.h" */
-#ifdef getParameters
-# undef getParameters
-#endif
+#define reflection_update_property(object, name, value) do { \
+ zval *member; \
+ MAKE_STD_ZVAL(member); \
+ ZVAL_STRINGL(member, name, sizeof(name)-1, 1); \
+ zend_std_write_property(object, member, value, NULL TSRMLS_CC); \
+ Z_DELREF_P(value); \
+ zval_ptr_dtor(&member); \
+ } while (0)
/* Class entry pointers */
PHPAPI zend_class_entry *reflector_ptr;
@@ -57,6 +62,7 @@ PHPAPI zend_class_entry *reflection_object_ptr;
PHPAPI zend_class_entry *reflection_method_ptr;
PHPAPI zend_class_entry *reflection_property_ptr;
PHPAPI zend_class_entry *reflection_extension_ptr;
+PHPAPI zend_class_entry *reflection_zend_extension_ptr;
#if MBO_0
ZEND_BEGIN_MODULE_GLOBALS(reflection)
@@ -119,7 +125,7 @@ static void string_init(string *str)
str->alloced = 1024;
*str->string = '\0';
}
-
+
static string *string_printf(string *str, const char *format, ...)
{
int len;
@@ -172,6 +178,8 @@ static void string_free(string *str)
}
/* }}} */
+/* {{{ Object structure */
+
/* Struct for properties */
typedef struct _property_reference {
zend_class_entry *ce;
@@ -204,9 +212,11 @@ typedef struct {
unsigned int ignore_visibility:1;
} reflection_object;
+/* }}} */
+
static zend_object_handlers reflection_object_handlers;
-static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC)
+static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */
{
zval **value;
@@ -216,6 +226,7 @@ static void _default_get_entry(zval *object, char *name, int name_len, zval *ret
MAKE_COPY_ZVAL(value, return_value);
}
+/* }}} */
#ifdef ilia_0
static void _default_lookup_entry(zval *object, char *name, int name_len, zval **return_value TSRMLS_DC) /* {{{ */
@@ -231,13 +242,14 @@ static void _default_lookup_entry(zval *object, char *name, int name_len, zval *
/* }}} */
#endif
-static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC)
+static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC) /* {{{ */
{
zend_uint num_interfaces = ++class_entry->num_interfaces;
class_entry->interfaces = (zend_class_entry **) realloc(class_entry->interfaces, sizeof(zend_class_entry *) * num_interfaces);
class_entry->interfaces[num_interfaces - 1] = interface_entry;
}
+/* }}} */
static zend_function *_copy_function(zend_function *fptr TSRMLS_DC) /* {{{ */
{
@@ -263,13 +275,13 @@ static void _free_function(zend_function *fptr TSRMLS_DC) /* {{{ */
&& fptr->type == ZEND_INTERNAL_FUNCTION
&& (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
{
- efree(fptr->internal_function.function_name);
+ efree((char*)fptr->internal_function.function_name);
efree(fptr);
}
}
/* }}} */
-static void reflection_free_objects_storage(void *object TSRMLS_DC)
+static void reflection_free_objects_storage(void *object TSRMLS_DC) /* {{{ */
{
reflection_object *intern = (reflection_object *) object;
parameter_reference *reference;
@@ -290,7 +302,7 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)
break;
case REF_TYPE_DYNAMIC_PROPERTY:
prop_reference = (property_reference*)intern->ptr;
- efree(prop_reference->prop.name);
+ efree((char*)prop_reference->prop.name);
efree(intern->ptr);
break;
case REF_TYPE_OTHER:
@@ -303,10 +315,10 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)
}
zend_objects_free_object_storage(object TSRMLS_CC);
}
+/* }}} */
-static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)
+static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- zval tmp;
zend_object_value retval;
reflection_object *intern;
@@ -314,13 +326,14 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->zo.ce = class_type;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
retval.handlers = &reflection_object_handlers;
return retval;
}
+/* }}} */
-static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
+static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) /* {{{ */
{
if (!object) {
ALLOC_ZVAL(object);
@@ -331,36 +344,44 @@ static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_
Z_SET_ISREF_P(object);
return object;
}
+/* }}} */
static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC);
-static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char *indent TSRMLS_DC);
+static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent TSRMLS_DC);
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC);
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
+static void _zend_extension_string(string *str, zend_extension *extension, char *indent TSRMLS_DC);
/* {{{ _class_string */
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
{
int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
string sub_indent;
-
+
string_init(&sub_indent);
string_printf(&sub_indent, "%s ", indent);
/* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
- if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
- string_printf(str, "%s%s", indent, ce->doc_comment);
+ if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
+ string_printf(str, "%s%s", indent, ce->info.user.doc_comment);
string_write(str, "\n", 1);
}
if (obj) {
string_printf(str, "%sObject of class [ ", indent);
} else {
- string_printf(str, "%s%s [ ", indent, (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : "Class");
+ char *kind = "Class";
+ if (ce->ce_flags & ZEND_ACC_INTERFACE) {
+ kind = "Interface";
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ kind = "Trait";
+ }
+ string_printf(str, "%s%s [ ", indent, kind);
}
string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
- if (ce->module) {
- string_printf(str, ":%s", ce->module->name);
+ if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
+ string_printf(str, ":%s", ce->info.internal.module->name);
}
string_printf(str, "> ");
if (ce->get_iterator != NULL) {
@@ -368,13 +389,15 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
string_printf(str, "interface ");
+ } else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+ string_printf(str, "trait ");
} else {
if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
string_printf(str, "abstract ");
}
if (ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
string_printf(str, "final ");
- }
+ }
string_printf(str, "class ");
}
string_printf(str, "%s", ce->name);
@@ -398,8 +421,8 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
/* The information where a class is declared is only available for user classes */
if (ce->type == ZEND_USER_CLASS) {
- string_printf(str, "%s @@ %s %d-%d\n", indent, ce->filename,
- ce->line_start, ce->line_end);
+ string_printf(str, "%s @@ %s %d-%d\n", indent, ce->info.user.filename,
+ ce->info.user.line_start, ce->info.user.line_end);
}
/* Constants */
@@ -429,7 +452,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
/* Static properties */
if (&ce->properties_info) {
- /* counting static properties */
+ /* counting static properties */
count = zend_hash_num_elements(&ce->properties_info);
if (count > 0) {
HashPosition pos;
@@ -447,7 +470,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
}
- /* static properties */
+ /* static properties */
string_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
if (count_static_props > 0) {
HashPosition pos;
@@ -465,10 +488,10 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "%s }\n", indent);
}
-
+
/* Static methods */
if (&ce->function_table) {
- /* counting static methods */
+ /* counting static methods */
count = zend_hash_num_elements(&ce->function_table);
if (count > 0) {
HashPosition pos;
@@ -486,7 +509,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
}
- /* static methods */
+ /* static methods */
string_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
if (count_static_funcs > 0) {
HashPosition pos;
@@ -550,7 +573,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
if (prop_name_size && prop_name[0]) { /* skip all private and protected properties */
if (!zend_hash_quick_exists(&ce->properties_info, prop_name, prop_name_size, zend_get_hash_value(prop_name, prop_name_size))) {
count++;
- _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC);
+ _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC);
}
}
efree(prop_name);
@@ -621,7 +644,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "%s }\n", indent);
}
-
+
string_printf(str, "%s}\n", indent);
string_free(&sub_indent);
}
@@ -659,7 +682,7 @@ static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
++offset;
while (op < end) {
if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
- && op->op1.u.constant.value.lval == (long)offset)
+ && op->op1.num == (long)offset)
{
return op;
}
@@ -683,8 +706,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
- } else if (arg_info->array_type_hint) {
- string_printf(str, "array ");
+ } else if (arg_info->type_hint) {
+ string_printf(str, "%s ", zend_get_type_by_const(arg_info->type_hint));
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
@@ -699,12 +722,12 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
}
if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
- if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
+ if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
zval *zv, zv_copy;
int use_copy;
string_write(str, " = ", sizeof(" = ")-1);
ALLOC_ZVAL(zv);
- *zv = precv->op2.u.constant;
+ *zv = *precv->op2.zv;
zval_copy_ctor(zv);
INIT_PZVAL(zv);
zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
@@ -723,6 +746,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_write(str, "...", sizeof("...")-1);
}
string_write(str, "'", sizeof("'")-1);
+ } else if (Z_TYPE_P(zv) == IS_ARRAY) {
+ string_write(str, "Array", sizeof("Array")-1);
} else {
zend_make_printable_zval(zv, &zv_copy, &use_copy);
string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
@@ -802,7 +827,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
unsigned int lc_name_len;
/* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
- * What's "wrong" is that any whitespace before the doc comment start is
+ * What's "wrong" is that any whitespace before the doc comment start is
* swallowed, leading to an unaligned comment.
*/
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
@@ -875,13 +900,13 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
string_printf(str, "function ");
}
- if (fptr->op_array.return_reference) {
+ if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
string_printf(str, "&");
}
string_printf(str, "%s ] {\n", fptr->common.function_name);
/* The information where a function is declared is only available for user classes */
if (fptr->type == ZEND_USER_FUNCTION) {
- string_printf(str, "%s @@ %s %d - %d\n", indent,
+ string_printf(str, "%s @@ %s %d - %d\n", indent,
fptr->op_array.filename,
fptr->op_array.line_start,
fptr->op_array.line_end);
@@ -900,7 +925,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
/* {{{ _property_string */
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC)
{
- char *class_name;
+ const char *class_name;
string_printf(str, "%sProperty [ ", indent);
if (!prop) {
@@ -913,7 +938,7 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_write(str, "<default> ", sizeof("<default> ") - 1);
}
}
-
+
/* These are mutually exclusive */
switch (prop->flags & ZEND_ACC_PPP_MASK) {
case ZEND_ACC_PUBLIC:
@@ -930,7 +955,7 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_printf(str, "static ");
}
- zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
+ zend_unmangle_property_name(prop->name, prop->name_length, &class_name, (const char**)&prop_name);
string_printf(str, "$%s", prop_name);
}
@@ -938,7 +963,7 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
}
/* }}} */
-static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
string *str = va_arg(args, string *);
char *indent = va_arg(args, char *);
@@ -972,23 +997,25 @@ static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_ar
}
return ZEND_HASH_APPLY_KEEP;
}
+/* }}} */
-static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
string *str = va_arg(args, string *);
char *indent = va_arg(args, char *);
struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
int *num_classes = va_arg(args, int*);
- if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+ if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
string_printf(str, "\n");
_class_string(str, *pce, NULL, indent TSRMLS_CC);
(*num_classes)++;
}
return ZEND_HASH_APPLY_KEEP;
}
+/* }}} */
-static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
string *str = va_arg(args, string *);
char *indent = va_arg(args, char *);
@@ -1001,6 +1028,7 @@ static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_ar
}
return ZEND_HASH_APPLY_KEEP;
}
+/* }}} */
/* {{{ _extension_string */
static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC)
@@ -1023,7 +1051,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
while(dep->name) {
string_printf(str, "%s Dependency [ %s (", indent, dep->name);
-
+
switch(dep->type) {
case MODULE_DEP_REQUIRED:
string_write(str, "Required", sizeof("Required") - 1);
@@ -1039,10 +1067,10 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
break;
}
- if (dep->rel) {
+ if (dep->rel) {
string_printf(str, " %s", dep->rel);
}
- if (dep->version) {
+ if (dep->version) {
string_printf(str, " %s", dep->version);
}
string_write(str, ") ]\n", sizeof(") ]\n") - 1);
@@ -1066,7 +1094,7 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
{
string str_constants;
int num_constants = 0;
-
+
string_init(&str_constants);
zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
if (num_constants) {
@@ -1087,26 +1115,26 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
while (func->fname) {
int fname_len = strlen(func->fname);
char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
-
- if (zend_hash_find(EG(function_table), lc_name, fname_len+1, (void**) &fptr) == FAILURE) {
+
+ if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
func++;
efree(lc_name);
continue;
}
-
+
_function_string(str, fptr, NULL, " " TSRMLS_CC);
efree(lc_name);
func++;
}
string_printf(str, "%s }\n", indent);
}
-
+
{
string str_classes;
string sub_indent;
int num_classes = 0;
-
+
string_init(&sub_indent);
string_printf(&sub_indent, "%s ", indent);
string_init(&str_classes);
@@ -1124,6 +1152,27 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
}
/* }}} */
+static void _zend_extension_string(string *str, zend_extension *extension, char *indent TSRMLS_DC) /* {{{ */
+{
+ string_printf(str, "%sZend Extension [ %s ", indent, extension->name);
+
+ if (extension->version) {
+ string_printf(str, "%s ", extension->version);
+ }
+ if (extension->copyright) {
+ string_printf(str, "%s ", extension->copyright);
+ }
+ if (extension->author) {
+ string_printf(str, "by %s ", extension->author);
+ }
+ if (extension->URL) {
+ string_printf(str, "<%s> ", extension->URL);
+ }
+
+ string_printf(str, "]\n");
+}
+/* }}} */
+
/* {{{ _function_check_flag */
static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
{
@@ -1151,7 +1200,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR
intern->ptr = ce;
intern->ref_type = REF_TYPE_OTHER;
intern->ce = ce;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1180,7 +1229,7 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
intern->ptr = module;
intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1211,7 +1260,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
intern->ref_type = REF_TYPE_PARAMETER;
intern->ce = fptr->common.scope;
intern->obj = closure_object;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1233,7 +1282,7 @@ static void reflection_function_factory(zend_function *function, zval *closure_o
intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = NULL;
intern->obj = closure_object;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
}
/* }}} */
@@ -1257,8 +1306,8 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = ce;
intern->obj = closure_object;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
+ reflection_update_property(object, "class", classname);
}
/* }}} */
@@ -1269,7 +1318,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
zval *name;
zval *classname;
property_reference *reference;
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
@@ -1304,8 +1353,8 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
intern->ref_type = REF_TYPE_PROPERTY;
intern->ce = ce;
intern->ignore_visibility = 0;
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
+ reflection_update_property(object, "class", classname);
}
/* }}} */
@@ -1361,7 +1410,7 @@ static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *c
fcc.object_ptr = reflector_ptr;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
-
+
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
@@ -1408,6 +1457,49 @@ static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *c
}
/* }}} */
+/* {{{ _reflection_param_get_default_param */
+static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
+ if (intern == NULL || intern->ptr == NULL) {
+ if (EG(exception) && Z_OBJCE_P(EG(exception)) == reflection_exception_ptr) {
+ return NULL;
+ }
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the reflection object");
+ }
+
+ param = intern->ptr;
+ if (param->fptr->type != ZEND_USER_FUNCTION) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
+ return NULL;
+ }
+
+ return param;
+}
+/* }}} */
+
+/* {{{ _reflection_param_get_default_precv */
+static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS, parameter_reference *param)
+{
+ zend_op *precv;
+
+ if (param == NULL) {
+ return NULL;
+ }
+
+ precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
+ if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error: Failed to retrieve the default value");
+ return NULL;
+ }
+
+ return precv;
+}
+/* }}} */
+
/* {{{ Preventing __clone from being called */
ZEND_METHOD(reflection, __clone)
{
@@ -1536,10 +1628,10 @@ ZEND_METHOD(reflection_function, __construct)
nsname = &lcname[1];
name_len--;
}
-
+
if (zend_hash_find(EG(function_table), nsname, name_len + 1, (void **)&fptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", name_str);
return;
}
@@ -1550,7 +1642,7 @@ ZEND_METHOD(reflection_function, __construct)
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, fptr->common.function_name, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
intern->ptr = fptr;
intern->ref_type = REF_TYPE_FUNCTION;
intern->obj = closure;
@@ -1602,6 +1694,65 @@ ZEND_METHOD(reflection_function, isClosure)
}
/* }}} */
+/* {{{ proto public bool ReflectionFunction::getClosureThis()
+ Returns this pointer bound to closure */
+ZEND_METHOD(reflection_function, getClosureThis)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+ zval* closure_this;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+ if (intern->obj) {
+ closure_this = zend_get_closure_this_ptr(intern->obj TSRMLS_CC);
+ if (closure_this) {
+ RETURN_ZVAL(closure_this, 1, 0);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
+ Returns the scope associated to the closure */
+ZEND_METHOD(reflection_function, getClosureScopeClass)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+ const zend_function *closure_func;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+ if (intern->obj) {
+ closure_func = zend_get_closure_method_def(intern->obj TSRMLS_CC);
+ if (closure_func && closure_func->common.scope) {
+ zend_reflection_class_factory(closure_func->common.scope, return_value TSRMLS_CC);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionFunction::getClosure()
+ Returns a dynamically created closure for the function */
+ZEND_METHOD(reflection_function, getClosure)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(fptr);
+
+ zend_create_closure(return_value, fptr, NULL, NULL TSRMLS_CC);
+}
+/* }}} */
+
+
/* {{{ proto public bool ReflectionFunction::isInternal()
Returns whether this is an internal function */
ZEND_METHOD(reflection_function, isInternal)
@@ -1724,7 +1875,7 @@ ZEND_METHOD(reflection_function, getStaticVariables)
zval *tmp_copy;
reflection_object *intern;
zend_function *fptr;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -1750,7 +1901,7 @@ ZEND_METHOD(reflection_function, invoke)
zend_fcall_info_cache fcc;
reflection_object *intern;
zend_function *fptr;
-
+
METHOD_NOTSTATIC(reflection_function_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);
@@ -1781,7 +1932,7 @@ ZEND_METHOD(reflection_function, invoke)
}
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
return;
}
@@ -1811,7 +1962,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
reflection_object *intern;
zend_function *fptr;
zval *param_array;
-
+
METHOD_NOTSTATIC(reflection_function_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);
@@ -1820,9 +1971,9 @@ ZEND_METHOD(reflection_function, invokeArgs)
}
argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
-
+
params = safe_emalloc(sizeof(zval **), argc, 0);
- zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
+ zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
params -= argc;
fci.size = sizeof(fci);
@@ -1846,7 +1997,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
efree(params);
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of function %s() failed", fptr->common.function_name);
return;
}
@@ -1867,7 +2018,7 @@ ZEND_METHOD(reflection_function, returnsReference)
METHOD_NOTSTATIC(reflection_function_abstract_ptr);
GET_REFLECTION_OBJECT_PTR(fptr);
- RETURN_BOOL(fptr->op_array.return_reference);
+ RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
}
/* }}} */
@@ -1915,7 +2066,7 @@ ZEND_METHOD(reflection_function, getParameters)
array_init(return_value);
for (i = 0; i < fptr->common.num_args; i++) {
- zval *parameter;
+ zval *parameter;
ALLOC_ZVAL(parameter);
reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), intern->obj, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
@@ -2006,7 +2157,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (intern == NULL) {
return;
}
-
+
/* First, find the function */
switch (Z_TYPE_P(reference)) {
case IS_STRING: {
@@ -2017,7 +2168,7 @@ ZEND_METHOD(reflection_parameter, __construct)
lcname = zend_str_tolower_dup(Z_STRVAL_P(reference), lcname_len);
if (zend_hash_find(EG(function_table), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Function %s() does not exist", Z_STRVAL_P(reference));
return;
}
@@ -2032,7 +2183,7 @@ ZEND_METHOD(reflection_parameter, __construct)
zend_class_entry **pce;
unsigned int lcname_len;
char *lcname;
-
+
if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
|| (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE))
{
@@ -2051,7 +2202,7 @@ ZEND_METHOD(reflection_parameter, __construct)
}
ce = *pce;
}
-
+
convert_to_string_ex(method);
lcname_len = Z_STRLEN_PP(method);
lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), lcname_len);
@@ -2060,21 +2211,21 @@ ZEND_METHOD(reflection_parameter, __construct)
&& memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
&& (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
{
- /* nothign to do. don't set is_closure since is the invoke handler,
- not the closure itself */
+ /* nothing to do. don't set is_closure since is the invoke handler,
+- not the closure itself */
} else if (zend_hash_find(&ce->function_table, lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", ce->name, Z_STRVAL_PP(method));
return;
}
efree(lcname);
}
break;
-
+
case IS_OBJECT: {
ce = Z_OBJCE_P(reference);
-
+
if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
fptr = (zend_function *)zend_get_closure_method_def(reference TSRMLS_CC);
Z_ADDREF_P(reference);
@@ -2086,12 +2237,12 @@ ZEND_METHOD(reflection_parameter, __construct)
}
}
break;
-
+
default:
_DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
/* returns out of this function */
}
-
+
/* Now, search for the parameter */
arg_info = fptr->common.arg_info;
if (Z_TYPE_PP(parameter) == IS_LONG) {
@@ -2099,7 +2250,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fptr->common.function_name);
+ efree((char*)fptr->common.function_name);
}
efree(fptr);
}
@@ -2123,7 +2274,7 @@ ZEND_METHOD(reflection_parameter, __construct)
if (position == -1) {
if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
- efree(fptr->common.function_name);
+ efree((char*)fptr->common.function_name);
}
efree(fptr);
}
@@ -2134,14 +2285,14 @@ ZEND_METHOD(reflection_parameter, __construct)
/* returns out of this function */
}
}
-
+
MAKE_STD_ZVAL(name);
if (arg_info[position].name) {
ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
} else {
ZVAL_NULL(name);
}
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
ref->arg_info = &arg_info[position];
@@ -2221,7 +2372,7 @@ ZEND_METHOD(reflection_parameter, getDeclaringClass)
if (param->fptr->common.scope) {
zend_reflection_class_factory(param->fptr->common.scope, return_value TSRMLS_CC);
- }
+ }
}
/* }}} */
@@ -2251,29 +2402,29 @@ ZEND_METHOD(reflection_parameter, getClass)
* TODO: Think about moving these checks to the compiler or some sort of
* lint-mode.
*/
- if (0 == strncmp(param->arg_info->class_name, "self", sizeof("self")- 1)) {
+ if (0 == zend_binary_strcasecmp(param->arg_info->class_name, param->arg_info->class_name_len, "self", sizeof("self")- 1)) {
ce = param->fptr->common.scope;
if (!ce) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter uses 'self' as type hint but function is not a class member!");
return;
}
pce= &ce;
- } else if (0 == strncmp(param->arg_info->class_name, "parent", sizeof("parent")- 1)) {
+ } else if (0 == zend_binary_strcasecmp(param->arg_info->class_name, param->arg_info->class_name_len, "parent", sizeof("parent")- 1)) {
ce = param->fptr->common.scope;
if (!ce) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter uses 'parent' as type hint but function is not a class member!");
return;
}
if (!ce->parent) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter uses 'parent' as type hint although class does not have a parent!");
return;
}
pce= &ce->parent;
} else if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", param->arg_info->class_name);
return;
}
@@ -2294,7 +2445,23 @@ ZEND_METHOD(reflection_parameter, isArray)
}
GET_REFLECTION_OBJECT_PTR(param);
- RETVAL_BOOL(param->arg_info->array_type_hint);
+ RETVAL_BOOL(param->arg_info->type_hint == IS_ARRAY);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionParameter::isCallable()
+ Returns whether parameter MUST be callable */
+ZEND_METHOD(reflection_parameter, isCallable)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETVAL_BOOL(param->arg_info->type_hint == IS_CALLABLE);
}
/* }}} */
@@ -2330,6 +2497,23 @@ ZEND_METHOD(reflection_parameter, isPassedByReference)
}
/* }}} */
+/* {{{ proto public bool ReflectionParameter::canBePassedByValue()
+ Returns whether this parameter can be passed by value */
+ZEND_METHOD(reflection_parameter, canBePassedByValue)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
+ RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF);
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionParameter::getPosition()
Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter, getPosition)
@@ -2381,7 +2565,7 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
}
precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
- if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+ if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
RETURN_FALSE;
}
RETURN_TRUE;
@@ -2392,27 +2576,24 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
Returns the default value of this parameter or throws an exception */
ZEND_METHOD(reflection_parameter, getDefaultValue)
{
- reflection_object *intern;
parameter_reference *param;
zend_op *precv;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- GET_REFLECTION_OBJECT_PTR(param);
- if (param->fptr->type != ZEND_USER_FUNCTION)
- {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
+ param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (!param) {
return;
}
- precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
- if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error");
+
+ precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
+ if (!precv) {
return;
}
- *return_value = precv->op2.u.constant;
+ *return_value = *precv->op2.zv;
INIT_PZVAL(return_value);
if ((Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT
&& (Z_TYPE_P(return_value) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT_ARRAY) {
@@ -2422,6 +2603,54 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
}
/* }}} */
+/* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
+ Returns whether the default value of this parameter is constant */
+ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
+{
+ zend_op *precv;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (!param) {
+ RETURN_FALSE;
+ }
+
+ precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
+ if (precv && (Z_TYPE_P(precv->op2.zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+ RETURN_TRUE;
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
+ Returns the default value's constant name if default value is constant or null */
+ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
+{
+ zend_op *precv;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (!param) {
+ return;
+ }
+
+ precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
+ if (precv && (Z_TYPE_P(precv->op2.zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+ RETURN_STRINGL(Z_STRVAL_P(precv->op2.zv), Z_STRLEN_P(precv->op2.zv), 1);
+ }
+}
+/* }}} */
+
/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_method, export)
@@ -2450,7 +2679,7 @@ ZEND_METHOD(reflection_method, __construct)
return;
}
if ((tmp = strstr(name_str, "::")) == NULL) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %s", name_str);
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %s", name_str);
return;
}
classname = &ztmp;
@@ -2470,13 +2699,13 @@ ZEND_METHOD(reflection_method, __construct)
if (intern == NULL) {
return;
}
-
+
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_P(classname));
+ "Class %s does not exist", Z_STRVAL_P(classname));
if (classname == &ztmp) {
zval_dtor(&ztmp);
}
@@ -2510,7 +2739,7 @@ ZEND_METHOD(reflection_method, __construct)
/* do nothing, mptr already set */
} else if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
efree(lcname);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s() does not exist", ce->name, name_str);
return;
}
@@ -2519,11 +2748,11 @@ ZEND_METHOD(reflection_method, __construct)
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1);
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
-
+ reflection_update_property(object, "class", classname);
+
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, mptr->common.function_name, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", name);
intern->ptr = mptr;
intern->ref_type = REF_TYPE_FUNCTION;
intern->ce = ce;
@@ -2548,6 +2777,41 @@ ZEND_METHOD(reflection_method, __toString)
}
/* }}} */
+/* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
+ Invokes the function */
+ZEND_METHOD(reflection_method, getClosure)
+{
+ reflection_object *intern;
+ zval *obj;
+ zend_function *mptr;
+
+ METHOD_NOTSTATIC(reflection_method_ptr);
+ GET_REFLECTION_OBJECT_PTR(mptr);
+
+ if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
+ zend_create_closure(return_value, mptr, mptr->common.scope, NULL TSRMLS_CC);
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
+ return;
+ }
+
+ if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope TSRMLS_CC)) {
+ _DO_THROW("Given object is not an instance of the class this method was declared in");
+ /* Returns from this function */
+ }
+
+ /* This is an original closure object and __invoke is to be called. */
+ if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION &&
+ (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
+ {
+ RETURN_ZVAL(obj, 1, 0);
+ } else {
+ zend_create_closure(return_value, mptr, mptr->common.scope, obj TSRMLS_CC);
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
Invokes the method. */
ZEND_METHOD(reflection_method, invoke)
@@ -2561,7 +2825,7 @@ ZEND_METHOD(reflection_method, invoke)
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zend_class_entry *obj_ce;
-
+
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
@@ -2571,12 +2835,12 @@ ZEND_METHOD(reflection_method, invoke)
&& intern->ignore_visibility == 0)
{
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s()",
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ "Trying to invoke abstract method %s::%s()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s() from scope %s",
+ "Trying to invoke %s method %s::%s() from scope %s",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2587,7 +2851,7 @@ ZEND_METHOD(reflection_method, invoke)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &params, &num_args) == FAILURE) {
return;
}
-
+
/* In case this is a static method, we should'nt pass an object_ptr
* (which is used as calling context aka $this). We can thus ignore the
* first parameter.
@@ -2613,10 +2877,10 @@ ZEND_METHOD(reflection_method, invoke)
_DO_THROW("Given object is not an instance of the class this method was declared in");
/* Returns from this function */
}
-
+
object_ptr = *params[0];
}
-
+
fci.size = sizeof(fci);
fci.function_table = NULL;
fci.function_name = NULL;
@@ -2634,13 +2898,13 @@ ZEND_METHOD(reflection_method, invoke)
fcc.object_ptr = object_ptr;
result = zend_call_function(&fci, &fcc TSRMLS_CC);
-
+
if (params) {
efree(params);
}
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2666,7 +2930,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
zend_fcall_info_cache fcc;
zend_class_entry *obj_ce;
zval *param_array;
-
+
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
@@ -2680,12 +2944,12 @@ ZEND_METHOD(reflection_method, invokeArgs)
&& intern->ignore_visibility == 0)
{
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s()",
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ "Trying to invoke abstract method %s::%s()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s() from scope %s",
+ "Trying to invoke %s method %s::%s() from scope %s",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2694,11 +2958,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
}
argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
-
+
params = safe_emalloc(sizeof(zval **), argc, 0);
- zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
+ zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
params -= argc;
-
+
/* In case this is a static method, we should'nt pass an object_ptr
* (which is used as calling context aka $this). We can thus ignore the
* first parameter.
@@ -2712,11 +2976,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (!object) {
efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke non static method %s::%s() without an object",
+ "Trying to invoke non static method %s::%s() without an object",
mptr->common.scope->name, mptr->common.function_name);
return;
}
-
+
obj_ce = Z_OBJCE_P(object);
if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
@@ -2725,7 +2989,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
/* Returns from this function */
}
}
-
+
fci.size = sizeof(fci);
fci.function_table = NULL;
fci.function_name = NULL;
@@ -2751,11 +3015,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
}
result = zend_call_function(&fci, &fcc TSRMLS_CC);
-
+
efree(params);
if (result == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2827,7 +3091,7 @@ ZEND_METHOD(reflection_function, isDeprecated)
ZEND_METHOD(reflection_function, inNamespace)
{
zval **name;
- char *colon;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -2836,8 +3100,8 @@ ZEND_METHOD(reflection_function, inNamespace)
RETURN_FALSE;
}
if (Z_TYPE_PP(name) == IS_STRING
- && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
- && colon > Z_STRVAL_PP(name))
+ && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
+ && backslash > Z_STRVAL_PP(name))
{
RETURN_TRUE;
}
@@ -2850,7 +3114,7 @@ ZEND_METHOD(reflection_function, inNamespace)
ZEND_METHOD(reflection_function, getNamespaceName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -2873,7 +3137,7 @@ ZEND_METHOD(reflection_function, getNamespaceName)
ZEND_METHOD(reflection_function, getShortName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -2902,7 +3166,7 @@ ZEND_METHOD(reflection_method, isConstructor)
return;
}
GET_REFLECTION_OBJECT_PTR(mptr);
- /* we need to check if the ctor is the ctor of the class level we we
+ /* we need to check if the ctor is the ctor of the class level we we
* looking at since we might be looking at an inherited old style ctor
* defined in base class. */
RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
@@ -2949,7 +3213,7 @@ ZEND_METHOD(reflection_method, getDeclaringClass)
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -2967,13 +3231,13 @@ ZEND_METHOD(reflection_method, getPrototype)
METHOD_NOTSTATIC(reflection_method_ptr);
GET_REFLECTION_OBJECT_PTR(mptr);
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
if (!mptr->common.prototype) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s::%s does not have a prototype", intern->ce->name, mptr->common.function_name);
return;
}
@@ -3035,17 +3299,17 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (intern == NULL) {
return;
}
-
+
if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", classname);
intern->ptr = Z_OBJCE_P(argument);
if (is_object) {
intern->obj = argument;
zval_add_ref(&argument);
}
- } else {
+ } else {
convert_to_string_ex(&argument);
if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
@@ -3056,7 +3320,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
MAKE_STD_ZVAL(classname);
ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
+ reflection_update_property(object, "name", classname);
intern->ptr = *ce;
}
@@ -3072,49 +3336,74 @@ ZEND_METHOD(reflection_class, __construct)
}
/* }}} */
+/* {{{ add_class_vars */
+static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
+{
+ HashPosition pos;
+ zend_property_info *prop_info;
+ zval *prop, *prop_copy;
+ char *key;
+ uint key_len;
+ ulong num_index;
+
+ zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+ while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
+ zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
+ zend_hash_move_forward_ex(&ce->properties_info, &pos);
+ if (((prop_info->flags & ZEND_ACC_SHADOW) &&
+ prop_info->ce != ce) ||
+ ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+ !zend_check_protected(prop_info->ce, ce)) ||
+ ((prop_info->flags & ZEND_ACC_PRIVATE) &&
+ prop_info->ce != ce)) {
+ continue;
+ }
+ prop = NULL;
+ if (prop_info->offset >= 0) {
+ if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
+ prop = ce->default_static_members_table[prop_info->offset];
+ } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
+ prop = ce->default_properties_table[prop_info->offset];
+ }
+ }
+ if (!prop) {
+ continue;
+ }
+
+ /* copy: enforce read only access */
+ ALLOC_ZVAL(prop_copy);
+ *prop_copy = *prop;
+ zval_copy_ctor(prop_copy);
+ INIT_PZVAL(prop_copy);
+
+ /* this is necessary to make it able to work with default array
+ * properties, returned to user */
+ if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+ zval_update_constant(&prop_copy, (void *) 1 TSRMLS_CC);
+ }
+
+ add_assoc_zval(return_value, key, prop_copy);
+ }
+}
+/* }}} */
+
/* {{{ proto public array ReflectionClass::getStaticProperties()
Returns an associative array containing all static property values of the class */
ZEND_METHOD(reflection_class, getStaticProperties)
{
reflection_object *intern;
zend_class_entry *ce;
- HashPosition pos;
- zval **value;
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
+
GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce TSRMLS_CC);
array_init(return_value);
-
- zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
-
- while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
- uint key_len;
- char *key;
- ulong num_index;
-
- if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) {
- char *prop_name, *class_name;
- zval *prop_copy;
-
- zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
-
- /* filter privates from base classes */
- if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) {
- /* copy: enforce read only access */
- ALLOC_ZVAL(prop_copy);
- MAKE_COPY_ZVAL(value, prop_copy);
-
- add_assoc_zval(return_value, prop_name, prop_copy);
- }
- }
- zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
- }
+ add_class_vars(ce, 1, return_value TSRMLS_CC);
}
/* }}} */
@@ -3127,7 +3416,7 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
char *name;
int name_len;
zval **prop, *def_value = NULL;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &name, &name_len, &def_value) == FAILURE) {
return;
}
@@ -3135,12 +3424,12 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce TSRMLS_CC);
- prop = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
+ prop = zend_std_get_static_property(ce, name, name_len, 1, NULL TSRMLS_CC);
if (!prop) {
if (def_value) {
RETURN_ZVAL(def_value, 1, 0);
} else {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not have a property named %s", ce->name, name);
}
return;
@@ -3161,7 +3450,7 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
zval **variable_ptr, *value;
int refcount;
zend_uchar is_ref;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &value) == FAILURE) {
return;
}
@@ -3169,12 +3458,12 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce TSRMLS_CC);
- variable_ptr = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
+ variable_ptr = zend_std_get_static_property(ce, name, name_len, 1, NULL TSRMLS_CC);
if (!variable_ptr) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not have a property named %s", ce->name, name);
return;
- }
+ }
refcount = Z_REFCOUNT_PP(variable_ptr);
is_ref = Z_ISREF_PP(variable_ptr);
zval_dtor(*variable_ptr);
@@ -3192,51 +3481,15 @@ ZEND_METHOD(reflection_class, getDefaultProperties)
{
reflection_object *intern;
zend_class_entry *ce;
- int count, i;
- HashTable *ht_list[3];
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
-
zend_update_class_constants(ce TSRMLS_CC);
-
- ht_list[0] = CE_STATIC_MEMBERS(ce);
- ht_list[1] = &ce->default_properties;
- ht_list[2] = NULL;
-
- for (i = 0; ht_list[i] != NULL; i++) {
-
- count = zend_hash_num_elements(ht_list[i]);
- if (count > 0) {
- HashPosition pos;
- zval **prop;
-
- zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
- while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
- char *key, *class_name, *prop_name;
- uint key_len;
- ulong num_index;
- zval *prop_copy;
-
- zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
- zend_hash_move_forward_ex(ht_list[i], &pos);
- zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
- if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
- /* filter privates from base classes */
- continue;
- }
-
- /* copy: enforce read only access */
- ALLOC_ZVAL(prop_copy);
- MAKE_COPY_ZVAL(prop, prop_copy);
-
- add_assoc_zval(return_value, prop_name, prop_copy);
- }
- }
- }
+ add_class_vars(ce, 1, return_value TSRMLS_CC);
+ add_class_vars(ce, 0, return_value TSRMLS_CC);
}
/* }}} */
@@ -3311,7 +3564,7 @@ ZEND_METHOD(reflection_class, getFileName)
}
GET_REFLECTION_OBJECT_PTR(ce);
if (ce->type == ZEND_USER_CLASS) {
- RETURN_STRING(ce->filename, 1);
+ RETURN_STRING(ce->info.user.filename, 1);
}
RETURN_FALSE;
}
@@ -3329,7 +3582,7 @@ ZEND_METHOD(reflection_class, getStartLine)
}
GET_REFLECTION_OBJECT_PTR(ce);
if (ce->type == ZEND_USER_FUNCTION) {
- RETURN_LONG(ce->line_start);
+ RETURN_LONG(ce->info.user.line_start);
}
RETURN_FALSE;
}
@@ -3347,7 +3600,7 @@ ZEND_METHOD(reflection_class, getEndLine)
}
GET_REFLECTION_OBJECT_PTR(ce);
if (ce->type == ZEND_USER_CLASS) {
- RETURN_LONG(ce->line_end);
+ RETURN_LONG(ce->info.user.line_end);
}
RETURN_FALSE;
}
@@ -3364,8 +3617,8 @@ ZEND_METHOD(reflection_class, getDocComment)
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
- if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
- RETURN_STRINGL(ce->doc_comment, ce->doc_comment_len, 1);
+ if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
+ RETURN_STRINGL(ce->info.user.doc_comment, ce->info.user.doc_comment_len, 1);
}
RETURN_FALSE;
}
@@ -3397,7 +3650,7 @@ ZEND_METHOD(reflection_class, hasMethod)
{
reflection_object *intern;
zend_class_entry *ce;
- char *name, *lc_name;
+ char *name, *lc_name;
int name_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3427,7 +3680,7 @@ ZEND_METHOD(reflection_class, getMethod)
zend_class_entry *ce;
zend_function *mptr;
zval obj_tmp;
- char *name, *lc_name;
+ char *name, *lc_name;
int name_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3458,7 +3711,7 @@ ZEND_METHOD(reflection_class, getMethod)
efree(lc_name);
} else {
efree(lc_name);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Method %s does not exist", name);
return;
}
@@ -3496,7 +3749,7 @@ static int _addmethod_va(zend_function *mptr TSRMLS_DC, int num_args, va_list ar
zval *retval = va_arg(args, zval*);
long filter = va_arg(args, long);
zval *obj = va_arg(args, zval *);
-
+
_addmethod(mptr, ce, retval, filter, obj TSRMLS_CC);
return ZEND_HASH_APPLY_KEEP;
}
@@ -3542,7 +3795,7 @@ ZEND_METHOD(reflection_class, hasProperty)
reflection_object *intern;
zend_property_info *property_info;
zend_class_entry *ce;
- char *name;
+ char *name;
int name_len;
zval *property;
@@ -3561,7 +3814,7 @@ ZEND_METHOD(reflection_class, hasProperty)
if (intern->obj && Z_OBJ_HANDLER_P(intern->obj, has_property)) {
MAKE_STD_ZVAL(property);
ZVAL_STRINGL(property, name, name_len, 1);
- if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 2 TSRMLS_CC)) {
+ if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 2, 0 TSRMLS_CC)) {
zval_ptr_dtor(&property);
RETURN_TRUE;
}
@@ -3579,7 +3832,7 @@ ZEND_METHOD(reflection_class, getProperty)
reflection_object *intern;
zend_class_entry *ce, **pce;
zend_property_info *property_info;
- char *name, *tmp, *classname;
+ char *name, *tmp, *classname;
int name_len, classname_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3635,9 +3888,9 @@ ZEND_METHOD(reflection_class, getProperty)
if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
return;
- }
+ }
}
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Property %s does not exist", name);
}
/* }}} */
@@ -3653,7 +3906,7 @@ static int _addproperty(zend_property_info *pptr TSRMLS_DC, int num_args, va_lis
if (pptr->flags & ZEND_ACC_SHADOW) {
return 0;
}
-
+
if (pptr->flags & filter) {
ALLOC_ZVAL(property);
reflection_property_factory(ce, pptr, property TSRMLS_CC);
@@ -3771,7 +4024,7 @@ ZEND_METHOD(reflection_class, getConstant)
reflection_object *intern;
zend_class_entry *ce;
zval **value;
- char *name;
+ char *name;
int name_len;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -3827,6 +4080,39 @@ ZEND_METHOD(reflection_class, isInstantiable)
}
/* }}} */
+/* {{{ proto public bool ReflectionClass::isCloneable()
+ Returns whether this class is cloneable */
+ZEND_METHOD(reflection_class, isCloneable)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zval obj;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+ if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
+ RETURN_FALSE;
+ }
+ if (intern->obj) {
+ if (ce->clone) {
+ RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
+ } else {
+ RETURN_BOOL(Z_OBJ_HANDLER_P(intern->obj, clone_obj) != NULL);
+ }
+ } else {
+ if (ce->clone) {
+ RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
+ } else {
+ object_init_ex(&obj, ce);
+ RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
+ zval_dtor(&obj);
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionClass::isInterface()
Returns whether this is an interface or a class */
ZEND_METHOD(reflection_class, isInterface)
@@ -3835,6 +4121,14 @@ ZEND_METHOD(reflection_class, isInterface)
}
/* }}} */
+/* {{{ proto public bool ReflectionClass::isTrait()
+ Returns whether this is a trait */
+ZEND_METHOD(reflection_class, isTrait)
+{
+ _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT & ~ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionClass::isFinal()
Returns whether this class is final */
ZEND_METHOD(reflection_class, isFinal)
@@ -3879,7 +4173,7 @@ ZEND_METHOD(reflection_class, isInstance)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
- GET_REFLECTION_OBJECT_PTR(ce);
+ GET_REFLECTION_OBJECT_PTR(ce);
RETURN_BOOL(HAS_CLASS_ENTRY(*object) && instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC));
}
/* }}} */
@@ -3891,7 +4185,7 @@ ZEND_METHOD(reflection_class, newInstance)
zval *retval_ptr = NULL;
reflection_object *intern;
zend_class_entry *ce;
-
+
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
@@ -3956,6 +4250,24 @@ ZEND_METHOD(reflection_class, newInstance)
}
/* }}} */
+/* {{{ proto public stdclass ReflectionClass::newInstanceWithoutConstructor()
+ Returns an instance of this class without invoking its constructor */
+ZEND_METHOD(reflection_class, newInstanceWithoutConstructor)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ METHOD_NOTSTATIC(reflection_class_ptr);
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ if (ce->create_object != NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s is an internal class that cannot be instantiated without invoking its constructor", ce->name);
+ }
+
+ object_init_ex(return_value, ce);
+}
+/* }}} */
+
/* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args])
Returns an instance of this class */
ZEND_METHOD(reflection_class, newInstanceArgs)
@@ -3965,8 +4277,8 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
zend_class_entry *ce;
int argc = 0;
HashTable *args;
-
-
+
+
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
@@ -3976,7 +4288,7 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
if (ZEND_NUM_ARGS() > 0) {
argc = args->nNumOfElements;
}
-
+
/* Run the constructor if there is one */
if (ce->constructor) {
zval ***params = NULL;
@@ -3987,10 +4299,10 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
return;
}
-
+
if (argc) {
params = safe_emalloc(sizeof(zval **), argc, 0);
- zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
+ zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
params -= argc;
}
@@ -4086,6 +4398,82 @@ ZEND_METHOD(reflection_class, getInterfaceNames)
}
/* }}} */
+/* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
+ Returns an array of traits used by this class */
+ZEND_METHOD(reflection_class, getTraits)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_uint i;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+
+ for (i=0; i < ce->num_traits; i++) {
+ zval *trait;
+ ALLOC_ZVAL(trait);
+ zend_reflection_class_factory(ce->traits[i], trait TSRMLS_CC);
+ add_assoc_zval_ex(return_value, ce->traits[i]->name, ce->traits[i]->name_length + 1, trait);
+ }
+}
+/* }}} */
+
+/* {{{ proto public String[] ReflectionClass::getTraitNames()
+ Returns an array of names of traits used by this class */
+ZEND_METHOD(reflection_class, getTraitNames)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_uint i;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+
+ for (i=0; i < ce->num_traits; i++) {
+ add_next_index_stringl(return_value, ce->traits[i]->name, ce->traits[i]->name_length, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto public arra ReflectionClass::getTraitaliases()
+ Returns an array of trait aliases */
+ZEND_METHOD(reflection_class, getTraitAliases)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+
+ if (ce->trait_aliases) {
+ zend_uint i = 0;
+ while (ce->trait_aliases[i]) {
+ char *method_name;
+ int method_name_len;
+ zend_trait_method_reference *cur_ref = ce->trait_aliases[i]->trait_method;
+
+ if (ce->trait_aliases[i]->alias) {
+ method_name_len = spprintf(&method_name, 0, "%s::%s", cur_ref->class_name, cur_ref->method_name);
+ add_assoc_stringl_ex(return_value, ce->trait_aliases[i]->alias, ce->trait_aliases[i]->alias_len + 1, method_name, method_name_len, 0);
+ }
+ i++;
+ }
+ }
+}
+/* }}} */
+
/* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
Returns the class' parent class, or, if none exists, FALSE */
ZEND_METHOD(reflection_class, getParentClass)
@@ -4097,7 +4485,7 @@ ZEND_METHOD(reflection_class, getParentClass)
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
-
+
if (ce->parent) {
zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC);
} else {
@@ -4120,16 +4508,16 @@ ZEND_METHOD(reflection_class, isSubclassOf)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &class_name) == FAILURE) {
return;
}
-
+
switch(class_name->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(class_name));
return;
}
class_ce = *pce;
- break;
+ break;
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr TSRMLS_CC)) {
argument = (reflection_object *) zend_object_store_get_object(class_name TSRMLS_CC);
@@ -4142,7 +4530,7 @@ ZEND_METHOD(reflection_class, isSubclassOf)
}
/* no break */
default:
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter one must either be a string or a ReflectionClass object");
return;
}
@@ -4165,16 +4553,16 @@ ZEND_METHOD(reflection_class, implementsInterface)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &interface) == FAILURE) {
return;
}
-
+
switch(interface->type) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(interface));
return;
}
interface_ce = *pce;
- break;
+ break;
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr TSRMLS_CC)) {
argument = (reflection_object *) zend_object_store_get_object(interface TSRMLS_CC);
@@ -4187,13 +4575,13 @@ ZEND_METHOD(reflection_class, implementsInterface)
}
/* no break */
default:
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Parameter one must either be a string or a ReflectionClass object");
return;
}
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s is a Class", interface_ce->name);
return;
}
@@ -4207,7 +4595,7 @@ ZEND_METHOD(reflection_class, isIterateable)
{
reflection_object *intern;
zend_class_entry *ce;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -4225,7 +4613,7 @@ ZEND_METHOD(reflection_class, getExtension)
{
reflection_object *intern;
zend_class_entry *ce;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -4233,8 +4621,8 @@ ZEND_METHOD(reflection_class, getExtension)
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
- if (ce->module) {
- reflection_extension_factory(return_value, ce->module->name TSRMLS_CC);
+ if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
+ reflection_extension_factory(return_value, ce->info.internal.module->name TSRMLS_CC);
}
}
/* }}} */
@@ -4245,7 +4633,7 @@ ZEND_METHOD(reflection_class, getExtensionName)
{
reflection_object *intern;
zend_class_entry *ce;
-
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -4253,8 +4641,8 @@ ZEND_METHOD(reflection_class, getExtensionName)
METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce);
- if (ce->module) {
- RETURN_STRING(ce->module->name, 1);
+ if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
+ RETURN_STRING(ce->info.internal.module->name, 1);
} else {
RETURN_FALSE;
}
@@ -4266,7 +4654,7 @@ ZEND_METHOD(reflection_class, getExtensionName)
ZEND_METHOD(reflection_class, inNamespace)
{
zval **name;
- char *colon;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -4275,8 +4663,8 @@ ZEND_METHOD(reflection_class, inNamespace)
RETURN_FALSE;
}
if (Z_TYPE_PP(name) == IS_STRING
- && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
- && colon > Z_STRVAL_PP(name))
+ && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
+ && backslash > Z_STRVAL_PP(name))
{
RETURN_TRUE;
}
@@ -4289,7 +4677,7 @@ ZEND_METHOD(reflection_class, inNamespace)
ZEND_METHOD(reflection_class, getNamespaceName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -4312,7 +4700,7 @@ ZEND_METHOD(reflection_class, getNamespaceName)
ZEND_METHOD(reflection_class, getShortName)
{
zval **name;
- char *backslash;
+ const char *backslash;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -4359,7 +4747,8 @@ ZEND_METHOD(reflection_property, export)
ZEND_METHOD(reflection_property, __construct)
{
zval *propname, *classname;
- char *name_str, *class_name, *prop_name;
+ char *name_str;
+ const char *class_name, *prop_name;
int name_len, dynam_prop = 0;
zval *object;
reflection_object *intern;
@@ -4377,13 +4766,13 @@ ZEND_METHOD(reflection_property, __construct)
if (intern == NULL) {
return;
}
-
+
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_P(classname));
+ "Class %s does not exist", Z_STRVAL_P(classname));
return;
}
ce = *pce;
@@ -4392,7 +4781,7 @@ ZEND_METHOD(reflection_property, __construct)
case IS_OBJECT:
ce = Z_OBJCE_P(classname);
break;
-
+
default:
_DO_THROW("The parameter class is expected to be either a string or an object");
/* returns out of this function */
@@ -4410,12 +4799,12 @@ ZEND_METHOD(reflection_property, __construct)
return;
}
}
-
+
if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
/* we have to search the class hierarchy for this (implicit) public or protected property */
zend_class_entry *tmp_ce = ce;
zend_property_info *tmp_info;
-
+
while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, name_str, name_len + 1, (void **) &tmp_info) != SUCCESS) {
ce = tmp_ce;
property_info = tmp_info;
@@ -4423,19 +4812,19 @@ ZEND_METHOD(reflection_property, __construct)
}
}
- MAKE_STD_ZVAL(classname);
+ MAKE_STD_ZVAL(classname);
MAKE_STD_ZVAL(propname);
-
+
if (dynam_prop == 0) {
zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
ZVAL_STRINGL(classname, property_info->ce->name, property_info->ce->name_length, 1);
ZVAL_STRING(propname, prop_name, 1);
} else {
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
ZVAL_STRINGL(propname, name_str, name_len, 1);
}
- zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
+ reflection_update_property(object, "class", classname);
+ reflection_update_property(object, "name", propname);
reference = (property_reference*) emalloc(sizeof(property_reference));
if (dynam_prop) {
@@ -4485,7 +4874,7 @@ ZEND_METHOD(reflection_property, getName)
}
/* }}} */
-static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
+static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
{
reflection_object *intern;
property_reference *ref;
@@ -4496,6 +4885,7 @@ static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
GET_REFLECTION_OBJECT_PTR(ref);
RETURN_BOOL(ref->prop.flags & mask);
}
+/* }}} */
/* {{{ proto public bool ReflectionProperty::isPublic()
Returns whether this property is public */
@@ -4560,14 +4950,14 @@ ZEND_METHOD(reflection_property, getValue)
reflection_object *intern;
property_reference *ref;
zval *object, name;
- zval **member = NULL, *member_p = NULL;
+ zval *member_p = NULL;
METHOD_NOTSTATIC(reflection_property_ptr);
GET_REFLECTION_OBJECT_PTR(ref);
if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) {
_default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
zval_dtor(&name);
return;
@@ -4575,14 +4965,16 @@ ZEND_METHOD(reflection_property, getValue)
if ((ref->prop.flags & ZEND_ACC_STATIC)) {
zend_update_class_constants(intern->ce TSRMLS_CC);
- if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) {
+ if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
/* Bails out */
}
- MAKE_COPY_ZVAL(member, return_value);
+ *return_value= *CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+ zval_copy_ctor(return_value);
+ INIT_PZVAL(return_value);
} else {
- char *class_name, *prop_name;
-
+ const char *class_name, *prop_name;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
@@ -4606,16 +4998,14 @@ ZEND_METHOD(reflection_property, setValue)
zval **variable_ptr;
zval *object, name;
zval *value;
- int setter_done = 0;
zval *tmp;
- HashTable *prop_table;
METHOD_NOTSTATIC(reflection_property_ptr);
GET_REFLECTION_OBJECT_PTR(ref);
if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
_default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
zval_dtor(&name);
return;
@@ -4628,36 +5018,37 @@ ZEND_METHOD(reflection_property, setValue)
}
}
zend_update_class_constants(intern->ce TSRMLS_CC);
- prop_table = CE_STATIC_MEMBERS(intern->ce);
- if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) {
+ if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
/* Bails out */
}
- if (*variable_ptr == value) {
- setter_done = 1;
- } else {
+ variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+ if (*variable_ptr != value) {
if (PZVAL_IS_REF(*variable_ptr)) {
- zval_dtor(*variable_ptr);
- (*variable_ptr)->type = value->type;
+ zval garbage = **variable_ptr; /* old value should be destroyed */
+
+ /* To check: can't *variable_ptr be some system variable like error_zval here? */
+ Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value);
(*variable_ptr)->value = value->value;
if (Z_REFCOUNT_P(value) > 0) {
zval_copy_ctor(*variable_ptr);
}
- setter_done = 1;
- }
- }
- if (!setter_done) {
- zval **foo;
+ zval_dtor(&garbage);
+ } else {
+ zval *garbage = *variable_ptr;
- Z_ADDREF_P(value);
- if (PZVAL_IS_REF(value)) {
- SEPARATE_ZVAL(&value);
+ /* if we assign referenced variable, we should separate it */
+ Z_ADDREF_P(value);
+ if (PZVAL_IS_REF(value)) {
+ SEPARATE_ZVAL(&value);
+ }
+ *variable_ptr = value;
+ zval_ptr_dtor(&garbage);
}
- zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
}
} else {
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
return;
@@ -4676,7 +5067,7 @@ ZEND_METHOD(reflection_property, getDeclaringClass)
property_reference *ref;
zend_class_entry *tmp_ce, *ce;
zend_property_info *tmp_info;
- char *prop_name, *class_name;
+ const char *prop_name, *class_name;
int prop_name_len;
if (zend_parse_parameters_none() == FAILURE) {
@@ -4780,14 +5171,14 @@ ZEND_METHOD(reflection_extension, __construct)
zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
free_alloca(lcname, use_heap);
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Extension %s does not exist", name_str);
return;
}
free_alloca(lcname, use_heap);
MAKE_STD_ZVAL(name);
ZVAL_STRING(name, module->name, 1);
- zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+ reflection_update_property( object, "name", name);
intern->ptr = module;
intern->ref_type = REF_TYPE_OTHER;
intern->ce = NULL;
@@ -4873,7 +5264,7 @@ ZEND_METHOD(reflection_extension, getFunctions)
efree(lc_name);
continue;
}
-
+
ALLOC_ZVAL(function);
reflection_function_factory(fptr, NULL, function TSRMLS_CC);
add_assoc_zval_ex(return_value, func->fname, fname_len+1, function);
@@ -4884,7 +5275,7 @@ ZEND_METHOD(reflection_extension, getFunctions)
}
/* }}} */
-static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
zval *const_val;
zval *retval = va_arg(args, zval*);
@@ -4899,6 +5290,7 @@ static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list
}
return 0;
}
+/* }}} */
/* {{{ proto public array ReflectionExtension::getConstants()
Returns an associative array containing this extension's constants and their values */
@@ -4958,7 +5350,7 @@ static int add_extension_class(zend_class_entry **pce TSRMLS_DC, int num_args, v
struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
int add_reflection_class = va_arg(args, int);
- if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+ if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
if (add_reflection_class) {
ALLOC_ZVAL(zclass);
zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
@@ -5017,11 +5409,11 @@ ZEND_METHOD(reflection_extension, getDependencies)
return;
}
GET_REFLECTION_OBJECT_PTR(module);
-
+
array_init(return_value);
dep = module->deps;
-
+
if (!dep)
{
return;
@@ -5031,7 +5423,7 @@ ZEND_METHOD(reflection_extension, getDependencies)
char *relation;
char *rel_type;
int len;
-
+
switch(dep->type) {
case MODULE_DEP_REQUIRED:
rel_type = "Required";
@@ -5047,10 +5439,10 @@ ZEND_METHOD(reflection_extension, getDependencies)
break;
}
- len = spprintf(&relation, 0, "%s%s%s%s%s",
+ len = spprintf(&relation, 0, "%s%s%s%s%s",
rel_type,
dep->rel ? " " : "",
- dep->rel ? dep->rel : "",
+ dep->rel ? dep->rel : "",
dep->version ? " " : "",
dep->version ? dep->version : "");
add_assoc_stringl(return_value, dep->name, relation, len, 0);
@@ -5059,7 +5451,7 @@ ZEND_METHOD(reflection_extension, getDependencies)
}
/* }}} */
-/* {{{ proto public void ReflectionExtension::info() U
+/* {{{ proto public void ReflectionExtension::info()
Prints phpinfo block for the extension */
ZEND_METHOD(reflection_extension, info)
{
@@ -5075,6 +5467,180 @@ ZEND_METHOD(reflection_extension, info)
}
/* }}} */
+/* {{{ proto public bool ReflectionExtension::isPersistent()
+ Returns whether this extension is persistent */
+ZEND_METHOD(reflection_extension, isPersistent)
+{
+ reflection_object *intern;
+ zend_module_entry *module;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(module);
+
+ RETURN_BOOL(module->type == MODULE_PERSISTENT);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionExtension::isTemporary()
+ Returns whether this extension is temporary */
+ZEND_METHOD(reflection_extension, isTemporary)
+{
+ reflection_object *intern;
+ zend_module_entry *module;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(module);
+
+ RETURN_BOOL(module->type == MODULE_TEMPORARY);
+}
+/* }}} */
+
+/* {{{ proto public static mixed ReflectionZendExtension::export(string name [, bool return]) throws ReflectionException
+ * Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
+ZEND_METHOD(reflection_zend_extension, export)
+{
+ _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_zend_extension_ptr, 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::__construct(string name)
+ Constructor. Throws an Exception in case the given Zend extension does not exist */
+ZEND_METHOD(reflection_zend_extension, __construct)
+{
+ zval *name;
+ zval *object;
+ reflection_object *intern;
+ zend_extension *extension;
+ char *name_str;
+ int name_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
+ return;
+ }
+
+ object = getThis();
+ intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
+ if (intern == NULL) {
+ return;
+ }
+
+ extension = zend_get_extension(name_str);
+ if (!extension) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ "Zend Extension %s does not exist", name_str);
+ return;
+ }
+ MAKE_STD_ZVAL(name);
+ ZVAL_STRING(name, extension->name, 1);
+ reflection_update_property(object, "name", name);
+ intern->ptr = extension;
+ intern->ref_type = REF_TYPE_OTHER;
+ intern->ce = NULL;
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionZendExtension::__toString()
+ Returns a string representation */
+ZEND_METHOD(reflection_zend_extension, __toString)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+ string str;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+ string_init(&str);
+ _zend_extension_string(&str, extension, "" TSRMLS_CC);
+ RETURN_STRINGL(str.string, str.len - 1, 0);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionZendExtension::getName()
+ Returns the name of this Zend extension */
+ZEND_METHOD(reflection_zend_extension, getName)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->name, 1);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionZendExtension::getVersion()
+ Returns the version information of this Zend extension */
+ZEND_METHOD(reflection_zend_extension, getVersion)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->version ? extension->version : "", 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::getAuthor()
+ * Returns the name of this Zend extension's author */
+ZEND_METHOD(reflection_zend_extension, getAuthor)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->author ? extension->author : "", 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::getURL()
+ Returns this Zend extension's URL*/
+ZEND_METHOD(reflection_zend_extension, getURL)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->URL ? extension->URL : "", 1);
+}
+/* }}} */
+
+/* {{{ proto public void ReflectionZendExtension::getCopyright()
+ Returns this Zend extension's copyright information */
+ZEND_METHOD(reflection_zend_extension, getCopyright)
+{
+ reflection_object *intern;
+ zend_extension *extension;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(extension);
+
+ RETURN_STRING(extension->copyright ? extension->copyright : "", 1);
+}
+/* }}} */
+
/* {{{ method tables */
static const zend_function_entry reflection_exception_functions[] = {
PHP_FE_END
@@ -5130,6 +5696,8 @@ static const zend_function_entry reflection_function_abstract_functions[] = {
ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
@@ -5154,6 +5722,7 @@ static const zend_function_entry reflection_function_functions[] = {
ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
+ ZEND_ME(reflection_function, getClosure, arginfo_reflection__void, 0)
PHP_FE_END
};
@@ -5182,6 +5751,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_getClosure, 0)
+ ZEND_ARG_INFO(0, object)
+ZEND_END_ARG_INFO()
+
static const zend_function_entry reflection_method_functions[] = {
ZEND_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
@@ -5194,6 +5767,7 @@ static const zend_function_entry reflection_method_functions[] = {
ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_method, getClosure, arginfo_reflection_method_getClosure, 0)
ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
@@ -5263,6 +5837,9 @@ ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
ZEND_ARG_INFO(0, args)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstanceWithoutConstructor, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
ZEND_ARG_ARRAY_INFO(0, args, 0)
ZEND_END_ARG_INFO()
@@ -5284,6 +5861,7 @@ static const zend_function_entry reflection_class_functions[] = {
ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
@@ -5301,11 +5879,16 @@ static const zend_function_entry reflection_class_functions[] = {
ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getTraits, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getTraitNames, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getTraitAliases, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
+ ZEND_ME(reflection_class, newInstanceWithoutConstructor, arginfo_reflection_class_newInstanceWithoutConstructor, 0)
ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
@@ -5402,15 +5985,19 @@ static const zend_function_entry reflection_parameter_functions[] = {
ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, canBePassedByValue, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0)
PHP_FE_END
};
@@ -5437,6 +6024,25 @@ static const zend_function_entry reflection_extension_functions[] = {
ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_extension, isPersistent, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_extension, isTemporary, arginfo_reflection__void, 0)
+ PHP_FE_END
+};
+
+ZEND_BEGIN_ARG_INFO(arginfo_reflection_zend_extension___construct, 0)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry reflection_zend_extension_functions[] = {
+ ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
+ ZEND_ME(reflection_zend_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
+ ZEND_ME(reflection_zend_extension, __construct, arginfo_reflection_extension___construct, 0)
+ ZEND_ME(reflection_zend_extension, __toString, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getName, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getVersion, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getAuthor, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getURL, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_zend_extension, getCopyright, arginfo_reflection__void, 0)
PHP_FE_END
};
/* }}} */
@@ -5448,19 +6054,19 @@ const zend_function_entry reflection_ext_functions[] = { /* {{{ */
static zend_object_handlers *zend_std_obj_handlers;
/* {{{ _reflection_write_property */
-static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+static void _reflection_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
if ((Z_TYPE_P(member) == IS_STRING)
- && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
+ && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
&& ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
|| (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
{
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
}
else
{
- zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC);
+ zend_std_obj_handlers->write_property(object, member, value, key TSRMLS_CC);
}
}
/* }}} */
@@ -5547,6 +6153,12 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
reflection_register_implement(reflection_extension_ptr, reflector_ptr TSRMLS_CC);
zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
+ INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
+ _reflection_entry.create_object = reflection_objects_new;
+ reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
+ reflection_register_implement(reflection_zend_extension_ptr, reflector_ptr TSRMLS_CC);
+ zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
+
return SUCCESS;
} /* }}} */
diff --git a/ext/reflection/php_reflection.h b/ext/reflection/php_reflection.h
index b68ee58a41..6f288546fc 100644
--- a/ext/reflection/php_reflection.h
+++ b/ext/reflection/php_reflection.h
@@ -40,6 +40,7 @@ extern PHPAPI zend_class_entry *reflection_object_ptr;
extern PHPAPI zend_class_entry *reflection_method_ptr;
extern PHPAPI zend_class_entry *reflection_property_ptr;
extern PHPAPI zend_class_entry *reflection_extension_ptr;
+extern PHPAPI zend_class_entry *reflection_zend_extension_ptr;
PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC);
diff --git a/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt b/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt
index 733c4c7e4d..ffd81ffb87 100644
--- a/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt
@@ -3,6 +3,8 @@ ReflectionClass::getStaticPropertyValue()
--CREDITS--
Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
--FILE--
<?php
class A {
diff --git a/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt b/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt
new file mode 100644
index 0000000000..c299412e13
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt
@@ -0,0 +1,61 @@
+--TEST--
+ReflectionClass::getStaticPropertyValue()
+--CREDITS--
+Robin Fernandes <robinf@php.net>
+Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+class A {
+ static private $privateOverridden = "original private";
+ static protected $protectedOverridden = "original protected";
+ static public $publicOverridden = "original public";
+}
+
+class B extends A {
+ static private $privateOverridden = "changed private";
+ static protected $protectedOverridden = "changed protected";
+ static public $publicOverridden = "changed public";
+}
+
+echo "Retrieving static values from A:\n";
+$rcA = new ReflectionClass('A');
+var_dump($rcA->getStaticPropertyValue("privateOverridden", "default value"));
+var_dump($rcA->getStaticPropertyValue("\0A\0privateOverridden"));
+var_dump($rcA->getStaticPropertyValue("protectedOverridden", "default value"));
+var_dump($rcA->getStaticPropertyValue("\0*\0protectedOverridden"));
+var_dump($rcA->getStaticPropertyValue("publicOverridden"));
+
+echo "\nRetrieving static values from B:\n";
+$rcB = new ReflectionClass('B');
+var_dump($rcB->getStaticPropertyValue("\0A\0privateOverridden"));
+var_dump($rcB->getStaticPropertyValue("\0B\0privateOverridden"));
+var_dump($rcB->getStaticPropertyValue("\0*\0protectedOverridden"));
+var_dump($rcB->getStaticPropertyValue("publicOverridden"));
+
+echo "\nRetrieving non-existent values from A with no default value:\n";
+try {
+ var_dump($rcA->getStaticPropertyValue("protectedOverridden"));
+ echo "you should not see this";
+} catch (Exception $e) {
+ echo $e->getMessage() . "\n";
+}
+
+try {
+ var_dump($rcA->getStaticPropertyValue("privateOverridden"));
+ echo "you should not see this";
+} catch (Exception $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECTF--
+Retrieving static values from A:
+string(13) "default value"
+
+Fatal error: Uncaught exception 'ReflectionException' with message 'Class A does not have a property named ' in %sReflectionClass_getStaticPropertyValue_001_2_4.php:%d
+Stack trace:
+#0 %sReflectionClass_getStaticPropertyValue_001_2_4.php(%d): ReflectionClass->getStaticPropertyValue('?A?privateOverr...')
+#1 {main}
+ thrown in %sReflectionClass_getStaticPropertyValue_001_2_4.php on line %d
diff --git a/ext/reflection/tests/ReflectionClass_isCloneable_001.phpt b/ext/reflection/tests/ReflectionClass_isCloneable_001.phpt
new file mode 100644
index 0000000000..f1042cc130
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_isCloneable_001.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Testing ReflectionClass::isCloneable()
+--SKIPIF--
+<?php if (!extension_loaded('simplexml') || !extension_loaded('xmlwriter')) die("skip SimpleXML and XMLWriter is required for this test"); ?>
+--FILE--
+<?php
+
+class foo {
+}
+$foo = new foo;
+
+print "User class\n";
+$obj = new ReflectionClass($foo);
+var_dump($obj->isCloneable());
+$obj = new ReflectionObject($foo);
+var_dump($obj->isCloneable());
+$h = clone $foo;
+
+class bar {
+ private function __clone() {
+ }
+}
+$bar = new bar;
+print "User class - private __clone\n";
+$obj = new ReflectionClass($bar);
+var_dump($obj->isCloneable());
+$obj = new ReflectionObject($bar);
+var_dump($obj->isCloneable());
+$h = clone $foo;
+
+print "Closure\n";
+$closure = function () { };
+$obj = new ReflectionClass($closure);
+var_dump($obj->isCloneable());
+$obj = new ReflectionObject($closure);
+var_dump($obj->isCloneable());
+$h = clone $closure;
+
+print "Internal class - SimpleXMLElement\n";
+$obj = new ReflectionClass('simplexmlelement');
+var_dump($obj->isCloneable());
+$obj = new ReflectionObject(new simplexmlelement('<test></test>'));
+var_dump($obj->isCloneable());
+$h = clone new simplexmlelement('<test></test>');
+
+print "Internal class - XMLWriter\n";
+$obj = new ReflectionClass('xmlwriter');
+var_dump($obj->isCloneable());
+$obj = new ReflectionObject(new XMLWriter);
+var_dump($obj->isCloneable());
+$h = clone new xmlwriter;
+
+?>
+--EXPECTF--
+User class
+bool(true)
+bool(true)
+User class - private __clone
+bool(false)
+bool(false)
+Closure
+bool(true)
+bool(true)
+Internal class - SimpleXMLElement
+bool(true)
+bool(true)
+Internal class - XMLWriter
+bool(false)
+bool(false)
+
+Fatal error: Trying to clone an uncloneable object of class XMLWriter in %s on line %d
diff --git a/ext/reflection/tests/ReflectionClass_isCloneable_002.phpt b/ext/reflection/tests/ReflectionClass_isCloneable_002.phpt
new file mode 100644
index 0000000000..7cde5768cc
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_isCloneable_002.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Testing ReflectionClass::isCloneable() with non instantiable objects
+--FILE--
+<?php
+
+trait foo {
+}
+$obj = new ReflectionClass('foo');
+var_dump($obj->isCloneable());
+
+abstract class bar {
+}
+$obj = new ReflectionClass('bar');
+var_dump($obj->isCloneable());
+
+interface baz {
+}
+$obj = new ReflectionClass('baz');
+var_dump($obj->isCloneable());
+
+?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
diff --git a/ext/reflection/tests/ReflectionClass_newInstanceArgs_002.phpt b/ext/reflection/tests/ReflectionClass_newInstanceArgs_002.phpt
index af5aeff2df..dd6f4384ee 100644
--- a/ext/reflection/tests/ReflectionClass_newInstanceArgs_002.phpt
+++ b/ext/reflection/tests/ReflectionClass_newInstanceArgs_002.phpt
@@ -17,4 +17,4 @@ var_dump($a);
?>
--EXPECTF--
-Catchable fatal error: Argument 1 passed to ReflectionClass::newInstanceArgs() must be an array, string given in %s on line 8
+Catchable fatal error: Argument 1 passed to ReflectionClass::newInstanceArgs() must be of the type array, string given in %s on line 8
diff --git a/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt b/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt
new file mode 100644
index 0000000000..1932dbfaf1
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt
@@ -0,0 +1,33 @@
+--TEST--
+ReflectionClass::newInstanceWithoutConstructor()
+--CREDITS--
+Sebastian Bergmann <sebastian@php.net>
+--FILE--
+<?php
+class Foo
+{
+ public function __construct()
+ {
+ print __METHOD__;
+ }
+}
+
+$class = new ReflectionClass('Foo');
+var_dump($class->newInstanceWithoutConstructor());
+
+$class = new ReflectionClass('StdClass');
+var_dump($class->newInstanceWithoutConstructor());
+
+$class = new ReflectionClass('DateTime');
+var_dump($class->newInstanceWithoutConstructor());
+--EXPECTF--
+object(Foo)#%d (0) {
+}
+object(stdClass)#%d (0) {
+}
+
+Fatal error: Uncaught exception 'ReflectionException' with message 'Class DateTime is an internal class that cannot be instantiated without invoking its constructor' in %sReflectionClass_newInstanceWithoutConstructor.php:%d
+Stack trace:
+#0 %sReflectionClass_newInstanceWithoutConstructor.php(%d): ReflectionClass->newInstanceWithoutConstructor()
+#1 {main}
+ thrown in %sReflectionClass_newInstanceWithoutConstructor.php on line %d
diff --git a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt
index 082ef676cd..9e8f01e679 100644
--- a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt
@@ -3,6 +3,8 @@ ReflectionClass::setStaticPropertyValue()
--CREDITS--
Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
--FILE--
<?php
class A {
diff --git a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt
new file mode 100644
index 0000000000..1092f6553d
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt
@@ -0,0 +1,61 @@
+--TEST--
+ReflectionClass::setStaticPropertyValue()
+--CREDITS--
+Robin Fernandes <robinf@php.net>
+Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+class A {
+ static private $privateOverridden = "original private";
+ static protected $protectedOverridden = "original protected";
+ static public $publicOverridden = "original public";
+}
+
+class B extends A {
+ static private $privateOverridden = "changed private";
+ static protected $protectedOverridden = "changed protected";
+ static public $publicOverridden = "changed public";
+}
+
+echo "Set static values in A:\n";
+$rcA = new ReflectionClass('A');
+$rcA->setStaticPropertyValue("\0A\0privateOverridden", "new value 1");
+$rcA->setStaticPropertyValue("\0*\0protectedOverridden", "new value 2");
+$rcA->setStaticPropertyValue("publicOverridden", "new value 3");
+print_r($rcA->getStaticProperties());
+
+echo "\nSet static values in B:\n";
+$rcB = new ReflectionClass('B');
+$rcB->setStaticPropertyValue("\0A\0privateOverridden", "new value 4");
+$rcB->setStaticPropertyValue("\0B\0privateOverridden", "new value 5");
+$rcB->setStaticPropertyValue("\0*\0protectedOverridden", "new value 6");
+$rcB->setStaticPropertyValue("publicOverridden", "new value 7");
+print_r($rcA->getStaticProperties());
+print_r($rcB->getStaticProperties());
+
+echo "\nSet non-existent values from A with no default value:\n";
+try {
+ var_dump($rcA->setStaticPropertyValue("protectedOverridden", "new value 8"));
+ echo "you should not see this";
+} catch (Exception $e) {
+ echo $e->getMessage() . "\n";
+}
+
+try {
+ var_dump($rcA->setStaticPropertyValue("privateOverridden", "new value 9"));
+ echo "you should not see this";
+} catch (Exception $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECTF--
+Set static values in A:
+
+Fatal error: Uncaught exception 'ReflectionException' with message 'Class A does not have a property named ' in %sReflectionClass_setStaticPropertyValue_001_2_4.php:%d
+Stack trace:
+#0 %sReflectionClass_setStaticPropertyValue_001_2_4.php(%d): ReflectionClass->setStaticPropertyValue('?A?privateOverr...', 'new value 1')
+#1 {main}
+ thrown in %sReflectionClass_setStaticPropertyValue_001_2_4.php on line %d
diff --git a/ext/reflection/tests/ReflectionClass_toString_001.phpt b/ext/reflection/tests/ReflectionClass_toString_001.phpt
index 6173cf0c0a..508530a547 100644
--- a/ext/reflection/tests/ReflectionClass_toString_001.phpt
+++ b/ext/reflection/tests/ReflectionClass_toString_001.phpt
@@ -34,7 +34,7 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
Property [ <default> public $name ]
}
- - Methods [43] {
+ - Methods [49] {
Method [ <internal:Reflection> final private method __clone ] {
- Parameters [0] {
@@ -78,6 +78,12 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
}
}
+ Method [ <internal:Reflection> public method isCloneable ] {
+
+ - Parameters [0] {
+ }
+ }
+
Method [ <internal:Reflection> public method getFileName ] {
- Parameters [0] {
@@ -188,6 +194,30 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
}
}
+ Method [ <internal:Reflection> public method getTraits ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal:Reflection> public method getTraitNames ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal:Reflection> public method getTraitAliases ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal:Reflection> public method isTrait ] {
+
+ - Parameters [0] {
+ }
+ }
+
Method [ <internal:Reflection> public method isAbstract ] {
- Parameters [0] {
@@ -220,6 +250,12 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
}
}
+ Method [ <internal:Reflection> public method newInstanceWithoutConstructor ] {
+
+ - Parameters [0] {
+ }
+ }
+
Method [ <internal:Reflection> public method newInstanceArgs ] {
- Parameters [1] {
diff --git a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
index f46c057c69..5df9e08c69 100644
--- a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
+++ b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
@@ -9,7 +9,7 @@ var_dump($ext->getClasses());
?>
==DONE==
--EXPECT--
-array(11) {
+array(12) {
["ReflectionException"]=>
&object(ReflectionClass)#2 (1) {
["name"]=>
@@ -65,5 +65,10 @@ array(11) {
["name"]=>
string(19) "ReflectionExtension"
}
+ ["ReflectionZendExtension"]=>
+ &object(ReflectionClass)#13 (1) {
+ ["name"]=>
+ string(23) "ReflectionZendExtension"
+ }
}
==DONE==
diff --git a/ext/reflection/tests/ReflectionExtension_isPersistant.phpt b/ext/reflection/tests/ReflectionExtension_isPersistant.phpt
new file mode 100644
index 0000000000..a78a8bbc3d
--- /dev/null
+++ b/ext/reflection/tests/ReflectionExtension_isPersistant.phpt
@@ -0,0 +1,11 @@
+--TEST--
+ReflectionExtension::isPersistent()
+--FILE--
+<?php
+$obj = new ReflectionExtension('reflection');
+var_dump($obj->isPersistent());
+?>
+==DONE==
+--EXPECT--
+bool(true)
+==DONE==
diff --git a/ext/reflection/tests/ReflectionExtension_isTemporary.phpt b/ext/reflection/tests/ReflectionExtension_isTemporary.phpt
new file mode 100644
index 0000000000..be97641be1
--- /dev/null
+++ b/ext/reflection/tests/ReflectionExtension_isTemporary.phpt
@@ -0,0 +1,11 @@
+--TEST--
+ReflectionExtension::isTemporary()
+--FILE--
+<?php
+$obj = new ReflectionExtension('reflection');
+var_dump($obj->isTemporary());
+?>
+==DONE==
+--EXPECT--
+bool(false)
+==DONE==
diff --git a/ext/reflection/tests/ReflectionFunction_getClosureScopeClass.phpt b/ext/reflection/tests/ReflectionFunction_getClosureScopeClass.phpt
new file mode 100644
index 0000000000..f725dfd088
--- /dev/null
+++ b/ext/reflection/tests/ReflectionFunction_getClosureScopeClass.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Reflection::getClosureScopeClass()
+--SKIPIF--
+<?php
+if (!extension_loaded('reflection') || !defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50399) {
+ print 'skip';
+}
+?>
+--FILE--
+<?php
+$closure = function($param) { return "this is a closure"; };
+$rf = new ReflectionFunction($closure);
+var_dump($rf->getClosureScopeClass());
+
+Class A {
+ public static function getClosure() {
+ return function($param) { return "this is a closure"; };
+ }
+}
+
+$closure = A::getClosure();
+$rf = new ReflectionFunction($closure);
+var_dump($rf->getClosureScopeClass());
+echo "Done!\n";
+--EXPECTF--
+NULL
+object(ReflectionClass)#%d (1) {
+ ["name"]=>
+ string(1) "A"
+}
+Done!
diff --git a/ext/reflection/tests/ReflectionFunction_getClosureThis.phpt b/ext/reflection/tests/ReflectionFunction_getClosureThis.phpt
new file mode 100644
index 0000000000..776bfafee0
--- /dev/null
+++ b/ext/reflection/tests/ReflectionFunction_getClosureThis.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Reflection::getClosureThis()
+--SKIPIF--
+<?php
+if (!extension_loaded('reflection') || !defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300) {
+ print 'skip';
+}
+?>
+--FILE--
+<?php
+$closure = function($param) { return "this is a closure"; };
+$rf = new ReflectionFunction($closure);
+var_dump($rf->getClosureThis());
+echo "Done!\n";
+--EXPECTF--
+NULL
+Done!
diff --git a/ext/reflection/tests/ReflectionFunction_getClosure_basic.phpt b/ext/reflection/tests/ReflectionFunction_getClosure_basic.phpt
new file mode 100644
index 0000000000..786be050c1
--- /dev/null
+++ b/ext/reflection/tests/ReflectionFunction_getClosure_basic.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Test ReflectionFunction::getClosure() function : basic functionality
+--FILE--
+<?php
+/* Prototype : public mixed ReflectionFunction::getClosure()
+ * Description: Returns a dynamically created closure for the function
+ * Source code: ext/reflection/php_reflection.c
+ * Alias to functions:
+ */
+
+echo "*** Testing ReflectionFunction::getClosure() : basic functionality ***\n";
+
+function foo()
+{
+ var_dump( "Inside foo function" );
+}
+
+function bar( $arg )
+{
+ var_dump( "Arg is " . $arg );
+}
+
+$func = new ReflectionFunction( 'foo' );
+$closure = $func->getClosure();
+$closure();
+
+$func = new ReflectionFunction( 'bar' );
+$closure = $func->getClosure();
+$closure( 'succeeded' );
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing ReflectionFunction::getClosure() : basic functionality ***
+string(19) "Inside foo function"
+string(16) "Arg is succeeded"
+===DONE===
diff --git a/ext/reflection/tests/ReflectionFunction_getClosure_error.phpt b/ext/reflection/tests/ReflectionFunction_getClosure_error.phpt
new file mode 100644
index 0000000000..9a963e41ca
--- /dev/null
+++ b/ext/reflection/tests/ReflectionFunction_getClosure_error.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test ReflectionFunction::getClosure() function : error functionality
+--FILE--
+<?php
+/* Prototype : public mixed ReflectionFunction::getClosure()
+ * Description: Returns a dynamically created closure for the function
+ * Source code: ext/reflection/php_reflection.c
+ * Alias to functions:
+ */
+
+echo "*** Testing ReflectionFunction::getClosure() : error conditions ***\n";
+
+function foo()
+{
+ var_dump( "Inside foo function" );
+}
+
+$func = new ReflectionFunction( 'foo' );
+$closure = $func->getClosure('bar');
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing ReflectionFunction::getClosure() : error conditions ***
+
+Warning: ReflectionFunction::getClosure() expects exactly 0 parameters, 1 given in %s on line %d
+===DONE===
diff --git a/ext/reflection/tests/ReflectionMethod_getClosureThis.phpt b/ext/reflection/tests/ReflectionMethod_getClosureThis.phpt
new file mode 100644
index 0000000000..58c09994cf
--- /dev/null
+++ b/ext/reflection/tests/ReflectionMethod_getClosureThis.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Reflection::getClosureThis()
+--SKIPIF--
+<?php
+if (!extension_loaded('reflection') || !defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300) {
+ print 'skip';
+}
+?>
+--FILE--
+<?php
+class StaticExample
+{
+ static function foo()
+ {
+ var_dump( "Static Example class, Hello World!" );
+ }
+}
+
+class Example
+{
+ public $bar = 42;
+ public function foo()
+ {
+ var_dump( "Example class, bar: " . $this->bar );
+ }
+}
+
+// Initialize classes
+$class = new ReflectionClass( 'Example' );
+$staticclass = new ReflectionClass( 'StaticExample' );
+$object = new Example();
+
+$method = $staticclass->getMethod( 'foo' );
+$closure = $method->getClosure();
+$rf = new ReflectionFunction($closure);
+
+var_dump($rf->getClosureThis());
+
+$method = $class->getMethod( 'foo' );
+
+$closure = $method->getClosure( $object );
+$rf = new ReflectionFunction($closure);
+
+var_dump($rf->getClosureThis());
+
+echo "Done!\n";
+--EXPECTF--
+NULL
+object(Example)#%d (1) {
+ ["bar"]=>
+ int(42)
+}
+Done!
diff --git a/ext/reflection/tests/ReflectionMethod_getClosure_basic.phpt b/ext/reflection/tests/ReflectionMethod_getClosure_basic.phpt
new file mode 100644
index 0000000000..c97c41c738
--- /dev/null
+++ b/ext/reflection/tests/ReflectionMethod_getClosure_basic.phpt
@@ -0,0 +1,55 @@
+--TEST--
+Test ReflectionMethod::getClosure() function : basic functionality
+--FILE--
+<?php
+/* Prototype : public mixed ReflectionFunction::getClosure()
+ * Description: Returns a dynamically created closure for the method
+ * Source code: ext/reflection/php_reflection.c
+ * Alias to functions:
+ */
+
+echo "*** Testing ReflectionMethod::getClosure() : basic functionality ***\n";
+
+class StaticExample
+{
+ static function foo()
+ {
+ var_dump( "Static Example class, Hello World!" );
+ }
+}
+
+class Example
+{
+ public $bar = 42;
+ public function foo()
+ {
+ var_dump( "Example class, bar: " . $this->bar );
+ }
+}
+
+// Initialize classes
+$class = new ReflectionClass( 'Example' );
+$staticclass = new ReflectionClass( 'StaticExample' );
+$object = new Example();
+$fakeobj = new StdClass();
+
+
+$method = $staticclass->getMethod( 'foo' );
+$closure = $method->getClosure();
+$closure();
+
+$method = $class->getMethod( 'foo' );
+
+$closure = $method->getClosure( $object );
+$closure();
+$object->bar = 34;
+$closure();
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing ReflectionMethod::getClosure() : basic functionality ***
+string(34) "Static Example class, Hello World!"
+string(22) "Example class, bar: 42"
+string(22) "Example class, bar: 34"
+===DONE===
diff --git a/ext/reflection/tests/ReflectionMethod_getClosure_error.phpt b/ext/reflection/tests/ReflectionMethod_getClosure_error.phpt
new file mode 100644
index 0000000000..d3b9ca3c81
--- /dev/null
+++ b/ext/reflection/tests/ReflectionMethod_getClosure_error.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Test ReflectionMethod::getClosure() function : error functionality
+--FILE--
+<?php
+/* Prototype : public mixed ReflectionFunction::getClosure()
+ * Description: Returns a dynamically created closure for the method
+ * Source code: ext/reflection/php_reflection.c
+ * Alias to functions:
+ */
+
+echo "*** Testing ReflectionMethod::getClosure() : error conditions ***\n";
+
+class StaticExample
+{
+ static function foo()
+ {
+ var_dump( "Static Example class, Hello World!" );
+ }
+}
+
+class Example
+{
+ public $bar = 42;
+ public function foo()
+ {
+ var_dump( "Example class, bar: " . $this->bar );
+ }
+}
+
+// Initialize classes
+$class = new ReflectionClass( 'Example' );
+$staticclass = new ReflectionClass( 'StaticExample' );
+$method = $class->getMethod( 'foo' );
+$staticmethod = $staticclass->getMethod( 'foo' );
+$object = new Example();
+$fakeobj = new StdClass();
+
+echo "\n-- Testing ReflectionMethod::getClosure() function with more than expected no. of arguments --\n";
+var_dump( $staticmethod->getClosure( 'foobar' ) );
+var_dump( $staticmethod->getClosure( 'foo', 'bar' ) );
+var_dump( $method->getClosure( $object, 'foobar' ) );
+
+echo "\n-- Testing ReflectionMethod::getClosure() function with Zero arguments --\n";
+$closure = $method->getClosure();
+
+echo "\n-- Testing ReflectionMethod::getClosure() function with Zero arguments --\n";
+try {
+ var_dump( $method->getClosure( $fakeobj ) );
+} catch( Exception $e ) {
+ var_dump( $e->getMessage() );
+}
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing ReflectionMethod::getClosure() : error conditions ***
+
+-- Testing ReflectionMethod::getClosure() function with more than expected no. of arguments --
+object(Closure)#%d (0) {
+}
+object(Closure)#%d (0) {
+}
+
+Warning: ReflectionMethod::getClosure() expects exactly 1 parameter, 2 given in %s on line %d
+NULL
+
+-- Testing ReflectionMethod::getClosure() function with Zero arguments --
+
+Warning: ReflectionMethod::getClosure() expects exactly 1 parameter, 0 given in %s on line %d
+
+-- Testing ReflectionMethod::getClosure() function with Zero arguments --
+string(72) "Given object is not an instance of the class this method was declared in"
+===DONE===
diff --git a/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt b/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt
index 02c7b9fa3e..72baa53fda 100644
--- a/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt
+++ b/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt
@@ -9,7 +9,7 @@ function reflectMethodModifiers($class) {
foreach ($methodArray as $method) {
echo "Modifiers for method $method->class::$method->name():\n";
- var_dump($method->getModifiers());
+ printf("0x%08x\n", $method->getModifiers());
echo "\n\n";
}
}
@@ -82,161 +82,161 @@ $a->getModifiers(1);
$a = new ReflectionMethod('ReflectionMethod::getModifiers');
echo "\nReflectionMethod::getModifiers() modifiers:\n";
-var_dump($a->getModifiers());
+printf("0x%08x\n", $a->getModifiers());
?>
--EXPECTF--
Modifiers for method TestClass::foo():
-int(65792)
+0x08010100
Modifiers for method TestClass::stat():
-int(257)
+0x08000101
Modifiers for method TestClass::priv():
-int(66560)
+0x08010400
Modifiers for method TestClass::prot():
-int(66048)
+0x08010200
Modifiers for method TestClass::fin():
-int(65796)
+0x08010104
Modifiers for method TestClass::__destruct():
-int(16640)
+0x08004100
Modifiers for method TestClass::__call():
-int(256)
+0x08000100
Modifiers for method TestClass::__clone():
-int(33024)
+0x08008100
Modifiers for method TestClass::__get():
-int(256)
+0x08000100
Modifiers for method TestClass::__set():
-int(256)
+0x08000100
Modifiers for method TestClass::__unset():
-int(256)
+0x08000100
Modifiers for method TestClass::__isset():
-int(256)
+0x08000100
Modifiers for method TestClass::__tostring():
-int(256)
+0x08000100
Modifiers for method TestClass::__sleep():
-int(65792)
+0x08010100
Modifiers for method TestClass::__wakeup():
-int(65792)
+0x08010100
Modifiers for method TestClass::__set_state():
-int(65792)
+0x08010100
Modifiers for method TestClass::__autoload():
-int(65792)
+0x08010100
Modifiers for method TestClass::foo():
-int(65792)
+0x08010100
Modifiers for method TestClass::stat():
-int(257)
+0x08000101
Modifiers for method TestClass::priv():
-int(66560)
+0x08010400
Modifiers for method TestClass::prot():
-int(66048)
+0x08010200
Modifiers for method TestClass::fin():
-int(65796)
+0x08010104
Modifiers for method TestClass::__destruct():
-int(16640)
+0x08004100
Modifiers for method TestClass::__call():
-int(256)
+0x08000100
Modifiers for method TestClass::__clone():
-int(33024)
+0x08008100
Modifiers for method TestClass::__get():
-int(256)
+0x08000100
Modifiers for method TestClass::__set():
-int(256)
+0x08000100
Modifiers for method TestClass::__unset():
-int(256)
+0x08000100
Modifiers for method TestClass::__isset():
-int(256)
+0x08000100
Modifiers for method TestClass::__tostring():
-int(256)
+0x08000100
Modifiers for method TestClass::__sleep():
-int(65792)
+0x08010100
Modifiers for method TestClass::__wakeup():
-int(65792)
+0x08010100
Modifiers for method TestClass::__set_state():
-int(65792)
+0x08010100
Modifiers for method TestClass::__autoload():
-int(65792)
+0x08010100
Modifiers for method TestInterface::int():
-int(258)
+0x08000102
Modifiers for method TestInterface::__clone():
-int(258)
+0x08000102
Modifiers for method AbstractClass::foo():
-int(65794)
+0x08010102
Wrong number of params:
-Warning: ReflectionMethod::getModifiers() expects exactly 0 parameters, 1 given in %s on line %d
+Warning: ReflectionMethod::getModifiers() expects exactly 0 parameters, 1 given in %sReflectionMethod_getModifiers_basic.php on line %d
ReflectionMethod::getModifiers() modifiers:
-int(256)
+0x00000100
diff --git a/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt b/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt
index 2ec41c2ddb..5fc7564245 100644
--- a/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt
+++ b/ext/reflection/tests/ReflectionMethod_invokeArgs_error2.phpt
@@ -24,4 +24,4 @@ try {
?>
--EXPECTF--
-Catchable fatal error: Argument 2 passed to ReflectionMethod::invokeArgs() must be an array, boolean given in %s on line %d
+Catchable fatal error: Argument 2 passed to ReflectionMethod::invokeArgs() must be of the type array, boolean given in %s on line %d
diff --git a/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt
new file mode 100644
index 0000000000..cdd00d2624
--- /dev/null
+++ b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic1.phpt
@@ -0,0 +1,52 @@
+--TEST--
+ReflectionParameter::isDefaultValueConstant() && getDefaultValueConstantName()
+--FILE--
+<?php
+
+define("CONST_TEST_1", "const1");
+
+function ReflectionParameterTest($test1=array(), $test2 = CONST_TEST_1) {
+ echo $test;
+}
+$reflect = new ReflectionFunction('ReflectionParameterTest');
+foreach($reflect->getParameters() as $param) {
+ if($param->getName() == 'test1') {
+ var_dump($param->isDefaultValueConstant());
+ }
+ if($param->getName() == 'test2') {
+ var_dump($param->isDefaultValueConstant());
+ }
+ if($param->isDefaultValueAvailable() && $param->isDefaultValueConstant()) {
+ var_dump($param->getDefaultValueConstantName());
+ }
+}
+
+class Foo2 {
+ const bar = 'Foo2::bar';
+}
+
+class Foo {
+ const bar = 'Foo::bar';
+
+ public function baz($param1 = self::bar, $param2=Foo2::bar, $param3=CONST_TEST_1) {
+ }
+}
+
+$method = new ReflectionMethod('Foo', 'baz');
+$params = $method->getParameters();
+
+foreach ($params as $param) {
+ if ($param->isDefaultValueConstant()) {
+ var_dump($param->getDefaultValueConstantName());
+ }
+}
+?>
+==DONE==
+--EXPECT--
+bool(false)
+bool(true)
+string(12) "CONST_TEST_1"
+string(9) "self::bar"
+string(9) "Foo2::bar"
+string(12) "CONST_TEST_1"
+==DONE==
diff --git a/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt
new file mode 100644
index 0000000000..1ee9e93735
--- /dev/null
+++ b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_basic2.phpt
@@ -0,0 +1,30 @@
+--TEST--
+ReflectionParameter::isDefaultValueConstant() && getDefaultValueConstantName() for namespace
+--FILE--
+<?php
+
+namespace ReflectionTestNamespace {
+ CONST TEST_CONST_1 = "Test Const 1";
+
+ class TestClass {
+ const TEST_CONST_2 = "Test Const 2 in class";
+ }
+}
+
+namespace {
+ function ReflectionParameterTest($test=ReflectionTestNamespace\TestClass::TEST_CONST_2, $test2 = ReflectionTestNamespace\CONST_TEST_1) {
+ echo $test;
+ }
+ $reflect = new ReflectionFunction('ReflectionParameterTest');
+ foreach($reflect->getParameters() as $param) {
+ if($param->isDefaultValueAvailable() && $param->isDefaultValueConstant()) {
+ echo $param->getDefaultValueConstantName() . "\n";
+ }
+ }
+ echo "==DONE==";
+}
+?>
+--EXPECT--
+ReflectionTestNamespace\TestClass::TEST_CONST_2
+ReflectionTestNamespace\CONST_TEST_1
+==DONE==
diff --git a/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt
new file mode 100644
index 0000000000..a2c2d24582
--- /dev/null
+++ b/ext/reflection/tests/ReflectionParameter_DefaultValueConstant_error.phpt
@@ -0,0 +1,23 @@
+--TEST--
+ReflectionParameter::getDefaultValueConstant() should raise exception on non optional parameter
+--FILE--
+<?php
+
+define("CONST_TEST_1", "const1");
+
+function ReflectionParameterTest($test, $test2 = CONST_TEST_1) {
+ echo $test;
+}
+$reflect = new ReflectionFunction('ReflectionParameterTest');
+foreach($reflect->getParameters() as $param) {
+ try {
+ echo $param->getDefaultValueConstantName() . "\n";
+ }
+ catch(ReflectionException $e) {
+ echo $e->getMessage() . "\n";
+ }
+}
+?>
+--EXPECT--
+Internal error: Failed to retrieve the default value
+CONST_TEST_1
diff --git a/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt b/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt
new file mode 100644
index 0000000000..82c6200122
--- /dev/null
+++ b/ext/reflection/tests/ReflectionParameter_canBePassedByValue.phpt
@@ -0,0 +1,84 @@
+--TEST--
+ReflectionParameter class - canBePassedByValue() method.
+--FILE--
+<?php
+
+function aux($fun) {
+
+ $func = new ReflectionFunction($fun);
+ $parameters = $func->getParameters();
+ foreach($parameters as $parameter) {
+ echo "Name: ", $parameter->getName(), "\n";
+ echo "Is passed by reference: ", $parameter->isPassedByReference()?"yes":"no", "\n";
+ echo "Can be passed by value: ", $parameter->canBePassedByValue()?"yes":"no", "\n";
+ echo "\n";
+ }
+
+}
+
+echo "=> array_multisort:\n\n";
+
+aux('array_multisort');
+
+
+echo "=> sort:\n\n";
+
+aux('sort');
+
+echo "=> user function:\n\n";
+
+function ufunc(&$arg1, $arg2) {}
+
+aux('ufunc');
+
+echo "Done.\n";
+
+?>
+--EXPECTF--
+=> array_multisort:
+
+Name: arr1
+Is passed by reference: yes
+Can be passed by value: yes
+
+Name: SORT_ASC_or_SORT_DESC
+Is passed by reference: yes
+Can be passed by value: yes
+
+Name: SORT_REGULAR_or_SORT_NUMERIC_or_SORT_STRING
+Is passed by reference: yes
+Can be passed by value: yes
+
+Name: arr2
+Is passed by reference: yes
+Can be passed by value: yes
+
+Name: SORT_ASC_or_SORT_DESC
+Is passed by reference: yes
+Can be passed by value: yes
+
+Name: SORT_REGULAR_or_SORT_NUMERIC_or_SORT_STRING
+Is passed by reference: yes
+Can be passed by value: yes
+
+=> sort:
+
+Name: arg
+Is passed by reference: yes
+Can be passed by value: no
+
+Name: sort_flags
+Is passed by reference: no
+Can be passed by value: yes
+
+=> user function:
+
+Name: arg1
+Is passed by reference: yes
+Can be passed by value: no
+
+Name: arg2
+Is passed by reference: no
+Can be passed by value: yes
+
+Done.
diff --git a/ext/reflection/tests/bug40431.phpt b/ext/reflection/tests/bug40431.phpt
index 6e6e4c5eb1..863df7a78f 100644
--- a/ext/reflection/tests/bug40431.phpt
+++ b/ext/reflection/tests/bug40431.phpt
@@ -4,7 +4,7 @@ Bug #40431 (dynamic properties may cause crash in ReflectionProperty methods)
<?php
echo "=== 1st test ===\n";
-
+$Obj = new stdClass;
$Obj->value = 'value';
$RefObj = new ReflectionObject($Obj);
@@ -78,8 +78,6 @@ echo "Done\n";
?>
--EXPECTF--
=== 1st test ===
-
-Strict Standards: Creating default object from empty value in %s on line %d
array(1) {
[0]=>
&object(ReflectionProperty)#%d (2) {
diff --git a/ext/reflection/tests/bug47254.phpt b/ext/reflection/tests/bug47254.phpt
index 4bcce1bb72..83593a4ff2 100644
--- a/ext/reflection/tests/bug47254.phpt
+++ b/ext/reflection/tests/bug47254.phpt
@@ -23,7 +23,6 @@ $m = $R->getMethods();
print_r($m);
?>
---CLEAN--
--EXPECT--
Array
(
diff --git a/ext/reflection/tests/bug60357.phpt b/ext/reflection/tests/bug60357.phpt
new file mode 100644
index 0000000000..a5ddd4096c
--- /dev/null
+++ b/ext/reflection/tests/bug60357.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #60357 (__toString() method triggers E_NOTICE "Array to string conversion")
+--FILE--
+<?php
+function foo( array $x = array( 'a', 'b' ) ) {}
+$r = new ReflectionParameter( 'foo', 0 );
+echo $r->__toString();
+?>
+--EXPECTF--
+Parameter #0 [ <optional> array $x = Array ]
diff --git a/ext/reflection/tests/closures_003_v1.phpt b/ext/reflection/tests/closures_003_v1.phpt
new file mode 100644
index 0000000000..1b8e1c4d0a
--- /dev/null
+++ b/ext/reflection/tests/closures_003_v1.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Reflection on closures: Segfaults with getParameters() and getDeclaringFunction()
+--FILE--
+<?php
+
+$closure = function($a, $b = 0) { };
+
+$method = new ReflectionFunction ($closure);
+$params = $method->getParameters ();
+unset ($method);
+$method = $params[0]->getDeclaringFunction ();
+unset ($params);
+echo $method->getName ()."\n";
+
+$parameter = new ReflectionParameter ($closure, 'b');
+$method = $parameter->getDeclaringFunction ();
+unset ($parameter);
+echo $method->getName ()."\n";
+
+?>
+===DONE===
+--EXPECTF--
+{closure}
+{closure}
+===DONE===
diff --git a/ext/reflection/tests/closures_004.phpt b/ext/reflection/tests/closures_004.phpt
new file mode 100644
index 0000000000..807aea1f38
--- /dev/null
+++ b/ext/reflection/tests/closures_004.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Reflection on closures: Segfault with getClosure() on closure itself
+--FILE--
+<?php
+$closure = function() { echo "Invoked!\n"; };
+
+$method = new ReflectionFunction ($closure);
+
+$closure2 = $method->getClosure ();
+
+$closure2 ();
+$closure2->__invoke ();
+
+unset ($closure);
+
+$closure2 ();
+$closure2->__invoke ();
+
+$closure = function() { echo "Invoked!\n"; };
+
+$method = new ReflectionMethod ($closure, '__invoke');
+$closure2 = $method->getClosure ($closure);
+
+$closure2 ();
+$closure2->__invoke ();
+
+unset ($closure);
+
+$closure2 ();
+$closure2->__invoke ();
+
+?>
+===DONE===
+--EXPECTF--
+Invoked!
+Invoked!
+Invoked!
+Invoked!
+Invoked!
+Invoked!
+Invoked!
+Invoked!
+===DONE===
diff --git a/ext/reflection/tests/traits001.phpt b/ext/reflection/tests/traits001.phpt
new file mode 100644
index 0000000000..4e36ceeaf0
--- /dev/null
+++ b/ext/reflection/tests/traits001.phpt
@@ -0,0 +1,70 @@
+--TEST--
+ReflectionClass and Traits
+--FILE--
+<?php
+trait Foo {
+ public function someMethod() { }
+}
+
+class Bar {
+ use Foo;
+
+ public function someOtherMethod() { }
+}
+
+$rFoo = new ReflectionClass('Foo');
+$rBar = new ReflectionClass('Bar');
+
+var_dump($rFoo->isTrait());
+var_dump($rBar->isTrait());
+echo $rFoo;
+echo $rBar;
+--EXPECTF--
+bool(true)
+bool(false)
+Trait [ <user> trait Foo ] {
+ @@ %straits001.php 2-4
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [1] {
+ Method [ <user> public method someMethod ] {
+ @@ %straits001.php 3 - 3
+ }
+ }
+}
+Class [ <user> class Bar ] {
+ @@ %straits001.php 6-10
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [2] {
+ Method [ <user> public method someOtherMethod ] {
+ @@ %straits001.php 9 - 9
+ }
+
+ Method [ <user> public method someMethod ] {
+ @@ %straits001.php 3 - 3
+ }
+ }
+}
diff --git a/ext/reflection/tests/traits002.phpt b/ext/reflection/tests/traits002.phpt
new file mode 100644
index 0000000000..b55b288aa0
--- /dev/null
+++ b/ext/reflection/tests/traits002.phpt
@@ -0,0 +1,54 @@
+--TEST--
+ReflectionClass and Traits
+--FILE--
+<?php
+
+abstract class foo {
+}
+
+trait bar {
+
+}
+
+reflectionclass::export('foo');
+reflectionclass::export('bar');
+
+?>
+--EXPECTF--
+Class [ <user> abstract class foo ] {
+ @@ %s 3-4
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [0] {
+ }
+}
+
+Trait [ <user> trait bar ] {
+ @@ %s 6-8
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [0] {
+ }
+}
diff --git a/ext/reflection/tests/traits003.phpt b/ext/reflection/tests/traits003.phpt
new file mode 100644
index 0000000000..c569a8e723
--- /dev/null
+++ b/ext/reflection/tests/traits003.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Reflection and Traits
+--FILE--
+<?php
+
+abstract class foo {
+}
+
+trait bar {
+
+}
+
+final class baz {
+
+}
+
+$x = new ReflectionClass('foo');
+var_dump($x->isTrait());
+
+$x = new ReflectionClass('bar');
+var_dump($x->isTrait());
+
+$x = new ReflectionClass('baz');
+var_dump($x->isTrait());
+
+?>
+--EXPECT--
+bool(false)
+bool(true)
+bool(false)
diff --git a/ext/reflection/tests/traits004.phpt b/ext/reflection/tests/traits004.phpt
new file mode 100644
index 0000000000..c9367c1f48
--- /dev/null
+++ b/ext/reflection/tests/traits004.phpt
@@ -0,0 +1,58 @@
+--TEST--
+ReflectionClass::getTraits() and ReflectionClass::getTraitNames
+--FILE--
+<?php
+trait T1 { }
+trait T2 { }
+
+class C1 { }
+class C2 { use T1; }
+class C3 { use T1; use T2; }
+
+for ($c = "C1"; $c <= "C3"; $c++) {
+ echo "class $c:\n";
+ $r = new ReflectionClass($c);
+ var_dump($r->getTraitNames());
+ var_dump($r->getTraits());
+ echo "\n";
+}
+--EXPECT--
+class C1:
+array(0) {
+}
+array(0) {
+}
+
+class C2:
+array(1) {
+ [0]=>
+ string(2) "T1"
+}
+array(1) {
+ ["T1"]=>
+ &object(ReflectionClass)#1 (1) {
+ ["name"]=>
+ string(2) "T1"
+ }
+}
+
+class C3:
+array(2) {
+ [0]=>
+ string(2) "T1"
+ [1]=>
+ string(2) "T2"
+}
+array(2) {
+ ["T1"]=>
+ &object(ReflectionClass)#2 (1) {
+ ["name"]=>
+ string(2) "T1"
+ }
+ ["T2"]=>
+ &object(ReflectionClass)#3 (1) {
+ ["name"]=>
+ string(2) "T2"
+ }
+}
+
diff --git a/ext/reflection/tests/traits005.phpt b/ext/reflection/tests/traits005.phpt
new file mode 100644
index 0000000000..1496a35ec9
--- /dev/null
+++ b/ext/reflection/tests/traits005.phpt
@@ -0,0 +1,41 @@
+--TEST--
+ReflectionClass::getTraitAlias
+--FILE--
+<?php
+trait T1 { function m1() { } function m2() { } }
+
+class C1 { }
+class C2 { use T1; }
+class C3 { use T1 { m1 as a1; } }
+class C4 { use T1 { m1 as a1; m2 as a2; } }
+
+for ($c = "C1"; $c <= "C4"; $c++) {
+ echo "class $c:\n";
+ $r = new ReflectionClass($c);
+ var_dump($r->getTraitAliases());
+ echo "\n";
+}
+?>
+--EXPECT--
+class C1:
+array(0) {
+}
+
+class C2:
+array(0) {
+}
+
+class C3:
+array(1) {
+ ["a1"]=>
+ string(10) "(null)::m1"
+}
+
+class C4:
+array(2) {
+ ["a1"]=>
+ string(10) "(null)::m1"
+ ["a2"]=>
+ string(10) "(null)::m2"
+}
+
diff --git a/ext/session/config.m4 b/ext/session/config.m4
index d65e872a3a..1c3ba78368 100644
--- a/ext/session/config.m4
+++ b/ext/session/config.m4
@@ -11,7 +11,7 @@ PHP_ARG_WITH(mm,for mm support,
if test "$PHP_SESSION" != "no"; then
PHP_PWRITE_TEST
PHP_PREAD_TEST
- PHP_NEW_EXTENSION(session, session.c mod_files.c mod_mm.c mod_user.c, $ext_shared)
+ PHP_NEW_EXTENSION(session, mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c, $ext_shared)
PHP_ADD_EXTENSION_DEP(session, hash, true)
PHP_ADD_EXTENSION_DEP(session, spl)
PHP_SUBST(SESSION_SHARED_LIBADD)
diff --git a/ext/session/config.w32 b/ext/session/config.w32
index 531fed1fb6..c8b217aad9 100644
--- a/ext/session/config.w32
+++ b/ext/session/config.w32
@@ -4,7 +4,7 @@
ARG_ENABLE("session", "session support", "yes");
if (PHP_SESSION == "yes") {
- EXTENSION("session", "session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */);
+ EXTENSION("session", "mod_user_class.c session.c mod_files.c mod_mm.c mod_user.c", false /* never shared */);
AC_DEFINE("HAVE_PHP_SESSION", 1, "Session support");
PHP_INSTALL_HEADERS("ext/session/", "mod_mm.h php_session.h mod_files.h mod_user.h");
}
diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c
index ec25bead10..621c4e1db7 100644
--- a/ext/session/mod_files.c
+++ b/ext/session/mod_files.c
@@ -171,20 +171,14 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC)
if (data->fd != -1) {
#ifndef PHP_WIN32
/* check to make sure that the opened file is not a symlink, linking to data outside of allowable dirs */
- if (PG(safe_mode) || PG(open_basedir)) {
+ if (PG(open_basedir)) {
struct stat sbuf;
if (fstat(data->fd, &sbuf)) {
close(data->fd);
return;
}
- if (
- S_ISLNK(sbuf.st_mode) &&
- (
- php_check_open_basedir(buf TSRMLS_CC) ||
- (PG(safe_mode) && !php_checkuid(buf, NULL, CHECKUID_CHECK_FILE_AND_DIR))
- )
- ) {
+ if (S_ISLNK(sbuf.st_mode) && php_check_open_basedir(buf TSRMLS_CC)) {
close(data->fd);
return;
}
@@ -274,9 +268,6 @@ PS_OPEN_FUNC(files)
/* if save path is an empty string, determine the temporary dir */
save_path = php_get_temporary_directory();
- if (PG(safe_mode) && (!php_checkuid(save_path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return FAILURE;
- }
if (php_check_open_basedir(save_path TSRMLS_CC)) {
return FAILURE;
}
@@ -320,6 +311,9 @@ PS_OPEN_FUNC(files)
data->basedir_len = strlen(save_path);
data->basedir = estrndup(save_path, data->basedir_len);
+ if (PS_GET_MOD_DATA()) {
+ ps_close_files(mod_data TSRMLS_CC);
+ }
PS_SET_MOD_DATA(data);
return SUCCESS;
@@ -399,7 +393,7 @@ PS_WRITE_FUNC(files)
/* Truncate file if the amount of new data is smaller than the existing data set. */
if (vallen < (int)data->st_size) {
- ftruncate(data->fd, 0);
+ php_ignore_value(ftruncate(data->fd, 0));
}
#if defined(HAVE_PWRITE)
diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c
index c187e26818..84a28d3427 100644
--- a/ext/session/mod_user.c
+++ b/ext/session/mod_user.c
@@ -62,15 +62,10 @@ static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC)
return retval;
}
-#define STDVARS1 \
+#define STDVARS \
zval *retval = NULL; \
int ret = FAILURE
-#define STDVARS \
- STDVARS1; \
- char *mdata = PS_GET_MOD_DATA(); \
- if (!mdata) { return FAILURE; }
-
#define PSF(a) PS(mod_user_names).name.ps_##a
#define FINISH \
@@ -84,8 +79,7 @@ static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC)
PS_OPEN_FUNC(user)
{
zval *args[2];
- static char dummy = 0;
- STDVARS1;
+ STDVARS;
if (PSF(open) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
@@ -98,25 +92,35 @@ PS_OPEN_FUNC(user)
SESS_ZVAL_STRING((char*)session_name, args[1]);
retval = ps_call_handler(PSF(open), 2, args TSRMLS_CC);
- if (retval) {
- /* This is necessary to fool the session module. Yes, it's safe to
- * use a static. Neither mod_user nor the session module itself will
- * ever touch this pointer. It could be set to 0xDEADBEEF for all the
- * difference it makes, but for the sake of paranoia it's set to some
- * valid value. */
- PS_SET_MOD_DATA(&dummy);
- }
+ PS(mod_user_implemented) = 1;
FINISH;
}
PS_CLOSE_FUNC(user)
{
- STDVARS1;
+ zend_bool bailout = 0;
+ STDVARS;
+
+ if (!PS(mod_user_implemented)) {
+ /* already closed */
+ return SUCCESS;
+ }
- retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC);
+ zend_try {
+ retval = ps_call_handler(PSF(close), 0, NULL TSRMLS_CC);
+ } zend_catch {
+ bailout = 1;
+ } zend_end_try();
- PS_SET_MOD_DATA(NULL);
+ PS(mod_user_implemented) = 0;
+
+ if (bailout) {
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+ zend_bailout();
+ }
FINISH;
}
diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c
new file mode 100644
index 0000000000..70d2f40df1
--- /dev/null
+++ b/ext/session/mod_user_class.c
@@ -0,0 +1,144 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Arpad Ray <arpad@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "php.h"
+#include "php_session.h"
+
+#define PS_SANITY_CHECK \
+ if (PS(default_mod) == NULL) { \
+ php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "Cannot call default session handler"); \
+ RETURN_FALSE; \
+ }
+
+#define PS_SANITY_CHECK_IS_OPEN \
+ PS_SANITY_CHECK; \
+ if (!PS(mod_user_is_open)) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parent session handler is not open"); \
+ RETURN_FALSE; \
+ }
+
+/* {{{ proto bool SessionHandler::open(string save_path, string session_name)
+ Wraps the old open handler */
+PHP_METHOD(SessionHandler, open)
+{
+ char *save_path = NULL, *session_name = NULL;
+ int save_path_len, session_name_len;
+
+ PS_SANITY_CHECK;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &save_path, &save_path_len, &session_name, &session_name_len) == FAILURE) {
+ return;
+ }
+
+ PS(mod_user_is_open) = 1;
+ RETVAL_BOOL(SUCCESS == PS(default_mod)->s_open(&PS(mod_data), save_path, session_name TSRMLS_CC));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::close()
+ Wraps the old close handler */
+PHP_METHOD(SessionHandler, close)
+{
+ PS_SANITY_CHECK_IS_OPEN;
+
+ // don't return on failure, since not closing the default handler
+ // could result in memory leaks or other nasties
+ zend_parse_parameters_none();
+
+ PS(mod_user_is_open) = 0;
+ RETVAL_BOOL(SUCCESS == PS(default_mod)->s_close(&PS(mod_data) TSRMLS_CC));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::read(string id)
+ Wraps the old read handler */
+PHP_METHOD(SessionHandler, read)
+{
+ char *key, *val;
+ int key_len, val_len;
+
+ PS_SANITY_CHECK_IS_OPEN;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
+ return;
+ }
+
+ if (PS(default_mod)->s_read(&PS(mod_data), key, &val, &val_len TSRMLS_CC) == FAILURE) {
+ RETVAL_FALSE;
+ return;
+ }
+
+ RETVAL_STRINGL(val, val_len, 1);
+ efree(val);
+ return;
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::write(string id, string data)
+ Wraps the old write handler */
+PHP_METHOD(SessionHandler, write)
+{
+ char *key, *val;
+ int key_len, val_len;
+
+ PS_SANITY_CHECK_IS_OPEN;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key, &key_len, &val, &val_len) == FAILURE) {
+ return;
+ }
+
+ RETVAL_BOOL(SUCCESS == PS(default_mod)->s_write(&PS(mod_data), key, val, val_len TSRMLS_CC));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::destroy(string id)
+ Wraps the old destroy handler */
+PHP_METHOD(SessionHandler, destroy)
+{
+ char *key;
+ int key_len;
+
+ PS_SANITY_CHECK_IS_OPEN;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
+ return;
+ }
+
+ PS(mod_user_is_open) = 0;
+ RETVAL_BOOL(SUCCESS == PS(default_mod)->s_destroy(&PS(mod_data), key TSRMLS_CC));
+}
+/* }}} */
+
+/* {{{ proto bool SessionHandler::gc(int maxlifetime)
+ Wraps the old gc handler */
+PHP_METHOD(SessionHandler, gc)
+{
+ long maxlifetime;
+ int nrdels;
+
+ PS_SANITY_CHECK_IS_OPEN;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxlifetime) == FAILURE) {
+ return;
+ }
+
+ RETVAL_BOOL(SUCCESS == PS(default_mod)->s_gc(&PS(mod_data), maxlifetime, &nrdels TSRMLS_CC));
+}
+/* }}} */
diff --git a/ext/session/package.xml b/ext/session/package.xml
index fdf85fc447..03fcbf66da 100644
--- a/ext/session/package.xml
+++ b/ext/session/package.xml
@@ -40,6 +40,7 @@ package.xml added to support installation using pear installer
<file role="src" name="mod_mm.c"/>
<file role="src" name="mod_mm.h"/>
<file role="src" name="mod_user.c"/>
+ <file role="src" name="mod_user_class.c"/>
<file role="src" name="mod_user.h"/>
<file role="src" name="php_session.h"/>
<file role="src" name="session.c"/>
diff --git a/ext/session/php_session.h b/ext/session/php_session.h
index 29b50b2255..ba0195bec4 100644
--- a/ext/session/php_session.h
+++ b/ext/session/php_session.h
@@ -95,6 +95,26 @@ typedef enum {
php_session_active
} php_session_status;
+typedef struct _php_session_rfc1867_progress {
+
+ size_t sname_len;
+ zval sid;
+ smart_str key;
+
+ long update_step;
+ long next_update;
+ double next_update_time;
+ zend_bool cancel_upload;
+ zend_bool apply_trans_sid;
+ size_t content_length;
+
+ zval *data; /* the array exported to session data */
+ zval *post_bytes_processed; /* data["bytes_processed"] */
+ zval *files; /* data["files"] array */
+ zval *current_file; /* array of currently uploading file */
+ zval *current_file_bytes_processed;
+} php_session_rfc1867_progress;
+
typedef struct _php_ps_globals {
char *save_path;
char *session_name;
@@ -109,6 +129,7 @@ typedef struct _php_ps_globals {
zend_bool cookie_secure;
zend_bool cookie_httponly;
ps_module *mod;
+ ps_module *default_mod;
void *mod_data;
php_session_status session_status;
long gc_probability;
@@ -127,8 +148,8 @@ typedef struct _php_ps_globals {
zval *ps_gc;
} name;
} mod_user_names;
- zend_bool bug_compat; /* Whether to behave like PHP 4.2 and earlier */
- zend_bool bug_compat_warn; /* Whether to warn about it */
+ int mod_user_implemented;
+ int mod_user_is_open;
const struct ps_serializer_struct *serializer;
zval *http_session_vars;
zend_bool auto_start;
@@ -145,6 +166,14 @@ typedef struct _php_ps_globals {
int send_cookie;
int define_sid;
zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
+
+ php_session_rfc1867_progress *rfc1867_progress;
+ zend_bool rfc1867_enabled; /* session.upload_progress.enabled */
+ zend_bool rfc1867_cleanup; /* session.upload_progress.cleanup */
+ smart_str rfc1867_prefix; /* session.upload_progress.prefix */
+ smart_str rfc1867_name; /* session.upload_progress.name */
+ long rfc1867_freq; /* session.upload_progress.freq */
+ double rfc1867_min_freq; /* session.upload_progress.min_freq */
} php_ps_globals;
typedef php_ps_globals zend_ps_globals;
@@ -242,4 +271,17 @@ PHPAPI ZEND_EXTERN_MODULE_GLOBALS(ps)
void php_session_auto_start(void *data);
void php_session_shutdown(void *data);
+#define PS_CLASS_NAME "SessionHandler"
+extern zend_class_entry *php_session_class_entry;
+
+#define PS_IFACE_NAME "SessionHandlerInterface"
+extern zend_class_entry *php_session_iface_entry;
+
+extern PHP_METHOD(SessionHandler, open);
+extern PHP_METHOD(SessionHandler, close);
+extern PHP_METHOD(SessionHandler, read);
+extern PHP_METHOD(SessionHandler, write);
+extern PHP_METHOD(SessionHandler, destroy);
+extern PHP_METHOD(SessionHandler, gc);
+
#endif
diff --git a/ext/session/session.c b/ext/session/session.c
index 47c1e35e49..0c08d49681 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -29,7 +29,7 @@
# include "win32/winutil.h"
# include "win32/time.h"
#else
-#include <sys/time.h>
+# include <sys/time.h>
#endif
#include <sys/stat.h>
@@ -37,6 +37,8 @@
#include "php_ini.h"
#include "SAPI.h"
+#include "rfc1867.h"
+#include "php_variables.h"
#include "php_session.h"
#include "ext/standard/md5.h"
#include "ext/standard/sha1.h"
@@ -48,6 +50,7 @@
#include "ext/standard/info.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/url.h"
+#include "ext/standard/basic_functions.h"
#include "mod_files.h"
#include "mod_user.h"
@@ -58,6 +61,15 @@
PHPAPI ZEND_DECLARE_MODULE_GLOBALS(ps)
+static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra TSRMLS_DC);
+static int (*php_session_rfc1867_orig_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC);
+
+/* SessionHandler class */
+zend_class_entry *php_session_class_entry;
+
+/* SessionHandlerInterface */
+zend_class_entry *php_session_iface_entry;
+
/* ***********
* Helpers *
*********** */
@@ -77,6 +89,7 @@ static inline void php_rinit_session_globals(TSRMLS_D) /* {{{ */
PS(id) = NULL;
PS(session_status) = php_session_none;
PS(mod_data) = NULL;
+ PS(mod_user_is_open) = 0;
/* Do NOT init PS(mod_user_names) here! */
PS(http_session_vars) = NULL;
}
@@ -90,7 +103,7 @@ static inline void php_rshutdown_session_globals(TSRMLS_D) /* {{{ */
PS(http_session_vars) = NULL;
}
/* Do NOT destroy PS(mod_user_names) here! */
- if (PS(mod_data)) {
+ if (PS(mod_data) || PS(mod_user_implemented)) {
zend_try {
PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
} zend_end_try();
@@ -132,76 +145,18 @@ PHPAPI void php_add_session_var(char *name, size_t namelen TSRMLS_DC) /* {{{ */
return;
}
- /* Set up a proper reference between $_SESSION["x"] and $x. */
-
- if (PG(register_globals)) {
- zval **sym_global = NULL;
-
- if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void *) &sym_global) == SUCCESS) {
- if ((Z_TYPE_PP(sym_global) == IS_ARRAY && Z_ARRVAL_PP(sym_global) == &EG(symbol_table)) || *sym_global == PS(http_session_vars)) {
- return;
- }
- }
+ if (sym_track == NULL) {
+ zval *empty_var;
- if (sym_global == NULL && sym_track == NULL) {
- zval *empty_var;
-
- ALLOC_INIT_ZVAL(empty_var); /* this sets refcount to 1 */
- Z_SET_REFCOUNT_P(empty_var, 0); /* our module does not maintain a ref */
- /* The next call will increase refcount by NR_OF_SYM_TABLES==2 */
- zend_set_hash_symbol(empty_var, name, namelen, 1, 2, Z_ARRVAL_P(PS(http_session_vars)), &EG(symbol_table));
- } else if (sym_global == NULL) {
- SEPARATE_ZVAL_IF_NOT_REF(sym_track);
- zend_set_hash_symbol(*sym_track, name, namelen, 1, 1, &EG(symbol_table));
- } else if (sym_track == NULL) {
- SEPARATE_ZVAL_IF_NOT_REF(sym_global);
- zend_set_hash_symbol(*sym_global, name, namelen, 1, 1, Z_ARRVAL_P(PS(http_session_vars)));
- }
- } else {
- if (sym_track == NULL) {
- zval *empty_var;
-
- ALLOC_INIT_ZVAL(empty_var);
- ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, empty_var, 1, 0);
- }
+ ALLOC_INIT_ZVAL(empty_var);
+ ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), name, namelen+1, empty_var, 1, 0);
}
}
/* }}} */
PHPAPI void php_set_session_var(char *name, size_t namelen, zval *state_val, php_unserialize_data_t *var_hash TSRMLS_DC) /* {{{ */
{
- if (PG(register_globals)) {
- zval **old_symbol;
- if (zend_hash_find(&EG(symbol_table),name,namelen+1,(void *)&old_symbol) == SUCCESS) {
- if ((Z_TYPE_PP(old_symbol) == IS_ARRAY && Z_ARRVAL_PP(old_symbol) == &EG(symbol_table)) || *old_symbol == PS(http_session_vars)) {
- return;
- }
-
- /* A global symbol with the same name exists already. That
- * symbol might have been created by other means (e.g. $_GET).
- *
- * hash_update in zend_set_hash_symbol is not good, because
- * it will leave referenced variables (such as local instances
- * of a global variable) dangling.
- *
- * BTW: if you use register_globals references between
- * session-vars won't work because of this very reason! */
-
- REPLACE_ZVAL_VALUE(old_symbol,state_val,1);
-
- /* The following line will update the reference table used for
- * unserialization. It is optional, because some storage
- * formats may not be able to represent references. */
-
- if (var_hash) {
- PHP_VAR_UNSERIALIZE_ZVAL_CHANGED(var_hash,state_val,*old_symbol);
- }
-
- zend_set_hash_symbol(*old_symbol, name, namelen, 1, 1, Z_ARRVAL_P(PS(http_session_vars)));
- } else {
- zend_set_hash_symbol(state_val, name, namelen, 1, 2, Z_ARRVAL_P(PS(http_session_vars)), &EG(symbol_table));
- }
- } else IF_SESSION_VARS() {
+ IF_SESSION_VARS() {
zend_set_hash_symbol(state_val, name, namelen, PZVAL_IS_REF(state_val), 1, Z_ARRVAL_P(PS(http_session_vars)));
}
}
@@ -213,20 +168,6 @@ PHPAPI int php_get_session_var(char *name, size_t namelen, zval ***state_var TSR
IF_SESSION_VARS() {
ret = zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, (void **) state_var);
-
- /* If register_globals is enabled, and
- * if there is an entry for the slot in $_SESSION, and
- * if that entry is still set to NULL, and
- * if the global var exists, then
- * we prefer the same key in the global sym table. */
-
- if (PG(register_globals) && ret == SUCCESS && Z_TYPE_PP(*state_var) == IS_NULL) {
- zval **tmp;
-
- if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) {
- *state_var = tmp;
- }
- }
}
return ret;
}
@@ -236,8 +177,7 @@ static void php_session_track_init(TSRMLS_D) /* {{{ */
{
zval *session_vars = NULL;
- /* Unconditionally destroy existing arrays -- possible dirty data */
- zend_delete_global_variable("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS")-1 TSRMLS_CC);
+ /* Unconditionally destroy existing array -- possible dirty data */
zend_delete_global_variable("_SESSION", sizeof("_SESSION")-1 TSRMLS_CC);
if (PS(http_session_vars)) {
@@ -248,13 +188,7 @@ static void php_session_track_init(TSRMLS_D) /* {{{ */
array_init(session_vars);
PS(http_session_vars) = session_vars;
- if (PG(register_long_arrays)) {
- ZEND_SET_GLOBAL_VAR_WITH_LENGTH("HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), PS(http_session_vars), 3, 1);
- ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 3, 1);
- }
- else {
- ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1);
- }
+ ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1);
}
/* }}} */
@@ -541,64 +475,12 @@ new_session:
}
/* }}} */
-static int migrate_global(HashTable *ht, HashPosition *pos TSRMLS_DC) /* {{{ */
-{
- char *str;
- uint str_len;
- ulong num_key;
- int n;
- zval **val;
- int ret = 0;
-
- n = zend_hash_get_current_key_ex(ht, &str, &str_len, &num_key, 0, pos);
-
- switch (n) {
- case HASH_KEY_IS_STRING:
- if (zend_hash_find(&EG(symbol_table), str, str_len, (void **) &val) == SUCCESS &&
- val && Z_TYPE_PP(val) != IS_NULL
- ) {
- ZEND_SET_SYMBOL_WITH_LENGTH(ht, str, str_len, *val, Z_REFCOUNT_PP(val) + 1, 1);
- ret = 1;
- }
- break;
- case HASH_KEY_IS_LONG:
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The session bug compatibility code will not "
- "try to locate the global variable $%lu due to its "
- "numeric nature", num_key);
- break;
- }
- return ret;
-}
-/* }}} */
-
static void php_session_save_current_state(TSRMLS_D) /* {{{ */
{
int ret = FAILURE;
IF_SESSION_VARS() {
- if (PS(bug_compat) && !PG(register_globals)) {
- HashTable *ht = Z_ARRVAL_P(PS(http_session_vars));
- HashPosition pos;
- zval **val;
- int do_warn = 0;
-
- zend_hash_internal_pointer_reset_ex(ht, &pos);
-
- while (zend_hash_get_current_data_ex(ht, (void **) &val, &pos) != FAILURE) {
- if (Z_TYPE_PP(val) == IS_NULL) {
- if (migrate_global(ht, &pos TSRMLS_CC)) {
- do_warn = 1;
- }
- }
- zend_hash_move_forward_ex(ht, &pos);
- }
-
- if (do_warn && PS(bug_compat_warn)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively");
- }
- }
-
- if (PS(mod_data)) {
+ if (PS(mod_data) || PS(mod_user_implemented)) {
char *val;
int vallen;
@@ -620,7 +502,7 @@ static void php_session_save_current_state(TSRMLS_D) /* {{{ */
}
}
- if (PS(mod_data)) {
+ if (PS(mod_data) || PS(mod_user_implemented)) {
PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
}
}
@@ -652,6 +534,8 @@ static PHP_INI_MH(OnUpdateSaveHandler) /* {{{ */
}
return FAILURE;
}
+
+ PS(default_mod) = PS(mod);
PS(mod) = tmp;
return SUCCESS;
@@ -721,10 +605,6 @@ static PHP_INI_MH(OnUpdateSaveDir) /* {{{ */
p = new_value;
}
- if (PG(safe_mode) && *p && (!php_checkuid(p, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return FAILURE;
- }
-
if (PG(open_basedir) && *p && php_check_open_basedir(p TSRMLS_CC)) {
return FAILURE;
}
@@ -783,11 +663,48 @@ static PHP_INI_MH(OnUpdateHashFunc) /* {{{ */
}
/* }}} */
+static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
+{
+ int tmp;
+ tmp = zend_atoi(new_value, new_value_length);
+ if(tmp < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.upload_progress.freq must be greater than or equal to zero");
+ return FAILURE;
+ }
+ if(new_value_length > 0 && new_value[new_value_length-1] == '%') {
+ if(tmp > 100) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.upload_progress.freq cannot be over 100%%");
+ return FAILURE;
+ }
+ PS(rfc1867_freq) = -tmp;
+ } else {
+ PS(rfc1867_freq) = tmp;
+ }
+ return SUCCESS;
+} /* }}} */
+
+static ZEND_INI_MH(OnUpdateSmartStr) /* {{{ */
+{
+ smart_str *p;
+#ifndef ZTS
+ char *base = (char *) mh_arg2;
+#else
+ char *base;
+
+ base = (char *) ts_resource(*((int *) mh_arg2));
+#endif
+
+ p = (smart_str *) (base+(size_t) mh_arg1);
+
+ smart_str_sets(p, new_value);
+
+ return SUCCESS;
+}
+/* }}} */
+
/* {{{ PHP_INI
*/
PHP_INI_BEGIN()
- STD_PHP_INI_BOOLEAN("session.bug_compat_42", "1", PHP_INI_ALL, OnUpdateBool, bug_compat, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.bug_compat_warn", "1", PHP_INI_ALL, OnUpdateBool, bug_compat_warn, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateString, session_name, php_ps_globals, ps_globals)
PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler)
@@ -804,14 +721,35 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_cookies, php_ps_globals, ps_globals)
STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_only_cookies, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateString, extern_referer_chk, php_ps_globals, ps_globals)
+#if HAVE_DEV_URANDOM
+ STD_PHP_INI_ENTRY("session.entropy_file", "/dev/urandom", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.entropy_length", "32", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
+#elif HAVE_DEV_ARANDOM
+ STD_PHP_INI_ENTRY("session.entropy_file", "/dev/arandom", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.entropy_length", "32", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
+#else
STD_PHP_INI_ENTRY("session.entropy_file", "", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.entropy_length", "0", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
+#endif
STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateString, cache_limiter, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateLong, cache_expire, php_ps_globals, ps_globals)
PHP_INI_ENTRY("session.use_trans_sid", "0", PHP_INI_ALL, OnUpdateTransSid)
PHP_INI_ENTRY("session.hash_function", "0", PHP_INI_ALL, OnUpdateHashFunc)
STD_PHP_INI_ENTRY("session.hash_bits_per_character", "4", PHP_INI_ALL, OnUpdateLong, hash_bits_per_character, php_ps_globals, ps_globals)
+ /* Upload progress */
+ STD_PHP_INI_BOOLEAN("session.upload_progress.enabled",
+ "1", ZEND_INI_PERDIR, OnUpdateBool, rfc1867_enabled, php_ps_globals, ps_globals)
+ STD_PHP_INI_BOOLEAN("session.upload_progress.cleanup",
+ "1", ZEND_INI_PERDIR, OnUpdateBool, rfc1867_cleanup, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.upload_progress.prefix",
+ "upload_progress_", ZEND_INI_PERDIR, OnUpdateSmartStr, rfc1867_prefix, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.upload_progress.name",
+ "PHP_SESSION_UPLOAD_PROGRESS", ZEND_INI_PERDIR, OnUpdateSmartStr, rfc1867_name, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.upload_progress.freq", "1%", ZEND_INI_PERDIR, OnUpdateRfc1867Freq, rfc1867_freq, php_ps_globals, ps_globals)
+ STD_PHP_INI_ENTRY("session.upload_progress.min_freq",
+ "1", ZEND_INI_PERDIR, OnUpdateReal, rfc1867_min_freq,php_ps_globals, ps_globals)
+
/* Commented out until future discussion */
/* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */
PHP_INI_END()
@@ -1188,8 +1126,8 @@ static int php_session_cache_limiter(TSRMLS_D) /* {{{ */
if (PS(cache_limiter)[0] == '\0') return 0;
if (SG(headers_sent)) {
- char *output_start_filename = php_get_output_start_filename(TSRMLS_C);
- int output_start_lineno = php_get_output_start_lineno(TSRMLS_C);
+ const char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
+ int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
if (output_start_filename) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", output_start_filename, output_start_lineno);
@@ -1228,8 +1166,8 @@ static void php_session_send_cookie(TSRMLS_D) /* {{{ */
char *e_session_name, *e_id;
if (SG(headers_sent)) {
- char *output_start_filename = php_get_output_start_filename(TSRMLS_C);
- int output_start_lineno = php_get_output_start_lineno(TSRMLS_C);
+ const char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
+ int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
if (output_start_filename) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cookie - headers already sent by (output started at %s:%d)", output_start_filename, output_start_lineno);
@@ -1492,7 +1430,7 @@ PHPAPI void php_session_start(TSRMLS_D) /* {{{ */
php_session_cache_limiter(TSRMLS_C);
- if (PS(mod_data) && PS(gc_probability) > 0) {
+ if ((PS(mod_data) || PS(mod_user_implemented)) && PS(gc_probability) > 0) {
int nrdels = -1;
nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C));
@@ -1625,7 +1563,7 @@ static PHP_FUNCTION(session_module_name)
zval_dtor(return_value);
RETURN_FALSE;
}
- if (PS(mod_data)) {
+ if (PS(mod_data) || PS(mod_user_implemented)) {
PS(mod)->s_close(&PS(mod_data) TSRMLS_CC);
}
PS(mod_data) = NULL;
@@ -1647,14 +1585,85 @@ static PHP_FUNCTION(session_set_save_handler)
RETURN_FALSE;
}
- if (argc != 6) {
+ if (argc != 1 && argc != 2 && argc != 6) {
WRONG_PARAM_COUNT;
}
+ if (argc <= 2) {
+ zval *obj = NULL, *callback = NULL;
+ zend_uint func_name_len;
+ char *func_name;
+ HashPosition pos;
+ zend_function *default_mptr, *current_mptr;
+ ulong func_index;
+ php_shutdown_function_entry shutdown_function_entry;
+ zend_bool register_shutdown = 1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &obj, php_session_iface_entry, &register_shutdown) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ /* Find implemented methods */
+ zend_hash_internal_pointer_reset_ex(&php_session_class_entry->function_table, &pos);
+ i = 0;
+ while (zend_hash_get_current_data_ex(&php_session_class_entry->function_table, (void **) &default_mptr, &pos) == SUCCESS) {
+ zend_hash_get_current_key_ex(&php_session_class_entry->function_table, &func_name, &func_name_len, &func_index, 0, &pos);
+
+ if (zend_hash_find(&Z_OBJCE_P(obj)->function_table, func_name, func_name_len, (void **)&current_mptr) == SUCCESS) {
+ if (PS(mod_user_names).names[i] != NULL) {
+ zval_ptr_dtor(&PS(mod_user_names).names[i]);
+ }
+
+ MAKE_STD_ZVAL(callback);
+ array_init_size(callback, 2);
+ Z_ADDREF_P(obj);
+ add_next_index_zval(callback, obj);
+ add_next_index_stringl(callback, func_name, func_name_len - 1, 1);
+ PS(mod_user_names).names[i] = callback;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Session handler's function table is corrupt");
+ RETURN_FALSE;
+ }
+
+ zend_hash_move_forward_ex(&php_session_class_entry->function_table, &pos);
+ ++i;
+ }
+
+ if (register_shutdown) {
+ /* create shutdown function */
+ shutdown_function_entry.arg_count = 1;
+ shutdown_function_entry.arguments = (zval **) safe_emalloc(sizeof(zval *), 1, 0);
+
+ MAKE_STD_ZVAL(callback);
+ ZVAL_STRING(callback, "session_register_shutdown", 1);
+ shutdown_function_entry.arguments[0] = callback;
+
+ /* add shutdown function, removing the old one if it exists */
+ if (!register_user_shutdown_function("session_shutdown", sizeof("session_shutdown"), &shutdown_function_entry TSRMLS_CC)) {
+ zval_ptr_dtor(&callback);
+ efree(shutdown_function_entry.arguments);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to register session shutdown function");
+ RETURN_FALSE;
+ }
+ } else {
+ /* remove shutdown function */
+ remove_user_shutdown_function("session_shutdown", sizeof("session_shutdown") TSRMLS_CC);
+ }
+
+ if (PS(mod) && PS(session_status) == php_session_none && PS(mod) != &ps_mod_user) {
+ zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ }
+
+ RETURN_TRUE;
+ }
+
if (zend_parse_parameters(argc TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
return;
}
+ /* remove shutdown function */
+ remove_user_shutdown_function("session_shutdown", sizeof("session_shutdown") TSRMLS_CC);
+
for (i = 0; i < 6; i++) {
if (!zend_is_callable(*args[i], 0, &name TSRMLS_CC)) {
efree(args);
@@ -1664,8 +1673,10 @@ static PHP_FUNCTION(session_set_save_handler)
}
efree(name);
}
-
- zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+
+ if (PS(mod) && PS(mod) != &ps_mod_user) {
+ zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
+ }
for (i = 0; i < 6; i++) {
if (PS(mod_user_names).names[i] != NULL) {
@@ -1805,37 +1816,6 @@ static PHP_FUNCTION(session_cache_expire)
}
/* }}} */
-/* {{{ static void php_register_var(zval** entry TSRMLS_DC) */
-static void php_register_var(zval** entry TSRMLS_DC)
-{
- zval **value;
-
- if (Z_TYPE_PP(entry) == IS_ARRAY) {
- if (Z_ARRVAL_PP(entry)->nApplyCount > 1) {
- return;
- }
-
- zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry));
- Z_ARRVAL_PP(entry)->nApplyCount++;
-
- while (zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void**)&value) == SUCCESS) {
- php_register_var(value TSRMLS_CC);
- zend_hash_move_forward(Z_ARRVAL_PP(entry));
- }
-
- Z_ARRVAL_PP(entry)->nApplyCount--;
- } else {
- convert_to_string_ex(entry);
-
- if ((strcmp(Z_STRVAL_PP(entry), "HTTP_SESSION_VARS") != 0) &&
- (strcmp(Z_STRVAL_PP(entry), "_SESSION") != 0)
- ) {
- PS_ADD_VARL(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry));
- }
- }
-}
-/* }}} */
-
/* {{{ proto string session_encode(void)
Serializes the current setup and returns the serialized representation */
static PHP_FUNCTION(session_encode)
@@ -1917,20 +1897,6 @@ static PHP_FUNCTION(session_unset)
SEPARATE_ZVAL_IF_NOT_REF(&PS(http_session_vars));
ht_sess_var = Z_ARRVAL_P(PS(http_session_vars));
- if (PG(register_globals)) {
- uint str_len;
- char *str;
- ulong num_key;
- HashPosition pos;
-
- zend_hash_internal_pointer_reset_ex(ht_sess_var, &pos);
-
- while (zend_hash_get_current_key_ex(ht_sess_var, &str, &str_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING) {
- zend_delete_global_variable(str, str_len - 1 TSRMLS_CC);
- zend_hash_move_forward_ex(ht_sess_var, &pos);
- }
- }
-
/* Clean $_SESSION. */
zend_hash_clean(ht_sess_var);
}
@@ -1945,85 +1911,52 @@ static PHP_FUNCTION(session_write_close)
}
/* }}} */
-/* {{{ proto bool session_register(mixed var_names [, mixed ...])
- Adds varname(s) to the list of variables which are freezed at the session end */
-static PHP_FUNCTION(session_register)
+/* {{{ proto int session_status(void)
+ Returns the current session status */
+static PHP_FUNCTION(session_status)
{
- zval ***args = NULL;
- int num_args, i;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
+ if (zend_parse_parameters_none() == FAILURE) {
return;
}
- if (PS(session_status) == php_session_none || PS(session_status) == php_session_disabled) {
- php_session_start(TSRMLS_C);
- }
-
- if (PS(session_status) == php_session_disabled) {
- if (args) {
- efree(args);
- }
- RETURN_FALSE;
- }
-
- for (i = 0; i < num_args; i++) {
- if (Z_TYPE_PP(args[i]) == IS_ARRAY) {
- SEPARATE_ZVAL(args[i]);
- }
- php_register_var(args[i] TSRMLS_CC);
- }
-
- if (args) {
- efree(args);
- }
-
- RETURN_TRUE;
+ RETURN_LONG(PS(session_status));
}
/* }}} */
-/* {{{ proto bool session_unregister(string varname)
- Removes varname from the list of variables which are freezed at the session end */
-static PHP_FUNCTION(session_unregister)
+/* {{{ proto void session_register_shutdown(void)
+ Registers session_write_close() as a shutdown function */
+static PHP_FUNCTION(session_register_shutdown)
{
- char *p_name;
- int p_name_len;
+ php_shutdown_function_entry shutdown_function_entry;
+ zval *callback;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &p_name, &p_name_len) == FAILURE) {
- return;
- }
+ /* This function is registered itself as a shutdown function by
+ * session_set_save_handler($obj). The reason we now register another
+ * shutdown function is in case the user registered their own shutdown
+ * function after calling session_set_save_handler(), which expects
+ * the session still to be available.
+ */
- IF_SESSION_VARS() {
- SEPARATE_ZVAL_IF_NOT_REF(&PS(http_session_vars));
- PS_DEL_VARL(p_name, p_name_len);
- }
+ shutdown_function_entry.arg_count = 1;
+ shutdown_function_entry.arguments = (zval **) safe_emalloc(sizeof(zval *), 1, 0);
- RETURN_TRUE;
-}
-/* }}} */
+ MAKE_STD_ZVAL(callback);
+ ZVAL_STRING(callback, "session_write_close", 1);
+ shutdown_function_entry.arguments[0] = callback;
-/* {{{ proto bool session_is_registered(string varname)
- Checks if a variable is registered in session */
-static PHP_FUNCTION(session_is_registered)
-{
- zval *p_var;
- char *p_name;
- int p_name_len;
+ if (!append_user_shutdown_function(shutdown_function_entry TSRMLS_CC)) {
+ zval_ptr_dtor(&callback);
+ efree(shutdown_function_entry.arguments);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &p_name, &p_name_len) == FAILURE) {
- return;
- }
-
- if (PS(session_status) == php_session_none) {
- RETURN_FALSE;
- }
-
- IF_SESSION_VARS() {
- if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), p_name, p_name_len+1, (void **)&p_var) == SUCCESS) {
- RETURN_TRUE;
- }
+ /* Unable to register shutdown function, presumably because of lack
+ * of memory, so flush the session now. It would be done in rshutdown
+ * anyway but the handler will have had it's dtor called by then.
+ * If the user does have a later shutdown function which needs the
+ * session then tough luck.
+ */
+ php_session_flush(TSRMLS_C);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to register session flush function");
}
- RETURN_FALSE;
}
/* }}} */
@@ -2052,19 +1985,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_session_decode, 0, 0, 1)
ZEND_ARG_INFO(0, data)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_session_register, 0, 0, 1)
- ZEND_ARG_INFO(0, name)
- ZEND_ARG_INFO(0, ...)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_session_unregister, 0, 0, 1)
- ZEND_ARG_INFO(0, name)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_session_is_registered, 0, 0, 1)
- ZEND_ARG_INFO(0, name)
-ZEND_END_ARG_INFO()
-
ZEND_BEGIN_ARG_INFO(arginfo_session_void, 0)
ZEND_END_ARG_INFO()
@@ -2092,6 +2012,31 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_session_set_cookie_params, 0, 0, 1)
ZEND_ARG_INFO(0, secure)
ZEND_ARG_INFO(0, httponly)
ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_open, 0)
+ ZEND_ARG_INFO(0, save_path)
+ ZEND_ARG_INFO(0, session_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_close, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_read, 0)
+ ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_write, 0)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, val)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_destroy, 0)
+ ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_session_class_gc, 0)
+ ZEND_ARG_INFO(0, maxlifetime)
+ZEND_END_ARG_INFO()
/* }}} */
/* {{{ session_functions[]
@@ -2103,9 +2048,6 @@ static const zend_function_entry session_functions[] = {
PHP_FE(session_id, arginfo_session_id)
PHP_FE(session_regenerate_id, arginfo_session_regenerate_id)
PHP_FE(session_decode, arginfo_session_decode)
- PHP_DEP_FE(session_register, arginfo_session_register)
- PHP_DEP_FE(session_unregister, arginfo_session_unregister)
- PHP_DEP_FE(session_is_registered, arginfo_session_is_registered)
PHP_FE(session_encode, arginfo_session_void)
PHP_FE(session_start, arginfo_session_void)
PHP_FE(session_destroy, arginfo_session_void)
@@ -2116,16 +2058,44 @@ static const zend_function_entry session_functions[] = {
PHP_FE(session_set_cookie_params, arginfo_session_set_cookie_params)
PHP_FE(session_get_cookie_params, arginfo_session_void)
PHP_FE(session_write_close, arginfo_session_void)
+ PHP_FE(session_status, arginfo_session_void)
+ PHP_FE(session_register_shutdown, arginfo_session_void)
PHP_FALIAS(session_commit, session_write_close, arginfo_session_void)
PHP_FE_END
};
/* }}} */
+/* {{{ SessionHandlerInterface functions[]
+*/
+static const zend_function_entry php_session_iface_functions[] = {
+ PHP_ABSTRACT_ME(SessionHandlerInterface, open, arginfo_session_class_open)
+ PHP_ABSTRACT_ME(SessionHandlerInterface, close, arginfo_session_class_close)
+ PHP_ABSTRACT_ME(SessionHandlerInterface, read, arginfo_session_class_read)
+ PHP_ABSTRACT_ME(SessionHandlerInterface, write, arginfo_session_class_write)
+ PHP_ABSTRACT_ME(SessionHandlerInterface, destroy, arginfo_session_class_destroy)
+ PHP_ABSTRACT_ME(SessionHandlerInterface, gc, arginfo_session_class_gc)
+ { NULL, NULL, NULL }
+};
+/* }}} */
+
+/* {{{ SessionHandler functions[]
+ */
+static const zend_function_entry php_session_class_functions[] = {
+ PHP_ME(SessionHandler, open, arginfo_session_class_open, ZEND_ACC_PUBLIC)
+ PHP_ME(SessionHandler, close, arginfo_session_class_close, ZEND_ACC_PUBLIC)
+ PHP_ME(SessionHandler, read, arginfo_session_class_read, ZEND_ACC_PUBLIC)
+ PHP_ME(SessionHandler, write, arginfo_session_class_write, ZEND_ACC_PUBLIC)
+ PHP_ME(SessionHandler, destroy, arginfo_session_class_destroy, ZEND_ACC_PUBLIC)
+ PHP_ME(SessionHandler, gc, arginfo_session_class_gc, ZEND_ACC_PUBLIC)
+ { NULL, NULL, NULL }
+};
+/* }}} */
+
/* ********************************
* Module Setup and Destruction *
******************************** */
-static PHP_RINIT_FUNCTION(session) /* {{{ */
+static int php_rinit_session(zend_bool auto_start TSRMLS_DC) /* {{{ */
{
php_rinit_session_globals(TSRMLS_C);
@@ -2153,11 +2123,16 @@ static PHP_RINIT_FUNCTION(session) /* {{{ */
return SUCCESS;
}
- if (PS(auto_start)) {
+ if (auto_start) {
php_session_start(TSRMLS_C);
}
return SUCCESS;
+} /* }}} */
+
+static PHP_RINIT_FUNCTION(session) /* {{{ */
+{
+ return php_rinit_session(PS(auto_start) TSRMLS_CC);
}
/* }}} */
@@ -2193,6 +2168,9 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */
ps_globals->serializer = NULL;
ps_globals->mod_data = NULL;
ps_globals->session_status = php_session_none;
+ ps_globals->default_mod = NULL;
+ ps_globals->mod_user_implemented = 0;
+ ps_globals->mod_user_is_open = 0;
for (i = 0; i < 6; i++) {
ps_globals->mod_user_names.names[i] = NULL;
}
@@ -2202,7 +2180,9 @@ static PHP_GINIT_FUNCTION(ps) /* {{{ */
static PHP_MINIT_FUNCTION(session) /* {{{ */
{
- zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, NULL TSRMLS_CC);
+ zend_class_entry ce;
+
+ zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, 0, NULL TSRMLS_CC);
PS(module_number) = module_number; /* if we really need this var we need to init it in zts mode as well! */
@@ -2212,6 +2192,23 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */
#ifdef HAVE_LIBMM
PHP_MINIT(ps_mm) (INIT_FUNC_ARGS_PASSTHRU);
#endif
+ php_session_rfc1867_orig_callback = php_rfc1867_callback;
+ php_rfc1867_callback = php_session_rfc1867_callback;
+
+ /* Register interface */
+ INIT_CLASS_ENTRY(ce, PS_IFACE_NAME, php_session_iface_functions);
+ php_session_iface_entry = zend_register_internal_class(&ce TSRMLS_CC);
+ php_session_iface_entry->ce_flags |= ZEND_ACC_INTERFACE;
+
+ /* Register base class */
+ INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions);
+ php_session_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
+ zend_class_implements(php_session_class_entry TSRMLS_CC, 1, php_session_iface_entry);
+
+ REGISTER_LONG_CONSTANT("PHP_SESSION_DISABLED", php_session_disabled, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("PHP_SESSION_NONE", php_session_none, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("PHP_SESSION_ACTIVE", php_session_active, CONST_CS | CONST_PERSISTENT);
+
return SUCCESS;
}
/* }}} */
@@ -2287,6 +2284,286 @@ static const zend_module_dep session_deps[] = { /* {{{ */
};
/* }}} */
+/* ************************
+ * Upload hook handling *
+ ************************ */
+
+static zend_bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */
+{
+ zval **ppid;
+
+ if (!PG(http_globals)[where]) {
+ return 0;
+ }
+
+ if (zend_hash_find(Z_ARRVAL_P(PG(http_globals)[where]), PS(session_name), progress->sname_len+1, (void **)&ppid) == SUCCESS
+ && Z_TYPE_PP(ppid) == IS_STRING) {
+ zval_dtor(dest);
+ ZVAL_ZVAL(dest, *ppid, 1, 0);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+static void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */
+{
+
+ if (PS(use_cookies)) {
+ sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC);
+ if (early_find_sid_in(&progress->sid, TRACK_VARS_COOKIE, progress TSRMLS_CC)) {
+ progress->apply_trans_sid = 0;
+ return;
+ }
+ }
+ if (PS(use_only_cookies)) {
+ return;
+ }
+ sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC);
+ early_find_sid_in(&progress->sid, TRACK_VARS_GET, progress TSRMLS_CC);
+} /* }}} */
+
+static zend_bool php_check_cancel_upload(php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */
+{
+ zval **progress_ary, **cancel_upload;
+
+ if (zend_symtable_find(Z_ARRVAL_P(PS(http_session_vars)), progress->key.c, progress->key.len+1, (void**)&progress_ary) != SUCCESS) {
+ return 0;
+ }
+ if (Z_TYPE_PP(progress_ary) != IS_ARRAY) {
+ return 0;
+ }
+ if (zend_hash_find(Z_ARRVAL_PP(progress_ary), "cancel_upload", sizeof("cancel_upload"), (void**)&cancel_upload) != SUCCESS) {
+ return 0;
+ }
+ return Z_TYPE_PP(cancel_upload) == IS_BOOL && Z_LVAL_PP(cancel_upload);
+} /* }}} */
+
+static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, int force_update TSRMLS_DC) /* {{{ */
+{
+ if (!force_update) {
+ if (Z_LVAL_P(progress->post_bytes_processed) < progress->next_update) {
+ return;
+ }
+#ifdef HAVE_GETTIMEOFDAY
+ if (PS(rfc1867_min_freq) > 0.0) {
+ struct timeval tv = {0};
+ double dtv;
+ gettimeofday(&tv, NULL);
+ dtv = (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+ if (dtv < progress->next_update_time) {
+ return;
+ }
+ progress->next_update_time = dtv + PS(rfc1867_min_freq);
+ }
+#endif
+ progress->next_update = Z_LVAL_P(progress->post_bytes_processed) + progress->update_step;
+ }
+
+ php_session_initialize(TSRMLS_C);
+ PS(session_status) = php_session_active;
+ IF_SESSION_VARS() {
+ progress->cancel_upload = php_check_cancel_upload(progress TSRMLS_CC);
+ ZEND_SET_SYMBOL_WITH_LENGTH(Z_ARRVAL_P(PS(http_session_vars)), progress->key.c, progress->key.len+1, progress->data, 2, 0);
+ }
+ php_session_flush(TSRMLS_C);
+} /* }}} */
+
+static void php_session_rfc1867_cleanup(php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */
+{
+ php_session_initialize(TSRMLS_C);
+ PS(session_status) = php_session_active;
+ IF_SESSION_VARS() {
+ zend_hash_del(Z_ARRVAL_P(PS(http_session_vars)), progress->key.c, progress->key.len+1);
+ }
+ php_session_flush(TSRMLS_C);
+} /* }}} */
+
+static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra TSRMLS_DC) /* {{{ */
+{
+ php_session_rfc1867_progress *progress;
+ int retval = SUCCESS;
+
+ if (php_session_rfc1867_orig_callback) {
+ retval = php_session_rfc1867_orig_callback(event, event_data, extra TSRMLS_CC);
+ }
+ if (!PS(rfc1867_enabled)) {
+ return retval;
+ }
+
+ progress = PS(rfc1867_progress);
+
+ switch(event) {
+ case MULTIPART_EVENT_START: {
+ multipart_event_start *data = (multipart_event_start *) event_data;
+ progress = ecalloc(1, sizeof(php_session_rfc1867_progress));
+ progress->content_length = data->content_length;
+ progress->sname_len = strlen(PS(session_name));
+ PS(rfc1867_progress) = progress;
+ }
+ break;
+ case MULTIPART_EVENT_FORMDATA: {
+ multipart_event_formdata *data = (multipart_event_formdata *) event_data;
+ size_t value_len;
+
+ if (Z_TYPE(progress->sid) && progress->key.c) {
+ break;
+ }
+
+ /* orig callback may have modified *data->newlength */
+ if (data->newlength) {
+ value_len = *data->newlength;
+ } else {
+ value_len = data->length;
+ }
+
+ if (data->name && data->value && value_len) {
+ size_t name_len = strlen(data->name);
+
+ if (name_len == progress->sname_len && memcmp(data->name, PS(session_name), name_len) == 0) {
+ zval_dtor(&progress->sid);
+ ZVAL_STRINGL(&progress->sid, (*data->value), value_len, 1);
+
+ } else if (name_len == PS(rfc1867_name).len && memcmp(data->name, PS(rfc1867_name).c, name_len) == 0) {
+ smart_str_free(&progress->key);
+ smart_str_appendl(&progress->key, PS(rfc1867_prefix).c, PS(rfc1867_prefix).len);
+ smart_str_appendl(&progress->key, *data->value, value_len);
+ smart_str_0(&progress->key);
+
+ progress->apply_trans_sid = PS(use_trans_sid);
+ php_session_rfc1867_early_find_sid(progress TSRMLS_CC);
+ }
+ }
+ }
+ break;
+ case MULTIPART_EVENT_FILE_START: {
+ multipart_event_file_start *data = (multipart_event_file_start *) event_data;
+
+ /* Do nothing when $_POST["PHP_SESSION_UPLOAD_PROGRESS"] is not set
+ * or when we have no session id */
+ if (!Z_TYPE(progress->sid) || !progress->key.c) {
+ break;
+ }
+
+ /* First FILE_START event, initializing data */
+ if (!progress->data) {
+
+ if (PS(rfc1867_freq) >= 0) {
+ progress->update_step = PS(rfc1867_freq);
+ } else if (PS(rfc1867_freq) < 0) { /* % of total size */
+ progress->update_step = progress->content_length * -PS(rfc1867_freq) / 100;
+ }
+ progress->next_update = 0;
+ progress->next_update_time = 0.0;
+
+ ALLOC_INIT_ZVAL(progress->data);
+ array_init(progress->data);
+
+ ALLOC_INIT_ZVAL(progress->post_bytes_processed);
+ ZVAL_LONG(progress->post_bytes_processed, data->post_bytes_processed);
+
+ ALLOC_INIT_ZVAL(progress->files);
+ array_init(progress->files);
+
+ add_assoc_long_ex(progress->data, "start_time", sizeof("start_time"), (long)sapi_get_request_time(TSRMLS_C));
+ add_assoc_long_ex(progress->data, "content_length", sizeof("content_length"), progress->content_length);
+ add_assoc_zval_ex(progress->data, "bytes_processed", sizeof("bytes_processed"), progress->post_bytes_processed);
+ add_assoc_bool_ex(progress->data, "done", sizeof("done"), 0);
+ add_assoc_zval_ex(progress->data, "files", sizeof("files"), progress->files);
+
+ php_rinit_session(0 TSRMLS_CC);
+ PS(id) = estrndup(Z_STRVAL(progress->sid), Z_STRLEN(progress->sid));
+ PS(apply_trans_sid) = progress->apply_trans_sid;
+ PS(send_cookie) = 0;
+ }
+
+ ALLOC_INIT_ZVAL(progress->current_file);
+ array_init(progress->current_file);
+
+ ALLOC_INIT_ZVAL(progress->current_file_bytes_processed);
+ ZVAL_LONG(progress->current_file_bytes_processed, 0);
+
+ /* Each uploaded file has its own array. Trying to make it close to $_FILES entries. */
+ add_assoc_string_ex(progress->current_file, "field_name", sizeof("field_name"), data->name, 1);
+ add_assoc_string_ex(progress->current_file, "name", sizeof("name"), *data->filename, 1);
+ add_assoc_null_ex(progress->current_file, "tmp_name", sizeof("tmp_name"));
+ add_assoc_long_ex(progress->current_file, "error", sizeof("error"), 0);
+
+ add_assoc_bool_ex(progress->current_file, "done", sizeof("done"), 0);
+ add_assoc_long_ex(progress->current_file, "start_time", sizeof("start_time"), (long)time(NULL));
+ add_assoc_zval_ex(progress->current_file, "bytes_processed", sizeof("bytes_processed"), progress->current_file_bytes_processed);
+
+ add_next_index_zval(progress->files, progress->current_file);
+
+ Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
+
+ php_session_rfc1867_update(progress, 0 TSRMLS_CC);
+ }
+ break;
+ case MULTIPART_EVENT_FILE_DATA: {
+ multipart_event_file_data *data = (multipart_event_file_data *) event_data;
+
+ if (!Z_TYPE(progress->sid) || !progress->key.c) {
+ break;
+ }
+
+ Z_LVAL_P(progress->current_file_bytes_processed) = data->offset + data->length;
+ Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
+
+ php_session_rfc1867_update(progress, 0 TSRMLS_CC);
+ }
+ break;
+ case MULTIPART_EVENT_FILE_END: {
+ multipart_event_file_end *data = (multipart_event_file_end *) event_data;
+
+ if (!Z_TYPE(progress->sid) || !progress->key.c) {
+ break;
+ }
+
+ if (data->temp_filename) {
+ add_assoc_string_ex(progress->current_file, "tmp_name", sizeof("tmp_name"), data->temp_filename, 1);
+ }
+ add_assoc_long_ex(progress->current_file, "error", sizeof("error"), data->cancel_upload);
+ add_assoc_bool_ex(progress->current_file, "done", sizeof("done"), 1);
+
+ Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
+
+ php_session_rfc1867_update(progress, 0 TSRMLS_CC);
+ }
+ break;
+ case MULTIPART_EVENT_END: {
+ multipart_event_end *data = (multipart_event_end *) event_data;
+
+ if (Z_TYPE(progress->sid) && progress->key.c) {
+ if (PS(rfc1867_cleanup)) {
+ php_session_rfc1867_cleanup(progress TSRMLS_CC);
+ } else {
+ add_assoc_bool_ex(progress->data, "done", sizeof("done"), 1);
+ Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed;
+ php_session_rfc1867_update(progress, 1 TSRMLS_CC);
+ }
+ php_rshutdown_session_globals(TSRMLS_C);
+ }
+
+ if (progress->data) {
+ zval_ptr_dtor(&progress->data);
+ }
+ zval_dtor(&progress->sid);
+ smart_str_free(&progress->key);
+ efree(progress);
+ progress = NULL;
+ PS(rfc1867_progress) = NULL;
+ }
+ break;
+ }
+
+ if (progress && progress->cancel_upload) {
+ return FAILURE;
+ }
+ return retval;
+
+} /* }}} */
+
zend_module_entry session_module_entry = {
STANDARD_MODULE_HEADER_EX,
NULL,
diff --git a/ext/session/tests/001.phpt b/ext/session/tests/001.phpt
index 543eba7133..eb04dc1147 100644
--- a/ext/session/tests/001.phpt
+++ b/ext/session/tests/001.phpt
@@ -5,7 +5,6 @@ session object serialization
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -24,17 +23,14 @@ $baz->method();
$arr[3] = new foo;
$arr[3]->method();
-session_register("baz");
-session_register("arr");
+session_start();
+
+$_SESSION["baz"] = $baz;
+$_SESSION["arr"] = $arr;
print session_encode()."\n";
session_destroy();
---EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-
-Deprecated: Function session_register() is deprecated in %s on line %d
+--EXPECT--
baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";s:4:"done";}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";s:4:"done";}}
diff --git a/ext/session/tests/003.phpt b/ext/session/tests/003.phpt
index 677a958e8e..03c3b95766 100644
--- a/ext/session/tests/003.phpt
+++ b/ext/session/tests/003.phpt
@@ -5,7 +5,6 @@ session object deserialization
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -21,14 +20,13 @@ session_id("abtest");
session_start();
session_decode('baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}');
-$baz->method();
-$arr[3]->method();
+$_SESSION["baz"]->method();
+$_SESSION["arr"][3]->method();
-var_dump($baz);
-var_dump($arr);
+var_dump($_SESSION["baz"]);
+var_dump($_SESSION["arr"]);
session_destroy();
--EXPECT--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
object(foo)#1 (2) {
["bar"]=>
string(2) "ok"
diff --git a/ext/session/tests/004.phpt b/ext/session/tests/004.phpt
index 3e6de2523b..aeb2c8b363 100644
--- a/ext/session/tests/004.phpt
+++ b/ext/session/tests/004.phpt
@@ -5,7 +5,6 @@ session_set_save_handler test
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
session.name=PHPSESSID
session.serialize_handler=php
--FILE--
@@ -56,24 +55,23 @@ session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd,
session_id("abtest");
session_start();
-$baz->method();
-$arr[3]->method();
+$_SESSION["baz"]->method();
+$_SESSION["arr"][3]->method();
-var_dump($baz);
-var_dump($arr);
+var_dump($_SESSION["baz"]);
+var_dump($_SESSION["arr"]);
session_write_close();
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
session_start();
-var_dump($baz);
-var_dump($arr);
+var_dump($_SESSION["baz"]);
+var_dump($_SESSION["arr"]);
session_destroy();
?>
--EXPECT--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
OPEN: PHPSESSID
READ: abtest
object(foo)#2 (2) {
@@ -94,7 +92,7 @@ array(1) {
WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
OPEN: PHPSESSID
READ: abtest
-object(foo)#4 (2) {
+object(foo)#3 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
diff --git a/ext/session/tests/005.phpt b/ext/session/tests/005.phpt
index 4e6682c86b..a970e6b71d 100644
--- a/ext/session/tests/005.phpt
+++ b/ext/session/tests/005.phpt
@@ -5,7 +5,6 @@ custom save handler, multiple session_start()s, complex data structure test.
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
session.name=PHPSESSID
session.serialize_handler=php
--FILE--
@@ -58,37 +57,41 @@ session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd,
session_id("abtest");
session_start();
-$baz->method();
-$arr[3]->method();
+session_decode($hnd->data);
-var_dump($baz);
-var_dump($arr);
+$_SESSION["baz"]->method();
+$_SESSION["arr"][3]->method();
+
+var_dump($_SESSION["baz"]);
+var_dump($_SESSION["arr"]);
session_write_close();
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
session_start();
-$baz->method();
-$arr[3]->method();
+$_SESSION["baz"]->method();
+$_SESSION["arr"][3]->method();
-$c = 123;
-session_register("c");
-var_dump($baz); var_dump($arr); var_dump($c);
+$_SESSION["c"] = 123;
+var_dump($_SESSION["baz"]);
+var_dump($_SESSION["arr"]);
+var_dump($_SESSION["c"]);
session_write_close();
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
session_start();
-var_dump($baz); var_dump($arr); var_dump($c);
+var_dump($_SESSION["baz"]);
+var_dump($_SESSION["arr"]);
+var_dump($_SESSION["c"]);
session_destroy();
?>
--EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
OPEN: PHPSESSID
READ: abtest
-object(foo)#2 (2) {
+object(foo)#4 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
@@ -96,7 +99,7 @@ object(foo)#2 (2) {
}
array(1) {
[3]=>
- object(foo)#3 (2) {
+ object(foo)#2 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
@@ -107,9 +110,7 @@ WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O
CLOSE
OPEN: PHPSESSID
READ: abtest
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-object(foo)#4 (2) {
+object(foo)#2 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
@@ -117,7 +118,7 @@ object(foo)#4 (2) {
}
array(1) {
[3]=>
- object(foo)#2 (2) {
+ object(foo)#4 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
@@ -129,7 +130,7 @@ WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}arr|a:1:{i:3;O
CLOSE
OPEN: PHPSESSID
READ: abtest
-object(foo)#3 (2) {
+object(foo)#4 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
@@ -137,7 +138,7 @@ object(foo)#3 (2) {
}
array(1) {
[3]=>
- object(foo)#4 (2) {
+ object(foo)#2 (2) {
["bar"]=>
string(2) "ok"
["yes"]=>
diff --git a/ext/session/tests/006.phpt b/ext/session/tests/006.phpt
index 9ab28f65d8..03fca10381 100644
--- a/ext/session/tests/006.phpt
+++ b/ext/session/tests/006.phpt
@@ -5,7 +5,6 @@ correct instantiation of references between variables in sessions
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -32,12 +31,11 @@ $b = new b($a);
echo "original values:\n";
var_dump($a,$b);
-session_register("a");
-session_register("b");
+$_SESSION["a"] = $a;
+$_SESSION["b"] = $b;
session_write_close();
-session_unregister("a");
-session_unregister("b");
+unset($_SESSION["a"], $_SESSION["b"]);
session_start();
@@ -45,7 +43,6 @@ echo "values after session:\n";
var_dump($a,$b);
?>
--EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
original values:
object(a)#%d (1) {
["test"]=>
@@ -58,14 +55,6 @@ object(b)#%d (1) {
string(5) "hallo"
}
}
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
values after session:
object(a)#%d (1) {
["test"]=>
@@ -78,4 +67,3 @@ object(b)#%d (1) {
string(5) "hallo"
}
}
-
diff --git a/ext/session/tests/007.phpt b/ext/session/tests/007.phpt
deleted file mode 100644
index 54768e2bd1..0000000000
--- a/ext/session/tests/007.phpt
+++ /dev/null
@@ -1,67 +0,0 @@
---TEST--
-bug compatibility: unset($c) with enabled register_globals
---SKIPIF--
-<?php include('skipif.inc'); ?>
---INI--
-register_long_arrays=1
-session.use_cookies=0
-session.cache_limiter=
-register_globals=1
-session.bug_compat_42=1
-session.serialize_handler=php
-session.save_handler=files
-precision=14
---FILE--
-<?php
-error_reporting(E_ALL);
-
-session_id("abtest");
-
-### Phase 1 cleanup
-session_start();
-session_destroy();
-
-### Phase 2 $HTTP_SESSION_VARS["c"] does not contain any value
-session_id("abtest");
-session_register("c");
-unset($c);
-$c = 3.14;
-session_write_close();
-unset($HTTP_SESSION_VARS);
-unset($c);
-
-### Phase 3 $HTTP_SESSION_VARS["c"] is set
-session_start();
-var_dump($c);
-var_dump($HTTP_SESSION_VARS);
-unset($c);
-$c = 2.78;
-
-session_write_close();
-unset($HTTP_SESSION_VARS);
-unset($c);
-
-### Phase 4 final
-
-session_start();
-var_dump($c);
-var_dump($HTTP_SESSION_VARS);
-
-session_destroy();
-?>
---EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Deprecated: Directive 'register_long_arrays' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-float(3.14)
-array(1) {
- ["c"]=>
- &float(3.14)
-}
-float(3.14)
-array(1) {
- ["c"]=>
- &float(3.14)
-}
diff --git a/ext/session/tests/008-php4.2.3.phpt b/ext/session/tests/008-php4.2.3.phpt
deleted file mode 100644
index 9464ecded6..0000000000
--- a/ext/session/tests/008-php4.2.3.phpt
+++ /dev/null
@@ -1,78 +0,0 @@
---TEST--
-bug compatibility: global is used albeit register_globals=0
---SKIPIF--
-<?php include('skipif.inc');
- if (version_compare(PHP_VERSION,"4.2.3-dev", "<")) die("skip this is for PHP >= 4.2.3");
-?>
---INI--
-register_long_arrays=1
-session.use_cookies=0
-session.cache_limiter=
-register_globals=0
-session.bug_compat_42=1
-session.bug_compat_warn=1
-track_errors=1
-log_errors=0
-html_errors=0
-display_errors=1
-session.serialize_handler=php
-session.save_handler=files
-precision=14
---FILE--
-<?php
-session_id("abtest");
-
-### Phase 1 cleanup
-session_start();
-session_destroy();
-
-### Phase 2 $HTTP_SESSION_VARS["c"] does not contain any value
-session_id("abtest");
-session_register("c");
-var_dump($c);
-unset($c);
-$c = 3.14;
-@session_write_close(); // this generates an E_WARNING which will be printed
-// by $php_errormsg so we can use "@" here. ANY further message IS an error.
-echo $php_errormsg."\n";
-unset($HTTP_SESSION_VARS);
-unset($c);
-
-### Phase 3 $HTTP_SESSION_VARS["c"] is set
-session_start();
-var_dump($HTTP_SESSION_VARS);
-unset($c);
-$c = 2.78;
-
-session_write_close();
-unset($HTTP_SESSION_VARS);
-unset($c);
-
-### Phase 4 final
-
-session_start();
-var_dump($c);
-var_dump($HTTP_SESSION_VARS);
-
-session_destroy();
-?>
---EXPECTF--
-Deprecated: Directive 'register_long_arrays' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-
-Notice: Undefined variable: c in %s on line %d
-NULL
-session_write_close(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting session.bug_compat_42 or session.bug_compat_warn to off, respectively
-array(1) {
- ["c"]=>
- float(3.14)
-}
-
-Notice: Undefined variable: c in %s on line %d
-NULL
-array(1) {
- ["c"]=>
- float(3.14)
-}
-
diff --git a/ext/session/tests/009.phpt b/ext/session/tests/009.phpt
index 1a7e87ce0d..d73bc238c9 100644
--- a/ext/session/tests/009.phpt
+++ b/ext/session/tests/009.phpt
@@ -1,14 +1,10 @@
--TEST--
-unset($_SESSION["name"]); should work with register_globals=off
+unset($_SESSION["name"]); test
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
-register_long_arrays=1
session.use_cookies=0
session.cache_limiter=
-register_globals=0
-session.bug_compat_42=1
-session.bug_compat_warn=0
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -21,29 +17,28 @@ session_id("abtest");
session_start();
session_destroy();
-### Phase 2 $HTTP_SESSION_VARS["c"] does not contain any value
+### Phase 2 $_SESSION["c"] does not contain any value
session_id("abtest");
session_start();
-var_dump($HTTP_SESSION_VARS);
-$HTTP_SESSION_VARS["name"] = "foo";
-var_dump($HTTP_SESSION_VARS);
+var_dump($_SESSION);
+$_SESSION["name"] = "foo";
+var_dump($_SESSION);
session_write_close();
-### Phase 3 $HTTP_SESSION_VARS["c"] is set
+### Phase 3 $_SESSION["c"] is set
session_start();
-var_dump($HTTP_SESSION_VARS);
-unset($HTTP_SESSION_VARS["name"]);
-var_dump($HTTP_SESSION_VARS);
+var_dump($_SESSION);
+unset($_SESSION["name"]);
+var_dump($_SESSION);
session_write_close();
### Phase 4 final
session_start();
-var_dump($HTTP_SESSION_VARS);
+var_dump($_SESSION);
session_destroy();
?>
--EXPECT--
-Deprecated: Directive 'register_long_arrays' is deprecated in PHP 5.3 and greater in Unknown on line 0
array(0) {
}
array(1) {
diff --git a/ext/session/tests/010.phpt b/ext/session/tests/010.phpt
index e1af8ce87f..79638d283d 100644
--- a/ext/session/tests/010.phpt
+++ b/ext/session/tests/010.phpt
@@ -5,9 +5,6 @@ $session_array = explode(";", session_encode()); should not segfault
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=0
-session.bug_compat_42=1
-session.bug_compat_warn=0
--FILE--
<?php
error_reporting(E_ALL);
diff --git a/ext/session/tests/011.phpt b/ext/session/tests/011.phpt
index 6aaa6bd797..ff1adbaec8 100644
--- a/ext/session/tests/011.phpt
+++ b/ext/session/tests/011.phpt
@@ -5,9 +5,6 @@ session_decode(); should not segfault
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=0
-session.bug_compat_42=1
-session.bug_compat_warn=0
--FILE--
<?php
error_reporting(E_ALL);
diff --git a/ext/session/tests/012.phpt b/ext/session/tests/012.phpt
index b52333a994..8708011273 100644
--- a/ext/session/tests/012.phpt
+++ b/ext/session/tests/012.phpt
@@ -5,9 +5,6 @@ registering $_SESSION should not segfault
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
-session.bug_compat_42=1
-session.bug_compat_warn=0
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -18,7 +15,7 @@ error_reporting(E_ALL);
session_id("abtest");
session_start();
-session_register("_SESSION");
+$_SESSION["_SESSION"] = Array();
$_SESSION = "kk";
session_write_close();
@@ -31,8 +28,5 @@ session_destroy();
print "I live\n";
?>
---EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Deprecated: Function session_register() is deprecated in %s on line %d
+--EXPECT--
I live
diff --git a/ext/session/tests/013.phpt b/ext/session/tests/013.phpt
index 04322f9f17..8d0f284b17 100644
--- a/ext/session/tests/013.phpt
+++ b/ext/session/tests/013.phpt
@@ -5,9 +5,6 @@ redefining SID should not cause warnings
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
-session.bug_compat_42=1
-session.bug_compat_warn=0
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -24,5 +21,4 @@ session_destroy();
print "I live\n";
?>
--EXPECT--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
I live
diff --git a/ext/session/tests/014.phpt b/ext/session/tests/014.phpt
index 09ad0f5b17..73bc28ea66 100644
--- a/ext/session/tests/014.phpt
+++ b/ext/session/tests/014.phpt
@@ -6,9 +6,6 @@ a script should not be able to modify session.use_trans_sid
session.use_trans_sid=0
session.use_cookies=0
session.cache_limiter=
-register_globals=1
-session.bug_compat_42=1
-session.bug_compat_warn=0
session.name=PHPSESSID
session.serialize_handler=php
session.save_handler=files
@@ -33,7 +30,6 @@ ini_set("session.use_trans_sid","0");
session_destroy();
?>
--EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
<a href="/link">
Warning: ini_set(): A session is active. You cannot change the session module's ini settings at this time in %s on line %d
diff --git a/ext/session/tests/019.phpt b/ext/session/tests/019.phpt
index 9c4f8caf93..3ee8ccd420 100644
--- a/ext/session/tests/019.phpt
+++ b/ext/session/tests/019.phpt
@@ -5,7 +5,6 @@ serializing references test case using globals
--INI--
session.use_cookies=0
session.cache_limiter=
-register_globals=1
session.serialize_handler=php
session.save_handler=files
--FILE--
@@ -25,31 +24,28 @@ class TFoo {
session_id("abtest");
session_start();
-session_register('o1', 'o2' );
-$o1 = new TFoo(42);
-$o2 =& $o1;
+$_SESSION["o1"] = new TFoo(42);
+$_SESSION["o2"] =& $_SESSION["o1"];
session_write_close();
-unset($o1);
-unset($o2);
+unset($_SESSION["o1"]);
+unset($_SESSION["o2"]);
session_start();
var_dump($_SESSION);
-$o1->inc();
-$o2->inc();
+$_SESSION["o1"]->inc();
+$_SESSION["o2"]->inc();
var_dump($_SESSION);
session_destroy();
?>
--EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in Unknown on line 0
-Deprecated: Function session_register() is deprecated in %s on line %d
array(2) {
["o1"]=>
&object(TFoo)#%d (1) {
diff --git a/ext/session/tests/bug24592.phpt b/ext/session/tests/bug24592.phpt
index 059125ba2e..9f6c395317 100644
--- a/ext/session/tests/bug24592.phpt
+++ b/ext/session/tests/bug24592.phpt
@@ -3,7 +3,6 @@ Bug #24592 (crash when multiple NULL values are being stored)
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
-register_globals=0
html_errors=0
session.save_handler=files
--FILE--
diff --git a/ext/session/tests/bug26862.phpt b/ext/session/tests/bug26862.phpt
index 44e7418cd0..7990f74359 100644
--- a/ext/session/tests/bug26862.phpt
+++ b/ext/session/tests/bug26862.phpt
@@ -3,7 +3,6 @@ Bug #26862 (ob_flush() before output_reset_rewrite_vars() results in data loss)
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
-register_globals=0
html_errors=0
session.use_trans_sid=0
session.save_handler=files
diff --git a/ext/session/tests/bug55688.phpt b/ext/session/tests/bug55688.phpt
new file mode 100644
index 0000000000..8db48384af
--- /dev/null
+++ b/ext/session/tests/bug55688.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #55688 (Crash when calling SessionHandler::gc())
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--INI--
+html_errors=0
+session.save_handler=files
+--FILE--
+<?php
+ini_set('session.save_handler', 'files');
+$x = new SessionHandler;
+$x->gc(1);
+?>
+--EXPECTF--
+Warning: SessionHandler::gc(): Parent session handler is not open in %s on line %d
diff --git a/ext/session/tests/bug60634_error_5.phpt b/ext/session/tests/bug60634_error_5.phpt
index 376b65f20b..8081ab988a 100644
--- a/ext/session/tests/bug60634_error_5.phpt
+++ b/ext/session/tests/bug60634_error_5.phpt
@@ -1,7 +1,5 @@
--TEST--
Bug #60634 (Segmentation fault when trying to die() in SessionHandler::write()) - fatal error in close during exec
---XFAIL--
-Long term low priority bug, working on it
--INI--
session.save_path=
session.name=PHPSESSID
diff --git a/ext/session/tests/bug61728.phpt b/ext/session/tests/bug61728.phpt
new file mode 100644
index 0000000000..3f8dbeb58a
--- /dev/null
+++ b/ext/session/tests/bug61728.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Bug #61728 (PHP crash when calling ob_start in request_shutdown phase)
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+function output_html($ext) {
+ return strlen($ext);
+}
+
+function open ($save_path, $session_name) {
+ return true;
+}
+
+function close() {
+ return true;
+}
+
+function read ($id) {
+}
+
+function write ($id, $sess_data) {
+ ob_start("output_html");
+ echo "laruence";
+ ob_end_flush();
+ return true;
+}
+
+function destroy ($id) {
+}
+
+function gc ($maxlifetime) {
+ return true;
+}
+
+session_set_save_handler ("open", "close", "read", "write", "destroy", "gc");
+session_start();
+--EXPECTF--
+8
diff --git a/ext/session/tests/rfc1867.phpt b/ext/session/tests/rfc1867.phpt
new file mode 100644
index 0000000000..dc44e8b443
--- /dev/null
+++ b/ext/session/tests/rfc1867.phpt
@@ -0,0 +1,129 @@
+--TEST--
+session rfc1867
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=1%
+session.upload_progress.min_freq=0.000000001
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
diff --git a/ext/session/tests/rfc1867_cleanup.phpt b/ext/session/tests/rfc1867_cleanup.phpt
new file mode 100644
index 0000000000..f70b395d22
--- /dev/null
+++ b/ext/session/tests/rfc1867_cleanup.phpt
@@ -0,0 +1,83 @@
+--TEST--
+session rfc1867
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=1
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=1%
+session.upload_progress.min_freq=0.000000001
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_cleanup.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_disabled.phpt b/ext/session/tests/rfc1867_disabled.phpt
new file mode 100644
index 0000000000..4490055791
--- /dev/null
+++ b/ext/session/tests/rfc1867_disabled.phpt
@@ -0,0 +1,76 @@
+--TEST--
+session rfc1867 disabled
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=0
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=1%
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_disabled_2.phpt b/ext/session/tests/rfc1867_disabled_2.phpt
new file mode 100644
index 0000000000..e878f4619f
--- /dev/null
+++ b/ext/session/tests/rfc1867_disabled_2.phpt
@@ -0,0 +1,76 @@
+--TEST--
+session rfc1867 disabled 2
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=1%
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_inter.phpt b/ext/session/tests/rfc1867_inter.phpt
new file mode 100644
index 0000000000..768637105c
--- /dev/null
+++ b/ext/session/tests/rfc1867_inter.phpt
@@ -0,0 +1,133 @@
+--TEST--
+session rfc1867
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=1%
+session.upload_progress.min_freq=0.000000001
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_inter.php_1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_inter.php_2
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__) . "_1"]);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__) . "_2"]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_invalid_settings-win.phpt b/ext/session/tests/rfc1867_invalid_settings-win.phpt
new file mode 100644
index 0000000000..ed854e8898
--- /dev/null
+++ b/ext/session/tests/rfc1867_invalid_settings-win.phpt
@@ -0,0 +1,19 @@
+--TEST--
+session rfc1867 invalid settings
+--INI--
+session.upload_progress.freq=-1
+error_log=
+--SKIPIF--
+<?php
+include('skipif.inc');
+if(substr(PHP_OS, 0, 3) != "WIN")
+ die("skip windows only test");
+?>
+--FILE--
+<?php
+var_dump(ini_get("session.upload_progress.freq"));
+?>
+--EXPECTF--
+Warning: PHP Startup: session.upload_progress.freq must be greater than or equal to zero in %s
+string(2) "1%"
+PHP Warning: PHP Startup: session.upload_progress.freq must be greater than or equal to zero in %s
diff --git a/ext/session/tests/rfc1867_invalid_settings.phpt b/ext/session/tests/rfc1867_invalid_settings.phpt
new file mode 100644
index 0000000000..640c4d2436
--- /dev/null
+++ b/ext/session/tests/rfc1867_invalid_settings.phpt
@@ -0,0 +1,20 @@
+--TEST--
+session rfc1867 invalid settings
+--INI--
+session.upload_progress.freq=-1
+error_log=
+--SKIPIF--
+<?php
+include('skipif.inc');
+if(substr(PHP_OS, 0, 3) == "WIN")
+ die("skip Not for Windows");
+?>
+--FILE--
+<?php
+var_dump(ini_get("session.upload_progress.freq"));
+?>
+--EXPECTF--
+PHP Warning: PHP Startup: session.upload_progress.freq must be greater than or equal to zero in %s
+
+Warning: PHP Startup: session.upload_progress.freq must be greater than or equal to zero in %s
+string(%d) "1%"
diff --git a/ext/session/tests/rfc1867_invalid_settings_2-win.phpt b/ext/session/tests/rfc1867_invalid_settings_2-win.phpt
new file mode 100644
index 0000000000..f8e6b6d208
--- /dev/null
+++ b/ext/session/tests/rfc1867_invalid_settings_2-win.phpt
@@ -0,0 +1,19 @@
+--TEST--
+session rfc1867 invalid settings 2
+--INI--
+session.upload_progress.freq=200%
+error_log=
+--SKIPIF--
+<?php
+include('skipif.inc');
+if(substr(PHP_OS, 0, 3) != "WIN")
+ die("skip windows only test");
+?>
+--FILE--
+<?php
+var_dump(ini_get("session.upload_progress.freq"));
+?>
+--EXPECTF--
+Warning: PHP Startup: session.upload_progress.freq cannot be over 100% in %s
+string(2) "1%"
+PHP Warning: PHP Startup: session.upload_progress.freq cannot be over 100% in %s
diff --git a/ext/session/tests/rfc1867_invalid_settings_2.phpt b/ext/session/tests/rfc1867_invalid_settings_2.phpt
new file mode 100644
index 0000000000..c2a0c6ac4e
--- /dev/null
+++ b/ext/session/tests/rfc1867_invalid_settings_2.phpt
@@ -0,0 +1,20 @@
+--TEST--
+session rfc1867 invalid settings 2
+--INI--
+session.upload_progress.freq=200%
+error_log=
+--SKIPIF--
+<?php
+include('skipif.inc');
+if(substr(PHP_OS, 0, 3) == "WIN")
+ die("skip Not for Windows");
+?>
+--FILE--
+<?php
+var_dump(ini_get("session.upload_progress.freq"));
+?>
+--EXPECTF--
+PHP Warning: PHP Startup: session.upload_progress.freq cannot be over 100% in %s
+
+Warning: PHP Startup: session.upload_progress.freq cannot be over 100% in %s
+string(%d) "1%"
diff --git a/ext/session/tests/rfc1867_no_name.phpt b/ext/session/tests/rfc1867_no_name.phpt
new file mode 100644
index 0000000000..c1dda8156e
--- /dev/null
+++ b/ext/session/tests/rfc1867_no_name.phpt
@@ -0,0 +1,76 @@
+--TEST--
+session rfc1867 no name
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=1%
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_sid_cookie.phpt b/ext/session/tests/rfc1867_sid_cookie.phpt
new file mode 100644
index 0000000000..735a5ac201
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_cookie.phpt
@@ -0,0 +1,128 @@
+--TEST--
+session rfc1867 sid cookie
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_cookie.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
diff --git a/ext/session/tests/rfc1867_sid_get.phpt b/ext/session/tests/rfc1867_sid_get.phpt
new file mode 100644
index 0000000000..cc5a793e7b
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_get.phpt
@@ -0,0 +1,126 @@
+--TEST--
+session rfc1867 sid get
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--GET--
+PHPSESSID=rfc1867-tests
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_get.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
diff --git a/ext/session/tests/rfc1867_sid_get_2.phpt b/ext/session/tests/rfc1867_sid_get_2.phpt
new file mode 100644
index 0000000000..1d22e5930b
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_get_2.phpt
@@ -0,0 +1,128 @@
+--TEST--
+session rfc1867 sid get 2
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=0
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests-cookie
+--GET--
+PHPSESSID=rfc1867-tests
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_get_2.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
diff --git a/ext/session/tests/rfc1867_sid_invalid.phpt b/ext/session/tests/rfc1867_sid_invalid.phpt
new file mode 100644
index 0000000000..b28a2e341b
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_invalid.phpt
@@ -0,0 +1,79 @@
+--TEST--
+session rfc1867 sid cookie
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.auto_start=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=_
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_invalid.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+error_reporting(0);
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+Warning: Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0
+string(%d) "%s"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_sid_only_cookie.phpt b/ext/session/tests/rfc1867_sid_only_cookie.phpt
new file mode 100644
index 0000000000..9a0105668f
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_only_cookie.phpt
@@ -0,0 +1,128 @@
+--TEST--
+session rfc1867 sid only cookie
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=1
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--COOKIE--
+PHPSESSID=rfc1867-tests
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_only_cookie.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
diff --git a/ext/session/tests/rfc1867_sid_only_cookie_2.phpt b/ext/session/tests/rfc1867_sid_only_cookie_2.phpt
new file mode 100644
index 0000000000..e705314d69
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_only_cookie_2.phpt
@@ -0,0 +1,80 @@
+--TEST--
+session rfc1867 sid only cookie 2
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=1
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--GET--
+PHPSESSID=rfc1867-tests-get
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests-post
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_only_cookie_2.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "%s"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+NULL
diff --git a/ext/session/tests/rfc1867_sid_post.phpt b/ext/session/tests/rfc1867_sid_post.phpt
new file mode 100644
index 0000000000..7c1eb2de5d
--- /dev/null
+++ b/ext/session/tests/rfc1867_sid_post.phpt
@@ -0,0 +1,124 @@
+--TEST--
+session rfc1867 sid post
+--INI--
+file_uploads=1
+error_reporting=E_ALL&~E_NOTICE
+comment=debug builds show some additional E_NOTICE errors
+upload_max_filesize=1024
+session.save_path=
+session.name=PHPSESSID
+session.use_cookies=1
+session.use_only_cookies=0
+session.upload_progress.enabled=1
+session.upload_progress.cleanup=0
+session.upload_progress.prefix=upload_progress_
+session.upload_progress.name=PHP_SESSION_UPLOAD_PROGRESS
+session.upload_progress.freq=0
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHPSESSID"
+
+rfc1867-tests
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
+
+rfc1867_sid_post.php
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+
+1
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file2"; filename="file2.txt"
+
+2
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+session_start();
+var_dump(session_id());
+var_dump(basename(__FILE__) == $_POST[ini_get("session.upload_progress.name")]);
+var_dump($_FILES);
+var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
+session_destroy();
+?>
+--EXPECTF--
+string(%d) "rfc1867-tests"
+bool(true)
+array(2) {
+ [%u|b%"file1"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file1.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+ [%u|b%"file2"]=>
+ array(5) {
+ [%u|b%"name"]=>
+ %string|unicode%(9) "file2.txt"
+ [%u|b%"type"]=>
+ %string|unicode%(0) ""
+ [%u|b%"tmp_name"]=>
+ %string|unicode%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"size"]=>
+ int(1)
+ }
+}
+array(5) {
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"content_length"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(%d)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"files"]=>
+ array(2) {
+ [0]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file1"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file1.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ [1]=>
+ array(7) {
+ [%u|b%"field_name"]=>
+ %unicode|string%(5) "file2"
+ [%u|b%"name"]=>
+ %unicode|string%(9) "file2.txt"
+ [%u|b%"tmp_name"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error"]=>
+ int(0)
+ [%u|b%"done"]=>
+ bool(true)
+ [%u|b%"start_time"]=>
+ int(%d)
+ [%u|b%"bytes_processed"]=>
+ int(1)
+ }
+ }
+}
diff --git a/ext/session/tests/session_encode_basic.phpt b/ext/session/tests/session_encode_basic.phpt
index b087f74414..dfe40d204d 100644
--- a/ext/session/tests/session_encode_basic.phpt
+++ b/ext/session/tests/session_encode_basic.phpt
@@ -1,5 +1,7 @@
--TEST--
Test session_encode() function : basic functionality
+--INI--
+serialize_precision=100
--SKIPIF--
<?php include('skipif.inc'); ?>
--FILE--
@@ -120,7 +122,7 @@ string(13) "data|d:-10.5;"
string(20) "data|d:123456789000;"
-- Iteration 8 --
-string(29) "data|d:1.2345678899999999E-9;"
+string(%d) "data|d:1.2345678899999999145113427164344339914681114578343112953007221221923828125E-9;"
-- Iteration 9 --
string(11) "data|d:0.5;"
diff --git a/ext/session/tests/session_id_variation2.phpt b/ext/session/tests/session_id_variation2.phpt
index 70db283aec..f69aa44c0d 100644
--- a/ext/session/tests/session_id_variation2.phpt
+++ b/ext/session/tests/session_id_variation2.phpt
@@ -4,6 +4,8 @@ Test session_id() function : variation
<?php include('skipif.inc'); ?>
--INI--
session.hash_function=0
+session.entropy_file=
+session.entropy_length=0
--FILE--
<?php
diff --git a/ext/session/tests/session_is_registered_basic.phpt b/ext/session/tests/session_is_registered_basic.phpt
deleted file mode 100644
index 5eb127ea46..0000000000
--- a/ext/session/tests/session_is_registered_basic.phpt
+++ /dev/null
@@ -1,318 +0,0 @@
---TEST--
-Test session_unregister() function : basic functionality
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_is_registered(string $name)
- * Description : Find out whether a global variable is registered in a session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_is_registered() : basic functionality ***\n";
-
-// Get an unset variable
-$unset_var = 10;
-unset($unset_var);
-
-class classA
-{
- public function __toString() {
- return "Hello World!";
- }
-}
-
-$heredoc = <<<EOT
-Hello World!
-EOT;
-
-$fp = fopen(__FILE__, "r");
-
-// Unexpected values to be passed as arguments
-$inputs = array(
-
- // Integer data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // Float data
-/*5*/ 10.5,
- -10.5,
- 12.3456789000e10,
- 12.3456789000E-10,
- .5,
-
- // Null data
-/*10*/ NULL,
- null,
-
- // Boolean data
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // Empty strings
-/*16*/ "",
- '',
-
- // Invalid string data
-/*18*/ "Nothing",
- 'Nothing',
- $heredoc,
-
- // Object data
-/*21*/ new classA(),
-
- // Undefined data
-/*22*/ @$undefined_var,
-
- // Unset data
-/*23*/ @$unset_var,
-
- // Resource variable
-/*24*/ $fp
-);
-
-
-$iterator = 1;
-foreach($inputs as $input) {
- echo "\n-- Iteration $iterator --\n";
- var_dump(session_start());
- var_dump(session_is_registered($input));
- var_dump($_SESSION);
- var_dump(session_destroy());
- $iterator++;
-};
-
-fclose($fp);
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_is_registered() : basic functionality ***
-
--- Iteration 1 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 2 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 3 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 4 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 5 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 6 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 7 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 8 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 9 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 10 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 11 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 12 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 13 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 14 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 15 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 16 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 17 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 18 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 19 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 20 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 21 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 22 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 23 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
--- Iteration 24 --
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-
-Warning: session_is_registered() expects parameter 1 to be string, resource given in %s on line %d
-NULL
-array(0) {
-}
-bool(true)
-Done
diff --git a/ext/session/tests/session_is_registered_variation1.phpt b/ext/session/tests/session_is_registered_variation1.phpt
deleted file mode 100644
index 35c357d14d..0000000000
--- a/ext/session/tests/session_is_registered_variation1.phpt
+++ /dev/null
@@ -1,109 +0,0 @@
---TEST--
-Test session_unregister() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_is_registered(string $name)
- * Description : Find out whether a global variable is registered in a session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_is_registered() : variation ***\n";
-
-// Get an unset variable
-$unset_var = 10;
-unset($unset_var);
-
-class classA
-{
- public function __toString() {
- return "Hello World!";
- }
-}
-
-$heredoc = <<<EOT
-Hello World!
-EOT;
-
-$fp = fopen(__FILE__, "r");
-
-// Unexpected values to be passed as arguments
-$inputs = array(
-
- // Integer data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // Float data
-/*5*/ 10.5,
- -10.5,
- 12.3456789000e10,
- 12.3456789000E-10,
- .5,
-
- // Null data
-/*10*/ NULL,
- null,
-
- // Boolean data
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // Empty strings
-/*16*/ "",
- '',
-
- // Invalid string data
-/*18*/ "Nothing",
- 'Nothing',
- $heredoc,
-
- // Object data
-/*21*/ new classA(),
-
- // Undefined data
-/*22*/ @$undefined_var,
-
- // Unset data
-/*23*/ @$unset_var,
-
- // Resource variable
-/*24*/ $fp
-);
-
-var_dump(session_start());
-var_dump($_SESSION);
-var_dump(session_is_registered($inputs));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-fclose($fp);
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_is_registered() : variation ***
-bool(true)
-array(0) {
-}
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-
-Warning: session_is_registered() expects parameter 1 to be string, array given in %s on line %d
-NULL
-array(0) {
-}
-bool(true)
-array(0) {
-}
-Done
diff --git a/ext/session/tests/session_is_registered_variation2.phpt b/ext/session/tests/session_is_registered_variation2.phpt
deleted file mode 100644
index 3727518b19..0000000000
--- a/ext/session/tests/session_is_registered_variation2.phpt
+++ /dev/null
@@ -1,75 +0,0 @@
---TEST--
-Test session_unregister() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_is_registered(string $name)
- * Description : Find out whether a global variable is registered in a session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_is_registered() : variation ***\n";
-
-var_dump(session_is_registered("foo"));
-var_dump(session_start());
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-$_SESSION["foo"] = "Hello World!";
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-var_dump(session_is_registered("foo"));
-var_dump(session_unregister("foo"));
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-var_dump(session_is_registered("foo"));
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_is_registered() : variation ***
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["foo"]=>
- string(12) "Hello World!"
-}
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(true)
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-Done
diff --git a/ext/session/tests/session_is_registered_variation3.phpt b/ext/session/tests/session_is_registered_variation3.phpt
deleted file mode 100644
index b435d043d9..0000000000
--- a/ext/session/tests/session_is_registered_variation3.phpt
+++ /dev/null
@@ -1,72 +0,0 @@
---TEST--
-Test session_unregister() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_is_registered(string $name)
- * Description : Find out whether a global variable is registered in a session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_is_registered() : variation ***\n";
-
-var_dump(session_is_registered("foo"));
-var_dump(session_start());
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-$blah = "Hello World!";
-var_dump(session_is_registered("foo"));
-$_SESSION["foo"] = &$blah;
-var_dump($_SESSION);
-var_dump(session_is_registered("foo"));
-var_dump(session_unregister("foo"));
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump(session_is_registered("foo"));
-var_dump($_SESSION);
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_is_registered() : variation ***
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(1) {
- ["foo"]=>
- &string(12) "Hello World!"
-}
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(true)
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-bool(true)
-
-Deprecated: Function session_is_registered() is deprecated in %s on line %d
-bool(false)
-array(0) {
-}
-Done
diff --git a/ext/session/tests/session_register_basic.phpt b/ext/session/tests/session_register_basic.phpt
deleted file mode 100644
index a394f748e8..0000000000
--- a/ext/session/tests/session_register_basic.phpt
+++ /dev/null
@@ -1,364 +0,0 @@
---TEST--
-Test session_register() function : basic functionality
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_register(mixed $name [,mixed $...])
- * Description : Register one or more global variables with the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_register() : basic functionality ***\n";
-
-// Get an unset variable
-$unset_var = 10;
-unset($unset_var);
-
-class classA
-{
- public function __toString() {
- return "Hello World!";
- }
-}
-
-$heredoc = <<<EOT
-Hello World!
-EOT;
-
-$fp = fopen(__FILE__, "r");
-
-// Unexpected values to be passed as arguments
-$inputs = array(
-
- // Integer data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // Float data
-/*5*/ 10.5,
- -10.5,
- 12.3456789000e10,
- 12.3456789000E-10,
- .5,
-
- // Null data
-/*10*/ NULL,
- null,
-
- // Boolean data
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // Empty strings
-/*16*/ "",
- '',
-
- // Invalid string data
-/*18*/ "Nothing",
- 'Nothing',
- $heredoc,
-
- // Object data
-/*21*/ new classA(),
-
- // Undefined data
-/*22*/ @$undefined_var,
-
- // Unset data
-/*23*/ @$unset_var,
-
- // Resource variable
-/*24*/ $fp
-);
-
-
-$iterator = 1;
-foreach($inputs as $input) {
- echo "\n-- Iteration $iterator --\n";
- var_dump(session_start());
- var_dump(session_register($input));
- var_dump($_SESSION);
- var_dump(session_destroy());
- $iterator++;
-};
-
-fclose($fp);
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_register() : basic functionality ***
-
--- Iteration 1 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["0"]=>
- NULL
-}
-bool(true)
-
--- Iteration 2 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["1"]=>
- NULL
-}
-bool(true)
-
--- Iteration 3 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["12345"]=>
- NULL
-}
-bool(true)
-
--- Iteration 4 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["-2345"]=>
- NULL
-}
-bool(true)
-
--- Iteration 5 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["10.5"]=>
- NULL
-}
-bool(true)
-
--- Iteration 6 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["-10.5"]=>
- NULL
-}
-bool(true)
-
--- Iteration 7 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["123456789000"]=>
- NULL
-}
-bool(true)
-
--- Iteration 8 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["1.23456789E-9"]=>
- NULL
-}
-bool(true)
-
--- Iteration 9 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["0.5"]=>
- NULL
-}
-bool(true)
-
--- Iteration 10 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 11 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 12 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["1"]=>
- NULL
-}
-bool(true)
-
--- Iteration 13 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 14 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["1"]=>
- NULL
-}
-bool(true)
-
--- Iteration 15 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 16 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 17 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 18 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["Nothing"]=>
- NULL
-}
-bool(true)
-
--- Iteration 19 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["Nothing"]=>
- NULL
-}
-bool(true)
-
--- Iteration 20 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["Hello World!"]=>
- NULL
-}
-bool(true)
-
--- Iteration 21 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["Hello World!"]=>
- NULL
-}
-bool(true)
-
--- Iteration 22 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 23 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- [""]=>
- NULL
-}
-bool(true)
-
--- Iteration 24 --
-bool(true)
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["Resource id #%d"]=>
- NULL
-}
-bool(true)
-Done
diff --git a/ext/session/tests/session_register_variation1.phpt b/ext/session/tests/session_register_variation1.phpt
deleted file mode 100644
index 82950d9a9e..0000000000
--- a/ext/session/tests/session_register_variation1.phpt
+++ /dev/null
@@ -1,159 +0,0 @@
---TEST--
-Test session_register() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_register(mixed $name [,mixed $...])
- * Description : Register one or more global variables with the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_register() : variation ***\n";
-
-// Get an unset variable
-$unset_var = 10;
-unset($unset_var);
-
-class classA
-{
- public function __toString() {
- return "Hello World!";
- }
-}
-
-$heredoc = <<<EOT
-Hello World!
-EOT;
-
-$fp = fopen(__FILE__, "r");
-
-// Unexpected values to be passed as arguments
-$inputs = array(
-
- // Integer data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // Float data
-/*5*/ 10.5,
- -10.5,
- 12.3456789000e10,
- 12.3456789000E-10,
- .5,
-
- // Null data
-/*10*/ NULL,
- null,
-
- // Boolean data
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // Empty strings
-/*16*/ "",
- '',
-
- // Invalid string data
-/*18*/ "Nothing",
- 'Nothing',
- $heredoc,
-
- // Object data
-/*21*/ new classA(),
-
- // Undefined data
-/*22*/ @$undefined_var,
-
- // Unset data
-/*23*/ @$unset_var,
-
- // Resource variable
-/*24*/ $fp
-);
-
-var_dump(session_start());
-var_dump($_SESSION);
-var_dump(session_register($inputs));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-fclose($fp);
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_register() : variation ***
-bool(true)
-array(0) {
-}
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(13) {
- ["0"]=>
- NULL
- ["1"]=>
- NULL
- ["12345"]=>
- NULL
- ["-2345"]=>
- NULL
- ["10.5"]=>
- NULL
- ["-10.5"]=>
- NULL
- ["123456789000"]=>
- NULL
- ["1.23456789E-9"]=>
- NULL
- ["0.5"]=>
- NULL
- [""]=>
- NULL
- ["Nothing"]=>
- NULL
- ["Hello World!"]=>
- NULL
- ["Resource id #%d"]=>
- NULL
-}
-bool(true)
-array(13) {
- ["0"]=>
- NULL
- ["1"]=>
- NULL
- ["12345"]=>
- NULL
- ["-2345"]=>
- NULL
- ["10.5"]=>
- NULL
- ["-10.5"]=>
- NULL
- ["123456789000"]=>
- NULL
- ["1.23456789E-9"]=>
- NULL
- ["0.5"]=>
- NULL
- [""]=>
- NULL
- ["Nothing"]=>
- NULL
- ["Hello World!"]=>
- NULL
- ["Resource id #%d"]=>
- NULL
-}
-Done
diff --git a/ext/session/tests/session_register_variation2.phpt b/ext/session/tests/session_register_variation2.phpt
deleted file mode 100644
index d9060c7e90..0000000000
--- a/ext/session/tests/session_register_variation2.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-Test session_register() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_register(mixed $name [,mixed $...])
- * Description : Register one or more global variables with the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_register() : variation ***\n";
-
-var_dump(session_start());
-var_dump($_SESSION);
-var_dump(session_register());
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_register() : variation ***
-bool(true)
-array(0) {
-}
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-
-Warning: session_register() expects at least 1 parameter, 0 given in %s on line %d
-NULL
-array(0) {
-}
-bool(true)
-array(0) {
-}
-Done
diff --git a/ext/session/tests/session_register_variation3.phpt b/ext/session/tests/session_register_variation3.phpt
deleted file mode 100644
index 43172ac49a..0000000000
--- a/ext/session/tests/session_register_variation3.phpt
+++ /dev/null
@@ -1,46 +0,0 @@
---TEST--
-Test session_register() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_register(mixed $name [,mixed $...])
- * Description : Register one or more global variables with the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_register() : variation ***\n";
-
-$blah = "Hello World!";
-var_dump(session_start());
-var_dump($_SESSION);
-var_dump(session_register("blah"));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_register() : variation ***
-bool(true)
-array(0) {
-}
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["blah"]=>
- NULL
-}
-bool(true)
-array(1) {
- ["blah"]=>
- NULL
-}
-Done
diff --git a/ext/session/tests/session_register_variation4.phpt b/ext/session/tests/session_register_variation4.phpt
deleted file mode 100644
index 4f07815026..0000000000
--- a/ext/session/tests/session_register_variation4.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-Test session_register() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_register(mixed $name [,mixed $...])
- * Description : Register one or more global variables with the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_register() : variation ***\n";
-
-$blah = "Hello World!";
-$foo = &$blah;
-var_dump(session_start());
-var_dump($_SESSION);
-var_dump(session_register("foo"));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_register() : variation ***
-bool(true)
-array(0) {
-}
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
-}
-bool(true)
-array(1) {
- ["foo"]=>
- NULL
-}
-Done
diff --git a/ext/session/tests/session_save_path_variation5.phpt b/ext/session/tests/session_save_path_variation5.phpt
index ca6cb51c51..5407b5e15a 100644
--- a/ext/session/tests/session_save_path_variation5.phpt
+++ b/ext/session/tests/session_save_path_variation5.phpt
@@ -6,15 +6,14 @@ if(substr(PHP_OS, 0, 3) == "WIN")
die("skip Not for Windows");
?>
--INI--
-open_basedir=.
session.save_handler=files
session.save_path=
session.name=PHPSESSID
+open_basedir=.
--FILE--
<?php
ob_start();
-
/*
* Prototype : string session_save_path([string $path])
* Description : Get and/or set the current session save path
diff --git a/ext/session/tests/session_set_save_handler_class_001.phpt b/ext/session/tests/session_set_save_handler_class_001.phpt
new file mode 100644
index 0000000000..83e899a2bc
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_001.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Test session_set_save_handler() : basic class wrapping existing handler
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : basic class wrapping existing handler ***\n";
+
+class MySession extends SessionHandler {
+ public $i = 0;
+ public function open($path, $name) {
+ ++$this->i;
+ echo 'Open ', session_id(), "\n";
+ return parent::open($path, $name);
+ }
+ public function read($key) {
+ ++$this->i;
+ echo 'Read ', session_id(), "\n";
+ return parent::read($key);
+ }
+}
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new MySession;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION);
+
+$_SESSION['foo'] = "hello";
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : basic class wrapping existing handler ***
+Open
+Read %s
+string(%d) "%s"
+string(5) "files"
+string(4) "user"
+int(2)
+array(0) {
+}
+Open %s
+Read %s
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
diff --git a/ext/session/tests/session_set_save_handler_class_002.phpt b/ext/session/tests/session_set_save_handler_class_002.phpt
new file mode 100644
index 0000000000..6fb831f695
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_002.phpt
@@ -0,0 +1,113 @@
+--TEST--
+Test session_set_save_handler() : full handler implementation
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : full handler implementation ***\n";
+
+class MySession2 extends SessionHandler {
+ public $path;
+
+ public function open($path, $name) {
+ if (!$path) {
+ $path = sys_get_temp_dir();
+ }
+ $this->path = $path . '/u_sess_' . $name;
+ return true;
+ }
+
+ public function close() {
+ return true;
+ }
+
+ public function read($id) {
+ return @file_get_contents($this->path . $id);
+ }
+
+ public function write($id, $data) {
+ return file_put_contents($this->path . $id, $data);
+ }
+
+ public function destroy($id) {
+ @unlink($this->path . $id);
+ }
+
+ public function gc($maxlifetime) {
+ foreach (glob($this->path . '*') as $filename) {
+ if (filemtime($filename) + $maxlifetime < time()) {
+ @unlink($filename);
+ }
+ }
+ return true;
+ }
+}
+
+$handler = new MySession2;
+session_set_save_handler(array($handler, 'open'), array($handler, 'close'),
+ array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'));
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : full handler implementation ***
+string(%d) "%s"
+string(4) "user"
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+string(%d) "%s"
+string(4) "user"
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
diff --git a/ext/session/tests/session_set_save_handler_class_003.phpt b/ext/session/tests/session_set_save_handler_class_003.phpt
new file mode 100644
index 0000000000..e9a3cc2feb
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_003.phpt
@@ -0,0 +1,78 @@
+--TEST--
+Test session_set_save_handler() : inheritance
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : inheritance ***\n";
+
+class MySession3 extends SessionHandler {
+ public $i = 0;
+ public function open($path, $name) {
+ ++$this->i;
+ return parent::open($path, $name);
+ }
+ public function read($key) {
+ ++$this->i;
+ return parent::read($key);
+ }
+}
+
+class MySession4 extends MySession3 {
+ public function write($id, $data) {
+ $this->i = "hai";
+ return parent::write($id, $data);
+ }
+}
+
+$handler = new MySession3;
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+session_write_close();
+session_unset();
+
+session_start();
+
+var_dump($_SESSION, $handler->i);
+
+session_write_close();
+session_unset();
+
+$handler = new MySession4;
+session_set_save_handler($handler);
+
+session_start();
+
+session_write_close();
+session_unset();
+
+var_dump(session_id(), $_SESSION, $handler->i);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : inheritance ***
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+int(4)
+string(%d) "%s"
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+string(3) "hai"
diff --git a/ext/session/tests/session_set_save_handler_class_004.phpt b/ext/session/tests/session_set_save_handler_class_004.phpt
new file mode 100644
index 0000000000..103b13baa7
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_004.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Test session_set_save_handler() : default object
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : default object ***\n";
+
+session_set_save_handler(new SessionHandler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+session_start();
+
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : default object ***
+string(%d) "%s"
+string(4) "user"
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
diff --git a/ext/session/tests/session_set_save_handler_class_005.phpt b/ext/session/tests/session_set_save_handler_class_005.phpt
new file mode 100644
index 0000000000..a996eb8d26
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_005.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Test session_set_save_handler() : incomplete implementation
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : incomplete implementation ***\n";
+
+class MySession6 extends SessionHandler {
+ public function open($path, $name) {
+ // don't call parent
+ return true;
+ }
+
+ public function read($id) {
+ // should error because parent::open hasn't been called
+ return parent::read($id);
+ }
+}
+
+$handler = new MySession6;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+
+--EXPECTF--
+*** Testing session_set_save_handler() : incomplete implementation ***
+
+Warning: SessionHandler::read(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d
+string(%d) "%s"
+string(4) "user"
+array(0) {
+}
+
+Warning: SessionHandler::write(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d
+
+Warning: SessionHandler::close(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d
diff --git a/ext/session/tests/session_set_save_handler_class_006.phpt b/ext/session/tests/session_set_save_handler_class_006.phpt
new file mode 100644
index 0000000000..5830b6d4fa
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_006.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Test session_set_save_handler() : using objects in close
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : using objects in close ***\n";
+
+class MySession7_Foo {
+ public $state = 'ok';
+ function __destruct() {
+ $this->state = 'destroyed';
+ }
+}
+
+class MySession7 extends SessionHandler {
+ public $foo;
+ public function close() {
+ var_dump($this->foo);
+ @var_dump($GLOBALS['bar']);
+ return parent::close();
+ }
+}
+
+$bar = new MySession7_Foo;
+$handler = new MySession7;
+$handler->foo = new MySession7_Foo;
+session_set_save_handler($handler);
+session_start();
+
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : using objects in close ***
+object(MySession7_Foo)#%d (%d) {
+ ["state"]=>
+ string(2) "ok"
+}
+object(MySession7_Foo)#%d (%d) {
+ ["state"]=>
+ string(2) "ok"
+}
diff --git a/ext/session/tests/session_set_save_handler_class_007.phpt b/ext/session/tests/session_set_save_handler_class_007.phpt
new file mode 100644
index 0000000000..7344ae1ef3
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_007.phpt
@@ -0,0 +1,74 @@
+--TEST--
+Test session_set_save_handler() : manual shutdown, reopen
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : manual shutdown, reopen ***\n";
+
+class MySession extends SessionHandler {
+ public $num;
+ public function __construct($num) {
+ $this->num = $num;
+ echo "(#$this->num) constructor called\n";
+ }
+ public function __destruct() {
+ echo "(#$this->num) destructor called\n";
+ }
+ public function finish() {
+ $id = session_id();
+ echo "(#$this->num) finish called $id\n";
+ session_write_close();
+ }
+ public function write($id, $data) {
+ echo "(#$this->num) writing $id = $data\n";
+ return parent::write($id, $data);
+ }
+ public function close() {
+ $id = session_id();
+ echo "(#$this->num) closing $id\n";
+ return parent::close();
+ }
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+// explicit close
+$handler->finish();
+
+$handler = new MySession(2);
+session_set_save_handler($handler);
+session_start();
+
+// implicit close (called by shutdown function)
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : manual shutdown, reopen ***
+(#1) constructor called
+(#1) finish called %s
+(#1) writing %s = foo|s:3:"bar";
+(#1) closing %s
+(#2) constructor called
+(#1) destructor called
+done
+(#2) writing %s = foo|s:3:"bar";
+(#2) closing %s
+(#2) destructor called
diff --git a/ext/session/tests/session_set_save_handler_class_008.phpt b/ext/session/tests/session_set_save_handler_class_008.phpt
new file mode 100644
index 0000000000..28cb692f0e
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_008.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Test session_set_save_handler() : manual shutdown
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : manual shutdown ***\n";
+
+class MySession extends SessionHandler {
+ public $num;
+ public function __construct($num) {
+ $this->num = $num;
+ echo "(#$this->num) constructor called\n";
+ }
+ public function __destruct() {
+ echo "(#$this->num) destructor called\n";
+ }
+ public function finish() {
+ $id = session_id();
+ echo "(#$this->num) finish called $id\n";
+ session_write_close();
+ }
+ public function write($id, $data) {
+ echo "(#$this->num) writing $id = $data\n";
+ return parent::write($id, $data);
+ }
+ public function close() {
+ $id = session_id();
+ echo "(#$this->num) closing $id\n";
+ return parent::close();
+ }
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+// explicit close
+$handler->finish();
+
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : manual shutdown ***
+(#1) constructor called
+(#1) finish called %s
+(#1) writing %s = foo|s:3:"bar";
+(#1) closing %s
+done
+(#1) destructor called
diff --git a/ext/session/tests/session_set_save_handler_class_009.phpt b/ext/session/tests/session_set_save_handler_class_009.phpt
new file mode 100644
index 0000000000..a8b57dc541
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_009.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Test session_set_save_handler() : implicit shutdown
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : implicit shutdown ***\n";
+
+class MySession extends SessionHandler {
+ public $num;
+ public function __construct($num) {
+ $this->num = $num;
+ echo "(#$this->num) constructor called\n";
+ }
+ public function __destruct() {
+ echo "(#$this->num) destructor called\n";
+ }
+ public function finish() {
+ $id = session_id();
+ echo "(#$this->num) finish called $id\n";
+ $this->shutdown();
+ }
+ public function write($id, $data) {
+ echo "(#$this->num) writing $id = $data\n";
+ return parent::write($id, $data);
+ }
+ public function close() {
+ $id = session_id();
+ echo "(#$this->num) closing $id\n";
+ return parent::close();
+ }
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+// implicit close
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : implicit shutdown ***
+(#1) constructor called
+done
+(#1) writing %s = foo|s:3:"bar";
+(#1) closing %s
+(#1) destructor called
diff --git a/ext/session/tests/session_set_save_handler_class_010.phpt b/ext/session/tests/session_set_save_handler_class_010.phpt
new file mode 100644
index 0000000000..02304f4974
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_010.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Test session_set_save_handler() : manual shutdown function
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : manual shutdown function ***\n";
+
+class MySession extends SessionHandler {
+ public $num;
+ public function __construct($num) {
+ $this->num = $num;
+ echo "(#$this->num) constructor called\n";
+ }
+ public function __destruct() {
+ echo "(#$this->num) destructor called\n";
+ }
+ public function finish() {
+ $id = session_id();
+ echo "(#$this->num) finish called $id\n";
+ session_write_close();
+ }
+ public function write($id, $data) {
+ echo "(#$this->num) writing $id = $data\n";
+ return parent::write($id, $data);
+ }
+ public function close() {
+ $id = session_id();
+ echo "(#$this->num) closing $id\n";
+ return parent::close();
+ }
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler, false);
+register_shutdown_function(array($handler, 'finish'));
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : manual shutdown function ***
+(#1) constructor called
+done
+(#1) finish called %s
+(#1) writing %s = foo|s:3:"bar";
+(#1) closing %s
+(#1) destructor called
diff --git a/ext/session/tests/session_set_save_handler_class_011.phpt b/ext/session/tests/session_set_save_handler_class_011.phpt
new file mode 100644
index 0000000000..7fa3657694
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_011.phpt
@@ -0,0 +1,66 @@
+--TEST--
+Test session_set_save_handler() : shutdown failure
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : shutdown failure ***\n";
+
+class MySession extends SessionHandler {
+ public $num;
+ public $destroyed = false;
+ public function __construct($num) {
+ $this->num = $num;
+ echo "(#$this->num) constructor called\n";
+ }
+ public function __destruct() {
+ echo "(#$this->num) destructor called\n";
+ $this->destroyed = true;
+ }
+ public function write($id, $data) {
+ if ($this->destroyed) {
+ echo "(#$this->num) destroyed, cannot write\n";
+ } else {
+ echo "(#$this->num) writing $id = $data\n";
+ }
+ return parent::write($id, $data);
+ }
+ public function close() {
+ $id = session_id();
+ if ($this->destroyed) {
+ echo "(#$this->num) destroyed, cannot write\n";
+ } else {
+ echo "(#$this->num) closing $id\n";
+ }
+ return parent::close();
+ }
+}
+
+$handler = new MySession(1);
+session_set_save_handler($handler, false);
+session_start();
+
+$_SESSION['foo'] = 'bar';
+
+echo "done\n";
+ob_end_flush();
+?>
+--EXPECTF--
+*** Testing session_set_save_handler() : shutdown failure ***
+(#1) constructor called
+done
+(#1) destructor called
+(#1) destroyed, cannot write
+(#1) destroyed, cannot write
diff --git a/ext/session/tests/session_set_save_handler_class_012.phpt b/ext/session/tests/session_set_save_handler_class_012.phpt
new file mode 100644
index 0000000000..706ef793ef
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_012.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Test session_set_save_handler() : incorrect arguments for existing handler open
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : incorrect arguments for existing handler open ***\n";
+
+class MySession extends SessionHandler {
+ public $i = 0;
+ public function open($path, $name) {
+ ++$this->i;
+ echo 'Open ', session_id(), "\n";
+ return parent::open();
+ }
+ public function read($key) {
+ ++$this->i;
+ echo 'Read ', session_id(), "\n";
+ return parent::read($key);
+ }
+}
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new MySession;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : incorrect arguments for existing handler open ***
+Open
+
+Warning: SessionHandler::open() expects exactly 2 parameters, 0 given in %s on line %d
+Read %s
+
+Warning: SessionHandler::read(): Parent session handler is not open in %s on line %d
+string(%d) "%s"
+string(5) "files"
+string(4) "user"
+int(2)
+array(0) {
+}
+
+Warning: Unknown: Parent session handler is not open in Unknown on line 0
+
+Warning: Unknown: Parent session handler is not open in Unknown on line 0
diff --git a/ext/session/tests/session_set_save_handler_class_013.phpt b/ext/session/tests/session_set_save_handler_class_013.phpt
new file mode 100644
index 0000000000..f536aa72ac
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_013.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Test session_set_save_handler() : incorrect arguments for existing handler close
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : incorrect arguments for existing handler close ***\n";
+
+class MySession extends SessionHandler {
+ public $i = 0;
+ public function open($path, $name) {
+ ++$this->i;
+ echo 'Open ', session_id(), "\n";
+ return parent::open($path, $name);
+ }
+ public function read($key) {
+ ++$this->i;
+ echo 'Read ', session_id(), "\n";
+ return parent::read($key);
+ }
+ public function close() {
+ return parent::close(false);
+ }
+}
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new MySession;
+session_set_save_handler($handler);
+session_start();
+
+var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : incorrect arguments for existing handler close ***
+Open
+Read %s
+string(%d) "%s"
+string(5) "files"
+string(4) "user"
+int(2)
+array(0) {
+}
+
+Warning: SessionHandler::close() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/session/tests/session_set_save_handler_class_014.phpt b/ext/session/tests/session_set_save_handler_class_014.phpt
new file mode 100644
index 0000000000..ea62beb0ff
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_014.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test session_set_save_handler() : calling default handler when save_handler=user
+--INI--
+session.save_handler=user
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : calling default handler when save_handler=user ***\n";
+
+$oldHandler = ini_get('session.save_handler');
+$handler = new SessionHandler;
+session_set_save_handler($handler);
+
+session_start();
+
+--EXPECTF--
+*** Testing session_set_save_handler() : calling default handler when save_handler=user ***
+
+Fatal error: SessionHandler::open(): Cannot call default session handler in %s on line %d
diff --git a/ext/session/tests/session_set_save_handler_class_015.phpt b/ext/session/tests/session_set_save_handler_class_015.phpt
new file mode 100644
index 0000000000..3bef51be4f
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_class_015.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test session_set_save_handler() : register session handler but don't start
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandler $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() : register session handler but don't start ***\n";
+
+session_set_save_handler(new SessionHandler);
+
+--EXPECTF--
+*** Testing session_set_save_handler() : register session handler but don't start ***
diff --git a/ext/session/tests/session_set_save_handler_iface_001.phpt b/ext/session/tests/session_set_save_handler_iface_001.phpt
new file mode 100644
index 0000000000..39a4b9975b
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_iface_001.phpt
@@ -0,0 +1,113 @@
+--TEST--
+Test session_set_save_handler() function: interface
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandlerInterface $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() function: interface ***\n";
+
+class MySession2 implements SessionHandlerInterface {
+ public $path;
+
+ public function open($path, $name) {
+ if (!$path) {
+ $path = sys_get_temp_dir();
+ }
+ $this->path = $path . '/u_sess_' . $name;
+ return true;
+ }
+
+ public function close() {
+ return true;
+ }
+
+ public function read($id) {
+ return @file_get_contents($this->path . $id);
+ }
+
+ public function write($id, $data) {
+ return file_put_contents($this->path . $id, $data);
+ }
+
+ public function destroy($id) {
+ @unlink($this->path . $id);
+ }
+
+ public function gc($maxlifetime) {
+ foreach (glob($this->path . '*') as $filename) {
+ if (filemtime($filename) + $maxlifetime < time()) {
+ @unlink($filename);
+ }
+ }
+ return true;
+ }
+}
+
+$handler = new MySession2;
+session_set_save_handler(array($handler, 'open'), array($handler, 'close'),
+ array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc'));
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+session_set_save_handler($handler);
+session_start();
+
+$_SESSION['foo'] = "hello";
+
+var_dump(session_id(), ini_get('session.save_handler'), $_SESSION);
+
+session_write_close();
+session_unset();
+
+session_start();
+var_dump($_SESSION);
+
+session_write_close();
+session_unset();
+
+--EXPECTF--
+*** Testing session_set_save_handler() function: interface ***
+string(%d) "%s"
+string(4) "user"
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+string(%d) "%s"
+string(4) "user"
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
+array(1) {
+ ["foo"]=>
+ string(5) "hello"
+}
diff --git a/ext/session/tests/session_set_save_handler_iface_002.phpt b/ext/session/tests/session_set_save_handler_iface_002.phpt
new file mode 100644
index 0000000000..40c9ac6825
--- /dev/null
+++ b/ext/session/tests/session_set_save_handler_iface_002.phpt
@@ -0,0 +1,90 @@
+--TEST--
+Test session_set_save_handler() function: interface wrong
+--INI--
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+/*
+ * Prototype : bool session_set_save_handler(SessionHandlerInterface $handler [, bool $register_shutdown_function = true])
+ * Description : Sets user-level session storage functions
+ * Source code : ext/session/session.c
+ */
+
+echo "*** Testing session_set_save_handler() function: interface wrong ***\n";
+
+interface MySessionHandlerInterface {
+ public function open($path, $name);
+ public function close();
+ public function read($id);
+ public function write($id, $data);
+ public function destroy($id);
+ public function gc($maxlifetime);
+}
+
+class MySession2 implements MySessionHandlerInterface {
+ public $path;
+
+ public function open($path, $name) {
+ if (!$path) {
+ $path = sys_get_temp_dir();
+ }
+ $this->path = $path . '/u_sess_' . $name;
+ return true;
+ }
+
+ public function close() {
+ return true;
+ }
+
+ public function read($id) {
+ return @file_get_contents($this->path . $id);
+ }
+
+ public function write($id, $data) {
+ echo "Unsupported session handler in use\n";
+ }
+
+ public function destroy($id) {
+ @unlink($this->path . $id);
+ }
+
+ public function gc($maxlifetime) {
+ foreach (glob($this->path . '*') as $filename) {
+ if (filemtime($filename) + $maxlifetime < time()) {
+ @unlink($filename);
+ }
+ }
+ return true;
+ }
+}
+
+function good_write($id, $data) {
+ global $handler;
+ echo "good handler writing\n";
+ return file_put_contents($handler->path . $id, $data);
+}
+
+$handler = new MySession2;
+
+$ret = session_set_save_handler(array($handler, 'open'), array($handler, 'close'),
+ array($handler, 'read'), 'good_write', array($handler, 'destroy'), array($handler, 'gc'));
+
+var_dump($ret);
+$ret = session_set_save_handler($handler);
+var_dump($ret);
+
+session_start();
+
+--EXPECTF--
+*** Testing session_set_save_handler() function: interface wrong ***
+bool(true)
+
+Warning: session_set_save_handler() expects parameter 1 to be SessionHandlerInterface, object given in %s
+bool(false)
+good handler writing
diff --git a/ext/session/tests/session_status.phpt b/ext/session/tests/session_status.phpt
new file mode 100644
index 0000000000..d1f7e2f386
--- /dev/null
+++ b/ext/session/tests/session_status.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test session_status() function : active, none
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ob_start();
+
+echo "*** Testing session_status() : active, none\n";
+
+var_dump(PHP_SESSION_NONE != PHP_SESSION_ACTIVE);
+var_dump(session_status() == PHP_SESSION_NONE);
+
+session_start();
+
+var_dump(session_status() == PHP_SESSION_ACTIVE);
+
+?>
+--EXPECTF--
+*** Testing session_status() : active, none
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/session/tests/session_status_disabled.phpt b/ext/session/tests/session_status_disabled.phpt
new file mode 100644
index 0000000000..24e0ecd7bf
--- /dev/null
+++ b/ext/session/tests/session_status_disabled.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test session_status() function : disabled
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--INI--
+session.save_handler=non-existant
+--FILE--
+<?php
+
+echo "*** Testing session_status() : disabled\n";
+
+var_dump(session_status() == PHP_SESSION_DISABLED);
+
+?>
+--EXPECTF--
+*** Testing session_status() : disabled
+bool(true)
diff --git a/ext/session/tests/session_unregister_basic.phpt b/ext/session/tests/session_unregister_basic.phpt
deleted file mode 100644
index 15ebb7dd21..0000000000
--- a/ext/session/tests/session_unregister_basic.phpt
+++ /dev/null
@@ -1,225 +0,0 @@
---TEST--
-Test session_unregister() function : basic functionality
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_unregister(string $name)
- * Description : Unregister a global variable from the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_unregister() : basic functionality ***\n";
-
-// Get an unset variable
-$unset_var = 10;
-unset($unset_var);
-
-class classA
-{
- public function __toString() {
- return "Hello World!";
- }
-}
-
-$heredoc = <<<EOT
-Hello World!
-EOT;
-
-$fp = fopen(__FILE__, "r");
-
-// Unexpected values to be passed as arguments
-$inputs = array(
-
- // Integer data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // Float data
-/*5*/ 10.5,
- -10.5,
- 12.3456789000e10,
- 12.3456789000E-10,
- .5,
-
- // Null data
-/*10*/ NULL,
- null,
-
- // Boolean data
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // Empty strings
-/*16*/ "",
- '',
-
- // Invalid string data
-/*18*/ "Nothing",
- 'Nothing',
- $heredoc,
-
- // Object data
-/*21*/ new classA(),
-
- // Undefined data
-/*22*/ @$undefined_var,
-
- // Unset data
-/*23*/ @$unset_var,
-
- // Resource variable
-/*24*/ $fp
-);
-
-
-var_dump(session_start());
-
-$iterator = 1;
-foreach($inputs as $input) {
- echo "\n-- Iteration $iterator --\n";
- var_dump(session_unregister($input));
- $iterator++;
-};
-
-var_dump(session_destroy());
-
-fclose($fp);
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_unregister() : basic functionality ***
-bool(true)
-
--- Iteration 1 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 2 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 3 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 4 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 5 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 6 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 7 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 8 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 9 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 10 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 11 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 12 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 13 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 14 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 15 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 16 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 17 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 18 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 19 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 20 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 21 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 22 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 23 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-
--- Iteration 24 --
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-
-Warning: session_unregister() expects parameter 1 to be string, resource given in %s on line %d
-NULL
-bool(true)
-Done
diff --git a/ext/session/tests/session_unregister_variation1.phpt b/ext/session/tests/session_unregister_variation1.phpt
deleted file mode 100644
index 609a05163f..0000000000
--- a/ext/session/tests/session_unregister_variation1.phpt
+++ /dev/null
@@ -1,159 +0,0 @@
---TEST--
-Test session_unregister() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_unregister(string $name)
- * Description : Unregister a global variable from the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_unregister() : variation ***\n";
-
-// Get an unset variable
-$unset_var = 10;
-unset($unset_var);
-
-class classA
-{
- public function __toString() {
- return "Hello World!";
- }
-}
-
-$heredoc = <<<EOT
-Hello World!
-EOT;
-
-$fp = fopen(__FILE__, "r");
-
-// Unexpected values to be passed as arguments
-$inputs = array(
-
- // Integer data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // Float data
-/*5*/ 10.5,
- -10.5,
- 12.3456789000e10,
- 12.3456789000E-10,
- .5,
-
- // Null data
-/*10*/ NULL,
- null,
-
- // Boolean data
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // Empty strings
-/*16*/ "",
- '',
-
- // Invalid string data
-/*18*/ "Nothing",
- 'Nothing',
- $heredoc,
-
- // Object data
-/*21*/ new classA(),
-
- // Undefined data
-/*22*/ @$undefined_var,
-
- // Unset data
-/*23*/ @$unset_var,
-
- // Resource variable
-/*24*/ $fp
-);
-
-var_dump(session_start());
-var_dump($_SESSION);
-var_dump(session_register($inputs));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-fclose($fp);
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_unregister() : variation ***
-bool(true)
-array(0) {
-}
-
-Deprecated: Function session_register() is deprecated in %s on line %d
-bool(true)
-array(13) {
- ["0"]=>
- NULL
- ["1"]=>
- NULL
- ["12345"]=>
- NULL
- ["-2345"]=>
- NULL
- ["10.5"]=>
- NULL
- ["-10.5"]=>
- NULL
- ["123456789000"]=>
- NULL
- ["1.23456789E-9"]=>
- NULL
- ["0.5"]=>
- NULL
- [""]=>
- NULL
- ["Nothing"]=>
- NULL
- ["Hello World!"]=>
- NULL
- ["Resource id #%d"]=>
- NULL
-}
-bool(true)
-array(13) {
- ["0"]=>
- NULL
- ["1"]=>
- NULL
- ["12345"]=>
- NULL
- ["-2345"]=>
- NULL
- ["10.5"]=>
- NULL
- ["-10.5"]=>
- NULL
- ["123456789000"]=>
- NULL
- ["1.23456789E-9"]=>
- NULL
- ["0.5"]=>
- NULL
- [""]=>
- NULL
- ["Nothing"]=>
- NULL
- ["Hello World!"]=>
- NULL
- ["Resource id #%d"]=>
- NULL
-}
-Done
diff --git a/ext/session/tests/session_unregister_variation2.phpt b/ext/session/tests/session_unregister_variation2.phpt
deleted file mode 100644
index 19cf4d5e61..0000000000
--- a/ext/session/tests/session_unregister_variation2.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-Test session_unregister() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_unregister(string $name)
- * Description : Unregister a global variable from the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_unregister() : variation ***\n";
-
-var_dump(session_start());
-var_dump($_SESSION);
-$_SESSION["foo"] = "Hello World!";
-var_dump($_SESSION);
-var_dump(session_unregister("foo"));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_unregister() : variation ***
-bool(true)
-array(0) {
-}
-array(1) {
- ["foo"]=>
- string(12) "Hello World!"
-}
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-array(0) {
-}
-bool(true)
-array(0) {
-}
-Done
diff --git a/ext/session/tests/session_unregister_variation3.phpt b/ext/session/tests/session_unregister_variation3.phpt
deleted file mode 100644
index 7933b08788..0000000000
--- a/ext/session/tests/session_unregister_variation3.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-Test session_unregister() function : variation
---SKIPIF--
-<?php include('skipif.inc'); ?>
---FILE--
-<?php
-
-ob_start();
-
-/*
- * Prototype : bool session_unregister(string $name)
- * Description : Unregister a global variable from the current session
- * Source code : ext/session/session.c
- */
-
-echo "*** Testing session_unregister() : variation ***\n";
-
-var_dump(session_start());
-var_dump($_SESSION);
-$blah = "Hello World!";
-$_SESSION["foo"] = &$blah;
-var_dump($_SESSION);
-var_dump(session_unregister("foo"));
-var_dump($_SESSION);
-var_dump(session_destroy());
-var_dump($_SESSION);
-
-echo "Done";
-ob_end_flush();
-?>
---EXPECTF--
-*** Testing session_unregister() : variation ***
-bool(true)
-array(0) {
-}
-array(1) {
- ["foo"]=>
- &string(12) "Hello World!"
-}
-
-Deprecated: Function session_unregister() is deprecated in %s on line %d
-bool(true)
-array(0) {
-}
-bool(true)
-array(0) {
-}
-Done
diff --git a/ext/session/tests/sessionhandler_open_001.phpt b/ext/session/tests/sessionhandler_open_001.phpt
new file mode 100644
index 0000000000..6ade9e00a5
--- /dev/null
+++ b/ext/session/tests/sessionhandler_open_001.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Testing repated SessionHandler::open() calls
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+
+ini_set('session.save_handler', 'files');
+$x = new SessionHandler;
+$x->open('','');
+$x->open('','');
+$x->open('','');
+$x->open('','');
+
+print "Done!\n";
+
+?>
+--EXPECTF--
+Done!
diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c
index d5c48764fc..17665bed85 100644
--- a/ext/shmop/shmop.c
+++ b/ext/shmop/shmop.c
@@ -226,7 +226,7 @@ PHP_FUNCTION(shmop_open)
shmop->size = shm.shm_segsz;
- rsid = zend_list_insert(shmop, shm_type);
+ rsid = zend_list_insert(shmop, shm_type TSRMLS_CC);
RETURN_LONG(rsid);
err:
efree(shmop);
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 236859686f..5514f0fc89 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -389,7 +389,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements,
/* {{{ sxe_property_read()
*/
-static zval * sxe_property_read(zval *object, zval *member, int type TSRMLS_DC)
+static zval * sxe_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
return sxe_prop_dim_read(object, member, 1, 0, type TSRMLS_CC);
}
@@ -680,7 +680,7 @@ next_iter:
/* {{{ sxe_property_write()
*/
-static void sxe_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
+static void sxe_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
sxe_prop_dim_write(object, member, value, 1, 0, NULL TSRMLS_CC);
}
@@ -694,7 +694,7 @@ static void sxe_dimension_write(zval *object, zval *offset, zval *value TSRMLS_D
}
/* }}} */
-static zval** sxe_property_get_adr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval** sxe_property_get_adr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
php_sxe_object *sxe;
xmlNodePtr node;
@@ -846,7 +846,7 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
/* {{{ sxe_property_exists()
*/
-static int sxe_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
+static int sxe_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
{
return sxe_prop_dim_exists(object, member, check_empty, 1, 0 TSRMLS_CC);
}
@@ -971,7 +971,7 @@ next_iter:
/* {{{ sxe_property_delete()
*/
-static void sxe_property_delete(zval *object, zval *member TSRMLS_DC)
+static void sxe_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
{
sxe_prop_dim_delete(object, member, 1, 0 TSRMLS_CC);
}
@@ -1069,6 +1069,10 @@ static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{
xmlAttrPtr attr;
int namelen;
int test;
+ char use_iter;
+ zval *iter_data;
+
+ use_iter = 0;
sxe = php_sxe_fetch_object(object TSRMLS_CC);
@@ -1122,6 +1126,7 @@ static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{
GET_NODE(sxe, node);
node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
+
if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
if (node->type == XML_ATTRIBUTE_NODE) {
MAKE_STD_ZVAL(value);
@@ -1129,7 +1134,17 @@ static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{
zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
node = NULL;
} else if (sxe->iter.type != SXE_ITER_CHILD) {
- node = node->children;
+
+ if ( !node->children || !node->parent || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
+ node = node->children;
+ } else {
+ iter_data = sxe->iter.data;
+ sxe->iter.data = NULL;
+
+ node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
+
+ use_iter = 1;
+ }
}
while (node) {
@@ -1161,12 +1176,27 @@ static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{
_get_base_node_value(sxe, node, &value, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
- sxe_properties_add(rv, name, namelen, value TSRMLS_CC);
+ if ( use_iter ) {
+ zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
+ } else {
+ sxe_properties_add(rv, name, namelen, value TSRMLS_CC);
+ }
next_iter:
- node = node->next;
+ if ( use_iter ) {
+ node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC);
+ } else {
+ node = node->next;
+ }
}
}
+ if ( use_iter ) {
+ if (sxe->iter.data) {
+ zval_ptr_dtor(&sxe->iter.data);
+ }
+ sxe->iter.data = iter_data;
+ }
+
return rv;
}
/* }}} */
@@ -1335,7 +1365,7 @@ SXE_METHOD(asXML)
}
if (ZEND_NUM_ARGS() == 1) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
RETURN_FALSE;
}
@@ -1487,22 +1517,28 @@ static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node,
}
/* }}} */
-/* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive])
+/* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive [, bool from_root])
Return all namespaces registered with document */
SXE_METHOD(getDocNamespaces)
{
- zend_bool recursive = 0;
+ zend_bool recursive = 0, from_root = 1;
php_sxe_object *sxe;
+ xmlNodePtr node;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &recursive, &from_root) == FAILURE) {
return;
}
array_init(return_value);
sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
+ if(from_root){
+ node = xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr);
+ }else{
+ GET_NODE(sxe, node);
+ }
- sxe_add_registered_namespaces(sxe, xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr), recursive, return_value TSRMLS_CC);
+ sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
}
/* }}} */
@@ -2122,7 +2158,7 @@ PHP_FUNCTION(simplexml_load_file)
zend_class_entry *ce= sxe_class_entry;
zend_bool isprefix = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C!lsb", &filename, &filename_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|C!lsb", &filename, &filename_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
return;
}
@@ -2492,6 +2528,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getnamespaces, 0, 0, 0)
ZEND_ARG_INFO(0, recursve)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getdocnamespaces, 0, 0, 0)
+ ZEND_ARG_INFO(0, recursve)
+ ZEND_ARG_INFO(0, from_root)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_children, 0, 0, 0)
ZEND_ARG_INFO(0, ns)
ZEND_ARG_INFO(0, is_prefix)
@@ -2560,7 +2601,7 @@ static const zend_function_entry sxe_functions[] = { /* {{{ */
SXE_ME(attributes, arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
SXE_ME(children, arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
SXE_ME(getNamespaces, arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
- SXE_ME(getDocNamespaces, arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
+ SXE_ME(getDocNamespaces, arginfo_simplexmlelement_getdocnamespaces, ZEND_ACC_PUBLIC)
SXE_ME(getName, arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
SXE_ME(addChild, arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
SXE_ME(addAttribute, arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
diff --git a/ext/simplexml/tests/034.phpt b/ext/simplexml/tests/034.phpt
index 1f3a854fde..8610f70367 100644
--- a/ext/simplexml/tests/034.phpt
+++ b/ext/simplexml/tests/034.phpt
@@ -1,7 +1,7 @@
--TEST--
-SimpleXML: array casting bug
---XFAIL--
-Does anyone know why?
+SimpleXML: cast to array
+--FAIL--
+Length of cast array does not match expected length
--SKIPIF--
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
--FILE--
diff --git a/ext/simplexml/tests/bug48601.phpt b/ext/simplexml/tests/bug48601.phpt
index 24bf2bf8a5..0b81facf49 100644
--- a/ext/simplexml/tests/bug48601.phpt
+++ b/ext/simplexml/tests/bug48601.phpt
@@ -10,7 +10,7 @@ $sxe = simplexml_load_string('<root><node1>1</node1></root>');
$nodes = $sxe->xpath("/root/node2/@test");
if (! is_array($nodes)) {
- echo "An error occured\n";
+ echo "An error occurred\n";
} else {
echo "Result Count: " . count($nodes) . "\n";
}
diff --git a/ext/simplexml/tests/bug51615.phpt b/ext/simplexml/tests/bug51615.phpt
index 94c7b20c4d..c96b3ae7ca 100644
--- a/ext/simplexml/tests/bug51615.phpt
+++ b/ext/simplexml/tests/bug51615.phpt
@@ -22,7 +22,7 @@ foreach ($html->body->span as $obj) {
Warning: DOMDocument::loadHTML(): error parsing attribute name in Entity, line: 1 in %s on line %d
Warning: DOMDocument::loadHTML(): error parsing attribute name in Entity, line: 1 in %s on line %d
-object(SimpleXMLElement)#%d (2) {
+object(SimpleXMLElement)#%d (3) {
["@attributes"]=>
array(2) {
["title"]=>
@@ -32,6 +32,8 @@ object(SimpleXMLElement)#%d (2) {
}
[0]=>
string(1) "x"
+ [1]=>
+ string(1) "x"
}
string(0) ""
string(0) ""
diff --git a/ext/simplexml/tests/feature55218.phpt b/ext/simplexml/tests/feature55218.phpt
new file mode 100644
index 0000000000..25ea534376
--- /dev/null
+++ b/ext/simplexml/tests/feature55218.phpt
@@ -0,0 +1,117 @@
+--TEST--
+Bug #55218 getDocNamespaces from current element and not root
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) print "skip SimpleXML not present";
+if (!extension_loaded("libxml")) print "skip LibXML not present";
+?>
+--FILE--
+<?php
+
+$x = new SimpleXMLElement(
+'<?xml version="1.0" standalone="yes"?>
+<people xmlns:p="http://example.org/p" >
+ <person id="1" xmlns:t="http://example.org/t" >
+ <t:name>John Doe</t:name>
+ </person>
+ <person id="2">Susie Q. Public</person>
+ <o>
+ <p:div>jdslkfjsldk jskdfjsmlkjfkldjkjflskj kljfslkjf sldk</p:div>
+ </o>
+</people>');
+
+echo "getDocNamespaces\n";
+echo "\nBackwards Compatibility:\n";
+echo "recursion:\n";
+
+var_dump ( $x->getDocNamespaces(true) ) ;
+var_dump( $x->person[0]->getDocNamespaces(true) );
+var_dump( $x->person[1]->getDocNamespaces(true) );
+
+echo "\nnon recursive:\n";
+
+var_dump( $x->getDocNamespaces(false) );
+var_dump( $x->person[0]->getDocNamespaces(false) );
+var_dump( $x->person[1]->getDocNamespaces(false) );
+
+echo "\n\nUsing new 'from_root' bool set to false:\n";
+echo "recursion:\n";
+
+var_dump ( $x->getDocNamespaces(true, false) ) ;
+var_dump( $x->person[0]->getDocNamespaces(true, false) );
+var_dump( $x->person[1]->getDocNamespaces(true, false) );
+
+echo "\nnon recursive:\n";
+
+var_dump( $x->getDocNamespaces(false, false) );
+var_dump( $x->person[0]->getDocNamespaces(false, false) );
+var_dump( $x->person[1]->getDocNamespaces(false, false) );
+
+?>
+===DONE===
+--EXPECTF--
+getDocNamespaces
+
+Backwards Compatibility:
+recursion:
+array(2) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+ ["t"]=>
+ string(20) "http://example.org/t"
+}
+array(2) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+ ["t"]=>
+ string(20) "http://example.org/t"
+}
+array(2) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+ ["t"]=>
+ string(20) "http://example.org/t"
+}
+
+non recursive:
+array(1) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+}
+array(1) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+}
+array(1) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+}
+
+
+Using new 'from_root' bool set to false:
+recursion:
+array(2) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+ ["t"]=>
+ string(20) "http://example.org/t"
+}
+array(1) {
+ ["t"]=>
+ string(20) "http://example.org/t"
+}
+array(0) {
+}
+
+non recursive:
+array(1) {
+ ["p"]=>
+ string(20) "http://example.org/p"
+}
+array(1) {
+ ["t"]=>
+ string(20) "http://example.org/t"
+}
+array(0) {
+}
+===DONE=== \ No newline at end of file
diff --git a/ext/snmp/CREDITS b/ext/snmp/CREDITS
index 2ff38dbe6d..2835d745fb 100644
--- a/ext/snmp/CREDITS
+++ b/ext/snmp/CREDITS
@@ -1,2 +1,2 @@
SNMP
-Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne
+Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne, Boris Lytochkin
diff --git a/ext/snmp/config.m4 b/ext/snmp/config.m4
index d24d54b122..ccb7eea9a7 100644
--- a/ext/snmp/config.m4
+++ b/ext/snmp/config.m4
@@ -8,14 +8,8 @@ PHP_ARG_WITH(snmp,for SNMP support,
PHP_ARG_WITH(openssl-dir,OpenSSL dir for SNMP,
[ --with-openssl-dir[=DIR] SNMP: openssl install prefix], no, no)
-PHP_ARG_ENABLE(ucd-snmp-hack, whether to enable UCD SNMP hack,
-[ --enable-ucd-snmp-hack SNMP: Enable UCD SNMP hack], no, no)
-
if test "$PHP_SNMP" != "no"; then
- dnl
- dnl Try net-snmp first
- dnl
if test "$PHP_SNMP" = "yes"; then
AC_PATH_PROG(SNMP_CONFIG,net-snmp-config,,[/usr/local/bin:$PATH])
else
@@ -26,92 +20,27 @@ if test "$PHP_SNMP" != "no"; then
SNMP_LIBS=`$SNMP_CONFIG --netsnmp-libs`
SNMP_LIBS="$SNMP_LIBS `$SNMP_CONFIG --external-libs`"
SNMP_PREFIX=`$SNMP_CONFIG --prefix`
-
- if test -n "$SNMP_LIBS" && test -n "$SNMP_PREFIX"; then
- PHP_ADD_INCLUDE(${SNMP_PREFIX}/include)
- PHP_EVAL_LIBLINE($SNMP_LIBS, SNMP_SHARED_LIBADD)
- AC_DEFINE(HAVE_NET_SNMP,1,[ ])
- SNMP_LIBNAME=netsnmp
- else
- AC_MSG_ERROR([Could not find the required paths. Please check your net-snmp installation.])
- fi
- else
-
- dnl
- dnl Try ucd-snmp if net-snmp test failed
- dnl
-
- if test "$PHP_SNMP" = "yes"; then
- for i in /usr/include /usr/local/include; do
- test -f $i/snmp.h && SNMP_INCDIR=$i
- test -f $i/ucd-snmp/snmp.h && SNMP_INCDIR=$i/ucd-snmp
- test -f $i/snmp/snmp.h && SNMP_INCDIR=$i/snmp
- test -f $i/snmp/include/ucd-snmp/snmp.h && SNMP_INCDIR=$i/snmp/include/ucd-snmp
- done
- for i in /usr/$PHP_LIBDIR /usr/snmp/lib /usr/local/$PHP_LIBDIR /usr/local/lib /usr/local/snmp/lib; do
- test -f $i/libsnmp.a || test -f $i/libsnmp.$SHLIB_SUFFIX_NAME && SNMP_LIBDIR=$i
- done
- else
- SNMP_INCDIR=$PHP_SNMP/include
- test -d $PHP_SNMP/include/ucd-snmp && SNMP_INCDIR=$PHP_SNMP/include/ucd-snmp
- SNMP_LIBDIR=$PHP_SNMP/lib
- fi
-
- if test -z "$SNMP_INCDIR"; then
- AC_MSG_ERROR(snmp.h not found. Check your SNMP installation.)
- elif test -z "$SNMP_LIBDIR"; then
- AC_MSG_ERROR(libsnmp not found. Check your SNMP installation.)
- fi
-
- old_CPPFLAGS=$CPPFLAGS
- CPPFLAGS=-I$SNMP_INCDIR
- AC_CHECK_HEADERS(default_store.h)
- if test "$ac_cv_header_default_store_h" = "yes"; then
- AC_MSG_CHECKING(for OpenSSL support in SNMP libraries)
- AC_EGREP_CPP(yes,[
-#include <ucd-snmp-config.h>
-#if USE_OPENSSL
- yes
-#endif
- ],[
- SNMP_SSL=yes
- ],[
- SNMP_SSL=no
- ])
- fi
- CPPFLAGS=$old_CPPFLAGS
- AC_MSG_RESULT($SNMP_SSL)
-
- if test "$SNMP_SSL" = "yes"; then
- if test "$PHP_OPENSSL_DIR" != "no"; then
- PHP_OPENSSL=$PHP_OPENSSL_DIR
- fi
-
- if test "$PHP_OPENSSL" = "no"; then
- AC_MSG_ERROR([The UCD-SNMP in this system is built with SSL support.
-
- Add --with-openssl-dir=DIR to your configure line.])
+ snmp_full_version=`$SNMP_CONFIG --version`
+ ac_IFS=$IFS
+ IFS="."
+ set $snmp_full_version
+ IFS=$ac_IFS
+ SNMP_VERSION=`expr [$]1 \* 1000 + [$]2`
+ if test "$SNMP_VERSION" -ge "5003"; then
+ if test -n "$SNMP_LIBS" && test -n "$SNMP_PREFIX"; then
+ PHP_ADD_INCLUDE(${SNMP_PREFIX}/include)
+ PHP_EVAL_LIBLINE($SNMP_LIBS, SNMP_SHARED_LIBADD)
+ SNMP_LIBNAME=netsnmp
else
- PHP_SETUP_OPENSSL(SNMP_SHARED_LIBADD, [], [
- AC_MSG_ERROR([SNMP: OpenSSL check failed. Please check config.log for more information.])
- ])
+ AC_MSG_ERROR([Could not find the required paths. Please check your net-snmp installation.])
fi
+ else
+ AC_MSG_ERROR([Net-SNMP version 5.3 or greater reqired (detected $snmp_full_version).])
fi
-
- AC_CHECK_LIB(kstat, kstat_read, [ PHP_ADD_LIBRARY(kstat,,SNMP_SHARED_LIBADD) ])
- PHP_ADD_INCLUDE($SNMP_INCDIR)
- PHP_ADD_LIBRARY_WITH_PATH(snmp, $SNMP_LIBDIR, SNMP_SHARED_LIBADD)
- SNMP_LIBNAME=snmp
+ else
+ AC_MSG_ERROR([Could not find net-snmp-config binary. Please check your net-snmp installation.])
fi
- dnl Check whether snmp_parse_oid() exists.
- PHP_CHECK_LIBRARY($SNMP_LIBNAME, snmp_parse_oid,
- [
- AC_DEFINE(HAVE_SNMP_PARSE_OID, 1, [ ])
- ], [], [
- $SNMP_SHARED_LIBADD
- ])
-
dnl Test build.
PHP_CHECK_LIBRARY($SNMP_LIBNAME, init_snmp,
[
@@ -122,10 +51,75 @@ if test "$PHP_SNMP" != "no"; then
$SNMP_SHARED_LIBADD
])
- if test "$PHP_UCD_SNMP_HACK" = "yes" ; then
- AC_DEFINE(UCD_SNMP_HACK, 1, [ ])
+ dnl Check whether shutdown_snmp_logging() exists.
+ PHP_CHECK_LIBRARY($SNMP_LIBNAME, shutdown_snmp_logging,
+ [
+ AC_DEFINE(HAVE_SHUTDOWN_SNMP_LOGGING, 1, [ ])
+ ], [], [
+ $SNMP_SHARED_LIBADD
+ ])
+
+ dnl Check for buggy snmp_snprint_value() (net-snmp BUGid 2027834)
+ AC_CACHE_CHECK([for buggy snmp_snprint_value], ac_cv_buggy_snprint_value,[
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -I${SNMP_PREFIX}/include $SNMP_SHARED_LIBADD"
+ AC_TRY_RUN( [
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+u_char uname[] = "Linux nex1.php.net 2.6.18-194.32.1.el5 #1 SMP Wed Jan 5 17:53:09 EST 2011 i686";
+
+int main(int argc, char **argv)
+{
+ struct variable_list vars;
+ char buf1[2048];
+ char buf2[sizeof(buf1)];
+
+ memset(&(buf1[0]), 0, sizeof(buf1));
+ memset(&(buf2[0]), 0, sizeof(buf2));
+ memset(&vars, 0, sizeof(vars));
+ vars.type = 4;
+ vars.val.integer = (long *)&(uname[0]);
+ vars.val.string = &(uname[0]);
+ vars.val.bitstring = &(uname[0]);
+ vars.val.counter64 = (struct counter64 *)&(uname[0]);
+ vars.val.floatVal = (float *)&(uname[0]);
+ vars.val_len = sizeof(uname),
+ vars.name_loc[0] = 1;
+ vars.name_loc[1] = 3;
+ vars.name_loc[2] = 6;
+ vars.name_loc[3] = 1;
+ vars.name_loc[4] = 2;
+ vars.name_loc[5] = 1;
+ vars.name_loc[6] = 1;
+ vars.name_loc[7] = 1;
+ vars.name = (oid *)&(vars.name_loc);
+ vars.name_length = 9;
+
+ init_snmp("snmpapp");
+
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, 0);
+
+ snprint_value(buf1, (sizeof(uname) + 32), vars.name, vars.name_length, &vars);
+ snprint_value(buf2, sizeof(buf2), vars.name, vars.name_length, &vars);
+ exit((strncmp(buf1, buf2, sizeof(buf1)) != 0));
+}
+ ],[
+ ac_cv_buggy_snprint_value=no
+ ],[
+ ac_cv_buggy_snprint_value=yes
+ ],[
+ ac_cv_buggy_snprint_value=no
+ ])
+ CFLAGS="$save_CFLAGS"
+ ])
+ if test "$ac_cv_buggy_snprint_value" = "yes"; then
+ AC_DEFINE(BUGGY_SNMPRINT_VALUE, 1, [ ])
fi
-
+
PHP_NEW_EXTENSION(snmp, snmp.c, $ext_shared)
PHP_SUBST(SNMP_SHARED_LIBADD)
fi
diff --git a/ext/snmp/config.w32 b/ext/snmp/config.w32
index 59b6a8266b..24622434c9 100644
--- a/ext/snmp/config.w32
+++ b/ext/snmp/config.w32
@@ -10,9 +10,6 @@ if (PHP_SNMP != "no") {
CHECK_LIB("libeay32.lib", "snmp", PHP_SNMP)
AC_DEFINE('HAVE_SNMP', 1);
AC_DEFINE("HAVE_NET_SNMP", 1);
- } else if (CHECK_LIB("libsnmp.lib", "snmp", PHP_SNMP)) {
- EXTENSION('snmp', 'snmp.c');
- AC_DEFINE('HAVE_SNMP', 1);
} else {
WARNING("snmp not enabled; libraries and headers not found");
}
diff --git a/ext/snmp/php_snmp.h b/ext/snmp/php_snmp.h
index 71be5711af..fe37917c76 100644
--- a/ext/snmp/php_snmp.h
+++ b/ext/snmp/php_snmp.h
@@ -17,6 +17,7 @@
| Steven Lawrance <slawrance@technologist.com> |
| Harrie Hazewinkel <harrie@lisanza.net> |
| Johann Hanne <jonny@nurfuerspam.de> |
+ | Boris Lytockin <lytboris@gmail.com> |
+----------------------------------------------------------------------+
*/
@@ -25,6 +26,8 @@
#ifndef PHP_SNMP_H
#define PHP_SNMP_H
+#define PHP_SNMP_VERSION "0.1"
+
#if HAVE_SNMP
#ifndef DLEXPORT
@@ -38,6 +41,9 @@ extern zend_module_entry snmp_module_entry;
#include "TSRM.h"
#endif
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
PHP_MINIT_FUNCTION(snmp);
PHP_MSHUTDOWN_FUNCTION(snmp);
PHP_MINFO_FUNCTION(snmp);
@@ -46,11 +52,11 @@ PHP_FUNCTION(snmpget);
PHP_FUNCTION(snmpgetnext);
PHP_FUNCTION(snmpwalk);
PHP_FUNCTION(snmprealwalk);
+PHP_FUNCTION(snmpset);
PHP_FUNCTION(snmp_get_quick_print);
PHP_FUNCTION(snmp_set_quick_print);
PHP_FUNCTION(snmp_set_enum_print);
PHP_FUNCTION(snmp_set_oid_output_format);
-PHP_FUNCTION(snmpset);
PHP_FUNCTION(snmp2_get);
PHP_FUNCTION(snmp2_getnext);
@@ -69,9 +75,50 @@ PHP_FUNCTION(snmp_get_valueretrieval);
PHP_FUNCTION(snmp_read_mib);
+PHP_METHOD(SNMP, setSecurity);
+PHP_METHOD(SNMP, close);
+PHP_METHOD(SNMP, get);
+PHP_METHOD(SNMP, getnext);
+PHP_METHOD(SNMP, walk);
+PHP_METHOD(SNMP, set);
+PHP_METHOD(SNMP, getErrno);
+PHP_METHOD(SNMP, getError);
+
+typedef struct _php_snmp_object {
+ zend_object zo;
+ struct snmp_session *session;
+ int max_oids;
+ int valueretrieval;
+ int quick_print;
+ int enum_print;
+ int oid_output_format;
+ int snmp_errno;
+ int oid_increasing_check;
+ int exceptions_enabled;
+ char snmp_errstr[256];
+} php_snmp_object;
+
+
+typedef int (*php_snmp_read_t)(php_snmp_object *snmp_object, zval **retval TSRMLS_DC);
+typedef int (*php_snmp_write_t)(php_snmp_object *snmp_object, zval *newval TSRMLS_DC);
+
+typedef struct _ptp_snmp_prop_handler {
+ const char *name;
+ size_t name_length;
+ php_snmp_read_t read_func;
+ php_snmp_write_t write_func;
+} php_snmp_prop_handler;
+
+typedef struct _snmpobjarg {
+ char *oid;
+ char type;
+ char *value;
+ oid name[MAX_OID_LEN];
+ size_t name_length;
+} snmpobjarg;
ZEND_BEGIN_MODULE_GLOBALS(snmp)
- int valueretrieval;
+ int valueretrieval;
ZEND_END_MODULE_GLOBALS(snmp)
#ifdef ZTS
@@ -80,6 +127,9 @@ ZEND_END_MODULE_GLOBALS(snmp)
#define SNMP_G(v) (snmp_globals.v)
#endif
+#define REGISTER_SNMP_CLASS_CONST_LONG(const_name, value) \
+ zend_declare_class_constant_long(php_snmp_ce, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
+
#else
#define snmp_module_ptr NULL
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index ff5312b043..403c629559 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -17,6 +17,7 @@
| Steven Lawrance <slawrance@technologist.com> |
| Harrie Hazewinkel <harrie@lisanza.net> |
| Johann Hanne <jonny@nurfuerspam.de> |
+ | Boris Lytockin <lytboris@gmail.com> |
+----------------------------------------------------------------------+
*/
@@ -27,9 +28,16 @@
#endif
#include "php.h"
+#include "main/php_network.h"
#include "ext/standard/info.h"
#include "php_snmp.h"
+#include "zend_exceptions.h"
+
+#if HAVE_SPL
+#include "ext/spl/spl_exceptions.h"
+#endif
+
#if HAVE_SNMP
#include <sys/types.h>
@@ -69,42 +77,53 @@
#endif
#endif
-#ifdef HAVE_NET_SNMP
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
-#else
-#ifdef HAVE_DEFAULT_STORE_H
-#include "default_store.h"
-#endif
-#include "asn1.h"
-#include "snmp_api.h"
-#include "snmp_client.h"
-#include "snmp_impl.h"
-#include "snmp.h"
-#include "snmpv3.h"
-#include "keytools.h"
-#include "parse.h"
-#include "mib.h"
-#ifndef PHP_WIN32
-/* this doesn't appear to be needed under win32 (perhaps at all)
- * and the header file is not present in my UCD-SNMP headers */
-# include "version.h"
-#endif
-#include "transform_oids.h"
-#endif
-/* Ugly macro, since the length of OIDs in UCD-SNMP and NET-SNMP
- * is different and this way the code is not full of 'ifdef's.
- */
-#define OIDSIZE(p) (sizeof(p)/sizeof(oid))
-/* For really old ucd-snmp versions.. */
-#ifndef HAVE_SNMP_PARSE_OID
-#define snmp_parse_oid read_objid
+/* For net-snmp prior to 5.4 */
+#ifndef HAVE_SHUTDOWN_SNMP_LOGGING
+extern netsnmp_log_handler *logh_head;
+#define shutdown_snmp_logging() \
+ { \
+ snmp_disable_log(); \
+ while(NULL != logh_head) \
+ netsnmp_remove_loghandler( logh_head ); \
+ }
#endif
-#define SNMP_VALUE_LIBRARY 0
-#define SNMP_VALUE_PLAIN 1
-#define SNMP_VALUE_OBJECT 2
+#define SNMP_VALUE_LIBRARY (0 << 0)
+#define SNMP_VALUE_PLAIN (1 << 0)
+#define SNMP_VALUE_OBJECT (1 << 1)
+
+typedef struct snmp_session php_snmp_session;
+#define PHP_SNMP_SESSION_RES_NAME "SNMP session"
+
+#define PHP_SNMP_ADD_PROPERTIES(a, b) \
+{ \
+ int i = 0; \
+ while (b[i].name != NULL) { \
+ php_snmp_add_property((a), (b)[i].name, (b)[i].name_length, \
+ (php_snmp_read_t)(b)[i].read_func, (php_snmp_write_t)(b)[i].write_func TSRMLS_CC); \
+ i++; \
+ } \
+}
+
+#define PHP_SNMP_ERRNO_NOERROR 0
+#define PHP_SNMP_ERRNO_GENERIC (1 << 1)
+#define PHP_SNMP_ERRNO_TIMEOUT (1 << 2)
+#define PHP_SNMP_ERRNO_ERROR_IN_REPLY (1 << 3)
+#define PHP_SNMP_ERRNO_OID_NOT_INCREASING (1 << 4)
+#define PHP_SNMP_ERRNO_OID_PARSING_ERROR (1 << 5)
+#define PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES (1 << 6)
+#define PHP_SNMP_ERRNO_ANY ( \
+ PHP_SNMP_ERRNO_GENERIC | \
+ PHP_SNMP_ERRNO_TIMEOUT | \
+ PHP_SNMP_ERRNO_ERROR_IN_REPLY | \
+ PHP_SNMP_ERRNO_OID_NOT_INCREASING | \
+ PHP_SNMP_ERRNO_OID_PARSING_ERROR | \
+ PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES | \
+ PHP_SNMP_ERRNO_NOERROR \
+ )
ZEND_DECLARE_MODULE_GLOBALS(snmp)
static PHP_GINIT_FUNCTION(snmp);
@@ -112,7 +131,20 @@ static PHP_GINIT_FUNCTION(snmp);
/* constant - can be shared among threads */
static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
+static int le_snmp_session;
+
+/* Handlers */
+static zend_object_handlers php_snmp_object_handlers;
+
+/* Class entries */
+zend_class_entry *php_snmp_ce;
+zend_class_entry *php_snmp_exception_ce;
+
+/* Class object properties */
+static HashTable php_snmp_properties;
+
/* {{{ arginfo */
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpget, 0, 0, 3)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, community)
@@ -145,6 +177,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_snmprealwalk, 0, 0, 3)
ZEND_ARG_INFO(0, retries)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
+ ZEND_ARG_INFO(0, host)
+ ZEND_ARG_INFO(0, community)
+ ZEND_ARG_INFO(0, object_id)
+ ZEND_ARG_INFO(0, type)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, timeout)
+ ZEND_ARG_INFO(0, retries)
+ZEND_END_ARG_INFO()
+
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get_quick_print, 0, 0, 1)
ZEND_ARG_INFO(0, d)
ZEND_END_ARG_INFO()
@@ -153,7 +196,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_quick_print, 0, 0, 1)
ZEND_ARG_INFO(0, quick_print)
ZEND_END_ARG_INFO()
-#ifdef HAVE_NET_SNMP
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_enum_print, 0, 0, 1)
ZEND_ARG_INFO(0, enum_print)
ZEND_END_ARG_INFO()
@@ -161,17 +203,6 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set_oid_output_format, 0, 0, 1)
ZEND_ARG_INFO(0, oid_format)
ZEND_END_ARG_INFO()
-#endif
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_snmpset, 0, 0, 5)
- ZEND_ARG_INFO(0, host)
- ZEND_ARG_INFO(0, community)
- ZEND_ARG_INFO(0, object_id)
- ZEND_ARG_INFO(0, type)
- ZEND_ARG_INFO(0, value)
- ZEND_ARG_INFO(0, timeout)
- ZEND_ARG_INFO(0, retries)
-ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_get, 0, 0, 3)
ZEND_ARG_INFO(0, host)
@@ -215,11 +246,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp2_set, 0, 0, 5)
ZEND_ARG_INFO(0, retries)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_php_snmpv3, 0, 0, 2)
- ZEND_ARG_INFO(0, s)
- ZEND_ARG_INFO(0, st)
-ZEND_END_ARG_INFO()
-
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp3_get, 0, 0, 8)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, sec_name)
@@ -297,69 +323,115 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_read_mib, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
+
+/* OO arginfo */
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_create, 0, 0, 3)
+ ZEND_ARG_INFO(0, version)
+ ZEND_ARG_INFO(0, host)
+ ZEND_ARG_INFO(0, community)
+ ZEND_ARG_INFO(0, timeout)
+ ZEND_ARG_INFO(0, retries)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_snmp_void, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_setSecurity, 0, 0, 8)
+ ZEND_ARG_INFO(0, session)
+ ZEND_ARG_INFO(0, sec_level)
+ ZEND_ARG_INFO(0, auth_protocol)
+ ZEND_ARG_INFO(0, auth_passphrase)
+ ZEND_ARG_INFO(0, priv_protocol)
+ ZEND_ARG_INFO(0, priv_passphrase)
+ ZEND_ARG_INFO(0, contextName)
+ ZEND_ARG_INFO(0, contextEngineID)
+ ZEND_ARG_INFO(0, )
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_get, 0, 0, 1)
+ ZEND_ARG_INFO(0, object_id)
+ ZEND_ARG_INFO(0, use_orignames)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_walk, 0, 0, 4)
+ ZEND_ARG_INFO(0, object_id)
+ ZEND_ARG_INFO(0, suffix_keys)
+ ZEND_ARG_INFO(0, max_repetitions)
+ ZEND_ARG_INFO(0, non_repeaters)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_set, 0, 0, 3)
+ ZEND_ARG_INFO(0, object_id)
+ ZEND_ARG_INFO(0, type)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_snmp_class_set_quick_print, 0, 0, 1)
+ ZEND_ARG_INFO(0, quick_print)
+ZEND_END_ARG_INFO()
/* }}} */
+struct objid_query {
+ int count;
+ int offset;
+ int step;
+ long non_repeaters;
+ long max_repetitions;
+ int valueretrieval;
+ int array_output;
+ int oid_increasing_check;
+ snmpobjarg *vars;
+};
+
/* {{{ snmp_functions[]
*/
const zend_function_entry snmp_functions[] = {
- PHP_FE(snmpget, arginfo_snmpget)
- PHP_FE(snmpgetnext, arginfo_snmpgetnext)
- PHP_FE(snmpwalk, arginfo_snmpwalk)
- PHP_FE(snmprealwalk, arginfo_snmprealwalk)
- PHP_FALIAS(snmpwalkoid, snmprealwalk, arginfo_snmprealwalk)
+ PHP_FE(snmpget, arginfo_snmpget)
+ PHP_FE(snmpgetnext, arginfo_snmpgetnext)
+ PHP_FE(snmpwalk, arginfo_snmpwalk)
+ PHP_FE(snmprealwalk, arginfo_snmprealwalk)
+ PHP_FALIAS(snmpwalkoid, snmprealwalk, arginfo_snmprealwalk)
+ PHP_FE(snmpset, arginfo_snmpset)
PHP_FE(snmp_get_quick_print, arginfo_snmp_get_quick_print)
PHP_FE(snmp_set_quick_print, arginfo_snmp_set_quick_print)
-#ifdef HAVE_NET_SNMP
PHP_FE(snmp_set_enum_print, arginfo_snmp_set_enum_print)
PHP_FE(snmp_set_oid_output_format, arginfo_snmp_set_oid_output_format)
PHP_FALIAS(snmp_set_oid_numeric_print, snmp_set_oid_output_format, arginfo_snmp_set_oid_output_format)
-#endif
- PHP_FE(snmpset, arginfo_snmpset)
PHP_FE(snmp2_get, arginfo_snmp2_get)
- PHP_FE(snmp2_getnext, arginfo_snmp2_getnext)
+ PHP_FE(snmp2_getnext, arginfo_snmp2_getnext)
PHP_FE(snmp2_walk, arginfo_snmp2_walk)
- PHP_FE(snmp2_real_walk, arginfo_snmp2_real_walk)
+ PHP_FE(snmp2_real_walk, arginfo_snmp2_real_walk)
PHP_FE(snmp2_set, arginfo_snmp2_set)
PHP_FE(snmp3_get, arginfo_snmp3_get)
- PHP_FE(snmp3_getnext, arginfo_snmp3_getnext)
+ PHP_FE(snmp3_getnext, arginfo_snmp3_getnext)
PHP_FE(snmp3_walk, arginfo_snmp3_walk)
- PHP_FE(snmp3_real_walk, arginfo_snmp3_real_walk)
+ PHP_FE(snmp3_real_walk, arginfo_snmp3_real_walk)
PHP_FE(snmp3_set, arginfo_snmp3_set)
- PHP_FE(snmp_set_valueretrieval, arginfo_snmp_set_valueretrieval)
- PHP_FE(snmp_get_valueretrieval, arginfo_snmp_get_valueretrieval)
+ PHP_FE(snmp_set_valueretrieval, arginfo_snmp_set_valueretrieval)
+ PHP_FE(snmp_get_valueretrieval, arginfo_snmp_get_valueretrieval)
- PHP_FE(snmp_read_mib, arginfo_snmp_read_mib)
+ PHP_FE(snmp_read_mib, arginfo_snmp_read_mib)
PHP_FE_END
};
/* }}} */
-#define SNMP_CMD_GET 1
-#define SNMP_CMD_GETNEXT 2
-#define SNMP_CMD_WALK 3
-#define SNMP_CMD_REALWALK 4
-#define SNMP_CMD_SET 11
-
-/* {{{ snmp_module_entry
- */
-zend_module_entry snmp_module_entry = {
- STANDARD_MODULE_HEADER,
- "snmp",
- snmp_functions,
- PHP_MINIT(snmp),
- PHP_MSHUTDOWN(snmp),
- NULL,
- NULL,
- PHP_MINFO(snmp),
- NO_VERSION_YET,
- PHP_MODULE_GLOBALS(snmp),
- PHP_GINIT(snmp),
- NULL,
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
-};
-/* }}} */
+/* query an agent with GET method */
+#define SNMP_CMD_GET (1<<0)
+/* query an agent with GETNEXT method */
+#define SNMP_CMD_GETNEXT (1<<1)
+/* query an agent with SET method */
+#define SNMP_CMD_SET (1<<2)
+/* walk the mib */
+#define SNMP_CMD_WALK (1<<3)
+/* force values-only output */
+#define SNMP_NUMERIC_KEYS (1<<7)
+/* use user-supplied OID names for keys in array output mode in GET method */
+#define SNMP_ORIGINAL_NAMES_AS_KEYS (1<<8)
+/* use OID suffix (`index') for keys in array output mode in WALK method */
+#define SNMP_USE_SUFFIX_AS_KEYS (1<<9)
#ifdef COMPILE_DL_SNMP
ZEND_GET_MODULE(snmp)
@@ -375,379 +447,481 @@ static PHP_GINIT_FUNCTION(snmp)
}
/* }}} */
-/* {{{ PHP_MINIT_FUNCTION
- */
-PHP_MINIT_FUNCTION(snmp)
+#define PHP_SNMP_SESSION_FREE(a) { \
+ if ((*session)->a) { \
+ efree((*session)->a); \
+ (*session)->a = NULL; \
+ } \
+}
+
+static void netsnmp_session_free(php_snmp_session **session)
{
- init_snmp("snmpapp");
+ if (*session) {
+ PHP_SNMP_SESSION_FREE(peername);
+ PHP_SNMP_SESSION_FREE(community);
+ PHP_SNMP_SESSION_FREE(securityName);
+ PHP_SNMP_SESSION_FREE(contextEngineID);
+ efree(*session);
+ *session = NULL;
+ }
+}
-#ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
- /* Prevent update of the snmpapp.conf file */
- netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
-#endif
+static void php_snmp_session_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ php_snmp_session *session = (php_snmp_session *)rsrc->ptr;
+ netsnmp_session_free(&session);
+}
-#ifdef HAVE_NET_SNMP
- REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
-#endif
+static void php_snmp_object_free_storage(void *object TSRMLS_DC)
+{
+ php_snmp_object *intern = (php_snmp_object *)object;
+
+ if (!intern) {
+ return;
+ }
- REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
-
- REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
+ netsnmp_session_free(&(intern->session));
- return SUCCESS;
+ zend_object_std_dtor(&intern->zo TSRMLS_CC);
+
+ efree(intern);
}
-/* }}} */
-/* {{{ PHP_MSHUTDOWN_FUNCTION
- */
-PHP_MSHUTDOWN_FUNCTION(snmp)
+static zend_object_value php_snmp_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- snmp_shutdown("snmpapp");
+ zend_object_value retval;
+ php_snmp_object *intern;
- return SUCCESS;
+ /* Allocate memory for it */
+ intern = emalloc(sizeof(php_snmp_object));
+ memset(&intern->zo, 0, sizeof(php_snmp_object));
+
+ zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
+ object_properties_init(&intern->zo, class_type);
+
+ retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) php_snmp_object_free_storage, NULL TSRMLS_CC);
+ retval.handlers = (zend_object_handlers *) &php_snmp_object_handlers;
+
+ return retval;
+
}
-/* }}} */
-/* {{{ PHP_MINFO_FUNCTION
+/* {{{ php_snmp_error
+ *
+ * Record last SNMP-related error in object
+ *
*/
-PHP_MINFO_FUNCTION(snmp)
+static void php_snmp_error(zval *object, const char *docref TSRMLS_DC, int type, const char *format, ...)
{
- php_info_print_table_start();
-#ifdef HAVE_NET_SNMP
- php_info_print_table_row(2, "NET-SNMP Support", "enabled");
- php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
-#else
- php_info_print_table_row(2, "UCD-SNMP Support", "enabled");
- php_info_print_table_row(2, "UCD-SNMP Version", VersionInfo);
-#endif
- php_info_print_table_end();
+ va_list args;
+ php_snmp_object *snmp_object;
+
+ if (object) {
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+ if (type == PHP_SNMP_ERRNO_NOERROR) {
+ memset(snmp_object->snmp_errstr, 0, sizeof(snmp_object->snmp_errstr));
+ } else {
+ va_start(args, format);
+ vsnprintf(snmp_object->snmp_errstr, sizeof(snmp_object->snmp_errstr) - 1, format, args);
+ va_end(args);
+ }
+ snmp_object->snmp_errno = type;
+ }
+
+ if (type == PHP_SNMP_ERRNO_NOERROR) {
+ return;
+ }
+
+ if (object && (snmp_object->exceptions_enabled & type)) {
+ zend_throw_exception_ex(php_snmp_exception_ce, type, snmp_object->snmp_errstr TSRMLS_CC);
+ } else {
+ va_start(args, format);
+ php_verror(docref, "", E_WARNING, format, args TSRMLS_CC);
+ va_end(args);
+ }
}
+
/* }}} */
-static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC)
+/* {{{ php_snmp_getvalue
+*
+* SNMP value to zval converter
+*
+*/
+static void php_snmp_getvalue(struct variable_list *vars, zval *snmpval TSRMLS_DC, int valueretrieval)
{
zval *val;
-#if I64CHARSZ > 2047
- char buf[I64CHARSZ + 1];
+#ifdef BUGGY_SNMPRINT_VALUE
+ char sbuf[2048];
#else
- char buf[2048];
+ char sbuf[64];
#endif
+ char *buf = &(sbuf[0]);
+ char *dbuf = (char *)NULL;
+ int buflen = sizeof(sbuf) - 1;
+ int val_len = vars->val_len;
+
+ if ((valueretrieval & SNMP_VALUE_PLAIN) == 0) {
+ val_len += 32; /* snprint_value will add type info into value, make some space for it */
+ }
- buf[0] = 0;
-
- if (SNMP_G(valueretrieval) == SNMP_VALUE_LIBRARY) {
-#ifdef HAVE_NET_SNMP
- snprint_value(buf, sizeof(buf), vars->name, vars->name_length, vars);
-#else
- sprint_value(buf,vars->name, vars->name_length, vars);
-#endif
- ZVAL_STRING(snmpval, buf, 1);
- return;
+ /* use emalloc() for large values, use static array otherwize */
+ if(val_len > buflen){
+ if ((dbuf = (char *)emalloc(val_len + 1))) {
+ buf = dbuf;
+ buflen = val_len;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed: %s, fallback to static array", strerror(errno));
+ }
}
+ *buf = 0;
+
MAKE_STD_ZVAL(val);
- switch (vars->type) {
- case ASN_BIT_STR: /* 0x03, asn1.h */
- ZVAL_STRINGL(val, vars->val.bitstring, vars->val_len, 1);
- break;
+ if (valueretrieval & SNMP_VALUE_PLAIN) {
+ switch (vars->type) {
+ case ASN_BIT_STR: /* 0x03, asn1.h */
+ ZVAL_STRINGL(val, (char *)vars->val.bitstring, vars->val_len, 1);
+ break;
- case ASN_OCTET_STR: /* 0x04, asn1.h */
- case ASN_OPAQUE: /* 0x44, snmp_impl.h */
- ZVAL_STRINGL(val, vars->val.string, vars->val_len, 1);
- break;
+ case ASN_OCTET_STR: /* 0x04, asn1.h */
+ case ASN_OPAQUE: /* 0x44, snmp_impl.h */
+ ZVAL_STRINGL(val, (char *)vars->val.string, vars->val_len, 1);
+ break;
- case ASN_NULL: /* 0x05, asn1.h */
- ZVAL_NULL(val);
- break;
+ case ASN_NULL: /* 0x05, asn1.h */
+ ZVAL_NULL(val);
+ break;
- case ASN_OBJECT_ID: /* 0x06, asn1.h */
-#ifdef HAVE_NET_SNMP
- snprint_objid(buf, sizeof(buf), vars->val.objid, vars->val_len / sizeof(oid));
-#else
- sprint_objid(buf, vars->val.objid, vars->val_len / sizeof(oid));
-#endif
+ case ASN_OBJECT_ID: /* 0x06, asn1.h */
+ snprint_objid(buf, buflen, vars->val.objid, vars->val_len / sizeof(oid));
+ ZVAL_STRING(val, buf, 1);
+ break;
- ZVAL_STRING(val, buf, 1);
- break;
+ case ASN_IPADDRESS: /* 0x40, snmp_impl.h */
+ snprintf(buf, buflen, "%d.%d.%d.%d",
+ (vars->val.string)[0], (vars->val.string)[1],
+ (vars->val.string)[2], (vars->val.string)[3]);
+ buf[buflen]=0;
+ ZVAL_STRING(val, buf, 1);
+ break;
- case ASN_IPADDRESS: /* 0x40, snmp_impl.h */
- snprintf(buf, sizeof(buf)-1, "%d.%d.%d.%d",
- (vars->val.string)[0], (vars->val.string)[1],
- (vars->val.string)[2], (vars->val.string)[3]);
- buf[sizeof(buf)-1]=0;
- ZVAL_STRING(val, buf, 1);
- break;
+ case ASN_COUNTER: /* 0x41, snmp_impl.h */
+ case ASN_GAUGE: /* 0x42, snmp_impl.h */
+ /* ASN_UNSIGNED is the same as ASN_GAUGE */
+ case ASN_TIMETICKS: /* 0x43, snmp_impl.h */
+ case ASN_UINTEGER: /* 0x47, snmp_impl.h */
+ snprintf(buf, buflen, "%lu", *vars->val.integer);
+ buf[buflen]=0;
+ ZVAL_STRING(val, buf, 1);
+ break;
- case ASN_COUNTER: /* 0x41, snmp_impl.h */
- case ASN_GAUGE: /* 0x42, snmp_impl.h */
- /* ASN_UNSIGNED is the same as ASN_GAUGE */
- case ASN_TIMETICKS: /* 0x43, snmp_impl.h */
- case ASN_UINTEGER: /* 0x47, snmp_impl.h */
- snprintf(buf, sizeof(buf)-1, "%lu", *vars->val.integer);
- buf[sizeof(buf)-1]=0;
- ZVAL_STRING(val, buf, 1);
- break;
+ case ASN_INTEGER: /* 0x02, asn1.h */
+ snprintf(buf, buflen, "%ld", *vars->val.integer);
+ buf[buflen]=0;
+ ZVAL_STRING(val, buf, 1);
+ break;
- case ASN_INTEGER: /* 0x02, asn1.h */
- snprintf(buf, sizeof(buf)-1, "%ld", *vars->val.integer);
- buf[sizeof(buf)-1]=0;
- ZVAL_STRING(val, buf, 1);
- break;
+#if defined(NETSNMP_WITH_OPAQUE_SPECIAL_TYPES) || defined(OPAQUE_SPECIAL_TYPES)
+ case ASN_OPAQUE_FLOAT: /* 0x78, asn1.h */
+ snprintf(buf, buflen, "%f", *vars->val.floatVal);
+ ZVAL_STRING(val, buf, 1);
+ break;
- case ASN_COUNTER64: /* 0x46, snmp_impl.h */
- printU64(buf, vars->val.counter64);
- ZVAL_STRING(val, buf, 1);
- break;
+ case ASN_OPAQUE_DOUBLE: /* 0x79, asn1.h */
+ snprintf(buf, buflen, "%Lf", *vars->val.doubleVal);
+ ZVAL_STRING(val, buf, 1);
+ break;
- default:
- ZVAL_STRING(val, "Unknown value type", 1);
- break;
+ case ASN_OPAQUE_I64: /* 0x80, asn1.h */
+ printI64(buf, vars->val.counter64);
+ ZVAL_STRING(val, buf, 1);
+ break;
+
+ case ASN_OPAQUE_U64: /* 0x81, asn1.h */
+#endif
+ case ASN_COUNTER64: /* 0x46, snmp_impl.h */
+ printU64(buf, vars->val.counter64);
+ ZVAL_STRING(val, buf, 1);
+ break;
+
+ default:
+ ZVAL_STRING(val, "Unknown value type", 1);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value type: %u", vars->type);
+ break;
+ }
+ } else /* use Net-SNMP value translation */ {
+ snprint_value(buf, buflen, vars->name, vars->name_length, vars);
+ ZVAL_STRING(val, buf, 1);
}
- if (SNMP_G(valueretrieval) == SNMP_VALUE_PLAIN) {
- *snmpval = *val;
- zval_copy_ctor(snmpval);
- } else {
+ if (valueretrieval & SNMP_VALUE_OBJECT) {
object_init(snmpval);
add_property_long(snmpval, "type", vars->type);
add_property_zval(snmpval, "value", val);
+ } else {
+ *snmpval = *val;
+ zval_copy_ctor(snmpval);
+ }
+ zval_ptr_dtor(&val);
+
+ if(dbuf){ /* malloc was used to store value */
+ efree(dbuf);
}
}
+/* }}} */
/* {{{ php_snmp_internal
*
-* Generic SNMP object fetcher (for all SNMP versions)
-*
-* st=SNMP_CMD_GET get - query an agent with SNMP-GET.
-* st=SNMP_CMD_GETNEXT getnext - query an agent with SNMP-GETNEXT.
-* st=SNMP_CMD_WALK walk - walk the mib and return a single dimensional array
-* containing the values.
-* st=SNMP_CMD_REALWALK realwalk() and walkoid() - walk the mib and return an
-* array of oid,value pairs.
-* st=SNMP_CMD_SET set() - query an agent and set a single value
+* SNMP object fetcher/setter for all SNMP versions
*
*/
static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
struct snmp_session *session,
- char *objid,
- char type,
- char* value)
+ struct objid_query *objid_query)
{
struct snmp_session *ss;
struct snmp_pdu *pdu=NULL, *response;
struct variable_list *vars;
- oid name[MAX_NAME_LEN];
- size_t name_length;
oid root[MAX_NAME_LEN];
size_t rootlen = 0;
- int gotroot = 0;
- int status, count;
+ int status, count, found;
char buf[2048];
char buf2[2048];
int keepwalking=1;
char *err;
zval *snmpval = NULL;
+ int snmp_errno;
- if (st >= SNMP_CMD_WALK) { /* walk */
- rootlen = MAX_NAME_LEN;
- if (strlen(objid)) { /* on a walk, an empty string means top of tree - no error */
- if (snmp_parse_oid(objid, root, &rootlen)) {
- gotroot = 1;
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
- }
- }
+ /* we start with retval=FALSE. If any actual data is aquired, retval will be set to appropriate type */
+ RETVAL_FALSE;
+
+ /* reset errno and errstr */
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_NOERROR, "");
- if (!gotroot) {
- memmove((char *) root, (char *) objid_mib, sizeof(objid_mib));
- rootlen = sizeof(objid_mib) / sizeof(oid);
- gotroot = 1;
- }
+ if (st & SNMP_CMD_WALK) { /* remember root OID */
+ memmove((char *)root, (char *)(objid_query->vars[0].name), (objid_query->vars[0].name_length) * sizeof(oid));
+ rootlen = objid_query->vars[0].name_length;
+ objid_query->offset = objid_query->count;
}
if ((ss = snmp_open(session)) == NULL) {
snmp_error(session, NULL, NULL, &err);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open snmp connection: %s", err);
free(err);
- RETURN_FALSE;
+ RETVAL_FALSE;
+ return;
}
- if (st >= SNMP_CMD_WALK) {
- memmove((char *)name, (char *)root, rootlen * sizeof(oid));
- name_length = rootlen;
- switch(st) {
- case SNMP_CMD_WALK:
- case SNMP_CMD_REALWALK:
- array_init(return_value);
- break;
- default:
- RETVAL_TRUE;
- break;
- }
+ if ((st & SNMP_CMD_SET) && objid_query->count > objid_query->step) {
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES, "Can not fit all OIDs for SET query into one packet, using multiple queries");
}
while (keepwalking) {
keepwalking = 0;
- if ((st == SNMP_CMD_GET) || (st == SNMP_CMD_GETNEXT)) {
- name_length = MAX_OID_LEN;
- if (!snmp_parse_oid(objid, name, &name_length)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object identifier: %s", objid);
- snmp_close(ss);
- RETURN_FALSE;
- }
- pdu = snmp_pdu_create((st == SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT);
- snmp_add_null_var(pdu, name, name_length);
- } else if (st == SNMP_CMD_SET) {
- pdu = snmp_pdu_create(SNMP_MSG_SET);
- if (snmp_add_var(pdu, name, name_length, type, value)) {
-#ifdef HAVE_NET_SNMP
- snprint_objid(buf, sizeof(buf), name, name_length);
-#else
- sprint_objid(buf, name, name_length);
-#endif
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not add variable: %s %c %s", buf, type, value);
- snmp_free_pdu(pdu);
- snmp_close(ss);
- RETURN_FALSE;
- }
- } else if (st >= SNMP_CMD_WALK) {
+ if (st & SNMP_CMD_WALK) {
if (session->version == SNMP_VERSION_1) {
pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
} else {
pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
- pdu->non_repeaters = 0;
- pdu->max_repetitions = 20;
+ pdu->non_repeaters = objid_query->non_repeaters;
+ pdu->max_repetitions = objid_query->max_repetitions;
+ }
+ snmp_add_null_var(pdu, objid_query->vars[0].name, objid_query->vars[0].name_length);
+ } else {
+ if (st & SNMP_CMD_GET) {
+ pdu = snmp_pdu_create(SNMP_MSG_GET);
+ } else if (st & SNMP_CMD_GETNEXT) {
+ pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
+ } else if (st & SNMP_CMD_SET) {
+ pdu = snmp_pdu_create(SNMP_MSG_SET);
+ } else {
+ snmp_close(ss);
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown SNMP command (internals)");
+ RETVAL_FALSE;
+ return;
+ }
+ for (count = 0; objid_query->offset < objid_query->count && count < objid_query->step; objid_query->offset++, count++){
+ if (st & SNMP_CMD_SET) {
+ if ((snmp_errno = snmp_add_var(pdu, objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length, objid_query->vars[objid_query->offset].type, objid_query->vars[objid_query->offset].value))) {
+ snprint_objid(buf, sizeof(buf), objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Could not add variable: OID='%s' type='%c' value='%s': %s", buf, objid_query->vars[objid_query->offset].type, objid_query->vars[objid_query->offset].value, snmp_api_errstring(snmp_errno));
+ snmp_free_pdu(pdu);
+ snmp_close(ss);
+ RETVAL_FALSE;
+ return;
+ }
+ } else {
+ snmp_add_null_var(pdu, objid_query->vars[objid_query->offset].name, objid_query->vars[objid_query->offset].name_length);
+ }
+ }
+ if(pdu->variables == NULL){
+ snmp_free_pdu(pdu);
+ snmp_close(ss);
+ RETVAL_FALSE;
+ return;
}
- snmp_add_null_var(pdu, name, name_length);
}
retry:
status = snmp_synch_response(ss, pdu, &response);
if (status == STAT_SUCCESS) {
if (response->errstat == SNMP_ERR_NOERROR) {
+ if (st & SNMP_CMD_SET) {
+ if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
+ keepwalking = 1;
+ continue;
+ }
+ snmp_free_pdu(response);
+ snmp_close(ss);
+ RETVAL_TRUE;
+ return;
+ }
for (vars = response->variables; vars; vars = vars->next_variable) {
- if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET &&
- (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) {
- continue; /* not part of this subtree */
+ /* do not output errors as values */
+ if ( vars->type == SNMP_ENDOFMIBVIEW ||
+ vars->type == SNMP_NOSUCHOBJECT ||
+ vars->type == SNMP_NOSUCHINSTANCE ) {
+ if ((st & SNMP_CMD_WALK) && Z_TYPE_P(return_value) == IS_ARRAY) {
+ break;
+ }
+ snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
+ snprint_value(buf2, sizeof(buf2), vars->name, vars->name_length, vars);
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, buf2);
+ continue;
}
-
- if (st != SNMP_CMD_SET) {
- MAKE_STD_ZVAL(snmpval);
- php_snmp_getvalue(vars, snmpval TSRMLS_CC);
+
+ if ((st & SNMP_CMD_WALK) &&
+ (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid)))) { /* not part of this subtree */
+ if (Z_TYPE_P(return_value) == IS_ARRAY) { /* some records are fetched already, shut down further lookup */
+ keepwalking = 0;
+ } else {
+ /* first fetched OID is out of subtree, fallback to GET query */
+ st |= SNMP_CMD_GET;
+ st ^= SNMP_CMD_WALK;
+ objid_query->offset = 0;
+ keepwalking = 1;
+ }
+ break;
}
- if (st == SNMP_CMD_GET) {
+ MAKE_STD_ZVAL(snmpval);
+ php_snmp_getvalue(vars, snmpval TSRMLS_CC, objid_query->valueretrieval);
+
+ if (objid_query->array_output) {
+ if (Z_TYPE_P(return_value) == IS_BOOL) {
+ array_init(return_value);
+ }
+ if (st & SNMP_NUMERIC_KEYS) {
+ add_next_index_zval(return_value, snmpval);
+ } else if (st & SNMP_ORIGINAL_NAMES_AS_KEYS && st & SNMP_CMD_GET) {
+ found = 0;
+ for (count = 0; count < objid_query->count; count++) {
+ if (objid_query->vars[count].name_length == vars->name_length && snmp_oid_compare(objid_query->vars[count].name, objid_query->vars[count].name_length, vars->name, vars->name_length) == 0) {
+ found = 1;
+ objid_query->vars[count].name_length = 0; /* mark this name as used */
+ break;
+ }
+ }
+ if (found) {
+ add_assoc_zval(return_value, objid_query->vars[count].oid, snmpval);
+ } else {
+ snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find original OID name for '%s'", buf2);
+ }
+ } else if (st & SNMP_USE_SUFFIX_AS_KEYS && st & SNMP_CMD_WALK) {
+ snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
+ if (objid_query->vars[0].name_length <= vars->name_length && snmp_oid_compare(objid_query->vars[0].name, objid_query->vars[0].name_length, vars->name, objid_query->vars[0].name_length) == 0) {
+ buf2[0] = '\0';
+ count = objid_query->vars[0].name_length;
+ while(count < vars->name_length){
+ sprintf(buf, "%lu.", vars->name[count]);
+ strcat(buf2, buf);
+ count++;
+ }
+ buf2[strlen(buf2) - 1] = '\0'; /* remove trailing '.' */
+ }
+ add_assoc_zval(return_value, buf2, snmpval);
+ } else {
+ snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
+ add_assoc_zval(return_value, buf2, snmpval);
+ }
+ } else {
*return_value = *snmpval;
zval_copy_ctor(return_value);
zval_ptr_dtor(&snmpval);
- snmp_free_pdu(response);
- snmp_close(ss);
- return;
- } else if (st == SNMP_CMD_GETNEXT) {
- *return_value = *snmpval;
- zval_copy_ctor(return_value);
- snmp_free_pdu(response);
- snmp_close(ss);
- return;
- } else if (st == SNMP_CMD_WALK) {
- add_next_index_zval(return_value,snmpval); /* Add to returned array */
- } else if (st == SNMP_CMD_REALWALK && vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
-#ifdef HAVE_NET_SNMP
- snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
-#else
- sprint_objid(buf2, vars->name, vars->name_length);
-#endif
- add_assoc_zval(return_value,buf2,snmpval);
+ break;
}
- if (st >= SNMP_CMD_WALK && st != SNMP_CMD_SET) {
- if (vars->type != SNMP_ENDOFMIBVIEW &&
- vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
- if (snmp_oid_compare(name, name_length, vars->name, vars->name_length) >= 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error: OID not increasing: %s",name);
- keepwalking = 0;
- } else {
- memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid));
- name_length = vars->name_length;
- keepwalking = 1;
- }
+
+ /* OID increase check */
+ if (st & SNMP_CMD_WALK) {
+ if (objid_query->oid_increasing_check == TRUE && snmp_oid_compare(objid_query->vars[0].name, objid_query->vars[0].name_length, vars->name, vars->name_length) >= 0) {
+ snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length);
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_NOT_INCREASING, "Error: OID not increasing: %s", buf2);
+ keepwalking = 0;
+ } else {
+ memmove((char *)(objid_query->vars[0].name), (char *)vars->name, vars->name_length * sizeof(oid));
+ objid_query->vars[0].name_length = vars->name_length;
+ keepwalking = 1;
}
}
- }
+ }
+ if (objid_query->offset < objid_query->count) { /* we have unprocessed OIDs */
+ keepwalking = 1;
+ }
} else {
- if ((st != SNMP_CMD_WALK && st != SNMP_CMD_REALWALK) || response->errstat != SNMP_ERR_NOSUCHNAME) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in packet: %s", snmp_errstring(response->errstat));
- if (response->errstat == SNMP_ERR_NOSUCHNAME) {
- for (count=1, vars = response->variables; vars && count != response->errindex;
+ if (!(st & SNMP_CMD_WALK) || response->errstat != SNMP_ERR_NOSUCHNAME || Z_TYPE_P(return_value) == IS_BOOL) {
+ for ( count=1, vars = response->variables;
+ vars && count != response->errindex;
vars = vars->next_variable, count++);
- if (vars) {
-#ifdef HAVE_NET_SNMP
- snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
-#else
- sprint_objid(buf,vars->name, vars->name_length);
-#endif
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "This name does not exist: %s",buf);
+
+ if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT) && response->errstat == SNMP_ERR_TOOBIG && objid_query->step > 1) { /* Answer will not fit into single packet */
+ objid_query->offset = ((objid_query->offset > objid_query->step) ? (objid_query->offset - objid_query->step) : 0 );
+ objid_query->step /= 2;
+ snmp_free_pdu(response);
+ keepwalking = 1;
+ continue;
}
- if (st == SNMP_CMD_GET) {
- if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) {
- snmp_free_pdu(response);
- goto retry;
- }
- } else if (st == SNMP_CMD_SET) {
- if ((pdu = snmp_fix_pdu(response, SNMP_MSG_SET)) != NULL) {
- snmp_free_pdu(response);
- goto retry;
- }
- } else if (st == SNMP_CMD_GETNEXT) {
- if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) {
- snmp_free_pdu(response);
- goto retry;
- }
- } else if (st >= SNMP_CMD_WALK) { /* Here we do walks. */
- if ((pdu = snmp_fix_pdu(response, ((session->version == SNMP_VERSION_1)
- ? SNMP_MSG_GETNEXT
- : SNMP_MSG_GETBULK))) != NULL) {
+ if (vars) {
+ snprint_objid(buf, sizeof(buf), vars->name, vars->name_length);
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at '%s': %s", buf, snmp_errstring(response->errstat));
+ } else {
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_ERROR_IN_REPLY, "Error in packet at %u object_id: %s", response->errindex, snmp_errstring(response->errstat));
+ }
+ if (st & (SNMP_CMD_GET | SNMP_CMD_GETNEXT)) { /* cut out bogus OID and retry */
+ if ((pdu = snmp_fix_pdu(response, ((st & SNMP_CMD_GET) ? SNMP_MSG_GET : SNMP_MSG_GETNEXT) )) != NULL) {
snmp_free_pdu(response);
goto retry;
}
}
snmp_free_pdu(response);
snmp_close(ss);
- if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
+ if (objid_query->array_output) {
zval_dtor(return_value);
}
- RETURN_FALSE;
+ RETVAL_FALSE;
+ return;
}
}
} else if (status == STAT_TIMEOUT) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No response from %s", session->peername);
- if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_TIMEOUT, "No response from %s", session->peername);
+ if (objid_query->array_output) {
zval_dtor(return_value);
}
snmp_close(ss);
- RETURN_FALSE;
+ RETVAL_FALSE;
+ return;
} else { /* status == STAT_ERROR */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred, quitting");
- if (st == SNMP_CMD_WALK || st == SNMP_CMD_REALWALK) {
+ snmp_error(ss, NULL, NULL, &err);
+ php_snmp_error(getThis(), NULL TSRMLS_CC, PHP_SNMP_ERRNO_GENERIC, "Fatal error: %s", err);
+ free(err);
+ if (objid_query->array_output) {
zval_dtor(return_value);
}
snmp_close(ss);
- RETURN_FALSE;
+ RETVAL_FALSE;
+ return;
}
if (response) {
snmp_free_pdu(response);
@@ -757,115 +931,642 @@ retry:
}
/* }}} */
+/* {{{ php_snmp_parse_oid
+*
+* OID parser (and type, value for SNMP_SET command)
+*/
+
+static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_query, zval **oid, zval **type, zval **value TSRMLS_DC)
+{
+ char *pptr;
+ HashPosition pos_oid, pos_type, pos_value;
+ zval **tmp_oid, **tmp_type, **tmp_value;
+
+ if (Z_TYPE_PP(oid) != IS_ARRAY) {
+ if (Z_ISREF_PP(oid)) {
+ SEPARATE_ZVAL(oid);
+ }
+ convert_to_string_ex(oid);
+ } else if (Z_TYPE_PP(oid) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
+ }
+
+ if (st & SNMP_CMD_SET) {
+ if (Z_TYPE_PP(type) != IS_ARRAY) {
+ if (Z_ISREF_PP(type)) {
+ SEPARATE_ZVAL(type);
+ }
+ convert_to_string_ex(type);
+ } else if (Z_TYPE_PP(type) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(type), &pos_type);
+ }
+
+ if (Z_TYPE_PP(value) != IS_ARRAY) {
+ if (Z_ISREF_PP(value)) {
+ SEPARATE_ZVAL(value);
+ }
+ convert_to_string_ex(value);
+ } else if (Z_TYPE_PP(value) == IS_ARRAY) {
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(value), &pos_value);
+ }
+ }
+
+ objid_query->count = 0;
+ objid_query->array_output = ((st & SNMP_CMD_WALK) ? TRUE : FALSE);
+ if (Z_TYPE_PP(oid) == IS_STRING) {
+ objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg));
+ if (objid_query->vars == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid: %s", strerror(errno));
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ objid_query->vars[objid_query->count].oid = Z_STRVAL_PP(oid);
+ if (st & SNMP_CMD_SET) {
+ if (Z_TYPE_PP(type) == IS_STRING && Z_TYPE_PP(value) == IS_STRING) {
+ if (Z_STRLEN_PP(type) != 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bogus type '%s', should be single char, got %u", Z_STRVAL_PP(type), Z_STRLEN_PP(type));
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ pptr = Z_STRVAL_PP(type);
+ objid_query->vars[objid_query->count].type = *pptr;
+ objid_query->vars[objid_query->count].value = Z_STRVAL_PP(value);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Single objid and multiple type or values are not supported");
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ }
+ objid_query->count++;
+ } else if (Z_TYPE_PP(oid) == IS_ARRAY) { /* we got objid array */
+ if (zend_hash_num_elements(Z_ARRVAL_PP(oid)) == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Got empty OID array");
+ return FALSE;
+ }
+ objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_PP(oid)));
+ if (objid_query->vars == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ objid_query->array_output = ( (st & SNMP_CMD_SET) ? FALSE : TRUE );
+ for ( zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(oid), &pos_oid);
+ zend_hash_get_current_data_ex(Z_ARRVAL_PP(oid), (void **) &tmp_oid, &pos_oid) == SUCCESS;
+ zend_hash_move_forward_ex(Z_ARRVAL_PP(oid), &pos_oid) ) {
+
+ convert_to_string_ex(tmp_oid);
+ objid_query->vars[objid_query->count].oid = Z_STRVAL_PP(tmp_oid);
+ if (st & SNMP_CMD_SET) {
+ if (Z_TYPE_PP(type) == IS_STRING) {
+ pptr = Z_STRVAL_PP(type);
+ objid_query->vars[objid_query->count].type = *pptr;
+ } else if (Z_TYPE_PP(type) == IS_ARRAY) {
+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(type), (void **) &tmp_type, &pos_type)) {
+ convert_to_string_ex(tmp_type);
+ if (Z_STRLEN_PP(tmp_type) != 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': bogus type '%s', should be single char, got %u", Z_STRVAL_PP(tmp_oid), Z_STRVAL_PP(tmp_type), Z_STRLEN_PP(tmp_type));
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ pptr = Z_STRVAL_PP(tmp_type);
+ objid_query->vars[objid_query->count].type = *pptr;
+ zend_hash_move_forward_ex(Z_ARRVAL_PP(type), &pos_type);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no type set", Z_STRVAL_PP(tmp_oid));
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ }
+
+ if (Z_TYPE_PP(value) == IS_STRING) {
+ objid_query->vars[objid_query->count].value = Z_STRVAL_PP(value);
+ } else if (Z_TYPE_PP(value) == IS_ARRAY) {
+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(value), (void **) &tmp_value, &pos_value)) {
+ convert_to_string_ex(tmp_value);
+ objid_query->vars[objid_query->count].value = Z_STRVAL_PP(tmp_value);
+ zend_hash_move_forward_ex(Z_ARRVAL_PP(value), &pos_value);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s': no value set", Z_STRVAL_PP(tmp_oid));
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ }
+ }
+ objid_query->count++;
+ }
+ }
+
+ /* now parse all OIDs */
+ if (st & SNMP_CMD_WALK) {
+ if (objid_query->count > 1) {
+ php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Multi OID walks are not supported!");
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ objid_query->vars[0].name_length = MAX_NAME_LEN;
+ if (strlen(objid_query->vars[0].oid)) { /* on a walk, an empty string means top of tree - no error */
+ if (!snmp_parse_oid(objid_query->vars[0].oid, objid_query->vars[0].name, &(objid_query->vars[0].name_length))) {
+ php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[0].oid);
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ } else {
+ memmove((char *)objid_query->vars[0].name, (char *)objid_mib, sizeof(objid_mib));
+ objid_query->vars[0].name_length = sizeof(objid_mib) / sizeof(oid);
+ }
+ } else {
+ for (objid_query->offset = 0; objid_query->offset < objid_query->count; objid_query->offset++) {
+ objid_query->vars[objid_query->offset].name_length = MAX_OID_LEN;
+ if (!snmp_parse_oid(objid_query->vars[objid_query->offset].oid, objid_query->vars[objid_query->offset].name, &(objid_query->vars[objid_query->offset].name_length))) {
+ php_snmp_error(object, NULL TSRMLS_CC, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[objid_query->offset].oid);
+ efree(objid_query->vars);
+ return FALSE;
+ }
+ }
+ }
+ objid_query->offset = 0;
+ objid_query->step = objid_query->count;
+ return (objid_query->count > 0);
+}
+/* }}} */
+
+/* {{{ netsnmp_session_init
+ allocates memory for session and session->peername, caller should free it manually using netsnmp_session_free() and efree()
+*/
+static int netsnmp_session_init(php_snmp_session **session_p, int version, char *hostname, char *community, int timeout, int retries TSRMLS_DC)
+{
+ php_snmp_session *session;
+ char *pptr;
+ char buf[MAX_NAME_LEN];
+ int force_ipv6 = FALSE;
+ int n;
+ struct sockaddr **psal;
+ struct sockaddr **res;
+
+ *session_p = (php_snmp_session *)emalloc(sizeof(php_snmp_session));
+ session = *session_p;
+ if (session == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed allocating session");
+ return (-1);
+ }
+ memset(session, 0, sizeof(php_snmp_session));
+
+ strlcpy(buf, hostname, sizeof(buf));
+
+ snmp_sess_init(session);
+
+ session->version = version;
+ session->remote_port = SNMP_PORT;
+
+ session->peername = emalloc(MAX_NAME_LEN);
+ if (session->peername == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while copying hostname");
+ return (-1);
+ }
+ *(session->peername) = '\0';
+
+ /* Reading the hostname and its optional non-default port number */
+ if (*hostname == '[') { /* IPv6 address */
+ force_ipv6 = TRUE;
+ hostname++;
+ if ((pptr = strchr(hostname, ']'))) {
+ if (pptr[1] == ':') {
+ session->remote_port = atoi(pptr + 2);
+ }
+ *pptr = '\0';
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "mailformed IPv6 address, closing square bracket missing");
+ return (-1);
+ }
+ } else { /* IPv4 address */
+ if ((pptr = strchr(hostname, ':'))) {
+ session->remote_port = atoi(pptr + 1);
+ *pptr = '\0';
+ }
+ }
+
+ /* since Net-SNMP library requires 'udp6:' prefix for all IPv6 addresses (in FQDN form too) we need to
+ perform possible name resolution before running any SNMP queries */
+ if ((n = php_network_getaddresses(hostname, SOCK_DGRAM, &psal, NULL TSRMLS_CC)) == 0) { /* some resover error */
+ /* warnings sent, bailing out */
+ return (-1);
+ }
+
+ res = psal;
+ while (n-- > 0) {
+ pptr = session->peername;
+#if HAVE_GETADDRINFO && HAVE_IPV6 && HAVE_INET_NTOP
+ if (force_ipv6 && (*res)->sa_family != AF_INET6) {
+ res++;
+ continue;
+ }
+ if ((*res)->sa_family == AF_INET6) {
+ strcpy(session->peername, "udp6:");
+ pptr = session->peername + strlen(session->peername);
+ inet_ntop((*res)->sa_family, &(((struct sockaddr_in6*)(*res))->sin6_addr), pptr, MAX_NAME_LEN);
+ } else if ((*res)->sa_family == AF_INET) {
+ inet_ntop((*res)->sa_family, &(((struct sockaddr_in*)(*res))->sin_addr), pptr, MAX_NAME_LEN);
+ } else {
+ res++;
+ continue;
+ }
+#else
+ if ((*res)->sa_family != AF_INET) {
+ res++;
+ continue;
+ }
+ strcat(pptr, inet_ntoa(((struct sockaddr_in*)(*res))->sin_addr));
+#endif
+ break;
+ }
+
+ if (strlen(session->peername) == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown failure while resolving '%s'", buf);
+ return (-1);
+ }
+ /* XXX FIXME
+ There should be check for non-empty session->peername!
+ */
+
+ /* put back non-standard SNMP port */
+ if (session->remote_port != SNMP_PORT) {
+ pptr = session->peername + strlen(session->peername);
+ sprintf(pptr, ":%d", session->remote_port);
+ }
+
+ php_network_freeaddresses(psal);
+
+ if (version == SNMP_VERSION_3) {
+ /* Setting the security name. */
+ session->securityName = estrdup(community);
+ session->securityNameLen = strlen(session->securityName);
+ } else {
+ session->authenticator = NULL;
+ session->community = (u_char *)estrdup(community);
+ session->community_len = strlen(community);
+ }
+
+ session->retries = retries;
+ session->timeout = timeout;
+ return (0);
+}
+/* }}} */
+
+/* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
+ Set the security level in the snmpv3 session */
+static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
+{
+ if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
+ s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
+ } else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
+ s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ } else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
+ s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
+ } else {
+ return (-1);
+ }
+ return (0);
+}
+/* }}} */
+
+/* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
+ Set the authentication protocol in the snmpv3 session */
+static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
+{
+ if (!strcasecmp(prot, "MD5")) {
+ s->securityAuthProto = usmHMACMD5AuthProtocol;
+ s->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
+ } else if (!strcasecmp(prot, "SHA")) {
+ s->securityAuthProto = usmHMACSHA1AuthProtocol;
+ s->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown authentication protocol '%s'", prot);
+ return (-1);
+ }
+ return (0);
+}
+/* }}} */
+
+/* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
+ Set the security protocol in the snmpv3 session */
+static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
+{
+ if (!strcasecmp(prot, "DES")) {
+ s->securityPrivProto = usmDESPrivProtocol;
+ s->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
+#ifdef HAVE_AES
+ } else if (!strcasecmp(prot, "AES128") || !strcasecmp(prot, "AES")) {
+ s->securityPrivProto = usmAESPrivProtocol;
+ s->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
+#endif
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown security protocol '%s'", prot);
+ return (-1);
+ }
+ return (0);
+}
+/* }}} */
+
+/* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
+ Make key from pass phrase in the snmpv3 session */
+static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
+{
+ int snmp_errno;
+ s->securityAuthKeyLen = USM_AUTH_KU_LEN;
+ if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
+ (u_char *) pass, strlen(pass),
+ s->securityAuthKey, &(s->securityAuthKeyLen)))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
+ return (-1);
+ }
+ return (0);
+}
+/* }}} */
+
+/* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
+ Make key from pass phrase in the snmpv3 session */
+static int netsnmp_session_gen_sec_key(struct snmp_session *s, char *pass TSRMLS_DC)
+{
+ int snmp_errno;
+
+ s->securityPrivKeyLen = USM_PRIV_KU_LEN;
+ if ((snmp_errno = generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
+ (u_char *)pass, strlen(pass),
+ s->securityPrivKey, &(s->securityPrivKeyLen)))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase '%s': %s", pass, snmp_api_errstring(snmp_errno));
+ return (-2);
+ }
+ return (0);
+}
+/* }}} */
+
+/* {{{ in netsnmp_session_set_contextEngineID(struct snmp_session *s, u_char * contextEngineID)
+ Set context Engine Id in the snmpv3 session */
+static int netsnmp_session_set_contextEngineID(struct snmp_session *s, char * contextEngineID TSRMLS_DC)
+{
+ size_t ebuf_len = 32, eout_len = 0;
+ u_char *ebuf = (u_char *) emalloc(ebuf_len);
+
+ if (ebuf == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "malloc failure setting contextEngineID");
+ return (-1);
+ }
+ if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, contextEngineID)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad engine ID value '%s'", contextEngineID);
+ efree(ebuf);
+ return (-1);
+ }
+
+ if (s->contextEngineID) {
+ efree(s->contextEngineID);
+ }
+
+ s->contextEngineID = ebuf;
+ s->contextEngineIDLen = eout_len;
+ return (0);
+}
+/* }}} */
+
+/* {{{ php_set_security(struct snmp_session *session, char *sec_level, char *auth_protocol, char *auth_passphrase, char *priv_protocol, char *priv_passphrase, char *contextName, char *contextEngineID)
+ Set all snmpv3-related security options */
+static int netsnmp_session_set_security(struct snmp_session *session, char *sec_level, char *auth_protocol, char *auth_passphrase, char *priv_protocol, char *priv_passphrase, char *contextName, char *contextEngineID TSRMLS_DC)
+{
+
+ /* Setting the security level. */
+ if (netsnmp_session_set_sec_level(session, sec_level)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level '%s'", sec_level);
+ return (-1);
+ }
+
+ if (session->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
+
+ /* Setting the authentication protocol. */
+ if (netsnmp_session_set_auth_protocol(session, auth_protocol TSRMLS_CC)) {
+ /* Warning message sent already, just bail out */
+ return (-1);
+ }
+
+ /* Setting the authentication passphrase. */
+ if (netsnmp_session_gen_auth_key(session, auth_passphrase TSRMLS_CC)) {
+ /* Warning message sent already, just bail out */
+ return (-1);
+ }
+
+ if (session->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
+ /* Setting the security protocol. */
+ if (netsnmp_session_set_sec_protocol(session, priv_protocol TSRMLS_CC)) {
+ /* Warning message sent already, just bail out */
+ return (-1);
+ }
+
+ /* Setting the security protocol passphrase. */
+ if (netsnmp_session_gen_sec_key(session, priv_passphrase TSRMLS_CC)) {
+ /* Warning message sent already, just bail out */
+ return (-1);
+ }
+ }
+ }
+
+ /* Setting contextName if specified */
+ if (contextName) {
+ session->contextName = contextName;
+ session->contextNameLen = strlen(contextName);
+ }
+
+ /* Setting contextEngineIS if specified */
+ if (contextEngineID && strlen(contextEngineID) && netsnmp_session_set_contextEngineID(session, contextEngineID TSRMLS_CC)) {
+ /* Warning message sent already, just bail out */
+ return (-1);
+ }
+
+ return (0);
+}
+/* }}} */
+
/* {{{ php_snmp
*
-* Generic community based SNMP handler for version 1 and 2.
+* Generic SNMP handler for all versions.
* This function makes use of the internal SNMP object fetcher.
-* The object fetcher is shared with SNMPv3.
-*
-* st=SNMP_CMD_GET get - query an agent with SNMP-GET.
-* st=SNMP_CMD_GETNEXT getnext - query an agent with SNMP-GETNEXT.
-* st=SNMP_CMD_WALK walk - walk the mib and return a single dimensional array
-* containing the values.
-* st=SNMP_CMD_REALWALK realwalk() and walkoid() - walk the mib and return an
-* array of oid,value pairs.
-* st=5-8 ** Reserved **
-* st=SNMP_CMD_SET set() - query an agent and set a single value
+* Used both in old (non-OO) and OO API
*
*/
-static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
+static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
{
- char *a1, *a2, *a3;
- int a1_len, a2_len, a3_len;
- struct snmp_session session;
+ zval **oid, **value, **type;
+ char *a1, *a2, *a3, *a4, *a5, *a6, *a7;
+ int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len;
+ zend_bool use_orignames = 0, suffix_keys = 0;
long timeout = SNMP_DEFAULT_TIMEOUT;
long retries = SNMP_DEFAULT_RETRIES;
- char type = (char) 0;
- char *value = (char *) 0, *stype = "";
- int value_len, stype_len;
- char hostname[MAX_NAME_LEN];
- int remote_port = 161;
- char *pptr;
int argc = ZEND_NUM_ARGS();
+ struct objid_query objid_query;
+ php_snmp_session *session;
+ int session_less_mode = (getThis() == NULL);
+ php_snmp_object *snmp_object;
+ php_snmp_object glob_snmp_object;
+
+ objid_query.max_repetitions = -1;
+ objid_query.non_repeaters = 0;
+ objid_query.valueretrieval = SNMP_G(valueretrieval);
+ objid_query.oid_increasing_check = TRUE;
+
+ if (session_less_mode) {
+ if (version == SNMP_VERSION_3) {
+ if (st & SNMP_CMD_SET) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
+ &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
+ RETURN_FALSE;
+ }
+ } else {
+ /* SNMP_CMD_GET
+ * SNMP_CMD_GETNEXT
+ * SNMP_CMD_WALK
+ */
+ if (zend_parse_parameters(argc TSRMLS_CC, "sssssssZ|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
+ &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &oid, &timeout, &retries) == FAILURE) {
+ RETURN_FALSE;
+ }
+ }
+ } else {
+ if (st & SNMP_CMD_SET) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "ssZZZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &type, &value, &timeout, &retries) == FAILURE) {
+ RETURN_FALSE;
+ }
+ } else {
+ /* SNMP_CMD_GET
+ * SNMP_CMD_GETNEXT
+ * SNMP_CMD_WALK
+ */
+ if (zend_parse_parameters(argc TSRMLS_CC, "ssZ|ll", &a1, &a1_len, &a2, &a2_len, &oid, &timeout, &retries) == FAILURE) {
+ RETURN_FALSE;
+ }
+ }
+ }
+ } else {
+ if (st & SNMP_CMD_SET) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "ZZZ", &oid, &type, &value) == FAILURE) {
+ RETURN_FALSE;
+ }
+ } else if (st & SNMP_CMD_WALK) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "Z|bll", &oid, &suffix_keys, &(objid_query.max_repetitions), &(objid_query.non_repeaters)) == FAILURE) {
+ RETURN_FALSE;
+ }
+ if (suffix_keys) {
+ st |= SNMP_USE_SUFFIX_AS_KEYS;
+ }
+ } else if (st & SNMP_CMD_GET) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "Z|b", &oid, &use_orignames) == FAILURE) {
+ RETURN_FALSE;
+ }
+ if (use_orignames) {
+ st |= SNMP_ORIGINAL_NAMES_AS_KEYS;
+ }
+ } else {
+ /* SNMP_CMD_GETNEXT
+ */
+ if (zend_parse_parameters(argc TSRMLS_CC, "Z", &oid) == FAILURE) {
+ RETURN_FALSE;
+ }
+ }
+ }
- if (st == SNMP_CMD_SET) {
- if (zend_parse_parameters(argc TSRMLS_CC, "sssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
- return;
+ if (!php_snmp_parse_oid(getThis(), st, &objid_query, oid, type, value TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ if (session_less_mode) {
+ if (netsnmp_session_init(&session, version, a1, a2, timeout, retries TSRMLS_CC)) {
+ efree(objid_query.vars);
+ netsnmp_session_free(&session);
+ RETURN_FALSE;
+ }
+ if (version == SNMP_VERSION_3 && netsnmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL TSRMLS_CC)) {
+ efree(objid_query.vars);
+ netsnmp_session_free(&session);
+ /* Warning message sent already, just bail out */
+ RETURN_FALSE;
}
} else {
- /* SNMP_CMD_GET
- * SNMP_CMD_GETNEXT
- * SNMP_CMD_WALK
- * SNMP_CMD_REALWALK
- */
- if (zend_parse_parameters(argc TSRMLS_CC, "sss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len, &timeout, &retries) == FAILURE) {
- return;
+ zval *object = getThis();
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+ session = snmp_object->session;
+ if (!session) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized SNMP object");
+ efree(objid_query.vars);
+ RETURN_FALSE;
+ }
+
+ if (snmp_object->max_oids > 0) {
+ objid_query.step = snmp_object->max_oids;
+ if (objid_query.max_repetitions < 0) { /* unspecified in function call, use session-wise */
+ objid_query.max_repetitions = snmp_object->max_oids;
+ }
}
+ objid_query.oid_increasing_check = snmp_object->oid_increasing_check;
+ objid_query.valueretrieval = snmp_object->valueretrieval;
+ glob_snmp_object.enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, snmp_object->enum_print);
+ glob_snmp_object.quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, snmp_object->quick_print);
+ glob_snmp_object.oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
+ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, snmp_object->oid_output_format);
}
+
+ if (objid_query.max_repetitions < 0) {
+ objid_query.max_repetitions = 20; /* provide correct default value */
+ }
+
+ php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_query);
- if (st == SNMP_CMD_SET) {
- type = stype[0];
- }
-
- snmp_sess_init(&session);
- strlcpy(hostname, a1, sizeof(hostname));
- if ((pptr = strchr (hostname, ':'))) {
- remote_port = strtol (pptr + 1, NULL, 0);
- }
-
- session.peername = hostname;
- session.remote_port = remote_port;
- session.version = version;
- /*
- * FIXME: potential memory leak
- * This is a workaround for an "artifact" (Mike Slifcak)
- * in (at least) ucd-snmp 3.6.1 which frees
- * memory it did not allocate
- */
-#ifdef UCD_SNMP_HACK
- session.community = (u_char *)strdup(a2); /* memory freed by SNMP library, strdup NOT estrdup */
-#else
- session.community = (u_char *)a2;
-#endif
- session.community_len = a2_len;
- session.retries = retries;
- session.timeout = timeout;
-
- session.authenticator = NULL;
+ efree(objid_query.vars);
- php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a3, type, value);
+ if (session_less_mode) {
+ netsnmp_session_free(&session);
+ } else {
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, glob_snmp_object.enum_print);
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, glob_snmp_object.quick_print);
+ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, glob_snmp_object.oid_output_format);
+ }
}
/* }}} */
-/* {{{ proto string snmpget(string host, string community, string object_id [, int timeout [, int retries]])
+/* {{{ proto mixed snmpget(string host, string community, mixed object_id [, int timeout [, int retries]])
Fetch a SNMP object */
PHP_FUNCTION(snmpget)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_1);
}
/* }}} */
-/* {{{ proto string snmpgetnext(string host, string community, string object_id [, int timeout [, int retries]])
+/* {{{ proto mixed snmpgetnext(string host, string community, mixed object_id [, int timeout [, int retries]])
Fetch a SNMP object */
PHP_FUNCTION(snmpgetnext)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_1);
}
/* }}} */
-/* {{{ proto array snmpwalk(string host, string community, string object_id [, int timeout [, int retries]])
+/* {{{ proto mixed snmpwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
Return all objects under the specified object id */
PHP_FUNCTION(snmpwalk)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_1);
}
/* }}} */
-/* {{{ proto array snmprealwalk(string host, string community, string object_id [, int timeout [, int retries]])
+/* {{{ proto mixed snmprealwalk(string host, string community, mixed object_id [, int timeout [, int retries]])
Return all objects including their respective object id withing the specified one */
PHP_FUNCTION(snmprealwalk)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_1);
+}
+/* }}} */
+
+/* {{{ proto bool snmpset(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
+ Set the value of a SNMP object */
+PHP_FUNCTION(snmpset)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_1);
}
/* }}} */
@@ -877,478 +1578,913 @@ PHP_FUNCTION(snmp_get_quick_print)
return;
}
-#ifdef HAVE_NET_SNMP
RETURN_BOOL(netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT));
-#else
- RETURN_BOOL(snmp_get_quick_print());
-#endif
}
/* }}} */
-/* {{{ proto void snmp_set_quick_print(int quick_print)
+/* {{{ proto bool snmp_set_quick_print(int quick_print)
Return all objects including their respective object id withing the specified one */
PHP_FUNCTION(snmp_set_quick_print)
{
long a1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
- return;
+ RETURN_FALSE;
}
-#ifdef HAVE_NET_SNMP
- netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int) a1);
-#else
- snmp_set_quick_print((int)a1);
-#endif
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, (int)a1);
+ RETURN_TRUE;
}
/* }}} */
-#ifdef HAVE_NET_SNMP
-/* {{{ proto void snmp_set_enum_print(int enum_print)
+/* {{{ proto bool snmp_set_enum_print(int enum_print)
Return all values that are enums with their enum value instead of the raw integer */
PHP_FUNCTION(snmp_set_enum_print)
{
long a1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
- return;
+ RETURN_FALSE;
}
netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, (int) a1);
+ RETURN_TRUE;
}
/* }}} */
-/* {{{ proto void snmp_set_oid_output_format(int oid_format)
+/* {{{ proto bool snmp_set_oid_output_format(int oid_format)
Set the OID output format. */
PHP_FUNCTION(snmp_set_oid_output_format)
{
long a1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &a1) == FAILURE) {
- return;
+ RETURN_FALSE;
}
- switch ((int) a1) {
- case 0:
+ switch((int) a1) {
+ case NETSNMP_OID_OUTPUT_SUFFIX:
+ case NETSNMP_OID_OUTPUT_MODULE:
case NETSNMP_OID_OUTPUT_FULL:
- a1 = NETSNMP_OID_OUTPUT_FULL;
+ case NETSNMP_OID_OUTPUT_NUMERIC:
+ case NETSNMP_OID_OUTPUT_UCD:
+ case NETSNMP_OID_OUTPUT_NONE:
+ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
+ RETURN_TRUE;
break;
-
default:
- case NETSNMP_OID_OUTPUT_NUMERIC:
- a1 = NETSNMP_OID_OUTPUT_NUMERIC;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%d'", (int) a1);
+ RETURN_FALSE;
break;
}
-
- netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, a1);
}
/* }}} */
-#endif
-/* {{{ proto int snmpset(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]])
- Set the value of a SNMP object */
-PHP_FUNCTION(snmpset)
+/* {{{ proto mixed snmp2_get(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Fetch a SNMP object */
+PHP_FUNCTION(snmp2_get)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_2c);
}
/* }}} */
-/* {{{ int netsnmp_session_set_sec_name(struct snmp_session *s, char *name)
- Set the security name in the snmpv3 session */
-static int netsnmp_session_set_sec_name(struct snmp_session *s, char *name)
+/* {{{ proto mixed snmp2_getnext(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Fetch a SNMP object */
+PHP_FUNCTION(snmp2_getnext)
{
- if ((s) && (name)) {
- s->securityName = strdup(name);
- s->securityNameLen = strlen(s->securityName);
- return (0);
- }
- return (-1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
}
/* }}} */
-/* {{{ int netsnmp_session_set_sec_level(struct snmp_session *s, char *level)
- Set the security level in the snmpv3 session */
-static int netsnmp_session_set_sec_level(struct snmp_session *s, char *level TSRMLS_DC)
-{
- if ((s) && (level)) {
- if (!strcasecmp(level, "noAuthNoPriv") || !strcasecmp(level, "nanp")) {
- s->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
- return (0);
- } else if (!strcasecmp(level, "authNoPriv") || !strcasecmp(level, "anp")) {
- s->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
- return (0);
- } else if (!strcasecmp(level, "authPriv") || !strcasecmp(level, "ap")) {
- s->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
- return (0);
- }
- }
- return (-1);
+/* {{{ proto mixed snmp2_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Return all objects under the specified object id */
+PHP_FUNCTION(snmp2_walk)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_2c);
}
/* }}} */
-/* {{{ int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot)
- Set the authentication protocol in the snmpv3 session */
-static int netsnmp_session_set_auth_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
+/* {{{ proto mixed snmp2_real_walk(string host, string community, mixed object_id [, int timeout [, int retries]])
+ Return all objects including their respective object id withing the specified one */
+PHP_FUNCTION(snmp2_real_walk)
{
- if ((s) && (prot)) {
- if (!strcasecmp(prot, "MD5")) {
- s->securityAuthProto = usmHMACMD5AuthProtocol;
- s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
- return (0);
- } else if (!strcasecmp(prot, "SHA")) {
- s->securityAuthProto = usmHMACSHA1AuthProtocol;
- s->securityAuthProtoLen = OIDSIZE(usmHMACSHA1AuthProtocol);
- return (0);
- }
- }
- return (-1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_2c);
}
/* }}} */
-/* {{{ int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot)
- Set the security protocol in the snmpv3 session */
-static int netsnmp_session_set_sec_protocol(struct snmp_session *s, char *prot TSRMLS_DC)
+/* {{{ proto bool snmp2_set(string host, string community, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
+ Set the value of a SNMP object */
+PHP_FUNCTION(snmp2_set)
{
- if ((s) && (prot)) {
- if (!strcasecmp(prot, "DES")) {
- s->securityPrivProto = usmDESPrivProtocol;
- s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
- return (0);
-#ifdef HAVE_AES
- } else if (!strcasecmp(prot, "AES128")
-#ifdef SNMP_VALIDATE_ERR
-/*
-* In Net-SNMP before 5.2, the following symbols exist:
-* usmAES128PrivProtocol, usmAES192PrivProtocol, usmAES256PrivProtocol
-* In an effort to be more standards-compliant, 5.2 removed the last two.
-* As of 5.2, the symbols are:
-* usmAESPrivProtocol, usmAES128PrivProtocol
-*
-* As we want this extension to compile on both versions, we use the latter
-* symbol on purpose, as it's defined to be the same as the former.
-*
-* However, in 5.2 the type of usmAES128PrivProtocol is a pointer, not an
-* array, so we cannot use the OIDSIZE macro because it uses sizeof().
-*
-*/
- || !strcasecmp(prot, "AES")) {
- s->securityPrivProto = usmAES128PrivProtocol;
- s->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
- return (0);
-#else
- ) {
- s->securityPrivProto = usmAES128PrivProtocol;
- s->securityPrivProtoLen = OIDSIZE(usmAES128PrivProtocol);
- return (0);
- } else if (!strcasecmp(prot, "AES192")) {
- s->securityPrivProto = usmAES192PrivProtocol;
- s->securityPrivProtoLen = OIDSIZE(usmAES192PrivProtocol);
- return (0);
- } else if (!strcasecmp(prot, "AES256")) {
- s->securityPrivProto = usmAES256PrivProtocol;
- s->securityPrivProtoLen = OIDSIZE(usmAES256PrivProtocol);
- return (0);
-#endif
-#endif
- }
- }
- return (-1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_2c);
}
/* }}} */
-/* {{{ int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass)
- Make key from pass phrase in the snmpv3 session */
-static int netsnmp_session_gen_auth_key(struct snmp_session *s, char *pass TSRMLS_DC)
+/* {{{ proto mixed snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
+ Fetch the value of a SNMP object */
+PHP_FUNCTION(snmp3_get)
{
- /*
- * make master key from pass phrases
- */
- if ((s) && (pass) && strlen(pass)) {
- s->securityAuthKeyLen = USM_AUTH_KU_LEN;
- if (s->securityAuthProto == NULL) {
- /* get .conf set default */
- const oid *def = get_default_authtype(&(s->securityAuthProtoLen));
- s->securityAuthProto = snmp_duplicate_objid(def, s->securityAuthProtoLen);
- }
- if (s->securityAuthProto == NULL) {
- /* assume MD5 */
- s->securityAuthProto =
- snmp_duplicate_objid(usmHMACMD5AuthProtocol, OIDSIZE(usmHMACMD5AuthProtocol));
- s->securityAuthProtoLen = OIDSIZE(usmHMACMD5AuthProtocol);
- }
- if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
- (u_char *) pass, strlen(pass),
- s->securityAuthKey, &(s->securityAuthKeyLen)) != SNMPERR_SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for authentication pass phrase");
- return (-2);
- }
- return (0);
- }
- return (-1);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, SNMP_VERSION_3);
}
/* }}} */
-/* {{{ int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass)
- Make key from pass phrase in the snmpv3 session */
-static int netsnmp_session_gen_sec_key(struct snmp_session *s, u_char *pass TSRMLS_DC)
-{
- if ((s) && (pass) && strlen(pass)) {
- s->securityPrivKeyLen = USM_PRIV_KU_LEN;
- if (s->securityPrivProto == NULL) {
- /* get .conf set default */
- const oid *def = get_default_privtype(&(s->securityPrivProtoLen));
- s->securityPrivProto = snmp_duplicate_objid(def, s->securityPrivProtoLen);
- }
- if (s->securityPrivProto == NULL) {
- /* assume DES */
- s->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol,
- OIDSIZE(usmDESPrivProtocol));
- s->securityPrivProtoLen = OIDSIZE(usmDESPrivProtocol);
- }
- if (generate_Ku(s->securityAuthProto, s->securityAuthProtoLen,
- pass, strlen(pass),
- s->securityPrivKey, &(s->securityPrivKeyLen)) != SNMPERR_SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error generating a key for privacy pass phrase");
- return (-2);
- }
- return (0);
- }
- return (-1);
+/* {{{ proto mixed snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
+ Fetch the value of a SNMP object */
+PHP_FUNCTION(snmp3_getnext)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, SNMP_VERSION_3);
}
/* }}} */
-/* {{{ proto string snmp2_get(string host, string community, string object_id [, int timeout [, int retries]])
- Fetch a SNMP object */
-PHP_FUNCTION(snmp2_get)
+/* {{{ proto mixed snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
+ Fetch the value of a SNMP object */
+PHP_FUNCTION(snmp3_walk)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GET, SNMP_VERSION_2c);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, (SNMP_CMD_WALK | SNMP_NUMERIC_KEYS), SNMP_VERSION_3);
}
/* }}} */
-/* {{{ proto string snmp2_getnext(string host, string community, string object_id [, int timeout [, int retries]])
- Fetch a SNMP object */
-PHP_FUNCTION(snmp2_getnext)
+/* {{{ proto mixed snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id [, int timeout [, int retries]])
+ Fetch the value of a SNMP object */
+PHP_FUNCTION(snmp3_real_walk)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_GETNEXT, SNMP_VERSION_2c);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, SNMP_VERSION_3);
}
/* }}} */
-/* {{{ proto array snmp2_walk(string host, string community, string object_id [, int timeout [, int retries]])
- Return all objects under the specified object id */
-PHP_FUNCTION(snmp2_walk)
+/* {{{ proto bool snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, mixed object_id, mixed type, mixed value [, int timeout [, int retries]])
+ Fetch the value of a SNMP object */
+PHP_FUNCTION(snmp3_set)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_WALK, SNMP_VERSION_2c);
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, SNMP_VERSION_3);
}
/* }}} */
-/* {{{ proto array snmp2_real_walk(string host, string community, string object_id [, int timeout [, int retries]])
- Return all objects including their respective object id withing the specified one */
-PHP_FUNCTION(snmp2_real_walk)
+/* {{{ proto bool snmp_set_valueretrieval(int method)
+ Specify the method how the SNMP values will be returned */
+PHP_FUNCTION(snmp_set_valueretrieval)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_REALWALK, SNMP_VERSION_2c);
+ long method;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (method >= 0 && method <= (SNMP_VALUE_LIBRARY|SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT)) {
+ SNMP_G(valueretrieval) = method;
+ RETURN_TRUE;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", method);
+ RETURN_FALSE;
+ }
}
/* }}} */
-/* {{{ proto int snmp2_set(string host, string community, string object_id, string type, mixed value [, int timeout [, int retries]])
- Set the value of a SNMP object */
-PHP_FUNCTION(snmp2_set)
+/* {{{ proto int snmp_get_valueretrieval()
+ Return the method how the SNMP values will be returned */
+PHP_FUNCTION(snmp_get_valueretrieval)
{
- php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,SNMP_CMD_SET, SNMP_VERSION_2c);
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(SNMP_G(valueretrieval));
}
/* }}} */
-/* {{{ proto void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
-*
-* Generic SNMPv3 object fetcher
-* From here is passed on the common internal object fetcher.
-*
-* st=SNMP_CMD_GET snmp3_get() - query an agent and return a single value.
-* st=SNMP_CMD_GETNEXT snmp3_getnext() - query an agent and return the next single value.
-* st=SNMP_CMD_WALK snmp3_walk() - walk the mib and return a single dimensional array
-* containing the values.
-* st=SNMP_CMD_REALWALK snmp3_real_walk() - walk the mib and return an
-* array of oid,value pairs.
-* st=SNMP_CMD_SET snmp3_set() - query an agent and set a single value
-*
-*/
-static void php_snmpv3(INTERNAL_FUNCTION_PARAMETERS, int st)
+/* {{{ proto bool snmp_read_mib(string filename)
+ Reads and parses a MIB file into the active MIB tree. */
+PHP_FUNCTION(snmp_read_mib)
{
- char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
- int a1_len, a2_len, a3_len, a4_len, a5_len, a6_len, a7_len, a8_len;
- struct snmp_session session;
+ char *filename;
+ int filename_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (!read_mib(filename)) {
+ char *error = strerror(errno);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto SNMP SNMP::__construct(int version, string hostname, string community|securityName [, long timeout [, long retries]])
+ Creates a new SNMP session to specified host. */
+PHP_METHOD(snmp, __construct)
+{
+ php_snmp_object *snmp_object;
+ zval *object = getThis();
+ char *a1, *a2;
+ int a1_len, a2_len;
long timeout = SNMP_DEFAULT_TIMEOUT;
long retries = SNMP_DEFAULT_RETRIES;
- char type = (char) 0;
- char *value = (char *) 0, *stype = "";
- int stype_len, value_len;
- char hostname[MAX_NAME_LEN];
- int remote_port = 161;
- char *pptr;
+ long version = SNMP_DEFAULT_VERSION;
int argc = ZEND_NUM_ARGS();
+ zend_error_handling error_handling;
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+ zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
- if (st == SNMP_CMD_SET) {
- if (zend_parse_parameters(argc TSRMLS_CC, "ssssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
- &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &stype, &stype_len, &value, &value_len, &timeout, &retries) == FAILURE) {
- return;
- }
- } else {
- /* SNMP_CMD_GET
- * SNMP_CMD_GETNEXT
- * SNMP_CMD_WALK
- * SNMP_CMD_REALWALK
- */
- if (zend_parse_parameters(argc TSRMLS_CC, "ssssssss|ll", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
- &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len, &a8, &a8_len, &timeout, &retries) == FAILURE) {
- return;
- }
+ if (zend_parse_parameters(argc TSRMLS_CC, "lss|ll", &version, &a1, &a1_len, &a2, &a2_len, &timeout, &retries) == FAILURE) {
+ zend_restore_error_handling(&error_handling TSRMLS_CC);
+ return;
}
- snmp_sess_init(&session);
- /* This is all SNMPv3 */
- session.version = SNMP_VERSION_3;
+ zend_restore_error_handling(&error_handling TSRMLS_CC);
- /* Reading the hostname and its optional non-default port number */
- strlcpy(hostname, a1, sizeof(hostname));
- if ((pptr = strchr(hostname, ':'))) {
- remote_port = strtol(pptr + 1, NULL, 0);
+ switch(version) {
+ case SNMP_VERSION_1:
+ case SNMP_VERSION_2c:
+ case SNMP_VERSION_3:
+ break;
+ default:
+ zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Unknown SNMP protocol version", 0 TSRMLS_CC);
+ return;
}
- session.peername = hostname;
- session.remote_port = remote_port;
- /* Setting the security name. */
- if (netsnmp_session_set_sec_name(&session, a2)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could net set security name: %s", a2);
- RETURN_FALSE;
+ /* handle re-open of snmp session */
+ if (snmp_object->session) {
+ netsnmp_session_free(&(snmp_object->session));
+ }
+
+ if (netsnmp_session_init(&(snmp_object->session), version, a1, a2, timeout, retries TSRMLS_CC)) {
+ return;
}
+ snmp_object->max_oids = 0;
+ snmp_object->valueretrieval = SNMP_G(valueretrieval);
+ snmp_object->enum_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM);
+ snmp_object->oid_output_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT);
+ snmp_object->quick_print = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT);
+ snmp_object->oid_increasing_check = TRUE;
+ snmp_object->exceptions_enabled = 0;
+}
+/* }}} */
- /* Setting the security level. */
- if (netsnmp_session_set_sec_level(&session, a3 TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security level: %s", a3);
+/* {{{ proto bool SNMP::close()
+ Close SNMP session */
+PHP_METHOD(snmp, close)
+{
+ php_snmp_object *snmp_object;
+ zval *object = getThis();
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+
+ if (zend_parse_parameters_none() == FAILURE) {
RETURN_FALSE;
}
- /* Setting the authentication protocol. */
- if (netsnmp_session_set_auth_protocol(&session, a4 TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid authentication protocol: %s", a4);
+ netsnmp_session_free(&(snmp_object->session));
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto mixed SNMP::get(mixed object_id [, bool preserve_keys])
+ Fetch a SNMP object returing scalar for single OID and array of oid->value pairs for multi OID request */
+PHP_METHOD(snmp, get)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET, (-1));
+}
+/* }}} */
+
+/* {{{ proto mixed SNMP::getnext(mixed object_id)
+ Fetch a SNMP object returing scalar for single OID and array of oid->value pairs for multi OID request */
+PHP_METHOD(snmp, getnext)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT, (-1));
+}
+/* }}} */
+
+/* {{{ proto mixed SNMP::walk(mixed object_id [, bool $suffix_as_key = FALSE [, int $max_repetitions [, int $non_repeaters]])
+ Return all objects including their respective object id withing the specified one as array of oid->value pairs */
+PHP_METHOD(snmp, walk)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK, (-1));
+}
+/* }}} */
+
+/* {{{ proto bool SNMP::set(mixed object_id, mixed type, mixed value)
+ Set the value of a SNMP object */
+PHP_METHOD(snmp, set)
+{
+ php_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET, (-1));
+}
+
+/* {{{ proto bool SNMP::setSecurity(string sec_level, [ string auth_protocol, string auth_passphrase [, string priv_protocol, string priv_passphrase [, string contextName [, string contextEngineID]]]])
+ Set SNMPv3 security-related session parameters */
+PHP_METHOD(snmp, setSecurity)
+{
+ php_snmp_object *snmp_object;
+ zval *object = getThis();
+ char *a1 = "", *a2 = "", *a3 = "", *a4 = "", *a5 = "", *a6 = "", *a7 = "";
+ int a1_len = 0, a2_len = 0, a3_len = 0, a4_len = 0, a5_len = 0, a6_len = 0, a7_len = 0;
+ int argc = ZEND_NUM_ARGS();
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+
+ if (zend_parse_parameters(argc TSRMLS_CC, "s|ssssss", &a1, &a1_len, &a2, &a2_len, &a3, &a3_len,
+ &a4, &a4_len, &a5, &a5_len, &a6, &a6_len, &a7, &a7_len) == FAILURE) {
RETURN_FALSE;
}
- /* Setting the authentication passphrase. */
- if (netsnmp_session_gen_auth_key(&session, a5 TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for authentication pass phrase: %s", a5);
+ if (netsnmp_session_set_security(snmp_object->session, a1, a2, a3, a4, a5, a6, a7 TSRMLS_CC)) {
+ /* Warning message sent already, just bail out */
RETURN_FALSE;
}
+ RETURN_TRUE;
+}
+/* }}} */
- /* Setting the security protocol. */
- if (netsnmp_session_set_sec_protocol(&session, a6 TSRMLS_CC) && a6_len) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid security protocol: %s", a6);
- RETURN_FALSE;
+/* {{{ proto long SNMP::getErrno()
+ Get last error code number */
+PHP_METHOD(snmp, getErrno)
+{
+ php_snmp_object *snmp_object;
+ zval *object = getThis();
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+
+ RETVAL_LONG(snmp_object->snmp_errno);
+ return;
+}
+/* }}} */
+
+/* {{{ proto long SNMP::getError()
+ Get last error message */
+PHP_METHOD(snmp, getError)
+{
+ php_snmp_object *snmp_object;
+ zval *object = getThis();
+
+ snmp_object = (php_snmp_object *)zend_object_store_get_object(object TSRMLS_CC);
+
+ RETVAL_STRING(snmp_object->snmp_errstr, 1);
+ return;
+}
+/* }}} */
+
+/* {{{ */
+void php_snmp_add_property(HashTable *h, const char *name, size_t name_length, php_snmp_read_t read_func, php_snmp_write_t write_func TSRMLS_DC)
+{
+ php_snmp_prop_handler p;
+
+ p.name = (char*) name;
+ p.name_length = name_length;
+ p.read_func = (read_func) ? read_func : NULL;
+ p.write_func = (write_func) ? write_func : NULL;
+ zend_hash_add(h, (char *)name, name_length + 1, &p, sizeof(php_snmp_prop_handler), NULL);
+}
+/* }}} */
+
+/* {{{ php_snmp_read_property(zval *object, zval *member, int type[, const zend_literal *key])
+ Generic object property reader */
+zval *php_snmp_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
+{
+ zval tmp_member;
+ zval *retval;
+ php_snmp_object *obj;
+ php_snmp_prop_handler *hnd;
+ int ret;
+
+ ret = FAILURE;
+ obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
+
+ if (Z_TYPE_P(member) != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
}
- /* Setting the security protocol passphrase. */
- if (netsnmp_session_gen_sec_key(&session, a7 TSRMLS_CC) && a7_len) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not generate key for security pass phrase: %s", a7);
- RETURN_FALSE;
+ ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+
+ if (ret == SUCCESS && hnd->read_func) {
+ ret = hnd->read_func(obj, &retval TSRMLS_CC);
+ if (ret == SUCCESS) {
+ /* ensure we're creating a temporary variable */
+ Z_SET_REFCOUNT_P(retval, 0);
+ } else {
+ retval = EG(uninitialized_zval_ptr);
+ }
+ } else {
+ zend_object_handlers * std_hnd = zend_get_std_object_handlers();
+ retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
+ }
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
}
+ return(retval);
+}
+/* }}} */
- if (st == SNMP_CMD_SET) {
- type = stype[0];
+/* {{{ php_snmp_write_property(zval *object, zval *member, zval *value[, const zend_literal *key])
+ Generic object property writer */
+void php_snmp_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
+{
+ zval tmp_member;
+ php_snmp_object *obj;
+ php_snmp_prop_handler *hnd;
+ int ret;
+
+ if (Z_TYPE_P(member) != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
}
- session.retries = retries;
- session.timeout = timeout;
+ ret = FAILURE;
+ obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
+
+ ret = zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &hnd);
- php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, &session, a8, type, value);
+ if (ret == SUCCESS && hnd->write_func) {
+ hnd->write_func(obj, value TSRMLS_CC);
+ if (! PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) == 0) {
+ Z_ADDREF_P(value);
+ zval_ptr_dtor(&value);
+ }
+ } else {
+ zend_object_handlers * std_hnd = zend_get_std_object_handlers();
+ std_hnd->write_property(object, member, value, key TSRMLS_CC);
+ }
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
}
/* }}} */
-/* {{{ proto int snmp3_get(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
- Fetch the value of a SNMP object */
-PHP_FUNCTION(snmp3_get)
+/* {{{ php_snmp_has_property(zval *object, zval *member, int has_set_exists[, const zend_literal *key])
+ Generic object property checker */
+static int php_snmp_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC)
{
- php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GET);
+ php_snmp_prop_handler *hnd;
+ int ret = 0;
+
+ if (zend_hash_find(&php_snmp_properties, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&hnd) == SUCCESS) {
+ switch (has_set_exists) {
+ case 2:
+ ret = 1;
+ break;
+ case 0: {
+ zval *value = php_snmp_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
+ if (value != EG(uninitialized_zval_ptr)) {
+ ret = Z_TYPE_P(value) != IS_NULL? 1:0;
+ /* refcount is 0 */
+ Z_ADDREF_P(value);
+ zval_ptr_dtor(&value);
+ }
+ break;
+ }
+ default: {
+ zval *value = php_snmp_read_property(object, member, BP_VAR_IS, key TSRMLS_CC);
+ if (value != EG(uninitialized_zval_ptr)) {
+ convert_to_boolean(value);
+ ret = Z_BVAL_P(value)? 1:0;
+ /* refcount is 0 */
+ Z_ADDREF_P(value);
+ zval_ptr_dtor(&value);
+ }
+ break;
+ }
+ }
+ } else {
+ zend_object_handlers * std_hnd = zend_get_std_object_handlers();
+ ret = std_hnd->has_property(object, member, has_set_exists, key TSRMLS_CC);
+ }
+ return ret;
}
/* }}} */
-/* {{{ proto int snmp3_getnext(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
- Fetch the value of a SNMP object */
-PHP_FUNCTION(snmp3_getnext)
+/* {{{ php_snmp_get_properties(zval *object)
+ Returns all object properties. Injects SNMP properties into object on first call */
+static HashTable *php_snmp_get_properties(zval *object TSRMLS_DC)
{
- php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_GETNEXT);
+ php_snmp_object *obj;
+ php_snmp_prop_handler *hnd;
+ HashTable *props;
+ zval *val;
+ char *key;
+ uint key_len;
+ HashPosition pos;
+ ulong num_key;
+
+ obj = (php_snmp_object *)zend_objects_get_address(object TSRMLS_CC);
+ props = zend_std_get_properties(object TSRMLS_CC);
+
+ zend_hash_internal_pointer_reset_ex(&php_snmp_properties, &pos);
+
+ while (zend_hash_get_current_data_ex(&php_snmp_properties, (void**)&hnd, &pos) == SUCCESS) {
+ zend_hash_get_current_key_ex(&php_snmp_properties, &key, &key_len, &num_key, 0, &pos);
+ if (!hnd->read_func || hnd->read_func(obj, &val TSRMLS_CC) != SUCCESS) {
+ val = EG(uninitialized_zval_ptr);
+ Z_ADDREF_P(val);
+ }
+ zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
+ zend_hash_move_forward_ex(&php_snmp_properties, &pos);
+ }
+ return obj->zo.properties;
}
/* }}} */
-/* {{{ proto int snmp3_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
- Fetch the value of a SNMP object */
-PHP_FUNCTION(snmp3_walk)
+/* {{{ */
+static int php_snmp_read_info(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
{
- php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_WALK);
+ zval *val;
+
+ MAKE_STD_ZVAL(*retval);
+ array_init(*retval);
+
+ if (snmp_object->session == NULL) {
+ return SUCCESS;
+ }
+
+ MAKE_STD_ZVAL(val);
+ ZVAL_STRINGL(val, snmp_object->session->peername, strlen(snmp_object->session->peername), 1);
+ add_assoc_zval(*retval, "hostname", val);
+
+ MAKE_STD_ZVAL(val);
+ ZVAL_LONG(val, snmp_object->session->remote_port);
+ add_assoc_zval(*retval, "port", val);
+
+ MAKE_STD_ZVAL(val);
+ ZVAL_LONG(val, snmp_object->session->timeout);
+ add_assoc_zval(*retval, "timeout", val);
+
+ MAKE_STD_ZVAL(val);
+ ZVAL_LONG(val, snmp_object->session->retries);
+ add_assoc_zval(*retval, "retries", val);
+
+ return SUCCESS;
}
/* }}} */
-/* {{{ proto int snmp3_real_walk(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id [, int timeout [, int retries]])
- Fetch the value of a SNMP object */
-PHP_FUNCTION(snmp3_real_walk)
+/* {{{ */
+static int php_snmp_read_max_oids(php_snmp_object *snmp_object, zval **retval TSRMLS_DC)
{
- php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_REALWALK);
+ MAKE_STD_ZVAL(*retval);
+ if (snmp_object->max_oids > 0) {
+ ZVAL_LONG(*retval, snmp_object->max_oids);
+ } else {
+ ZVAL_NULL(*retval);
+ }
+ return SUCCESS;
}
/* }}} */
-/* {{{ proto int snmp3_set(string host, string sec_name, string sec_level, string auth_protocol, string auth_passphrase, string priv_protocol, string priv_passphrase, string object_id, string type, mixed value [, int timeout [, int retries]])
- Fetch the value of a SNMP object */
-PHP_FUNCTION(snmp3_set)
+#define PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(name) \
+ static int php_snmp_read_##name(php_snmp_object *snmp_object, zval **retval TSRMLS_DC) \
+ { \
+ MAKE_STD_ZVAL(*retval); \
+ ZVAL_BOOL(*retval, snmp_object->name); \
+ return SUCCESS; \
+ }
+
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(oid_increasing_check)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(quick_print)
+PHP_SNMP_BOOL_PROPERTY_READER_FUNCTION(enum_print)
+
+#define PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(name) \
+ static int php_snmp_read_##name(php_snmp_object *snmp_object, zval **retval TSRMLS_DC) \
+ { \
+ MAKE_STD_ZVAL(*retval); \
+ ZVAL_LONG(*retval, snmp_object->name); \
+ return SUCCESS; \
+ }
+
+PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(valueretrieval)
+PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(oid_output_format)
+PHP_SNMP_LONG_PROPERTY_READER_FUNCTION(exceptions_enabled)
+
+/* {{{ */
+static int php_snmp_write_info(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
{
- php_snmpv3(INTERNAL_FUNCTION_PARAM_PASSTHRU, SNMP_CMD_SET);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "info property is read-only");
+ return FAILURE;
}
/* }}} */
-/* {{{ proto void snmp_set_valueretrieval(int method)
- Specify the method how the SNMP values will be returned */
-PHP_FUNCTION(snmp_set_valueretrieval)
+/* {{{ */
+static int php_snmp_write_max_oids(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
{
- long method;
+ zval ztmp;
+ int ret = SUCCESS;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
- return;
+ if (Z_TYPE_P(newval) == IS_NULL) {
+ snmp_object->max_oids = 0;
+ return ret;
+ }
+
+ if (Z_TYPE_P(newval) != IS_LONG) {
+ ztmp = *newval;
+ zval_copy_ctor(&ztmp);
+ convert_to_long(&ztmp);
+ newval = &ztmp;
}
- if ((method == SNMP_VALUE_LIBRARY) || (method == SNMP_VALUE_PLAIN) || (method == SNMP_VALUE_OBJECT)) {
- SNMP_G(valueretrieval) = method;
+ if (Z_LVAL_P(newval) > 0) {
+ snmp_object->max_oids = Z_LVAL_P(newval);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "max_oids should be positive integer or NULL, got %ld", Z_LVAL_P(newval));
}
+
+ if (newval == &ztmp) {
+ zval_dtor(newval);
+ }
+
+ return ret;
}
/* }}} */
-/* {{{ proto int snmp_get_valueretrieval()
- Return the method how the SNMP values will be returned */
-PHP_FUNCTION(snmp_get_valueretrieval)
+/* {{{ */
+static int php_snmp_write_valueretrieval(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
{
- RETURN_LONG(SNMP_G(valueretrieval));
+ zval ztmp;
+ int ret = SUCCESS;
+
+ if (Z_TYPE_P(newval) != IS_LONG) {
+ ztmp = *newval;
+ zval_copy_ctor(&ztmp);
+ convert_to_long(&ztmp);
+ newval = &ztmp;
+ }
+
+ if (Z_LVAL_P(newval) >= 0 && Z_LVAL_P(newval) <= (SNMP_VALUE_LIBRARY|SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT)) {
+ snmp_object->valueretrieval = Z_LVAL_P(newval);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP value retrieval method '%ld'", Z_LVAL_P(newval));
+ ret = FAILURE;
+ }
+
+ if (newval == &ztmp) {
+ zval_dtor(newval);
+ }
+
+ return ret;
}
/* }}} */
-/* {{{ proto int snmp_read_mib(string filename)
- Reads and parses a MIB file into the active MIB tree. */
-PHP_FUNCTION(snmp_read_mib)
+#define PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(name) \
+static int php_snmp_write_##name(php_snmp_object *snmp_object, zval *newval TSRMLS_DC) \
+{ \
+ zval ztmp; \
+ if (Z_TYPE_P(newval) != IS_BOOL) { \
+ ztmp = *newval; \
+ zval_copy_ctor(&ztmp); \
+ convert_to_boolean(&ztmp); \
+ newval = &ztmp; \
+ } \
+\
+ snmp_object->name = Z_LVAL_P(newval); \
+\
+ if (newval == &ztmp) { \
+ zval_dtor(newval); \
+ } \
+ return SUCCESS; \
+}
+
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(quick_print)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(enum_print)
+PHP_SNMP_BOOL_PROPERTY_WRITER_FUNCTION(oid_increasing_check)
+
+/* {{{ */
+static int php_snmp_write_oid_output_format(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
{
- char *filename;
- int filename_len;
+ zval ztmp;
+ int ret = SUCCESS;
+ if (Z_TYPE_P(newval) != IS_LONG) {
+ ztmp = *newval;
+ zval_copy_ctor(&ztmp);
+ convert_to_long(&ztmp);
+ newval = &ztmp;
+ }
+
+ switch(Z_LVAL_P(newval)) {
+ case NETSNMP_OID_OUTPUT_SUFFIX:
+ case NETSNMP_OID_OUTPUT_MODULE:
+ case NETSNMP_OID_OUTPUT_FULL:
+ case NETSNMP_OID_OUTPUT_NUMERIC:
+ case NETSNMP_OID_OUTPUT_UCD:
+ case NETSNMP_OID_OUTPUT_NONE:
+ snmp_object->oid_output_format = Z_LVAL_P(newval);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown SNMP output print format '%ld'", Z_LVAL_P(newval));
+ ret = FAILURE;
+ break;
+ }
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
- return;
+ if (newval == &ztmp) {
+ zval_dtor(newval);
}
+ return ret;
+}
+/* }}} */
- /* Prevent read_mib() from printing any errors. */
- snmp_disable_stderrlog();
-
- if (!read_mib(filename)) {
- char *error = strerror(errno);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading MIB file '%s': %s", filename, error);
- RETURN_FALSE;
+/* {{{ */
+static int php_snmp_write_exceptions_enabled(php_snmp_object *snmp_object, zval *newval TSRMLS_DC)
+{
+ zval ztmp;
+ int ret = SUCCESS;
+ if (Z_TYPE_P(newval) != IS_LONG) {
+ ztmp = *newval;
+ zval_copy_ctor(&ztmp);
+ convert_to_long(&ztmp);
+ newval = &ztmp;
}
- RETURN_TRUE;
+
+ snmp_object->exceptions_enabled = Z_LVAL_P(newval);
+
+ if (newval == &ztmp) {
+ zval_dtor(newval);
+ }
+ return ret;
}
/* }}} */
+/* {{{ php_snmp_class_methods[] */
+static zend_function_entry php_snmp_class_methods[] = {
+ PHP_ME(snmp, __construct, arginfo_snmp_create, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, close, arginfo_snmp_void, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, setSecurity, arginfo_snmp_setSecurity, ZEND_ACC_PUBLIC)
+
+ PHP_ME(snmp, get, arginfo_snmp_get, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, getnext, arginfo_snmp_get, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, walk, arginfo_snmp_walk, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, set, arginfo_snmp_set, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, getErrno, arginfo_snmp_void, ZEND_ACC_PUBLIC)
+ PHP_ME(snmp, getError, arginfo_snmp_void, ZEND_ACC_PUBLIC)
+
+ PHP_FE_END
+};
+
+#define PHP_SNMP_PROPERTY_ENTRY_RECORD(name) \
+ { "" #name "", sizeof("" #name "") - 1, php_snmp_read_##name, php_snmp_write_##name }
+
+const php_snmp_prop_handler php_snmp_property_entries[] = {
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(info),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(max_oids),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(valueretrieval),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(quick_print),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(enum_print),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_output_format),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(oid_increasing_check),
+ PHP_SNMP_PROPERTY_ENTRY_RECORD(exceptions_enabled),
+ { NULL, 0, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(snmp)
+{
+ netsnmp_log_handler *logh;
+ zend_class_entry ce, cex;
+
+ le_snmp_session = zend_register_list_destructors_ex(php_snmp_session_destructor, NULL, PHP_SNMP_SESSION_RES_NAME, module_number);
+
+ init_snmp("snmpapp");
+
+#ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE
+ /* Prevent update of the snmpapp.conf file */
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1);
+#endif
+
+ /* Disable logging, use exit status'es and related variabled to detect errors */
+ shutdown_snmp_logging();
+ logh = netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_ERR);
+ if (logh) {
+ logh->pri_max = LOG_ERR;
+ }
+
+ memcpy(&php_snmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_snmp_object_handlers.read_property = php_snmp_read_property;
+ php_snmp_object_handlers.write_property = php_snmp_write_property;
+ php_snmp_object_handlers.has_property = php_snmp_has_property;
+ php_snmp_object_handlers.get_properties = php_snmp_get_properties;
+
+ /* Register SNMP Class */
+ INIT_CLASS_ENTRY(ce, "SNMP", php_snmp_class_methods);
+ ce.create_object = php_snmp_object_new;
+ php_snmp_object_handlers.clone_obj = NULL;
+ php_snmp_ce = zend_register_internal_class(&ce TSRMLS_CC);
+
+ /* Register SNMP Class properties */
+ zend_hash_init(&php_snmp_properties, 0, NULL, NULL, 1);
+ PHP_SNMP_ADD_PROPERTIES(&php_snmp_properties, php_snmp_property_entries);
+
+ REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_SUFFIX", NETSNMP_OID_OUTPUT_SUFFIX, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_MODULE", NETSNMP_OID_OUTPUT_MODULE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_FULL", NETSNMP_OID_OUTPUT_FULL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NUMERIC", NETSNMP_OID_OUTPUT_NUMERIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_UCD", NETSNMP_OID_OUTPUT_UCD, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OID_OUTPUT_NONE", NETSNMP_OID_OUTPUT_NONE, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("SNMP_VALUE_LIBRARY", SNMP_VALUE_LIBRARY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_VALUE_PLAIN", SNMP_VALUE_PLAIN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_VALUE_OBJECT", SNMP_VALUE_OBJECT, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("SNMP_BIT_STR", ASN_BIT_STR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OCTET_STR", ASN_OCTET_STR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OPAQUE", ASN_OPAQUE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_NULL", ASN_NULL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_OBJECT_ID", ASN_OBJECT_ID, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_IPADDRESS", ASN_IPADDRESS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_COUNTER", ASN_GAUGE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_UNSIGNED", ASN_UNSIGNED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_TIMETICKS", ASN_TIMETICKS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_UINTEGER", ASN_UINTEGER, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_INTEGER", ASN_INTEGER, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SNMP_COUNTER64", ASN_COUNTER64, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_SNMP_CLASS_CONST_LONG("VERSION_1", SNMP_VERSION_1);
+ REGISTER_SNMP_CLASS_CONST_LONG("VERSION_2c", SNMP_VERSION_2c);
+ REGISTER_SNMP_CLASS_CONST_LONG("VERSION_2C", SNMP_VERSION_2c);
+ REGISTER_SNMP_CLASS_CONST_LONG("VERSION_3", SNMP_VERSION_3);
+
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_NOERROR", PHP_SNMP_ERRNO_NOERROR);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ANY", PHP_SNMP_ERRNO_ANY);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_GENERIC", PHP_SNMP_ERRNO_GENERIC);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_TIMEOUT", PHP_SNMP_ERRNO_TIMEOUT);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_ERROR_IN_REPLY", PHP_SNMP_ERRNO_ERROR_IN_REPLY);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_NOT_INCREASING", PHP_SNMP_ERRNO_OID_NOT_INCREASING);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_OID_PARSING_ERROR", PHP_SNMP_ERRNO_OID_PARSING_ERROR);
+ REGISTER_SNMP_CLASS_CONST_LONG("ERRNO_MULTIPLE_SET_QUERIES", PHP_SNMP_ERRNO_MULTIPLE_SET_QUERIES);
+
+ /* Register SNMPException class */
+ INIT_CLASS_ENTRY(cex, "SNMPException", NULL);
+#ifdef HAVE_SPL
+ php_snmp_exception_ce = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException, NULL TSRMLS_CC);
+#else
+ php_snmp_exception_ce = zend_register_internal_class_ex(&cex, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
+#endif
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(snmp)
+{
+ snmp_shutdown("snmpapp");
+
+ zend_hash_destroy(&php_snmp_properties);
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(snmp)
+{
+ php_info_print_table_start();
+ php_info_print_table_row(2, "NET-SNMP Support", "enabled");
+ php_info_print_table_row(2, "NET-SNMP Version", netsnmp_get_version());
+ php_info_print_table_row(2, "PHP SNMP Version", PHP_SNMP_VERSION);
+ php_info_print_table_end();
+}
+/* }}} */
+
+/* {{{ snmp_module_deps[]
+ */
+static const zend_module_dep snmp_module_deps[] = {
+#ifdef HAVE_SPL
+ ZEND_MOD_REQUIRED("spl")
+#endif
+ ZEND_MOD_END
+};
+/* }}} */
+
+/* {{{ snmp_module_entry
+ */
+zend_module_entry snmp_module_entry = {
+ STANDARD_MODULE_HEADER_EX,
+ NULL,
+ snmp_module_deps,
+ "snmp",
+ snmp_functions,
+ PHP_MINIT(snmp),
+ PHP_MSHUTDOWN(snmp),
+ NULL,
+ NULL,
+ PHP_MINFO(snmp),
+ PHP_SNMP_VERSION,
+ PHP_MODULE_GLOBALS(snmp),
+ PHP_GINIT(snmp),
+ NULL,
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+/* }}} */
+
#endif
/*
diff --git a/ext/snmp/tests/README b/ext/snmp/tests/README
new file mode 100644
index 0000000000..819a50d8a2
--- /dev/null
+++ b/ext/snmp/tests/README
@@ -0,0 +1,46 @@
+SNMP Tests
+----------
+
+To enable these tests, you must have :
+- PHP compiled with SNMP (--with-snmp)
+- an SNMP server running.
+
+
+** How to test **
+You need to give credentials with environment vars if default ones are not
+sutable (see snmp_include.inc for more info):
+SNMP_HOSTNAME : IPv4 of remote SNMP agent
+SNMP_HOSTNAME : IPv6 or remote SNMP agent
+SNMP_PORT : SNMP port for queries
+SNMP_COMMUNITY : community name
+SNMP_COMMUNITY_WRITE : community used for write tests (snmpset()).
+SNMP_MIBDIR : Directory containing MIBS
+
+To run test suite you may use this command (presuming that you pwd is where
+this README file is located):
+> make -C ../../.. test TESTS="`cd ../../..; /bin/ls -1 ext/snmp/tests/*.phpt | xargs echo`"
+Running run-tests.php directly will clear your environment and therefore
+tests will fail if your SNMP configuration does not fit into default values
+specified in snmp_include.inc.
+
+** Configuring the SNMPD server **
+
+On Linux/FreeBSD
+--------
+
+- Install package net-snmpd (name may differ based on your distribution).
+- Replace config file (by default this is /etc/snmp/snmpd.conf on Linux and
+ /usr/local/etc/snmp/snmpd.conf on FreeBSD) with snmpd.conf supplied.
+
+Before launching daemon make sure that there is no file /var/net-snmp/snmpd.conf
+Delete it if exists. Ingoring to to so will fail SNMPv3 tests.
+
+- Launch snmpd (service snmpd start or /etc/init.d/snmpd start).
+ Alternatively you can start snmpd daemon using following command line:
+ sudo snmpd -C -c ./snmpd.conf -f -Le
+
+
+On Windows
+----------
+
+[to be completed]
diff --git a/ext/snmp/tests/bug60749.phpt b/ext/snmp/tests/bug60749.phpt
new file mode 100644
index 0000000000..302f351c10
--- /dev/null
+++ b/ext/snmp/tests/bug60749.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #60749: SNMP module should not strip non-standard SNMP port from hostname
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+$hostname = "php.net";
+$ip = gethostbyname($hostname);
+if (ip2long($ip) === FALSE) {
+ echo "Could not resolve $hostname properly!\n";
+ exit(1);
+}
+$port = 1161;
+$session = new SNMP(SNMP::VERSION_1, "$hostname:$port", $community, $timeout, $retries);
+$info = $session->info;
+if (strcmp($info["hostname"], "$ip:$port") !== 0) {
+ echo "'" . $info["hostname"] . "' != '$ip:$port'\n";
+}
+var_dump($session->close());
+?>
+--EXPECTF--
+bool(true)
diff --git a/ext/snmp/tests/clean.inc b/ext/snmp/tests/clean.inc
new file mode 100644
index 0000000000..70ac0f5b59
--- /dev/null
+++ b/ext/snmp/tests/clean.inc
@@ -0,0 +1,4 @@
+<?php
+include_once(dirname(__FILE__) . '/snmp_include.inc');
+
+// To be completed if necessary
diff --git a/ext/snmp/tests/generic_timeout_error.phpt b/ext/snmp/tests/generic_timeout_error.phpt
new file mode 100644
index 0000000000..c333a0d20b
--- /dev/null
+++ b/ext/snmp/tests/generic_timeout_error.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Generic timeout (wrong community)
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+var_dump(snmpget($hostname, 'timeout_community_432', '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+var_dump(snmpget($hostname, 'timeout_community_432', array('.1.3.6.1.2.1.1.1.0'), $timeout, $retries));
+
+?>
+--EXPECTF--
+Warning: snmpget(): No response from %s in %s on line %d
+bool(false)
+
+Warning: snmpget(): No response from %s in %s on line %d
+bool(false)
+
diff --git a/ext/snmp/tests/ipv6.phpt b/ext/snmp/tests/ipv6.phpt
new file mode 100644
index 0000000000..12879416c6
--- /dev/null
+++ b/ext/snmp/tests/ipv6.phpt
@@ -0,0 +1,25 @@
+--TEST--
+IPv6 support
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+
+$packed = str_repeat(chr(0), 15) . chr(1);
+if (@inet_ntop($packed) === false) {
+ die("skip no IPv6 support");
+}
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+var_dump(snmpget($hostname6_port, $community, '.1.3.6.1.2.1.1.1.0'));
+?>
+--EXPECTF--
+%unicode|string%(%d) "%s"
diff --git a/ext/snmp/tests/skipif.inc b/ext/snmp/tests/skipif.inc
new file mode 100644
index 0000000000..4d37902636
--- /dev/null
+++ b/ext/snmp/tests/skipif.inc
@@ -0,0 +1,13 @@
+<?php
+extension_loaded('snmp') or die('skip snmp extension not available in this build');
+
+require_once (dirname(__FILE__).'/snmp_include.inc');
+
+//test server is available
+// this require snmpget to work ...
+//snmpget ( string $hostname , string $community ,
+//string $object_id [, int $timeout [, int $retries ]] )
+
+if (snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout) === false)
+ die('NO SNMPD on this host or community invalid');
+
diff --git a/ext/snmp/tests/snmp-object-errno-errstr.phpt b/ext/snmp/tests/snmp-object-errno-errstr.phpt
new file mode 100644
index 0000000000..b6047af857
--- /dev/null
+++ b/ext/snmp/tests/snmp-object-errno-errstr.phpt
@@ -0,0 +1,147 @@
+--TEST--
+OO API: getErrno & getError methods
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_enum_print(false);
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+snmp_set_oid_output_format(SNMP_OID_OUTPUT_FULL);
+
+echo "SNMP::ERRNO_NOERROR\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump(@$session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getErrno() == SNMP::ERRNO_NOERROR);
+var_dump($session->getError());
+$session->close();
+
+echo "SNMP::ERRNO_TIMEOUT\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, 'timeout_community_432', $timeout, $retries);
+$session->valueretrieval = SNMP_VALUE_LIBRARY;
+var_dump(@$session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getErrno() == SNMP::ERRNO_TIMEOUT);
+var_dump($session->getError());
+$session->close();
+
+echo "SNMP::ERRNO_ERROR_IN_REPLY\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump(@$session->get('.1.3.6.1.2.1.1.1.110'));
+var_dump($session->getErrno() == SNMP::ERRNO_ERROR_IN_REPLY);
+var_dump($session->getError());
+$session->close();
+
+echo "SNMP::ERRNO_GENERIC\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, 'somebogususer', $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+var_dump(@$session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getErrno() == SNMP::ERRNO_GENERIC);
+var_dump($session->getError());
+var_dump(@$session->get(array('.1.3.6.1.2.1.1.1.0')));
+$session->close();
+
+echo "SNMP::ERRNO_OID_PARSING_ERROR\n";
+echo "GET: Single wrong OID\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump(@$session->get('.1.3.6.1.2..1.1.1.0'));
+var_dump($session->getErrno() == SNMP::ERRNO_OID_PARSING_ERROR);
+var_dump($session->getError());
+$session->close();
+echo "GET: Miltiple OID, one wrong\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump(@$session->get(array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2..1.1.1.0')));
+var_dump($session->getErrno() == SNMP::ERRNO_OID_PARSING_ERROR);
+var_dump($session->getError());
+$session->close();
+echo "WALK: Single wrong OID\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump(@$session->walk('.1.3.6.1.2..1.1'));
+var_dump($session->getErrno() == SNMP::ERRNO_OID_PARSING_ERROR);
+var_dump($session->getError());
+$session->close();
+echo "SET: Wrong type\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+$oid1 = 'SNMPv2-MIB::sysContact.0';
+var_dump(@$session->set($oid1, 'q', 'blah'));
+var_dump($session->getErrno() == SNMP::ERRNO_OID_PARSING_ERROR);
+var_dump($session->getError());
+
+echo "SNMP::ERRNO_MULTIPLE_SET_QUERIES\n";
+$oid1 = 'SNMPv2-MIB::sysContact.0';
+$oid2 = 'SNMPv2-MIB::sysLocation.0';
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+$session->max_oids = 1;
+$oldvalue1 = $session->get($oid1);
+$newvalue1 = $oldvalue1 . '0';
+$oldvalue2 = $session->get($oid2);
+$newvalue2 = $oldvalue2 . '0';
+$z = @$session->set(array($oid1, $oid2), array('s','s'), array($newvalue1, $newvalue2));
+var_dump($z);
+var_dump($session->getErrno() == SNMP::ERRNO_MULTIPLE_SET_QUERIES);
+var_dump($session->getError());
+var_dump(($session->get($oid1) === $newvalue1));
+var_dump(($session->get($oid2) === $newvalue2));
+$z = @$session->set(array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2));
+var_dump($z);
+var_dump($session->getErrno() == SNMP::ERRNO_MULTIPLE_SET_QUERIES);
+var_dump($session->getError());
+var_dump(($session->get($oid1) === $oldvalue1));
+var_dump(($session->get($oid2) === $oldvalue2));
+var_dump($session->close());
+?>
+--EXPECTF--
+SNMP::ERRNO_NOERROR
+%string|unicode%(%d) "%s"
+bool(true)
+%string|unicode%(0) ""
+SNMP::ERRNO_TIMEOUT
+bool(false)
+bool(true)
+%string|unicode%(%d) "No response from %s"
+SNMP::ERRNO_ERROR_IN_REPLY
+bool(false)
+bool(true)
+%string|unicode%(%d) "Error in packet %s"
+SNMP::ERRNO_GENERIC
+bool(false)
+bool(true)
+%string|unicode%(%d) "Fatal error: Unknown user name"
+bool(false)
+SNMP::ERRNO_OID_PARSING_ERROR
+GET: Single wrong OID
+bool(false)
+bool(true)
+string(46) "Invalid object identifier: .1.3.6.1.2..1.1.1.0"
+GET: Miltiple OID, one wrong
+bool(false)
+bool(true)
+string(46) "Invalid object identifier: .1.3.6.1.2..1.1.1.0"
+WALK: Single wrong OID
+bool(false)
+bool(true)
+string(42) "Invalid object identifier: .1.3.6.1.2..1.1"
+SET: Wrong type
+bool(false)
+bool(true)
+string(129) "Could not add variable: OID='.iso.org.dod.internet.mgmt.mib-2.system.sysContact.0' type='q' value='blah': Bad variable type ("q")"
+SNMP::ERRNO_MULTIPLE_SET_QUERIES
+bool(true)
+bool(true)
+string(74) "Can not fit all OIDs for SET query into one packet, using multiple queries"
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+string(74) "Can not fit all OIDs for SET query into one packet, using multiple queries"
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmp-object-error.phpt b/ext/snmp/tests/snmp-object-error.phpt
new file mode 100644
index 0000000000..b2fed9f373
--- /dev/null
+++ b/ext/snmp/tests/snmp-object-error.phpt
@@ -0,0 +1,122 @@
+--TEST--
+OO API: Generic errors
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+try {
+var_dump(new SNMP(SNMP::VERSION_1, $hostname));
+} catch (Exception $e) {
+ print $e->getMessage() . "\n";
+}
+try {
+var_dump(new SNMP(SNMP::VERSION_1, $hostname, $community, ''));
+} catch (Exception $e) {
+ print $e->getMessage() . "\n";
+}
+try {
+var_dump(new SNMP(SNMP::VERSION_1, $hostname, $community, $timeout, ''));
+} catch (Exception $e) {
+ print $e->getMessage() . "\n";
+}
+try {
+var_dump(new SNMP(7, $hostname, $community));
+} catch (Exception $e) {
+ print $e->getMessage() . "\n";
+}
+
+echo "Exception handling\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $user_noauth, $timeout, $retries);
+try {
+ var_dump($session->get('.1.3.6.1.2.1.1.1..0'));
+} catch (SNMPException $e) {
+ var_dump($e->getCode());
+ var_dump($e->getMessage());
+}
+$session->exceptions_enabled = SNMP::ERRNO_ANY;
+try {
+ var_dump($session->get('.1.3.6.1.2.1.1.1..0'));
+} catch (SNMPException $e) {
+ var_dump($e->getCode());
+ var_dump($e->getMessage());
+}
+var_dump($session->close());
+
+echo "Open normal session\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $user_noauth, $timeout, $retries);
+$session->valueretrieval = 67;
+var_dump($session->valueretrieval);
+echo "Closing session\n";
+var_dump($session->close(''));
+var_dump($session->close());
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump($session->walk('.1.3.6.1.2.1.1', FALSE, ''));
+var_dump($session->walk('.1.3.6.1.2.1.1', FALSE, 30, ''));
+var_dump($session->get());
+var_dump($session->getnext());
+var_dump($session->set());
+
+var_dump($session->max_oids);
+$session->max_oids = "ttt";
+$session->max_oids = 0;
+var_dump($session->max_oids);
+?>
+--EXPECTF--
+SNMP::__construct() expects at least 3 parameters, 2 given
+SNMP::__construct() expects parameter 4 to be long, string given
+SNMP::__construct() expects parameter 5 to be long, string given
+Unknown SNMP protocol version
+Exception handling
+
+Warning: SNMP::get(): Invalid object identifier: .1.3.6.1.2.1.1.1..0 in %s on line %d
+bool(false)
+int(32)
+string(46) "Invalid object identifier: .1.3.6.1.2.1.1.1..0"
+bool(true)
+Open normal session
+
+Warning: main(): Unknown SNMP value retrieval method '67' in %s on line %d
+int(%d)
+Closing session
+
+Warning: SNMP::close() expects exactly 0 parameters, 1 given in %s on line %d
+bool(false)
+bool(true)
+
+Warning: SNMP::get(): Invalid or uninitialized SNMP object in %s on line %d
+bool(false)
+bool(true)
+
+Warning: SNMP::walk() expects parameter 3 to be long, string given in %s on line %d
+bool(false)
+
+Warning: SNMP::walk() expects parameter 4 to be long, string given in %s on line %d
+bool(false)
+
+Warning: SNMP::get() expects at least 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: SNMP::getnext() expects exactly 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: SNMP::set() expects exactly 3 parameters, 0 given in %s on line %d
+bool(false)
+NULL
+
+Warning: main(): max_oids should be positive integer or NULL, got 0 in %s on line %d
+
+Warning: main(): max_oids should be positive integer or NULL, got 0 in %s on line %d
+NULL
diff --git a/ext/snmp/tests/snmp-object-properties.phpt b/ext/snmp/tests/snmp-object-properties.phpt
new file mode 100644
index 0000000000..40b69683df
--- /dev/null
+++ b/ext/snmp/tests/snmp-object-properties.phpt
@@ -0,0 +1,208 @@
+--TEST--
+OO API: SNMP object properties
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_enum_print(false);
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+snmp_set_oid_output_format(SNMP_OID_OUTPUT_FULL);
+
+echo "Check working\n";
+
+$session = new SNMP(SNMP::VERSION_1, $hostname, $community, $timeout, $retries);
+var_dump($session);
+
+$session->max_oids = 40;
+$session->enum_print = TRUE;
+$session->quick_print = TRUE;
+$session->valueretrieval = SNMP_VALUE_LIBRARY;
+$session->oid_output_format = SNMP_OID_OUTPUT_NUMERIC;
+$session->oid_increasing_check = FALSE;
+
+var_dump($session);
+
+$session->max_oids = "40";
+$session->enum_print = "1";
+$session->quick_print = "1";
+$session->valueretrieval = "1";
+$session->oid_output_format = "3";
+$session->oid_increasing_check = "45";
+
+var_dump($session);
+
+var_dump(property_exists($session, "enum_print"));
+var_dump(isset($session->enum_print));
+var_dump(empty($session->enum_print));
+
+$param=123;
+$session->$param = "param_value";
+var_dump($session);
+var_dump($session->$param);
+var_dump(property_exists($session, $param));
+
+echo "Error handling\n";
+$param = 'there is no such parameter';
+var_dump($session->$param);
+var_dump(property_exists($session, $param));
+
+$session->valueretrieval = 67;
+var_dump($session->valueretrieval);
+$session->oid_output_format = 78;
+var_dump($session->oid_output_format);
+
+$session->info = array("blah" => 2);
+var_dump($session->info);
+
+$session->max_oids = NULL;
+var_dump($session->max_oids);
+?>
+--EXPECTF--
+Check working
+object(SNMP)#%d (%d) {
+ ["info"]=>
+ array(4) {
+ ["hostname"]=>
+ %string|unicode%(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["timeout"]=>
+ int(%i)
+ ["retries"]=>
+ int(%d)
+ }
+ ["max_oids"]=>
+ NULL
+ ["valueretrieval"]=>
+ int(1)
+ ["quick_print"]=>
+ bool(false)
+ ["enum_print"]=>
+ bool(false)
+ ["oid_output_format"]=>
+ int(3)
+ ["oid_increasing_check"]=>
+ bool(true)
+ ["exceptions_enabled"]=>
+ int(0)
+}
+object(SNMP)#%d (%d) {
+ ["info"]=>
+ array(4) {
+ ["hostname"]=>
+ %string|unicode%(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["timeout"]=>
+ int(%i)
+ ["retries"]=>
+ int(%d)
+ }
+ ["max_oids"]=>
+ int(40)
+ ["valueretrieval"]=>
+ int(0)
+ ["quick_print"]=>
+ bool(true)
+ ["enum_print"]=>
+ bool(true)
+ ["oid_output_format"]=>
+ int(4)
+ ["oid_increasing_check"]=>
+ bool(false)
+ ["exceptions_enabled"]=>
+ int(0)
+}
+object(SNMP)#%d (%d) {
+ ["info"]=>
+ array(4) {
+ ["hostname"]=>
+ %string|unicode%(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["timeout"]=>
+ int(%i)
+ ["retries"]=>
+ int(%d)
+ }
+ ["max_oids"]=>
+ int(40)
+ ["valueretrieval"]=>
+ int(1)
+ ["quick_print"]=>
+ bool(true)
+ ["enum_print"]=>
+ bool(true)
+ ["oid_output_format"]=>
+ int(3)
+ ["oid_increasing_check"]=>
+ bool(true)
+ ["exceptions_enabled"]=>
+ int(0)
+}
+bool(true)
+bool(true)
+bool(false)
+object(SNMP)#%d (%d) {
+ ["info"]=>
+ array(4) {
+ ["hostname"]=>
+ %string|unicode%(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["timeout"]=>
+ int(%i)
+ ["retries"]=>
+ int(%d)
+ }
+ ["max_oids"]=>
+ int(40)
+ ["valueretrieval"]=>
+ int(1)
+ ["quick_print"]=>
+ bool(true)
+ ["enum_print"]=>
+ bool(true)
+ ["oid_output_format"]=>
+ int(3)
+ ["oid_increasing_check"]=>
+ bool(true)
+ ["exceptions_enabled"]=>
+ int(0)
+ ["123"]=>
+ string(11) "param_value"
+}
+string(11) "param_value"
+bool(true)
+Error handling
+
+Notice: Undefined property: SNMP::$there is no such parameter in %s on line %d
+NULL
+bool(false)
+
+Warning: main(): Unknown SNMP value retrieval method '67' in %s on line %d
+int(1)
+
+Warning: main(): Unknown SNMP output print format '78' in %s on line %d
+int(3)
+
+Warning: main(): info property is read-only in %s on line %d
+array(4) {
+ ["hostname"]=>
+ %string|unicode%(%d) "%s"
+ ["port"]=>
+ int(%d)
+ ["timeout"]=>
+ int(%i)
+ ["retries"]=>
+ int(%d)
+}
+NULL
diff --git a/ext/snmp/tests/snmp-object-setSecurity_error.phpt b/ext/snmp/tests/snmp-object-setSecurity_error.phpt
new file mode 100644
index 0000000000..fc3a1b2269
--- /dev/null
+++ b/ext/snmp/tests/snmp-object-setSecurity_error.phpt
@@ -0,0 +1,66 @@
+--TEST--
+OO API: SNMP::setSecurity (errors)
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+$session = new SNMP(SNMP::VERSION_3, $hostname, $user_noauth, $timeout, $retries);
+$session->setSecurity('noAuthNoPriv');
+
+#echo "Checking error handling\n";
+var_dump($session->setSecurity());
+var_dump($session->setSecurity(''));
+var_dump($session->setSecurity('bugusPriv'));
+var_dump($session->setSecurity('authNoPriv', 'TTT'));
+var_dump($session->setSecurity('authNoPriv', 'MD5', ''));
+var_dump($session->setSecurity('authNoPriv', 'MD5', 'te'));
+var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'BBB'));
+var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', ''));
+var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'ty'));
+var_dump($session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', 'test12345', 'context', 'dsa'));
+
+var_dump($session->close());
+
+?>
+--EXPECTF--
+
+Warning: SNMP::setSecurity() expects at least 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Invalid security level '' in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Invalid security level 'bugusPriv' in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Unknown authentication protocol 'TTT' in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Error generating a key for authentication pass phrase '': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Error generating a key for authentication pass phrase 'te': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Unknown security protocol 'BBB' in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Error generating a key for privacy pass phrase '': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Error generating a key for privacy pass phrase 'ty': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: SNMP::setSecurity(): Bad engine ID value 'dsa' in %s on line %d
+bool(false)
+bool(true)
diff --git a/ext/snmp/tests/snmp-object.phpt b/ext/snmp/tests/snmp-object.phpt
new file mode 100644
index 0000000000..06b6492bd7
--- /dev/null
+++ b/ext/snmp/tests/snmp-object.phpt
@@ -0,0 +1,234 @@
+--TEST--
+OO API
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_enum_print(false);
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+snmp_set_oid_output_format(SNMP_OID_OUTPUT_FULL);
+
+echo "SNMPv1\n";
+$session = new SNMP(SNMP::VERSION_1, $hostname, $community, $timeout, $retries);
+$session->valueretrieval = SNMP_VALUE_LIBRARY;
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->get(array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.3.0')));
+var_dump($session->getnext('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+echo "SNMPv2\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getnext('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+echo "GET with preserving original OID names\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+$orig = array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.5.0');
+$result = $session->get($orig, TRUE);
+foreach($orig as $oid){
+ var_dump($result[$oid]);
+}
+var_dump($session->close());
+
+echo "WALK multiple on single OID\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+$z = $session->walk('.1.3.6.1.2.1.1');
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+var_dump($session->close());
+
+echo "WALK multiple on single OID, max_repetitions set to 30\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+$z = $session->walk('.1.3.6.1.2.1.1', FALSE, 30);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+var_dump($session->close());
+
+echo "WALK multiple on single OID, max_repetitions set to 30, non_repeaters set to 0\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+$z = $session->walk('.1.3.6.1.2.1.1', FALSE, 30, 0);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+var_dump($session->close());
+
+echo "WALK multiple on single OID, max_oids set to 30\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+$session->max_oids = 30;
+$z = $session->walk('.1.3.6.1.2.1.1');
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+var_dump($session->close());
+
+echo "WALK multiple on single OID with OID suffix as keys\n";
+$session = new SNMP(SNMP::VERSION_2c, $hostname, $community, $timeout, $retries);
+$z = $session->walk('.1.3.6.1.2.1.1', TRUE);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+var_dump($session->close());
+
+echo "SNMPv3 (default security settings)\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $user_noauth, $timeout, $retries);
+#$session->setSecurity($user_noauth, 'noAuthNoPriv', '', '', '', '', '', '');
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getnext('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+echo "SNMPv3 (noAuthNoPriv)\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $user_noauth, $timeout, $retries);
+$session->setSecurity('noAuthNoPriv');
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getnext('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+echo "SNMPv3 (authPriv)\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->getnext('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->walk('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+echo "SET single OID\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+$oid1 = 'SNMPv2-MIB::sysContact.0';
+$oldvalue1 = $session->get($oid1);
+$newvalue1 = $oldvalue1 . '0';
+
+$z = $session->set($oid1, 's', $newvalue1);
+var_dump($z);
+var_dump(($session->get($oid1) === $newvalue1));
+$z = $session->set($oid1, 's', $oldvalue1);
+var_dump($z);
+var_dump(($session->get($oid1) === $oldvalue1));
+var_dump($session->close());
+
+echo "Multiple OID with max_oids = 1\n";
+$oid2 = 'SNMPv2-MIB::sysLocation.0';
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass);
+$session->max_oids = 1;
+$oldvalue2 = $session->get($oid2);
+$newvalue2 = $oldvalue2 . '0';
+$z = $session->set(array($oid1, $oid2), array('s','s'), array($newvalue1, $newvalue2));
+var_dump($z);
+var_dump(($session->get($oid1) === $newvalue1));
+var_dump(($session->get($oid2) === $newvalue2));
+$z = $session->set(array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2));
+var_dump($z);
+var_dump(($session->get($oid1) === $oldvalue1));
+var_dump(($session->get($oid2) === $oldvalue2));
+var_dump($session->close());
+
+echo "SNMPv3, setting contextEngineID (authPriv)\n";
+$session = new SNMP(SNMP::VERSION_3, $hostname, $rwuser, $timeout, $retries);
+$session->setSecurity('authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '', 'aeeeff');
+var_dump($session->get('.1.3.6.1.2.1.1.1.0'));
+var_dump($session->close());
+
+?>
+--EXPECTF--
+SNMPv1
+string(%d) "%S"
+array(2) {
+ ["%s"]=>
+ string(%d) "%S"
+ ["%s"]=>
+ string(%d) "%S"
+}
+string(%d) "%S"
+bool(true)
+SNMPv2
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+GET with preserving original OID names
+string(%d) "%s"
+string(%d) "%s"
+bool(true)
+WALK multiple on single OID
+string(5) "array"
+int(%d)
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+WALK multiple on single OID, max_repetitions set to 30
+string(5) "array"
+int(%d)
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+WALK multiple on single OID, max_repetitions set to 30, non_repeaters set to 0
+string(5) "array"
+int(%d)
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+WALK multiple on single OID, max_oids set to 30
+string(5) "array"
+int(%d)
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+WALK multiple on single OID with OID suffix as keys
+string(5) "array"
+int(%d)
+string(3) "1.0"
+string(%d) "%s"
+bool(true)
+SNMPv3 (default security settings)
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+SNMPv3 (noAuthNoPriv)
+string(%d) "%S"
+string(%d) "%S"
+bool(true)
+SNMPv3 (authPriv)
+string(%d) "%S"
+string(%d) "%S"
+array(1) {
+ [%s]=>
+ string(%d) "%S"
+}
+bool(true)
+SET single OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID with max_oids = 1
+
+Warning: SNMP::set(): Can not fit all OIDs for SET query into one packet, using multiple queries in %s on line %d
+bool(true)
+bool(true)
+bool(true)
+
+Warning: SNMP::set(): Can not fit all OIDs for SET query into one packet, using multiple queries in %s on line %d
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+SNMPv3, setting contextEngineID (authPriv)
+string(%d) "%S"
+bool(true)
diff --git a/ext/snmp/tests/snmp2_get.phpt b/ext/snmp/tests/snmp2_get.phpt
new file mode 100644
index 0000000000..b6b50cea90
--- /dev/null
+++ b/ext/snmp/tests/snmp2_get.phpt
@@ -0,0 +1,104 @@
+--TEST--
+Function snmp2_get
+--CREDITS--
+Olivier Doucet & Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Checking error handling\n";
+var_dump(snmp2_get($hostname, $community, '.1.3.6.1.2.1.1.1.0', ''));
+var_dump(snmp2_get($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, ''));
+echo "Empty OID array\n";
+var_dump(snmp2_get($hostname, $community, array(), $timeout, $retries));
+
+echo "Checking working\n";
+echo "Single OID\n";
+var_dump(snmp2_get($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1.1.1.0'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.3.0'), $timeout, $retries));
+
+echo "More error handling\n";
+echo "Single OID\n";
+var_dump(snmp2_get($hostname, $community, '.1.3.6.1.2..1.1.1.0', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1...1.1.0'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1...1.1.0', '.1.3.6.1.2.1.1.3.0'), $timeout, $retries));
+
+echo "noSuchName checks\n";
+echo "Single OID\n";
+var_dump(snmp2_get($hostname, $community, '.1.3.6.1.2.1.1.1.110', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1.1.1.110'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmp2_get($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.3.220'), $timeout, $retries));
+
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp2_get() expects parameter 4 to be long,%s given in %s on line %d
+bool(false)
+
+Warning: snmp2_get() expects parameter 5 to be long,%s given in %s on line %d
+bool(false)
+Empty OID array
+
+Warning: snmp2_get(): Got empty OID array in %s on line %d
+bool(false)
+Checking working
+Single OID
+%unicode|string%(%d) "%s"
+Single OID in array
+array(1) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+}
+Multiple OID
+array(2) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+ ["%s"]=>
+ %unicode|string%(%d) "%d"
+}
+More error handling
+Single OID
+
+Warning: snmp2_get(): Invalid object identifier: .1.3.6.1.2..1.1.1.0 in %s on line %d
+bool(false)
+Single OID in array
+
+Warning: snmp2_get(): Invalid object identifier: .1.3.6.1.2.1...1.1.0 in %s on line %d
+bool(false)
+Multiple OID
+
+Warning: snmp2_get(): Invalid object identifier: .1.3.6.1.2.1...1.1.0 in %s on line %d
+bool(false)
+noSuchName checks
+Single OID
+
+Warning: snmp2_get(): Error in packet at 'SNMPv2-MIB::sysDescr.110': No Such Instance currently exists at this OID in %s on line %d
+bool(false)
+Single OID in array
+
+Warning: snmp2_get(): Error in packet at 'SNMPv2-MIB::sysDescr.110': No Such Instance currently exists at this OID in %s on line %d
+bool(false)
+Multiple OID
+
+Warning: snmp2_get(): Error in packet at 'SNMPv2-MIB::sysUpTime.220': No Such Instance currently exists at this OID in %s on line %d
+array(1) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+}
diff --git a/ext/snmp/tests/snmp2_getnext.phpt b/ext/snmp/tests/snmp2_getnext.phpt
new file mode 100644
index 0000000000..5c5abf428e
--- /dev/null
+++ b/ext/snmp/tests/snmp2_getnext.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Function snmp2_getnext
+--CREDITS--
+Olivier Doucet & Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Single OID\n";
+var_dump(snmp2_getnext($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmp2_getnext($hostname, $community, array('.1.3.6.1.2.1.1.1.0'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmp2_getnext($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.6.0'), $timeout, $retries));
+
+?>
+--EXPECTF--
+Single OID
+%unicode|string%(%d) "%s"
+Single OID in array
+array(1) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+}
+Multiple OID
+array(2) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+ ["%s"]=>
+ %unicode|string%(%d) "%d"
+}
diff --git a/ext/snmp/tests/snmp2_real_walk.phpt b/ext/snmp/tests/snmp2_real_walk.phpt
new file mode 100644
index 0000000000..afaabd42c4
--- /dev/null
+++ b/ext/snmp/tests/snmp2_real_walk.phpt
@@ -0,0 +1,86 @@
+--TEST--
+Function snmp2_real_walk
+--CREDITS--
+Olivier Doucet Olivier Doucet Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Checking error handling\n";
+var_dump(snmp2_real_walk($hostname, $community, '.1.3.6.1.2.1.1', ''));
+var_dump(snmp2_real_walk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, ''));
+
+echo "Checking working\n";
+echo "Single OID\n";
+$return = snmp2_real_walk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, $retries);
+var_dump(gettype($return));
+var_dump(sizeof($return));
+var_dump(key($return));
+var_dump(array_shift($return));
+
+echo "Single OID in array\n";
+$return = snmp2_real_walk($hostname, $community, array('.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump(gettype($return));
+var_dump(sizeof($return));
+var_dump(key($return));
+var_dump(array_shift($return));
+
+echo "More error handling\n";
+echo "Multiple correct OID\n";
+$return = snmp2_real_walk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6'), $timeout, $retries);
+var_dump($return);
+
+echo "Multiple OID with wrong OID\n";
+$return = snmp2_real_walk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6...1'), $timeout, $retries);
+var_dump($return);
+$return = snmp2_real_walk($hostname, $community, array('.1.3.6...1', '.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump($return);
+
+echo "Single nonexisting OID\n";
+$return = snmp2_real_walk($hostname, $community, array('.1.3.6.99999.0.99999.111'), $timeout, $retries);
+var_dump($return);
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp2_real_walk() expects parameter 4 to be long, %s given in %s on line %d
+bool(false)
+
+Warning: snmp2_real_walk() expects parameter 5 to be long, %s given in %s on line %d
+bool(false)
+Checking working
+Single OID
+%unicode|string%(5) "array"
+int(%d)
+string(%d) "%s"
+string(%d) "%s"
+Single OID in array
+%unicode|string%(5) "array"
+int(%d)
+string(%d) "%s"
+string(%d) "%s"
+More error handling
+Multiple correct OID
+
+Warning: snmp2_real_walk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Multiple OID with wrong OID
+
+Warning: snmp2_real_walk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+
+Warning: snmp2_real_walk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Single nonexisting OID
+
+Warning: snmp2_real_walk(): Error in packet at '%s': No more variables left in this MIB View (It is past the end of the MIB tree) in %s on line %d
+bool(false)
diff --git a/ext/snmp/tests/snmp2_set-nomib.phpt b/ext/snmp/tests/snmp2_set-nomib.phpt
new file mode 100644
index 0000000000..af0baa3fdd
--- /dev/null
+++ b/ext/snmp/tests/snmp2_set-nomib.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Function snmp2_set (without MIBs loading)
+--CREDITS--
+Boris Lytockin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--ENV--
+return <<<END
+MIBS=
+END;
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Check error handing\n";
+echo "Nonexisting OID\n";
+$z = snmp2_set($hostname, $communityWrite, '.1.3.6.777.888.999.444.0', 's', 'bbb', $timeout, $retries);
+var_dump($z);
+
+echo "Bogus OID\n";
+$z = snmp2_set($hostname, $communityWrite, '.1.3.6...777.888.999.444.0', 's', 'bbb', $timeout, $retries);
+var_dump($z);
+
+echo "Checking working\n";
+$oid1 = '.1.3.6.1.2.1.1.4.0';
+$oldvalue1 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
+$newvalue1 = $oldvalue1 . '0';
+
+echo "Single OID\n";
+$z = snmp2_set($hostname, $communityWrite, $oid1, 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+$z = snmp2_set($hostname, $communityWrite, $oid1, 's', $oldvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+
+?>
+--EXPECTF--
+Check error handing
+Nonexisting OID
+
+Warning: snmp2_set(): Error in packet at '%s': notWritable (That object does not support modification) in %s on line %d
+bool(false)
+Bogus OID
+
+Warning: snmp2_set(): Invalid object identifier: %s in %s on line %d
+bool(false)
+Checking working
+Single OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmp2_set.phpt b/ext/snmp/tests/snmp2_set.phpt
new file mode 100644
index 0000000000..b833b9b504
--- /dev/null
+++ b/ext/snmp/tests/snmp2_set.phpt
@@ -0,0 +1,248 @@
+--TEST--
+Function snmp2_set
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Check error handing\n";
+echo "4args (5 needed)\n";
+$z = snmp2_set($hostname, $communityWrite, 'SNMPv2-MIB::sysLocation.0');
+var_dump($z);
+
+echo "No type & no value (timeout & retries instead)\n";
+$z = snmp2_set($hostname, $communityWrite, 'SNMPv2-MIB::sysLocation.0', $timeout, $retries);
+var_dump($z);
+
+echo "No value (timeout instead), retries instead of timeout\n";
+$z = snmp2_set($hostname, $communityWrite, 'SNMPv2-MIB::sysLocation.0', 'q', $timeout, $retries);
+var_dump($z);
+
+echo "Bogus OID\n";
+$z = snmp2_set($hostname, $communityWrite, '.1.3.6.777.888.999.444.0', 's', 'bbb', $timeout, $retries);
+var_dump($z);
+
+echo "Checking working\n";
+$oid1 = 'SNMPv2-MIB::sysContact.0';
+$oldvalue1 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
+$newvalue1 = $oldvalue1 . '0';
+$oid2 = 'SNMPv2-MIB::sysLocation.0';
+$oldvalue2 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
+$newvalue2 = $oldvalue2 . '0';
+
+echo "Single OID\n";
+$z = snmp2_set($hostname, $communityWrite, $oid1, 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+$z = snmp2_set($hostname, $communityWrite, $oid1, 's', $oldvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+
+echo "Multiple OID\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $newvalue2));
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single type & value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $newvalue1));
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single type, multiple value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), 's', array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $newvalue2));
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+
+echo "More error handing\n";
+echo "Single OID, single type in array, single value\n";
+$z = snmp2_set($hostname, $communityWrite, $oid1, array('s'), $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Single OID, single type, single value in array\n";
+$z = snmp2_set($hostname, $communityWrite, $oid1, 's', array($newvalue1), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 1st wrong type\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('sw','s'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 2nd wrong type\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s','sb'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single type in array, multiple value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID & type, singe value in array\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 1st bogus, single type, multiple value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1 . '44.55.66.77', $oid2), 's', array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 2nd bogus, single type, multiple value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2 . '44.55.66.77'), 's', array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single multiple type (1st bogus), multiple value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('q', 's'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single multiple type (2nd bogus), multiple value\n";
+$z = snmp2_set($hostname, $communityWrite, array($oid1, $oid2), array('s', 'w'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+?>
+--EXPECTF--
+Check error handing
+4args (5 needed)
+
+Warning: snmp2_set() expects at least 5 parameters, 3 given in %s on line %d
+bool(false)
+No type & no value (timeout & retries instead)
+
+Warning: snmp2_set(): Bogus type '-1', should be single char, got 2 in %s on line %d
+bool(false)
+No value (timeout instead), retries instead of timeout
+
+Warning: snmp2_set(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d
+bool(false)
+Bogus OID
+
+Warning: snmp2_set(): Error in packet at '%s': notWritable (That object does not support modification) in %s on line %d
+bool(false)
+Checking working
+Single OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID, single type & value
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID, single type, multiple value
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+More error handing
+Single OID, single type in array, single value
+
+Warning: snmp2_set(): Single objid and multiple type or values are not supported in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Single OID, single type, single value in array
+
+Warning: snmp2_set(): Single objid and multiple type or values are not supported in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 1st wrong type
+
+Warning: snmp2_set(): '%s': bogus type 'sw', should be single char, got 2 in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 2nd wrong type
+
+Warning: snmp2_set(): '%s': bogus type 'sb', should be single char, got 2 in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, single type in array, multiple value
+
+Warning: snmp2_set(): '%s': no type set in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID & type, singe value in array
+
+Warning: snmp2_set(): '%s': no value set in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 1st bogus, single type, multiple value
+
+Warning: snmp2_set(): Error in packet at '%s': %rnoCreation|notWritable%r (%s) in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 2nd bogus, single type, multiple value
+
+Warning: snmp2_set(): Error in packet at '%s': %rnoCreation|notWritable%r (%s) in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, single multiple type (1st bogus), multiple value
+
+Warning: snmp2_set(): Could not add variable: OID='%s' type='q' value='%s': Bad variable type ("q") in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, single multiple type (2nd bogus), multiple value
+
+Warning: snmp2_set(): Could not add variable: OID='%s' type='w' value='%s': Bad variable type ("w") in %s on line %d
+bool(false)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmp2_walk.phpt b/ext/snmp/tests/snmp2_walk.phpt
new file mode 100644
index 0000000000..3981676eb1
--- /dev/null
+++ b/ext/snmp/tests/snmp2_walk.phpt
@@ -0,0 +1,99 @@
+--TEST--
+Function snmp2_walk
+--CREDITS--
+Olivier Doucet Olivier Doucet Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Checking error handling\n";
+var_dump(snmp2_walk($hostname, $community, '.1.3.6.1.2.1.1', ''));
+var_dump(snmp2_walk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, ''));
+
+echo "Checking working\n";
+echo "Single OID\n";
+$return = snmp2_walk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, $retries);
+
+var_dump(gettype($return));
+var_dump(sizeof($return));
+var_dump(gettype($return[0]));
+var_dump(gettype($return[1]));
+
+echo "Single OID in array\n";
+$return = snmp2_walk($hostname, $community, array('.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump(gettype($return));
+var_dump(gettype($return[0]));
+
+echo "Default OID\n";
+$return = snmpwalk($hostname, $community, '', $timeout, $retries);
+var_dump(gettype($return));
+var_dump(gettype($return[0]));
+
+echo "More error handling\n";
+echo "Single incorrect OID\n";
+$return = snmpwalk($hostname, $community, '.1.3.6...1', $timeout, $retries);
+var_dump($return);
+
+echo "Multiple correct OID\n";
+$return = snmp2_walk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6'), $timeout, $retries);
+var_dump($return);
+
+echo "Multiple OID with wrong OID\n";
+$return = snmp2_walk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6...1'), $timeout, $retries);
+var_dump($return);
+$return = snmp2_walk($hostname, $community, array('.1.3.6...1', '.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump($return);
+
+echo "Single nonexisting OID\n";
+$return = snmp2_walk($hostname, $community, array('.1.3.6.99999.0.99999.111'), $timeout, $retries);
+var_dump($return);
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp2_walk() expects parameter 4 to be long, %s given in %s on line %d
+bool(false)
+
+Warning: snmp2_walk() expects parameter 5 to be long, %s given in %s on line %d
+bool(false)
+Checking working
+Single OID
+%unicode|string%(5) "array"
+int(%d)
+%unicode|string%(6) "string"
+%unicode|string%(6) "string"
+Single OID in array
+%unicode|string%(5) "array"
+%unicode|string%(6) "string"
+Default OID
+%unicode|string%(5) "array"
+%unicode|string%(6) "string"
+More error handling
+Single incorrect OID
+
+Warning: snmpwalk(): Invalid object identifier: %s in %s on line %d
+bool(false)
+Multiple correct OID
+
+Warning: snmp2_walk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Multiple OID with wrong OID
+
+Warning: snmp2_walk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+
+Warning: snmp2_walk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Single nonexisting OID
+
+Warning: snmp2_walk(): Error in packet at '%s': No more variables left in this MIB View (It is past the end of the MIB tree) in %s on line %d
+bool(false)
diff --git a/ext/snmp/tests/snmp3-error.phpt b/ext/snmp/tests/snmp3-error.phpt
new file mode 100644
index 0000000000..3c0c499221
--- /dev/null
+++ b/ext/snmp/tests/snmp3-error.phpt
@@ -0,0 +1,76 @@
+--TEST--
+SNMPv3 Support (errors)
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+echo "Checking error handling\n";
+
+//int snmp3_get(string host, string sec_name, string sec_level, string auth_protocol,
+// string auth_passphrase, string priv_protocol, string priv_passphrase,
+// string object_id [, int timeout [, int retries]]);
+
+var_dump(snmp3_get($hostname, $community, '', '', '', '', ''));
+var_dump(snmp3_get($hostname, $community, '', '', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'bugusPriv', '', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'TTT', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'MD5', '', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authNoPriv', 'MD5', 'te', '', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'BBB', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', '', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', 'ty', '.1.3.6.1.2.1.1.1.0'));
+var_dump(snmp3_get($hostname, 'somebogususer', 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+
+var_dump(snmp3_set($hostname, $community, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '', 's'));
+
+var_dump(snmp3_set($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '.1.3.6.777...7.5.3', 's', 'ttt', $timeout, $retries));
+var_dump(snmp3_set($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, '.1.3.6.777.7.5.3', array('s'), 'yyy', $timeout, $retries));
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp3_get() expects at least 8 parameters, 7 given in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Invalid security level '' in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Invalid security level 'bugusPriv' in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Unknown authentication protocol 'TTT' in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Error generating a key for authentication pass phrase '': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Error generating a key for authentication pass phrase 'te': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Unknown security protocol 'BBB' in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Error generating a key for privacy pass phrase '': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Error generating a key for privacy pass phrase 'ty': Generic error (The supplied password length is too short.) in %s on line %d
+bool(false)
+
+Warning: snmp3_get(): Fatal error: Unknown user name in %s on line %d
+bool(false)
+
+Warning: snmp3_set() expects at least 10 parameters, 9 given in %s on line %d
+bool(false)
+
+Warning: snmp3_set(): Invalid object identifier: .1.3.6.777...7.5.3 in %s on line %d
+bool(false)
+
+Warning: snmp3_set(): Single objid and multiple type or values are not supported in %s on line %d
+bool(false)
diff --git a/ext/snmp/tests/snmp3.phpt b/ext/snmp/tests/snmp3.phpt
new file mode 100644
index 0000000000..49d205fc42
--- /dev/null
+++ b/ext/snmp/tests/snmp3.phpt
@@ -0,0 +1,127 @@
+--TEST--
+SNMPv3 Support
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//int snmp3_get(string host, string sec_name, string sec_level, string auth_protocol,
+// string auth_passphrase, string priv_protocol, string priv_passphrase,
+// string object_id [, int timeout [, int retries]]);
+
+echo "Working version\n";
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+echo "GET single: noAuthNoPriv\n";
+var_dump(snmp3_get($hostname, $user_noauth, 'noAuthNoPriv', '', '', '', '', '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+
+foreach(array('MD5', 'SHA') as $signalg) {
+ echo "GET single: $signalg\n";
+ var_dump(snmp3_get($hostname, $user_auth_prefix . $signalg, 'authNoPriv', $signalg, $auth_pass, '', '', '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+}
+
+foreach(array('AES', 'DES', 'AES128') as $chipher) {
+ echo "GET single: MD5/$chipher\n";
+ var_dump(snmp3_get($hostname, $user_auth_prefix . 'MD5' . $chipher, 'authPriv', 'MD5', $auth_pass, $chipher, $priv_pass, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+}
+$username = $user_auth_prefix . 'MD5';
+echo "GET multiple\n";
+var_dump(snmp3_get($hostname, $username, 'authNoPriv', 'MD5', $auth_pass, '', '', array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.3.0'), $timeout, $retries));
+echo "GETNEXT single\n";
+var_dump(snmp3_getnext($hostname, $username, 'authNoPriv', 'MD5', $auth_pass, '', '', '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+
+echo "WALK single on single OID\n";
+$z = snmp3_walk($hostname, $username, 'authNoPriv', 'MD5', $auth_pass, '', '', '.1.3.6.1.2.1.1.1.0', $timeout, $retries);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump($z);
+
+echo "REALWALK single on single OID\n";
+$z = snmp3_real_walk($hostname, $username, 'authNoPriv', 'MD5', $auth_pass, '', '', '.1.3.6.1.2.1.1.1.0', $timeout, $retries);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump($z);
+
+echo "WALK multiple on single OID\n";
+$z = snmp3_walk($hostname, $username, 'authNoPriv', 'MD5', $auth_pass, '', '', '.1.3.6.1.2.1.1', $timeout, $retries);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+
+echo "REALWALK multiple on single OID\n";
+$z = snmp3_real_walk($hostname, $username, 'authNoPriv', 'MD5', $auth_pass, 'AES', '', '.1.3.6.1.2.1.1', $timeout, $retries);
+var_dump(gettype($z));
+var_dump(count($z));
+var_dump(key($z));
+var_dump(array_shift($z));
+
+echo "SET single OID\n";
+$oid1 = 'SNMPv2-MIB::sysContact.0';
+$oldvalue1 = snmp3_get($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, $oid1, $timeout, $retries);
+$newvalue1 = $oldvalue1 . '0';
+
+$z = snmp3_set($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, $oid1, 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmp3_get($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, $oid1, $timeout, $retries) === $newvalue1));
+$z = snmp3_set($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, $oid1, 's', $oldvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmp3_get($hostname, $rwuser, 'authPriv', 'MD5', $auth_pass, 'AES', $priv_pass, $oid1, $timeout, $retries) === $oldvalue1));
+
+?>
+--EXPECTF--
+Working version
+GET single: noAuthNoPriv
+%string|unicode%(%d) "%s"
+GET single: MD5
+%string|unicode%(%d) "%s"
+GET single: SHA
+%string|unicode%(%d) "%s"
+GET single: MD5/AES
+%string|unicode%(%d) "%s"
+GET single: MD5/DES
+%string|unicode%(%d) "%s"
+GET single: MD5/AES128
+%string|unicode%(%d) "%s"
+GET multiple
+array(2) {
+ ["%s"]=>
+ %string|unicode%(%d) "%s"
+ ["%s"]=>
+ %string|unicode%(%d) "%s"
+}
+GETNEXT single
+%string|unicode%(%d) "%s"
+WALK single on single OID
+%string|unicode%(5) "array"
+int(1)
+array(1) {
+ [0]=>
+ %string|unicode%(%d) "%s"
+}
+REALWALK single on single OID
+%string|unicode%(5) "array"
+int(1)
+array(1) {
+ ["%s"]=>
+ %string|unicode%(%d) "%s"
+}
+WALK multiple on single OID
+%string|unicode%(5) "array"
+int(%d)
+int(0)
+%string|unicode%(%d) "%s"
+REALWALK multiple on single OID
+%string|unicode%(5) "array"
+int(%d)
+%string|unicode%(%d) "%s"
+%string|unicode%(%d) "%s"
+SET single OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmp_get_quick_print.phpt b/ext/snmp/tests/snmp_get_quick_print.phpt
new file mode 100644
index 0000000000..9abfd92cb4
--- /dev/null
+++ b/ext/snmp/tests/snmp_get_quick_print.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Function snmp_get_quick_print / snmp_set_quick_print
+--CREDITS--
+Olivier Doucet
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+echo "Checking error handling\n";
+var_dump(snmp_get_quick_print('noarg'));
+var_dump(snmp_set_quick_print('noarg'));
+var_dump(snmp_set_quick_print());
+
+echo "Checking working\n";
+var_dump(snmp_get_quick_print());
+snmp_set_quick_print(false);
+var_dump(snmp_get_quick_print());
+snmp_set_quick_print(true);
+var_dump(snmp_get_quick_print());
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp_get_quick_print() expects exactly 0 parameters, 1 given in %s on line %d
+NULL
+
+Warning: snmp_set_quick_print() expects parameter 1 to be long, %s given in %s on line %d
+bool(false)
+
+Warning: snmp_set_quick_print() expects exactly 1 parameter, 0 given in %s on line %d
+bool(false)
+Checking working
+bool(%s)
+bool(false)
+bool(true)
+
diff --git a/ext/snmp/tests/snmp_get_valueretrieval.phpt b/ext/snmp/tests/snmp_get_valueretrieval.phpt
new file mode 100644
index 0000000000..660d643e41
--- /dev/null
+++ b/ext/snmp/tests/snmp_get_valueretrieval.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Function snmp_get_valueretrieval / snmp_set_valueretrieval
+--CREDITS--
+Olivier Doucet
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+echo "Checking error handling\n";
+var_dump(snmp_get_valueretrieval('noarg'));
+var_dump(snmp_set_valueretrieval());
+var_dump(snmp_set_valueretrieval('noarg'));
+var_dump(snmp_set_valueretrieval(67));
+
+echo "Checking working\n";
+var_dump(snmp_get_valueretrieval());
+snmp_set_valueretrieval(SNMP_VALUE_LIBRARY);
+var_dump(snmp_get_valueretrieval() === SNMP_VALUE_LIBRARY);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+var_dump(snmp_get_valueretrieval() === SNMP_VALUE_PLAIN);
+snmp_set_valueretrieval(SNMP_VALUE_OBJECT);
+var_dump(snmp_get_valueretrieval() === SNMP_VALUE_OBJECT);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT);
+var_dump(snmp_get_valueretrieval() === (SNMP_VALUE_PLAIN|SNMP_VALUE_OBJECT));
+snmp_set_valueretrieval(SNMP_VALUE_LIBRARY|SNMP_VALUE_OBJECT);
+var_dump(snmp_get_valueretrieval() === (SNMP_VALUE_LIBRARY|SNMP_VALUE_OBJECT));
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp_get_valueretrieval() expects exactly 0 parameters, 1 given in %s on line %d
+bool(false)
+
+Warning: snmp_set_valueretrieval() expects exactly 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: snmp_set_valueretrieval() expects parameter 1 to be long, %s given in %s on line %d
+bool(false)
+
+Warning: snmp_set_valueretrieval(): Unknown SNMP value retrieval method '67' in %s on line %d
+bool(false)
+Checking working
+int(%d)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmp_getvalue.phpt b/ext/snmp/tests/snmp_getvalue.phpt
new file mode 100644
index 0000000000..178354a8cf
--- /dev/null
+++ b/ext/snmp/tests/snmp_getvalue.phpt
@@ -0,0 +1,83 @@
+--TEST--
+Function snmp_getvalue
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+
+echo "Get with SNMP_VALUE_LIBRARY\n";
+snmp_set_valueretrieval(SNMP_VALUE_LIBRARY);
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+
+echo "Get with SNMP_VALUE_PLAIN\n";
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+
+echo "Get with SNMP_VALUE_OBJECT\n";
+snmp_set_valueretrieval(SNMP_VALUE_OBJECT);
+$z = snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries);
+echo gettype($z)."\n";
+var_dump($z->type);
+var_dump($z->value);
+
+echo "Get with SNMP_VALUE_OBJECT | SNMP_VALUE_PLAIN\n";
+snmp_set_valueretrieval(SNMP_VALUE_OBJECT | SNMP_VALUE_PLAIN);
+$z = snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries);
+echo gettype($z)."\n";
+var_dump($z->type);
+var_dump($z->value);
+
+echo "Get with SNMP_VALUE_OBJECT for BITS OID\n";
+snmp_set_valueretrieval(SNMP_VALUE_OBJECT);
+$z = snmpget($hostname, $community, '.1.3.6.1.2.1.88.1.4.2.1.3.6.95.115.110.109.112.100.95.108.105.110.107.68.111.119.110', $timeout, $retries);
+echo gettype($z)."\n";
+var_dump($z->type);
+var_dump($z->value);
+
+echo "Get with SNMP_VALUE_OBJECT | SNMP_VALUE_PLAIN for BITS OID\n";
+snmp_set_valueretrieval(SNMP_VALUE_OBJECT | SNMP_VALUE_PLAIN);
+$z = snmpget($hostname, $community, '.1.3.6.1.2.1.88.1.4.2.1.3.6.95.115.110.109.112.100.95.108.105.110.107.68.111.119.110', $timeout, $retries);
+echo gettype($z)."\n";
+var_dump($z->type);
+var_dump(is_numeric($z->value));
+var_dump(is_string($z->value));
+var_dump(bin2hex($z->value));
+
+echo "Check parsing of different OID types\n";
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+var_dump(count(snmp2_walk($hostname, $community, '.', $timeout, $retries)));
+
+?>
+--EXPECTF--
+Get with SNMP_VALUE_LIBRARY
+string(%d) "STRING: %s"
+Get with SNMP_VALUE_PLAIN
+string(%d) "%s"
+Get with SNMP_VALUE_OBJECT
+object
+int(4)
+string(%d) "STRING: %s"
+Get with SNMP_VALUE_OBJECT | SNMP_VALUE_PLAIN
+object
+int(4)
+string(%d) "%s"
+Get with SNMP_VALUE_OBJECT for BITS OID
+object
+int(4)
+string(25) "BITS: %d %s"
+Get with SNMP_VALUE_OBJECT | SNMP_VALUE_PLAIN for BITS OID
+object
+int(4)
+bool(false)
+bool(true)
+string(2) "%d"
+Check parsing of different OID types
+int(%d)
diff --git a/ext/snmp/tests/snmp_include.inc b/ext/snmp/tests/snmp_include.inc
new file mode 100644
index 0000000000..caa0721890
--- /dev/null
+++ b/ext/snmp/tests/snmp_include.inc
@@ -0,0 +1,31 @@
+<?php
+
+/*
+By default tests will try to access SNMP agent @ '127.0.0.1:161' and will use 'public' community for read
+requests and 'private' community for write requests.
+Default timeout is 1000ms and there will be one request performed.
+*/
+
+$hostname4 = getenv('SNMP_HOSTNAME') ? getenv('SNMP_HOSTNAME') : '127.0.0.1';
+$hostname6 = getenv('SNMP_HOSTNAME6') ? getenv('SNMP_HOSTNAME6') : '::1';
+$port = getenv('SNMP_PORT') ? getenv('SNMP_PORT') : '161';
+$hostname = "$hostname4:$port";
+$hostname6_port = "[$hostname6]:$port";
+$community = getenv('SNMP_COMMUNITY') ? getenv('SNMP_COMMUNITY') : 'public';
+$communityWrite = getenv('SNMP_COMMUNITY_WRITE')? getenv('SNMP_COMMUNITY_WRITE'):'private';
+
+$timeout = getenv('SNMP_TIMEOUT') ? getenv('SNMP_TIMEOUT') : -1;
+$retries = getenv('SNMP_RETRIES') ? getenv('SNMP_RETRIES') : 1;
+
+if (stristr(PHP_OS, "FreeBSD")) {
+ $mibdir = getenv('SNMP_MIBDIR') ? getenv('SNMP_MIBDIR') : "/usr/local/share/snmp/mibs";
+} else {
+ $mibdir = getenv('SNMP_MIBDIR') ? getenv('SNMP_MIBDIR') : "/usr/share/snmp/mibs";
+}
+
+
+$user_noauth = getenv('SNMP_USER_NOAUTH') ? getenv('SNMP_USER_NOAUTH') : 'noAuthUser';
+$user_auth_prefix = getenv('SNMP_USER_PREFIX') ? getenv('SNMP_USER_PREFIX') : 'admin';
+$rwuser = getenv('SNMP_RWUSER') ? getenv('SNMP_RWUSER') : ($user_auth_prefix . 'MD5AES');
+$auth_pass = getenv('SNMP_AUTH_PASS') ? getenv('SNMP_AUTH_PASS') : 'test1234';
+$priv_pass = getenv('SNMP_PRIV_PASS') ? getenv('SNMP_PRIV_PASS') : 'test1234';
diff --git a/ext/snmp/tests/snmp_read_mib.phpt b/ext/snmp/tests/snmp_read_mib.phpt
new file mode 100644
index 0000000000..b26ba5e52a
--- /dev/null
+++ b/ext/snmp/tests/snmp_read_mib.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Function snmp_read_mib
+--CREDITS--
+Olivier Doucet Olivier Doucet Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+if (!file_exists($mibdir . '/SNMPv2-MIB.txt')) die('MIB file not in the system');
+
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+echo "Checking error handling\n";
+var_dump(snmp_read_mib());
+var_dump(snmp_read_mib(dirname(__FILE__).'/cannotfindthisfile'));
+
+echo "Checking working\n";
+var_dump(snmp_read_mib($mibdir . '/SNMPv2-MIB.txt'));
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp_read_mib() expects exactly 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: snmp_read_mib(): Error while reading MIB file '%s': No such file or directory in %s on line %d
+bool(false)
+Checking working
+bool(true)
diff --git a/ext/snmp/tests/snmp_set_enum_print.phpt b/ext/snmp/tests/snmp_set_enum_print.phpt
new file mode 100644
index 0000000000..97683444fe
--- /dev/null
+++ b/ext/snmp/tests/snmp_set_enum_print.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Function snmp_set_enum_print
+--CREDITS--
+Olivier Doucet
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+if (!function_exists('snmp_set_enum_print')) die('This function is only available if using NET_SNMP');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+echo "Checking error handling\n";
+var_dump(snmp_set_enum_print());
+
+echo "Checking working\n";
+var_dump(snmp_set_enum_print(0));
+var_dump(snmp_set_enum_print(1));
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp_set_enum_print() expects exactly 1 parameter, 0 given in %s on line %d
+bool(false)
+Checking working
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmp_set_oid_output_format.phpt b/ext/snmp/tests/snmp_set_oid_output_format.phpt
new file mode 100644
index 0000000000..20a48d4fe1
--- /dev/null
+++ b/ext/snmp/tests/snmp_set_oid_output_format.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Function snmp_set_oid_output_format
+--CREDITS--
+Olivier Doucet
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+if (!function_exists('snmp_set_oid_output_format')) die('This function is only available if using NET_SNMP');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+echo "Checking error handling\n";
+var_dump(snmp_set_oid_output_format());
+var_dump(snmp_set_oid_output_format(123));
+
+echo "Checking working\n";
+var_dump(snmp_set_oid_output_format(SNMP_OID_OUTPUT_FULL));
+var_dump(snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC));
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmp_set_oid_output_format() expects exactly 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: snmp_set_oid_output_format(): Unknown SNMP output print format '123' in %s on line %d
+bool(false)
+Checking working
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmpd.conf b/ext/snmp/tests/snmpd.conf
new file mode 100644
index 0000000000..3e91372944
--- /dev/null
+++ b/ext/snmp/tests/snmpd.conf
@@ -0,0 +1,25 @@
+# Listen for connections from the local system only
+agentaddress udp:127.0.0.1:161,udp6:[::1]:161
+
+rocommunity public 127.0.0.1
+rocommunity6 public ::1
+rwcommunity private 127.0.0.1
+
+Do not enable them - being set here they make appropriate OID switch into r/o
+#syslocation "Somewhere in the world"
+#syscontact "root"
+
+#SNMPv3 credentials
+rouser adminMD5
+rouser adminSHA
+rwuser adminMD5AES
+rouser adminMD5AES128
+rouser adminMD5DES
+createUser adminMD5 MD5 test1234
+createUser adminSHA SHA test1234
+createUser adminMD5AES MD5 test1234 AES test1234
+createUser adminMD5AES128 MD5 test1234 AES test1234
+createUser adminMD5DES MD5 test1234 DES test1234
+
+createUser noAuthUser
+authuser read noAuthUser noauth
diff --git a/ext/snmp/tests/snmpget.phpt b/ext/snmp/tests/snmpget.phpt
new file mode 100644
index 0000000000..e4514a2538
--- /dev/null
+++ b/ext/snmp/tests/snmpget.phpt
@@ -0,0 +1,106 @@
+--TEST--
+Function snmpget
+--CREDITS--
+Olivier Doucet & Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Checking error handling\n";
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', ''));
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, ''));
+
+echo "Checking working\n";
+echo "Single OID, default timeout and retries\n";
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0'));
+echo "Single OID, default retries\n";
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout));
+echo "Single OID\n";
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmpget($hostname, $community, array('.1.3.6.1.2.1.1.1.0'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmpget($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.3.0'), $timeout, $retries));
+
+echo "More error handling\n";
+echo "Single OID\n";
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1..1.1.0', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmpget($hostname, $community, array('.1.3.6.1.2.1...1.1.0'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmpget($hostname, $community, array('.1.3.6.1.2.1...1.1.0', '.1.3.6.1.2.1.1.3.0'), $timeout, $retries));
+
+echo "noSuchName checks\n";
+echo "Single OID\n";
+var_dump(snmpget($hostname, $community, '.1.3.6.1.2.1.1.1.110', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmpget($hostname, $community, array('.1.3.6.1.2.1.1.1.110'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmpget($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.3.220'), $timeout, $retries));
+
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmpget() expects parameter 4 to be long,%s given in %s on line %d
+bool(false)
+
+Warning: snmpget() expects parameter 5 to be long,%s given in %s on line %d
+bool(false)
+Checking working
+Single OID, default timeout and retries
+%unicode|string%(%d) "%s"
+Single OID, default retries
+%unicode|string%(%d) "%s"
+Single OID
+%unicode|string%(%d) "%s"
+Single OID in array
+array(1) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+}
+Multiple OID
+array(2) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+ ["%s"]=>
+ %unicode|string%(%d) "%d"
+}
+More error handling
+Single OID
+
+Warning: snmpget(): Invalid object identifier: .1.3.6.1.2.1..1.1.0 in %s on line %d
+bool(false)
+Single OID in array
+
+Warning: snmpget(): Invalid object identifier: .1.3.6.1.2.1...1.1.0 in %s on line %d
+bool(false)
+Multiple OID
+
+Warning: snmpget(): Invalid object identifier: .1.3.6.1.2.1...1.1.0 in %s on line %d
+bool(false)
+noSuchName checks
+Single OID
+
+Warning: snmpget(): Error in packet at 'SNMPv2-MIB::sysDescr.110': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
+Single OID in array
+
+Warning: snmpget(): Error in packet at 'SNMPv2-MIB::sysDescr.110': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
+Multiple OID
+
+Warning: snmpget(): Error in packet at 'SNMPv2-MIB::sysUpTime.220': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+array(1) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+}
diff --git a/ext/snmp/tests/snmpgetnext.phpt b/ext/snmp/tests/snmpgetnext.phpt
new file mode 100644
index 0000000000..af92d56c7c
--- /dev/null
+++ b/ext/snmp/tests/snmpgetnext.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Function snmpgetnext
+--CREDITS--
+Olivier Doucet & Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Single OID\n";
+var_dump(snmpgetnext($hostname, $community, '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+echo "Single OID in array\n";
+var_dump(snmpgetnext($hostname, $community, array('.1.3.6.1.2.1.1.1.0'), $timeout, $retries));
+echo "Multiple OID\n";
+var_dump(snmpgetnext($hostname, $community, array('.1.3.6.1.2.1.1.1.0', '.1.3.6.1.2.1.1.6.0'), $timeout, $retries));
+
+?>
+--EXPECTF--
+Single OID
+%unicode|string%(%d) "%s"
+Single OID in array
+array(1) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+}
+Multiple OID
+array(2) {
+ ["%s"]=>
+ %unicode|string%(%d) "%s"
+ ["%s"]=>
+ %unicode|string%(%d) "%d"
+}
diff --git a/ext/snmp/tests/snmprealwalk.phpt b/ext/snmp/tests/snmprealwalk.phpt
new file mode 100644
index 0000000000..d1e343e80d
--- /dev/null
+++ b/ext/snmp/tests/snmprealwalk.phpt
@@ -0,0 +1,86 @@
+--TEST--
+Function snmprealwalk
+--CREDITS--
+Olivier Doucet Olivier Doucet Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Checking error handling\n";
+var_dump(snmprealwalk($hostname, $community, '.1.3.6.1.2.1.1', ''));
+var_dump(snmprealwalk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, ''));
+
+echo "Checking working\n";
+echo "Single OID\n";
+$return = snmprealwalk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, $retries);
+var_dump(gettype($return));
+var_dump(sizeof($return));
+var_dump(key($return));
+var_dump(array_shift($return));
+
+echo "Single OID in array\n";
+$return = snmprealwalk($hostname, $community, array('.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump(gettype($return));
+var_dump(sizeof($return));
+var_dump(key($return));
+var_dump(array_shift($return));
+
+echo "More error handling\n";
+echo "Multiple correct OID\n";
+$return = snmprealwalk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6'), $timeout, $retries);
+var_dump($return);
+
+echo "Multiple OID with wrong OID\n";
+$return = snmprealwalk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6...1'), $timeout, $retries);
+var_dump($return);
+$return = snmprealwalk($hostname, $community, array('.1.3.6...1', '.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump($return);
+
+echo "Single nonexisting OID\n";
+$return = snmprealwalk($hostname, $community, array('.1.3.6.99999.0.99999.111'), $timeout, $retries);
+var_dump($return);
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmprealwalk() expects parameter 4 to be long, %s given in %s on line %d
+bool(false)
+
+Warning: snmprealwalk() expects parameter 5 to be long, %s given in %s on line %d
+bool(false)
+Checking working
+Single OID
+%unicode|string%(5) "array"
+int(%d)
+string(%d) "%s"
+string(%d) "%s"
+Single OID in array
+%unicode|string%(5) "array"
+int(%d)
+string(%d) "%s"
+string(%d) "%s"
+More error handling
+Multiple correct OID
+
+Warning: snmprealwalk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Multiple OID with wrong OID
+
+Warning: snmprealwalk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+
+Warning: snmprealwalk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Single nonexisting OID
+
+Warning: snmprealwalk(): Error in packet at '%s': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
diff --git a/ext/snmp/tests/snmpset-nomib.phpt b/ext/snmp/tests/snmpset-nomib.phpt
new file mode 100644
index 0000000000..7428e57c78
--- /dev/null
+++ b/ext/snmp/tests/snmpset-nomib.phpt
@@ -0,0 +1,60 @@
+--TEST--
+Function snmpset (without MIBs loading)
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--ENV--
+return <<<END
+MIBS=
+END;
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Check error handing\n";
+echo "Nonexisting OID\n";
+$z = snmpset($hostname, $communityWrite, '.1.3.6.777.888.999.444.0', 's', 'bbb', $timeout, $retries);
+var_dump($z);
+
+echo "Bogus OID\n";
+$z = snmpset($hostname, $communityWrite, '.1.3...6.777.888.999.444.0', 's', 'bbb', $timeout, $retries);
+var_dump($z);
+
+
+echo "Checking working\n";
+$oid1 = '.1.3.6.1.2.1.1.4.0';
+$oldvalue1 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
+$newvalue1 = $oldvalue1 . '0';
+
+echo "Single OID\n";
+$z = snmpset($hostname, $communityWrite, $oid1, 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+$z = snmpset($hostname, $communityWrite, $oid1, 's', $oldvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+
+?>
+--EXPECTF--
+Check error handing
+Nonexisting OID
+
+Warning: snmpset(): Error in packet at '%s': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
+Bogus OID
+
+Warning: snmpset(): Invalid object identifier: %s in %s on line %d
+bool(false)
+Checking working
+Single OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmpset.phpt b/ext/snmp/tests/snmpset.phpt
new file mode 100644
index 0000000000..055b789d54
--- /dev/null
+++ b/ext/snmp/tests/snmpset.phpt
@@ -0,0 +1,248 @@
+--TEST--
+Function snmpset
+--CREDITS--
+Olivier Doucet Olivier Doucet Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Check error handing\n";
+echo "4args (5 needed)\n";
+$z = snmpset($hostname, $communityWrite, 'SNMPv2-MIB::sysLocation.0');
+var_dump($z);
+
+echo "No type & no value (timeout & retries instead)\n";
+$z = snmpset($hostname, $communityWrite, 'SNMPv2-MIB::sysLocation.0', $timeout, $retries);
+var_dump($z);
+
+echo "No value (timeout instead), retries instead of timeout\n";
+$z = snmpset($hostname, $communityWrite, 'SNMPv2-MIB::sysLocation.0', 'q', $timeout, $retries);
+var_dump($z);
+
+echo "Bogus OID\n";
+$z = snmpset($hostname, $communityWrite, '.1.3.6.777.888.999.444.0', 's', 'bbb', $timeout, $retries);
+var_dump($z);
+
+echo "Checking working\n";
+$oid1 = 'SNMPv2-MIB::sysContact.0';
+$oldvalue1 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
+$newvalue1 = $oldvalue1 . '0';
+$oid2 = 'SNMPv2-MIB::sysLocation.0';
+$oldvalue2 = snmpget($hostname, $communityWrite, $oid1, $timeout, $retries);
+$newvalue2 = $oldvalue2 . '0';
+
+echo "Single OID\n";
+$z = snmpset($hostname, $communityWrite, $oid1, 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+$z = snmpset($hostname, $communityWrite, $oid1, 's', $oldvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+
+echo "Multiple OID\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $newvalue2));
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single type & value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), 's', $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $newvalue1));
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single type, multiple value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), 's', array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $newvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $newvalue2));
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s','s'), array($oldvalue1, $oldvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+
+echo "More error handing\n";
+echo "Single OID, single type in array, single value\n";
+$z = snmpset($hostname, $communityWrite, $oid1, array('s'), $newvalue1, $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Single OID, single type, single value in array\n";
+$z = snmpset($hostname, $communityWrite, $oid1, 's', array($newvalue1), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 1st wrong type\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('sw','s'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 2nd wrong type\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s','sb'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single type in array, multiple value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID & type, singe value in array\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s', 's'), array($newvalue1), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 1st bogus, single type, multiple value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1 . '44.55.66.77', $oid2), 's', array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, 2nd bogus, single type, multiple value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2 . '44.55.66.77'), 's', array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single multiple type (1st bogus), multiple value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('q', 's'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+echo "Multiple OID, single multiple type (2nd bogus), multiple value\n";
+$z = snmpset($hostname, $communityWrite, array($oid1, $oid2), array('s', 'w'), array($newvalue1, $newvalue2), $timeout, $retries);
+var_dump($z);
+var_dump((snmpget($hostname, $communityWrite, $oid1, $timeout, $retries) === $oldvalue1));
+var_dump((snmpget($hostname, $communityWrite, $oid2, $timeout, $retries) === $oldvalue2));
+
+?>
+--EXPECTF--
+Check error handing
+4args (5 needed)
+
+Warning: snmpset() expects at least 5 parameters, 3 given in %s on line %d
+bool(false)
+No type & no value (timeout & retries instead)
+
+Warning: snmpset(): Bogus type '-1', should be single char, got 2 in %s on line %d
+bool(false)
+No value (timeout instead), retries instead of timeout
+
+Warning: snmpset(): Could not add variable: OID='%s' type='q' value='%i': Bad variable type ("q") in %s on line %d
+bool(false)
+Bogus OID
+
+Warning: snmpset(): Error in packet at '%s': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
+Checking working
+Single OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID, single type & value
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Multiple OID, single type, multiple value
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+More error handing
+Single OID, single type in array, single value
+
+Warning: snmpset(): Single objid and multiple type or values are not supported in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Single OID, single type, single value in array
+
+Warning: snmpset(): Single objid and multiple type or values are not supported in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 1st wrong type
+
+Warning: snmpset(): '%s': bogus type 'sw', should be single char, got 2 in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 2nd wrong type
+
+Warning: snmpset(): '%s': bogus type 'sb', should be single char, got 2 in %s on line %s
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, single type in array, multiple value
+
+Warning: snmpset(): '%s': no type set in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID & type, singe value in array
+
+Warning: snmpset(): '%s': no value set in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 1st bogus, single type, multiple value
+
+Warning: snmpset(): Error in packet at '%s': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, 2nd bogus, single type, multiple value
+
+Warning: snmpset(): Error in packet at '%s': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, single multiple type (1st bogus), multiple value
+
+Warning: snmpset(): Could not add variable: OID='%s' type='q' value='%s': Bad variable type ("q") in %s on line %d
+bool(false)
+bool(true)
+bool(true)
+Multiple OID, single multiple type (2nd bogus), multiple value
+
+Warning: snmpset(): Could not add variable: OID='%s' type='w' value='%s': Bad variable type ("w") in %s on line %d
+bool(false)
+bool(true)
+bool(true)
diff --git a/ext/snmp/tests/snmpwalk.phpt b/ext/snmp/tests/snmpwalk.phpt
new file mode 100644
index 0000000000..dd184d6c95
--- /dev/null
+++ b/ext/snmp/tests/snmpwalk.phpt
@@ -0,0 +1,99 @@
+--TEST--
+Function snmpwalk
+--CREDITS--
+Olivier Doucet Olivier Doucet Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+echo "Checking error handling\n";
+var_dump(snmpwalk($hostname, $community, '.1.3.6.1.2.1.1', ''));
+var_dump(snmpwalk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, ''));
+
+echo "Checking working\n";
+echo "Single OID\n";
+$return = snmpwalk($hostname, $community, '.1.3.6.1.2.1.1', $timeout, $retries);
+
+var_dump(gettype($return));
+var_dump(sizeof($return));
+var_dump(gettype($return[0]));
+var_dump(gettype($return[1]));
+
+echo "Single OID in array\n";
+$return = snmpwalk($hostname, $community, array('.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump(gettype($return));
+var_dump(gettype($return[0]));
+
+echo "Default OID\n";
+$return = snmpwalk($hostname, $community, '', $timeout, $retries);
+var_dump(gettype($return));
+var_dump(gettype($return[0]));
+
+echo "More error handling\n";
+echo "Single incorrect OID\n";
+$return = snmpwalk($hostname, $community, '.1.3.6...1', $timeout, $retries);
+var_dump($return);
+
+echo "Multiple correct OID\n";
+$return = snmpwalk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6'), $timeout, $retries);
+var_dump($return);
+
+echo "Multiple OID with wrong OID\n";
+$return = snmpwalk($hostname, $community, array('.1.3.6.1.2.1.1', '.1.3.6...1'), $timeout, $retries);
+var_dump($return);
+$return = snmpwalk($hostname, $community, array('.1.3.6...1', '.1.3.6.1.2.1.1'), $timeout, $retries);
+var_dump($return);
+
+echo "Single nonexisting OID\n";
+$return = snmpwalk($hostname, $community, array('.1.3.6.99999.0.99999.111'), $timeout, $retries);
+var_dump($return);
+
+?>
+--EXPECTF--
+Checking error handling
+
+Warning: snmpwalk() expects parameter 4 to be long, %s given in %s on line %d
+bool(false)
+
+Warning: snmpwalk() expects parameter 5 to be long, %s given in %s on line %d
+bool(false)
+Checking working
+Single OID
+%unicode|string%(5) "array"
+int(%d)
+%unicode|string%(6) "string"
+%unicode|string%(6) "string"
+Single OID in array
+%unicode|string%(5) "array"
+%unicode|string%(6) "string"
+Default OID
+%unicode|string%(5) "array"
+%unicode|string%(6) "string"
+More error handling
+Single incorrect OID
+
+Warning: snmpwalk(): Invalid object identifier: %s in %s on line %d
+bool(false)
+Multiple correct OID
+
+Warning: snmpwalk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Multiple OID with wrong OID
+
+Warning: snmpwalk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+
+Warning: snmpwalk(): Multi OID walks are not supported! in %s on line %d
+bool(false)
+Single nonexisting OID
+
+Warning: snmpwalk(): Error in packet at '%s': (noSuchName) There is no such variable name in this MIB. in %s on line %d
+bool(false)
diff --git a/ext/snmp/tests/wrong_hostname.phpt b/ext/snmp/tests/wrong_hostname.phpt
new file mode 100644
index 0000000000..53c6b22cb0
--- /dev/null
+++ b/ext/snmp/tests/wrong_hostname.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Wrong hostname
+--CREDITS--
+Boris Lytochkin
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__).'/skipif.inc');
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__).'/snmp_include.inc');
+
+//EXPECTF format is quickprint OFF
+snmp_set_quick_print(false);
+snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
+
+var_dump(snmpget('192.168..6.1', 'community', '.1.3.6.1.2.1.1.1.0', $timeout, $retries));
+
+?>
+--EXPECTF--
+Warning: snmpget(): php_network_getaddresses:%snot known in %s on line %d
+bool(false)
diff --git a/ext/soap/TODO.old b/ext/soap/TODO.old
index a1cc15c397..59deb4b9dc 100644
--- a/ext/soap/TODO.old
+++ b/ext/soap/TODO.old
@@ -6,7 +6,6 @@ make internal refrences for soap encoding (use seralization logic)
add ini option for always soap_error_handler
provide user space overriding of serialization certin objects and types
serialization in general needs to be polished/finished... all xsd types
-make perstistant objects and work with or without register_globals on
look to see if php-soap will work with out always_populate_raw_post_data on
see if client will work with ssl.. should be eaiser with php_streams
work on soap seralizer (php serialization)
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
index ee28d99dc0..5addec4ff2 100644
--- a/ext/soap/php_encoding.c
+++ b/ext/soap/php_encoding.c
@@ -29,60 +29,60 @@
#include "zend_interfaces.h"
/* zval type decode */
-static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data);
-
-static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+
+static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
/* String encode */
-static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
/* Null encode */
-static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
/* Array encode */
-static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
-static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
+static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
/* Datetime encode/decode */
-static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-
-static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data);
-static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data);
-
-static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-
-static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data);
-static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+
+static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+
+static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+
+static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
/* Try and guess for non-wsdl clients and servers */
-static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data);
-static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
static int is_map(zval *array);
static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
@@ -391,11 +391,10 @@ static zend_bool soap_check_xml_ref(zval **data, xmlNodePtr node TSRMLS_DC)
return 0;
}
-static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xmlNodePtr parent, int check_class_map)
+static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xmlNodePtr parent, int check_class_map TSRMLS_DC)
{
xmlNodePtr node = NULL;
int add_type = 0;
- TSRMLS_FETCH();
/* Special handling of class SoapVar */
if (data &&
@@ -440,9 +439,9 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml
}
if (zend_hash_find(ht, "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) {
- node = master_to_xml(enc, NULL, style, parent);
+ node = master_to_xml(enc, NULL, style, parent TSRMLS_CC);
} else {
- node = master_to_xml(enc, *zdata, style, parent);
+ node = master_to_xml(enc, *zdata, style, parent TSRMLS_CC);
}
if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode != enc)) {
@@ -519,7 +518,7 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml
smart_str_free(&nscat);
}
if (encode->to_xml) {
- node = encode->to_xml(&encode->details, data, style, parent);
+ node = encode->to_xml(&encode->details, data, style, parent TSRMLS_CC);
if (add_type) {
set_ns_and_type(node, &encode->details);
}
@@ -528,15 +527,14 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml
return node;
}
-xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent)
+xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return master_to_xml_int(encode, data, style, parent, 1);
+ return master_to_xml_int(encode, data, style, parent, 1 TSRMLS_CC);
}
-static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data)
+static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data TSRMLS_DC)
{
zval *ret = NULL;
- TSRMLS_FETCH();
if (SOAP_GLOBAL(typemap)) {
if (encode->details.type_str) {
@@ -580,14 +578,13 @@ static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data)
}
}
if (encode->to_zval) {
- ret = encode->to_zval(&encode->details, data);
+ ret = encode->to_zval(&encode->details, data TSRMLS_CC);
}
return ret;
}
-zval *master_to_zval(encodePtr encode, xmlNodePtr data)
+zval *master_to_zval(encodePtr encode, xmlNodePtr data TSRMLS_DC)
{
- TSRMLS_FETCH();
data = check_and_resolve_href(data);
if (encode == NULL) {
@@ -617,14 +614,13 @@ zval *master_to_zval(encodePtr encode, xmlNodePtr data)
}
}
}
- return master_to_zval_int(encode, data);
+ return master_to_zval_int(encode, data TSRMLS_CC);
}
-xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret = NULL;
zval *return_value;
- TSRMLS_FETCH();
if (type && type->map && type->map->to_xml) {
MAKE_STD_ZVAL(return_value);
@@ -652,10 +648,9 @@ xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr par
return ret;
}
-zval *to_zval_user(encodeTypePtr type, xmlNodePtr node)
+zval *to_zval_user(encodeTypePtr type, xmlNodePtr node TSRMLS_DC)
{
zval *return_value;
- TSRMLS_FETCH();
if (type && type->map && type->map->to_zval) {
xmlBufferPtr buf;
@@ -684,15 +679,13 @@ zval *to_zval_user(encodeTypePtr type, xmlNodePtr node)
/* TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name */
/* String encode/decode */
-static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
FIND_XML_NULL(data, ret);
if (data && data->children) {
if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
- TSRMLS_FETCH();
-
if (SOAP_GLOBAL(encoding) != NULL) {
xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
xmlBufferPtr out = xmlBufferCreate();
@@ -719,15 +712,13 @@ static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
FIND_XML_NULL(data, ret);
if (data && data->children) {
if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
- TSRMLS_FETCH();
-
whiteSpace_replace(data->children->content);
if (SOAP_GLOBAL(encoding) != NULL) {
xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
@@ -755,15 +746,13 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
FIND_XML_NULL(data, ret);
if (data && data->children) {
if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
- TSRMLS_FETCH();
-
whiteSpace_collapse(data->children->content);
if (SOAP_GLOBAL(encoding) != NULL) {
xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
@@ -791,7 +780,7 @@ static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
char *str;
@@ -822,7 +811,7 @@ static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
unsigned char *str;
@@ -870,12 +859,11 @@ static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret, text;
char *str;
int new_len;
- TSRMLS_FETCH();
ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlAddChild(parent, ret);
@@ -959,7 +947,7 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo
return ret;
}
-static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret, text;
unsigned char *str;
@@ -992,7 +980,7 @@ static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNo
return ret;
}
-static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
static char hexconvtab[] = "0123456789ABCDEF";
xmlNodePtr ret, text;
@@ -1031,7 +1019,7 @@ static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNo
return ret;
}
-static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
@@ -1072,7 +1060,7 @@ static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
@@ -1105,7 +1093,7 @@ static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret;
@@ -1136,12 +1124,11 @@ static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNode
return ret;
}
-static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret;
zval tmp;
char *str;
- TSRMLS_FETCH();
ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlAddChild(parent, ret);
@@ -1164,7 +1151,7 @@ static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNo
return ret;
}
-static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
@@ -1194,7 +1181,7 @@ static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret;
@@ -1215,7 +1202,7 @@ static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNode
}
/* Null encode/decode */
-static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
MAKE_STD_ZVAL(ret);
@@ -1223,7 +1210,7 @@ static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret;
@@ -1241,9 +1228,7 @@ static void set_zval_property(zval* object, char* name, zval* val TSRMLS_DC)
old_scope = EG(scope);
EG(scope) = Z_OBJCE_P(object);
-#ifdef ZEND_ENGINE_2
Z_DELREF_P(val);
-#endif
add_property_zval(object, name, val);
EG(scope) = old_scope;
}
@@ -1259,7 +1244,7 @@ static zval* get_zval_property(zval* object, char* name TSRMLS_DC)
ZVAL_STRING(&member, name, 0);
old_scope = EG(scope);
EG(scope) = Z_OBJCE_P(object);
- data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS TSRMLS_CC);
+ data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS, 0 TSRMLS_CC);
if (data == EG(uninitialized_zval_ptr)) {
/* Hack for bug #32455 */
zend_property_info *property_info;
@@ -1293,7 +1278,7 @@ static void unset_zval_property(zval* object, char* name TSRMLS_DC)
ZVAL_STRING(&member, name, 0);
old_scope = EG(scope);
EG(scope) = Z_OBJCE_P(object);
- Z_OBJ_HT_P(object)->unset_property(object, &member TSRMLS_CC);
+ Z_OBJ_HT_P(object)->unset_property(object, &member, 0 TSRMLS_CC);
EG(scope) = old_scope;
} else if (Z_TYPE_P(object) == IS_ARRAY) {
zend_hash_del(Z_ARRVAL_P(object), name, strlen(name)+1);
@@ -1307,7 +1292,7 @@ static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC)
while (node != NULL) {
if (get_zval_property(ret, (char*)node->name TSRMLS_CC) == NULL) {
- zval* val = master_to_zval(get_conversion(XSD_ANYXML), node);
+ zval* val = master_to_zval(get_conversion(XSD_ANYXML), node TSRMLS_CC);
if (any && Z_TYPE_P(any) != IS_ARRAY) {
/* Convert into array */
@@ -1326,7 +1311,7 @@ static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC)
if (Z_TYPE_P(val) == IS_STRING && *Z_STRVAL_P(val) == '<') {
name = NULL;
while (node->next != NULL) {
- zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next);
+ zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next TSRMLS_CC);
if (Z_TYPE_P(val2) != IS_STRING || *Z_STRVAL_P(val) != '<') {
break;
}
@@ -1398,19 +1383,19 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr
if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)r_node->children->content) != 0) {
soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, r_node->children->content);
}
- val = master_to_zval(model->u.element->encode, r_node);
+ val = master_to_zval(model->u.element->encode, r_node TSRMLS_CC);
} else if (model->u.element->fixed) {
xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
- val = master_to_zval(model->u.element->encode, dummy);
+ val = master_to_zval(model->u.element->encode, dummy TSRMLS_CC);
xmlFreeNode(dummy);
} else if (model->u.element->def && !model->u.element->nillable) {
xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
- val = master_to_zval(model->u.element->encode, dummy);
+ val = master_to_zval(model->u.element->encode, dummy TSRMLS_CC);
xmlFreeNode(dummy);
} else {
- val = master_to_zval(model->u.element->encode, r_node);
+ val = master_to_zval(model->u.element->encode, r_node TSRMLS_CC);
}
if ((node = get_node(node->next, model->u.element->name)) != NULL) {
zval *array;
@@ -1423,19 +1408,19 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr
if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)node->children->content) != 0) {
soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, node->children->content);
}
- val = master_to_zval(model->u.element->encode, node);
+ val = master_to_zval(model->u.element->encode, node TSRMLS_CC);
} else if (model->u.element->fixed) {
xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
- val = master_to_zval(model->u.element->encode, dummy);
+ val = master_to_zval(model->u.element->encode, dummy TSRMLS_CC);
xmlFreeNode(dummy);
} else if (model->u.element->def && !model->u.element->nillable) {
xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
- val = master_to_zval(model->u.element->encode, dummy);
+ val = master_to_zval(model->u.element->encode, dummy TSRMLS_CC);
xmlFreeNode(dummy);
} else {
- val = master_to_zval(model->u.element->encode, node);
+ val = master_to_zval(model->u.element->encode, node TSRMLS_CC);
}
add_next_index_zval(array, val);
} while ((node = get_node(node->next, model->u.element->name)) != NULL);
@@ -1484,7 +1469,7 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr
}
/* Struct encode/decode */
-static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_entry *pce)
+static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_entry *pce TSRMLS_DC)
{
zval *ret;
xmlNodePtr trav;
@@ -1492,7 +1477,6 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
sdlTypePtr sdlType = type->sdl_type;
zend_class_entry *ce = ZEND_STANDARD_CLASS_DEF_PTR;
zval *redo_any = NULL;
- TSRMLS_FETCH();
if (pce) {
ce = pce;
@@ -1528,7 +1512,7 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
}
object_init_ex(ret, ce);
- base = master_to_zval_int(enc, data);
+ base = master_to_zval_int(enc, data TSRMLS_CC);
set_zval_property(ret, "_", base TSRMLS_CC);
} else {
ALLOC_INIT_ZVAL(ret);
@@ -1560,9 +1544,9 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
(sdlType->encode->details.sdl_type->encode == NULL ||
(sdlType->encode->details.sdl_type->encode->details.type != IS_ARRAY &&
sdlType->encode->details.sdl_type->encode->details.type != SOAP_ENC_ARRAY))) {
- ret = to_zval_object_ex(&sdlType->encode->details, data, ce);
+ ret = to_zval_object_ex(&sdlType->encode->details, data, ce TSRMLS_CC);
} else {
- ret = master_to_zval_int(sdlType->encode, data);
+ ret = master_to_zval_int(sdlType->encode, data TSRMLS_CC);
}
if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
return ret;
@@ -1581,7 +1565,7 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
}
object_init_ex(ret, ce);
- base = master_to_zval_int(sdlType->encode, data);
+ base = master_to_zval_int(sdlType->encode, data TSRMLS_CC);
set_zval_property(ret, "_", base TSRMLS_CC);
}
} else {
@@ -1637,7 +1621,7 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
text = xmlNewText(BAD_CAST(str_val));
xmlAddChild(dummy, text);
- data = master_to_zval((*attr)->encode, dummy);
+ data = master_to_zval((*attr)->encode, dummy TSRMLS_CC);
xmlFreeNode(dummy);
set_zval_property(ret, (*attr)->name, data TSRMLS_CC);
}
@@ -1661,7 +1645,7 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
zval *tmpVal;
zval *prop;
- tmpVal = master_to_zval(NULL, trav);
+ tmpVal = master_to_zval(NULL, trav TSRMLS_CC);
prop = get_zval_property(ret, (char*)trav->name TSRMLS_CC);
if (!prop) {
@@ -1698,9 +1682,9 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
return ret;
}
-static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
- return to_zval_object_ex(type, data, NULL);
+ return to_zval_object_ex(type, data, NULL TSRMLS_CC);
}
@@ -1735,7 +1719,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *
xmlAddChild(node, property);
set_xsi_nil(property);
} else {
- property = master_to_xml(enc, *val, style, node);
+ property = master_to_xml(enc, *val, style, node TSRMLS_CC);
if (property->children && property->children->content &&
model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
@@ -1758,7 +1742,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *
} else if (Z_TYPE_P(data) == IS_NULL && model->min_occurs == 0) {
return 1;
} else {
- property = master_to_xml(enc, data, style, node);
+ property = master_to_xml(enc, data, style, node TSRMLS_CC);
if (property->children && property->children->content &&
model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
@@ -1810,11 +1794,11 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *
zend_hash_internal_pointer_reset(ht);
while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
- property = master_to_xml(enc, *val, style, node);
+ property = master_to_xml(enc, *val, style, node TSRMLS_CC);
zend_hash_move_forward(ht);
}
} else {
- property = master_to_xml(enc, data, style, node);
+ property = master_to_xml(enc, data, style, node TSRMLS_CC);
}
return 1;
} else if (model->min_occurs == 0) {
@@ -1902,13 +1886,12 @@ static sdlTypePtr model_array_element(sdlContentModelPtr model)
return NULL;
}
-static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr xmlParam;
HashTable *prop = NULL;
int i;
sdlTypePtr sdlType = type->sdl_type;
- TSRMLS_FETCH();
if (!data || Z_TYPE_P(data) == IS_NULL) {
xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
@@ -1941,9 +1924,9 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
if (enc) {
zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
if (tmp) {
- xmlParam = master_to_xml(enc, tmp, style, parent);
+ xmlParam = master_to_xml(enc, tmp, style, parent TSRMLS_CC);
} else if (prop == NULL) {
- xmlParam = master_to_xml(enc, data, style, parent);
+ xmlParam = master_to_xml(enc, data, style, parent TSRMLS_CC);
} else {
xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlAddChild(parent, xmlParam);
@@ -1960,15 +1943,15 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
if (prop) prop->nApplyCount++;
- xmlParam = master_to_xml(sdlType->encode, data, style, parent);
+ xmlParam = master_to_xml(sdlType->encode, data, style, parent TSRMLS_CC);
if (prop) prop->nApplyCount--;
} else {
zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
if (tmp) {
- xmlParam = master_to_xml(sdlType->encode, tmp, style, parent);
+ xmlParam = master_to_xml(sdlType->encode, tmp, style, parent TSRMLS_CC);
} else if (prop == NULL) {
- xmlParam = master_to_xml(sdlType->encode, data, style, parent);
+ xmlParam = master_to_xml(sdlType->encode, data, style, parent TSRMLS_CC);
} else {
xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
xmlAddChild(parent, xmlParam);
@@ -2000,7 +1983,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
xmlAddChild(xmlParam, property);
set_xsi_nil(property);
} else {
- property = master_to_xml(array_el->encode, *val, style, xmlParam);
+ property = master_to_xml(array_el->encode, *val, style, xmlParam TSRMLS_CC);
}
xmlNodeSetName(property, BAD_CAST(array_el->name));
if (style == SOAP_LITERAL &&
@@ -2026,7 +2009,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
if (zattr) {
xmlNodePtr dummy;
- dummy = master_to_xml((*attr)->encode, zattr, SOAP_LITERAL, xmlParam);
+ dummy = master_to_xml((*attr)->encode, zattr, SOAP_LITERAL, xmlParam TSRMLS_CC);
if (dummy->children && dummy->children->content) {
if ((*attr)->fixed && strcmp((*attr)->fixed, (char*)dummy->children->content) != 0) {
soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", (*attr)->name, (*attr)->fixed, dummy->children->content);
@@ -2077,13 +2060,13 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
key_type = zend_hash_get_current_key_ex(prop, &str_key, &str_key_len, &index, FALSE, NULL);
zend_hash_get_current_data(prop, (void **)&zprop);
- property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam);
+ property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam TSRMLS_CC);
if (key_type == HASH_KEY_IS_STRING) {
- char *prop_name;
+ const char *prop_name;
if (Z_TYPE_P(data) == IS_OBJECT) {
- char *class_name;
+ const char *class_name;
zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
} else {
@@ -2104,7 +2087,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
}
/* Array encode/decode */
-static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
encodePtr enc = NULL;
@@ -2119,7 +2102,7 @@ static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xml
enc = get_conversion(IS_NULL);
}
- return master_to_xml(enc, data, style, parent);
+ return master_to_xml(enc, data, style, parent TSRMLS_CC);
}
static int calc_dimension_12(const char* str)
@@ -2222,7 +2205,8 @@ static void add_xml_array_elements(xmlNodePtr xmlParam,
int dimension ,
int* dims,
zval* data,
- int style)
+ int style
+ TSRMLS_DC)
{
int j;
@@ -2239,9 +2223,9 @@ static void add_xml_array_elements(xmlNodePtr xmlParam,
if (zdata) {
if (enc == NULL) {
- xparam = master_to_xml(get_conversion((*zdata)->type), (*zdata), style, xmlParam);
+ xparam = master_to_xml(get_conversion((*zdata)->type), (*zdata), style, xmlParam TSRMLS_CC);
} else {
- xparam = master_to_xml(enc, (*zdata), style, xmlParam);
+ xparam = master_to_xml(enc, (*zdata), style, xmlParam TSRMLS_CC);
}
} else {
xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
@@ -2258,9 +2242,9 @@ static void add_xml_array_elements(xmlNodePtr xmlParam,
}
} else {
if (zdata) {
- add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, *zdata, style);
+ add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, *zdata, style TSRMLS_CC);
} else {
- add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
+ add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style TSRMLS_CC);
}
}
zend_hash_move_forward(data->value.ht);
@@ -2281,7 +2265,7 @@ static void add_xml_array_elements(xmlNodePtr xmlParam,
xmlNodeSetName(xparam, BAD_CAST("item"));
}
} else {
- add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
+ add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style TSRMLS_CC);
}
}
}
@@ -2295,7 +2279,7 @@ static inline int array_num_elements(HashTable* ht)
return 0;
}
-static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
sdlTypePtr sdl_type = type->sdl_type;
sdlTypePtr element_type = NULL;
@@ -2307,7 +2291,6 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
int* dims;
int soap_version;
zval *array_copy = NULL;
- TSRMLS_FETCH();
soap_version = SOAP_GLOBAL(soap_version);
@@ -2562,7 +2545,7 @@ iterator_done:
smart_str_free(&array_type);
smart_str_free(&array_size);
- add_xml_array_elements(xmlParam, element_type, enc, enc?encode_add_ns(xmlParam,enc->details.ns):NULL, dimension, dims, data, style);
+ add_xml_array_elements(xmlParam, element_type, enc, enc?encode_add_ns(xmlParam,enc->details.ns):NULL, dimension, dims, data, style TSRMLS_CC);
efree(dims);
}
if (style == SOAP_ENCODED) {
@@ -2580,7 +2563,7 @@ iterator_done:
return xmlParam;
}
-static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret;
xmlNodePtr trav;
@@ -2594,8 +2577,6 @@ static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
sdlExtraAttributePtr *ext;
sdlTypePtr elementType;
- TSRMLS_FETCH();
-
MAKE_STD_ZVAL(ret);
FIND_XML_NULL(data, ret);
sdl = SOAP_GLOBAL(sdl);
@@ -2747,7 +2728,7 @@ static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
zval *tmpVal, *ar;
xmlAttrPtr position = get_attribute(trav->properties,"position");
- tmpVal = master_to_zval(enc, trav);
+ tmpVal = master_to_zval(enc, trav TSRMLS_CC);
if (position != NULL && position->children && position->children->content) {
char* tmp = strrchr((char*)position->children->content, '[');
if (tmp == NULL) {
@@ -2798,7 +2779,7 @@ static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
}
/* Map encode/decode */
-static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr xmlParam;
int i;
@@ -2840,7 +2821,7 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP
smart_str_free(&tmp);
}
- xparam = master_to_xml(get_conversion((*temp_data)->type), (*temp_data), style, item);
+ xparam = master_to_xml(get_conversion((*temp_data)->type), (*temp_data), style, item TSRMLS_CC);
xmlNodeSetName(xparam, BAD_CAST("value"));
zend_hash_move_forward(data->value.ht);
@@ -2853,7 +2834,7 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP
return xmlParam;
}
-static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
zval *ret, *key, *value;
xmlNodePtr trav, item, xmlKey, xmlValue;
@@ -2877,8 +2858,8 @@ static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
soap_error0(E_ERROR, "Encoding: Can't decode apache map, missing value");
}
- key = master_to_zval(NULL, xmlKey);
- value = master_to_zval(NULL, xmlValue);
+ key = master_to_zval(NULL, xmlKey TSRMLS_CC);
+ value = master_to_zval(NULL, xmlValue TSRMLS_CC);
if (Z_TYPE_P(key) == IS_STRING) {
zend_symtable_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
@@ -2897,7 +2878,7 @@ static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
}
/* Unknown encode/decode */
-static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
encodePtr enc;
xmlNodePtr ret;
@@ -2907,7 +2888,7 @@ static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, x
} else {
enc = get_conversion(IS_NULL);
}
- ret = master_to_xml_int(enc, data, style, parent, 0);
+ ret = master_to_xml_int(enc, data, style, parent, 0 TSRMLS_CC);
/*
if (style == SOAP_LITERAL && SOAP_GLOBAL(sdl)) {
set_ns_and_type(ret, &enc->details);
@@ -2916,13 +2897,12 @@ static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, x
return ret;
}
-static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
+static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
encodePtr enc = NULL;
xmlAttrPtr tmpattr;
xmlChar *type_name = NULL;
zval *ret;
- TSRMLS_FETCH();
data = check_and_resolve_href(data);
@@ -2975,7 +2955,7 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
}
}
}
- ret = master_to_zval_int(enc, data);
+ ret = master_to_zval_int(enc, data TSRMLS_CC);
if (SOAP_GLOBAL(sdl) && type_name && enc->details.sdl_type) {
zval* soapvar;
char *ns, *cptype;
@@ -2984,9 +2964,7 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
MAKE_STD_ZVAL(soapvar);
object_init_ex(soapvar, soap_var_class_entry);
add_property_long(soapvar, "enc_type", enc->details.type);
-#ifdef ZEND_ENGINE_2
Z_DELREF_P(ret);
-#endif
add_property_zval(soapvar, "enc_value", ret);
parse_namespace(type_name, &cptype, &ns);
nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
@@ -3002,7 +2980,7 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
}
/* Time encode/decode */
-static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent TSRMLS_DC)
{
/* logic hacked from ext/standard/datetime.c */
struct tm *ta, tmbuf;
@@ -3066,59 +3044,59 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma
return xmlParam;
}
-static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
/* TODO: '-'?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T([0-9]+H)?([0-9]+M)?([0-9]+S)? */
- return to_xml_string(type, data, style, parent);
+ return to_xml_string(type, data, style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent);
+ return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
/* TODO: microsecconds */
- return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent);
+ return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent);
+ return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "%Y-%m", style, parent);
+ return to_xml_datetime_ex(type, data, "%Y-%m", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "%Y", style, parent);
+ return to_xml_datetime_ex(type, data, "%Y", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "--%m-%d", style, parent);
+ return to_xml_datetime_ex(type, data, "--%m-%d", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "---%d", style, parent);
+ return to_xml_datetime_ex(type, data, "---%d", style, parent TSRMLS_CC);
}
-static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
- return to_xml_datetime_ex(type, data, "--%m--", style, parent);
+ return to_xml_datetime_ex(type, data, "--%m--", style, parent TSRMLS_CC);
}
-static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data) {
+static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data TSRMLS_DC) {
/*FIXME*/
- return to_zval_stringc(enc, data);
+ return to_zval_stringc(enc, data TSRMLS_CC);
}
-static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
+static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent TSRMLS_DC) {
xmlNodePtr ret;
encodePtr list_enc = NULL;
@@ -3141,7 +3119,7 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
zend_hash_internal_pointer_reset(ht);
while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
- xmlNodePtr dummy = master_to_xml(list_enc, *tmp, SOAP_LITERAL, ret);
+ xmlNodePtr dummy = master_to_xml(list_enc, *tmp, SOAP_LITERAL, ret TSRMLS_CC);
if (dummy && dummy->children && dummy->children->content) {
if (list.len != 0) {
smart_str_appendc(&list, ' ');
@@ -3180,7 +3158,7 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
next++;
}
ZVAL_STRING(&dummy_zval, start, 0);
- dummy = master_to_xml(list_enc, &dummy_zval, SOAP_LITERAL, ret);
+ dummy = master_to_xml(list_enc, &dummy_zval, SOAP_LITERAL, ret TSRMLS_CC);
if (dummy && dummy->children && dummy->children->content) {
if (list.len != 0) {
smart_str_appendc(&list, ' ');
@@ -3203,26 +3181,25 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
return ret;
}
-static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
+static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent TSRMLS_DC) {
/*FIXME: minLength=1 */
- return to_xml_list(enc,data,style, parent);
+ return to_xml_list(enc,data,style, parent TSRMLS_CC);
}
-static zval* to_zval_union(encodeTypePtr enc, xmlNodePtr data) {
+static zval* to_zval_union(encodeTypePtr enc, xmlNodePtr data TSRMLS_DC) {
/*FIXME*/
- return to_zval_list(enc, data);
+ return to_zval_list(enc, data TSRMLS_CC);
}
-static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
+static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent TSRMLS_DC) {
/*FIXME*/
- return to_xml_list(enc,data,style, parent);
+ return to_xml_list(enc,data,style, parent TSRMLS_CC);
}
-static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
+static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data TSRMLS_DC)
{
xmlBufferPtr buf;
zval *ret;
- TSRMLS_FETCH();
if (SOAP_GLOBAL(sdl) && SOAP_GLOBAL(sdl)->elements && data->name) {
smart_str nscat = {0};
@@ -3238,7 +3215,7 @@ static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
if (zend_hash_find(SOAP_GLOBAL(sdl)->elements, nscat.c, nscat.len+1, (void **)&sdl_type) == SUCCESS &&
(*sdl_type)->encode) {
smart_str_free(&nscat);
- return master_to_zval_int((*sdl_type)->encode, data);
+ return master_to_zval_int((*sdl_type)->encode, data TSRMLS_CC);
}
smart_str_free(&nscat);
}
@@ -3251,7 +3228,7 @@ static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
return ret;
}
-static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
+static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
xmlNodePtr ret = NULL;
@@ -3266,7 +3243,7 @@ static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodeP
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &el, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos)) {
- ret = master_to_xml(enc, *el, style, parent);
+ ret = master_to_xml(enc, *el, style, parent TSRMLS_CC);
if (ret &&
ret->name != xmlStringTextNoenc &&
zend_hash_get_current_key_ex(Z_ARRVAL_P(data), &name, &name_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
@@ -3301,13 +3278,13 @@ static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodeP
return ret;
}
-zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
+zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data TSRMLS_DC)
{
sdlTypePtr type;
type = enc->sdl_type;
if (type == NULL) {
- return guess_zval_convert(enc, data);
+ return guess_zval_convert(enc, data TSRMLS_CC);
}
/*FIXME: restriction support
if (type && type->restrictions &&
@@ -3341,31 +3318,31 @@ zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
switch (type->kind) {
case XSD_TYPEKIND_SIMPLE:
if (type->encode && enc != &type->encode->details) {
- return master_to_zval_int(type->encode, data);
+ return master_to_zval_int(type->encode, data TSRMLS_CC);
} else {
- return guess_zval_convert(enc, data);
+ return guess_zval_convert(enc, data TSRMLS_CC);
}
break;
case XSD_TYPEKIND_LIST:
- return to_zval_list(enc, data);
+ return to_zval_list(enc, data TSRMLS_CC);
case XSD_TYPEKIND_UNION:
- return to_zval_union(enc, data);
+ return to_zval_union(enc, data TSRMLS_CC);
case XSD_TYPEKIND_COMPLEX:
case XSD_TYPEKIND_RESTRICTION:
case XSD_TYPEKIND_EXTENSION:
if (type->encode &&
(type->encode->details.type == IS_ARRAY ||
type->encode->details.type == SOAP_ENC_ARRAY)) {
- return to_zval_array(enc, data);
+ return to_zval_array(enc, data TSRMLS_CC);
}
- return to_zval_object(enc, data);
+ return to_zval_object(enc, data TSRMLS_CC);
default:
soap_error0(E_ERROR, "Encoding: Internal Error");
- return guess_zval_convert(enc, data);
+ return guess_zval_convert(enc, data TSRMLS_CC);
}
}
-xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent)
+xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent TSRMLS_DC)
{
sdlTypePtr type;
xmlNodePtr ret = NULL;
@@ -3373,7 +3350,7 @@ xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNo
type = enc->sdl_type;
if (type == NULL) {
- ret = guess_xml_convert(enc, data, style, parent);
+ ret = guess_xml_convert(enc, data, style, parent TSRMLS_CC);
if (style == SOAP_ENCODED) {
set_ns_and_type(ret, enc);
}
@@ -3405,16 +3382,16 @@ xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNo
switch(type->kind) {
case XSD_TYPEKIND_SIMPLE:
if (type->encode && enc != &type->encode->details) {
- ret = master_to_xml(type->encode, data, style, parent);
+ ret = master_to_xml(type->encode, data, style, parent TSRMLS_CC);
} else {
- ret = guess_xml_convert(enc, data, style, parent);
+ ret = guess_xml_convert(enc, data, style, parent TSRMLS_CC);
}
break;
case XSD_TYPEKIND_LIST:
- ret = to_xml_list(enc, data, style, parent);
+ ret = to_xml_list(enc, data, style, parent TSRMLS_CC);
break;
case XSD_TYPEKIND_UNION:
- ret = to_xml_union(enc, data, style, parent);
+ ret = to_xml_union(enc, data, style, parent TSRMLS_CC);
break;
case XSD_TYPEKIND_COMPLEX:
case XSD_TYPEKIND_RESTRICTION:
@@ -3422,9 +3399,9 @@ xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNo
if (type->encode &&
(type->encode->details.type == IS_ARRAY ||
type->encode->details.type == SOAP_ENC_ARRAY)) {
- return to_xml_array(enc, data, style, parent);
+ return to_xml_array(enc, data, style, parent TSRMLS_CC);
} else {
- return to_xml_object(enc, data, style, parent);
+ return to_xml_object(enc, data, style, parent TSRMLS_CC);
}
break;
default:
@@ -3548,7 +3525,7 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
}
if (xmlns == NULL) {
xmlChar* prefix;
- TSRMLS_FETCH();
+ TSRMLS_FETCH();
if (zend_hash_find(&SOAP_GLOBAL(defEncNs), (char*)ns, strlen(ns) + 1, (void **)&prefix) == SUCCESS) {
xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), prefix);
@@ -3726,7 +3703,7 @@ static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type TS
smart_str array_type = {0};
if (cur_ns) {
- xmlNsPtr ns = encode_add_ns(node,cur_ns);
+ xmlNsPtr ns = encode_add_ns(node, cur_ns);
smart_str_appends(type, (char*)ns->prefix);
smart_str_appendc(type, ':');
@@ -3762,7 +3739,7 @@ static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smar
strcmp(ns,SOAP_1_2_ENC_NAMESPACE) == 0) {
ns = SOAP_1_1_ENC_NAMESPACE;
}
- xmlns = encode_add_ns(node,ns);
+ xmlns = encode_add_ns(node, ns);
smart_str_appends(ret, (char*)xmlns->prefix);
smart_str_appendc(ret, ':');
}
diff --git a/ext/soap/php_encoding.h b/ext/soap/php_encoding.h
index 93b42eacc0..f3e8f9bbfa 100644
--- a/ext/soap/php_encoding.h
+++ b/ext/soap/php_encoding.h
@@ -183,23 +183,23 @@ struct _encodeType {
struct _encode {
encodeType details;
- zval *(*to_zval)(encodeTypePtr type, xmlNodePtr data);
- xmlNodePtr (*to_xml)(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
+ zval *(*to_zval)(encodeTypePtr type, xmlNodePtr data TSRMLS_DC);
+ xmlNodePtr (*to_xml)(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
};
/* Master functions all encode/decode should be called thur these functions */
-xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent);
-zval *master_to_zval(encodePtr encode, xmlNodePtr data);
+xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+zval *master_to_zval(encodePtr encode, xmlNodePtr data TSRMLS_DC);
/* user defined mapping */
-xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
-zval *to_zval_user(encodeTypePtr type, xmlNodePtr node);
+xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent TSRMLS_DC);
+zval *to_zval_user(encodeTypePtr type, xmlNodePtr node TSRMLS_DC);
void whiteSpace_replace(xmlChar* str);
void whiteSpace_collapse(xmlChar* str);
-xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval* data, int style, xmlNodePtr parent);
-zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data);
+xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval* data, int style, xmlNodePtr parent TSRMLS_DC);
+zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data TSRMLS_DC);
void encode_finish();
void encode_reset_ns();
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
index 358877df63..69deccde7f 100644
--- a/ext/soap/php_http.c
+++ b/ext/soap/php_http.c
@@ -192,7 +192,7 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, ph
namelen = spprintf(&name, 0, "%s://%s:%d", (use_ssl && !*use_proxy)? "ssl" : "tcp", host, port);
stream = php_stream_xport_create(name, namelen,
- ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ REPORT_ERRORS,
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
NULL /*persistent_id*/,
timeout,
@@ -336,7 +336,7 @@ int make_http_soap_request(zval *this_ptr,
n = 3;
ZVAL_STRING(&func, "gzencode", 0);
smart_str_append_const(&soap_headers_z,"Content-Encoding: gzip\r\n");
- ZVAL_LONG(params[2], 1);
+ ZVAL_LONG(params[2], 0x1f);
}
if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, n, params TSRMLS_CC) == SUCCESS &&
Z_TYPE(retval) == IS_STRING) {
@@ -461,7 +461,7 @@ try_again:
if (stream) {
zval **cookies, **login, **password;
- int ret = zend_list_insert(phpurl, le_url);
+ int ret = zend_list_insert(phpurl, le_url TSRMLS_CC);
add_property_resource(this_ptr, "httpurl", ret);
/*zend_list_addref(ret);*/
@@ -507,12 +507,14 @@ try_again:
smart_str_appendc(&soap_headers, ':');
smart_str_append_unsigned(&soap_headers, phpurl->port);
}
- if (http_1_1) {
+ if (!http_1_1 ||
+ (zend_hash_find(Z_OBJPROP_P(this_ptr), "_keep_alive", sizeof("_keep_alive"), (void **)&tmp) == SUCCESS &&
+ Z_LVAL_PP(tmp) == 0)) {
smart_str_append_const(&soap_headers, "\r\n"
- "Connection: Keep-Alive\r\n");
+ "Connection: close\r\n");
} else {
smart_str_append_const(&soap_headers, "\r\n"
- "Connection: close\r\n");
+ "Connection: Keep-Alive\r\n");
}
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_user_agent", sizeof("_user_agent"), (void **)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
@@ -1401,7 +1403,7 @@ static int get_http_body(php_stream *stream, int close, char *headers, char **r
if (header_length < 0 || header_length >= INT_MAX) {
return FALSE;
}
- http_buf = emalloc(header_length + 1);
+ http_buf = safe_emalloc(1, header_length, 1);
while (http_buf_size < header_length) {
int len_read = php_stream_read(stream, http_buf + http_buf_size, header_length - http_buf_size);
if (len_read <= 0) {
diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c
index 318c4e4dcd..c2e3fc3e3a 100644
--- a/ext/soap/php_packet_soap.c
+++ b/ext/soap/php_packet_soap.c
@@ -191,21 +191,21 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
tmp = get_node(fault->children, "faultstring");
if (tmp != NULL && tmp->children != NULL) {
- zval *zv = master_to_zval(get_conversion(IS_STRING), tmp);
+ zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
faultstring = Z_STRVAL_P(zv);
FREE_ZVAL(zv);
}
tmp = get_node(fault->children, "faultactor");
if (tmp != NULL && tmp->children != NULL) {
- zval *zv = master_to_zval(get_conversion(IS_STRING), tmp);
+ zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
faultactor = Z_STRVAL_P(zv);
FREE_ZVAL(zv);
}
tmp = get_node(fault->children, "detail");
if (tmp != NULL) {
- details = master_to_zval(NULL, tmp);
+ details = master_to_zval(NULL, tmp TSRMLS_CC);
}
} else {
tmp = get_node(fault->children, "Code");
@@ -221,7 +221,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
/* TODO: lang attribute */
tmp = get_node(tmp->children,"Text");
if (tmp != NULL && tmp->children != NULL) {
- zval *zv = master_to_zval(get_conversion(IS_STRING), tmp);
+ zval *zv = master_to_zval(get_conversion(IS_STRING), tmp TSRMLS_CC);
faultstring = Z_STRVAL_P(zv);
FREE_ZVAL(zv);
}
@@ -229,7 +229,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
tmp = get_node(fault->children,"Detail");
if (tmp != NULL) {
- details = master_to_zval(NULL, tmp);
+ details = master_to_zval(NULL, tmp TSRMLS_CC);
}
}
add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC);
@@ -239,11 +239,9 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
if (faultactor) {
efree(faultactor);
}
-#ifdef ZEND_ENGINE_2
if (details) {
Z_DELREF_P(details);
}
-#endif
xmlFreeDoc(response);
return FALSE;
}
@@ -327,9 +325,9 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
} else {
/* Decoding value of parameter */
if (param != NULL) {
- tmp = master_to_zval(param->encode, val);
+ tmp = master_to_zval(param->encode, val TSRMLS_CC);
} else {
- tmp = master_to_zval(NULL, val);
+ tmp = master_to_zval(NULL, val TSRMLS_CC);
}
}
add_assoc_zval(return_value, param->paramName, tmp);
@@ -352,7 +350,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
zval *tmp;
zval **arr;
- tmp = master_to_zval(NULL, val);
+ tmp = master_to_zval(NULL, val TSRMLS_CC);
if (val->name) {
if (zend_hash_find(Z_ARRVAL_P(return_value), (char*)val->name, strlen((char*)val->name)+1, (void**)&arr) == SUCCESS) {
add_next_index_zval(*arr, tmp);
@@ -416,7 +414,7 @@ int parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunction
}
smart_str_free(&key);
}
- val = master_to_zval(enc, trav);
+ val = master_to_zval(enc, trav TSRMLS_CC);
add_assoc_zval(soap_headers, (char*)trav->name, val);
}
trav = trav->next;
diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
index e85b606a37..d250850786 100644
--- a/ext/soap/php_sdl.c
+++ b/ext/soap/php_sdl.c
@@ -2373,7 +2373,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s
}
}
- write(f, buf.c, buf.len);
+ php_ignore_value(write(f, buf.c, buf.len));
close(f);
smart_str_free(&buf);
zend_hash_destroy(&tmp_functions);
@@ -3228,7 +3228,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
unsigned char digest[16];
int len = strlen(SOAP_GLOBAL(cache_dir));
time_t cached;
- char *user = php_get_current_user();
+ char *user = php_get_current_user(TSRMLS_C);
int user_len = user ? strlen(user) + 1 : 0;
md5str[0] = '\0';
@@ -3258,7 +3258,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
"_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
context = php_stream_context_from_zval(*tmp, 0);
} else {
- context = php_stream_context_alloc();
+ context = php_stream_context_alloc(TSRMLS_C);
}
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_user_agent", sizeof("_user_agent"), (void **) &tmp) == SUCCESS &&
@@ -3288,7 +3288,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
smart_str_free(&proxy);
if (!context) {
- context = php_stream_context_alloc();
+ context = php_stream_context_alloc(TSRMLS_C);
}
php_stream_context_set_option(context, "http", "proxy", str_proxy);
zval_ptr_dtor(&str_proxy);
@@ -3320,7 +3320,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, long cache_wsdl TSRMLS_DC)
zval *str_headers;
if (!context) {
- context = php_stream_context_alloc();
+ context = php_stream_context_alloc(TSRMLS_C);
} else {
http_context_headers(context, has_authorization, has_proxy_authorization, 0, &headers TSRMLS_CC);
}
diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c
index 93a0606086..9c1f96e215 100644
--- a/ext/soap/php_xml.c
+++ b/ext/soap/php_xml.c
@@ -169,32 +169,6 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
return ret;
}
-#ifndef ZEND_ENGINE_2
-int php_stream_xmlIO_match_wrapper(const char *filename)
-{
- TSRMLS_FETCH();
- return php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ? 1 : 0;
-}
-
-void *php_stream_xmlIO_open_wrapper(const char *filename)
-{
- TSRMLS_FETCH();
- return php_stream_open_wrapper((char*)filename, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
-}
-
-int php_stream_xmlIO_read(void *context, char *buffer, int len)
-{
- TSRMLS_FETCH();
- return php_stream_read((php_stream*)context, buffer, len);
-}
-
-int php_stream_xmlIO_close(void *context)
-{
- TSRMLS_FETCH();
- return php_stream_close((php_stream*)context);
-}
-#endif
-
xmlNsPtr attr_find_ns(xmlAttrPtr node)
{
if (node->ns) {
diff --git a/ext/soap/php_xml.h b/ext/soap/php_xml.h
index 946223c52e..cee5bbd42d 100644
--- a/ext/soap/php_xml.h
+++ b/ext/soap/php_xml.h
@@ -44,13 +44,6 @@ xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns
xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns);
int parse_namespace(const xmlChar *inval,char **value,char **namespace);
-#ifndef ZEND_ENGINE_2
-int php_stream_xmlIO_match_wrapper(const char *filename);
-void *php_stream_xmlIO_open_wrapper(const char *filename);
-int php_stream_xmlIO_read(void *context, char *buffer, int len);
-int php_stream_xmlIO_close(void *context);
-#endif
-
#define FOREACHATTRNODE(n,c,i) FOREACHATTRNODEEX(n,c,NULL,i)
#define FOREACHATTRNODEEX(n,c,ns,i) \
do { \
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 120f78071b..abeab53b9e 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -26,9 +26,8 @@
#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
#include "ext/session/php_session.h"
#endif
-#ifdef ZEND_ENGINE_2
-# include "zend_exceptions.h"
-#endif
+#include "zend_exceptions.h"
+
static int le_sdl = 0;
int le_url = 0;
@@ -69,10 +68,6 @@ static void delete_service(void *service);
static void delete_url(void *handle);
static void delete_hashtable(void *hashtable);
-#ifndef ZEND_ENGINE_2
-static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
-#endif
-
static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
#define SOAP_SERVER_BEGIN_CODE() \
@@ -90,7 +85,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const
SOAP_GLOBAL(error_object) = _old_error_object;\
SOAP_GLOBAL(soap_version) = _old_soap_version;
-#ifdef ZEND_ENGINE_2
#define SOAP_CLIENT_BEGIN_CODE() \
zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
char* _old_error_code = SOAP_GLOBAL(error_code);\
@@ -134,22 +128,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const
if (_bailout) {\
zend_bailout();\
}
-#else
-#define SOAP_CLIENT_BEGIN_CODE() \
- zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
- char* _old_error_code = SOAP_GLOBAL(error_code);\
- zval* _old_error_object = SOAP_GLOBAL(error_object);\
- int _old_soap_version = SOAP_GLOBAL(soap_version);\
- SOAP_GLOBAL(use_soap_error_handler) = 1;\
- SOAP_GLOBAL(error_code) = "Client";\
- SOAP_GLOBAL(error_object) = this_ptr;
-
-#define SOAP_CLIENT_END_CODE() \
- SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
- SOAP_GLOBAL(error_code) = _old_error_code;\
- SOAP_GLOBAL(error_object) = _old_error_object;\
- SOAP_GLOBAL(soap_version) = _old_soap_version;
-#endif
#define FETCH_THIS_SDL(ss) \
{ \
@@ -215,27 +193,6 @@ PHP_MINIT_FUNCTION(soap);
PHP_MSHUTDOWN_FUNCTION(soap);
PHP_MINFO_FUNCTION(soap);
-#ifndef ZEND_ENGINE_2
-# ifndef PHP_METHOD
-# define PHP_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name))
-# define PHP_ME(classname, name, arg_info, flags) ZEND_NAMED_FE(name, ZEND_FN(classname##_##name), arg_info)
-# endif
-
-static char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length)
-{
- register unsigned char *str = (unsigned char*)source;
- register unsigned char *result = (unsigned char*)dest;
- register unsigned char *end = str + length;
-
- while (str < end) {
- *result++ = tolower((int)*str++);
- }
- *result = *end;
-
- return dest;
-}
-#endif
-
/*
Registry Functions
TODO: this!
@@ -276,9 +233,7 @@ PHP_METHOD(SoapVar, SoapVar);
/* SoapFault Functions */
PHP_METHOD(SoapFault, SoapFault);
-#ifdef ZEND_ENGINE_2
PHP_METHOD(SoapFault, __toString);
-#endif
/* SoapParam Functions */
PHP_METHOD(SoapParam, SoapParam);
@@ -289,7 +244,6 @@ PHP_METHOD(SoapHeader, SoapHeader);
#define SOAP_CTOR(class_name, func_name, arginfo, flags) PHP_ME(class_name, func_name, arginfo, flags)
/* {{{ arginfo */
-#ifdef ZEND_ENGINE_2
ZEND_BEGIN_ARG_INFO(arginfo_soap__void, 0)
ZEND_END_ARG_INFO()
@@ -429,43 +383,6 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_is_soap_fault, 0, 0, 1)
ZEND_ARG_INFO(0, object)
ZEND_END_ARG_INFO()
-#else
-unsigned char arginfo_soapclient___call[] = { 2, BYREF_NONE, BYREF_NONE };
-unsigned char arginfo_soapclient___soapcall[] = { 5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
-# define arginfo_soapclient_soapclient NULL
-# define arginfo_soapclient___getlastrequest NULL
-# define arginfo_soapclient___getlastresponse NULL
-# define arginfo_soapclient___getlastrequestheaders NULL
-# define arginfo_soapclient___getlastresponseheaders NULL
-# define arginfo_soapclient___getfunctions NULL
-# define arginfo_soapclient___gettypes NULL
-# define arginfo_soapclient___dorequest NULL
-# define arginfo_soapclient___setcookie NULL
-# define arginfo_soapclient___setlocation NULL
-# define arginfo_soapclient___setsoapheaders NULL
-
-# define arginfo_soapserver_soapserver NULL
-# define arginfo_soapserver_setpersistence NULL
-# define arginfo_soapserver_setclass NULL
-# define arginfo_soapserver_setobject NULL
-# define arginfo_soapserver_addfunction NULL
-# define arginfo_soapserver_getfunctions NULL
-# defina arginfo_soapserver_handle NULL
-# define arginfo_soapserver_fault NULL
-# define arginfo_soapserver_addsoapheader NULL
-
-# define arginfo_soapvar_soapvar NULL
-
-# define arginfo_soapfault_soapfault NULL
-
-# define arginfo_soapheader_soapheader NULL
-
-# define arginfo_soapparam_soapparam NULL
-
-# define arginfo_soap_use_soap_error_handler NULL
-
-# define arginfo_soap_is_soap_fault NULL
-#endif
/* }}} */
static const zend_function_entry soap_functions[] = {
@@ -476,9 +393,7 @@ static const zend_function_entry soap_functions[] = {
static const zend_function_entry soap_fault_functions[] = {
SOAP_CTOR(SoapFault, SoapFault, arginfo_soapfault_soapfault, 0)
-#ifdef ZEND_ENGINE_2
PHP_ME(SoapFault, __toString, arginfo_soap__void, 0)
-#endif
PHP_FE_END
};
@@ -548,10 +463,6 @@ zend_module_entry soap_module_entry = {
ZEND_GET_MODULE(soap)
#endif
-#ifndef ZEND_ENGINE_2
-# define OnUpdateLong OnUpdateInt
-#endif
-
ZEND_INI_MH(OnUpdateCacheEnabled)
{
if (OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) {
@@ -694,18 +605,10 @@ PHP_MINIT_FUNCTION(soap)
ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, NULL);
REGISTER_INI_ENTRIES();
-#ifndef ZEND_ENGINE_2
- /* Enable php stream/wrapper support for libxml */
- xmlRegisterDefaultInputCallbacks();
- xmlRegisterInputCallbacks(php_stream_xmlIO_match_wrapper, php_stream_xmlIO_open_wrapper,
- php_stream_xmlIO_read, php_stream_xmlIO_close);
-#endif
-
/* Register SoapClient class */
/* BIG NOTE : THIS EMITS AN COMPILATION WARNING UNDER ZE2 - handle_function_call deprecated.
soap_call_function_handler should be of type struct _zend_function, not (*handle_function_call).
*/
-#ifdef ZEND_ENGINE_2
{
zend_internal_function fe;
@@ -717,17 +620,11 @@ PHP_MINIT_FUNCTION(soap)
fe.prototype = NULL;
fe.num_args = 2;
fe.arg_info = NULL;
- fe.pass_rest_by_reference = 0;
INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
(zend_function *)&fe, NULL, NULL);
soap_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
}
-#else
- INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions, soap_call_function_handler, NULL, NULL);
- soap_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
-#endif
-
/* Register SoapVar class */
INIT_CLASS_ENTRY(ce, PHP_SOAP_VAR_CLASSNAME, soap_var_functions);
soap_var_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
@@ -738,11 +635,7 @@ PHP_MINIT_FUNCTION(soap)
/* Register SoapFault class */
INIT_CLASS_ENTRY(ce, PHP_SOAP_FAULT_CLASSNAME, soap_fault_functions);
-#ifdef ZEND_ENGINE_2
soap_fault_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
-#else
- soap_fault_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
-#endif
/* Register SoapParam class */
INIT_CLASS_ENTRY(ce, PHP_SOAP_PARAM_CLASSNAME, soap_param_functions);
@@ -880,9 +773,6 @@ PHP_METHOD(SoapParam, SoapParam)
return;
}
-#ifndef ZEND_ENGINE_2
- zval_add_ref(&data);
-#endif
add_property_stringl(this_ptr, "param_name", name, name_length, 1);
add_property_zval(this_ptr, "param_data", data);
}
@@ -913,9 +803,6 @@ PHP_METHOD(SoapHeader, SoapHeader)
add_property_stringl(this_ptr, "namespace", ns, ns_len, 1);
add_property_stringl(this_ptr, "name", name, name_len, 1);
if (data) {
-#ifndef ZEND_ENGINE_2
- zval_add_ref(&data);
-#endif
add_property_zval(this_ptr, "data", data);
}
add_property_bool(this_ptr, "mustUnderstand", must_understand);
@@ -987,7 +874,6 @@ PHP_METHOD(SoapFault, SoapFault)
/* }}} */
-#ifdef ZEND_ENGINE_2
/* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
SoapFault constructor */
PHP_METHOD(SoapFault, __toString)
@@ -1030,7 +916,6 @@ PHP_METHOD(SoapFault, __toString)
RETURN_STRINGL(str, len, 0);
}
/* }}} */
-#endif
/* {{{ proto object SoapVar::SoapVar ( mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]])
SoapVar constructor */
@@ -1056,9 +941,6 @@ PHP_METHOD(SoapVar, SoapVar)
}
if (data) {
-#ifndef ZEND_ENGINE_2
- zval_add_ref(&data);
-#endif
add_property_zval(this_ptr, "enc_value", data);
}
@@ -1265,7 +1147,7 @@ PHP_METHOD(SoapServer, SoapServer)
ALLOC_HASHTABLE(service->class_map);
zend_hash_init(service->class_map, zend_hash_num_elements((*tmp)->value.ht), NULL, ZVAL_PTR_DTOR, 0);
- zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_property_ctor, (void *) &ztmp, sizeof(zval *));
+ zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *));
}
if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
@@ -1315,7 +1197,7 @@ PHP_METHOD(SoapServer, SoapServer)
service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
}
- ret = zend_list_insert(service, le_service);
+ ret = zend_list_insert(service, le_service TSRMLS_CC);
add_property_resource(this_ptr, "service", ret);
SOAP_SERVER_END_CODE();
@@ -1360,11 +1242,8 @@ PHP_METHOD(SoapServer, setClass)
{
soapServicePtr service;
char *classname;
-#ifdef ZEND_ENGINE_2
zend_class_entry **ce;
-#else
- zend_class_entry *ce;
-#endif
+
int classname_len, found, num_args = 0;
zval ***argv = NULL;
@@ -1376,20 +1255,12 @@ PHP_METHOD(SoapServer, setClass)
return;
}
-#ifdef ZEND_ENGINE_2
found = zend_lookup_class(classname, classname_len, &ce TSRMLS_CC);
-#else
- char *class_name = estrdup(classname);
- found = zend_hash_find(EG(class_table), php_strtolower(class_name, classname_len), classname_len + 1, (void **)&ce);
- efree(class_name);
-#endif
+
if (found != FAILURE) {
service->type = SOAP_CLASS;
-#ifdef ZEND_ENGINE_2
service->soap_class.ce = *ce;
-#else
- service->soap_class.ce = ce;
-#endif
+
service->soap_class.persistance = SOAP_PERSISTENCE_REQUEST;
service->soap_class.argc = num_args;
if (service->soap_class.argc > 0) {
@@ -1666,7 +1537,7 @@ PHP_METHOD(SoapServer, handle)
ALLOC_INIT_ZVAL(retval);
- if (php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC) != SUCCESS) {
+ if (php_output_start_default(TSRMLS_C) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_ERROR,"ob_start failed");
}
@@ -1751,17 +1622,15 @@ PHP_METHOD(SoapServer, handle)
old_soap_version = SOAP_GLOBAL(soap_version);
function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers TSRMLS_CC);
xmlFreeDoc(doc_request);
-
-#ifdef ZEND_ENGINE_2
+
if (EG(exception)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
}
goto fail;
}
-#endif
service->soap_headers_ptr = &soap_headers;
@@ -1796,7 +1665,6 @@ PHP_METHOD(SoapServer, handle)
object_init_ex(tmp_soap, service->soap_class.ce);
/* Call constructor */
-#ifdef ZEND_ENGINE_2
if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
zval c_ret, constructor;
@@ -1808,7 +1676,7 @@ PHP_METHOD(SoapServer, handle)
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
}
if (EG(exception)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
@@ -1821,9 +1689,6 @@ PHP_METHOD(SoapServer, handle)
zval_dtor(&constructor);
zval_dtor(&c_ret);
} else {
-#else
- {
-#endif
int class_name_len = strlen(service->soap_class.ce->name);
char *class_name = emalloc(class_name_len+1);
@@ -1838,9 +1703,9 @@ PHP_METHOD(SoapServer, handle)
if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
}
-#ifdef ZEND_ENGINE_2
+
if (EG(exception)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
@@ -1851,7 +1716,7 @@ PHP_METHOD(SoapServer, handle)
zval_ptr_dtor(&tmp_soap);
goto fail;
}
-#endif
+
zval_dtor(&constructor);
zval_dtor(&c_ret);
}
@@ -1920,14 +1785,13 @@ PHP_METHOD(SoapServer, handle)
Z_TYPE_PP(tmp) != IS_NULL) {
headerfault = *tmp;
}
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
soap_server_fault_ex(function, &h->retval, h TSRMLS_CC);
efree(fn_name);
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
goto fail;
-#ifdef ZEND_ENGINE_2
} else if (EG(exception)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
zval *headerfault = NULL, **tmp;
@@ -1941,7 +1805,6 @@ PHP_METHOD(SoapServer, handle)
efree(fn_name);
if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
goto fail;
-#endif
}
} else if (h->mustUnderstand) {
soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
@@ -1975,9 +1838,8 @@ PHP_METHOD(SoapServer, handle)
}
efree(fn_name);
-#ifdef ZEND_ENGINE_2
if (EG(exception)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
@@ -1993,13 +1855,13 @@ PHP_METHOD(SoapServer, handle)
}
goto fail;
}
-#endif
+
if (call_status == SUCCESS) {
char *response_name;
if (Z_TYPE_P(retval) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(retval), soap_fault_class_entry TSRMLS_CC)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
soap_server_fault_ex(function, retval, NULL TSRMLS_CC);
goto fail;
}
@@ -2018,9 +1880,8 @@ PHP_METHOD(SoapServer, handle)
return;
}
-#ifdef ZEND_ENGINE_2
if (EG(exception)) {
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
@@ -2036,10 +1897,9 @@ PHP_METHOD(SoapServer, handle)
}
goto fail;
}
-#endif
/* Flush buffer */
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
if (doc_return) {
/* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
@@ -2057,39 +1917,14 @@ PHP_METHOD(SoapServer, handle)
xmlFreeDoc(doc_return);
- if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0) &&
- zend_hash_exists(EG(function_table), "ob_gzhandler", sizeof("ob_gzhandler"))) {
- zval nm_ob_gzhandler;
- zval str;
- zval mode;
- zval result;
- zval *params[2];
-
- INIT_ZVAL(result);
- ZVAL_STRINGL(&nm_ob_gzhandler, "ob_gzhandler", sizeof("ob_gzhandler") - 1, 0);
- INIT_PZVAL(&str);
- ZVAL_STRINGL(&str, (char*)buf, size, 0);
- params[0] = &str;
- INIT_PZVAL(&mode);
- ZVAL_LONG(&mode, PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END);
- params[1] = &mode;
- if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE &&
- Z_TYPE(result) == IS_STRING &&
- zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) {
- xmlFree(buf);
- buf = NULL;
- snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", Z_STRLEN(result));
- sapi_add_header(cont_len, strlen(cont_len), 1);
- php_write(Z_STRVAL(result), Z_STRLEN(result) TSRMLS_CC);
- }
- zval_dtor(&result);
- }
- if (buf) {
+ if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
+ sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
+ } else {
snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
sapi_add_header(cont_len, strlen(cont_len), 1);
- php_write(buf, size TSRMLS_CC);
- xmlFree(buf);
}
+ php_write(buf, size TSRMLS_CC);
+ xmlFree(buf);
} else {
sapi_add_header("HTTP/1.1 202 Accepted", sizeof("HTTP/1.1 202 Accepted")-1, 1);
sapi_add_header("Content-Length: 0", sizeof("Content-Length: 0")-1, 1);
@@ -2228,47 +2063,22 @@ static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeade
if (use_http_error_status) {
sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1);
}
+ if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
+ sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
+ } else {
+ snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
+ sapi_add_header(cont_len, strlen(cont_len), 1);
+ }
if (soap_version == SOAP_1_2) {
sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
} else {
sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
}
- if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0) &&
- zend_hash_exists(EG(function_table), "ob_gzhandler", sizeof("ob_gzhandler"))) {
- zval nm_ob_gzhandler;
- zval str;
- zval mode;
- zval result;
- zval *params[2];
-
- INIT_ZVAL(result);
- ZVAL_STRINGL(&nm_ob_gzhandler, "ob_gzhandler", sizeof("ob_gzhandler") - 1, 0);
- INIT_PZVAL(&str);
- ZVAL_STRINGL(&str, (char*)buf, size, 0);
- params[0] = &str;
- INIT_PZVAL(&mode);
- ZVAL_LONG(&mode, PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END);
- params[1] = &mode;
- if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE &&
- Z_TYPE(result) == IS_STRING &&
- zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) {
- xmlFree(buf);
- buf = NULL;
- snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", Z_STRLEN(result));
- sapi_add_header(cont_len, strlen(cont_len), 1);
- php_write(Z_STRVAL(result), Z_STRLEN(result) TSRMLS_CC);
- }
- zval_dtor(&result);
- }
- if (buf) {
- snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
- sapi_add_header(cont_len, strlen(cont_len), 1);
- php_write(buf, size TSRMLS_CC);
- xmlFree(buf);
- }
+ php_write(buf, size TSRMLS_CC);
xmlFreeDoc(doc_return);
+ xmlFree(buf);
zend_clear_exception(TSRMLS_C);
}
@@ -2306,7 +2116,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const
if (SOAP_GLOBAL(error_object) &&
Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_class_entry TSRMLS_CC)) {
-#ifdef ZEND_ENGINE_2
zval **tmp;
int use_exceptions = 0;
@@ -2379,9 +2188,6 @@ static void soap_error_handler(int error_num, const char *error_filename, const
/* Ignore libxml warnings during WSDL parsing */
call_old_error_handler(error_num, error_filename, error_lineno, format, args);
}
-#else
- call_old_error_handler(error_num, error_filename, error_lineno, format, args);
-#endif
} else {
int old = PG(display_errors);
int fault = 0;
@@ -2431,11 +2237,11 @@ static void soap_error_handler(int error_num, const char *error_filename, const
}
/* Get output buffer and send as fault detials */
- if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
+ if (php_output_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
ALLOC_INIT_ZVAL(outbuf);
- php_ob_get_buffer(outbuf TSRMLS_CC);
+ php_output_get_contents(outbuf TSRMLS_CC);
}
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
}
INIT_ZVAL(fault_obj);
@@ -2591,7 +2397,7 @@ PHP_METHOD(SoapClient, SoapClient)
if (zend_hash_find(ht, "local_cert", sizeof("local_cert"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_STRING) {
if (!context) {
- context = php_stream_context_alloc();
+ context = php_stream_context_alloc(TSRMLS_C);
}
php_stream_context_set_option(context, "ssl", "local_cert", *tmp);
if (zend_hash_find(ht, "passphrase", sizeof("passphrase"), (void**)&tmp) == SUCCESS &&
@@ -2604,13 +2410,13 @@ PHP_METHOD(SoapClient, SoapClient)
Z_LVAL_PP(tmp) == 1) {
add_property_long(this_ptr, "trace", 1);
}
-#ifdef ZEND_ENGINE_2
+
if (zend_hash_find(ht, "exceptions", sizeof("exceptions"), (void**)&tmp) == SUCCESS &&
(Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
Z_LVAL_PP(tmp) == 0) {
add_property_bool(this_ptr, "_exceptions", 0);
}
-#endif
+
if (zend_hash_find(ht, "compression", sizeof("compression"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_LONG &&
zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate")) &&
@@ -2638,9 +2444,8 @@ PHP_METHOD(SoapClient, SoapClient)
MAKE_STD_ZVAL(class_map);
MAKE_COPY_ZVAL(tmp, class_map);
-#ifdef ZEND_ENGINE_2
Z_DELREF_P(class_map);
-#endif
+
add_property_zval(this_ptr, "_classmap", class_map);
}
@@ -2675,6 +2480,11 @@ PHP_METHOD(SoapClient, SoapClient)
Z_TYPE_PP(tmp) == IS_STRING) {
add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
+
+ if (zend_hash_find(ht, "keep_alive", sizeof("keep_alive"), (void**)&tmp) == SUCCESS &&
+ (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) && Z_LVAL_PP(tmp) == 0) {
+ add_property_long(this_ptr, "_keep_alive", 0);
+ }
} else if (Z_TYPE_P(wsdl) == IS_NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are required in nonWSDL mode");
}
@@ -2688,7 +2498,7 @@ PHP_METHOD(SoapClient, SoapClient)
SOAP_GLOBAL(soap_version) = soap_version;
sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
- ret = zend_list_insert(sdl, le_sdl);
+ ret = zend_list_insert(sdl, le_sdl TSRMLS_CC);
add_property_resource(this_ptr, "sdl", ret);
@@ -2700,7 +2510,7 @@ PHP_METHOD(SoapClient, SoapClient)
if (typemap) {
int ret;
- ret = zend_list_insert(typemap, le_typemap);
+ ret = zend_list_insert(typemap, le_typemap TSRMLS_CC);
add_property_resource(this_ptr, "typemap", ret);
}
}
@@ -2958,7 +2768,7 @@ static void do_soap_call(zval* this_ptr,
zval_copy_ctor(return_value);
}
}
-#ifdef ZEND_ENGINE_2
+
if (!EG(exception) &&
Z_TYPE_P(return_value) == IS_OBJECT &&
instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry TSRMLS_CC) &&
@@ -2970,7 +2780,7 @@ static void do_soap_call(zval* this_ptr,
MAKE_COPY_ZVAL(&return_value, exception);
zend_throw_exception_object(exception TSRMLS_CC);
}
-#endif
+
if (SOAP_GLOBAL(encoding) != NULL) {
xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
}
@@ -3379,41 +3189,6 @@ PHP_METHOD(SoapClient, __setLocation)
}
/* }}} */
-#ifndef ZEND_ENGINE_2
-static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
-{
- zval *object = property_reference->object;
- zend_overloaded_element *function_name = (zend_overloaded_element *)property_reference->elements_list->tail->data;
- char *function = Z_STRVAL(function_name->element);
- zend_function *builtin_function;
-
- /*
- Find if the function being called is already defined...
- ( IMHO: zend should handle this functionality )
- */
- if (zend_hash_find(&Z_OBJCE_P(this_ptr)->function_table, function, Z_STRLEN(function_name->element) + 1, (void **) &builtin_function) == SUCCESS) {
- builtin_function->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- } else {
- int arg_count = ZEND_NUM_ARGS();
- zval **arguments = (zval **) safe_emalloc(sizeof(zval *), arg_count, 0);
- zval **soap_headers_p
- HashTable *soap_headers;
-
- zend_get_parameters_array(ht, arg_count, arguments);
-
- if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_properties"), (void **) soap_headers_p)==SUCCESS
- && Z_TYPE_P(soap_headers_p)==IS_ARRAY) {
- soap_headers = Z_ARRVAL_P(soap_headers_p);
- } else {
- soap_headers = NULL;
- }
- do_soap_call(this_ptr, function, Z_STRLEN(function_name->element) + 1, arg_count, arguments, return_value, NULL, NULL, NULL, soap_headers, NULL TSRMLS_CC);
- efree(arguments);
- }
- zval_dtor(&function_name->element);
-}
-#endif
-
static void clear_soap_fault(zval *obj TSRMLS_DC)
{
if (obj != NULL && obj->type == IS_OBJECT) {
@@ -3426,9 +3201,8 @@ zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *faul
zval *fault;
ALLOC_INIT_ZVAL(fault);
set_soap_fault(fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC);
-#ifdef ZEND_ENGINE_2
Z_DELREF_P(fault);
-#endif
+
add_property_zval(obj, "__soap_fault", fault);
return fault;
}
@@ -3440,9 +3214,7 @@ static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, cha
}
add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
-#ifdef ZEND_ENGINE_2
zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
-#endif
if (fault_code != NULL) {
int soap_version = SOAP_GLOBAL(soap_version);
@@ -3488,7 +3260,7 @@ static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, cha
}
}
-static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval ***parameters)
+static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval ***parameters TSRMLS_DC)
{
int cur_param = 0,num_of_params = 0;
zval **tmp_parameters = NULL;
@@ -3519,7 +3291,7 @@ static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, i
MAKE_STD_ZVAL(tmp_parameters[cur_param]);
ZVAL_NULL(tmp_parameters[cur_param]);
} else {
- tmp_parameters[cur_param] = master_to_zval((*param)->encode, val);
+ tmp_parameters[cur_param] = master_to_zval((*param)->encode, val TSRMLS_CC);
}
cur_param++;
@@ -3549,7 +3321,7 @@ static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, i
((sdlSoapBindingFunctionPtr)function->bindingAttributes)->style == SOAP_DOCUMENT &&
(function->requestParameters == NULL ||
zend_hash_num_elements(function->requestParameters) == 0) &&
- strcmp(params->name, function->functionName) == 0) {
+ strcmp((char *)params->name, function->functionName) == 0) {
num_of_params = 0;
} else if (num_of_params > 0) {
tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
@@ -3569,7 +3341,7 @@ static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, i
} else {
enc = (*param)->encode;
}
- tmp_parameters[cur_param] = master_to_zval(enc, trav);
+ tmp_parameters[cur_param] = master_to_zval(enc, trav TSRMLS_CC);
cur_param++;
}
trav = trav->next;
@@ -3577,7 +3349,6 @@ static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, i
}
}
if (num_of_params > cur_param) {
- TSRMLS_FETCH();
soap_server_fault("Client","Missing parameter", NULL, NULL, NULL TSRMLS_CC);
}
(*parameters) = tmp_parameters;
@@ -3837,7 +3608,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
if (h->hdr) {
h->num_params = 1;
h->parameters = emalloc(sizeof(zval*));
- h->parameters[0] = master_to_zval(h->hdr->encode, hdr_func);
+ h->parameters[0] = master_to_zval(h->hdr->encode, hdr_func TSRMLS_CC);
} else {
if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) {
sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes;
@@ -3845,7 +3616,7 @@ static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, c
hdr_func = hdr_func->children;
}
}
- deserialize_parameters(hdr_func, h->function, &h->num_params, &h->parameters);
+ deserialize_parameters(hdr_func, h->function, &h->num_params, &h->parameters TSRMLS_CC);
}
INIT_ZVAL(h->retval);
if (last == NULL) {
@@ -3868,7 +3639,7 @@ ignore_header:
} else {
func = func->children;
}
- deserialize_parameters(func, function, num_params, parameters);
+ deserialize_parameters(func, function, num_params, parameters TSRMLS_CC);
encode_finish();
@@ -4060,7 +3831,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
use = SOAP_ENCODED;
}
} else {
- xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head);
+ xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
if (hdr_name) {
xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
}
@@ -4141,11 +3912,11 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
efree(str);
}
if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
- xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param);
+ xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param TSRMLS_CC);
xmlNodeSetName(node, BAD_CAST("faultstring"));
}
if (zend_hash_find(prop, "faultactor", sizeof("faultactor"), (void**)&tmp) == SUCCESS) {
- xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param);
+ xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param TSRMLS_CC);
xmlNodeSetName(node, BAD_CAST("faultactor"));
}
detail_name = "detail";
@@ -4167,7 +3938,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
}
if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Reason"), NULL);
- node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, node);
+ node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, node TSRMLS_CC);
xmlNodeSetName(node, BAD_CAST("Text"));
xmlSetNs(node, ns);
}
@@ -4285,7 +4056,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
use = SOAP_ENCODED;
}
} else {
- xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head);
+ xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
if (hdr_name) {
xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
}
@@ -4490,7 +4261,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
}
if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
- h = master_to_xml(enc, *tmp, hdr_use, head);
+ h = master_to_xml(enc, *tmp, hdr_use, head TSRMLS_CC);
xmlNodeSetName(h, BAD_CAST(Z_STRVAL_PP(name)));
} else {
h = xmlNewNode(NULL, BAD_CAST(Z_STRVAL_PP(name)));
@@ -4610,7 +4381,7 @@ static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName,
} else {
enc = NULL;
}
- xmlParam = master_to_xml(enc, val, style, parent);
+ xmlParam = master_to_xml(enc, val, style, parent TSRMLS_CC);
if (!strcmp((char*)xmlParam->name, "BOGUS")) {
xmlNodeSetName(xmlParam, BAD_CAST(paramName));
}
diff --git a/ext/soap/tests/bugs/bug31422.phpt b/ext/soap/tests/bugs/bug31422.phpt
index 40e89730f8..c8ddcfe092 100644
--- a/ext/soap/tests/bugs/bug31422.phpt
+++ b/ext/soap/tests/bugs/bug31422.phpt
@@ -9,6 +9,7 @@ require_once('skipif.inc');
?>
--INI--
log_errors=1
+error_log=
--FILE--
<?php
function Add($x,$y) {
diff --git a/ext/soap/tests/error_handler.phpt b/ext/soap/tests/error_handler.phpt
deleted file mode 100644
index 54162d7740..0000000000
--- a/ext/soap/tests/error_handler.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Bug #46760 (SoapClient doRequest fails when proxy is used)
---SKIPIF--
-<?php require_once('skipif.inc');
-if (!extension_loaded('sqlite')) die('skip sqlite extension not available');
-?>
---FILE--
-<?php
-echo "blllllllllaaaaaaa\n";
-$var475 = sqlite_factory("\x00");
-$var147 = use_soap_error_handler();
-$var477 = flock(false,false);dump($client->_proxy_port);
-?>
---EXPECT--
-blllllllllaaaaaaa
-<?xml version="1.0" encoding="UTF-8"?>
-<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Call to undefined function dump()</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
diff --git a/ext/sockets/config.m4 b/ext/sockets/config.m4
index 574548d605..4032621ce6 100644
--- a/ext/sockets/config.m4
+++ b/ext/sockets/config.m4
@@ -18,8 +18,8 @@ if test "$PHP_SOCKETS" != "no"; then
AC_DEFINE(HAVE_CMSGHDR,1,[Whether you have struct cmsghdr])
fi
- AC_CHECK_FUNCS([hstrerror socketpair])
- AC_CHECK_HEADERS([netdb.h netinet/tcp.h sys/un.h errno.h])
+ AC_CHECK_FUNCS([hstrerror socketpair if_nametoindex if_indextoname])
+ AC_CHECK_HEADERS([netdb.h netinet/tcp.h sys/un.h sys/sockio.h errno.h])
AC_TRY_COMPILE([
#include <sys/types.h>
#include <sys/socket.h>
@@ -27,7 +27,22 @@ if test "$PHP_SOCKETS" != "no"; then
[AC_DEFINE(MISSING_MSGHDR_MSGFLAGS, 1, [ ])]
)
AC_DEFINE([HAVE_SOCKETS], 1, [ ])
+
+ dnl Check for fied ss_family in sockaddr_storage (missing in AIX until 5.3)
+ AC_CACHE_CHECK([for field ss_family in struct sockaddr_storage], ac_cv_ss_family,
+ [
+ AC_TRY_COMPILE([
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+ ], [struct sockaddr_storage sa_store; sa_store.ss_family = AF_INET6;],
+ ac_cv_ss_family=yes, ac_cv_ss_family=no)
+ ])
+
+ if test "$ac_cv_ss_family" = yes; then
+ AC_DEFINE(HAVE_SA_SS_FAMILY,1,[Whether you have sockaddr_storage.ss_family])
+ fi
- PHP_NEW_EXTENSION([sockets], [sockets.c], [$ext_shared])
+ PHP_NEW_EXTENSION([sockets], [sockets.c multicast.c], [$ext_shared])
PHP_INSTALL_HEADERS([ext/sockets/], [php_sockets.h])
fi
diff --git a/ext/sockets/config.w32 b/ext/sockets/config.w32
index 8b63381900..9c234db8f8 100644
--- a/ext/sockets/config.w32
+++ b/ext/sockets/config.w32
@@ -5,8 +5,9 @@ ARG_ENABLE("sockets", "SOCKETS support", "no");
if (PHP_SOCKETS != "no") {
if (CHECK_LIB("ws2_32.lib", "sockets", PHP_SOCKETS)
+ && CHECK_LIB("Iphlpapi.lib", "sockets", PHP_SOCKETS)
&& CHECK_HEADER_ADD_INCLUDE("winsock.h", "CFLAGS_SOCKETS")) {
- EXTENSION('sockets', 'sockets.c');
+ EXTENSION('sockets', 'sockets.c multicast.c');
AC_DEFINE('HAVE_SOCKETS', 1);
PHP_INSTALL_HEADERS("ext/sockets", "php_sockets.h");
} else {
diff --git a/ext/sockets/multicast.c b/ext/sockets/multicast.c
new file mode 100644
index 0000000000..670d29f7ad
--- /dev/null
+++ b/ext/sockets/multicast.c
@@ -0,0 +1,545 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if HAVE_SOCKETS
+
+#include "php_network.h"
+#ifdef PHP_WIN32
+# include "win32/inet.h"
+# include <winsock2.h>
+# include <windows.h>
+# include <Ws2tcpip.h>
+# include <Ws2ipdef.h>
+# include "php_sockets.h"
+# include "win32/sockets.h"
+# define NTDDI_XP NTDDI_WINXP /* bug in SDK */
+# include <IPHlpApi.h>
+# undef NTDDI_XP
+#else
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "php_sockets.h"
+#include "multicast.h"
+#include "main/php_network.h"
+
+
+enum source_op {
+ JOIN_SOURCE,
+ LEAVE_SOURCE,
+ BLOCK_SOURCE,
+ UNBLOCK_SOURCE
+};
+
+static int _php_mcast_join_leave(php_socket *sock, int level, struct sockaddr *group, socklen_t group_len, unsigned int if_index, int join TSRMLS_DC);
+#ifdef HAS_MCAST_EXT
+static int _php_mcast_source_op(php_socket *sock, int level, struct sockaddr *group, socklen_t group_len, struct sockaddr *source, socklen_t source_len, unsigned int if_index, enum source_op sop TSRMLS_DC);
+#endif
+
+#ifdef RFC3678_API
+static int _php_source_op_to_rfc3678_op(enum source_op sop);
+#elif HAS_MCAST_EXT
+static const char *_php_source_op_to_string(enum source_op sop);
+static int _php_source_op_to_ipv4_op(enum source_op sop);
+#endif
+
+int php_mcast_join(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ unsigned int if_index TSRMLS_DC)
+{
+ return _php_mcast_join_leave(sock, level, group, group_len, if_index, 1 TSRMLS_CC);
+}
+
+int php_mcast_leave(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ unsigned int if_index TSRMLS_DC)
+{
+ return _php_mcast_join_leave(sock, level, group, group_len, if_index, 0 TSRMLS_CC);
+}
+
+#ifdef HAS_MCAST_EXT
+int php_mcast_join_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC)
+{
+ return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, JOIN_SOURCE TSRMLS_CC);
+}
+
+int php_mcast_leave_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC)
+{
+ return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, LEAVE_SOURCE TSRMLS_CC);
+}
+
+int php_mcast_block_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC)
+{
+ return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, BLOCK_SOURCE TSRMLS_CC);
+}
+
+int php_mcast_unblock_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC)
+{
+ return _php_mcast_source_op(sock, level, group, group_len, source, source_len, if_index, UNBLOCK_SOURCE TSRMLS_CC);
+}
+#endif /* HAS_MCAST_EXT */
+
+
+static int _php_mcast_join_leave(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group, /* struct sockaddr_in/sockaddr_in6 */
+ socklen_t group_len,
+ unsigned int if_index,
+ int join TSRMLS_DC)
+{
+#ifdef RFC3678_API
+ struct group_req greq = {0};
+
+ memcpy(&greq.gr_group, group, group_len);
+ assert(greq.gr_group.ss_family != 0); /* the caller has set this */
+ greq.gr_interface = if_index;
+
+ return setsockopt(sock->bsd_socket, level,
+ join ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (char*)&greq,
+ sizeof(greq));
+#else
+ if (sock->type == AF_INET) {
+ struct ip_mreq mreq = {0};
+ struct in_addr addr;
+
+ assert(group_len == sizeof(struct sockaddr_in));
+
+ if (if_index != 0) {
+ if (php_if_index_to_addr4(if_index, sock, &addr TSRMLS_CC) ==
+ FAILURE)
+ return -2; /* failure, but notice already emitted */
+ mreq.imr_interface = addr;
+ } else {
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ }
+ mreq.imr_multiaddr = ((struct sockaddr_in*)group)->sin_addr;
+ return setsockopt(sock->bsd_socket, level,
+ join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, (char*)&mreq,
+ sizeof(mreq));
+ }
+#if HAVE_IPV6
+ else if (sock->type == AF_INET6) {
+ struct ipv6_mreq mreq = {0};
+
+ assert(group_len == sizeof(struct sockaddr_in6));
+
+ mreq.ipv6mr_multiaddr = ((struct sockaddr_in6*)group)->sin6_addr;
+ mreq.ipv6mr_interface = if_index;
+
+ return setsockopt(sock->bsd_socket, level,
+ join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, (char*)&mreq,
+ sizeof(mreq));
+ }
+#endif
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Option %s is inapplicable to this socket type",
+ join ? "MCAST_JOIN_GROUP" : "MCAST_LEAVE_GROUP");
+ return -2;
+ }
+#endif
+}
+
+#ifdef HAS_MCAST_EXT
+static int _php_mcast_source_op(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index,
+ enum source_op sop TSRMLS_DC)
+{
+#ifdef RFC3678_API
+ struct group_source_req gsreq = {0};
+
+ memcpy(&gsreq.gsr_group, group, group_len);
+ assert(gsreq.gsr_group.ss_family != 0);
+ memcpy(&gsreq.gsr_source, source, source_len);
+ assert(gsreq.gsr_source.ss_family != 0);
+ gsreq.gsr_interface = if_index;
+
+ return setsockopt(sock->bsd_socket, level,
+ _php_source_op_to_rfc3678_op(sop), (char*)&gsreq, sizeof(gsreq));
+#else
+ if (sock->type == AF_INET) {
+ struct ip_mreq_source mreqs = {0};
+ struct in_addr addr;
+
+ mreqs.imr_multiaddr = ((struct sockaddr_in*)group)->sin_addr;
+ mreqs.imr_sourceaddr = ((struct sockaddr_in*)source)->sin_addr;
+
+ assert(group_len == sizeof(struct sockaddr_in));
+ assert(source_len == sizeof(struct sockaddr_in));
+
+ if (if_index != 0) {
+ if (php_if_index_to_addr4(if_index, sock, &addr TSRMLS_CC) ==
+ FAILURE)
+ return -2; /* failure, but notice already emitted */
+ mreqs.imr_interface = addr;
+ } else {
+ mreqs.imr_interface.s_addr = htonl(INADDR_ANY);
+ }
+
+ return setsockopt(sock->bsd_socket, level,
+ _php_source_op_to_ipv4_op(sop), (char*)&mreqs, sizeof(mreqs));
+ }
+#if HAVE_IPV6
+ else if (sock->type == AF_INET6) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "This platform does not support %s for IPv6 sockets",
+ _php_source_op_to_string(sop));
+ return -2;
+ }
+#endif
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Option %s is inapplicable to this socket type",
+ _php_source_op_to_string(sop));
+ return -2;
+ }
+#endif
+}
+
+#if RFC3678_API
+static int _php_source_op_to_rfc3678_op(enum source_op sop)
+{
+ switch (sop) {
+ case JOIN_SOURCE:
+ return MCAST_JOIN_SOURCE_GROUP;
+ case LEAVE_SOURCE:
+ return MCAST_LEAVE_SOURCE_GROUP;
+ case BLOCK_SOURCE:
+ return MCAST_BLOCK_SOURCE;
+ case UNBLOCK_SOURCE:
+ return MCAST_UNBLOCK_SOURCE;
+ }
+
+ assert(0);
+ return 0;
+}
+#else
+static const char *_php_source_op_to_string(enum source_op sop)
+{
+ switch (sop) {
+ case JOIN_SOURCE:
+ return "MCAST_JOIN_SOURCE_GROUP";
+ case LEAVE_SOURCE:
+ return "MCAST_LEAVE_SOURCE_GROUP";
+ case BLOCK_SOURCE:
+ return "MCAST_BLOCK_SOURCE";
+ case UNBLOCK_SOURCE:
+ return "MCAST_UNBLOCK_SOURCE";
+ }
+
+ assert(0);
+ return "";
+}
+
+static int _php_source_op_to_ipv4_op(enum source_op sop)
+{
+ switch (sop) {
+ case JOIN_SOURCE:
+ return IP_ADD_SOURCE_MEMBERSHIP;
+ case LEAVE_SOURCE:
+ return IP_DROP_SOURCE_MEMBERSHIP;
+ case BLOCK_SOURCE:
+ return IP_BLOCK_SOURCE;
+ case UNBLOCK_SOURCE:
+ return IP_UNBLOCK_SOURCE;
+ }
+
+ assert(0);
+ return 0;
+}
+#endif
+
+#endif /* HAS_MCAST_EXT */
+
+#if PHP_WIN32
+int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_addr *out_addr TSRMLS_DC)
+{
+ MIB_IPADDRTABLE *addr_table;
+ ULONG size;
+ DWORD retval;
+ DWORD i;
+
+ (void) php_sock; /* not necessary */
+
+ if (if_index == 0) {
+ out_addr->s_addr = INADDR_ANY;
+ return SUCCESS;
+ }
+
+ size = 4 * (sizeof *addr_table);
+ addr_table = emalloc(size);
+retry:
+ retval = GetIpAddrTable(addr_table, &size, 0);
+ if (retval == ERROR_INSUFFICIENT_BUFFER) {
+ efree(addr_table);
+ addr_table = emalloc(size);
+ goto retry;
+ }
+ if (retval != NO_ERROR) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "GetIpAddrTable failed with error %lu", retval);
+ return FAILURE;
+ }
+ for (i = 0; i < addr_table->dwNumEntries; i++) {
+ MIB_IPADDRROW r = addr_table->table[i];
+ if (r.dwIndex == if_index) {
+ out_addr->s_addr = r.dwAddr;
+ return SUCCESS;
+ }
+ }
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "No interface with index %u was found", if_index);
+ return FAILURE;
+}
+
+int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *if_index TSRMLS_DC)
+{
+ MIB_IPADDRTABLE *addr_table;
+ ULONG size;
+ DWORD retval;
+ DWORD i;
+
+ (void) php_sock; /* not necessary */
+
+ if (addr->s_addr == INADDR_ANY) {
+ *if_index = 0;
+ return SUCCESS;
+ }
+
+ size = 4 * (sizeof *addr_table);
+ addr_table = emalloc(size);
+retry:
+ retval = GetIpAddrTable(addr_table, &size, 0);
+ if (retval == ERROR_INSUFFICIENT_BUFFER) {
+ efree(addr_table);
+ addr_table = emalloc(size);
+ goto retry;
+ }
+ if (retval != NO_ERROR) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "GetIpAddrTable failed with error %lu", retval);
+ return FAILURE;
+ }
+ for (i = 0; i < addr_table->dwNumEntries; i++) {
+ MIB_IPADDRROW r = addr_table->table[i];
+ if (r.dwAddr == addr->s_addr) {
+ *if_index = r.dwIndex;
+ return SUCCESS;
+ }
+ }
+
+ {
+ char addr_str[17] = {0};
+ inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "The interface with IP address %s was not found", addr_str);
+ }
+ return FAILURE;
+}
+
+#else
+
+int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_addr *out_addr TSRMLS_DC)
+{
+ struct ifreq if_req;
+
+ if (if_index == 0) {
+ out_addr->s_addr = INADDR_ANY;
+ return SUCCESS;
+ }
+
+#if !defined(ifr_ifindex) && defined(ifr_index)
+#define ifr_ifindex ifr_index
+#endif
+
+#if defined(SIOCGIFNAME)
+ if_req.ifr_ifindex = if_index;
+ if (ioctl(php_sock->bsd_socket, SIOCGIFNAME, &if_req) == -1) {
+#elif defined(HAVE_IF_INDEXTONAME)
+ if (if_indextoname(if_index, if_req.ifr_name) == NULL) {
+#else
+#error Neither SIOCGIFNAME nor if_indextoname are available
+#endif
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Failed obtaining address for interface %u: error %d", if_index, errno);
+ return FAILURE;
+ }
+
+ if (ioctl(php_sock->bsd_socket, SIOCGIFADDR, &if_req) == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Failed obtaining address for interface %u: error %d", if_index, errno);
+ return FAILURE;
+ }
+
+ memcpy(out_addr, &((struct sockaddr_in *) &if_req.ifr_addr)->sin_addr,
+ sizeof *out_addr);
+ return SUCCESS;
+}
+
+int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *if_index TSRMLS_DC)
+{
+ struct ifconf if_conf = {0};
+ char *buf = NULL,
+ *p;
+ int size = 0,
+ lastsize = 0;
+ size_t entry_len;
+
+ if (addr->s_addr == INADDR_ANY) {
+ *if_index = 0;
+ return SUCCESS;
+ }
+
+ for(;;) {
+ size += 5 * sizeof(struct ifreq);
+ buf = ecalloc(size, 1);
+ if_conf.ifc_len = size;
+ if_conf.ifc_buf = buf;
+
+ if (ioctl(php_sock->bsd_socket, SIOCGIFCONF, (char*)&if_conf) == -1 &&
+ (errno != EINVAL || lastsize != 0)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Failed obtaining interfaces list: error %d", errno);
+ goto err;
+ }
+
+ if (if_conf.ifc_len == lastsize)
+ /* not increasing anymore */
+ break;
+ else {
+ lastsize = if_conf.ifc_len;
+ efree(buf);
+ buf = NULL;
+ }
+ }
+
+ for (p = if_conf.ifc_buf;
+ p < if_conf.ifc_buf + if_conf.ifc_len;
+ p += entry_len) {
+ struct ifreq *cur_req;
+
+ /* let's hope the pointer is aligned */
+ cur_req = (struct ifreq*) p;
+
+#ifdef HAVE_SOCKADDR_SA_LEN
+ entry_len = cur_req->ifr_addr.sa_len + sizeof(cur_req->ifr_name);
+#else
+ /* if there's no sa_len, assume the ifr_addr field is a sockaddr */
+ entry_len = sizeof(struct sockaddr) + sizeof(cur_req->ifr_name);
+#endif
+ entry_len = MAX(entry_len, sizeof(*cur_req));
+
+ if ((((struct sockaddr*)&cur_req->ifr_addr)->sa_family == AF_INET) &&
+ (((struct sockaddr_in*)&cur_req->ifr_addr)->sin_addr.s_addr ==
+ addr->s_addr)) {
+#if defined(SIOCGIFINDEX)
+ if (ioctl(php_sock->bsd_socket, SIOCGIFINDEX, (char*)cur_req)
+ == -1) {
+#elif defined(HAVE_IF_NAMETOINDEX)
+ unsigned index_tmp;
+ if ((index_tmp = if_nametoindex(cur_req->ifr_name)) == 0) {
+#else
+#error Neither SIOCGIFINDEX nor if_nametoindex are available
+#endif
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Error converting interface name to index: error %d",
+ errno);
+ goto err;
+ } else {
+#if defined(SIOCGIFINDEX)
+ *if_index = cur_req->ifr_ifindex;
+#else
+ *if_index = index_tmp;
+#endif
+ efree(buf);
+ return SUCCESS;
+ }
+ }
+ }
+
+ {
+ char addr_str[17] = {0};
+ inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "The interface with IP address %s was not found", addr_str);
+ }
+
+err:
+ if (buf != NULL)
+ efree(buf);
+ return FAILURE;
+}
+#endif
+
+#endif /* HAVE_SOCKETS */
diff --git a/ext/sockets/multicast.h b/ext/sockets/multicast.h
new file mode 100644
index 0000000000..5619c9c7fb
--- /dev/null
+++ b/ext/sockets/multicast.h
@@ -0,0 +1,92 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#if defined(MCAST_JOIN_GROUP) && \
+ (!defined(PHP_WIN32) || (_WIN32_WINNT >= 0x600 && SOCKETS_ENABLE_VISTA_API)) && \
+ !defined(__APPLE__)
+#define RFC3678_API 1
+/* has block/unblock and source membership, in this case for both IPv4 and IPv6 */
+#define HAS_MCAST_EXT 1
+#elif defined(IP_ADD_SOURCE_MEMBERSHIP) && !defined(__APPLE__)
+/* has block/unblock and source membership, but only for IPv4 */
+#define HAS_MCAST_EXT 1
+#endif
+
+int php_if_index_to_addr4(
+ unsigned if_index,
+ php_socket *php_sock,
+ struct in_addr *out_addr TSRMLS_DC);
+
+int php_add4_to_if_index(
+ struct in_addr *addr,
+ php_socket *php_sock,
+ unsigned *if_index TSRMLS_DC);
+
+int php_mcast_join(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ unsigned int if_index TSRMLS_DC);
+
+int php_mcast_leave(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ unsigned int if_index TSRMLS_DC);
+
+#ifdef HAS_MCAST_EXT
+int php_mcast_join_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC);
+
+int php_mcast_leave_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC);
+
+int php_mcast_block_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC);
+
+int php_mcast_unblock_source(
+ php_socket *sock,
+ int level,
+ struct sockaddr *group,
+ socklen_t group_len,
+ struct sockaddr *source,
+ socklen_t source_len,
+ unsigned int if_index TSRMLS_DC);
+#endif
diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h
index acb7ab5abd..38a68879b1 100644
--- a/ext/sockets/php_sockets.h
+++ b/ext/sockets/php_sockets.h
@@ -70,6 +70,7 @@ PHP_FUNCTION(socket_shutdown);
#endif
PHP_FUNCTION(socket_last_error);
PHP_FUNCTION(socket_clear_error);
+PHP_FUNCTION(socket_import_stream);
#ifndef PHP_WIN32
typedef int PHP_SOCKET;
@@ -80,10 +81,11 @@ typedef SOCKET PHP_SOCKET;
#endif
typedef struct {
- PHP_SOCKET bsd_socket;
- int type;
- int error;
- int blocking;
+ PHP_SOCKET bsd_socket;
+ int type;
+ int error;
+ int blocking;
+ zval *zstream;
} php_socket;
#ifdef PHP_WIN32
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 914fbf58c6..0d1714257d 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -15,6 +15,7 @@
| Authors: Chris Vandomelen <chrisv@b0rked.dhs.org> |
| Sterling Hughes <sterling@php.net> |
| Jason Greene <jason@php.net> |
+ | Gustavo Lopes <cataphract@php.net> |
| WinSock: Daniel Beulshausen <daniel@php4win.de> |
+----------------------------------------------------------------------+
*/
@@ -56,6 +57,9 @@
# define h_errno WSAGetLastError()
# define set_errno(a) WSASetLastError(a)
# define close(a) closesocket(a)
+# if _WIN32_WINNT >= 0x0600 && SOCKETS_ENABLE_VISTA_API
+# define HAVE_IF_NAMETOINDEX 1
+# endif
#else
# include <sys/types.h>
# include <sys/socket.h>
@@ -73,8 +77,16 @@
# define IS_INVALID_SOCKET(a) (a->bsd_socket < 0)
# define set_errno(a) (errno = a)
# include "php_sockets.h"
+# if defined(_AIX) && !defined(HAVE_SA_SS_FAMILY)
+# define ss_family __ss_family
+# endif
+# if HAVE_IF_NAMETOINDEX
+# include <net/if.h>
+# endif
#endif
+#include "multicast.h"
+
ZEND_DECLARE_MODULE_GLOBALS(sockets)
static PHP_GINIT_FUNCTION(sockets);
@@ -261,6 +273,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_clear_error, 0, 0, 0)
ZEND_ARG_INFO(0, socket)
ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_import_stream, 0, 0, 1)
+ ZEND_ARG_INFO(0, stream)
+ZEND_END_ARG_INFO()
/* }}} */
/* {{{ sockets_functions[]
@@ -295,6 +311,7 @@ const zend_function_entry sockets_functions[] = {
#endif
PHP_FE(socket_last_error, arginfo_socket_last_error)
PHP_FE(socket_clear_error, arginfo_socket_clear_error)
+ PHP_FE(socket_import_stream, arginfo_socket_import_stream)
/* for downwards compatability */
PHP_FALIAS(socket_getopt, socket_get_option, arginfo_socket_get_option)
@@ -335,11 +352,33 @@ PHP_SOCKETS_API int php_sockets_le_socket(void) /* {{{ */
}
/* }}} */
+/* allocating function to make programming errors due to uninitialized fields
+ * less likely */
+static php_socket *php_create_socket(void) /* {{{ */
+{
+ php_socket *php_sock = emalloc(sizeof *php_sock);
+
+ php_sock->bsd_socket = -1; /* invalid socket */
+ php_sock->type = PF_UNSPEC;
+ php_sock->error = 0;
+ php_sock->blocking = 1;
+ php_sock->zstream = NULL;
+
+ return php_sock;
+}
+/* }}} */
+
static void php_destroy_socket(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
{
- php_socket *php_sock = (php_socket *) rsrc->ptr;
+ php_socket *php_sock = rsrc->ptr;
- close(php_sock->bsd_socket);
+ if (php_sock->zstream == NULL) {
+ if (!IS_INVALID_SOCKET(php_sock)) {
+ close(php_sock->bsd_socket);
+ }
+ } else {
+ zval_ptr_dtor(&php_sock->zstream);
+ }
efree(php_sock);
}
/* }}} */
@@ -348,7 +387,7 @@ static int php_open_listen_sock(php_socket **php_sock, int port, int backlog TSR
{
struct sockaddr_in la;
struct hostent *hp;
- php_socket *sock = (php_socket*)emalloc(sizeof(php_socket));
+ php_socket *sock = php_create_socket();
*php_sock = sock;
@@ -396,7 +435,7 @@ static int php_open_listen_sock(php_socket **php_sock, int port, int backlog TSR
static int php_accept_connect(php_socket *in_sock, php_socket **new_sock, struct sockaddr *la, socklen_t *la_len TSRMLS_DC) /* {{{ */
{
- php_socket *out_sock = (php_socket*)emalloc(sizeof(php_socket));
+ php_socket *out_sock = php_create_socket();
*new_sock = out_sock;
@@ -605,6 +644,111 @@ static int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *
}
/* }}} */
+/* Sets addr by hostname or by ip in string form (AF_INET or AF_INET6,
+ * depending on the socket) */
+static int php_set_inet46_addr(php_sockaddr_storage *ss, socklen_t *ss_len, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */
+{
+ if (php_sock->type == AF_INET) {
+ struct sockaddr_in t = {0};
+ if (php_set_inet_addr(&t, string, php_sock TSRMLS_CC)) {
+ memcpy(ss, &t, sizeof t);
+ ss->ss_family = AF_INET;
+ *ss_len = sizeof(t);
+ return 1;
+ }
+ }
+#if HAVE_IPV6
+ else if (php_sock->type == AF_INET6) {
+ struct sockaddr_in6 t = {0};
+ if (php_set_inet6_addr(&t, string, php_sock TSRMLS_CC)) {
+ memcpy(ss, &t, sizeof t);
+ ss->ss_family = AF_INET6;
+ *ss_len = sizeof(t);
+ return 1;
+ }
+ }
+#endif
+ else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "IP address used in the context of an unexpected type of socket");
+ }
+ return 0;
+}
+
+static int php_get_if_index_from_zval(zval *val, unsigned *out TSRMLS_DC)
+{
+ int ret;
+
+ if (Z_TYPE_P(val) == IS_LONG) {
+ if (Z_LVAL_P(val) < 0 || Z_LVAL_P(val) > UINT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "the interface index cannot be negative or larger than %u;"
+ " given %ld", UINT_MAX, Z_LVAL_P(val));
+ ret = FAILURE;
+ } else {
+ *out = Z_LVAL_P(val);
+ ret = SUCCESS;
+ }
+ } else {
+#if HAVE_IF_NAMETOINDEX
+ unsigned int ind;
+ zval_add_ref(&val);
+ convert_to_string_ex(&val);
+ ind = if_nametoindex(Z_STRVAL_P(val));
+ if (ind == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "no interface with name \"%s\" could be found", Z_STRVAL_P(val));
+ ret = FAILURE;
+ } else {
+ *out = ind;
+ ret = SUCCESS;
+ }
+ zval_ptr_dtor(&val);
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "this platform does not support looking up an interface by "
+ "name, an integer interface index must be supplied instead");
+ ret = FAILURE;
+#endif
+ }
+
+ return ret;
+}
+
+static int php_get_if_index_from_array(const HashTable *ht, const char *key,
+ php_socket *sock, unsigned int *if_index TSRMLS_DC)
+{
+ zval **val;
+
+ if (zend_hash_find(ht, key, strlen(key) + 1, (void **)&val) == FAILURE) {
+ *if_index = 0; /* default: 0 */
+ return SUCCESS;
+ }
+
+ return php_get_if_index_from_zval(*val, if_index TSRMLS_CC);
+}
+
+static int php_get_address_from_array(const HashTable *ht, const char *key,
+ php_socket *sock, php_sockaddr_storage *ss, socklen_t *ss_len TSRMLS_DC)
+{
+ zval **val,
+ *valcp;
+
+ if (zend_hash_find(ht, key, strlen(key) + 1, (void **)&val) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", key);
+ return FAILURE;
+ }
+ valcp = *val;
+ zval_add_ref(&valcp);
+ convert_to_string_ex(val);
+ if (!php_set_inet46_addr(ss, ss_len, Z_STRVAL_P(valcp), sock TSRMLS_CC)) {
+ zval_ptr_dtor(&valcp);
+ return FAILURE;
+ }
+ zval_ptr_dtor(&valcp);
+ return SUCCESS;
+}
+
/* {{{ PHP_GINIT_FUNCTION */
static PHP_GINIT_FUNCTION(sockets)
{
@@ -617,8 +761,6 @@ static PHP_GINIT_FUNCTION(sockets)
*/
PHP_MINIT_FUNCTION(sockets)
{
- struct protoent *pe;
-
le_socket = zend_register_list_destructors_ex(php_destroy_socket, NULL, le_socket_name, module_number);
REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT);
@@ -667,19 +809,48 @@ PHP_MINIT_FUNCTION(sockets)
REGISTER_LONG_CONSTANT("PHP_NORMAL_READ", PHP_NORMAL_READ, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PHP_BINARY_READ", PHP_BINARY_READ, CONST_CS | CONST_PERSISTENT);
+#ifndef RFC3678_API
+#define MCAST_JOIN_GROUP IP_ADD_MEMBERSHIP
+#define MCAST_LEAVE_GROUP IP_DROP_MEMBERSHIP
+#ifdef HAS_MCAST_EXT
+#define MCAST_BLOCK_SOURCE IP_BLOCK_SOURCE
+#define MCAST_UNBLOCK_SOURCE IP_UNBLOCK_SOURCE
+#define MCAST_JOIN_SOURCE_GROUP IP_ADD_SOURCE_MEMBERSHIP
+#define MCAST_LEAVE_SOURCE_GROUP IP_DROP_SOURCE_MEMBERSHIP
+#endif
+#endif
+
+ REGISTER_LONG_CONSTANT("MCAST_JOIN_GROUP", MCAST_JOIN_GROUP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MCAST_LEAVE_GROUP", MCAST_LEAVE_GROUP, CONST_CS | CONST_PERSISTENT);
+#ifdef HAS_MCAST_EXT
+ REGISTER_LONG_CONSTANT("MCAST_BLOCK_SOURCE", MCAST_BLOCK_SOURCE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MCAST_UNBLOCK_SOURCE", MCAST_UNBLOCK_SOURCE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MCAST_JOIN_SOURCE_GROUP", MCAST_JOIN_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MCAST_LEAVE_SOURCE_GROUP", MCAST_LEAVE_SOURCE_GROUP, CONST_CS | CONST_PERSISTENT);
+#endif
+
+ REGISTER_LONG_CONSTANT("IP_MULTICAST_IF", IP_MULTICAST_IF, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IP_MULTICAST_TTL", IP_MULTICAST_TTL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT);
+#if HAVE_IPV6
+ REGISTER_LONG_CONSTANT("IPV6_MULTICAST_IF", IPV6_MULTICAST_IF, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IPV6_MULTICAST_HOPS", IPV6_MULTICAST_HOPS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("IPV6_MULTICAST_LOOP", IPV6_MULTICAST_LOOP, CONST_CS | CONST_PERSISTENT);
+#endif
+
#ifndef WIN32
# include "unix_socket_constants.h"
#else
# include "win32_socket_constants.h"
#endif
- if ((pe = getprotobyname("tcp"))) {
- REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
- }
+ REGISTER_LONG_CONSTANT("IPPROTO_IP", IPPROTO_IP, CONST_CS | CONST_PERSISTENT);
+#if HAVE_IPV6
+ REGISTER_LONG_CONSTANT("IPPROTO_IPV6", IPPROTO_IPV6, CONST_CS | CONST_PERSISTENT);
+#endif
- if ((pe = getprotobyname("udp"))) {
- REGISTER_LONG_CONSTANT("SOL_UDP", pe->p_proto, CONST_CS | CONST_PERSISTENT);
- }
+ REGISTER_LONG_CONSTANT("SOL_TCP", IPPROTO_TCP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SOL_UDP", IPPROTO_UDP, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
@@ -912,6 +1083,20 @@ PHP_FUNCTION(socket_set_nonblock)
}
ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
+
+ if (php_sock->zstream != NULL) {
+ php_stream *stream;
+ /* omit notice if resource doesn't exist anymore */
+ stream = zend_fetch_resource(&php_sock->zstream TSRMLS_CC, -1,
+ NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream != NULL) {
+ if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 0,
+ NULL) != -1) {
+ php_sock->blocking = 1;
+ RETURN_TRUE;
+ }
+ }
+ }
if (php_set_sock_blocking(php_sock->bsd_socket, 0 TSRMLS_CC) == SUCCESS) {
php_sock->blocking = 0;
@@ -935,6 +1120,22 @@ PHP_FUNCTION(socket_set_block)
}
ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
+
+ /* if socket was created from a stream, give the stream a chance to take
+ * care of the operation itself, thereby allowing it to update its internal
+ * state */
+ if (php_sock->zstream != NULL) {
+ php_stream *stream;
+ stream = zend_fetch_resource(&php_sock->zstream TSRMLS_CC, -1,
+ NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream != NULL) {
+ if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 1,
+ NULL) != -1) {
+ php_sock->blocking = 1;
+ RETURN_TRUE;
+ }
+ }
+ }
if (php_set_sock_blocking(php_sock->bsd_socket, 1 TSRMLS_CC) == SUCCESS) {
php_sock->blocking = 1;
@@ -980,6 +1181,16 @@ PHP_FUNCTION(socket_close)
}
ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
+ if (php_sock->zstream != NULL) {
+ php_stream *stream = NULL;
+ php_stream_from_zval_no_verify(stream, &php_sock->zstream);
+ if (stream != NULL) {
+ /* close & destroy stream, incl. removing it from the rsrc list;
+ * resource stored in php_sock->zstream will become invalid */
+ php_stream_free(stream, PHP_STREAM_FREE_CLOSE |
+ (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0));
+ }
+ }
zend_list_delete(Z_RESVAL_P(arg1));
}
/* }}} */
@@ -1237,7 +1448,7 @@ PHP_FUNCTION(socket_getpeername)
PHP_FUNCTION(socket_create)
{
long arg1, arg2, arg3;
- php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket));
+ php_socket *php_sock = php_create_socket();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) {
efree(php_sock);
@@ -1281,11 +1492,6 @@ PHP_FUNCTION(socket_connect)
{
zval *arg1;
php_socket *php_sock;
- struct sockaddr_in sin;
-#if HAVE_IPV6
- struct sockaddr_in6 sin6;
-#endif
- struct sockaddr_un s_un;
char *addr;
int retval, addr_len;
long port = 0;
@@ -1299,7 +1505,9 @@ PHP_FUNCTION(socket_connect)
switch(php_sock->type) {
#if HAVE_IPV6
- case AF_INET6:
+ case AF_INET6: {
+ struct sockaddr_in6 sin6 = {0};
+
if (argc != 3) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET6 requires 3 arguments");
RETURN_FALSE;
@@ -1316,15 +1524,16 @@ PHP_FUNCTION(socket_connect)
retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin6, sizeof(struct sockaddr_in6));
break;
+ }
#endif
- case AF_INET:
+ case AF_INET: {
+ struct sockaddr_in sin = {0};
+
if (argc != 3) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET requires 3 arguments");
RETURN_FALSE;
}
- memset(&sin, 0, sizeof(struct sockaddr_in));
-
sin.sin_family = AF_INET;
sin.sin_port = htons((unsigned short int)port);
@@ -1334,19 +1543,22 @@ PHP_FUNCTION(socket_connect)
retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
break;
+ }
- case AF_UNIX:
+ case AF_UNIX: {
+ struct sockaddr_un s_un = {0};
+
if (addr_len >= sizeof(s_un.sun_path)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Path too long");
RETURN_FALSE;
}
-
- memset(&s_un, 0, sizeof(struct sockaddr_un));
s_un.sun_family = AF_UNIX;
memcpy(&s_un.sun_path, addr, addr_len);
- retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un, (socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + addr_len);
+ retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un,
+ (socklen_t)(XtOffsetOf(struct sockaddr_un, sun_path) + addr_len));
break;
+ }
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported socket type %d", php_sock->type);
@@ -1746,6 +1958,26 @@ PHP_FUNCTION(socket_get_option)
ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);
+ if (level == IPPROTO_IP) {
+ switch (optname) {
+ case IP_MULTICAST_IF: {
+ struct in_addr if_addr;
+ unsigned int if_index;
+ optlen = sizeof(if_addr);
+ if (getsockopt(php_sock->bsd_socket, level, optname, (char*)&if_addr, &optlen) != 0) {
+ PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
+ RETURN_FALSE;
+ }
+ if (php_add4_to_if_index(&if_addr, php_sock, &if_index TSRMLS_CC) == SUCCESS) {
+ RETURN_LONG((long) if_index);
+ } else {
+ RETURN_FALSE;
+ }
+ }
+ }
+ }
+
+ /* sol_socket options and general case */
switch(optname) {
case SO_LINGER:
optlen = sizeof(linger_val);
@@ -1786,7 +2018,7 @@ PHP_FUNCTION(socket_get_option)
add_assoc_long(return_value, "sec", tv.tv_sec);
add_assoc_long(return_value, "usec", tv.tv_usec);
break;
-
+
default:
optlen = sizeof(other_val);
@@ -1794,6 +2026,8 @@ PHP_FUNCTION(socket_get_option)
PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket option", errno);
RETURN_FALSE;
}
+ if (optlen == 1)
+ other_val = *((unsigned char *)&other_val);
RETURN_LONG(other_val);
break;
@@ -1801,30 +2035,126 @@ PHP_FUNCTION(socket_get_option)
}
/* }}} */
+static int php_do_mcast_opt(php_socket *php_sock, int level, int optname, zval **arg4 TSRMLS_DC)
+{
+ HashTable *opt_ht;
+ unsigned int if_index;
+ int retval;
+ int (*mcast_req_fun)(php_socket *, int, struct sockaddr *, socklen_t,
+ unsigned TSRMLS_DC);
+#ifdef HAS_MCAST_EXT
+ int (*mcast_sreq_fun)(php_socket *, int, struct sockaddr *, socklen_t,
+ struct sockaddr *, socklen_t, unsigned TSRMLS_DC);
+#endif
+
+ switch (optname) {
+ case MCAST_JOIN_GROUP:
+ mcast_req_fun = &php_mcast_join;
+ goto mcast_req_fun;
+ case MCAST_LEAVE_GROUP:
+ {
+ php_sockaddr_storage group = {0};
+ socklen_t glen;
+
+ mcast_req_fun = &php_mcast_leave;
+mcast_req_fun:
+ convert_to_array_ex(arg4);
+ opt_ht = HASH_OF(*arg4);
+
+ if (php_get_address_from_array(opt_ht, "group", php_sock, &group,
+ &glen TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
+ if (php_get_if_index_from_array(opt_ht, "interface", php_sock,
+ &if_index TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
+
+ retval = mcast_req_fun(php_sock, level, (struct sockaddr*)&group,
+ glen, if_index TSRMLS_CC);
+ break;
+ }
+
+#ifdef HAS_MCAST_EXT
+ case MCAST_BLOCK_SOURCE:
+ mcast_sreq_fun = &php_mcast_block_source;
+ goto mcast_sreq_fun;
+ case MCAST_UNBLOCK_SOURCE:
+ mcast_sreq_fun = &php_mcast_unblock_source;
+ goto mcast_sreq_fun;
+ case MCAST_JOIN_SOURCE_GROUP:
+ mcast_sreq_fun = &php_mcast_join_source;
+ goto mcast_sreq_fun;
+ case MCAST_LEAVE_SOURCE_GROUP:
+ {
+ php_sockaddr_storage group = {0},
+ source = {0};
+ socklen_t glen,
+ slen;
+
+ mcast_sreq_fun = &php_mcast_leave_source;
+ mcast_sreq_fun:
+ convert_to_array_ex(arg4);
+ opt_ht = HASH_OF(*arg4);
+
+ if (php_get_address_from_array(opt_ht, "group", php_sock, &group,
+ &glen TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
+ if (php_get_address_from_array(opt_ht, "source", php_sock, &source,
+ &slen TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
+ if (php_get_if_index_from_array(opt_ht, "interface", php_sock,
+ &if_index TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
+
+ retval = mcast_sreq_fun(php_sock, level, (struct sockaddr*)&group,
+ glen, (struct sockaddr*)&source, slen, if_index TSRMLS_CC);
+ break;
+ }
+#endif
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "unexpected option in php_do_mcast_opt (level %d, option %d). "
+ "This is a bug.", level, optname);
+ return FAILURE;
+ }
+
+ if (retval != 0) {
+ if (retval != -2) { /* error, but message already emitted */
+ PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
+ }
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
/* {{{ proto bool socket_set_option(resource socket, int level, int optname, int|array optval)
Sets socket options for the socket */
PHP_FUNCTION(socket_set_option)
{
- zval *arg1, **arg4;
- struct linger lv;
- php_socket *php_sock;
- int ov, optlen, retval;
+ zval *arg1, **arg4;
+ struct linger lv;
+ php_socket *php_sock;
+ int ov, optlen, retval;
#ifdef PHP_WIN32
- int timeout;
+ int timeout;
#else
- struct timeval tv;
+ struct timeval tv;
#endif
- long level, optname;
- void *opt_ptr;
- HashTable *opt_ht;
- zval **l_onoff, **l_linger;
- zval **sec, **usec;
- /* key name constants */
- char *l_onoff_key = "l_onoff";
- char *l_linger_key = "l_linger";
- char *sec_key = "sec";
- char *usec_key = "usec";
-
+ long level, optname;
+ void *opt_ptr;
+ HashTable *opt_ht;
+ zval **l_onoff, **l_linger;
+ zval **sec, **usec;
+
+ /* Multicast */
+ unsigned int if_index;
+ struct in_addr if_addr;
+ unsigned char ipv4_mcast_ttl_lback;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllZ", &arg1, &level, &optname, &arg4) == FAILURE) {
return;
}
@@ -1833,16 +2163,110 @@ PHP_FUNCTION(socket_set_option)
set_errno(0);
+ if (level == IPPROTO_IP) {
+ switch (optname) {
+ case MCAST_JOIN_GROUP:
+ case MCAST_LEAVE_GROUP:
+#ifdef HAS_MCAST_EXT
+ case MCAST_BLOCK_SOURCE:
+ case MCAST_UNBLOCK_SOURCE:
+ case MCAST_JOIN_SOURCE_GROUP:
+ case MCAST_LEAVE_SOURCE_GROUP:
+#endif
+ if (php_do_mcast_opt(php_sock, level, optname, arg4 TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+
+ case IP_MULTICAST_IF:
+ if (php_get_if_index_from_zval(*arg4, &if_index TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (php_if_index_to_addr4(if_index, php_sock, &if_addr TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ }
+ opt_ptr = &if_addr;
+ optlen = sizeof(if_addr);
+ goto dosockopt;
+
+ case IP_MULTICAST_LOOP:
+ convert_to_boolean_ex(arg4);
+ goto ipv4_loop_ttl;
+ case IP_MULTICAST_TTL:
+ convert_to_long_ex(arg4);
+ if (Z_LVAL_PP(arg4) < 0L || Z_LVAL_PP(arg4) > 255L) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Expected a value between 0 and 255");
+ RETURN_FALSE;
+ }
+ipv4_loop_ttl:
+ ipv4_mcast_ttl_lback = (unsigned char) Z_LVAL_PP(arg4);
+ opt_ptr = &ipv4_mcast_ttl_lback;
+ optlen = sizeof(ipv4_mcast_ttl_lback);
+ goto dosockopt;
+ }
+ }
+
+#if HAVE_IPV6
+ else if (level == IPPROTO_IPV6) {
+ switch (optname) {
+ case MCAST_JOIN_GROUP:
+ case MCAST_LEAVE_GROUP:
+#ifdef HAS_MCAST_EXT
+ case MCAST_BLOCK_SOURCE:
+ case MCAST_UNBLOCK_SOURCE:
+ case MCAST_JOIN_SOURCE_GROUP:
+ case MCAST_LEAVE_SOURCE_GROUP:
+#endif
+ if (php_do_mcast_opt(php_sock, level, optname, arg4 TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+
+ case IPV6_MULTICAST_IF:
+ if (php_get_if_index_from_zval(*arg4, &if_index TSRMLS_CC) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ opt_ptr = &if_index;
+ optlen = sizeof(if_index);
+ goto dosockopt;
+
+ case IPV6_MULTICAST_LOOP:
+ convert_to_boolean_ex(arg4);
+ goto ipv6_loop_hops;
+ case IPV6_MULTICAST_HOPS:
+ convert_to_long_ex(arg4);
+ if (Z_LVAL_PP(arg4) < -1L || Z_LVAL_PP(arg4) > 255L) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Expected a value between -1 and 255");
+ RETURN_FALSE;
+ }
+ipv6_loop_hops:
+ ov = (int) Z_LVAL_PP(arg4);
+ opt_ptr = &ov;
+ optlen = sizeof(ov);
+ goto dosockopt;
+ }
+ }
+#endif
+
switch (optname) {
- case SO_LINGER:
+ case SO_LINGER: {
+ const char l_onoff_key[] = "l_onoff";
+ const char l_linger_key[] = "l_linger";
+
convert_to_array_ex(arg4);
opt_ht = HASH_OF(*arg4);
- if (zend_hash_find(opt_ht, l_onoff_key, strlen(l_onoff_key) + 1, (void **)&l_onoff) == FAILURE) {
+ if (zend_hash_find(opt_ht, l_onoff_key, sizeof(l_onoff_key), (void **)&l_onoff) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_onoff_key);
RETURN_FALSE;
}
- if (zend_hash_find(opt_ht, l_linger_key, strlen(l_linger_key) + 1, (void **)&l_linger) == FAILURE) {
+ if (zend_hash_find(opt_ht, l_linger_key, sizeof(l_linger_key), (void **)&l_linger) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", l_linger_key);
RETURN_FALSE;
}
@@ -1856,17 +2280,21 @@ PHP_FUNCTION(socket_set_option)
optlen = sizeof(lv);
opt_ptr = &lv;
break;
+ }
case SO_RCVTIMEO:
- case SO_SNDTIMEO:
+ case SO_SNDTIMEO: {
+ const char sec_key[] = "sec";
+ const char usec_key[] = "usec";
+
convert_to_array_ex(arg4);
opt_ht = HASH_OF(*arg4);
- if (zend_hash_find(opt_ht, sec_key, strlen(sec_key) + 1, (void **)&sec) == FAILURE) {
+ if (zend_hash_find(opt_ht, sec_key, sizeof(sec_key), (void **)&sec) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", sec_key);
RETURN_FALSE;
}
- if (zend_hash_find(opt_ht, usec_key, strlen(usec_key) + 1, (void **)&usec) == FAILURE) {
+ if (zend_hash_find(opt_ht, usec_key, sizeof(usec_key), (void **)&usec) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "no key \"%s\" passed in optval", usec_key);
RETURN_FALSE;
}
@@ -1884,7 +2312,8 @@ PHP_FUNCTION(socket_set_option)
opt_ptr = &timeout;
#endif
break;
-
+ }
+
default:
convert_to_long_ex(arg4);
ov = Z_LVAL_PP(arg4);
@@ -1894,10 +2323,12 @@ PHP_FUNCTION(socket_set_option)
break;
}
+dosockopt:
retval = setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen);
-
if (retval != 0) {
- PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
+ if (retval != -2) { /* error, but message already emitted */
+ PHP_SOCKET_ERROR(php_sock, "unable to set socket option", errno);
+ }
RETURN_FALSE;
}
@@ -1919,8 +2350,8 @@ PHP_FUNCTION(socket_create_pair)
return;
}
- php_sock[0] = (php_socket*)emalloc(sizeof(php_socket));
- php_sock[1] = (php_socket*)emalloc(sizeof(php_socket));
+ php_sock[0] = php_create_socket();
+ php_sock[1] = php_create_socket();
if (domain != AF_INET
#if HAVE_IPV6
@@ -2037,6 +2468,83 @@ PHP_FUNCTION(socket_clear_error)
}
/* }}} */
+/* {{{ proto void socket_import_stream(resource stream)
+ Imports a stream that encapsulates a socket into a socket extension resource. */
+PHP_FUNCTION(socket_import_stream)
+{
+ zval *zstream;
+ php_stream *stream;
+ php_socket *retsock = NULL;
+ PHP_SOCKET socket; /* fd */
+ php_sockaddr_storage addr;
+ socklen_t addr_len = sizeof(addr);
+#ifndef PHP_WIN32
+ int t;
+#endif
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) == FAILURE) {
+ return;
+ }
+ php_stream_from_zval(stream, &zstream);
+
+ if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void**)&socket, 1)) {
+ /* error supposedly already shown */
+ RETURN_FALSE;
+ }
+
+ retsock = php_create_socket();
+
+ retsock->bsd_socket = socket;
+
+ /* determine family */
+ if (getsockname(socket, (struct sockaddr*)&addr, &addr_len) == 0) {
+ retsock->type = addr.ss_family;
+ } else {
+ PHP_SOCKET_ERROR(retsock, "unable to obtain socket family", errno);
+ goto error;
+ }
+
+ /* determine blocking mode */
+#ifndef PHP_WIN32
+ t = fcntl(socket, F_GETFL);
+ if(t == -1) {
+ PHP_SOCKET_ERROR(retsock, "unable to obtain blocking state", errno);
+ goto error;
+ } else {
+ retsock->blocking = !(t & O_NONBLOCK);
+ }
+#else
+ /* on windows, check if the stream is a socket stream and read its
+ * private data; otherwise assume it's in non-blocking mode */
+ if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) {
+ retsock->blocking =
+ ((php_netstream_data_t *)stream->abstract)->is_blocked;
+ } else {
+ retsock->blocking = 1;
+ }
+#endif
+
+ /* hold a zval reference to the stream (holding a php_stream* directly could
+ * also be done, but this might be slightly better if in the future we want
+ * to provide a socket_export_stream) */
+ MAKE_STD_ZVAL(retsock->zstream);
+ *retsock->zstream = *zstream;
+ zval_copy_ctor(retsock->zstream);
+ Z_UNSET_ISREF_P(retsock->zstream);
+ Z_SET_REFCOUNT_P(retsock->zstream, 1);
+
+ php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER,
+ PHP_STREAM_BUFFER_NONE, NULL);
+
+ ZEND_REGISTER_RESOURCE(return_value, retsock, le_socket);
+ return;
+error:
+ if (retsock != NULL)
+ efree(retsock);
+ RETURN_FALSE;
+}
+/* }}} */
+
#endif
/*
diff --git a/ext/sockets/tests/bug63000.phpt b/ext/sockets/tests/bug63000.phpt
new file mode 100644
index 0000000000..c806ba4c08
--- /dev/null
+++ b/ext/sockets/tests/bug63000.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #63000: Multicast on OSX
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (PHP_OS !== 'Darwin') {
+ die('is not OSX.');
+}
+--FILE--
+<?php
+$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
+socket_bind($socket, '0.0.0.0', 31057);
+
+$so = socket_set_option($socket, IPPROTO_IP, MCAST_JOIN_GROUP, array(
+ "group" => '224.0.0.251',
+ "interface" => 0,
+));
+var_dump($so);
+--EXPECTF--
+bool(true)
diff --git a/ext/sockets/tests/mcast_helpers.php.inc b/ext/sockets/tests/mcast_helpers.php.inc
new file mode 100644
index 0000000000..ad65a3f9d6
--- /dev/null
+++ b/ext/sockets/tests/mcast_helpers.php.inc
@@ -0,0 +1,8 @@
+<?php
+function checktimeout($sock, $limit) {
+ $readfs = array($sock);
+ $writefs = $exceptfs = array();
+ if (socket_select($readfs, $writefs, $exceptfs, 0, $limit*1000) != 1) {
+ die("Socket read timeout hit. Can be a bug, a test bug, or a firewall issue.");
+ }
+}
diff --git a/ext/sockets/tests/mcast_ipv4_recv.phpt b/ext/sockets/tests/mcast_ipv4_recv.phpt
new file mode 100644
index 0000000000..8c90ae0b17
--- /dev/null
+++ b/ext/sockets/tests/mcast_ipv4_recv.phpt
@@ -0,0 +1,197 @@
+--TEST--
+Multicast support: IPv4 receive options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '0.0.0.0', 3000);
+$so = socket_set_option($s, IPPROTO_IP, MCAST_JOIN_GROUP, array(
+ "group" => '224.0.0.23',
+ "interface" => 'lo',
+));
+if ($so === false) {
+ die('skip interface \'lo\' is unavailable.');
+}
+if (!defined("MCAST_BLOCK_SOURCE")) {
+ die('skip source operations are unavailable');
+}
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+$domain = AF_INET;
+$level = IPPROTO_IP;
+$interface = "lo";
+$mcastaddr = '224.0.0.23';
+$sblock = "127.0.0.1";
+
+echo "creating send socket bound to 127.0.0.1\n";
+$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($sends1, '127.0.0.1');
+var_dump($br);
+
+echo "creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to $mcastaddr\n";
+$sends2 = socket_create($domain, SOCK_DGRAM, SOL_UDP);
+var_dump($br);
+
+echo "creating receive socket\n";
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP);
+var_dump($s);
+$br = socket_bind($s, '0.0.0.0', 3000);
+var_dump($br);
+
+$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+));
+var_dump($so);
+
+$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+
+$i = 0;
+checktimeout($s, 500);
+while (($str = socket_read($s, 3000)) !== FALSE) {
+ $i++;
+ echo "$i> ", $str, "\n";
+
+if ($i == 1) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 2) {
+ echo "re-joining group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends2, $m = "ignored mcast packet (different interface)", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 3) {
+ echo "blocking source\n";
+ $so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 4) {
+ echo "unblocking source\n";
+ $so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 5) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 6) {
+ echo "joining source group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet from 127.0.0.1", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 7) {
+ echo "leaving source group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "127.0.0.1", 3000);
+ var_dump($r);
+}
+if ($i == 8) {
+/* echo "rjsg\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);*/
+ break;
+}
+
+}
+--EXPECTF--
+creating send socket bound to 127.0.0.1
+bool(true)
+creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to 224.0.0.23
+bool(true)
+creating receive socket
+resource(%d) of type (Socket)
+bool(true)
+bool(true)
+int(14)
+1> initial packet
+leaving group
+bool(true)
+int(20)
+int(14)
+2> unicast packet
+re-joining group
+bool(true)
+int(42)
+int(12)
+3> mcast packet
+blocking source
+bool(true)
+int(31)
+int(14)
+4> unicast packet
+unblocking source
+bool(true)
+int(27)
+5> mcast packet from 127.0.0.1
+leaving group
+bool(true)
+int(20)
+int(14)
+6> unicast packet
+joining source group
+bool(true)
+int(27)
+7> mcast packet from 127.0.0.1
+leaving source group
+bool(true)
+int(20)
+int(14)
+8> unicast packet
diff --git a/ext/sockets/tests/mcast_ipv4_send.phpt b/ext/sockets/tests/mcast_ipv4_send.phpt
new file mode 100644
index 0000000000..ac5bce9162
--- /dev/null
+++ b/ext/sockets/tests/mcast_ipv4_send.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Multicast support: IPv4 send options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) {
+ die("skip interface 1 either doesn't exist or has no ipv4 address");
+}
+--FILE--
+<?php
+$domain = AF_INET;
+$level = IPPROTO_IP;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+
+echo "Setting IP_MULTICAST_TTL\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_TTL, 9);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_TTL);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_LOOP\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_LOOP);
+var_dump($r);
+$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_LOOP);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_IF\n";
+echo "interface 0:\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_IF, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_IF);
+var_dump($r);
+echo "interface 1:\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_IF, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_IF);
+var_dump($r);
+echo "\n";
+
+--EXPECT--
+Setting IP_MULTICAST_TTL
+bool(true)
+int(9)
+
+Setting IP_MULTICAST_LOOP
+bool(true)
+int(0)
+bool(true)
+int(1)
+
+Setting IP_MULTICAST_IF
+interface 0:
+bool(true)
+int(0)
+interface 1:
+bool(true)
+int(1)
diff --git a/ext/sockets/tests/mcast_ipv4_send_error.phpt b/ext/sockets/tests/mcast_ipv4_send_error.phpt
new file mode 100644
index 0000000000..5cd3d8e7d7
--- /dev/null
+++ b/ext/sockets/tests/mcast_ipv4_send_error.phpt
@@ -0,0 +1,79 @@
+--TEST--
+Multicast support: IPv4 send options with unusual values
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) {
+ die("skip interface 1 either doesn't exist or has no ipv4 address");
+}
+--FILE--
+<?php
+$domain = AF_INET;
+$level = IPPROTO_IP;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+
+echo "Setting IP_MULTICAST_LOOP with 256\n";
+//if we had a simple cast to unsigned char, this would be the same as 0
+$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, 256);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_LOOP);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_LOOP with false\n";
+//should convert to (unsigned char)0
+$r = socket_set_option($s, $level, IP_MULTICAST_LOOP, false);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_LOOP);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_TTL with 256\n";
+//if we had a simple cast to unsigned char, this would be the same as 0
+$r = socket_set_option($s, $level, IP_MULTICAST_TTL, 256);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_TTL);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_TTL with \"254\"\n";
+$r = socket_set_option($s, $level, IP_MULTICAST_TTL, "254");
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_TTL);
+var_dump($r);
+echo "\n";
+
+echo "Setting IP_MULTICAST_TTL with -1\n";
+//should give error, not be the same as 255
+$r = socket_set_option($s, $level, IP_MULTICAST_TTL, -1);
+var_dump($r);
+$r = socket_get_option($s, $level, IP_MULTICAST_TTL);
+var_dump($r);
+echo "\n";
+
+--EXPECTF--
+Setting IP_MULTICAST_LOOP with 256
+bool(true)
+int(1)
+
+Setting IP_MULTICAST_LOOP with false
+bool(true)
+int(0)
+
+Setting IP_MULTICAST_TTL with 256
+
+Warning: socket_set_option(): Expected a value between 0 and 255 in %s on line %d
+bool(false)
+int(1)
+
+Setting IP_MULTICAST_TTL with "254"
+bool(true)
+int(254)
+
+Setting IP_MULTICAST_TTL with -1
+
+Warning: socket_set_option(): Expected a value between 0 and 255 in %s on line %d
+bool(false)
+int(254)
diff --git a/ext/sockets/tests/mcast_ipv6_recv.phpt b/ext/sockets/tests/mcast_ipv6_recv.phpt
new file mode 100644
index 0000000000..38390c025c
--- /dev/null
+++ b/ext/sockets/tests/mcast_ipv6_recv.phpt
@@ -0,0 +1,223 @@
+--TEST--
+Multicast support: IPv6 receive options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '::', 3000);
+/* On Linux, there is no route ff00::/8 by default on lo, which makes it
+ * troublesome to send multicast traffic from lo, which we must since
+ * we're dealing with interface-local traffic... */
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+if ($so === false) {
+ die('skip unable to join multicast group on any interface.');
+}
+$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000);
+if ($r === false) {
+ die('skip unable to send multicast packet.');
+}
+
+if (!defined("MCAST_JOIN_SOURCE_GROUP"))
+ die('skip source operations are unavailable');
+
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+ "source" => '2001::dead:beef',
+));
+if ($so === false) {
+ die('skip protocol independent multicast API is unavailable.');
+}
+
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+$domain = AF_INET6;
+$level = IPPROTO_IPV6;
+$interface = 0;
+$mcastaddr = 'ff01::114';
+$sblock = "?";
+
+echo "creating send socket\n";
+$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($sends1);
+
+echo "creating receive socket\n";
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($s);
+$br = socket_bind($s, '::0', 3000) or die("err");
+var_dump($br);
+
+$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+)) or die("err");
+var_dump($so);
+
+$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+checktimeout($s, 500);
+$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort);
+var_dump($r, $str, $from);
+$sblock = $from;
+
+$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+
+$i = 0;
+checktimeout($s, 500);
+while (($str = socket_read($s, 3000)) !== FALSE) {
+ $i++;
+ echo "$i> ", $str, "\n";
+
+if ($i == 1) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 2) {
+ echo "re-joining group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 3) {
+ echo "blocking source\n";
+ $so = socket_set_option($s, $level, MCAST_BLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored packet (blocked source)", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 4) {
+ echo "unblocking source\n";
+ $so = socket_set_option($s, $level, MCAST_UNBLOCK_SOURCE, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 5) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 6) {
+ echo "joining source group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet from desired source", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 7) {
+ echo "leaving source group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 8) {
+ /*echo "joining source group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ "source" => $sblock,
+ ));
+ var_dump($so);*/
+ break;
+}
+
+}
+--EXPECTF--
+creating send socket
+resource(%d) of type (Socket)
+creating receive socket
+resource(%d) of type (Socket)
+bool(true)
+bool(true)
+int(14)
+int(14)
+string(14) "testing packet"
+string(%d) "%s"
+int(14)
+1> initial packet
+leaving group
+bool(true)
+int(20)
+int(14)
+2> unicast packet
+re-joining group
+bool(true)
+int(12)
+3> mcast packet
+blocking source
+bool(true)
+int(31)
+int(14)
+4> unicast packet
+unblocking source
+bool(true)
+int(12)
+5> mcast packet
+leaving group
+bool(true)
+int(20)
+int(14)
+6> unicast packet
+joining source group
+bool(true)
+int(32)
+7> mcast packet from desired source
+leaving source group
+bool(true)
+int(20)
+int(14)
+8> unicast packet
diff --git a/ext/sockets/tests/mcast_ipv6_recv_limited.phpt b/ext/sockets/tests/mcast_ipv6_recv_limited.phpt
new file mode 100644
index 0000000000..fda099877d
--- /dev/null
+++ b/ext/sockets/tests/mcast_ipv6_recv_limited.phpt
@@ -0,0 +1,131 @@
+--TEST--
+Multicast support: IPv6 receive options (limited)
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+$s = socket_create(AF_INET6, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '::', 3000);
+/* On Linux, there is no route ff00::/8 by default on lo, which makes it
+ * troublesome to send multicast traffic from lo, which we must since
+ * we're dealing with interface-local traffic... */
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+if ($so === false) {
+ die('skip unable to join multicast group on any interface.');
+}
+$r = socket_sendto($s, $m = "testing packet", strlen($m), 0, 'ff01::114', 3000);
+if ($r === false) {
+ die('skip unable to send multicast packet.');
+}
+$so = socket_set_option($s, IPPROTO_IPV6, MCAST_LEAVE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+));
+if (defined("MCAST_JOIN_SOURCE_GROUP")) {
+ $so = socket_set_option($s, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, array(
+ "group" => 'ff01::114',
+ "interface" => 0,
+ "source" => '2001::dead:beef',
+ ));
+ if ($so !== false) {
+ die('skip protocol independent multicast API is available.');
+ }
+}
+
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+$domain = AF_INET6;
+$level = IPPROTO_IPV6;
+$interface = 0;
+$mcastaddr = 'ff01::114';
+$sblock = "?";
+
+echo "creating send socket\n";
+$sends1 = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($sends1);
+
+echo "creating receive socket\n";
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+var_dump($s);
+$br = socket_bind($s, '::0', 3000) or die("err");
+var_dump($br);
+
+$so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+)) or die("err");
+var_dump($so);
+
+$r = socket_sendto($sends1, $m = "testing packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+checktimeout($s, 500);
+$r = socket_recvfrom($s, $str, 2000, 0, $from, $fromPort);
+var_dump($r, $str, $from);
+$sblock = $from;
+
+$r = socket_sendto($sends1, $m = "initial packet", strlen($m), 0, $mcastaddr, 3000);
+var_dump($r);
+
+$i = 0;
+checktimeout($s, 500);
+while (($str = socket_read($s, 3000, 500)) !== FALSE) {
+ $i++;
+ echo "$i> ", $str, "\n";
+
+if ($i == 1) {
+ echo "leaving group\n";
+ $so = socket_set_option($s, $level, MCAST_LEAVE_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "ignored mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+ $r = socket_sendto($sends1, $m = "unicast packet", strlen($m), 0, "::1", 3000);
+ var_dump($r);
+}
+if ($i == 2) {
+ echo "re-joining group\n";
+ $so = socket_set_option($s, $level, MCAST_JOIN_GROUP, array(
+ "group" => $mcastaddr,
+ "interface" => $interface,
+ ));
+ var_dump($so);
+ $r = socket_sendto($sends1, $m = "mcast packet", strlen($m), 0, $mcastaddr, 3000);
+ var_dump($r);
+}
+if ($i == 3) {
+ break;
+}
+
+}
+--EXPECTF--
+creating send socket
+resource(%d) of type (Socket)
+creating receive socket
+resource(%d) of type (Socket)
+bool(true)
+bool(true)
+int(14)
+int(14)
+string(14) "testing packet"
+string(%d) "%s"
+int(14)
+1> initial packet
+leaving group
+bool(true)
+int(20)
+int(14)
+2> unicast packet
+re-joining group
+bool(true)
+int(12)
+3> mcast packet
diff --git a/ext/sockets/tests/mcast_ipv6_send.phpt b/ext/sockets/tests/mcast_ipv6_send.phpt
new file mode 100644
index 0000000000..b8d38bf68f
--- /dev/null
+++ b/ext/sockets/tests/mcast_ipv6_send.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Multicast support: IPv6 send options
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('skip sockets extension not available.');
+}
+if (!defined('IPPROTO_IPV6')) {
+ die('skip IPv6 not available.');
+}
+$level = IPPROTO_IPV6;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("skip Can not create socket");
+if (socket_set_option($s, $level, IP_MULTICAST_IF, 1) === false) {
+ die("skip interface 1 either doesn't exist or has no ipv6 address");
+}
+--FILE--
+<?php
+$domain = AF_INET6;
+$level = IPPROTO_IPV6;
+$s = socket_create($domain, SOCK_DGRAM, SOL_UDP) or die("err");
+
+echo "Setting IPV6_MULTICAST_TTL\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_HOPS, 9);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_HOPS);
+var_dump($r);
+echo "\n";
+
+echo "Setting IPV6_MULTICAST_LOOP\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_LOOP, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_LOOP);
+var_dump($r);
+$r = socket_set_option($s, $level, IPV6_MULTICAST_LOOP, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_LOOP);
+var_dump($r);
+echo "\n";
+
+echo "Setting IPV6_MULTICAST_IF\n";
+echo "interface 0:\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_IF, 0);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_IF);
+var_dump($r);
+echo "interface 1:\n";
+$r = socket_set_option($s, $level, IPV6_MULTICAST_IF, 1);
+var_dump($r);
+$r = socket_get_option($s, $level, IPV6_MULTICAST_IF);
+var_dump($r);
+echo "\n";
+
+--EXPECT--
+Setting IPV6_MULTICAST_TTL
+bool(true)
+int(9)
+
+Setting IPV6_MULTICAST_LOOP
+bool(true)
+int(0)
+bool(true)
+int(1)
+
+Setting IPV6_MULTICAST_IF
+interface 0:
+bool(true)
+int(0)
+interface 1:
+bool(true)
+int(1)
diff --git a/ext/sockets/tests/socket_import_stream-1.phpt b/ext/sockets/tests/socket_import_stream-1.phpt
new file mode 100644
index 0000000000..222fca5e2d
--- /dev/null
+++ b/ext/sockets/tests/socket_import_stream-1.phpt
@@ -0,0 +1,26 @@
+--TEST--
+socket_import_stream: Basic test
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+
+--FILE--
+<?php
+
+$domain = (strtoupper(substr(PHP_OS, 0, 3) == 'WIN') ? STREAM_PF_INET : STREAM_PF_UNIX);
+$s = stream_socket_pair($domain, STREAM_SOCK_STREAM, 0);
+
+$s0 = reset($s);
+$s1 = next($s);
+
+$sock = socket_import_stream($s0);
+var_dump($sock);
+socket_write($sock, "test message");
+socket_close($sock);
+
+var_dump(stream_get_contents($s1));
+--EXPECTF--
+resource(%d) of type (Socket)
+string(12) "test message"
diff --git a/ext/sockets/tests/socket_import_stream-2.phpt b/ext/sockets/tests/socket_import_stream-2.phpt
new file mode 100644
index 0000000000..085f0e3834
--- /dev/null
+++ b/ext/sockets/tests/socket_import_stream-2.phpt
@@ -0,0 +1,49 @@
+--TEST--
+socket_import_stream: Bad arguments
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+
+--FILE--
+<?php
+
+var_dump(socket_import_stream());
+var_dump(socket_import_stream(1, 2));
+var_dump(socket_import_stream(1));
+var_dump(socket_import_stream(new stdclass));
+var_dump(socket_import_stream(fopen(__FILE__, "rb")));
+var_dump(socket_import_stream(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)));
+$s = stream_socket_server("udp://127.0.0.1:58392", $errno, $errstr, STREAM_SERVER_BIND);
+var_dump($s);
+var_dump(fclose($s));
+var_dump(socket_import_stream($s));
+
+
+echo "Done.";
+--EXPECTF--
+Warning: socket_import_stream() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: socket_import_stream() expects exactly 1 parameter, 2 given in %s on line %d
+NULL
+
+Warning: socket_import_stream() expects parameter 1 to be resource, integer given in %s on line %d
+NULL
+
+Warning: socket_import_stream() expects parameter 1 to be resource, object given in %s on line %d
+NULL
+
+Warning: socket_import_stream(): cannot represent a stream of type STDIO as a Socket Descriptor in %s on line %d
+bool(false)
+
+Warning: socket_import_stream(): supplied resource is not a valid stream resource in %s on line %d
+bool(false)
+resource(%d) of type (stream)
+bool(true)
+
+Warning: socket_import_stream(): %d is not a valid stream resource in %s on line %d
+bool(false)
+Done.
+
diff --git a/ext/sockets/tests/socket_import_stream-3.phpt b/ext/sockets/tests/socket_import_stream-3.phpt
new file mode 100644
index 0000000000..2261a03ee4
--- /dev/null
+++ b/ext/sockets/tests/socket_import_stream-3.phpt
@@ -0,0 +1,46 @@
+--TEST--
+socket_import_stream: Test with multicasting
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
+$br = socket_bind($s, '0.0.0.0', 58381);
+if ($br === false)
+ die("SKIP IPv4/port 58381 not available");
+$so = socket_set_option($s, IPPROTO_IP, MCAST_JOIN_GROUP, array(
+ "group" => '224.0.0.23',
+ "interface" => "lo",
+));
+if ($so === false)
+ die("SKIP joining group 224.0.0.23 on interface lo failed");
+--FILE--
+<?php
+
+$stream = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND);
+$sock = socket_import_stream($stream);
+var_dump($sock);
+$so = socket_set_option($sock, IPPROTO_IP, MCAST_JOIN_GROUP, array(
+ "group" => '224.0.0.23',
+ "interface" => "lo",
+));
+var_dump($so);
+
+$sendsock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
+var_dump($sendsock);
+$br = socket_bind($sendsock, '127.0.0.1');
+$so = socket_sendto($sendsock, $m = "my message", strlen($m), 0, "224.0.0.23", 58381);
+var_dump($so);
+
+stream_set_blocking($stream, 0);
+var_dump(fread($stream, strlen($m)));
+echo "Done.\n";
+--EXPECTF--
+resource(%d) of type (Socket)
+bool(true)
+resource(%d) of type (Socket)
+int(10)
+string(10) "my message"
+Done.
+
diff --git a/ext/sockets/tests/socket_import_stream-4-win.phpt b/ext/sockets/tests/socket_import_stream-4-win.phpt
new file mode 100644
index 0000000000..e2fc523ce5
--- /dev/null
+++ b/ext/sockets/tests/socket_import_stream-4-win.phpt
@@ -0,0 +1,106 @@
+--TEST--
+socket_import_stream: effects of closing
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die("skip Not Valid for Linux");
+}
+
+--FILE--
+<?php
+
+function test($stream, $sock) {
+ if ($stream !== null) {
+ echo "stream_set_blocking ";
+ print_r(stream_set_blocking($stream, 0));
+ echo "\n";
+ }
+ if ($sock !== null) {
+ echo "socket_set_block ";
+ print_r(socket_set_block($sock));
+ echo "\n";
+ echo "socket_get_option ";
+ print_r(socket_get_option($sock, SOL_SOCKET, SO_TYPE));
+ echo "\n";
+ }
+ echo "\n";
+}
+
+echo "normal\n";
+$stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND);
+$sock0 = socket_import_stream($stream0);
+test($stream0, $sock0);
+
+echo "\nunset stream\n";
+$stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND);
+$sock1 = socket_import_stream($stream1);
+unset($stream1);
+test(null, $sock1);
+
+echo "\nunset socket\n";
+$stream2 = stream_socket_server("udp://0.0.0.0:58382", $errno, $errstr, STREAM_SERVER_BIND);
+$sock2 = socket_import_stream($stream2);
+unset($sock2);
+test($stream2, null);
+
+echo "\nclose stream\n";
+$stream3 = stream_socket_server("udp://0.0.0.0:58383", $errno, $errstr, STREAM_SERVER_BIND);
+$sock3 = socket_import_stream($stream3);
+fclose($stream3);
+test($stream3, $sock3);
+
+echo "\nclose socket\n";
+$stream4 = stream_socket_server("udp://0.0.0.0:58384", $errno, $errstr, STREAM_SERVER_BIND);
+$sock4 = socket_import_stream($stream4);
+socket_close($sock4);
+test($stream4, $sock4);
+
+echo "Done.\n";
+--EXPECTF--
+normal
+stream_set_blocking 1
+socket_set_block 1
+socket_get_option 2
+
+
+unset stream
+socket_set_block 1
+socket_get_option 2
+
+
+unset socket
+stream_set_blocking 1
+
+
+close stream
+stream_set_blocking
+Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d
+
+socket_set_block
+Warning: socket_set_block(): An operation was attempted on something that is not a socket.
+ in %ssocket_import_stream-4-win.php on line %d
+
+Warning: socket_set_block(): unable to set blocking mode [%d]: An operation was attempted on something that is not a socket.
+ in %ssocket_import_stream-4-win.php on line %d
+
+socket_get_option
+Warning: socket_get_option(): unable to retrieve socket option [%d]: An operation was attempted on something that is not a socket.
+ in %ssocket_import_stream-4-win.php on line %d
+
+
+
+close socket
+stream_set_blocking
+Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d
+
+socket_set_block
+Warning: socket_set_block(): %d is not a valid Socket resource in %s on line %d
+
+socket_get_option
+Warning: socket_get_option(): %d is not a valid Socket resource in %s on line %d
+
+
+Done.
diff --git a/ext/sockets/tests/socket_import_stream-4.phpt b/ext/sockets/tests/socket_import_stream-4.phpt
new file mode 100644
index 0000000000..8095d8dac7
--- /dev/null
+++ b/ext/sockets/tests/socket_import_stream-4.phpt
@@ -0,0 +1,100 @@
+--TEST--
+socket_import_stream: effects of closing
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die("skip Not Valid for Windows");
+}
+--FILE--
+<?php
+
+function test($stream, $sock) {
+ if ($stream !== null) {
+ echo "stream_set_blocking ";
+ print_r(stream_set_blocking($stream, 0));
+ echo "\n";
+ }
+ if ($sock !== null) {
+ echo "socket_set_block ";
+ print_r(socket_set_block($sock));
+ echo "\n";
+ echo "socket_get_option ";
+ print_r(socket_get_option($sock, SOL_SOCKET, SO_TYPE));
+ echo "\n";
+ }
+ echo "\n";
+}
+
+echo "normal\n";
+$stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND);
+$sock0 = socket_import_stream($stream0);
+test($stream0, $sock0);
+
+echo "\nunset stream\n";
+$stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND);
+$sock1 = socket_import_stream($stream1);
+unset($stream1);
+test(null, $sock1);
+
+echo "\nunset socket\n";
+$stream2 = stream_socket_server("udp://0.0.0.0:58382", $errno, $errstr, STREAM_SERVER_BIND);
+$sock2 = socket_import_stream($stream2);
+unset($sock2);
+test($stream2, null);
+
+echo "\nclose stream\n";
+$stream3 = stream_socket_server("udp://0.0.0.0:58383", $errno, $errstr, STREAM_SERVER_BIND);
+$sock3 = socket_import_stream($stream3);
+fclose($stream3);
+test($stream3, $sock3);
+
+echo "\nclose socket\n";
+$stream4 = stream_socket_server("udp://0.0.0.0:58384", $errno, $errstr, STREAM_SERVER_BIND);
+$sock4 = socket_import_stream($stream4);
+socket_close($sock4);
+test($stream4, $sock4);
+
+echo "Done.\n";
+--EXPECTF--
+normal
+stream_set_blocking 1
+socket_set_block 1
+socket_get_option 2
+
+
+unset stream
+socket_set_block 1
+socket_get_option 2
+
+
+unset socket
+stream_set_blocking 1
+
+
+close stream
+stream_set_blocking
+Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d
+
+socket_set_block
+Warning: socket_set_block(): unable to set blocking mode [%d]: %s in %s on line %d
+
+socket_get_option
+Warning: socket_get_option(): unable to retrieve socket option [%d]: %s in %s on line %d
+
+
+
+close socket
+stream_set_blocking
+Warning: stream_set_blocking(): %d is not a valid stream resource in %s on line %d
+
+socket_set_block
+Warning: socket_set_block(): %d is not a valid Socket resource in %s on line %d
+
+socket_get_option
+Warning: socket_get_option(): %d is not a valid Socket resource in %s on line %d
+
+
+Done.
diff --git a/ext/sockets/tests/socket_import_stream-5.phpt b/ext/sockets/tests/socket_import_stream-5.phpt
new file mode 100644
index 0000000000..d48531e410
--- /dev/null
+++ b/ext/sockets/tests/socket_import_stream-5.phpt
@@ -0,0 +1,23 @@
+--TEST--
+socket_import_stream: effects of leaked handles
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+if (!function_exists('leak_variable'))
+ die('SKIP only for debug builds');
+--FILE--
+<?php
+
+$stream0 = stream_socket_server("udp://0.0.0.0:58380", $errno, $errstr, STREAM_SERVER_BIND);
+$sock0 = socket_import_stream($stream0);
+leak_variable($stream0, true);
+
+$stream1 = stream_socket_server("udp://0.0.0.0:58381", $errno, $errstr, STREAM_SERVER_BIND);
+$sock1 = socket_import_stream($stream1);
+leak_variable($sock1, true);
+
+echo "Done.\n";
+--EXPECT--
+Done.
diff --git a/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt b/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt
index 96cbf8f4db..bf95044d48 100644
--- a/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt
+++ b/ext/sockets/tests/socket_sentto_recvfrom_ipv4_udp.phpt
@@ -25,7 +25,7 @@ if (!extension_loaded('sockets')) {
$len = strlen($msg);
$bytes_sent = socket_sendto($socket, $msg, $len, 0, $address, 1223);
if ($bytes_sent == -1) {
- die('An error occured while sending to the socket');
+ die('An error occurred while sending to the socket');
} else if ($bytes_sent != $len) {
die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected');
}
@@ -36,7 +36,7 @@ if (!extension_loaded('sockets')) {
socket_recvfrom($socket, $buf, 12, 0, $from); // cause warning
$bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from, $port);
if ($bytes_received == -1) {
- die('An error occured while receiving from the socket');
+ die('An error occurred while receiving from the socket');
} else if ($bytes_received != $len) {
die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected');
}
diff --git a/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt
index 1fa42fd5da..04f62eddd3 100644
--- a/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt
+++ b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp.phpt
@@ -26,7 +26,7 @@ require 'ipv6_skipif.inc';
$len = strlen($msg);
$bytes_sent = socket_sendto($socket, $msg, $len, 0, $address, 1223);
if ($bytes_sent == -1) {
- die('An error occured while sending to the socket');
+ die('An error occurred while sending to the socket');
} else if ($bytes_sent != $len) {
die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected');
}
@@ -37,7 +37,7 @@ require 'ipv6_skipif.inc';
socket_recvfrom($socket, $buf, 12, 0, $from); // cause warning
$bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from, $port);
if ($bytes_received == -1) {
- die('An error occured while receiving from the socket');
+ die('An error occurred while receiving from the socket');
} else if ($bytes_received != $len) {
die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected');
}
diff --git a/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt b/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt
index 4cfdebbcbe..55ad75c65e 100644
--- a/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt
+++ b/ext/sockets/tests/socket_sentto_recvfrom_unix.phpt
@@ -30,7 +30,7 @@ if (!extension_loaded('sockets')) {
$bytes_sent = socket_sendto($socket, $msg, $len, 0, $address);
if ($bytes_sent == -1) {
@unlink($address);
- die('An error occured while sending to the socket');
+ die('An error occurred while sending to the socket');
} else if ($bytes_sent != $len) {
@unlink($address);
die($bytes_sent . ' bytes have been sent instead of the ' . $len . ' bytes expected');
@@ -41,7 +41,7 @@ if (!extension_loaded('sockets')) {
$bytes_received = socket_recvfrom($socket, $buf, 12, 0, $from);
if ($bytes_received == -1) {
@unlink($address);
- die('An error occured while receiving from the socket');
+ die('An error occurred while receiving from the socket');
} else if ($bytes_received != $len) {
@unlink($address);
die($bytes_received . ' bytes have been received instead of the ' . $len . ' bytes expected');
diff --git a/ext/sockets/tests/socket_set_option_seolinger.phpt b/ext/sockets/tests/socket_set_option_seolinger.phpt
index e49a7eb155..36606b4eed 100644
--- a/ext/sockets/tests/socket_set_option_seolinger.phpt
+++ b/ext/sockets/tests/socket_set_option_seolinger.phpt
@@ -1,8 +1,8 @@
--TEST--
Test if socket_set_option() works, option:SO_SEOLINGER
--DESCRIPTION--
--wrong params
--set/get params comparison
+-wrong params
+-set/get params comparison
-l_linger not given
--SKIPIF--
<?php
@@ -30,7 +30,9 @@ $options_2 = array("l_onoff" => 1);
var_dump(socket_set_option( $socket, SOL_SOCKET, SO_LINGER, $options_2));
var_dump($retval_2);
-var_dump($retval_3 === $options);
+var_dump($retval_3["l_linger"] === $options["l_linger"]);
+// value of l_onoff is not always 1, Darwin returns 128
+var_dump((bool)$retval_3["l_onoff"] === (bool)$options["l_onoff"]);
socket_close($socket);
?>
@@ -42,6 +44,7 @@ Warning: socket_set_option(): no key "l_linger" passed in optval in %s on line %
bool(false)
bool(true)
bool(true)
+bool(true)
--CREDITS--
Moritz Neuhaeuser, info@xcompile.net
PHP Testfest Berlin 2009-05-10
diff --git a/ext/spl/examples/dbaarray.inc b/ext/spl/examples/dbaarray.inc
index fcd6bb378a..d448ad7299 100644
--- a/ext/spl/examples/dbaarray.inc
+++ b/ext/spl/examples/dbaarray.inc
@@ -51,9 +51,6 @@ class DbaArray extends DbaReader implements ArrayAccess
{
$data = dba_fetch($name, $this->db);
if($data) {
- if (ini_get('magic_quotes_runtime')) {
- $data = stripslashes($data);
- }
//return unserialize($data);
return $data;
}
@@ -95,4 +92,4 @@ class DbaArray extends DbaReader implements ArrayAccess
}
}
-?> \ No newline at end of file
+?>
diff --git a/ext/spl/internal/regexiterator.inc b/ext/spl/internal/regexiterator.inc
index 96b8f81126..c6addb93d2 100644
--- a/ext/spl/internal/regexiterator.inc
+++ b/ext/spl/internal/regexiterator.inc
@@ -158,6 +158,13 @@ class RegexIterator extends FilterIterator
{
$this->preg_flags = $preg_flags;
}
+
+ /** @return current regular expression
+ */
+ function getRegex()
+ {
+ return $this->regex;
+ }
}
?>
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index e2bd7cf281..cd0086626f 100644
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -150,6 +150,35 @@ PHP_FUNCTION(class_implements)
}
/* }}} */
+/* {{{ proto array class_uses(mixed what [, bool autoload ])
+ Return all traits used by a class. */
+PHP_FUNCTION(class_uses)
+{
+ zval *obj;
+ zend_bool autoload = 1;
+ zend_class_entry *ce;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) {
+ RETURN_FALSE;
+ }
+ if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected");
+ RETURN_FALSE;
+ }
+
+ if (Z_TYPE_P(obj) == IS_STRING) {
+ if (NULL == (ce = spl_find_ce_by_name(Z_STRVAL_P(obj), Z_STRLEN_P(obj), autoload TSRMLS_CC))) {
+ RETURN_FALSE;
+ }
+ } else {
+ ce = Z_OBJCE_P(obj);
+ }
+
+ array_init(return_value);
+ spl_add_traits(return_value, ce, 1, ZEND_ACC_TRAIT TSRMLS_CC);
+}
+/* }}} */
+
#define SPL_ADD_CLASS(class_name, z_list, sub, allow, ce_flags) \
spl_add_classes(spl_ce_ ## class_name, z_list, sub, allow, ce_flags TSRMLS_CC)
@@ -160,6 +189,7 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(BadFunctionCallException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(BadMethodCallException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(CallbackFilterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(Countable, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(DomainException, z_list, sub, allow, ce_flags); \
@@ -183,6 +213,7 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(RangeException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveArrayIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveCachingIterator, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(RecursiveCallbackFilterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveDirectoryIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveFilterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveIterator, z_list, sub, allow, ce_flags); \
@@ -242,7 +273,7 @@ static int spl_autoload(const char *class_name, const char * lc_name, int class_
}
#endif
- ret = php_stream_open_for_zend_ex(class_file, &file_handle, ENFORCE_SAFE_MODE|USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
+ ret = php_stream_open_for_zend_ex(class_file, &file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
if (ret == SUCCESS) {
if (!file_handle.opened_path) {
@@ -567,7 +598,14 @@ PHP_FUNCTION(spl_autoload_register)
}
}
- zend_hash_add(SPL_G(autoload_functions), lc_name, func_name_len+1, &alfi.func_ptr, sizeof(autoload_func_info), NULL);
+ if (zend_hash_add(SPL_G(autoload_functions), lc_name, func_name_len+1, &alfi.func_ptr, sizeof(autoload_func_info), NULL) == FAILURE) {
+ if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
+ Z_DELREF_P(alfi.obj);
+ }
+ if (alfi.closure) {
+ Z_DELREF_P(alfi.closure);
+ }
+ }
if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
/* Move the newly created element to the head of the hashtable */
HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
@@ -828,6 +866,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_implements, 0, 0, 1)
ZEND_ARG_INFO(0, autoload)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_class_uses, 0, 0, 1)
+ ZEND_ARG_INFO(0, what)
+ ZEND_ARG_INFO(0, autoload)
+ZEND_END_ARG_INFO()
+
+
ZEND_BEGIN_ARG_INFO(arginfo_spl_classes, 0)
ZEND_END_ARG_INFO()
@@ -872,6 +916,7 @@ const zend_function_entry spl_functions[] = {
PHP_FE(spl_autoload_call, arginfo_spl_autoload_call)
PHP_FE(class_parents, arginfo_class_parents)
PHP_FE(class_implements, arginfo_class_implements)
+ PHP_FE(class_uses, arginfo_class_uses)
PHP_FE(spl_object_hash, arginfo_spl_object_hash)
#ifdef SPL_ITERATORS_H
PHP_FE(iterator_to_array, arginfo_iterator_to_array)
diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h
index fb0765a81b..855a78c404 100644
--- a/ext/spl/php_spl.h
+++ b/ext/spl/php_spl.h
@@ -83,6 +83,7 @@ extern zend_spl_globals spl_globals;
PHP_FUNCTION(spl_classes);
PHP_FUNCTION(class_parents);
PHP_FUNCTION(class_implements);
+PHP_FUNCTION(class_uses);
PHPAPI void php_spl_object_hash(zval *obj, char* md5str TSRMLS_DC);
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 11540decd9..3c6b41edbc 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -58,35 +58,41 @@ PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator;
#define SPL_ARRAY_INT_MASK 0xFFFF0000
#define SPL_ARRAY_CLONE_MASK 0x0300FFFF
+#define SPL_ARRAY_METHOD_NO_ARG 0
+#define SPL_ARRAY_METHOD_USE_ARG 1
+#define SPL_ARRAY_METHOD_MAY_USER_ARG 2
+
typedef struct _spl_array_object {
- zend_object std;
- zval *array;
- zval *retval;
- HashPosition pos;
- ulong pos_h;
- int ar_flags;
- int is_self;
- zend_function *fptr_offset_get;
- zend_function *fptr_offset_set;
- zend_function *fptr_offset_has;
- zend_function *fptr_offset_del;
- zend_function *fptr_count;
- zend_function *fptr_serialize;
- zend_function *fptr_unserialize;
- zend_class_entry *ce_get_iterator;
- php_serialize_data_t *serialize_data;
- php_unserialize_data_t *unserialize_data;
+ zend_object std;
+ zval *array;
+ zval *retval;
+ HashPosition pos;
+ ulong pos_h;
+ int ar_flags;
+ int is_self;
+ zend_function *fptr_offset_get;
+ zend_function *fptr_offset_set;
+ zend_function *fptr_offset_has;
+ zend_function *fptr_offset_del;
+ zend_function *fptr_count;
+ zend_class_entry* ce_get_iterator;
HashTable *debug_info;
unsigned char nApplyCount;
} spl_array_object;
static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */
if ((intern->ar_flags & SPL_ARRAY_IS_SELF) != 0) {
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
return intern->std.properties;
} else if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0) && Z_TYPE_P(intern->array) == IS_OBJECT) {
spl_array_object *other = (spl_array_object*)zend_object_store_get_object(intern->array TSRMLS_CC);
return spl_array_get_hash_table(other, check_std_props TSRMLS_CC);
} else if ((intern->ar_flags & ((check_std_props ? SPL_ARRAY_STD_PROP_LIST : 0) | SPL_ARRAY_IS_SELF)) != 0) {
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
return intern->std.properties;
} else {
return HASH_OF(intern->array);
@@ -156,8 +162,6 @@ static void spl_array_object_free_storage(void *object TSRMLS_DC)
/* }}} */
zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
-int spl_array_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC);
-int spl_array_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC);
/* {{{ spl_array_object_new_ex */
static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, spl_array_object **obj, zval *orig, int clone_orig TSRMLS_DC)
@@ -174,11 +178,9 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
intern->ar_flags = 0;
- intern->serialize_data = NULL;
- intern->unserialize_data = NULL;
intern->debug_info = NULL;
intern->ce_get_iterator = spl_ce_ArrayIterator;
if (orig) {
@@ -245,14 +247,6 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
if (intern->fptr_count->common.scope == parent) {
intern->fptr_count = NULL;
}
- zend_hash_find(&class_type->function_table, "serialize", sizeof("serialize"), (void **) &intern->fptr_serialize);
- if (intern->fptr_serialize->common.scope == parent) {
- intern->fptr_serialize = NULL;
- }
- zend_hash_find(&class_type->function_table, "unserialize", sizeof("unserialize"), (void **) &intern->fptr_unserialize);
- if (intern->fptr_unserialize->common.scope == parent) {
- intern->fptr_unserialize = NULL;
- }
}
/* Cache iterator functions if ArrayIterator or derived. Check current's */
/* cache since only current is always required */
@@ -329,13 +323,13 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(offset));
+ zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(offset));
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
+ zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
case BP_VAR_W: {
zval *value;
ALLOC_INIT_ZVAL(value);
@@ -357,13 +351,13 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE, "Undefined offset: %ld", index);
+ zend_error(E_NOTICE, "Undefined offset: %ld", index);
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE, "Undefined offset: %ld", index);
+ zend_error(E_NOTICE, "Undefined offset: %ld", index);
case BP_VAR_W: {
zval *value;
ALLOC_INIT_ZVAL(value);
@@ -526,12 +520,39 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
}
if (ht == &EG(symbol_table)) {
if (zend_delete_global_variable(Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC)) {
- zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
+ zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
}
} else {
if (zend_symtable_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
- zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
- }
+ zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
+ } else {
+ spl_array_object *obj = intern;
+
+ while (1) {
+ if ((obj->ar_flags & SPL_ARRAY_IS_SELF) != 0) {
+ break;
+ } else if (Z_TYPE_P(obj->array) == IS_OBJECT) {
+ if ((obj->ar_flags & SPL_ARRAY_USE_OTHER) == 0) {
+ obj = (spl_array_object*)zend_object_store_get_object(obj->array TSRMLS_CC);
+ break;
+ } else {
+ obj = (spl_array_object*)zend_object_store_get_object(obj->array TSRMLS_CC);
+ }
+ } else {
+ obj = NULL;
+ break;
+ }
+ }
+ if (obj) {
+ zend_property_info *property_info = zend_get_property_info(obj->std.ce, offset, 1 TSRMLS_CC);
+
+ if (property_info &&
+ (property_info->flags & ZEND_ACC_STATIC) == 0 &&
+ property_info->offset >= 0) {
+ obj->std.properties_table[property_info->offset] = NULL;
+ }
+ }
+ }
}
break;
case IS_DOUBLE:
@@ -549,7 +570,7 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
return;
}
if (zend_hash_index_del(ht, index) == FAILURE) {
- zend_error(E_NOTICE,"Undefined offset: %ld", Z_LVAL_P(offset));
+ zend_error(E_NOTICE,"Undefined offset: %ld", Z_LVAL_P(offset));
}
break;
default:
@@ -598,13 +619,13 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
return zend_is_true(*tmp);
}
}
- return 0;
}
+ return 0;
case IS_DOUBLE:
case IS_RESOURCE:
case IS_BOOL:
- case IS_LONG:
- {
+ case IS_LONG:
+ {
HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
if (offset->type == IS_DOUBLE) {
index = (long)Z_DVAL_P(offset);
@@ -634,6 +655,28 @@ static int spl_array_has_dimension(zval *object, zval *offset, int check_empty T
return spl_array_has_dimension_ex(1, object, offset, check_empty TSRMLS_CC);
} /* }}} */
+/* {{{ spl_array_object_verify_pos_ex */
+static inline int spl_array_object_verify_pos_ex(spl_array_object *object, HashTable *ht, const char *msg_prefix TSRMLS_DC)
+{
+ if (!ht) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%sArray was modified outside object and is no longer an array", msg_prefix);
+ return FAILURE;
+ }
+
+ if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, ht TSRMLS_CC) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%sArray was modified outside object and internal position is no longer valid", msg_prefix);
+ return FAILURE;
+ }
+
+ return SUCCESS;
+} /* }}} */
+
+/* {{{ spl_array_object_verify_pos */
+static inline int spl_array_object_verify_pos(spl_array_object *object, HashTable *ht TSRMLS_DC)
+{
+ return spl_array_object_verify_pos_ex(object, ht, "" TSRMLS_CC);
+} /* }}} */
+
/* {{{ proto bool ArrayObject::offsetExists(mixed $index)
proto bool ArrayIterator::offsetExists(mixed $index)
Returns whether the requested $index exists. */
@@ -754,6 +797,10 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /*
*is_temp = 0;
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
+
if (HASH_OF(intern->array) == intern->std.properties) {
return intern->std.properties;
} else {
@@ -780,63 +827,62 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /*
}
/* }}} */
-static zval *spl_array_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
+static zval *spl_array_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
{
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
- && !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
+ && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) {
return spl_array_read_dimension(object, member, type TSRMLS_CC);
}
- return std_object_handlers.read_property(object, member, type TSRMLS_CC);
+ return std_object_handlers.read_property(object, member, type, key TSRMLS_CC);
} /* }}} */
-static void spl_array_write_property(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */
+static void spl_array_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
{
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
- && !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
+ && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) {
spl_array_write_dimension(object, member, value TSRMLS_CC);
return;
}
- std_object_handlers.write_property(object, member, value TSRMLS_CC);
+ std_object_handlers.write_property(object, member, value, key TSRMLS_CC);
} /* }}} */
-static zval **spl_array_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval **spl_array_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
- && !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
+ && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) {
return spl_array_get_dimension_ptr_ptr(1, object, member, BP_VAR_RW TSRMLS_CC);
}
- return std_object_handlers.get_property_ptr_ptr(object, member TSRMLS_CC);
+ return std_object_handlers.get_property_ptr_ptr(object, member, key TSRMLS_CC);
} /* }}} */
-static int spl_array_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */
+static int spl_array_has_property(zval *object, zval *member, int has_set_exists, const zend_literal *key TSRMLS_DC) /* {{{ */
{
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
- && !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
+ && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) {
return spl_array_has_dimension(object, member, has_set_exists TSRMLS_CC);
}
- return std_object_handlers.has_property(object, member, has_set_exists TSRMLS_CC);
-
+ return std_object_handlers.has_property(object, member, has_set_exists, key TSRMLS_CC);
} /* }}} */
-static void spl_array_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static void spl_array_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
- && !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
+ && !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) {
spl_array_unset_dimension(object, member TSRMLS_CC);
spl_array_rewind(intern TSRMLS_CC); /* because deletion might invalidate position */
return;
}
- std_object_handlers.unset_property(object, member TSRMLS_CC);
+ std_object_handlers.unset_property(object, member, key TSRMLS_CC);
} /* }}} */
static int spl_array_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
@@ -943,17 +989,11 @@ static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
if (object->ar_flags & SPL_ARRAY_OVERLOADED_VALID) {
return zend_user_it_valid(iter TSRMLS_CC);
} else {
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and is no longer an array");
+ if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::valid(): " TSRMLS_CC) == FAILURE) {
return FAILURE;
}
-
- if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and internal position is no longer valid");
- return FAILURE;
- } else {
- return zend_hash_has_more_elements_ex(aht, &object->pos);
- }
+
+ return zend_hash_has_more_elements_ex(aht, &object->pos);
}
}
/* }}} */
@@ -983,13 +1023,7 @@ static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_k
if (object->ar_flags & SPL_ARRAY_OVERLOADED_KEY) {
return zend_user_it_get_current_key(iter, str_key, str_key_len, int_key TSRMLS_CC);
} else {
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array");
- return HASH_KEY_NON_EXISTANT;
- }
-
- if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and internal position is no longer valid");
+ if (spl_array_object_verify_pos_ex(object, aht, "ArrayIterator::current(): " TSRMLS_CC) == FAILURE) {
return HASH_KEY_NON_EXISTANT;
}
@@ -1396,26 +1430,36 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
{
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
- zval *tmp, *arg;
+ zval *tmp, *arg = NULL;
zval *retval_ptr = NULL;
MAKE_STD_ZVAL(tmp);
Z_TYPE_P(tmp) = IS_ARRAY;
Z_ARRVAL_P(tmp) = aht;
- if (use_arg) {
- if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
+ if (!use_arg) {
+ aht->nApplyCount++;
+ zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+ aht->nApplyCount--;
+ } else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|z", &arg) == FAILURE) {
Z_TYPE_P(tmp) = IS_NULL;
zval_ptr_dtor(&tmp);
- zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
+ zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0 TSRMLS_CC);
return;
}
aht->nApplyCount++;
- zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
+ zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, arg? 2 : 1, tmp, arg TSRMLS_CC);
aht->nApplyCount--;
} else {
+ if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
+ Z_TYPE_P(tmp) = IS_NULL;
+ zval_ptr_dtor(&tmp);
+ zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
+ return;
+ }
aht->nApplyCount++;
- zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+ zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
aht->nApplyCount--;
}
Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */
@@ -1431,35 +1475,35 @@ SPL_METHOD(cname, fname) \
spl_array_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, #fname, sizeof(#fname)-1, use_arg); \
}
-/* {{{ proto int ArrayObject::asort()
- proto int ArrayIterator::asort()
+/* {{{ proto int ArrayObject::asort([int $sort_flags = SORT_REGULAR ])
+ proto int ArrayIterator::asort([int $sort_flags = SORT_REGULAR ])
Sort the entries by values. */
-SPL_ARRAY_METHOD(Array, asort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, asort, SPL_ARRAY_METHOD_MAY_USER_ARG) /* }}} */
-/* {{{ proto int ArrayObject::ksort()
- proto int ArrayIterator::ksort()
+/* {{{ proto int ArrayObject::ksort([int $sort_flags = SORT_REGULAR ])
+ proto int ArrayIterator::ksort([int $sort_flags = SORT_REGULAR ])
Sort the entries by key. */
-SPL_ARRAY_METHOD(Array, ksort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, ksort, SPL_ARRAY_METHOD_MAY_USER_ARG) /* }}} */
/* {{{ proto int ArrayObject::uasort(callback cmp_function)
proto int ArrayIterator::uasort(callback cmp_function)
Sort the entries by values user defined function. */
-SPL_ARRAY_METHOD(Array, uasort, 1) /* }}} */
+SPL_ARRAY_METHOD(Array, uasort, SPL_ARRAY_METHOD_USE_ARG) /* }}} */
/* {{{ proto int ArrayObject::uksort(callback cmp_function)
proto int ArrayIterator::uksort(callback cmp_function)
Sort the entries by key using user defined function. */
-SPL_ARRAY_METHOD(Array, uksort, 1) /* }}} */
+SPL_ARRAY_METHOD(Array, uksort, SPL_ARRAY_METHOD_USE_ARG) /* }}} */
/* {{{ proto int ArrayObject::natsort()
proto int ArrayIterator::natsort()
Sort the entries by values using "natural order" algorithm. */
-SPL_ARRAY_METHOD(Array, natsort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, natsort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */
/* {{{ proto int ArrayObject::natcasesort()
proto int ArrayIterator::natcasesort()
Sort the entries by key using case insensitive "natural order" algorithm. */
-SPL_ARRAY_METHOD(Array, natcasesort, 0) /* }}} */
+SPL_ARRAY_METHOD(Array, natcasesort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */
/* {{{ proto mixed|NULL ArrayIterator::current()
Return current array entry */
@@ -1474,13 +1518,7 @@ SPL_METHOD(Array, current)
return;
}
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- return;
- }
-
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
+ if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) {
return;
}
@@ -1510,13 +1548,7 @@ void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ *
ulong num_key;
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- return;
- }
-
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
+ if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) {
return;
}
@@ -1544,13 +1576,12 @@ SPL_METHOD(Array, next)
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
+
+ if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) {
return;
}
- spl_array_next_ex(intern, aht TSRMLS_CC);
+ spl_array_next_no_verify(intern, aht TSRMLS_CC);
}
/* }}} */
@@ -1565,14 +1596,8 @@ SPL_METHOD(Array, valid)
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- return;
- }
- if (intern->pos && (intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
+ if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
} else {
RETURN_BOOL(zend_hash_has_more_elements_ex(aht, &intern->pos) == SUCCESS);
@@ -1591,14 +1616,8 @@ SPL_METHOD(Array, hasChildren)
if (zend_parse_parameters_none() == FAILURE) {
return;
}
-
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- RETURN_FALSE;
- }
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
+ if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
@@ -1622,13 +1641,7 @@ SPL_METHOD(Array, getChildren)
return;
}
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- return;
- }
-
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht TSRMLS_CC) == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
+ if (spl_array_object_verify_pos(intern, aht TSRMLS_CC) == FAILURE) {
return;
}
@@ -1652,68 +1665,55 @@ SPL_METHOD(Array, getChildren)
}
/* }}} */
-smart_str spl_array_serialize_helper(spl_array_object *intern, php_serialize_data_t *var_hash_p TSRMLS_DC) { /* {{{ */
+/* {{{ proto string ArrayObject::serialize()
+ Serialize the object */
+SPL_METHOD(Array, serialize)
+{
+ zval *object = getThis();
+ spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
zval members, *pmembers;
+ php_serialize_data_t var_hash;
smart_str buf = {0};
zval *flags;
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
if (!aht) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- return buf;
+ return;
}
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+
MAKE_STD_ZVAL(flags);
ZVAL_LONG(flags, (intern->ar_flags & SPL_ARRAY_CLONE_MASK));
/* storage */
smart_str_appendl(&buf, "x:", 2);
- php_var_serialize(&buf, &flags, var_hash_p TSRMLS_CC);
+ php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC);
zval_ptr_dtor(&flags);
if (!(intern->ar_flags & SPL_ARRAY_IS_SELF)) {
- php_var_serialize(&buf, &intern->array, var_hash_p TSRMLS_CC);
+ php_var_serialize(&buf, &intern->array, &var_hash TSRMLS_CC);
smart_str_appendc(&buf, ';');
}
/* members */
smart_str_appendl(&buf, "m:", 2);
INIT_PZVAL(&members);
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
Z_ARRVAL(members) = intern->std.properties;
Z_TYPE(members) = IS_ARRAY;
pmembers = &members;
- php_var_serialize(&buf, &pmembers, var_hash_p TSRMLS_CC); /* finishes the string */
+ php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
/* done */
- return buf;
-}
-/* }}} */
-
-/* {{{ proto string ArrayObject::serialize()
- Serialize the object */
-SPL_METHOD(Array, serialize)
-{
- zval *object = getThis();
- spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
- int was_in_serialize = intern->serialize_data != NULL;
- smart_str buf;
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- if (!was_in_serialize) {
- intern->serialize_data = emalloc(sizeof(php_serialize_data_t));
- PHP_VAR_SERIALIZE_INIT(*intern->serialize_data);
- }
-
- buf = spl_array_serialize_helper(intern, intern->serialize_data TSRMLS_CC);
-
- if (!was_in_serialize) {
- PHP_VAR_SERIALIZE_DESTROY(*intern->serialize_data);
- efree(intern->serialize_data);
- intern->serialize_data = NULL;
- }
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
if (buf.c) {
RETURN_STRINGL(buf.c, buf.len, 0);
@@ -1722,47 +1722,32 @@ SPL_METHOD(Array, serialize)
RETURN_NULL();
} /* }}} */
-int spl_array_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) /* {{{ */
+/* {{{ proto void ArrayObject::unserialize(string serialized)
+ * unserialize the object
+ */
+SPL_METHOD(Array, unserialize)
{
- spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
-
- if (intern->fptr_serialize) {
- int retval;
- php_serialize_data_t *before;
-
- before = intern->serialize_data;
- intern->serialize_data = (php_serialize_data_t *)data;
-
- retval = zend_user_serialize(object, buffer, buf_len, data TSRMLS_CC);
-
- intern->serialize_data = before;
-
- return retval;
- } else {
- smart_str buf;
-
- buf = spl_array_serialize_helper(intern, (php_serialize_data_t *)data TSRMLS_CC);
-
- if (buf.c) {
- *buffer = (unsigned char*)estrndup(buf.c, buf.len);
- *buf_len = buf.len;
- efree(buf.c);
- return SUCCESS;
- } else {
- return FAILURE;
- }
- }
-}
-/* }}} */
+ spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char *buf, int buf_len, php_unserialize_data_t *var_hash_p TSRMLS_DC) /* {{{ */
-{
+ char *buf;
+ int buf_len;
const unsigned char *p, *s;
+ php_unserialize_data_t var_hash;
zval *pmembers, *pflags = NULL;
long flags;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
+ return;
+ }
+
+ if (buf_len == 0) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty");
+ return;
+ }
/* storage */
- s = p = buf;
+ s = p = (const unsigned char*)buf;
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
if (*p!= 'x' || *++p != ':') {
goto outexcept;
@@ -1770,7 +1755,7 @@ void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char
++p;
ALLOC_INIT_ZVAL(pflags);
- if (!php_var_unserialize(&pflags, &p, s + buf_len, var_hash_p TSRMLS_CC) || Z_TYPE_P(pflags) != IS_LONG) {
+ if (!php_var_unserialize(&pflags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pflags) != IS_LONG) {
zval_ptr_dtor(&pflags);
goto outexcept;
}
@@ -1796,7 +1781,7 @@ void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char
intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK;
zval_ptr_dtor(&intern->array);
ALLOC_INIT_ZVAL(intern->array);
- if (!php_var_unserialize(&intern->array, &p, s + buf_len, var_hash_p TSRMLS_CC)) {
+ if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) {
goto outexcept;
}
}
@@ -1812,90 +1797,30 @@ void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char
++p;
ALLOC_INIT_ZVAL(pmembers);
- if (!php_var_unserialize(&pmembers, &p, s + buf_len, var_hash_p TSRMLS_CC)) {
+ if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) {
zval_ptr_dtor(&pmembers);
goto outexcept;
}
/* copy members */
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
zval_ptr_dtor(&pmembers);
/* done reading $serialized */
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
return;
outexcept:
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - (char *)buf), buf_len);
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
return;
-}
-/* }}} */
-
-/* {{{ proto void ArrayObject::unserialize(string serialized)
- Unserialize the object */
-SPL_METHOD(Array, unserialize)
-{
- char *buf;
- int buf_len;
- spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- int was_in_unserialize = intern->unserialize_data != NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
- return;
- }
-
- if (buf_len == 0) {
- zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty");
- return;
- }
-
- if (!was_in_unserialize) {
- intern->unserialize_data = emalloc(sizeof(php_unserialize_data_t));
- PHP_VAR_UNSERIALIZE_INIT(*intern->unserialize_data);
- }
-
- spl_array_unserialize_helper(intern, (const unsigned char *)buf, buf_len, intern->unserialize_data TSRMLS_CC);
-
- if (!was_in_unserialize) {
- PHP_VAR_UNSERIALIZE_DESTROY(*intern->unserialize_data);
- efree(intern->unserialize_data);
- intern->unserialize_data = NULL;
- }
} /* }}} */
-int spl_array_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
-{
- spl_array_object *intern;
-
- object_init_ex(*object, ce);
- intern = (spl_array_object*)zend_object_store_get_object(*object TSRMLS_CC);
-
- if (intern->fptr_unserialize) {
- zval *zdata;
- php_unserialize_data_t *before;
- MAKE_STD_ZVAL(zdata);
- ZVAL_STRINGL(zdata, (char *)buf, buf_len, 1);
-
- before = intern->unserialize_data;
- intern->unserialize_data = (php_unserialize_data_t *)data;
-
- zend_call_method_with_1_params(object, ce, &ce->unserialize_func, "unserialize", NULL, zdata);
-
- intern->unserialize_data = before;
-
- zval_ptr_dtor(&zdata);
- } else {
- spl_array_unserialize_helper(intern, buf, buf_len, (php_unserialize_data_t *)data TSRMLS_CC);
- }
-
- if (EG(exception)) {
- return FAILURE;
- } else {
- return SUCCESS;
- }
-}
-/* }}} */
-
/* {{{ arginfo and function tbale */
ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0)
ZEND_ARG_INFO(0, array)
@@ -2012,8 +1937,6 @@ PHP_MINIT_FUNCTION(spl_array)
REGISTER_SPL_IMPLEMENTS(ArrayObject, ArrayAccess);
REGISTER_SPL_IMPLEMENTS(ArrayObject, Serializable);
REGISTER_SPL_IMPLEMENTS(ArrayObject, Countable);
- spl_ce_ArrayObject->serialize = spl_array_serialize;
- spl_ce_ArrayObject->unserialize = spl_array_unserialize;
memcpy(&spl_handler_ArrayObject, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
spl_handler_ArrayObject.clone_obj = spl_array_object_clone;
@@ -2039,8 +1962,6 @@ PHP_MINIT_FUNCTION(spl_array)
REGISTER_SPL_IMPLEMENTS(ArrayIterator, SeekableIterator);
REGISTER_SPL_IMPLEMENTS(ArrayIterator, Serializable);
REGISTER_SPL_IMPLEMENTS(ArrayIterator, Countable);
- spl_ce_ArrayIterator->serialize = spl_array_serialize;
- spl_ce_ArrayIterator->unserialize = spl_array_unserialize;
memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers));
spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator;
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 8c1810ef71..b86e68659d 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -148,7 +148,6 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
{
zend_object_value retval;
spl_filesystem_object *intern;
- zval *tmp;
intern = emalloc(sizeof(spl_filesystem_object));
memset(intern, 0, sizeof(spl_filesystem_object));
@@ -158,7 +157,7 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
if (obj) *obj = intern;
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC);
retval.handlers = &spl_filesystem_object_handlers;
@@ -245,7 +244,7 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path TS
intern->type = SPL_FS_DIR;
intern->_path_len = strlen(path);
- intern->u.dir.dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
+ intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context));
if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) {
intern->_path = estrndup(path, --intern->_path_len);
@@ -284,7 +283,7 @@ static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_inclu
}
intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
- intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, intern->u.file.context);
+ intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, intern->u.file.context);
if (!intern->file_name_len || !intern->u.file.stream) {
if (!EG(exception)) {
@@ -595,6 +594,10 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T
*is_temp = 1;
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
+
ALLOC_HASHTABLE(rv);
ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0);
@@ -656,16 +659,17 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T
}
/* }}} */
-zend_function *spl_filesystem_object_get_method_check(zval **object_ptr, char *method, int method_len TSRMLS_DC) /* {{{ */
+zend_function *spl_filesystem_object_get_method_check(zval **object_ptr, char *method, int method_len, const struct _zend_literal *key TSRMLS_DC) /* {{{ */
{
spl_filesystem_object *fsobj = zend_object_store_get_object(*object_ptr TSRMLS_CC);
if (fsobj->u.dir.entry.d_name[0] == '\0' && fsobj->orig_path == NULL) {
method = "_bad_state_ex";
method_len = sizeof("_bad_state_ex") - 1;
+ key = NULL;
}
- return zend_get_std_object_handlers()->get_method(object_ptr, method, method_len TSRMLS_CC);
+ return zend_get_std_object_handlers()->get_method(object_ptr, method, method_len, key TSRMLS_CC);
}
/* }}} */
@@ -1247,11 +1251,7 @@ SPL_METHOD(SplFileInfo, getLinkTarget)
RETURN_FALSE;
} else if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) {
char expanded_path[MAXPATHLEN];
-
- /* TODO: Fix expand_filepath to do not resolve links but only expand the path
- avoiding double two resolution attempts
- (Pierre) */
- if (!expand_filepath(intern->file_name, expanded_path TSRMLS_CC)) {
+ if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
RETURN_FALSE;
}
@@ -1431,6 +1431,7 @@ SPL_METHOD(FilesystemIterator, __construct)
SPL_METHOD(FilesystemIterator, rewind)
{
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1442,7 +1443,7 @@ SPL_METHOD(FilesystemIterator, rewind)
}
do {
spl_filesystem_dir_read(intern TSRMLS_CC);
- } while (spl_filesystem_is_dot(intern->u.dir.entry.d_name));
+ } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
}
/* }}} */
@@ -2042,7 +2043,6 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS
{
char *buf;
size_t line_len = 0;
- int len;
long line_add = (intern->u.file.current_line || intern->u.file.current_zval) ? 1 : 0;
spl_filesystem_file_free_line(intern TSRMLS_CC);
@@ -2075,11 +2075,6 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TS
buf[line_len] = '\0';
}
- if (PG(magic_quotes_runtime)) {
- buf = php_addslashes(buf, line_len, &len, 1 TSRMLS_CC);
- line_len = len;
- }
-
intern->u.file.current_line = buf;
intern->u.file.current_line_len = line_len;
}
@@ -2287,7 +2282,7 @@ SPL_METHOD(SplFileObject, __construct)
intern->u.file.open_mode = NULL;
intern->u.file.open_mode_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbr",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbr",
&intern->file_name, &intern->file_name_len,
&intern->u.file.open_mode, &intern->u.file.open_mode_len,
&use_include_path, &intern->u.file.zcontext) == FAILURE) {
@@ -2301,7 +2296,7 @@ SPL_METHOD(SplFileObject, __construct)
intern->u.file.open_mode = "r";
intern->u.file.open_mode_len = 1;
}
-
+
if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) {
tmp_path_len = strlen(intern->u.file.stream->orig_path);
@@ -2489,7 +2484,9 @@ SPL_METHOD(SplFileObject, setFlags)
{
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags);
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags) == FAILURE) {
+ return;
+ }
} /* }}} */
/* {{{ proto int SplFileObject::getFlags()
@@ -2609,6 +2606,43 @@ SPL_METHOD(SplFileObject, fgetcsv)
}
/* }}} */
+/* {{{ proto int SplFileObject::fputcsv(array fields, [string delimiter [, string enclosure]])
+ Output a field array as a CSV line */
+SPL_METHOD(SplFileObject, fputcsv)
+{
+ spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape;
+ char *delim = NULL, *enclo = NULL;
+ int d_len = 0, e_len = 0, ret;
+ zval *fields = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &fields, &delim, &d_len, &enclo, &e_len) == SUCCESS) {
+ switch(ZEND_NUM_ARGS())
+ {
+ case 3:
+ if (e_len != 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
+ RETURN_FALSE;
+ }
+ enclosure = enclo[0];
+ /* no break */
+ case 2:
+ if (d_len != 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
+ RETURN_FALSE;
+ }
+ delimiter = delim[0];
+ /* no break */
+ case 1:
+ case 0:
+ break;
+ }
+ ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape TSRMLS_CC);
+ RETURN_LONG(ret);
+ }
+}
+/* }}} */
+
/* {{{ proto void SplFileObject::setCsvControl([string delimiter = ',' [, string enclosure = '"' [, string escape = '\\']]])
Set the delimiter and enclosure character used in fgetcsv */
SPL_METHOD(SplFileObject, setCsvControl)
@@ -2790,7 +2824,6 @@ SPL_METHOD(SplFileObject, fwrite)
spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
char *str;
int str_len;
- int ret;
long length = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &length) == FAILURE) {
@@ -2804,14 +2837,6 @@ SPL_METHOD(SplFileObject, fwrite)
RETURN_LONG(0);
}
- if (PG(magic_quotes_runtime)) {
- str = estrndup(str, str_len);
- php_stripslashes(str, &str_len TSRMLS_CC);
- ret = php_stream_write(intern->u.file.stream, str, str_len);
- efree(str);
- RETURN_LONG(ret);
- }
-
RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len));
} /* }}} */
@@ -2882,6 +2907,13 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetcsv, 0, 0, 0)
ZEND_ARG_INFO(0, delimiter)
ZEND_ARG_INFO(0, enclosure)
+ ZEND_ARG_INFO(0, escape)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fputcsv, 0, 0, 1)
+ ZEND_ARG_INFO(0, fields)
+ ZEND_ARG_INFO(0, delimiter)
+ ZEND_ARG_INFO(0, enclosure)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1)
@@ -2898,7 +2930,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0)
ZEND_ARG_INFO(0, allowable_tags)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 1, 0, 1)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 1, 0, 1)
ZEND_ARG_INFO(0, format)
ZEND_END_ARG_INFO()
@@ -2922,6 +2954,7 @@ static const zend_function_entry spl_SplFileObject_functions[] = {
SPL_ME(SplFileObject, valid, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
SPL_ME(SplFileObject, fgets, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
SPL_ME(SplFileObject, fgetcsv, arginfo_file_object_fgetcsv, ZEND_ACC_PUBLIC)
+ SPL_ME(SplFileObject, fputcsv, arginfo_file_object_fputcsv, ZEND_ACC_PUBLIC)
SPL_ME(SplFileObject, setCsvControl, arginfo_file_object_fgetcsv, ZEND_ACC_PUBLIC)
SPL_ME(SplFileObject, getCsvControl, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
SPL_ME(SplFileObject, flock, arginfo_file_object_flock, ZEND_ACC_PUBLIC)
@@ -2990,6 +3023,7 @@ PHP_MINIT_FUNCTION(spl_directory)
REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "FOLLOW_SYMLINKS", SPL_FILE_DIR_FOLLOW_SYMLINKS);
REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_FILENAME", SPL_FILE_DIR_KEY_AS_FILENAME);
REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "NEW_CURRENT_AND_KEY", SPL_FILE_DIR_KEY_AS_FILENAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO);
+ REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "OTHER_MODE_MASK", SPL_FILE_DIR_OTHERS_MASK);
REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "SKIP_DOTS", SPL_FILE_DIR_SKIPDOTS);
REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "UNIX_PATHS", SPL_FILE_DIR_UNIXPATHS);
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 0774857cc3..5cc586f48a 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -27,6 +27,9 @@
#include "zend_hash.h"
#include "php_spl.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_var.h"
+#include "ext/standard/php_smart_str.h"
#include "spl_functions.h"
#include "spl_engine.h"
#include "spl_iterators.h"
@@ -367,7 +370,6 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type,
{
zend_object_value retval;
spl_dllist_object *intern;
- zval *tmp;
zend_class_entry *parent = class_type;
int inherited = 0;
@@ -376,7 +378,7 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type,
ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
intern->flags = 0;
intern->traverse_position = 0;
@@ -523,6 +525,9 @@ static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRML
INIT_PZVAL(&zrv);
Z_ARRVAL(zrv) = intern->debug_info;
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
@@ -1127,6 +1132,108 @@ SPL_METHOD(SplDoublyLinkedList, current)
}
}
/* }}} */
+/* {{{ proto string SplDoublyLinkedList::serialize()
+ Serializes storage */
+SPL_METHOD(SplDoublyLinkedList, serialize)
+{
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ smart_str buf = {0};
+ spl_ptr_llist_element *current = intern->llist->head, *next;
+ zval *flags;
+ php_serialize_data_t var_hash;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ PHP_VAR_SERIALIZE_INIT(var_hash);
+
+ /* flags */
+ MAKE_STD_ZVAL(flags);
+ ZVAL_LONG(flags, intern->flags);
+ php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC);
+ zval_ptr_dtor(&flags);
+
+ /* elements */
+ while (current) {
+ smart_str_appendc(&buf, ':');
+ next = current->next;
+
+ php_var_serialize(&buf, (zval **)&current->data, &var_hash TSRMLS_CC);
+
+ current = next;
+ }
+
+ smart_str_0(&buf);
+
+ /* done */
+ PHP_VAR_SERIALIZE_DESTROY(var_hash);
+
+ if (buf.c) {
+ RETURN_STRINGL(buf.c, buf.len, 0);
+ } else {
+ RETURN_NULL();
+ }
+
+} /* }}} */
+
+/* {{{ proto void SplDoublyLinkedList::unserialize(string serialized)
+ Unserializes storage */
+SPL_METHOD(SplDoublyLinkedList, unserialize)
+{
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ zval *flags, *elem;
+ char *buf;
+ int buf_len;
+ const unsigned char *p, *s;
+ php_unserialize_data_t var_hash;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
+ return;
+ }
+
+ if (buf_len == 0) {
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Serialized string cannot be empty");
+ return;
+ }
+
+ s = p = (const unsigned char*)buf;
+ PHP_VAR_UNSERIALIZE_INIT(var_hash);
+
+ /* flags */
+ ALLOC_INIT_ZVAL(flags);
+ if (!php_var_unserialize(&flags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(flags) != IS_LONG) {
+ zval_ptr_dtor(&flags);
+ goto error;
+ }
+ intern->flags = Z_LVAL_P(flags);
+ zval_ptr_dtor(&flags);
+
+ /* elements */
+ while(*p == ':') {
+ ++p;
+ ALLOC_INIT_ZVAL(elem);
+ if (!php_var_unserialize(&elem, &p, s + buf_len, &var_hash TSRMLS_CC)) {
+ zval_ptr_dtor(&elem);
+ goto error;
+ }
+
+ spl_ptr_llist_push(intern->llist, elem TSRMLS_CC);
+ }
+
+ if (*p != '\0') {
+ goto error;
+ }
+
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ return;
+
+error:
+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
+ return;
+
+} /* }}} */
/* iterator handler table */
zend_object_iterator_funcs spl_dllist_it_funcs = {
@@ -1188,6 +1295,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_dllist_void, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_dllist_serialized, 0)
+ ZEND_ARG_INFO(0, serialized)
+ZEND_END_ARG_INFO();
+
static const zend_function_entry spl_funcs_SplQueue[] = {
SPL_MA(SplQueue, enqueue, SplDoublyLinkedList, push, arginfo_dllist_push, ZEND_ACC_PUBLIC)
SPL_MA(SplQueue, dequeue, SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC)
@@ -1201,20 +1312,26 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
SPL_ME(SplDoublyLinkedList, unshift, arginfo_dllist_push, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, top, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, bottom, arginfo_dllist_void, ZEND_ACC_PUBLIC)
- SPL_ME(SplDoublyLinkedList, count, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, isEmpty, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void, ZEND_ACC_PUBLIC)
+ /* Countable */
+ SPL_ME(SplDoublyLinkedList, count, arginfo_dllist_void, ZEND_ACC_PUBLIC)
+ /* ArrayAccess */
SPL_ME(SplDoublyLinkedList, offsetExists, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
+ /* Iterator */
SPL_ME(SplDoublyLinkedList, rewind, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, current, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, key, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, next, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, prev, arginfo_dllist_void, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, valid, arginfo_dllist_void, ZEND_ACC_PUBLIC)
+ /* Serializable */
+ SPL_ME(SplDoublyLinkedList, unserialize, arginfo_dllist_serialized, ZEND_ACC_PUBLIC)
+ SPL_ME(SplDoublyLinkedList, serialize, arginfo_dllist_void, ZEND_ACC_PUBLIC)
PHP_FE_END
};
/* }}} */
@@ -1236,6 +1353,7 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */
REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator);
REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable);
REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess);
+ REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Serializable);
spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator;
diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c
index 0aac6d3f30..244bd3e0df 100644
--- a/ext/spl/spl_fixedarray.c
+++ b/ext/spl/spl_fixedarray.c
@@ -150,28 +150,29 @@ static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from TSRMLS_
static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */
{
spl_fixedarray_object *intern = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC);
+ HashTable *ht = zend_std_get_properties(obj TSRMLS_CC);
int i = 0;
if (intern->array && !GC_G(gc_active)) {
- int j = zend_hash_num_elements(intern->std.properties);
+ int j = zend_hash_num_elements(ht);
for (i = 0; i < intern->array->size; i++) {
if (intern->array->elements[i]) {
- zend_hash_index_update(intern->std.properties, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
+ zend_hash_index_update(ht, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
Z_ADDREF_P(intern->array->elements[i]);
} else {
- zend_hash_index_update(intern->std.properties, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
+ zend_hash_index_update(ht, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
Z_ADDREF_P(EG(uninitialized_zval_ptr));
}
}
if (j > intern->array->size) {
for (i = intern->array->size; i < j; ++i) {
- zend_hash_index_del(intern->std.properties, i);
+ zend_hash_index_del(ht, i);
}
}
}
- return intern->std.properties;
+ return ht;
}
/* }}}} */
@@ -206,7 +207,6 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty
{
zend_object_value retval;
spl_fixedarray_object *intern;
- zval *tmp;
zend_class_entry *parent = class_type;
int inherited = 0;
@@ -215,7 +215,7 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty
ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
intern->current = 0;
intern->flags = 0;
@@ -606,7 +606,6 @@ SPL_METHOD(SplFixedArray, count)
*/
SPL_METHOD(SplFixedArray, toArray)
{
- spl_fixedarray_object *intern;
zval *ret, *tmp;
HashTable *ret_ht, *obj_ht;
@@ -614,8 +613,6 @@ SPL_METHOD(SplFixedArray, toArray)
return;
}
- intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
ALLOC_HASHTABLE(ret_ht);
zend_hash_init(ret_ht, 0, NULL, ZVAL_PTR_DTOR, 0);
ALLOC_INIT_ZVAL(ret);
diff --git a/ext/spl/spl_functions.c b/ext/spl/spl_functions.c
index 3a3cdcc708..b9fd5dc8b9 100644
--- a/ext/spl/spl_functions.c
+++ b/ext/spl/spl_functions.c
@@ -103,6 +103,18 @@ void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_fl
}
/* }}} */
+/* {{{ spl_add_traits */
+void spl_add_traits(zval *list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC)
+{
+ zend_uint num_traits;
+
+ for (num_traits = 0; num_traits < pce->num_traits; num_traits++) {
+ spl_add_class_name(list, pce->traits[num_traits], allow, ce_flags TSRMLS_CC);
+ }
+}
+/* }}} */
+
+
/* {{{ spl_add_classes */
int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC)
{
diff --git a/ext/spl/spl_functions.h b/ext/spl/spl_functions.h
index 8cf98e55b3..394de6ae9d 100644
--- a/ext/spl/spl_functions.h
+++ b/ext/spl/spl_functions.h
@@ -62,6 +62,7 @@ void spl_register_property( zend_class_entry * class_entry, char *prop_name, int
*/
void spl_add_class_name(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC);
void spl_add_interfaces(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC);
+void spl_add_traits(zval * list, zend_class_entry * pce, int allow, int ce_flags TSRMLS_DC);
int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags TSRMLS_DC);
/* caller must efree(return) */
diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c
index a663422a27..c6decd0ad5 100644
--- a/ext/spl/spl_heap.c
+++ b/ext/spl/spl_heap.c
@@ -385,7 +385,6 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp
{
zend_object_value retval;
spl_heap_object *intern;
- zval *tmp;
zend_class_entry *parent = class_type;
int inherited = 0;
@@ -394,7 +393,7 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp
ALLOC_INIT_ZVAL(intern->retval);
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
intern->flags = 0;
intern->fptr_cmp = NULL;
@@ -529,6 +528,10 @@ static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zv
*is_temp = 0;
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
+
if (intern->debug_info == NULL) {
ALLOC_HASHTABLE(intern->debug_info);
ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index a46b7d4e48..098d7dc1e2 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -44,7 +44,9 @@
PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
PHPAPI zend_class_entry *spl_ce_FilterIterator;
+PHPAPI zend_class_entry *spl_ce_CallbackFilterIterator;
PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
+PHPAPI zend_class_entry *spl_ce_RecursiveCallbackFilterIterator;
PHPAPI zend_class_entry *spl_ce_ParentIterator;
PHPAPI zend_class_entry *spl_ce_SeekableIterator;
PHPAPI zend_class_entry *spl_ce_LimitIterator;
@@ -223,11 +225,12 @@ next_step:
zend_clear_exception(TSRMLS_C);
}
}
+ /* fall through */
case RS_START:
if (iterator->funcs->valid(iterator TSRMLS_CC) == FAILURE) {
break;
}
- object->iterators[object->level].state = RS_TEST;
+ object->iterators[object->level].state = RS_TEST;
/* break; */
case RS_TEST:
ce = object->iterators[object->level].ce;
@@ -839,7 +842,7 @@ SPL_METHOD(RecursiveIteratorIterator, getMaxDepth)
}
} /* }}} */
-static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char *method, int method_len TSRMLS_DC)
+static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char *method, int method_len, const zend_literal *key TSRMLS_DC)
{
union _zend_function *function_handler;
spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(*object_ptr TSRMLS_CC);
@@ -851,12 +854,12 @@ static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char
}
zobj = object->iterators[level].zobject;
- function_handler = std_object_handlers.get_method(object_ptr, method, method_len TSRMLS_CC);
+ function_handler = std_object_handlers.get_method(object_ptr, method, method_len, key TSRMLS_CC);
if (!function_handler) {
if (zend_hash_find(&Z_OBJCE_P(zobj)->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) {
if (Z_OBJ_HT_P(zobj)->get_method) {
*object_ptr = zobj;
- function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len TSRMLS_CC);
+ function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len, key TSRMLS_CC);
}
}
}
@@ -884,7 +887,7 @@ static void spl_RecursiveIteratorIterator_dtor(zend_object *_object, zend_object
}
/* }}} */
-/* {{{ spl_RecursiveIteratorIterator_dtor */
+/* {{{ spl_RecursiveIteratorIterator_free_storage */
static void spl_RecursiveIteratorIterator_free_storage(void *_object TSRMLS_DC)
{
spl_recursive_it_object *object = (spl_recursive_it_object *)_object;
@@ -906,7 +909,6 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *
{
zend_object_value retval;
spl_recursive_it_object *intern;
- zval *tmp;
intern = emalloc(sizeof(spl_recursive_it_object));
memset(intern, 0, sizeof(spl_recursive_it_object));
@@ -921,7 +923,7 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *
}
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)spl_RecursiveIteratorIterator_dtor, (zend_objects_free_object_storage_t) spl_RecursiveIteratorIterator_free_storage, NULL TSRMLS_CC);
retval.handlers = &spl_handlers_rec_it_it;
@@ -1273,19 +1275,19 @@ static int spl_dual_it_gets_implemented(zend_class_entry *interface, zend_class_
}
#endif
-static union _zend_function *spl_dual_it_get_method(zval **object_ptr, char *method, int method_len TSRMLS_DC)
+static union _zend_function *spl_dual_it_get_method(zval **object_ptr, char *method, int method_len, const zend_literal *key TSRMLS_DC)
{
union _zend_function *function_handler;
spl_dual_it_object *intern;
intern = (spl_dual_it_object*)zend_object_store_get_object(*object_ptr TSRMLS_CC);
- function_handler = std_object_handlers.get_method(object_ptr, method, method_len TSRMLS_CC);
+ function_handler = std_object_handlers.get_method(object_ptr, method, method_len, key TSRMLS_CC);
if (!function_handler && intern->inner.ce) {
if (zend_hash_find(&intern->inner.ce->function_table, method, method_len+1, (void **) &function_handler) == FAILURE) {
if (Z_OBJ_HT_P(intern->inner.zobject)->get_method) {
*object_ptr = intern->inner.zobject;
- function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len TSRMLS_CC);
+ function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len, key TSRMLS_CC);
}
} else {
*object_ptr = intern->inner.zobject;
@@ -1487,6 +1489,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
}
intern->u.regex.mode = mode;
intern->u.regex.regex = estrndup(regex, regex_len);
+ intern->u.regex.regex_len = regex_len;
intern->u.regex.pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC);
if (intern->u.regex.pce == NULL) {
/* pcre_get_compiled_regex_cache has already sent error */
@@ -1497,6 +1500,23 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
break;
}
#endif
+ case DIT_CallbackFilterIterator:
+ case DIT_RecursiveCallbackFilterIterator: {
+ _spl_cbfilter_it_intern *cfi = emalloc(sizeof(*cfi));
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) {
+ zend_restore_error_handling(&error_handling TSRMLS_CC);
+ efree(cfi);
+ return NULL;
+ }
+ if (cfi->fci.function_name) {
+ Z_ADDREF_P(cfi->fci.function_name);
+ }
+ if (cfi->fci.object_ptr) {
+ Z_ADDREF_P(cfi->fci.object_ptr);
+ }
+ intern->u.cbfilter = cfi;
+ break;
+ }
default:
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobject, ce_inner) == FAILURE) {
zend_restore_error_handling(&error_handling TSRMLS_CC);
@@ -1525,6 +1545,13 @@ SPL_METHOD(FilterIterator, __construct)
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_FilterIterator, zend_ce_iterator, DIT_FilterIterator);
} /* }}} */
+/* {{{ proto void CallbackFilterIterator::__construct(Iterator it, callback)
+ Create an Iterator from another iterator */
+SPL_METHOD(CallbackFilterIterator, __construct)
+{
+ spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_CallbackFilterIterator, zend_ce_iterator, DIT_CallbackFilterIterator);
+} /* }}} */
+
/* {{{ proto Iterator FilterIterator::getInnerIterator()
proto Iterator CachingIterator::getInnerIterator()
proto Iterator LimitIterator::getInnerIterator()
@@ -1798,6 +1825,14 @@ SPL_METHOD(FilterIterator, next)
spl_filter_it_next(getThis(), intern TSRMLS_CC);
} /* }}} */
+/* {{{ proto void RecursiveCallbackFilterIterator::__construct(RecursiveIterator it, callback)
+ Create a RecursiveCallbackFilterIterator from a RecursiveIterator */
+SPL_METHOD(RecursiveCallbackFilterIterator, __construct)
+{
+ spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveCallbackFilterIterator, spl_ce_RecursiveIterator, DIT_RecursiveCallbackFilterIterator);
+} /* }}} */
+
+
/* {{{ proto void RecursiveFilterIterator::__construct(RecursiveIterator it)
Create a RecursiveFilterIterator from a RecursiveIterator */
SPL_METHOD(RecursiveFilterIterator, __construct)
@@ -1848,6 +1883,27 @@ SPL_METHOD(RecursiveFilterIterator, getChildren)
}
} /* }}} */
+/* {{{ proto RecursiveCallbackFilterIterator RecursiveCallbackFilterIterator::getChildren()
+ Return the inner iterator's children contained in a RecursiveCallbackFilterIterator */
+SPL_METHOD(RecursiveCallbackFilterIterator, getChildren)
+{
+ spl_dual_it_object *intern;
+ zval *retval;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
+ if (!EG(exception) && retval) {
+ spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, retval, intern->u.cbfilter->fci.function_name TSRMLS_CC);
+ }
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
+} /* }}} */
/* {{{ proto void ParentIterator::__construct(RecursiveIterator it)
Create a ParentIterator from a RecursiveIterator */
SPL_METHOD(ParentIterator, __construct)
@@ -1863,6 +1919,53 @@ SPL_METHOD(RegexIterator, __construct)
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RegexIterator, zend_ce_iterator, DIT_RegexIterator);
} /* }}} */
+/* {{{ proto bool CallbackFilterIterator::accept()
+ Calls the callback with the current value, the current key and the inner iterator as arguments */
+SPL_METHOD(CallbackFilterIterator, accept)
+{
+ spl_dual_it_object *intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ zend_fcall_info *fci = &intern->u.cbfilter->fci;
+ zend_fcall_info_cache *fcc = &intern->u.cbfilter->fcc;
+ zval **params[3];
+ zval zkey;
+ zval *zkey_p = &zkey;
+ zval *result;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ if (intern->current.data == NULL) {
+ RETURN_FALSE;
+ }
+
+ INIT_PZVAL(&zkey);
+ if (intern->current.key_type == HASH_KEY_IS_LONG) {
+ ZVAL_LONG(&zkey, intern->current.int_key);
+ } else {
+ ZVAL_STRINGL(&zkey, intern->current.str_key, intern->current.str_key_len-1, 0);
+ }
+
+ params[0] = &intern->current.data;
+ params[1] = &zkey_p;
+ params[2] = &intern->inner.zobject;
+
+ fci->retval_ptr_ptr = &result;
+ fci->param_count = 3;
+ fci->params = params;
+ fci->no_separation = 0;
+
+ if (zend_call_function(fci, fcc TSRMLS_CC) != SUCCESS || !result) {
+ RETURN_FALSE;
+ }
+ if (EG(exception)) {
+ return;
+ }
+
+ RETURN_ZVAL(result, 1, 1);
+}
+/* }}} */
+
/* {{{ proto bool RegexIterator::accept()
Match (string)current() against regular expression */
SPL_METHOD(RegexIterator, accept)
@@ -1975,6 +2078,19 @@ SPL_METHOD(RegexIterator, accept)
}
} /* }}} */
+/* {{{ proto string RegexIterator::getRegex()
+ Returns current regular expression */
+SPL_METHOD(RegexIterator, getRegex)
+{
+ spl_dual_it_object *intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ RETURN_STRINGL(intern->u.regex.regex, intern->u.regex.regex_len, 1);
+} /* }}} */
+
/* {{{ proto bool RegexIterator::getMode()
Returns current operation mode */
SPL_METHOD(RegexIterator, getMode)
@@ -2133,6 +2249,7 @@ static void spl_dual_it_free_storage(void *_object TSRMLS_DC)
{
spl_dual_it_object *object = (spl_dual_it_object *)_object;
+
if (object->inner.zobject) {
zval_ptr_dtor(&object->inner.zobject);
}
@@ -2162,6 +2279,18 @@ static void spl_dual_it_free_storage(void *_object TSRMLS_DC)
}
#endif
+ if (object->dit_type == DIT_CallbackFilterIterator || object->dit_type == DIT_RecursiveCallbackFilterIterator) {
+ if (object->u.cbfilter) {
+ if (object->u.cbfilter->fci.function_name) {
+ zval_ptr_dtor(&object->u.cbfilter->fci.function_name);
+ }
+ if (object->u.cbfilter->fci.object_ptr) {
+ zval_ptr_dtor(&object->u.cbfilter->fci.object_ptr);
+ }
+ efree(object->u.cbfilter);
+ }
+ }
+
zend_object_std_dtor(&object->std TSRMLS_CC);
efree(object);
@@ -2173,14 +2302,13 @@ static zend_object_value spl_dual_it_new(zend_class_entry *class_type TSRMLS_DC)
{
zend_object_value retval;
spl_dual_it_object *intern;
- zval *tmp;
intern = emalloc(sizeof(spl_dual_it_object));
memset(intern, 0, sizeof(spl_dual_it_object));
intern->dit_type = DIT_Unknown;
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)spl_dual_it_dtor, (zend_objects_free_object_storage_t) spl_dual_it_free_storage, NULL TSRMLS_CC);
retval.handlers = &spl_handlers_dual_it;
@@ -2204,6 +2332,29 @@ static const zend_function_entry spl_funcs_FilterIterator[] = {
PHP_FE_END
};
+ZEND_BEGIN_ARG_INFO(arginfo_callback_filter_it___construct, 0)
+ ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
+ ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO();
+
+static const zend_function_entry spl_funcs_CallbackFilterIterator[] = {
+ SPL_ME(CallbackFilterIterator, __construct, arginfo_callback_filter_it___construct, ZEND_ACC_PUBLIC)
+ SPL_ME(CallbackFilterIterator, accept, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
+ZEND_BEGIN_ARG_INFO(arginfo_recursive_callback_filter_it___construct, 0)
+ ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
+ ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO();
+
+static const zend_function_entry spl_funcs_RecursiveCallbackFilterIterator[] = {
+ SPL_ME(RecursiveCallbackFilterIterator, __construct, arginfo_recursive_callback_filter_it___construct, ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
+ SPL_ME(RecursiveCallbackFilterIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
+ PHP_FE_END
+};
+
ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0)
ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
ZEND_END_ARG_INFO();
@@ -2251,6 +2402,7 @@ static const zend_function_entry spl_funcs_RegexIterator[] = {
SPL_ME(RegexIterator, setFlags, arginfo_regex_it_set_flags, ZEND_ACC_PUBLIC)
SPL_ME(RegexIterator, getPregFlags, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
SPL_ME(RegexIterator, setPregFlags, arginfo_regex_it_set_preg_flags, ZEND_ACC_PUBLIC)
+ SPL_ME(RegexIterator, getRegex, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
PHP_FE_END
};
@@ -2668,7 +2820,7 @@ SPL_METHOD(CachingIterator, offsetGet)
}
if (zend_symtable_find(HASH_OF(intern->u.caching.zcache), arKey, nKeyLength+1, (void**)&value) == FAILURE) {
- zend_error(E_NOTICE, "Undefined index: %s", arKey);
+ zend_error(E_NOTICE, "Undefined index: %s", arKey);
return;
}
@@ -3544,6 +3696,12 @@ PHP_MINIT_FUNCTION(spl_iterators)
REGISTER_SPL_SUB_CLASS_EX(RecursiveFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_RecursiveFilterIterator);
REGISTER_SPL_IMPLEMENTS(RecursiveFilterIterator, RecursiveIterator);
+ REGISTER_SPL_SUB_CLASS_EX(CallbackFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_CallbackFilterIterator);
+
+ REGISTER_SPL_SUB_CLASS_EX(RecursiveCallbackFilterIterator, CallbackFilterIterator, spl_dual_it_new, spl_funcs_RecursiveCallbackFilterIterator);
+ REGISTER_SPL_IMPLEMENTS(RecursiveCallbackFilterIterator, RecursiveIterator);
+
+
REGISTER_SPL_SUB_CLASS_EX(ParentIterator, RecursiveFilterIterator, spl_dual_it_new, spl_funcs_ParentIterator);
REGISTER_SPL_INTERFACE(Countable);
diff --git a/ext/spl/spl_iterators.h b/ext/spl/spl_iterators.h
index 525a25cc9e..4a2c999c30 100644
--- a/ext/spl/spl_iterators.h
+++ b/ext/spl/spl_iterators.h
@@ -52,6 +52,8 @@ extern PHPAPI zend_class_entry *spl_ce_AppendIterator;
extern PHPAPI zend_class_entry *spl_ce_RegexIterator;
extern PHPAPI zend_class_entry *spl_ce_RecursiveRegexIterator;
extern PHPAPI zend_class_entry *spl_ce_Countable;
+extern PHPAPI zend_class_entry *spl_ce_CallbackFilterIterator;
+extern PHPAPI zend_class_entry *spl_ce_RecursiveCallbackFilterIterator;
PHP_MINIT_FUNCTION(spl_iterators);
@@ -75,6 +77,8 @@ typedef enum {
DIT_RegexIterator,
DIT_RecursiveRegexIterator,
#endif
+ DIT_CallbackFilterIterator,
+ DIT_RecursiveCallbackFilterIterator,
DIT_Unknown = ~0
} dual_it_type;
@@ -114,6 +118,11 @@ typedef enum {
REGIT_MODE_MAX
} regex_mode;
+typedef struct _spl_cbfilter_it_intern {
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcc;
+} _spl_cbfilter_it_intern;
+
typedef struct _spl_dual_it_object {
zend_object std;
struct {
@@ -154,8 +163,10 @@ typedef struct _spl_dual_it_object {
long preg_flags;
pcre_cache_entry *pce;
char *regex;
+ uint regex_len;
} regex;
#endif
+ _spl_cbfilter_it_intern *cbfilter;
} u;
} spl_dual_it_object;
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
index 85bbeec731..4b8be82eee 100644
--- a/ext/spl/spl_observer.c
+++ b/ext/spl/spl_observer.c
@@ -84,6 +84,7 @@ typedef struct _spl_SplObjectStorage { /* {{{ */
long index;
HashPosition pos;
long flags;
+ zend_function *fptr_get_hash;
HashTable *debug_info;
} spl_SplObjectStorage; /* }}} */
@@ -109,37 +110,101 @@ void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
efree(object);
} /* }}} */
+static char *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj, int *hash_len_ptr TSRMLS_DC) {
+ if (intern->fptr_get_hash) {
+ zval *rv;
+ zend_call_method_with_1_params(&this, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, obj);
+ if (rv) {
+ if (Z_TYPE_P(rv) == IS_STRING) {
+ int hash_len = Z_STRLEN_P(rv);
+ char *hash = emalloc((hash_len+1)*sizeof(char));
+ strncpy(hash, Z_STRVAL_P(rv), hash_len);
+ hash[hash_len] = 0;
+
+ zval_ptr_dtor(&rv);
+ if (hash_len_ptr) {
+ *hash_len_ptr = hash_len;
+ }
+ return hash;
+ } else {
+ zend_throw_exception(spl_ce_RuntimeException, "Hash needs to be a string", 0 TSRMLS_CC);
+
+ zval_ptr_dtor(&rv);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ } else {
+ int hash_len = sizeof(zend_object_value);
+
+#if HAVE_PACKED_OBJECT_VALUE
+
+ if (hash_len_ptr) {
+ *hash_len_ptr = hash_len;
+ }
+
+ return (char*)&Z_OBJVAL_P(obj);
+#else
+ char *hash = emalloc(hash_len + 1);
+
+ zend_object_value zvalue;
+ memset(&zvalue, 0, sizeof(zend_object_value));
+ zvalue.handle = Z_OBJ_HANDLE_P(obj);
+ zvalue.handlers = Z_OBJ_HT_P(obj);
+
+ memcpy(hash, (char *)&zvalue, hash_len);
+ hash[hash_len] = 0;
+
+ if (hash_len_ptr) {
+ *hash_len_ptr = hash_len;
+ }
+
+ return hash;
+#endif
+ }
+}
+
+static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, char *hash) {
+ if (intern->fptr_get_hash) {
+ efree(hash);
+ } else {
+#if HAVE_PACKED_OBJECT_VALUE
+ /* Nothing to do */
+#else
+ efree(hash);
+#endif
+ }
+}
+
static void spl_object_storage_dtor(spl_SplObjectStorageElement *element) /* {{{ */
{
zval_ptr_dtor(&element->obj);
zval_ptr_dtor(&element->inf);
} /* }}} */
-
-spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
+spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, char *hash, int hash_len TSRMLS_DC) /* {{{ */
{
spl_SplObjectStorageElement *element;
- zend_object_value *pzvalue;
-#if HAVE_PACKED_OBJECT_VALUE
- pzvalue = &Z_OBJVAL_P(obj);
-#else
- zend_object_value zvalue;
- memset(&zvalue, 0, sizeof(zend_object_value));
- zvalue.handle = Z_OBJ_HANDLE_P(obj);
- zvalue.handlers = Z_OBJ_HT_P(obj);
- pzvalue = &zvalue;
-#endif
- if (zend_hash_find(&intern->storage, (char*)pzvalue, sizeof(zend_object_value), (void**)&element) == SUCCESS) {
+ if (zend_hash_find(&intern->storage, hash, hash_len, (void**)&element) == SUCCESS) {
return element;
} else {
return NULL;
}
} /* }}} */
-void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
+void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
{
spl_SplObjectStorageElement *pelement, element;
- pelement = spl_object_storage_get(intern, obj TSRMLS_CC);
+
+ int hash_len;
+ char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC);
+ if (!hash) {
+ return;
+ }
+
+ pelement = spl_object_storage_get(intern, hash, hash_len TSRMLS_CC);
+
if (inf) {
Z_ADDREF_P(inf);
} else {
@@ -148,46 +213,36 @@ void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj, zval *in
if (pelement) {
zval_ptr_dtor(&pelement->inf);
pelement->inf = inf;
+ spl_object_storage_free_hash(intern, hash);
return;
}
Z_ADDREF_P(obj);
element.obj = obj;
element.inf = inf;
-#if HAVE_PACKED_OBJECT_VALUE
- zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL);
-#else
- {
- zend_object_value zvalue;
- memset(&zvalue, 0, sizeof(zend_object_value));
- zvalue.handle = Z_OBJ_HANDLE_P(obj);
- zvalue.handlers = Z_OBJ_HT_P(obj);
- zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL);
- }
-#endif
+ zend_hash_update(&intern->storage, hash, hash_len, &element, sizeof(spl_SplObjectStorageElement), NULL);
+ spl_object_storage_free_hash(intern, hash);
} /* }}} */
-int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
+int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *obj TSRMLS_DC) /* {{{ */
{
-#if HAVE_PACKED_OBJECT_VALUE
- return zend_hash_del(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value));
-#else
- {
- zend_object_value zvalue;
- memset(&zvalue, 0, sizeof(zend_object_value));
- zvalue.handle = Z_OBJ_HANDLE_P(obj);
- zvalue.handlers = Z_OBJ_HT_P(obj);
- return zend_hash_del(&intern->storage, (char*)&zvalue, sizeof(zend_object_value));
+ int hash_len, ret = FAILURE;
+ char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC);
+ if (!hash) {
+ return ret;
}
-#endif
+ ret = zend_hash_del(&intern->storage, hash, hash_len);
+ spl_object_storage_free_hash(intern, hash);
+
+ return ret;
} /* }}}*/
-void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorage *other TSRMLS_DC) { /* {{{ */
+void spl_object_storage_addall(spl_SplObjectStorage *intern, zval *this, spl_SplObjectStorage *other TSRMLS_DC) { /* {{{ */
HashPosition pos;
spl_SplObjectStorageElement *element;
zend_hash_internal_pointer_reset_ex(&other->storage, &pos);
while (zend_hash_get_current_data_ex(&other->storage, (void **)&element, &pos) == SUCCESS) {
- spl_object_storage_attach(intern, element->obj, element->inf TSRMLS_CC);
+ spl_object_storage_attach(intern, this, element->obj, element->inf TSRMLS_CC);
zend_hash_move_forward_ex(&other->storage, &pos);
}
@@ -197,16 +252,16 @@ void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorag
static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */
{
- zend_object_value retval;
+ zend_object_value retval;
spl_SplObjectStorage *intern;
- zval *tmp;
+ zend_class_entry *parent = class_type;
intern = emalloc(sizeof(spl_SplObjectStorage));
memset(intern, 0, sizeof(spl_SplObjectStorage));
*obj = intern;
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0);
@@ -215,7 +270,21 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type,
if (orig) {
spl_SplObjectStorage *other = (spl_SplObjectStorage*)zend_object_store_get_object(orig TSRMLS_CC);
- spl_object_storage_addall(intern, other TSRMLS_CC);
+ spl_object_storage_addall(intern, orig, other TSRMLS_CC);
+ }
+
+ while (parent) {
+ if (parent == spl_ce_SplObjectStorage) {
+ if (class_type != spl_ce_SplObjectStorage) {
+ zend_hash_find(&class_type->function_table, "gethash", sizeof("gethash"), (void **) &intern->fptr_get_hash);
+ if (intern->fptr_get_hash->common.scope == spl_ce_SplObjectStorage) {
+ intern->fptr_get_hash = NULL;
+ }
+ }
+ break;
+ }
+
+ parent = parent->parent;
}
return retval;
@@ -374,19 +443,17 @@ static zend_object_value spl_SplObjectStorage_new(zend_class_entry *class_type T
}
/* }}} */
-int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
+int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *this, zval *obj TSRMLS_DC) /* {{{ */
{
-#if HAVE_PACKED_OBJECT_VALUE
- return zend_hash_exists(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value));
-#else
- {
- zend_object_value zvalue;
- memset(&zvalue, 0, sizeof(zend_object_value));
- zvalue.handle = Z_OBJ_HANDLE_P(obj);
- zvalue.handlers = Z_OBJ_HT_P(obj);
- return zend_hash_exists(&intern->storage, (char*)&zvalue, sizeof(zend_object_value));
+ int hash_len, found;
+ char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC);
+ if (!hash) {
+ return 0;
}
-#endif
+
+ found = zend_hash_exists(&intern->storage, hash, hash_len);
+ spl_object_storage_free_hash(intern, hash);
+ return found;
} /* }}} */
/* {{{ proto void SplObjectStorage::attach($obj, $inf = NULL)
@@ -400,7 +467,7 @@ SPL_METHOD(SplObjectStorage, attach)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|z!", &obj, &inf) == FAILURE) {
return;
}
- spl_object_storage_attach(intern, obj, inf TSRMLS_CC);
+ spl_object_storage_attach(intern, getThis(), obj, inf TSRMLS_CC);
} /* }}} */
/* {{{ proto void SplObjectStorage::detach($obj)
@@ -413,12 +480,30 @@ SPL_METHOD(SplObjectStorage, detach)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
return;
}
- spl_object_storage_detach(intern, obj TSRMLS_CC);
+ spl_object_storage_detach(intern, getThis(), obj TSRMLS_CC);
zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
intern->index = 0;
} /* }}} */
+/* {{{ proto string SplObjectStorage::getHash($object)
+ Returns the hash of an object */
+SPL_METHOD(SplObjectStorage, getHash)
+{
+ zval *obj;
+ char *hash;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
+ return;
+ }
+
+ hash = emalloc(33);
+ php_spl_object_hash(obj, hash TSRMLS_CC);
+
+ RETVAL_STRING(hash, 0);
+
+} /* }}} */
+
/* {{{ proto mixed SplObjectStorage::offsetGet($object)
Returns associated information for a stored object */
SPL_METHOD(SplObjectStorage, offsetGet)
@@ -426,11 +511,21 @@ SPL_METHOD(SplObjectStorage, offsetGet)
zval *obj;
spl_SplObjectStorageElement *element;
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
+ char *hash;
+ int hash_len;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
return;
}
- element = spl_object_storage_get(intern, obj TSRMLS_CC);
+
+ hash = spl_object_storage_get_hash(intern, getThis(), obj, &hash_len TSRMLS_CC);
+ if (!hash) {
+ return;
+ }
+
+ element = spl_object_storage_get(intern, hash, hash_len TSRMLS_CC);
+ spl_object_storage_free_hash(intern, hash);
+
if (!element) {
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Object not found");
} else {
@@ -452,7 +547,7 @@ SPL_METHOD(SplObjectStorage, addAll)
other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC);
- spl_object_storage_addall(intern, other TSRMLS_CC);
+ spl_object_storage_addall(intern, getThis(), other TSRMLS_CC);
RETURN_LONG(zend_hash_num_elements(&intern->storage));
} /* }}} */
@@ -474,7 +569,7 @@ SPL_METHOD(SplObjectStorage, removeAll)
zend_hash_internal_pointer_reset(&other->storage);
while (zend_hash_get_current_data(&other->storage, (void **)&element) == SUCCESS) {
- if (spl_object_storage_detach(intern, element->obj TSRMLS_CC) == FAILURE) {
+ if (spl_object_storage_detach(intern, getThis(), element->obj TSRMLS_CC) == FAILURE) {
zend_hash_move_forward(&other->storage);
}
}
@@ -502,8 +597,8 @@ SPL_METHOD(SplObjectStorage, removeAllExcept)
zend_hash_internal_pointer_reset(&intern->storage);
while (zend_hash_get_current_data(&intern->storage, (void **)&element) == SUCCESS) {
- if (!spl_object_storage_contains(other, element->obj TSRMLS_CC)) {
- spl_object_storage_detach(intern, element->obj TSRMLS_CC);
+ if (!spl_object_storage_contains(other, getThis(), element->obj TSRMLS_CC)) {
+ spl_object_storage_detach(intern, getThis(), element->obj TSRMLS_CC);
}
zend_hash_move_forward(&intern->storage);
}
@@ -525,7 +620,7 @@ SPL_METHOD(SplObjectStorage, contains)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
return;
}
- RETURN_BOOL(spl_object_storage_contains(intern, obj TSRMLS_CC));
+ RETURN_BOOL(spl_object_storage_contains(intern, getThis(), obj TSRMLS_CC));
} /* }}} */
/* {{{ proto int SplObjectStorage::count()
@@ -656,7 +751,7 @@ SPL_METHOD(SplObjectStorage, serialize)
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
spl_SplObjectStorageElement *element;
- zval members, *pmembers;
+ zval members, *pmembers, *flags;
HashPosition pos;
php_serialize_data_t var_hash;
smart_str buf = {0};
@@ -668,9 +763,11 @@ SPL_METHOD(SplObjectStorage, serialize)
PHP_VAR_SERIALIZE_INIT(var_hash);
/* storage */
- smart_str_appendl(&buf, "x:i:", 4);
- smart_str_append_long(&buf, zend_hash_num_elements(&intern->storage));
- smart_str_appendc(&buf, ';');
+ smart_str_appendl(&buf, "x:", 2);
+ MAKE_STD_ZVAL(flags);
+ ZVAL_LONG(flags, zend_hash_num_elements(&intern->storage));
+ php_var_serialize(&buf, &flags, &var_hash TSRMLS_CC);
+ zval_ptr_dtor(&flags);
zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
@@ -690,7 +787,7 @@ SPL_METHOD(SplObjectStorage, serialize)
/* members */
smart_str_appendl(&buf, "m:", 2);
INIT_PZVAL(&members);
- Z_ARRVAL(members) = intern->std.properties;
+ Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC);
Z_TYPE(members) = IS_ARRAY;
pmembers = &members;
php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
@@ -738,17 +835,17 @@ SPL_METHOD(SplObjectStorage, unserialize)
++p;
ALLOC_INIT_ZVAL(pcount);
- if (!php_var_unserialize(&pcount, &p, s + buf_len, NULL TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) {
- zval_ptr_dtor(&pcount);
+ if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) {
goto outexcept;
}
--p; /* for ';' */
count = Z_LVAL_P(pcount);
- zval_ptr_dtor(&pcount);
while(count-- > 0) {
spl_SplObjectStorageElement *pelement;
+ char *hash;
+ int hash_len;
if (*p != ';') {
goto outexcept;
@@ -774,8 +871,15 @@ SPL_METHOD(SplObjectStorage, unserialize)
goto outexcept;
}
}
-
- pelement = spl_object_storage_get(intern, pentry TSRMLS_CC);
+
+ hash = spl_object_storage_get_hash(intern, getThis(), pentry, &hash_len TSRMLS_CC);
+ if (!hash) {
+ zval_ptr_dtor(&pentry);
+ zval_ptr_dtor(&pinf);
+ goto outexcept;
+ }
+ pelement = spl_object_storage_get(intern, hash, hash_len TSRMLS_CC);
+ spl_object_storage_free_hash(intern, hash);
if(pelement) {
if(pelement->inf) {
var_push_dtor(&var_hash, &pelement->inf);
@@ -784,7 +888,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
var_push_dtor(&var_hash, &pelement->obj);
}
}
- spl_object_storage_attach(intern, pentry, pinf TSRMLS_CC);
+ spl_object_storage_attach(intern, getThis(), pentry, pinf TSRMLS_CC);
zval_ptr_dtor(&pentry);
zval_ptr_dtor(&pinf);
}
@@ -807,15 +911,23 @@ SPL_METHOD(SplObjectStorage, unserialize)
}
/* copy members */
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
zval_ptr_dtor(&pmembers);
/* done reading $serialized */
-
+ if (pcount) {
+ zval_ptr_dtor(&pcount);
+ }
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
return;
outexcept:
+ if (pcount) {
+ zval_ptr_dtor(&pcount);
+ }
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
return;
@@ -839,6 +951,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_setInfo, 0)
ZEND_ARG_INFO(0, info)
ZEND_END_ARG_INFO();
+ZEND_BEGIN_ARG_INFO(arginfo_getHash, 0)
+ ZEND_ARG_INFO(0, object)
+ZEND_END_ARG_INFO();
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1)
ZEND_ARG_INFO(0, object)
ZEND_END_ARG_INFO()
@@ -852,9 +968,10 @@ static const zend_function_entry spl_funcs_SplObjectStorage[] = {
SPL_ME(SplObjectStorage, contains, arginfo_Object, 0)
SPL_ME(SplObjectStorage, addAll, arginfo_Object, 0)
SPL_ME(SplObjectStorage, removeAll, arginfo_Object, 0)
- SPL_ME(SplObjectStorage, removeAllExcept, arginfo_Object, 0)
+ SPL_ME(SplObjectStorage, removeAllExcept, arginfo_Object, 0)
SPL_ME(SplObjectStorage, getInfo, arginfo_splobject_void,0)
SPL_ME(SplObjectStorage, setInfo, arginfo_setInfo, 0)
+ SPL_ME(SplObjectStorage, getHash, arginfo_getHash, 0)
/* Countable */
SPL_ME(SplObjectStorage, count, arginfo_splobject_void,0)
/* Iterator */
@@ -964,7 +1081,7 @@ SPL_METHOD(MultipleIterator, attachIterator)
}
}
- spl_object_storage_attach(intern, iterator, info TSRMLS_CC);
+ spl_object_storage_attach(intern, getThis(), iterator, info TSRMLS_CC);
}
/* }}} */
diff --git a/ext/spl/tests/CallbackFilterIteratorTest-002.phpt b/ext/spl/tests/CallbackFilterIteratorTest-002.phpt
new file mode 100644
index 0000000000..cbad2e3b9c
--- /dev/null
+++ b/ext/spl/tests/CallbackFilterIteratorTest-002.phpt
@@ -0,0 +1,50 @@
+--TEST--
+CallbackFilterIterator 002
+--FILE--
+<?php
+
+set_error_handler(function($errno, $errstr){
+ echo $errstr . "\n";
+ return true;
+});
+
+try {
+ new CallbackFilterIterator();
+} catch(InvalidArgumentException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+try {
+ new CallbackFilterIterator(null);
+} catch(InvalidArgumentException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+try {
+ new CallbackFilterIterator(new ArrayIterator(array()), null);
+} catch(InvalidArgumentException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+try {
+ new CallbackFilterIterator(new ArrayIterator(array()), array());
+} catch(InvalidArgumentException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+$it = new CallbackFilterIterator(new ArrayIterator(array(1)), function() {
+ throw new Exception("some message");
+});
+try {
+ foreach($it as $e);
+} catch(Exception $e) {
+ echo $e->getMessage() . "\n";
+}
+
+--EXPECT--
+CallbackFilterIterator::__construct() expects exactly 2 parameters, 0 given
+Argument 1 passed to CallbackFilterIterator::__construct() must implement interface Iterator, null given
+CallbackFilterIterator::__construct() expects exactly 2 parameters, 1 given
+CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, no array or string given
+CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, array must have exactly two members
+some message
diff --git a/ext/spl/tests/CallbackFilterIteratorTest.phpt b/ext/spl/tests/CallbackFilterIteratorTest.phpt
new file mode 100644
index 0000000000..36bc770a95
--- /dev/null
+++ b/ext/spl/tests/CallbackFilterIteratorTest.phpt
@@ -0,0 +1,133 @@
+--TEST--
+CallbackFilterIterator
+--FILE--
+<?php
+
+class A {
+ function test($value, $key, $inner) {
+ return test($value, $key, $inner);
+ }
+}
+
+class B {
+ static function test($value, $key, $inner) {
+ return test($value, $key, $inner);
+ }
+}
+
+function test($value, $key, $inner) {
+ printf("%s / %s / %d / %d\n"
+ , $value
+ , $key
+ , $value == $inner->current()
+ , $key == $inner->key()
+ );
+ return $value === 1 || $value === 4;
+}
+
+$tests = array(
+ 'instance method' => function() { return array(new A, 'test'); },
+ 'static method' => function() { return array('B', 'test'); },
+ 'static method (2)' => function() { return 'B::test'; },
+ 'function' => function() { return 'test'; },
+ 'anonymous function' => function() { return function($value, $key, $inner) { return test($value, $key, $inner); }; },
+);
+
+foreach($tests as $name => $test) {
+
+ $callback = $test();
+ $it = new ArrayIterator(range(1, 5));
+ $it = new CallbackFilterIterator($it, $callback);
+
+ echo " = $name =\n";
+
+ foreach($it as $value) {
+ echo "=> $value\n";
+ }
+
+ // same test, with no reference to callback
+
+ $it = new ArrayIterator(range(1, 5));
+ $it = new CallbackFilterIterator($it, $test());
+ unset($callback);
+
+ foreach($it as $value) {
+ echo "=> $value\n";
+ }
+}
+--EXPECT--
+= instance method =
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+ = static method =
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+ = static method (2) =
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+ = function =
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+ = anonymous function =
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 1 / 1 / 1
+3 / 2 / 1 / 1
+4 / 3 / 1 / 1
+=> 4
+5 / 4 / 1 / 1
diff --git a/ext/spl/tests/RecursiveCallbackFilterIteratorTest.phpt b/ext/spl/tests/RecursiveCallbackFilterIteratorTest.phpt
new file mode 100644
index 0000000000..f55afd8202
--- /dev/null
+++ b/ext/spl/tests/RecursiveCallbackFilterIteratorTest.phpt
@@ -0,0 +1,138 @@
+--TEST--
+RecursiveCallbackFilterIterator
+--FILE--
+<?php
+
+class A {
+ function test($value, $key, $inner) {
+ return test($value, $key, $inner);
+ }
+}
+
+class B {
+ static function test($value, $key, $inner) {
+ return test($value, $key, $inner);
+ }
+}
+
+function test($value, $key, $inner) {
+ if ($inner->hasChildren()) {
+ return true;
+ }
+ printf("%s / %s / %d / %d\n"
+ , print_r($value, true)
+ , $key
+ , $value == $inner->current()
+ , $key == $inner->key()
+ );
+ return $value === 1 || $value === 4;
+}
+
+$tests = array(
+ 'instance method' => function() { return array(new A, 'test'); },
+ 'static method' => function() { return array('B', 'test'); },
+ 'static method (2)' => function() { return 'B::test'; },
+ 'function' => function() { return 'test'; },
+ 'anonymous function' => function() { return function($value, $key, $inner) { return test($value, $key, $inner); }; },
+);
+
+foreach($tests as $name => $test) {
+
+ $callback = $test();
+ $it = new RecursiveArrayIterator(array(1, array(2, 3), array(4, 5)));
+ $it = new RecursiveCallbackFilterIterator($it, $callback);
+ $it = new RecursiveIteratorIterator($it);
+
+ echo " = $name =\n";
+
+ foreach($it as $value) {
+ echo "=> $value\n";
+ }
+
+ // same test, with no reference to callback
+
+ $it = new RecursiveArrayIterator(array(1, array(2, 3), array(4, 5)));
+ $it = new RecursiveCallbackFilterIterator($it, $test());
+ $it = new RecursiveIteratorIterator($it);
+ unset($callback);
+
+ foreach($it as $value) {
+ echo "=> $value\n";
+ }
+}
+--EXPECT--
+= instance method =
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+ = static method =
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+ = static method (2) =
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+ = function =
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+ = anonymous function =
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
+1 / 0 / 1 / 1
+=> 1
+2 / 0 / 1 / 1
+3 / 1 / 1 / 1
+4 / 0 / 1 / 1
+=> 4
+5 / 1 / 1 / 1
diff --git a/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt b/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt
new file mode 100644
index 0000000000..f0b2b0182c
--- /dev/null
+++ b/ext/spl/tests/RecursiveDirectoryIterator_getSubPath_basic.phpt
@@ -0,0 +1,50 @@
+--TEST--
+RecursiveDirectoryIterator::getBasePath() - basic test
+--CREDITS--
+Pawel Krynicki <pawel [dot] krynicki [at] xsolve [dot] pl>
+#testfest AmsterdamPHP 2012-06-23
+--FILE--
+<?php
+$depth0 = "depth0";
+$depth1 = 'depth1';
+$depth2 = 'depth2';
+$targetDir = __DIR__ . DIRECTORY_SEPARATOR . $depth0 . DIRECTORY_SEPARATOR . $depth1 . DIRECTORY_SEPARATOR . $depth2;
+mkdir($targetDir, 0777, true);
+touch($targetDir . DIRECTORY_SEPARATOR . 'getSubPath_test.tmp');
+$iterator = new RecursiveDirectoryIterator(__DIR__ . DIRECTORY_SEPARATOR . $depth0);
+$it = new RecursiveIteratorIterator($iterator);
+
+$list = [];
+while($it->valid()) {
+ $list[] = $it->getSubPath();
+ $it->next();
+}
+asort($list);
+foreach ($list as $item) {
+ echo $item . "\n";
+}
+?>
+--CLEAN--
+<?php
+function rrmdir($dir) {
+ foreach(glob($dir . '/*') as $file) {
+ if(is_dir($file)) {
+ rrmdir($file);
+ } else {
+ unlink($file);
+ }
+ }
+
+ rmdir($dir);
+}
+
+$targetDir = __DIR__.DIRECTORY_SEPARATOR . "depth0";
+rrmdir($targetDir);
+?>
+
+--EXPECTF--
+depth1
+depth1
+depth1%cdepth2
+depth1%cdepth2
+depth1%cdepth2
diff --git a/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt b/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt
new file mode 100644
index 0000000000..7b12672e14
--- /dev/null
+++ b/ext/spl/tests/RecursiveDirectoryIterator_getSubPathname_basic.phpt
@@ -0,0 +1,56 @@
+--TEST--
+RecursiveDirectoryIterator::getBasePathname() - basic test
+--CREDITS--
+Pawel Krynicki <pawel [dot] krynicki [at] xsolve [dot] pl>
+#testfest AmsterdamPHP 2012-06-23
+--FILE--
+<?php
+$depth0 = "depth0";
+$depth1 = "depth1";
+$depth2 = "depth2";
+$targetDir = __DIR__ . DIRECTORY_SEPARATOR . $depth0 . DIRECTORY_SEPARATOR . $depth1 . DIRECTORY_SEPARATOR . $depth2;
+mkdir($targetDir, 0777, true);
+touch($targetDir . DIRECTORY_SEPARATOR . 'getSubPathname_test_2.tmp');
+touch(__DIR__ . DIRECTORY_SEPARATOR . $depth0 . DIRECTORY_SEPARATOR . $depth1 . DIRECTORY_SEPARATOR . 'getSubPathname_test_3.tmp');
+touch(__DIR__ . DIRECTORY_SEPARATOR . $depth0 . DIRECTORY_SEPARATOR . 'getSubPathname_test_1.tmp');
+$iterator = new RecursiveDirectoryIterator(__DIR__ . DIRECTORY_SEPARATOR . $depth0);
+$it = new RecursiveIteratorIterator($iterator);
+
+$list = [];
+$it->rewind(); //see https://bugs.php.net/bug.php?id=62914
+while($it->valid()) {
+ $list[] = $it->getSubPathname();
+ $it->next();
+}
+asort($list);
+foreach ($list as $item) {
+ echo $item . "\n";
+}
+?>
+--CLEAN--
+<?php
+function rrmdir($dir) {
+ foreach(glob($dir . '/*') as $file) {
+ if(is_dir($file)) {
+ rrmdir($file);
+ } else {
+ unlink($file);
+ }
+ }
+
+ rmdir($dir);
+}
+
+$targetDir = __DIR__ . DIRECTORY_SEPARATOR . "depth0";
+rrmdir($targetDir);
+?>
+--EXPECTF--
+.
+..
+depth1%c.
+depth1%c..
+depth1%cdepth2%c.
+depth1%cdepth2%c..
+depth1%cdepth2%cgetSubPathname_test_2.tmp
+depth1%cgetSubPathname_test_3.tmp
+getSubPathname_test_1.tmp
diff --git a/ext/spl/tests/SplDoublyLinkedList_serialization.phpt b/ext/spl/tests/SplDoublyLinkedList_serialization.phpt
new file mode 100644
index 0000000000..7ab7d78174
--- /dev/null
+++ b/ext/spl/tests/SplDoublyLinkedList_serialization.phpt
@@ -0,0 +1,67 @@
+--TEST--
+Check Serialization/unserialization
+--FILE--
+<?php
+$q = new SplQueue();
+
+$q->enqueue("a");
+$q->enqueue("b");
+
+var_dump($q, $ss = serialize($q), unserialize($ss));
+
+$s = new SplStack();
+
+$s->push("a");
+$s->push("b");
+
+var_dump($s, $ss = serialize($s), unserialize($ss));
+?>
+==END==
+--EXPECTF--
+object(SplQueue)#%d (2) {
+ ["flags":"SplDoublyLinkedList":private]=>
+ int(4)
+ ["dllist":"SplDoublyLinkedList":private]=>
+ array(2) {
+ [0]=>
+ string(1) "a"
+ [1]=>
+ string(1) "b"
+ }
+}
+string(42) "C:8:"SplQueue":22:{i:4;:s:1:"a";:s:1:"b";}"
+object(SplQueue)#%d (2) {
+ ["flags":"SplDoublyLinkedList":private]=>
+ int(4)
+ ["dllist":"SplDoublyLinkedList":private]=>
+ array(2) {
+ [0]=>
+ string(1) "a"
+ [1]=>
+ string(1) "b"
+ }
+}
+object(SplStack)#%d (2) {
+ ["flags":"SplDoublyLinkedList":private]=>
+ int(6)
+ ["dllist":"SplDoublyLinkedList":private]=>
+ array(2) {
+ [0]=>
+ string(1) "a"
+ [1]=>
+ string(1) "b"
+ }
+}
+string(42) "C:8:"SplStack":22:{i:6;:s:1:"a";:s:1:"b";}"
+object(SplStack)#%d (2) {
+ ["flags":"SplDoublyLinkedList":private]=>
+ int(6)
+ ["dllist":"SplDoublyLinkedList":private]=>
+ array(2) {
+ [0]=>
+ string(1) "a"
+ [1]=>
+ string(1) "b"
+ }
+}
+==END==
diff --git a/ext/spl/tests/SplFileObject_current_basic.phpt b/ext/spl/tests/SplFileObject_current_basic.phpt
new file mode 100644
index 0000000000..d3f4802a53
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_current_basic.phpt
@@ -0,0 +1,18 @@
+--TEST--
+SPL: SplFileObject::current basic
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+echo $s->current();
+
+?>
+--EXPECT--
+<?php
diff --git a/ext/spl/tests/SplFileObject_current_error001.phpt b/ext/spl/tests/SplFileObject_current_error001.phpt
new file mode 100644
index 0000000000..23c126648f
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_current_error001.phpt
@@ -0,0 +1,19 @@
+--TEST--
+SPL: SplFileObject::current variation error
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+$s->seek(2);
+
+echo $s->current('foo');
+?>
+--EXPECTF--
+Warning: SplFileObject::current() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/SplFileObject_current_variation001.phpt b/ext/spl/tests/SplFileObject_current_variation001.phpt
new file mode 100644
index 0000000000..0cc588a7f0
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_current_variation001.phpt
@@ -0,0 +1,21 @@
+--TEST--
+SPL: SplFileObject::current variation
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+$s->seek(2);
+
+echo $s->current();
+echo $s->current();
+?>
+--EXPECT--
+//line 3
+//line 3
diff --git a/ext/spl/tests/SplFileObject_fputcsv.phpt b/ext/spl/tests/SplFileObject_fputcsv.phpt
new file mode 100644
index 0000000000..66fdbfd1b9
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv.phpt
@@ -0,0 +1,106 @@
+--TEST--
+SplFileObject::fputcsv(): functionality tests
+--FILE--
+<?php
+$file = __DIR__ . '/SplFileObject_fputcsv.csv';
+$fo = new SplFileObject($file, 'w');
+
+$list = array (
+ 0 => 'aaa,bbb',
+ 1 => 'aaa,"bbb"',
+ 2 => '"aaa","bbb"',
+ 3 => 'aaa,bbb',
+ 4 => '"aaa",bbb',
+ 5 => '"aaa", "bbb"',
+ 6 => ',',
+ 7 => 'aaa,',
+ 8 => ',"aaa"',
+ 9 => '"",""',
+ 10 => '"""""",',
+ 11 => '""""",aaa',
+ 12 => 'aaa,bbb ',
+ 13 => 'aaa,"bbb "',
+ 14 => 'aaa"aaa","bbb"bbb',
+ 15 => 'aaa"aaa""",bbb',
+ 16 => 'aaa,"\\"bbb,ccc',
+ 17 => 'aaa"\\"a","bbb"',
+ 18 => '"\\"","aaa"',
+ 19 => '"\\""",aaa',
+);
+
+foreach ($list as $v) {
+ $fo->fputcsv(explode(',', $v));
+}
+unset($fo);
+
+$res = file($file);
+foreach($res as &$val)
+{
+ $val = substr($val, 0, -1);
+}
+echo '$list = ';var_export($res);echo ";\n";
+
+$fp = fopen($file, "r");
+$res = array();
+while($l=fgetcsv($fp))
+{
+ $res[] = join(',',$l);
+}
+fclose($fp);
+
+echo '$list = ';var_export($res);echo ";\n";
+
+?>
+===DONE===
+<?php exit(0); ?>
+--CLEAN--
+<?php
+$file = __DIR__ . '/SplFileObject_fputcsv.csv';
+unlink($file);
+?>
+--EXPECT--
+$list = array (
+ 0 => 'aaa,bbb',
+ 1 => 'aaa,"""bbb"""',
+ 2 => '"""aaa""","""bbb"""',
+ 3 => 'aaa,bbb',
+ 4 => '"""aaa""",bbb',
+ 5 => '"""aaa"""," ""bbb"""',
+ 6 => ',',
+ 7 => 'aaa,',
+ 8 => ',"""aaa"""',
+ 9 => '"""""",""""""',
+ 10 => '"""""""""""""",',
+ 11 => '"""""""""""",aaa',
+ 12 => 'aaa,"bbb "',
+ 13 => 'aaa,"""bbb """',
+ 14 => '"aaa""aaa""","""bbb""bbb"',
+ 15 => '"aaa""aaa""""""",bbb',
+ 16 => 'aaa,"""\\"bbb",ccc',
+ 17 => '"aaa""\\"a""","""bbb"""',
+ 18 => '"""\\"""","""aaa"""',
+ 19 => '"""\\"""""",aaa',
+);
+$list = array (
+ 0 => 'aaa,bbb',
+ 1 => 'aaa,"bbb"',
+ 2 => '"aaa","bbb"',
+ 3 => 'aaa,bbb',
+ 4 => '"aaa",bbb',
+ 5 => '"aaa", "bbb"',
+ 6 => ',',
+ 7 => 'aaa,',
+ 8 => ',"aaa"',
+ 9 => '"",""',
+ 10 => '"""""",',
+ 11 => '""""",aaa',
+ 12 => 'aaa,bbb ',
+ 13 => 'aaa,"bbb "',
+ 14 => 'aaa"aaa","bbb"bbb',
+ 15 => 'aaa"aaa""",bbb',
+ 16 => 'aaa,"\\"bbb,ccc',
+ 17 => 'aaa"\\"a","bbb"',
+ 18 => '"\\"","aaa"',
+ 19 => '"\\""",aaa',
+);
+===DONE===
diff --git a/ext/spl/tests/SplFileObject_fputcsv_002.phpt b/ext/spl/tests/SplFileObject_fputcsv_002.phpt
new file mode 100644
index 0000000000..db174931f7
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_002.phpt
@@ -0,0 +1,42 @@
+--TEST--
+SplFileObject::fputcsv(): Checking data after calling the function
+--FILE--
+<?php
+$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv.csv', 'w');
+
+$data = array(1, 2, 'foo', 'haha', array(4, 5, 6), 1.3, null);
+
+$fo->fputcsv($data);
+
+var_dump($data);
+?>
+--CLEAN--
+<?php
+$file = __DIR__ . '/SplFileObject_fputcsv.csv';
+unlink($file);
+?>
+--EXPECTF--
+Notice: Array to string conversion in %s on line %d
+array(7) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ string(3) "foo"
+ [3]=>
+ string(4) "haha"
+ [4]=>
+ array(3) {
+ [0]=>
+ int(4)
+ [1]=>
+ int(5)
+ [2]=>
+ int(6)
+ }
+ [5]=>
+ float(1.3)
+ [6]=>
+ NULL
+}
diff --git a/ext/spl/tests/SplFileObject_fputcsv_error.phpt b/ext/spl/tests/SplFileObject_fputcsv_error.phpt
new file mode 100644
index 0000000000..8368e4211d
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_error.phpt
@@ -0,0 +1,35 @@
+--TEST--
+SplFileObject::fputcsv(): error conditions
+--FILE--
+<?php
+$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv.csv', 'w');
+
+echo "*** Testing error conditions ***\n";
+// zero argument
+echo "-- Testing fputcsv() with zero argument --\n";
+var_dump( $fo->fputcsv() );
+
+// more than expected no. of args
+echo "-- Testing fputcsv() with more than expected number of arguments --\n";
+$fields = array("fld1", "fld2");
+$delim = ";";
+$enclosure ="\"";
+var_dump( $fo->fputcsv($fields, $delim, $enclosure, $fo) );
+
+echo "Done\n";
+--CLEAN--
+<?php
+$file = __DIR__ . '/SplFileObject_fputcsv.csv';
+unlink($file);
+?>
+--EXPECTF--
+*** Testing error conditions ***
+-- Testing fputcsv() with zero argument --
+
+Warning: SplFileObject::fputcsv() expects at least 1 parameter, 0 given in %s on line %d
+NULL
+-- Testing fputcsv() with more than expected number of arguments --
+
+Warning: SplFileObject::fputcsv() expects at most 3 parameters, 4 given in %s on line %d
+NULL
+Done
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation1.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation1.phpt
new file mode 100644
index 0000000000..6780b242dd
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation1.phpt
@@ -0,0 +1,826 @@
+--TEST--
+Test fputcsv() : usage variations - with all parameters specified
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when all its parameters are provided */
+
+echo "*** Testing fputcsv() : with all parameters specified ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water','fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation1.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+
+ var_dump( $fo->fputcsv($csv_field, $delimiter, $enclosure) );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with all parameters specified ***
+
+-- file opened in r+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in a+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in w+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in x+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in r+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in r+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in r+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in a+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in a+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in a+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in w+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in w+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in w+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in x+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in x+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in x+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in r+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in r+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in r+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in a+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in a+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in a+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in w+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in w+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in w+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in x+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in x+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in x+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation10.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation10.phpt
new file mode 100644
index 0000000000..08a2461b4d
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation10.phpt
@@ -0,0 +1,327 @@
+--TEST--
+SplFileObject::fputcsv(): Usage variations -- with line without any CSV fields
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when the field has no CSV format */
+
+echo "*** Testing fputcsv() : with no CSV format in the field ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+
+$fields = array( array('water_fruit\n'),
+ array("water_fruit\n"),
+ array("")
+ );
+
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation10.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($fields as $field) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $csv_field = $field;
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field) );
+
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with no CSV format in the field ***
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water_fruit\n"
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water_fruit\n"
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water_fruit\n"
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water_fruit\n"
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water_fruit\n"
+"
+
+-- file opened in r+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in r+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in r+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water_fruit
+"
+"
+
+-- file opened in a+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in a+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in a+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water_fruit
+"
+"
+
+-- file opened in w+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in w+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in w+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water_fruit
+"
+"
+
+-- file opened in x+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in x+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water_fruit
+"
+"
+
+-- file opened in x+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water_fruit
+"
+"
+
+-- file opened in r+ --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in r+b --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in r+t --
+int(1)
+int(1)
+bool(false)
+string(%d) "
+"
+
+-- file opened in a+ --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in a+b --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in a+t --
+int(1)
+int(1)
+bool(false)
+string(%d) "
+"
+
+-- file opened in w+ --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in w+b --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in w+t --
+int(1)
+int(1)
+bool(false)
+string(%d) "
+"
+
+-- file opened in x+ --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in x+b --
+int(1)
+int(1)
+bool(false)
+string(1) "
+"
+
+-- file opened in x+t --
+int(1)
+int(1)
+bool(false)
+string(%d) "
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation11.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation11.phpt
new file mode 100644
index 0000000000..c85dd0a8cd
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation11.phpt
@@ -0,0 +1,826 @@
+--TEST--
+SplFileObject::fputcsv(): Usage variations -- with default enclosure value
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when default enclosure value is provided */
+
+echo "*** Testing fputcsv() : with default enclosure value ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water,fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation11.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field, $delimiter) );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with default enclosure value ***
+
+-- file opened in r+ --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in r+b --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in r+t --
+int(14)
+int(14)
+bool(false)
+string(%d) ""water,fruit"
+"
+
+-- file opened in a+ --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in a+b --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in a+t --
+int(14)
+int(14)
+bool(false)
+string(%d) ""water,fruit"
+"
+
+-- file opened in w+ --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in w+b --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in w+t --
+int(14)
+int(14)
+bool(false)
+string(%d) ""water,fruit"
+"
+
+-- file opened in x+ --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in x+b --
+int(14)
+int(14)
+bool(false)
+string(14) ""water,fruit"
+"
+
+-- file opened in x+t --
+int(14)
+int(14)
+bool(false)
+string(%d) ""water,fruit"
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""&water&:&fruit&"
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""&water&:&fruit&"
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""&water&:&fruit&"
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""&water&:&fruit&"
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""&water&:&fruit&"
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""=water===fruit="
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""=water===fruit="
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""=water===fruit="
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""=water===fruit="
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""=water===fruit="
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) ""-water--fruit-air"
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) ""-water--fruit-air"
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) ""-water--fruit-air"
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) ""-water--fruit-air"
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) ""-water--fruit-air"
+"
+
+-- file opened in r+ --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in r+b --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in r+t --
+int(24)
+int(24)
+bool(false)
+string(%d) ""-water---fruit---air-"
+"
+
+-- file opened in a+ --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in a+b --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in a+t --
+int(24)
+int(24)
+bool(false)
+string(%d) ""-water---fruit---air-"
+"
+
+-- file opened in w+ --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in w+b --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in w+t --
+int(24)
+int(24)
+bool(false)
+string(%d) ""-water---fruit---air-"
+"
+
+-- file opened in x+ --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in x+b --
+int(24)
+int(24)
+bool(false)
+string(24) ""-water---fruit---air-"
+"
+
+-- file opened in x+t --
+int(24)
+int(24)
+bool(false)
+string(%d) ""-water---fruit---air-"
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation12.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation12.phpt
new file mode 100644
index 0000000000..8bb47d3371
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation12.phpt
@@ -0,0 +1,827 @@
+--TEST--
+SplFileObject::fputcsv(): Usage variations -- with default enclosure and different delimiter
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when default enclosure value and delimiter value
+ other than that in the field is provided */
+
+echo "*** Testing fputcsv() : with default enclosure and different delimiter value ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water,fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation12.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field, '+') );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with default enclosure and different delimiter value ***
+
+-- file opened in r+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in a+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in w+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in x+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation13.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation13.phpt
new file mode 100644
index 0000000000..b7c2a6381d
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation13.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Test fputcsv() : usage variations - with default enclosure & delimiter of two chars
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when default enclosure value and delimiter
+ of two chars is provided */
+
+echo "*** Testing fputcsv() : with default enclosure & delimiter of two chars ***\n";
+
+$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv.csv', 'w');
+
+var_dump($fo->fputcsv(array('water', 'fruit'), ',,', '"'));
+
+unset($fo);
+
+echo "Done\n";
+?>
+--CLEAN--
+<?php
+$file = __DIR__ . '/SplFileObject_fputcsv.csv';
+unlink($file);
+?>
+--EXPECTF--
+*** Testing fputcsv() : with default enclosure & delimiter of two chars ***
+
+Warning: SplFileObject::fputcsv(): delimiter must be a character in %s on line %d
+bool(false)
+Done
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation14.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation14.phpt
new file mode 100644
index 0000000000..f8cda0e96f
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation14.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Test fputcsv() : usage variations - with enclosure & delimiter of two chars
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when default enclosure value and delimiter
+ of two chars is provided and file is opened in read only mode */
+
+echo "*** Testing fputcsv() : with enclosure & delimiter of two chars and file opened in read mode ***\n";
+
+$fo = new SplFileObject(__DIR__ . '/SplFileObject_fputcsv.csv', 'w');
+
+var_dump($fo->fputcsv(array('water', 'fruit'), ',,', '""'));
+
+unset($fo);
+
+echo "Done\n";
+?>
+--CLEAN--
+<?php
+$file = __DIR__ . '/SplFileObject_fputcsv.csv';
+unlink($file);
+?>
+--EXPECTF--
+*** Testing fputcsv() : with enclosure & delimiter of two chars and file opened in read mode ***
+
+Warning: SplFileObject::fputcsv(): enclosure must be a character in %s on line %d
+bool(false)
+Done
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation5.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation5.phpt
new file mode 100644
index 0000000000..9c4c01f54f
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation5.phpt
@@ -0,0 +1,826 @@
+--TEST--
+Test fputcsv() : usage variations - with default arguments value
+--FILE--
+<?php
+
+/* Testing fputcsv() to write to a file when default arguments values are considered */
+
+echo "*** Testing fputcsv() : with default arguments value ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water','fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation5.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field) );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with default arguments value ***
+
+-- file opened in r+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in a+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in w+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in x+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) ""^water^ ^fruit^"
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) ""^water^ ^fruit^"
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) ""&""""""""&:&""&:,:"":&,&:,,,,"
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation6.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation6.phpt
new file mode 100644
index 0000000000..6cbb880aaf
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation6.phpt
@@ -0,0 +1,829 @@
+--TEST--
+Test fputcsv() : usage variations - with different delimiter and enclosure
+--FILE--
+<?php
+
+/*
+ Testing fputcsv() to write to a file when delimiter are different from those
+ present in the field to be written to the file
+ */
+
+echo "*** Testing fputcsv() : with different delimiter and enclosure ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water,fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation6.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field, '+', '%') );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with different delimiter and enclosure ***
+
+-- file opened in r+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in r+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in a+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in a+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in w+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in w+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in x+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water,fruit
+"
+
+-- file opened in x+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water,fruit
+"
+
+-- file opened in r+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in r+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in r+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water","fruit
+"
+
+-- file opened in a+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in a+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in a+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water","fruit
+"
+
+-- file opened in w+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in w+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in w+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water","fruit
+"
+
+-- file opened in x+ --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in x+b --
+int(15)
+int(15)
+bool(false)
+string(15) ""water","fruit
+"
+
+-- file opened in x+t --
+int(15)
+int(15)
+bool(false)
+string(%d) ""water","fruit
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water","fruit"
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water","fruit"
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water","fruit"
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) ""water","fruit"
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) ""water","fruit"
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "%^water^ ^fruit^%
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "%^water^ ^fruit^%
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "%^water^ ^fruit^%
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "%^water^ ^fruit^%
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "%^water^ ^fruit^%
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) "&water&:&fruit&
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "&water&:&fruit&
+"
+
+-- file opened in r+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in r+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in r+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in a+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in a+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in a+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in w+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in w+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in w+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in x+ --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in x+b --
+int(16)
+int(16)
+bool(false)
+string(16) "=water===fruit=
+"
+
+-- file opened in x+t --
+int(16)
+int(16)
+bool(false)
+string(%d) "=water===fruit=
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "-water--fruit-air
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "-water--fruit-air
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "-water---fruit---air-
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "-water---fruit---air-
+"
+
+-- file opened in r+ --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in r+b --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in r+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in a+ --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in a+b --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in a+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in w+ --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in w+b --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in w+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in x+ --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in x+b --
+int(24)
+int(24)
+bool(false)
+string(24) "&""""&:&"&:,:":&,&:,,,,
+"
+
+-- file opened in x+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "&""""&:&"&:,:":&,&:,,,,
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation7.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation7.phpt
new file mode 100644
index 0000000000..ceb438a9f1
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation7.phpt
@@ -0,0 +1,829 @@
+--TEST--
+Test fputcsv() : usage variations - with different delimiter and same enclosure
+--FILE--
+<?php
+
+/*
+ Testing fputcsv() to write to a file when enclosure is same but delimiter is different from those
+ present in the field to be written to the file
+ */
+
+echo "*** Testing fputcsv() : with different delimiter and same enclosure ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water','fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation7.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field, '+', $enclosure) );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with different delimiter and same enclosure ***
+
+-- file opened in r+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in r+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in r+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water+fruit
+"
+
+-- file opened in a+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in a+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in a+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water+fruit
+"
+
+-- file opened in w+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in w+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in w+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water+fruit
+"
+
+-- file opened in x+ --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in x+b --
+int(12)
+int(12)
+bool(false)
+string(12) "water+fruit
+"
+
+-- file opened in x+t --
+int(12)
+int(12)
+bool(false)
+string(%d) "water+fruit
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) """"water"",""fruit"
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) """"water"",""fruit"
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) """"water"",""fruit"""
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) """"water"",""fruit"""
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "^^^water^^ ^^fruit^^^
+"
+
+-- file opened in r+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in r+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in r+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in a+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in a+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in a+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in w+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in w+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in w+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in x+ --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in x+b --
+int(22)
+int(22)
+bool(false)
+string(22) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in x+t --
+int(22)
+int(22)
+bool(false)
+string(%d) "&&&water&&:&&fruit&&&
+"
+
+-- file opened in r+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in r+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in r+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in a+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in a+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in a+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in w+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in w+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in w+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in x+ --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in x+b --
+int(23)
+int(23)
+bool(false)
+string(23) "===water======fruit===
+"
+
+-- file opened in x+t --
+int(23)
+int(23)
+bool(false)
+string(%d) "===water======fruit===
+"
+
+-- file opened in r+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in r+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in r+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in a+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in a+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in a+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in w+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in w+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in w+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in x+ --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in x+b --
+int(24)
+int(24)
+bool(false)
+string(24) "---water----fruit--air-
+"
+
+-- file opened in x+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "---water----fruit--air-
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) "---water------fruit------air---
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "---water------fruit------air---
+"
+
+-- file opened in r+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in r+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in r+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in a+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in a+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in a+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in w+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in w+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in w+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in x+ --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in x+b --
+int(32)
+int(32)
+bool(false)
+string(32) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+
+-- file opened in x+t --
+int(32)
+int(32)
+bool(false)
+string(%d) "&&&""""&&:&&"&&:,:":&&,&&:,,,,&
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fputcsv_variation8.phpt b/ext/spl/tests/SplFileObject_fputcsv_variation8.phpt
new file mode 100644
index 0000000000..f1a8cbf7b1
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_fputcsv_variation8.phpt
@@ -0,0 +1,829 @@
+--TEST--
+Test fputcsv() : usage variations - with same delimiter and different enclosure
+--FILE--
+<?php
+
+/*
+ Testing fputcsv() to write to a file when delimiter is same but enclosure is different from those
+ present in the field to be written to the file
+ */
+
+echo "*** Testing fputcsv() : with same delimiter and different enclosure ***\n";
+
+/* the array is with three elements in it. Each element should be read as
+ 1st element is delimiter, 2nd element is enclosure
+ and 3rd element is csv fields
+*/
+$csv_lists = array (
+ array(',', '"', array('water,fruit') ),
+ array(',', '"', array('"water","fruit') ),
+ array(',', '"', array('"water","fruit"') ),
+ array(' ', '^', array('^water^ ^fruit^')),
+ array(':', '&', array('&water&:&fruit&')),
+ array('=', '=', array('=water===fruit=')),
+ array('-', '-', array('-water--fruit-air')),
+ array('-', '-', array('-water---fruit---air-')),
+ array(':', '&', array('&""""&:&"&:,:":&,&:,,,,'))
+
+);
+$file_path = dirname(__FILE__);
+$file = "$file_path/fputcsv_variation8.tmp";
+
+$file_modes = array ("r+", "r+b", "r+t",
+ "a+", "a+b", "a+t",
+ "w+", "w+b", "w+t",
+ "x+", "x+b", "x+t");
+
+$loop_counter = 1;
+foreach ($csv_lists as $csv_list) {
+ for($mode_counter = 0; $mode_counter < count($file_modes); $mode_counter++) {
+
+ echo "\n-- file opened in $file_modes[$mode_counter] --\n";
+ // create the file and add the content with has csv fields
+ if ( strstr($file_modes[$mode_counter], "r") ) {
+ $fo = new SplFileObject($file, 'w');
+ } else {
+ $fo = new SplFileObject($file, $file_modes[$mode_counter]);
+ }
+ $delimiter = $csv_list[0];
+ $enclosure = $csv_list[1];
+ $csv_field = $csv_list[2];
+
+ // write to a file in csv format
+ var_dump( $fo->fputcsv($csv_field, $delimiter, '+') );
+ // check the file pointer position and eof
+ var_dump( $fo->ftell() );
+ var_dump( $fo->eof() );
+ //close the file
+ unset($fo);
+
+ // print the file contents
+ var_dump( file_get_contents($file) );
+
+ //delete file
+ unlink($file);
+ } //end of mode loop
+} // end of foreach
+
+echo "Done\n";
+?>
+--EXPECTF--
+*** Testing fputcsv() : with same delimiter and different enclosure ***
+
+-- file opened in r+ --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in r+b --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in r+t --
+int(14)
+int(14)
+bool(false)
+string(%d) "+water,fruit+
+"
+
+-- file opened in a+ --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in a+b --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in a+t --
+int(14)
+int(14)
+bool(false)
+string(%d) "+water,fruit+
+"
+
+-- file opened in w+ --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in w+b --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in w+t --
+int(14)
+int(14)
+bool(false)
+string(%d) "+water,fruit+
+"
+
+-- file opened in x+ --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in x+b --
+int(14)
+int(14)
+bool(false)
+string(14) "+water,fruit+
+"
+
+-- file opened in x+t --
+int(14)
+int(14)
+bool(false)
+string(%d) "+water,fruit+
+"
+
+-- file opened in r+ --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in r+b --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in r+t --
+int(17)
+int(17)
+bool(false)
+string(%d) "+"water","fruit+
+"
+
+-- file opened in a+ --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in a+b --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in a+t --
+int(17)
+int(17)
+bool(false)
+string(%d) "+"water","fruit+
+"
+
+-- file opened in w+ --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in w+b --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in w+t --
+int(17)
+int(17)
+bool(false)
+string(%d) "+"water","fruit+
+"
+
+-- file opened in x+ --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in x+b --
+int(17)
+int(17)
+bool(false)
+string(17) "+"water","fruit+
+"
+
+-- file opened in x+t --
+int(17)
+int(17)
+bool(false)
+string(%d) "+"water","fruit+
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+"water","fruit"+
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+"water","fruit"+
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+"water","fruit"+
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+"water","fruit"+
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+"water","fruit"+
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+^water^ ^fruit^+
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+^water^ ^fruit^+
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+^water^ ^fruit^+
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+^water^ ^fruit^+
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+^water^ ^fruit^+
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+&water&:&fruit&+
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+&water&:&fruit&+
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+&water&:&fruit&+
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+&water&:&fruit&+
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+&water&:&fruit&+
+"
+
+-- file opened in r+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in r+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in r+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+=water===fruit=+
+"
+
+-- file opened in a+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in a+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in a+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+=water===fruit=+
+"
+
+-- file opened in w+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in w+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in w+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+=water===fruit=+
+"
+
+-- file opened in x+ --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in x+b --
+int(18)
+int(18)
+bool(false)
+string(18) "+=water===fruit=+
+"
+
+-- file opened in x+t --
+int(18)
+int(18)
+bool(false)
+string(%d) "+=water===fruit=+
+"
+
+-- file opened in r+ --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in r+b --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in r+t --
+int(20)
+int(20)
+bool(false)
+string(%d) "+-water--fruit-air+
+"
+
+-- file opened in a+ --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in a+b --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in a+t --
+int(20)
+int(20)
+bool(false)
+string(%d) "+-water--fruit-air+
+"
+
+-- file opened in w+ --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in w+b --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in w+t --
+int(20)
+int(20)
+bool(false)
+string(%d) "+-water--fruit-air+
+"
+
+-- file opened in x+ --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in x+b --
+int(20)
+int(20)
+bool(false)
+string(20) "+-water--fruit-air+
+"
+
+-- file opened in x+t --
+int(20)
+int(20)
+bool(false)
+string(%d) "+-water--fruit-air+
+"
+
+-- file opened in r+ --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in r+b --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in r+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "+-water---fruit---air-+
+"
+
+-- file opened in a+ --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in a+b --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in a+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "+-water---fruit---air-+
+"
+
+-- file opened in w+ --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in w+b --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in w+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "+-water---fruit---air-+
+"
+
+-- file opened in x+ --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in x+b --
+int(24)
+int(24)
+bool(false)
+string(24) "+-water---fruit---air-+
+"
+
+-- file opened in x+t --
+int(24)
+int(24)
+bool(false)
+string(%d) "+-water---fruit---air-+
+"
+
+-- file opened in r+ --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in r+b --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in r+t --
+int(26)
+int(26)
+bool(false)
+string(%d) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in a+ --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in a+b --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in a+t --
+int(26)
+int(26)
+bool(false)
+string(%d) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in w+ --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in w+b --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in w+t --
+int(26)
+int(26)
+bool(false)
+string(%d) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in x+ --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in x+b --
+int(26)
+int(26)
+bool(false)
+string(26) "+&""""&:&"&:,:":&,&:,,,,+
+"
+
+-- file opened in x+t --
+int(26)
+int(26)
+bool(false)
+string(%d) "+&""""&:&"&:,:":&,&:,,,,+
+"
+Done
+
diff --git a/ext/spl/tests/SplFileObject_fwrite_variation_003.phpt b/ext/spl/tests/SplFileObject_fwrite_variation_003.phpt
deleted file mode 100644
index 429d2a66bc..0000000000
--- a/ext/spl/tests/SplFileObject_fwrite_variation_003.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-SplFileObject::fwrite function - writing with magic_quotes_runtime ini set
---FILE--
-<?php
-ini_set('magic_quotes_runtime',true);
-$file = dirname(__FILE__).'/SplFileObject_fwrite_variation_002.txt';
-if(file_exists($file)) {
- unlink($file);
-}
-$obj = New SplFileObject($file,'w');
-$obj->fwrite('"test" \'write\'');
-var_dump(file_get_contents($file));
-?>
---CLEAN--
-<?php
-$file = dirname(__FILE__).'/SplFileObject_fwrite_variation_002.txt';
-if(file_exists($file)) {
- unlink($file);
-}
-?>
---EXPECT--
-string(18) "\"test\" \'write\'"
diff --git a/ext/spl/tests/SplFileObject_getchildren_basic.phpt b/ext/spl/tests/SplFileObject_getchildren_basic.phpt
new file mode 100644
index 0000000000..065e8eae45
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_getchildren_basic.phpt
@@ -0,0 +1,12 @@
+--TEST--
+SPL: SplFileObject::getchildren basic
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+var_dump($s->getChildren());
+
+?>
+--EXPECT--
+NULL
diff --git a/ext/spl/tests/SplFileObject_getchildren_error001.phpt b/ext/spl/tests/SplFileObject_getchildren_error001.phpt
new file mode 100644
index 0000000000..9c17a82977
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_getchildren_error001.phpt
@@ -0,0 +1,12 @@
+--TEST--
+SPL: SplFileObject::getchildren error 001
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+$s->getChildren('string');
+
+?>
+--EXPECTF--
+Warning: SplFileObject::getChildren() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/SplFileObject_getflags_basic.phpt b/ext/spl/tests/SplFileObject_getflags_basic.phpt
new file mode 100644
index 0000000000..5addadf380
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_getflags_basic.phpt
@@ -0,0 +1,22 @@
+--TEST--
+SPL: SplFileObject::getFlags basic
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+
+file_put_contents('testdata.csv', 'eerste;tweede;derde');
+
+$fo = new SplFileObject('testdata.csv');
+
+$fo->setFlags(SplFileObject::DROP_NEW_LINE);
+var_dump($fo->getFlags());
+?>
+--CLEAN--
+<?php
+unlink('testdata.csv');
+?>
+--EXPECT--
+int(1)
diff --git a/ext/spl/tests/SplFileObject_getflags_error001.phpt b/ext/spl/tests/SplFileObject_getflags_error001.phpt
new file mode 100644
index 0000000000..1602f88885
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_getflags_error001.phpt
@@ -0,0 +1,26 @@
+--TEST--
+SPL: SplFileObject::getFlags error 001
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+
+file_put_contents('testdata.csv', 'eerste;tweede;derde');
+
+
+$fo = new SplFileObject('testdata.csv');
+$fo->setFlags(SplFileObject::READ_CSV);
+
+$fo->setFlags(SplFileObject::DROP_NEW_LINE);
+
+var_dump($fo->getFlags());
+
+?>
+--CLEAN--
+<?php
+unlink('testdata.csv');
+?>
+--EXPECT--
+int(1)
diff --git a/ext/spl/tests/SplFileObject_getflags_error002.phpt b/ext/spl/tests/SplFileObject_getflags_error002.phpt
new file mode 100644
index 0000000000..e2c8255f44
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_getflags_error002.phpt
@@ -0,0 +1,21 @@
+--TEST--
+SPL: SplFileObject::getFlags error 001
+--CREDITS--
+Erwin Poeze <erwin.poeze@gmail.com>
+--FILE--
+<?php
+
+file_put_contents('testdata.csv', 'eerste;tweede;derde');
+
+$fo = new SplFileObject('testdata.csv');
+$fo->setFlags(SplFileObject::READ_CSV);
+
+$fo->getFlags('fake');
+
+?>
+--CLEAN--
+<?php
+unlink('testdata.csv');
+?>
+--EXPECTF--
+Warning: SplFileObject::getFlags() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/SplFileObject_getflags_variation001.phpt b/ext/spl/tests/SplFileObject_getflags_variation001.phpt
new file mode 100644
index 0000000000..640de03511
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_getflags_variation001.phpt
@@ -0,0 +1,29 @@
+--TEST--
+SPL: SplFileObject::getFlags
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+
+$fo = new SplFileObject(__FILE__);
+
+$fo->setFlags(SplFileObject::DROP_NEW_LINE);
+var_dump($fo->getFlags());
+
+$fo->setFlags(SplFileObject::READ_AHEAD);
+var_dump($fo->getFlags());
+
+$fo->setFlags(SplFileObject::SKIP_EMPTY);
+var_dump($fo->getFlags());
+
+$fo->setFlags(SplFileObject::READ_CSV);
+var_dump($fo->getFlags());
+
+?>
+--EXPECT--
+int(1)
+int(2)
+int(4)
+int(8)
diff --git a/ext/spl/tests/SplFileObject_haschildren_basic.phpt b/ext/spl/tests/SplFileObject_haschildren_basic.phpt
new file mode 100644
index 0000000000..1ce00bfd42
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_haschildren_basic.phpt
@@ -0,0 +1,12 @@
+--TEST--
+SPL: SplFileObject::haschildren basic
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+var_dump($s->hasChildren());
+
+?>
+--EXPECT--
+bool(false)
diff --git a/ext/spl/tests/SplFileObject_haschildren_error001.phpt b/ext/spl/tests/SplFileObject_haschildren_error001.phpt
new file mode 100644
index 0000000000..0c4e1de3b7
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_haschildren_error001.phpt
@@ -0,0 +1,12 @@
+--TEST--
+SPL: SplFileObject::haschildren error 001
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+$s->hasChildren('string');
+
+?>
+--EXPECTF--
+Warning: SplFileObject::hasChildren() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/SplFileObject_key_basic.phpt b/ext/spl/tests/SplFileObject_key_basic.phpt
new file mode 100644
index 0000000000..4081d314ea
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_key_basic.phpt
@@ -0,0 +1,19 @@
+--TEST--
+SPL: SplFileObject::key basic
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(3);
+echo $s->key();
+?>
+--EXPECT--
+3
diff --git a/ext/spl/tests/SplFileObject_key_error001.phpt b/ext/spl/tests/SplFileObject_key_error001.phpt
new file mode 100644
index 0000000000..b0834f0029
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_key_error001.phpt
@@ -0,0 +1,22 @@
+--TEST--
+SPL: SplFileObject::key error
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(12);
+$s->next();
+var_dump($s->key());
+var_dump($s->valid());
+?>
+--EXPECT--
+int(13)
+bool(false)
diff --git a/ext/spl/tests/SplFileObject_key_error002.phpt b/ext/spl/tests/SplFileObject_key_error002.phpt
new file mode 100644
index 0000000000..8fc9b7fef0
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_key_error002.phpt
@@ -0,0 +1,22 @@
+--TEST--
+SPL: SplFileObject::key error
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(120);
+$s->next();
+var_dump($s->key());
+var_dump($s->valid());
+?>
+--EXPECT--
+int(13)
+bool(false)
diff --git a/ext/spl/tests/SplFileObject_key_error003.phpt b/ext/spl/tests/SplFileObject_key_error003.phpt
new file mode 100644
index 0000000000..7568cf55f4
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_key_error003.phpt
@@ -0,0 +1,15 @@
+--TEST--
+SPL: SplFileObject::key error
+--CREDITS--
+Erwin Poeze <erwin.poeze AT gmail.com>
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+$s->key(3);
+?>
+--EXPECTF--
+Warning: SplFileObject::key() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/SplFileObject_next_basic.phpt b/ext/spl/tests/SplFileObject_next_basic.phpt
new file mode 100644
index 0000000000..59dc7ab58d
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_next_basic.phpt
@@ -0,0 +1,22 @@
+--TEST--
+SPL: SplFileObject::next basic
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+echo $s->current();
+$s->next();
+
+echo $s->current();
+
+?>
+--EXPECT--
+<?php
+//line 2
diff --git a/ext/spl/tests/SplFileObject_next_variation001.phpt b/ext/spl/tests/SplFileObject_next_variation001.phpt
new file mode 100644
index 0000000000..34771dd523
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_next_variation001.phpt
@@ -0,0 +1,24 @@
+--TEST--
+SPL: SplFileObject::next variation 001
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(13);
+echo $s->current();
+
+$s->next();
+echo $s->current();
+var_dump($s->valid());
+?>
+--EXPECT--
+?>
+bool(false)
diff --git a/ext/spl/tests/SplFileObject_next_variation002.phpt b/ext/spl/tests/SplFileObject_next_variation002.phpt
new file mode 100644
index 0000000000..d48ff8c223
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_next_variation002.phpt
@@ -0,0 +1,30 @@
+--TEST--
+SPL: SplFileObject::next variation 002, read ahead
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+$s->seek(2);
+echo $s->current();
+$s->next();
+echo $s->current();
+
+$s->setFlags(SplFileObject::READ_AHEAD);
+
+$s->seek(2);
+echo $s->current();
+$s->next();
+echo $s->current();
+?>
+--EXPECT--
+//line 3
+//line 4
+//line 3
+//line 4
diff --git a/ext/spl/tests/SplFileObject_rewind_basic.phpt b/ext/spl/tests/SplFileObject_rewind_basic.phpt
new file mode 100644
index 0000000000..331c587e4a
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_rewind_basic.phpt
@@ -0,0 +1,21 @@
+--TEST--
+SPL: SplFileObject::rewind basic
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(3);
+
+$s->rewind();
+echo $s->current();
+?>
+--EXPECT--
+<?php
diff --git a/ext/spl/tests/SplFileObject_rewind_error001.phpt b/ext/spl/tests/SplFileObject_rewind_error001.phpt
new file mode 100644
index 0000000000..bdb3301e63
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_rewind_error001.phpt
@@ -0,0 +1,18 @@
+--TEST--
+SPL: SplFileObject::rewind() with a parameter.
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+
+file_put_contents('testdata.csv', 'eerste;tweede;derde');
+
+$fo = new SplFileObject('testdata.csv');
+
+$fo->rewind( "invalid" );
+
+?>
+--EXPECTF--
+Warning: SplFileObject::rewind() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/SplFileObject_rewind_variation001.phpt b/ext/spl/tests/SplFileObject_rewind_variation001.phpt
new file mode 100644
index 0000000000..d835c443de
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_rewind_variation001.phpt
@@ -0,0 +1,28 @@
+--TEST--
+SPL: SplFileObject::rewind variation 001
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(15);
+echo $s->current();
+$s->next();
+echo $s->current();
+var_dump($s->valid());
+$s->rewind();
+var_dump($s->valid());
+echo $s->current();
+?>
+--EXPECT--
+?>
+bool(false)
+bool(true)
+<?php
diff --git a/ext/spl/tests/SplFileObject_seek_basic.phpt b/ext/spl/tests/SplFileObject_seek_basic.phpt
new file mode 100644
index 0000000000..7106f70cce
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_seek_basic.phpt
@@ -0,0 +1,19 @@
+--TEST--
+SPL: SplFileObject::seek basic
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(2);
+echo $s->current();
+?>
+--EXPECT--
+//line 3
diff --git a/ext/spl/tests/SplFileObject_seek_error002.phpt b/ext/spl/tests/SplFileObject_seek_error002.phpt
new file mode 100644
index 0000000000..057c8d3251
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_seek_error002.phpt
@@ -0,0 +1,18 @@
+--TEST--
+SPL: SplFileObject::seek error 001
+--CREDITS--
+Ricardo Oedietram <ricardo@odracir.nl>
+Erwin Poeze <erwin.poeze@gmail.com>
+#PFZ June PHP TestFest 2012
+--FILE--
+<?php
+//line 2
+//line 3
+//line 4
+//line 5
+$s = new SplFileObject(__FILE__);
+
+$s->seek(20);
+echo $s->current();
+?>
+--EXPECT--
diff --git a/ext/spl/tests/SplFileObject_setCsvControl_basic.phpt b/ext/spl/tests/SplFileObject_setCsvControl_basic.phpt
new file mode 100644
index 0000000000..b2630606e8
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_setCsvControl_basic.phpt
@@ -0,0 +1,30 @@
+--TEST--
+SPL: SplFileObject::setCsvControl basic
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+file_put_contents('csv_control_data.csv',
+<<<CDATA
+'groene appelen'|10
+'gele bananen'|20
+'rode kersen'|30
+CDATA
+);
+$s = new SplFileObject('csv_control_data.csv');
+$s->setFlags(SplFileObject::READ_CSV);
+$s->setCsvControl('|', '\'', '/');
+foreach ($s as $row) {
+ list($fruit, $quantity) = $row;
+ echo "$fruit : $quantity\n";
+}
+?>
+--CLEAN--
+<?php
+unlink('csv_control_data.csv');
+?>
+--EXPECT--
+groene appelen : 10
+gele bananen : 20
+rode kersen : 30
+
diff --git a/ext/spl/tests/SplFileObject_setCsvControl_error001.phpt b/ext/spl/tests/SplFileObject_setCsvControl_error001.phpt
new file mode 100644
index 0000000000..f582a4a894
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_setCsvControl_error001.phpt
@@ -0,0 +1,24 @@
+--TEST--
+SPL: SplFileObject::setCsvControl error 001
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+file_put_contents('csv_control_data.csv',
+<<<CDATA
+'groene appelen'|10
+'gele bananen'|20
+'rode kersen'|30
+CDATA
+);
+$s = new SplFileObject('csv_control_data.csv');
+$s->setFlags(SplFileObject::READ_CSV);
+$s->setCsvControl('||');
+?>
+--CLEAN--
+<?php
+unlink('csv_control_data.csv');
+?>
+--EXPECTF--
+Warning: SplFileObject::setCsvControl(): delimiter must be a character in %s on line %d
+
diff --git a/ext/spl/tests/SplFileObject_setCsvControl_error002.phpt b/ext/spl/tests/SplFileObject_setCsvControl_error002.phpt
new file mode 100644
index 0000000000..bcfd9c4dd6
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_setCsvControl_error002.phpt
@@ -0,0 +1,24 @@
+--TEST--
+SPL: SplFileObject::setCsvControl error 002
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+file_put_contents('csv_control_data.csv',
+<<<CDATA
+'groene appelen'|10
+'gele bananen'|20
+'rode kersen'|30
+CDATA
+);
+$s = new SplFileObject('csv_control_data.csv');
+$s->setFlags(SplFileObject::READ_CSV);
+$s->setCsvControl('|', 'two');
+?>
+--CLEAN--
+<?php
+unlink('csv_control_data.csv');
+?>
+--EXPECTF--
+Warning: SplFileObject::setCsvControl(): enclosure must be a character in %s on line %d
+
diff --git a/ext/spl/tests/SplFileObject_setCsvControl_error003.phpt b/ext/spl/tests/SplFileObject_setCsvControl_error003.phpt
new file mode 100644
index 0000000000..8b1f54d5a4
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_setCsvControl_error003.phpt
@@ -0,0 +1,26 @@
+--TEST--
+SPL: SplFileObject::setCsvControl error 003
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--INI--
+include_path=.
+--FILE--
+<?php
+file_put_contents('csv_control_data.csv',
+<<<CDATA
+'groene appelen'|10
+'gele bananen'|20
+'rode kersen'|30
+CDATA
+);
+$s = new SplFileObject('csv_control_data.csv');
+$s->setFlags(SplFileObject::READ_CSV);
+$s->setCsvControl('|', '\'', 'three');
+?>
+--CLEAN--
+<?php
+unlink('csv_control_data.csv');
+?>
+--EXPECTF--
+Warning: SplFileObject::setCsvControl(): escape must be a character in %s on line %d
+
diff --git a/ext/spl/tests/SplFileObject_setCsvControl_variation001.phpt b/ext/spl/tests/SplFileObject_setCsvControl_variation001.phpt
new file mode 100644
index 0000000000..7aaf8a3fe6
--- /dev/null
+++ b/ext/spl/tests/SplFileObject_setCsvControl_variation001.phpt
@@ -0,0 +1,30 @@
+--TEST--
+SPL: SplFileObject::setCsvControl variation 001
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+file_put_contents('csv_control_data.csv',
+<<<CDATA
+"groene appelen",10
+"gele bananen",20
+"rode kersen",30
+CDATA
+);
+$s = new SplFileObject('csv_control_data.csv');
+$s->setFlags(SplFileObject::READ_CSV);
+$s->setCsvControl();
+foreach ($s as $row) {
+ list($fruit, $quantity) = $row;
+ echo "$fruit : $quantity\n";
+}
+?>
+--CLEAN--
+<?php
+unlink('csv_control_data.csv');
+?>
+--EXPECT--
+groene appelen : 10
+gele bananen : 20
+rode kersen : 30
+
diff --git a/ext/spl/tests/SplObjectStorage_getHash.phpt b/ext/spl/tests/SplObjectStorage_getHash.phpt
new file mode 100644
index 0000000000..f309b3d84f
--- /dev/null
+++ b/ext/spl/tests/SplObjectStorage_getHash.phpt
@@ -0,0 +1,60 @@
+--TEST--
+SplObjectStorage::getHash implementation
+--FILE--
+<?php
+$s = new SplObjectStorage();
+$o1 = new Stdclass;
+$o2 = new Stdclass;
+$s[$o1] = "some_value\n";
+echo $s->offsetGet($o1);
+
+class MySplObjectStorage extends SplObjectStorage {
+ public function getHash($obj) {
+ return 2;
+ }
+}
+
+try {
+ $s1 = new MySplObjectStorage;
+ $s1[$o1] = "foo";
+} catch(Exception $e) {
+ echo "caught\n";
+}
+
+class MySplObjectStorage2 extends SplObjectStorage {
+ public function getHash($obj) {
+ throw new Exception("foo");
+ return "asd";
+ }
+}
+
+try {
+ $s2 = new MySplObjectStorage2;
+ $s2[$o2] = "foo";
+} catch(Exception $e) {
+ echo "caught\n";
+}
+
+class MySplObjectStorage3 extends SplObjectStorage {
+ public function getHash($obj) {
+ return "asd";
+ }
+}
+
+$s3 = new MySplObjectStorage3;
+$s3[$o1] = $o1;
+var_dump($s3[$o1]);
+$s3[$o2] = $o2;
+
+var_dump($s3[$o1] === $s3[$o2]);
+
+?>
+===DONE===
+--EXPECT--
+some_value
+caught
+caught
+object(stdClass)#2 (0) {
+}
+bool(true)
+===DONE===
diff --git a/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt b/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
index 9e3f3605b7..a525317093 100644
--- a/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
+++ b/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
@@ -5,8 +5,8 @@ SPL: Test that serialized blob contains unique elements (CVE-2010-2225)
$badblobs = array(
'x:i:2;i:0;,i:1;;i:0;,i:2;;m:a:0:{}',
-'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};R:1;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
-'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};r:1;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
+'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};R:2;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
+'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};r:2;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
);
foreach($badblobs as $blob) {
try {
@@ -37,7 +37,7 @@ object(SplObjectStorage)#2 (1) {
object(stdClass)#1 (0) {
}
["inf"]=>
- object(stdClass)#4 (0) {
+ object(stdClass)#3 (0) {
}
}
}
diff --git a/ext/spl/tests/SplObjectStorage_unserialize_nested.phpt b/ext/spl/tests/SplObjectStorage_unserialize_nested.phpt
index 56e83f805d..e96a82a7a1 100644
--- a/ext/spl/tests/SplObjectStorage_unserialize_nested.phpt
+++ b/ext/spl/tests/SplObjectStorage_unserialize_nested.phpt
@@ -19,7 +19,7 @@ $so1 = unserialize($s);
var_dump($so1);
--EXPECTF--
-C:16:"SplObjectStorage":76:{x:i:2;O:8:"stdClass":1:{s:1:"a";O:8:"stdClass":0:{}},i:1;;r:2;,i:2;;m:a:0:{}}
+C:16:"SplObjectStorage":76:{x:i:2;O:8:"stdClass":1:{s:1:"a";O:8:"stdClass":0:{}},i:1;;r:4;,i:2;;m:a:0:{}}
object(SplObjectStorage)#4 (1) {
["storage":"SplObjectStorage":private]=>
array(2) {
diff --git a/ext/spl/tests/arrayObject___construct_basic2.phpt b/ext/spl/tests/arrayObject___construct_basic2.phpt
index 9ff0e4257a..bd27c42774 100644
--- a/ext/spl/tests/arrayObject___construct_basic2.phpt
+++ b/ext/spl/tests/arrayObject___construct_basic2.phpt
@@ -63,7 +63,7 @@ bool(true)
Notice: Undefined property: ArrayObject::$prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
@@ -91,7 +91,7 @@ bool(true)
Notice: Undefined property: MyArrayObject::$prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
diff --git a/ext/spl/tests/arrayObject___construct_basic3.phpt b/ext/spl/tests/arrayObject___construct_basic3.phpt
index 1abd1a1ab1..11a17a6dc4 100644
--- a/ext/spl/tests/arrayObject___construct_basic3.phpt
+++ b/ext/spl/tests/arrayObject___construct_basic3.phpt
@@ -63,7 +63,7 @@ bool(true)
Notice: Undefined property: ArrayObject::$prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
@@ -91,7 +91,7 @@ bool(true)
Notice: Undefined property: MyArrayObject::$prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
diff --git a/ext/spl/tests/arrayObject___construct_basic4.phpt b/ext/spl/tests/arrayObject___construct_basic4.phpt
index 80f5e0861e..b0809de0d4 100644
--- a/ext/spl/tests/arrayObject___construct_basic4.phpt
+++ b/ext/spl/tests/arrayObject___construct_basic4.phpt
@@ -61,11 +61,11 @@ bool(true)
bool(true)
- Unset:
-Notice: Undefined index: prop in %s on line 39
+Notice: Undefined index: prop in %s on line 39
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
@@ -91,9 +91,9 @@ bool(true)
bool(true)
- Unset:
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
diff --git a/ext/spl/tests/arrayObject___construct_basic5.phpt b/ext/spl/tests/arrayObject___construct_basic5.phpt
index 5368d250a1..8c44ee2ce4 100644
--- a/ext/spl/tests/arrayObject___construct_basic5.phpt
+++ b/ext/spl/tests/arrayObject___construct_basic5.phpt
@@ -61,11 +61,11 @@ bool(true)
bool(true)
- Unset:
-Notice: Undefined index: prop in %s on line 39
+Notice: Undefined index: prop in %s on line 39
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
@@ -91,9 +91,9 @@ bool(true)
bool(true)
- Unset:
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
-Notice: Undefined index: prop in %s on line 40
+Notice: Undefined index: prop in %s on line 40
NULL
NULL
- After:
diff --git a/ext/spl/tests/arrayObject_asort_basic1.phpt b/ext/spl/tests/arrayObject_asort_basic1.phpt
index ec69049a32..53df1d502b 100644
--- a/ext/spl/tests/arrayObject_asort_basic1.phpt
+++ b/ext/spl/tests/arrayObject_asort_basic1.phpt
@@ -17,12 +17,14 @@ var_dump($ao1->asort());
var_dump($ao1);
var_dump($ao2->asort('blah'));
var_dump($ao2);
+var_dump($ao2->asort(SORT_NUMERIC));
+var_dump($ao2);
?>
===DONE===
--EXPECTF--
*** Testing ArrayObject::asort() : basic functionality ***
bool(true)
-object(ArrayObject)#1 (1) {
+object(ArrayObject)#%d (1) {
["storage":"ArrayObject":private]=>
array(3) {
[1]=>
@@ -33,8 +35,22 @@ object(ArrayObject)#1 (1) {
int(4)
}
}
+
+Warning: asort() expects parameter 2 to be long, string given in %sarrayObject_asort_basic1.php on line %d
+bool(false)
+object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ ["a"]=>
+ int(4)
+ ["b"]=>
+ int(2)
+ ["c"]=>
+ int(3)
+ }
+}
bool(true)
-object(ArrayObject)#2 (1) {
+object(ArrayObject)#%d (1) {
["storage":"ArrayObject":private]=>
array(3) {
["b"]=>
diff --git a/ext/spl/tests/arrayObject_ksort_basic1.phpt b/ext/spl/tests/arrayObject_ksort_basic1.phpt
index 9c8d1e7345..8f37938126 100644
--- a/ext/spl/tests/arrayObject_ksort_basic1.phpt
+++ b/ext/spl/tests/arrayObject_ksort_basic1.phpt
@@ -16,12 +16,14 @@ var_dump($ao1->ksort());
var_dump($ao1);
var_dump($ao2->ksort('blah'));
var_dump($ao2);
+var_dump($ao2->ksort(SORT_STRING));
+var_dump($ao2);
?>
===DONE===
--EXPECTF--
*** Testing ArrayObject::ksort() : basic functionality ***
bool(true)
-object(ArrayObject)#1 (1) {
+object(ArrayObject)#%d (1) {
["storage":"ArrayObject":private]=>
array(3) {
[0]=>
@@ -32,18 +34,34 @@ object(ArrayObject)#1 (1) {
int(3)
}
}
-bool(true)
+
+Warning: ksort() expects parameter 2 to be long, string given in %sarrayObject_ksort_basic1.php on line %d
+bool(false)
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(4) {
- ["a"]=>
- int(2)
["b"]=>
int(4)
+ ["a"]=>
+ int(2)
["q"]=>
int(3)
[99]=>
string(1) "x"
}
}
+bool(true)
+object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ array(4) {
+ [99]=>
+ string(1) "x"
+ ["a"]=>
+ int(2)
+ ["b"]=>
+ int(4)
+ ["q"]=>
+ int(3)
+ }
+}
===DONE===
diff --git a/ext/spl/tests/arrayObject_magicMethods1.phpt b/ext/spl/tests/arrayObject_magicMethods1.phpt
index b1de4a951e..ec4812f107 100644
--- a/ext/spl/tests/arrayObject_magicMethods1.phpt
+++ b/ext/spl/tests/arrayObject_magicMethods1.phpt
@@ -102,7 +102,7 @@ object(ArrayObject)#2 (1) {
--> Read existent, non-existent and dynamic:
string(7) "changed"
-Notice: Undefined index: nonexistent in %s on line 42
+Notice: Undefined index: nonexistent in %s on line 42
NULL
string(11) "new.changed"
Original wrapped object:
@@ -171,7 +171,7 @@ object(ArrayObject)#2 (1) {
--> Unset existent, non-existent and dynamic:
-Notice: Undefined index: nonexistent in %s on line 60
+Notice: Undefined index: nonexistent in %s on line 60
Original wrapped object:
object(UsesMagic)#1 (3) {
["b"]=>
diff --git a/ext/spl/tests/arrayObject_magicMethods3.phpt b/ext/spl/tests/arrayObject_magicMethods3.phpt
index 16a6a3b80c..6231ceabb7 100644
--- a/ext/spl/tests/arrayObject_magicMethods3.phpt
+++ b/ext/spl/tests/arrayObject_magicMethods3.phpt
@@ -102,7 +102,7 @@ object(ArrayObject)#2 (1) {
--> Read existent, non-existent and dynamic:
string(7) "changed"
-Notice: Undefined index: nonexistent in %s on line 42
+Notice: Undefined index: nonexistent in %s on line 42
NULL
string(11) "new.changed"
Original wrapped object:
@@ -171,7 +171,7 @@ object(ArrayObject)#2 (1) {
--> Unset existent, non-existent and dynamic:
-Notice: Undefined index: nonexistent in %s on line 60
+Notice: Undefined index: nonexistent in %s on line 60
Original wrapped object:
object(UsesMagic)#1 (3) {
["b"]=>
diff --git a/ext/spl/tests/arrayObject_magicMethods4.phpt b/ext/spl/tests/arrayObject_magicMethods4.phpt
index 3c9f78781a..9580dc5ae7 100644
--- a/ext/spl/tests/arrayObject_magicMethods4.phpt
+++ b/ext/spl/tests/arrayObject_magicMethods4.phpt
@@ -107,7 +107,7 @@ object(UsesMagic)#2 (2) {
--> Read existent, non-existent and dynamic:
string(7) "changed"
-Notice: Undefined index: nonexistent in %s on line 45
+Notice: Undefined index: nonexistent in %s on line 45
NULL
string(11) "new.changed"
Original wrapped object:
@@ -180,7 +180,7 @@ object(UsesMagic)#2 (2) {
--> Unset existent, non-existent and dynamic:
-Notice: Undefined index: nonexistent in %s on line 63
+Notice: Undefined index: nonexistent in %s on line 63
Original wrapped object:
object(C)#1 (3) {
["b"]=>
diff --git a/ext/spl/tests/arrayObject_magicMethods6.phpt b/ext/spl/tests/arrayObject_magicMethods6.phpt
index 45a0e4a768..b43f56c2b0 100644
--- a/ext/spl/tests/arrayObject_magicMethods6.phpt
+++ b/ext/spl/tests/arrayObject_magicMethods6.phpt
@@ -107,7 +107,7 @@ object(UsesMagic)#2 (2) {
--> Read existent, non-existent and dynamic:
string(7) "changed"
-Notice: Undefined index: nonexistent in %s on line 45
+Notice: Undefined index: nonexistent in %s on line 45
NULL
string(11) "new.changed"
Original wrapped object:
@@ -180,7 +180,7 @@ object(UsesMagic)#2 (2) {
--> Unset existent, non-existent and dynamic:
-Notice: Undefined index: nonexistent in %s on line 63
+Notice: Undefined index: nonexistent in %s on line 63
Original wrapped object:
object(C)#1 (3) {
["b"]=>
diff --git a/ext/spl/tests/arrayObject_setFlags_basic1.phpt b/ext/spl/tests/arrayObject_setFlags_basic1.phpt
index d8d4f2e96d..391b0eeae7 100644
--- a/ext/spl/tests/arrayObject_setFlags_basic1.phpt
+++ b/ext/spl/tests/arrayObject_setFlags_basic1.phpt
@@ -44,8 +44,8 @@ string(21) "array element.changed"
--> Remove the array element and try access again:
bool(false)
-Notice: Undefined index: p in %s on line 10
+Notice: Undefined index: p in %s on line 10
NULL
-Notice: Undefined index: p in %s on line 12
+Notice: Undefined index: p in %s on line 12
string(8) ".changed"
diff --git a/ext/spl/tests/array_001.phpt b/ext/spl/tests/array_001.phpt
index d9fb57c4ce..b55fcba1fd 100644
--- a/ext/spl/tests/array_001.phpt
+++ b/ext/spl/tests/array_001.phpt
@@ -79,15 +79,15 @@ object(ArrayObject)#%d (1) {
}
int(0)
-Notice: Undefined offset: 6 in %sarray_001.php on line %d
+Notice: Undefined offset: 6 in %sarray_001.php on line %d
NULL
-Notice: Undefined index: b in %sarray_001.php on line %d
+Notice: Undefined index: b in %sarray_001.php on line %d
NULL
-Notice: Undefined offset: 7 in %sarray_001.php on line %d
+Notice: Undefined offset: 7 in %sarray_001.php on line %d
-Notice: Undefined index: c in %sarray_001.php on line %d
+Notice: Undefined index: c in %sarray_001.php on line %d
object(ArrayObject)#%d (1) {
["storage":"ArrayObject":private]=>
array(2) {
diff --git a/ext/spl/tests/array_004.phpt b/ext/spl/tests/array_004.phpt
index dd07f29820..0b80e5c89f 100644
--- a/ext/spl/tests/array_004.phpt
+++ b/ext/spl/tests/array_004.phpt
@@ -1,12 +1,8 @@
--TEST--
SPL: ArrayIterator
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
-echo "==Normal==\n";
-
$arr = array(0=>0, 1=>1, 2=>2);
$obj = new ArrayObject($arr);
@@ -19,66 +15,9 @@ foreach($obj as $ak=>$av) {
}
}
-echo "==UseRef==\n";
-
-$arr = array(0=>0, 1=>1, 2=>2);
-$obj = new ArrayObject(&$arr);
-
-foreach($obj as $ak=>$av) {
- foreach($obj as $bk=>$bv) {
- if ($ak==0 && $bk==0) {
- $arr[0] = "modify";
- }
- echo "$ak=>$av - $bk=>$bv\n";
- }
-}
-
-echo "==Modify==\n";
-
-$arr = array(0=>0, 1=>1, 2=>2);
-$obj = new ArrayObject(&$arr);
-
-foreach($obj as $ak=>$av) {
- foreach($obj as $bk=>$bv) {
- if ($ak==0 && $bk==0) {
- $arr[0] = "modify";
- }
- echo "$ak=>$av - $bk=>$bv\n";
- }
-}
-
-echo "==Delete==\n";
-
-$arr = array(0=>0, 1=>1, 2=>2);
-$obj = new ArrayObject(&$arr);
-
-foreach($obj as $ak=>$av) {
- foreach($obj as $bk=>$bv) {
- if ($ak==1 && $bk==1) {
- unset($arr[1]);
- }
- echo "$ak=>$av - $bk=>$bv\n";
- }
-}
-
-echo "==Change==\n";
-
-$arr = array(0=>0, 1=>1, 2=>2);
-$obj = new ArrayObject(&$arr);
-
-foreach($obj as $ak=>$av) {
- foreach($obj as $bk=>$bv) {
- if ($ak==1 && $bk==1) {
- $arr = NULL;
- }
- echo "$ak=>$av - $bk=>$bv\n";
- }
-}
-
echo "Done\n";
?>
--EXPECTF--
-==Normal==
0=>0 - 0=>0
0=>0 - 1=>1
0=>0 - 2=>2
@@ -88,54 +27,4 @@ echo "Done\n";
2=>2 - 0=>0
2=>2 - 1=>1
2=>2 - 2=>2
-==UseRef==
-0=>0 - 0=>0
-0=>0 - 1=>1
-0=>0 - 2=>2
-1=>1 - 0=>modify
-1=>1 - 1=>1
-1=>1 - 2=>2
-2=>2 - 0=>modify
-2=>2 - 1=>1
-2=>2 - 2=>2
-==Modify==
-0=>0 - 0=>0
-0=>0 - 1=>1
-0=>0 - 2=>2
-1=>1 - 0=>modify
-1=>1 - 1=>1
-1=>1 - 2=>2
-2=>2 - 0=>modify
-2=>2 - 1=>1
-2=>2 - 2=>2
-==Delete==
-0=>0 - 0=>0
-0=>0 - 1=>1
-0=>0 - 2=>2
-1=>1 - 0=>0
-1=>1 - 1=>1
-
-Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_004.php on line %d
-1=>1 - 0=>0
-1=>1 - 2=>2
-
-Notice: main(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sarray_004.php on line %d
-0=>0 - 0=>0
-0=>0 - 2=>2
-2=>2 - 0=>0
-2=>2 - 2=>2
-==Change==
-0=>0 - 0=>0
-0=>0 - 1=>1
-0=>0 - 2=>2
-1=>1 - 0=>0
-1=>1 - 1=>1
-
-Notice: main(): ArrayIterator::current(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d
-
-Notice: main(): ArrayIterator::valid(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d
-
-Notice: main(): ArrayIterator::current(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d
-
-Notice: main(): ArrayIterator::valid(): Array was modified outside object and is no longer an array in %sarray_004.php on line %d
Done
diff --git a/ext/spl/tests/array_008.phpt b/ext/spl/tests/array_008.phpt
index 61c7abd7c6..e7a618dda5 100644
--- a/ext/spl/tests/array_008.phpt
+++ b/ext/spl/tests/array_008.phpt
@@ -1,12 +1,8 @@
--TEST--
SPL: ArrayIterator and foreach reference
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
-echo "==Normal==\n";
-
$arr = array(0=>0, 1=>1, 2=>2);
$obj = new ArrayObject($arr);
@@ -19,35 +15,10 @@ foreach($obj as $ak=>&$av) {
}
}
-echo "==UseRef==\n";
-
-$arr = array(0=>0, 1=>1, 2=>2);
-$obj = new ArrayObject(&$arr);
-
-foreach($obj as $ak=>&$av) {
- foreach($obj as $bk=>&$bv) {
- if ($ak==0 && $bk==0) {
- $bv = "modify";
- }
- echo "$ak=>$av - $bk=>$bv\n";
- }
-}
-
?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
-==Normal==
-0=>modify - 0=>modify
-0=>modify - 1=>1
-0=>modify - 2=>2
-1=>1 - 0=>modify
-1=>1 - 1=>1
-1=>1 - 2=>2
-2=>2 - 0=>modify
-2=>2 - 1=>1
-2=>2 - 2=>2
-==UseRef==
0=>modify - 0=>modify
0=>modify - 1=>1
0=>modify - 2=>2
diff --git a/ext/spl/tests/array_010.phpt b/ext/spl/tests/array_010.phpt
index 6b331e4b51..d2f3de7f6d 100644
--- a/ext/spl/tests/array_010.phpt
+++ b/ext/spl/tests/array_010.phpt
@@ -94,10 +94,10 @@ int(1)
string(3) "3rd"
int(4)
-Notice: Undefined index: 5th in %sarray_010.php on line %d
+Notice: Undefined index: 5th in %sarray_010.php on line %d
NULL
-Notice: Undefined offset: 6 in %sarray_010.php on line %d
+Notice: Undefined offset: 6 in %sarray_010.php on line %d
NULL
===offsetSet===
WRITE 1
@@ -128,9 +128,9 @@ array(6) {
string(9) "changed 6"
}
-Notice: Undefined offset: 7 in %sarray_010.php on line %d
+Notice: Undefined offset: 7 in %sarray_010.php on line %d
-Notice: Undefined index: 8th in %sarray_010.php on line %d
+Notice: Undefined index: 8th in %sarray_010.php on line %d
array(4) {
[0]=>
string(3) "1st"
diff --git a/ext/spl/tests/bug45622.phpt b/ext/spl/tests/bug45622.phpt
index c47b62cbdf..a8fe2c4641 100644
--- a/ext/spl/tests/bug45622.phpt
+++ b/ext/spl/tests/bug45622.phpt
@@ -42,7 +42,7 @@ bool(true)
--> Remove the array element and try access again:
bool(false)
-Notice: Undefined index: p in %s on line %d
+Notice: Undefined index: p in %s on line %d
NULL
--> Re-add the real property:
diff --git a/ext/spl/tests/bug45622b.phpt b/ext/spl/tests/bug45622b.phpt
index 9d49392111..f101a8459d 100644
--- a/ext/spl/tests/bug45622b.phpt
+++ b/ext/spl/tests/bug45622b.phpt
@@ -25,9 +25,9 @@ isset($ao->prop4);
--EXPECTF--
Doesn't trigger __get.
-Notice: Undefined index: prop1 in %s on line 11
+Notice: Undefined index: prop1 in %s on line 11
Doesn't trigger __set.
Doesn't trigger __unset.
-Notice: Undefined index: prop3 in %s on line 17
+Notice: Undefined index: prop3 in %s on line 17
Shouldn't trigger __isset. \ No newline at end of file
diff --git a/ext/spl/tests/bug49263.phpt b/ext/spl/tests/bug49263.phpt
index 14d0950f12..2075577ba8 100644
--- a/ext/spl/tests/bug49263.phpt
+++ b/ext/spl/tests/bug49263.phpt
@@ -19,7 +19,7 @@ var_dump(unserialize($ss));
?>
===DONE===
--EXPECTF--
-C:16:"SplObjectStorage":113:{x:i:2;O:8:"stdClass":0:{},a:2:{s:4:"prev";i:2;s:4:"next";O:8:"stdClass":0:{}};r:4;,a:1:{s:4:"prev";r:1;};m:a:0:{}}
+C:16:"SplObjectStorage":113:{x:i:2;O:8:"stdClass":0:{},a:2:{s:4:"prev";i:2;s:4:"next";O:8:"stdClass":0:{}};r:6;,a:1:{s:4:"prev";r:3;};m:a:0:{}}
object(SplObjectStorage)#2 (1) {
["storage":"SplObjectStorage":private]=>
array(2) {
diff --git a/ext/spl/tests/bug52238.phpt b/ext/spl/tests/bug52238.phpt
index 85410bdf1e..10da0b5fd9 100644
--- a/ext/spl/tests/bug52238.phpt
+++ b/ext/spl/tests/bug52238.phpt
@@ -1,5 +1,5 @@
--TEST--
-Bug #52238 - Crash when an Exception occured in iterator_to_array
+Bug #52238 - Crash when an Exception occurred in iterator_to_array
--FILE--
<?php
class Foo implements IteratorAggregate
diff --git a/ext/spl/tests/bug53515.phpt b/ext/spl/tests/bug53515.phpt
index f99840e322..8ecb02b1e6 100644
--- a/ext/spl/tests/bug53515.phpt
+++ b/ext/spl/tests/bug53515.phpt
@@ -10,7 +10,7 @@ $a['z'] = '';
$a[''] = '';
foreach ($a as $key => $value) {
- echo $key . ': ' . (is_null($value) ? 'null' : $value) .
+ echo $key . ': ' . (is_null($value) ? 'null' : @"$value") .
' array_key_exists: ' . (array_key_exists($key, $a) ? 'true' : 'false') .
' property_exists: ' . (property_exists($o, $key) ? 'true' : 'false'),"\n";
}
diff --git a/ext/spl/tests/bug54323.phpt b/ext/spl/tests/bug54323.phpt
new file mode 100644
index 0000000000..df6416a0f1
--- /dev/null
+++ b/ext/spl/tests/bug54323.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #54323 (Accessing unset()'ed ArrayObject's property causes crash)
+--FILE--
+<?php
+class C {
+ public $prop = 'C::prop.orig';
+}
+class MyArrayObject extends ArrayObject {
+}
+$c = new C;
+$ao = new MyArrayObject($c);
+testAccess($c, $ao);
+function testAccess($c, $ao) {
+ foreach ($ao as $key=>$value) {
+ }
+ unset($ao['prop']);
+ var_dump($c->prop, $ao['prop']);
+}
+--EXPECTF--
+Notice: Undefined property: C::$prop in %sbug54323.php on line 14
+
+Notice: Undefined index: prop in %sbug54323.php on line 14
+NULL
+NULL
diff --git a/ext/spl/tests/bug60082.phpt b/ext/spl/tests/bug60082.phpt
deleted file mode 100644
index 346bee7974..0000000000
--- a/ext/spl/tests/bug60082.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Bug #60082 (100% CPU / when using references with ArrayObject(&$ref))
---SKIPIF--
-<?php
-if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
-if ((stristr(PHP_OS, 'freebsd'))) {
- die('skip.. this test causes the run-tests.php to hang on Freebsd, see #60186');
-}
-?>
---INI--
-allow_call_time_pass_reference = Off
---FILE--
-<?php
-$test = array();
-$test = new ArrayObject(&$test);
-$test['a'] = $test['b'];
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Deprecated: Call-time pass-by-reference has been deprecated in %sbug60082.php on line %d
-
-Fatal error: main(): Nesting level too deep - recursive dependency? in %sbug60082.php on line %d
diff --git a/ext/spl/tests/bug60201.phpt b/ext/spl/tests/bug60201.phpt
new file mode 100644
index 0000000000..68a5daabfd
--- /dev/null
+++ b/ext/spl/tests/bug60201.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #60201 (SplFileObject::setCsvControl does not expose third argument via Reflection)
+--FILE--
+<?php
+
+$method = new ReflectionMethod('SplFileObject', 'setCsvControl');
+$params = $method->getParameters();
+var_dump($params);
+
+?>
+===DONE===
+--EXPECTF--
+array(3) {
+ [0]=>
+ &object(ReflectionParameter)#%d (1) {
+ ["name"]=>
+ string(9) "delimiter"
+ }
+ [1]=>
+ &object(ReflectionParameter)#%d (1) {
+ ["name"]=>
+ string(9) "enclosure"
+ }
+ [2]=>
+ &object(ReflectionParameter)#%d (1) {
+ ["name"]=>
+ string(6) "escape"
+ }
+}
+===DONE===
diff --git a/ext/spl/tests/bug61453.phpt b/ext/spl/tests/bug61453.phpt
new file mode 100644
index 0000000000..e5b1387fd2
--- /dev/null
+++ b/ext/spl/tests/bug61453.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #61453: SplObjectStorage does not identify objects correctly
+--FILE--
+<?php
+$limit = 1000;
+$objects = new SplObjectStorage;
+for($i = 0; $i < $limit; $i++){
+ $object = new StdClass;
+
+ if(isset($objects[$object])){
+ die("this should never happen, but did after $i iteration");
+ }
+
+ $objects[$object] = 1;
+}
+?>
+==DONE==
+--EXPECT--
+==DONE==
diff --git a/ext/spl/tests/bug61527.phpt b/ext/spl/tests/bug61527.phpt
new file mode 100644
index 0000000000..ab13c69547
--- /dev/null
+++ b/ext/spl/tests/bug61527.phpt
@@ -0,0 +1,92 @@
+--TEST--
+Bug #61527 (Recursive/ArrayIterator gives misleading notice when array empty or moved to the end)
+--FILE--
+<?php
+$ao = new ArrayObject(array());
+$ai = $ao->getIterator();
+
+/* testing empty array, should no notice at all */
+$ai->next();
+var_dump($ai->key());
+var_dump($ai->current());
+
+/* testing array changing */
+$ao2 = new ArrayObject(array(1 => 1, 2, 3, 4, 5));
+$ai2 = $ao2->getIterator();
+
+$ao2->offsetUnset($ai2->key());
+$ai2->next();
+
+/* now point to 2 */
+$ao2->offsetUnset($ai2->key());
+var_dump($ai2->key());
+
+/* now point to 3 */
+$ao2->offsetUnset($ai2->key());
+var_dump($ai2->current());
+
+$ai2->next();
+var_dump($ai2->key());
+var_dump($ai2->current());
+
+/* should be at the end and no notice */
+$ai2->next();
+var_dump($ai2->key());
+var_dump($ai2->current());
+
+$ai2->rewind();
+$ai2->next();
+$ai2->next();
+/* should reached the end */
+var_dump($ai2->next());
+var_dump($ai2->key());
+
+/* testing RecursiveArrayIterator */
+$ao3 = new ArrayObject(array(), NULL, 'RecursiveArrayIterator');
+$ai3 = $ao3->getIterator();
+
+var_dump($ai3->getChildren());
+
+$ao4 = new ArrayObject(array(1, 2), NULL, 'RecursiveArrayIterator');
+$ai4 = $ao4->getIterator();
+
+$ai4->next();
+$ai4->next();
+$ai4->next();
+var_dump($ai4->hasChildren());
+
+$ai4->rewind();
+$ao4->offsetUnset($ai4->key());
+var_dump($ai4->hasChildren());
+
+$ao4->offsetUnset($ai4->key());
+var_dump($ai4->getChildren());
+?>
+==DONE==
+<?php exit(0); ?>
+--EXPECTF--
+NULL
+NULL
+
+Notice: ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d
+
+Notice: ArrayIterator::key(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d
+NULL
+
+Notice: ArrayIterator::current(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d
+NULL
+int(5)
+int(5)
+NULL
+NULL
+NULL
+NULL
+NULL
+bool(false)
+
+Notice: RecursiveArrayIterator::hasChildren(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d
+bool(false)
+
+Notice: RecursiveArrayIterator::getChildren(): Array was modified outside object and internal position is no longer valid in %sbug61527.php on line %d
+NULL
+==DONE==
diff --git a/ext/spl/tests/bug62328.phpt b/ext/spl/tests/bug62328.phpt
new file mode 100644
index 0000000000..33a8aeee95
--- /dev/null
+++ b/ext/spl/tests/bug62328.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #62328 (cast_object takes precedence over __toString)
+--CREDITS--
+leight at gmail dot com
+--FILE--
+<?php
+
+class SplFileInfo62328 extends SplFileInfo
+{
+ public function __toString()
+ {
+ return '__toString';
+ }
+}
+
+$fi = new SplFileInfo62328(__FILE__);
+
+echo (string)$fi . PHP_EOL;
+echo (string)$fi->__toString() . PHP_EOL;
+
+?>
+--EXPECT--
+__toString
+__toString
diff --git a/ext/spl/tests/bug62433.phpt b/ext/spl/tests/bug62433.phpt
new file mode 100644
index 0000000000..bfb3568bac
--- /dev/null
+++ b/ext/spl/tests/bug62433.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #62433 Inconsistent behavior of RecursiveDirectoryIterator to dot files (. and ..)
+--FILE--
+<?php
+$dots = array_keys(iterator_to_array(new RecursiveDirectoryIterator(__DIR__)));
+$ndots = array_keys(iterator_to_array(new RecursiveDirectoryIterator(__DIR__, FilesystemIterator::SKIP_DOTS)));
+
+var_dump(in_array(__DIR__ . DIRECTORY_SEPARATOR . '.', $dots));
+var_dump(in_array(__DIR__ . DIRECTORY_SEPARATOR . '..', $dots));
+
+var_dump(in_array(__DIR__ . DIRECTORY_SEPARATOR . '.', $ndots));
+var_dump(in_array(__DIR__ . DIRECTORY_SEPARATOR . '..', $ndots));
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(false)
+bool(false)
diff --git a/ext/spl/tests/bug62978.phpt b/ext/spl/tests/bug62978.phpt
index 94068d5604..0d91609f88 100644
--- a/ext/spl/tests/bug62978.phpt
+++ b/ext/spl/tests/bug62978.phpt
@@ -25,7 +25,7 @@ var_dump($a[$fp]);
fclose($fp);
--EXPECTF--
-Notice: Undefined index: epic_magic in %sbug62978.php on line %d
+Notice: Undefined index: epic_magic in %sbug62978.php on line %d
NULL
Notice: Undefined index: epic_magic in %sbug62978.php on line %d
@@ -34,17 +34,17 @@ NULL
Notice: Undefined variable: c in %sbug62978.php on line %d
NULL
-Notice: Undefined index: epic_magic in %sbug62978.php on line %d
+Notice: Undefined index: epic_magic in %sbug62978.php on line %d
NULL
Notice: Undefined index: epic_magic in %sbug62978.php on line %d
NULL
-Notice: Undefined index: epic_magic in %sbug62978.php on line %d
+Notice: Undefined index: epic_magic in %sbug62978.php on line %d
NULL
bool(false)
Strict Standards: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d
-Notice: Undefined offset: %d in %sbug62978.php on line %d
+Notice: Undefined offset: %d in %sbug62978.php on line %d
NULL
diff --git a/ext/spl/tests/class_uses_basic.phpt b/ext/spl/tests/class_uses_basic.phpt
new file mode 100644
index 0000000000..8aeb7b52a7
--- /dev/null
+++ b/ext/spl/tests/class_uses_basic.phpt
@@ -0,0 +1,33 @@
+--TEST--
+SPL: Test class_implements() function : basic
+--FILE--
+<?php
+/* Prototype : array class_uses(mixed what [, bool autoload ])
+ * Description: Return all traits used by a class
+ * Source code: ext/spl/php_spl.c
+ * Alias to functions:
+ */
+
+echo "*** Testing class_uses() : basic ***\n";
+
+
+trait foo { }
+class bar { use foo; }
+
+var_dump(class_uses(new bar));
+var_dump(class_uses('bar'));
+
+
+?>
+===DONE===
+--EXPECT--
+*** Testing class_uses() : basic ***
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+===DONE===
diff --git a/ext/spl/tests/class_uses_basic2.phpt b/ext/spl/tests/class_uses_basic2.phpt
new file mode 100644
index 0000000000..a0ffe8b861
--- /dev/null
+++ b/ext/spl/tests/class_uses_basic2.phpt
@@ -0,0 +1,69 @@
+--TEST--
+SPL: Test class_uses() function : basic
+--FILE--
+<?php
+/* Prototype : array class_uses(mixed what [, bool autoload ])
+ * Description: Return all traits used by a class
+ * Source code: ext/spl/php_spl.c
+ * Alias to functions:
+ */
+
+echo "*** Testing class_uses() : basic ***\n";
+
+
+trait foo { }
+class fooUser { use foo; }
+
+trait bar { }
+class barUser { use bar; }
+
+class foobarUser { use foo, bar; }
+
+/** There is no semantics for traits in the inheritance chain.
+ Traits are flattend into a class, and that semantics is nothing
+ like a type, or interface, and thus, not propergated. */
+class fooViaBarUser extends barUser { use foo; }
+
+class fooExtended extends fooUser {}
+
+s_var_dump(class_uses(new foobarUser));
+s_var_dump(class_uses('foobarUser'));
+s_var_dump(class_uses(new fooViaBarUser));
+s_var_dump(class_uses('fooViaBarUser'));
+s_var_dump(class_uses(new fooExtended));
+s_var_dump(class_uses('fooExtended'));
+
+
+function s_var_dump($arr) {
+ krsort($arr);
+ var_dump($arr);
+}
+?>
+===DONE===
+--EXPECT--
+*** Testing class_uses() : basic ***
+array(2) {
+ ["foo"]=>
+ string(3) "foo"
+ ["bar"]=>
+ string(3) "bar"
+}
+array(2) {
+ ["foo"]=>
+ string(3) "foo"
+ ["bar"]=>
+ string(3) "bar"
+}
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+array(0) {
+}
+array(0) {
+}
+===DONE===
diff --git a/ext/spl/tests/class_uses_variation.phpt b/ext/spl/tests/class_uses_variation.phpt
new file mode 100644
index 0000000000..9c21521c60
--- /dev/null
+++ b/ext/spl/tests/class_uses_variation.phpt
@@ -0,0 +1,45 @@
+--TEST--
+SPL: Test class_uses() function : variation - no interfaces and autoload
+--FILE--
+<?php
+/* Prototype : array class_uses(mixed what [, bool autoload ])
+ * Description: Return all traits used by a class
+ * Source code: ext/spl/php_spl.c
+ * Alias to functions:
+ */
+
+echo "*** Testing class_uses() : variation ***\n";
+
+echo "--- testing no traits ---\n";
+class fs {}
+var_dump(class_uses(new fs));
+var_dump(class_uses('fs'));
+
+echo "\n--- testing autoload ---\n";
+var_dump(class_uses('non-existent'));
+var_dump(class_uses('non-existent2', false));
+
+
+function __autoload($classname) {
+ echo "attempting to autoload $classname\n";
+}
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing class_uses() : variation ***
+--- testing no traits ---
+array(0) {
+}
+array(0) {
+}
+
+--- testing autoload ---
+attempting to autoload non-existent
+
+Warning: class_uses(): Class non-existent does not exist and could not be loaded in %s on line %d
+bool(false)
+
+Warning: class_uses(): Class non-existent2 does not exist in %s on line %d
+bool(false)
+===DONE===
diff --git a/ext/spl/tests/class_uses_variation1.phpt b/ext/spl/tests/class_uses_variation1.phpt
new file mode 100644
index 0000000000..aa0ba35c94
--- /dev/null
+++ b/ext/spl/tests/class_uses_variation1.phpt
@@ -0,0 +1,221 @@
+--TEST--
+SPL: Test class_uses() function : variation
+--FILE--
+<?php
+/* Prototype : array class_uses(mixed what [, bool autoload ])
+ * Description: Return all traits used by a class
+ * Source code: ext/spl/php_spl.c
+ * Alias to functions:
+ */
+
+echo "*** Testing class_uses() : variation ***\n";
+
+
+// Define error handler
+function test_error_handler($err_no, $err_msg, $filename, $linenum, $vars) {
+ if (error_reporting() != 0) {
+ // report non-silenced errors
+ echo "Error: $err_no - $err_msg, $filename($linenum)\n";
+ }
+}
+set_error_handler('test_error_handler');
+
+// Initialise function arguments not being substituted (if any)
+$autoload = true;
+
+//resource
+$res = fopen(__FILE__,'r');
+
+//get an unset variable
+$unset_var = 10;
+unset ($unset_var);
+
+// define some classes
+class classWithToString
+{
+ public function __toString() {
+ return "Class A object";
+ }
+}
+
+class classWithoutToString
+{
+}
+
+// heredoc string
+$heredoc = <<<EOT
+hello world
+EOT;
+
+// add arrays
+$index_array = array (1, 2, 3);
+$assoc_array = array ('one' => 1, 'two' => 2);
+
+//array of values to iterate over
+$inputs = array(
+
+ // int data
+ 'int 0' => 0,
+ 'int 1' => 1,
+ 'int 12345' => 12345,
+ 'int -12345' => -2345,
+
+ // float data
+ 'float 10.5' => 10.5,
+ 'float -10.5' => -10.5,
+ 'float 12.3456789000e10' => 12.3456789000e10,
+ 'float -12.3456789000e10' => -12.3456789000e10,
+ 'float .5' => .5,
+
+ // array data
+ 'empty array' => array(),
+ 'int indexed array' => $index_array,
+ 'associative array' => $assoc_array,
+ 'nested arrays' => array('foo', $index_array, $assoc_array),
+
+ // null data
+ 'uppercase NULL' => NULL,
+ 'lowercase null' => null,
+
+ // boolean data
+ 'lowercase true' => true,
+ 'lowercase false' =>false,
+ 'uppercase TRUE' =>TRUE,
+ 'uppercase FALSE' =>FALSE,
+
+ // empty data
+ 'empty string DQ' => "",
+ 'empty string SQ' => '',
+
+ // object data
+ 'instance of classWithToString' => new classWithToString(),
+ 'instance of classWithoutToString' => new classWithoutToString(),
+
+ // undefined data
+ 'undefined var' => @$undefined_var,
+
+ // unset data
+ 'unset var' => @$unset_var,
+
+ //resource
+ 'resource' => $res,
+);
+
+// loop through each element of the array for pattern
+
+foreach($inputs as $key =>$value) {
+ echo "\n--$key--\n";
+ var_dump( class_uses($value, $autoload) );
+};
+
+fclose($res);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing class_uses() : variation ***
+
+--int 0--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--int 1--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--int 12345--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--int -12345--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--float 10.5--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--float -10.5--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--float 12.3456789000e10--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--float -12.3456789000e10--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--float .5--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--empty array--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--int indexed array--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--associative array--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--nested arrays--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--uppercase NULL--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--lowercase null--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--lowercase true--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--lowercase false--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--uppercase TRUE--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--uppercase FALSE--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--empty string DQ--
+Error: 2 - class_uses(): Class does not exist and could not be loaded, %s(%d)
+bool(false)
+
+--empty string SQ--
+Error: 2 - class_uses(): Class does not exist and could not be loaded, %s(%d)
+bool(false)
+
+--instance of classWithToString--
+array(0) {
+}
+
+--instance of classWithoutToString--
+array(0) {
+}
+
+--undefined var--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--unset var--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+
+--resource--
+Error: 2 - class_uses(): object or string expected, %s(%d)
+bool(false)
+===DONE===
diff --git a/ext/spl/tests/class_uses_variation2.phpt b/ext/spl/tests/class_uses_variation2.phpt
new file mode 100644
index 0000000000..36c9623cb3
--- /dev/null
+++ b/ext/spl/tests/class_uses_variation2.phpt
@@ -0,0 +1,261 @@
+--TEST--
+SPL: Test class_uses() function : variation
+--FILE--
+<?php
+/* Prototype : array class_uses(mixed what [, bool autoload ])
+ * Description: Return all traits used by a class
+ * Source code: ext/spl/php_spl.c
+ * Alias to functions:
+ */
+
+echo "*** Testing class_uses() : variation ***\n";
+
+trait foo {}
+class fooUser { use foo; }
+
+// Define error handler
+function test_error_handler($err_no, $err_msg, $filename, $linenum, $vars) {
+ if (error_reporting() != 0) {
+ // report non-silenced errors
+ echo "Error: $err_no - $err_msg, $filename($linenum)\n";
+ }
+}
+set_error_handler('test_error_handler');
+
+// Initialise function arguments not being substituted (if any)
+$class = 'fooUser';
+
+//resource
+$res = fopen(__FILE__,'r');
+
+//get an unset variable
+$unset_var = 10;
+unset ($unset_var);
+
+// define some classes
+class classWithToString
+{
+ public function __toString() {
+ return "Class A object";
+ }
+}
+
+class classWithoutToString
+{
+}
+
+// heredoc string
+$heredoc = <<<EOT
+hello world
+EOT;
+
+// add arrays
+$index_array = array (1, 2, 3);
+$assoc_array = array ('one' => 1, 'two' => 2);
+
+//array of values to iterate over
+$inputs = array(
+
+ // int data
+ 'int 0' => 0,
+ 'int 1' => 1,
+ 'int 12345' => 12345,
+ 'int -12345' => -2345,
+
+ // float data
+ 'float 10.5' => 10.5,
+ 'float -10.5' => -10.5,
+ 'float 12.3456789000e10' => 12.3456789000e10,
+ 'float -12.3456789000e10' => -12.3456789000e10,
+ 'float .5' => .5,
+
+ // array data
+ 'empty array' => array(),
+ 'int indexed array' => $index_array,
+ 'associative array' => $assoc_array,
+ 'nested arrays' => array('foo', $index_array, $assoc_array),
+
+ // null data
+ 'uppercase NULL' => NULL,
+ 'lowercase null' => null,
+
+ // boolean data
+ 'lowercase true' => true,
+ 'lowercase false' =>false,
+ 'uppercase TRUE' =>TRUE,
+ 'uppercase FALSE' =>FALSE,
+
+ // empty data
+ 'empty string DQ' => "",
+ 'empty string SQ' => '',
+
+ // object data
+ 'instance of classWithToString' => new classWithToString(),
+ 'instance of classWithoutToString' => new classWithoutToString(),
+
+ // undefined data
+ 'undefined var' => @$undefined_var,
+
+ // unset data
+ 'unset var' => @$unset_var,
+
+ //resource
+ 'resource' => $res,
+);
+
+// loop through each element of the array for pattern
+
+foreach($inputs as $key =>$value) {
+ echo "\n--$key--\n";
+ var_dump( class_uses($class, $value) );
+};
+
+fclose($res);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing class_uses() : variation ***
+
+--int 0--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--int 1--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--int 12345--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--int -12345--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--float 10.5--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--float -10.5--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--float 12.3456789000e10--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--float -12.3456789000e10--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--float .5--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--empty array--
+Error: 2 - class_uses() expects parameter 2 to be boolean, array given, %s(%d)
+bool(false)
+
+--int indexed array--
+Error: 2 - class_uses() expects parameter 2 to be boolean, array given, %s(%d)
+bool(false)
+
+--associative array--
+Error: 2 - class_uses() expects parameter 2 to be boolean, array given, %s(%d)
+bool(false)
+
+--nested arrays--
+Error: 2 - class_uses() expects parameter 2 to be boolean, array given, %s(%d)
+bool(false)
+
+--uppercase NULL--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--lowercase null--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--lowercase true--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--lowercase false--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--uppercase TRUE--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--uppercase FALSE--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--empty string DQ--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--empty string SQ--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--instance of classWithToString--
+Error: 2 - class_uses() expects parameter 2 to be boolean, object given, %s(%d)
+bool(false)
+
+--instance of classWithoutToString--
+Error: 2 - class_uses() expects parameter 2 to be boolean, object given, %s(%d)
+bool(false)
+
+--undefined var--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--unset var--
+array(1) {
+ ["foo"]=>
+ string(3) "foo"
+}
+
+--resource--
+Error: 2 - class_uses() expects parameter 2 to be boolean, resource given, %s(%d)
+bool(false)
+===DONE===
diff --git a/ext/spl/tests/dllist_001.phpt b/ext/spl/tests/dllist_001.phpt
index 2a21561883..e27f23ca44 100644
--- a/ext/spl/tests/dllist_001.phpt
+++ b/ext/spl/tests/dllist_001.phpt
@@ -1,7 +1,5 @@
--TEST--
SPL: DoublyLinkedList: std operations
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
$dll = new SplDoublyLinkedList();
@@ -20,18 +18,10 @@ try {
// data consistency
$a = 2;
$dll->push($a);
-$a = 3;
-$dll->push(&$a);
-$a = 4;
-echo $dll->pop()."\n";
echo $dll->pop()."\n";
$a = 2;
$dll->unshift($a);
-$a = 3;
-$dll->unshift(&$a);
-$a = 4;
-echo $dll->shift()."\n";
echo $dll->shift()."\n";
// peakable
@@ -61,9 +51,7 @@ echo count($dll)."\n";
--EXPECTF--
Exception: Can't pop from an empty datastructure
Exception: Can't shift from an empty datastructure
-3
2
-3
2
2
1
diff --git a/ext/spl/tests/dllist_004.phpt b/ext/spl/tests/dllist_004.phpt
index 0b20f6eb6a..44d9611fca 100644
--- a/ext/spl/tests/dllist_004.phpt
+++ b/ext/spl/tests/dllist_004.phpt
@@ -1,7 +1,5 @@
--TEST--
SPL: DoublyLinkedList: Stacks
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
$stack = new SplStack();
@@ -20,10 +18,6 @@ try {
// data consistency
$a = 2;
$stack->push($a);
-$a = 3;
-$stack->push(&$a);
-$a = 4;
-echo $stack->pop()."\n";
echo $stack->pop()."\n";
// peakable
@@ -55,7 +49,6 @@ echo count($stack)."\n";
--EXPECTF--
Exception: Can't pop from an empty datastructure
Exception: Can't shift from an empty datastructure
-3
2
2
[2]
diff --git a/ext/spl/tests/dllist_005.phpt b/ext/spl/tests/dllist_005.phpt
index f95cedd1fa..33161ba17d 100644
--- a/ext/spl/tests/dllist_005.phpt
+++ b/ext/spl/tests/dllist_005.phpt
@@ -1,7 +1,5 @@
--TEST--
SPL: DoublyLinkedList: Queues
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
$queue = new SplQueue();
@@ -20,10 +18,6 @@ try {
// data consistency
$a = 2;
$queue->enqueue($a);
-$a = 3;
-$queue->enqueue(&$a);
-$a = 4;
-echo $queue->dequeue()."\n";
echo $queue->dequeue()."\n";
// peakable
@@ -56,7 +50,6 @@ echo count($queue)."\n";
Exception: Can't shift from an empty datastructure
Exception: Can't shift from an empty datastructure
2
-3
2
[1]
[2]
diff --git a/ext/spl/tests/fileobject_getmaxlinelen_error001.phpt b/ext/spl/tests/fileobject_getmaxlinelen_error001.phpt
new file mode 100644
index 0000000000..3c0c9eebd5
--- /dev/null
+++ b/ext/spl/tests/fileobject_getmaxlinelen_error001.phpt
@@ -0,0 +1,14 @@
+--TEST--
+SPL: SplFileObject::getMaxLineLen error 001
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--INI--
+include_path=.
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+$s->getMaxLineLen('string');
+
+?>
+--EXPECTF--
+Warning: SplFileObject::getMaxLineLen() expects exactly 0 parameters, 1 given in %s on line %d
diff --git a/ext/spl/tests/fileobject_setmaxlinelen_error001.phpt b/ext/spl/tests/fileobject_setmaxlinelen_error001.phpt
new file mode 100644
index 0000000000..6bfdfdcf50
--- /dev/null
+++ b/ext/spl/tests/fileobject_setmaxlinelen_error001.phpt
@@ -0,0 +1,17 @@
+--TEST--
+SPL: SplFileObject::setMaxLineLen error 001()
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+try {
+ $s->setMaxLineLen(-1);
+}
+catch (DomainException $e) {
+ echo 'DomainException thrown';
+}
+
+?>
+--EXPECT--
+DomainException thrown
diff --git a/ext/spl/tests/fileobject_setmaxlinelen_error002.phpt b/ext/spl/tests/fileobject_setmaxlinelen_error002.phpt
new file mode 100644
index 0000000000..dad59fca5f
--- /dev/null
+++ b/ext/spl/tests/fileobject_setmaxlinelen_error002.phpt
@@ -0,0 +1,12 @@
+--TEST--
+SPL: SplFileObject::setMaxLineLen error 002
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+$s->setMaxLineLen();
+
+?>
+--EXPECTF--
+Warning: SplFileObject::setMaxLineLen() expects exactly 1 parameter, 0 given in %s on line %d
diff --git a/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt b/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt
new file mode 100644
index 0000000000..8dc50d5fc7
--- /dev/null
+++ b/ext/spl/tests/fileobject_setmaxlinelen_error003.phpt
@@ -0,0 +1,12 @@
+--TEST--
+SPL: SplFileObject::setMaxLineLen error 003
+--CREDITS--
+Erwin Poeze <erwin.poeze at gmail.com>
+--FILE--
+<?php
+$s = new SplFileObject( __FILE__ );
+$s->setMaxLineLen('string');
+
+?>
+--EXPECTF--
+Warning: SplFileObject::setMaxLineLen() expects parameter 1 to be long, string given in %s on line %d
diff --git a/ext/spl/tests/filesystemiterator_flags.phpt b/ext/spl/tests/filesystemiterator_flags.phpt
new file mode 100644
index 0000000000..635345655b
--- /dev/null
+++ b/ext/spl/tests/filesystemiterator_flags.phpt
@@ -0,0 +1,40 @@
+--TEST--
+SPL: FilesystemIterator::getFlags() basic tests
+--CREDITS--
+Joshua Thijssen <jthijssen@noxlogic.nl>
+--FILE--
+<?php
+
+$it = new FileSystemIterator(".");
+printflags($it);
+
+$it->setFlags(FileSystemIterator::CURRENT_AS_SELF |
+ FileSystemIterator::KEY_AS_FILENAME |
+ FileSystemIterator::SKIP_DOTS |
+ FileSystemIterator::UNIX_PATHS);
+printflags($it);
+
+$it->setFlags(-1);
+printflags($it);
+
+function printflags($it) {
+ printf("%08X\n", $it->getFlags());
+ printf("%08X\n", ($it->getFlags() & FileSystemIterator::CURRENT_MODE_MASK));
+ printf("%08X\n", ($it->getFlags() & FileSystemIterator::KEY_MODE_MASK));
+ printf("%08X\n", ($it->getFlags() & FileSystemIterator::OTHER_MODE_MASK));
+}
+
+?>
+--EXPECT--
+00001000
+00000000
+00000000
+00001000
+00003110
+00000010
+00000100
+00003000
+00003FF0
+000000F0
+00000F00
+00003000
diff --git a/ext/spl/tests/fixedarray_001.phpt b/ext/spl/tests/fixedarray_001.phpt
index 39e1bc9f6c..8276333e10 100644
--- a/ext/spl/tests/fixedarray_001.phpt
+++ b/ext/spl/tests/fixedarray_001.phpt
@@ -1,7 +1,5 @@
--TEST--
SPL: FixedArray: std operations
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
$a = new SplFixedArray(0);
diff --git a/ext/spl/tests/fixedarray_002.phpt b/ext/spl/tests/fixedarray_002.phpt
index 9b9c0ac315..534d41f184 100644
--- a/ext/spl/tests/fixedarray_002.phpt
+++ b/ext/spl/tests/fixedarray_002.phpt
@@ -1,7 +1,5 @@
--TEST--
SPL: FixedArray: overloading
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
class A extends SplFixedArray {
diff --git a/ext/spl/tests/iterator_026.phpt b/ext/spl/tests/iterator_026.phpt
index 1e6058246b..8eb77a7baf 100644
--- a/ext/spl/tests/iterator_026.phpt
+++ b/ext/spl/tests/iterator_026.phpt
@@ -23,10 +23,14 @@ foreach($it as $k=>$v)
hasNext: yes
1=>2
hasNext: yes
+
+Notice: Array to string conversion in %siterator_026.php on line %d
0=>31
hasNext: yes
1=>32
hasNext: yes
+
+Notice: Array to string conversion in %siterator_026.php on line %d
0=>331
hasNext: no
3=>4
diff --git a/ext/spl/tests/iterator_041b.phpt b/ext/spl/tests/iterator_041b.phpt
index e166f6bdce..e7ea8b8008 100644
--- a/ext/spl/tests/iterator_041b.phpt
+++ b/ext/spl/tests/iterator_041b.phpt
@@ -82,6 +82,10 @@ class MyArrayIterator extends ArrayIterator
{
self::$fail++;
}
+ try {
+ $e = null;
+ } catch (Exception $e) {
+ }
}
}
}
@@ -101,10 +105,19 @@ State 3: valid()
State 4: current()
State 5: key()
State 6: next()
+State 7: __destruct()
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+}
===iterator_count===
State 0: __construct()
State 1: __construct()
State 2: rewind()
State 3: valid()
State 6: next()
+State 7: __destruct()
+int(2)
===DONE===
diff --git a/ext/spl/tests/iterator_044.phpt b/ext/spl/tests/iterator_044.phpt
index 6d25531175..1271ccaa64 100644
--- a/ext/spl/tests/iterator_044.phpt
+++ b/ext/spl/tests/iterator_044.phpt
@@ -81,7 +81,7 @@ NULL
int(0)
bool(false)
-Notice: Undefined index: 0 in %siterator_044.php on line %d
+Notice: Undefined index: 0 in %siterator_044.php on line %d
NULL
===1===
object(stdClass)#%d (0) {
@@ -97,31 +97,31 @@ object(MyFoo)#%d (0) {
}
bool(false)
-Notice: Undefined index: foo in %siterator_044.php on line %d
+Notice: Undefined index: foo in %siterator_044.php on line %d
NULL
===3===
NULL
bool(false)
-Notice: Undefined index: in %siterator_044.php on line %d
+Notice: Undefined index: in %siterator_044.php on line %d
NULL
===4===
int(2)
bool(false)
-Notice: Undefined index: 2 in %siterator_044.php on line %d
+Notice: Undefined index: 2 in %siterator_044.php on line %d
NULL
===5===
string(3) "foo"
bool(false)
-Notice: Undefined index: foo in %siterator_044.php on line %d
+Notice: Undefined index: foo in %siterator_044.php on line %d
NULL
===6===
int(3)
bool(false)
-Notice: Undefined index: 3 in %siterator_044.php on line %d
+Notice: Undefined index: 3 in %siterator_044.php on line %d
NULL
===FILL===
===0===
@@ -146,7 +146,7 @@ int(1)
NULL
bool(false)
-Notice: Undefined index: in %siterator_044.php on line %d
+Notice: Undefined index: in %siterator_044.php on line %d
NULL
===4===
int(2)
@@ -160,6 +160,6 @@ int(1)
int(3)
bool(false)
-Notice: Undefined index: 3 in %siterator_044.php on line %d
+Notice: Undefined index: 3 in %siterator_044.php on line %d
NULL
===DONE===
diff --git a/ext/spl/tests/iterator_047.phpt b/ext/spl/tests/iterator_047.phpt
index e5fec4f585..548f486528 100644
--- a/ext/spl/tests/iterator_047.phpt
+++ b/ext/spl/tests/iterator_047.phpt
@@ -70,6 +70,8 @@ int(0)
int(0)
MyRecursiveArrayIterator::hasChildren()
MyRecursiveArrayIterator::getChildren()
+
+Notice: Array to string conversion in %siterator_047.php on line %d
MyRecursiveArrayIterator::hasChildren()
int(0)
int(10)
@@ -78,6 +80,8 @@ int(2)
int(2)
MyRecursiveArrayIterator::hasChildren()
MyRecursiveArrayIterator::getChildren()
+
+Notice: Array to string conversion in %siterator_047.php on line %d
MyRecursiveArrayIterator::hasChildren()
int(0)
int(30)
@@ -100,6 +104,8 @@ int(0)
int(0)
MyRecursiveArrayIterator::hasChildren()
MyRecursiveArrayIterator::getChildren()
+
+Notice: Array to string conversion in %siterator_047.php on line %d
MyRecursiveArrayIterator::hasChildren()
int(0)
int(10)
@@ -108,6 +114,8 @@ int(2)
int(2)
MyRecursiveArrayIterator::hasChildren()
MyRecursiveArrayIterator::getChildren()
+
+Notice: Array to string conversion in %siterator_047.php on line %d
MyRecursiveArrayIterator::hasChildren()
int(0)
int(30)
diff --git a/ext/spl/tests/iterator_050.phpt b/ext/spl/tests/iterator_050.phpt
index 63d8fbfa9a..fed4a3b2ee 100644
--- a/ext/spl/tests/iterator_050.phpt
+++ b/ext/spl/tests/iterator_050.phpt
@@ -46,6 +46,8 @@ array(3) {
[2]=>
%s(1) "2"
}
+
+Notice: Array to string conversion in %siterator_050.php on line %d
int(0)
array(2) {
[0]=>
@@ -67,6 +69,8 @@ array(2) {
[1]=>
%s(1) "1"
}
+
+Notice: Array to string conversion in %siterator_050.php on line %d
object(ArrayIterator)#%d (1) {
%s"storage"%s"ArrayIterator":private]=>
array(9) {
diff --git a/ext/spl/tests/iterator_052.phpt b/ext/spl/tests/iterator_052.phpt
index a0cbdd8f73..c68bd5234d 100644
--- a/ext/spl/tests/iterator_052.phpt
+++ b/ext/spl/tests/iterator_052.phpt
@@ -122,6 +122,8 @@ array(3) {
array(0) {
}
}
+
+Notice: Array to string conversion in %siterator_052.php on line %d
bool(true)
int(5)
array(3) {
@@ -248,6 +250,8 @@ array(2) {
array(0) {
}
}
+
+Notice: Array to string conversion in %siterator_052.php on line %d
bool(true)
int(5)
array(2) {
diff --git a/ext/spl/tests/iterator_054.phpt b/ext/spl/tests/iterator_054.phpt
index 91266c9571..1f1cd580c1 100644
--- a/ext/spl/tests/iterator_054.phpt
+++ b/ext/spl/tests/iterator_054.phpt
@@ -42,6 +42,8 @@ array(3) {
[2]=>
string(1) "3"
}
+
+Notice: Array to string conversion in %siterator_054.php on line %d
int(7)
array(2) {
[0]=>
diff --git a/ext/spl/tests/regexiterator_getregex.phpt b/ext/spl/tests/regexiterator_getregex.phpt
new file mode 100644
index 0000000000..d3113a52ca
--- /dev/null
+++ b/ext/spl/tests/regexiterator_getregex.phpt
@@ -0,0 +1,29 @@
+--TEST--
+SPL: RegexIterator::getRegex() basic tests
+--CREDITS--
+Joshua Thijssen <jthijssen@noxlogic.nl>
+--FILE--
+<?php
+
+$array = array('cat', 'hat', 'sat');
+$iterator = new ArrayIterator($array);
+
+# Simple regex
+$regexIterator = new RegexIterator($iterator, '/.at/');
+var_dump($regexIterator->getRegex());
+
+# Empty regular expression
+$regexIterator = new RegexIterator($iterator, '//');
+var_dump($regexIterator->getRegex());
+
+# "Complex" email regular expression
+$regexIterator = new RegexIterator($iterator, '|\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b|');
+var_dump($regexIterator->getRegex());
+
+
+
+?>
+--EXPECT--
+string(5) "/.at/"
+string(2) "//"
+string(43) "|\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b|"
diff --git a/ext/spl/tests/spl_004.phpt b/ext/spl/tests/spl_004.phpt
index bea5695846..97896f8154 100644
--- a/ext/spl/tests/spl_004.phpt
+++ b/ext/spl/tests/spl_004.phpt
@@ -74,7 +74,7 @@ int(5)
int(6)
int(4)
===ERRORS===
-Error: Argument 3 passed to iterator_apply() must be an array, integer given
+Error: Argument 3 passed to iterator_apply() must be of the type array, integer given
Error: iterator_apply() expects parameter 3 to be array, integer given
NULL
Error: iterator_apply() expects parameter 2 to be a valid callback, function 'non_existing_functon' not found or invalid function name
diff --git a/ext/sqlite/CREDITS b/ext/sqlite/CREDITS
deleted file mode 100644
index f77d1919ce..0000000000
--- a/ext/sqlite/CREDITS
+++ /dev/null
@@ -1,2 +0,0 @@
-SQLite
-Wez Furlong, Tal Peer, Marcus Boerger, Ilia Alshanetsky
diff --git a/ext/sqlite/Makefile.frag b/ext/sqlite/Makefile.frag
deleted file mode 100644
index dd691d7980..0000000000
--- a/ext/sqlite/Makefile.frag
+++ /dev/null
@@ -1,2 +0,0 @@
-$(srcdir)/libsqlite/src/parse.c: $(srcdir)/libsqlite/src/parse.y
- @$(LEMON) $(srcdir)/libsqlite/src/parse.y
diff --git a/ext/sqlite/README b/ext/sqlite/README
deleted file mode 100644
index 2f6cbb0f87..0000000000
--- a/ext/sqlite/README
+++ /dev/null
@@ -1,14 +0,0 @@
-This is an extension for the SQLite Embeddable SQL Database Engine.
-http://www.sqlite.org/
-
-SQLite is a C library that implements an embeddable SQL database engine.
-Programs that link with the SQLite library can have SQL database access
-without running a separate RDBMS process.
-
-SQLite is not a client library used to connect to a big database server.
-SQLite is the server. The SQLite library reads and writes directly to and from
-the database files on disk
-
-
-
-vim:tw=78:et
diff --git a/ext/sqlite/TODO b/ext/sqlite/TODO
deleted file mode 100644
index 45903cf8d1..0000000000
--- a/ext/sqlite/TODO
+++ /dev/null
@@ -1,19 +0,0 @@
-- Implement a PDO driver, called sqlite2
-
-- Transparent binary encoding of return values from PHP callback functions.
-
-- Add user-space callback for the authorizer function (this is potentially
- very slow, so it needs to be implemented carefully).
-
-- Add user-space callback to handle busy databases.
-
- o Test how robust we are when a user-space function is registered as
- a callback for a persistent connection in script A, then script B is
- called that doesn't register the callback but does make use of the
- function in an SQL query.
- --> Our test suite doesn't allow us to test persistent connections
- at this time :/
-
-- Use later version of built-in library
-
-vim:tw=78
diff --git a/ext/sqlite/config.m4 b/ext/sqlite/config.m4
deleted file mode 100644
index dbee55fa94..0000000000
--- a/ext/sqlite/config.m4
+++ /dev/null
@@ -1,157 +0,0 @@
-dnl $Id$
-dnl config.m4 for extension sqlite
-dnl vim:et:ts=2:sw=2
-
-PHP_ARG_WITH(sqlite, for sqlite support,
-[ --without-sqlite=DIR Do not include sqlite support. DIR is the sqlite base
- install directory [BUNDLED]], yes)
-
-PHP_ARG_ENABLE(sqlite-utf8, whether to enable UTF-8 support in sqlite (default: ISO-8859-1),
-[ --enable-sqlite-utf8 SQLite: Enable UTF-8 support for SQLite], no, no)
-
-
-
-dnl
-dnl PHP_PROG_LEMON
-dnl
-dnl Search for lemon binary and check its version
-dnl
-AC_DEFUN([PHP_PROG_LEMON],[
- # we only support certain lemon versions
- lemon_version_list="1.0"
-
- AC_CHECK_PROG(LEMON, lemon, lemon)
- if test "$LEMON"; then
- AC_CACHE_CHECK([for lemon version], php_cv_lemon_version, [
- lemon_version=`$LEMON -x 2>/dev/null | $SED -e 's/^.* //'`
- php_cv_lemon_version=invalid
- for lemon_check_version in $lemon_version_list; do
- if test "$lemon_version" = "$lemon_check_version"; then
- php_cv_lemon_version="$lemon_check_version (ok)"
- fi
- done
- ])
- else
- lemon_version=none
- fi
- case $php_cv_lemon_version in
- ""|invalid[)]
- lemon_msg="lemon versions supported for regeneration of libsqlite parsers: $lemon_version_list (found: $lemon_version)."
- AC_MSG_WARN([$lemon_msg])
- LEMON="exit 0;"
- ;;
- esac
- PHP_SUBST(LEMON)
-])
-
-
-if test "$PHP_SQLITE" != "no"; then
- if test "$PHP_PDO" != "no"; then
- PHP_CHECK_PDO_INCLUDES([], [AC_MSG_WARN([Cannot find php_pdo_driver.h.])])
- if test -n "$pdo_inc_path"; then
- AC_DEFINE([PHP_SQLITE2_HAVE_PDO], [1], [Have PDO])
- pdo_inc_path="-I$pdo_inc_path"
- fi
- fi
-
- if test "$PHP_SQLITE" != "yes"; then
- SEARCH_PATH="/usr/local /usr"
- SEARCH_FOR="/include/sqlite.h"
- if test -r $PHP_SQLITE/; then # path given as parameter
- SQLITE_DIR=$PHP_SQLITE
- else # search default path list
- AC_MSG_CHECKING([for sqlite files in default path])
- for i in $SEARCH_PATH ; do
- if test -r $i/$SEARCH_FOR; then
- SQLITE_DIR=$i
- AC_MSG_RESULT(found in $i)
- fi
- done
- fi
-
- if test -z "$SQLITE_DIR"; then
- AC_MSG_RESULT([not found])
- AC_MSG_ERROR([Please reinstall the sqlite distribution from http://www.sqlite.org])
- fi
-
- PHP_CHECK_LIBRARY(sqlite, sqlite_open, [
- PHP_ADD_LIBRARY_WITH_PATH(sqlite, $SQLITE_DIR/$PHP_LIBDIR, SQLITE_SHARED_LIBADD)
- PHP_ADD_INCLUDE($SQLITE_DIR/include)
- ],[
- AC_MSG_ERROR([wrong sqlite lib version or lib not found])
- ],[
- -L$SQLITE_DIR/$PHP_LIBDIR -lm
- ])
- SQLITE_MODULE_TYPE=external
- PHP_SQLITE_CFLAGS=$pdo_inc_path
- sqlite_extra_sources="libsqlite/src/encode.c"
- else
- # use bundled library
- PHP_PROG_LEMON
- SQLITE_MODULE_TYPE=builtin
- PHP_SQLITE_CFLAGS="-I@ext_srcdir@/libsqlite/src -I@ext_builddir@/libsqlite/src $pdo_inc_path"
- sqlite_extra_sources="libsqlite/src/opcodes.c \
- libsqlite/src/parse.c libsqlite/src/encode.c \
- libsqlite/src/auth.c libsqlite/src/btree.c libsqlite/src/build.c \
- libsqlite/src/delete.c libsqlite/src/expr.c libsqlite/src/func.c \
- libsqlite/src/hash.c libsqlite/src/insert.c libsqlite/src/main.c \
- libsqlite/src/os.c libsqlite/src/pager.c \
- libsqlite/src/printf.c libsqlite/src/random.c \
- libsqlite/src/select.c libsqlite/src/table.c libsqlite/src/tokenize.c \
- libsqlite/src/update.c libsqlite/src/util.c libsqlite/src/vdbe.c \
- libsqlite/src/attach.c libsqlite/src/btree_rb.c libsqlite/src/pragma.c \
- libsqlite/src/vacuum.c libsqlite/src/copy.c \
- libsqlite/src/vdbeaux.c libsqlite/src/date.c \
- libsqlite/src/where.c libsqlite/src/trigger.c"
- fi
- dnl
- dnl Common for both bundled/external
- dnl
- sqlite_sources="sqlite.c sess_sqlite.c pdo_sqlite2.c $sqlite_extra_sources"
- PHP_NEW_EXTENSION(sqlite, $sqlite_sources, $ext_shared,,$PHP_SQLITE_CFLAGS)
- PHP_ADD_EXTENSION_DEP(sqlite, spl, true)
- PHP_ADD_EXTENSION_DEP(sqlite, pdo, true)
-
- PHP_ADD_MAKEFILE_FRAGMENT
- PHP_SUBST(SQLITE_SHARED_LIBADD)
- PHP_INSTALL_HEADERS([$ext_builddir/libsqlite/src/sqlite.h])
-
- if test "$SQLITE_MODULE_TYPE" = "builtin"; then
- PHP_ADD_BUILD_DIR($ext_builddir/libsqlite/src, 1)
- AC_CHECK_SIZEOF(char *, 4)
- AC_DEFINE(SQLITE_PTR_SZ, SIZEOF_CHAR_P, [Size of a pointer])
- dnl use latin 1 for SQLite older than 2.8.9; the utf-8 handling
- dnl in funcs.c uses assert(), which is a bit silly and something
- dnl we want to avoid. This assert() was removed in SQLite 2.8.9.
- if test "$PHP_SQLITE_UTF8" = "yes"; then
- SQLITE_ENCODING="UTF8"
- AC_DEFINE(SQLITE_UTF8, 1, [ ])
- else
- SQLITE_ENCODING="ISO8859"
- fi
- PHP_SUBST(SQLITE_ENCODING)
-
- SQLITE_VERSION=`cat $ext_srcdir/libsqlite/VERSION`
- PHP_SUBST(SQLITE_VERSION)
-
- sed -e s/--VERS--/$SQLITE_VERSION/ -e s/--ENCODING--/$SQLITE_ENCODING/ $ext_srcdir/libsqlite/src/sqlite.h.in > $ext_builddir/libsqlite/src/sqlite.h
-
- if test "$ext_shared" = "no" || test "$ext_srcdir" != "$abs_srcdir"; then
- echo '#include <php_config.h>' > $ext_builddir/libsqlite/src/config.h
- else
- echo "#include \"$abs_builddir/config.h\"" > $ext_builddir/libsqlite/src/config.h
- fi
-
- cat >> $ext_builddir/libsqlite/src/config.h <<EOF
-#if ZTS
-# define THREADSAFE 1
-#endif
-#if !ZEND_DEBUG
-# define NDEBUG
-#endif
-EOF
- fi
-
- AC_CHECK_FUNCS(usleep nanosleep)
- AC_CHECK_HEADERS(time.h)
-fi
diff --git a/ext/sqlite/config.w32 b/ext/sqlite/config.w32
deleted file mode 100644
index 58d4ea7b9e..0000000000
--- a/ext/sqlite/config.w32
+++ /dev/null
@@ -1,39 +0,0 @@
-// $Id$
-// vim:ft=javascript
-
-ARG_WITH("sqlite", "SQLite support", "no");
-
-if (PHP_SQLITE != "no") {
- copy_and_subst(configure_module_dirname + "\\libsqlite\\src\\sqlite.h.in",
- configure_module_dirname + "\\libsqlite\\src\\sqlite.h", new Array(
- "--VERS--", file_get_contents(configure_module_dirname + "\\libsqlite\\VERSION").replace(new RegExp("[\r\n]+", "g"), ""),
- "--ENCODING--", "ISO8859"
- ));
-
- FSO.CopyFile(configure_module_dirname + "\\libsqlite\\src\\sqlite_config.w32.h",
- configure_module_dirname + "\\libsqlite\\src\\config.h");
-
- if (FSO.FileExists(configure_module_dirname + "\\..\\pdo\\php_pdo_driver.h")) {
- PHP_SQLITE2_PDO_CFLAGS = " /DPHP_SQLITE2_HAVE_PDO=1 /I " + configure_module_dirname + "\\..";
- ADD_EXTENSION_DEP('sqlite', 'pdo')
- } else {
- PHP_SQLITE2_PDO_CFLAGS = "";
- }
-
- EXTENSION("sqlite", "sqlite.c sess_sqlite.c pdo_sqlite2.c", null,
- "/D PHP_SQLITE_EXPORTS /I " + configure_module_dirname + "/libsqlite/src" +
- PHP_SQLITE2_PDO_CFLAGS);
-
-
- ADD_SOURCES(configure_module_dirname + "/libsqlite/src", "opcodes.c parse.c encode.c \
- auth.c btree.c build.c delete.c expr.c func.c hash.c insert.c \
- main.c os.c pager.c printf.c random.c select.c table.c tokenize.c \
- update.c util.c vdbe.c attach.c btree_rb.c pragma.c vacuum.c \
- copy.c where.c trigger.c vdbeaux.c date.c", "sqlite");
-
- AC_DEFINE("HAVE_SQLITE", 1, "SQLite support");
- if (!PHP_SQLITE_SHARED) {
- ADD_DEF_FILE(configure_module_dirname + "\\php_sqlite.def");
- }
- ADD_EXTENSION_DEP('sqlite', 'spl')
-}
diff --git a/ext/sqlite/libsqlite/README b/ext/sqlite/libsqlite/README
deleted file mode 100644
index 326f3aa1ac..0000000000
--- a/ext/sqlite/libsqlite/README
+++ /dev/null
@@ -1,37 +0,0 @@
-This directory contains source code to
-
- SQLite: An Embeddable SQL Database Engine
-
-To compile the project, first create a directory in which to place
-the build products. It is recommended, but not required, that the
-build directory be separate from the source directory. Cd into the
-build directory and then from the build directory run the configure
-script found at the root of the source tree. Then run "make".
-
-For example:
-
- tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
- mkdir bld ;# Build will occur in a sibling directory
- cd bld ;# Change to the build directory
- ../sqlite/configure ;# Run the configure script
- make ;# Run the makefile.
-
-The configure script uses autoconf 2.50 and libtool. If the configure
-script does not work out for you, there is a generic makefile named
-"Makefile.linux-gcc" in the top directory of the source tree that you
-can copy and edit to suite your needs. Comments on the generic makefile
-show what changes are needed.
-
-The linux binaries on the website are created using the generic makefile,
-not the configure script. The configure script is unmaintained. (You
-can volunteer to take over maintenance of the configure script, if you want!)
-The windows binaries on the website are created using MinGW32 configured
-as a cross-compiler running under Linux. For details, see the ./publish.sh
-script at the top-level of the source tree.
-
-Contacts:
-
- http://www.sqlite.org/
- http://www.hwaci.com/sw/sqlite/
- http://groups.yahoo.com/group/sqlite/
- drh@hwaci.com
diff --git a/ext/sqlite/libsqlite/VERSION b/ext/sqlite/libsqlite/VERSION
deleted file mode 100644
index 6ece8e7d51..0000000000
--- a/ext/sqlite/libsqlite/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-2.8.17
diff --git a/ext/sqlite/libsqlite/src/attach.c b/ext/sqlite/libsqlite/src/attach.c
deleted file mode 100644
index 4e445ec413..0000000000
--- a/ext/sqlite/libsqlite/src/attach.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
-** 2003 April 6
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code used to implement the ATTACH and DETACH commands.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** This routine is called by the parser to process an ATTACH statement:
-**
-** ATTACH DATABASE filename AS dbname
-**
-** The pFilename and pDbname arguments are the tokens that define the
-** filename and dbname in the ATTACH statement.
-*/
-void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
- Db *aNew;
- int rc, i;
- char *zFile, *zName;
- sqlite *db;
- Vdbe *v;
-
- v = sqliteGetVdbe(pParse);
- sqliteVdbeAddOp(v, OP_Halt, 0, 0);
- if( pParse->explain ) return;
- db = pParse->db;
- if( db->file_format<4 ){
- sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
- "older format master database", 0);
- pParse->rc = SQLITE_ERROR;
- return;
- }
- if( db->nDb>=MAX_ATTACHED+2 ){
- sqliteErrorMsg(pParse, "too many attached databases - max %d",
- MAX_ATTACHED);
- pParse->rc = SQLITE_ERROR;
- return;
- }
-
- zFile = 0;
- sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
- if( zFile==0 ) return;
- sqliteDequote(zFile);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
- sqliteFree(zFile);
- return;
- }
-#endif /* SQLITE_OMIT_AUTHORIZATION */
-
- zName = 0;
- sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
- if( zName==0 ) return;
- sqliteDequote(zName);
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
- sqliteErrorMsg(pParse, "database %z is already in use", zName);
- pParse->rc = SQLITE_ERROR;
- sqliteFree(zFile);
- return;
- }
- }
-
- if( db->aDb==db->aDbStatic ){
- aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
- if( aNew==0 ) return;
- memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
- }else{
- aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
- if( aNew==0 ) return;
- }
- db->aDb = aNew;
- aNew = &db->aDb[db->nDb++];
- memset(aNew, 0, sizeof(*aNew));
- sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
- sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
- sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
- sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
- aNew->zName = zName;
- rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
- if( rc ){
- sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
- }
-#if SQLITE_HAS_CODEC
- {
- extern int sqliteCodecAttach(sqlite*, int, void*, int);
- char *zKey = 0;
- int nKey;
- if( pKey && pKey->z && pKey->n ){
- sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
- sqliteDequote(zKey);
- nKey = strlen(zKey);
- }else{
- zKey = 0;
- nKey = 0;
- }
- sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
- }
-#endif
- sqliteFree(zFile);
- db->flags &= ~SQLITE_Initialized;
- if( pParse->nErr ) return;
- if( rc==SQLITE_OK ){
- rc = sqliteInit(pParse->db, &pParse->zErrMsg);
- }
- if( rc ){
- int i = db->nDb - 1;
- assert( i>=2 );
- if( db->aDb[i].pBt ){
- sqliteBtreeClose(db->aDb[i].pBt);
- db->aDb[i].pBt = 0;
- }
- sqliteResetInternalSchema(db, 0);
- pParse->nErr++;
- pParse->rc = SQLITE_ERROR;
- }
-}
-
-/*
-** This routine is called by the parser to process a DETACH statement:
-**
-** DETACH DATABASE dbname
-**
-** The pDbname argument is the name of the database in the DETACH statement.
-*/
-void sqliteDetach(Parse *pParse, Token *pDbname){
- int i;
- sqlite *db;
- Vdbe *v;
- Db *pDb;
-
- v = sqliteGetVdbe(pParse);
- sqliteVdbeAddOp(v, OP_Halt, 0, 0);
- if( pParse->explain ) return;
- db = pParse->db;
- for(i=0; i<db->nDb; i++){
- pDb = &db->aDb[i];
- if( pDb->pBt==0 || pDb->zName==0 ) continue;
- if( strlen(pDb->zName)!=pDbname->n ) continue;
- if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
- }
- if( i>=db->nDb ){
- sqliteErrorMsg(pParse, "no such database: %T", pDbname);
- return;
- }
- if( i<2 ){
- sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
- return;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
- return;
- }
-#endif /* SQLITE_OMIT_AUTHORIZATION */
- sqliteBtreeClose(pDb->pBt);
- pDb->pBt = 0;
- sqliteFree(pDb->zName);
- sqliteResetInternalSchema(db, i);
- if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
- db->nDb--;
- if( i<db->nDb ){
- db->aDb[i] = db->aDb[db->nDb];
- memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
- sqliteResetInternalSchema(db, i);
- }
-}
-
-/*
-** Initialize a DbFixer structure. This routine must be called prior
-** to passing the structure to one of the sqliteFixAAAA() routines below.
-**
-** The return value indicates whether or not fixation is required. TRUE
-** means we do need to fix the database references, FALSE means we do not.
-*/
-int sqliteFixInit(
- DbFixer *pFix, /* The fixer to be initialized */
- Parse *pParse, /* Error messages will be written here */
- int iDb, /* This is the database that must must be used */
- const char *zType, /* "view", "trigger", or "index" */
- const Token *pName /* Name of the view, trigger, or index */
-){
- sqlite *db;
-
- if( iDb<0 || iDb==1 ) return 0;
- db = pParse->db;
- assert( db->nDb>iDb );
- pFix->pParse = pParse;
- pFix->zDb = db->aDb[iDb].zName;
- pFix->zType = zType;
- pFix->pName = pName;
- return 1;
-}
-
-/*
-** The following set of routines walk through the parse tree and assign
-** a specific database to all table references where the database name
-** was left unspecified in the original SQL statement. The pFix structure
-** must have been initialized by a prior call to sqliteFixInit().
-**
-** These routines are used to make sure that an index, trigger, or
-** view in one database does not refer to objects in a different database.
-** (Exception: indices, triggers, and views in the TEMP database are
-** allowed to refer to anything.) If a reference is explicitly made
-** to an object in a different database, an error message is added to
-** pParse->zErrMsg and these routines return non-zero. If everything
-** checks out, these routines return 0.
-*/
-int sqliteFixSrcList(
- DbFixer *pFix, /* Context of the fixation */
- SrcList *pList /* The Source list to check and modify */
-){
- int i;
- const char *zDb;
-
- if( pList==0 ) return 0;
- zDb = pFix->zDb;
- for(i=0; i<pList->nSrc; i++){
- if( pList->a[i].zDatabase==0 ){
- pList->a[i].zDatabase = sqliteStrDup(zDb);
- }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
- sqliteErrorMsg(pFix->pParse,
- "%s %z cannot reference objects in database %s",
- pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
- pList->a[i].zDatabase);
- return 1;
- }
- if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
- if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
- }
- return 0;
-}
-int sqliteFixSelect(
- DbFixer *pFix, /* Context of the fixation */
- Select *pSelect /* The SELECT statement to be fixed to one database */
-){
- while( pSelect ){
- if( sqliteFixExprList(pFix, pSelect->pEList) ){
- return 1;
- }
- if( sqliteFixSrcList(pFix, pSelect->pSrc) ){
- return 1;
- }
- if( sqliteFixExpr(pFix, pSelect->pWhere) ){
- return 1;
- }
- if( sqliteFixExpr(pFix, pSelect->pHaving) ){
- return 1;
- }
- pSelect = pSelect->pPrior;
- }
- return 0;
-}
-int sqliteFixExpr(
- DbFixer *pFix, /* Context of the fixation */
- Expr *pExpr /* The expression to be fixed to one database */
-){
- while( pExpr ){
- if( sqliteFixSelect(pFix, pExpr->pSelect) ){
- return 1;
- }
- if( sqliteFixExprList(pFix, pExpr->pList) ){
- return 1;
- }
- if( sqliteFixExpr(pFix, pExpr->pRight) ){
- return 1;
- }
- pExpr = pExpr->pLeft;
- }
- return 0;
-}
-int sqliteFixExprList(
- DbFixer *pFix, /* Context of the fixation */
- ExprList *pList /* The expression to be fixed to one database */
-){
- int i;
- if( pList==0 ) return 0;
- for(i=0; i<pList->nExpr; i++){
- if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){
- return 1;
- }
- }
- return 0;
-}
-int sqliteFixTriggerStep(
- DbFixer *pFix, /* Context of the fixation */
- TriggerStep *pStep /* The trigger step be fixed to one database */
-){
- while( pStep ){
- if( sqliteFixSelect(pFix, pStep->pSelect) ){
- return 1;
- }
- if( sqliteFixExpr(pFix, pStep->pWhere) ){
- return 1;
- }
- if( sqliteFixExprList(pFix, pStep->pExprList) ){
- return 1;
- }
- pStep = pStep->pNext;
- }
- return 0;
-}
diff --git a/ext/sqlite/libsqlite/src/auth.c b/ext/sqlite/libsqlite/src/auth.c
deleted file mode 100644
index 040488077c..0000000000
--- a/ext/sqlite/libsqlite/src/auth.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-** 2003 January 11
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code used to implement the sqlite_set_authorizer()
-** API. This facility is an optional feature of the library. Embedded
-** systems that do not need this facility may omit it by recompiling
-** the library with -DSQLITE_OMIT_AUTHORIZATION=1
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** All of the code in this file may be omitted by defining a single
-** macro.
-*/
-#ifndef SQLITE_OMIT_AUTHORIZATION
-
-/*
-** Set or clear the access authorization function.
-**
-** The access authorization function is be called during the compilation
-** phase to verify that the user has read and/or write access permission on
-** various fields of the database. The first argument to the auth function
-** is a copy of the 3rd argument to this routine. The second argument
-** to the auth function is one of these constants:
-**
-** SQLITE_COPY
-** SQLITE_CREATE_INDEX
-** SQLITE_CREATE_TABLE
-** SQLITE_CREATE_TEMP_INDEX
-** SQLITE_CREATE_TEMP_TABLE
-** SQLITE_CREATE_TEMP_TRIGGER
-** SQLITE_CREATE_TEMP_VIEW
-** SQLITE_CREATE_TRIGGER
-** SQLITE_CREATE_VIEW
-** SQLITE_DELETE
-** SQLITE_DROP_INDEX
-** SQLITE_DROP_TABLE
-** SQLITE_DROP_TEMP_INDEX
-** SQLITE_DROP_TEMP_TABLE
-** SQLITE_DROP_TEMP_TRIGGER
-** SQLITE_DROP_TEMP_VIEW
-** SQLITE_DROP_TRIGGER
-** SQLITE_DROP_VIEW
-** SQLITE_INSERT
-** SQLITE_PRAGMA
-** SQLITE_READ
-** SQLITE_SELECT
-** SQLITE_TRANSACTION
-** SQLITE_UPDATE
-**
-** The third and fourth arguments to the auth function are the name of
-** the table and the column that are being accessed. The auth function
-** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If
-** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY
-** means that the SQL statement will never-run - the sqlite_exec() call
-** will return with an error. SQLITE_IGNORE means that the SQL statement
-** should run but attempts to read the specified column will return NULL
-** and attempts to write the column will be ignored.
-**
-** Setting the auth function to NULL disables this hook. The default
-** setting of the auth function is NULL.
-*/
-int sqlite_set_authorizer(
- sqlite *db,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pArg
-){
- db->xAuth = xAuth;
- db->pAuthArg = pArg;
- return SQLITE_OK;
-}
-
-/*
-** Write an error message into pParse->zErrMsg that explains that the
-** user-supplied authorization function returned an illegal value.
-*/
-static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
- sqliteErrorMsg(pParse, "illegal return value (%d) from the "
- "authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
- "or SQLITE_DENY", rc);
- pParse->rc = SQLITE_MISUSE;
-}
-
-/*
-** The pExpr should be a TK_COLUMN expression. The table referred to
-** is in pTabList or else it is the NEW or OLD table of a trigger.
-** Check to see if it is OK to read this particular column.
-**
-** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
-** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
-** then generate an error.
-*/
-void sqliteAuthRead(
- Parse *pParse, /* The parser context */
- Expr *pExpr, /* The expression to check authorization on */
- SrcList *pTabList /* All table that pExpr might refer to */
-){
- sqlite *db = pParse->db;
- int rc;
- Table *pTab; /* The table being read */
- const char *zCol; /* Name of the column of the table */
- int iSrc; /* Index in pTabList->a[] of table being read */
- const char *zDBase; /* Name of database being accessed */
- TriggerStack *pStack; /* The stack of current triggers */
-
- if( db->xAuth==0 ) return;
- assert( pExpr->op==TK_COLUMN );
- for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
- if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
- }
- if( iSrc>=0 && iSrc<pTabList->nSrc ){
- pTab = pTabList->a[iSrc].pTab;
- }else if( (pStack = pParse->trigStack)!=0 ){
- /* This must be an attempt to read the NEW or OLD pseudo-tables
- ** of a trigger.
- */
- assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
- pTab = pStack->pTab;
- }else{
- return;
- }
- if( pTab==0 ) return;
- if( pExpr->iColumn>=0 ){
- assert( pExpr->iColumn<pTab->nCol );
- zCol = pTab->aCol[pExpr->iColumn].zName;
- }else if( pTab->iPKey>=0 ){
- assert( pTab->iPKey<pTab->nCol );
- zCol = pTab->aCol[pTab->iPKey].zName;
- }else{
- zCol = "ROWID";
- }
- assert( pExpr->iDb<db->nDb );
- zDBase = db->aDb[pExpr->iDb].zName;
- rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase,
- pParse->zAuthContext);
- if( rc==SQLITE_IGNORE ){
- pExpr->op = TK_NULL;
- }else if( rc==SQLITE_DENY ){
- if( db->nDb>2 || pExpr->iDb!=0 ){
- sqliteErrorMsg(pParse, "access to %s.%s.%s is prohibited",
- zDBase, pTab->zName, zCol);
- }else{
- sqliteErrorMsg(pParse, "access to %s.%s is prohibited", pTab->zName,zCol);
- }
- pParse->rc = SQLITE_AUTH;
- }else if( rc!=SQLITE_OK ){
- sqliteAuthBadReturnCode(pParse, rc);
- }
-}
-
-/*
-** Do an authorization check using the code and arguments given. Return
-** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
-** is returned, then the error count and error message in pParse are
-** modified appropriately.
-*/
-int sqliteAuthCheck(
- Parse *pParse,
- int code,
- const char *zArg1,
- const char *zArg2,
- const char *zArg3
-){
- sqlite *db = pParse->db;
- int rc;
-
- if( db->init.busy || db->xAuth==0 ){
- return SQLITE_OK;
- }
- rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
- if( rc==SQLITE_DENY ){
- sqliteErrorMsg(pParse, "not authorized");
- pParse->rc = SQLITE_AUTH;
- }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
- rc = SQLITE_DENY;
- sqliteAuthBadReturnCode(pParse, rc);
- }
- return rc;
-}
-
-/*
-** Push an authorization context. After this routine is called, the
-** zArg3 argument to authorization callbacks will be zContext until
-** popped. Or if pParse==0, this routine is a no-op.
-*/
-void sqliteAuthContextPush(
- Parse *pParse,
- AuthContext *pContext,
- const char *zContext
-){
- pContext->pParse = pParse;
- if( pParse ){
- pContext->zAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = zContext;
- }
-}
-
-/*
-** Pop an authorization context that was previously pushed
-** by sqliteAuthContextPush
-*/
-void sqliteAuthContextPop(AuthContext *pContext){
- if( pContext->pParse ){
- pContext->pParse->zAuthContext = pContext->zAuthContext;
- pContext->pParse = 0;
- }
-}
-
-#endif /* SQLITE_OMIT_AUTHORIZATION */
diff --git a/ext/sqlite/libsqlite/src/btree.c b/ext/sqlite/libsqlite/src/btree.c
deleted file mode 100644
index a367092501..0000000000
--- a/ext/sqlite/libsqlite/src/btree.c
+++ /dev/null
@@ -1,3584 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** $Id$
-**
-** This file implements a external (disk-based) database using BTrees.
-** For a detailed discussion of BTrees, refer to
-**
-** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
-** "Sorting And Searching", pages 473-480. Addison-Wesley
-** Publishing Company, Reading, Massachusetts.
-**
-** The basic idea is that each page of the file contains N database
-** entries and N+1 pointers to subpages.
-**
-** ----------------------------------------------------------------
-** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N) | Ptr(N+1) |
-** ----------------------------------------------------------------
-**
-** All of the keys on the page that Ptr(0) points to have values less
-** than Key(0). All of the keys on page Ptr(1) and its subpages have
-** values greater than Key(0) and less than Key(1). All of the keys
-** on Ptr(N+1) and its subpages have values greater than Key(N). And
-** so forth.
-**
-** Finding a particular key requires reading O(log(M)) pages from the
-** disk where M is the number of entries in the tree.
-**
-** In this implementation, a single file can hold one or more separate
-** BTrees. Each BTree is identified by the index of its root page. The
-** key and data for any entry are combined to form the "payload". Up to
-** MX_LOCAL_PAYLOAD bytes of payload can be carried directly on the
-** database page. If the payload is larger than MX_LOCAL_PAYLOAD bytes
-** then surplus bytes are stored on overflow pages. The payload for an
-** entry and the preceding pointer are combined to form a "Cell". Each
-** page has a small header which contains the Ptr(N+1) pointer.
-**
-** The first page of the file contains a magic string used to verify that
-** the file really is a valid BTree database, a pointer to a list of unused
-** pages in the file, and some meta information. The root of the first
-** BTree begins on page 2 of the file. (Pages are numbered beginning with
-** 1, not 0.) Thus a minimum database contains 2 pages.
-*/
-#include "sqliteInt.h"
-#include "pager.h"
-#include "btree.h"
-#include <assert.h>
-
-/* Forward declarations */
-static BtOps sqliteBtreeOps;
-static BtCursorOps sqliteBtreeCursorOps;
-
-/*
-** Macros used for byteswapping. B is a pointer to the Btree
-** structure. This is needed to access the Btree.needSwab boolean
-** in order to tell if byte swapping is needed or not.
-** X is an unsigned integer. SWAB16 byte swaps a 16-bit integer.
-** SWAB32 byteswaps a 32-bit integer.
-*/
-#define SWAB16(B,X) ((B)->needSwab? swab16((u16)X) : ((u16)X))
-#define SWAB32(B,X) ((B)->needSwab? swab32(X) : (X))
-#define SWAB_ADD(B,X,A) \
- if((B)->needSwab){ X=swab32(swab32(X)+A); }else{ X += (A); }
-
-/*
-** The following global variable - available only if SQLITE_TEST is
-** defined - is used to determine whether new databases are created in
-** native byte order or in non-native byte order. Non-native byte order
-** databases are created for testing purposes only. Under normal operation,
-** only native byte-order databases should be created, but we should be
-** able to read or write existing databases regardless of the byteorder.
-*/
-#ifdef SQLITE_TEST
-int btree_native_byte_order = 1;
-#else
-# define btree_native_byte_order 1
-#endif
-
-/*
-** Forward declarations of structures used only in this file.
-*/
-typedef struct PageOne PageOne;
-typedef struct MemPage MemPage;
-typedef struct PageHdr PageHdr;
-typedef struct Cell Cell;
-typedef struct CellHdr CellHdr;
-typedef struct FreeBlk FreeBlk;
-typedef struct OverflowPage OverflowPage;
-typedef struct FreelistInfo FreelistInfo;
-
-/*
-** All structures on a database page are aligned to 4-byte boundries.
-** This routine rounds up a number of bytes to the next multiple of 4.
-**
-** This might need to change for computer architectures that require
-** and 8-byte alignment boundry for structures.
-*/
-#define ROUNDUP(X) ((X+3) & ~3)
-
-/*
-** This is a magic string that appears at the beginning of every
-** SQLite database in order to identify the file as a real database.
-*/
-static const char zMagicHeader[] =
- "** This file contains an SQLite 2.1 database **";
-#define MAGIC_SIZE (sizeof(zMagicHeader))
-
-/*
-** This is a magic integer also used to test the integrity of the database
-** file. This integer is used in addition to the string above so that
-** if the file is written on a little-endian architecture and read
-** on a big-endian architectures (or vice versa) we can detect the
-** problem.
-**
-** The number used was obtained at random and has no special
-** significance other than the fact that it represents a different
-** integer on little-endian and big-endian machines.
-*/
-#define MAGIC 0xdae37528
-
-/*
-** The first page of the database file contains a magic header string
-** to identify the file as an SQLite database file. It also contains
-** a pointer to the first free page of the file. Page 2 contains the
-** root of the principle BTree. The file might contain other BTrees
-** rooted on pages above 2.
-**
-** The first page also contains SQLITE_N_BTREE_META integers that
-** can be used by higher-level routines.
-**
-** Remember that pages are numbered beginning with 1. (See pager.c
-** for additional information.) Page 0 does not exist and a page
-** number of 0 is used to mean "no such page".
-*/
-struct PageOne {
- char zMagic[MAGIC_SIZE]; /* String that identifies the file as a database */
- int iMagic; /* Integer to verify correct byte order */
- Pgno freeList; /* First free page in a list of all free pages */
- int nFree; /* Number of pages on the free list */
- int aMeta[SQLITE_N_BTREE_META-1]; /* User defined integers */
-};
-
-/*
-** Each database page has a header that is an instance of this
-** structure.
-**
-** PageHdr.firstFree is 0 if there is no free space on this page.
-** Otherwise, PageHdr.firstFree is the index in MemPage.u.aDisk[] of a
-** FreeBlk structure that describes the first block of free space.
-** All free space is defined by a linked list of FreeBlk structures.
-**
-** Data is stored in a linked list of Cell structures. PageHdr.firstCell
-** is the index into MemPage.u.aDisk[] of the first cell on the page. The
-** Cells are kept in sorted order.
-**
-** A Cell contains all information about a database entry and a pointer
-** to a child page that contains other entries less than itself. In
-** other words, the i-th Cell contains both Ptr(i) and Key(i). The
-** right-most pointer of the page is contained in PageHdr.rightChild.
-*/
-struct PageHdr {
- Pgno rightChild; /* Child page that comes after all cells on this page */
- u16 firstCell; /* Index in MemPage.u.aDisk[] of the first cell */
- u16 firstFree; /* Index in MemPage.u.aDisk[] of the first free block */
-};
-
-/*
-** Entries on a page of the database are called "Cells". Each Cell
-** has a header and data. This structure defines the header. The
-** key and data (collectively the "payload") follow this header on
-** the database page.
-**
-** A definition of the complete Cell structure is given below. The
-** header for the cell must be defined first in order to do some
-** of the sizing #defines that follow.
-*/
-struct CellHdr {
- Pgno leftChild; /* Child page that comes before this cell */
- u16 nKey; /* Number of bytes in the key */
- u16 iNext; /* Index in MemPage.u.aDisk[] of next cell in sorted order */
- u8 nKeyHi; /* Upper 8 bits of key size for keys larger than 64K bytes */
- u8 nDataHi; /* Upper 8 bits of data size when the size is more than 64K */
- u16 nData; /* Number of bytes of data */
-};
-
-/*
-** The key and data size are split into a lower 16-bit segment and an
-** upper 8-bit segment in order to pack them together into a smaller
-** space. The following macros reassembly a key or data size back
-** into an integer.
-*/
-#define NKEY(b,h) (SWAB16(b,h.nKey) + h.nKeyHi*65536)
-#define NDATA(b,h) (SWAB16(b,h.nData) + h.nDataHi*65536)
-
-/*
-** The minimum size of a complete Cell. The Cell must contain a header
-** and at least 4 bytes of payload.
-*/
-#define MIN_CELL_SIZE (sizeof(CellHdr)+4)
-
-/*
-** The maximum number of database entries that can be held in a single
-** page of the database.
-*/
-#define MX_CELL ((SQLITE_USABLE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE)
-
-/*
-** The amount of usable space on a single page of the BTree. This is the
-** page size minus the overhead of the page header.
-*/
-#define USABLE_SPACE (SQLITE_USABLE_SIZE - sizeof(PageHdr))
-
-/*
-** The maximum amount of payload (in bytes) that can be stored locally for
-** a database entry. If the entry contains more data than this, the
-** extra goes onto overflow pages.
-**
-** This number is chosen so that at least 4 cells will fit on every page.
-*/
-#define MX_LOCAL_PAYLOAD ((USABLE_SPACE/4-(sizeof(CellHdr)+sizeof(Pgno)))&~3)
-
-/*
-** Data on a database page is stored as a linked list of Cell structures.
-** Both the key and the data are stored in aPayload[]. The key always comes
-** first. The aPayload[] field grows as necessary to hold the key and data,
-** up to a maximum of MX_LOCAL_PAYLOAD bytes. If the size of the key and
-** data combined exceeds MX_LOCAL_PAYLOAD bytes, then Cell.ovfl is the
-** page number of the first overflow page.
-**
-** Though this structure is fixed in size, the Cell on the database
-** page varies in size. Every cell has a CellHdr and at least 4 bytes
-** of payload space. Additional payload bytes (up to the maximum of
-** MX_LOCAL_PAYLOAD) and the Cell.ovfl value are allocated only as
-** needed.
-*/
-struct Cell {
- CellHdr h; /* The cell header */
- char aPayload[MX_LOCAL_PAYLOAD]; /* Key and data */
- Pgno ovfl; /* The first overflow page */
-};
-
-/*
-** Free space on a page is remembered using a linked list of the FreeBlk
-** structures. Space on a database page is allocated in increments of
-** at least 4 bytes and is always aligned to a 4-byte boundry. The
-** linked list of FreeBlks is always kept in order by address.
-*/
-struct FreeBlk {
- u16 iSize; /* Number of bytes in this block of free space */
- u16 iNext; /* Index in MemPage.u.aDisk[] of the next free block */
-};
-
-/*
-** The number of bytes of payload that will fit on a single overflow page.
-*/
-#define OVERFLOW_SIZE (SQLITE_USABLE_SIZE-sizeof(Pgno))
-
-/*
-** When the key and data for a single entry in the BTree will not fit in
-** the MX_LOCAL_PAYLOAD bytes of space available on the database page,
-** then all extra bytes are written to a linked list of overflow pages.
-** Each overflow page is an instance of the following structure.
-**
-** Unused pages in the database are also represented by instances of
-** the OverflowPage structure. The PageOne.freeList field is the
-** page number of the first page in a linked list of unused database
-** pages.
-*/
-struct OverflowPage {
- Pgno iNext;
- char aPayload[OVERFLOW_SIZE];
-};
-
-/*
-** The PageOne.freeList field points to a linked list of overflow pages
-** hold information about free pages. The aPayload section of each
-** overflow page contains an instance of the following structure. The
-** aFree[] array holds the page number of nFree unused pages in the disk
-** file.
-*/
-struct FreelistInfo {
- int nFree;
- Pgno aFree[(OVERFLOW_SIZE-sizeof(int))/sizeof(Pgno)];
-};
-
-/*
-** For every page in the database file, an instance of the following structure
-** is stored in memory. The u.aDisk[] array contains the raw bits read from
-** the disk. The rest is auxiliary information held in memory only. The
-** auxiliary info is only valid for regular database pages - it is not
-** used for overflow pages and pages on the freelist.
-**
-** Of particular interest in the auxiliary info is the apCell[] entry. Each
-** apCell[] entry is a pointer to a Cell structure in u.aDisk[]. The cells are
-** put in this array so that they can be accessed in constant time, rather
-** than in linear time which would be needed if we had to walk the linked
-** list on every access.
-**
-** Note that apCell[] contains enough space to hold up to two more Cells
-** than can possibly fit on one page. In the steady state, every apCell[]
-** points to memory inside u.aDisk[]. But in the middle of an insert
-** operation, some apCell[] entries may temporarily point to data space
-** outside of u.aDisk[]. This is a transient situation that is quickly
-** resolved. But while it is happening, it is possible for a database
-** page to hold as many as two more cells than it might otherwise hold.
-** The extra two entries in apCell[] are an allowance for this situation.
-**
-** The pParent field points back to the parent page. This allows us to
-** walk up the BTree from any leaf to the root. Care must be taken to
-** unref() the parent page pointer when this page is no longer referenced.
-** The pageDestructor() routine handles that chore.
-*/
-struct MemPage {
- union u_page_data {
- char aDisk[SQLITE_PAGE_SIZE]; /* Page data stored on disk */
- PageHdr hdr; /* Overlay page header */
- } u;
- u8 isInit; /* True if auxiliary data is initialized */
- u8 idxShift; /* True if apCell[] indices have changed */
- u8 isOverfull; /* Some apCell[] points outside u.aDisk[] */
- MemPage *pParent; /* The parent of this page. NULL for root */
- int idxParent; /* Index in pParent->apCell[] of this node */
- int nFree; /* Number of free bytes in u.aDisk[] */
- int nCell; /* Number of entries on this page */
- Cell *apCell[MX_CELL+2]; /* All data entires in sorted order */
-};
-
-/*
-** The in-memory image of a disk page has the auxiliary information appended
-** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
-** that extra information.
-*/
-#define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data))
-
-/*
-** Everything we need to know about an open database
-*/
-struct Btree {
- BtOps *pOps; /* Function table */
- Pager *pPager; /* The page cache */
- BtCursor *pCursor; /* A list of all open cursors */
- PageOne *page1; /* First page of the database */
- u8 inTrans; /* True if a transaction is in progress */
- u8 inCkpt; /* True if there is a checkpoint on the transaction */
- u8 readOnly; /* True if the underlying file is readonly */
- u8 needSwab; /* Need to byte-swapping */
-};
-typedef Btree Bt;
-
-/*
-** A cursor is a pointer to a particular entry in the BTree.
-** The entry is identified by its MemPage and the index in
-** MemPage.apCell[] of the entry.
-*/
-struct BtCursor {
- BtCursorOps *pOps; /* Function table */
- Btree *pBt; /* The Btree to which this cursor belongs */
- BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
- BtCursor *pShared; /* Loop of cursors with the same root page */
- Pgno pgnoRoot; /* The root page of this tree */
- MemPage *pPage; /* Page that contains the entry */
- int idx; /* Index of the entry in pPage->apCell[] */
- u8 wrFlag; /* True if writable */
- u8 eSkip; /* Determines if next step operation is a no-op */
- u8 iMatch; /* compare result from last sqliteBtreeMoveto() */
-};
-
-/*
-** Legal values for BtCursor.eSkip.
-*/
-#define SKIP_NONE 0 /* Always step the cursor */
-#define SKIP_NEXT 1 /* The next sqliteBtreeNext() is a no-op */
-#define SKIP_PREV 2 /* The next sqliteBtreePrevious() is a no-op */
-#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */
-
-/* Forward declarations */
-static int fileBtreeCloseCursor(BtCursor *pCur);
-
-/*
-** Routines for byte swapping.
-*/
-u16 swab16(u16 x){
- return ((x & 0xff)<<8) | ((x>>8)&0xff);
-}
-u32 swab32(u32 x){
- return ((x & 0xff)<<24) | ((x & 0xff00)<<8) |
- ((x>>8) & 0xff00) | ((x>>24)&0xff);
-}
-
-/*
-** Compute the total number of bytes that a Cell needs on the main
-** database page. The number returned includes the Cell header,
-** local payload storage, and the pointer to overflow pages (if
-** applicable). Additional space allocated on overflow pages
-** is NOT included in the value returned from this routine.
-*/
-static int cellSize(Btree *pBt, Cell *pCell){
- int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
- if( n>MX_LOCAL_PAYLOAD ){
- n = MX_LOCAL_PAYLOAD + sizeof(Pgno);
- }else{
- n = ROUNDUP(n);
- }
- n += sizeof(CellHdr);
- return n;
-}
-
-/*
-** Defragment the page given. All Cells are moved to the
-** beginning of the page and all free space is collected
-** into one big FreeBlk at the end of the page.
-*/
-static void defragmentPage(Btree *pBt, MemPage *pPage){
- int pc, i, n;
- FreeBlk *pFBlk;
- char newPage[SQLITE_USABLE_SIZE];
-
- assert( sqlitepager_iswriteable(pPage) );
- assert( pPage->isInit );
- pc = sizeof(PageHdr);
- pPage->u.hdr.firstCell = SWAB16(pBt, pc);
- memcpy(newPage, pPage->u.aDisk, pc);
- for(i=0; i<pPage->nCell; i++){
- Cell *pCell = pPage->apCell[i];
-
- /* This routine should never be called on an overfull page. The
- ** following asserts verify that constraint. */
- assert( Addr(pCell) > Addr(pPage) );
- assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE );
-
- n = cellSize(pBt, pCell);
- pCell->h.iNext = SWAB16(pBt, pc + n);
- memcpy(&newPage[pc], pCell, n);
- pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc];
- pc += n;
- }
- assert( pPage->nFree==SQLITE_USABLE_SIZE-pc );
- memcpy(pPage->u.aDisk, newPage, pc);
- if( pPage->nCell>0 ){
- pPage->apCell[pPage->nCell-1]->h.iNext = 0;
- }
- pFBlk = (FreeBlk*)&pPage->u.aDisk[pc];
- pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc);
- pFBlk->iNext = 0;
- pPage->u.hdr.firstFree = SWAB16(pBt, pc);
- memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk));
-}
-
-/*
-** Allocate nByte bytes of space on a page. nByte must be a
-** multiple of 4.
-**
-** Return the index into pPage->u.aDisk[] of the first byte of
-** the new allocation. Or return 0 if there is not enough free
-** space on the page to satisfy the allocation request.
-**
-** If the page contains nBytes of free space but does not contain
-** nBytes of contiguous free space, then this routine automatically
-** calls defragementPage() to consolidate all free space before
-** allocating the new chunk.
-*/
-static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){
- FreeBlk *p;
- u16 *pIdx;
- int start;
- int iSize;
-#ifndef NDEBUG
- int cnt = 0;
-#endif
-
- assert( sqlitepager_iswriteable(pPage) );
- assert( nByte==ROUNDUP(nByte) );
- assert( pPage->isInit );
- if( pPage->nFree<nByte || pPage->isOverfull ) return 0;
- pIdx = &pPage->u.hdr.firstFree;
- p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
- while( (iSize = SWAB16(pBt, p->iSize))<nByte ){
- assert( cnt++ < SQLITE_USABLE_SIZE/4 );
- if( p->iNext==0 ){
- defragmentPage(pBt, pPage);
- pIdx = &pPage->u.hdr.firstFree;
- }else{
- pIdx = &p->iNext;
- }
- p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
- }
- if( iSize==nByte ){
- start = SWAB16(pBt, *pIdx);
- *pIdx = p->iNext;
- }else{
- FreeBlk *pNew;
- start = SWAB16(pBt, *pIdx);
- pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
- pNew->iNext = p->iNext;
- pNew->iSize = SWAB16(pBt, iSize - nByte);
- *pIdx = SWAB16(pBt, start + nByte);
- }
- pPage->nFree -= nByte;
- return start;
-}
-
-/*
-** Return a section of the MemPage.u.aDisk[] to the freelist.
-** The first byte of the new free block is pPage->u.aDisk[start]
-** and the size of the block is "size" bytes. Size must be
-** a multiple of 4.
-**
-** Most of the effort here is involved in coalesing adjacent
-** free blocks into a single big free block.
-*/
-static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){
- int end = start + size;
- u16 *pIdx, idx;
- FreeBlk *pFBlk;
- FreeBlk *pNew;
- FreeBlk *pNext;
- int iSize;
-
- assert( sqlitepager_iswriteable(pPage) );
- assert( size == ROUNDUP(size) );
- assert( start == ROUNDUP(start) );
- assert( pPage->isInit );
- pIdx = &pPage->u.hdr.firstFree;
- idx = SWAB16(pBt, *pIdx);
- while( idx!=0 && idx<start ){
- pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
- iSize = SWAB16(pBt, pFBlk->iSize);
- if( idx + iSize == start ){
- pFBlk->iSize = SWAB16(pBt, iSize + size);
- if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){
- pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size];
- if( pBt->needSwab ){
- pFBlk->iSize = swab16((u16)swab16(pNext->iSize)+iSize+size);
- }else{
- pFBlk->iSize += pNext->iSize;
- }
- pFBlk->iNext = pNext->iNext;
- }
- pPage->nFree += size;
- return;
- }
- pIdx = &pFBlk->iNext;
- idx = SWAB16(pBt, *pIdx);
- }
- pNew = (FreeBlk*)&pPage->u.aDisk[start];
- if( idx != end ){
- pNew->iSize = SWAB16(pBt, size);
- pNew->iNext = SWAB16(pBt, idx);
- }else{
- pNext = (FreeBlk*)&pPage->u.aDisk[idx];
- pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize));
- pNew->iNext = pNext->iNext;
- }
- *pIdx = SWAB16(pBt, start);
- pPage->nFree += size;
-}
-
-/*
-** Initialize the auxiliary information for a disk block.
-**
-** The pParent parameter must be a pointer to the MemPage which
-** is the parent of the page being initialized. The root of the
-** BTree (usually page 2) has no parent and so for that page,
-** pParent==NULL.
-**
-** Return SQLITE_OK on success. If we see that the page does
-** not contain a well-formed database page, then return
-** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
-** guarantee that the page is well-formed. It only shows that
-** we failed to detect any corruption.
-*/
-static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
- int idx; /* An index into pPage->u.aDisk[] */
- Cell *pCell; /* A pointer to a Cell in pPage->u.aDisk[] */
- FreeBlk *pFBlk; /* A pointer to a free block in pPage->u.aDisk[] */
- int sz; /* The size of a Cell in bytes */
- int freeSpace; /* Amount of free space on the page */
-
- if( pPage->pParent ){
- assert( pPage->pParent==pParent );
- return SQLITE_OK;
- }
- if( pParent ){
- pPage->pParent = pParent;
- sqlitepager_ref(pParent);
- }
- if( pPage->isInit ) return SQLITE_OK;
- pPage->isInit = 1;
- pPage->nCell = 0;
- freeSpace = USABLE_SPACE;
- idx = SWAB16(pBt, pPage->u.hdr.firstCell);
- while( idx!=0 ){
- if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error;
- if( idx<sizeof(PageHdr) ) goto page_format_error;
- if( idx!=ROUNDUP(idx) ) goto page_format_error;
- pCell = (Cell*)&pPage->u.aDisk[idx];
- sz = cellSize(pBt, pCell);
- if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error;
- freeSpace -= sz;
- pPage->apCell[pPage->nCell++] = pCell;
- idx = SWAB16(pBt, pCell->h.iNext);
- }
- pPage->nFree = 0;
- idx = SWAB16(pBt, pPage->u.hdr.firstFree);
- while( idx!=0 ){
- int iNext;
- if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error;
- if( idx<sizeof(PageHdr) ) goto page_format_error;
- pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
- pPage->nFree += SWAB16(pBt, pFBlk->iSize);
- iNext = SWAB16(pBt, pFBlk->iNext);
- if( iNext>0 && iNext <= idx ) goto page_format_error;
- idx = iNext;
- }
- if( pPage->nCell==0 && pPage->nFree==0 ){
- /* As a special case, an uninitialized root page appears to be
- ** an empty database */
- return SQLITE_OK;
- }
- if( pPage->nFree!=freeSpace ) goto page_format_error;
- return SQLITE_OK;
-
-page_format_error:
- return SQLITE_CORRUPT;
-}
-
-/*
-** Set up a raw page so that it looks like a database page holding
-** no entries.
-*/
-static void zeroPage(Btree *pBt, MemPage *pPage){
- PageHdr *pHdr;
- FreeBlk *pFBlk;
- assert( sqlitepager_iswriteable(pPage) );
- memset(pPage, 0, SQLITE_USABLE_SIZE);
- pHdr = &pPage->u.hdr;
- pHdr->firstCell = 0;
- pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr));
- pFBlk = (FreeBlk*)&pHdr[1];
- pFBlk->iNext = 0;
- pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr);
- pFBlk->iSize = SWAB16(pBt, pPage->nFree);
- pPage->nCell = 0;
- pPage->isOverfull = 0;
-}
-
-/*
-** This routine is called when the reference count for a page
-** reaches zero. We need to unref the pParent pointer when that
-** happens.
-*/
-static void pageDestructor(void *pData){
- MemPage *pPage = (MemPage*)pData;
- if( pPage->pParent ){
- MemPage *pParent = pPage->pParent;
- pPage->pParent = 0;
- sqlitepager_unref(pParent);
- }
-}
-
-/*
-** Open a new database.
-**
-** Actually, this routine just sets up the internal data structures
-** for accessing the database. We do not open the database file
-** until the first page is loaded.
-**
-** zFilename is the name of the database file. If zFilename is NULL
-** a new database with a random name is created. This randomly named
-** database file will be deleted when sqliteBtreeClose() is called.
-*/
-int sqliteBtreeOpen(
- const char *zFilename, /* Name of the file containing the BTree database */
- int omitJournal, /* if TRUE then do not journal this file */
- int nCache, /* How many pages in the page cache */
- Btree **ppBtree /* Pointer to new Btree object written here */
-){
- Btree *pBt;
- int rc;
-
- /*
- ** The following asserts make sure that structures used by the btree are
- ** the right size. This is to guard against size changes that result
- ** when compiling on a different architecture.
- */
- assert( sizeof(u32)==4 );
- assert( sizeof(u16)==2 );
- assert( sizeof(Pgno)==4 );
- assert( sizeof(PageHdr)==8 );
- assert( sizeof(CellHdr)==12 );
- assert( sizeof(FreeBlk)==4 );
- assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE );
- assert( sizeof(FreelistInfo)==OVERFLOW_SIZE );
- assert( sizeof(ptr)==sizeof(char*) );
- assert( sizeof(uptr)==sizeof(ptr) );
-
- pBt = sqliteMalloc( sizeof(*pBt) );
- if( pBt==0 ){
- *ppBtree = 0;
- return SQLITE_NOMEM;
- }
- if( nCache<10 ) nCache = 10;
- rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE,
- !omitJournal);
- if( rc!=SQLITE_OK ){
- if( pBt->pPager ) sqlitepager_close(pBt->pPager);
- sqliteFree(pBt);
- *ppBtree = 0;
- return rc;
- }
- sqlitepager_set_destructor(pBt->pPager, pageDestructor);
- pBt->pCursor = 0;
- pBt->page1 = 0;
- pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
- pBt->pOps = &sqliteBtreeOps;
- *ppBtree = pBt;
- return SQLITE_OK;
-}
-
-/*
-** Close an open database and invalidate all cursors.
-*/
-static int fileBtreeClose(Btree *pBt){
- while( pBt->pCursor ){
- fileBtreeCloseCursor(pBt->pCursor);
- }
- sqlitepager_close(pBt->pPager);
- sqliteFree(pBt);
- return SQLITE_OK;
-}
-
-/*
-** Change the limit on the number of pages allowed in the cache.
-**
-** The maximum number of cache pages is set to the absolute
-** value of mxPage. If mxPage is negative, the pager will
-** operate asynchronously - it will not stop to do fsync()s
-** to insure data is written to the disk surface before
-** continuing. Transactions still work if synchronous is off,
-** and the database cannot be corrupted if this program
-** crashes. But if the operating system crashes or there is
-** an abrupt power failure when synchronous is off, the database
-** could be left in an inconsistent and unrecoverable state.
-** Synchronous is on by default so database corruption is not
-** normally a worry.
-*/
-static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){
- sqlitepager_set_cachesize(pBt->pPager, mxPage);
- return SQLITE_OK;
-}
-
-/*
-** Change the way data is synced to disk in order to increase or decrease
-** how well the database resists damage due to OS crashes and power
-** failures. Level 1 is the same as asynchronous (no syncs() occur and
-** there is a high probability of damage) Level 2 is the default. There
-** is a very low but non-zero probability of damage. Level 3 reduces the
-** probability of damage to near zero but with a write performance reduction.
-*/
-static int fileBtreeSetSafetyLevel(Btree *pBt, int level){
- sqlitepager_set_safety_level(pBt->pPager, level);
- return SQLITE_OK;
-}
-
-/*
-** Get a reference to page1 of the database file. This will
-** also acquire a readlock on that file.
-**
-** SQLITE_OK is returned on success. If the file is not a
-** well-formed database file, then SQLITE_CORRUPT is returned.
-** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
-** is returned if we run out of memory. SQLITE_PROTOCOL is returned
-** if there is a locking protocol violation.
-*/
-static int lockBtree(Btree *pBt){
- int rc;
- if( pBt->page1 ) return SQLITE_OK;
- rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1);
- if( rc!=SQLITE_OK ) return rc;
-
- /* Do some checking to help insure the file we opened really is
- ** a valid database file.
- */
- if( sqlitepager_pagecount(pBt->pPager)>0 ){
- PageOne *pP1 = pBt->page1;
- if( strcmp(pP1->zMagic,zMagicHeader)!=0 ||
- (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){
- rc = SQLITE_NOTADB;
- goto page1_init_failed;
- }
- pBt->needSwab = pP1->iMagic!=MAGIC;
- }
- return rc;
-
-page1_init_failed:
- sqlitepager_unref(pBt->page1);
- pBt->page1 = 0;
- return rc;
-}
-
-/*
-** If there are no outstanding cursors and we are not in the middle
-** of a transaction but there is a read lock on the database, then
-** this routine unrefs the first page of the database file which
-** has the effect of releasing the read lock.
-**
-** If there are any outstanding cursors, this routine is a no-op.
-**
-** If there is a transaction in progress, this routine is a no-op.
-*/
-static void unlockBtreeIfUnused(Btree *pBt){
- if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
- sqlitepager_unref(pBt->page1);
- pBt->page1 = 0;
- pBt->inTrans = 0;
- pBt->inCkpt = 0;
- }
-}
-
-/*
-** Create a new database by initializing the first two pages of the
-** file.
-*/
-static int newDatabase(Btree *pBt){
- MemPage *pRoot;
- PageOne *pP1;
- int rc;
- if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
- pP1 = pBt->page1;
- rc = sqlitepager_write(pBt->page1);
- if( rc ) return rc;
- rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot);
- if( rc ) return rc;
- rc = sqlitepager_write(pRoot);
- if( rc ){
- sqlitepager_unref(pRoot);
- return rc;
- }
- strcpy(pP1->zMagic, zMagicHeader);
- if( btree_native_byte_order ){
- pP1->iMagic = MAGIC;
- pBt->needSwab = 0;
- }else{
- pP1->iMagic = swab32(MAGIC);
- pBt->needSwab = 1;
- }
- zeroPage(pBt, pRoot);
- sqlitepager_unref(pRoot);
- return SQLITE_OK;
-}
-
-/*
-** Attempt to start a new transaction.
-**
-** A transaction must be started before attempting any changes
-** to the database. None of the following routines will work
-** unless a transaction is started first:
-**
-** sqliteBtreeCreateTable()
-** sqliteBtreeCreateIndex()
-** sqliteBtreeClearTable()
-** sqliteBtreeDropTable()
-** sqliteBtreeInsert()
-** sqliteBtreeDelete()
-** sqliteBtreeUpdateMeta()
-*/
-static int fileBtreeBeginTrans(Btree *pBt){
- int rc;
- if( pBt->inTrans ) return SQLITE_ERROR;
- if( pBt->readOnly ) return SQLITE_READONLY;
- if( pBt->page1==0 ){
- rc = lockBtree(pBt);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- rc = sqlitepager_begin(pBt->page1);
- if( rc==SQLITE_OK ){
- rc = newDatabase(pBt);
- }
- if( rc==SQLITE_OK ){
- pBt->inTrans = 1;
- pBt->inCkpt = 0;
- }else{
- unlockBtreeIfUnused(pBt);
- }
- return rc;
-}
-
-/*
-** Commit the transaction currently in progress.
-**
-** This will release the write lock on the database file. If there
-** are no active cursors, it also releases the read lock.
-*/
-static int fileBtreeCommit(Btree *pBt){
- int rc;
- rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
- pBt->inTrans = 0;
- pBt->inCkpt = 0;
- unlockBtreeIfUnused(pBt);
- return rc;
-}
-
-/*
-** Rollback the transaction in progress. All cursors will be
-** invalided by this operation. Any attempt to use a cursor
-** that was open at the beginning of this operation will result
-** in an error.
-**
-** This will release the write lock on the database file. If there
-** are no active cursors, it also releases the read lock.
-*/
-static int fileBtreeRollback(Btree *pBt){
- int rc;
- BtCursor *pCur;
- if( pBt->inTrans==0 ) return SQLITE_OK;
- pBt->inTrans = 0;
- pBt->inCkpt = 0;
- rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->pPage && pCur->pPage->isInit==0 ){
- sqlitepager_unref(pCur->pPage);
- pCur->pPage = 0;
- }
- }
- unlockBtreeIfUnused(pBt);
- return rc;
-}
-
-/*
-** Set the checkpoint for the current transaction. The checkpoint serves
-** as a sub-transaction that can be rolled back independently of the
-** main transaction. You must start a transaction before starting a
-** checkpoint. The checkpoint is ended automatically if the transaction
-** commits or rolls back.
-**
-** Only one checkpoint may be active at a time. It is an error to try
-** to start a new checkpoint if another checkpoint is already active.
-*/
-static int fileBtreeBeginCkpt(Btree *pBt){
- int rc;
- if( !pBt->inTrans || pBt->inCkpt ){
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager);
- pBt->inCkpt = 1;
- return rc;
-}
-
-
-/*
-** Commit a checkpoint to transaction currently in progress. If no
-** checkpoint is active, this is a no-op.
-*/
-static int fileBtreeCommitCkpt(Btree *pBt){
- int rc;
- if( pBt->inCkpt && !pBt->readOnly ){
- rc = sqlitepager_ckpt_commit(pBt->pPager);
- }else{
- rc = SQLITE_OK;
- }
- pBt->inCkpt = 0;
- return rc;
-}
-
-/*
-** Rollback the checkpoint to the current transaction. If there
-** is no active checkpoint or transaction, this routine is a no-op.
-**
-** All cursors will be invalided by this operation. Any attempt
-** to use a cursor that was open at the beginning of this operation
-** will result in an error.
-*/
-static int fileBtreeRollbackCkpt(Btree *pBt){
- int rc;
- BtCursor *pCur;
- if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
- rc = sqlitepager_ckpt_rollback(pBt->pPager);
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->pPage && pCur->pPage->isInit==0 ){
- sqlitepager_unref(pCur->pPage);
- pCur->pPage = 0;
- }
- }
- pBt->inCkpt = 0;
- return rc;
-}
-
-/*
-** Create a new cursor for the BTree whose root is on the page
-** iTable. The act of acquiring a cursor gets a read lock on
-** the database file.
-**
-** If wrFlag==0, then the cursor can only be used for reading.
-** If wrFlag==1, then the cursor can be used for reading or for
-** writing if other conditions for writing are also met. These
-** are the conditions that must be met in order for writing to
-** be allowed:
-**
-** 1: The cursor must have been opened with wrFlag==1
-**
-** 2: No other cursors may be open with wrFlag==0 on the same table
-**
-** 3: The database must be writable (not on read-only media)
-**
-** 4: There must be an active transaction.
-**
-** Condition 2 warrants further discussion. If any cursor is opened
-** on a table with wrFlag==0, that prevents all other cursors from
-** writing to that table. This is a kind of "read-lock". When a cursor
-** is opened with wrFlag==0 it is guaranteed that the table will not
-** change as long as the cursor is open. This allows the cursor to
-** do a sequential scan of the table without having to worry about
-** entries being inserted or deleted during the scan. Cursors should
-** be opened with wrFlag==0 only if this read-lock property is needed.
-** That is to say, cursors should be opened with wrFlag==0 only if they
-** intend to use the sqliteBtreeNext() system call. All other cursors
-** should be opened with wrFlag==1 even if they never really intend
-** to write.
-**
-** No checking is done to make sure that page iTable really is the
-** root page of a b-tree. If it is not, then the cursor acquired
-** will not work correctly.
-*/
-static
-int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
- int rc;
- BtCursor *pCur, *pRing;
-
- if( pBt->readOnly && wrFlag ){
- *ppCur = 0;
- return SQLITE_READONLY;
- }
- if( pBt->page1==0 ){
- rc = lockBtree(pBt);
- if( rc!=SQLITE_OK ){
- *ppCur = 0;
- return rc;
- }
- }
- pCur = sqliteMalloc( sizeof(*pCur) );
- if( pCur==0 ){
- rc = SQLITE_NOMEM;
- goto create_cursor_exception;
- }
- pCur->pgnoRoot = (Pgno)iTable;
- rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
- if( rc!=SQLITE_OK ){
- goto create_cursor_exception;
- }
- rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
- if( rc!=SQLITE_OK ){
- goto create_cursor_exception;
- }
- pCur->pOps = &sqliteBtreeCursorOps;
- pCur->pBt = pBt;
- pCur->wrFlag = wrFlag;
- pCur->idx = 0;
- pCur->eSkip = SKIP_INVALID;
- pCur->pNext = pBt->pCursor;
- if( pCur->pNext ){
- pCur->pNext->pPrev = pCur;
- }
- pCur->pPrev = 0;
- pRing = pBt->pCursor;
- while( pRing && pRing->pgnoRoot!=pCur->pgnoRoot ){ pRing = pRing->pNext; }
- if( pRing ){
- pCur->pShared = pRing->pShared;
- pRing->pShared = pCur;
- }else{
- pCur->pShared = pCur;
- }
- pBt->pCursor = pCur;
- *ppCur = pCur;
- return SQLITE_OK;
-
-create_cursor_exception:
- *ppCur = 0;
- if( pCur ){
- if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
- sqliteFree(pCur);
- }
- unlockBtreeIfUnused(pBt);
- return rc;
-}
-
-/*
-** Close a cursor. The read lock on the database file is released
-** when the last cursor is closed.
-*/
-static int fileBtreeCloseCursor(BtCursor *pCur){
- Btree *pBt = pCur->pBt;
- if( pCur->pPrev ){
- pCur->pPrev->pNext = pCur->pNext;
- }else{
- pBt->pCursor = pCur->pNext;
- }
- if( pCur->pNext ){
- pCur->pNext->pPrev = pCur->pPrev;
- }
- if( pCur->pPage ){
- sqlitepager_unref(pCur->pPage);
- }
- if( pCur->pShared!=pCur ){
- BtCursor *pRing = pCur->pShared;
- while( pRing->pShared!=pCur ){ pRing = pRing->pShared; }
- pRing->pShared = pCur->pShared;
- }
- unlockBtreeIfUnused(pBt);
- sqliteFree(pCur);
- return SQLITE_OK;
-}
-
-/*
-** Make a temporary cursor by filling in the fields of pTempCur.
-** The temporary cursor is not on the cursor list for the Btree.
-*/
-static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
- memcpy(pTempCur, pCur, sizeof(*pCur));
- pTempCur->pNext = 0;
- pTempCur->pPrev = 0;
- if( pTempCur->pPage ){
- sqlitepager_ref(pTempCur->pPage);
- }
-}
-
-/*
-** Delete a temporary cursor such as was made by the CreateTemporaryCursor()
-** function above.
-*/
-static void releaseTempCursor(BtCursor *pCur){
- if( pCur->pPage ){
- sqlitepager_unref(pCur->pPage);
- }
-}
-
-/*
-** Set *pSize to the number of bytes of key in the entry the
-** cursor currently points to. Always return SQLITE_OK.
-** Failure is not possible. If the cursor is not currently
-** pointing to an entry (which can happen, for example, if
-** the database is empty) then *pSize is set to 0.
-*/
-static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
- Cell *pCell;
- MemPage *pPage;
-
- pPage = pCur->pPage;
- assert( pPage!=0 );
- if( pCur->idx >= pPage->nCell ){
- *pSize = 0;
- }else{
- pCell = pPage->apCell[pCur->idx];
- *pSize = NKEY(pCur->pBt, pCell->h);
- }
- return SQLITE_OK;
-}
-
-/*
-** Read payload information from the entry that the pCur cursor is
-** pointing to. Begin reading the payload at "offset" and read
-** a total of "amt" bytes. Put the result in zBuf.
-**
-** This routine does not make a distinction between key and data.
-** It just reads bytes from the payload area.
-*/
-static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
- char *aPayload;
- Pgno nextPage;
- int rc;
- Btree *pBt = pCur->pBt;
- assert( pCur!=0 && pCur->pPage!=0 );
- assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
- aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
- if( offset<MX_LOCAL_PAYLOAD ){
- int a = amt;
- if( a+offset>MX_LOCAL_PAYLOAD ){
- a = MX_LOCAL_PAYLOAD - offset;
- }
- memcpy(zBuf, &aPayload[offset], a);
- if( a==amt ){
- return SQLITE_OK;
- }
- offset = 0;
- zBuf += a;
- amt -= a;
- }else{
- offset -= MX_LOCAL_PAYLOAD;
- }
- if( amt>0 ){
- nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl);
- }
- while( amt>0 && nextPage ){
- OverflowPage *pOvfl;
- rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
- if( rc!=0 ){
- return rc;
- }
- nextPage = SWAB32(pBt, pOvfl->iNext);
- if( offset<OVERFLOW_SIZE ){
- int a = amt;
- if( a + offset > OVERFLOW_SIZE ){
- a = OVERFLOW_SIZE - offset;
- }
- memcpy(zBuf, &pOvfl->aPayload[offset], a);
- offset = 0;
- amt -= a;
- zBuf += a;
- }else{
- offset -= OVERFLOW_SIZE;
- }
- sqlitepager_unref(pOvfl);
- }
- if( amt>0 ){
- return SQLITE_CORRUPT;
- }
- return SQLITE_OK;
-}
-
-/*
-** Read part of the key associated with cursor pCur. A maximum
-** of "amt" bytes will be transfered into zBuf[]. The transfer
-** begins at "offset". The number of bytes actually read is
-** returned.
-**
-** Change: It used to be that the amount returned will be smaller
-** than the amount requested if there are not enough bytes in the key
-** to satisfy the request. But now, it must be the case that there
-** is enough data available to satisfy the request. If not, an exception
-** is raised. The change was made in an effort to boost performance
-** by eliminating unneeded tests.
-*/
-static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
- MemPage *pPage;
-
- assert( amt>=0 );
- assert( offset>=0 );
- assert( pCur->pPage!=0 );
- pPage = pCur->pPage;
- if( pCur->idx >= pPage->nCell ){
- return 0;
- }
- assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) );
- getPayload(pCur, offset, amt, zBuf);
- return amt;
-}
-
-/*
-** Set *pSize to the number of bytes of data in the entry the
-** cursor currently points to. Always return SQLITE_OK.
-** Failure is not possible. If the cursor is not currently
-** pointing to an entry (which can happen, for example, if
-** the database is empty) then *pSize is set to 0.
-*/
-static int fileBtreeDataSize(BtCursor *pCur, int *pSize){
- Cell *pCell;
- MemPage *pPage;
-
- pPage = pCur->pPage;
- assert( pPage!=0 );
- if( pCur->idx >= pPage->nCell ){
- *pSize = 0;
- }else{
- pCell = pPage->apCell[pCur->idx];
- *pSize = NDATA(pCur->pBt, pCell->h);
- }
- return SQLITE_OK;
-}
-
-/*
-** Read part of the data associated with cursor pCur. A maximum
-** of "amt" bytes will be transfered into zBuf[]. The transfer
-** begins at "offset". The number of bytes actually read is
-** returned. The amount returned will be smaller than the
-** amount requested if there are not enough bytes in the data
-** to satisfy the request.
-*/
-static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
- Cell *pCell;
- MemPage *pPage;
-
- assert( amt>=0 );
- assert( offset>=0 );
- assert( pCur->pPage!=0 );
- pPage = pCur->pPage;
- if( pCur->idx >= pPage->nCell ){
- return 0;
- }
- pCell = pPage->apCell[pCur->idx];
- assert( amt+offset <= NDATA(pCur->pBt, pCell->h) );
- getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf);
- return amt;
-}
-
-/*
-** Compare an external key against the key on the entry that pCur points to.
-**
-** The external key is pKey and is nKey bytes long. The last nIgnore bytes
-** of the key associated with pCur are ignored, as if they do not exist.
-** (The normal case is for nIgnore to be zero in which case the entire
-** internal key is used in the comparison.)
-**
-** The comparison result is written to *pRes as follows:
-**
-** *pRes<0 This means pCur<pKey
-**
-** *pRes==0 This means pCur==pKey for all nKey bytes
-**
-** *pRes>0 This means pCur>pKey
-**
-** When one key is an exact prefix of the other, the shorter key is
-** considered less than the longer one. In order to be equal the
-** keys must be exactly the same length. (The length of the pCur key
-** is the actual key length minus nIgnore bytes.)
-*/
-static int fileBtreeKeyCompare(
- BtCursor *pCur, /* Pointer to entry to compare against */
- const void *pKey, /* Key to compare against entry that pCur points to */
- int nKey, /* Number of bytes in pKey */
- int nIgnore, /* Ignore this many bytes at the end of pCur */
- int *pResult /* Write the result here */
-){
- Pgno nextPage;
- int n, c, rc, nLocal;
- Cell *pCell;
- Btree *pBt = pCur->pBt;
- const char *zKey = (const char*)pKey;
-
- assert( pCur->pPage );
- assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
- pCell = pCur->pPage->apCell[pCur->idx];
- nLocal = NKEY(pBt, pCell->h) - nIgnore;
- if( nLocal<0 ) nLocal = 0;
- n = nKey<nLocal ? nKey : nLocal;
- if( n>MX_LOCAL_PAYLOAD ){
- n = MX_LOCAL_PAYLOAD;
- }
- c = memcmp(pCell->aPayload, zKey, n);
- if( c!=0 ){
- *pResult = c;
- return SQLITE_OK;
- }
- zKey += n;
- nKey -= n;
- nLocal -= n;
- nextPage = SWAB32(pBt, pCell->ovfl);
- while( nKey>0 && nLocal>0 ){
- OverflowPage *pOvfl;
- if( nextPage==0 ){
- return SQLITE_CORRUPT;
- }
- rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
- if( rc ){
- return rc;
- }
- nextPage = SWAB32(pBt, pOvfl->iNext);
- n = nKey<nLocal ? nKey : nLocal;
- if( n>OVERFLOW_SIZE ){
- n = OVERFLOW_SIZE;
- }
- c = memcmp(pOvfl->aPayload, zKey, n);
- sqlitepager_unref(pOvfl);
- if( c!=0 ){
- *pResult = c;
- return SQLITE_OK;
- }
- nKey -= n;
- nLocal -= n;
- zKey += n;
- }
- if( c==0 ){
- c = nLocal - nKey;
- }
- *pResult = c;
- return SQLITE_OK;
-}
-
-/*
-** Move the cursor down to a new child page. The newPgno argument is the
-** page number of the child page in the byte order of the disk image.
-*/
-static int moveToChild(BtCursor *pCur, int newPgno){
- int rc;
- MemPage *pNewPage;
- Btree *pBt = pCur->pBt;
-
- newPgno = SWAB32(pBt, newPgno);
- rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
- if( rc ) return rc;
- rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
- if( rc ) return rc;
- assert( pCur->idx>=pCur->pPage->nCell
- || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) );
- assert( pCur->idx<pCur->pPage->nCell
- || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) );
- pNewPage->idxParent = pCur->idx;
- pCur->pPage->idxShift = 0;
- sqlitepager_unref(pCur->pPage);
- pCur->pPage = pNewPage;
- pCur->idx = 0;
- if( pNewPage->nCell<1 ){
- return SQLITE_CORRUPT;
- }
- return SQLITE_OK;
-}
-
-/*
-** Move the cursor up to the parent page.
-**
-** pCur->idx is set to the cell index that contains the pointer
-** to the page we are coming from. If we are coming from the
-** right-most child page then pCur->idx is set to one more than
-** the largest cell index.
-*/
-static void moveToParent(BtCursor *pCur){
- Pgno oldPgno;
- MemPage *pParent;
- MemPage *pPage;
- int idxParent;
- pPage = pCur->pPage;
- assert( pPage!=0 );
- pParent = pPage->pParent;
- assert( pParent!=0 );
- idxParent = pPage->idxParent;
- sqlitepager_ref(pParent);
- sqlitepager_unref(pPage);
- pCur->pPage = pParent;
- assert( pParent->idxShift==0 );
- if( pParent->idxShift==0 ){
- pCur->idx = idxParent;
-#ifndef NDEBUG
- /* Verify that pCur->idx is the correct index to point back to the child
- ** page we just came from
- */
- oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
- if( pCur->idx<pParent->nCell ){
- assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
- }else{
- assert( pParent->u.hdr.rightChild==oldPgno );
- }
-#endif
- }else{
- /* The MemPage.idxShift flag indicates that cell indices might have
- ** changed since idxParent was set and hence idxParent might be out
- ** of date. So recompute the parent cell index by scanning all cells
- ** and locating the one that points to the child we just came from.
- */
- int i;
- pCur->idx = pParent->nCell;
- oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
- for(i=0; i<pParent->nCell; i++){
- if( pParent->apCell[i]->h.leftChild==oldPgno ){
- pCur->idx = i;
- break;
- }
- }
- }
-}
-
-/*
-** Move the cursor to the root page
-*/
-static int moveToRoot(BtCursor *pCur){
- MemPage *pNew;
- int rc;
- Btree *pBt = pCur->pBt;
-
- rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
- if( rc ) return rc;
- rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
- if( rc ) return rc;
- sqlitepager_unref(pCur->pPage);
- pCur->pPage = pNew;
- pCur->idx = 0;
- return SQLITE_OK;
-}
-
-/*
-** Move the cursor down to the left-most leaf entry beneath the
-** entry to which it is currently pointing.
-*/
-static int moveToLeftmost(BtCursor *pCur){
- Pgno pgno;
- int rc;
-
- while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
- rc = moveToChild(pCur, pgno);
- if( rc ) return rc;
- }
- return SQLITE_OK;
-}
-
-/*
-** Move the cursor down to the right-most leaf entry beneath the
-** page to which it is currently pointing. Notice the difference
-** between moveToLeftmost() and moveToRightmost(). moveToLeftmost()
-** finds the left-most entry beneath the *entry* whereas moveToRightmost()
-** finds the right-most entry beneath the *page*.
-*/
-static int moveToRightmost(BtCursor *pCur){
- Pgno pgno;
- int rc;
-
- while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
- pCur->idx = pCur->pPage->nCell;
- rc = moveToChild(pCur, pgno);
- if( rc ) return rc;
- }
- pCur->idx = pCur->pPage->nCell - 1;
- return SQLITE_OK;
-}
-
-/* Move the cursor to the first entry in the table. Return SQLITE_OK
-** on success. Set *pRes to 0 if the cursor actually points to something
-** or set *pRes to 1 if the table is empty.
-*/
-static int fileBtreeFirst(BtCursor *pCur, int *pRes){
- int rc;
- if( pCur->pPage==0 ) return SQLITE_ABORT;
- rc = moveToRoot(pCur);
- if( rc ) return rc;
- if( pCur->pPage->nCell==0 ){
- *pRes = 1;
- return SQLITE_OK;
- }
- *pRes = 0;
- rc = moveToLeftmost(pCur);
- pCur->eSkip = SKIP_NONE;
- return rc;
-}
-
-/* Move the cursor to the last entry in the table. Return SQLITE_OK
-** on success. Set *pRes to 0 if the cursor actually points to something
-** or set *pRes to 1 if the table is empty.
-*/
-static int fileBtreeLast(BtCursor *pCur, int *pRes){
- int rc;
- if( pCur->pPage==0 ) return SQLITE_ABORT;
- rc = moveToRoot(pCur);
- if( rc ) return rc;
- assert( pCur->pPage->isInit );
- if( pCur->pPage->nCell==0 ){
- *pRes = 1;
- return SQLITE_OK;
- }
- *pRes = 0;
- rc = moveToRightmost(pCur);
- pCur->eSkip = SKIP_NONE;
- return rc;
-}
-
-/* Move the cursor so that it points to an entry near pKey.
-** Return a success code.
-**
-** If an exact match is not found, then the cursor is always
-** left pointing at a leaf page which would hold the entry if it
-** were present. The cursor might point to an entry that comes
-** before or after the key.
-**
-** The result of comparing the key with the entry to which the
-** cursor is left pointing is stored in pCur->iMatch. The same
-** value is also written to *pRes if pRes!=NULL. The meaning of
-** this value is as follows:
-**
-** *pRes<0 The cursor is left pointing at an entry that
-** is smaller than pKey or if the table is empty
-** and the cursor is therefore left point to nothing.
-**
-** *pRes==0 The cursor is left pointing at an entry that
-** exactly matches pKey.
-**
-** *pRes>0 The cursor is left pointing at an entry that
-** is larger than pKey.
-*/
-static
-int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
- int rc;
- if( pCur->pPage==0 ) return SQLITE_ABORT;
- pCur->eSkip = SKIP_NONE;
- rc = moveToRoot(pCur);
- if( rc ) return rc;
- for(;;){
- int lwr, upr;
- Pgno chldPg;
- MemPage *pPage = pCur->pPage;
- int c = -1; /* pRes return if table is empty must be -1 */
- lwr = 0;
- upr = pPage->nCell-1;
- while( lwr<=upr ){
- pCur->idx = (lwr+upr)/2;
- rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c);
- if( rc ) return rc;
- if( c==0 ){
- pCur->iMatch = c;
- if( pRes ) *pRes = 0;
- return SQLITE_OK;
- }
- if( c<0 ){
- lwr = pCur->idx+1;
- }else{
- upr = pCur->idx-1;
- }
- }
- assert( lwr==upr+1 );
- assert( pPage->isInit );
- if( lwr>=pPage->nCell ){
- chldPg = pPage->u.hdr.rightChild;
- }else{
- chldPg = pPage->apCell[lwr]->h.leftChild;
- }
- if( chldPg==0 ){
- pCur->iMatch = c;
- if( pRes ) *pRes = c;
- return SQLITE_OK;
- }
- pCur->idx = lwr;
- rc = moveToChild(pCur, chldPg);
- if( rc ) return rc;
- }
- /* NOT REACHED */
-}
-
-/*
-** Advance the cursor to the next entry in the database. If
-** successful then set *pRes=0. If the cursor
-** was already pointing to the last entry in the database before
-** this routine was called, then set *pRes=1.
-*/
-static int fileBtreeNext(BtCursor *pCur, int *pRes){
- int rc;
- MemPage *pPage = pCur->pPage;
- assert( pRes!=0 );
- if( pPage==0 ){
- *pRes = 1;
- return SQLITE_ABORT;
- }
- assert( pPage->isInit );
- assert( pCur->eSkip!=SKIP_INVALID );
- if( pPage->nCell==0 ){
- *pRes = 1;
- return SQLITE_OK;
- }
- assert( pCur->idx<pPage->nCell );
- if( pCur->eSkip==SKIP_NEXT ){
- pCur->eSkip = SKIP_NONE;
- *pRes = 0;
- return SQLITE_OK;
- }
- pCur->eSkip = SKIP_NONE;
- pCur->idx++;
- if( pCur->idx>=pPage->nCell ){
- if( pPage->u.hdr.rightChild ){
- rc = moveToChild(pCur, pPage->u.hdr.rightChild);
- if( rc ) return rc;
- rc = moveToLeftmost(pCur);
- *pRes = 0;
- return rc;
- }
- do{
- if( pPage->pParent==0 ){
- *pRes = 1;
- return SQLITE_OK;
- }
- moveToParent(pCur);
- pPage = pCur->pPage;
- }while( pCur->idx>=pPage->nCell );
- *pRes = 0;
- return SQLITE_OK;
- }
- *pRes = 0;
- if( pPage->u.hdr.rightChild==0 ){
- return SQLITE_OK;
- }
- rc = moveToLeftmost(pCur);
- return rc;
-}
-
-/*
-** Step the cursor to the back to the previous entry in the database. If
-** successful then set *pRes=0. If the cursor
-** was already pointing to the first entry in the database before
-** this routine was called, then set *pRes=1.
-*/
-static int fileBtreePrevious(BtCursor *pCur, int *pRes){
- int rc;
- Pgno pgno;
- MemPage *pPage;
- pPage = pCur->pPage;
- if( pPage==0 ){
- *pRes = 1;
- return SQLITE_ABORT;
- }
- assert( pPage->isInit );
- assert( pCur->eSkip!=SKIP_INVALID );
- if( pPage->nCell==0 ){
- *pRes = 1;
- return SQLITE_OK;
- }
- if( pCur->eSkip==SKIP_PREV ){
- pCur->eSkip = SKIP_NONE;
- *pRes = 0;
- return SQLITE_OK;
- }
- pCur->eSkip = SKIP_NONE;
- assert( pCur->idx>=0 );
- if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
- rc = moveToChild(pCur, pgno);
- if( rc ) return rc;
- rc = moveToRightmost(pCur);
- }else{
- while( pCur->idx==0 ){
- if( pPage->pParent==0 ){
- if( pRes ) *pRes = 1;
- return SQLITE_OK;
- }
- moveToParent(pCur);
- pPage = pCur->pPage;
- }
- pCur->idx--;
- rc = SQLITE_OK;
- }
- *pRes = 0;
- return rc;
-}
-
-/*
-** Allocate a new page from the database file.
-**
-** The new page is marked as dirty. (In other words, sqlitepager_write()
-** has already been called on the new page.) The new page has also
-** been referenced and the calling routine is responsible for calling
-** sqlitepager_unref() on the new page when it is done.
-**
-** SQLITE_OK is returned on success. Any other return value indicates
-** an error. *ppPage and *pPgno are undefined in the event of an error.
-** Do not invoke sqlitepager_unref() on *ppPage if an error is returned.
-**
-** If the "nearby" parameter is not 0, then a (feeble) effort is made to
-** locate a page close to the page number "nearby". This can be used in an
-** attempt to keep related pages close to each other in the database file,
-** which in turn can make database access faster.
-*/
-static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
- PageOne *pPage1 = pBt->page1;
- int rc;
- if( pPage1->freeList ){
- OverflowPage *pOvfl;
- FreelistInfo *pInfo;
-
- rc = sqlitepager_write(pPage1);
- if( rc ) return rc;
- SWAB_ADD(pBt, pPage1->nFree, -1);
- rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
- (void**)&pOvfl);
- if( rc ) return rc;
- rc = sqlitepager_write(pOvfl);
- if( rc ){
- sqlitepager_unref(pOvfl);
- return rc;
- }
- pInfo = (FreelistInfo*)pOvfl->aPayload;
- if( pInfo->nFree==0 ){
- *pPgno = SWAB32(pBt, pPage1->freeList);
- pPage1->freeList = pOvfl->iNext;
- *ppPage = (MemPage*)pOvfl;
- }else{
- int closest, n;
- n = SWAB32(pBt, pInfo->nFree);
- if( n>1 && nearby>0 ){
- int i, dist;
- closest = 0;
- dist = SWAB32(pBt, pInfo->aFree[0]) - nearby;
- if( dist<0 ) dist = -dist;
- for(i=1; i<n; i++){
- int d2 = SWAB32(pBt, pInfo->aFree[i]) - nearby;
- if( d2<0 ) d2 = -d2;
- if( d2<dist ) closest = i;
- }
- }else{
- closest = 0;
- }
- SWAB_ADD(pBt, pInfo->nFree, -1);
- *pPgno = SWAB32(pBt, pInfo->aFree[closest]);
- pInfo->aFree[closest] = pInfo->aFree[n-1];
- rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
- sqlitepager_unref(pOvfl);
- if( rc==SQLITE_OK ){
- sqlitepager_dont_rollback(*ppPage);
- rc = sqlitepager_write(*ppPage);
- }
- }
- }else{
- *pPgno = sqlitepager_pagecount(pBt->pPager) + 1;
- rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
- if( rc ) return rc;
- rc = sqlitepager_write(*ppPage);
- }
- return rc;
-}
-
-/*
-** Add a page of the database file to the freelist. Either pgno or
-** pPage but not both may be 0.
-**
-** sqlitepager_unref() is NOT called for pPage.
-*/
-static int freePage(Btree *pBt, void *pPage, Pgno pgno){
- PageOne *pPage1 = pBt->page1;
- OverflowPage *pOvfl = (OverflowPage*)pPage;
- int rc;
- int needUnref = 0;
- MemPage *pMemPage;
-
- if( pgno==0 ){
- assert( pOvfl!=0 );
- pgno = sqlitepager_pagenumber(pOvfl);
- }
- assert( pgno>2 );
- assert( sqlitepager_pagenumber(pOvfl)==pgno );
- pMemPage = (MemPage*)pPage;
- pMemPage->isInit = 0;
- if( pMemPage->pParent ){
- sqlitepager_unref(pMemPage->pParent);
- pMemPage->pParent = 0;
- }
- rc = sqlitepager_write(pPage1);
- if( rc ){
- return rc;
- }
- SWAB_ADD(pBt, pPage1->nFree, 1);
- if( pPage1->nFree!=0 && pPage1->freeList!=0 ){
- OverflowPage *pFreeIdx;
- rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
- (void**)&pFreeIdx);
- if( rc==SQLITE_OK ){
- FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload;
- int n = SWAB32(pBt, pInfo->nFree);
- if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
- rc = sqlitepager_write(pFreeIdx);
- if( rc==SQLITE_OK ){
- pInfo->aFree[n] = SWAB32(pBt, pgno);
- SWAB_ADD(pBt, pInfo->nFree, 1);
- sqlitepager_unref(pFreeIdx);
- sqlitepager_dont_write(pBt->pPager, pgno);
- return rc;
- }
- }
- sqlitepager_unref(pFreeIdx);
- }
- }
- if( pOvfl==0 ){
- assert( pgno>0 );
- rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl);
- if( rc ) return rc;
- needUnref = 1;
- }
- rc = sqlitepager_write(pOvfl);
- if( rc ){
- if( needUnref ) sqlitepager_unref(pOvfl);
- return rc;
- }
- pOvfl->iNext = pPage1->freeList;
- pPage1->freeList = SWAB32(pBt, pgno);
- memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
- if( needUnref ) rc = sqlitepager_unref(pOvfl);
- return rc;
-}
-
-/*
-** Erase all the data out of a cell. This involves returning overflow
-** pages back the freelist.
-*/
-static int clearCell(Btree *pBt, Cell *pCell){
- Pager *pPager = pBt->pPager;
- OverflowPage *pOvfl;
- Pgno ovfl, nextOvfl;
- int rc;
-
- if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){
- return SQLITE_OK;
- }
- ovfl = SWAB32(pBt, pCell->ovfl);
- pCell->ovfl = 0;
- while( ovfl ){
- rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
- if( rc ) return rc;
- nextOvfl = SWAB32(pBt, pOvfl->iNext);
- rc = freePage(pBt, pOvfl, ovfl);
- if( rc ) return rc;
- sqlitepager_unref(pOvfl);
- ovfl = nextOvfl;
- }
- return SQLITE_OK;
-}
-
-/*
-** Create a new cell from key and data. Overflow pages are allocated as
-** necessary and linked to this cell.
-*/
-static int fillInCell(
- Btree *pBt, /* The whole Btree. Needed to allocate pages */
- Cell *pCell, /* Populate this Cell structure */
- const void *pKey, int nKey, /* The key */
- const void *pData,int nData /* The data */
-){
- OverflowPage *pOvfl, *pPrior;
- Pgno *pNext;
- int spaceLeft;
- int n, rc;
- int nPayload;
- const char *pPayload;
- char *pSpace;
- Pgno nearby = 0;
-
- pCell->h.leftChild = 0;
- pCell->h.nKey = SWAB16(pBt, nKey & 0xffff);
- pCell->h.nKeyHi = nKey >> 16;
- pCell->h.nData = SWAB16(pBt, nData & 0xffff);
- pCell->h.nDataHi = nData >> 16;
- pCell->h.iNext = 0;
-
- pNext = &pCell->ovfl;
- pSpace = pCell->aPayload;
- spaceLeft = MX_LOCAL_PAYLOAD;
- pPayload = pKey;
- pKey = 0;
- nPayload = nKey;
- pPrior = 0;
- while( nPayload>0 ){
- if( spaceLeft==0 ){
- rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby);
- if( rc ){
- *pNext = 0;
- }else{
- nearby = *pNext;
- }
- if( pPrior ) sqlitepager_unref(pPrior);
- if( rc ){
- clearCell(pBt, pCell);
- return rc;
- }
- if( pBt->needSwab ) *pNext = swab32(*pNext);
- pPrior = pOvfl;
- spaceLeft = OVERFLOW_SIZE;
- pSpace = pOvfl->aPayload;
- pNext = &pOvfl->iNext;
- }
- n = nPayload;
- if( n>spaceLeft ) n = spaceLeft;
- memcpy(pSpace, pPayload, n);
- nPayload -= n;
- if( nPayload==0 && pData ){
- pPayload = pData;
- nPayload = nData;
- pData = 0;
- }else{
- pPayload += n;
- }
- spaceLeft -= n;
- pSpace += n;
- }
- *pNext = 0;
- if( pPrior ){
- sqlitepager_unref(pPrior);
- }
- return SQLITE_OK;
-}
-
-/*
-** Change the MemPage.pParent pointer on the page whose number is
-** given in the second argument so that MemPage.pParent holds the
-** pointer in the third argument.
-*/
-static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){
- MemPage *pThis;
-
- if( pgno==0 ) return;
- assert( pPager!=0 );
- pThis = sqlitepager_lookup(pPager, pgno);
- if( pThis && pThis->isInit ){
- if( pThis->pParent!=pNewParent ){
- if( pThis->pParent ) sqlitepager_unref(pThis->pParent);
- pThis->pParent = pNewParent;
- if( pNewParent ) sqlitepager_ref(pNewParent);
- }
- pThis->idxParent = idx;
- sqlitepager_unref(pThis);
- }
-}
-
-/*
-** Reparent all children of the given page to be the given page.
-** In other words, for every child of pPage, invoke reparentPage()
-** to make sure that each child knows that pPage is its parent.
-**
-** This routine gets called after you memcpy() one page into
-** another.
-*/
-static void reparentChildPages(Btree *pBt, MemPage *pPage){
- int i;
- Pager *pPager = pBt->pPager;
- for(i=0; i<pPage->nCell; i++){
- reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i);
- }
- reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i);
- pPage->idxShift = 0;
-}
-
-/*
-** Remove the i-th cell from pPage. This routine effects pPage only.
-** The cell content is not freed or deallocated. It is assumed that
-** the cell content has been copied someplace else. This routine just
-** removes the reference to the cell from pPage.
-**
-** "sz" must be the number of bytes in the cell.
-**
-** Do not bother maintaining the integrity of the linked list of Cells.
-** Only the pPage->apCell[] array is important. The relinkCellList()
-** routine will be called soon after this routine in order to rebuild
-** the linked list.
-*/
-static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){
- int j;
- assert( idx>=0 && idx<pPage->nCell );
- assert( sz==cellSize(pBt, pPage->apCell[idx]) );
- assert( sqlitepager_iswriteable(pPage) );
- freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
- for(j=idx; j<pPage->nCell-1; j++){
- pPage->apCell[j] = pPage->apCell[j+1];
- }
- pPage->nCell--;
- pPage->idxShift = 1;
-}
-
-/*
-** Insert a new cell on pPage at cell index "i". pCell points to the
-** content of the cell.
-**
-** If the cell content will fit on the page, then put it there. If it
-** will not fit, then just make pPage->apCell[i] point to the content
-** and set pPage->isOverfull.
-**
-** Do not bother maintaining the integrity of the linked list of Cells.
-** Only the pPage->apCell[] array is important. The relinkCellList()
-** routine will be called soon after this routine in order to rebuild
-** the linked list.
-*/
-static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){
- int idx, j;
- assert( i>=0 && i<=pPage->nCell );
- assert( sz==cellSize(pBt, pCell) );
- assert( sqlitepager_iswriteable(pPage) );
- idx = allocateSpace(pBt, pPage, sz);
- for(j=pPage->nCell; j>i; j--){
- pPage->apCell[j] = pPage->apCell[j-1];
- }
- pPage->nCell++;
- if( idx<=0 ){
- pPage->isOverfull = 1;
- pPage->apCell[i] = pCell;
- }else{
- memcpy(&pPage->u.aDisk[idx], pCell, sz);
- pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx];
- }
- pPage->idxShift = 1;
-}
-
-/*
-** Rebuild the linked list of cells on a page so that the cells
-** occur in the order specified by the pPage->apCell[] array.
-** Invoke this routine once to repair damage after one or more
-** invocations of either insertCell() or dropCell().
-*/
-static void relinkCellList(Btree *pBt, MemPage *pPage){
- int i;
- u16 *pIdx;
- assert( sqlitepager_iswriteable(pPage) );
- pIdx = &pPage->u.hdr.firstCell;
- for(i=0; i<pPage->nCell; i++){
- int idx = Addr(pPage->apCell[i]) - Addr(pPage);
- assert( idx>0 && idx<SQLITE_USABLE_SIZE );
- *pIdx = SWAB16(pBt, idx);
- pIdx = &pPage->apCell[i]->h.iNext;
- }
- *pIdx = 0;
-}
-
-/*
-** Make a copy of the contents of pFrom into pTo. The pFrom->apCell[]
-** pointers that point into pFrom->u.aDisk[] must be adjusted to point
-** into pTo->u.aDisk[] instead. But some pFrom->apCell[] entries might
-** not point to pFrom->u.aDisk[]. Those are unchanged.
-*/
-static void copyPage(MemPage *pTo, MemPage *pFrom){
- uptr from, to;
- int i;
- memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE);
- pTo->pParent = 0;
- pTo->isInit = 1;
- pTo->nCell = pFrom->nCell;
- pTo->nFree = pFrom->nFree;
- pTo->isOverfull = pFrom->isOverfull;
- to = Addr(pTo);
- from = Addr(pFrom);
- for(i=0; i<pTo->nCell; i++){
- uptr x = Addr(pFrom->apCell[i]);
- if( x>from && x<from+SQLITE_USABLE_SIZE ){
- *((uptr*)&pTo->apCell[i]) = x + to - from;
- }else{
- pTo->apCell[i] = pFrom->apCell[i];
- }
- }
-}
-
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation. NN is the number of neighbors on either side
-** of the page that participate in the balancing operation. NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course). Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1 /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1) /* Total pages involved in the balance */
-
-/*
-** This routine redistributes Cells on pPage and up to two siblings
-** of pPage so that all pages have about the same amount of free space.
-** Usually one sibling on either side of pPage is used in the balancing,
-** though both siblings might come from one side if pPage is the first
-** or last child of its parent. If pPage has fewer than two siblings
-** (something which can only happen if pPage is the root page or a
-** child of root) then all available siblings participate in the balancing.
-**
-** The number of siblings of pPage might be increased or decreased by
-** one in an effort to keep pages between 66% and 100% full. The root page
-** is special and is allowed to be less than 66% full. If pPage is
-** the root page, then the depth of the tree might be increased
-** or decreased by one, as necessary, to keep the root page from being
-** overfull or empty.
-**
-** This routine calls relinkCellList() on its input page regardless of
-** whether or not it does any real balancing. Client routines will typically
-** invoke insertCell() or dropCell() before calling this routine, so we
-** need to call relinkCellList() to clean up the mess that those other
-** routines left behind.
-**
-** pCur is left pointing to the same cell as when this routine was called
-** even if that cell gets moved to a different page. pCur may be NULL.
-** Set the pCur parameter to NULL if you do not care about keeping track
-** of a cell as that will save this routine the work of keeping track of it.
-**
-** Note that when this routine is called, some of the Cells on pPage
-** might not actually be stored in pPage->u.aDisk[]. This can happen
-** if the page is overfull. Part of the job of this routine is to
-** make sure all Cells for pPage once again fit in pPage->u.aDisk[].
-**
-** In the course of balancing the siblings of pPage, the parent of pPage
-** might become overfull or underfull. If that happens, then this routine
-** is called recursively on the parent.
-**
-** If this routine fails for any reason, it might leave the database
-** in a corrupted state. So if this routine fails, the database should
-** be rolled back.
-*/
-static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
- MemPage *pParent; /* The parent of pPage */
- int nCell; /* Number of cells in apCell[] */
- int nOld; /* Number of pages in apOld[] */
- int nNew; /* Number of pages in apNew[] */
- int nDiv; /* Number of cells in apDiv[] */
- int i, j, k; /* Loop counters */
- int idx; /* Index of pPage in pParent->apCell[] */
- int nxDiv; /* Next divider slot in pParent->apCell[] */
- int rc; /* The return code */
- int iCur; /* apCell[iCur] is the cell of the cursor */
- MemPage *pOldCurPage; /* The cursor originally points to this page */
- int subtotal; /* Subtotal of bytes in cells on one page */
- MemPage *extraUnref = 0; /* A page that needs to be unref-ed */
- MemPage *apOld[NB]; /* pPage and up to two siblings */
- Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
- MemPage *apNew[NB+1]; /* pPage and up to NB siblings after balancing */
- Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */
- int idxDiv[NB]; /* Indices of divider cells in pParent */
- Cell *apDiv[NB]; /* Divider cells in pParent */
- Cell aTemp[NB]; /* Temporary holding area for apDiv[] */
- int cntNew[NB+1]; /* Index in apCell[] of cell after i-th page */
- int szNew[NB+1]; /* Combined size of cells place on i-th page */
- MemPage aOld[NB]; /* Temporary copies of pPage and its siblings */
- Cell *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
- int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */
-
- /*
- ** Return without doing any work if pPage is neither overfull nor
- ** underfull.
- */
- assert( sqlitepager_iswriteable(pPage) );
- if( !pPage->isOverfull && pPage->nFree<SQLITE_USABLE_SIZE/2
- && pPage->nCell>=2){
- relinkCellList(pBt, pPage);
- return SQLITE_OK;
- }
-
- /*
- ** Find the parent of the page to be balanceed.
- ** If there is no parent, it means this page is the root page and
- ** special rules apply.
- */
- pParent = pPage->pParent;
- if( pParent==0 ){
- Pgno pgnoChild;
- MemPage *pChild;
- assert( pPage->isInit );
- if( pPage->nCell==0 ){
- if( pPage->u.hdr.rightChild ){
- /*
- ** The root page is empty. Copy the one child page
- ** into the root page and return. This reduces the depth
- ** of the BTree by one.
- */
- pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild);
- rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild);
- if( rc ) return rc;
- memcpy(pPage, pChild, SQLITE_USABLE_SIZE);
- pPage->isInit = 0;
- rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0);
- assert( rc==SQLITE_OK );
- reparentChildPages(pBt, pPage);
- if( pCur && pCur->pPage==pChild ){
- sqlitepager_unref(pChild);
- pCur->pPage = pPage;
- sqlitepager_ref(pPage);
- }
- freePage(pBt, pChild, pgnoChild);
- sqlitepager_unref(pChild);
- }else{
- relinkCellList(pBt, pPage);
- }
- return SQLITE_OK;
- }
- if( !pPage->isOverfull ){
- /* It is OK for the root page to be less than half full.
- */
- relinkCellList(pBt, pPage);
- return SQLITE_OK;
- }
- /*
- ** If we get to here, it means the root page is overfull.
- ** When this happens, Create a new child page and copy the
- ** contents of the root into the child. Then make the root
- ** page an empty page with rightChild pointing to the new
- ** child. Then fall thru to the code below which will cause
- ** the overfull child page to be split.
- */
- rc = sqlitepager_write(pPage);
- if( rc ) return rc;
- rc = allocatePage(pBt, &pChild, &pgnoChild, sqlitepager_pagenumber(pPage));
- if( rc ) return rc;
- assert( sqlitepager_iswriteable(pChild) );
- copyPage(pChild, pPage);
- pChild->pParent = pPage;
- pChild->idxParent = 0;
- sqlitepager_ref(pPage);
- pChild->isOverfull = 1;
- if( pCur && pCur->pPage==pPage ){
- sqlitepager_unref(pPage);
- pCur->pPage = pChild;
- }else{
- extraUnref = pChild;
- }
- zeroPage(pBt, pPage);
- pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild);
- pParent = pPage;
- pPage = pChild;
- }
- rc = sqlitepager_write(pParent);
- if( rc ) return rc;
- assert( pParent->isInit );
-
- /*
- ** Find the Cell in the parent page whose h.leftChild points back
- ** to pPage. The "idx" variable is the index of that cell. If pPage
- ** is the rightmost child of pParent then set idx to pParent->nCell
- */
- if( pParent->idxShift ){
- Pgno pgno, swabPgno;
- pgno = sqlitepager_pagenumber(pPage);
- swabPgno = SWAB32(pBt, pgno);
- for(idx=0; idx<pParent->nCell; idx++){
- if( pParent->apCell[idx]->h.leftChild==swabPgno ){
- break;
- }
- }
- assert( idx<pParent->nCell || pParent->u.hdr.rightChild==swabPgno );
- }else{
- idx = pPage->idxParent;
- }
-
- /*
- ** Initialize variables so that it will be safe to jump
- ** directly to balance_cleanup at any moment.
- */
- nOld = nNew = 0;
- sqlitepager_ref(pParent);
-
- /*
- ** Find sibling pages to pPage and the Cells in pParent that divide
- ** the siblings. An attempt is made to find NN siblings on either
- ** side of pPage. More siblings are taken from one side, however, if
- ** pPage there are fewer than NN siblings on the other side. If pParent
- ** has NB or fewer children then all children of pParent are taken.
- */
- nxDiv = idx - NN;
- if( nxDiv + NB > pParent->nCell ){
- nxDiv = pParent->nCell - NB + 1;
- }
- if( nxDiv<0 ){
- nxDiv = 0;
- }
- nDiv = 0;
- for(i=0, k=nxDiv; i<NB; i++, k++){
- if( k<pParent->nCell ){
- idxDiv[i] = k;
- apDiv[i] = pParent->apCell[k];
- nDiv++;
- pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild);
- }else if( k==pParent->nCell ){
- pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild);
- }else{
- break;
- }
- rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
- if( rc ) goto balance_cleanup;
- rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
- if( rc ) goto balance_cleanup;
- apOld[i]->idxParent = k;
- nOld++;
- }
-
- /*
- ** Set iCur to be the index in apCell[] of the cell that the cursor
- ** is pointing to. We will need this later on in order to keep the
- ** cursor pointing at the same cell. If pCur points to a page that
- ** has no involvement with this rebalancing, then set iCur to a large
- ** number so that the iCur==j tests always fail in the main cell
- ** distribution loop below.
- */
- if( pCur ){
- iCur = 0;
- for(i=0; i<nOld; i++){
- if( pCur->pPage==apOld[i] ){
- iCur += pCur->idx;
- break;
- }
- iCur += apOld[i]->nCell;
- if( i<nOld-1 && pCur->pPage==pParent && pCur->idx==idxDiv[i] ){
- break;
- }
- iCur++;
- }
- pOldCurPage = pCur->pPage;
- }
-
- /*
- ** Make copies of the content of pPage and its siblings into aOld[].
- ** The rest of this function will use data from the copies rather
- ** that the original pages since the original pages will be in the
- ** process of being overwritten.
- */
- for(i=0; i<nOld; i++){
- copyPage(&aOld[i], apOld[i]);
- }
-
- /*
- ** Load pointers to all cells on sibling pages and the divider cells
- ** into the local apCell[] array. Make copies of the divider cells
- ** into aTemp[] and remove the the divider Cells from pParent.
- */
- nCell = 0;
- for(i=0; i<nOld; i++){
- MemPage *pOld = &aOld[i];
- for(j=0; j<pOld->nCell; j++){
- apCell[nCell] = pOld->apCell[j];
- szCell[nCell] = cellSize(pBt, apCell[nCell]);
- nCell++;
- }
- if( i<nOld-1 ){
- szCell[nCell] = cellSize(pBt, apDiv[i]);
- memcpy(&aTemp[i], apDiv[i], szCell[nCell]);
- apCell[nCell] = &aTemp[i];
- dropCell(pBt, pParent, nxDiv, szCell[nCell]);
- assert( SWAB32(pBt, apCell[nCell]->h.leftChild)==pgnoOld[i] );
- apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild;
- nCell++;
- }
- }
-
- /*
- ** Figure out the number of pages needed to hold all nCell cells.
- ** Store this number in "k". Also compute szNew[] which is the total
- ** size of all cells on the i-th page and cntNew[] which is the index
- ** in apCell[] of the cell that divides path i from path i+1.
- ** cntNew[k] should equal nCell.
- **
- ** This little patch of code is critical for keeping the tree
- ** balanced.
- */
- for(subtotal=k=i=0; i<nCell; i++){
- subtotal += szCell[i];
- if( subtotal > USABLE_SPACE ){
- szNew[k] = subtotal - szCell[i];
- cntNew[k] = i;
- subtotal = 0;
- k++;
- }
- }
- szNew[k] = subtotal;
- cntNew[k] = nCell;
- k++;
- for(i=k-1; i>0; i--){
- while( szNew[i]<USABLE_SPACE/2 ){
- cntNew[i-1]--;
- assert( cntNew[i-1]>0 );
- szNew[i] += szCell[cntNew[i-1]];
- szNew[i-1] -= szCell[cntNew[i-1]-1];
- }
- }
- assert( cntNew[0]>0 );
-
- /*
- ** Allocate k new pages. Reuse old pages where possible.
- */
- for(i=0; i<k; i++){
- if( i<nOld ){
- apNew[i] = apOld[i];
- pgnoNew[i] = pgnoOld[i];
- apOld[i] = 0;
- sqlitepager_write(apNew[i]);
- }else{
- rc = allocatePage(pBt, &apNew[i], &pgnoNew[i], pgnoNew[i-1]);
- if( rc ) goto balance_cleanup;
- }
- nNew++;
- zeroPage(pBt, apNew[i]);
- apNew[i]->isInit = 1;
- }
-
- /* Free any old pages that were not reused as new pages.
- */
- while( i<nOld ){
- rc = freePage(pBt, apOld[i], pgnoOld[i]);
- if( rc ) goto balance_cleanup;
- sqlitepager_unref(apOld[i]);
- apOld[i] = 0;
- i++;
- }
-
- /*
- ** Put the new pages in accending order. This helps to
- ** keep entries in the disk file in order so that a scan
- ** of the table is a linear scan through the file. That
- ** in turn helps the operating system to deliver pages
- ** from the disk more rapidly.
- **
- ** An O(n^2) insertion sort algorithm is used, but since
- ** n is never more than NB (a small constant), that should
- ** not be a problem.
- **
- ** When NB==3, this one optimization makes the database
- ** about 25% faster for large insertions and deletions.
- */
- for(i=0; i<k-1; i++){
- int minV = pgnoNew[i];
- int minI = i;
- for(j=i+1; j<k; j++){
- if( pgnoNew[j]<(unsigned)minV ){
- minI = j;
- minV = pgnoNew[j];
- }
- }
- if( minI>i ){
- int t;
- MemPage *pT;
- t = pgnoNew[i];
- pT = apNew[i];
- pgnoNew[i] = pgnoNew[minI];
- apNew[i] = apNew[minI];
- pgnoNew[minI] = t;
- apNew[minI] = pT;
- }
- }
-
- /*
- ** Evenly distribute the data in apCell[] across the new pages.
- ** Insert divider cells into pParent as necessary.
- */
- j = 0;
- for(i=0; i<nNew; i++){
- MemPage *pNew = apNew[i];
- while( j<cntNew[i] ){
- assert( pNew->nFree>=szCell[j] );
- if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; }
- insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]);
- j++;
- }
- assert( pNew->nCell>0 );
- assert( !pNew->isOverfull );
- relinkCellList(pBt, pNew);
- if( i<nNew-1 && j<nCell ){
- pNew->u.hdr.rightChild = apCell[j]->h.leftChild;
- apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]);
- if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; }
- insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]);
- j++;
- nxDiv++;
- }
- }
- assert( j==nCell );
- apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild;
- if( nxDiv==pParent->nCell ){
- pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]);
- }else{
- pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]);
- }
- if( pCur ){
- if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){
- assert( pCur->pPage==pOldCurPage );
- pCur->idx += nNew - nOld;
- }else{
- assert( pOldCurPage!=0 );
- sqlitepager_ref(pCur->pPage);
- sqlitepager_unref(pOldCurPage);
- }
- }
-
- /*
- ** Reparent children of all cells.
- */
- for(i=0; i<nNew; i++){
- reparentChildPages(pBt, apNew[i]);
- }
- reparentChildPages(pBt, pParent);
-
- /*
- ** balance the parent page.
- */
- rc = balance(pBt, pParent, pCur);
-
- /*
- ** Cleanup before returning.
- */
-balance_cleanup:
- if( extraUnref ){
- sqlitepager_unref(extraUnref);
- }
- for(i=0; i<nOld; i++){
- if( apOld[i]!=0 && apOld[i]!=&aOld[i] ) sqlitepager_unref(apOld[i]);
- }
- for(i=0; i<nNew; i++){
- sqlitepager_unref(apNew[i]);
- }
- if( pCur && pCur->pPage==0 ){
- pCur->pPage = pParent;
- pCur->idx = 0;
- }else{
- sqlitepager_unref(pParent);
- }
- return rc;
-}
-
-/*
-** This routine checks all cursors that point to the same table
-** as pCur points to. If any of those cursors were opened with
-** wrFlag==0 then this routine returns SQLITE_LOCKED. If all
-** cursors point to the same table were opened with wrFlag==1
-** then this routine returns SQLITE_OK.
-**
-** In addition to checking for read-locks (where a read-lock
-** means a cursor opened with wrFlag==0) this routine also moves
-** all cursors other than pCur so that they are pointing to the
-** first Cell on root page. This is necessary because an insert
-** or delete might change the number of cells on a page or delete
-** a page entirely and we do not want to leave any cursors
-** pointing to non-existant pages or cells.
-*/
-static int checkReadLocks(BtCursor *pCur){
- BtCursor *p;
- assert( pCur->wrFlag );
- for(p=pCur->pShared; p!=pCur; p=p->pShared){
- assert( p );
- assert( p->pgnoRoot==pCur->pgnoRoot );
- if( p->wrFlag==0 ) return SQLITE_LOCKED;
- if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){
- moveToRoot(p);
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Insert a new record into the BTree. The key is given by (pKey,nKey)
-** and the data is given by (pData,nData). The cursor is used only to
-** define what database the record should be inserted into. The cursor
-** is left pointing at the new record.
-*/
-static int fileBtreeInsert(
- BtCursor *pCur, /* Insert data into the table of this cursor */
- const void *pKey, int nKey, /* The key of the new record */
- const void *pData, int nData /* The data of the new record */
-){
- Cell newCell;
- int rc;
- int loc;
- int szNew;
- MemPage *pPage;
- Btree *pBt = pCur->pBt;
-
- if( pCur->pPage==0 ){
- return SQLITE_ABORT; /* A rollback destroyed this cursor */
- }
- if( !pBt->inTrans || nKey+nData==0 ){
- /* Must start a transaction before doing an insert */
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- assert( !pBt->readOnly );
- if( !pCur->wrFlag ){
- return SQLITE_PERM; /* Cursor not open for writing */
- }
- if( checkReadLocks(pCur) ){
- return SQLITE_LOCKED; /* The table pCur points to has a read lock */
- }
- rc = fileBtreeMoveto(pCur, pKey, nKey, &loc);
- if( rc ) return rc;
- pPage = pCur->pPage;
- assert( pPage->isInit );
- rc = sqlitepager_write(pPage);
- if( rc ) return rc;
- rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData);
- if( rc ) return rc;
- szNew = cellSize(pBt, &newCell);
- if( loc==0 ){
- newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild;
- rc = clearCell(pBt, pPage->apCell[pCur->idx]);
- if( rc ) return rc;
- dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx]));
- }else if( loc<0 && pPage->nCell>0 ){
- assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
- pCur->idx++;
- }else{
- assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
- }
- insertCell(pBt, pPage, pCur->idx, &newCell, szNew);
- rc = balance(pCur->pBt, pPage, pCur);
- /* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
- /* fflush(stdout); */
- pCur->eSkip = SKIP_INVALID;
- return rc;
-}
-
-/*
-** Delete the entry that the cursor is pointing to.
-**
-** The cursor is left pointing at either the next or the previous
-** entry. If the cursor is left pointing to the next entry, then
-** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to
-** sqliteBtreeNext() to be a no-op. That way, you can always call
-** sqliteBtreeNext() after a delete and the cursor will be left
-** pointing to the first entry after the deleted entry. Similarly,
-** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
-** the entry prior to the deleted entry so that a subsequent call to
-** sqliteBtreePrevious() will always leave the cursor pointing at the
-** entry immediately before the one that was deleted.
-*/
-static int fileBtreeDelete(BtCursor *pCur){
- MemPage *pPage = pCur->pPage;
- Cell *pCell;
- int rc;
- Pgno pgnoChild;
- Btree *pBt = pCur->pBt;
-
- assert( pPage->isInit );
- if( pCur->pPage==0 ){
- return SQLITE_ABORT; /* A rollback destroyed this cursor */
- }
- if( !pBt->inTrans ){
- /* Must start a transaction before doing a delete */
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- assert( !pBt->readOnly );
- if( pCur->idx >= pPage->nCell ){
- return SQLITE_ERROR; /* The cursor is not pointing to anything */
- }
- if( !pCur->wrFlag ){
- return SQLITE_PERM; /* Did not open this cursor for writing */
- }
- if( checkReadLocks(pCur) ){
- return SQLITE_LOCKED; /* The table pCur points to has a read lock */
- }
- rc = sqlitepager_write(pPage);
- if( rc ) return rc;
- pCell = pPage->apCell[pCur->idx];
- pgnoChild = SWAB32(pBt, pCell->h.leftChild);
- clearCell(pBt, pCell);
- if( pgnoChild ){
- /*
- ** The entry we are about to delete is not a leaf so if we do not
- ** do something we will leave a hole on an internal page.
- ** We have to fill the hole by moving in a cell from a leaf. The
- ** next Cell after the one to be deleted is guaranteed to exist and
- ** to be a leaf so we can use it.
- */
- BtCursor leafCur;
- Cell *pNext;
- int szNext;
- int notUsed;
- getTempCursor(pCur, &leafCur);
- rc = fileBtreeNext(&leafCur, &notUsed);
- if( rc!=SQLITE_OK ){
- if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT;
- return rc;
- }
- rc = sqlitepager_write(leafCur.pPage);
- if( rc ) return rc;
- dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
- pNext = leafCur.pPage->apCell[leafCur.idx];
- szNext = cellSize(pBt, pNext);
- pNext->h.leftChild = SWAB32(pBt, pgnoChild);
- insertCell(pBt, pPage, pCur->idx, pNext, szNext);
- rc = balance(pBt, pPage, pCur);
- if( rc ) return rc;
- pCur->eSkip = SKIP_NEXT;
- dropCell(pBt, leafCur.pPage, leafCur.idx, szNext);
- rc = balance(pBt, leafCur.pPage, pCur);
- releaseTempCursor(&leafCur);
- }else{
- dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
- if( pCur->idx>=pPage->nCell ){
- pCur->idx = pPage->nCell-1;
- if( pCur->idx<0 ){
- pCur->idx = 0;
- pCur->eSkip = SKIP_NEXT;
- }else{
- pCur->eSkip = SKIP_PREV;
- }
- }else{
- pCur->eSkip = SKIP_NEXT;
- }
- rc = balance(pBt, pPage, pCur);
- }
- return rc;
-}
-
-/*
-** Create a new BTree table. Write into *piTable the page
-** number for the root page of the new table.
-**
-** In the current implementation, BTree tables and BTree indices are the
-** the same. In the future, we may change this so that BTree tables
-** are restricted to having a 4-byte integer key and arbitrary data and
-** BTree indices are restricted to having an arbitrary key and no data.
-** But for now, this routine also serves to create indices.
-*/
-static int fileBtreeCreateTable(Btree *pBt, int *piTable){
- MemPage *pRoot;
- Pgno pgnoRoot;
- int rc;
- if( !pBt->inTrans ){
- /* Must start a transaction first */
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- if( pBt->readOnly ){
- return SQLITE_READONLY;
- }
- rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0);
- if( rc ) return rc;
- assert( sqlitepager_iswriteable(pRoot) );
- zeroPage(pBt, pRoot);
- sqlitepager_unref(pRoot);
- *piTable = (int)pgnoRoot;
- return SQLITE_OK;
-}
-
-/*
-** Erase the given database page and all its children. Return
-** the page to the freelist.
-*/
-static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
- MemPage *pPage;
- int rc;
- Cell *pCell;
- int idx;
-
- rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage);
- if( rc ) return rc;
- rc = sqlitepager_write(pPage);
- if( rc ) return rc;
- rc = initPage(pBt, pPage, pgno, 0);
- if( rc ) return rc;
- idx = SWAB16(pBt, pPage->u.hdr.firstCell);
- while( idx>0 ){
- pCell = (Cell*)&pPage->u.aDisk[idx];
- idx = SWAB16(pBt, pCell->h.iNext);
- if( pCell->h.leftChild ){
- rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
- if( rc ) return rc;
- }
- rc = clearCell(pBt, pCell);
- if( rc ) return rc;
- }
- if( pPage->u.hdr.rightChild ){
- rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
- if( rc ) return rc;
- }
- if( freePageFlag ){
- rc = freePage(pBt, pPage, pgno);
- }else{
- zeroPage(pBt, pPage);
- }
- sqlitepager_unref(pPage);
- return rc;
-}
-
-/*
-** Delete all information from a single table in the database.
-*/
-static int fileBtreeClearTable(Btree *pBt, int iTable){
- int rc;
- BtCursor *pCur;
- if( !pBt->inTrans ){
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->pgnoRoot==(Pgno)iTable ){
- if( pCur->wrFlag==0 ) return SQLITE_LOCKED;
- moveToRoot(pCur);
- }
- }
- rc = clearDatabasePage(pBt, (Pgno)iTable, 0);
- if( rc ){
- fileBtreeRollback(pBt);
- }
- return rc;
-}
-
-/*
-** Erase all information in a table and add the root of the table to
-** the freelist. Except, the root of the principle table (the one on
-** page 2) is never added to the freelist.
-*/
-static int fileBtreeDropTable(Btree *pBt, int iTable){
- int rc;
- MemPage *pPage;
- BtCursor *pCur;
- if( !pBt->inTrans ){
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( pCur->pgnoRoot==(Pgno)iTable ){
- return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */
- }
- }
- rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
- if( rc ) return rc;
- rc = fileBtreeClearTable(pBt, iTable);
- if( rc ) return rc;
- if( iTable>2 ){
- rc = freePage(pBt, pPage, iTable);
- }else{
- zeroPage(pBt, pPage);
- }
- sqlitepager_unref(pPage);
- return rc;
-}
-
-#if 0 /* UNTESTED */
-/*
-** Copy all cell data from one database file into another.
-** pages back the freelist.
-*/
-static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){
- Pager *pFromPager = pBtFrom->pPager;
- OverflowPage *pOvfl;
- Pgno ovfl, nextOvfl;
- Pgno *pPrev;
- int rc = SQLITE_OK;
- MemPage *pNew, *pPrevPg;
- Pgno new;
-
- if( NKEY(pBtTo, pCell->h) + NDATA(pBtTo, pCell->h) <= MX_LOCAL_PAYLOAD ){
- return SQLITE_OK;
- }
- pPrev = &pCell->ovfl;
- pPrevPg = 0;
- ovfl = SWAB32(pBtTo, pCell->ovfl);
- while( ovfl && rc==SQLITE_OK ){
- rc = sqlitepager_get(pFromPager, ovfl, (void**)&pOvfl);
- if( rc ) return rc;
- nextOvfl = SWAB32(pBtFrom, pOvfl->iNext);
- rc = allocatePage(pBtTo, &pNew, &new, 0);
- if( rc==SQLITE_OK ){
- rc = sqlitepager_write(pNew);
- if( rc==SQLITE_OK ){
- memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE);
- *pPrev = SWAB32(pBtTo, new);
- if( pPrevPg ){
- sqlitepager_unref(pPrevPg);
- }
- pPrev = &pOvfl->iNext;
- pPrevPg = pNew;
- }
- }
- sqlitepager_unref(pOvfl);
- ovfl = nextOvfl;
- }
- if( pPrevPg ){
- sqlitepager_unref(pPrevPg);
- }
- return rc;
-}
-#endif
-
-
-#if 0 /* UNTESTED */
-/*
-** Copy a page of data from one database over to another.
-*/
-static int copyDatabasePage(
- Btree *pBtFrom,
- Pgno pgnoFrom,
- Btree *pBtTo,
- Pgno *pTo
-){
- MemPage *pPageFrom, *pPage;
- Pgno to;
- int rc;
- Cell *pCell;
- int idx;
-
- rc = sqlitepager_get(pBtFrom->pPager, pgno, (void**)&pPageFrom);
- if( rc ) return rc;
- rc = allocatePage(pBt, &pPage, pTo, 0);
- if( rc==SQLITE_OK ){
- rc = sqlitepager_write(pPage);
- }
- if( rc==SQLITE_OK ){
- memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE);
- idx = SWAB16(pBt, pPage->u.hdr.firstCell);
- while( idx>0 ){
- pCell = (Cell*)&pPage->u.aDisk[idx];
- idx = SWAB16(pBt, pCell->h.iNext);
- if( pCell->h.leftChild ){
- Pgno newChld;
- rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pCell->h.leftChild),
- pBtTo, &newChld);
- if( rc ) return rc;
- pCell->h.leftChild = SWAB32(pBtFrom, newChld);
- }
- rc = copyCell(pBtFrom, pBtTo, pCell);
- if( rc ) return rc;
- }
- if( pPage->u.hdr.rightChild ){
- Pgno newChld;
- rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pPage->u.hdr.rightChild),
- pBtTo, &newChld);
- if( rc ) return rc;
- pPage->u.hdr.rightChild = SWAB32(pBtTo, newChild);
- }
- }
- sqlitepager_unref(pPage);
- return rc;
-}
-#endif
-
-/*
-** Read the meta-information out of a database file.
-*/
-static int fileBtreeGetMeta(Btree *pBt, int *aMeta){
- PageOne *pP1;
- int rc;
- int i;
-
- rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1);
- if( rc ) return rc;
- aMeta[0] = SWAB32(pBt, pP1->nFree);
- for(i=0; i<sizeof(pP1->aMeta)/sizeof(pP1->aMeta[0]); i++){
- aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]);
- }
- sqlitepager_unref(pP1);
- return SQLITE_OK;
-}
-
-/*
-** Write meta-information back into the database.
-*/
-static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){
- PageOne *pP1;
- int rc, i;
- if( !pBt->inTrans ){
- return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
- }
- pP1 = pBt->page1;
- rc = sqlitepager_write(pP1);
- if( rc ) return rc;
- for(i=0; i<sizeof(pP1->aMeta)/sizeof(pP1->aMeta[0]); i++){
- pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]);
- }
- return SQLITE_OK;
-}
-
-/******************************************************************************
-** The complete implementation of the BTree subsystem is above this line.
-** All the code the follows is for testing and troubleshooting the BTree
-** subsystem. None of the code that follows is used during normal operation.
-******************************************************************************/
-
-/*
-** Print a disassembly of the given page on standard output. This routine
-** is used for debugging and testing only.
-*/
-#ifdef SQLITE_TEST
-static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){
- int rc;
- MemPage *pPage;
- int i, j;
- int nFree;
- u16 idx;
- char range[20];
- unsigned char payload[20];
- rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage);
- if( rc ){
- return rc;
- }
- if( recursive ) printf("PAGE %d:\n", pgno);
- i = 0;
- idx = SWAB16(pBt, pPage->u.hdr.firstCell);
- while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
- Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
- int sz = cellSize(pBt, pCell);
- sprintf(range,"%d..%d", idx, idx+sz-1);
- sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
- if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1;
- memcpy(payload, pCell->aPayload, sz);
- for(j=0; j<sz; j++){
- if( payload[j]<0x20 || payload[j]>0x7f ) payload[j] = '.';
- }
- payload[sz] = 0;
- printf(
- "cell %2d: i=%-10s chld=%-4d nk=%-4d nd=%-4d payload=%s\n",
- i, range, (int)pCell->h.leftChild,
- NKEY(pBt, pCell->h), NDATA(pBt, pCell->h),
- payload
- );
- if( pPage->isInit && pPage->apCell[i]!=pCell ){
- printf("**** apCell[%d] does not match on prior entry ****\n", i);
- }
- i++;
- idx = SWAB16(pBt, pCell->h.iNext);
- }
- if( idx!=0 ){
- printf("ERROR: next cell index out of range: %d\n", idx);
- }
- printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild));
- nFree = 0;
- i = 0;
- idx = SWAB16(pBt, pPage->u.hdr.firstFree);
- while( idx>0 && idx<SQLITE_USABLE_SIZE ){
- FreeBlk *p = (FreeBlk*)&pPage->u.aDisk[idx];
- sprintf(range,"%d..%d", idx, idx+p->iSize-1);
- nFree += SWAB16(pBt, p->iSize);
- printf("freeblock %2d: i=%-10s size=%-4d total=%d\n",
- i, range, SWAB16(pBt, p->iSize), nFree);
- idx = SWAB16(pBt, p->iNext);
- i++;
- }
- if( idx!=0 ){
- printf("ERROR: next freeblock index out of range: %d\n", idx);
- }
- if( recursive && pPage->u.hdr.rightChild!=0 ){
- idx = SWAB16(pBt, pPage->u.hdr.firstCell);
- while( idx>0 && idx<SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){
- Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
- fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
- idx = SWAB16(pBt, pCell->h.iNext);
- }
- fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
- }
- sqlitepager_unref(pPage);
- return SQLITE_OK;
-}
-#endif
-
-#ifdef SQLITE_TEST
-/*
-** Fill aResult[] with information about the entry and page that the
-** cursor is pointing to.
-**
-** aResult[0] = The page number
-** aResult[1] = The entry number
-** aResult[2] = Total number of entries on this page
-** aResult[3] = Size of this entry
-** aResult[4] = Number of free bytes on this page
-** aResult[5] = Number of free blocks on the page
-** aResult[6] = Page number of the left child of this entry
-** aResult[7] = Page number of the right child for the whole page
-**
-** This routine is used for testing and debugging only.
-*/
-static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){
- int cnt, idx;
- MemPage *pPage = pCur->pPage;
- Btree *pBt = pCur->pBt;
- aResult[0] = sqlitepager_pagenumber(pPage);
- aResult[1] = pCur->idx;
- aResult[2] = pPage->nCell;
- if( pCur->idx>=0 && pCur->idx<pPage->nCell ){
- aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]);
- aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild);
- }else{
- aResult[3] = 0;
- aResult[6] = 0;
- }
- aResult[4] = pPage->nFree;
- cnt = 0;
- idx = SWAB16(pBt, pPage->u.hdr.firstFree);
- while( idx>0 && idx<SQLITE_USABLE_SIZE ){
- cnt++;
- idx = SWAB16(pBt, ((FreeBlk*)&pPage->u.aDisk[idx])->iNext);
- }
- aResult[5] = cnt;
- aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild);
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Return the pager associated with a BTree. This routine is used for
-** testing and debugging only.
-*/
-static Pager *fileBtreePager(Btree *pBt){
- return pBt->pPager;
-}
-
-/*
-** This structure is passed around through all the sanity checking routines
-** in order to keep track of some global state information.
-*/
-typedef struct IntegrityCk IntegrityCk;
-struct IntegrityCk {
- Btree *pBt; /* The tree being checked out */
- Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
- int nPage; /* Number of pages in the database */
- int *anRef; /* Number of times each page is referenced */
- char *zErrMsg; /* An error message. NULL of no errors seen. */
-};
-
-/*
-** Append a message to the error message string.
-*/
-static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
- if( pCheck->zErrMsg ){
- char *zOld = pCheck->zErrMsg;
- pCheck->zErrMsg = 0;
- sqliteSetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0);
- sqliteFree(zOld);
- }else{
- sqliteSetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
- }
-}
-
-/*
-** Add 1 to the reference count for page iPage. If this is the second
-** reference to the page, add an error message to pCheck->zErrMsg.
-** Return 1 if there are 2 ore more references to the page and 0 if
-** if this is the first reference to the page.
-**
-** Also check that the page number is in bounds.
-*/
-static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
- if( iPage==0 ) return 1;
- if( iPage>pCheck->nPage || iPage<0 ){
- char zBuf[100];
- sprintf(zBuf, "invalid page number %d", iPage);
- checkAppendMsg(pCheck, zContext, zBuf);
- return 1;
- }
- if( pCheck->anRef[iPage]==1 ){
- char zBuf[100];
- sprintf(zBuf, "2nd reference to page %d", iPage);
- checkAppendMsg(pCheck, zContext, zBuf);
- return 1;
- }
- return (pCheck->anRef[iPage]++)>1;
-}
-
-/*
-** Check the integrity of the freelist or of an overflow page list.
-** Verify that the number of pages on the list is N.
-*/
-static void checkList(
- IntegrityCk *pCheck, /* Integrity checking context */
- int isFreeList, /* True for a freelist. False for overflow page list */
- int iPage, /* Page number for first page in the list */
- int N, /* Expected number of pages in the list */
- char *zContext /* Context for error messages */
-){
- int i;
- char zMsg[100];
- while( N-- > 0 ){
- OverflowPage *pOvfl;
- if( iPage<1 ){
- sprintf(zMsg, "%d pages missing from overflow list", N+1);
- checkAppendMsg(pCheck, zContext, zMsg);
- break;
- }
- if( checkRef(pCheck, iPage, zContext) ) break;
- if( sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){
- sprintf(zMsg, "failed to get page %d", iPage);
- checkAppendMsg(pCheck, zContext, zMsg);
- break;
- }
- if( isFreeList ){
- FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload;
- int n = SWAB32(pCheck->pBt, pInfo->nFree);
- for(i=0; i<n; i++){
- checkRef(pCheck, SWAB32(pCheck->pBt, pInfo->aFree[i]), zContext);
- }
- N -= n;
- }
- iPage = SWAB32(pCheck->pBt, pOvfl->iNext);
- sqlitepager_unref(pOvfl);
- }
-}
-
-/*
-** Return negative if zKey1<zKey2.
-** Return zero if zKey1==zKey2.
-** Return positive if zKey1>zKey2.
-*/
-static int keyCompare(
- const char *zKey1, int nKey1,
- const char *zKey2, int nKey2
-){
- int min = nKey1>nKey2 ? nKey2 : nKey1;
- int c = memcmp(zKey1, zKey2, min);
- if( c==0 ){
- c = nKey1 - nKey2;
- }
- return c;
-}
-
-/*
-** Do various sanity checks on a single page of a tree. Return
-** the tree depth. Root pages return 0. Parents of root pages
-** return 1, and so forth.
-**
-** These checks are done:
-**
-** 1. Make sure that cells and freeblocks do not overlap
-** but combine to completely cover the page.
-** 2. Make sure cell keys are in order.
-** 3. Make sure no key is less than or equal to zLowerBound.
-** 4. Make sure no key is greater than or equal to zUpperBound.
-** 5. Check the integrity of overflow pages.
-** 6. Recursively call checkTreePage on all children.
-** 7. Verify that the depth of all children is the same.
-** 8. Make sure this page is at least 33% full or else it is
-** the root of the tree.
-*/
-static int checkTreePage(
- IntegrityCk *pCheck, /* Context for the sanity check */
- int iPage, /* Page number of the page to check */
- MemPage *pParent, /* Parent page */
- char *zParentContext, /* Parent context */
- char *zLowerBound, /* All keys should be greater than this, if not NULL */
- int nLower, /* Number of characters in zLowerBound */
- char *zUpperBound, /* All keys should be less than this, if not NULL */
- int nUpper /* Number of characters in zUpperBound */
-){
- MemPage *pPage;
- int i, rc, depth, d2, pgno;
- char *zKey1, *zKey2;
- int nKey1, nKey2;
- BtCursor cur;
- Btree *pBt;
- char zMsg[100];
- char zContext[100];
- char hit[SQLITE_USABLE_SIZE];
-
- /* Check that the page exists
- */
- cur.pBt = pBt = pCheck->pBt;
- if( iPage==0 ) return 0;
- if( checkRef(pCheck, iPage, zParentContext) ) return 0;
- sprintf(zContext, "On tree page %d: ", iPage);
- if( (rc = sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pPage))!=0 ){
- sprintf(zMsg, "unable to get the page. error code=%d", rc);
- checkAppendMsg(pCheck, zContext, zMsg);
- return 0;
- }
- if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){
- sprintf(zMsg, "initPage() returns error code %d", rc);
- checkAppendMsg(pCheck, zContext, zMsg);
- sqlitepager_unref(pPage);
- return 0;
- }
-
- /* Check out all the cells.
- */
- depth = 0;
- if( zLowerBound ){
- zKey1 = sqliteMalloc( nLower+1 );
- memcpy(zKey1, zLowerBound, nLower);
- zKey1[nLower] = 0;
- }else{
- zKey1 = 0;
- }
- nKey1 = nLower;
- cur.pPage = pPage;
- for(i=0; i<pPage->nCell; i++){
- Cell *pCell = pPage->apCell[i];
- int sz;
-
- /* Check payload overflow pages
- */
- nKey2 = NKEY(pBt, pCell->h);
- sz = nKey2 + NDATA(pBt, pCell->h);
- sprintf(zContext, "On page %d cell %d: ", iPage, i);
- if( sz>MX_LOCAL_PAYLOAD ){
- int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE;
- checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext);
- }
-
- /* Check that keys are in the right order
- */
- cur.idx = i;
- zKey2 = sqliteMallocRaw( nKey2+1 );
- getPayload(&cur, 0, nKey2, zKey2);
- if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){
- checkAppendMsg(pCheck, zContext, "Key is out of order");
- }
-
- /* Check sanity of left child page.
- */
- pgno = SWAB32(pBt, pCell->h.leftChild);
- d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2);
- if( i>0 && d2!=depth ){
- checkAppendMsg(pCheck, zContext, "Child page depth differs");
- }
- depth = d2;
- sqliteFree(zKey1);
- zKey1 = zKey2;
- nKey1 = nKey2;
- }
- pgno = SWAB32(pBt, pPage->u.hdr.rightChild);
- sprintf(zContext, "On page %d at right child: ", iPage);
- checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper);
- sqliteFree(zKey1);
-
- /* Check for complete coverage of the page
- */
- memset(hit, 0, sizeof(hit));
- memset(hit, 1, sizeof(PageHdr));
- for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && i<SQLITE_USABLE_SIZE; ){
- Cell *pCell = (Cell*)&pPage->u.aDisk[i];
- int j;
- for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++;
- i = SWAB16(pBt, pCell->h.iNext);
- }
- for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && i<SQLITE_USABLE_SIZE; ){
- FreeBlk *pFBlk = (FreeBlk*)&pPage->u.aDisk[i];
- int j;
- for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++;
- i = SWAB16(pBt,pFBlk->iNext);
- }
- for(i=0; i<SQLITE_USABLE_SIZE; i++){
- if( hit[i]==0 ){
- sprintf(zMsg, "Unused space at byte %d of page %d", i, iPage);
- checkAppendMsg(pCheck, zMsg, 0);
- break;
- }else if( hit[i]>1 ){
- sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage);
- checkAppendMsg(pCheck, zMsg, 0);
- break;
- }
- }
-
- /* Check that free space is kept to a minimum
- */
-#if 0
- if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){
- sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree,
- SQLITE_USABLE_SIZE/3);
- checkAppendMsg(pCheck, zContext, zMsg);
- }
-#endif
-
- sqlitepager_unref(pPage);
- return depth;
-}
-
-/*
-** This routine does a complete check of the given BTree file. aRoot[] is
-** an array of pages numbers were each page number is the root page of
-** a table. nRoot is the number of entries in aRoot.
-**
-** If everything checks out, this routine returns NULL. If something is
-** amiss, an error message is written into memory obtained from malloc()
-** and a pointer to that error message is returned. The calling function
-** is responsible for freeing the error message when it is done.
-*/
-char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
- int i;
- int nRef;
- IntegrityCk sCheck;
-
- nRef = *sqlitepager_stats(pBt->pPager);
- if( lockBtree(pBt)!=SQLITE_OK ){
- return sqliteStrDup("Unable to acquire a read lock on the database");
- }
- sCheck.pBt = pBt;
- sCheck.pPager = pBt->pPager;
- sCheck.nPage = sqlitepager_pagecount(sCheck.pPager);
- if( sCheck.nPage==0 ){
- unlockBtreeIfUnused(pBt);
- return 0;
- }
- sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
- sCheck.anRef[1] = 1;
- for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
- sCheck.zErrMsg = 0;
-
- /* Check the integrity of the freelist
- */
- checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList),
- SWAB32(pBt, pBt->page1->nFree), "Main freelist: ");
-
- /* Check all the tables.
- */
- for(i=0; i<nRoot; i++){
- if( aRoot[i]==0 ) continue;
- checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0);
- }
-
- /* Make sure every page in the file is referenced
- */
- for(i=1; i<=sCheck.nPage; i++){
- if( sCheck.anRef[i]==0 ){
- char zBuf[100];
- sprintf(zBuf, "Page %d is never used", i);
- checkAppendMsg(&sCheck, zBuf, 0);
- }
- }
-
- /* Make sure this analysis did not leave any unref() pages
- */
- unlockBtreeIfUnused(pBt);
- if( nRef != *sqlitepager_stats(pBt->pPager) ){
- char zBuf[100];
- sprintf(zBuf,
- "Outstanding page count goes from %d to %d during this analysis",
- nRef, *sqlitepager_stats(pBt->pPager)
- );
- checkAppendMsg(&sCheck, zBuf, 0);
- }
-
- /* Clean up and report errors.
- */
- sqliteFree(sCheck.anRef);
- return sCheck.zErrMsg;
-}
-
-/*
-** Return the full pathname of the underlying database file.
-*/
-static const char *fileBtreeGetFilename(Btree *pBt){
- assert( pBt->pPager!=0 );
- return sqlitepager_filename(pBt->pPager);
-}
-
-/*
-** Copy the complete content of pBtFrom into pBtTo. A transaction
-** must be active for both files.
-**
-** The size of file pBtFrom may be reduced by this operation.
-** If anything goes wrong, the transaction on pBtFrom is rolled back.
-*/
-static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
- int rc = SQLITE_OK;
- Pgno i, nPage, nToPage;
-
- if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
- if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR;
- if( pBtTo->pCursor ) return SQLITE_BUSY;
- memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE);
- rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1);
- nToPage = sqlitepager_pagecount(pBtTo->pPager);
- nPage = sqlitepager_pagecount(pBtFrom->pPager);
- for(i=2; rc==SQLITE_OK && i<=nPage; i++){
- void *pPage;
- rc = sqlitepager_get(pBtFrom->pPager, i, &pPage);
- if( rc ) break;
- rc = sqlitepager_overwrite(pBtTo->pPager, i, pPage);
- if( rc ) break;
- sqlitepager_unref(pPage);
- }
- for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
- void *pPage;
- rc = sqlitepager_get(pBtTo->pPager, i, &pPage);
- if( rc ) break;
- rc = sqlitepager_write(pPage);
- sqlitepager_unref(pPage);
- sqlitepager_dont_write(pBtTo->pPager, i);
- }
- if( !rc && nPage<nToPage ){
- rc = sqlitepager_truncate(pBtTo->pPager, nPage);
- }
- if( rc ){
- fileBtreeRollback(pBtTo);
- }
- return rc;
-}
-
-/*
-** The following tables contain pointers to all of the interface
-** routines for this implementation of the B*Tree backend. To
-** substitute a different implemention of the backend, one has merely
-** to provide pointers to alternative functions in similar tables.
-*/
-static BtOps sqliteBtreeOps = {
- fileBtreeClose,
- fileBtreeSetCacheSize,
- fileBtreeSetSafetyLevel,
- fileBtreeBeginTrans,
- fileBtreeCommit,
- fileBtreeRollback,
- fileBtreeBeginCkpt,
- fileBtreeCommitCkpt,
- fileBtreeRollbackCkpt,
- fileBtreeCreateTable,
- fileBtreeCreateTable, /* Really sqliteBtreeCreateIndex() */
- fileBtreeDropTable,
- fileBtreeClearTable,
- fileBtreeCursor,
- fileBtreeGetMeta,
- fileBtreeUpdateMeta,
- fileBtreeIntegrityCheck,
- fileBtreeGetFilename,
- fileBtreeCopyFile,
- fileBtreePager,
-#ifdef SQLITE_TEST
- fileBtreePageDump,
-#endif
-};
-static BtCursorOps sqliteBtreeCursorOps = {
- fileBtreeMoveto,
- fileBtreeDelete,
- fileBtreeInsert,
- fileBtreeFirst,
- fileBtreeLast,
- fileBtreeNext,
- fileBtreePrevious,
- fileBtreeKeySize,
- fileBtreeKey,
- fileBtreeKeyCompare,
- fileBtreeDataSize,
- fileBtreeData,
- fileBtreeCloseCursor,
-#ifdef SQLITE_TEST
- fileBtreeCursorDump,
-#endif
-};
diff --git a/ext/sqlite/libsqlite/src/btree.h b/ext/sqlite/libsqlite/src/btree.h
deleted file mode 100644
index 8d318a3c03..0000000000
--- a/ext/sqlite/libsqlite/src/btree.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This header file defines the interface that the sqlite B-Tree file
-** subsystem. See comments in the source code for a detailed description
-** of what each interface routine does.
-**
-** @(#) $Id$
-*/
-#ifndef _BTREE_H_
-#define _BTREE_H_
-
-/*
-** Forward declarations of structure
-*/
-typedef struct Btree Btree;
-typedef struct BtCursor BtCursor;
-typedef struct BtOps BtOps;
-typedef struct BtCursorOps BtCursorOps;
-
-
-/*
-** An instance of the following structure contains pointers to all
-** methods against an open BTree. Alternative BTree implementations
-** (examples: file based versus in-memory) can be created by substituting
-** different methods. Users of the BTree cannot tell the difference.
-**
-** In C++ we could do this by defining a virtual base class and then
-** creating subclasses for each different implementation. But this is
-** C not C++ so we have to be a little more explicit.
-*/
-struct BtOps {
- int (*Close)(Btree*);
- int (*SetCacheSize)(Btree*, int);
- int (*SetSafetyLevel)(Btree*, int);
- int (*BeginTrans)(Btree*);
- int (*Commit)(Btree*);
- int (*Rollback)(Btree*);
- int (*BeginCkpt)(Btree*);
- int (*CommitCkpt)(Btree*);
- int (*RollbackCkpt)(Btree*);
- int (*CreateTable)(Btree*, int*);
- int (*CreateIndex)(Btree*, int*);
- int (*DropTable)(Btree*, int);
- int (*ClearTable)(Btree*, int);
- int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
- int (*GetMeta)(Btree*, int*);
- int (*UpdateMeta)(Btree*, int*);
- char *(*IntegrityCheck)(Btree*, int*, int);
- const char *(*GetFilename)(Btree*);
- int (*Copyfile)(Btree*,Btree*);
- struct Pager *(*Pager)(Btree*);
-#ifdef SQLITE_TEST
- int (*PageDump)(Btree*, int, int);
-#endif
-};
-
-/*
-** An instance of this structure defines all of the methods that can
-** be executed against a cursor.
-*/
-struct BtCursorOps {
- int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
- int (*Delete)(BtCursor*);
- int (*Insert)(BtCursor*, const void *pKey, int nKey,
- const void *pData, int nData);
- int (*First)(BtCursor*, int *pRes);
- int (*Last)(BtCursor*, int *pRes);
- int (*Next)(BtCursor*, int *pRes);
- int (*Previous)(BtCursor*, int *pRes);
- int (*KeySize)(BtCursor*, int *pSize);
- int (*Key)(BtCursor*, int offset, int amt, char *zBuf);
- int (*KeyCompare)(BtCursor*, const void *pKey, int nKey,
- int nIgnore, int *pRes);
- int (*DataSize)(BtCursor*, int *pSize);
- int (*Data)(BtCursor*, int offset, int amt, char *zBuf);
- int (*CloseCursor)(BtCursor*);
-#ifdef SQLITE_TEST
- int (*CursorDump)(BtCursor*, int*);
-#endif
-};
-
-/*
-** The number of 4-byte "meta" values contained on the first page of each
-** database file.
-*/
-#define SQLITE_N_BTREE_META 10
-
-int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
-int sqliteRbtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
-
-#define btOps(pBt) (*((BtOps **)(pBt)))
-#define btCOps(pCur) (*((BtCursorOps **)(pCur)))
-
-#define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt))
-#define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz))
-#define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl))
-#define sqliteBtreeBeginTrans(pBt) (btOps(pBt)->BeginTrans(pBt))
-#define sqliteBtreeCommit(pBt) (btOps(pBt)->Commit(pBt))
-#define sqliteBtreeRollback(pBt) (btOps(pBt)->Rollback(pBt))
-#define sqliteBtreeBeginCkpt(pBt) (btOps(pBt)->BeginCkpt(pBt))
-#define sqliteBtreeCommitCkpt(pBt) (btOps(pBt)->CommitCkpt(pBt))
-#define sqliteBtreeRollbackCkpt(pBt) (btOps(pBt)->RollbackCkpt(pBt))
-#define sqliteBtreeCreateTable(pBt,piTable)\
- (btOps(pBt)->CreateTable(pBt,piTable))
-#define sqliteBtreeCreateIndex(pBt, piIndex)\
- (btOps(pBt)->CreateIndex(pBt, piIndex))
-#define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable))
-#define sqliteBtreeClearTable(pBt, iTable)\
- (btOps(pBt)->ClearTable(pBt, iTable))
-#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\
- (btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur))
-#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\
- (btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes))
-#define sqliteBtreeDelete(pCur) (btCOps(pCur)->Delete(pCur))
-#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \
- (btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData))
-#define sqliteBtreeFirst(pCur, pRes) (btCOps(pCur)->First(pCur, pRes))
-#define sqliteBtreeLast(pCur, pRes) (btCOps(pCur)->Last(pCur, pRes))
-#define sqliteBtreeNext(pCur, pRes) (btCOps(pCur)->Next(pCur, pRes))
-#define sqliteBtreePrevious(pCur, pRes) (btCOps(pCur)->Previous(pCur, pRes))
-#define sqliteBtreeKeySize(pCur, pSize) (btCOps(pCur)->KeySize(pCur, pSize) )
-#define sqliteBtreeKey(pCur, offset, amt, zBuf)\
- (btCOps(pCur)->Key(pCur, offset, amt, zBuf))
-#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\
- (btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes))
-#define sqliteBtreeDataSize(pCur, pSize) (btCOps(pCur)->DataSize(pCur, pSize))
-#define sqliteBtreeData(pCur, offset, amt, zBuf)\
- (btCOps(pCur)->Data(pCur, offset, amt, zBuf))
-#define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur))
-#define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta))
-#define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta))
-#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
- (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
-#define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt))
-#define sqliteBtreeCopyFile(pBt1, pBt2) (btOps(pBt1)->Copyfile(pBt1, pBt2))
-#define sqliteBtreePager(pBt) (btOps(pBt)->Pager(pBt))
-
-#ifdef SQLITE_TEST
-#define sqliteBtreePageDump(pBt, pgno, recursive)\
- (btOps(pBt)->PageDump(pBt, pgno, recursive))
-#define sqliteBtreeCursorDump(pCur, aResult)\
- (btCOps(pCur)->CursorDump(pCur, aResult))
-int btree_native_byte_order;
-#endif /* SQLITE_TEST */
-
-
-#endif /* _BTREE_H_ */
diff --git a/ext/sqlite/libsqlite/src/btree_rb.c b/ext/sqlite/libsqlite/src/btree_rb.c
deleted file mode 100644
index d932ab4a97..0000000000
--- a/ext/sqlite/libsqlite/src/btree_rb.c
+++ /dev/null
@@ -1,1488 +0,0 @@
-/*
-** 2003 Feb 4
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** $Id$
-**
-** This file implements an in-core database using Red-Black balanced
-** binary trees.
-**
-** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
-*/
-#include "btree.h"
-#include "sqliteInt.h"
-#include <assert.h>
-
-/*
-** Omit this whole file if the SQLITE_OMIT_INMEMORYDB macro is
-** defined. This allows a lot of code to be omitted for installations
-** that do not need it.
-*/
-#ifndef SQLITE_OMIT_INMEMORYDB
-
-
-typedef struct BtRbTree BtRbTree;
-typedef struct BtRbNode BtRbNode;
-typedef struct BtRollbackOp BtRollbackOp;
-typedef struct Rbtree Rbtree;
-typedef struct RbtCursor RbtCursor;
-
-/* Forward declarations */
-static BtOps sqliteRbtreeOps;
-static BtCursorOps sqliteRbtreeCursorOps;
-
-/*
- * During each transaction (or checkpoint), a linked-list of
- * "rollback-operations" is accumulated. If the transaction is rolled back,
- * then the list of operations must be executed (to restore the database to
- * it's state before the transaction started). If the transaction is to be
- * committed, just delete the list.
- *
- * Each operation is represented as follows, depending on the value of eOp:
- *
- * ROLLBACK_INSERT -> Need to insert (pKey, pData) into table iTab.
- * ROLLBACK_DELETE -> Need to delete the record (pKey) into table iTab.
- * ROLLBACK_CREATE -> Need to create table iTab.
- * ROLLBACK_DROP -> Need to drop table iTab.
- */
-struct BtRollbackOp {
- u8 eOp;
- int iTab;
- int nKey;
- void *pKey;
- int nData;
- void *pData;
- BtRollbackOp *pNext;
-};
-
-/*
-** Legal values for BtRollbackOp.eOp:
-*/
-#define ROLLBACK_INSERT 1 /* Insert a record */
-#define ROLLBACK_DELETE 2 /* Delete a record */
-#define ROLLBACK_CREATE 3 /* Create a table */
-#define ROLLBACK_DROP 4 /* Drop a table */
-
-struct Rbtree {
- BtOps *pOps; /* Function table */
- int aMetaData[SQLITE_N_BTREE_META];
-
- int next_idx; /* next available table index */
- Hash tblHash; /* All created tables, by index */
- u8 isAnonymous; /* True if this Rbtree is to be deleted when closed */
- u8 eTransState; /* State of this Rbtree wrt transactions */
-
- BtRollbackOp *pTransRollback;
- BtRollbackOp *pCheckRollback;
- BtRollbackOp *pCheckRollbackTail;
-};
-
-/*
-** Legal values for Rbtree.eTransState.
-*/
-#define TRANS_NONE 0 /* No transaction is in progress */
-#define TRANS_INTRANSACTION 1 /* A transaction is in progress */
-#define TRANS_INCHECKPOINT 2 /* A checkpoint is in progress */
-#define TRANS_ROLLBACK 3 /* We are currently rolling back a checkpoint or
- * transaction. */
-
-struct RbtCursor {
- BtCursorOps *pOps; /* Function table */
- Rbtree *pRbtree;
- BtRbTree *pTree;
- int iTree; /* Index of pTree in pRbtree */
- BtRbNode *pNode;
- RbtCursor *pShared; /* List of all cursors on the same Rbtree */
- u8 eSkip; /* Determines if next step operation is a no-op */
- u8 wrFlag; /* True if this cursor is open for writing */
-};
-
-/*
-** Legal values for RbtCursor.eSkip.
-*/
-#define SKIP_NONE 0 /* Always step the cursor */
-#define SKIP_NEXT 1 /* The next sqliteRbtreeNext() is a no-op */
-#define SKIP_PREV 2 /* The next sqliteRbtreePrevious() is a no-op */
-#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */
-
-struct BtRbTree {
- RbtCursor *pCursors; /* All cursors pointing to this tree */
- BtRbNode *pHead; /* Head of the tree, or NULL */
-};
-
-struct BtRbNode {
- int nKey;
- void *pKey;
- int nData;
- void *pData;
- u8 isBlack; /* true for a black node, 0 for a red node */
- BtRbNode *pParent; /* Nodes parent node, NULL for the tree head */
- BtRbNode *pLeft; /* Nodes left child, or NULL */
- BtRbNode *pRight; /* Nodes right child, or NULL */
-
- int nBlackHeight; /* Only used during the red-black integrity check */
-};
-
-/* Forward declarations */
-static int memRbtreeMoveto(
- RbtCursor* pCur,
- const void *pKey,
- int nKey,
- int *pRes
-);
-static int memRbtreeClearTable(Rbtree* tree, int n);
-static int memRbtreeNext(RbtCursor* pCur, int *pRes);
-static int memRbtreeLast(RbtCursor* pCur, int *pRes);
-static int memRbtreePrevious(RbtCursor* pCur, int *pRes);
-
-
-/*
-** This routine checks all cursors that point to the same table
-** as pCur points to. If any of those cursors were opened with
-** wrFlag==0 then this routine returns SQLITE_LOCKED. If all
-** cursors point to the same table were opened with wrFlag==1
-** then this routine returns SQLITE_OK.
-**
-** In addition to checking for read-locks (where a read-lock
-** means a cursor opened with wrFlag==0) this routine also NULLs
-** out the pNode field of all other cursors.
-** This is necessary because an insert
-** or delete might change erase the node out from under
-** another cursor.
-*/
-static int checkReadLocks(RbtCursor *pCur){
- RbtCursor *p;
- assert( pCur->wrFlag );
- for(p=pCur->pTree->pCursors; p; p=p->pShared){
- if( p!=pCur ){
- if( p->wrFlag==0 ) return SQLITE_LOCKED;
- p->pNode = 0;
- }
- }
- return SQLITE_OK;
-}
-
-/*
- * The key-compare function for the red-black trees. Returns as follows:
- *
- * (key1 < key2) -1
- * (key1 == key2) 0
- * (key1 > key2) 1
- *
- * Keys are compared using memcmp(). If one key is an exact prefix of the
- * other, then the shorter key is less than the longer key.
- */
-static int key_compare(void const*pKey1, int nKey1, void const*pKey2, int nKey2)
-{
- int mcmp = memcmp(pKey1, pKey2, (nKey1 <= nKey2)?nKey1:nKey2);
- if( mcmp == 0){
- if( nKey1 == nKey2 ) return 0;
- return ((nKey1 < nKey2)?-1:1);
- }
- return ((mcmp>0)?1:-1);
-}
-
-/*
- * Perform the LEFT-rotate transformation on node X of tree pTree. This
- * transform is part of the red-black balancing code.
- *
- * | |
- * X Y
- * / \ / \
- * a Y X c
- * / \ / \
- * b c a b
- *
- * BEFORE AFTER
- */
-static void leftRotate(BtRbTree *pTree, BtRbNode *pX)
-{
- BtRbNode *pY;
- BtRbNode *pb;
- pY = pX->pRight;
- pb = pY->pLeft;
-
- pY->pParent = pX->pParent;
- if( pX->pParent ){
- if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
- else pX->pParent->pRight = pY;
- }
- pY->pLeft = pX;
- pX->pParent = pY;
- pX->pRight = pb;
- if( pb ) pb->pParent = pX;
- if( pTree->pHead == pX ) pTree->pHead = pY;
-}
-
-/*
- * Perform the RIGHT-rotate transformation on node X of tree pTree. This
- * transform is part of the red-black balancing code.
- *
- * | |
- * X Y
- * / \ / \
- * Y c a X
- * / \ / \
- * a b b c
- *
- * BEFORE AFTER
- */
-static void rightRotate(BtRbTree *pTree, BtRbNode *pX)
-{
- BtRbNode *pY;
- BtRbNode *pb;
- pY = pX->pLeft;
- pb = pY->pRight;
-
- pY->pParent = pX->pParent;
- if( pX->pParent ){
- if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
- else pX->pParent->pRight = pY;
- }
- pY->pRight = pX;
- pX->pParent = pY;
- pX->pLeft = pb;
- if( pb ) pb->pParent = pX;
- if( pTree->pHead == pX ) pTree->pHead = pY;
-}
-
-/*
- * A string-manipulation helper function for check_redblack_tree(). If (orig ==
- * NULL) a copy of val is returned. If (orig != NULL) then a copy of the *
- * concatenation of orig and val is returned. The original orig is deleted
- * (using sqliteFree()).
- */
-static char *append_val(char * orig, char const * val){
- char *z;
- if( !orig ){
- z = sqliteStrDup( val );
- } else{
- z = 0;
- sqliteSetString(&z, orig, val, (char*)0);
- sqliteFree( orig );
- }
- return z;
-}
-
-/*
- * Append a string representation of the entire node to orig and return it.
- * This is used to produce debugging information if check_redblack_tree() finds
- * a problem with a red-black binary tree.
- */
-static char *append_node(char * orig, BtRbNode *pNode, int indent)
-{
- char buf[128];
- int i;
-
- for( i=0; i<indent; i++ ){
- orig = append_val(orig, " ");
- }
-
- sprintf(buf, "%p", pNode);
- orig = append_val(orig, buf);
-
- if( pNode ){
- indent += 3;
- if( pNode->isBlack ){
- orig = append_val(orig, " B \n");
- }else{
- orig = append_val(orig, " R \n");
- }
- orig = append_node( orig, pNode->pLeft, indent );
- orig = append_node( orig, pNode->pRight, indent );
- }else{
- orig = append_val(orig, "\n");
- }
- return orig;
-}
-
-/*
- * Print a representation of a node to stdout. This function is only included
- * so you can call it from within a debugger if things get really bad. It
- * is not called from anyplace in the code.
- */
-static void print_node(BtRbNode *pNode)
-{
- char * str = append_node(0, pNode, 0);
- printf("%s", str);
-
- /* Suppress a warning message about print_node() being unused */
- (void)print_node;
-}
-
-/*
- * Check the following properties of the red-black tree:
- * (1) - If a node is red, both of it's children are black
- * (2) - Each path from a given node to a leaf (NULL) node passes thru the
- * same number of black nodes
- *
- * If there is a problem, append a description (using append_val() ) to *msg.
- */
-static void check_redblack_tree(BtRbTree * tree, char ** msg)
-{
- BtRbNode *pNode;
-
- /* 0 -> came from parent
- * 1 -> came from left
- * 2 -> came from right */
- int prev_step = 0;
-
- pNode = tree->pHead;
- while( pNode ){
- switch( prev_step ){
- case 0:
- if( pNode->pLeft ){
- pNode = pNode->pLeft;
- }else{
- prev_step = 1;
- }
- break;
- case 1:
- if( pNode->pRight ){
- pNode = pNode->pRight;
- prev_step = 0;
- }else{
- prev_step = 2;
- }
- break;
- case 2:
- /* Check red-black property (1) */
- if( !pNode->isBlack &&
- ( (pNode->pLeft && !pNode->pLeft->isBlack) ||
- (pNode->pRight && !pNode->pRight->isBlack) )
- ){
- char buf[128];
- sprintf(buf, "Red node with red child at %p\n", pNode);
- *msg = append_val(*msg, buf);
- *msg = append_node(*msg, tree->pHead, 0);
- *msg = append_val(*msg, "\n");
- }
-
- /* Check red-black property (2) */
- {
- int leftHeight = 0;
- int rightHeight = 0;
- if( pNode->pLeft ){
- leftHeight += pNode->pLeft->nBlackHeight;
- leftHeight += (pNode->pLeft->isBlack?1:0);
- }
- if( pNode->pRight ){
- rightHeight += pNode->pRight->nBlackHeight;
- rightHeight += (pNode->pRight->isBlack?1:0);
- }
- if( leftHeight != rightHeight ){
- char buf[128];
- sprintf(buf, "Different black-heights at %p\n", pNode);
- *msg = append_val(*msg, buf);
- *msg = append_node(*msg, tree->pHead, 0);
- *msg = append_val(*msg, "\n");
- }
- pNode->nBlackHeight = leftHeight;
- }
-
- if( pNode->pParent ){
- if( pNode == pNode->pParent->pLeft ) prev_step = 1;
- else prev_step = 2;
- }
- pNode = pNode->pParent;
- break;
- default: assert(0);
- }
- }
-}
-
-/*
- * Node pX has just been inserted into pTree (by code in sqliteRbtreeInsert()).
- * It is possible that pX is a red node with a red parent, which is a violation
- * of the red-black tree properties. This function performs rotations and
- * color changes to rebalance the tree
- */
-static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
-{
- /* In the first iteration of this loop, pX points to the red node just
- * inserted in the tree. If the parent of pX exists (pX is not the root
- * node) and is red, then the properties of the red-black tree are
- * violated.
- *
- * At the start of any subsequent iterations, pX points to a red node
- * with a red parent. In all other respects the tree is a legal red-black
- * binary tree. */
- while( pX != pTree->pHead && !pX->pParent->isBlack ){
- BtRbNode *pUncle;
- BtRbNode *pGrandparent;
-
- /* Grandparent of pX must exist and must be black. */
- pGrandparent = pX->pParent->pParent;
- assert( pGrandparent );
- assert( pGrandparent->isBlack );
-
- /* Uncle of pX may or may not exist. */
- if( pX->pParent == pGrandparent->pLeft )
- pUncle = pGrandparent->pRight;
- else
- pUncle = pGrandparent->pLeft;
-
- /* If the uncle of pX exists and is red, we do the following:
- * | |
- * G(b) G(r)
- * / \ / \
- * U(r) P(r) U(b) P(b)
- * \ \
- * X(r) X(r)
- *
- * BEFORE AFTER
- * pX is then set to G. If the parent of G is red, then the while loop
- * will run again. */
- if( pUncle && !pUncle->isBlack ){
- pGrandparent->isBlack = 0;
- pUncle->isBlack = 1;
- pX->pParent->isBlack = 1;
- pX = pGrandparent;
- }else{
-
- if( pX->pParent == pGrandparent->pLeft ){
- if( pX == pX->pParent->pRight ){
- /* If pX is a right-child, do the following transform, essentially
- * to change pX into a left-child:
- * | |
- * G(b) G(b)
- * / \ / \
- * P(r) U(b) X(r) U(b)
- * \ /
- * X(r) P(r) <-- new X
- *
- * BEFORE AFTER
- */
- pX = pX->pParent;
- leftRotate(pTree, pX);
- }
-
- /* Do the following transform, which balances the tree :)
- * | |
- * G(b) P(b)
- * / \ / \
- * P(r) U(b) X(r) G(r)
- * / \
- * X(r) U(b)
- *
- * BEFORE AFTER
- */
- assert( pGrandparent == pX->pParent->pParent );
- pGrandparent->isBlack = 0;
- pX->pParent->isBlack = 1;
- rightRotate( pTree, pGrandparent );
-
- }else{
- /* This code is symetric to the illustrated case above. */
- if( pX == pX->pParent->pLeft ){
- pX = pX->pParent;
- rightRotate(pTree, pX);
- }
- assert( pGrandparent == pX->pParent->pParent );
- pGrandparent->isBlack = 0;
- pX->pParent->isBlack = 1;
- leftRotate( pTree, pGrandparent );
- }
- }
- }
- pTree->pHead->isBlack = 1;
-}
-
-/*
- * A child of pParent, which in turn had child pX, has just been removed from
- * pTree (the figure below depicts the operation, Z is being removed). pParent
- * or pX, or both may be NULL.
- * | |
- * P P
- * / \ / \
- * Z X
- * / \
- * X nil
- *
- * This function is only called if Z was black. In this case the red-black tree
- * properties have been violated, and pX has an "extra black". This function
- * performs rotations and color-changes to re-balance the tree.
- */
-static
-void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
-{
- BtRbNode *pSib;
-
- /* TODO: Comment this code! */
- while( pX != pTree->pHead && (!pX || pX->isBlack) ){
- if( pX == pParent->pLeft ){
- pSib = pParent->pRight;
- if( pSib && !(pSib->isBlack) ){
- pSib->isBlack = 1;
- pParent->isBlack = 0;
- leftRotate(pTree, pParent);
- pSib = pParent->pRight;
- }
- if( !pSib ){
- pX = pParent;
- }else if(
- (!pSib->pLeft || pSib->pLeft->isBlack) &&
- (!pSib->pRight || pSib->pRight->isBlack) ) {
- pSib->isBlack = 0;
- pX = pParent;
- }else{
- if( (!pSib->pRight || pSib->pRight->isBlack) ){
- if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
- pSib->isBlack = 0;
- rightRotate( pTree, pSib );
- pSib = pParent->pRight;
- }
- pSib->isBlack = pParent->isBlack;
- pParent->isBlack = 1;
- if( pSib->pRight ) pSib->pRight->isBlack = 1;
- leftRotate(pTree, pParent);
- pX = pTree->pHead;
- }
- }else{
- pSib = pParent->pLeft;
- if( pSib && !(pSib->isBlack) ){
- pSib->isBlack = 1;
- pParent->isBlack = 0;
- rightRotate(pTree, pParent);
- pSib = pParent->pLeft;
- }
- if( !pSib ){
- pX = pParent;
- }else if(
- (!pSib->pLeft || pSib->pLeft->isBlack) &&
- (!pSib->pRight || pSib->pRight->isBlack) ){
- pSib->isBlack = 0;
- pX = pParent;
- }else{
- if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
- if( pSib->pRight ) pSib->pRight->isBlack = 1;
- pSib->isBlack = 0;
- leftRotate( pTree, pSib );
- pSib = pParent->pLeft;
- }
- pSib->isBlack = pParent->isBlack;
- pParent->isBlack = 1;
- if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
- rightRotate(pTree, pParent);
- pX = pTree->pHead;
- }
- }
- pParent = pX->pParent;
- }
- if( pX ) pX->isBlack = 1;
-}
-
-/*
- * Create table n in tree pRbtree. Table n must not exist.
- */
-static void btreeCreateTable(Rbtree* pRbtree, int n)
-{
- BtRbTree *pNewTbl = sqliteMalloc(sizeof(BtRbTree));
- sqliteHashInsert(&pRbtree->tblHash, 0, n, pNewTbl);
-}
-
-/*
- * Log a single "rollback-op" for the given Rbtree. See comments for struct
- * BtRollbackOp.
- */
-static void btreeLogRollbackOp(Rbtree* pRbtree, BtRollbackOp *pRollbackOp)
-{
- assert( pRbtree->eTransState == TRANS_INCHECKPOINT ||
- pRbtree->eTransState == TRANS_INTRANSACTION );
- if( pRbtree->eTransState == TRANS_INTRANSACTION ){
- pRollbackOp->pNext = pRbtree->pTransRollback;
- pRbtree->pTransRollback = pRollbackOp;
- }
- if( pRbtree->eTransState == TRANS_INCHECKPOINT ){
- if( !pRbtree->pCheckRollback ){
- pRbtree->pCheckRollbackTail = pRollbackOp;
- }
- pRollbackOp->pNext = pRbtree->pCheckRollback;
- pRbtree->pCheckRollback = pRollbackOp;
- }
-}
-
-int sqliteRbtreeOpen(
- const char *zFilename,
- int mode,
- int nPg,
- Btree **ppBtree
-){
- Rbtree **ppRbtree = (Rbtree**)ppBtree;
- *ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree));
- if( sqlite_malloc_failed ) goto open_no_mem;
- sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0);
-
- /* Create a binary tree for the SQLITE_MASTER table at location 2 */
- btreeCreateTable(*ppRbtree, 2);
- if( sqlite_malloc_failed ) goto open_no_mem;
- (*ppRbtree)->next_idx = 3;
- (*ppRbtree)->pOps = &sqliteRbtreeOps;
- /* Set file type to 4; this is so that "attach ':memory:' as ...." does not
- ** think that the database in uninitialised and refuse to attach
- */
- (*ppRbtree)->aMetaData[2] = 4;
-
- return SQLITE_OK;
-
-open_no_mem:
- *ppBtree = 0;
- return SQLITE_NOMEM;
-}
-
-/*
- * Create a new table in the supplied Rbtree. Set *n to the new table number.
- * Return SQLITE_OK if the operation is a success.
- */
-static int memRbtreeCreateTable(Rbtree* tree, int* n)
-{
- assert( tree->eTransState != TRANS_NONE );
-
- *n = tree->next_idx++;
- btreeCreateTable(tree, *n);
- if( sqlite_malloc_failed ) return SQLITE_NOMEM;
-
- /* Set up the rollback structure (if we are not doing this as part of a
- * rollback) */
- if( tree->eTransState != TRANS_ROLLBACK ){
- BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
- if( pRollbackOp==0 ) return SQLITE_NOMEM;
- pRollbackOp->eOp = ROLLBACK_DROP;
- pRollbackOp->iTab = *n;
- btreeLogRollbackOp(tree, pRollbackOp);
- }
-
- return SQLITE_OK;
-}
-
-/*
- * Delete table n from the supplied Rbtree.
- */
-static int memRbtreeDropTable(Rbtree* tree, int n)
-{
- BtRbTree *pTree;
- assert( tree->eTransState != TRANS_NONE );
-
- memRbtreeClearTable(tree, n);
- pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0);
- assert(pTree);
- assert( pTree->pCursors==0 );
- sqliteFree(pTree);
-
- if( tree->eTransState != TRANS_ROLLBACK ){
- BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
- if( pRollbackOp==0 ) return SQLITE_NOMEM;
- pRollbackOp->eOp = ROLLBACK_CREATE;
- pRollbackOp->iTab = n;
- btreeLogRollbackOp(tree, pRollbackOp);
- }
-
- return SQLITE_OK;
-}
-
-static int memRbtreeKeyCompare(RbtCursor* pCur, const void *pKey, int nKey,
- int nIgnore, int *pRes)
-{
- assert(pCur);
-
- if( !pCur->pNode ) {
- *pRes = -1;
- } else {
- if( (pCur->pNode->nKey - nIgnore) < 0 ){
- *pRes = -1;
- }else{
- *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore,
- pKey, nKey);
- }
- }
- return SQLITE_OK;
-}
-
-/*
- * Get a new cursor for table iTable of the supplied Rbtree. The wrFlag
- * parameter indicates that the cursor is open for writing.
- *
- * Note that RbtCursor.eSkip and RbtCursor.pNode both initialize to 0.
- */
-static int memRbtreeCursor(
- Rbtree* tree,
- int iTable,
- int wrFlag,
- RbtCursor **ppCur
-){
- RbtCursor *pCur;
- assert(tree);
- pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
- if( sqlite_malloc_failed ) return SQLITE_NOMEM;
- pCur->pTree = sqliteHashFind(&tree->tblHash, 0, iTable);
- assert( pCur->pTree );
- pCur->pRbtree = tree;
- pCur->iTree = iTable;
- pCur->pOps = &sqliteRbtreeCursorOps;
- pCur->wrFlag = wrFlag;
- pCur->pShared = pCur->pTree->pCursors;
- pCur->pTree->pCursors = pCur;
-
- assert( (*ppCur)->pTree );
- return SQLITE_OK;
-}
-
-/*
- * Insert a new record into the Rbtree. The key is given by (pKey,nKey)
- * and the data is given by (pData,nData). The cursor is used only to
- * define what database the record should be inserted into. The cursor
- * is left pointing at the new record.
- *
- * If the key exists already in the tree, just replace the data.
- */
-static int memRbtreeInsert(
- RbtCursor* pCur,
- const void *pKey,
- int nKey,
- const void *pDataInput,
- int nData
-){
- void * pData;
- int match;
-
- /* It is illegal to call sqliteRbtreeInsert() if we are
- ** not in a transaction */
- assert( pCur->pRbtree->eTransState != TRANS_NONE );
-
- /* Make sure some other cursor isn't trying to read this same table */
- if( checkReadLocks(pCur) ){
- return SQLITE_LOCKED; /* The table pCur points to has a read lock */
- }
-
- /* Take a copy of the input data now, in case we need it for the
- * replace case */
- pData = sqliteMallocRaw(nData);
- if( sqlite_malloc_failed ) return SQLITE_NOMEM;
- memcpy(pData, pDataInput, nData);
-
- /* Move the cursor to a node near the key to be inserted. If the key already
- * exists in the table, then (match == 0). In this case we can just replace
- * the data associated with the entry, we don't need to manipulate the tree.
- *
- * If there is no exact match, then the cursor points at what would be either
- * the predecessor (match == -1) or successor (match == 1) of the
- * searched-for key, were it to be inserted. The new node becomes a child of
- * this node.
- *
- * The new node is initially red.
- */
- memRbtreeMoveto( pCur, pKey, nKey, &match);
- if( match ){
- BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode));
- if( pNode==0 ) return SQLITE_NOMEM;
- pNode->nKey = nKey;
- pNode->pKey = sqliteMallocRaw(nKey);
- if( sqlite_malloc_failed ) return SQLITE_NOMEM;
- memcpy(pNode->pKey, pKey, nKey);
- pNode->nData = nData;
- pNode->pData = pData;
- if( pCur->pNode ){
- switch( match ){
- case -1:
- assert( !pCur->pNode->pRight );
- pNode->pParent = pCur->pNode;
- pCur->pNode->pRight = pNode;
- break;
- case 1:
- assert( !pCur->pNode->pLeft );
- pNode->pParent = pCur->pNode;
- pCur->pNode->pLeft = pNode;
- break;
- default:
- assert(0);
- }
- }else{
- pCur->pTree->pHead = pNode;
- }
-
- /* Point the cursor at the node just inserted, as per SQLite requirements */
- pCur->pNode = pNode;
-
- /* A new node has just been inserted, so run the balancing code */
- do_insert_balancing(pCur->pTree, pNode);
-
- /* Set up a rollback-op in case we have to roll this operation back */
- if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
- BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
- if( pOp==0 ) return SQLITE_NOMEM;
- pOp->eOp = ROLLBACK_DELETE;
- pOp->iTab = pCur->iTree;
- pOp->nKey = pNode->nKey;
- pOp->pKey = sqliteMallocRaw( pOp->nKey );
- if( sqlite_malloc_failed ) return SQLITE_NOMEM;
- memcpy( pOp->pKey, pNode->pKey, pOp->nKey );
- btreeLogRollbackOp(pCur->pRbtree, pOp);
- }
-
- }else{
- /* No need to insert a new node in the tree, as the key already exists.
- * Just clobber the current nodes data. */
-
- /* Set up a rollback-op in case we have to roll this operation back */
- if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
- BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
- if( pOp==0 ) return SQLITE_NOMEM;
- pOp->iTab = pCur->iTree;
- pOp->nKey = pCur->pNode->nKey;
- pOp->pKey = sqliteMallocRaw( pOp->nKey );
- if( sqlite_malloc_failed ) return SQLITE_NOMEM;
- memcpy( pOp->pKey, pCur->pNode->pKey, pOp->nKey );
- pOp->nData = pCur->pNode->nData;
- pOp->pData = pCur->pNode->pData;
- pOp->eOp = ROLLBACK_INSERT;
- btreeLogRollbackOp(pCur->pRbtree, pOp);
- }else{
- sqliteFree( pCur->pNode->pData );
- }
-
- /* Actually clobber the nodes data */
- pCur->pNode->pData = pData;
- pCur->pNode->nData = nData;
- }
-
- return SQLITE_OK;
-}
-
-/* Move the cursor so that it points to an entry near pKey.
-** Return a success code.
-**
-** *pRes<0 The cursor is left pointing at an entry that
-** is smaller than pKey or if the table is empty
-** and the cursor is therefore left point to nothing.
-**
-** *pRes==0 The cursor is left pointing at an entry that
-** exactly matches pKey.
-**
-** *pRes>0 The cursor is left pointing at an entry that
-** is larger than pKey.
-*/
-static int memRbtreeMoveto(
- RbtCursor* pCur,
- const void *pKey,
- int nKey,
- int *pRes
-){
- BtRbNode *pTmp = 0;
-
- pCur->pNode = pCur->pTree->pHead;
- *pRes = -1;
- while( pCur->pNode && *pRes ) {
- *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey);
- pTmp = pCur->pNode;
- switch( *pRes ){
- case 1: /* cursor > key */
- pCur->pNode = pCur->pNode->pLeft;
- break;
- case -1: /* cursor < key */
- pCur->pNode = pCur->pNode->pRight;
- break;
- }
- }
-
- /* If (pCur->pNode == NULL), then we have failed to find a match. Set
- * pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the
- * last node traversed in the search. In either case the relation ship
- * between pTmp and the searched for key is already stored in *pRes. pTmp is
- * either the successor or predecessor of the key we tried to move to. */
- if( !pCur->pNode ) pCur->pNode = pTmp;
- pCur->eSkip = SKIP_NONE;
-
- return SQLITE_OK;
-}
-
-
-/*
-** Delete the entry that the cursor is pointing to.
-**
-** The cursor is left pointing at either the next or the previous
-** entry. If the cursor is left pointing to the next entry, then
-** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to
-** sqliteRbtreeNext() to be a no-op. That way, you can always call
-** sqliteRbtreeNext() after a delete and the cursor will be left
-** pointing to the first entry after the deleted entry. Similarly,
-** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
-** the entry prior to the deleted entry so that a subsequent call to
-** sqliteRbtreePrevious() will always leave the cursor pointing at the
-** entry immediately before the one that was deleted.
-*/
-static int memRbtreeDelete(RbtCursor* pCur)
-{
- BtRbNode *pZ; /* The one being deleted */
- BtRbNode *pChild; /* The child of the spliced out node */
-
- /* It is illegal to call sqliteRbtreeDelete() if we are
- ** not in a transaction */
- assert( pCur->pRbtree->eTransState != TRANS_NONE );
-
- /* Make sure some other cursor isn't trying to read this same table */
- if( checkReadLocks(pCur) ){
- return SQLITE_LOCKED; /* The table pCur points to has a read lock */
- }
-
- pZ = pCur->pNode;
- if( !pZ ){
- return SQLITE_OK;
- }
-
- /* If we are not currently doing a rollback, set up a rollback op for this
- * deletion */
- if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
- BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
- if( pOp==0 ) return SQLITE_NOMEM;
- pOp->iTab = pCur->iTree;
- pOp->nKey = pZ->nKey;
- pOp->pKey = pZ->pKey;
- pOp->nData = pZ->nData;
- pOp->pData = pZ->pData;
- pOp->eOp = ROLLBACK_INSERT;
- btreeLogRollbackOp(pCur->pRbtree, pOp);
- }
-
- /* First do a standard binary-tree delete (node pZ is to be deleted). How
- * to do this depends on how many children pZ has:
- *
- * If pZ has no children or one child, then splice out pZ. If pZ has two
- * children, splice out the successor of pZ and replace the key and data of
- * pZ with the key and data of the spliced out successor. */
- if( pZ->pLeft && pZ->pRight ){
- BtRbNode *pTmp;
- int dummy;
- pCur->eSkip = SKIP_NONE;
- memRbtreeNext(pCur, &dummy);
- assert( dummy == 0 );
- if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
- sqliteFree(pZ->pKey);
- sqliteFree(pZ->pData);
- }
- pZ->pData = pCur->pNode->pData;
- pZ->nData = pCur->pNode->nData;
- pZ->pKey = pCur->pNode->pKey;
- pZ->nKey = pCur->pNode->nKey;
- pTmp = pZ;
- pZ = pCur->pNode;
- pCur->pNode = pTmp;
- pCur->eSkip = SKIP_NEXT;
- }else{
- int res;
- pCur->eSkip = SKIP_NONE;
- memRbtreeNext(pCur, &res);
- pCur->eSkip = SKIP_NEXT;
- if( res ){
- memRbtreeLast(pCur, &res);
- memRbtreePrevious(pCur, &res);
- pCur->eSkip = SKIP_PREV;
- }
- if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
- sqliteFree(pZ->pKey);
- sqliteFree(pZ->pData);
- }
- }
-
- /* pZ now points at the node to be spliced out. This block does the
- * splicing. */
- {
- BtRbNode **ppParentSlot = 0;
- assert( !pZ->pLeft || !pZ->pRight ); /* pZ has at most one child */
- pChild = ((pZ->pLeft)?pZ->pLeft:pZ->pRight);
- if( pZ->pParent ){
- assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight );
- ppParentSlot = ((pZ == pZ->pParent->pLeft)
- ?&pZ->pParent->pLeft:&pZ->pParent->pRight);
- *ppParentSlot = pChild;
- }else{
- pCur->pTree->pHead = pChild;
- }
- if( pChild ) pChild->pParent = pZ->pParent;
- }
-
- /* pZ now points at the spliced out node. pChild is the only child of pZ, or
- * NULL if pZ has no children. If pZ is black, and not the tree root, then we
- * will have violated the "same number of black nodes in every path to a
- * leaf" property of the red-black tree. The code in do_delete_balancing()
- * repairs this. */
- if( pZ->isBlack ){
- do_delete_balancing(pCur->pTree, pChild, pZ->pParent);
- }
-
- sqliteFree(pZ);
- return SQLITE_OK;
-}
-
-/*
- * Empty table n of the Rbtree.
- */
-static int memRbtreeClearTable(Rbtree* tree, int n)
-{
- BtRbTree *pTree;
- BtRbNode *pNode;
-
- pTree = sqliteHashFind(&tree->tblHash, 0, n);
- assert(pTree);
-
- pNode = pTree->pHead;
- while( pNode ){
- if( pNode->pLeft ){
- pNode = pNode->pLeft;
- }
- else if( pNode->pRight ){
- pNode = pNode->pRight;
- }
- else {
- BtRbNode *pTmp = pNode->pParent;
- if( tree->eTransState == TRANS_ROLLBACK ){
- sqliteFree( pNode->pKey );
- sqliteFree( pNode->pData );
- }else{
- BtRollbackOp *pRollbackOp = sqliteMallocRaw(sizeof(BtRollbackOp));
- if( pRollbackOp==0 ) return SQLITE_NOMEM;
- pRollbackOp->eOp = ROLLBACK_INSERT;
- pRollbackOp->iTab = n;
- pRollbackOp->nKey = pNode->nKey;
- pRollbackOp->pKey = pNode->pKey;
- pRollbackOp->nData = pNode->nData;
- pRollbackOp->pData = pNode->pData;
- btreeLogRollbackOp(tree, pRollbackOp);
- }
- sqliteFree( pNode );
- if( pTmp ){
- if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
- else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
- }
- pNode = pTmp;
- }
- }
-
- pTree->pHead = 0;
- return SQLITE_OK;
-}
-
-static int memRbtreeFirst(RbtCursor* pCur, int *pRes)
-{
- if( pCur->pTree->pHead ){
- pCur->pNode = pCur->pTree->pHead;
- while( pCur->pNode->pLeft ){
- pCur->pNode = pCur->pNode->pLeft;
- }
- }
- if( pCur->pNode ){
- *pRes = 0;
- }else{
- *pRes = 1;
- }
- pCur->eSkip = SKIP_NONE;
- return SQLITE_OK;
-}
-
-static int memRbtreeLast(RbtCursor* pCur, int *pRes)
-{
- if( pCur->pTree->pHead ){
- pCur->pNode = pCur->pTree->pHead;
- while( pCur->pNode->pRight ){
- pCur->pNode = pCur->pNode->pRight;
- }
- }
- if( pCur->pNode ){
- *pRes = 0;
- }else{
- *pRes = 1;
- }
- pCur->eSkip = SKIP_NONE;
- return SQLITE_OK;
-}
-
-/*
-** Advance the cursor to the next entry in the database. If
-** successful then set *pRes=0. If the cursor
-** was already pointing to the last entry in the database before
-** this routine was called, then set *pRes=1.
-*/
-static int memRbtreeNext(RbtCursor* pCur, int *pRes)
-{
- if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){
- if( pCur->pNode->pRight ){
- pCur->pNode = pCur->pNode->pRight;
- while( pCur->pNode->pLeft )
- pCur->pNode = pCur->pNode->pLeft;
- }else{
- BtRbNode * pX = pCur->pNode;
- pCur->pNode = pX->pParent;
- while( pCur->pNode && (pCur->pNode->pRight == pX) ){
- pX = pCur->pNode;
- pCur->pNode = pX->pParent;
- }
- }
- }
- pCur->eSkip = SKIP_NONE;
-
- if( !pCur->pNode ){
- *pRes = 1;
- }else{
- *pRes = 0;
- }
-
- return SQLITE_OK;
-}
-
-static int memRbtreePrevious(RbtCursor* pCur, int *pRes)
-{
- if( pCur->pNode && pCur->eSkip != SKIP_PREV ){
- if( pCur->pNode->pLeft ){
- pCur->pNode = pCur->pNode->pLeft;
- while( pCur->pNode->pRight )
- pCur->pNode = pCur->pNode->pRight;
- }else{
- BtRbNode * pX = pCur->pNode;
- pCur->pNode = pX->pParent;
- while( pCur->pNode && (pCur->pNode->pLeft == pX) ){
- pX = pCur->pNode;
- pCur->pNode = pX->pParent;
- }
- }
- }
- pCur->eSkip = SKIP_NONE;
-
- if( !pCur->pNode ){
- *pRes = 1;
- }else{
- *pRes = 0;
- }
-
- return SQLITE_OK;
-}
-
-static int memRbtreeKeySize(RbtCursor* pCur, int *pSize)
-{
- if( pCur->pNode ){
- *pSize = pCur->pNode->nKey;
- }else{
- *pSize = 0;
- }
- return SQLITE_OK;
-}
-
-static int memRbtreeKey(RbtCursor* pCur, int offset, int amt, char *zBuf)
-{
- if( !pCur->pNode ) return 0;
- if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
- memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
- }else{
- memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
- amt = pCur->pNode->nKey-offset;
- }
- return amt;
-}
-
-static int memRbtreeDataSize(RbtCursor* pCur, int *pSize)
-{
- if( pCur->pNode ){
- *pSize = pCur->pNode->nData;
- }else{
- *pSize = 0;
- }
- return SQLITE_OK;
-}
-
-static int memRbtreeData(RbtCursor *pCur, int offset, int amt, char *zBuf)
-{
- if( !pCur->pNode ) return 0;
- if( (amt + offset) <= pCur->pNode->nData ){
- memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
- }else{
- memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
- amt = pCur->pNode->nData-offset;
- }
- return amt;
-}
-
-static int memRbtreeCloseCursor(RbtCursor* pCur)
-{
- if( pCur->pTree->pCursors==pCur ){
- pCur->pTree->pCursors = pCur->pShared;
- }else{
- RbtCursor *p = pCur->pTree->pCursors;
- while( p && p->pShared!=pCur ){ p = p->pShared; }
- assert( p!=0 );
- if( p ){
- p->pShared = pCur->pShared;
- }
- }
- sqliteFree(pCur);
- return SQLITE_OK;
-}
-
-static int memRbtreeGetMeta(Rbtree* tree, int* aMeta)
-{
- memcpy( aMeta, tree->aMetaData, sizeof(int) * SQLITE_N_BTREE_META );
- return SQLITE_OK;
-}
-
-static int memRbtreeUpdateMeta(Rbtree* tree, int* aMeta)
-{
- memcpy( tree->aMetaData, aMeta, sizeof(int) * SQLITE_N_BTREE_META );
- return SQLITE_OK;
-}
-
-/*
- * Check that each table in the Rbtree meets the requirements for a red-black
- * binary tree. If an error is found, return an explanation of the problem in
- * memory obtained from sqliteMalloc(). Parameters aRoot and nRoot are ignored.
- */
-static char *memRbtreeIntegrityCheck(Rbtree* tree, int* aRoot, int nRoot)
-{
- char * msg = 0;
- HashElem *p;
-
- for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){
- BtRbTree *pTree = sqliteHashData(p);
- check_redblack_tree(pTree, &msg);
- }
-
- return msg;
-}
-
-static int memRbtreeSetCacheSize(Rbtree* tree, int sz)
-{
- return SQLITE_OK;
-}
-
-static int memRbtreeSetSafetyLevel(Rbtree *pBt, int level){
- return SQLITE_OK;
-}
-
-static int memRbtreeBeginTrans(Rbtree* tree)
-{
- if( tree->eTransState != TRANS_NONE )
- return SQLITE_ERROR;
-
- assert( tree->pTransRollback == 0 );
- tree->eTransState = TRANS_INTRANSACTION;
- return SQLITE_OK;
-}
-
-/*
-** Delete a linked list of BtRollbackOp structures.
-*/
-static void deleteRollbackList(BtRollbackOp *pOp){
- while( pOp ){
- BtRollbackOp *pTmp = pOp->pNext;
- sqliteFree(pOp->pData);
- sqliteFree(pOp->pKey);
- sqliteFree(pOp);
- pOp = pTmp;
- }
-}
-
-static int memRbtreeCommit(Rbtree* tree){
- /* Just delete pTransRollback and pCheckRollback */
- deleteRollbackList(tree->pCheckRollback);
- deleteRollbackList(tree->pTransRollback);
- tree->pTransRollback = 0;
- tree->pCheckRollback = 0;
- tree->pCheckRollbackTail = 0;
- tree->eTransState = TRANS_NONE;
- return SQLITE_OK;
-}
-
-/*
- * Close the supplied Rbtree. Delete everything associated with it.
- */
-static int memRbtreeClose(Rbtree* tree)
-{
- HashElem *p;
- memRbtreeCommit(tree);
- while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){
- tree->eTransState = TRANS_ROLLBACK;
- memRbtreeDropTable(tree, sqliteHashKeysize(p));
- }
- sqliteHashClear(&tree->tblHash);
- sqliteFree(tree);
- return SQLITE_OK;
-}
-
-/*
- * Execute and delete the supplied rollback-list on pRbtree.
- */
-static void execute_rollback_list(Rbtree *pRbtree, BtRollbackOp *pList)
-{
- BtRollbackOp *pTmp;
- RbtCursor cur;
- int res;
-
- cur.pRbtree = pRbtree;
- cur.wrFlag = 1;
- while( pList ){
- switch( pList->eOp ){
- case ROLLBACK_INSERT:
- cur.pTree = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
- assert(cur.pTree);
- cur.iTree = pList->iTab;
- cur.eSkip = SKIP_NONE;
- memRbtreeInsert( &cur, pList->pKey,
- pList->nKey, pList->pData, pList->nData );
- break;
- case ROLLBACK_DELETE:
- cur.pTree = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
- assert(cur.pTree);
- cur.iTree = pList->iTab;
- cur.eSkip = SKIP_NONE;
- memRbtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
- assert(res == 0);
- memRbtreeDelete( &cur );
- break;
- case ROLLBACK_CREATE:
- btreeCreateTable(pRbtree, pList->iTab);
- break;
- case ROLLBACK_DROP:
- memRbtreeDropTable(pRbtree, pList->iTab);
- break;
- default:
- assert(0);
- }
- sqliteFree(pList->pKey);
- sqliteFree(pList->pData);
- pTmp = pList->pNext;
- sqliteFree(pList);
- pList = pTmp;
- }
-}
-
-static int memRbtreeRollback(Rbtree* tree)
-{
- tree->eTransState = TRANS_ROLLBACK;
- execute_rollback_list(tree, tree->pCheckRollback);
- execute_rollback_list(tree, tree->pTransRollback);
- tree->pTransRollback = 0;
- tree->pCheckRollback = 0;
- tree->pCheckRollbackTail = 0;
- tree->eTransState = TRANS_NONE;
- return SQLITE_OK;
-}
-
-static int memRbtreeBeginCkpt(Rbtree* tree)
-{
- if( tree->eTransState != TRANS_INTRANSACTION )
- return SQLITE_ERROR;
-
- assert( tree->pCheckRollback == 0 );
- assert( tree->pCheckRollbackTail == 0 );
- tree->eTransState = TRANS_INCHECKPOINT;
- return SQLITE_OK;
-}
-
-static int memRbtreeCommitCkpt(Rbtree* tree)
-{
- if( tree->eTransState == TRANS_INCHECKPOINT ){
- if( tree->pCheckRollback ){
- tree->pCheckRollbackTail->pNext = tree->pTransRollback;
- tree->pTransRollback = tree->pCheckRollback;
- tree->pCheckRollback = 0;
- tree->pCheckRollbackTail = 0;
- }
- tree->eTransState = TRANS_INTRANSACTION;
- }
- return SQLITE_OK;
-}
-
-static int memRbtreeRollbackCkpt(Rbtree* tree)
-{
- if( tree->eTransState != TRANS_INCHECKPOINT ) return SQLITE_OK;
- tree->eTransState = TRANS_ROLLBACK;
- execute_rollback_list(tree, tree->pCheckRollback);
- tree->pCheckRollback = 0;
- tree->pCheckRollbackTail = 0;
- tree->eTransState = TRANS_INTRANSACTION;
- return SQLITE_OK;
-}
-
-#ifdef SQLITE_TEST
-static int memRbtreePageDump(Rbtree* tree, int pgno, int rec)
-{
- assert(!"Cannot call sqliteRbtreePageDump");
- return SQLITE_OK;
-}
-
-static int memRbtreeCursorDump(RbtCursor* pCur, int* aRes)
-{
- assert(!"Cannot call sqliteRbtreeCursorDump");
- return SQLITE_OK;
-}
-#endif
-
-static struct Pager *memRbtreePager(Rbtree* tree)
-{
- return 0;
-}
-
-/*
-** Return the full pathname of the underlying database file.
-*/
-static const char *memRbtreeGetFilename(Rbtree *pBt){
- return 0; /* A NULL return indicates there is no underlying file */
-}
-
-/*
-** The copy file function is not implemented for the in-memory database
-*/
-static int memRbtreeCopyFile(Rbtree *pBt, Rbtree *pBt2){
- return SQLITE_INTERNAL; /* Not implemented */
-}
-
-static BtOps sqliteRbtreeOps = {
- (int(*)(Btree*)) memRbtreeClose,
- (int(*)(Btree*,int)) memRbtreeSetCacheSize,
- (int(*)(Btree*,int)) memRbtreeSetSafetyLevel,
- (int(*)(Btree*)) memRbtreeBeginTrans,
- (int(*)(Btree*)) memRbtreeCommit,
- (int(*)(Btree*)) memRbtreeRollback,
- (int(*)(Btree*)) memRbtreeBeginCkpt,
- (int(*)(Btree*)) memRbtreeCommitCkpt,
- (int(*)(Btree*)) memRbtreeRollbackCkpt,
- (int(*)(Btree*,int*)) memRbtreeCreateTable,
- (int(*)(Btree*,int*)) memRbtreeCreateTable,
- (int(*)(Btree*,int)) memRbtreeDropTable,
- (int(*)(Btree*,int)) memRbtreeClearTable,
- (int(*)(Btree*,int,int,BtCursor**)) memRbtreeCursor,
- (int(*)(Btree*,int*)) memRbtreeGetMeta,
- (int(*)(Btree*,int*)) memRbtreeUpdateMeta,
- (char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
- (const char*(*)(Btree*)) memRbtreeGetFilename,
- (int(*)(Btree*,Btree*)) memRbtreeCopyFile,
- (struct Pager*(*)(Btree*)) memRbtreePager,
-#ifdef SQLITE_TEST
- (int(*)(Btree*,int,int)) memRbtreePageDump,
-#endif
-};
-
-static BtCursorOps sqliteRbtreeCursorOps = {
- (int(*)(BtCursor*,const void*,int,int*)) memRbtreeMoveto,
- (int(*)(BtCursor*)) memRbtreeDelete,
- (int(*)(BtCursor*,const void*,int,const void*,int)) memRbtreeInsert,
- (int(*)(BtCursor*,int*)) memRbtreeFirst,
- (int(*)(BtCursor*,int*)) memRbtreeLast,
- (int(*)(BtCursor*,int*)) memRbtreeNext,
- (int(*)(BtCursor*,int*)) memRbtreePrevious,
- (int(*)(BtCursor*,int*)) memRbtreeKeySize,
- (int(*)(BtCursor*,int,int,char*)) memRbtreeKey,
- (int(*)(BtCursor*,const void*,int,int,int*)) memRbtreeKeyCompare,
- (int(*)(BtCursor*,int*)) memRbtreeDataSize,
- (int(*)(BtCursor*,int,int,char*)) memRbtreeData,
- (int(*)(BtCursor*)) memRbtreeCloseCursor,
-#ifdef SQLITE_TEST
- (int(*)(BtCursor*,int*)) memRbtreeCursorDump,
-#endif
-
-};
-
-#endif /* SQLITE_OMIT_INMEMORYDB */
diff --git a/ext/sqlite/libsqlite/src/build.c b/ext/sqlite/libsqlite/src/build.c
deleted file mode 100644
index a089bfe625..0000000000
--- a/ext/sqlite/libsqlite/src/build.c
+++ /dev/null
@@ -1,2156 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains C code routines that are called by the SQLite parser
-** when syntax rules are reduced. The routines in this file handle the
-** following kinds of SQL syntax:
-**
-** CREATE TABLE
-** DROP TABLE
-** CREATE INDEX
-** DROP INDEX
-** creating ID lists
-** BEGIN TRANSACTION
-** COMMIT
-** ROLLBACK
-** PRAGMA
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include <ctype.h>
-
-/*
-** This routine is called when a new SQL statement is beginning to
-** be parsed. Check to see if the schema for the database needs
-** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
-** If it does, then read it.
-*/
-void sqliteBeginParse(Parse *pParse, int explainFlag){
- sqlite *db = pParse->db;
- int i;
- pParse->explain = explainFlag;
- if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
- int rc = sqliteInit(db, &pParse->zErrMsg);
- if( rc!=SQLITE_OK ){
- pParse->rc = rc;
- pParse->nErr++;
- }
- }
- for(i=0; i<db->nDb; i++){
- DbClearProperty(db, i, DB_Locked);
- if( !db->aDb[i].inTrans ){
- DbClearProperty(db, i, DB_Cookie);
- }
- }
- pParse->nVar = 0;
-}
-
-/*
-** This routine is called after a single SQL statement has been
-** parsed and we want to execute the VDBE code to implement
-** that statement. Prior action routines should have already
-** constructed VDBE code to do the work of the SQL statement.
-** This routine just has to execute the VDBE code.
-**
-** Note that if an error occurred, it might be the case that
-** no VDBE code was generated.
-*/
-void sqliteExec(Parse *pParse){
- sqlite *db = pParse->db;
- Vdbe *v = pParse->pVdbe;
-
- if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){
- sqliteVdbeAddOp(v, OP_Halt, 0, 0);
- }
- if( sqlite_malloc_failed ) return;
- if( v && pParse->nErr==0 ){
- FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
- sqliteVdbeTrace(v, trace);
- sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain);
- pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
- pParse->colNamesSet = 0;
- }else if( pParse->rc==SQLITE_OK ){
- pParse->rc = SQLITE_ERROR;
- }
- pParse->nTab = 0;
- pParse->nMem = 0;
- pParse->nSet = 0;
- pParse->nAgg = 0;
- pParse->nVar = 0;
-}
-
-/*
-** Locate the in-memory structure that describes
-** a particular database table given the name
-** of that table and (optionally) the name of the database
-** containing the table. Return NULL if not found.
-**
-** If zDatabase is 0, all databases are searched for the
-** table and the first matching table is returned. (No checking
-** for duplicate table names is done.) The search order is
-** TEMP first, then MAIN, then any auxiliary databases added
-** using the ATTACH command.
-**
-** See also sqliteLocateTable().
-*/
-Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
- Table *p = 0;
- int i;
- for(i=0; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue;
- p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
- if( p ) break;
- }
- return p;
-}
-
-/*
-** Locate the in-memory structure that describes
-** a particular database table given the name
-** of that table and (optionally) the name of the database
-** containing the table. Return NULL if not found.
-** Also leave an error message in pParse->zErrMsg.
-**
-** The difference between this routine and sqliteFindTable()
-** is that this routine leaves an error message in pParse->zErrMsg
-** where sqliteFindTable() does not.
-*/
-Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){
- Table *p;
-
- p = sqliteFindTable(pParse->db, zName, zDbase);
- if( p==0 ){
- if( zDbase ){
- sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
- }else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){
- sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
- zName, zDbase);
- }else{
- sqliteErrorMsg(pParse, "no such table: %s", zName);
- }
- }
- return p;
-}
-
-/*
-** Locate the in-memory structure that describes
-** a particular index given the name of that index
-** and the name of the database that contains the index.
-** Return NULL if not found.
-**
-** If zDatabase is 0, all databases are searched for the
-** table and the first matching index is returned. (No checking
-** for duplicate index names is done.) The search order is
-** TEMP first, then MAIN, then any auxiliary databases added
-** using the ATTACH command.
-*/
-Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
- Index *p = 0;
- int i;
- for(i=0; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue;
- p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
- if( p ) break;
- }
- return p;
-}
-
-/*
-** Remove the given index from the index hash table, and free
-** its memory structures.
-**
-** The index is removed from the database hash tables but
-** it is not unlinked from the Table that it indexes.
-** Unlinking from the Table must be done by the calling function.
-*/
-static void sqliteDeleteIndex(sqlite *db, Index *p){
- Index *pOld;
-
- assert( db!=0 && p->zName!=0 );
- pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName,
- strlen(p->zName)+1, 0);
- if( pOld!=0 && pOld!=p ){
- sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
- strlen(pOld->zName)+1, pOld);
- }
- sqliteFree(p);
-}
-
-/*
-** Unlink the given index from its table, then remove
-** the index from the index hash table and free its memory
-** structures.
-*/
-void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){
- if( pIndex->pTable->pIndex==pIndex ){
- pIndex->pTable->pIndex = pIndex->pNext;
- }else{
- Index *p;
- for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
- if( p && p->pNext==pIndex ){
- p->pNext = pIndex->pNext;
- }
- }
- sqliteDeleteIndex(db, pIndex);
-}
-
-/*
-** Erase all schema information from the in-memory hash tables of
-** database connection. This routine is called to reclaim memory
-** before the connection closes. It is also called during a rollback
-** if there were schema changes during the transaction.
-**
-** If iDb<=0 then reset the internal schema tables for all database
-** files. If iDb>=2 then reset the internal schema for only the
-** single file indicated.
-*/
-void sqliteResetInternalSchema(sqlite *db, int iDb){
- HashElem *pElem;
- Hash temp1;
- Hash temp2;
- int i, j;
-
- assert( iDb>=0 && iDb<db->nDb );
- db->flags &= ~SQLITE_Initialized;
- for(i=iDb; i<db->nDb; i++){
- Db *pDb = &db->aDb[i];
- temp1 = pDb->tblHash;
- temp2 = pDb->trigHash;
- sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
- sqliteHashClear(&pDb->aFKey);
- sqliteHashClear(&pDb->idxHash);
- for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
- Trigger *pTrigger = sqliteHashData(pElem);
- sqliteDeleteTrigger(pTrigger);
- }
- sqliteHashClear(&temp2);
- sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
- for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
- Table *pTab = sqliteHashData(pElem);
- sqliteDeleteTable(db, pTab);
- }
- sqliteHashClear(&temp1);
- DbClearProperty(db, i, DB_SchemaLoaded);
- if( iDb>0 ) return;
- }
- assert( iDb==0 );
- db->flags &= ~SQLITE_InternChanges;
-
- /* If one or more of the auxiliary database files has been closed,
- ** then remove then from the auxiliary database list. We take the
- ** opportunity to do this here since we have just deleted all of the
- ** schema hash tables and therefore do not have to make any changes
- ** to any of those tables.
- */
- for(i=0; i<db->nDb; i++){
- struct Db *pDb = &db->aDb[i];
- if( pDb->pBt==0 ){
- if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
- pDb->pAux = 0;
- }
- }
- for(i=j=2; i<db->nDb; i++){
- struct Db *pDb = &db->aDb[i];
- if( pDb->pBt==0 ){
- sqliteFree(pDb->zName);
- pDb->zName = 0;
- continue;
- }
- if( j<i ){
- db->aDb[j] = db->aDb[i];
- }
- j++;
- }
- memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
- db->nDb = j;
- if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
- memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
- sqliteFree(db->aDb);
- db->aDb = db->aDbStatic;
- }
-}
-
-/*
-** This routine is called whenever a rollback occurs. If there were
-** schema changes during the transaction, then we have to reset the
-** internal hash tables and reload them from disk.
-*/
-void sqliteRollbackInternalChanges(sqlite *db){
- if( db->flags & SQLITE_InternChanges ){
- sqliteResetInternalSchema(db, 0);
- }
-}
-
-/*
-** This routine is called when a commit occurs.
-*/
-void sqliteCommitInternalChanges(sqlite *db){
- db->aDb[0].schema_cookie = db->next_cookie;
- db->flags &= ~SQLITE_InternChanges;
-}
-
-/*
-** Remove the memory data structures associated with the given
-** Table. No changes are made to disk by this routine.
-**
-** This routine just deletes the data structure. It does not unlink
-** the table data structure from the hash table. Nor does it remove
-** foreign keys from the sqlite.aFKey hash table. But it does destroy
-** memory structures of the indices and foreign keys associated with
-** the table.
-**
-** Indices associated with the table are unlinked from the "db"
-** data structure if db!=NULL. If db==NULL, indices attached to
-** the table are deleted, but it is assumed they have already been
-** unlinked.
-*/
-void sqliteDeleteTable(sqlite *db, Table *pTable){
- int i;
- Index *pIndex, *pNext;
- FKey *pFKey, *pNextFKey;
-
- if( pTable==0 ) return;
-
- /* Delete all indices associated with this table
- */
- for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
- pNext = pIndex->pNext;
- assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );
- sqliteDeleteIndex(db, pIndex);
- }
-
- /* Delete all foreign keys associated with this table. The keys
- ** should have already been unlinked from the db->aFKey hash table
- */
- for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
- pNextFKey = pFKey->pNextFrom;
- assert( pTable->iDb<db->nDb );
- assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey,
- pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
- sqliteFree(pFKey);
- }
-
- /* Delete the Table structure itself.
- */
- for(i=0; i<pTable->nCol; i++){
- sqliteFree(pTable->aCol[i].zName);
- sqliteFree(pTable->aCol[i].zDflt);
- sqliteFree(pTable->aCol[i].zType);
- }
- sqliteFree(pTable->zName);
- sqliteFree(pTable->aCol);
- sqliteSelectDelete(pTable->pSelect);
- sqliteFree(pTable);
-}
-
-/*
-** Unlink the given table from the hash tables and the delete the
-** table structure with all its indices and foreign keys.
-*/
-static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
- Table *pOld;
- FKey *pF1, *pF2;
- int i = p->iDb;
- assert( db!=0 );
- pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);
- assert( pOld==0 || pOld==p );
- for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
- int nTo = strlen(pF1->zTo) + 1;
- pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
- if( pF2==pF1 ){
- sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
- }else{
- while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
- if( pF2 ){
- pF2->pNextTo = pF1->pNextTo;
- }
- }
- }
- sqliteDeleteTable(db, p);
-}
-
-/*
-** Construct the name of a user table or index from a token.
-**
-** Space to hold the name is obtained from sqliteMalloc() and must
-** be freed by the calling function.
-*/
-char *sqliteTableNameFromToken(Token *pName){
- char *zName = sqliteStrNDup(pName->z, pName->n);
- sqliteDequote(zName);
- return zName;
-}
-
-/*
-** Generate code to open the appropriate master table. The table
-** opened will be SQLITE_MASTER for persistent tables and
-** SQLITE_TEMP_MASTER for temporary tables. The table is opened
-** on cursor 0.
-*/
-void sqliteOpenMasterTable(Vdbe *v, int isTemp){
- sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
- sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
-}
-
-/*
-** Begin constructing a new table representation in memory. This is
-** the first of several action routines that get called in response
-** to a CREATE TABLE statement. In particular, this routine is called
-** after seeing tokens "CREATE" and "TABLE" and the table name. The
-** pStart token is the CREATE and pName is the table name. The isTemp
-** flag is true if the table should be stored in the auxiliary database
-** file instead of in the main database file. This is normally the case
-** when the "TEMP" or "TEMPORARY" keyword occurs in between
-** CREATE and TABLE.
-**
-** The new table record is initialized and put in pParse->pNewTable.
-** As more of the CREATE TABLE statement is parsed, additional action
-** routines will be called to add more information to this record.
-** At the end of the CREATE TABLE statement, the sqliteEndTable() routine
-** is called to complete the construction of the new table record.
-*/
-void sqliteStartTable(
- Parse *pParse, /* Parser context */
- Token *pStart, /* The "CREATE" token */
- Token *pName, /* Name of table or view to create */
- int isTemp, /* True if this is a TEMP table */
- int isView /* True if this is a VIEW */
-){
- Table *pTable;
- Index *pIdx;
- char *zName;
- sqlite *db = pParse->db;
- Vdbe *v;
- int iDb;
-
- pParse->sFirstToken = *pStart;
- zName = sqliteTableNameFromToken(pName);
- if( zName==0 ) return;
- if( db->init.iDb==1 ) isTemp = 1;
-#ifndef SQLITE_OMIT_AUTHORIZATION
- assert( (isTemp & 1)==isTemp );
- {
- int code;
- char *zDb = isTemp ? "temp" : "main";
- if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
- sqliteFree(zName);
- return;
- }
- if( isView ){
- if( isTemp ){
- code = SQLITE_CREATE_TEMP_VIEW;
- }else{
- code = SQLITE_CREATE_VIEW;
- }
- }else{
- if( isTemp ){
- code = SQLITE_CREATE_TEMP_TABLE;
- }else{
- code = SQLITE_CREATE_TABLE;
- }
- }
- if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){
- sqliteFree(zName);
- return;
- }
- }
-#endif
-
-
- /* Before trying to create a temporary table, make sure the Btree for
- ** holding temporary tables is open.
- */
- if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){
- int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt);
- if( rc!=SQLITE_OK ){
- sqliteErrorMsg(pParse, "unable to open a temporary database "
- "file for storing temporary tables");
- pParse->nErr++;
- return;
- }
- if( db->flags & SQLITE_InTrans ){
- rc = sqliteBtreeBeginTrans(db->aDb[1].pBt);
- if( rc!=SQLITE_OK ){
- sqliteErrorMsg(pParse, "unable to get a write lock on "
- "the temporary database file");
- return;
- }
- }
- }
-
- /* Make sure the new table name does not collide with an existing
- ** index or table name. Issue an error message if it does.
- **
- ** If we are re-reading the sqlite_master table because of a schema
- ** change and a new permanent table is found whose name collides with
- ** an existing temporary table, that is not an error.
- */
- pTable = sqliteFindTable(db, zName, 0);
- iDb = isTemp ? 1 : db->init.iDb;
- if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
- sqliteErrorMsg(pParse, "table %T already exists", pName);
- sqliteFree(zName);
- return;
- }
- if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
- (pIdx->iDb==0 || !db->init.busy) ){
- sqliteErrorMsg(pParse, "there is already an index named %s", zName);
- sqliteFree(zName);
- return;
- }
- pTable = sqliteMalloc( sizeof(Table) );
- if( pTable==0 ){
- sqliteFree(zName);
- return;
- }
- pTable->zName = zName;
- pTable->nCol = 0;
- pTable->aCol = 0;
- pTable->iPKey = -1;
- pTable->pIndex = 0;
- pTable->iDb = iDb;
- if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
- pParse->pNewTable = pTable;
-
- /* Begin generating the code that will insert the table record into
- ** the SQLITE_MASTER table. Note in particular that we must go ahead
- ** and allocate the record number for the table entry now. Before any
- ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
- ** indices to be created and the table record must come before the
- ** indices. Hence, the record number for the table must be allocated
- ** now.
- */
- if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
- sqliteBeginWriteOperation(pParse, 0, isTemp);
- if( !isTemp ){
- sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
- sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
- }
- sqliteOpenMasterTable(v, isTemp);
- sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
- }
-}
-
-/*
-** Add a new column to the table currently being constructed.
-**
-** The parser calls this routine once for each column declaration
-** in a CREATE TABLE statement. sqliteStartTable() gets called
-** first to get things going. Then this routine is called for each
-** column.
-*/
-void sqliteAddColumn(Parse *pParse, Token *pName){
- Table *p;
- int i;
- char *z = 0;
- Column *pCol;
- if( (p = pParse->pNewTable)==0 ) return;
- sqliteSetNString(&z, pName->z, pName->n, 0);
- if( z==0 ) return;
- sqliteDequote(z);
- for(i=0; i<p->nCol; i++){
- if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){
- sqliteErrorMsg(pParse, "duplicate column name: %s", z);
- sqliteFree(z);
- return;
- }
- }
- if( (p->nCol & 0x7)==0 ){
- Column *aNew;
- aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
- if( aNew==0 ) return;
- p->aCol = aNew;
- }
- pCol = &p->aCol[p->nCol];
- memset(pCol, 0, sizeof(p->aCol[0]));
- pCol->zName = z;
- pCol->sortOrder = SQLITE_SO_NUM;
- p->nCol++;
-}
-
-/*
-** This routine is called by the parser while in the middle of
-** parsing a CREATE TABLE statement. A "NOT NULL" constraint has
-** been seen on a column. This routine sets the notNull flag on
-** the column currently under construction.
-*/
-void sqliteAddNotNull(Parse *pParse, int onError){
- Table *p;
- int i;
- if( (p = pParse->pNewTable)==0 ) return;
- i = p->nCol-1;
- if( i>=0 ) p->aCol[i].notNull = onError;
-}
-
-/*
-** This routine is called by the parser while in the middle of
-** parsing a CREATE TABLE statement. The pFirst token is the first
-** token in the sequence of tokens that describe the type of the
-** column currently under construction. pLast is the last token
-** in the sequence. Use this information to construct a string
-** that contains the typename of the column and store that string
-** in zType.
-*/
-void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
- Table *p;
- int i, j;
- int n;
- char *z, **pz;
- Column *pCol;
- if( (p = pParse->pNewTable)==0 ) return;
- i = p->nCol-1;
- if( i<0 ) return;
- pCol = &p->aCol[i];
- pz = &pCol->zType;
- n = pLast->n + Addr(pLast->z) - Addr(pFirst->z);
- sqliteSetNString(pz, pFirst->z, n, 0);
- z = *pz;
- if( z==0 ) return;
- for(i=j=0; z[i]; i++){
- int c = z[i];
- if( isspace(c) ) continue;
- z[j++] = c;
- }
- z[j] = 0;
- if( pParse->db->file_format>=4 ){
- pCol->sortOrder = sqliteCollateType(z, n);
- }else{
- pCol->sortOrder = SQLITE_SO_NUM;
- }
-}
-
-/*
-** The given token is the default value for the last column added to
-** the table currently under construction. If "minusFlag" is true, it
-** means the value token was preceded by a minus sign.
-**
-** This routine is called by the parser while in the middle of
-** parsing a CREATE TABLE statement.
-*/
-void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
- Table *p;
- int i;
- char **pz;
- if( (p = pParse->pNewTable)==0 ) return;
- i = p->nCol-1;
- if( i<0 ) return;
- pz = &p->aCol[i].zDflt;
- if( minusFlag ){
- sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
- }else{
- sqliteSetNString(pz, pVal->z, pVal->n, 0);
- }
- sqliteDequote(*pz);
-}
-
-/*
-** Designate the PRIMARY KEY for the table. pList is a list of names
-** of columns that form the primary key. If pList is NULL, then the
-** most recently added column of the table is the primary key.
-**
-** A table can have at most one primary key. If the table already has
-** a primary key (and this is the second primary key) then create an
-** error.
-**
-** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
-** then we will try to use that column as the row id. (Exception:
-** For backwards compatibility with older databases, do not do this
-** if the file format version number is less than 1.) Set the Table.iPKey
-** field of the table under construction to be the index of the
-** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is
-** no INTEGER PRIMARY KEY.
-**
-** If the key is not an INTEGER PRIMARY KEY, then create a unique
-** index for the key. No index is created for INTEGER PRIMARY KEYs.
-*/
-void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){
- Table *pTab = pParse->pNewTable;
- char *zType = 0;
- int iCol = -1, i;
- if( pTab==0 ) goto primary_key_exit;
- if( pTab->hasPrimKey ){
- sqliteErrorMsg(pParse,
- "table \"%s\" has more than one primary key", pTab->zName);
- goto primary_key_exit;
- }
- pTab->hasPrimKey = 1;
- if( pList==0 ){
- iCol = pTab->nCol - 1;
- pTab->aCol[iCol].isPrimKey = 1;
- }else{
- for(i=0; i<pList->nId; i++){
- for(iCol=0; iCol<pTab->nCol; iCol++){
- if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break;
- }
- if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1;
- }
- if( pList->nId>1 ) iCol = -1;
- }
- if( iCol>=0 && iCol<pTab->nCol ){
- zType = pTab->aCol[iCol].zType;
- }
- if( pParse->db->file_format>=1 &&
- zType && sqliteStrICmp(zType, "INTEGER")==0 ){
- pTab->iPKey = iCol;
- pTab->keyConf = onError;
- }else{
- sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0);
- pList = 0;
- }
-
-primary_key_exit:
- sqliteIdListDelete(pList);
- return;
-}
-
-/*
-** Return the appropriate collating type given a type name.
-**
-** The collation type is text (SQLITE_SO_TEXT) if the type
-** name contains the character stream "text" or "blob" or
-** "clob". Any other type name is collated as numeric
-** (SQLITE_SO_NUM).
-*/
-int sqliteCollateType(const char *zType, int nType){
- int i;
- for(i=0; i<nType-3; i++){
- int c = *(zType++) | 0x60;
- if( (c=='b' || c=='c') && sqliteStrNICmp(zType, "lob", 3)==0 ){
- return SQLITE_SO_TEXT;
- }
- if( c=='c' && sqliteStrNICmp(zType, "har", 3)==0 ){
- return SQLITE_SO_TEXT;
- }
- if( c=='t' && sqliteStrNICmp(zType, "ext", 3)==0 ){
- return SQLITE_SO_TEXT;
- }
- }
- return SQLITE_SO_NUM;
-}
-
-/*
-** This routine is called by the parser while in the middle of
-** parsing a CREATE TABLE statement. A "COLLATE" clause has
-** been seen on a column. This routine sets the Column.sortOrder on
-** the column currently under construction.
-*/
-void sqliteAddCollateType(Parse *pParse, int collType){
- Table *p;
- int i;
- if( (p = pParse->pNewTable)==0 ) return;
- i = p->nCol-1;
- if( i>=0 ) p->aCol[i].sortOrder = collType;
-}
-
-/*
-** Come up with a new random value for the schema cookie. Make sure
-** the new value is different from the old.
-**
-** The schema cookie is used to determine when the schema for the
-** database changes. After each schema change, the cookie value
-** changes. When a process first reads the schema it records the
-** cookie. Thereafter, whenever it goes to access the database,
-** it checks the cookie to make sure the schema has not changed
-** since it was last read.
-**
-** This plan is not completely bullet-proof. It is possible for
-** the schema to change multiple times and for the cookie to be
-** set back to prior value. But schema changes are infrequent
-** and the probability of hitting the same cookie value is only
-** 1 chance in 2^32. So we're safe enough.
-*/
-void sqliteChangeCookie(sqlite *db, Vdbe *v){
- if( db->next_cookie==db->aDb[0].schema_cookie ){
- unsigned char r;
- sqliteRandomness(1, &r);
- db->next_cookie = db->aDb[0].schema_cookie + r + 1;
- db->flags |= SQLITE_InternChanges;
- sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
- sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
- }
-}
-
-/*
-** Measure the number of characters needed to output the given
-** identifier. The number returned includes any quotes used
-** but does not include the null terminator.
-*/
-static int identLength(const char *z){
- int n;
- int needQuote = 0;
- for(n=0; *z; n++, z++){
- if( *z=='\'' ){ n++; needQuote=1; }
- }
- return n + needQuote*2;
-}
-
-/*
-** Write an identifier onto the end of the given string. Add
-** quote characters as needed.
-*/
-static void identPut(char *z, int *pIdx, char *zIdent){
- int i, j, needQuote;
- i = *pIdx;
- for(j=0; zIdent[j]; j++){
- if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
- }
- needQuote = zIdent[j]!=0 || isdigit(zIdent[0])
- || sqliteKeywordCode(zIdent, j)!=TK_ID;
- if( needQuote ) z[i++] = '\'';
- for(j=0; zIdent[j]; j++){
- z[i++] = zIdent[j];
- if( zIdent[j]=='\'' ) z[i++] = '\'';
- }
- if( needQuote ) z[i++] = '\'';
- z[i] = 0;
- *pIdx = i;
-}
-
-/*
-** Generate a CREATE TABLE statement appropriate for the given
-** table. Memory to hold the text of the statement is obtained
-** from sqliteMalloc() and must be freed by the calling function.
-*/
-static char *createTableStmt(Table *p){
- int i, k, n;
- char *zStmt;
- char *zSep, *zSep2, *zEnd;
- n = 0;
- for(i=0; i<p->nCol; i++){
- n += identLength(p->aCol[i].zName);
- }
- n += identLength(p->zName);
- if( n<40 ){
- zSep = "";
- zSep2 = ",";
- zEnd = ")";
- }else{
- zSep = "\n ";
- zSep2 = ",\n ";
- zEnd = "\n)";
- }
- n += 35 + 6*p->nCol;
- zStmt = sqliteMallocRaw( n );
- if( zStmt==0 ) return 0;
- strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE ");
- k = strlen(zStmt);
- identPut(zStmt, &k, p->zName);
- zStmt[k++] = '(';
- for(i=0; i<p->nCol; i++){
- strcpy(&zStmt[k], zSep);
- k += strlen(&zStmt[k]);
- zSep = zSep2;
- identPut(zStmt, &k, p->aCol[i].zName);
- }
- strcpy(&zStmt[k], zEnd);
- return zStmt;
-}
-
-/*
-** This routine is called to report the final ")" that terminates
-** a CREATE TABLE statement.
-**
-** The table structure that other action routines have been building
-** is added to the internal hash tables, assuming no errors have
-** occurred.
-**
-** An entry for the table is made in the master table on disk, unless
-** this is a temporary table or db->init.busy==1. When db->init.busy==1
-** it means we are reading the sqlite_master table because we just
-** connected to the database or because the sqlite_master table has
-** recently changes, so the entry for this table already exists in
-** the sqlite_master table. We do not want to create it again.
-**
-** If the pSelect argument is not NULL, it means that this routine
-** was called to create a table generated from a
-** "CREATE TABLE ... AS SELECT ..." statement. The column names of
-** the new table will match the result set of the SELECT.
-*/
-void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
- Table *p;
- sqlite *db = pParse->db;
-
- if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return;
- p = pParse->pNewTable;
- if( p==0 ) return;
-
- /* If the table is generated from a SELECT, then construct the
- ** list of columns and the text of the table.
- */
- if( pSelect ){
- Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
- if( pSelTab==0 ) return;
- assert( p->aCol==0 );
- p->nCol = pSelTab->nCol;
- p->aCol = pSelTab->aCol;
- pSelTab->nCol = 0;
- pSelTab->aCol = 0;
- sqliteDeleteTable(0, pSelTab);
- }
-
- /* If the db->init.busy is 1 it means we are reading the SQL off the
- ** "sqlite_master" or "sqlite_temp_master" table on the disk.
- ** So do not write to the disk again. Extract the root page number
- ** for the table from the db->init.newTnum field. (The page number
- ** should have been put there by the sqliteOpenCb routine.)
- */
- if( db->init.busy ){
- p->tnum = db->init.newTnum;
- }
-
- /* If not initializing, then create a record for the new table
- ** in the SQLITE_MASTER table of the database. The record number
- ** for the new table entry should already be on the stack.
- **
- ** If this is a TEMPORARY table, write the entry into the auxiliary
- ** file instead of into the main database file.
- */
- if( !db->init.busy ){
- int n;
- Vdbe *v;
-
- v = sqliteGetVdbe(pParse);
- if( v==0 ) return;
- if( p->pSelect==0 ){
- /* A regular table */
- sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
- }else{
- /* A view */
- sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- }
- p->tnum = 0;
- sqliteVdbeAddOp(v, OP_Pull, 1, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC);
- sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0);
- sqliteVdbeAddOp(v, OP_Dup, 4, 0);
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- if( pSelect ){
- char *z = createTableStmt(p);
- n = z ? strlen(z) : 0;
- sqliteVdbeChangeP3(v, -1, z, n);
- sqliteFree(z);
- }else{
- assert( pEnd!=0 );
- n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
- sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
- }
- sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
- if( !p->iDb ){
- sqliteChangeCookie(db, v);
- }
- sqliteVdbeAddOp(v, OP_Close, 0, 0);
- if( pSelect ){
- sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0);
- sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
- pParse->nTab = 2;
- sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
- }
- sqliteEndWriteOperation(pParse);
- }
-
- /* Add the table to the in-memory representation of the database.
- */
- if( pParse->explain==0 && pParse->nErr==0 ){
- Table *pOld;
- FKey *pFKey;
- pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash,
- p->zName, strlen(p->zName)+1, p);
- if( pOld ){
- assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
- return;
- }
- for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
- int nTo = strlen(pFKey->zTo) + 1;
- pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo);
- sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey);
- }
- pParse->pNewTable = 0;
- db->nTable++;
- db->flags |= SQLITE_InternChanges;
- }
-}
-
-/*
-** The parser calls this routine in order to create a new VIEW
-*/
-void sqliteCreateView(
- Parse *pParse, /* The parsing context */
- Token *pBegin, /* The CREATE token that begins the statement */
- Token *pName, /* The token that holds the name of the view */
- Select *pSelect, /* A SELECT statement that will become the new view */
- int isTemp /* TRUE for a TEMPORARY view */
-){
- Table *p;
- int n;
- const char *z;
- Token sEnd;
- DbFixer sFix;
-
- sqliteStartTable(pParse, pBegin, pName, isTemp, 1);
- p = pParse->pNewTable;
- if( p==0 || pParse->nErr ){
- sqliteSelectDelete(pSelect);
- return;
- }
- if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName)
- && sqliteFixSelect(&sFix, pSelect)
- ){
- sqliteSelectDelete(pSelect);
- return;
- }
-
- /* Make a copy of the entire SELECT statement that defines the view.
- ** This will force all the Expr.token.z values to be dynamically
- ** allocated rather than point to the input string - which means that
- ** they will persist after the current sqlite_exec() call returns.
- */
- p->pSelect = sqliteSelectDup(pSelect);
- sqliteSelectDelete(pSelect);
- if( !pParse->db->init.busy ){
- sqliteViewGetColumnNames(pParse, p);
- }
-
- /* Locate the end of the CREATE VIEW statement. Make sEnd point to
- ** the end.
- */
- sEnd = pParse->sLastToken;
- if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
- sEnd.z += sEnd.n;
- }
- sEnd.n = 0;
- n = sEnd.z - pBegin->z;
- z = pBegin->z;
- while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
- sEnd.z = &z[n-1];
- sEnd.n = 1;
-
- /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */
- sqliteEndTable(pParse, &sEnd, 0);
- return;
-}
-
-/*
-** The Table structure pTable is really a VIEW. Fill in the names of
-** the columns of the view in the pTable structure. Return the number
-** of errors. If an error is seen leave an error message in pParse->zErrMsg.
-*/
-int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){
- ExprList *pEList;
- Select *pSel;
- Table *pSelTab;
- int nErr = 0;
-
- assert( pTable );
-
- /* A positive nCol means the columns names for this view are
- ** already known.
- */
- if( pTable->nCol>0 ) return 0;
-
- /* A negative nCol is a special marker meaning that we are currently
- ** trying to compute the column names. If we enter this routine with
- ** a negative nCol, it means two or more views form a loop, like this:
- **
- ** CREATE VIEW one AS SELECT * FROM two;
- ** CREATE VIEW two AS SELECT * FROM one;
- **
- ** Actually, this error is caught previously and so the following test
- ** should always fail. But we will leave it in place just to be safe.
- */
- if( pTable->nCol<0 ){
- sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
- return 1;
- }
-
- /* If we get this far, it means we need to compute the table names.
- */
- assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */
- pSel = pTable->pSelect;
-
- /* Note that the call to sqliteResultSetOfSelect() will expand any
- ** "*" elements in this list. But we will need to restore the list
- ** back to its original configuration afterwards, so we save a copy of
- ** the original in pEList.
- */
- pEList = pSel->pEList;
- pSel->pEList = sqliteExprListDup(pEList);
- if( pSel->pEList==0 ){
- pSel->pEList = pEList;
- return 1; /* Malloc failed */
- }
- pTable->nCol = -1;
- pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel);
- if( pSelTab ){
- assert( pTable->aCol==0 );
- pTable->nCol = pSelTab->nCol;
- pTable->aCol = pSelTab->aCol;
- pSelTab->nCol = 0;
- pSelTab->aCol = 0;
- sqliteDeleteTable(0, pSelTab);
- DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);
- }else{
- pTable->nCol = 0;
- nErr++;
- }
- sqliteSelectUnbind(pSel);
- sqliteExprListDelete(pSel->pEList);
- pSel->pEList = pEList;
- return nErr;
-}
-
-/*
-** Clear the column names from the VIEW pTable.
-**
-** This routine is called whenever any other table or view is modified.
-** The view passed into this routine might depend directly or indirectly
-** on the modified or deleted table so we need to clear the old column
-** names so that they will be recomputed.
-*/
-static void sqliteViewResetColumnNames(Table *pTable){
- int i;
- Column *pCol;
- assert( pTable!=0 && pTable->pSelect!=0 );
- for(i=0, pCol=pTable->aCol; i<pTable->nCol; i++, pCol++){
- sqliteFree(pCol->zName);
- sqliteFree(pCol->zDflt);
- sqliteFree(pCol->zType);
- }
- sqliteFree(pTable->aCol);
- pTable->aCol = 0;
- pTable->nCol = 0;
-}
-
-/*
-** Clear the column names from every VIEW in database idx.
-*/
-static void sqliteViewResetAll(sqlite *db, int idx){
- HashElem *i;
- if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
- for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
- Table *pTab = sqliteHashData(i);
- if( pTab->pSelect ){
- sqliteViewResetColumnNames(pTab);
- }
- }
- DbClearProperty(db, idx, DB_UnresetViews);
-}
-
-/*
-** Given a token, look up a table with that name. If not found, leave
-** an error for the parser to find and return NULL.
-*/
-Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
- char *zName;
- Table *pTab;
- zName = sqliteTableNameFromToken(pTok);
- if( zName==0 ) return 0;
- pTab = sqliteFindTable(pParse->db, zName, 0);
- sqliteFree(zName);
- if( pTab==0 ){
- sqliteErrorMsg(pParse, "no such table: %T", pTok);
- }
- return pTab;
-}
-
-/*
-** This routine is called to do the work of a DROP TABLE statement.
-** pName is the name of the table to be dropped.
-*/
-void sqliteDropTable(Parse *pParse, Token *pName, int isView){
- Table *pTable;
- Vdbe *v;
- int base;
- sqlite *db = pParse->db;
- int iDb;
-
- if( pParse->nErr || sqlite_malloc_failed ) return;
- pTable = sqliteTableFromToken(pParse, pName);
- if( pTable==0 ) return;
- iDb = pTable->iDb;
- assert( iDb>=0 && iDb<db->nDb );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code;
- const char *zTab = SCHEMA_TABLE(pTable->iDb);
- const char *zDb = db->aDb[pTable->iDb].zName;
- if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
- return;
- }
- if( isView ){
- if( iDb==1 ){
- code = SQLITE_DROP_TEMP_VIEW;
- }else{
- code = SQLITE_DROP_VIEW;
- }
- }else{
- if( iDb==1 ){
- code = SQLITE_DROP_TEMP_TABLE;
- }else{
- code = SQLITE_DROP_TABLE;
- }
- }
- if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){
- return;
- }
- if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){
- return;
- }
- }
-#endif
- if( pTable->readOnly ){
- sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName);
- pParse->nErr++;
- return;
- }
- if( isView && pTable->pSelect==0 ){
- sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName);
- return;
- }
- if( !isView && pTable->pSelect ){
- sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName);
- return;
- }
-
- /* Generate code to remove the table from the master table
- ** on disk.
- */
- v = sqliteGetVdbe(pParse);
- if( v ){
- static VdbeOpList dropTable[] = {
- { OP_Rewind, 0, ADDR(8), 0},
- { OP_String, 0, 0, 0}, /* 1 */
- { OP_MemStore, 1, 1, 0},
- { OP_MemLoad, 1, 0, 0}, /* 3 */
- { OP_Column, 0, 2, 0},
- { OP_Ne, 0, ADDR(7), 0},
- { OP_Delete, 0, 0, 0},
- { OP_Next, 0, ADDR(3), 0}, /* 7 */
- };
- Index *pIdx;
- Trigger *pTrigger;
- sqliteBeginWriteOperation(pParse, 0, pTable->iDb);
-
- /* Drop all triggers associated with the table being dropped */
- pTrigger = pTable->pTrigger;
- while( pTrigger ){
- assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 );
- sqliteDropTriggerPtr(pParse, pTrigger, 1);
- if( pParse->explain ){
- pTrigger = pTrigger->pNext;
- }else{
- pTrigger = pTable->pTrigger;
- }
- }
-
- /* Drop all SQLITE_MASTER entries that refer to the table */
- sqliteOpenMasterTable(v, pTable->iDb);
- base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
- sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
-
- /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */
- if( pTable->iDb!=1 ){
- sqliteOpenMasterTable(v, 1);
- base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
- sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
- }
-
- if( pTable->iDb==0 ){
- sqliteChangeCookie(db, v);
- }
- sqliteVdbeAddOp(v, OP_Close, 0, 0);
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb);
- for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
- sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
- }
- }
- sqliteEndWriteOperation(pParse);
- }
-
- /* Delete the in-memory description of the table.
- **
- ** Exception: if the SQL statement began with the EXPLAIN keyword,
- ** then no changes should be made.
- */
- if( !pParse->explain ){
- sqliteUnlinkAndDeleteTable(db, pTable);
- db->flags |= SQLITE_InternChanges;
- }
- sqliteViewResetAll(db, iDb);
-}
-
-/*
-** This routine constructs a P3 string suitable for an OP_MakeIdxKey
-** opcode and adds that P3 string to the most recently inserted instruction
-** in the virtual machine. The P3 string consists of a single character
-** for each column in the index pIdx of table pTab. If the column uses
-** a numeric sort order, then the P3 string character corresponding to
-** that column is 'n'. If the column uses a text sort order, then the
-** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for
-** additional information. See also the sqliteAddKeyType() routine.
-*/
-void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){
- char *zType;
- Table *pTab;
- int i, n;
- assert( pIdx!=0 && pIdx->pTable!=0 );
- pTab = pIdx->pTable;
- n = pIdx->nColumn;
- zType = sqliteMallocRaw( n+1 );
- if( zType==0 ) return;
- for(i=0; i<n; i++){
- int iCol = pIdx->aiColumn[i];
- assert( iCol>=0 && iCol<pTab->nCol );
- if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
- zType[i] = 't';
- }else{
- zType[i] = 'n';
- }
- }
- zType[n] = 0;
- sqliteVdbeChangeP3(v, -1, zType, n);
- sqliteFree(zType);
-}
-
-/*
-** This routine is called to create a new foreign key on the table
-** currently under construction. pFromCol determines which columns
-** in the current table point to the foreign key. If pFromCol==0 then
-** connect the key to the last column inserted. pTo is the name of
-** the table referred to. pToCol is a list of tables in the other
-** pTo table that the foreign key points to. flags contains all
-** information about the conflict resolution algorithms specified
-** in the ON DELETE, ON UPDATE and ON INSERT clauses.
-**
-** An FKey structure is created and added to the table currently
-** under construction in the pParse->pNewTable field. The new FKey
-** is not linked into db->aFKey at this point - that does not happen
-** until sqliteEndTable().
-**
-** The foreign key is set for IMMEDIATE processing. A subsequent call
-** to sqliteDeferForeignKey() might change this to DEFERRED.
-*/
-void sqliteCreateForeignKey(
- Parse *pParse, /* Parsing context */
- IdList *pFromCol, /* Columns in this table that point to other table */
- Token *pTo, /* Name of the other table */
- IdList *pToCol, /* Columns in the other table */
- int flags /* Conflict resolution algorithms. */
-){
- Table *p = pParse->pNewTable;
- int nByte;
- int i;
- int nCol;
- char *z;
- FKey *pFKey = 0;
-
- assert( pTo!=0 );
- if( p==0 || pParse->nErr ) goto fk_end;
- if( pFromCol==0 ){
- int iCol = p->nCol-1;
- if( iCol<0 ) goto fk_end;
- if( pToCol && pToCol->nId!=1 ){
- sqliteErrorMsg(pParse, "foreign key on %s"
- " should reference only one column of table %T",
- p->aCol[iCol].zName, pTo);
- goto fk_end;
- }
- nCol = 1;
- }else if( pToCol && pToCol->nId!=pFromCol->nId ){
- sqliteErrorMsg(pParse,
- "number of columns in foreign key does not match the number of "
- "columns in the referenced table");
- goto fk_end;
- }else{
- nCol = pFromCol->nId;
- }
- nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
- if( pToCol ){
- for(i=0; i<pToCol->nId; i++){
- nByte += strlen(pToCol->a[i].zName) + 1;
- }
- }
- pFKey = sqliteMalloc( nByte );
- if( pFKey==0 ) goto fk_end;
- pFKey->pFrom = p;
- pFKey->pNextFrom = p->pFKey;
- z = (char*)&pFKey[1];
- pFKey->aCol = (struct sColMap*)z;
- z += sizeof(struct sColMap)*nCol;
- pFKey->zTo = z;
- memcpy(z, pTo->z, pTo->n);
- z[pTo->n] = 0;
- z += pTo->n+1;
- pFKey->pNextTo = 0;
- pFKey->nCol = nCol;
- if( pFromCol==0 ){
- pFKey->aCol[0].iFrom = p->nCol-1;
- }else{
- for(i=0; i<nCol; i++){
- int j;
- for(j=0; j<p->nCol; j++){
- if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
- pFKey->aCol[i].iFrom = j;
- break;
- }
- }
- if( j>=p->nCol ){
- sqliteErrorMsg(pParse,
- "unknown column \"%s\" in foreign key definition",
- pFromCol->a[i].zName);
- goto fk_end;
- }
- }
- }
- if( pToCol ){
- for(i=0; i<nCol; i++){
- int n = strlen(pToCol->a[i].zName);
- pFKey->aCol[i].zCol = z;
- memcpy(z, pToCol->a[i].zName, n);
- z[n] = 0;
- z += n+1;
- }
- }
- pFKey->isDeferred = 0;
- pFKey->deleteConf = flags & 0xff;
- pFKey->updateConf = (flags >> 8 ) & 0xff;
- pFKey->insertConf = (flags >> 16 ) & 0xff;
-
- /* Link the foreign key to the table as the last step.
- */
- p->pFKey = pFKey;
- pFKey = 0;
-
-fk_end:
- sqliteFree(pFKey);
- sqliteIdListDelete(pFromCol);
- sqliteIdListDelete(pToCol);
-}
-
-/*
-** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
-** clause is seen as part of a foreign key definition. The isDeferred
-** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
-** The behavior of the most recently created foreign key is adjusted
-** accordingly.
-*/
-void sqliteDeferForeignKey(Parse *pParse, int isDeferred){
- Table *pTab;
- FKey *pFKey;
- if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
- pFKey->isDeferred = isDeferred;
-}
-
-/*
-** Create a new index for an SQL table. pIndex is the name of the index
-** and pTable is the name of the table that is to be indexed. Both will
-** be NULL for a primary key or an index that is created to satisfy a
-** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
-** as the table to be indexed. pParse->pNewTable is a table that is
-** currently being constructed by a CREATE TABLE statement.
-**
-** pList is a list of columns to be indexed. pList will be NULL if this
-** is a primary key or unique-constraint on the most recent column added
-** to the table currently under construction.
-*/
-void sqliteCreateIndex(
- Parse *pParse, /* All information about this parse */
- Token *pName, /* Name of the index. May be NULL */
- SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */
- IdList *pList, /* A list of columns to be indexed */
- int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */
- Token *pEnd /* The ")" that closes the CREATE INDEX statement */
-){
- Table *pTab; /* Table to be indexed */
- Index *pIndex; /* The index to be created */
- char *zName = 0;
- int i, j;
- Token nullId; /* Fake token for an empty ID list */
- DbFixer sFix; /* For assigning database names to pTable */
- int isTemp; /* True for a temporary index */
- sqlite *db = pParse->db;
-
- if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
- if( db->init.busy
- && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
- && sqliteFixSrcList(&sFix, pTable)
- ){
- goto exit_create_index;
- }
-
- /*
- ** Find the table that is to be indexed. Return early if not found.
- */
- if( pTable!=0 ){
- assert( pName!=0 );
- assert( pTable->nSrc==1 );
- pTab = sqliteSrcListLookup(pParse, pTable);
- }else{
- assert( pName==0 );
- pTab = pParse->pNewTable;
- }
- if( pTab==0 || pParse->nErr ) goto exit_create_index;
- if( pTab->readOnly ){
- sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
- goto exit_create_index;
- }
- if( pTab->iDb>=2 && db->init.busy==0 ){
- sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
- goto exit_create_index;
- }
- if( pTab->pSelect ){
- sqliteErrorMsg(pParse, "views may not be indexed");
- goto exit_create_index;
- }
- isTemp = pTab->iDb==1;
-
- /*
- ** Find the name of the index. Make sure there is not already another
- ** index or table with the same name.
- **
- ** Exception: If we are reading the names of permanent indices from the
- ** sqlite_master table (because some other process changed the schema) and
- ** one of the index names collides with the name of a temporary table or
- ** index, then we will continue to process this index.
- **
- ** If pName==0 it means that we are
- ** dealing with a primary key or UNIQUE constraint. We have to invent our
- ** own name.
- */
- if( pName && !db->init.busy ){
- Index *pISameName; /* Another index with the same name */
- Table *pTSameName; /* A table with same name as the index */
- zName = sqliteTableNameFromToken(pName);
- if( zName==0 ) goto exit_create_index;
- if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
- sqliteErrorMsg(pParse, "index %s already exists", zName);
- goto exit_create_index;
- }
- if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
- sqliteErrorMsg(pParse, "there is already a table named %s", zName);
- goto exit_create_index;
- }
- }else if( pName==0 ){
- char zBuf[30];
- int n;
- Index *pLoop;
- for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
- sprintf(zBuf,"%d)",n);
- zName = 0;
- sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);
- if( zName==0 ) goto exit_create_index;
- }else{
- zName = sqliteTableNameFromToken(pName);
- }
-
- /* Check for authorization to create an index.
- */
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- const char *zDb = db->aDb[pTab->iDb].zName;
-
- assert( pTab->iDb==db->init.iDb || isTemp );
- if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
- goto exit_create_index;
- }
- i = SQLITE_CREATE_INDEX;
- if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
- if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
- goto exit_create_index;
- }
- }
-#endif
-
- /* If pList==0, it means this routine was called to make a primary
- ** key out of the last column added to the table under construction.
- ** So create a fake list to simulate this.
- */
- if( pList==0 ){
- nullId.z = pTab->aCol[pTab->nCol-1].zName;
- nullId.n = strlen(nullId.z);
- pList = sqliteIdListAppend(0, &nullId);
- if( pList==0 ) goto exit_create_index;
- }
-
- /*
- ** Allocate the index structure.
- */
- pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
- sizeof(int)*pList->nId );
- if( pIndex==0 ) goto exit_create_index;
- pIndex->aiColumn = (int*)&pIndex[1];
- pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
- strcpy(pIndex->zName, zName);
- pIndex->pTable = pTab;
- pIndex->nColumn = pList->nId;
- pIndex->onError = onError;
- pIndex->autoIndex = pName==0;
- pIndex->iDb = isTemp ? 1 : db->init.iDb;
-
- /* Scan the names of the columns of the table to be indexed and
- ** load the column indices into the Index structure. Report an error
- ** if any column is not found.
- */
- for(i=0; i<pList->nId; i++){
- for(j=0; j<pTab->nCol; j++){
- if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;
- }
- if( j>=pTab->nCol ){
- sqliteErrorMsg(pParse, "table %s has no column named %s",
- pTab->zName, pList->a[i].zName);
- sqliteFree(pIndex);
- goto exit_create_index;
- }
- pIndex->aiColumn[i] = j;
- }
-
- /* Link the new Index structure to its table and to the other
- ** in-memory database structures.
- */
- if( !pParse->explain ){
- Index *p;
- p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash,
- pIndex->zName, strlen(pIndex->zName)+1, pIndex);
- if( p ){
- assert( p==pIndex ); /* Malloc must have failed */
- sqliteFree(pIndex);
- goto exit_create_index;
- }
- db->flags |= SQLITE_InternChanges;
- }
-
- /* When adding an index to the list of indices for a table, make
- ** sure all indices labeled OE_Replace come after all those labeled
- ** OE_Ignore. This is necessary for the correct operation of UPDATE
- ** and INSERT.
- */
- if( onError!=OE_Replace || pTab->pIndex==0
- || pTab->pIndex->onError==OE_Replace){
- pIndex->pNext = pTab->pIndex;
- pTab->pIndex = pIndex;
- }else{
- Index *pOther = pTab->pIndex;
- while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
- pOther = pOther->pNext;
- }
- pIndex->pNext = pOther->pNext;
- pOther->pNext = pIndex;
- }
-
- /* If the db->init.busy is 1 it means we are reading the SQL off the
- ** "sqlite_master" table on the disk. So do not write to the disk
- ** again. Extract the table number from the db->init.newTnum field.
- */
- if( db->init.busy && pTable!=0 ){
- pIndex->tnum = db->init.newTnum;
- }
-
- /* If the db->init.busy is 0 then create the index on disk. This
- ** involves writing the index into the master table and filling in the
- ** index with the current table contents.
- **
- ** The db->init.busy is 0 when the user first enters a CREATE INDEX
- ** command. db->init.busy is 1 when a database is opened and
- ** CREATE INDEX statements are read out of the master table. In
- ** the latter case the index already exists on disk, which is why
- ** we don't want to recreate it.
- **
- ** If pTable==0 it means this index is generated as a primary key
- ** or UNIQUE constraint of a CREATE TABLE statement. Since the table
- ** has just been created, it contains no data and the index initialization
- ** step can be skipped.
- */
- else if( db->init.busy==0 ){
- int n;
- Vdbe *v;
- int lbl1, lbl2;
- int i;
- int addr;
-
- v = sqliteGetVdbe(pParse);
- if( v==0 ) goto exit_create_index;
- if( pTable!=0 ){
- sqliteBeginWriteOperation(pParse, 0, isTemp);
- sqliteOpenMasterTable(v, isTemp);
- }
- sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC);
- sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0);
- sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER);
- pIndex->tnum = 0;
- if( pTable ){
- sqliteVdbeCode(v,
- OP_Dup, 0, 0,
- OP_Integer, isTemp, 0,
- OP_OpenWrite, 1, 0,
- 0);
- }
- addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
- if( pStart && pEnd ){
- n = Addr(pEnd->z) - Addr(pStart->z) + 1;
- sqliteVdbeChangeP3(v, addr, pStart->z, n);
- }
- sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
- if( pTable ){
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0);
- lbl2 = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
- lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
- for(i=0; i<pIndex->nColumn; i++){
- int iCol = pIndex->aiColumn[i];
- if( pTab->iPKey==iCol ){
- sqliteVdbeAddOp(v, OP_Dup, i, 0);
- }else{
- sqliteVdbeAddOp(v, OP_Column, 2, iCol);
- }
- }
- sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
- if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex);
- sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
- "indexed columns are not unique", P3_STATIC);
- sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
- sqliteVdbeResolveLabel(v, lbl2);
- sqliteVdbeAddOp(v, OP_Close, 2, 0);
- sqliteVdbeAddOp(v, OP_Close, 1, 0);
- }
- if( pTable!=0 ){
- if( !isTemp ){
- sqliteChangeCookie(db, v);
- }
- sqliteVdbeAddOp(v, OP_Close, 0, 0);
- sqliteEndWriteOperation(pParse);
- }
- }
-
- /* Clean up before exiting */
-exit_create_index:
- sqliteIdListDelete(pList);
- sqliteSrcListDelete(pTable);
- sqliteFree(zName);
- return;
-}
-
-/*
-** This routine will drop an existing named index. This routine
-** implements the DROP INDEX statement.
-*/
-void sqliteDropIndex(Parse *pParse, SrcList *pName){
- Index *pIndex;
- Vdbe *v;
- sqlite *db = pParse->db;
-
- if( pParse->nErr || sqlite_malloc_failed ) return;
- assert( pName->nSrc==1 );
- pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
- if( pIndex==0 ){
- sqliteErrorMsg(pParse, "no such index: %S", pName, 0);
- goto exit_drop_index;
- }
- if( pIndex->autoIndex ){
- sqliteErrorMsg(pParse, "index associated with UNIQUE "
- "or PRIMARY KEY constraint cannot be dropped", 0);
- goto exit_drop_index;
- }
- if( pIndex->iDb>1 ){
- sqliteErrorMsg(pParse, "cannot alter schema of attached "
- "databases", 0);
- goto exit_drop_index;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code = SQLITE_DROP_INDEX;
- Table *pTab = pIndex->pTable;
- const char *zDb = db->aDb[pIndex->iDb].zName;
- const char *zTab = SCHEMA_TABLE(pIndex->iDb);
- if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
- goto exit_drop_index;
- }
- if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
- if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
- goto exit_drop_index;
- }
- }
-#endif
-
- /* Generate code to remove the index and from the master table */
- v = sqliteGetVdbe(pParse);
- if( v ){
- static VdbeOpList dropIndex[] = {
- { OP_Rewind, 0, ADDR(9), 0},
- { OP_String, 0, 0, 0}, /* 1 */
- { OP_MemStore, 1, 1, 0},
- { OP_MemLoad, 1, 0, 0}, /* 3 */
- { OP_Column, 0, 1, 0},
- { OP_Eq, 0, ADDR(8), 0},
- { OP_Next, 0, ADDR(3), 0},
- { OP_Goto, 0, ADDR(9), 0},
- { OP_Delete, 0, 0, 0}, /* 8 */
- };
- int base;
-
- sqliteBeginWriteOperation(pParse, 0, pIndex->iDb);
- sqliteOpenMasterTable(v, pIndex->iDb);
- base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
- sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0);
- if( pIndex->iDb==0 ){
- sqliteChangeCookie(db, v);
- }
- sqliteVdbeAddOp(v, OP_Close, 0, 0);
- sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
- sqliteEndWriteOperation(pParse);
- }
-
- /* Delete the in-memory description of this index.
- */
- if( !pParse->explain ){
- sqliteUnlinkAndDeleteIndex(db, pIndex);
- db->flags |= SQLITE_InternChanges;
- }
-
-exit_drop_index:
- sqliteSrcListDelete(pName);
-}
-
-/*
-** Append a new element to the given IdList. Create a new IdList if
-** need be.
-**
-** A new IdList is returned, or NULL if malloc() fails.
-*/
-IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
- if( pList==0 ){
- pList = sqliteMalloc( sizeof(IdList) );
- if( pList==0 ) return 0;
- pList->nAlloc = 0;
- }
- if( pList->nId>=pList->nAlloc ){
- struct IdList_item *a;
- pList->nAlloc = pList->nAlloc*2 + 5;
- a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
- if( a==0 ){
- sqliteIdListDelete(pList);
- return 0;
- }
- pList->a = a;
- }
- memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
- if( pToken ){
- char **pz = &pList->a[pList->nId].zName;
- sqliteSetNString(pz, pToken->z, pToken->n, 0);
- if( *pz==0 ){
- sqliteIdListDelete(pList);
- return 0;
- }else{
- sqliteDequote(*pz);
- }
- }
- pList->nId++;
- return pList;
-}
-
-/*
-** Append a new table name to the given SrcList. Create a new SrcList if
-** need be. A new entry is created in the SrcList even if pToken is NULL.
-**
-** A new SrcList is returned, or NULL if malloc() fails.
-**
-** If pDatabase is not null, it means that the table has an optional
-** database name prefix. Like this: "database.table". The pDatabase
-** points to the table name and the pTable points to the database name.
-** The SrcList.a[].zName field is filled with the table name which might
-** come from pTable (if pDatabase is NULL) or from pDatabase.
-** SrcList.a[].zDatabase is filled with the database name from pTable,
-** or with NULL if no database is specified.
-**
-** In other words, if call like this:
-**
-** sqliteSrcListAppend(A,B,0);
-**
-** Then B is a table name and the database name is unspecified. If called
-** like this:
-**
-** sqliteSrcListAppend(A,B,C);
-**
-** Then C is the table name and B is the database name.
-*/
-SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
- if( pList==0 ){
- pList = sqliteMalloc( sizeof(SrcList) );
- if( pList==0 ) return 0;
- pList->nAlloc = 1;
- }
- if( pList->nSrc>=pList->nAlloc ){
- SrcList *pNew;
- pList->nAlloc *= 2;
- pNew = sqliteRealloc(pList,
- sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
- if( pNew==0 ){
- sqliteSrcListDelete(pList);
- return 0;
- }
- pList = pNew;
- }
- memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0]));
- if( pDatabase && pDatabase->z==0 ){
- pDatabase = 0;
- }
- if( pDatabase && pTable ){
- Token *pTemp = pDatabase;
- pDatabase = pTable;
- pTable = pTemp;
- }
- if( pTable ){
- char **pz = &pList->a[pList->nSrc].zName;
- sqliteSetNString(pz, pTable->z, pTable->n, 0);
- if( *pz==0 ){
- sqliteSrcListDelete(pList);
- return 0;
- }else{
- sqliteDequote(*pz);
- }
- }
- if( pDatabase ){
- char **pz = &pList->a[pList->nSrc].zDatabase;
- sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0);
- if( *pz==0 ){
- sqliteSrcListDelete(pList);
- return 0;
- }else{
- sqliteDequote(*pz);
- }
- }
- pList->a[pList->nSrc].iCursor = -1;
- pList->nSrc++;
- return pList;
-}
-
-/*
-** Assign cursors to all tables in a SrcList
-*/
-void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){
- int i;
- for(i=0; i<pList->nSrc; i++){
- if( pList->a[i].iCursor<0 ){
- pList->a[i].iCursor = pParse->nTab++;
- }
- }
-}
-
-/*
-** Add an alias to the last identifier on the given identifier list.
-*/
-void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){
- if( pList && pList->nSrc>0 ){
- int i = pList->nSrc - 1;
- sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0);
- sqliteDequote(pList->a[i].zAlias);
- }
-}
-
-/*
-** Delete an IdList.
-*/
-void sqliteIdListDelete(IdList *pList){
- int i;
- if( pList==0 ) return;
- for(i=0; i<pList->nId; i++){
- sqliteFree(pList->a[i].zName);
- }
- sqliteFree(pList->a);
- sqliteFree(pList);
-}
-
-/*
-** Return the index in pList of the identifier named zId. Return -1
-** if not found.
-*/
-int sqliteIdListIndex(IdList *pList, const char *zName){
- int i;
- if( pList==0 ) return -1;
- for(i=0; i<pList->nId; i++){
- if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i;
- }
- return -1;
-}
-
-/*
-** Delete an entire SrcList including all its substructure.
-*/
-void sqliteSrcListDelete(SrcList *pList){
- int i;
- if( pList==0 ) return;
- for(i=0; i<pList->nSrc; i++){
- sqliteFree(pList->a[i].zDatabase);
- sqliteFree(pList->a[i].zName);
- sqliteFree(pList->a[i].zAlias);
- if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){
- sqliteDeleteTable(0, pList->a[i].pTab);
- }
- sqliteSelectDelete(pList->a[i].pSelect);
- sqliteExprDelete(pList->a[i].pOn);
- sqliteIdListDelete(pList->a[i].pUsing);
- }
- sqliteFree(pList);
-}
-
-/*
-** Begin a transaction
-*/
-void sqliteBeginTransaction(Parse *pParse, int onError){
- sqlite *db;
-
- if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite_malloc_failed ) return;
- if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
- if( db->flags & SQLITE_InTrans ){
- sqliteErrorMsg(pParse, "cannot start a transaction within a transaction");
- return;
- }
- sqliteBeginWriteOperation(pParse, 0, 0);
- if( !pParse->explain ){
- db->flags |= SQLITE_InTrans;
- db->onError = onError;
- }
-}
-
-/*
-** Commit a transaction
-*/
-void sqliteCommitTransaction(Parse *pParse){
- sqlite *db;
-
- if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite_malloc_failed ) return;
- if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
- if( (db->flags & SQLITE_InTrans)==0 ){
- sqliteErrorMsg(pParse, "cannot commit - no transaction is active");
- return;
- }
- if( !pParse->explain ){
- db->flags &= ~SQLITE_InTrans;
- }
- sqliteEndWriteOperation(pParse);
- if( !pParse->explain ){
- db->onError = OE_Default;
- }
-}
-
-/*
-** Rollback a transaction
-*/
-void sqliteRollbackTransaction(Parse *pParse){
- sqlite *db;
- Vdbe *v;
-
- if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite_malloc_failed ) return;
- if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
- if( (db->flags & SQLITE_InTrans)==0 ){
- sqliteErrorMsg(pParse, "cannot rollback - no transaction is active");
- return;
- }
- v = sqliteGetVdbe(pParse);
- if( v ){
- sqliteVdbeAddOp(v, OP_Rollback, 0, 0);
- }
- if( !pParse->explain ){
- db->flags &= ~SQLITE_InTrans;
- db->onError = OE_Default;
- }
-}
-
-/*
-** Generate VDBE code that will verify the schema cookie for all
-** named database files.
-*/
-void sqliteCodeVerifySchema(Parse *pParse, int iDb){
- sqlite *db = pParse->db;
- Vdbe *v = sqliteGetVdbe(pParse);
- assert( iDb>=0 && iDb<db->nDb );
- assert( db->aDb[iDb].pBt!=0 );
- if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){
- sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie);
- DbSetProperty(db, iDb, DB_Cookie);
- }
-}
-
-/*
-** Generate VDBE code that prepares for doing an operation that
-** might change the database.
-**
-** This routine starts a new transaction if we are not already within
-** a transaction. If we are already within a transaction, then a checkpoint
-** is set if the setCheckpoint parameter is true. A checkpoint should
-** be set for operations that might fail (due to a constraint) part of
-** the way through and which will need to undo some writes without having to
-** rollback the whole transaction. For operations where all constraints
-** can be checked before any changes are made to the database, it is never
-** necessary to undo a write and the checkpoint should not be set.
-**
-** Only database iDb and the temp database are made writable by this call.
-** If iDb==0, then the main and temp databases are made writable. If
-** iDb==1 then only the temp database is made writable. If iDb>1 then the
-** specified auxiliary database and the temp database are made writable.
-*/
-void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){
- Vdbe *v;
- sqlite *db = pParse->db;
- if( DbHasProperty(db, iDb, DB_Locked) ) return;
- v = sqliteGetVdbe(pParse);
- if( v==0 ) return;
- if( !db->aDb[iDb].inTrans ){
- sqliteVdbeAddOp(v, OP_Transaction, iDb, 0);
- DbSetProperty(db, iDb, DB_Locked);
- sqliteCodeVerifySchema(pParse, iDb);
- if( iDb!=1 ){
- sqliteBeginWriteOperation(pParse, setCheckpoint, 1);
- }
- }else if( setCheckpoint ){
- sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0);
- DbSetProperty(db, iDb, DB_Locked);
- }
-}
-
-/*
-** Generate code that concludes an operation that may have changed
-** the database. If a statement transaction was started, then emit
-** an OP_Commit that will cause the changes to be committed to disk.
-**
-** Note that checkpoints are automatically committed at the end of
-** a statement. Note also that there can be multiple calls to
-** sqliteBeginWriteOperation() but there should only be a single
-** call to sqliteEndWriteOperation() at the conclusion of the statement.
-*/
-void sqliteEndWriteOperation(Parse *pParse){
- Vdbe *v;
- sqlite *db = pParse->db;
- if( pParse->trigStack ) return; /* if this is in a trigger */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) return;
- if( db->flags & SQLITE_InTrans ){
- /* A BEGIN has executed. Do not commit until we see an explicit
- ** COMMIT statement. */
- }else{
- sqliteVdbeAddOp(v, OP_Commit, 0, 0);
- }
-}
diff --git a/ext/sqlite/libsqlite/src/config_static.w32.h b/ext/sqlite/libsqlite/src/config_static.w32.h
deleted file mode 100644
index d9893024fa..0000000000
--- a/ext/sqlite/libsqlite/src/config_static.w32.h
+++ /dev/null
@@ -1 +0,0 @@
-#define SQLITE_PTR_SZ 4 \ No newline at end of file
diff --git a/ext/sqlite/libsqlite/src/copy.c b/ext/sqlite/libsqlite/src/copy.c
deleted file mode 100644
index 2f70fce17b..0000000000
--- a/ext/sqlite/libsqlite/src/copy.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-** 2003 April 6
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code used to implement the COPY command.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** The COPY command is for compatibility with PostgreSQL and specificially
-** for the ability to read the output of pg_dump. The format is as
-** follows:
-**
-** COPY table FROM file [USING DELIMITERS string]
-**
-** "table" is an existing table name. We will read lines of code from
-** file to fill this table with data. File might be "stdin". The optional
-** delimiter string identifies the field separators. The default is a tab.
-*/
-void sqliteCopy(
- Parse *pParse, /* The parser context */
- SrcList *pTableName, /* The name of the table into which we will insert */
- Token *pFilename, /* The file from which to obtain information */
- Token *pDelimiter, /* Use this as the field delimiter */
- int onError /* What to do if a constraint fails */
-){
- Table *pTab;
- int i;
- Vdbe *v;
- int addr, end;
- char *zFile = 0;
- const char *zDb;
- sqlite *db = pParse->db;
-
-
- if( sqlite_malloc_failed ) goto copy_cleanup;
- assert( pTableName->nSrc==1 );
- pTab = sqliteSrcListLookup(pParse, pTableName);
- if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
- zFile = sqliteStrNDup(pFilename->z, pFilename->n);
- sqliteDequote(zFile);
- assert( pTab->iDb<db->nDb );
- zDb = db->aDb[pTab->iDb].zName;
- if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
- || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
- goto copy_cleanup;
- }
- v = sqliteGetVdbe(pParse);
- if( v ){
- sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
- addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
- sqliteVdbeDequoteP3(v, addr);
- sqliteOpenTableAndIndices(pParse, pTab, 0);
- if( db->flags & SQLITE_CountRows ){
- sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */
- }
- end = sqliteVdbeMakeLabel(v);
- addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
- if( pDelimiter ){
- sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
- sqliteVdbeDequoteP3(v, addr);
- }else{
- sqliteVdbeChangeP3(v, addr, "\t", 1);
- }
- if( pTab->iPKey>=0 ){
- sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
- sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
- }else{
- sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
- }
- for(i=0; i<pTab->nCol; i++){
- if( i==pTab->iPKey ){
- /* The integer primary key column is filled with NULL since its
- ** value is always pulled from the record number */
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- }else{
- sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
- }
- }
- sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0,
- 0, onError, addr);
- sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
- if( (db->flags & SQLITE_CountRows)!=0 ){
- sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */
- }
- sqliteVdbeAddOp(v, OP_Goto, 0, addr);
- sqliteVdbeResolveLabel(v, end);
- sqliteVdbeAddOp(v, OP_Noop, 0, 0);
- sqliteEndWriteOperation(pParse);
- if( db->flags & SQLITE_CountRows ){
- sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
- sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
- sqliteVdbeAddOp(v, OP_Callback, 1, 0);
- }
- }
-
-copy_cleanup:
- sqliteSrcListDelete(pTableName);
- sqliteFree(zFile);
- return;
-}
diff --git a/ext/sqlite/libsqlite/src/date.c b/ext/sqlite/libsqlite/src/date.c
deleted file mode 100644
index cd6761b66a..0000000000
--- a/ext/sqlite/libsqlite/src/date.c
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
-** 2003 October 31
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains the C functions that implement date and time
-** functions for SQLite.
-**
-** There is only one exported symbol in this file - the function
-** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
-** All other code has file scope.
-**
-** $Id$
-**
-** NOTES:
-**
-** SQLite processes all times and dates as Julian Day numbers. The
-** dates and times are stored as the number of days since noon
-** in Greenwich on November 24, 4714 B.C. according to the Gregorian
-** calendar system.
-**
-** 1970-01-01 00:00:00 is JD 2440587.5
-** 2000-01-01 00:00:00 is JD 2451544.5
-**
-** This implemention requires years to be expressed as a 4-digit number
-** which means that only dates between 0000-01-01 and 9999-12-31 can
-** be represented, even though julian day numbers allow a much wider
-** range of dates.
-**
-** The Gregorian calendar system is used for all dates and times,
-** even those that predate the Gregorian calendar. Historians usually
-** use the Julian calendar for dates prior to 1582-10-15 and for some
-** dates afterwards, depending on locale. Beware of this difference.
-**
-** The conversion algorithms are implemented based on descriptions
-** in the following text:
-**
-** Jean Meeus
-** Astronomical Algorithms, 2nd Edition, 1998
-** ISBM 0-943396-61-1
-** Willmann-Bell, Inc
-** Richmond, Virginia (USA)
-*/
-#include "os.h"
-#include "sqliteInt.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <time.h>
-#ifndef PHP_WIN32
-#include "main/php_reentrancy.h"
-#endif
-
-#ifndef SQLITE_OMIT_DATETIME_FUNCS
-
-/*
-** A structure for holding a single date and time.
-*/
-typedef struct DateTime DateTime;
-struct DateTime {
- double rJD; /* The julian day number */
- int Y, M, D; /* Year, month, and day */
- int h, m; /* Hour and minutes */
- int tz; /* Timezone offset in minutes */
- double s; /* Seconds */
- char validYMD; /* True if Y,M,D are valid */
- char validHMS; /* True if h,m,s are valid */
- char validJD; /* True if rJD is valid */
- char validTZ; /* True if tz is valid */
-};
-
-
-/*
-** Convert zDate into one or more integers. Additional arguments
-** come in groups of 5 as follows:
-**
-** N number of digits in the integer
-** min minimum allowed value of the integer
-** max maximum allowed value of the integer
-** nextC first character after the integer
-** pVal where to write the integers value.
-**
-** Conversions continue until one with nextC==0 is encountered.
-** The function returns the number of successful conversions.
-*/
-static int getDigits(const char *zDate, ...){
- va_list ap;
- int val;
- int N;
- int min;
- int max;
- int nextC;
- int *pVal;
- int cnt = 0;
- va_start(ap, zDate);
- do{
- N = va_arg(ap, int);
- min = va_arg(ap, int);
- max = va_arg(ap, int);
- nextC = va_arg(ap, int);
- pVal = va_arg(ap, int*);
- val = 0;
- while( N-- ){
- if( !isdigit(*zDate) ){
- return cnt;
- }
- val = val*10 + *zDate - '0';
- zDate++;
- }
- if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
- return cnt;
- }
- *pVal = val;
- zDate++;
- cnt++;
- }while( nextC );
- return cnt;
-}
-
-/*
-** Read text from z[] and convert into a floating point number. Return
-** the number of digits converted.
-*/
-static int getValue(const char *z, double *pR){
- const char *zEnd;
- *pR = sqliteAtoF(z, &zEnd);
- return zEnd - z;
-}
-
-/*
-** Parse a timezone extension on the end of a date-time.
-** The extension is of the form:
-**
-** (+/-)HH:MM
-**
-** If the parse is successful, write the number of minutes
-** of change in *pnMin and return 0. If a parser error occurs,
-** return 0.
-**
-** A missing specifier is not considered an error.
-*/
-static int parseTimezone(const char *zDate, DateTime *p){
- int sgn = 0;
- int nHr, nMn;
- while( isspace(*zDate) ){ zDate++; }
- p->tz = 0;
- if( *zDate=='-' ){
- sgn = -1;
- }else if( *zDate=='+' ){
- sgn = +1;
- }else{
- return *zDate!=0;
- }
- zDate++;
- if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
- return 1;
- }
- zDate += 5;
- p->tz = sgn*(nMn + nHr*60);
- while( isspace(*zDate) ){ zDate++; }
- return *zDate!=0;
-}
-
-/*
-** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
-** The HH, MM, and SS must each be exactly 2 digits. The
-** fractional seconds FFFF can be one or more digits.
-**
-** Return 1 if there is a parsing error and 0 on success.
-*/
-static int parseHhMmSs(const char *zDate, DateTime *p){
- int h, m, s;
- double ms = 0.0;
- if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
- return 1;
- }
- zDate += 5;
- if( *zDate==':' ){
- zDate++;
- if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
- return 1;
- }
- zDate += 2;
- if( *zDate=='.' && isdigit(zDate[1]) ){
- double rScale = 1.0;
- zDate++;
- while( isdigit(*zDate) ){
- ms = ms*10.0 + *zDate - '0';
- rScale *= 10.0;
- zDate++;
- }
- ms /= rScale;
- }
- }else{
- s = 0;
- }
- p->validJD = 0;
- p->validHMS = 1;
- p->h = h;
- p->m = m;
- p->s = s + ms;
- if( parseTimezone(zDate, p) ) return 1;
- p->validTZ = p->tz!=0;
- return 0;
-}
-
-/*
-** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
-** that the YYYY-MM-DD is according to the Gregorian calendar.
-**
-** Reference: Meeus page 61
-*/
-static void computeJD(DateTime *p){
- int Y, M, D, A, B, X1, X2;
-
- if( p->validJD ) return;
- if( p->validYMD ){
- Y = p->Y;
- M = p->M;
- D = p->D;
- }else{
- Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */
- M = 1;
- D = 1;
- }
- if( M<=2 ){
- Y--;
- M += 12;
- }
- A = Y/100;
- B = 2 - A + (A/4);
- X1 = 365.25*(Y+4716);
- X2 = 30.6001*(M+1);
- p->rJD = X1 + X2 + D + B - 1524.5;
- p->validJD = 1;
- p->validYMD = 0;
- if( p->validHMS ){
- p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
- if( p->validTZ ){
- p->rJD += p->tz*60/86400.0;
- p->validHMS = 0;
- p->validTZ = 0;
- }
- }
-}
-
-/*
-** Parse dates of the form
-**
-** YYYY-MM-DD HH:MM:SS.FFF
-** YYYY-MM-DD HH:MM:SS
-** YYYY-MM-DD HH:MM
-** YYYY-MM-DD
-**
-** Write the result into the DateTime structure and return 0
-** on success and 1 if the input string is not a well-formed
-** date.
-*/
-static int parseYyyyMmDd(const char *zDate, DateTime *p){
- int Y, M, D, neg;
-
- if( zDate[0]=='-' ){
- zDate++;
- neg = 1;
- }else{
- neg = 0;
- }
- if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
- return 1;
- }
- zDate += 10;
- while( isspace(*zDate) ){ zDate++; }
- if( parseHhMmSs(zDate, p)==0 ){
- /* We got the time */
- }else if( *zDate==0 ){
- p->validHMS = 0;
- }else{
- return 1;
- }
- p->validJD = 0;
- p->validYMD = 1;
- p->Y = neg ? -Y : Y;
- p->M = M;
- p->D = D;
- if( p->validTZ ){
- computeJD(p);
- }
- return 0;
-}
-
-/*
-** Attempt to parse the given string into a Julian Day Number. Return
-** the number of errors.
-**
-** The following are acceptable forms for the input string:
-**
-** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
-** DDDD.DD
-** now
-**
-** In the first form, the +/-HH:MM is always optional. The fractional
-** seconds extension (the ".FFF") is optional. The seconds portion
-** (":SS.FFF") is option. The year and date can be omitted as long
-** as there is a time string. The time string can be omitted as long
-** as there is a year and date.
-*/
-static int parseDateOrTime(const char *zDate, DateTime *p){
- memset(p, 0, sizeof(*p));
- if( parseYyyyMmDd(zDate,p)==0 ){
- return 0;
- }else if( parseHhMmSs(zDate, p)==0 ){
- return 0;
- }else if( sqliteStrICmp(zDate,"now")==0){
- double r;
- if( sqliteOsCurrentTime(&r)==0 ){
- p->rJD = r;
- p->validJD = 1;
- return 0;
- }
- return 1;
- }else if( sqliteIsNumber(zDate) ){
- p->rJD = sqliteAtoF(zDate, 0);
- p->validJD = 1;
- return 0;
- }
- return 1;
-}
-
-/*
-** Compute the Year, Month, and Day from the julian day number.
-*/
-static void computeYMD(DateTime *p){
- int Z, A, B, C, D, E, X1;
- if( p->validYMD ) return;
- if( !p->validJD ){
- p->Y = 2000;
- p->M = 1;
- p->D = 1;
- }else{
- Z = p->rJD + 0.5;
- A = (Z - 1867216.25)/36524.25;
- A = Z + 1 + A - (A/4);
- B = A + 1524;
- C = (B - 122.1)/365.25;
- D = 365.25*C;
- E = (B-D)/30.6001;
- X1 = 30.6001*E;
- p->D = B - D - X1;
- p->M = E<14 ? E-1 : E-13;
- p->Y = p->M>2 ? C - 4716 : C - 4715;
- }
- p->validYMD = 1;
-}
-
-/*
-** Compute the Hour, Minute, and Seconds from the julian day number.
-*/
-static void computeHMS(DateTime *p){
- int Z, s;
- if( p->validHMS ) return;
- Z = p->rJD + 0.5;
- s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
- p->s = 0.001*s;
- s = p->s;
- p->s -= s;
- p->h = s/3600;
- s -= p->h*3600;
- p->m = s/60;
- p->s += s - p->m*60;
- p->validHMS = 1;
-}
-
-/*
-** Compute both YMD and HMS
-*/
-static void computeYMD_HMS(DateTime *p){
- computeYMD(p);
- computeHMS(p);
-}
-
-/*
-** Clear the YMD and HMS and the TZ
-*/
-static void clearYMD_HMS_TZ(DateTime *p){
- p->validYMD = 0;
- p->validHMS = 0;
- p->validTZ = 0;
-}
-
-/*
-** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
-** for the time value p where p is in UTC.
-*/
-static double localtimeOffset(DateTime *p){
- DateTime x, y;
- time_t t;
- struct tm *pTm, tmbuf;
- x = *p;
- computeYMD_HMS(&x);
- if( x.Y<1971 || x.Y>=2038 ){
- x.Y = 2000;
- x.M = 1;
- x.D = 1;
- x.h = 0;
- x.m = 0;
- x.s = 0.0;
- } else {
- int s = x.s + 0.5;
- x.s = s;
- }
- x.tz = 0;
- x.validJD = 0;
- computeJD(&x);
- t = (x.rJD-2440587.5)*86400.0 + 0.5;
- sqliteOsEnterMutex();
- pTm = php_localtime_r(&t, &tmbuf);
- if (!pTm) {
- return 0;
- }
- y.Y = pTm->tm_year + 1900;
- y.M = pTm->tm_mon + 1;
- y.D = pTm->tm_mday;
- y.h = pTm->tm_hour;
- y.m = pTm->tm_min;
- y.s = pTm->tm_sec;
- sqliteOsLeaveMutex();
- y.validYMD = 1;
- y.validHMS = 1;
- y.validJD = 0;
- y.validTZ = 0;
- computeJD(&y);
- return y.rJD - x.rJD;
-}
-
-/*
-** Process a modifier to a date-time stamp. The modifiers are
-** as follows:
-**
-** NNN days
-** NNN hours
-** NNN minutes
-** NNN.NNNN seconds
-** NNN months
-** NNN years
-** start of month
-** start of year
-** start of week
-** start of day
-** weekday N
-** unixepoch
-** localtime
-** utc
-**
-** Return 0 on success and 1 if there is any kind of error.
-*/
-static int parseModifier(const char *zMod, DateTime *p){
- int rc = 1;
- int n;
- double r;
- char *z, zBuf[30];
- z = zBuf;
- for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
- z[n] = tolower(zMod[n]);
- }
- z[n] = 0;
- switch( z[0] ){
- case 'l': {
- /* localtime
- **
- ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
- ** show local time.
- */
- if( strcmp(z, "localtime")==0 ){
- computeJD(p);
- p->rJD += localtimeOffset(p);
- clearYMD_HMS_TZ(p);
- rc = 0;
- }
- break;
- }
- case 'u': {
- /*
- ** unixepoch
- **
- ** Treat the current value of p->rJD as the number of
- ** seconds since 1970. Convert to a real julian day number.
- */
- if( strcmp(z, "unixepoch")==0 && p->validJD ){
- p->rJD = p->rJD/86400.0 + 2440587.5;
- clearYMD_HMS_TZ(p);
- rc = 0;
- }else if( strcmp(z, "utc")==0 ){
- double c1;
- computeJD(p);
- c1 = localtimeOffset(p);
- p->rJD -= c1;
- clearYMD_HMS_TZ(p);
- p->rJD += c1 - localtimeOffset(p);
- rc = 0;
- }
- break;
- }
- case 'w': {
- /*
- ** weekday N
- **
- ** Move the date to the same time on the next occurrance of
- ** weekday N where 0==Sunday, 1==Monday, and so forth. If the
- ** date is already on the appropriate weekday, this is a no-op.
- */
- if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
- && (n=r)==r && n>=0 && r<7 ){
- int Z;
- computeYMD_HMS(p);
- p->validTZ = 0;
- p->validJD = 0;
- computeJD(p);
- Z = p->rJD + 1.5;
- Z %= 7;
- if( Z>n ) Z -= 7;
- p->rJD += n - Z;
- clearYMD_HMS_TZ(p);
- rc = 0;
- }
- break;
- }
- case 's': {
- /*
- ** start of TTTTT
- **
- ** Move the date backwards to the beginning of the current day,
- ** or month or year.
- */
- if( strncmp(z, "start of ", 9)!=0 ) break;
- z += 9;
- computeYMD(p);
- p->validHMS = 1;
- p->h = p->m = 0;
- p->s = 0.0;
- p->validTZ = 0;
- p->validJD = 0;
- if( strcmp(z,"month")==0 ){
- p->D = 1;
- rc = 0;
- }else if( strcmp(z,"year")==0 ){
- computeYMD(p);
- p->M = 1;
- p->D = 1;
- rc = 0;
- }else if( strcmp(z,"day")==0 ){
- rc = 0;
- }
- break;
- }
- case '+':
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- n = getValue(z, &r);
- if( n<=0 ) break;
- if( z[n]==':' ){
- /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
- ** specified number of hours, minutes, seconds, and fractional seconds
- ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be
- ** omitted.
- */
- const char *z2 = z;
- DateTime tx;
- int day;
- if( !isdigit(*z2) ) z2++;
- memset(&tx, 0, sizeof(tx));
- if( parseHhMmSs(z2, &tx) ) break;
- computeJD(&tx);
- tx.rJD -= 0.5;
- day = (int)tx.rJD;
- tx.rJD -= day;
- if( z[0]=='-' ) tx.rJD = -tx.rJD;
- computeJD(p);
- clearYMD_HMS_TZ(p);
- p->rJD += tx.rJD;
- rc = 0;
- break;
- }
- z += n;
- while( isspace(z[0]) ) z++;
- n = strlen(z);
- if( n>10 || n<3 ) break;
- if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
- computeJD(p);
- rc = 0;
- if( n==3 && strcmp(z,"day")==0 ){
- p->rJD += r;
- }else if( n==4 && strcmp(z,"hour")==0 ){
- p->rJD += r/24.0;
- }else if( n==6 && strcmp(z,"minute")==0 ){
- p->rJD += r/(24.0*60.0);
- }else if( n==6 && strcmp(z,"second")==0 ){
- p->rJD += r/(24.0*60.0*60.0);
- }else if( n==5 && strcmp(z,"month")==0 ){
- int x, y;
- computeYMD_HMS(p);
- p->M += r;
- x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
- p->Y += x;
- p->M -= x*12;
- p->validJD = 0;
- computeJD(p);
- y = r;
- if( y!=r ){
- p->rJD += (r - y)*30.0;
- }
- }else if( n==4 && strcmp(z,"year")==0 ){
- computeYMD_HMS(p);
- p->Y += r;
- p->validJD = 0;
- computeJD(p);
- }else{
- rc = 1;
- }
- clearYMD_HMS_TZ(p);
- break;
- }
- default: {
- break;
- }
- }
- return rc;
-}
-
-/*
-** Process time function arguments. argv[0] is a date-time stamp.
-** argv[1] and following are modifiers. Parse them all and write
-** the resulting time into the DateTime structure p. Return 0
-** on success and 1 if there are any errors.
-*/
-static int isDate(int argc, const char **argv, DateTime *p){
- int i;
- if( argc==0 ) return 1;
- if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1;
- for(i=1; i<argc; i++){
- if( argv[i]==0 || parseModifier(argv[i], p) ) return 1;
- }
- return 0;
-}
-
-
-/*
-** The following routines implement the various date and time functions
-** of SQLite.
-*/
-
-/*
-** julianday( TIMESTRING, MOD, MOD, ...)
-**
-** Return the julian day number of the date specified in the arguments
-*/
-static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
- DateTime x;
- if( isDate(argc, argv, &x)==0 ){
- computeJD(&x);
- sqlite_set_result_double(context, x.rJD);
- }
-}
-
-/*
-** datetime( TIMESTRING, MOD, MOD, ...)
-**
-** Return YYYY-MM-DD HH:MM:SS
-*/
-static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
- DateTime x;
- if( isDate(argc, argv, &x)==0 ){
- char zBuf[100];
- computeYMD_HMS(&x);
- sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
- (int)(x.s));
- sqlite_set_result_string(context, zBuf, -1);
- }
-}
-
-/*
-** time( TIMESTRING, MOD, MOD, ...)
-**
-** Return HH:MM:SS
-*/
-static void timeFunc(sqlite_func *context, int argc, const char **argv){
- DateTime x;
- if( isDate(argc, argv, &x)==0 ){
- char zBuf[100];
- computeHMS(&x);
- sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
- sqlite_set_result_string(context, zBuf, -1);
- }
-}
-
-/*
-** date( TIMESTRING, MOD, MOD, ...)
-**
-** Return YYYY-MM-DD
-*/
-static void dateFunc(sqlite_func *context, int argc, const char **argv){
- DateTime x;
- if( isDate(argc, argv, &x)==0 ){
- char zBuf[100];
- computeYMD(&x);
- sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
- sqlite_set_result_string(context, zBuf, -1);
- }
-}
-
-/*
-** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
-**
-** Return a string described by FORMAT. Conversions as follows:
-**
-** %d day of month
-** %f ** fractional seconds SS.SSS
-** %H hour 00-24
-** %j day of year 000-366
-** %J ** Julian day number
-** %m month 01-12
-** %M minute 00-59
-** %s seconds since 1970-01-01
-** %S seconds 00-59
-** %w day of week 0-6 sunday==0
-** %W week of year 00-53
-** %Y year 0000-9999
-** %% %
-*/
-static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
- DateTime x;
- int n, i, j;
- char *z;
- const char *zFmt = argv[0];
- char zBuf[100];
- if( argv[0]==0 || isDate(argc-1, argv+1, &x) ) return;
- for(i=0, n=1; zFmt[i]; i++, n++){
- if( zFmt[i]=='%' ){
- switch( zFmt[i+1] ){
- case 'd':
- case 'H':
- case 'm':
- case 'M':
- case 'S':
- case 'W':
- n++;
- /* fall thru */
- case 'w':
- case '%':
- break;
- case 'f':
- n += 8;
- break;
- case 'j':
- n += 3;
- break;
- case 'Y':
- n += 8;
- break;
- case 's':
- case 'J':
- n += 50;
- break;
- default:
- return; /* ERROR. return a NULL */
- }
- i++;
- }
- }
- if( n<sizeof(zBuf) ){
- z = zBuf;
- }else{
- z = sqliteMalloc( n );
- if( z==0 ) return;
- }
- computeJD(&x);
- computeYMD_HMS(&x);
- for(i=j=0; zFmt[i]; i++){
- if( zFmt[i]!='%' ){
- z[j++] = zFmt[i];
- }else{
- i++;
- switch( zFmt[i] ){
- case 'd': sprintf(&z[j],"%02d",x.D); j+=2; break;
- case 'f': {
- int s = x.s;
- int ms = (x.s - s)*1000.0;
- sprintf(&z[j],"%02d.%03d",s,ms);
- j += strlen(&z[j]);
- break;
- }
- case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
- case 'W': /* Fall thru */
- case 'j': {
- int n; /* Number of days since 1st day of year */
- DateTime y = x;
- y.validJD = 0;
- y.M = 1;
- y.D = 1;
- computeJD(&y);
- n = x.rJD - y.rJD;
- if( zFmt[i]=='W' ){
- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
- wd = ((int)(x.rJD+0.5)) % 7;
- sprintf(&z[j],"%02d",(n+7-wd)/7);
- j += 2;
- }else{
- sprintf(&z[j],"%03d",n+1);
- j += 3;
- }
- break;
- }
- case 'J': sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
- case 'm': sprintf(&z[j],"%02d",x.M); j+=2; break;
- case 'M': sprintf(&z[j],"%02d",x.m); j+=2; break;
- case 's': {
- sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
- j += strlen(&z[j]);
- break;
- }
- case 'S': sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
- case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
- case 'Y': sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
- case '%': z[j++] = '%'; break;
- }
- }
- }
- z[j] = 0;
- sqlite_set_result_string(context, z, -1);
- if( z!=zBuf ){
- sqliteFree(z);
- }
-}
-
-
-#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
-
-/*
-** This function registered all of the above C functions as SQL
-** functions. This should be the only routine in this file with
-** external linkage.
-*/
-void sqliteRegisterDateTimeFunctions(sqlite *db){
-#ifndef SQLITE_OMIT_DATETIME_FUNCS
- static struct {
- char *zName;
- int nArg;
- int dataType;
- void (*xFunc)(sqlite_func*,int,const char**);
- } aFuncs[] = {
- { "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
- { "date", -1, SQLITE_TEXT, dateFunc },
- { "time", -1, SQLITE_TEXT, timeFunc },
- { "datetime", -1, SQLITE_TEXT, datetimeFunc },
- { "strftime", -1, SQLITE_TEXT, strftimeFunc },
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- sqlite_create_function(db, aFuncs[i].zName,
- aFuncs[i].nArg, aFuncs[i].xFunc, 0);
- if( aFuncs[i].xFunc ){
- sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
- }
- }
-#endif
-}
diff --git a/ext/sqlite/libsqlite/src/delete.c b/ext/sqlite/libsqlite/src/delete.c
deleted file mode 100644
index d83c314c79..0000000000
--- a/ext/sqlite/libsqlite/src/delete.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains C code routines that are called by the parser
-** to handle DELETE FROM statements.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** Look up every table that is named in pSrc. If any table is not found,
-** add an error message to pParse->zErrMsg and return NULL. If all tables
-** are found, return a pointer to the last table.
-*/
-Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
- Table *pTab = 0;
- int i;
- for(i=0; i<pSrc->nSrc; i++){
- const char *zTab = pSrc->a[i].zName;
- const char *zDb = pSrc->a[i].zDatabase;
- pTab = sqliteLocateTable(pParse, zTab, zDb);
- pSrc->a[i].pTab = pTab;
- }
- return pTab;
-}
-
-/*
-** Check to make sure the given table is writable. If it is not
-** writable, generate an error message and return 1. If it is
-** writable return 0;
-*/
-int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- if( pTab->readOnly ){
- sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
- return 1;
- }
- if( !viewOk && pTab->pSelect ){
- sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
- return 1;
- }
- return 0;
-}
-
-/*
-** Process a DELETE FROM statement.
-*/
-void sqliteDeleteFrom(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* The table from which we should delete things */
- Expr *pWhere /* The WHERE clause. May be null */
-){
- Vdbe *v; /* The virtual database engine */
- Table *pTab; /* The table from which records will be deleted */
- const char *zDb; /* Name of database holding pTab */
- int end, addr; /* A couple addresses of generated code */
- int i; /* Loop counter */
- WhereInfo *pWInfo; /* Information about the WHERE clause */
- Index *pIdx; /* For looping over indices of the table */
- int iCur; /* VDBE Cursor number for pTab */
- sqlite *db; /* Main database structure */
- int isView; /* True if attempting to delete from a view */
- AuthContext sContext; /* Authorization context */
-
- int row_triggers_exist = 0; /* True if any triggers exist */
- int before_triggers; /* True if there are BEFORE triggers */
- int after_triggers; /* True if there are AFTER triggers */
- int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
-
- sContext.pParse = 0;
- if( pParse->nErr || sqlite_malloc_failed ){
- pTabList = 0;
- goto delete_from_cleanup;
- }
- db = pParse->db;
- assert( pTabList->nSrc==1 );
-
- /* Locate the table which we want to delete. This table has to be
- ** put in an SrcList structure because some of the subroutines we
- ** will be calling are designed to work with multiple tables and expect
- ** an SrcList* parameter instead of just a Table* parameter.
- */
- pTab = sqliteSrcListLookup(pParse, pTabList);
- if( pTab==0 ) goto delete_from_cleanup;
- before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
- TK_DELETE, TK_BEFORE, TK_ROW, 0);
- after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
- TK_DELETE, TK_AFTER, TK_ROW, 0);
- row_triggers_exist = before_triggers || after_triggers;
- isView = pTab->pSelect!=0;
- if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
- goto delete_from_cleanup;
- }
- assert( pTab->iDb<db->nDb );
- zDb = db->aDb[pTab->iDb].zName;
- if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
- goto delete_from_cleanup;
- }
-
- /* If pTab is really a view, make sure it has been initialized.
- */
- if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
- goto delete_from_cleanup;
- }
-
- /* Allocate a cursor used to store the old.* data for a trigger.
- */
- if( row_triggers_exist ){
- oldIdx = pParse->nTab++;
- }
-
- /* Resolve the column names in all the expressions.
- */
- assert( pTabList->nSrc==1 );
- iCur = pTabList->a[0].iCursor = pParse->nTab++;
- if( pWhere ){
- if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
- goto delete_from_cleanup;
- }
- if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
- goto delete_from_cleanup;
- }
- }
-
- /* Start the view context
- */
- if( isView ){
- sqliteAuthContextPush(pParse, &sContext, pTab->zName);
- }
-
- /* Begin generating code.
- */
- v = sqliteGetVdbe(pParse);
- if( v==0 ){
- goto delete_from_cleanup;
- }
- sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
-
- /* If we are trying to delete from a view, construct that view into
- ** a temporary table.
- */
- if( isView ){
- Select *pView = sqliteSelectDup(pTab->pSelect);
- sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
- sqliteSelectDelete(pView);
- }
-
- /* Initialize the counter of the number of rows deleted, if
- ** we are counting rows.
- */
- if( db->flags & SQLITE_CountRows ){
- sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- }
-
- /* Special case: A DELETE without a WHERE clause deletes everything.
- ** It is easier just to erase the whole table. Note, however, that
- ** this means that the row change count will be incorrect.
- */
- if( pWhere==0 && !row_triggers_exist ){
- if( db->flags & SQLITE_CountRows ){
- /* If counting rows deleted, just count the total number of
- ** entries in the table. */
- int endOfLoop = sqliteVdbeMakeLabel(v);
- int addr;
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
- }
- sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
- addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
- sqliteVdbeAddOp(v, OP_Next, iCur, addr);
- sqliteVdbeResolveLabel(v, endOfLoop);
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- }
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
- }
- }
- }
-
- /* The usual case: There is a WHERE clause so we have to scan through
- ** the table and pick which records to delete.
- */
- else{
- /* Begin the database scan
- */
- pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
- if( pWInfo==0 ) goto delete_from_cleanup;
-
- /* Remember the key of every item to be deleted.
- */
- sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
- if( db->flags & SQLITE_CountRows ){
- sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
- }
-
- /* End the database scan loop.
- */
- sqliteWhereEnd(pWInfo);
-
- /* Open the pseudo-table used to store OLD if there are triggers.
- */
- if( row_triggers_exist ){
- sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
- }
-
- /* Delete every item whose key was written to the list during the
- ** database scan. We have to delete items after the scan is complete
- ** because deleting an item can change the scan order.
- */
- sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
- end = sqliteVdbeMakeLabel(v);
-
- /* This is the beginning of the delete loop when there are
- ** row triggers.
- */
- if( row_triggers_exist ){
- addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
- }
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
-
- sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
- sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- }
-
- sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
- oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
- addr);
- }
-
- if( !isView ){
- /* Open cursors for the table we are deleting from and all its
- ** indices. If there are row triggers, this happens inside the
- ** OP_ListRead loop because the cursor have to all be closed
- ** before the trigger fires. If there are no row triggers, the
- ** cursors are opened only once on the outside the loop.
- */
- pParse->nTab = iCur + 1;
- sqliteOpenTableAndIndices(pParse, pTab, iCur);
-
- /* This is the beginning of the delete loop when there are no
- ** row triggers */
- if( !row_triggers_exist ){
- addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
- }
-
- /* Delete the row */
- sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
- }
-
- /* If there are row triggers, close all cursors then invoke
- ** the AFTER triggers
- */
- if( row_triggers_exist ){
- if( !isView ){
- for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
- }
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- }
- sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
- oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
- addr);
- }
-
- /* End of the delete loop */
- sqliteVdbeAddOp(v, OP_Goto, 0, addr);
- sqliteVdbeResolveLabel(v, end);
- sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
-
- /* Close the cursors after the loop if there are no row triggers */
- if( !row_triggers_exist ){
- for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
- }
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- pParse->nTab = iCur;
- }
- }
- sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
- sqliteEndWriteOperation(pParse);
-
- /*
- ** Return the number of rows that were deleted.
- */
- if( db->flags & SQLITE_CountRows ){
- sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
- sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
- sqliteVdbeAddOp(v, OP_Callback, 1, 0);
- }
-
-delete_from_cleanup:
- sqliteAuthContextPop(&sContext);
- sqliteSrcListDelete(pTabList);
- sqliteExprDelete(pWhere);
- return;
-}
-
-/*
-** This routine generates VDBE code that causes a single row of a
-** single table to be deleted.
-**
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
-**
-** 1. A read/write cursor pointing to pTab, the table containing the row
-** to be deleted, must be opened as cursor number "base".
-**
-** 2. Read/write cursors for all indices of pTab must be open as
-** cursor number base+i for the i-th index.
-**
-** 3. The record number of the row to be deleted must be on the top
-** of the stack.
-**
-** This routine pops the top of the stack to remove the record number
-** and then generates code to remove both the table record and all index
-** entries that point to that record.
-*/
-void sqliteGenerateRowDelete(
- sqlite *db, /* The database containing the index */
- Vdbe *v, /* Generate code into this VDBE */
- Table *pTab, /* Table containing the row to be deleted */
- int iCur, /* Cursor number for the table */
- int count /* Increment the row change counter */
-){
- int addr;
- addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
- sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
- sqliteVdbeAddOp(v, OP_Delete, iCur,
- (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
- sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
-}
-
-/*
-** This routine generates VDBE code that causes the deletion of all
-** index entries associated with a single row of a single table.
-**
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
-**
-** 1. A read/write cursor pointing to pTab, the table containing the row
-** to be deleted, must be opened as cursor number "iCur".
-**
-** 2. Read/write cursors for all indices of pTab must be open as
-** cursor number iCur+i for the i-th index.
-**
-** 3. The "iCur" cursor must be pointing to the row that is to be
-** deleted.
-*/
-void sqliteGenerateRowIndexDelete(
- sqlite *db, /* The database containing the index */
- Vdbe *v, /* Generate code into this VDBE */
- Table *pTab, /* Table containing the row to be deleted */
- int iCur, /* Cursor number for the table */
- char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
-){
- int i;
- Index *pIdx;
-
- for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- int j;
- if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
- sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
- for(j=0; j<pIdx->nColumn; j++){
- int idx = pIdx->aiColumn[j];
- if( idx==pTab->iPKey ){
- sqliteVdbeAddOp(v, OP_Dup, j, 0);
- }else{
- sqliteVdbeAddOp(v, OP_Column, iCur, idx);
- }
- }
- sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
- if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
- sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
- }
-}
diff --git a/ext/sqlite/libsqlite/src/encode.c b/ext/sqlite/libsqlite/src/encode.c
deleted file mode 100644
index 6318477857..0000000000
--- a/ext/sqlite/libsqlite/src/encode.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
-** 2002 April 25
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains helper routines used to translate binary data into
-** a null-terminated string (suitable for use in SQLite) and back again.
-** These are convenience routines for use by people who want to store binary
-** data in an SQLite database. The code in this file is not used by any other
-** part of the SQLite library.
-**
-** $Id$
-*/
-#include <string.h>
-#include <assert.h>
-
-/*
-** How This Encoder Works
-**
-** The output is allowed to contain any character except 0x27 (') and
-** 0x00. This is accomplished by using an escape character to encode
-** 0x27 and 0x00 as a two-byte sequence. The escape character is always
-** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The
-** 0x27 character is encoded as the two byte sequence 0x01 0x28. Finally,
-** the escape character itself is encoded as the two-character sequence
-** 0x01 0x02.
-**
-** To summarize, the encoder works by using an escape sequences as follows:
-**
-** 0x00 -> 0x01 0x01
-** 0x01 -> 0x01 0x02
-** 0x27 -> 0x01 0x28
-**
-** If that were all the encoder did, it would work, but in certain cases
-** it could double the size of the encoded string. For example, to
-** encode a string of 100 0x27 characters would require 100 instances of
-** the 0x01 0x03 escape sequence resulting in a 200-character output.
-** We would prefer to keep the size of the encoded string smaller than
-** this.
-**
-** To minimize the encoding size, we first add a fixed offset value to each
-** byte in the sequence. The addition is modulo 256. (That is to say, if
-** the sum of the original character value and the offset exceeds 256, then
-** the higher order bits are truncated.) The offset is chosen to minimize
-** the number of characters in the string that need to be escaped. For
-** example, in the case above where the string was composed of 100 0x27
-** characters, the offset might be 0x01. Each of the 0x27 characters would
-** then be converted into an 0x28 character which would not need to be
-** escaped at all and so the 100 character input string would be converted
-** into just 100 characters of output. Actually 101 characters of output -
-** we have to record the offset used as the first byte in the sequence so
-** that the string can be decoded. Since the offset value is stored as
-** part of the output string and the output string is not allowed to contain
-** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27.
-**
-** Here, then, are the encoding steps:
-**
-** (1) Choose an offset value and make it the first character of
-** output.
-**
-** (2) Copy each input character into the output buffer, one by
-** one, adding the offset value as you copy.
-**
-** (3) If the value of an input character plus offset is 0x00, replace
-** that one character by the two-character sequence 0x01 0x01.
-** If the sum is 0x01, replace it with 0x01 0x02. If the sum
-** is 0x27, replace it with 0x01 0x03.
-**
-** (4) Put a 0x00 terminator at the end of the output.
-**
-** Decoding is obvious:
-**
-** (5) Copy encoded characters except the first into the decode
-** buffer. Set the first encoded character aside for use as
-** the offset in step 7 below.
-**
-** (6) Convert each 0x01 0x01 sequence into a single character 0x00.
-** Convert 0x01 0x02 into 0x01. Convert 0x01 0x28 into 0x27.
-**
-** (7) Subtract the offset value that was the first character of
-** the encoded buffer from all characters in the output buffer.
-**
-** The only tricky part is step (1) - how to compute an offset value to
-** minimize the size of the output buffer. This is accomplished by testing
-** all offset values and picking the one that results in the fewest number
-** of escapes. To do that, we first scan the entire input and count the
-** number of occurances of each character value in the input. Suppose
-** the number of 0x00 characters is N(0), the number of occurances of 0x01
-** is N(1), and so forth up to the number of occurances of 0xff is N(255).
-** An offset of 0 is not allowed so we don't have to test it. The number
-** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number
-** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth.
-** In this way we find the offset that gives the minimum number of escapes,
-** and thus minimizes the length of the output string.
-*/
-
-/*
-** Encode a binary buffer "in" of size n bytes so that it contains
-** no instances of characters '\'' or '\000'. The output is
-** null-terminated and can be used as a string value in an INSERT
-** or UPDATE statement. Use sqlite_decode_binary() to convert the
-** string back into its original binary.
-**
-** The result is written into a preallocated output buffer "out".
-** "out" must be able to hold at least 2 +(257*n)/254 bytes.
-** In other words, the output will be expanded by as much as 3
-** bytes for every 254 bytes of input plus 2 bytes of fixed overhead.
-** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.)
-**
-** The return value is the number of characters in the encoded
-** string, excluding the "\000" terminator.
-**
-** If out==NULL then no output is generated but the routine still returns
-** the number of characters that would have been generated if out had
-** not been NULL.
-*/
-int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
- int i, j, e, m;
- unsigned char x;
- int cnt[256];
- if( n<=0 ){
- if( out ){
- out[0] = 'x';
- out[1] = 0;
- }
- return 1;
- }
- memset(cnt, 0, sizeof(cnt));
- for(i=n-1; i>=0; i--){ cnt[in[i]]++; }
- m = n;
- for(i=1; i<256; i++){
- int sum;
- if( i=='\'' ) continue;
- sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff];
- if( sum<m ){
- m = sum;
- e = i;
- if( m==0 ) break;
- }
- }
- if( out==0 ){
- return n+m+1;
- }
- out[0] = e;
- j = 1;
- for(i=0; i<n; i++){
- x = in[i] - e;
- if( x==0 || x==1 || x=='\''){
- out[j++] = 1;
- x++;
- }
- out[j++] = x;
- }
- out[j] = 0;
- assert( j==n+m+1 );
- return j;
-}
-
-/*
-** Decode the string "in" into binary data and write it into "out".
-** This routine reverses the encoding created by sqlite_encode_binary().
-** The output will always be a few bytes less than the input. The number
-** of bytes of output is returned. If the input is not a well-formed
-** encoding, -1 is returned.
-**
-** The "in" and "out" parameters may point to the same buffer in order
-** to decode a string in place.
-*/
-int sqlite_decode_binary(const unsigned char *in, unsigned char *out){
- int i, e;
- unsigned char c;
- e = *(in++);
- if (e == 0) {
- return 0;
- }
- i = 0;
- while( (c = *(in++))!=0 ){
- if (c == 1) {
- c = *(in++) - 1;
- }
- out[i++] = c + e;
- }
- return i;
-}
-
-#ifdef ENCODER_TEST
-#include <stdio.h>
-/*
-** The subroutines above are not tested by the usual test suite. To test
-** these routines, compile just this one file with a -DENCODER_TEST=1 option
-** and run the result.
-*/
-int main(int argc, char **argv){
- int i, j, n, m, nOut, nByteIn, nByteOut;
- unsigned char in[30000];
- unsigned char out[33000];
-
- nByteIn = nByteOut = 0;
- for(i=0; i<sizeof(in); i++){
- printf("Test %d: ", i+1);
- n = rand() % (i+1);
- if( i%100==0 ){
- int k;
- for(j=k=0; j<n; j++){
- /* if( k==0 || k=='\'' ) k++; */
- in[j] = k;
- k = (k+1)&0xff;
- }
- }else{
- for(j=0; j<n; j++) in[j] = rand() & 0xff;
- }
- nByteIn += n;
- nOut = sqlite_encode_binary(in, n, out);
- nByteOut += nOut;
- if( nOut!=strlen(out) ){
- printf(" ERROR return value is %d instead of %d\n", nOut, strlen(out));
- exit(1);
- }
- if( nOut!=sqlite_encode_binary(in, n, 0) ){
- printf(" ERROR actual output size disagrees with predicted size\n");
- exit(1);
- }
- m = (256*n + 1262)/253;
- printf("size %d->%d (max %d)", n, strlen(out)+1, m);
- if( strlen(out)+1>m ){
- printf(" ERROR output too big\n");
- exit(1);
- }
- for(j=0; out[j]; j++){
- if( out[j]=='\'' ){
- printf(" ERROR contains (')\n");
- exit(1);
- }
- }
- j = sqlite_decode_binary(out, out);
- if( j!=n ){
- printf(" ERROR decode size %d\n", j);
- exit(1);
- }
- if( memcmp(in, out, n)!=0 ){
- printf(" ERROR decode mismatch\n");
- exit(1);
- }
- printf(" OK\n");
- }
- fprintf(stderr,"Finished. Total encoding: %d->%d bytes\n",
- nByteIn, nByteOut);
- fprintf(stderr,"Avg size increase: %.3f%%\n",
- (nByteOut-nByteIn)*100.0/(double)nByteIn);
-}
-#endif /* ENCODER_TEST */
diff --git a/ext/sqlite/libsqlite/src/expr.c b/ext/sqlite/libsqlite/src/expr.c
deleted file mode 100644
index 86346fa5d9..0000000000
--- a/ext/sqlite/libsqlite/src/expr.c
+++ /dev/null
@@ -1,1662 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains routines used for analyzing expressions and
-** for generating VDBE code that evaluates expressions in SQLite.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include <ctype.h>
-
-/*
-** Construct a new expression node and return a pointer to it. Memory
-** for this node is obtained from sqliteMalloc(). The calling function
-** is responsible for making sure the node eventually gets freed.
-*/
-Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
- Expr *pNew;
- pNew = sqliteMalloc( sizeof(Expr) );
- if( pNew==0 ){
- /* When malloc fails, we leak memory from pLeft and pRight */
- return 0;
- }
- pNew->op = op;
- pNew->pLeft = pLeft;
- pNew->pRight = pRight;
- if( pToken ){
- assert( pToken->dyn==0 );
- pNew->token = *pToken;
- pNew->span = *pToken;
- }else{
- assert( pNew->token.dyn==0 );
- assert( pNew->token.z==0 );
- assert( pNew->token.n==0 );
- if( pLeft && pRight ){
- sqliteExprSpan(pNew, &pLeft->span, &pRight->span);
- }else{
- pNew->span = pNew->token;
- }
- }
- return pNew;
-}
-
-/*
-** Set the Expr.span field of the given expression to span all
-** text between the two given tokens.
-*/
-void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
- assert( pRight!=0 );
- assert( pLeft!=0 );
- /* Note: pExpr might be NULL due to a prior malloc failure */
- if( pExpr && pRight->z && pLeft->z ){
- if( pLeft->dyn==0 && pRight->dyn==0 ){
- pExpr->span.z = pLeft->z;
- pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
- }else{
- pExpr->span.z = 0;
- }
- }
-}
-
-/*
-** Construct a new expression node for a function with multiple
-** arguments.
-*/
-Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
- Expr *pNew;
- pNew = sqliteMalloc( sizeof(Expr) );
- if( pNew==0 ){
- /* sqliteExprListDelete(pList); // Leak pList when malloc fails */
- return 0;
- }
- pNew->op = TK_FUNCTION;
- pNew->pList = pList;
- if( pToken ){
- assert( pToken->dyn==0 );
- pNew->token = *pToken;
- }else{
- pNew->token.z = 0;
- }
- pNew->span = pNew->token;
- return pNew;
-}
-
-/*
-** Recursively delete an expression tree.
-*/
-void sqliteExprDelete(Expr *p){
- if( p==0 ) return;
- if( p->span.dyn ) sqliteFree((char*)p->span.z);
- if( p->token.dyn ) sqliteFree((char*)p->token.z);
- sqliteExprDelete(p->pLeft);
- sqliteExprDelete(p->pRight);
- sqliteExprListDelete(p->pList);
- sqliteSelectDelete(p->pSelect);
- sqliteFree(p);
-}
-
-
-/*
-** The following group of routines make deep copies of expressions,
-** expression lists, ID lists, and select statements. The copies can
-** be deleted (by being passed to their respective ...Delete() routines)
-** without effecting the originals.
-**
-** The expression list, ID, and source lists return by sqliteExprListDup(),
-** sqliteIdListDup(), and sqliteSrcListDup() can not be further expanded
-** by subsequent calls to sqlite*ListAppend() routines.
-**
-** Any tables that the SrcList might point to are not duplicated.
-*/
-Expr *sqliteExprDup(Expr *p){
- Expr *pNew;
- if( p==0 ) return 0;
- pNew = sqliteMallocRaw( sizeof(*p) );
- if( pNew==0 ) return 0;
- memcpy(pNew, p, sizeof(*pNew));
- if( p->token.z!=0 ){
- pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
- pNew->token.dyn = 1;
- }else{
- assert( pNew->token.z==0 );
- }
- pNew->span.z = 0;
- pNew->pLeft = sqliteExprDup(p->pLeft);
- pNew->pRight = sqliteExprDup(p->pRight);
- pNew->pList = sqliteExprListDup(p->pList);
- pNew->pSelect = sqliteSelectDup(p->pSelect);
- return pNew;
-}
-void sqliteTokenCopy(Token *pTo, Token *pFrom){
- if( pTo->dyn ) sqliteFree((char*)pTo->z);
- if( pFrom->z ){
- pTo->n = pFrom->n;
- pTo->z = sqliteStrNDup(pFrom->z, pFrom->n);
- pTo->dyn = 1;
- }else{
- pTo->z = 0;
- }
-}
-ExprList *sqliteExprListDup(ExprList *p){
- ExprList *pNew;
- struct ExprList_item *pItem;
- int i;
- if( p==0 ) return 0;
- pNew = sqliteMalloc( sizeof(*pNew) );
- if( pNew==0 ) return 0;
- pNew->nExpr = pNew->nAlloc = p->nExpr;
- pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
- if( pItem==0 ){
- sqliteFree(pNew);
- return 0;
- }
- for(i=0; i<p->nExpr; i++, pItem++){
- Expr *pNewExpr, *pOldExpr;
- pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr);
- if( pOldExpr->span.z!=0 && pNewExpr ){
- /* Always make a copy of the span for top-level expressions in the
- ** expression list. The logic in SELECT processing that determines
- ** the names of columns in the result set needs this information */
- sqliteTokenCopy(&pNewExpr->span, &pOldExpr->span);
- }
- assert( pNewExpr==0 || pNewExpr->span.z!=0
- || pOldExpr->span.z==0 || sqlite_malloc_failed );
- pItem->zName = sqliteStrDup(p->a[i].zName);
- pItem->sortOrder = p->a[i].sortOrder;
- pItem->isAgg = p->a[i].isAgg;
- pItem->done = 0;
- }
- return pNew;
-}
-SrcList *sqliteSrcListDup(SrcList *p){
- SrcList *pNew;
- int i;
- int nByte;
- if( p==0 ) return 0;
- nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
- pNew = sqliteMallocRaw( nByte );
- if( pNew==0 ) return 0;
- pNew->nSrc = pNew->nAlloc = p->nSrc;
- for(i=0; i<p->nSrc; i++){
- struct SrcList_item *pNewItem = &pNew->a[i];
- struct SrcList_item *pOldItem = &p->a[i];
- pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
- pNewItem->zName = sqliteStrDup(pOldItem->zName);
- pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
- pNewItem->jointype = pOldItem->jointype;
- pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->pTab = 0;
- pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect);
- pNewItem->pOn = sqliteExprDup(pOldItem->pOn);
- pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing);
- }
- return pNew;
-}
-IdList *sqliteIdListDup(IdList *p){
- IdList *pNew;
- int i;
- if( p==0 ) return 0;
- pNew = sqliteMallocRaw( sizeof(*pNew) );
- if( pNew==0 ) return 0;
- pNew->nId = pNew->nAlloc = p->nId;
- pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) );
- if( pNew->a==0 ) return 0;
- for(i=0; i<p->nId; i++){
- struct IdList_item *pNewItem = &pNew->a[i];
- struct IdList_item *pOldItem = &p->a[i];
- pNewItem->zName = sqliteStrDup(pOldItem->zName);
- pNewItem->idx = pOldItem->idx;
- }
- return pNew;
-}
-Select *sqliteSelectDup(Select *p){
- Select *pNew;
- if( p==0 ) return 0;
- pNew = sqliteMallocRaw( sizeof(*p) );
- if( pNew==0 ) return 0;
- pNew->isDistinct = p->isDistinct;
- pNew->pEList = sqliteExprListDup(p->pEList);
- pNew->pSrc = sqliteSrcListDup(p->pSrc);
- pNew->pWhere = sqliteExprDup(p->pWhere);
- pNew->pGroupBy = sqliteExprListDup(p->pGroupBy);
- pNew->pHaving = sqliteExprDup(p->pHaving);
- pNew->pOrderBy = sqliteExprListDup(p->pOrderBy);
- pNew->op = p->op;
- pNew->pPrior = sqliteSelectDup(p->pPrior);
- pNew->nLimit = p->nLimit;
- pNew->nOffset = p->nOffset;
- pNew->zSelect = 0;
- pNew->iLimit = -1;
- pNew->iOffset = -1;
- return pNew;
-}
-
-
-/*
-** Add a new element to the end of an expression list. If pList is
-** initially NULL, then create a new expression list.
-*/
-ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
- if( pList==0 ){
- pList = sqliteMalloc( sizeof(ExprList) );
- if( pList==0 ){
- /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
- return 0;
- }
- assert( pList->nAlloc==0 );
- }
- if( pList->nAlloc<=pList->nExpr ){
- pList->nAlloc = pList->nAlloc*2 + 4;
- pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
- if( pList->a==0 ){
- /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
- pList->nExpr = pList->nAlloc = 0;
- return pList;
- }
- }
- assert( pList->a!=0 );
- if( pExpr || pName ){
- struct ExprList_item *pItem = &pList->a[pList->nExpr++];
- memset(pItem, 0, sizeof(*pItem));
- pItem->pExpr = pExpr;
- if( pName ){
- sqliteSetNString(&pItem->zName, pName->z, pName->n, 0);
- sqliteDequote(pItem->zName);
- }
- }
- return pList;
-}
-
-/*
-** Delete an entire expression list.
-*/
-void sqliteExprListDelete(ExprList *pList){
- int i;
- if( pList==0 ) return;
- assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
- assert( pList->nExpr<=pList->nAlloc );
- for(i=0; i<pList->nExpr; i++){
- sqliteExprDelete(pList->a[i].pExpr);
- sqliteFree(pList->a[i].zName);
- }
- sqliteFree(pList->a);
- sqliteFree(pList);
-}
-
-/*
-** Walk an expression tree. Return 1 if the expression is constant
-** and 0 if it involves variables.
-**
-** For the purposes of this function, a double-quoted string (ex: "abc")
-** is considered a variable but a single-quoted string (ex: 'abc') is
-** a constant.
-*/
-int sqliteExprIsConstant(Expr *p){
- switch( p->op ){
- case TK_ID:
- case TK_COLUMN:
- case TK_DOT:
- case TK_FUNCTION:
- return 0;
- case TK_NULL:
- case TK_STRING:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_VARIABLE:
- return 1;
- default: {
- if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0;
- if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0;
- if( p->pList ){
- int i;
- for(i=0; i<p->pList->nExpr; i++){
- if( !sqliteExprIsConstant(p->pList->a[i].pExpr) ) return 0;
- }
- }
- return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
- }
- }
- return 0;
-}
-
-/*
-** If the given expression codes a constant integer that is small enough
-** to fit in a 32-bit integer, return 1 and put the value of the integer
-** in *pValue. If the expression is not an integer or if it is too big
-** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
-*/
-int sqliteExprIsInteger(Expr *p, int *pValue){
- switch( p->op ){
- case TK_INTEGER: {
- if( sqliteFitsIn32Bits(p->token.z) ){
- *pValue = atoi(p->token.z);
- return 1;
- }
- break;
- }
- case TK_STRING: {
- const char *z = p->token.z;
- int n = p->token.n;
- if( n>0 && z[0]=='-' ){ z++; n--; }
- while( n>0 && *z && isdigit(*z) ){ z++; n--; }
- if( n==0 && sqliteFitsIn32Bits(p->token.z) ){
- *pValue = atoi(p->token.z);
- return 1;
- }
- break;
- }
- case TK_UPLUS: {
- return sqliteExprIsInteger(p->pLeft, pValue);
- }
- case TK_UMINUS: {
- int v;
- if( sqliteExprIsInteger(p->pLeft, &v) ){
- *pValue = -v;
- return 1;
- }
- break;
- }
- default: break;
- }
- return 0;
-}
-
-/*
-** Return TRUE if the given string is a row-id column name.
-*/
-int sqliteIsRowid(const char *z){
- if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1;
- if( sqliteStrICmp(z, "ROWID")==0 ) return 1;
- if( sqliteStrICmp(z, "OID")==0 ) return 1;
- return 0;
-}
-
-/*
-** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
-** expression node refer back to that source column. The following changes
-** are made to pExpr:
-**
-** pExpr->iDb Set the index in db->aDb[] of the database holding
-** the table.
-** pExpr->iTable Set to the cursor number for the table obtained
-** from pSrcList.
-** pExpr->iColumn Set to the column number within the table.
-** pExpr->dataType Set to the appropriate data type for the column.
-** pExpr->op Set to TK_COLUMN.
-** pExpr->pLeft Any expression this points to is deleted
-** pExpr->pRight Any expression this points to is deleted.
-**
-** The pDbToken is the name of the database (the "X"). This value may be
-** NULL meaning that name is of the form Y.Z or Z. Any available database
-** can be used. The pTableToken is the name of the table (the "Y"). This
-** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
-** means that the form of the name is Z and that columns from any table
-** can be used.
-**
-** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return non-zero. Return zero on success.
-*/
-static int lookupName(
- Parse *pParse, /* The parsing context */
- Token *pDbToken, /* Name of the database containing table, or NULL */
- Token *pTableToken, /* Name of table containing column, or NULL */
- Token *pColumnToken, /* Name of the column. */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
- Expr *pExpr /* Make this EXPR node point to the selected column */
-){
- char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
- char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
- char *zCol = 0; /* Name of the column. The "Z" */
- int i, j; /* Loop counters */
- int cnt = 0; /* Number of matching column names */
- int cntTab = 0; /* Number of matching table names */
- sqlite *db = pParse->db; /* The database */
-
- assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
- if( pDbToken && pDbToken->z ){
- zDb = sqliteStrNDup(pDbToken->z, pDbToken->n);
- sqliteDequote(zDb);
- }else{
- zDb = 0;
- }
- if( pTableToken && pTableToken->z ){
- zTab = sqliteStrNDup(pTableToken->z, pTableToken->n);
- sqliteDequote(zTab);
- }else{
- assert( zDb==0 );
- zTab = 0;
- }
- zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n);
- sqliteDequote(zCol);
- if( sqlite_malloc_failed ){
- return 1; /* Leak memory (zDb and zTab) if malloc fails */
- }
- assert( zTab==0 || pEList==0 );
-
- pExpr->iTable = -1;
- for(i=0; i<pSrcList->nSrc; i++){
- struct SrcList_item *pItem = &pSrcList->a[i];
- Table *pTab = pItem->pTab;
- Column *pCol;
-
- if( pTab==0 ) continue;
- assert( pTab->nCol>0 );
- if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqliteStrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue;
- if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
- continue;
- }
- }
- }
- if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pExpr->iDb = pTab->iDb;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqliteStrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iTable = pItem->iCursor;
- pExpr->iDb = pTab->iDb;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
- break;
- }
- }
- }
-
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference
- */
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- Table *pTab = 0;
- if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- }
-
- if( pTab ){
- int j;
- Column *pCol = pTab->aCol;
-
- pExpr->iDb = pTab->iDb;
- cntTab++;
- for(j=0; j < pTab->nCol; j++, pCol++) {
- if( sqliteStrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
- break;
- }
- }
- }
- }
-
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->dataType = SQLITE_SO_NUM;
- }
-
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- */
- if( cnt==0 && pEList!=0 ){
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- pExpr->op = TK_AS;
- pExpr->iColumn = j;
- pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr);
- sqliteFree(zCol);
- assert( zTab==0 && zDb==0 );
- return 0;
- }
- }
- }
-
- /*
- ** If X and Y are NULL (in other words if only the column name Z is
- ** supplied) and the value of Z is enclosed in double-quotes, then
- ** Z is a string literal if it doesn't match any column names. In that
- ** case, we need to return right away and not make any changes to
- ** pExpr.
- */
- if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
- sqliteFree(zCol);
- return 0;
- }
-
- /*
- ** cnt==0 means there was not match. cnt>1 means there were two or
- ** more matches. Either way, we have an error.
- */
- if( cnt!=1 ){
- char *z = 0;
- char *zErr;
- zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s";
- if( zDb ){
- sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0);
- }else if( zTab ){
- sqliteSetString(&z, zTab, ".", zCol, 0);
- }else{
- z = sqliteStrDup(zCol);
- }
- sqliteErrorMsg(pParse, zErr, z);
- sqliteFree(z);
- }
-
- /* Clean up and return
- */
- sqliteFree(zDb);
- sqliteFree(zTab);
- sqliteFree(zCol);
- sqliteExprDelete(pExpr->pLeft);
- pExpr->pLeft = 0;
- sqliteExprDelete(pExpr->pRight);
- pExpr->pRight = 0;
- pExpr->op = TK_COLUMN;
- sqliteAuthRead(pParse, pExpr, pSrcList);
- return cnt!=1;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns. Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset. The
-** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value. The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table. The Expr.iColumn value is changed to the index of the column
-** of the referenced table. The Expr.iColumn value for the special
-** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** We also check for instances of the IN operator. IN comes in two
-** forms:
-**
-** expr IN (exprlist)
-** and
-** expr IN (SELECT ...)
-**
-** The first form is handled by creating a set holding the list
-** of allowed values. The second form causes the SELECT to generate
-** a temporary table.
-**
-** This routine also looks for scalar SELECTs that are part of an expression.
-** If it finds any, it generates code to write the value of that select
-** into a memory cell.
-**
-** Unknown columns or tables provoke an error. The function returns
-** the number of errors seen and leaves an error message on pParse->zErrMsg.
-*/
-int sqliteExprResolveIds(
- Parse *pParse, /* The parser context */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
- Expr *pExpr /* The expression to be analyzed. */
-){
- int i;
-
- if( pExpr==0 || pSrcList==0 ) return 0;
- for(i=0; i<pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab );
- }
- switch( pExpr->op ){
- /* Double-quoted strings (ex: "abc") are used as identifiers if
- ** possible. Otherwise they remain as strings. Single-quoted
- ** strings (ex: 'abc') are always string literals.
- */
- case TK_STRING: {
- if( pExpr->token.z[0]=='\'' ) break;
- /* Fall thru into the TK_ID case if this is a double-quoted string */
- }
- /* A lone identifier is the name of a columnd.
- */
- case TK_ID: {
- if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
- return 1;
- }
- break;
- }
-
- /* A table name and column name: ID.ID
- ** Or a database, table and column: ID.ID.ID
- */
- case TK_DOT: {
- Token *pColumn;
- Token *pTable;
- Token *pDb;
- Expr *pRight;
-
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
- pDb = 0;
- pTable = &pExpr->pLeft->token;
- pColumn = &pRight->token;
- }else{
- assert( pRight->op==TK_DOT );
- pDb = &pExpr->pLeft->token;
- pTable = &pRight->pLeft->token;
- pColumn = &pRight->pRight->token;
- }
- if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
- return 1;
- }
- break;
- }
-
- case TK_IN: {
- Vdbe *v = sqliteGetVdbe(pParse);
- if( v==0 ) return 1;
- if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
- return 1;
- }
- if( pExpr->pSelect ){
- /* Case 1: expr IN (SELECT ...)
- **
- ** Generate code to write the results of the select into a temporary
- ** table. The cursor number of the temporary table has already
- ** been put in iTable by sqliteExprResolveInSelect().
- */
- pExpr->iTable = pParse->nTab++;
- sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1);
- sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0);
- }else if( pExpr->pList ){
- /* Case 2: expr IN (exprlist)
- **
- ** Create a set to put the exprlist values in. The Set id is stored
- ** in iTable.
- */
- int i, iSet;
- for(i=0; i<pExpr->pList->nExpr; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
- if( !sqliteExprIsConstant(pE2) ){
- sqliteErrorMsg(pParse,
- "right-hand side of IN operator must be constant");
- return 1;
- }
- if( sqliteExprCheck(pParse, pE2, 0, 0) ){
- return 1;
- }
- }
- iSet = pExpr->iTable = pParse->nSet++;
- for(i=0; i<pExpr->pList->nExpr; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
- switch( pE2->op ){
- case TK_FLOAT:
- case TK_INTEGER:
- case TK_STRING: {
- int addr;
- assert( pE2->token.z );
- addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0,
- pE2->token.z, pE2->token.n);
- sqliteVdbeDequoteP3(v, addr);
- break;
- }
- default: {
- sqliteExprCode(pParse, pE2);
- sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0);
- break;
- }
- }
- }
- }
- break;
- }
-
- case TK_SELECT: {
- /* This has to be a scalar SELECT. Generate code to put the
- ** value of this select in a memory cell and record the number
- ** of the memory cell in iColumn.
- */
- pExpr->iColumn = pParse->nMem++;
- if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){
- return 1;
- }
- break;
- }
-
- /* For all else, just recursively walk the tree */
- default: {
- if( pExpr->pLeft
- && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
- return 1;
- }
- if( pExpr->pRight
- && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
- return 1;
- }
- if( pExpr->pList ){
- int i;
- ExprList *pList = pExpr->pList;
- for(i=0; i<pList->nExpr; i++){
- Expr *pArg = pList->a[i].pExpr;
- if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){
- return 1;
- }
- }
- }
- }
- }
- return 0;
-}
-
-/*
-** pExpr is a node that defines a function of some kind. It might
-** be a syntactic function like "count(x)" or it might be a function
-** that implements an operator, like "a LIKE b".
-**
-** This routine makes *pzName point to the name of the function and
-** *pnName hold the number of characters in the function name.
-*/
-static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
- switch( pExpr->op ){
- case TK_FUNCTION: {
- *pzName = pExpr->token.z;
- *pnName = pExpr->token.n;
- break;
- }
- case TK_LIKE: {
- *pzName = "like";
- *pnName = 4;
- break;
- }
- case TK_GLOB: {
- *pzName = "glob";
- *pnName = 4;
- break;
- }
- default: {
- *pzName = "can't happen";
- *pnName = 12;
- break;
- }
- }
-}
-
-/*
-** Error check the functions in an expression. Make sure all
-** function names are recognized and all functions have the correct
-** number of arguments. Leave an error message in pParse->zErrMsg
-** if anything is amiss. Return the number of errors.
-**
-** if pIsAgg is not null and this expression is an aggregate function
-** (like count(*) or max(value)) then write a 1 into *pIsAgg.
-*/
-int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
- int nErr = 0;
- if( pExpr==0 ) return 0;
- switch( pExpr->op ){
- case TK_GLOB:
- case TK_LIKE:
- case TK_FUNCTION: {
- int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */
- int no_such_func = 0; /* True if no such function exists */
- int wrong_num_args = 0; /* True if wrong number of arguments */
- int is_agg = 0; /* True if is an aggregate function */
- int i;
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef;
-
- getFunctionName(pExpr, &zId, &nId);
- pDef = sqliteFindFunction(pParse->db, zId, nId, n, 0);
- if( pDef==0 ){
- pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
- }else{
- is_agg = pDef->xFunc==0;
- }
- if( is_agg && !allowAgg ){
- sqliteErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
- nErr++;
- is_agg = 0;
- }else if( no_such_func ){
- sqliteErrorMsg(pParse, "no such function: %.*s", nId, zId);
- nErr++;
- }else if( wrong_num_args ){
- sqliteErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- nErr++;
- }
- if( is_agg ){
- pExpr->op = TK_AGG_FUNCTION;
- if( pIsAgg ) *pIsAgg = 1;
- }
- for(i=0; nErr==0 && i<n; i++){
- nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr,
- allowAgg && !is_agg, pIsAgg);
- }
- if( pDef==0 ){
- /* Already reported an error */
- }else if( pDef->dataType>=0 ){
- if( pDef->dataType<n ){
- pExpr->dataType =
- sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr);
- }else{
- pExpr->dataType = SQLITE_SO_NUM;
- }
- }else if( pDef->dataType==SQLITE_ARGS ){
- pDef->dataType = SQLITE_SO_TEXT;
- for(i=0; i<n; i++){
- if( sqliteExprType(pExpr->pList->a[i].pExpr)==SQLITE_SO_NUM ){
- pExpr->dataType = SQLITE_SO_NUM;
- break;
- }
- }
- }else if( pDef->dataType==SQLITE_NUMERIC ){
- pExpr->dataType = SQLITE_SO_NUM;
- }else{
- pExpr->dataType = SQLITE_SO_TEXT;
- }
- }
- default: {
- if( pExpr->pLeft ){
- nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
- }
- if( nErr==0 && pExpr->pRight ){
- nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
- }
- if( nErr==0 && pExpr->pList ){
- int n = pExpr->pList->nExpr;
- int i;
- for(i=0; nErr==0 && i<n; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
- nErr = sqliteExprCheck(pParse, pE2, allowAgg, pIsAgg);
- }
- }
- break;
- }
- }
- return nErr;
-}
-
-/*
-** Return either SQLITE_SO_NUM or SQLITE_SO_TEXT to indicate whether the
-** given expression should sort as numeric values or as text.
-**
-** The sqliteExprResolveIds() and sqliteExprCheck() routines must have
-** both been called on the expression before it is passed to this routine.
-*/
-int sqliteExprType(Expr *p){
- if( p==0 ) return SQLITE_SO_NUM;
- while( p ) switch( p->op ){
- case TK_PLUS:
- case TK_MINUS:
- case TK_STAR:
- case TK_SLASH:
- case TK_AND:
- case TK_OR:
- case TK_ISNULL:
- case TK_NOTNULL:
- case TK_NOT:
- case TK_UMINUS:
- case TK_UPLUS:
- case TK_BITAND:
- case TK_BITOR:
- case TK_BITNOT:
- case TK_LSHIFT:
- case TK_RSHIFT:
- case TK_REM:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_IN:
- case TK_BETWEEN:
- case TK_GLOB:
- case TK_LIKE:
- return SQLITE_SO_NUM;
-
- case TK_STRING:
- case TK_NULL:
- case TK_CONCAT:
- case TK_VARIABLE:
- return SQLITE_SO_TEXT;
-
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ:
- if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){
- return SQLITE_SO_NUM;
- }
- p = p->pRight;
- break;
-
- case TK_AS:
- p = p->pLeft;
- break;
-
- case TK_COLUMN:
- case TK_FUNCTION:
- case TK_AGG_FUNCTION:
- return p->dataType;
-
- case TK_SELECT:
- assert( p->pSelect );
- assert( p->pSelect->pEList );
- assert( p->pSelect->pEList->nExpr>0 );
- p = p->pSelect->pEList->a[0].pExpr;
- break;
-
- case TK_CASE: {
- if( p->pRight && sqliteExprType(p->pRight)==SQLITE_SO_NUM ){
- return SQLITE_SO_NUM;
- }
- if( p->pList ){
- int i;
- ExprList *pList = p->pList;
- for(i=1; i<pList->nExpr; i+=2){
- if( sqliteExprType(pList->a[i].pExpr)==SQLITE_SO_NUM ){
- return SQLITE_SO_NUM;
- }
- }
- }
- return SQLITE_SO_TEXT;
- }
-
- default:
- assert( p->op==TK_ABORT ); /* Can't Happen */
- break;
- }
- return SQLITE_SO_NUM;
-}
-
-/*
-** Generate code into the current Vdbe to evaluate the given
-** expression and leave the result on the top of stack.
-*/
-void sqliteExprCode(Parse *pParse, Expr *pExpr){
- Vdbe *v = pParse->pVdbe;
- int op;
- if( v==0 || pExpr==0 ) return;
- switch( pExpr->op ){
- case TK_PLUS: op = OP_Add; break;
- case TK_MINUS: op = OP_Subtract; break;
- case TK_STAR: op = OP_Multiply; break;
- case TK_SLASH: op = OP_Divide; break;
- case TK_AND: op = OP_And; break;
- case TK_OR: op = OP_Or; break;
- case TK_LT: op = OP_Lt; break;
- case TK_LE: op = OP_Le; break;
- case TK_GT: op = OP_Gt; break;
- case TK_GE: op = OP_Ge; break;
- case TK_NE: op = OP_Ne; break;
- case TK_EQ: op = OP_Eq; break;
- case TK_ISNULL: op = OP_IsNull; break;
- case TK_NOTNULL: op = OP_NotNull; break;
- case TK_NOT: op = OP_Not; break;
- case TK_UMINUS: op = OP_Negative; break;
- case TK_BITAND: op = OP_BitAnd; break;
- case TK_BITOR: op = OP_BitOr; break;
- case TK_BITNOT: op = OP_BitNot; break;
- case TK_LSHIFT: op = OP_ShiftLeft; break;
- case TK_RSHIFT: op = OP_ShiftRight; break;
- case TK_REM: op = OP_Remainder; break;
- default: break;
- }
- switch( pExpr->op ){
- case TK_COLUMN: {
- if( pParse->useAgg ){
- sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
- }else if( pExpr->iColumn>=0 ){
- sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
- }else{
- sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
- }
- break;
- }
- case TK_STRING:
- case TK_FLOAT:
- case TK_INTEGER: {
- if( pExpr->op==TK_INTEGER && sqliteFitsIn32Bits(pExpr->token.z) ){
- sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
- }else{
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- }
- assert( pExpr->token.z );
- sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
- sqliteVdbeDequoteP3(v, -1);
- break;
- }
- case TK_NULL: {
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- break;
- }
- case TK_VARIABLE: {
- sqliteVdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
- break;
- }
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
- if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
- op += 6; /* Convert numeric opcodes to text opcodes */
- }
- /* Fall through into the next case */
- }
- case TK_AND:
- case TK_OR:
- case TK_PLUS:
- case TK_STAR:
- case TK_MINUS:
- case TK_REM:
- case TK_BITAND:
- case TK_BITOR:
- case TK_SLASH: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteExprCode(pParse, pExpr->pRight);
- sqliteVdbeAddOp(v, op, 0, 0);
- break;
- }
- case TK_LSHIFT:
- case TK_RSHIFT: {
- sqliteExprCode(pParse, pExpr->pRight);
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, op, 0, 0);
- break;
- }
- case TK_CONCAT: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteExprCode(pParse, pExpr->pRight);
- sqliteVdbeAddOp(v, OP_Concat, 2, 0);
- break;
- }
- case TK_UMINUS: {
- assert( pExpr->pLeft );
- if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){
- Token *p = &pExpr->pLeft->token;
- char *z = sqliteMalloc( p->n + 2 );
- sprintf(z, "-%.*s", p->n, p->z);
- if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){
- sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0);
- }else{
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- }
- sqliteVdbeChangeP3(v, -1, z, p->n+1);
- sqliteFree(z);
- break;
- }
- /* Fall through into TK_NOT */
- }
- case TK_BITNOT:
- case TK_NOT: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, op, 0, 0);
- break;
- }
- case TK_ISNULL:
- case TK_NOTNULL: {
- int dest;
- sqliteVdbeAddOp(v, OP_Integer, 1, 0);
- sqliteExprCode(pParse, pExpr->pLeft);
- dest = sqliteVdbeCurrentAddr(v) + 2;
- sqliteVdbeAddOp(v, op, 1, dest);
- sqliteVdbeAddOp(v, OP_AddImm, -1, 0);
- break;
- }
- case TK_AGG_FUNCTION: {
- sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
- break;
- }
- case TK_GLOB:
- case TK_LIKE:
- case TK_FUNCTION: {
- ExprList *pList = pExpr->pList;
- int nExpr = pList ? pList->nExpr : 0;
- FuncDef *pDef;
- int nId;
- const char *zId;
- getFunctionName(pExpr, &zId, &nId);
- pDef = sqliteFindFunction(pParse->db, zId, nId, nExpr, 0);
- assert( pDef!=0 );
- nExpr = sqliteExprCodeExprList(pParse, pList, pDef->includeTypes);
- sqliteVdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
- break;
- }
- case TK_SELECT: {
- sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
- break;
- }
- case TK_IN: {
- int addr;
- sqliteVdbeAddOp(v, OP_Integer, 1, 0);
- sqliteExprCode(pParse, pExpr->pLeft);
- addr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4);
- sqliteVdbeAddOp(v, OP_Pop, 2, 0);
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, addr+6);
- if( pExpr->pSelect ){
- sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+6);
- }else{
- sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6);
- }
- sqliteVdbeAddOp(v, OP_AddImm, -1, 0);
- break;
- }
- case TK_BETWEEN: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
- sqliteVdbeAddOp(v, OP_Ge, 0, 0);
- sqliteVdbeAddOp(v, OP_Pull, 1, 0);
- sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
- sqliteVdbeAddOp(v, OP_Le, 0, 0);
- sqliteVdbeAddOp(v, OP_And, 0, 0);
- break;
- }
- case TK_UPLUS:
- case TK_AS: {
- sqliteExprCode(pParse, pExpr->pLeft);
- break;
- }
- case TK_CASE: {
- int expr_end_label;
- int jumpInst;
- int addr;
- int nExpr;
- int i;
-
- assert(pExpr->pList);
- assert((pExpr->pList->nExpr % 2) == 0);
- assert(pExpr->pList->nExpr > 0);
- nExpr = pExpr->pList->nExpr;
- expr_end_label = sqliteVdbeMakeLabel(v);
- if( pExpr->pLeft ){
- sqliteExprCode(pParse, pExpr->pLeft);
- }
- for(i=0; i<nExpr; i=i+2){
- sqliteExprCode(pParse, pExpr->pList->a[i].pExpr);
- if( pExpr->pLeft ){
- sqliteVdbeAddOp(v, OP_Dup, 1, 1);
- jumpInst = sqliteVdbeAddOp(v, OP_Ne, 1, 0);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- }else{
- jumpInst = sqliteVdbeAddOp(v, OP_IfNot, 1, 0);
- }
- sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr);
- sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label);
- addr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeChangeP2(v, jumpInst, addr);
- }
- if( pExpr->pLeft ){
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- }
- if( pExpr->pRight ){
- sqliteExprCode(pParse, pExpr->pRight);
- }else{
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- }
- sqliteVdbeResolveLabel(v, expr_end_label);
- break;
- }
- case TK_RAISE: {
- if( !pParse->trigStack ){
- sqliteErrorMsg(pParse,
- "RAISE() may only be used within a trigger-program");
- pParse->nErr++;
- return;
- }
- if( pExpr->iColumn == OE_Rollback ||
- pExpr->iColumn == OE_Abort ||
- pExpr->iColumn == OE_Fail ){
- sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
- pExpr->token.z, pExpr->token.n);
- sqliteVdbeDequoteP3(v, -1);
- } else {
- assert( pExpr->iColumn == OE_Ignore );
- sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump,
- "(IGNORE jump)", 0);
- }
- }
- break;
- }
-}
-
-/*
-** Generate code that pushes the value of every element of the given
-** expression list onto the stack. If the includeTypes flag is true,
-** then also push a string that is the datatype of each element onto
-** the stack after the value.
-**
-** Return the number of elements pushed onto the stack.
-*/
-int sqliteExprCodeExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* The expression list to be coded */
- int includeTypes /* TRUE to put datatypes on the stack too */
-){
- struct ExprList_item *pItem;
- int i, n;
- Vdbe *v;
- if( pList==0 ) return 0;
- v = sqliteGetVdbe(pParse);
- n = pList->nExpr;
- for(pItem=pList->a, i=0; i<n; i++, pItem++){
- sqliteExprCode(pParse, pItem->pExpr);
- if( includeTypes ){
- sqliteVdbeOp3(v, OP_String, 0, 0,
- sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text",
- P3_STATIC);
- }
- }
- return includeTypes ? n*2 : n;
-}
-
-/*
-** Generate code for a boolean expression such that a jump is made
-** to the label "dest" if the expression is true but execution
-** continues straight thru if the expression is false.
-**
-** If the expression evaluates to NULL (neither true nor false), then
-** take the jump if the jumpIfNull flag is true.
-*/
-void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
- Vdbe *v = pParse->pVdbe;
- int op = 0;
- if( v==0 || pExpr==0 ) return;
- switch( pExpr->op ){
- case TK_LT: op = OP_Lt; break;
- case TK_LE: op = OP_Le; break;
- case TK_GT: op = OP_Gt; break;
- case TK_GE: op = OP_Ge; break;
- case TK_NE: op = OP_Ne; break;
- case TK_EQ: op = OP_Eq; break;
- case TK_ISNULL: op = OP_IsNull; break;
- case TK_NOTNULL: op = OP_NotNull; break;
- default: break;
- }
- switch( pExpr->op ){
- case TK_AND: {
- int d2 = sqliteVdbeMakeLabel(v);
- sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull);
- sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- sqliteVdbeResolveLabel(v, d2);
- break;
- }
- case TK_OR: {
- sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- break;
- }
- case TK_NOT: {
- sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- break;
- }
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteExprCode(pParse, pExpr->pRight);
- if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
- op += 6; /* Convert numeric opcodes to text opcodes */
- }
- sqliteVdbeAddOp(v, op, jumpIfNull, dest);
- break;
- }
- case TK_ISNULL:
- case TK_NOTNULL: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, op, 1, dest);
- break;
- }
- case TK_IN: {
- int addr;
- sqliteExprCode(pParse, pExpr->pLeft);
- addr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);
- if( pExpr->pSelect ){
- sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest);
- }else{
- sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest);
- }
- break;
- }
- case TK_BETWEEN: {
- int addr;
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
- addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0);
- sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
- sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest);
- sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- break;
- }
- default: {
- sqliteExprCode(pParse, pExpr);
- sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest);
- break;
- }
- }
-}
-
-/*
-** Generate code for a boolean expression such that a jump is made
-** to the label "dest" if the expression is false but execution
-** continues straight thru if the expression is true.
-**
-** If the expression evaluates to NULL (neither true nor false) then
-** jump if jumpIfNull is true or fall through if jumpIfNull is false.
-*/
-void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
- Vdbe *v = pParse->pVdbe;
- int op = 0;
- if( v==0 || pExpr==0 ) return;
- switch( pExpr->op ){
- case TK_LT: op = OP_Ge; break;
- case TK_LE: op = OP_Gt; break;
- case TK_GT: op = OP_Le; break;
- case TK_GE: op = OP_Lt; break;
- case TK_NE: op = OP_Eq; break;
- case TK_EQ: op = OP_Ne; break;
- case TK_ISNULL: op = OP_NotNull; break;
- case TK_NOTNULL: op = OP_IsNull; break;
- default: break;
- }
- switch( pExpr->op ){
- case TK_AND: {
- sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- break;
- }
- case TK_OR: {
- int d2 = sqliteVdbeMakeLabel(v);
- sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull);
- sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- sqliteVdbeResolveLabel(v, d2);
- break;
- }
- case TK_NOT: {
- sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- break;
- }
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_NE:
- case TK_EQ: {
- if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
- /* Convert numeric comparison opcodes into text comparison opcodes.
- ** This step depends on the fact that the text comparision opcodes are
- ** always 6 greater than their corresponding numeric comparison
- ** opcodes.
- */
- assert( OP_Eq+6 == OP_StrEq );
- op += 6;
- }
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteExprCode(pParse, pExpr->pRight);
- sqliteVdbeAddOp(v, op, jumpIfNull, dest);
- break;
- }
- case TK_ISNULL:
- case TK_NOTNULL: {
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, op, 1, dest);
- break;
- }
- case TK_IN: {
- int addr;
- sqliteExprCode(pParse, pExpr->pLeft);
- addr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4);
- if( pExpr->pSelect ){
- sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest);
- }else{
- sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest);
- }
- break;
- }
- case TK_BETWEEN: {
- int addr;
- sqliteExprCode(pParse, pExpr->pLeft);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- sqliteExprCode(pParse, pExpr->pList->a[0].pExpr);
- addr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, dest);
- sqliteExprCode(pParse, pExpr->pList->a[1].pExpr);
- sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest);
- break;
- }
- default: {
- sqliteExprCode(pParse, pExpr);
- sqliteVdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
- break;
- }
- }
-}
-
-/*
-** Do a deep comparison of two expression trees. Return TRUE (non-zero)
-** if they are identical and return FALSE if they differ in any way.
-*/
-int sqliteExprCompare(Expr *pA, Expr *pB){
- int i;
- if( pA==0 ){
- return pB==0;
- }else if( pB==0 ){
- return 0;
- }
- if( pA->op!=pB->op ) return 0;
- if( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0;
- if( !sqliteExprCompare(pA->pRight, pB->pRight) ) return 0;
- if( pA->pList ){
- if( pB->pList==0 ) return 0;
- if( pA->pList->nExpr!=pB->pList->nExpr ) return 0;
- for(i=0; i<pA->pList->nExpr; i++){
- if( !sqliteExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){
- return 0;
- }
- }
- }else if( pB->pList ){
- return 0;
- }
- if( pA->pSelect || pB->pSelect ) return 0;
- if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
- if( pA->token.z ){
- if( pB->token.z==0 ) return 0;
- if( pB->token.n!=pA->token.n ) return 0;
- if( sqliteStrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0;
- }
- return 1;
-}
-
-/*
-** Add a new element to the pParse->aAgg[] array and return its index.
-*/
-static int appendAggInfo(Parse *pParse){
- if( (pParse->nAgg & 0x7)==0 ){
- int amt = pParse->nAgg + 8;
- AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
- if( aAgg==0 ){
- return -1;
- }
- pParse->aAgg = aAgg;
- }
- memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
- return pParse->nAgg++;
-}
-
-/*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
-**
-** This routine should only be called after the expression has been
-** analyzed by sqliteExprResolveIds() and sqliteExprCheck().
-**
-** If errors are seen, leave an error message in zErrMsg and return
-** the number of errors.
-*/
-int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
- int i;
- AggExpr *aAgg;
- int nErr = 0;
-
- if( pExpr==0 ) return 0;
- switch( pExpr->op ){
- case TK_COLUMN: {
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( aAgg[i].isAgg ) continue;
- if( aAgg[i].pExpr->iTable==pExpr->iTable
- && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
- break;
- }
- }
- if( i>=pParse->nAgg ){
- i = appendAggInfo(pParse);
- if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 0;
- pParse->aAgg[i].pExpr = pExpr;
- }
- pExpr->iAgg = i;
- break;
- }
- case TK_AGG_FUNCTION: {
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( !aAgg[i].isAgg ) continue;
- if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){
- break;
- }
- }
- if( i>=pParse->nAgg ){
- i = appendAggInfo(pParse);
- if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 1;
- pParse->aAgg[i].pExpr = pExpr;
- pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db,
- pExpr->token.z, pExpr->token.n,
- pExpr->pList ? pExpr->pList->nExpr : 0, 0);
- }
- pExpr->iAgg = i;
- break;
- }
- default: {
- if( pExpr->pLeft ){
- nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft);
- }
- if( nErr==0 && pExpr->pRight ){
- nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight);
- }
- if( nErr==0 && pExpr->pList ){
- int n = pExpr->pList->nExpr;
- int i;
- for(i=0; nErr==0 && i<n; i++){
- nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);
- }
- }
- break;
- }
- }
- return nErr;
-}
-
-/*
-** Locate a user function given a name and a number of arguments.
-** Return a pointer to the FuncDef structure that defines that
-** function, or return NULL if the function does not exist.
-**
-** If the createFlag argument is true, then a new (blank) FuncDef
-** structure is created and liked into the "db" structure if a
-** no matching function previously existed. When createFlag is true
-** and the nArg parameter is -1, then only a function that accepts
-** any number of arguments will be returned.
-**
-** If createFlag is false and nArg is -1, then the first valid
-** function found is returned. A function is valid if either xFunc
-** or xStep is non-zero.
-*/
-FuncDef *sqliteFindFunction(
- sqlite *db, /* An open database */
- const char *zName, /* Name of the function. Not null-terminated */
- int nName, /* Number of characters in the name */
- int nArg, /* Number of arguments. -1 means any number */
- int createFlag /* Create new entry if true and does not otherwise exist */
-){
- FuncDef *pFirst, *p, *pMaybe;
- pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName);
- if( p && !createFlag && nArg<0 ){
- while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; }
- return p;
- }
- pMaybe = 0;
- while( p && p->nArg!=nArg ){
- if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p;
- p = p->pNext;
- }
- if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){
- return 0;
- }
- if( p==0 && pMaybe ){
- assert( createFlag==0 );
- return pMaybe;
- }
- if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){
- p->nArg = nArg;
- p->pNext = pFirst;
- p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC;
- sqliteHashInsert(&db->aFunc, zName, nName, (void*)p);
- }
- return p;
-}
diff --git a/ext/sqlite/libsqlite/src/func.c b/ext/sqlite/libsqlite/src/func.c
deleted file mode 100644
index 8d6012eff7..0000000000
--- a/ext/sqlite/libsqlite/src/func.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
-** 2002 February 23
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains the C functions that implement various SQL
-** functions of SQLite.
-**
-** There is only one exported symbol in this file - the function
-** sqliteRegisterBuildinFunctions() found at the bottom of the file.
-** All other code has file scope.
-**
-** $Id$
-*/
-#include <ctype.h>
-#include <math.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "sqliteInt.h"
-#include "os.h"
-
-/*
-** Implementation of the non-aggregate min() and max() functions
-*/
-static void minmaxFunc(sqlite_func *context, int argc, const char **argv){
- const char *zBest;
- int i;
- int (*xCompare)(const char*, const char*);
- int mask; /* 0 for min() or 0xffffffff for max() */
-
- if( argc==0 ) return;
- mask = (int)sqlite_user_data(context);
- zBest = argv[0];
- if( zBest==0 ) return;
- if( argv[1][0]=='n' ){
- xCompare = sqliteCompare;
- }else{
- xCompare = strcmp;
- }
- for(i=2; i<argc; i+=2){
- if( argv[i]==0 ) return;
- if( (xCompare(argv[i], zBest)^mask)<0 ){
- zBest = argv[i];
- }
- }
- sqlite_set_result_string(context, zBest, -1);
-}
-
-/*
-** Return the type of the argument.
-*/
-static void typeofFunc(sqlite_func *context, int argc, const char **argv){
- assert( argc==2 );
- sqlite_set_result_string(context, argv[1], -1);
-}
-
-/*
-** Implementation of the length() function
-*/
-static void lengthFunc(sqlite_func *context, int argc, const char **argv){
- const char *z;
- int len;
-
- assert( argc==1 );
- z = argv[0];
- if( z==0 ) return;
-#ifdef SQLITE_UTF8
- for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
-#else
- len = strlen(z);
-#endif
- sqlite_set_result_int(context, len);
-}
-
-/*
-** Implementation of the abs() function
-*/
-static void absFunc(sqlite_func *context, int argc, const char **argv){
- const char *z;
- assert( argc==1 );
- z = argv[0];
- if( z==0 ) return;
- if( z[0]=='-' && isdigit(z[1]) ) z++;
- sqlite_set_result_string(context, z, -1);
-}
-
-/*
-** Implementation of the substr() function
-*/
-static void substrFunc(sqlite_func *context, int argc, const char **argv){
- const char *z;
-#ifdef SQLITE_UTF8
- const char *z2;
- int i;
-#endif
- int p1, p2, len;
- assert( argc==3 );
- z = argv[0];
- if( z==0 ) return;
- p1 = atoi(argv[1]?argv[1]:0);
- p2 = atoi(argv[2]?argv[2]:0);
-#ifdef SQLITE_UTF8
- for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; }
-#else
- len = strlen(z);
-#endif
- if( p1<0 ){
- p1 += len;
- if( p1<0 ){
- p2 += p1;
- p1 = 0;
- }
- }else if( p1>0 ){
- p1--;
- }
- if( p1+p2>len ){
- p2 = len-p1;
- }
-#ifdef SQLITE_UTF8
- for(i=0; i<p1 && z[i]; i++){
- if( (z[i]&0xc0)==0x80 ) p1++;
- }
- while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; }
- for(; i<p1+p2 && z[i]; i++){
- if( (z[i]&0xc0)==0x80 ) p2++;
- }
- while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; }
-#endif
- if( p2<0 ) p2 = 0;
- sqlite_set_result_string(context, &z[p1], p2);
-}
-
-/*
-** Implementation of the round() function
-*/
-static void roundFunc(sqlite_func *context, int argc, const char **argv){
- int n;
- double r;
- char zBuf[100];
- assert( argc==1 || argc==2 );
- if( argv[0]==0 || (argc==2 && argv[1]==0) ) return;
- n = argc==2 ? atoi(argv[1]) : 0;
- if( n>30 ) n = 30;
- if( n<0 ) n = 0;
- r = sqliteAtoF(argv[0], 0);
- sprintf(zBuf,"%.*f",n,r);
- sqlite_set_result_string(context, zBuf, -1);
-}
-
-/*
-** Implementation of the upper() and lower() SQL functions.
-*/
-static void upperFunc(sqlite_func *context, int argc, const char **argv){
- unsigned char *z;
- int i;
- if( argc<1 || argv[0]==0 ) return;
- z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
- if( z==0 ) return;
- for(i=0; z[i]; i++){
- if( islower(z[i]) ) z[i] = toupper(z[i]);
- }
-}
-static void lowerFunc(sqlite_func *context, int argc, const char **argv){
- unsigned char *z;
- int i;
- if( argc<1 || argv[0]==0 ) return;
- z = (unsigned char*)sqlite_set_result_string(context, argv[0], -1);
- if( z==0 ) return;
- for(i=0; z[i]; i++){
- if( isupper(z[i]) ) z[i] = tolower(z[i]);
- }
-}
-
-/*
-** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
-** All three do the same thing. They return the first non-NULL
-** argument.
-*/
-static void ifnullFunc(sqlite_func *context, int argc, const char **argv){
- int i;
- for(i=0; i<argc; i++){
- if( argv[i] ){
- sqlite_set_result_string(context, argv[i], -1);
- break;
- }
- }
-}
-
-/*
-** Implementation of random(). Return a random integer.
-*/
-static void randomFunc(sqlite_func *context, int argc, const char **argv){
- int r;
- sqliteRandomness(sizeof(r), &r);
- sqlite_set_result_int(context, r);
-}
-
-/*
-** Implementation of the last_insert_rowid() SQL function. The return
-** value is the same as the sqlite_last_insert_rowid() API function.
-*/
-static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){
- sqlite *db = sqlite_user_data(context);
- sqlite_set_result_int(context, sqlite_last_insert_rowid(db));
-}
-
-/*
-** Implementation of the change_count() SQL function. The return
-** value is the same as the sqlite_changes() API function.
-*/
-static void change_count(sqlite_func *context, int arg, const char **argv){
- sqlite *db = sqlite_user_data(context);
- sqlite_set_result_int(context, sqlite_changes(db));
-}
-
-/*
-** Implementation of the last_statement_change_count() SQL function. The
-** return value is the same as the sqlite_last_statement_changes() API function.
-*/
-static void last_statement_change_count(sqlite_func *context, int arg,
- const char **argv){
- sqlite *db = sqlite_user_data(context);
- sqlite_set_result_int(context, sqlite_last_statement_changes(db));
-}
-
-/*
-** Implementation of the like() SQL function. This function implements
-** the build-in LIKE operator. The first argument to the function is the
-** string and the second argument is the pattern. So, the SQL statements:
-**
-** A LIKE B
-**
-** is implemented as like(A,B).
-*/
-static void likeFunc(sqlite_func *context, int arg, const char **argv){
- if( argv[0]==0 || argv[1]==0 ) return;
- sqlite_set_result_int(context,
- sqliteLikeCompare((const unsigned char*)argv[0],
- (const unsigned char*)argv[1]));
-}
-
-/*
-** Implementation of the glob() SQL function. This function implements
-** the build-in GLOB operator. The first argument to the function is the
-** string and the second argument is the pattern. So, the SQL statements:
-**
-** A GLOB B
-**
-** is implemented as glob(A,B).
-*/
-static void globFunc(sqlite_func *context, int arg, const char **argv){
- if( argv[0]==0 || argv[1]==0 ) return;
- sqlite_set_result_int(context,
- sqliteGlobCompare((const unsigned char*)argv[0],
- (const unsigned char*)argv[1]));
-}
-
-/*
-** Implementation of the NULLIF(x,y) function. The result is the first
-** argument if the arguments are different. The result is NULL if the
-** arguments are equal to each other.
-*/
-static void nullifFunc(sqlite_func *context, int argc, const char **argv){
- if( argv[0]!=0 && sqliteCompare(argv[0],argv[1])!=0 ){
- sqlite_set_result_string(context, argv[0], -1);
- }
-}
-
-/*
-** Implementation of the VERSION(*) function. The result is the version
-** of the SQLite library that is running.
-*/
-static void versionFunc(sqlite_func *context, int argc, const char **argv){
- sqlite_set_result_string(context, sqlite_version, -1);
-}
-
-/*
-** EXPERIMENTAL - This is not an official function. The interface may
-** change. This function may disappear. Do not write code that depends
-** on this function.
-**
-** Implementation of the QUOTE() function. This function takes a single
-** argument. If the argument is numeric, the return value is the same as
-** the argument. If the argument is NULL, the return value is the string
-** "NULL". Otherwise, the argument is enclosed in single quotes with
-** single-quote escapes.
-*/
-static void quoteFunc(sqlite_func *context, int argc, const char **argv){
- if( argc<1 ) return;
- if( argv[0]==0 ){
- sqlite_set_result_string(context, "NULL", 4);
- }else if( sqliteIsNumber(argv[0]) ){
- sqlite_set_result_string(context, argv[0], -1);
- }else{
- int i,j,n;
- char *z;
- for(i=n=0; argv[0][i]; i++){ if( argv[0][i]=='\'' ) n++; }
- z = sqliteMalloc( i+n+3 );
- if( z==0 ) return;
- z[0] = '\'';
- for(i=0, j=1; argv[0][i]; i++){
- z[j++] = argv[0][i];
- if( argv[0][i]=='\'' ){
- z[j++] = '\'';
- }
- }
- z[j++] = '\'';
- z[j] = 0;
- sqlite_set_result_string(context, z, j);
- sqliteFree(z);
- }
-}
-
-#ifdef SQLITE_SOUNDEX
-/*
-** Compute the soundex encoding of a word.
-*/
-static void soundexFunc(sqlite_func *context, int argc, const char **argv){
- char zResult[8];
- const char *zIn;
- int i, j;
- static const unsigned char iCode[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
- 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
- 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
- };
- assert( argc==1 );
- zIn = argv[0];
- for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
- if( zIn[i] ){
- zResult[0] = toupper(zIn[i]);
- for(j=1; j<4 && zIn[i]; i++){
- int code = iCode[zIn[i]&0x7f];
- if( code>0 ){
- zResult[j++] = code + '0';
- }
- }
- while( j<4 ){
- zResult[j++] = '0';
- }
- zResult[j] = 0;
- sqlite_set_result_string(context, zResult, 4);
- }else{
- sqlite_set_result_string(context, "?000", 4);
- }
-}
-#endif
-
-#ifdef SQLITE_TEST
-/*
-** This function generates a string of random characters. Used for
-** generating test data.
-*/
-static void randStr(sqlite_func *context, int argc, const char **argv){
- static const unsigned char zSrc[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- ".-!,:*^+=_|?/<> ";
- int iMin, iMax, n, r, i;
- unsigned char zBuf[1000];
- if( argc>=1 ){
- iMin = atoi(argv[0]);
- if( iMin<0 ) iMin = 0;
- if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
- }else{
- iMin = 1;
- }
- if( argc>=2 ){
- iMax = atoi(argv[1]);
- if( iMax<iMin ) iMax = iMin;
- if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1;
- }else{
- iMax = 50;
- }
- n = iMin;
- if( iMax>iMin ){
- sqliteRandomness(sizeof(r), &r);
- r &= 0x7fffffff;
- n += r%(iMax + 1 - iMin);
- }
- assert( n<sizeof(zBuf) );
- sqliteRandomness(n, zBuf);
- for(i=0; i<n; i++){
- zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
- }
- zBuf[n] = 0;
- sqlite_set_result_string(context, zBuf, n);
-}
-#endif
-
-/*
-** An instance of the following structure holds the context of a
-** sum() or avg() aggregate computation.
-*/
-typedef struct SumCtx SumCtx;
-struct SumCtx {
- double sum; /* Sum of terms */
- int cnt; /* Number of elements summed */
-};
-
-/*
-** Routines used to compute the sum or average.
-*/
-static void sumStep(sqlite_func *context, int argc, const char **argv){
- SumCtx *p;
- if( argc<1 ) return;
- p = sqlite_aggregate_context(context, sizeof(*p));
- if( p && argv[0] ){
- p->sum += sqliteAtoF(argv[0], 0);
- p->cnt++;
- }
-}
-static void sumFinalize(sqlite_func *context){
- SumCtx *p;
- p = sqlite_aggregate_context(context, sizeof(*p));
- sqlite_set_result_double(context, p ? p->sum : 0.0);
-}
-static void avgFinalize(sqlite_func *context){
- SumCtx *p;
- p = sqlite_aggregate_context(context, sizeof(*p));
- if( p && p->cnt>0 ){
- sqlite_set_result_double(context, p->sum/(double)p->cnt);
- }
-}
-
-/*
-** An instance of the following structure holds the context of a
-** variance or standard deviation computation.
-*/
-typedef struct StdDevCtx StdDevCtx;
-struct StdDevCtx {
- double sum; /* Sum of terms */
- double sum2; /* Sum of the squares of terms */
- int cnt; /* Number of terms counted */
-};
-
-#if 0 /* Omit because math library is required */
-/*
-** Routines used to compute the standard deviation as an aggregate.
-*/
-static void stdDevStep(sqlite_func *context, int argc, const char **argv){
- StdDevCtx *p;
- double x;
- if( argc<1 ) return;
- p = sqlite_aggregate_context(context, sizeof(*p));
- if( p && argv[0] ){
- x = sqliteAtoF(argv[0], 0);
- p->sum += x;
- p->sum2 += x*x;
- p->cnt++;
- }
-}
-static void stdDevFinalize(sqlite_func *context){
- double rN = sqlite_aggregate_count(context);
- StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
- if( p && p->cnt>1 ){
- double rCnt = cnt;
- sqlite_set_result_double(context,
- sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
- }
-}
-#endif
-
-/*
-** The following structure keeps track of state information for the
-** count() aggregate function.
-*/
-typedef struct CountCtx CountCtx;
-struct CountCtx {
- int n;
-};
-
-/*
-** Routines to implement the count() aggregate function.
-*/
-static void countStep(sqlite_func *context, int argc, const char **argv){
- CountCtx *p;
- p = sqlite_aggregate_context(context, sizeof(*p));
- if( (argc==0 || argv[0]) && p ){
- p->n++;
- }
-}
-static void countFinalize(sqlite_func *context){
- CountCtx *p;
- p = sqlite_aggregate_context(context, sizeof(*p));
- sqlite_set_result_int(context, p ? p->n : 0);
-}
-
-/*
-** This function tracks state information for the min() and max()
-** aggregate functions.
-*/
-typedef struct MinMaxCtx MinMaxCtx;
-struct MinMaxCtx {
- char *z; /* The best so far */
- char zBuf[28]; /* Space that can be used for storage */
-};
-
-/*
-** Routines to implement min() and max() aggregate functions.
-*/
-static void minmaxStep(sqlite_func *context, int argc, const char **argv){
- MinMaxCtx *p;
- int (*xCompare)(const char*, const char*);
- int mask; /* 0 for min() or 0xffffffff for max() */
-
- assert( argc==2 );
- if( argv[0]==0 ) return; /* Ignore NULL values */
- if( argv[1][0]=='n' ){
- xCompare = sqliteCompare;
- }else{
- xCompare = strcmp;
- }
- mask = (int)sqlite_user_data(context);
- assert( mask==0 || mask==-1 );
- p = sqlite_aggregate_context(context, sizeof(*p));
- if( p==0 || argc<1 ) return;
- if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
- int len;
- if( p->zBuf[0] ){
- sqliteFree(p->z);
- }
- len = strlen(argv[0]);
- if( len < sizeof(p->zBuf)-1 ){
- p->z = &p->zBuf[1];
- p->zBuf[0] = 0;
- }else{
- p->z = sqliteMalloc( len+1 );
- p->zBuf[0] = 1;
- if( p->z==0 ) return;
- }
- strcpy(p->z, argv[0]);
- }
-}
-static void minMaxFinalize(sqlite_func *context){
- MinMaxCtx *p;
- p = sqlite_aggregate_context(context, sizeof(*p));
- if( p && p->z && p->zBuf[0]<2 ){
- sqlite_set_result_string(context, p->z, strlen(p->z));
- }
- if( p && p->zBuf[0] ){
- sqliteFree(p->z);
- }
-}
-
-/*
-** This function registered all of the above C functions as SQL
-** functions. This should be the only routine in this file with
-** external linkage.
-*/
-void sqliteRegisterBuiltinFunctions(sqlite *db){
- static struct {
- char *zName;
- signed char nArg;
- signed char dataType;
- u8 argType; /* 0: none. 1: db 2: (-1) */
- void (*xFunc)(sqlite_func*,int,const char**);
- } aFuncs[] = {
- { "min", -1, SQLITE_ARGS, 0, minmaxFunc },
- { "min", 0, 0, 0, 0 },
- { "max", -1, SQLITE_ARGS, 2, minmaxFunc },
- { "max", 0, 0, 2, 0 },
- { "typeof", 1, SQLITE_TEXT, 0, typeofFunc },
- { "length", 1, SQLITE_NUMERIC, 0, lengthFunc },
- { "substr", 3, SQLITE_TEXT, 0, substrFunc },
- { "abs", 1, SQLITE_NUMERIC, 0, absFunc },
- { "round", 1, SQLITE_NUMERIC, 0, roundFunc },
- { "round", 2, SQLITE_NUMERIC, 0, roundFunc },
- { "upper", 1, SQLITE_TEXT, 0, upperFunc },
- { "lower", 1, SQLITE_TEXT, 0, lowerFunc },
- { "coalesce", -1, SQLITE_ARGS, 0, ifnullFunc },
- { "coalesce", 0, 0, 0, 0 },
- { "coalesce", 1, 0, 0, 0 },
- { "ifnull", 2, SQLITE_ARGS, 0, ifnullFunc },
- { "random", -1, SQLITE_NUMERIC, 0, randomFunc },
- { "like", 2, SQLITE_NUMERIC, 0, likeFunc },
- { "glob", 2, SQLITE_NUMERIC, 0, globFunc },
- { "nullif", 2, SQLITE_ARGS, 0, nullifFunc },
- { "sqlite_version",0,SQLITE_TEXT, 0, versionFunc},
- { "quote", 1, SQLITE_ARGS, 0, quoteFunc },
- { "last_insert_rowid", 0, SQLITE_NUMERIC, 1, last_insert_rowid },
- { "change_count", 0, SQLITE_NUMERIC, 1, change_count },
- { "last_statement_change_count",
- 0, SQLITE_NUMERIC, 1, last_statement_change_count },
-#ifdef SQLITE_SOUNDEX
- { "soundex", 1, SQLITE_TEXT, 0, soundexFunc},
-#endif
-#ifdef SQLITE_TEST
- { "randstr", 2, SQLITE_TEXT, 0, randStr },
-#endif
- };
- static struct {
- char *zName;
- signed char nArg;
- signed char dataType;
- u8 argType;
- void (*xStep)(sqlite_func*,int,const char**);
- void (*xFinalize)(sqlite_func*);
- } aAggs[] = {
- { "min", 1, 0, 0, minmaxStep, minMaxFinalize },
- { "max", 1, 0, 2, minmaxStep, minMaxFinalize },
- { "sum", 1, SQLITE_NUMERIC, 0, sumStep, sumFinalize },
- { "avg", 1, SQLITE_NUMERIC, 0, sumStep, avgFinalize },
- { "count", 0, SQLITE_NUMERIC, 0, countStep, countFinalize },
- { "count", 1, SQLITE_NUMERIC, 0, countStep, countFinalize },
-#if 0
- { "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep, stdDevFinalize },
-#endif
- };
- static const char *azTypeFuncs[] = { "min", "max", "typeof" };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- void *pArg;
- switch( aFuncs[i].argType ){
- case 0: pArg = 0; break;
- case 1: pArg = db; break;
- case 2: pArg = (void*)(-1); break;
- }
- sqlite_create_function(db, aFuncs[i].zName,
- aFuncs[i].nArg, aFuncs[i].xFunc, pArg);
- if( aFuncs[i].xFunc ){
- sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
- }
- }
- for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
- void *pArg;
- switch( aAggs[i].argType ){
- case 0: pArg = 0; break;
- case 1: pArg = db; break;
- case 2: pArg = (void*)(-1); break;
- }
- sqlite_create_aggregate(db, aAggs[i].zName,
- aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, pArg);
- sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
- }
- for(i=0; i<sizeof(azTypeFuncs)/sizeof(azTypeFuncs[0]); i++){
- int n = strlen(azTypeFuncs[i]);
- FuncDef *p = sqliteHashFind(&db->aFunc, azTypeFuncs[i], n);
- while( p ){
- p->includeTypes = 1;
- p = p->pNext;
- }
- }
- sqliteRegisterDateTimeFunctions(db);
-}
diff --git a/ext/sqlite/libsqlite/src/hash.c b/ext/sqlite/libsqlite/src/hash.c
deleted file mode 100644
index 77be2807b2..0000000000
--- a/ext/sqlite/libsqlite/src/hash.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
-** 2001 September 22
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This is the implementation of generic hash-tables
-** used in SQLite.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include <assert.h>
-
-/* Turn bulk memory into a hash table object by initializing the
-** fields of the Hash structure.
-**
-** "new" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
-** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass
-** determines what kind of key the hash table will use. "copyKey" is
-** true if the hash table should make its own private copy of keys and
-** false if it should just use the supplied pointer. CopyKey only makes
-** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
-** for other key classes.
-*/
-void sqliteHashInit(Hash *new, int keyClass, int copyKey){
- assert( new!=0 );
- assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY );
- new->keyClass = keyClass;
- new->copyKey = copyKey &&
- (keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY);
- new->first = 0;
- new->count = 0;
- new->htsize = 0;
- new->ht = 0;
-}
-
-/* Remove all entries from a hash table. Reclaim all memory.
-** Call this routine to delete a hash table or to reset a hash table
-** to the empty state.
-*/
-void sqliteHashClear(Hash *pH){
- HashElem *elem; /* For looping over all elements of the table */
-
- assert( pH!=0 );
- elem = pH->first;
- pH->first = 0;
- if( pH->ht ) sqliteFree(pH->ht);
- pH->ht = 0;
- pH->htsize = 0;
- while( elem ){
- HashElem *next_elem = elem->next;
- if( pH->copyKey && elem->pKey ){
- sqliteFree(elem->pKey);
- }
- sqliteFree(elem);
- elem = next_elem;
- }
- pH->count = 0;
-}
-
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_INT
-*/
-static int intHash(const void *pKey, int nKey){
- return nKey ^ (nKey<<8) ^ (nKey>>8);
-}
-static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- return n2 - n1;
-}
-
-#if 0 /* NOT USED */
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
-*/
-static int ptrHash(const void *pKey, int nKey){
- uptr x = Addr(pKey);
- return x ^ (x<<8) ^ (x>>8);
-}
-static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( pKey1==pKey2 ) return 0;
- if( pKey1<pKey2 ) return -1;
- return 1;
-}
-#endif
-
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_STRING
-*/
-static int strHash(const void *pKey, int nKey){
- return sqliteHashNoCase((const char*)pKey, nKey);
-}
-static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return n2-n1;
- return sqliteStrNICmp((const char*)pKey1,(const char*)pKey2,n1);
-}
-
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
-*/
-static int binHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
-}
-static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return n2-n1;
- return memcmp(pKey1,pKey2,n1);
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** The C syntax in this function definition may be unfamilar to some
-** programmers, so we provide the following additional explanation:
-**
-** The name of the function is "hashFunction". The function takes a
-** single parameter "keyClass". The return value of hashFunction()
-** is a pointer to another function. Specifically, the return value
-** of hashFunction() is a pointer to a function that takes two parameters
-** with types "const void*" and "int" and returns an "int".
-*/
-static int (*hashFunction(int keyClass))(const void*,int){
- switch( keyClass ){
- case SQLITE_HASH_INT: return &intHash;
- /* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */
- case SQLITE_HASH_STRING: return &strHash;
- case SQLITE_HASH_BINARY: return &binHash;;
- default: break;
- }
- return 0;
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** For help in interpreted the obscure C code in the function definition,
-** see the header comment on the previous function.
-*/
-static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
- switch( keyClass ){
- case SQLITE_HASH_INT: return &intCompare;
- /* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */
- case SQLITE_HASH_STRING: return &strCompare;
- case SQLITE_HASH_BINARY: return &binCompare;
- default: break;
- }
- return 0;
-}
-
-
-/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
-** to resize if sqliteMalloc() fails.
-*/
-static void rehash(Hash *pH, int new_size){
- struct _ht *new_ht; /* The new hash table */
- HashElem *elem, *next_elem; /* For looping over existing elements */
- HashElem *x; /* Element being copied to new hash table */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( (new_size & (new_size-1))==0 );
- new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) );
- if( new_ht==0 ) return;
- if( pH->ht ) sqliteFree(pH->ht);
- pH->ht = new_ht;
- pH->htsize = new_size;
- xHash = hashFunction(pH->keyClass);
- for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
- next_elem = elem->next;
- x = new_ht[h].chain;
- if( x ){
- elem->next = x;
- elem->prev = x->prev;
- if( x->prev ) x->prev->next = elem;
- else pH->first = elem;
- x->prev = elem;
- }else{
- elem->next = pH->first;
- if( pH->first ) pH->first->prev = elem;
- elem->prev = 0;
- pH->first = elem;
- }
- new_ht[h].chain = elem;
- new_ht[h].count++;
- }
-}
-
-/* This function (for internal use only) locates an element in an
-** hash table that matches the given key. The hash for this key has
-** already been computed and is passed as the 4th parameter.
-*/
-static HashElem *findElementGivenHash(
- const Hash *pH, /* The pH to be searched */
- const void *pKey, /* The key we are searching for */
- int nKey,
- int h /* The hash for this key. */
-){
- HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- int (*xCompare)(const void*,int,const void*,int); /* comparison function */
-
- if( pH->ht ){
- elem = pH->ht[h].chain;
- count = pH->ht[h].count;
- xCompare = compareFunction(pH->keyClass);
- while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- }
- return 0;
-}
-
-/* Remove a single entry from the hash table given a pointer to that
-** element and a hash on the element's key.
-*/
-static void removeElementGivenHash(
- Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- int h /* Hash value for the element */
-){
- if( elem->prev ){
- elem->prev->next = elem->next;
- }else{
- pH->first = elem->next;
- }
- if( elem->next ){
- elem->next->prev = elem->prev;
- }
- if( pH->ht[h].chain==elem ){
- pH->ht[h].chain = elem->next;
- }
- pH->ht[h].count--;
- if( pH->ht[h].count<=0 ){
- pH->ht[h].chain = 0;
- }
- if( pH->copyKey && elem->pKey ){
- sqliteFree(elem->pKey);
- }
- sqliteFree( elem );
- pH->count--;
-}
-
-/* Attempt to locate an element of the hash table pH with a key
-** that matches pKey,nKey. Return the data for this element if it is
-** found, or NULL if there is no match.
-*/
-void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
- int h; /* A hash on key */
- HashElem *elem; /* The element that matches key */
- int (*xHash)(const void*,int); /* The hash function */
-
- if( pH==0 || pH->ht==0 ) return 0;
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- h = (*xHash)(pKey,nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
- return elem ? elem->data : 0;
-}
-
-/* Insert an element into the hash table pH. The key is pKey,nKey
-** and the data is "data".
-**
-** If no element exists with a matching key, then a new
-** element is created. A copy of the key is made if the copyKey
-** flag is set. NULL is returned.
-**
-** If another element already exists with the same key, then the
-** new data replaces the old data and the old data is returned.
-** The key is not copied in this instance. If a malloc fails, then
-** the new data is returned and the hash table is unchanged.
-**
-** If the "data" parameter to this function is NULL, then the
-** element corresponding to "key" is removed from the hash table.
-*/
-void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
- int hraw; /* Raw hash value of the key */
- int h; /* the hash of the key modulo hash table size */
- HashElem *elem; /* Used to loop thru the element list */
- HashElem *new_elem; /* New element added to the pH */
- int (*xHash)(const void*,int); /* The hash function */
-
- assert( pH!=0 );
- xHash = hashFunction(pH->keyClass);
- assert( xHash!=0 );
- hraw = (*xHash)(pKey, nKey);
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = findElementGivenHash(pH,pKey,nKey,h);
- if( elem ){
- void *old_data = elem->data;
- if( data==0 ){
- removeElementGivenHash(pH,elem,h);
- }else{
- elem->data = data;
- }
- return old_data;
- }
- if( data==0 ) return 0;
- new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) );
- if( new_elem==0 ) return data;
- if( pH->copyKey && pKey!=0 ){
- new_elem->pKey = sqliteMallocRaw( nKey );
- if( new_elem->pKey==0 ){
- sqliteFree(new_elem);
- return data;
- }
- memcpy((void*)new_elem->pKey, pKey, nKey);
- }else{
- new_elem->pKey = (void*)pKey;
- }
- new_elem->nKey = nKey;
- pH->count++;
- if( pH->htsize==0 ) rehash(pH,8);
- if( pH->htsize==0 ){
- pH->count = 0;
- sqliteFree(new_elem);
- return data;
- }
- if( pH->count > pH->htsize ){
- rehash(pH,pH->htsize*2);
- }
- assert( (pH->htsize & (pH->htsize-1))==0 );
- h = hraw & (pH->htsize-1);
- elem = pH->ht[h].chain;
- if( elem ){
- new_elem->next = elem;
- new_elem->prev = elem->prev;
- if( elem->prev ){ elem->prev->next = new_elem; }
- else { pH->first = new_elem; }
- elem->prev = new_elem;
- }else{
- new_elem->next = pH->first;
- new_elem->prev = 0;
- if( pH->first ){ pH->first->prev = new_elem; }
- pH->first = new_elem;
- }
- pH->ht[h].count++;
- pH->ht[h].chain = new_elem;
- new_elem->data = data;
- return 0;
-}
diff --git a/ext/sqlite/libsqlite/src/hash.h b/ext/sqlite/libsqlite/src/hash.h
deleted file mode 100644
index 5f6335e1c8..0000000000
--- a/ext/sqlite/libsqlite/src/hash.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
-** 2001 September 22
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This is the header file for the generic hash-table implemenation
-** used in SQLite.
-**
-** $Id$
-*/
-#ifndef _SQLITE_HASH_H_
-#define _SQLITE_HASH_H_
-
-/* Forward declarations of structures. */
-typedef struct Hash Hash;
-typedef struct HashElem HashElem;
-
-/* A complete hash table is an instance of the following structure.
-** The internals of this structure are intended to be opaque -- client
-** code should not attempt to access or modify the fields of this structure
-** directly. Change this structure only by using the routines below.
-** However, many of the "procedures" and "functions" for modifying and
-** accessing this structure are really macros, so we can't really make
-** this structure opaque.
-*/
-struct Hash {
- char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */
- char copyKey; /* True if copy of key made on insert */
- int count; /* Number of entries in this table */
- HashElem *first; /* The first element of the array */
- int htsize; /* Number of buckets in the hash table */
- struct _ht { /* the hash table */
- int count; /* Number of entries with this hash */
- HashElem *chain; /* Pointer to first entry with this hash */
- } *ht;
-};
-
-/* Each element in the hash table is an instance of the following
-** structure. All elements are stored on a single doubly-linked list.
-**
-** Again, this structure is intended to be opaque, but it can't really
-** be opaque because it is used by macros.
-*/
-struct HashElem {
- HashElem *next, *prev; /* Next and previous elements in the table */
- void *data; /* Data associated with this element */
- void *pKey; int nKey; /* Key associated with this element */
-};
-
-/*
-** There are 4 different modes of operation for a hash table:
-**
-** SQLITE_HASH_INT nKey is used as the key and pKey is ignored.
-**
-** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored.
-**
-** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long
-** (including the null-terminator, if any). Case
-** is ignored in comparisons.
-**
-** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long.
-** memcmp() is used to compare keys.
-**
-** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
-** if the copyKey parameter to HashInit is 1.
-*/
-#define SQLITE_HASH_INT 1
-/* #define SQLITE_HASH_POINTER 2 // NOT USED */
-#define SQLITE_HASH_STRING 3
-#define SQLITE_HASH_BINARY 4
-
-/*
-** Access routines. To delete, insert a NULL pointer.
-*/
-void sqliteHashInit(Hash*, int keytype, int copyKey);
-void *sqliteHashInsert(Hash*, const void *pKey, int nKey, void *pData);
-void *sqliteHashFind(const Hash*, const void *pKey, int nKey);
-void sqliteHashClear(Hash*);
-
-/*
-** Macros for looping over all elements of a hash table. The idiom is
-** like this:
-**
-** Hash h;
-** HashElem *p;
-** ...
-** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
-** SomeStructure *pData = sqliteHashData(p);
-** // do something with pData
-** }
-*/
-#define sqliteHashFirst(H) ((H)->first)
-#define sqliteHashNext(E) ((E)->next)
-#define sqliteHashData(E) ((E)->data)
-#define sqliteHashKey(E) ((E)->pKey)
-#define sqliteHashKeysize(E) ((E)->nKey)
-
-/*
-** Number of entries in a hash table
-*/
-#define sqliteHashCount(H) ((H)->count)
-
-#endif /* _SQLITE_HASH_H_ */
diff --git a/ext/sqlite/libsqlite/src/insert.c b/ext/sqlite/libsqlite/src/insert.c
deleted file mode 100644
index 86c581edee..0000000000
--- a/ext/sqlite/libsqlite/src/insert.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains C code routines that are called by the parser
-** to handle INSERT statements in SQLite.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** This routine is call to handle SQL of the following forms:
-**
-** insert into TABLE (IDLIST) values(EXPRLIST)
-** insert into TABLE (IDLIST) select
-**
-** The IDLIST following the table name is always optional. If omitted,
-** then a list of all columns for the table is substituted. The IDLIST
-** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted.
-**
-** The pList parameter holds EXPRLIST in the first form of the INSERT
-** statement above, and pSelect is NULL. For the second form, pList is
-** NULL and pSelect is a pointer to the select statement used to generate
-** data for the insert.
-**
-** The code generated follows one of three templates. For a simple
-** select with data coming from a VALUES clause, the code executes
-** once straight down through. The template looks like this:
-**
-** open write cursor to <table> and its indices
-** puts VALUES clause expressions onto the stack
-** write the resulting record into <table>
-** cleanup
-**
-** If the statement is of the form
-**
-** INSERT INTO <table> SELECT ...
-**
-** And the SELECT clause does not read from <table> at any time, then
-** the generated code follows this template:
-**
-** goto B
-** A: setup for the SELECT
-** loop over the tables in the SELECT
-** gosub C
-** end loop
-** cleanup after the SELECT
-** goto D
-** B: open write cursor to <table> and its indices
-** goto A
-** C: insert the select result into <table>
-** return
-** D: cleanup
-**
-** The third template is used if the insert statement takes its
-** values from a SELECT but the data is being inserted into a table
-** that is also read as part of the SELECT. In the third form,
-** we have to use a intermediate table to store the results of
-** the select. The template is like this:
-**
-** goto B
-** A: setup for the SELECT
-** loop over the tables in the SELECT
-** gosub C
-** end loop
-** cleanup after the SELECT
-** goto D
-** C: insert the select result into the intermediate table
-** return
-** B: open a cursor to an intermediate table
-** goto A
-** D: open write cursor to <table> and its indices
-** loop over the intermediate table
-** transfer values form intermediate table into <table>
-** end the loop
-** cleanup
-*/
-void sqliteInsert(
- Parse *pParse, /* Parser context */
- SrcList *pTabList, /* Name of table into which we are inserting */
- ExprList *pList, /* List of values to be inserted */
- Select *pSelect, /* A SELECT statement to use as the data source */
- IdList *pColumn, /* Column names corresponding to IDLIST. */
- int onError /* How to handle constraint errors */
-){
- Table *pTab; /* The table to insert into */
- char *zTab; /* Name of the table into which we are inserting */
- const char *zDb; /* Name of the database holding this table */
- int i, j, idx; /* Loop counters */
- Vdbe *v; /* Generate code into this virtual machine */
- Index *pIdx; /* For looping over indices of the table */
- int nColumn; /* Number of columns in the data */
- int base; /* VDBE Cursor number for pTab */
- int iCont, iBreak; /* Beginning and end of the loop over srcTab */
- sqlite *db; /* The main database structure */
- int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
- int endOfLoop; /* Label for the end of the insertion loop */
- int useTempTable; /* Store SELECT results in intermediate table */
- int srcTab; /* Data comes from this temporary cursor if >=0 */
- int iSelectLoop; /* Address of code that implements the SELECT */
- int iCleanup; /* Address of the cleanup code */
- int iInsertBlock; /* Address of the subroutine used to insert data */
- int iCntMem; /* Memory cell used for the row counter */
- int isView; /* True if attempting to insert into a view */
-
- int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
- int before_triggers; /* True if there are BEFORE triggers */
- int after_triggers; /* True if there are AFTER triggers */
- int newIdx = -1; /* Cursor for the NEW table */
-
- if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
- db = pParse->db;
-
- /* Locate the table into which we will be inserting new information.
- */
- assert( pTabList->nSrc==1 );
- zTab = pTabList->a[0].zName;
- if( zTab==0 ) goto insert_cleanup;
- pTab = sqliteSrcListLookup(pParse, pTabList);
- if( pTab==0 ){
- goto insert_cleanup;
- }
- assert( pTab->iDb<db->nDb );
- zDb = db->aDb[pTab->iDb].zName;
- if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
- goto insert_cleanup;
- }
-
- /* Ensure that:
- * (a) the table is not read-only,
- * (b) that if it is a view then ON INSERT triggers exist
- */
- before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT,
- TK_BEFORE, TK_ROW, 0);
- after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT,
- TK_AFTER, TK_ROW, 0);
- row_triggers_exist = before_triggers || after_triggers;
- isView = pTab->pSelect!=0;
- if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
- goto insert_cleanup;
- }
- if( pTab==0 ) goto insert_cleanup;
-
- /* If pTab is really a view, make sure it has been initialized.
- */
- if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
- goto insert_cleanup;
- }
-
- /* Allocate a VDBE
- */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) goto insert_cleanup;
- sqliteBeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);
-
- /* if there are row triggers, allocate a temp table for new.* references. */
- if( row_triggers_exist ){
- newIdx = pParse->nTab++;
- }
-
- /* Figure out how many columns of data are supplied. If the data
- ** is coming from a SELECT statement, then this step also generates
- ** all the code to implement the SELECT statement and invoke a subroutine
- ** to process each row of the result. (Template 2.) If the SELECT
- ** statement uses the the table that is being inserted into, then the
- ** subroutine is also coded here. That subroutine stores the SELECT
- ** results in a temporary table. (Template 3.)
- */
- if( pSelect ){
- /* Data is coming from a SELECT. Generate code to implement that SELECT
- */
- int rc, iInitCode;
- iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
- iSelectLoop = sqliteVdbeCurrentAddr(v);
- iInsertBlock = sqliteVdbeMakeLabel(v);
- rc = sqliteSelect(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0);
- if( rc || pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
- iCleanup = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_Goto, 0, iCleanup);
- assert( pSelect->pEList );
- nColumn = pSelect->pEList->nExpr;
-
- /* Set useTempTable to TRUE if the result of the SELECT statement
- ** should be written into a temporary table. Set to FALSE if each
- ** row of the SELECT can be written directly into the result table.
- **
- ** A temp table must be used if the table being updated is also one
- ** of the tables being read by the SELECT statement. Also use a
- ** temp table in the case of row triggers.
- */
- if( row_triggers_exist ){
- useTempTable = 1;
- }else{
- int addr = sqliteVdbeFindOp(v, OP_OpenRead, pTab->tnum);
- useTempTable = 0;
- if( addr>0 ){
- VdbeOp *pOp = sqliteVdbeGetOp(v, addr-2);
- if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){
- useTempTable = 1;
- }
- }
- }
-
- if( useTempTable ){
- /* Generate the subroutine that SELECT calls to process each row of
- ** the result. Store the result in a temporary table
- */
- srcTab = pParse->nTab++;
- sqliteVdbeResolveLabel(v, iInsertBlock);
- sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
- sqliteVdbeAddOp(v, OP_NewRecno, srcTab, 0);
- sqliteVdbeAddOp(v, OP_Pull, 1, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, srcTab, 0);
- sqliteVdbeAddOp(v, OP_Return, 0, 0);
-
- /* The following code runs first because the GOTO at the very top
- ** of the program jumps to it. Create the temporary table, then jump
- ** back up and execute the SELECT code above.
- */
- sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
- sqliteVdbeAddOp(v, OP_OpenTemp, srcTab, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
- sqliteVdbeResolveLabel(v, iCleanup);
- }else{
- sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
- }
- }else{
- /* This is the case if the data for the INSERT is coming from a VALUES
- ** clause
- */
- SrcList dummy;
- assert( pList!=0 );
- srcTab = -1;
- useTempTable = 0;
- assert( pList );
- nColumn = pList->nExpr;
- dummy.nSrc = 0;
- for(i=0; i<nColumn; i++){
- if( sqliteExprResolveIds(pParse, &dummy, 0, pList->a[i].pExpr) ){
- goto insert_cleanup;
- }
- if( sqliteExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){
- goto insert_cleanup;
- }
- }
- }
-
- /* Make sure the number of columns in the source data matches the number
- ** of columns to be inserted into the table.
- */
- if( pColumn==0 && nColumn!=pTab->nCol ){
- sqliteErrorMsg(pParse,
- "table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol, nColumn);
- goto insert_cleanup;
- }
- if( pColumn!=0 && nColumn!=pColumn->nId ){
- sqliteErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
- goto insert_cleanup;
- }
-
- /* If the INSERT statement included an IDLIST term, then make sure
- ** all elements of the IDLIST really are columns of the table and
- ** remember the column indices.
- **
- ** If the table has an INTEGER PRIMARY KEY column and that column
- ** is named in the IDLIST, then record in the keyColumn variable
- ** the index into IDLIST of the primary key column. keyColumn is
- ** the index of the primary key as it appears in IDLIST, not as
- ** is appears in the original table. (The index of the primary
- ** key in the original table is pTab->iPKey.)
- */
- if( pColumn ){
- for(i=0; i<pColumn->nId; i++){
- pColumn->a[i].idx = -1;
- }
- for(i=0; i<pColumn->nId; i++){
- for(j=0; j<pTab->nCol; j++){
- if( sqliteStrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
- pColumn->a[i].idx = j;
- if( j==pTab->iPKey ){
- keyColumn = i;
- }
- break;
- }
- }
- if( j>=pTab->nCol ){
- if( sqliteIsRowid(pColumn->a[i].zName) ){
- keyColumn = i;
- }else{
- sqliteErrorMsg(pParse, "table %S has no column named %s",
- pTabList, 0, pColumn->a[i].zName);
- pParse->nErr++;
- goto insert_cleanup;
- }
- }
- }
- }
-
- /* If there is no IDLIST term but the table has an integer primary
- ** key, the set the keyColumn variable to the primary key column index
- ** in the original table definition.
- */
- if( pColumn==0 ){
- keyColumn = pTab->iPKey;
- }
-
- /* Open the temp table for FOR EACH ROW triggers
- */
- if( row_triggers_exist ){
- sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
- }
-
- /* Initialize the count of rows to be inserted
- */
- if( db->flags & SQLITE_CountRows ){
- iCntMem = pParse->nMem++;
- sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1);
- }
-
- /* Open tables and indices if there are no row triggers */
- if( !row_triggers_exist ){
- base = pParse->nTab;
- idx = sqliteOpenTableAndIndices(pParse, pTab, base);
- pParse->nTab += idx;
- }
-
- /* If the data source is a temporary table, then we have to create
- ** a loop because there might be multiple rows of data. If the data
- ** source is a subroutine call from the SELECT statement, then we need
- ** to launch the SELECT statement processing.
- */
- if( useTempTable ){
- iBreak = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
- iCont = sqliteVdbeCurrentAddr(v);
- }else if( pSelect ){
- sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
- sqliteVdbeResolveLabel(v, iInsertBlock);
- }
-
- /* Run the BEFORE and INSTEAD OF triggers, if there are any
- */
- endOfLoop = sqliteVdbeMakeLabel(v);
- if( before_triggers ){
-
- /* build the NEW.* reference row. Note that if there is an INTEGER
- ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
- ** translated into a unique ID for the row. But on a BEFORE trigger,
- ** we do not know what the unique ID will be (because the insert has
- ** not happened yet) so we substitute a rowid of -1
- */
- if( keyColumn<0 ){
- sqliteVdbeAddOp(v, OP_Integer, -1, 0);
- }else if( useTempTable ){
- sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
- }else if( pSelect ){
- sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
- }else{
- sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
- sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_Integer, -1, 0);
- sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
- }
-
- /* Create the new column data
- */
- for(i=0; i<pTab->nCol; i++){
- if( pColumn==0 ){
- j = i;
- }else{
- for(j=0; j<pColumn->nId; j++){
- if( pColumn->a[j].idx==i ) break;
- }
- }
- if( pColumn && j>=pColumn->nId ){
- sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
- }else if( useTempTable ){
- sqliteVdbeAddOp(v, OP_Column, srcTab, j);
- }else if( pSelect ){
- sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
- }else{
- sqliteExprCode(pParse, pList->a[j].pExpr);
- }
- }
- sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
-
- /* Fire BEFORE or INSTEAD OF triggers */
- if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab,
- newIdx, -1, onError, endOfLoop) ){
- goto insert_cleanup;
- }
- }
-
- /* If any triggers exists, the opening of tables and indices is deferred
- ** until now.
- */
- if( row_triggers_exist && !isView ){
- base = pParse->nTab;
- idx = sqliteOpenTableAndIndices(pParse, pTab, base);
- pParse->nTab += idx;
- }
-
- /* Push the record number for the new entry onto the stack. The
- ** record number is a randomly generate integer created by NewRecno
- ** except when the table has an INTEGER PRIMARY KEY column, in which
- ** case the record number is the same as that column.
- */
- if( !isView ){
- if( keyColumn>=0 ){
- if( useTempTable ){
- sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
- }else if( pSelect ){
- sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
- }else{
- sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
- }
- /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
- ** to generate a unique primary key value.
- */
- sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
- sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
- }else{
- sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
- }
-
- /* Push onto the stack, data for all columns of the new entry, beginning
- ** with the first column.
- */
- for(i=0; i<pTab->nCol; i++){
- if( i==pTab->iPKey ){
- /* The value of the INTEGER PRIMARY KEY column is always a NULL.
- ** Whenever this column is read, the record number will be substituted
- ** in its place. So will fill this column with a NULL to avoid
- ** taking up data space with information that will never be used. */
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- continue;
- }
- if( pColumn==0 ){
- j = i;
- }else{
- for(j=0; j<pColumn->nId; j++){
- if( pColumn->a[j].idx==i ) break;
- }
- }
- if( pColumn && j>=pColumn->nId ){
- sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
- }else if( useTempTable ){
- sqliteVdbeAddOp(v, OP_Column, srcTab, j);
- }else if( pSelect ){
- sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1);
- }else{
- sqliteExprCode(pParse, pList->a[j].pExpr);
- }
- }
-
- /* Generate code to check constraints and generate index keys and
- ** do the insertion.
- */
- sqliteGenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
- 0, onError, endOfLoop);
- sqliteCompleteInsertion(pParse, pTab, base, 0,0,0,
- after_triggers ? newIdx : -1);
- }
-
- /* Update the count of rows that are inserted
- */
- if( (db->flags & SQLITE_CountRows)!=0 ){
- sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0);
- }
-
- if( row_triggers_exist ){
- /* Close all tables opened */
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Close, base, 0);
- for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
- sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
- }
- }
-
- /* Code AFTER triggers */
- if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1,
- onError, endOfLoop) ){
- goto insert_cleanup;
- }
- }
-
- /* The bottom of the loop, if the data source is a SELECT statement
- */
- sqliteVdbeResolveLabel(v, endOfLoop);
- if( useTempTable ){
- sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);
- sqliteVdbeResolveLabel(v, iBreak);
- sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
- }else if( pSelect ){
- sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
- sqliteVdbeAddOp(v, OP_Return, 0, 0);
- sqliteVdbeResolveLabel(v, iCleanup);
- }
-
- if( !row_triggers_exist ){
- /* Close all tables opened */
- sqliteVdbeAddOp(v, OP_Close, base, 0);
- for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
- sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
- }
- }
-
- sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
- sqliteEndWriteOperation(pParse);
-
- /*
- ** Return the number of rows inserted.
- */
- if( db->flags & SQLITE_CountRows ){
- sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC);
- sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0);
- sqliteVdbeAddOp(v, OP_Callback, 1, 0);
- }
-
-insert_cleanup:
- sqliteSrcListDelete(pTabList);
- if( pList ) sqliteExprListDelete(pList);
- if( pSelect ) sqliteSelectDelete(pSelect);
- sqliteIdListDelete(pColumn);
-}
-
-/*
-** Generate code to do a constraint check prior to an INSERT or an UPDATE.
-**
-** When this routine is called, the stack contains (from bottom to top)
-** the following values:
-**
-** 1. The recno of the row to be updated before the update. This
-** value is omitted unless we are doing an UPDATE that involves a
-** change to the record number.
-**
-** 2. The recno of the row after the update.
-**
-** 3. The data in the first column of the entry after the update.
-**
-** i. Data from middle columns...
-**
-** N. The data in the last column of the entry after the update.
-**
-** The old recno shown as entry (1) above is omitted unless both isUpdate
-** and recnoChng are 1. isUpdate is true for UPDATEs and false for
-** INSERTs and recnoChng is true if the record number is being changed.
-**
-** The code generated by this routine pushes additional entries onto
-** the stack which are the keys for new index entries for the new record.
-** The order of index keys is the same as the order of the indices on
-** the pTable->pIndex list. A key is only created for index i if
-** aIdxUsed!=0 and aIdxUsed[i]!=0.
-**
-** This routine also generates code to check constraints. NOT NULL,
-** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
-** then the appropriate action is performed. There are five possible
-** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
-**
-** Constraint type Action What Happens
-** --------------- ---------- ----------------------------------------
-** any ROLLBACK The current transaction is rolled back and
-** sqlite_exec() returns immediately with a
-** return code of SQLITE_CONSTRAINT.
-**
-** any ABORT Back out changes from the current command
-** only (do not do a complete rollback) then
-** cause sqlite_exec() to return immediately
-** with SQLITE_CONSTRAINT.
-**
-** any FAIL Sqlite_exec() returns immediately with a
-** return code of SQLITE_CONSTRAINT. The
-** transaction is not rolled back and any
-** prior changes are retained.
-**
-** any IGNORE The record number and data is popped from
-** the stack and there is an immediate jump
-** to label ignoreDest.
-**
-** NOT NULL REPLACE The NULL value is replace by the default
-** value for that column. If the default value
-** is NULL, the action is the same as ABORT.
-**
-** UNIQUE REPLACE The other row that conflicts with the row
-** being inserted is removed.
-**
-** CHECK REPLACE Illegal. The results in an exception.
-**
-** Which action to take is determined by the overrideError parameter.
-** Or if overrideError==OE_Default, then the pParse->onError parameter
-** is used. Or if pParse->onError==OE_Default then the onError value
-** for the constraint is used.
-**
-** The calling routine must open a read/write cursor for pTab with
-** cursor number "base". All indices of pTab must also have open
-** read/write cursors with cursor number base+i for the i-th cursor.
-** Except, if there is no possibility of a REPLACE action then
-** cursors do not need to be open for indices where aIdxUsed[i]==0.
-**
-** If the isUpdate flag is true, it means that the "base" cursor is
-** initially pointing to an entry that is being updated. The isUpdate
-** flag causes extra code to be generated so that the "base" cursor
-** is still pointing at the same entry after the routine returns.
-** Without the isUpdate flag, the "base" cursor might be moved.
-*/
-void sqliteGenerateConstraintChecks(
- Parse *pParse, /* The parser context */
- Table *pTab, /* the table into which we are inserting */
- int base, /* Index of a read/write cursor pointing at pTab */
- char *aIdxUsed, /* Which indices are used. NULL means all are used */
- int recnoChng, /* True if the record number will change */
- int isUpdate, /* True for UPDATE, False for INSERT */
- int overrideError, /* Override onError to this if not OE_Default */
- int ignoreDest /* Jump to this label on an OE_Ignore resolution */
-){
- int i;
- Vdbe *v;
- int nCol;
- int onError;
- int addr;
- int extra;
- int iCur;
- Index *pIdx;
- int seenReplace = 0;
- int jumpInst1, jumpInst2;
- int contAddr;
- int hasTwoRecnos = (isUpdate && recnoChng);
-
- v = sqliteGetVdbe(pParse);
- assert( v!=0 );
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
- nCol = pTab->nCol;
-
- /* Test all NOT NULL constraints.
- */
- for(i=0; i<nCol; i++){
- if( i==pTab->iPKey ){
- continue;
- }
- onError = pTab->aCol[i].notNull;
- if( onError==OE_None ) continue;
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( pParse->db->onError!=OE_Default ){
- onError = pParse->db->onError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
- if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
- onError = OE_Abort;
- }
- sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
- addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0);
- switch( onError ){
- case OE_Rollback:
- case OE_Abort:
- case OE_Fail: {
- char *zMsg = 0;
- sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
- sqliteSetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,
- " may not be NULL", (char*)0);
- sqliteVdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);
- break;
- }
- case OE_Ignore: {
- sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
- break;
- }
- case OE_Replace: {
- sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
- sqliteVdbeAddOp(v, OP_Push, nCol-i, 0);
- break;
- }
- default: assert(0);
- }
- sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
- }
-
- /* Test all CHECK constraints
- */
- /**** TBD ****/
-
- /* If we have an INTEGER PRIMARY KEY, make sure the primary key
- ** of the new record does not previously exist. Except, if this
- ** is an UPDATE and the primary key is not changing, that is OK.
- */
- if( recnoChng ){
- onError = pTab->keyConf;
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( pParse->db->onError!=OE_Default ){
- onError = pParse->db->onError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
-
- if( isUpdate ){
- sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
- sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
- jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);
- }
- sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
- jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
- switch( onError ){
- default: {
- onError = OE_Abort;
- /* Fall thru into the next case */
- }
- case OE_Rollback:
- case OE_Abort:
- case OE_Fail: {
- sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
- "PRIMARY KEY must be unique", P3_STATIC);
- break;
- }
- case OE_Replace: {
- sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
- if( isUpdate ){
- sqliteVdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
- sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
- }
- seenReplace = 1;
- break;
- }
- case OE_Ignore: {
- assert( seenReplace==0 );
- sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
- break;
- }
- }
- contAddr = sqliteVdbeCurrentAddr(v);
- sqliteVdbeChangeP2(v, jumpInst2, contAddr);
- if( isUpdate ){
- sqliteVdbeChangeP2(v, jumpInst1, contAddr);
- sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
- sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
- }
- }
-
- /* Test all UNIQUE constraints by creating entries for each UNIQUE
- ** index and making sure that duplicate entries do not already exist.
- ** Add the new records to the indices as we go.
- */
- extra = -1;
- for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
- if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; /* Skip unused indices */
- extra++;
-
- /* Create a key for accessing the index entry */
- sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1);
- for(i=0; i<pIdx->nColumn; i++){
- int idx = pIdx->aiColumn[i];
- if( idx==pTab->iPKey ){
- sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
- }else{
- sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
- }
- }
- jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
- if( pParse->db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
-
- /* Find out what action to take in case there is an indexing conflict */
- onError = pIdx->onError;
- if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( pParse->db->onError!=OE_Default ){
- onError = pParse->db->onError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
- if( seenReplace ){
- if( onError==OE_Ignore ) onError = OE_Replace;
- else if( onError==OE_Fail ) onError = OE_Abort;
- }
-
-
- /* Check to see if the new index entry will be unique */
- sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
- jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
-
- /* Generate code that executes if the new index entry is not unique */
- switch( onError ){
- case OE_Rollback:
- case OE_Abort:
- case OE_Fail: {
- int j, n1, n2;
- char zErrMsg[200];
- strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column ");
- n1 = strlen(zErrMsg);
- for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){
- char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
- n2 = strlen(zCol);
- if( j>0 ){
- strcpy(&zErrMsg[n1], ", ");
- n1 += 2;
- }
- if( n1+n2>sizeof(zErrMsg)-30 ){
- strcpy(&zErrMsg[n1], "...");
- n1 += 3;
- break;
- }else{
- strcpy(&zErrMsg[n1], zCol);
- n1 += n2;
- }
- }
- strcpy(&zErrMsg[n1],
- pIdx->nColumn>1 ? " are not unique" : " is not unique");
- sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);
- break;
- }
- case OE_Ignore: {
- assert( seenReplace==0 );
- sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
- break;
- }
- case OE_Replace: {
- sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0);
- if( isUpdate ){
- sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
- sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
- }
- seenReplace = 1;
- break;
- }
- default: assert(0);
- }
- contAddr = sqliteVdbeCurrentAddr(v);
-#if NULL_DISTINCT_FOR_UNIQUE
- sqliteVdbeChangeP2(v, jumpInst1, contAddr);
-#endif
- sqliteVdbeChangeP2(v, jumpInst2, contAddr);
- }
-}
-
-/*
-** This routine generates code to finish the INSERT or UPDATE operation
-** that was started by a prior call to sqliteGenerateConstraintChecks.
-** The stack must contain keys for all active indices followed by data
-** and the recno for the new entry. This routine creates the new
-** entries in all indices and in the main table.
-**
-** The arguments to this routine should be the same as the first six
-** arguments to sqliteGenerateConstraintChecks.
-*/
-void sqliteCompleteInsertion(
- Parse *pParse, /* The parser context */
- Table *pTab, /* the table into which we are inserting */
- int base, /* Index of a read/write cursor pointing at pTab */
- char *aIdxUsed, /* Which indices are used. NULL means all are used */
- int recnoChng, /* True if the record number will change */
- int isUpdate, /* True for UPDATE, False for INSERT */
- int newIdx /* Index of NEW table for triggers. -1 if none */
-){
- int i;
- Vdbe *v;
- int nIdx;
- Index *pIdx;
-
- v = sqliteGetVdbe(pParse);
- assert( v!=0 );
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
- for(i=nIdx-1; i>=0; i--){
- if( aIdxUsed && aIdxUsed[i]==0 ) continue;
- sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, 0);
- }
- sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
- if( newIdx>=0 ){
- sqliteVdbeAddOp(v, OP_Dup, 1, 0);
- sqliteVdbeAddOp(v, OP_Dup, 1, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
- }
- sqliteVdbeAddOp(v, OP_PutIntKey, base,
- (pParse->trigStack?0:OPFLAG_NCHANGE) |
- (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);
- if( isUpdate && recnoChng ){
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- }
-}
-
-/*
-** Generate code that will open write cursors for a table and for all
-** indices of that table. The "base" parameter is the cursor number used
-** for the table. Indices are opened on subsequent cursors.
-**
-** Return the total number of cursors opened. This is always at least
-** 1 (for the main table) plus more for each cursor.
-*/
-int sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base){
- int i;
- Index *pIdx;
- Vdbe *v = sqliteGetVdbe(pParse);
- assert( v!=0 );
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenWrite, base, pTab->tnum, pTab->zName, P3_STATIC);
- for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC);
- }
- return i;
-}
diff --git a/ext/sqlite/libsqlite/src/libsqlite.dsp b/ext/sqlite/libsqlite/src/libsqlite.dsp
deleted file mode 100755
index a60543c0eb..0000000000
--- a/ext/sqlite/libsqlite/src/libsqlite.dsp
+++ /dev/null
@@ -1,353 +0,0 @@
-# Microsoft Developer Studio Project File - Name="libsqlite" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=libsqlite - Win32 Debug_TS
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "libsqlite.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "libsqlite.mak" CFG="libsqlite - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "libsqlite - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
-!MESSAGE "libsqlite - Win32 Release_TS" (based on "Win32 (x86) Static Library")
-!MESSAGE "libsqlite - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "libsqlite - Win32 Debug_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug_TS"
-# PROP BASE Intermediate_Dir "Debug_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "..\..\Debug_TS"
-# PROP Intermediate_Dir "..\..\Debug_TS"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /GZ /c
-# ADD BASE RSC /l 0x406 /d "_DEBUG"
-# ADD RSC /l 0x406 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release_TS"
-# PROP BASE Intermediate_Dir "Release_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\..\Release_TS"
-# PROP Intermediate_Dir "..\..\Release_TS"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c
-# ADD BASE RSC /l 0x406 /d "NDEBUG"
-# ADD RSC /l 0x406 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TSDbg"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "libsqlite___Win32_Release_TSDbg"
-# PROP BASE Intermediate_Dir "libsqlite___Win32_Release_TSDbg"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\..\Release_TSDbg"
-# PROP Intermediate_Dir "..\..\Release_TSDbg"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D THREADSAFE=1 /YX /FD /c
-# ADD BASE RSC /l 0x406 /d "NDEBUG"
-# ADD RSC /l 0x406 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo /out:"Release_TS\libsqlite.lib"
-# ADD LIB32 /nologo
-
-!ENDIF
-
-# Begin Target
-
-# Name "libsqlite - Win32 Debug_TS"
-# Name "libsqlite - Win32 Release_TS"
-# Name "libsqlite - Win32 Release_TSDbg"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=attach.c
-# End Source File
-# Begin Source File
-
-SOURCE=auth.c
-# End Source File
-# Begin Source File
-
-SOURCE=btree.c
-# End Source File
-# Begin Source File
-
-SOURCE=btree_rb.c
-# End Source File
-# Begin Source File
-
-SOURCE=build.c
-# End Source File
-# Begin Source File
-
-SOURCE=copy.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\date.c
-# End Source File
-# Begin Source File
-
-SOURCE=delete.c
-# End Source File
-# Begin Source File
-
-SOURCE=encode.c
-# End Source File
-# Begin Source File
-
-SOURCE=expr.c
-# End Source File
-# Begin Source File
-
-SOURCE=func.c
-# End Source File
-# Begin Source File
-
-SOURCE=hash.c
-# End Source File
-# Begin Source File
-
-SOURCE=insert.c
-# End Source File
-# Begin Source File
-
-SOURCE=main.c
-# End Source File
-# Begin Source File
-
-SOURCE=opcodes.c
-# End Source File
-# Begin Source File
-
-SOURCE=os.c
-# End Source File
-# Begin Source File
-
-SOURCE=pager.c
-# End Source File
-# Begin Source File
-
-SOURCE=parse.c
-# End Source File
-# Begin Source File
-
-SOURCE=pragma.c
-# End Source File
-# Begin Source File
-
-SOURCE=printf.c
-# End Source File
-# Begin Source File
-
-SOURCE=random.c
-# End Source File
-# Begin Source File
-
-SOURCE=select.c
-# End Source File
-# Begin Source File
-
-SOURCE=table.c
-# End Source File
-# Begin Source File
-
-SOURCE=tokenize.c
-# End Source File
-# Begin Source File
-
-SOURCE=trigger.c
-# End Source File
-# Begin Source File
-
-SOURCE=update.c
-# End Source File
-# Begin Source File
-
-SOURCE=util.c
-# End Source File
-# Begin Source File
-
-SOURCE=vacuum.c
-# End Source File
-# Begin Source File
-
-SOURCE=vdbe.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\vdbeaux.c
-# End Source File
-# Begin Source File
-
-SOURCE=where.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=btree.h
-# End Source File
-# Begin Source File
-
-SOURCE=config_static.w32.h
-
-!IF "$(CFG)" == "libsqlite - Win32 Debug_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=config_static.w32.h
-
-"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\config.h
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=config_static.w32.h
-
-"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\config.h
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TSDbg"
-
-# Begin Custom Build
-InputDir=.
-InputPath=config_static.w32.h
-
-"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\config.h
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=hash.h
-# End Source File
-# Begin Source File
-
-SOURCE=opcodes.h
-# End Source File
-# Begin Source File
-
-SOURCE=os.h
-# End Source File
-# Begin Source File
-
-SOURCE=pager.h
-# End Source File
-# Begin Source File
-
-SOURCE=parse.h
-# End Source File
-# Begin Source File
-
-SOURCE=sqlite.w32.h
-
-!IF "$(CFG)" == "libsqlite - Win32 Debug_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=sqlite.w32.h
-
-"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\sqlite.h
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TS"
-
-# Begin Custom Build
-InputDir=.
-InputPath=sqlite.w32.h
-
-"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\sqlite.h
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "libsqlite - Win32 Release_TSDbg"
-
-# Begin Custom Build
-InputDir=.
-InputPath=sqlite.w32.h
-
-"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\sqlite.h
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=sqliteInt.h
-# End Source File
-# Begin Source File
-
-SOURCE=vdbe.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/ext/sqlite/libsqlite/src/main.c b/ext/sqlite/libsqlite/src/main.c
deleted file mode 100644
index c16300558a..0000000000
--- a/ext/sqlite/libsqlite/src/main.c
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** Main file for the SQLite library. The routines in this file
-** implement the programmer interface to the library. Routines in
-** other files are for internal use by SQLite and should not be
-** accessed by users of the library.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include "os.h"
-#include <ctype.h>
-
-/*
-** A pointer to this structure is used to communicate information
-** from sqliteInit into the sqliteInitCallback.
-*/
-typedef struct {
- sqlite *db; /* The database being initialized */
- char **pzErrMsg; /* Error message stored here */
-} InitData;
-
-/*
-** Fill the InitData structure with an error message that indicates
-** that the database is corrupt.
-*/
-static void corruptSchema(InitData *pData, const char *zExtra){
- sqliteSetString(pData->pzErrMsg, "malformed database schema",
- zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
-}
-
-/*
-** This is the callback routine for the code that initializes the
-** database. See sqliteInit() below for additional information.
-**
-** Each callback contains the following information:
-**
-** argv[0] = "file-format" or "schema-cookie" or "table" or "index"
-** argv[1] = table or index name or meta statement type.
-** argv[2] = root page number for table or index. NULL for meta.
-** argv[3] = SQL text for a CREATE TABLE or CREATE INDEX statement.
-** argv[4] = "1" for temporary files, "0" for main database, "2" or more
-** for auxiliary database files.
-**
-*/
-static
-int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
- InitData *pData = (InitData*)pInit;
- int nErr = 0;
-
- assert( argc==5 );
- if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
- if( argv[0]==0 ){
- corruptSchema(pData, 0);
- return 1;
- }
- switch( argv[0][0] ){
- case 'v':
- case 'i':
- case 't': { /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
- sqlite *db = pData->db;
- if( argv[2]==0 || argv[4]==0 ){
- corruptSchema(pData, 0);
- return 1;
- }
- if( argv[3] && argv[3][0] ){
- /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
- ** But because db->init.busy is set to 1, no VDBE code is generated
- ** or executed. All the parser does is build the internal data
- ** structures that describe the table, index, or view.
- */
- char *zErr;
- assert( db->init.busy );
- db->init.iDb = atoi(argv[4]);
- assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
- db->init.newTnum = atoi(argv[2]);
- if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
- corruptSchema(pData, zErr);
- sqlite_freemem(zErr);
- }
- db->init.iDb = 0;
- }else{
- /* If the SQL column is blank it means this is an index that
- ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
- ** constraint for a CREATE TABLE. The index should have already
- ** been created when we processed the CREATE TABLE. All we have
- ** to do here is record the root page number for that index.
- */
- int iDb;
- Index *pIndex;
-
- iDb = atoi(argv[4]);
- assert( iDb>=0 && iDb<db->nDb );
- pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);
- if( pIndex==0 || pIndex->tnum!=0 ){
- /* This can occur if there exists an index on a TEMP table which
- ** has the same name as another index on a permanent index. Since
- ** the permanent table is hidden by the TEMP table, we can also
- ** safely ignore the index on the permanent table.
- */
- /* Do Nothing */;
- }else{
- pIndex->tnum = atoi(argv[2]);
- }
- }
- break;
- }
- default: {
- /* This can not happen! */
- nErr = 1;
- assert( nErr==0 );
- }
- }
- return nErr;
-}
-
-/*
-** This is a callback procedure used to reconstruct a table. The
-** name of the table to be reconstructed is passed in as argv[0].
-**
-** This routine is used to automatically upgrade a database from
-** format version 1 or 2 to version 3. The correct operation of
-** this routine relys on the fact that no indices are used when
-** copying a table out to a temporary file.
-**
-** The change from version 2 to version 3 occurred between SQLite
-** version 2.5.6 and 2.6.0 on 2002-July-18.
-*/
-static
-int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){
- InitData *pData = (InitData*)pInit;
- int rc;
- Table *pTab;
- Trigger *pTrig;
- char *zErr = 0;
-
- pTab = sqliteFindTable(pData->db, argv[0], 0);
- assert( pTab!=0 );
- assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
- if( pTab ){
- pTrig = pTab->pTrigger;
- pTab->pTrigger = 0; /* Disable all triggers before rebuilding the table */
- }
- rc = sqlite_exec_printf(pData->db,
- "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; "
- "DELETE FROM '%q'; "
- "INSERT INTO '%q' SELECT * FROM sqlite_x; "
- "DROP TABLE sqlite_x;",
- 0, 0, &zErr, argv[0], argv[0], argv[0]);
- if( zErr ){
- if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg);
- *pData->pzErrMsg = zErr;
- }
-
- /* If an error occurred in the SQL above, then the transaction will
- ** rollback which will delete the internal symbol tables. This will
- ** cause the structure that pTab points to be deleted. In case that
- ** happened, we need to refetch pTab.
- */
- pTab = sqliteFindTable(pData->db, argv[0], 0);
- if( pTab ){
- assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
- pTab->pTrigger = pTrig; /* Re-enable triggers */
- }
- return rc!=SQLITE_OK;
-}
-
-
-
-/*
-** Attempt to read the database schema and initialize internal
-** data structures for a single database file. The index of the
-** database file is given by iDb. iDb==0 is used for the main
-** database. iDb==1 should never be used. iDb>=2 is used for
-** auxiliary databases. Return one of the SQLITE_ error codes to
-** indicate success or failure.
-*/
-static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
- int rc;
- BtCursor *curMain;
- int size;
- Table *pTab;
- char const *azArg[6];
- char zDbNum[30];
- int meta[SQLITE_N_BTREE_META];
- InitData initData;
- char const *zMasterSchema;
- char const *zMasterName;
- char *zSql = 0;
-
- /*
- ** The master database table has a structure like this
- */
- static char master_schema[] =
- "CREATE TABLE sqlite_master(\n"
- " type text,\n"
- " name text,\n"
- " tbl_name text,\n"
- " rootpage integer,\n"
- " sql text\n"
- ")"
- ;
- static char temp_master_schema[] =
- "CREATE TEMP TABLE sqlite_temp_master(\n"
- " type text,\n"
- " name text,\n"
- " tbl_name text,\n"
- " rootpage integer,\n"
- " sql text\n"
- ")"
- ;
-
- assert( iDb>=0 && iDb<db->nDb );
-
- /* zMasterSchema and zInitScript are set to point at the master schema
- ** and initialisation script appropriate for the database being
- ** initialised. zMasterName is the name of the master table.
- */
- if( iDb==1 ){
- zMasterSchema = temp_master_schema;
- zMasterName = TEMP_MASTER_NAME;
- }else{
- zMasterSchema = master_schema;
- zMasterName = MASTER_NAME;
- }
-
- /* Construct the schema table.
- */
- sqliteSafetyOff(db);
- azArg[0] = "table";
- azArg[1] = zMasterName;
- azArg[2] = "2";
- azArg[3] = zMasterSchema;
- sprintf(zDbNum, "%d", iDb);
- azArg[4] = zDbNum;
- azArg[5] = 0;
- initData.db = db;
- initData.pzErrMsg = pzErrMsg;
- sqliteInitCallback(&initData, 5, (char **)azArg, 0);
- pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
- if( pTab ){
- pTab->readOnly = 1;
- }else{
- return SQLITE_NOMEM;
- }
- sqliteSafetyOn(db);
-
- /* Create a cursor to hold the database open
- */
- if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
- rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
- if( rc ){
- sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
- return rc;
- }
-
- /* Get the database meta information
- */
- rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);
- if( rc ){
- sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
- sqliteBtreeCloseCursor(curMain);
- return rc;
- }
- db->aDb[iDb].schema_cookie = meta[1];
- if( iDb==0 ){
- db->next_cookie = meta[1];
- db->file_format = meta[2];
- size = meta[3];
- if( size==0 ){ size = MAX_PAGES; }
- db->cache_size = size;
- db->safety_level = meta[4];
- if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){
- db->temp_store = meta[6];
- }
- if( db->safety_level==0 ) db->safety_level = 2;
-
- /*
- ** file_format==1 Version 2.1.0.
- ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY.
- ** file_format==3 Version 2.6.0. Fix empty-string index bug.
- ** file_format==4 Version 2.7.0. Add support for separate numeric and
- ** text datatypes.
- */
- if( db->file_format==0 ){
- /* This happens if the database was initially empty */
- db->file_format = 4;
- }else if( db->file_format>4 ){
- sqliteBtreeCloseCursor(curMain);
- sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
- return SQLITE_ERROR;
- }
- }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
- assert( db->file_format>=4 );
- if( meta[2]==0 ){
- sqliteSetString(pzErrMsg, "cannot attach empty database: ",
- db->aDb[iDb].zName, (char*)0);
- }else{
- sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
- "database: ", db->aDb[iDb].zName, (char*)0);
- }
- sqliteBtreeClose(db->aDb[iDb].pBt);
- db->aDb[iDb].pBt = 0;
- return SQLITE_FORMAT;
- }
- sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
- sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);
-
- /* Read the schema information out of the schema tables
- */
- assert( db->init.busy );
- sqliteSafetyOff(db);
-
- /* The following SQL will read the schema from the master tables.
- ** The first version works with SQLite file formats 2 or greater.
- ** The second version is for format 1 files.
- **
- ** Beginning with file format 2, the rowid for new table entries
- ** (including entries in sqlite_master) is an increasing integer.
- ** So for file format 2 and later, we can play back sqlite_master
- ** and all the CREATE statements will appear in the right order.
- ** But with file format 1, table entries were random and so we
- ** have to make sure the CREATE TABLEs occur before their corresponding
- ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or
- ** CREATE TRIGGER in file format 1 because those constructs did
- ** not exist then.)
- */
- if( db->file_format>=2 ){
- sqliteSetString(&zSql,
- "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
- db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
- }else{
- sqliteSetString(&zSql,
- "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
- db->aDb[iDb].zName, "\".", zMasterName,
- " WHERE type IN ('table', 'index')"
- " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
- }
- rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
-
- sqliteFree(zSql);
- sqliteSafetyOn(db);
- sqliteBtreeCloseCursor(curMain);
- if( sqlite_malloc_failed ){
- sqliteSetString(pzErrMsg, "out of memory", (char*)0);
- rc = SQLITE_NOMEM;
- sqliteResetInternalSchema(db, 0);
- }
- if( rc==SQLITE_OK ){
- DbSetProperty(db, iDb, DB_SchemaLoaded);
- }else{
- sqliteResetInternalSchema(db, iDb);
- }
- return rc;
-}
-
-/*
-** Initialize all database files - the main database file, the file
-** used to store temporary tables, and any additional database files
-** created using ATTACH statements. Return a success code. If an
-** error occurs, write an error message into *pzErrMsg.
-**
-** After the database is initialized, the SQLITE_Initialized
-** bit is set in the flags field of the sqlite structure. An
-** attempt is made to initialize the database as soon as it
-** is opened. If that fails (perhaps because another process
-** has the sqlite_master table locked) than another attempt
-** is made the first time the database is accessed.
-*/
-int sqliteInit(sqlite *db, char **pzErrMsg){
- int i, rc;
-
- if( db->init.busy ) return SQLITE_OK;
- assert( (db->flags & SQLITE_Initialized)==0 );
- rc = SQLITE_OK;
- db->init.busy = 1;
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
- rc = sqliteInitOne(db, i, pzErrMsg);
- if( rc ){
- sqliteResetInternalSchema(db, i);
- }
- }
-
- /* Once all the other databases have been initialised, load the schema
- ** for the TEMP database. This is loaded last, as the TEMP database
- ** schema may contain references to objects in other databases.
- */
- if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
- rc = sqliteInitOne(db, 1, pzErrMsg);
- if( rc ){
- sqliteResetInternalSchema(db, 1);
- }
- }
-
- db->init.busy = 0;
- if( rc==SQLITE_OK ){
- db->flags |= SQLITE_Initialized;
- sqliteCommitInternalChanges(db);
- }
-
- /* If the database is in formats 1 or 2, then upgrade it to
- ** version 3. This will reconstruct all indices. If the
- ** upgrade fails for any reason (ex: out of disk space, database
- ** is read only, interrupt received, etc.) then fail the init.
- */
- if( rc==SQLITE_OK && db->file_format<3 ){
- char *zErr = 0;
- InitData initData;
- int meta[SQLITE_N_BTREE_META];
-
- db->magic = SQLITE_MAGIC_OPEN;
- initData.db = db;
- initData.pzErrMsg = &zErr;
- db->file_format = 3;
- rc = sqlite_exec(db,
- "BEGIN; SELECT name FROM sqlite_master WHERE type='table';",
- upgrade_3_callback,
- &initData,
- &zErr);
- if( rc==SQLITE_OK ){
- sqliteBtreeGetMeta(db->aDb[0].pBt, meta);
- meta[2] = 4;
- sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
- sqlite_exec(db, "COMMIT", 0, 0, 0);
- }
- if( rc!=SQLITE_OK ){
- sqliteSetString(pzErrMsg,
- "unable to upgrade database to the version 2.6 format",
- zErr ? ": " : 0, zErr, (char*)0);
- }
- sqlite_freemem(zErr);
- }
-
- if( rc!=SQLITE_OK ){
- db->flags &= ~SQLITE_Initialized;
- }
- return rc;
-}
-
-/*
-** The version of the library
-*/
-const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
-const char sqlite_version[] = SQLITE_VERSION;
-
-/*
-** Does the library expect data to be encoded as UTF-8 or iso8859? The
-** following global constant always lets us know.
-*/
-#ifdef SQLITE_UTF8
-const char sqlite_encoding[] = "UTF-8";
-#else
-const char sqlite_encoding[] = "iso8859";
-#endif
-
-/*
-** Open a new SQLite database. Construct an "sqlite" structure to define
-** the state of this database and return a pointer to that structure.
-**
-** An attempt is made to initialize the in-memory data structures that
-** hold the database schema. But if this fails (because the schema file
-** is locked) then that step is deferred until the first call to
-** sqlite_exec().
-*/
-sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
- sqlite *db;
- int rc, i;
-
- /* Allocate the sqlite data structure */
- db = sqliteMalloc( sizeof(sqlite) );
- if( pzErrMsg ) *pzErrMsg = 0;
- if( db==0 ) goto no_mem_on_open;
- db->onError = OE_Default;
- db->priorNewRowid = 0;
- db->magic = SQLITE_MAGIC_BUSY;
- db->nDb = 2;
- db->aDb = db->aDbStatic;
- /* db->flags |= SQLITE_ShortColNames; */
- sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
- for(i=0; i<db->nDb; i++){
- sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
- sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
- sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
- sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
- }
-
- /* Open the backend database driver */
- if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
- db->temp_store = 2;
- }
- rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
- if( rc!=SQLITE_OK ){
- switch( rc ){
- default: {
- sqliteSetString(pzErrMsg, "unable to open database: ",
- zFilename, (char*)0);
- }
- }
- sqliteFree(db);
- sqliteStrRealloc(pzErrMsg);
- return 0;
- }
- db->aDb[0].zName = "main";
- db->aDb[1].zName = "temp";
-
- /* Attempt to read the schema */
- sqliteRegisterBuiltinFunctions(db);
- rc = sqliteInit(db, pzErrMsg);
- db->magic = SQLITE_MAGIC_OPEN;
- if( sqlite_malloc_failed ){
- sqlite_close(db);
- goto no_mem_on_open;
- }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
- sqlite_close(db);
- sqliteStrRealloc(pzErrMsg);
- return 0;
- }else if( pzErrMsg ){
- sqliteFree(*pzErrMsg);
- *pzErrMsg = 0;
- }
-
- /* Return a pointer to the newly opened database structure */
- return db;
-
-no_mem_on_open:
- sqliteSetString(pzErrMsg, "out of memory", (char*)0);
- sqliteStrRealloc(pzErrMsg);
- return 0;
-}
-
-/*
-** Return the ROWID of the most recent insert
-*/
-int sqlite_last_insert_rowid(sqlite *db){
- return db->lastRowid;
-}
-
-/*
-** Return the number of changes in the most recent call to sqlite_exec().
-*/
-int sqlite_changes(sqlite *db){
- return db->nChange;
-}
-
-/*
-** Return the number of changes produced by the last INSERT, UPDATE, or
-** DELETE statement to complete execution. The count does not include
-** changes due to SQL statements executed in trigger programs that were
-** triggered by that statement
-*/
-int sqlite_last_statement_changes(sqlite *db){
- return db->lsChange;
-}
-
-/*
-** Close an existing SQLite database
-*/
-void sqlite_close(sqlite *db){
- HashElem *i;
- int j;
- db->want_to_close = 1;
- if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){
- /* printf("DID NOT CLOSE\n"); fflush(stdout); */
- return;
- }
- db->magic = SQLITE_MAGIC_CLOSED;
- for(j=0; j<db->nDb; j++){
- struct Db *pDb = &db->aDb[j];
- if( pDb->pBt ){
- sqliteBtreeClose(pDb->pBt);
- pDb->pBt = 0;
- }
- }
- sqliteResetInternalSchema(db, 0);
- assert( db->nDb<=2 );
- assert( db->aDb==db->aDbStatic );
- for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
- FuncDef *pFunc, *pNext;
- for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
- pNext = pFunc->pNext;
- sqliteFree(pFunc);
- }
- }
- sqliteHashClear(&db->aFunc);
- sqliteFree(db);
-}
-
-/*
-** Rollback all database files.
-*/
-void sqliteRollbackAll(sqlite *db){
- int i;
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt ){
- sqliteBtreeRollback(db->aDb[i].pBt);
- db->aDb[i].inTrans = 0;
- }
- }
- sqliteResetInternalSchema(db, 0);
- /* sqliteRollbackInternalChanges(db); */
-}
-
-/*
-** Execute SQL code. Return one of the SQLITE_ success/failure
-** codes. Also write an error message into memory obtained from
-** malloc() and make *pzErrMsg point to that message.
-**
-** If the SQL is a query, then for each row in the query result
-** the xCallback() function is called. pArg becomes the first
-** argument to xCallback(). If xCallback=NULL then no callback
-** is invoked, even for queries.
-*/
-int sqlite_exec(
- sqlite *db, /* The database on which the SQL executes */
- const char *zSql, /* The SQL to be executed */
- sqlite_callback xCallback, /* Invoke this callback routine */
- void *pArg, /* First argument to xCallback() */
- char **pzErrMsg /* Write error messages here */
-){
- int rc = SQLITE_OK;
- const char *zLeftover;
- sqlite_vm *pVm;
- int nRetry = 0;
- int nChange = 0;
- int nCallback;
-
- if( zSql==0 ) return SQLITE_OK;
- while( rc==SQLITE_OK && zSql[0] ){
- pVm = 0;
- rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg);
- if( rc!=SQLITE_OK ){
- assert( pVm==0 || sqlite_malloc_failed );
- return rc;
- }
- if( pVm==0 ){
- /* This happens if the zSql input contained only whitespace */
- break;
- }
- db->nChange += nChange;
- nCallback = 0;
- while(1){
- int nArg;
- char **azArg, **azCol;
- rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol);
- if( rc==SQLITE_ROW ){
- if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){
- sqlite_finalize(pVm, 0);
- return SQLITE_ABORT;
- }
- nCallback++;
- }else{
- if( rc==SQLITE_DONE && nCallback==0
- && (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){
- xCallback(pArg, nArg, azArg, azCol);
- }
- rc = sqlite_finalize(pVm, pzErrMsg);
- if( rc==SQLITE_SCHEMA && nRetry<2 ){
- nRetry++;
- rc = SQLITE_OK;
- break;
- }
- if( db->pVdbe==0 ){
- nChange = db->nChange;
- }
- nRetry = 0;
- zSql = zLeftover;
- while( isspace(zSql[0]) ) zSql++;
- break;
- }
- }
- }
- return rc;
-}
-
-
-/*
-** Compile a single statement of SQL into a virtual machine. Return one
-** of the SQLITE_ success/failure codes. Also write an error message into
-** memory obtained from malloc() and make *pzErrMsg point to that message.
-*/
-int sqlite_compile(
- sqlite *db, /* The database on which the SQL executes */
- const char *zSql, /* The SQL to be executed */
- const char **pzTail, /* OUT: Next statement after the first */
- sqlite_vm **ppVm, /* OUT: The virtual machine */
- char **pzErrMsg /* OUT: Write error messages here */
-){
- Parse sParse;
-
- if( pzErrMsg ) *pzErrMsg = 0;
- if( sqliteSafetyOn(db) ) goto exec_misuse;
- if( !db->init.busy ){
- if( (db->flags & SQLITE_Initialized)==0 ){
- int rc, cnt = 1;
- while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
- && db->xBusyCallback
- && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
- if( rc!=SQLITE_OK ){
- sqliteStrRealloc(pzErrMsg);
- sqliteSafetyOff(db);
- return rc;
- }
- if( pzErrMsg ){
- sqliteFree(*pzErrMsg);
- *pzErrMsg = 0;
- }
- }
- if( db->file_format<3 ){
- sqliteSafetyOff(db);
- sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
- return SQLITE_ERROR;
- }
- }
- assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
- if( db->pVdbe==0 ){ db->nChange = 0; }
- memset(&sParse, 0, sizeof(sParse));
- sParse.db = db;
- sqliteRunParser(&sParse, zSql, pzErrMsg);
- if( db->xTrace && !db->init.busy ){
- /* Trace only the statment that was compiled.
- ** Make a copy of that part of the SQL string since zSQL is const
- ** and we must pass a zero terminated string to the trace function
- ** The copy is unnecessary if the tail pointer is pointing at the
- ** beginnig or end of the SQL string.
- */
- if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){
- char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql);
- if( tmpSql ){
- db->xTrace(db->pTraceArg, tmpSql);
- free(tmpSql);
- }else{
- /* If a memory error occurred during the copy,
- ** trace entire SQL string and fall through to the
- ** sqlite_malloc_failed test to report the error.
- */
- db->xTrace(db->pTraceArg, zSql);
- }
- }else{
- db->xTrace(db->pTraceArg, zSql);
- }
- }
- if( sqlite_malloc_failed ){
- sqliteSetString(pzErrMsg, "out of memory", (char*)0);
- sParse.rc = SQLITE_NOMEM;
- sqliteRollbackAll(db);
- sqliteResetInternalSchema(db, 0);
- db->flags &= ~SQLITE_InTrans;
- }
- if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
- if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
- sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0);
- }
- sqliteStrRealloc(pzErrMsg);
- if( sParse.rc==SQLITE_SCHEMA ){
- sqliteResetInternalSchema(db, 0);
- }
- assert( ppVm );
- *ppVm = (sqlite_vm*)sParse.pVdbe;
- if( pzTail ) *pzTail = sParse.zTail;
- if( sqliteSafetyOff(db) ) goto exec_misuse;
- return sParse.rc;
-
-exec_misuse:
- if( pzErrMsg ){
- *pzErrMsg = 0;
- sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
- sqliteStrRealloc(pzErrMsg);
- }
- return SQLITE_MISUSE;
-}
-
-
-/*
-** The following routine destroys a virtual machine that is created by
-** the sqlite_compile() routine.
-**
-** The integer returned is an SQLITE_ success/failure code that describes
-** the result of executing the virtual machine. An error message is
-** written into memory obtained from malloc and *pzErrMsg is made to
-** point to that error if pzErrMsg is not NULL. The calling routine
-** should use sqlite_freemem() to delete the message when it has finished
-** with it.
-*/
-int sqlite_finalize(
- sqlite_vm *pVm, /* The virtual machine to be destroyed */
- char **pzErrMsg /* OUT: Write error messages here */
-){
- int rc = sqliteVdbeFinalize((Vdbe*)pVm, pzErrMsg);
- sqliteStrRealloc(pzErrMsg);
- return rc;
-}
-
-/*
-** Terminate the current execution of a virtual machine then
-** reset the virtual machine back to its starting state so that it
-** can be reused. Any error message resulting from the prior execution
-** is written into *pzErrMsg. A success code from the prior execution
-** is returned.
-*/
-int sqlite_reset(
- sqlite_vm *pVm, /* The virtual machine to be destroyed */
- char **pzErrMsg /* OUT: Write error messages here */
-){
- int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg);
- sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0);
- sqliteStrRealloc(pzErrMsg);
- return rc;
-}
-
-/*
-** Return a static string that describes the kind of error specified in the
-** argument.
-*/
-const char *sqlite_error_string(int rc){
- const char *z;
- switch( rc ){
- case SQLITE_OK: z = "not an error"; break;
- case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
- case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break;
- case SQLITE_PERM: z = "access permission denied"; break;
- case SQLITE_ABORT: z = "callback requested query abort"; break;
- case SQLITE_BUSY: z = "database is locked"; break;
- case SQLITE_LOCKED: z = "database table is locked"; break;
- case SQLITE_NOMEM: z = "out of memory"; break;
- case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
- case SQLITE_INTERRUPT: z = "interrupted"; break;
- case SQLITE_IOERR: z = "disk I/O error"; break;
- case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
- case SQLITE_NOTFOUND: z = "table or record not found"; break;
- case SQLITE_FULL: z = "database is full"; break;
- case SQLITE_CANTOPEN: z = "unable to open database file"; break;
- case SQLITE_PROTOCOL: z = "database locking protocol failure"; break;
- case SQLITE_EMPTY: z = "table contains no data"; break;
- case SQLITE_SCHEMA: z = "database schema has changed"; break;
- case SQLITE_TOOBIG: z = "too much data for one table row"; break;
- case SQLITE_CONSTRAINT: z = "constraint failed"; break;
- case SQLITE_MISMATCH: z = "datatype mismatch"; break;
- case SQLITE_MISUSE: z = "library routine called out of sequence";break;
- case SQLITE_NOLFS: z = "kernel lacks large file support"; break;
- case SQLITE_AUTH: z = "authorization denied"; break;
- case SQLITE_FORMAT: z = "auxiliary database format error"; break;
- case SQLITE_RANGE: z = "bind index out of range"; break;
- case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
- default: z = "unknown error"; break;
- }
- return z;
-}
-
-/*
-** This routine implements a busy callback that sleeps and tries
-** again until a timeout value is reached. The timeout value is
-** an integer number of milliseconds passed in as the first
-** argument.
-*/
-static int sqliteDefaultBusyCallback(
- void *Timeout, /* Maximum amount of time to wait */
- const char *NotUsed, /* The name of the table that is busy */
- int count /* Number of times table has been busy */
-){
-#if SQLITE_MIN_SLEEP_MS==1
- static const char delays[] =
- { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100};
- static const short int totals[] =
- { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
-# define NDELAY (sizeof(delays)/sizeof(delays[0]))
- int timeout = (int)(long)Timeout;
- int delay, prior;
-
- if( count <= NDELAY ){
- delay = delays[count-1];
- prior = totals[count-1];
- }else{
- delay = delays[NDELAY-1];
- prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
- }
- if( prior + delay > timeout ){
- delay = timeout - prior;
- if( delay<=0 ) return 0;
- }
- sqliteOsSleep(delay);
- return 1;
-#else
- int timeout = (int)(long)Timeout;
- if( (count+1)*1000 > timeout ){
- return 0;
- }
- sqliteOsSleep(1000);
- return 1;
-#endif
-}
-
-/*
-** This routine sets the busy callback for an Sqlite database to the
-** given callback function with the given argument.
-*/
-void sqlite_busy_handler(
- sqlite *db,
- int (*xBusy)(void*,const char*,int),
- void *pArg
-){
- db->xBusyCallback = xBusy;
- db->pBusyArg = pArg;
-}
-
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-/*
-** This routine sets the progress callback for an Sqlite database to the
-** given callback function with the given argument. The progress callback will
-** be invoked every nOps opcodes.
-*/
-void sqlite_progress_handler(
- sqlite *db,
- int nOps,
- int (*xProgress)(void*),
- void *pArg
-){
- if( nOps>0 ){
- db->xProgress = xProgress;
- db->nProgressOps = nOps;
- db->pProgressArg = pArg;
- }else{
- db->xProgress = 0;
- db->nProgressOps = 0;
- db->pProgressArg = 0;
- }
-}
-#endif
-
-
-/*
-** This routine installs a default busy handler that waits for the
-** specified number of milliseconds before returning 0.
-*/
-void sqlite_busy_timeout(sqlite *db, int ms){
- if( ms>0 ){
- sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
- }else{
- sqlite_busy_handler(db, 0, 0);
- }
-}
-
-/*
-** Cause any pending operation to stop at its earliest opportunity.
-*/
-void sqlite_interrupt(sqlite *db){
- db->flags |= SQLITE_Interrupt;
-}
-
-/*
-** Windows systems should call this routine to free memory that
-** is returned in the in the errmsg parameter of sqlite_open() when
-** SQLite is a DLL. For some reason, it does not work to call free()
-** directly.
-**
-** Note that we need to call free() not sqliteFree() here, since every
-** string that is exported from SQLite should have already passed through
-** sqliteStrRealloc().
-*/
-void sqlite_freemem(void *p){ free(p); }
-
-/*
-** Windows systems need functions to call to return the sqlite_version
-** and sqlite_encoding strings since they are unable to access constants
-** within DLLs.
-*/
-const char *sqlite_libversion(void){ return sqlite_version; }
-const char *sqlite_libencoding(void){ return sqlite_encoding; }
-
-/*
-** Create new user-defined functions. The sqlite_create_function()
-** routine creates a regular function and sqlite_create_aggregate()
-** creates an aggregate function.
-**
-** Passing a NULL xFunc argument or NULL xStep and xFinalize arguments
-** disables the function. Calling sqlite_create_function() with the
-** same name and number of arguments as a prior call to
-** sqlite_create_aggregate() disables the prior call to
-** sqlite_create_aggregate(), and vice versa.
-**
-** If nArg is -1 it means that this function will accept any number
-** of arguments, including 0. The maximum allowed value of nArg is 127.
-*/
-int sqlite_create_function(
- sqlite *db, /* Add the function to this database connection */
- const char *zName, /* Name of the function to add */
- int nArg, /* Number of arguments */
- void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */
- void *pUserData /* User data */
-){
- FuncDef *p;
- int nName;
- if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
- if( nArg<-1 || nArg>127 ) return 1;
- nName = strlen(zName);
- if( nName>255 ) return 1;
- p = sqliteFindFunction(db, zName, nName, nArg, 1);
- if( p==0 ) return 1;
- p->xFunc = xFunc;
- p->xStep = 0;
- p->xFinalize = 0;
- p->pUserData = pUserData;
- return 0;
-}
-int sqlite_create_aggregate(
- sqlite *db, /* Add the function to this database connection */
- const char *zName, /* Name of the function to add */
- int nArg, /* Number of arguments */
- void (*xStep)(sqlite_func*,int,const char**), /* The step function */
- void (*xFinalize)(sqlite_func*), /* The finalizer */
- void *pUserData /* User data */
-){
- FuncDef *p;
- int nName;
- if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1;
- if( nArg<-1 || nArg>127 ) return 1;
- nName = strlen(zName);
- if( nName>255 ) return 1;
- p = sqliteFindFunction(db, zName, nName, nArg, 1);
- if( p==0 ) return 1;
- p->xFunc = 0;
- p->xStep = xStep;
- p->xFinalize = xFinalize;
- p->pUserData = pUserData;
- return 0;
-}
-
-/*
-** Change the datatype for all functions with a given name. See the
-** header comment for the prototype of this function in sqlite.h for
-** additional information.
-*/
-int sqlite_function_type(sqlite *db, const char *zName, int dataType){
- FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName));
- while( p ){
- p->dataType = dataType;
- p = p->pNext;
- }
- return SQLITE_OK;
-}
-
-/*
-** Register a trace function. The pArg from the previously registered trace
-** is returned.
-**
-** A NULL trace function means that no tracing is executes. A non-NULL
-** trace is a pointer to a function that is invoked at the start of each
-** sqlite_exec().
-*/
-void *sqlite_trace(sqlite *db, void (*xTrace)(void*,const char*), void *pArg){
- void *pOld = db->pTraceArg;
- db->xTrace = xTrace;
- db->pTraceArg = pArg;
- return pOld;
-}
-
-/*** EXPERIMENTAL ***
-**
-** Register a function to be invoked when a transaction comments.
-** If either function returns non-zero, then the commit becomes a
-** rollback.
-*/
-void *sqlite_commit_hook(
- sqlite *db, /* Attach the hook to this database */
- int (*xCallback)(void*), /* Function to invoke on each commit */
- void *pArg /* Argument to the function */
-){
- void *pOld = db->pCommitArg;
- db->xCommitCallback = xCallback;
- db->pCommitArg = pArg;
- return pOld;
-}
-
-
-/*
-** This routine is called to create a connection to a database BTree
-** driver. If zFilename is the name of a file, then that file is
-** opened and used. If zFilename is the magic name ":memory:" then
-** the database is stored in memory (and is thus forgotten as soon as
-** the connection is closed.) If zFilename is NULL then the database
-** is for temporary use only and is deleted as soon as the connection
-** is closed.
-**
-** A temporary database can be either a disk file (that is automatically
-** deleted when the file is closed) or a set of red-black trees held in memory,
-** depending on the values of the TEMP_STORE compile-time macro and the
-** db->temp_store variable, according to the following chart:
-**
-** TEMP_STORE db->temp_store Location of temporary database
-** ---------- -------------- ------------------------------
-** 0 any file
-** 1 1 file
-** 1 2 memory
-** 1 0 file
-** 2 1 file
-** 2 2 memory
-** 2 0 memory
-** 3 any memory
-*/
-int sqliteBtreeFactory(
- const sqlite *db, /* Main database when opening aux otherwise 0 */
- const char *zFilename, /* Name of the file containing the BTree database */
- int omitJournal, /* if TRUE then do not journal this file */
- int nCache, /* How many pages in the page cache */
- Btree **ppBtree){ /* Pointer to new Btree object written here */
-
- assert( ppBtree != 0);
-
-#ifndef SQLITE_OMIT_INMEMORYDB
- if( zFilename==0 ){
- if (TEMP_STORE == 0) {
- /* Always use file based temporary DB */
- return sqliteBtreeOpen(0, omitJournal, nCache, ppBtree);
- } else if (TEMP_STORE == 1 || TEMP_STORE == 2) {
- /* Switch depending on compile-time and/or runtime settings. */
- int location = db->temp_store==0 ? TEMP_STORE : db->temp_store;
-
- if (location == 1) {
- return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree);
- } else {
- return sqliteRbtreeOpen(0, 0, 0, ppBtree);
- }
- } else {
- /* Always use in-core DB */
- return sqliteRbtreeOpen(0, 0, 0, ppBtree);
- }
- }else if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
- return sqliteRbtreeOpen(0, 0, 0, ppBtree);
- }else
-#endif
- {
- return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree);
- }
-}
diff --git a/ext/sqlite/libsqlite/src/opcodes.c b/ext/sqlite/libsqlite/src/opcodes.c
deleted file mode 100644
index 0907e0e797..0000000000
--- a/ext/sqlite/libsqlite/src/opcodes.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* Automatically generated file. Do not edit */
-char *sqliteOpcodeNames[] = { "???",
- "Goto",
- "Gosub",
- "Return",
- "Halt",
- "Integer",
- "String",
- "Variable",
- "Pop",
- "Dup",
- "Pull",
- "Push",
- "ColumnName",
- "Callback",
- "Concat",
- "Add",
- "Subtract",
- "Multiply",
- "Divide",
- "Remainder",
- "Function",
- "BitAnd",
- "BitOr",
- "ShiftLeft",
- "ShiftRight",
- "AddImm",
- "ForceInt",
- "MustBeInt",
- "Eq",
- "Ne",
- "Lt",
- "Le",
- "Gt",
- "Ge",
- "StrEq",
- "StrNe",
- "StrLt",
- "StrLe",
- "StrGt",
- "StrGe",
- "And",
- "Or",
- "Negative",
- "AbsValue",
- "Not",
- "BitNot",
- "Noop",
- "If",
- "IfNot",
- "IsNull",
- "NotNull",
- "MakeRecord",
- "MakeIdxKey",
- "MakeKey",
- "IncrKey",
- "Checkpoint",
- "Transaction",
- "Commit",
- "Rollback",
- "ReadCookie",
- "SetCookie",
- "VerifyCookie",
- "OpenRead",
- "OpenWrite",
- "OpenTemp",
- "OpenPseudo",
- "Close",
- "MoveLt",
- "MoveTo",
- "Distinct",
- "NotFound",
- "Found",
- "IsUnique",
- "NotExists",
- "NewRecno",
- "PutIntKey",
- "PutStrKey",
- "Delete",
- "SetCounts",
- "KeyAsData",
- "RowKey",
- "RowData",
- "Column",
- "Recno",
- "FullKey",
- "NullRow",
- "Last",
- "Rewind",
- "Prev",
- "Next",
- "IdxPut",
- "IdxDelete",
- "IdxRecno",
- "IdxLT",
- "IdxGT",
- "IdxGE",
- "IdxIsNull",
- "Destroy",
- "Clear",
- "CreateIndex",
- "CreateTable",
- "IntegrityCk",
- "ListWrite",
- "ListRewind",
- "ListRead",
- "ListReset",
- "ListPush",
- "ListPop",
- "ContextPush",
- "ContextPop",
- "SortPut",
- "SortMakeRec",
- "SortMakeKey",
- "Sort",
- "SortNext",
- "SortCallback",
- "SortReset",
- "FileOpen",
- "FileRead",
- "FileColumn",
- "MemStore",
- "MemLoad",
- "MemIncr",
- "AggReset",
- "AggInit",
- "AggFunc",
- "AggFocus",
- "AggSet",
- "AggGet",
- "AggNext",
- "SetInsert",
- "SetFound",
- "SetNotFound",
- "SetFirst",
- "SetNext",
- "Vacuum",
- "StackDepth",
- "StackReset",
-};
diff --git a/ext/sqlite/libsqlite/src/opcodes.h b/ext/sqlite/libsqlite/src/opcodes.h
deleted file mode 100644
index 35e050697f..0000000000
--- a/ext/sqlite/libsqlite/src/opcodes.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* Automatically generated file. Do not edit */
-#define OP_Goto 1
-#define OP_Gosub 2
-#define OP_Return 3
-#define OP_Halt 4
-#define OP_Integer 5
-#define OP_String 6
-#define OP_Variable 7
-#define OP_Pop 8
-#define OP_Dup 9
-#define OP_Pull 10
-#define OP_Push 11
-#define OP_ColumnName 12
-#define OP_Callback 13
-#define OP_Concat 14
-#define OP_Add 15
-#define OP_Subtract 16
-#define OP_Multiply 17
-#define OP_Divide 18
-#define OP_Remainder 19
-#define OP_Function 20
-#define OP_BitAnd 21
-#define OP_BitOr 22
-#define OP_ShiftLeft 23
-#define OP_ShiftRight 24
-#define OP_AddImm 25
-#define OP_ForceInt 26
-#define OP_MustBeInt 27
-#define OP_Eq 28
-#define OP_Ne 29
-#define OP_Lt 30
-#define OP_Le 31
-#define OP_Gt 32
-#define OP_Ge 33
-#define OP_StrEq 34
-#define OP_StrNe 35
-#define OP_StrLt 36
-#define OP_StrLe 37
-#define OP_StrGt 38
-#define OP_StrGe 39
-#define OP_And 40
-#define OP_Or 41
-#define OP_Negative 42
-#define OP_AbsValue 43
-#define OP_Not 44
-#define OP_BitNot 45
-#define OP_Noop 46
-#define OP_If 47
-#define OP_IfNot 48
-#define OP_IsNull 49
-#define OP_NotNull 50
-#define OP_MakeRecord 51
-#define OP_MakeIdxKey 52
-#define OP_MakeKey 53
-#define OP_IncrKey 54
-#define OP_Checkpoint 55
-#define OP_Transaction 56
-#define OP_Commit 57
-#define OP_Rollback 58
-#define OP_ReadCookie 59
-#define OP_SetCookie 60
-#define OP_VerifyCookie 61
-#define OP_OpenRead 62
-#define OP_OpenWrite 63
-#define OP_OpenTemp 64
-#define OP_OpenPseudo 65
-#define OP_Close 66
-#define OP_MoveLt 67
-#define OP_MoveTo 68
-#define OP_Distinct 69
-#define OP_NotFound 70
-#define OP_Found 71
-#define OP_IsUnique 72
-#define OP_NotExists 73
-#define OP_NewRecno 74
-#define OP_PutIntKey 75
-#define OP_PutStrKey 76
-#define OP_Delete 77
-#define OP_SetCounts 78
-#define OP_KeyAsData 79
-#define OP_RowKey 80
-#define OP_RowData 81
-#define OP_Column 82
-#define OP_Recno 83
-#define OP_FullKey 84
-#define OP_NullRow 85
-#define OP_Last 86
-#define OP_Rewind 87
-#define OP_Prev 88
-#define OP_Next 89
-#define OP_IdxPut 90
-#define OP_IdxDelete 91
-#define OP_IdxRecno 92
-#define OP_IdxLT 93
-#define OP_IdxGT 94
-#define OP_IdxGE 95
-#define OP_IdxIsNull 96
-#define OP_Destroy 97
-#define OP_Clear 98
-#define OP_CreateIndex 99
-#define OP_CreateTable 100
-#define OP_IntegrityCk 101
-#define OP_ListWrite 102
-#define OP_ListRewind 103
-#define OP_ListRead 104
-#define OP_ListReset 105
-#define OP_ListPush 106
-#define OP_ListPop 107
-#define OP_ContextPush 108
-#define OP_ContextPop 109
-#define OP_SortPut 110
-#define OP_SortMakeRec 111
-#define OP_SortMakeKey 112
-#define OP_Sort 113
-#define OP_SortNext 114
-#define OP_SortCallback 115
-#define OP_SortReset 116
-#define OP_FileOpen 117
-#define OP_FileRead 118
-#define OP_FileColumn 119
-#define OP_MemStore 120
-#define OP_MemLoad 121
-#define OP_MemIncr 122
-#define OP_AggReset 123
-#define OP_AggInit 124
-#define OP_AggFunc 125
-#define OP_AggFocus 126
-#define OP_AggSet 127
-#define OP_AggGet 128
-#define OP_AggNext 129
-#define OP_SetInsert 130
-#define OP_SetFound 131
-#define OP_SetNotFound 132
-#define OP_SetFirst 133
-#define OP_SetNext 134
-#define OP_Vacuum 135
-#define OP_StackDepth 136
-#define OP_StackReset 137
diff --git a/ext/sqlite/libsqlite/src/os.c b/ext/sqlite/libsqlite/src/os.c
deleted file mode 100644
index dccd65f1d6..0000000000
--- a/ext/sqlite/libsqlite/src/os.c
+++ /dev/null
@@ -1,1850 +0,0 @@
-/*
-** 2001 September 16
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains code that is specific to particular operating
-** systems. The purpose of this file is to provide a uniform abstraction
-** on which the rest of SQLite can operate.
-*/
-#include "os.h" /* Must be first to enable large file support */
-#include "sqliteInt.h"
-
-#if OS_UNIX
-# include <time.h>
-# include <errno.h>
-# include <unistd.h>
-# ifndef O_LARGEFILE
-# define O_LARGEFILE 0
-# endif
-# ifdef SQLITE_DISABLE_LFS
-# undef O_LARGEFILE
-# define O_LARGEFILE 0
-# endif
-# ifndef O_NOFOLLOW
-# define O_NOFOLLOW 0
-# endif
-# ifndef O_BINARY
-# define O_BINARY 0
-# endif
-#endif
-
-
-#if OS_WIN
-# include <winbase.h>
-#endif
-
-#if OS_MAC
-# include <extras.h>
-# include <path2fss.h>
-# include <TextUtils.h>
-# include <FinderRegistry.h>
-# include <Folders.h>
-# include <Timer.h>
-# include <OSUtils.h>
-#endif
-
-/*
-** The DJGPP compiler environment looks mostly like Unix, but it
-** lacks the fcntl() system call. So redefine fcntl() to be something
-** that always succeeds. This means that locking does not occur under
-** DJGPP. But its DOS - what did you expect?
-*/
-#ifdef __DJGPP__
-# define fcntl(A,B,C) 0
-#endif
-
-/*
-** Macros used to determine whether or not to use threads. The
-** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
-** Posix threads and SQLITE_W32_THREADS is defined if we are
-** synchronizing using Win32 threads.
-*/
-#if OS_UNIX && defined(THREADSAFE) && THREADSAFE
-# include <pthread.h>
-# define SQLITE_UNIX_THREADS 1
-#endif
-#if OS_WIN && defined(THREADSAFE) && THREADSAFE
-# define SQLITE_W32_THREADS 1
-#endif
-#if OS_MAC && defined(THREADSAFE) && THREADSAFE
-# include <Multiprocessing.h>
-# define SQLITE_MACOS_MULTITASKING 1
-#endif
-
-/*
-** Macros for performance tracing. Normally turned off
-*/
-#if 0
-static int last_page = 0;
-__inline__ unsigned long long int hwtime(void){
- unsigned long long int x;
- __asm__("rdtsc\n\t"
- "mov %%edx, %%ecx\n\t"
- :"=A" (x));
- return x;
-}
-static unsigned long long int g_start;
-static unsigned int elapse;
-#define TIMER_START g_start=hwtime()
-#define TIMER_END elapse=hwtime()-g_start
-#define SEEK(X) last_page=(X)
-#define TRACE1(X) fprintf(stderr,X)
-#define TRACE2(X,Y) fprintf(stderr,X,Y)
-#define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z)
-#define TRACE4(X,Y,Z,A) fprintf(stderr,X,Y,Z,A)
-#define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B)
-#else
-#define TIMER_START
-#define TIMER_END
-#define SEEK(X)
-#define TRACE1(X)
-#define TRACE2(X,Y)
-#define TRACE3(X,Y,Z)
-#define TRACE4(X,Y,Z,A)
-#define TRACE5(X,Y,Z,A,B)
-#endif
-
-
-#if OS_UNIX
-/*
-** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996)
-** section 6.5.2.2 lines 483 through 490 specify that when a process
-** sets or clears a lock, that operation overrides any prior locks set
-** by the same process. It does not explicitly say so, but this implies
-** that it overrides locks set by the same process using a different
-** file descriptor. Consider this test case:
-**
-** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
-** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
-**
-** Suppose ./file1 and ./file2 are really the same file (because
-** one is a hard or symbolic link to the other) then if you set
-** an exclusive lock on fd1, then try to get an exclusive lock
-** on fd2, it works. I would have expected the second lock to
-** fail since there was already a lock on the file due to fd1.
-** But not so. Since both locks came from the same process, the
-** second overrides the first, even though they were on different
-** file descriptors opened on different file names.
-**
-** Bummer. If you ask me, this is broken. Badly broken. It means
-** that we cannot use POSIX locks to synchronize file access among
-** competing threads of the same process. POSIX locks will work fine
-** to synchronize access for threads in separate processes, but not
-** threads within the same process.
-**
-** To work around the problem, SQLite has to manage file locks internally
-** on its own. Whenever a new database is opened, we have to find the
-** specific inode of the database file (the inode is determined by the
-** st_dev and st_ino fields of the stat structure that fstat() fills in)
-** and check for locks already existing on that inode. When locks are
-** created or removed, we have to look at our own internal record of the
-** locks to see if another thread has previously set a lock on that same
-** inode.
-**
-** The OsFile structure for POSIX is no longer just an integer file
-** descriptor. It is now a structure that holds the integer file
-** descriptor and a pointer to a structure that describes the internal
-** locks on the corresponding inode. There is one locking structure
-** per inode, so if the same inode is opened twice, both OsFile structures
-** point to the same locking structure. The locking structure keeps
-** a reference count (so we will know when to delete it) and a "cnt"
-** field that tells us its internal lock status. cnt==0 means the
-** file is unlocked. cnt==-1 means the file has an exclusive lock.
-** cnt>0 means there are cnt shared locks on the file.
-**
-** Any attempt to lock or unlock a file first checks the locking
-** structure. The fcntl() system call is only invoked to set a
-** POSIX lock if the internal lock structure transitions between
-** a locked and an unlocked state.
-**
-** 2004-Jan-11:
-** More recent discoveries about POSIX advisory locks. (The more
-** I discover, the more I realize the a POSIX advisory locks are
-** an abomination.)
-**
-** If you close a file descriptor that points to a file that has locks,
-** all locks on that file that are owned by the current process are
-** released. To work around this problem, each OsFile structure contains
-** a pointer to an openCnt structure. There is one openCnt structure
-** per open inode, which means that multiple OsFiles can point to a single
-** openCnt. When an attempt is made to close an OsFile, if there are
-** other OsFiles open on the same inode that are holding locks, the call
-** to close() the file descriptor is deferred until all of the locks clear.
-** The openCnt structure keeps a list of file descriptors that need to
-** be closed and that list is walked (and cleared) when the last lock
-** clears.
-**
-** First, under Linux threads, because each thread has a separate
-** process ID, lock operations in one thread do not override locks
-** to the same file in other threads. Linux threads behave like
-** separate processes in this respect. But, if you close a file
-** descriptor in linux threads, all locks are cleared, even locks
-** on other threads and even though the other threads have different
-** process IDs. Linux threads is inconsistent in this respect.
-** (I'm beginning to think that linux threads is an abomination too.)
-** The consequence of this all is that the hash table for the lockInfo
-** structure has to include the process id as part of its key because
-** locks in different threads are treated as distinct. But the
-** openCnt structure should not include the process id in its
-** key because close() clears lock on all threads, not just the current
-** thread. Were it not for this goofiness in linux threads, we could
-** combine the lockInfo and openCnt structures into a single structure.
-*/
-
-/*
-** An instance of the following structure serves as the key used
-** to locate a particular lockInfo structure given its inode. Note
-** that we have to include the process ID as part of the key. On some
-** threading implementations (ex: linux), each thread has a separate
-** process ID.
-*/
-struct lockKey {
- dev_t dev; /* Device number */
- ino_t ino; /* Inode number */
- pid_t pid; /* Process ID */
-};
-
-/*
-** An instance of the following structure is allocated for each open
-** inode on each thread with a different process ID. (Threads have
-** different process IDs on linux, but not on most other unixes.)
-**
-** A single inode can have multiple file descriptors, so each OsFile
-** structure contains a pointer to an instance of this object and this
-** object keeps a count of the number of OsFiles pointing to it.
-*/
-struct lockInfo {
- struct lockKey key; /* The lookup key */
- int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */
- int nRef; /* Number of pointers to this structure */
-};
-
-/*
-** An instance of the following structure serves as the key used
-** to locate a particular openCnt structure given its inode. This
-** is the same as the lockKey except that the process ID is omitted.
-*/
-struct openKey {
- dev_t dev; /* Device number */
- ino_t ino; /* Inode number */
-};
-
-/*
-** An instance of the following structure is allocated for each open
-** inode. This structure keeps track of the number of locks on that
-** inode. If a close is attempted against an inode that is holding
-** locks, the close is deferred until all locks clear by adding the
-** file descriptor to be closed to the pending list.
-*/
-struct openCnt {
- struct openKey key; /* The lookup key */
- int nRef; /* Number of pointers to this structure */
- int nLock; /* Number of outstanding locks */
- int nPending; /* Number of pending close() operations */
- int *aPending; /* Malloced space holding fd's awaiting a close() */
-};
-
-/*
-** These hash table maps inodes and process IDs into lockInfo and openCnt
-** structures. Access to these hash tables must be protected by a mutex.
-*/
-static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
-static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };
-
-/*
-** Release a lockInfo structure previously allocated by findLockInfo().
-*/
-static void releaseLockInfo(struct lockInfo *pLock){
- pLock->nRef--;
- if( pLock->nRef==0 ){
- sqliteHashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
- sqliteFree(pLock);
- }
-}
-
-/*
-** Release a openCnt structure previously allocated by findLockInfo().
-*/
-static void releaseOpenCnt(struct openCnt *pOpen){
- pOpen->nRef--;
- if( pOpen->nRef==0 ){
- sqliteHashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
- sqliteFree(pOpen->aPending);
- sqliteFree(pOpen);
- }
-}
-
-/*
-** Given a file descriptor, locate lockInfo and openCnt structures that
-** describes that file descriptor. Create a new ones if necessary. The
-** return values might be unset if an error occurs.
-**
-** Return the number of errors.
-*/
-int findLockInfo(
- int fd, /* The file descriptor used in the key */
- struct lockInfo **ppLock, /* Return the lockInfo structure here */
- struct openCnt **ppOpen /* Return the openCnt structure here */
-){
- int rc;
- struct lockKey key1;
- struct openKey key2;
- struct stat statbuf;
- struct lockInfo *pLock;
- struct openCnt *pOpen;
- rc = fstat(fd, &statbuf);
- if( rc!=0 ) return 1;
- memset(&key1, 0, sizeof(key1));
- key1.dev = statbuf.st_dev;
- key1.ino = statbuf.st_ino;
- key1.pid = getpid();
- memset(&key2, 0, sizeof(key2));
- key2.dev = statbuf.st_dev;
- key2.ino = statbuf.st_ino;
- pLock = (struct lockInfo*)sqliteHashFind(&lockHash, &key1, sizeof(key1));
- if( pLock==0 ){
- struct lockInfo *pOld;
- pLock = sqliteMallocRaw( sizeof(*pLock) );
- if( pLock==0 ) return 1;
- pLock->key = key1;
- pLock->nRef = 1;
- pLock->cnt = 0;
- pOld = sqliteHashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
- if( pOld!=0 ){
- assert( pOld==pLock );
- sqliteFree(pLock);
- return 1;
- }
- }else{
- pLock->nRef++;
- }
- *ppLock = pLock;
- pOpen = (struct openCnt*)sqliteHashFind(&openHash, &key2, sizeof(key2));
- if( pOpen==0 ){
- struct openCnt *pOld;
- pOpen = sqliteMallocRaw( sizeof(*pOpen) );
- if( pOpen==0 ){
- releaseLockInfo(pLock);
- return 1;
- }
- pOpen->key = key2;
- pOpen->nRef = 1;
- pOpen->nLock = 0;
- pOpen->nPending = 0;
- pOpen->aPending = 0;
- pOld = sqliteHashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
- if( pOld!=0 ){
- assert( pOld==pOpen );
- sqliteFree(pOpen);
- releaseLockInfo(pLock);
- return 1;
- }
- }else{
- pOpen->nRef++;
- }
- *ppOpen = pOpen;
- return 0;
-}
-
-#endif /** POSIX advisory lock work-around **/
-
-/*
-** If we compile with the SQLITE_TEST macro set, then the following block
-** of code will give us the ability to simulate a disk I/O error. This
-** is used for testing the I/O recovery logic.
-*/
-#ifdef SQLITE_TEST
-int sqlite_io_error_pending = 0;
-#define SimulateIOError(A) \
- if( sqlite_io_error_pending ) \
- if( sqlite_io_error_pending-- == 1 ){ local_ioerr(); return A; }
-static void local_ioerr(){
- sqlite_io_error_pending = 0; /* Really just a place to set a breakpoint */
-}
-#else
-#define SimulateIOError(A)
-#endif
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#ifdef SQLITE_TEST
-int sqlite_open_file_count = 0;
-#define OpenCounter(X) sqlite_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif
-
-
-/*
-** Delete the named file
-*/
-int sqliteOsDelete(const char *zFilename){
-#if OS_UNIX
- unlink(zFilename);
-#endif
-#if OS_WIN
- DeleteFile(zFilename);
-#endif
-#if OS_MAC
- unlink(zFilename);
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the named file exists.
-*/
-int sqliteOsFileExists(const char *zFilename){
-#if OS_UNIX
- return access(zFilename, 0)==0;
-#endif
-#if OS_WIN
- return GetFileAttributes(zFilename) != 0xffffffff;
-#endif
-#if OS_MAC
- return access(zFilename, 0)==0;
-#endif
-}
-
-
-#if 0 /* NOT USED */
-/*
-** Change the name of an existing file.
-*/
-int sqliteOsFileRename(const char *zOldName, const char *zNewName){
-#if OS_UNIX
- if( link(zOldName, zNewName) ){
- return SQLITE_ERROR;
- }
- unlink(zOldName);
- return SQLITE_OK;
-#endif
-#if OS_WIN
- if( !MoveFile(zOldName, zNewName) ){
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-#endif
-#if OS_MAC
- /**** FIX ME ***/
- return SQLITE_ERROR;
-#endif
-}
-#endif /* NOT USED */
-
-/*
-** Attempt to open a file for both reading and writing. If that
-** fails, try opening it read-only. If the file does not exist,
-** try to create it.
-**
-** On success, a handle for the open file is written to *id
-** and *pReadonly is set to 0 if the file was opened for reading and
-** writing or 1 if the file was opened read-only. The function returns
-** SQLITE_OK.
-**
-** On failure, the function returns SQLITE_CANTOPEN and leaves
-** *id and *pReadonly unchanged.
-*/
-int sqliteOsOpenReadWrite(
- const char *zFilename,
- OsFile *id,
- int *pReadonly
-){
-#if OS_UNIX
- int rc;
- id->dirfd = -1;
- id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
- if( id->fd<0 ){
-#ifdef EISDIR
- if( errno==EISDIR ){
- return SQLITE_CANTOPEN;
- }
-#endif
- id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
- if( id->fd<0 ){
- return SQLITE_CANTOPEN;
- }
- *pReadonly = 1;
- }else{
- *pReadonly = 0;
- }
- sqliteOsEnterMutex();
- rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
- sqliteOsLeaveMutex();
- if( rc ){
- close(id->fd);
- return SQLITE_NOMEM;
- }
- id->locked = 0;
- TRACE3("OPEN %-3d %s\n", id->fd, zFilename);
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-#if OS_WIN
- HANDLE h = CreateFile(zFilename,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
- NULL
- );
- if( h==INVALID_HANDLE_VALUE ){
- h = CreateFile(zFilename,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
- NULL
- );
- if( h==INVALID_HANDLE_VALUE ){
- return SQLITE_CANTOPEN;
- }
- *pReadonly = 1;
- }else{
- *pReadonly = 0;
- }
- id->h = h;
- id->locked = 0;
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-#if OS_MAC
- FSSpec fsSpec;
-# ifdef _LARGE_FILE
- HFSUniStr255 dfName;
- FSRef fsRef;
- if( __path2fss(zFilename, &fsSpec) != noErr ){
- if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
- return SQLITE_CANTOPEN;
- }
- if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
- return SQLITE_CANTOPEN;
- FSGetDataForkName(&dfName);
- if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
- fsRdWrShPerm, &(id->refNum)) != noErr ){
- if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
- fsRdWrPerm, &(id->refNum)) != noErr ){
- if (FSOpenFork(&fsRef, dfName.length, dfName.unicode,
- fsRdPerm, &(id->refNum)) != noErr )
- return SQLITE_CANTOPEN;
- else
- *pReadonly = 1;
- } else
- *pReadonly = 0;
- } else
- *pReadonly = 0;
-# else
- __path2fss(zFilename, &fsSpec);
- if( !sqliteOsFileExists(zFilename) ){
- if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
- return SQLITE_CANTOPEN;
- }
- if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){
- if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){
- if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
- return SQLITE_CANTOPEN;
- else
- *pReadonly = 1;
- } else
- *pReadonly = 0;
- } else
- *pReadonly = 0;
-# endif
- if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
- id->refNumRF = -1;
- }
- id->locked = 0;
- id->delOnClose = 0;
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-}
-
-
-/*
-** Attempt to open a new file for exclusive access by this process.
-** The file will be opened for both reading and writing. To avoid
-** a potential security problem, we do not allow the file to have
-** previously existed. Nor do we allow the file to be a symbolic
-** link.
-**
-** If delFlag is true, then make arrangements to automatically delete
-** the file when it is closed.
-**
-** On success, write the file handle into *id and return SQLITE_OK.
-**
-** On failure, return SQLITE_CANTOPEN.
-*/
-int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
-#if OS_UNIX
- int rc;
- if( access(zFilename, 0)==0 ){
- return SQLITE_CANTOPEN;
- }
- id->dirfd = -1;
- id->fd = open(zFilename,
- O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
- if( id->fd<0 ){
- return SQLITE_CANTOPEN;
- }
- sqliteOsEnterMutex();
- rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
- sqliteOsLeaveMutex();
- if( rc ){
- close(id->fd);
- unlink(zFilename);
- return SQLITE_NOMEM;
- }
- id->locked = 0;
- if( delFlag ){
- unlink(zFilename);
- }
- TRACE3("OPEN-EX %-3d %s\n", id->fd, zFilename);
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-#if OS_WIN
- HANDLE h;
- int fileflags;
- if( delFlag ){
- fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
- | FILE_FLAG_DELETE_ON_CLOSE;
- }else{
- fileflags = FILE_FLAG_RANDOM_ACCESS;
- }
- h = CreateFile(zFilename,
- GENERIC_READ | GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- fileflags,
- NULL
- );
- if( h==INVALID_HANDLE_VALUE ){
- return SQLITE_CANTOPEN;
- }
- id->h = h;
- id->locked = 0;
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-#if OS_MAC
- FSSpec fsSpec;
-# ifdef _LARGE_FILE
- HFSUniStr255 dfName;
- FSRef fsRef;
- __path2fss(zFilename, &fsSpec);
- if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
- return SQLITE_CANTOPEN;
- if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
- return SQLITE_CANTOPEN;
- FSGetDataForkName(&dfName);
- if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
- fsRdWrPerm, &(id->refNum)) != noErr )
- return SQLITE_CANTOPEN;
-# else
- __path2fss(zFilename, &fsSpec);
- if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr )
- return SQLITE_CANTOPEN;
- if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr )
- return SQLITE_CANTOPEN;
-# endif
- id->refNumRF = -1;
- id->locked = 0;
- id->delOnClose = delFlag;
- if (delFlag)
- id->pathToDel = sqliteOsFullPathname(zFilename);
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-}
-
-/*
-** Attempt to open a new file for read-only access.
-**
-** On success, write the file handle into *id and return SQLITE_OK.
-**
-** On failure, return SQLITE_CANTOPEN.
-*/
-int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){
-#if OS_UNIX
- int rc;
- id->dirfd = -1;
- id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
- if( id->fd<0 ){
- return SQLITE_CANTOPEN;
- }
- sqliteOsEnterMutex();
- rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
- sqliteOsLeaveMutex();
- if( rc ){
- close(id->fd);
- return SQLITE_NOMEM;
- }
- id->locked = 0;
- TRACE3("OPEN-RO %-3d %s\n", id->fd, zFilename);
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-#if OS_WIN
- HANDLE h = CreateFile(zFilename,
- GENERIC_READ,
- 0,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
- NULL
- );
- if( h==INVALID_HANDLE_VALUE ){
- return SQLITE_CANTOPEN;
- }
- id->h = h;
- id->locked = 0;
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-#if OS_MAC
- FSSpec fsSpec;
-# ifdef _LARGE_FILE
- HFSUniStr255 dfName;
- FSRef fsRef;
- if( __path2fss(zFilename, &fsSpec) != noErr )
- return SQLITE_CANTOPEN;
- if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr )
- return SQLITE_CANTOPEN;
- FSGetDataForkName(&dfName);
- if( FSOpenFork(&fsRef, dfName.length, dfName.unicode,
- fsRdPerm, &(id->refNum)) != noErr )
- return SQLITE_CANTOPEN;
-# else
- __path2fss(zFilename, &fsSpec);
- if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr )
- return SQLITE_CANTOPEN;
-# endif
- if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){
- id->refNumRF = -1;
- }
- id->locked = 0;
- id->delOnClose = 0;
- OpenCounter(+1);
- return SQLITE_OK;
-#endif
-}
-
-/*
-** Attempt to open a file descriptor for the directory that contains a
-** file. This file descriptor can be used to fsync() the directory
-** in order to make sure the creation of a new file is actually written
-** to disk.
-**
-** This routine is only meaningful for Unix. It is a no-op under
-** windows since windows does not support hard links.
-**
-** On success, a handle for a previously open file is at *id is
-** updated with the new directory file descriptor and SQLITE_OK is
-** returned.
-**
-** On failure, the function returns SQLITE_CANTOPEN and leaves
-** *id unchanged.
-*/
-int sqliteOsOpenDirectory(
- const char *zDirname,
- OsFile *id
-){
-#if OS_UNIX
- if( id->fd<0 ){
- /* Do not open the directory if the corresponding file is not already
- ** open. */
- return SQLITE_CANTOPEN;
- }
- assert( id->dirfd<0 );
- id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644);
- if( id->dirfd<0 ){
- return SQLITE_CANTOPEN;
- }
- TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname);
-#endif
- return SQLITE_OK;
-}
-
-/*
-** If the following global variable points to a string which is the
-** name of a directory, then that directory will be used to store
-** temporary files.
-*/
-const char *sqlite_temp_directory = 0;
-
-/*
-** Create a temporary file name in zBuf. zBuf must be big enough to
-** hold at least SQLITE_TEMPNAME_SIZE characters.
-*/
-int sqliteOsTempFileName(char *zBuf){
-#if OS_UNIX
- static const char *azDirs[] = {
- 0,
- "/var/tmp",
- "/usr/tmp",
- "/tmp",
- ".",
- };
- static unsigned char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789";
- int i, j;
- struct stat buf;
- const char *zDir = ".";
- azDirs[0] = sqlite_temp_directory;
- for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
- if( azDirs[i]==0 ) continue;
- if( stat(azDirs[i], &buf) ) continue;
- if( !S_ISDIR(buf.st_mode) ) continue;
- if( access(azDirs[i], 07) ) continue;
- zDir = azDirs[i];
- break;
- }
- do{
- sprintf(zBuf, "%s/"TEMP_FILE_PREFIX, zDir);
- j = strlen(zBuf);
- sqliteRandomness(15, &zBuf[j]);
- for(i=0; i<15; i++, j++){
- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
- }
- zBuf[j] = 0;
- }while( access(zBuf,0)==0 );
-#endif
-#if OS_WIN
- static char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789";
- int i, j;
- const char *zDir;
- char zTempPath[SQLITE_TEMPNAME_SIZE];
- if( sqlite_temp_directory==0 ){
- GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath);
- for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
- zTempPath[i] = 0;
- zDir = zTempPath;
- }else{
- zDir = sqlite_temp_directory;
- }
- for(;;){
- sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir);
- j = strlen(zBuf);
- sqliteRandomness(15, &zBuf[j]);
- for(i=0; i<15; i++, j++){
- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
- }
- zBuf[j] = 0;
- if( !sqliteOsFileExists(zBuf) ) break;
- }
-#endif
-#if OS_MAC
- static char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789";
- int i, j;
- char *zDir;
- char zTempPath[SQLITE_TEMPNAME_SIZE];
- char zdirName[32];
- CInfoPBRec infoRec;
- Str31 dirName;
- memset(&infoRec, 0, sizeof(infoRec));
- memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE);
- if( sqlite_temp_directory!=0 ){
- zDir = sqlite_temp_directory;
- }else if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
- &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){
- infoRec.dirInfo.ioNamePtr = dirName;
- do{
- infoRec.dirInfo.ioFDirIndex = -1;
- infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID;
- if( PBGetCatInfoSync(&infoRec) == noErr ){
- CopyPascalStringToC(dirName, zdirName);
- i = strlen(zdirName);
- memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath));
- strcpy(zTempPath, zdirName);
- zTempPath[i] = ':';
- }else{
- *zTempPath = 0;
- break;
- }
- } while( infoRec.dirInfo.ioDrDirID != fsRtDirID );
- zDir = zTempPath;
- }
- if( zDir[0]==0 ){
- getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24);
- zDir = zTempPath;
- }
- for(;;){
- sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir);
- j = strlen(zBuf);
- sqliteRandomness(15, &zBuf[j]);
- for(i=0; i<15; i++, j++){
- zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
- }
- zBuf[j] = 0;
- if( !sqliteOsFileExists(zBuf) ) break;
- }
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Close a file.
-*/
-int sqliteOsClose(OsFile *id){
-#if OS_UNIX
- sqliteOsUnlock(id);
- if( id->dirfd>=0 ) close(id->dirfd);
- id->dirfd = -1;
- sqliteOsEnterMutex();
- if( id->pOpen->nLock ){
- /* If there are outstanding locks, do not actually close the file just
- ** yet because that would clear those locks. Instead, add the file
- ** descriptor to pOpen->aPending. It will be automatically closed when
- ** the last lock is cleared.
- */
- int *aNew;
- struct openCnt *pOpen = id->pOpen;
- pOpen->nPending++;
- aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) );
- if( aNew==0 ){
- /* If a malloc fails, just leak the file descriptor */
- }else{
- pOpen->aPending = aNew;
- pOpen->aPending[pOpen->nPending-1] = id->fd;
- }
- }else{
- /* There are no outstanding locks so we can close the file immediately */
- close(id->fd);
- }
- releaseLockInfo(id->pLock);
- releaseOpenCnt(id->pOpen);
- sqliteOsLeaveMutex();
- TRACE2("CLOSE %-3d\n", id->fd);
- OpenCounter(-1);
- return SQLITE_OK;
-#endif
-#if OS_WIN
- CloseHandle(id->h);
- OpenCounter(-1);
- return SQLITE_OK;
-#endif
-#if OS_MAC
- if( id->refNumRF!=-1 )
- FSClose(id->refNumRF);
-# ifdef _LARGE_FILE
- FSCloseFork(id->refNum);
-# else
- FSClose(id->refNum);
-# endif
- if( id->delOnClose ){
- unlink(id->pathToDel);
- sqliteFree(id->pathToDel);
- }
- OpenCounter(-1);
- return SQLITE_OK;
-#endif
-}
-
-/*
-** Read data from a file into a buffer. Return SQLITE_OK if all
-** bytes were read successfully and SQLITE_IOERR if anything goes
-** wrong.
-*/
-int sqliteOsRead(OsFile *id, void *pBuf, int amt){
-#if OS_UNIX
- int got;
- SimulateIOError(SQLITE_IOERR);
- TIMER_START;
- got = read(id->fd, pBuf, amt);
- TIMER_END;
- TRACE4("READ %-3d %7d %d\n", id->fd, last_page, elapse);
- SEEK(0);
- /* if( got<0 ) got = 0; */
- if( got==amt ){
- return SQLITE_OK;
- }else{
- return SQLITE_IOERR;
- }
-#endif
-#if OS_WIN
- DWORD got;
- SimulateIOError(SQLITE_IOERR);
- TRACE2("READ %d\n", last_page);
- if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
- got = 0;
- }
- if( got==(DWORD)amt ){
- return SQLITE_OK;
- }else{
- return SQLITE_IOERR;
- }
-#endif
-#if OS_MAC
- int got;
- SimulateIOError(SQLITE_IOERR);
- TRACE2("READ %d\n", last_page);
-# ifdef _LARGE_FILE
- FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got);
-# else
- got = amt;
- FSRead(id->refNum, &got, pBuf);
-# endif
- if( got==amt ){
- return SQLITE_OK;
- }else{
- return SQLITE_IOERR;
- }
-#endif
-}
-
-/*
-** Write data from a buffer into a file. Return SQLITE_OK on success
-** or some other error code on failure.
-*/
-int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
-#if OS_UNIX
- int wrote = 0;
- SimulateIOError(SQLITE_IOERR);
- TIMER_START;
- while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){
- amt -= wrote;
- pBuf = &((char*)pBuf)[wrote];
- }
- TIMER_END;
- TRACE4("WRITE %-3d %7d %d\n", id->fd, last_page, elapse);
- SEEK(0);
- if( amt>0 ){
- return SQLITE_FULL;
- }
- return SQLITE_OK;
-#endif
-#if OS_WIN
- int rc;
- DWORD wrote;
- SimulateIOError(SQLITE_IOERR);
- TRACE2("WRITE %d\n", last_page);
- while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
- amt -= wrote;
- pBuf = &((char*)pBuf)[wrote];
- }
- if( !rc || amt>(int)wrote ){
- return SQLITE_FULL;
- }
- return SQLITE_OK;
-#endif
-#if OS_MAC
- OSErr oserr;
- int wrote = 0;
- SimulateIOError(SQLITE_IOERR);
- TRACE2("WRITE %d\n", last_page);
- while( amt>0 ){
-# ifdef _LARGE_FILE
- oserr = FSWriteFork(id->refNum, fsAtMark, 0,
- (ByteCount)amt, pBuf, (ByteCount*)&wrote);
-# else
- wrote = amt;
- oserr = FSWrite(id->refNum, &wrote, pBuf);
-# endif
- if( wrote == 0 || oserr != noErr)
- break;
- amt -= wrote;
- pBuf = &((char*)pBuf)[wrote];
- }
- if( oserr != noErr || amt>wrote ){
- return SQLITE_FULL;
- }
- return SQLITE_OK;
-#endif
-}
-
-/*
-** Move the read/write pointer in a file.
-*/
-int sqliteOsSeek(OsFile *id, off_t offset){
- SEEK(offset/1024 + 1);
-#if OS_UNIX
- lseek(id->fd, offset, SEEK_SET);
- return SQLITE_OK;
-#endif
-#if OS_WIN
- {
- LONG upperBits = offset>>32;
- LONG lowerBits = offset & 0xffffffff;
- DWORD rc;
- rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
- /* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */
- }
- return SQLITE_OK;
-#endif
-#if OS_MAC
- {
- off_t curSize;
- if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){
- return SQLITE_IOERR;
- }
- if( offset >= curSize ){
- if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){
- return SQLITE_IOERR;
- }
- }
-# ifdef _LARGE_FILE
- if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){
-# else
- if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){
-# endif
- return SQLITE_IOERR;
- }else{
- return SQLITE_OK;
- }
- }
-#endif
-}
-
-#ifdef SQLITE_NOSYNC
-# define fsync(X) 0
-#endif
-
-/*
-** Make sure all writes to a particular file are committed to disk.
-**
-** Under Unix, also make sure that the directory entry for the file
-** has been created by fsync-ing the directory that contains the file.
-** If we do not do this and we encounter a power failure, the directory
-** entry for the journal might not exist after we reboot. The next
-** SQLite to access the file will not know that the journal exists (because
-** the directory entry for the journal was never created) and the transaction
-** will not roll back - possibly leading to database corruption.
-*/
-int sqliteOsSync(OsFile *id){
-#if OS_UNIX
- SimulateIOError(SQLITE_IOERR);
- TRACE2("SYNC %-3d\n", id->fd);
- if( fsync(id->fd) ){
- return SQLITE_IOERR;
- }else{
- if( id->dirfd>=0 ){
- TRACE2("DIRSYNC %-3d\n", id->dirfd);
- fsync(id->dirfd);
- close(id->dirfd); /* Only need to sync once, so close the directory */
- id->dirfd = -1; /* when we are done. */
- }
- return SQLITE_OK;
- }
-#endif
-#if OS_WIN
- if( FlushFileBuffers(id->h) ){
- return SQLITE_OK;
- }else{
- return SQLITE_IOERR;
- }
-#endif
-#if OS_MAC
-# ifdef _LARGE_FILE
- if( FSFlushFork(id->refNum) != noErr ){
-# else
- ParamBlockRec params;
- memset(&params, 0, sizeof(ParamBlockRec));
- params.ioParam.ioRefNum = id->refNum;
- if( PBFlushFileSync(&params) != noErr ){
-# endif
- return SQLITE_IOERR;
- }else{
- return SQLITE_OK;
- }
-#endif
-}
-
-/*
-** Truncate an open file to a specified size
-*/
-int sqliteOsTruncate(OsFile *id, off_t nByte){
- SimulateIOError(SQLITE_IOERR);
-#if OS_UNIX
- return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
-#endif
-#if OS_WIN
- {
- LONG upperBits = nByte>>32;
- SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN);
- SetEndOfFile(id->h);
- }
- return SQLITE_OK;
-#endif
-#if OS_MAC
-# ifdef _LARGE_FILE
- if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){
-# else
- if( SetEOF(id->refNum, nByte) != noErr ){
-# endif
- return SQLITE_IOERR;
- }else{
- return SQLITE_OK;
- }
-#endif
-}
-
-/*
-** Determine the current size of a file in bytes
-*/
-int sqliteOsFileSize(OsFile *id, off_t *pSize){
-#if OS_UNIX
- struct stat buf;
- SimulateIOError(SQLITE_IOERR);
- if( fstat(id->fd, &buf)!=0 ){
- return SQLITE_IOERR;
- }
- *pSize = buf.st_size;
- return SQLITE_OK;
-#endif
-#if OS_WIN
- DWORD upperBits, lowerBits;
- SimulateIOError(SQLITE_IOERR);
- lowerBits = GetFileSize(id->h, &upperBits);
- *pSize = (((off_t)upperBits)<<32) + lowerBits;
- return SQLITE_OK;
-#endif
-#if OS_MAC
-# ifdef _LARGE_FILE
- if( FSGetForkSize(id->refNum, pSize) != noErr){
-# else
- if( GetEOF(id->refNum, pSize) != noErr ){
-# endif
- return SQLITE_IOERR;
- }else{
- return SQLITE_OK;
- }
-#endif
-}
-
-#if OS_WIN
-/*
-** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
-** Return false (zero) for Win95, Win98, or WinME.
-**
-** Here is an interesting observation: Win95, Win98, and WinME lack
-** the LockFileEx() API. But we can still statically link against that
-** API as long as we don't call it win running Win95/98/ME. A call to
-** this routine is used to determine if the host is Win95/98/ME or
-** WinNT/2K/XP so that we will know whether or not we can safely call
-** the LockFileEx() API.
-*/
-int isNT(void){
- static int osType = 0; /* 0=unknown 1=win95 2=winNT */
- if( osType==0 ){
- OSVERSIONINFO sInfo;
- sInfo.dwOSVersionInfoSize = sizeof(sInfo);
- GetVersionEx(&sInfo);
- osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
- }
- return osType==2;
-}
-#endif
-
-/*
-** Windows file locking notes: [similar issues apply to MacOS]
-**
-** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
-** those functions are not available. So we use only LockFile() and
-** UnlockFile().
-**
-** LockFile() prevents not just writing but also reading by other processes.
-** (This is a design error on the part of Windows, but there is nothing
-** we can do about that.) So the region used for locking is at the
-** end of the file where it is unlikely to ever interfere with an
-** actual read attempt.
-**
-** A database read lock is obtained by locking a single randomly-chosen
-** byte out of a specific range of bytes. The lock byte is obtained at
-** random so two separate readers can probably access the file at the
-** same time, unless they are unlucky and choose the same lock byte.
-** A database write lock is obtained by locking all bytes in the range.
-** There can only be one writer.
-**
-** A lock is obtained on the first byte of the lock range before acquiring
-** either a read lock or a write lock. This prevents two processes from
-** attempting to get a lock at a same time. The semantics of
-** sqliteOsReadLock() require that if there is already a write lock, that
-** lock is converted into a read lock atomically. The lock on the first
-** byte allows us to drop the old write lock and get the read lock without
-** another process jumping into the middle and messing us up. The same
-** argument applies to sqliteOsWriteLock().
-**
-** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
-** which means we can use reader/writer locks. When reader writer locks
-** are used, the lock is placed on the same range of bytes that is used
-** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
-** will support two or more Win95 readers or two or more WinNT readers.
-** But a single Win95 reader will lock out all WinNT readers and a single
-** WinNT reader will lock out all other Win95 readers.
-**
-** Note: On MacOS we use the resource fork for locking.
-**
-** The following #defines specify the range of bytes used for locking.
-** N_LOCKBYTE is the number of bytes available for doing the locking.
-** The first byte used to hold the lock while the lock is changing does
-** not count toward this number. FIRST_LOCKBYTE is the address of
-** the first byte in the range of bytes used for locking.
-*/
-#define N_LOCKBYTE 10239
-#if OS_MAC
-# define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE)
-#else
-# define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE)
-#endif
-
-/*
-** Change the status of the lock on the file "id" to be a readlock.
-** If the file was write locked, then this reduces the lock to a read.
-** If the file was read locked, then this acquires a new read lock.
-**
-** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this
-** library was compiled with large file support (LFS) but LFS is not
-** available on the host, then an SQLITE_NOLFS is returned.
-*/
-int sqliteOsReadLock(OsFile *id){
-#if OS_UNIX
- int rc;
- sqliteOsEnterMutex();
- if( id->pLock->cnt>0 ){
- if( !id->locked ){
- id->pLock->cnt++;
- id->locked = 1;
- id->pOpen->nLock++;
- }
- rc = SQLITE_OK;
- }else if( id->locked || id->pLock->cnt==0 ){
- struct flock lock;
- int s;
- lock.l_type = F_RDLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = lock.l_len = 0L;
- s = fcntl(id->fd, F_SETLK, &lock);
- if( s!=0 ){
- rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
- }else{
- rc = SQLITE_OK;
- if( !id->locked ){
- id->pOpen->nLock++;
- id->locked = 1;
- }
- id->pLock->cnt = 1;
- }
- }else{
- rc = SQLITE_BUSY;
- }
- sqliteOsLeaveMutex();
- return rc;
-#endif
-#if OS_WIN
- int rc;
- if( id->locked>0 ){
- rc = SQLITE_OK;
- }else{
- int lk;
- int res;
- int cnt = 100;
- sqliteRandomness(sizeof(lk), &lk);
- lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
- while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
- Sleep(1);
- }
- if( res ){
- UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
- if( isNT() ){
- OVERLAPPED ovlp;
- ovlp.Offset = FIRST_LOCKBYTE+1;
- ovlp.OffsetHigh = 0;
- ovlp.hEvent = 0;
- res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY,
- 0, N_LOCKBYTE, 0, &ovlp);
- }else{
- res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
- }
- UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
- }
- if( res ){
- id->locked = lk;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- }
- return rc;
-#endif
-#if OS_MAC
- int rc;
- if( id->locked>0 || id->refNumRF == -1 ){
- rc = SQLITE_OK;
- }else{
- int lk;
- OSErr res;
- int cnt = 5;
- ParamBlockRec params;
- sqliteRandomness(sizeof(lk), &lk);
- lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
- memset(&params, 0, sizeof(params));
- params.ioParam.ioRefNum = id->refNumRF;
- params.ioParam.ioPosMode = fsFromStart;
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
- params.ioParam.ioReqCount = 1;
- while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){
- UInt32 finalTicks;
- Delay(1, &finalTicks); /* 1/60 sec */
- }
- if( res == noErr ){
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
- params.ioParam.ioReqCount = N_LOCKBYTE;
- PBUnlockRangeSync(&params);
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;
- params.ioParam.ioReqCount = 1;
- res = PBLockRangeSync(&params);
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
- params.ioParam.ioReqCount = 1;
- PBUnlockRangeSync(&params);
- }
- if( res == noErr ){
- id->locked = lk;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- }
- return rc;
-#endif
-}
-
-/*
-** Change the lock status to be an exclusive or write lock. Return
-** SQLITE_OK on success and SQLITE_BUSY on a failure. If this
-** library was compiled with large file support (LFS) but LFS is not
-** available on the host, then an SQLITE_NOLFS is returned.
-*/
-int sqliteOsWriteLock(OsFile *id){
-#if OS_UNIX
- int rc;
- sqliteOsEnterMutex();
- if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){
- struct flock lock;
- int s;
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = lock.l_len = 0L;
- s = fcntl(id->fd, F_SETLK, &lock);
- if( s!=0 ){
- rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
- }else{
- rc = SQLITE_OK;
- if( !id->locked ){
- id->pOpen->nLock++;
- id->locked = 1;
- }
- id->pLock->cnt = -1;
- }
- }else{
- rc = SQLITE_BUSY;
- }
- sqliteOsLeaveMutex();
- return rc;
-#endif
-#if OS_WIN
- int rc;
- if( id->locked<0 ){
- rc = SQLITE_OK;
- }else{
- int res;
- int cnt = 100;
- while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
- Sleep(1);
- }
- if( res ){
- if( id->locked>0 ){
- if( isNT() ){
- UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
- }else{
- res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
- }
- }
- if( res ){
- res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
- }else{
- res = 0;
- }
- UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
- }
- if( res ){
- id->locked = -1;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- }
- return rc;
-#endif
-#if OS_MAC
- int rc;
- if( id->locked<0 || id->refNumRF == -1 ){
- rc = SQLITE_OK;
- }else{
- OSErr res;
- int cnt = 5;
- ParamBlockRec params;
- memset(&params, 0, sizeof(params));
- params.ioParam.ioRefNum = id->refNumRF;
- params.ioParam.ioPosMode = fsFromStart;
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
- params.ioParam.ioReqCount = 1;
- while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){
- UInt32 finalTicks;
- Delay(1, &finalTicks); /* 1/60 sec */
- }
- if( res == noErr ){
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked;
- params.ioParam.ioReqCount = 1;
- if( id->locked==0
- || PBUnlockRangeSync(&params)==noErr ){
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
- params.ioParam.ioReqCount = N_LOCKBYTE;
- res = PBLockRangeSync(&params);
- }else{
- res = afpRangeNotLocked;
- }
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE;
- params.ioParam.ioReqCount = 1;
- PBUnlockRangeSync(&params);
- }
- if( res == noErr ){
- id->locked = -1;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- }
- return rc;
-#endif
-}
-
-/*
-** Unlock the given file descriptor. If the file descriptor was
-** not previously locked, then this routine is a no-op. If this
-** library was compiled with large file support (LFS) but LFS is not
-** available on the host, then an SQLITE_NOLFS is returned.
-*/
-int sqliteOsUnlock(OsFile *id){
-#if OS_UNIX
- int rc;
- if( !id->locked ) return SQLITE_OK;
- sqliteOsEnterMutex();
- assert( id->pLock->cnt!=0 );
- if( id->pLock->cnt>1 ){
- id->pLock->cnt--;
- rc = SQLITE_OK;
- }else{
- struct flock lock;
- int s;
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = lock.l_len = 0L;
- s = fcntl(id->fd, F_SETLK, &lock);
- if( s!=0 ){
- rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
- }else{
- rc = SQLITE_OK;
- id->pLock->cnt = 0;
- }
- }
- if( rc==SQLITE_OK ){
- /* Decrement the count of locks against this same file. When the
- ** count reaches zero, close any other file descriptors whose close
- ** was deferred because of outstanding locks.
- */
- struct openCnt *pOpen = id->pOpen;
- pOpen->nLock--;
- assert( pOpen->nLock>=0 );
- if( pOpen->nLock==0 && pOpen->nPending>0 ){
- int i;
- for(i=0; i<pOpen->nPending; i++){
- close(pOpen->aPending[i]);
- }
- sqliteFree(pOpen->aPending);
- pOpen->nPending = 0;
- pOpen->aPending = 0;
- }
- }
- sqliteOsLeaveMutex();
- id->locked = 0;
- return rc;
-#endif
-#if OS_WIN
- int rc;
- if( id->locked==0 ){
- rc = SQLITE_OK;
- }else if( isNT() || id->locked<0 ){
- UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
- rc = SQLITE_OK;
- id->locked = 0;
- }else{
- UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
- rc = SQLITE_OK;
- id->locked = 0;
- }
- return rc;
-#endif
-#if OS_MAC
- int rc;
- ParamBlockRec params;
- memset(&params, 0, sizeof(params));
- params.ioParam.ioRefNum = id->refNumRF;
- params.ioParam.ioPosMode = fsFromStart;
- if( id->locked==0 || id->refNumRF == -1 ){
- rc = SQLITE_OK;
- }else if( id->locked<0 ){
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;
- params.ioParam.ioReqCount = N_LOCKBYTE;
- PBUnlockRangeSync(&params);
- rc = SQLITE_OK;
- id->locked = 0;
- }else{
- params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked;
- params.ioParam.ioReqCount = 1;
- PBUnlockRangeSync(&params);
- rc = SQLITE_OK;
- id->locked = 0;
- }
- return rc;
-#endif
-}
-
-/*
-** Get information to seed the random number generator. The seed
-** is written into the buffer zBuf[256]. The calling function must
-** supply a sufficiently large buffer.
-*/
-int sqliteOsRandomSeed(char *zBuf){
- /* We have to initialize zBuf to prevent valgrind from reporting
- ** errors. The reports issued by valgrind are incorrect - we would
- ** prefer that the randomness be increased by making use of the
- ** uninitialized space in zBuf - but valgrind errors tend to worry
- ** some users. Rather than argue, it seems easier just to initialize
- ** the whole array and silence valgrind, even if that means less randomness
- ** in the random seed.
- **
- ** When testing, initializing zBuf[] to zero is all we do. That means
- ** that we always use the same random number sequence.* This makes the
- ** tests repeatable.
- */
- memset(zBuf, 0, 256);
-#if OS_UNIX && !defined(SQLITE_TEST)
- {
- int pid;
- time((time_t*)zBuf);
- pid = getpid();
- memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
- }
-#endif
-#if OS_WIN && !defined(SQLITE_TEST)
- GetSystemTime((LPSYSTEMTIME)zBuf);
-#endif
-#if OS_MAC
- {
- int pid;
- Microseconds((UnsignedWide*)zBuf);
- pid = getpid();
- memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid));
- }
-#endif
- return SQLITE_OK;
-}
-
-/*
-** Sleep for a little while. Return the amount of time slept.
-*/
-int sqliteOsSleep(int ms){
-#if OS_UNIX
-#if defined(HAVE_USLEEP) && HAVE_USLEEP
- usleep(ms*1000);
- return ms;
-#else
- sleep((ms+999)/1000);
- return 1000*((ms+999)/1000);
-#endif
-#endif
-#if OS_WIN
- Sleep(ms);
- return ms;
-#endif
-#if OS_MAC
- UInt32 finalTicks;
- UInt32 ticks = (((UInt32)ms+16)*3)/50; /* 1/60 sec per tick */
- Delay(ticks, &finalTicks);
- return (int)((ticks*50)/3);
-#endif
-}
-
-/*
-** Static variables used for thread synchronization
-*/
-static int inMutex = 0;
-#ifdef SQLITE_UNIX_THREADS
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-#endif
-#ifdef SQLITE_W32_THREADS
- static CRITICAL_SECTION cs;
-#endif
-#ifdef SQLITE_MACOS_MULTITASKING
- static MPCriticalRegionID criticalRegion;
-#endif
-
-/*
-** The following pair of routine implement mutual exclusion for
-** multi-threaded processes. Only a single thread is allowed to
-** executed code that is surrounded by EnterMutex() and LeaveMutex().
-**
-** SQLite uses only a single Mutex. There is not much critical
-** code and what little there is executes quickly and without blocking.
-*/
-void sqliteOsEnterMutex(){
-#ifdef SQLITE_UNIX_THREADS
- pthread_mutex_lock(&mutex);
-#endif
-#ifdef SQLITE_W32_THREADS
- static int isInit = 0;
- while( !isInit ){
- static long lock = 0;
- if( InterlockedIncrement(&lock)==1 ){
- InitializeCriticalSection(&cs);
- isInit = 1;
- }else{
- Sleep(1);
- }
- }
- EnterCriticalSection(&cs);
-#endif
-#ifdef SQLITE_MACOS_MULTITASKING
- static volatile int notInit = 1;
- if( notInit ){
- if( notInit == 2 ) /* as close as you can get to thread safe init */
- MPYield();
- else{
- notInit = 2;
- MPCreateCriticalRegion(&criticalRegion);
- notInit = 0;
- }
- }
- MPEnterCriticalRegion(criticalRegion, kDurationForever);
-#endif
- assert( !inMutex );
- inMutex = 1;
-}
-void sqliteOsLeaveMutex(){
- assert( inMutex );
- inMutex = 0;
-#ifdef SQLITE_UNIX_THREADS
- pthread_mutex_unlock(&mutex);
-#endif
-#ifdef SQLITE_W32_THREADS
- LeaveCriticalSection(&cs);
-#endif
-#ifdef SQLITE_MACOS_MULTITASKING
- MPExitCriticalRegion(criticalRegion);
-#endif
-}
-
-/*
-** Turn a relative pathname into a full pathname. Return a pointer
-** to the full pathname stored in space obtained from sqliteMalloc().
-** The calling function is responsible for freeing this space once it
-** is no longer needed.
-*/
-char *sqliteOsFullPathname(const char *zRelative){
-#if OS_UNIX
- char *zFull = 0;
- if( zRelative[0]=='/' ){
- sqliteSetString(&zFull, zRelative, (char*)0);
- }else{
- char zBuf[5000];
- zBuf[0] = 0;
- sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
- (char*)0);
- }
- return zFull;
-#endif
-#if OS_WIN
- char *zNotUsed;
- char *zFull;
- int nByte;
- nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;
- zFull = sqliteMalloc( nByte );
- if( zFull==0 ) return 0;
- GetFullPathName(zRelative, nByte, zFull, &zNotUsed);
- return zFull;
-#endif
-#if OS_MAC
- char *zFull = 0;
- if( zRelative[0]==':' ){
- char zBuf[_MAX_PATH+1];
- sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]),
- (char*)0);
- }else{
- if( strchr(zRelative, ':') ){
- sqliteSetString(&zFull, zRelative, (char*)0);
- }else{
- char zBuf[_MAX_PATH+1];
- sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0);
- }
- }
- return zFull;
-#endif
-}
-
-/*
-** The following variable, if set to a non-zero value, becomes the result
-** returned from sqliteOsCurrentTime(). This is used for testing.
-*/
-#ifdef SQLITE_TEST
-int sqlite_current_time = 0;
-#endif
-
-/*
-** Find the current time (in Universal Coordinated Time). Write the
-** current time and date as a Julian Day number into *prNow and
-** return 0. Return 1 if the time and date cannot be found.
-*/
-int sqliteOsCurrentTime(double *prNow){
-#if OS_UNIX
- time_t t;
- time(&t);
- *prNow = t/86400.0 + 2440587.5;
-#endif
-#if OS_WIN
- FILETIME ft;
- /* FILETIME structure is a 64-bit value representing the number of
- 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
- */
- double now;
- GetSystemTimeAsFileTime( &ft );
- now = ((double)ft.dwHighDateTime) * 4294967296.0;
- *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
-#endif
-#ifdef SQLITE_TEST
- if( sqlite_current_time ){
- *prNow = sqlite_current_time/86400.0 + 2440587.5;
- }
-#endif
- return 0;
-}
diff --git a/ext/sqlite/libsqlite/src/os.h b/ext/sqlite/libsqlite/src/os.h
deleted file mode 100644
index d1395841d2..0000000000
--- a/ext/sqlite/libsqlite/src/os.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-** 2001 September 16
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This header file (together with is companion C source-code file
-** "os.c") attempt to abstract the underlying operating system so that
-** the SQLite library will work on both POSIX and windows systems.
-*/
-#ifndef _SQLITE_OS_H_
-#define _SQLITE_OS_H_
-
-/*
-** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE
-** to the compiler command line.
-*/
-
-/*
-** These #defines should enable >2GB file support on Posix if the
-** underlying operating system supports it. If the OS lacks
-** large file support, or if the OS is windows, these should be no-ops.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: RedHat 7.2) but you want your code to work
-** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
-** without this option, LFS is enable. But LFS does not exist in the kernel
-** in RedHat 6.0, so the code won't work. Hence, for maximum binary
-** portability you should omit LFS.
-**
-** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-/*
-** Temporary files are named starting with this prefix followed by 16 random
-** alphanumeric characters, and no file extension. They are stored in the
-** OS's standard temporary file directory, and are deleted prior to exit.
-** If sqlite is being embedded in another program, you may wish to change the
-** prefix to reflect your program's name, so that if your program exits
-** prematurely, old temporary files can be easily identified. This can be done
-** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
-*/
-#ifndef TEMP_FILE_PREFIX
-# define TEMP_FILE_PREFIX "sqlite_"
-#endif
-
-/*
-** Figure out if we are dealing with Unix, Windows or MacOS.
-**
-** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix.
-** The MacOS build is designed to use CodeWarrior (tested with v8)
-*/
-#ifndef OS_UNIX
-# ifndef OS_WIN
-# ifndef OS_MAC
-# if defined(__MACOS__)
-# define OS_MAC 1
-# define OS_WIN 0
-# define OS_UNIX 0
-# elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
-# define OS_MAC 0
-# define OS_WIN 1
-# define OS_UNIX 0
-# else
-# define OS_MAC 0
-# define OS_WIN 0
-# define OS_UNIX 1
-# endif
-# else
-# define OS_WIN 0
-# define OS_UNIX 0
-# endif
-# else
-# define OS_MAC 0
-# define OS_UNIX 0
-# endif
-#else
-# define OS_MAC 0
-# ifndef OS_WIN
-# define OS_WIN 0
-# endif
-#endif
-
-/*
-** A handle for an open file is stored in an OsFile object.
-*/
-#if OS_UNIX
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <unistd.h>
- typedef struct OsFile OsFile;
- struct OsFile {
- struct openCnt *pOpen; /* Info about all open fd's on this inode */
- struct lockInfo *pLock; /* Info about locks on this inode */
- int fd; /* The file descriptor */
- int locked; /* True if this instance holds the lock */
- int dirfd; /* File descriptor for the directory */
- };
-# define SQLITE_TEMPNAME_SIZE 200
-# if defined(HAVE_USLEEP) && HAVE_USLEEP
-# define SQLITE_MIN_SLEEP_MS 1
-# else
-# define SQLITE_MIN_SLEEP_MS 1000
-# endif
-#endif
-
-#if OS_WIN
-#include <windows.h>
-#include <winbase.h>
- typedef struct OsFile OsFile;
- struct OsFile {
- HANDLE h; /* Handle for accessing the file */
- int locked; /* 0: unlocked, <0: write lock, >0: read lock */
- };
-# if defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 off_t;
-# else
-# if !defined(_CYGWIN_TYPES_H)
- typedef long long off_t;
-# if defined(__MINGW32__)
-# define _OFF_T_
-# endif
-# endif
-# endif
-# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
-# define SQLITE_MIN_SLEEP_MS 1
-#endif
-
-#if OS_MAC
-# include <unistd.h>
-# include <Files.h>
- typedef struct OsFile OsFile;
- struct OsFile {
- SInt16 refNum; /* Data fork/file reference number */
- SInt16 refNumRF; /* Resource fork reference number (for locking) */
- int locked; /* 0: unlocked, <0: write lock, >0: read lock */
- int delOnClose; /* True if file is to be deleted on close */
- char *pathToDel; /* Name of file to delete on close */
- };
-# ifdef _LARGE_FILE
- typedef SInt64 off_t;
-# else
- typedef SInt32 off_t;
-# endif
-# define SQLITE_TEMPNAME_SIZE _MAX_PATH
-# define SQLITE_MIN_SLEEP_MS 17
-#endif
-
-int sqliteOsDelete(const char*);
-int sqliteOsFileExists(const char*);
-int sqliteOsFileRename(const char*, const char*);
-int sqliteOsOpenReadWrite(const char*, OsFile*, int*);
-int sqliteOsOpenExclusive(const char*, OsFile*, int);
-int sqliteOsOpenReadOnly(const char*, OsFile*);
-int sqliteOsOpenDirectory(const char*, OsFile*);
-int sqliteOsTempFileName(char*);
-int sqliteOsClose(OsFile*);
-int sqliteOsRead(OsFile*, void*, int amt);
-int sqliteOsWrite(OsFile*, const void*, int amt);
-int sqliteOsSeek(OsFile*, off_t offset);
-int sqliteOsSync(OsFile*);
-int sqliteOsTruncate(OsFile*, off_t size);
-int sqliteOsFileSize(OsFile*, off_t *pSize);
-int sqliteOsReadLock(OsFile*);
-int sqliteOsWriteLock(OsFile*);
-int sqliteOsUnlock(OsFile*);
-int sqliteOsRandomSeed(char*);
-int sqliteOsSleep(int ms);
-int sqliteOsCurrentTime(double*);
-void sqliteOsEnterMutex(void);
-void sqliteOsLeaveMutex(void);
-char *sqliteOsFullPathname(const char*);
-
-
-
-#endif /* _SQLITE_OS_H_ */
diff --git a/ext/sqlite/libsqlite/src/pager.c b/ext/sqlite/libsqlite/src/pager.c
deleted file mode 100644
index 278a99f604..0000000000
--- a/ext/sqlite/libsqlite/src/pager.c
+++ /dev/null
@@ -1,2220 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This is the implementation of the page cache subsystem or "pager".
-**
-** The pager is used to access a database disk file. It implements
-** atomic commit and rollback through the use of a journal file that
-** is separate from the database file. The pager also implements file
-** locking to prevent two processes from writing the same database
-** file simultaneously, or one process from reading the database while
-** another is writing.
-**
-** @(#) $Id$
-*/
-#include "os.h" /* Must be first to enable large file support */
-#include "sqliteInt.h"
-#include "pager.h"
-#include <assert.h>
-#include <string.h>
-
-/*
-** Macros for troubleshooting. Normally turned off
-*/
-#if 0
-static Pager *mainPager = 0;
-#define SET_PAGER(X) if( mainPager==0 ) mainPager = (X)
-#define CLR_PAGER(X) if( mainPager==(X) ) mainPager = 0
-#define TRACE1(X) if( pPager==mainPager ) fprintf(stderr,X)
-#define TRACE2(X,Y) if( pPager==mainPager ) fprintf(stderr,X,Y)
-#define TRACE3(X,Y,Z) if( pPager==mainPager ) fprintf(stderr,X,Y,Z)
-#else
-#define SET_PAGER(X)
-#define CLR_PAGER(X)
-#define TRACE1(X)
-#define TRACE2(X,Y)
-#define TRACE3(X,Y,Z)
-#endif
-
-
-/*
-** The page cache as a whole is always in one of the following
-** states:
-**
-** SQLITE_UNLOCK The page cache is not currently reading or
-** writing the database file. There is no
-** data held in memory. This is the initial
-** state.
-**
-** SQLITE_READLOCK The page cache is reading the database.
-** Writing is not permitted. There can be
-** multiple readers accessing the same database
-** file at the same time.
-**
-** SQLITE_WRITELOCK The page cache is writing the database.
-** Access is exclusive. No other processes or
-** threads can be reading or writing while one
-** process is writing.
-**
-** The page cache comes up in SQLITE_UNLOCK. The first time a
-** sqlite_page_get() occurs, the state transitions to SQLITE_READLOCK.
-** After all pages have been released using sqlite_page_unref(),
-** the state transitions back to SQLITE_UNLOCK. The first time
-** that sqlite_page_write() is called, the state transitions to
-** SQLITE_WRITELOCK. (Note that sqlite_page_write() can only be
-** called on an outstanding page which means that the pager must
-** be in SQLITE_READLOCK before it transitions to SQLITE_WRITELOCK.)
-** The sqlite_page_rollback() and sqlite_page_commit() functions
-** transition the state from SQLITE_WRITELOCK back to SQLITE_READLOCK.
-*/
-#define SQLITE_UNLOCK 0
-#define SQLITE_READLOCK 1
-#define SQLITE_WRITELOCK 2
-
-
-/*
-** Each in-memory image of a page begins with the following header.
-** This header is only visible to this pager module. The client
-** code that calls pager sees only the data that follows the header.
-**
-** Client code should call sqlitepager_write() on a page prior to making
-** any modifications to that page. The first time sqlitepager_write()
-** is called, the original page contents are written into the rollback
-** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once
-** the journal page has made it onto the disk surface, PgHdr.needSync
-** is cleared. The modified page cannot be written back into the original
-** database file until the journal pages has been synced to disk and the
-** PgHdr.needSync has been cleared.
-**
-** The PgHdr.dirty flag is set when sqlitepager_write() is called and
-** is cleared again when the page content is written back to the original
-** database file.
-*/
-typedef struct PgHdr PgHdr;
-struct PgHdr {
- Pager *pPager; /* The pager to which this page belongs */
- Pgno pgno; /* The page number for this page */
- PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
- int nRef; /* Number of users of this page */
- PgHdr *pNextFree, *pPrevFree; /* Freelist of pages where nRef==0 */
- PgHdr *pNextAll, *pPrevAll; /* A list of all pages */
- PgHdr *pNextCkpt, *pPrevCkpt; /* List of pages in the checkpoint journal */
- u8 inJournal; /* TRUE if has been written to journal */
- u8 inCkpt; /* TRUE if written to the checkpoint journal */
- u8 dirty; /* TRUE if we need to write back changes */
- u8 needSync; /* Sync journal before writing this page */
- u8 alwaysRollback; /* Disable dont_rollback() for this page */
- PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */
- /* SQLITE_PAGE_SIZE bytes of page data follow this header */
- /* Pager.nExtra bytes of local data follow the page data */
-};
-
-
-/*
-** A macro used for invoking the codec if there is one
-*/
-#ifdef SQLITE_HAS_CODEC
-# define CODEC(P,D,N,X) if( P->xCodec ){ P->xCodec(P->pCodecArg,D,N,X); }
-#else
-# define CODEC(P,D,N,X)
-#endif
-
-/*
-** Convert a pointer to a PgHdr into a pointer to its data
-** and back again.
-*/
-#define PGHDR_TO_DATA(P) ((void*)(&(P)[1]))
-#define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1])
-#define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE])
-
-/*
-** How big to make the hash table used for locating in-memory pages
-** by page number.
-*/
-#define N_PG_HASH 2048
-
-/*
-** Hash a page number
-*/
-#define pager_hash(PN) ((PN)&(N_PG_HASH-1))
-
-/*
-** A open page cache is an instance of the following structure.
-*/
-struct Pager {
- char *zFilename; /* Name of the database file */
- char *zJournal; /* Name of the journal file */
- char *zDirectory; /* Directory hold database and journal files */
- OsFile fd, jfd; /* File descriptors for database and journal */
- OsFile cpfd; /* File descriptor for the checkpoint journal */
- int dbSize; /* Number of pages in the file */
- int origDbSize; /* dbSize before the current change */
- int ckptSize; /* Size of database (in pages) at ckpt_begin() */
- off_t ckptJSize; /* Size of journal at ckpt_begin() */
- int nRec; /* Number of pages written to the journal */
- u32 cksumInit; /* Quasi-random value added to every checksum */
- int ckptNRec; /* Number of records in the checkpoint journal */
- int nExtra; /* Add this many bytes to each in-memory page */
- void (*xDestructor)(void*); /* Call this routine when freeing pages */
- int nPage; /* Total number of in-memory pages */
- int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
- int mxPage; /* Maximum number of pages to hold in cache */
- int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
- void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
- void *pCodecArg; /* First argument to xCodec() */
- u8 journalOpen; /* True if journal file descriptors is valid */
- u8 journalStarted; /* True if header of journal is synced */
- u8 useJournal; /* Use a rollback journal on this file */
- u8 ckptOpen; /* True if the checkpoint journal is open */
- u8 ckptInUse; /* True we are in a checkpoint */
- u8 ckptAutoopen; /* Open ckpt journal when main journal is opened*/
- u8 noSync; /* Do not sync the journal if true */
- u8 fullSync; /* Do extra syncs of the journal for robustness */
- u8 state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */
- u8 errMask; /* One of several kinds of errors */
- u8 tempFile; /* zFilename is a temporary file */
- u8 readOnly; /* True for a read-only database */
- u8 needSync; /* True if an fsync() is needed on the journal */
- u8 dirtyFile; /* True if database file has changed in any way */
- u8 alwaysRollback; /* Disable dont_rollback() for all pages */
- u8 *aInJournal; /* One bit for each page in the database file */
- u8 *aInCkpt; /* One bit for each page in the database */
- PgHdr *pFirst, *pLast; /* List of free pages */
- PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */
- PgHdr *pAll; /* List of all pages */
- PgHdr *pCkpt; /* List of pages in the checkpoint journal */
- PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */
-};
-
-/*
-** These are bits that can be set in Pager.errMask.
-*/
-#define PAGER_ERR_FULL 0x01 /* a write() failed */
-#define PAGER_ERR_MEM 0x02 /* malloc() failed */
-#define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */
-#define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */
-#define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */
-
-/*
-** The journal file contains page records in the following
-** format.
-**
-** Actually, this structure is the complete page record for pager
-** formats less than 3. Beginning with format 3, this record is surrounded
-** by two checksums.
-*/
-typedef struct PageRecord PageRecord;
-struct PageRecord {
- Pgno pgno; /* The page number */
- char aData[SQLITE_PAGE_SIZE]; /* Original data for page pgno */
-};
-
-/*
-** Journal files begin with the following magic string. The data
-** was obtained from /dev/random. It is used only as a sanity check.
-**
-** There are three journal formats (so far). The 1st journal format writes
-** 32-bit integers in the byte-order of the host machine. New
-** formats writes integers as big-endian. All new journals use the
-** new format, but we have to be able to read an older journal in order
-** to rollback journals created by older versions of the library.
-**
-** The 3rd journal format (added for 2.8.0) adds additional sanity
-** checking information to the journal. If the power fails while the
-** journal is being written, semi-random garbage data might appear in
-** the journal file after power is restored. If an attempt is then made
-** to roll the journal back, the database could be corrupted. The additional
-** sanity checking data is an attempt to discover the garbage in the
-** journal and ignore it.
-**
-** The sanity checking information for the 3rd journal format consists
-** of a 32-bit checksum on each page of data. The checksum covers both
-** the page number and the SQLITE_PAGE_SIZE bytes of data for the page.
-** This cksum is initialized to a 32-bit random value that appears in the
-** journal file right after the header. The random initializer is important,
-** because garbage data that appears at the end of a journal is likely
-** data that was once in other files that have now been deleted. If the
-** garbage data came from an obsolete journal file, the checksums might
-** be correct. But by initializing the checksum to random value which
-** is different for every journal, we minimize that risk.
-*/
-static const unsigned char aJournalMagic1[] = {
- 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4,
-};
-static const unsigned char aJournalMagic2[] = {
- 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd5,
-};
-static const unsigned char aJournalMagic3[] = {
- 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd6,
-};
-#define JOURNAL_FORMAT_1 1
-#define JOURNAL_FORMAT_2 2
-#define JOURNAL_FORMAT_3 3
-
-/*
-** The following integer determines what format to use when creating
-** new primary journal files. By default we always use format 3.
-** When testing, we can set this value to older journal formats in order to
-** make sure that newer versions of the library are able to rollback older
-** journal files.
-**
-** Note that checkpoint journals always use format 2 and omit the header.
-*/
-#ifdef SQLITE_TEST
-int journal_format = 3;
-#else
-# define journal_format 3
-#endif
-
-/*
-** The size of the header and of each page in the journal varies according
-** to which journal format is being used. The following macros figure out
-** the sizes based on format numbers.
-*/
-#define JOURNAL_HDR_SZ(X) \
- (sizeof(aJournalMagic1) + sizeof(Pgno) + ((X)>=3)*2*sizeof(u32))
-#define JOURNAL_PG_SZ(X) \
- (SQLITE_PAGE_SIZE + sizeof(Pgno) + ((X)>=3)*sizeof(u32))
-
-/*
-** Enable reference count tracking here:
-*/
-#ifdef SQLITE_TEST
- int pager_refinfo_enable = 0;
- static void pager_refinfo(PgHdr *p){
- static int cnt = 0;
- if( !pager_refinfo_enable ) return;
- printf(
- "REFCNT: %4d addr=0x%08x nRef=%d\n",
- p->pgno, (int)PGHDR_TO_DATA(p), p->nRef
- );
- cnt++; /* Something to set a breakpoint on */
- }
-# define REFINFO(X) pager_refinfo(X)
-#else
-# define REFINFO(X)
-#endif
-
-/*
-** Read a 32-bit integer from the given file descriptor. Store the integer
-** that is read in *pRes. Return SQLITE_OK if everything worked, or an
-** error code is something goes wrong.
-**
-** If the journal format is 2 or 3, read a big-endian integer. If the
-** journal format is 1, read an integer in the native byte-order of the
-** host machine.
-*/
-static int read32bits(int format, OsFile *fd, u32 *pRes){
- u32 res;
- int rc;
- rc = sqliteOsRead(fd, &res, sizeof(res));
- if( rc==SQLITE_OK && format>JOURNAL_FORMAT_1 ){
- unsigned char ac[4];
- memcpy(ac, &res, 4);
- res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
- }
- *pRes = res;
- return rc;
-}
-
-/*
-** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
-** on success or an error code is something goes wrong.
-**
-** If the journal format is 2 or 3, write the integer as 4 big-endian
-** bytes. If the journal format is 1, write the integer in the native
-** byte order. In normal operation, only formats 2 and 3 are used.
-** Journal format 1 is only used for testing.
-*/
-static int write32bits(OsFile *fd, u32 val){
- unsigned char ac[4];
- if( journal_format<=1 ){
- return sqliteOsWrite(fd, &val, 4);
- }
- ac[0] = (val>>24) & 0xff;
- ac[1] = (val>>16) & 0xff;
- ac[2] = (val>>8) & 0xff;
- ac[3] = val & 0xff;
- return sqliteOsWrite(fd, ac, 4);
-}
-
-/*
-** Write a 32-bit integer into a page header right before the
-** page data. This will overwrite the PgHdr.pDirty pointer.
-**
-** The integer is big-endian for formats 2 and 3 and native byte order
-** for journal format 1.
-*/
-static void store32bits(u32 val, PgHdr *p, int offset){
- unsigned char *ac;
- ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];
- if( journal_format<=1 ){
- memcpy(ac, &val, 4);
- }else{
- ac[0] = (val>>24) & 0xff;
- ac[1] = (val>>16) & 0xff;
- ac[2] = (val>>8) & 0xff;
- ac[3] = val & 0xff;
- }
-}
-
-
-/*
-** Convert the bits in the pPager->errMask into an approprate
-** return code.
-*/
-static int pager_errcode(Pager *pPager){
- int rc = SQLITE_OK;
- if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL;
- if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR;
- if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL;
- if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM;
- if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;
- return rc;
-}
-
-/*
-** Add or remove a page from the list of all pages that are in the
-** checkpoint journal.
-**
-** The Pager keeps a separate list of pages that are currently in
-** the checkpoint journal. This helps the sqlitepager_ckpt_commit()
-** routine run MUCH faster for the common case where there are many
-** pages in memory but only a few are in the checkpoint journal.
-*/
-static void page_add_to_ckpt_list(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- if( pPg->inCkpt ) return;
- assert( pPg->pPrevCkpt==0 && pPg->pNextCkpt==0 );
- pPg->pPrevCkpt = 0;
- if( pPager->pCkpt ){
- pPager->pCkpt->pPrevCkpt = pPg;
- }
- pPg->pNextCkpt = pPager->pCkpt;
- pPager->pCkpt = pPg;
- pPg->inCkpt = 1;
-}
-static void page_remove_from_ckpt_list(PgHdr *pPg){
- if( !pPg->inCkpt ) return;
- if( pPg->pPrevCkpt ){
- assert( pPg->pPrevCkpt->pNextCkpt==pPg );
- pPg->pPrevCkpt->pNextCkpt = pPg->pNextCkpt;
- }else{
- assert( pPg->pPager->pCkpt==pPg );
- pPg->pPager->pCkpt = pPg->pNextCkpt;
- }
- if( pPg->pNextCkpt ){
- assert( pPg->pNextCkpt->pPrevCkpt==pPg );
- pPg->pNextCkpt->pPrevCkpt = pPg->pPrevCkpt;
- }
- pPg->pNextCkpt = 0;
- pPg->pPrevCkpt = 0;
- pPg->inCkpt = 0;
-}
-
-/*
-** Find a page in the hash table given its page number. Return
-** a pointer to the page or NULL if not found.
-*/
-static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
- PgHdr *p = pPager->aHash[pager_hash(pgno)];
- while( p && p->pgno!=pgno ){
- p = p->pNextHash;
- }
- return p;
-}
-
-/*
-** Unlock the database and clear the in-memory cache. This routine
-** sets the state of the pager back to what it was when it was first
-** opened. Any outstanding pages are invalidated and subsequent attempts
-** to access those pages will likely result in a coredump.
-*/
-static void pager_reset(Pager *pPager){
- PgHdr *pPg, *pNext;
- for(pPg=pPager->pAll; pPg; pPg=pNext){
- pNext = pPg->pNextAll;
- sqliteFree(pPg);
- }
- pPager->pFirst = 0;
- pPager->pFirstSynced = 0;
- pPager->pLast = 0;
- pPager->pAll = 0;
- memset(pPager->aHash, 0, sizeof(pPager->aHash));
- pPager->nPage = 0;
- if( pPager->state>=SQLITE_WRITELOCK ){
- sqlitepager_rollback(pPager);
- }
- sqliteOsUnlock(&pPager->fd);
- pPager->state = SQLITE_UNLOCK;
- pPager->dbSize = -1;
- pPager->nRef = 0;
- assert( pPager->journalOpen==0 );
-}
-
-/*
-** When this routine is called, the pager has the journal file open and
-** a write lock on the database. This routine releases the database
-** write lock and acquires a read lock in its place. The journal file
-** is deleted and closed.
-**
-** TODO: Consider keeping the journal file open for temporary databases.
-** This might give a performance improvement on windows where opening
-** a file is an expensive operation.
-*/
-static int pager_unwritelock(Pager *pPager){
- int rc;
- PgHdr *pPg;
- if( pPager->state<SQLITE_WRITELOCK ) return SQLITE_OK;
- sqlitepager_ckpt_commit(pPager);
- if( pPager->ckptOpen ){
- sqliteOsClose(&pPager->cpfd);
- pPager->ckptOpen = 0;
- }
- if( pPager->journalOpen ){
- sqliteOsClose(&pPager->jfd);
- pPager->journalOpen = 0;
- sqliteOsDelete(pPager->zJournal);
- sqliteFree( pPager->aInJournal );
- pPager->aInJournal = 0;
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- pPg->inJournal = 0;
- pPg->dirty = 0;
- pPg->needSync = 0;
- }
- }else{
- assert( pPager->dirtyFile==0 || pPager->useJournal==0 );
- }
- rc = sqliteOsReadLock(&pPager->fd);
- if( rc==SQLITE_OK ){
- pPager->state = SQLITE_READLOCK;
- }else{
- /* This can only happen if a process does a BEGIN, then forks and the
- ** child process does the COMMIT. Because of the semantics of unix
- ** file locking, the unlock will fail.
- */
- pPager->state = SQLITE_UNLOCK;
- }
- return rc;
-}
-
-/*
-** Compute and return a checksum for the page of data.
-**
-** This is not a real checksum. It is really just the sum of the
-** random initial value and the page number. We considered do a checksum
-** of the database, but that was found to be too slow.
-*/
-static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){
- u32 cksum = pPager->cksumInit + pgno;
- return cksum;
-}
-
-/*
-** Read a single page from the journal file opened on file descriptor
-** jfd. Playback this one page.
-**
-** There are three different journal formats. The format parameter determines
-** which format is used by the journal that is played back.
-*/
-static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){
- int rc;
- PgHdr *pPg; /* An existing page in the cache */
- PageRecord pgRec;
- u32 cksum;
-
- rc = read32bits(format, jfd, &pgRec.pgno);
- if( rc!=SQLITE_OK ) return rc;
- rc = sqliteOsRead(jfd, &pgRec.aData, sizeof(pgRec.aData));
- if( rc!=SQLITE_OK ) return rc;
-
- /* Sanity checking on the page. This is more important that I originally
- ** thought. If a power failure occurs while the journal is being written,
- ** it could cause invalid data to be written into the journal. We need to
- ** detect this invalid data (with high probability) and ignore it.
- */
- if( pgRec.pgno==0 ){
- return SQLITE_DONE;
- }
- if( pgRec.pgno>(unsigned)pPager->dbSize ){
- return SQLITE_OK;
- }
- if( format>=JOURNAL_FORMAT_3 ){
- rc = read32bits(format, jfd, &cksum);
- if( rc ) return rc;
- if( pager_cksum(pPager, pgRec.pgno, pgRec.aData)!=cksum ){
- return SQLITE_DONE;
- }
- }
-
- /* Playback the page. Update the in-memory copy of the page
- ** at the same time, if there is one.
- */
- pPg = pager_lookup(pPager, pgRec.pgno);
- TRACE2("PLAYBACK %d\n", pgRec.pgno);
- sqliteOsSeek(&pPager->fd, (pgRec.pgno-1)*(off_t)SQLITE_PAGE_SIZE);
- rc = sqliteOsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
- if( pPg ){
- /* No page should ever be rolled back that is in use, except for page
- ** 1 which is held in use in order to keep the lock on the database
- ** active.
- */
- assert( pPg->nRef==0 || pPg->pgno==1 );
- memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
- memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
- pPg->dirty = 0;
- pPg->needSync = 0;
- CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
- }
- return rc;
-}
-
-/*
-** Playback the journal and thus restore the database file to
-** the state it was in before we started making changes.
-**
-** The journal file format is as follows:
-**
-** * 8 byte prefix. One of the aJournalMagic123 vectors defined
-** above. The format of the journal file is determined by which
-** of the three prefix vectors is seen.
-** * 4 byte big-endian integer which is the number of valid page records
-** in the journal. If this value is 0xffffffff, then compute the
-** number of page records from the journal size. This field appears
-** in format 3 only.
-** * 4 byte big-endian integer which is the initial value for the
-** sanity checksum. This field appears in format 3 only.
-** * 4 byte integer which is the number of pages to truncate the
-** database to during a rollback.
-** * Zero or more pages instances, each as follows:
-** + 4 byte page number.
-** + SQLITE_PAGE_SIZE bytes of data.
-** + 4 byte checksum (format 3 only)
-**
-** When we speak of the journal header, we mean the first 4 bullets above.
-** Each entry in the journal is an instance of the 5th bullet. Note that
-** bullets 2 and 3 only appear in format-3 journals.
-**
-** Call the value from the second bullet "nRec". nRec is the number of
-** valid page entries in the journal. In most cases, you can compute the
-** value of nRec from the size of the journal file. But if a power
-** failure occurred while the journal was being written, it could be the
-** case that the size of the journal file had already been increased but
-** the extra entries had not yet made it safely to disk. In such a case,
-** the value of nRec computed from the file size would be too large. For
-** that reason, we always use the nRec value in the header.
-**
-** If the nRec value is 0xffffffff it means that nRec should be computed
-** from the file size. This value is used when the user selects the
-** no-sync option for the journal. A power failure could lead to corruption
-** in this case. But for things like temporary table (which will be
-** deleted when the power is restored) we don't care.
-**
-** Journal formats 1 and 2 do not have an nRec value in the header so we
-** have to compute nRec from the file size. This has risks (as described
-** above) which is why all persistent tables have been changed to use
-** format 3.
-**
-** If the file opened as the journal file is not a well-formed
-** journal file then the database will likely already be
-** corrupted, so the PAGER_ERR_CORRUPT bit is set in pPager->errMask
-** and SQLITE_CORRUPT is returned. If it all works, then this routine
-** returns SQLITE_OK.
-*/
-static int pager_playback(Pager *pPager, int useJournalSize){
- off_t szJ; /* Size of the journal file in bytes */
- int nRec; /* Number of Records in the journal */
- int i; /* Loop counter */
- Pgno mxPg = 0; /* Size of the original file in pages */
- int format; /* Format of the journal file. */
- unsigned char aMagic[sizeof(aJournalMagic1)];
- int rc;
-
- /* Figure out how many records are in the journal. Abort early if
- ** the journal is empty.
- */
- assert( pPager->journalOpen );
- sqliteOsSeek(&pPager->jfd, 0);
- rc = sqliteOsFileSize(&pPager->jfd, &szJ);
- if( rc!=SQLITE_OK ){
- goto end_playback;
- }
-
- /* If the journal file is too small to contain a complete header,
- ** it must mean that the process that created the journal was just
- ** beginning to write the journal file when it died. In that case,
- ** the database file should have still been completely unchanged.
- ** Nothing needs to be rolled back. We can safely ignore this journal.
- */
- if( szJ < sizeof(aMagic)+sizeof(Pgno) ){
- goto end_playback;
- }
-
- /* Read the beginning of the journal and truncate the
- ** database file back to its original size.
- */
- rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic));
- if( rc!=SQLITE_OK ){
- rc = SQLITE_PROTOCOL;
- goto end_playback;
- }
- if( memcmp(aMagic, aJournalMagic3, sizeof(aMagic))==0 ){
- format = JOURNAL_FORMAT_3;
- }else if( memcmp(aMagic, aJournalMagic2, sizeof(aMagic))==0 ){
- format = JOURNAL_FORMAT_2;
- }else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){
- format = JOURNAL_FORMAT_1;
- }else{
- rc = SQLITE_PROTOCOL;
- goto end_playback;
- }
- if( format>=JOURNAL_FORMAT_3 ){
- if( szJ < sizeof(aMagic) + 3*sizeof(u32) ){
- /* Ignore the journal if it is too small to contain a complete
- ** header. We already did this test once above, but at the prior
- ** test, we did not know the journal format and so we had to assume
- ** the smallest possible header. Now we know the header is bigger
- ** than the minimum so we test again.
- */
- goto end_playback;
- }
- rc = read32bits(format, &pPager->jfd, (u32*)&nRec);
- if( rc ) goto end_playback;
- rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
- if( rc ) goto end_playback;
- if( nRec==0xffffffff || useJournalSize ){
- nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
- }
- }else{
- nRec = (szJ - JOURNAL_HDR_SZ(2))/JOURNAL_PG_SZ(2);
- assert( nRec*JOURNAL_PG_SZ(2)+JOURNAL_HDR_SZ(2)==szJ );
- }
- rc = read32bits(format, &pPager->jfd, &mxPg);
- if( rc!=SQLITE_OK ){
- goto end_playback;
- }
- assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
- rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg);
- if( rc!=SQLITE_OK ){
- goto end_playback;
- }
- pPager->dbSize = mxPg;
-
- /* Copy original pages out of the journal and back into the database file.
- */
- for(i=0; i<nRec; i++){
- rc = pager_playback_one_page(pPager, &pPager->jfd, format);
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }
- break;
- }
- }
-
- /* Pages that have been written to the journal but never synced
- ** where not restored by the loop above. We have to restore those
- ** pages by reading them back from the original database.
- */
- if( rc==SQLITE_OK ){
- PgHdr *pPg;
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- char zBuf[SQLITE_PAGE_SIZE];
- if( !pPg->dirty ) continue;
- if( (int)pPg->pgno <= pPager->origDbSize ){
- sqliteOsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1));
- rc = sqliteOsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE);
- TRACE2("REFETCH %d\n", pPg->pgno);
- CODEC(pPager, zBuf, pPg->pgno, 2);
- if( rc ) break;
- }else{
- memset(zBuf, 0, SQLITE_PAGE_SIZE);
- }
- if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){
- memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE);
- memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
- }
- pPg->needSync = 0;
- pPg->dirty = 0;
- }
- }
-
-end_playback:
- if( rc!=SQLITE_OK ){
- pager_unwritelock(pPager);
- pPager->errMask |= PAGER_ERR_CORRUPT;
- rc = SQLITE_CORRUPT;
- }else{
- rc = pager_unwritelock(pPager);
- }
- return rc;
-}
-
-/*
-** Playback the checkpoint journal.
-**
-** This is similar to playing back the transaction journal but with
-** a few extra twists.
-**
-** (1) The number of pages in the database file at the start of
-** the checkpoint is stored in pPager->ckptSize, not in the
-** journal file itself.
-**
-** (2) In addition to playing back the checkpoint journal, also
-** playback all pages of the transaction journal beginning
-** at offset pPager->ckptJSize.
-*/
-static int pager_ckpt_playback(Pager *pPager){
- off_t szJ; /* Size of the full journal */
- int nRec; /* Number of Records */
- int i; /* Loop counter */
- int rc;
-
- /* Truncate the database back to its original size.
- */
- rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->ckptSize);
- pPager->dbSize = pPager->ckptSize;
-
- /* Figure out how many records are in the checkpoint journal.
- */
- assert( pPager->ckptInUse && pPager->journalOpen );
- sqliteOsSeek(&pPager->cpfd, 0);
- nRec = pPager->ckptNRec;
-
- /* Copy original pages out of the checkpoint journal and back into the
- ** database file. Note that the checkpoint journal always uses format
- ** 2 instead of format 3 since it does not need to be concerned with
- ** power failures corrupting the journal and can thus omit the checksums.
- */
- for(i=nRec-1; i>=0; i--){
- rc = pager_playback_one_page(pPager, &pPager->cpfd, 2);
- assert( rc!=SQLITE_DONE );
- if( rc!=SQLITE_OK ) goto end_ckpt_playback;
- }
-
- /* Figure out how many pages need to be copied out of the transaction
- ** journal.
- */
- rc = sqliteOsSeek(&pPager->jfd, pPager->ckptJSize);
- if( rc!=SQLITE_OK ){
- goto end_ckpt_playback;
- }
- rc = sqliteOsFileSize(&pPager->jfd, &szJ);
- if( rc!=SQLITE_OK ){
- goto end_ckpt_playback;
- }
- nRec = (szJ - pPager->ckptJSize)/JOURNAL_PG_SZ(journal_format);
- for(i=nRec-1; i>=0; i--){
- rc = pager_playback_one_page(pPager, &pPager->jfd, journal_format);
- if( rc!=SQLITE_OK ){
- assert( rc!=SQLITE_DONE );
- goto end_ckpt_playback;
- }
- }
-
-end_ckpt_playback:
- if( rc!=SQLITE_OK ){
- pPager->errMask |= PAGER_ERR_CORRUPT;
- rc = SQLITE_CORRUPT;
- }
- return rc;
-}
-
-/*
-** Change the maximum number of in-memory pages that are allowed.
-**
-** The maximum number is the absolute value of the mxPage parameter.
-** If mxPage is negative, the noSync flag is also set. noSync bypasses
-** calls to sqliteOsSync(). The pager runs much faster with noSync on,
-** but if the operating system crashes or there is an abrupt power
-** failure, the database file might be left in an inconsistent and
-** unrepairable state.
-*/
-void sqlitepager_set_cachesize(Pager *pPager, int mxPage){
- if( mxPage>=0 ){
- pPager->noSync = pPager->tempFile;
- if( pPager->noSync==0 ) pPager->needSync = 0;
- }else{
- pPager->noSync = 1;
- mxPage = -mxPage;
- }
- if( mxPage>10 ){
- pPager->mxPage = mxPage;
- }
-}
-
-/*
-** Adjust the robustness of the database to damage due to OS crashes
-** or power failures by changing the number of syncs()s when writing
-** the rollback journal. There are three levels:
-**
-** OFF sqliteOsSync() is never called. This is the default
-** for temporary and transient files.
-**
-** NORMAL The journal is synced once before writes begin on the
-** database. This is normally adequate protection, but
-** it is theoretically possible, though very unlikely,
-** that an inopertune power failure could leave the journal
-** in a state which would cause damage to the database
-** when it is rolled back.
-**
-** FULL The journal is synced twice before writes begin on the
-** database (with some additional information - the nRec field
-** of the journal header - being written in between the two
-** syncs). If we assume that writing a
-** single disk sector is atomic, then this mode provides
-** assurance that the journal will not be corrupted to the
-** point of causing damage to the database during rollback.
-**
-** Numeric values associated with these states are OFF==1, NORMAL=2,
-** and FULL=3.
-*/
-void sqlitepager_set_safety_level(Pager *pPager, int level){
- pPager->noSync = level==1 || pPager->tempFile;
- pPager->fullSync = level==3 && !pPager->tempFile;
- if( pPager->noSync==0 ) pPager->needSync = 0;
-}
-
-/*
-** Open a temporary file. Write the name of the file into zName
-** (zName must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write
-** the file descriptor into *fd. Return SQLITE_OK on success or some
-** other error code if we fail.
-**
-** The OS will automatically delete the temporary file when it is
-** closed.
-*/
-static int sqlitepager_opentemp(char *zFile, OsFile *fd){
- int cnt = 8;
- int rc;
- do{
- cnt--;
- sqliteOsTempFileName(zFile);
- rc = sqliteOsOpenExclusive(zFile, fd, 1);
- }while( cnt>0 && rc!=SQLITE_OK );
- return rc;
-}
-
-/*
-** Create a new page cache and put a pointer to the page cache in *ppPager.
-** The file to be cached need not exist. The file is not locked until
-** the first call to sqlitepager_get() and is only held open until the
-** last page is released using sqlitepager_unref().
-**
-** If zFilename is NULL then a randomly-named temporary file is created
-** and used as the file to be cached. The file will be deleted
-** automatically when it is closed.
-*/
-int sqlitepager_open(
- Pager **ppPager, /* Return the Pager structure here */
- const char *zFilename, /* Name of the database file to open */
- int mxPage, /* Max number of in-memory cache pages */
- int nExtra, /* Extra bytes append to each in-memory page */
- int useJournal /* TRUE to use a rollback journal on this file */
-){
- Pager *pPager;
- char *zFullPathname;
- int nameLen;
- OsFile fd;
- int rc, i;
- int tempFile;
- int readOnly = 0;
- char zTemp[SQLITE_TEMPNAME_SIZE];
-
- *ppPager = 0;
- if( sqlite_malloc_failed ){
- return SQLITE_NOMEM;
- }
- if( zFilename && zFilename[0] ){
- zFullPathname = sqliteOsFullPathname(zFilename);
- rc = sqliteOsOpenReadWrite(zFullPathname, &fd, &readOnly);
- tempFile = 0;
- }else{
- rc = sqlitepager_opentemp(zTemp, &fd);
- zFilename = zTemp;
- zFullPathname = sqliteOsFullPathname(zFilename);
- tempFile = 1;
- }
- if( sqlite_malloc_failed ){
- return SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- sqliteFree(zFullPathname);
- return SQLITE_CANTOPEN;
- }
- nameLen = strlen(zFullPathname);
- pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 );
- if( pPager==0 ){
- sqliteOsClose(&fd);
- sqliteFree(zFullPathname);
- return SQLITE_NOMEM;
- }
- SET_PAGER(pPager);
- pPager->zFilename = (char*)&pPager[1];
- pPager->zDirectory = &pPager->zFilename[nameLen+1];
- pPager->zJournal = &pPager->zDirectory[nameLen+1];
- strcpy(pPager->zFilename, zFullPathname);
- strcpy(pPager->zDirectory, zFullPathname);
- for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){}
- if( i>0 ) pPager->zDirectory[i-1] = 0;
- strcpy(pPager->zJournal, zFullPathname);
- sqliteFree(zFullPathname);
- strcpy(&pPager->zJournal[nameLen], "-journal");
- pPager->fd = fd;
- pPager->journalOpen = 0;
- pPager->useJournal = useJournal;
- pPager->ckptOpen = 0;
- pPager->ckptInUse = 0;
- pPager->nRef = 0;
- pPager->dbSize = -1;
- pPager->ckptSize = 0;
- pPager->ckptJSize = 0;
- pPager->nPage = 0;
- pPager->mxPage = mxPage>5 ? mxPage : 10;
- pPager->state = SQLITE_UNLOCK;
- pPager->errMask = 0;
- pPager->tempFile = tempFile;
- pPager->readOnly = readOnly;
- pPager->needSync = 0;
- pPager->noSync = pPager->tempFile || !useJournal;
- pPager->pFirst = 0;
- pPager->pFirstSynced = 0;
- pPager->pLast = 0;
- pPager->nExtra = nExtra;
- memset(pPager->aHash, 0, sizeof(pPager->aHash));
- *ppPager = pPager;
- return SQLITE_OK;
-}
-
-/*
-** Set the destructor for this pager. If not NULL, the destructor is called
-** when the reference count on each page reaches zero. The destructor can
-** be used to clean up information in the extra segment appended to each page.
-**
-** The destructor is not called as a result sqlitepager_close().
-** Destructors are only called by sqlitepager_unref().
-*/
-void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
- pPager->xDestructor = xDesc;
-}
-
-/*
-** Return the total number of pages in the disk file associated with
-** pPager.
-*/
-int sqlitepager_pagecount(Pager *pPager){
- off_t n;
- assert( pPager!=0 );
- if( pPager->dbSize>=0 ){
- return pPager->dbSize;
- }
- if( sqliteOsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
- pPager->errMask |= PAGER_ERR_DISK;
- return 0;
- }
- n /= SQLITE_PAGE_SIZE;
- if( pPager->state!=SQLITE_UNLOCK ){
- pPager->dbSize = n;
- }
- return n;
-}
-
-/*
-** Forward declaration
-*/
-static int syncJournal(Pager*);
-
-/*
-** Truncate the file to the number of pages specified.
-*/
-int sqlitepager_truncate(Pager *pPager, Pgno nPage){
- int rc;
- if( pPager->dbSize<0 ){
- sqlitepager_pagecount(pPager);
- }
- if( pPager->errMask!=0 ){
- rc = pager_errcode(pPager);
- return rc;
- }
- if( nPage>=(unsigned)pPager->dbSize ){
- return SQLITE_OK;
- }
- syncJournal(pPager);
- rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
- if( rc==SQLITE_OK ){
- pPager->dbSize = nPage;
- }
- return rc;
-}
-
-/*
-** Shutdown the page cache. Free all memory and close all files.
-**
-** If a transaction was in progress when this routine is called, that
-** transaction is rolled back. All outstanding pages are invalidated
-** and their memory is freed. Any attempt to use a page associated
-** with this page cache after this function returns will likely
-** result in a coredump.
-*/
-int sqlitepager_close(Pager *pPager){
- PgHdr *pPg, *pNext;
- switch( pPager->state ){
- case SQLITE_WRITELOCK: {
- sqlitepager_rollback(pPager);
- sqliteOsUnlock(&pPager->fd);
- assert( pPager->journalOpen==0 );
- break;
- }
- case SQLITE_READLOCK: {
- sqliteOsUnlock(&pPager->fd);
- break;
- }
- default: {
- /* Do nothing */
- break;
- }
- }
- for(pPg=pPager->pAll; pPg; pPg=pNext){
- pNext = pPg->pNextAll;
- sqliteFree(pPg);
- }
- sqliteOsClose(&pPager->fd);
- assert( pPager->journalOpen==0 );
- /* Temp files are automatically deleted by the OS
- ** if( pPager->tempFile ){
- ** sqliteOsDelete(pPager->zFilename);
- ** }
- */
- CLR_PAGER(pPager);
- if( pPager->zFilename!=(char*)&pPager[1] ){
- assert( 0 ); /* Cannot happen */
- sqliteFree(pPager->zFilename);
- sqliteFree(pPager->zJournal);
- sqliteFree(pPager->zDirectory);
- }
- sqliteFree(pPager);
- return SQLITE_OK;
-}
-
-/*
-** Return the page number for the given page data.
-*/
-Pgno sqlitepager_pagenumber(void *pData){
- PgHdr *p = DATA_TO_PGHDR(pData);
- return p->pgno;
-}
-
-/*
-** Increment the reference count for a page. If the page is
-** currently on the freelist (the reference count is zero) then
-** remove it from the freelist.
-*/
-#define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
-static void _page_ref(PgHdr *pPg){
- if( pPg->nRef==0 ){
- /* The page is currently on the freelist. Remove it. */
- if( pPg==pPg->pPager->pFirstSynced ){
- PgHdr *p = pPg->pNextFree;
- while( p && p->needSync ){ p = p->pNextFree; }
- pPg->pPager->pFirstSynced = p;
- }
- if( pPg->pPrevFree ){
- pPg->pPrevFree->pNextFree = pPg->pNextFree;
- }else{
- pPg->pPager->pFirst = pPg->pNextFree;
- }
- if( pPg->pNextFree ){
- pPg->pNextFree->pPrevFree = pPg->pPrevFree;
- }else{
- pPg->pPager->pLast = pPg->pPrevFree;
- }
- pPg->pPager->nRef++;
- }
- pPg->nRef++;
- REFINFO(pPg);
-}
-
-/*
-** Increment the reference count for a page. The input pointer is
-** a reference to the page data.
-*/
-int sqlitepager_ref(void *pData){
- PgHdr *pPg = DATA_TO_PGHDR(pData);
- page_ref(pPg);
- return SQLITE_OK;
-}
-
-/*
-** Sync the journal. In other words, make sure all the pages that have
-** been written to the journal have actually reached the surface of the
-** disk. It is not safe to modify the original database file until after
-** the journal has been synced. If the original database is modified before
-** the journal is synced and a power failure occurs, the unsynced journal
-** data would be lost and we would be unable to completely rollback the
-** database changes. Database corruption would occur.
-**
-** This routine also updates the nRec field in the header of the journal.
-** (See comments on the pager_playback() routine for additional information.)
-** If the sync mode is FULL, two syncs will occur. First the whole journal
-** is synced, then the nRec field is updated, then a second sync occurs.
-**
-** For temporary databases, we do not care if we are able to rollback
-** after a power failure, so sync occurs.
-**
-** This routine clears the needSync field of every page current held in
-** memory.
-*/
-static int syncJournal(Pager *pPager){
- PgHdr *pPg;
- int rc = SQLITE_OK;
-
- /* Sync the journal before modifying the main database
- ** (assuming there is a journal and it needs to be synced.)
- */
- if( pPager->needSync ){
- if( !pPager->tempFile ){
- assert( pPager->journalOpen );
- /* assert( !pPager->noSync ); // noSync might be set if synchronous
- ** was turned off after the transaction was started. Ticket #615 */
-#ifndef NDEBUG
- {
- /* Make sure the pPager->nRec counter we are keeping agrees
- ** with the nRec computed from the size of the journal file.
- */
- off_t hdrSz, pgSz, jSz;
- hdrSz = JOURNAL_HDR_SZ(journal_format);
- pgSz = JOURNAL_PG_SZ(journal_format);
- rc = sqliteOsFileSize(&pPager->jfd, &jSz);
- if( rc!=0 ) return rc;
- assert( pPager->nRec*pgSz+hdrSz==jSz );
- }
-#endif
- if( journal_format>=3 ){
- /* Write the nRec value into the journal file header */
- off_t szJ;
- if( pPager->fullSync ){
- TRACE1("SYNC\n");
- rc = sqliteOsSync(&pPager->jfd);
- if( rc!=0 ) return rc;
- }
- sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1));
- rc = write32bits(&pPager->jfd, pPager->nRec);
- if( rc ) return rc;
- szJ = JOURNAL_HDR_SZ(journal_format) +
- pPager->nRec*JOURNAL_PG_SZ(journal_format);
- sqliteOsSeek(&pPager->jfd, szJ);
- }
- TRACE1("SYNC\n");
- rc = sqliteOsSync(&pPager->jfd);
- if( rc!=0 ) return rc;
- pPager->journalStarted = 1;
- }
- pPager->needSync = 0;
-
- /* Erase the needSync flag from every page.
- */
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- pPg->needSync = 0;
- }
- pPager->pFirstSynced = pPager->pFirst;
- }
-
-#ifndef NDEBUG
- /* If the Pager.needSync flag is clear then the PgHdr.needSync
- ** flag must also be clear for all pages. Verify that this
- ** invariant is true.
- */
- else{
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- assert( pPg->needSync==0 );
- }
- assert( pPager->pFirstSynced==pPager->pFirst );
- }
-#endif
-
- return rc;
-}
-
-/*
-** Given a list of pages (connected by the PgHdr.pDirty pointer) write
-** every one of those pages out to the database file and mark them all
-** as clean.
-*/
-static int pager_write_pagelist(PgHdr *pList){
- Pager *pPager;
- int rc;
-
- if( pList==0 ) return SQLITE_OK;
- pPager = pList->pPager;
- while( pList ){
- assert( pList->dirty );
- sqliteOsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE);
- CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
- TRACE2("STORE %d\n", pList->pgno);
- rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE);
- CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
- if( rc ) return rc;
- pList->dirty = 0;
- pList = pList->pDirty;
- }
- return SQLITE_OK;
-}
-
-/*
-** Collect every dirty page into a dirty list and
-** return a pointer to the head of that list. All pages are
-** collected even if they are still in use.
-*/
-static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
- PgHdr *p, *pList;
- pList = 0;
- for(p=pPager->pAll; p; p=p->pNextAll){
- if( p->dirty ){
- p->pDirty = pList;
- pList = p;
- }
- }
- return pList;
-}
-
-/*
-** Acquire a page.
-**
-** A read lock on the disk file is obtained when the first page is acquired.
-** This read lock is dropped when the last page is released.
-**
-** A _get works for any page number greater than 0. If the database
-** file is smaller than the requested page, then no actual disk
-** read occurs and the memory image of the page is initialized to
-** all zeros. The extra data appended to a page is always initialized
-** to zeros the first time a page is loaded into memory.
-**
-** The acquisition might fail for several reasons. In all cases,
-** an appropriate error code is returned and *ppPage is set to NULL.
-**
-** See also sqlitepager_lookup(). Both this routine and _lookup() attempt
-** to find a page in the in-memory cache first. If the page is not already
-** in memory, this routine goes to disk to read it in whereas _lookup()
-** just returns 0. This routine acquires a read-lock the first time it
-** has to go to disk, and could also playback an old journal if necessary.
-** Since _lookup() never goes to disk, it never has to deal with locks
-** or journal files.
-*/
-int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
- PgHdr *pPg;
- int rc;
-
- /* Make sure we have not hit any critical errors.
- */
- assert( pPager!=0 );
- assert( pgno!=0 );
- *ppPage = 0;
- if( pPager->errMask & ~(PAGER_ERR_FULL) ){
- return pager_errcode(pPager);
- }
-
- /* If this is the first page accessed, then get a read lock
- ** on the database file.
- */
- if( pPager->nRef==0 ){
- rc = sqliteOsReadLock(&pPager->fd);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pPager->state = SQLITE_READLOCK;
-
- /* If a journal file exists, try to play it back.
- */
- if( pPager->useJournal && sqliteOsFileExists(pPager->zJournal) ){
- int rc;
-
- /* Get a write lock on the database
- */
- rc = sqliteOsWriteLock(&pPager->fd);
- if( rc!=SQLITE_OK ){
- if( sqliteOsUnlock(&pPager->fd)!=SQLITE_OK ){
- /* This should never happen! */
- rc = SQLITE_INTERNAL;
- }
- return rc;
- }
- pPager->state = SQLITE_WRITELOCK;
-
- /* Open the journal for reading only. Return SQLITE_BUSY if
- ** we are unable to open the journal file.
- **
- ** The journal file does not need to be locked itself. The
- ** journal file is never open unless the main database file holds
- ** a write lock, so there is never any chance of two or more
- ** processes opening the journal at the same time.
- */
- rc = sqliteOsOpenReadOnly(pPager->zJournal, &pPager->jfd);
- if( rc!=SQLITE_OK ){
- rc = sqliteOsUnlock(&pPager->fd);
- assert( rc==SQLITE_OK );
- return SQLITE_BUSY;
- }
- pPager->journalOpen = 1;
- pPager->journalStarted = 0;
-
- /* Playback and delete the journal. Drop the database write
- ** lock and reacquire the read lock.
- */
- rc = pager_playback(pPager, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- pPg = 0;
- }else{
- /* Search for page in cache */
- pPg = pager_lookup(pPager, pgno);
- }
- if( pPg==0 ){
- /* The requested page is not in the page cache. */
- int h;
- pPager->nMiss++;
- if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 ){
- /* Create a new page */
- pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE
- + sizeof(u32) + pPager->nExtra );
- if( pPg==0 ){
- pager_unwritelock(pPager);
- pPager->errMask |= PAGER_ERR_MEM;
- return SQLITE_NOMEM;
- }
- memset(pPg, 0, sizeof(*pPg));
- pPg->pPager = pPager;
- pPg->pNextAll = pPager->pAll;
- if( pPager->pAll ){
- pPager->pAll->pPrevAll = pPg;
- }
- pPg->pPrevAll = 0;
- pPager->pAll = pPg;
- pPager->nPage++;
- }else{
- /* Find a page to recycle. Try to locate a page that does not
- ** require us to do an fsync() on the journal.
- */
- pPg = pPager->pFirstSynced;
-
- /* If we could not find a page that does not require an fsync()
- ** on the journal file then fsync the journal file. This is a
- ** very slow operation, so we work hard to avoid it. But sometimes
- ** it can't be helped.
- */
- if( pPg==0 ){
- int rc = syncJournal(pPager);
- if( rc!=0 ){
- sqlitepager_rollback(pPager);
- return SQLITE_IOERR;
- }
- pPg = pPager->pFirst;
- }
- assert( pPg->nRef==0 );
-
- /* Write the page to the database file if it is dirty.
- */
- if( pPg->dirty ){
- assert( pPg->needSync==0 );
- pPg->pDirty = 0;
- rc = pager_write_pagelist( pPg );
- if( rc!=SQLITE_OK ){
- sqlitepager_rollback(pPager);
- return SQLITE_IOERR;
- }
- }
- assert( pPg->dirty==0 );
-
- /* If the page we are recycling is marked as alwaysRollback, then
- ** set the global alwaysRollback flag, thus disabling the
- ** sqlite_dont_rollback() optimization for the rest of this transaction.
- ** It is necessary to do this because the page marked alwaysRollback
- ** might be reloaded at a later time but at that point we won't remember
- ** that is was marked alwaysRollback. This means that all pages must
- ** be marked as alwaysRollback from here on out.
- */
- if( pPg->alwaysRollback ){
- pPager->alwaysRollback = 1;
- }
-
- /* Unlink the old page from the free list and the hash table
- */
- if( pPg==pPager->pFirstSynced ){
- PgHdr *p = pPg->pNextFree;
- while( p && p->needSync ){ p = p->pNextFree; }
- pPager->pFirstSynced = p;
- }
- if( pPg->pPrevFree ){
- pPg->pPrevFree->pNextFree = pPg->pNextFree;
- }else{
- assert( pPager->pFirst==pPg );
- pPager->pFirst = pPg->pNextFree;
- }
- if( pPg->pNextFree ){
- pPg->pNextFree->pPrevFree = pPg->pPrevFree;
- }else{
- assert( pPager->pLast==pPg );
- pPager->pLast = pPg->pPrevFree;
- }
- pPg->pNextFree = pPg->pPrevFree = 0;
- if( pPg->pNextHash ){
- pPg->pNextHash->pPrevHash = pPg->pPrevHash;
- }
- if( pPg->pPrevHash ){
- pPg->pPrevHash->pNextHash = pPg->pNextHash;
- }else{
- h = pager_hash(pPg->pgno);
- assert( pPager->aHash[h]==pPg );
- pPager->aHash[h] = pPg->pNextHash;
- }
- pPg->pNextHash = pPg->pPrevHash = 0;
- pPager->nOvfl++;
- }
- pPg->pgno = pgno;
- if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
- sqliteCheckMemory(pPager->aInJournal, pgno/8);
- assert( pPager->journalOpen );
- pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0;
- pPg->needSync = 0;
- }else{
- pPg->inJournal = 0;
- pPg->needSync = 0;
- }
- if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize
- && (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0 ){
- page_add_to_ckpt_list(pPg);
- }else{
- page_remove_from_ckpt_list(pPg);
- }
- pPg->dirty = 0;
- pPg->nRef = 1;
- REFINFO(pPg);
- pPager->nRef++;
- h = pager_hash(pgno);
- pPg->pNextHash = pPager->aHash[h];
- pPager->aHash[h] = pPg;
- if( pPg->pNextHash ){
- assert( pPg->pNextHash->pPrevHash==0 );
- pPg->pNextHash->pPrevHash = pPg;
- }
- if( pPager->nExtra>0 ){
- memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
- }
- if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager);
- if( pPager->errMask!=0 ){
- sqlitepager_unref(PGHDR_TO_DATA(pPg));
- rc = pager_errcode(pPager);
- return rc;
- }
- if( pPager->dbSize<(int)pgno ){
- memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
- }else{
- int rc;
- sqliteOsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE);
- rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
- TRACE2("FETCH %d\n", pPg->pgno);
- CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
- if( rc!=SQLITE_OK ){
- off_t fileSize;
- if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
- || fileSize>=pgno*SQLITE_PAGE_SIZE ){
- sqlitepager_unref(PGHDR_TO_DATA(pPg));
- return rc;
- }else{
- memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
- }
- }
- }
- }else{
- /* The requested page is in the page cache. */
- pPager->nHit++;
- page_ref(pPg);
- }
- *ppPage = PGHDR_TO_DATA(pPg);
- return SQLITE_OK;
-}
-
-/*
-** Acquire a page if it is already in the in-memory cache. Do
-** not read the page from disk. Return a pointer to the page,
-** or 0 if the page is not in cache.
-**
-** See also sqlitepager_get(). The difference between this routine
-** and sqlitepager_get() is that _get() will go to the disk and read
-** in the page if the page is not already in cache. This routine
-** returns NULL if the page is not in cache or if a disk I/O error
-** has ever happened.
-*/
-void *sqlitepager_lookup(Pager *pPager, Pgno pgno){
- PgHdr *pPg;
-
- assert( pPager!=0 );
- assert( pgno!=0 );
- if( pPager->errMask & ~(PAGER_ERR_FULL) ){
- return 0;
- }
- /* if( pPager->nRef==0 ){
- ** return 0;
- ** }
- */
- pPg = pager_lookup(pPager, pgno);
- if( pPg==0 ) return 0;
- page_ref(pPg);
- return PGHDR_TO_DATA(pPg);
-}
-
-/*
-** Release a page.
-**
-** If the number of references to the page drop to zero, then the
-** page is added to the LRU list. When all references to all pages
-** are released, a rollback occurs and the lock on the database is
-** removed.
-*/
-int sqlitepager_unref(void *pData){
- PgHdr *pPg;
-
- /* Decrement the reference count for this page
- */
- pPg = DATA_TO_PGHDR(pData);
- assert( pPg->nRef>0 );
- pPg->nRef--;
- REFINFO(pPg);
-
- /* When the number of references to a page reach 0, call the
- ** destructor and add the page to the freelist.
- */
- if( pPg->nRef==0 ){
- Pager *pPager;
- pPager = pPg->pPager;
- pPg->pNextFree = 0;
- pPg->pPrevFree = pPager->pLast;
- pPager->pLast = pPg;
- if( pPg->pPrevFree ){
- pPg->pPrevFree->pNextFree = pPg;
- }else{
- pPager->pFirst = pPg;
- }
- if( pPg->needSync==0 && pPager->pFirstSynced==0 ){
- pPager->pFirstSynced = pPg;
- }
- if( pPager->xDestructor ){
- pPager->xDestructor(pData);
- }
-
- /* When all pages reach the freelist, drop the read lock from
- ** the database file.
- */
- pPager->nRef--;
- assert( pPager->nRef>=0 );
- if( pPager->nRef==0 ){
- pager_reset(pPager);
- }
- }
- return SQLITE_OK;
-}
-
-/*
-** Create a journal file for pPager. There should already be a write
-** lock on the database file when this routine is called.
-**
-** Return SQLITE_OK if everything. Return an error code and release the
-** write lock if anything goes wrong.
-*/
-static int pager_open_journal(Pager *pPager){
- int rc;
- assert( pPager->state==SQLITE_WRITELOCK );
- assert( pPager->journalOpen==0 );
- assert( pPager->useJournal );
- sqlitepager_pagecount(pPager);
- pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
- if( pPager->aInJournal==0 ){
- sqliteOsReadLock(&pPager->fd);
- pPager->state = SQLITE_READLOCK;
- return SQLITE_NOMEM;
- }
- rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile);
- if( rc!=SQLITE_OK ){
- sqliteFree(pPager->aInJournal);
- pPager->aInJournal = 0;
- sqliteOsReadLock(&pPager->fd);
- pPager->state = SQLITE_READLOCK;
- return SQLITE_CANTOPEN;
- }
- sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd);
- pPager->journalOpen = 1;
- pPager->journalStarted = 0;
- pPager->needSync = 0;
- pPager->alwaysRollback = 0;
- pPager->nRec = 0;
- if( pPager->errMask!=0 ){
- rc = pager_errcode(pPager);
- return rc;
- }
- pPager->origDbSize = pPager->dbSize;
- if( journal_format==JOURNAL_FORMAT_3 ){
- rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3));
- if( rc==SQLITE_OK ){
- rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0);
- }
- if( rc==SQLITE_OK ){
- sqliteRandomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
- rc = write32bits(&pPager->jfd, pPager->cksumInit);
- }
- }else if( journal_format==JOURNAL_FORMAT_2 ){
- rc = sqliteOsWrite(&pPager->jfd, aJournalMagic2, sizeof(aJournalMagic2));
- }else{
- assert( journal_format==JOURNAL_FORMAT_1 );
- rc = sqliteOsWrite(&pPager->jfd, aJournalMagic1, sizeof(aJournalMagic1));
- }
- if( rc==SQLITE_OK ){
- rc = write32bits(&pPager->jfd, pPager->dbSize);
- }
- if( pPager->ckptAutoopen && rc==SQLITE_OK ){
- rc = sqlitepager_ckpt_begin(pPager);
- }
- if( rc!=SQLITE_OK ){
- rc = pager_unwritelock(pPager);
- if( rc==SQLITE_OK ){
- rc = SQLITE_FULL;
- }
- }
- return rc;
-}
-
-/*
-** Acquire a write-lock on the database. The lock is removed when
-** the any of the following happen:
-**
-** * sqlitepager_commit() is called.
-** * sqlitepager_rollback() is called.
-** * sqlitepager_close() is called.
-** * sqlitepager_unref() is called to on every outstanding page.
-**
-** The parameter to this routine is a pointer to any open page of the
-** database file. Nothing changes about the page - it is used merely
-** to acquire a pointer to the Pager structure and as proof that there
-** is already a read-lock on the database.
-**
-** A journal file is opened if this is not a temporary file. For
-** temporary files, the opening of the journal file is deferred until
-** there is an actual need to write to the journal.
-**
-** If the database is already write-locked, this routine is a no-op.
-*/
-int sqlitepager_begin(void *pData){
- PgHdr *pPg = DATA_TO_PGHDR(pData);
- Pager *pPager = pPg->pPager;
- int rc = SQLITE_OK;
- assert( pPg->nRef>0 );
- assert( pPager->state!=SQLITE_UNLOCK );
- if( pPager->state==SQLITE_READLOCK ){
- assert( pPager->aInJournal==0 );
- rc = sqliteOsWriteLock(&pPager->fd);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pPager->state = SQLITE_WRITELOCK;
- pPager->dirtyFile = 0;
- TRACE1("TRANSACTION\n");
- if( pPager->useJournal && !pPager->tempFile ){
- rc = pager_open_journal(pPager);
- }
- }
- return rc;
-}
-
-/*
-** Mark a data page as writeable. The page is written into the journal
-** if it is not there already. This routine must be called before making
-** changes to a page.
-**
-** The first time this routine is called, the pager creates a new
-** journal and acquires a write lock on the database. If the write
-** lock could not be acquired, this routine returns SQLITE_BUSY. The
-** calling routine must check for that return value and be careful not to
-** change any page data until this routine returns SQLITE_OK.
-**
-** If the journal file could not be written because the disk is full,
-** then this routine returns SQLITE_FULL and does an immediate rollback.
-** All subsequent write attempts also return SQLITE_FULL until there
-** is a call to sqlitepager_commit() or sqlitepager_rollback() to
-** reset.
-*/
-int sqlitepager_write(void *pData){
- PgHdr *pPg = DATA_TO_PGHDR(pData);
- Pager *pPager = pPg->pPager;
- int rc = SQLITE_OK;
-
- /* Check for errors
- */
- if( pPager->errMask ){
- return pager_errcode(pPager);
- }
- if( pPager->readOnly ){
- return SQLITE_PERM;
- }
-
- /* Mark the page as dirty. If the page has already been written
- ** to the journal then we can return right away.
- */
- pPg->dirty = 1;
- if( pPg->inJournal && (pPg->inCkpt || pPager->ckptInUse==0) ){
- pPager->dirtyFile = 1;
- return SQLITE_OK;
- }
-
- /* If we get this far, it means that the page needs to be
- ** written to the transaction journal or the ckeckpoint journal
- ** or both.
- **
- ** First check to see that the transaction journal exists and
- ** create it if it does not.
- */
- assert( pPager->state!=SQLITE_UNLOCK );
- rc = sqlitepager_begin(pData);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- assert( pPager->state==SQLITE_WRITELOCK );
- if( !pPager->journalOpen && pPager->useJournal ){
- rc = pager_open_journal(pPager);
- if( rc!=SQLITE_OK ) return rc;
- }
- assert( pPager->journalOpen || !pPager->useJournal );
- pPager->dirtyFile = 1;
-
- /* The transaction journal now exists and we have a write lock on the
- ** main database file. Write the current page to the transaction
- ** journal if it is not there already.
- */
- if( !pPg->inJournal && pPager->useJournal ){
- if( (int)pPg->pgno <= pPager->origDbSize ){
- int szPg;
- u32 saved;
- if( journal_format>=JOURNAL_FORMAT_3 ){
- u32 cksum = pager_cksum(pPager, pPg->pgno, pData);
- saved = *(u32*)PGHDR_TO_EXTRA(pPg);
- store32bits(cksum, pPg, SQLITE_PAGE_SIZE);
- szPg = SQLITE_PAGE_SIZE+8;
- }else{
- szPg = SQLITE_PAGE_SIZE+4;
- }
- store32bits(pPg->pgno, pPg, -4);
- CODEC(pPager, pData, pPg->pgno, 7);
- rc = sqliteOsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
- TRACE3("JOURNAL %d %d\n", pPg->pgno, pPg->needSync);
- CODEC(pPager, pData, pPg->pgno, 0);
- if( journal_format>=JOURNAL_FORMAT_3 ){
- *(u32*)PGHDR_TO_EXTRA(pPg) = saved;
- }
- if( rc!=SQLITE_OK ){
- sqlitepager_rollback(pPager);
- pPager->errMask |= PAGER_ERR_FULL;
- return rc;
- }
- pPager->nRec++;
- assert( pPager->aInJournal!=0 );
- pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- pPg->needSync = !pPager->noSync;
- pPg->inJournal = 1;
- if( pPager->ckptInUse ){
- pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- page_add_to_ckpt_list(pPg);
- }
- }else{
- pPg->needSync = !pPager->journalStarted && !pPager->noSync;
- TRACE3("APPEND %d %d\n", pPg->pgno, pPg->needSync);
- }
- if( pPg->needSync ){
- pPager->needSync = 1;
- }
- }
-
- /* If the checkpoint journal is open and the page is not in it,
- ** then write the current page to the checkpoint journal. Note that
- ** the checkpoint journal always uses the simplier format 2 that lacks
- ** checksums. The header is also omitted from the checkpoint journal.
- */
- if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
- assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
- store32bits(pPg->pgno, pPg, -4);
- CODEC(pPager, pData, pPg->pgno, 7);
- rc = sqliteOsWrite(&pPager->cpfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4);
- TRACE2("CKPT-JOURNAL %d\n", pPg->pgno);
- CODEC(pPager, pData, pPg->pgno, 0);
- if( rc!=SQLITE_OK ){
- sqlitepager_rollback(pPager);
- pPager->errMask |= PAGER_ERR_FULL;
- return rc;
- }
- pPager->ckptNRec++;
- assert( pPager->aInCkpt!=0 );
- pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- page_add_to_ckpt_list(pPg);
- }
-
- /* Update the database size and return.
- */
- if( pPager->dbSize<(int)pPg->pgno ){
- pPager->dbSize = pPg->pgno;
- }
- return rc;
-}
-
-/*
-** Return TRUE if the page given in the argument was previously passed
-** to sqlitepager_write(). In other words, return TRUE if it is ok
-** to change the content of the page.
-*/
-int sqlitepager_iswriteable(void *pData){
- PgHdr *pPg = DATA_TO_PGHDR(pData);
- return pPg->dirty;
-}
-
-/*
-** Replace the content of a single page with the information in the third
-** argument.
-*/
-int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
- void *pPage;
- int rc;
-
- rc = sqlitepager_get(pPager, pgno, &pPage);
- if( rc==SQLITE_OK ){
- rc = sqlitepager_write(pPage);
- if( rc==SQLITE_OK ){
- memcpy(pPage, pData, SQLITE_PAGE_SIZE);
- }
- sqlitepager_unref(pPage);
- }
- return rc;
-}
-
-/*
-** A call to this routine tells the pager that it is not necessary to
-** write the information on page "pgno" back to the disk, even though
-** that page might be marked as dirty.
-**
-** The overlying software layer calls this routine when all of the data
-** on the given page is unused. The pager marks the page as clean so
-** that it does not get written to disk.
-**
-** Tests show that this optimization, together with the
-** sqlitepager_dont_rollback() below, more than double the speed
-** of large INSERT operations and quadruple the speed of large DELETEs.
-**
-** When this routine is called, set the alwaysRollback flag to true.
-** Subsequent calls to sqlitepager_dont_rollback() for the same page
-** will thereafter be ignored. This is necessary to avoid a problem
-** where a page with data is added to the freelist during one part of
-** a transaction then removed from the freelist during a later part
-** of the same transaction and reused for some other purpose. When it
-** is first added to the freelist, this routine is called. When reused,
-** the dont_rollback() routine is called. But because the page contains
-** critical data, we still need to be sure it gets rolled back in spite
-** of the dont_rollback() call.
-*/
-void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
- PgHdr *pPg;
-
- pPg = pager_lookup(pPager, pgno);
- pPg->alwaysRollback = 1;
- if( pPg && pPg->dirty && !pPager->ckptInUse ){
- if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
- /* If this pages is the last page in the file and the file has grown
- ** during the current transaction, then do NOT mark the page as clean.
- ** When the database file grows, we must make sure that the last page
- ** gets written at least once so that the disk file will be the correct
- ** size. If you do not write this page and the size of the file
- ** on the disk ends up being too small, that can lead to database
- ** corruption during the next transaction.
- */
- }else{
- TRACE2("DONT_WRITE %d\n", pgno);
- pPg->dirty = 0;
- }
- }
-}
-
-/*
-** A call to this routine tells the pager that if a rollback occurs,
-** it is not necessary to restore the data on the given page. This
-** means that the pager does not have to record the given page in the
-** rollback journal.
-*/
-void sqlitepager_dont_rollback(void *pData){
- PgHdr *pPg = DATA_TO_PGHDR(pData);
- Pager *pPager = pPg->pPager;
-
- if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return;
- if( pPg->alwaysRollback || pPager->alwaysRollback ) return;
- if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
- assert( pPager->aInJournal!=0 );
- pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- pPg->inJournal = 1;
- if( pPager->ckptInUse ){
- pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- page_add_to_ckpt_list(pPg);
- }
- TRACE2("DONT_ROLLBACK %d\n", pPg->pgno);
- }
- if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
- assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
- assert( pPager->aInCkpt!=0 );
- pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
- page_add_to_ckpt_list(pPg);
- }
-}
-
-/*
-** Commit all changes to the database and release the write lock.
-**
-** If the commit fails for any reason, a rollback attempt is made
-** and an error code is returned. If the commit worked, SQLITE_OK
-** is returned.
-*/
-int sqlitepager_commit(Pager *pPager){
- int rc;
- PgHdr *pPg;
-
- if( pPager->errMask==PAGER_ERR_FULL ){
- rc = sqlitepager_rollback(pPager);
- if( rc==SQLITE_OK ){
- rc = SQLITE_FULL;
- }
- return rc;
- }
- if( pPager->errMask!=0 ){
- rc = pager_errcode(pPager);
- return rc;
- }
- if( pPager->state!=SQLITE_WRITELOCK ){
- return SQLITE_ERROR;
- }
- TRACE1("COMMIT\n");
- if( pPager->dirtyFile==0 ){
- /* Exit early (without doing the time-consuming sqliteOsSync() calls)
- ** if there have been no changes to the database file. */
- assert( pPager->needSync==0 );
- rc = pager_unwritelock(pPager);
- pPager->dbSize = -1;
- return rc;
- }
- assert( pPager->journalOpen );
- rc = syncJournal(pPager);
- if( rc!=SQLITE_OK ){
- goto commit_abort;
- }
- pPg = pager_get_all_dirty_pages(pPager);
- if( pPg ){
- rc = pager_write_pagelist(pPg);
- if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){
- goto commit_abort;
- }
- }
- rc = pager_unwritelock(pPager);
- pPager->dbSize = -1;
- return rc;
-
- /* Jump here if anything goes wrong during the commit process.
- */
-commit_abort:
- rc = sqlitepager_rollback(pPager);
- if( rc==SQLITE_OK ){
- rc = SQLITE_FULL;
- }
- return rc;
-}
-
-/*
-** Rollback all changes. The database falls back to read-only mode.
-** All in-memory cache pages revert to their original data contents.
-** The journal is deleted.
-**
-** This routine cannot fail unless some other process is not following
-** the correct locking protocol (SQLITE_PROTOCOL) or unless some other
-** process is writing trash into the journal file (SQLITE_CORRUPT) or
-** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error
-** codes are returned for all these occasions. Otherwise,
-** SQLITE_OK is returned.
-*/
-int sqlitepager_rollback(Pager *pPager){
- int rc;
- TRACE1("ROLLBACK\n");
- if( !pPager->dirtyFile || !pPager->journalOpen ){
- rc = pager_unwritelock(pPager);
- pPager->dbSize = -1;
- return rc;
- }
-
- if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
- if( pPager->state>=SQLITE_WRITELOCK ){
- pager_playback(pPager, 1);
- }
- return pager_errcode(pPager);
- }
- if( pPager->state!=SQLITE_WRITELOCK ){
- return SQLITE_OK;
- }
- rc = pager_playback(pPager, 1);
- if( rc!=SQLITE_OK ){
- rc = SQLITE_CORRUPT;
- pPager->errMask |= PAGER_ERR_CORRUPT;
- }
- pPager->dbSize = -1;
- return rc;
-}
-
-/*
-** Return TRUE if the database file is opened read-only. Return FALSE
-** if the database is (in theory) writable.
-*/
-int sqlitepager_isreadonly(Pager *pPager){
- return pPager->readOnly;
-}
-
-/*
-** This routine is used for testing and analysis only.
-*/
-int *sqlitepager_stats(Pager *pPager){
- static int a[9];
- a[0] = pPager->nRef;
- a[1] = pPager->nPage;
- a[2] = pPager->mxPage;
- a[3] = pPager->dbSize;
- a[4] = pPager->state;
- a[5] = pPager->errMask;
- a[6] = pPager->nHit;
- a[7] = pPager->nMiss;
- a[8] = pPager->nOvfl;
- return a;
-}
-
-/*
-** Set the checkpoint.
-**
-** This routine should be called with the transaction journal already
-** open. A new checkpoint journal is created that can be used to rollback
-** changes of a single SQL command within a larger transaction.
-*/
-int sqlitepager_ckpt_begin(Pager *pPager){
- int rc;
- char zTemp[SQLITE_TEMPNAME_SIZE];
- if( !pPager->journalOpen ){
- pPager->ckptAutoopen = 1;
- return SQLITE_OK;
- }
- assert( pPager->journalOpen );
- assert( !pPager->ckptInUse );
- pPager->aInCkpt = sqliteMalloc( pPager->dbSize/8 + 1 );
- if( pPager->aInCkpt==0 ){
- sqliteOsReadLock(&pPager->fd);
- return SQLITE_NOMEM;
- }
-#ifndef NDEBUG
- rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize);
- if( rc ) goto ckpt_begin_failed;
- assert( pPager->ckptJSize ==
- pPager->nRec*JOURNAL_PG_SZ(journal_format)+JOURNAL_HDR_SZ(journal_format) );
-#endif
- pPager->ckptJSize = pPager->nRec*JOURNAL_PG_SZ(journal_format)
- + JOURNAL_HDR_SZ(journal_format);
- pPager->ckptSize = pPager->dbSize;
- if( !pPager->ckptOpen ){
- rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
- if( rc ) goto ckpt_begin_failed;
- pPager->ckptOpen = 1;
- pPager->ckptNRec = 0;
- }
- pPager->ckptInUse = 1;
- return SQLITE_OK;
-
-ckpt_begin_failed:
- if( pPager->aInCkpt ){
- sqliteFree(pPager->aInCkpt);
- pPager->aInCkpt = 0;
- }
- return rc;
-}
-
-/*
-** Commit a checkpoint.
-*/
-int sqlitepager_ckpt_commit(Pager *pPager){
- if( pPager->ckptInUse ){
- PgHdr *pPg, *pNext;
- sqliteOsSeek(&pPager->cpfd, 0);
- /* sqliteOsTruncate(&pPager->cpfd, 0); */
- pPager->ckptNRec = 0;
- pPager->ckptInUse = 0;
- sqliteFree( pPager->aInCkpt );
- pPager->aInCkpt = 0;
- for(pPg=pPager->pCkpt; pPg; pPg=pNext){
- pNext = pPg->pNextCkpt;
- assert( pPg->inCkpt );
- pPg->inCkpt = 0;
- pPg->pPrevCkpt = pPg->pNextCkpt = 0;
- }
- pPager->pCkpt = 0;
- }
- pPager->ckptAutoopen = 0;
- return SQLITE_OK;
-}
-
-/*
-** Rollback a checkpoint.
-*/
-int sqlitepager_ckpt_rollback(Pager *pPager){
- int rc;
- if( pPager->ckptInUse ){
- rc = pager_ckpt_playback(pPager);
- sqlitepager_ckpt_commit(pPager);
- }else{
- rc = SQLITE_OK;
- }
- pPager->ckptAutoopen = 0;
- return rc;
-}
-
-/*
-** Return the full pathname of the database file.
-*/
-const char *sqlitepager_filename(Pager *pPager){
- return pPager->zFilename;
-}
-
-/*
-** Set the codec for this pager
-*/
-void sqlitepager_set_codec(
- Pager *pPager,
- void (*xCodec)(void*,void*,Pgno,int),
- void *pCodecArg
-){
- pPager->xCodec = xCodec;
- pPager->pCodecArg = pCodecArg;
-}
-
-#ifdef SQLITE_TEST
-/*
-** Print a listing of all referenced pages and their ref count.
-*/
-void sqlitepager_refdump(Pager *pPager){
- PgHdr *pPg;
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- if( pPg->nRef<=0 ) continue;
- printf("PAGE %3d addr=0x%08x nRef=%d\n",
- pPg->pgno, (int)PGHDR_TO_DATA(pPg), pPg->nRef);
- }
-}
-#endif
diff --git a/ext/sqlite/libsqlite/src/pager.h b/ext/sqlite/libsqlite/src/pager.h
deleted file mode 100644
index 7172db88f5..0000000000
--- a/ext/sqlite/libsqlite/src/pager.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This header file defines the interface that the sqlite page cache
-** subsystem. The page cache subsystem reads and writes a file a page
-** at a time and provides a journal for rollback.
-**
-** @(#) $Id$
-*/
-
-/*
-** The size of one page
-**
-** You can change this value to another (reasonable) value you want.
-** It need not be a power of two, though the interface to the disk
-** will likely be faster if it is.
-**
-** Experiments show that a page size of 1024 gives the best speed
-** for common usages. The speed differences for different sizes
-** such as 512, 2048, 4096, an so forth, is minimal. Note, however,
-** that changing the page size results in a completely imcompatible
-** file format.
-*/
-#ifndef SQLITE_PAGE_SIZE
-#define SQLITE_PAGE_SIZE 1024
-#endif
-
-/*
-** Number of extra bytes of data allocated at the end of each page and
-** stored on disk but not used by the higher level btree layer. Changing
-** this value results in a completely incompatible file format.
-*/
-#ifndef SQLITE_PAGE_RESERVE
-#define SQLITE_PAGE_RESERVE 0
-#endif
-
-/*
-** The total number of usable bytes stored on disk for each page.
-** The usable bytes come at the beginning of the page and the reserve
-** bytes come at the end.
-*/
-#define SQLITE_USABLE_SIZE (SQLITE_PAGE_SIZE-SQLITE_PAGE_RESERVE)
-
-/*
-** Maximum number of pages in one database. (This is a limitation of
-** imposed by 4GB files size limits.)
-*/
-#define SQLITE_MAX_PAGE 1073741823
-
-/*
-** The type used to represent a page number. The first page in a file
-** is called page 1. 0 is used to represent "not a page".
-*/
-typedef unsigned int Pgno;
-
-/*
-** Each open file is managed by a separate instance of the "Pager" structure.
-*/
-typedef struct Pager Pager;
-
-/*
-** See source code comments for a detailed description of the following
-** routines:
-*/
-int sqlitepager_open(Pager **ppPager, const char *zFilename,
- int nPage, int nExtra, int useJournal);
-void sqlitepager_set_destructor(Pager*, void(*)(void*));
-void sqlitepager_set_cachesize(Pager*, int);
-int sqlitepager_close(Pager *pPager);
-int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage);
-void *sqlitepager_lookup(Pager *pPager, Pgno pgno);
-int sqlitepager_ref(void*);
-int sqlitepager_unref(void*);
-Pgno sqlitepager_pagenumber(void*);
-int sqlitepager_write(void*);
-int sqlitepager_iswriteable(void*);
-int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*);
-int sqlitepager_pagecount(Pager*);
-int sqlitepager_truncate(Pager*,Pgno);
-int sqlitepager_begin(void*);
-int sqlitepager_commit(Pager*);
-int sqlitepager_rollback(Pager*);
-int sqlitepager_isreadonly(Pager*);
-int sqlitepager_ckpt_begin(Pager*);
-int sqlitepager_ckpt_commit(Pager*);
-int sqlitepager_ckpt_rollback(Pager*);
-void sqlitepager_dont_rollback(void*);
-void sqlitepager_dont_write(Pager*, Pgno);
-int *sqlitepager_stats(Pager*);
-void sqlitepager_set_safety_level(Pager*,int);
-const char *sqlitepager_filename(Pager*);
-int sqlitepager_rename(Pager*, const char *zNewName);
-void sqlitepager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
-
-#ifdef SQLITE_TEST
-void sqlitepager_refdump(Pager*);
-int pager_refinfo_enable;
-int journal_format;
-#endif
diff --git a/ext/sqlite/libsqlite/src/parse.c b/ext/sqlite/libsqlite/src/parse.c
deleted file mode 100644
index ea1452c287..0000000000
--- a/ext/sqlite/libsqlite/src/parse.c
+++ /dev/null
@@ -1,3355 +0,0 @@
-/* Driver template for the LEMON parser generator.
-** The author disclaims copyright to this source code.
-*/
-/* First off, code is included that follows the "include" declaration
-** in the input grammar file. */
-#include <stdio.h>
-#line 33 "ext/sqlite/libsqlite/src/parse.y"
-
-#include "sqliteInt.h"
-#include "parse.h"
-
-/*
-** An instance of this structure holds information about the
-** LIMIT clause of a SELECT statement.
-*/
-struct LimitVal {
- int limit; /* The LIMIT value. -1 if there is no limit */
- int offset; /* The OFFSET. 0 if there is none */
-};
-
-/*
-** An instance of the following structure describes the event of a
-** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
-** TK_DELETE, or TK_INSTEAD. If the event is of the form
-**
-** UPDATE ON (a,b,c)
-**
-** Then the "b" IdList records the list "a,b,c".
-*/
-struct TrigEvent { int a; IdList * b; };
-
-#line 33 "ext/sqlite/libsqlite/src/parse.c"
-/* Next is all token values, in a form suitable for use by makeheaders.
-** This section will be null unless lemon is run with the -m switch.
-*/
-/*
-** These constants (all generated automatically by the parser generator)
-** specify the various kinds of tokens (terminals) that the parser
-** understands.
-**
-** Each symbol here is a terminal symbol in the grammar.
-*/
-/* Make sure the INTERFACE macro is defined.
-*/
-#ifndef INTERFACE
-# define INTERFACE 1
-#endif
-/* The next thing included is series of defines which control
-** various aspects of the generated parser.
-** YYCODETYPE is the data type used for storing terminal
-** and nonterminal numbers. "unsigned char" is
-** used if there are fewer than 250 terminals
-** and nonterminals. "int" is used otherwise.
-** YYNOCODE is a number of type YYCODETYPE which corresponds
-** to no legal terminal or nonterminal number. This
-** number is used to fill in empty slots of the hash
-** table.
-** YYFALLBACK If defined, this indicates that one or more tokens
-** have fall-back values which should be used if the
-** original value of the token will not parse.
-** YYACTIONTYPE is the data type used for storing terminal
-** and nonterminal numbers. "unsigned char" is
-** used if there are fewer than 250 rules and
-** states combined. "int" is used otherwise.
-** sqliteParserTOKENTYPE is the data type used for minor tokens given
-** directly to the parser from the tokenizer.
-** YYMINORTYPE is the data type used for all minor tokens.
-** This is typically a union of many types, one of
-** which is sqliteParserTOKENTYPE. The entry in the union
-** for base tokens is called "yy0".
-** YYSTACKDEPTH is the maximum depth of the parser's stack. If
-** zero the stack is dynamically sized using realloc()
-** sqliteParserARG_SDECL A static variable declaration for the %extra_argument
-** sqliteParserARG_PDECL A parameter declaration for the %extra_argument
-** sqliteParserARG_STORE Code to store %extra_argument into yypParser
-** sqliteParserARG_FETCH Code to extract %extra_argument from yypParser
-** YYNSTATE the combined number of states.
-** YYNRULE the number of rules in the grammar
-** YYERRORSYMBOL is the code number of the error symbol. If not
-** defined, then do no error processing.
-*/
-#define YYCODETYPE unsigned char
-#define YYNOCODE 221
-#define YYACTIONTYPE unsigned short int
-#define sqliteParserTOKENTYPE Token
-typedef union {
- int yyinit;
- sqliteParserTOKENTYPE yy0;
- TriggerStep * yy19;
- struct LimitVal yy124;
- Select* yy179;
- Expr * yy182;
- Expr* yy242;
- struct TrigEvent yy290;
- SrcList* yy307;
- IdList* yy320;
- ExprList* yy322;
- int yy372;
- struct {int value; int mask;} yy407;
-} YYMINORTYPE;
-#ifndef YYSTACKDEPTH
-#define YYSTACKDEPTH 100
-#endif
-#define sqliteParserARG_SDECL Parse *pParse;
-#define sqliteParserARG_PDECL ,Parse *pParse
-#define sqliteParserARG_FETCH Parse *pParse = yypParser->pParse
-#define sqliteParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 563
-#define YYNRULE 293
-#define YYFALLBACK 1
-#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
-#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
-#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
-
-/* The yyzerominor constant is used to initialize instances of
-** YYMINORTYPE objects to zero. */
-static const YYMINORTYPE yyzerominor = { 0 };
-
-/* Define the yytestcase() macro to be a no-op if is not already defined
-** otherwise.
-**
-** Applications can choose to define yytestcase() in the %include section
-** to a macro that can assist in verifying code coverage. For production
-** code the yytestcase() macro should be turned off. But it is useful
-** for testing.
-*/
-#ifndef yytestcase
-# define yytestcase(X)
-#endif
-
-
-/* Next are the tables used to determine what action to take based on the
-** current state and lookahead token. These tables are used to implement
-** functions that take a state number and lookahead value and return an
-** action integer.
-**
-** Suppose the action integer is N. Then the action is determined as
-** follows
-**
-** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
-** token onto the stack and goto state N.
-**
-** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
-**
-** N == YYNSTATE+YYNRULE A syntax error has occurred.
-**
-** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
-**
-** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
-** slots in the yy_action[] table.
-**
-** The action table is constructed as a single large table named yy_action[].
-** Given state S and lookahead X, the action is computed as
-**
-** yy_action[ yy_shift_ofst[S] + X ]
-**
-** If the index value yy_shift_ofst[S]+X is out of range or if the value
-** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
-** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
-** and that yy_default[S] should be used instead.
-**
-** The formula above is for computing the action when the lookahead is
-** a terminal symbol. If the lookahead is a non-terminal (as occurs after
-** a reduce action) then the yy_reduce_ofst[] array is used in place of
-** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
-** YY_SHIFT_USE_DFLT.
-**
-** The following are the tables generated in this section:
-**
-** yy_action[] A single table containing all actions.
-** yy_lookahead[] A table containing the lookahead for each entry in
-** yy_action. Used to detect hash collisions.
-** yy_shift_ofst[] For each state, the offset into yy_action for
-** shifting terminals.
-** yy_reduce_ofst[] For each state, the offset into yy_action for
-** shifting non-terminals after a reduce.
-** yy_default[] Default action for each state.
-*/
-#define YY_ACTTAB_COUNT (1090)
-static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 186, 561, 483, 69, 67, 70, 68, 64, 63, 62,
- /* 10 */ 61, 58, 57, 56, 55, 54, 53, 181, 180, 179,
- /* 20 */ 514, 421, 334, 420, 468, 515, 64, 63, 62, 61,
- /* 30 */ 58, 57, 56, 55, 54, 53, 9, 423, 422, 71,
- /* 40 */ 72, 129, 65, 66, 513, 510, 305, 52, 138, 69,
- /* 50 */ 67, 70, 68, 64, 63, 62, 61, 58, 57, 56,
- /* 60 */ 55, 54, 53, 448, 469, 175, 482, 514, 470, 344,
- /* 70 */ 342, 36, 515, 58, 57, 56, 55, 54, 53, 8,
- /* 80 */ 341, 281, 285, 307, 437, 178, 71, 72, 129, 65,
- /* 90 */ 66, 513, 510, 305, 52, 138, 69, 67, 70, 68,
- /* 100 */ 64, 63, 62, 61, 58, 57, 56, 55, 54, 53,
- /* 110 */ 130, 362, 360, 508, 507, 267, 551, 436, 298, 297,
- /* 120 */ 369, 368, 50, 128, 543, 29, 266, 449, 537, 447,
- /* 130 */ 591, 528, 442, 441, 187, 132, 514, 536, 47, 48,
- /* 140 */ 472, 515, 122, 427, 331, 409, 49, 371, 370, 518,
- /* 150 */ 328, 363, 517, 520, 45, 71, 72, 129, 65, 66,
- /* 160 */ 513, 510, 305, 52, 138, 69, 67, 70, 68, 64,
- /* 170 */ 63, 62, 61, 58, 57, 56, 55, 54, 53, 185,
- /* 180 */ 550, 549, 512, 175, 467, 516, 18, 344, 342, 36,
- /* 190 */ 544, 175, 320, 230, 231, 344, 342, 36, 341, 56,
- /* 200 */ 55, 54, 53, 212, 531, 514, 341, 551, 3, 213,
- /* 210 */ 515, 2, 551, 73, 7, 551, 184, 132, 551, 172,
- /* 220 */ 551, 309, 348, 42, 71, 72, 129, 65, 66, 513,
- /* 230 */ 510, 305, 52, 138, 69, 67, 70, 68, 64, 63,
- /* 240 */ 62, 61, 58, 57, 56, 55, 54, 53, 243, 197,
- /* 250 */ 282, 358, 268, 373, 264, 372, 183, 241, 436, 169,
- /* 260 */ 356, 171, 269, 240, 471, 426, 29, 446, 506, 514,
- /* 270 */ 445, 550, 549, 494, 515, 354, 550, 549, 359, 550,
- /* 280 */ 549, 144, 550, 549, 550, 549, 592, 309, 71, 72,
- /* 290 */ 129, 65, 66, 513, 510, 305, 52, 138, 69, 67,
- /* 300 */ 70, 68, 64, 63, 62, 61, 58, 57, 56, 55,
- /* 310 */ 54, 53, 514, 857, 82, 377, 1, 515, 268, 373,
- /* 320 */ 264, 372, 183, 241, 362, 12, 508, 507, 500, 240,
- /* 330 */ 17, 71, 72, 129, 65, 66, 513, 510, 305, 52,
- /* 340 */ 138, 69, 67, 70, 68, 64, 63, 62, 61, 58,
- /* 350 */ 57, 56, 55, 54, 53, 362, 182, 508, 507, 514,
- /* 360 */ 362, 527, 508, 507, 515, 563, 429, 463, 182, 444,
- /* 370 */ 375, 338, 443, 430, 379, 378, 593, 156, 71, 72,
- /* 380 */ 129, 65, 66, 513, 510, 305, 52, 138, 69, 67,
- /* 390 */ 70, 68, 64, 63, 62, 61, 58, 57, 56, 55,
- /* 400 */ 54, 53, 514, 526, 542, 450, 534, 515, 286, 493,
- /* 410 */ 453, 17, 478, 240, 80, 11, 533, 153, 194, 155,
- /* 420 */ 286, 71, 51, 129, 65, 66, 513, 510, 305, 52,
- /* 430 */ 138, 69, 67, 70, 68, 64, 63, 62, 61, 58,
- /* 440 */ 57, 56, 55, 54, 53, 514, 195, 466, 160, 17,
- /* 450 */ 515, 454, 490, 80, 459, 440, 460, 176, 239, 238,
- /* 460 */ 80, 80, 562, 1, 71, 40, 129, 65, 66, 513,
- /* 470 */ 510, 305, 52, 138, 69, 67, 70, 68, 64, 63,
- /* 480 */ 62, 61, 58, 57, 56, 55, 54, 53, 514, 365,
- /* 490 */ 154, 19, 339, 515, 80, 232, 405, 80, 165, 404,
- /* 500 */ 193, 32, 396, 13, 32, 86, 414, 108, 72, 129,
- /* 510 */ 65, 66, 513, 510, 305, 52, 138, 69, 67, 70,
- /* 520 */ 68, 64, 63, 62, 61, 58, 57, 56, 55, 54,
- /* 530 */ 53, 514, 551, 365, 483, 192, 515, 488, 323, 207,
- /* 540 */ 366, 249, 177, 186, 87, 483, 483, 46, 38, 44,
- /* 550 */ 458, 108, 129, 65, 66, 513, 510, 305, 52, 138,
- /* 560 */ 69, 67, 70, 68, 64, 63, 62, 61, 58, 57,
- /* 570 */ 56, 55, 54, 53, 274, 457, 272, 271, 270, 23,
- /* 580 */ 8, 551, 211, 412, 307, 257, 365, 385, 201, 31,
- /* 590 */ 217, 388, 141, 205, 387, 219, 550, 549, 482, 511,
- /* 600 */ 215, 376, 560, 134, 90, 477, 214, 514, 392, 482,
- /* 610 */ 482, 152, 515, 360, 203, 212, 409, 531, 800, 284,
- /* 620 */ 365, 145, 505, 50, 300, 365, 365, 173, 321, 212,
- /* 630 */ 487, 137, 135, 8, 41, 136, 531, 307, 93, 47,
- /* 640 */ 48, 346, 316, 106, 106, 550, 549, 49, 371, 370,
- /* 650 */ 518, 509, 531, 517, 520, 504, 531, 531, 162, 495,
- /* 660 */ 170, 317, 503, 319, 223, 231, 360, 551, 502, 283,
- /* 670 */ 162, 207, 557, 486, 212, 191, 50, 10, 289, 304,
- /* 680 */ 303, 556, 207, 531, 8, 531, 516, 18, 307, 498,
- /* 690 */ 498, 189, 47, 48, 393, 531, 555, 28, 302, 554,
- /* 700 */ 49, 371, 370, 518, 484, 480, 517, 520, 322, 299,
- /* 710 */ 553, 418, 365, 323, 17, 365, 365, 360, 416, 207,
- /* 720 */ 322, 417, 207, 418, 327, 212, 480, 50, 207, 326,
- /* 730 */ 106, 550, 549, 106, 105, 247, 407, 475, 332, 516,
- /* 740 */ 18, 326, 365, 47, 48, 207, 295, 365, 475, 294,
- /* 750 */ 158, 49, 371, 370, 518, 293, 473, 517, 520, 485,
- /* 760 */ 106, 391, 390, 202, 148, 93, 351, 480, 204, 301,
- /* 770 */ 333, 190, 291, 541, 60, 531, 498, 252, 453, 498,
- /* 780 */ 365, 365, 290, 365, 501, 475, 365, 79, 475, 531,
- /* 790 */ 516, 18, 379, 378, 475, 365, 465, 245, 89, 112,
- /* 800 */ 365, 109, 365, 131, 121, 288, 499, 365, 365, 439,
- /* 810 */ 365, 475, 365, 120, 365, 365, 343, 365, 119, 365,
- /* 820 */ 118, 365, 365, 365, 365, 117, 116, 365, 126, 365,
- /* 830 */ 125, 365, 124, 123, 365, 115, 365, 114, 431, 140,
- /* 840 */ 139, 255, 254, 365, 365, 253, 365, 280, 365, 107,
- /* 850 */ 365, 365, 113, 365, 111, 26, 365, 365, 365, 365,
- /* 860 */ 365, 279, 278, 365, 277, 365, 92, 365, 104, 103,
- /* 870 */ 365, 91, 365, 365, 102, 101, 110, 100, 99, 347,
- /* 880 */ 25, 98, 340, 30, 24, 97, 266, 174, 96, 85,
- /* 890 */ 95, 94, 166, 292, 78, 165, 415, 14, 163, 60,
- /* 900 */ 164, 22, 6, 408, 5, 77, 34, 33, 159, 16,
- /* 910 */ 157, 151, 75, 149, 15, 146, 313, 312, 395, 384,
- /* 920 */ 143, 20, 60, 206, 21, 273, 198, 559, 375, 548,
- /* 930 */ 547, 546, 374, 4, 540, 539, 538, 308, 535, 532,
- /* 940 */ 530, 212, 261, 38, 260, 352, 259, 39, 258, 367,
- /* 950 */ 529, 196, 210, 256, 521, 522, 53, 53, 209, 43,
- /* 960 */ 496, 188, 492, 208, 256, 81, 246, 37, 479, 349,
- /* 970 */ 244, 37, 474, 464, 276, 27, 452, 451, 433, 432,
- /* 980 */ 275, 235, 234, 335, 424, 35, 329, 413, 410, 127,
- /* 990 */ 161, 84, 76, 403, 38, 400, 188, 399, 224, 398,
- /* 1000 */ 38, 150, 318, 220, 83, 147, 315, 200, 381, 383,
- /* 1010 */ 199, 142, 545, 265, 88, 262, 523, 361, 491, 476,
- /* 1020 */ 463, 406, 397, 287, 389, 386, 310, 382, 552, 74,
- /* 1030 */ 306, 525, 524, 364, 519, 357, 355, 353, 497, 489,
- /* 1040 */ 481, 263, 242, 462, 461, 456, 455, 438, 296, 345,
- /* 1050 */ 434, 237, 425, 337, 168, 167, 336, 236, 419, 330,
- /* 1060 */ 233, 325, 324, 229, 228, 402, 401, 227, 226, 225,
- /* 1070 */ 222, 221, 218, 314, 394, 311, 216, 380, 251, 250,
- /* 1080 */ 133, 350, 248, 364, 558, 59, 435, 411, 428, 212,
-};
-static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 21, 9, 23, 70, 71, 72, 73, 74, 75, 76,
- /* 10 */ 77, 78, 79, 80, 81, 82, 83, 100, 101, 102,
- /* 20 */ 41, 100, 101, 102, 20, 46, 74, 75, 76, 77,
- /* 30 */ 78, 79, 80, 81, 82, 83, 19, 55, 56, 60,
- /* 40 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- /* 50 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 60 */ 81, 82, 83, 23, 108, 90, 87, 41, 112, 94,
- /* 70 */ 95, 96, 46, 78, 79, 80, 81, 82, 83, 19,
- /* 80 */ 105, 149, 143, 23, 152, 153, 60, 61, 62, 63,
- /* 90 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
- /* 100 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 110 */ 31, 107, 52, 109, 110, 93, 23, 140, 78, 79,
- /* 120 */ 78, 79, 62, 22, 147, 148, 104, 87, 34, 89,
- /* 130 */ 113, 89, 92, 93, 183, 184, 41, 43, 78, 79,
- /* 140 */ 80, 46, 165, 166, 205, 53, 86, 87, 88, 89,
- /* 150 */ 211, 62, 92, 93, 128, 60, 61, 62, 63, 64,
- /* 160 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- /* 170 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 146,
- /* 180 */ 87, 88, 93, 90, 20, 125, 126, 94, 95, 96,
- /* 190 */ 20, 90, 100, 101, 102, 94, 95, 96, 105, 80,
- /* 200 */ 81, 82, 83, 111, 171, 41, 105, 23, 19, 48,
- /* 210 */ 46, 19, 23, 19, 19, 23, 183, 184, 23, 17,
- /* 220 */ 23, 62, 189, 128, 60, 61, 62, 63, 64, 65,
- /* 230 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- /* 240 */ 76, 77, 78, 79, 80, 81, 82, 83, 20, 90,
- /* 250 */ 91, 15, 93, 94, 95, 96, 97, 98, 140, 57,
- /* 260 */ 24, 59, 144, 104, 80, 147, 148, 89, 20, 41,
- /* 270 */ 92, 87, 88, 20, 46, 39, 87, 88, 42, 87,
- /* 280 */ 88, 19, 87, 88, 87, 88, 113, 62, 60, 61,
- /* 290 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 300 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 310 */ 82, 83, 41, 132, 133, 134, 135, 46, 93, 94,
- /* 320 */ 95, 96, 97, 98, 107, 63, 109, 110, 20, 104,
- /* 330 */ 22, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 340 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 350 */ 79, 80, 81, 82, 83, 107, 47, 109, 110, 41,
- /* 360 */ 107, 89, 109, 110, 46, 0, 161, 162, 47, 89,
- /* 370 */ 99, 62, 92, 168, 9, 10, 113, 17, 60, 61,
- /* 380 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 390 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 400 */ 82, 83, 41, 89, 155, 156, 26, 46, 99, 20,
- /* 410 */ 161, 22, 20, 104, 22, 118, 36, 57, 22, 59,
- /* 420 */ 99, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 430 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 440 */ 79, 80, 81, 82, 83, 41, 50, 20, 22, 22,
- /* 450 */ 46, 20, 22, 22, 91, 20, 93, 22, 20, 20,
- /* 460 */ 22, 22, 134, 135, 60, 61, 62, 63, 64, 65,
- /* 470 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- /* 480 */ 76, 77, 78, 79, 80, 81, 82, 83, 41, 140,
- /* 490 */ 130, 22, 20, 46, 22, 20, 20, 22, 22, 20,
- /* 500 */ 113, 22, 20, 19, 22, 21, 18, 158, 61, 62,
- /* 510 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
- /* 520 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
- /* 530 */ 83, 41, 23, 140, 23, 113, 46, 22, 140, 140,
- /* 540 */ 191, 192, 19, 21, 114, 23, 23, 127, 122, 129,
- /* 550 */ 29, 158, 62, 63, 64, 65, 66, 67, 68, 69,
- /* 560 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- /* 570 */ 80, 81, 82, 83, 11, 54, 13, 14, 15, 16,
- /* 580 */ 19, 23, 174, 95, 23, 192, 140, 78, 79, 181,
- /* 590 */ 27, 89, 146, 195, 92, 32, 87, 88, 87, 93,
- /* 600 */ 37, 136, 137, 88, 158, 206, 141, 41, 99, 87,
- /* 610 */ 87, 146, 46, 52, 51, 111, 53, 171, 130, 19,
- /* 620 */ 140, 58, 14, 62, 103, 140, 140, 146, 124, 111,
- /* 630 */ 115, 146, 146, 19, 68, 69, 171, 23, 158, 78,
- /* 640 */ 79, 80, 124, 158, 158, 87, 88, 86, 87, 88,
- /* 650 */ 89, 108, 171, 92, 93, 20, 171, 171, 146, 93,
- /* 660 */ 146, 196, 20, 100, 101, 102, 52, 23, 20, 106,
- /* 670 */ 146, 140, 15, 115, 111, 22, 62, 118, 198, 194,
- /* 680 */ 194, 24, 140, 171, 19, 171, 125, 126, 23, 204,
- /* 690 */ 204, 22, 78, 79, 140, 171, 39, 19, 167, 42,
- /* 700 */ 86, 87, 88, 89, 115, 152, 92, 93, 196, 167,
- /* 710 */ 53, 140, 140, 140, 22, 140, 140, 52, 25, 140,
- /* 720 */ 196, 28, 140, 140, 212, 111, 152, 62, 140, 217,
- /* 730 */ 158, 87, 88, 158, 158, 182, 212, 206, 45, 125,
- /* 740 */ 126, 217, 140, 78, 79, 140, 167, 140, 206, 167,
- /* 750 */ 146, 86, 87, 88, 89, 167, 182, 92, 93, 115,
- /* 760 */ 158, 207, 208, 209, 146, 158, 194, 152, 195, 194,
- /* 770 */ 199, 22, 167, 156, 200, 171, 204, 201, 161, 204,
- /* 780 */ 140, 140, 199, 140, 20, 206, 140, 20, 206, 171,
- /* 790 */ 125, 126, 9, 10, 206, 140, 20, 182, 158, 158,
- /* 800 */ 140, 158, 140, 113, 158, 198, 204, 140, 140, 20,
- /* 810 */ 140, 206, 140, 158, 140, 140, 48, 140, 158, 140,
- /* 820 */ 158, 140, 140, 140, 140, 158, 158, 140, 158, 140,
- /* 830 */ 158, 140, 158, 158, 140, 158, 140, 158, 139, 158,
- /* 840 */ 158, 158, 158, 140, 140, 158, 140, 158, 140, 158,
- /* 850 */ 140, 140, 158, 140, 158, 19, 140, 140, 140, 140,
- /* 860 */ 140, 158, 158, 140, 158, 140, 158, 140, 158, 158,
- /* 870 */ 140, 158, 140, 140, 158, 158, 158, 158, 158, 140,
- /* 880 */ 19, 158, 48, 158, 19, 158, 104, 97, 158, 21,
- /* 890 */ 158, 158, 99, 38, 49, 22, 49, 158, 99, 200,
- /* 900 */ 130, 19, 11, 14, 9, 103, 63, 63, 123, 19,
- /* 910 */ 114, 114, 103, 123, 19, 114, 116, 35, 87, 20,
- /* 920 */ 21, 150, 200, 160, 160, 138, 12, 139, 99, 138,
- /* 930 */ 138, 138, 145, 22, 139, 139, 164, 44, 139, 139,
- /* 940 */ 171, 111, 176, 122, 177, 119, 178, 120, 179, 117,
- /* 950 */ 180, 121, 193, 98, 151, 23, 83, 83, 202, 127,
- /* 960 */ 186, 113, 186, 193, 98, 186, 187, 99, 188, 116,
- /* 970 */ 187, 99, 188, 139, 159, 19, 151, 164, 139, 139,
- /* 980 */ 159, 186, 215, 40, 216, 127, 186, 139, 169, 60,
- /* 990 */ 169, 197, 19, 176, 122, 186, 113, 186, 186, 176,
- /* 1000 */ 122, 169, 186, 186, 197, 169, 186, 218, 33, 219,
- /* 1010 */ 116, 218, 142, 157, 173, 175, 157, 203, 157, 157,
- /* 1020 */ 162, 176, 176, 152, 210, 210, 152, 152, 140, 140,
- /* 1030 */ 154, 154, 154, 140, 140, 140, 140, 140, 140, 185,
- /* 1040 */ 140, 172, 140, 140, 163, 163, 163, 152, 154, 154,
- /* 1050 */ 140, 140, 140, 140, 140, 213, 214, 140, 140, 140,
- /* 1060 */ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- /* 1070 */ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- /* 1080 */ 140, 140, 140, 140, 170, 200, 166, 170, 166, 111,
-};
-#define YY_SHIFT_USE_DFLT (-84)
-#define YY_SHIFT_COUNT (376)
-#define YY_SHIFT_MIN (-83)
-#define YY_SHIFT_MAX (978)
-static const short yy_shift_ofst[] = {
- /* 0 */ 783, 563, 614, 614, 93, 92, 92, 978, 614, 561,
- /* 10 */ 665, 665, 509, 197, -21, 665, 665, 665, 665, 665,
- /* 20 */ 159, 309, 197, 488, 197, 197, 197, 197, 197, 511,
- /* 30 */ 271, 60, 665, 665, 665, 665, 665, 665, 665, 665,
- /* 40 */ 665, 665, 665, 665, 665, 665, 665, 665, 665, 665,
- /* 50 */ 665, 665, 665, 665, 665, 665, 665, 665, 665, 665,
- /* 60 */ 665, 665, 665, 665, 665, 665, 665, 665, 665, 665,
- /* 70 */ 665, 665, 665, 665, 225, 197, 197, 197, 197, 522,
- /* 80 */ 197, 522, 365, 518, 504, 978, 978, -84, -84, 228,
- /* 90 */ 164, 95, 26, 318, 318, 318, 318, 318, 318, 318,
- /* 100 */ 318, 404, 318, 318, 318, 318, 318, 361, 318, 447,
- /* 110 */ 490, 490, 490, -67, -67, -67, -67, -67, -48, -48,
- /* 120 */ -48, -48, 101, -5, -5, -5, -5, 657, -25, 566,
- /* 130 */ 657, 184, 195, 644, 558, 253, 192, 248, 189, 119,
- /* 140 */ 119, 4, 197, 197, 197, 197, 197, 197, 217, 197,
- /* 150 */ 197, 197, 217, 197, 197, 197, 197, 197, 217, 197,
- /* 160 */ 197, 197, 217, 197, 197, 197, 197, -79, 693, 197,
- /* 170 */ 217, 197, 197, 217, 197, 197, 42, 42, 523, 521,
- /* 180 */ 521, 521, 197, 197, 515, 217, 197, 515, 197, 197,
- /* 190 */ 197, 197, 197, 197, 42, 42, 42, 197, 197, 511,
- /* 200 */ 511, 502, 502, 511, 426, 426, 321, 380, 380, 420,
- /* 210 */ 380, 430, -44, 380, 484, 975, 894, 975, 883, 929,
- /* 220 */ 973, 883, 883, 929, 878, 883, 883, 883, 872, 973,
- /* 230 */ 929, 929, 829, 848, 858, 943, 848, 956, 829, 829,
- /* 240 */ 893, 932, 956, 829, 853, 872, 853, 868, 848, 866,
- /* 250 */ 848, 848, 832, 874, 874, 873, 932, 855, 830, 832,
- /* 260 */ 827, 826, 821, 830, 829, 829, 893, 829, 829, 911,
- /* 270 */ 914, 914, 914, 829, 914, -84, -84, -84, -84, -84,
- /* 280 */ -84, -84, 40, 360, 236, 202, -83, 262, 482, 479,
- /* 290 */ 476, 475, -18, 472, 439, 438, 435, 280, 178, 431,
- /* 300 */ 363, 427, 392, 389, 308, 89, 396, 17, 94, 22,
- /* 310 */ 899, 899, 831, 882, 800, 801, 895, 790, 809, 797,
- /* 320 */ 796, 890, 785, 844, 843, 802, 895, 889, 891, 882,
- /* 330 */ 799, 770, 847, 873, 845, 855, 793, 868, 782, 790,
- /* 340 */ 865, 834, 861, 836, 768, 789, 776, 690, 767, 678,
- /* 350 */ 589, 692, 559, 764, 669, 648, 749, 642, 653, 635,
- /* 360 */ 600, 608, 543, 506, 422, 387, 469, 297, 314, 272,
- /* 370 */ 263, 173, 194, 161, 170, 79, -8,
-};
-#define YY_REDUCE_USE_DFLT (-69)
-#define YY_REDUCE_COUNT (281)
-#define YY_REDUCE_MIN (-68)
-#define YY_REDUCE_MAX (943)
-static const short yy_reduce_ofst[] = {
- /* 0 */ 181, 465, 486, 485, -23, 524, 512, 33, 446, 575,
- /* 10 */ 572, 349, 554, 118, 574, 607, 480, 602, 576, 393,
- /* 20 */ 249, 205, 605, -61, 588, 582, 579, 542, 531, -68,
- /* 30 */ 699, 739, 733, 732, 730, 727, 725, 723, 720, 719,
- /* 40 */ 718, 717, 716, 713, 711, 710, 708, 706, 704, 703,
- /* 50 */ 696, 694, 691, 689, 687, 684, 683, 682, 681, 679,
- /* 60 */ 677, 675, 674, 672, 670, 668, 667, 662, 660, 655,
- /* 70 */ 646, 643, 641, 640, 617, 573, 583, 398, 571, 615,
- /* 80 */ 399, 553, 328, 618, 604, 514, 481, -49, 408, 722,
- /* 90 */ 722, 722, 722, 722, 722, 722, 722, 722, 722, 722,
- /* 100 */ 722, 722, 722, 722, 722, 722, 722, 722, 722, 722,
- /* 110 */ 722, 722, 722, 722, 722, 722, 722, 722, 722, 722,
- /* 120 */ 722, 722, 922, 722, 722, 722, 722, 917, 920, 885,
- /* 130 */ 914, 943, 942, 941, 940, 869, 939, 869, 938, 722,
- /* 140 */ 722, 869, 937, 936, 935, 934, 933, 932, 869, 931,
- /* 150 */ 930, 929, 869, 928, 927, 926, 925, 924, 869, 923,
- /* 160 */ 922, 921, 869, 920, 919, 918, 917, 842, 842, 914,
- /* 170 */ 869, 913, 912, 869, 911, 910, 895, 894, 895, 883,
- /* 180 */ 882, 881, 903, 902, 854, 869, 900, 854, 898, 897,
- /* 190 */ 896, 895, 894, 893, 878, 877, 876, 889, 888, 875,
- /* 200 */ 874, 815, 814, 871, 846, 845, 858, 862, 861, 814,
- /* 210 */ 859, 840, 841, 856, 870, 793, 790, 789, 820, 836,
- /* 220 */ 807, 817, 816, 832, 823, 812, 811, 809, 817, 794,
- /* 230 */ 821, 819, 848, 800, 768, 767, 795, 821, 840, 839,
- /* 240 */ 813, 825, 815, 834, 784, 783, 780, 779, 779, 770,
- /* 250 */ 776, 774, 756, 722, 722, 722, 803, 759, 770, 769,
- /* 260 */ 768, 767, 766, 769, 800, 799, 772, 796, 795, 787,
- /* 270 */ 793, 792, 791, 788, 787, 764, 763, 722, 722, 722,
- /* 280 */ 722, 771,
-};
-static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 570, 856, 797, 797, 856, 839, 839, 685, 856, 797,
- /* 10 */ 797, 856, 822, 856, 681, 856, 856, 797, 793, 856,
- /* 20 */ 586, 649, 856, 581, 856, 856, 856, 856, 856, 594,
- /* 30 */ 651, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 40 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 50 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 60 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 70 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 681,
- /* 80 */ 856, 681, 570, 856, 856, 856, 856, 685, 675, 856,
- /* 90 */ 856, 856, 856, 730, 729, 724, 723, 837, 697, 721,
- /* 100 */ 714, 856, 789, 790, 788, 792, 796, 856, 705, 748,
- /* 110 */ 780, 774, 747, 779, 760, 759, 754, 753, 752, 751,
- /* 120 */ 750, 749, 640, 758, 757, 756, 755, 856, 856, 856,
- /* 130 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 764,
- /* 140 */ 763, 856, 856, 856, 856, 809, 856, 856, 726, 856,
- /* 150 */ 856, 856, 663, 856, 856, 856, 856, 856, 842, 856,
- /* 160 */ 856, 856, 844, 856, 856, 856, 856, 856, 828, 856,
- /* 170 */ 661, 856, 856, 583, 856, 856, 856, 856, 595, 856,
- /* 180 */ 856, 856, 856, 856, 689, 688, 856, 683, 856, 856,
- /* 190 */ 856, 856, 856, 856, 856, 856, 856, 856, 573, 856,
- /* 200 */ 856, 856, 856, 856, 720, 720, 621, 708, 708, 791,
- /* 210 */ 708, 682, 673, 708, 856, 854, 852, 854, 690, 653,
- /* 220 */ 731, 690, 690, 653, 720, 690, 690, 690, 720, 731,
- /* 230 */ 653, 653, 651, 690, 836, 833, 690, 801, 651, 651,
- /* 240 */ 636, 856, 801, 651, 700, 698, 700, 698, 690, 709,
- /* 250 */ 690, 690, 856, 767, 766, 765, 856, 709, 715, 701,
- /* 260 */ 713, 711, 720, 856, 651, 651, 636, 651, 651, 639,
- /* 270 */ 572, 572, 572, 651, 572, 624, 624, 777, 776, 775,
- /* 280 */ 768, 604, 856, 856, 856, 856, 856, 816, 856, 856,
- /* 290 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 300 */ 856, 856, 856, 856, 856, 856, 716, 737, 856, 856,
- /* 310 */ 856, 856, 856, 856, 808, 856, 856, 856, 856, 856,
- /* 320 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 330 */ 856, 856, 856, 832, 831, 856, 856, 856, 856, 856,
- /* 340 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 350 */ 856, 712, 856, 856, 856, 856, 856, 856, 856, 856,
- /* 360 */ 856, 856, 666, 856, 739, 856, 702, 856, 856, 856,
- /* 370 */ 738, 743, 856, 856, 856, 856, 856, 565, 569, 567,
- /* 380 */ 855, 853, 851, 850, 815, 821, 818, 820, 819, 817,
- /* 390 */ 814, 813, 812, 811, 810, 807, 725, 722, 719, 849,
- /* 400 */ 806, 662, 660, 843, 841, 732, 840, 838, 823, 728,
- /* 410 */ 727, 654, 799, 798, 580, 827, 826, 825, 734, 733,
- /* 420 */ 830, 829, 835, 834, 824, 579, 585, 643, 642, 650,
- /* 430 */ 648, 647, 646, 645, 644, 641, 587, 598, 599, 597,
- /* 440 */ 596, 615, 612, 614, 611, 613, 610, 609, 608, 607,
- /* 450 */ 606, 635, 623, 622, 802, 629, 628, 633, 632, 631,
- /* 460 */ 630, 627, 626, 625, 620, 746, 745, 735, 778, 672,
- /* 470 */ 671, 678, 677, 676, 687, 804, 805, 803, 699, 686,
- /* 480 */ 680, 679, 590, 589, 696, 695, 694, 693, 692, 684,
- /* 490 */ 674, 704, 786, 783, 784, 772, 785, 691, 795, 794,
- /* 500 */ 781, 848, 847, 846, 845, 787, 782, 669, 668, 667,
- /* 510 */ 771, 773, 770, 769, 762, 761, 744, 742, 741, 740,
- /* 520 */ 736, 710, 588, 703, 718, 717, 602, 601, 600, 670,
- /* 530 */ 665, 664, 619, 707, 706, 618, 638, 637, 634, 617,
- /* 540 */ 616, 605, 603, 584, 582, 578, 577, 576, 575, 593,
- /* 550 */ 592, 591, 574, 659, 658, 657, 656, 655, 652, 571,
- /* 560 */ 568, 566, 564,
-};
-
-/* The next table maps tokens into fallback tokens. If a construct
-** like the following:
-**
-** %fallback ID X Y Z.
-**
-** appears in the grammar, then ID becomes a fallback token for X, Y,
-** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
-** but it does not parse, the type of the token is changed to ID and
-** the parse is retried before an error is thrown.
-*/
-#ifdef YYFALLBACK
-static const YYCODETYPE yyFallback[] = {
- 0, /* $ => nothing */
- 0, /* END_OF_FILE => nothing */
- 0, /* ILLEGAL => nothing */
- 0, /* SPACE => nothing */
- 0, /* UNCLOSED_STRING => nothing */
- 0, /* COMMENT => nothing */
- 0, /* FUNCTION => nothing */
- 0, /* COLUMN => nothing */
- 0, /* AGG_FUNCTION => nothing */
- 0, /* SEMI => nothing */
- 23, /* EXPLAIN => ID */
- 23, /* BEGIN => ID */
- 0, /* TRANSACTION => nothing */
- 0, /* COMMIT => nothing */
- 23, /* END => ID */
- 0, /* ROLLBACK => nothing */
- 0, /* CREATE => nothing */
- 0, /* TABLE => nothing */
- 23, /* TEMP => ID */
- 0, /* LP => nothing */
- 0, /* RP => nothing */
- 0, /* AS => nothing */
- 0, /* COMMA => nothing */
- 0, /* ID => nothing */
- 23, /* ABORT => ID */
- 23, /* AFTER => ID */
- 23, /* ASC => ID */
- 23, /* ATTACH => ID */
- 23, /* BEFORE => ID */
- 23, /* CASCADE => ID */
- 23, /* CLUSTER => ID */
- 23, /* CONFLICT => ID */
- 23, /* COPY => ID */
- 23, /* DATABASE => ID */
- 23, /* DEFERRED => ID */
- 23, /* DELIMITERS => ID */
- 23, /* DESC => ID */
- 23, /* DETACH => ID */
- 23, /* EACH => ID */
- 23, /* FAIL => ID */
- 23, /* FOR => ID */
- 23, /* GLOB => ID */
- 23, /* IGNORE => ID */
- 23, /* IMMEDIATE => ID */
- 23, /* INITIALLY => ID */
- 23, /* INSTEAD => ID */
- 23, /* LIKE => ID */
- 23, /* MATCH => ID */
- 23, /* KEY => ID */
- 23, /* OF => ID */
- 23, /* OFFSET => ID */
- 23, /* PRAGMA => ID */
- 23, /* RAISE => ID */
- 23, /* REPLACE => ID */
- 23, /* RESTRICT => ID */
- 23, /* ROW => ID */
- 23, /* STATEMENT => ID */
- 23, /* TRIGGER => ID */
- 23, /* VACUUM => ID */
- 23, /* VIEW => ID */
-};
-#endif /* YYFALLBACK */
-
-/* The following structure represents a single element of the
-** parser's stack. Information stored includes:
-**
-** + The state number for the parser at this level of the stack.
-**
-** + The value of the token stored at this level of the stack.
-** (In other words, the "major" token.)
-**
-** + The semantic value stored at this level of the stack. This is
-** the information used by the action routines in the grammar.
-** It is sometimes called the "minor" token.
-*/
-struct yyStackEntry {
- YYACTIONTYPE stateno; /* The state-number */
- YYCODETYPE major; /* The major token value. This is the code
- ** number for the token at this stack level */
- YYMINORTYPE minor; /* The user-supplied minor token value. This
- ** is the value of the token */
-};
-typedef struct yyStackEntry yyStackEntry;
-
-/* The state of the parser is completely contained in an instance of
-** the following structure */
-struct yyParser {
- int yyidx; /* Index of top element in stack */
-#ifdef YYTRACKMAXSTACKDEPTH
- int yyidxMax; /* Maximum value of yyidx */
-#endif
- int yyerrcnt; /* Shifts left before out of the error */
- sqliteParserARG_SDECL /* A place to hold %extra_argument */
-#if YYSTACKDEPTH<=0
- int yystksz; /* Current side of the stack */
- yyStackEntry *yystack; /* The parser's stack */
-#else
- yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
-#endif
-};
-typedef struct yyParser yyParser;
-
-#ifndef NDEBUG
-#include <stdio.h>
-static FILE *yyTraceFILE = 0;
-static char *yyTracePrompt = 0;
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/*
-** Turn parser tracing on by giving a stream to which to write the trace
-** and a prompt to preface each trace message. Tracing is turned off
-** by making either argument NULL
-**
-** Inputs:
-** <ul>
-** <li> A FILE* to which trace output should be written.
-** If NULL, then tracing is turned off.
-** <li> A prefix string written at the beginning of every
-** line of trace output. If NULL, then tracing is
-** turned off.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void sqliteParserTrace(FILE *TraceFILE, char *zTracePrompt){
- yyTraceFILE = TraceFILE;
- yyTracePrompt = zTracePrompt;
- if( yyTraceFILE==0 ) yyTracePrompt = 0;
- else if( yyTracePrompt==0 ) yyTraceFILE = 0;
-}
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/* For tracing shifts, the names of all terminals and nonterminals
-** are required. The following table supplies these names */
-static const char *const yyTokenName[] = {
- "$", "END_OF_FILE", "ILLEGAL", "SPACE",
- "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN",
- "AGG_FUNCTION", "SEMI", "EXPLAIN", "BEGIN",
- "TRANSACTION", "COMMIT", "END", "ROLLBACK",
- "CREATE", "TABLE", "TEMP", "LP",
- "RP", "AS", "COMMA", "ID",
- "ABORT", "AFTER", "ASC", "ATTACH",
- "BEFORE", "CASCADE", "CLUSTER", "CONFLICT",
- "COPY", "DATABASE", "DEFERRED", "DELIMITERS",
- "DESC", "DETACH", "EACH", "FAIL",
- "FOR", "GLOB", "IGNORE", "IMMEDIATE",
- "INITIALLY", "INSTEAD", "LIKE", "MATCH",
- "KEY", "OF", "OFFSET", "PRAGMA",
- "RAISE", "REPLACE", "RESTRICT", "ROW",
- "STATEMENT", "TRIGGER", "VACUUM", "VIEW",
- "OR", "AND", "NOT", "EQ",
- "NE", "ISNULL", "NOTNULL", "IS",
- "BETWEEN", "IN", "GT", "GE",
- "LT", "LE", "BITAND", "BITOR",
- "LSHIFT", "RSHIFT", "PLUS", "MINUS",
- "STAR", "SLASH", "REM", "CONCAT",
- "UMINUS", "UPLUS", "BITNOT", "STRING",
- "JOIN_KW", "INTEGER", "CONSTRAINT", "DEFAULT",
- "FLOAT", "NULL", "PRIMARY", "UNIQUE",
- "CHECK", "REFERENCES", "COLLATE", "ON",
- "DELETE", "UPDATE", "INSERT", "SET",
- "DEFERRABLE", "FOREIGN", "DROP", "UNION",
- "ALL", "INTERSECT", "EXCEPT", "SELECT",
- "DISTINCT", "DOT", "FROM", "JOIN",
- "USING", "ORDER", "BY", "GROUP",
- "HAVING", "LIMIT", "WHERE", "INTO",
- "VALUES", "VARIABLE", "CASE", "WHEN",
- "THEN", "ELSE", "INDEX", "error",
- "input", "cmdlist", "ecmd", "explain",
- "cmdx", "cmd", "trans_opt", "onconf",
- "nm", "create_table", "create_table_args", "temp",
- "columnlist", "conslist_opt", "select", "column",
- "columnid", "type", "carglist", "id",
- "ids", "typename", "signed", "carg",
- "ccons", "sortorder", "expr", "idxlist_opt",
- "refargs", "defer_subclause", "refarg", "refact",
- "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
- "defer_subclause_opt", "orconf", "resolvetype", "oneselect",
- "multiselect_op", "distinct", "selcollist", "from",
- "where_opt", "groupby_opt", "having_opt", "orderby_opt",
- "limit_opt", "sclp", "as", "seltablist",
- "stl_prefix", "joinop", "dbnm", "on_opt",
- "using_opt", "seltablist_paren", "joinop2", "sortlist",
- "sortitem", "collate", "exprlist", "setlist",
- "insert_cmd", "inscollist_opt", "itemlist", "inscollist",
- "likeop", "case_operand", "case_exprlist", "case_else",
- "expritem", "uniqueflag", "idxitem", "plus_num",
- "minus_num", "plus_opt", "number", "trigger_decl",
- "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
- "when_clause", "trigger_cmd", "database_kw_opt", "key_opt",
-};
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/* For tracing reduce actions, the names of all rules are required.
-*/
-static const char *const yyRuleName[] = {
- /* 0 */ "input ::= cmdlist",
- /* 1 */ "cmdlist ::= cmdlist ecmd",
- /* 2 */ "cmdlist ::= ecmd",
- /* 3 */ "ecmd ::= explain cmdx SEMI",
- /* 4 */ "ecmd ::= SEMI",
- /* 5 */ "cmdx ::= cmd",
- /* 6 */ "explain ::= EXPLAIN",
- /* 7 */ "explain ::=",
- /* 8 */ "cmd ::= BEGIN trans_opt onconf",
- /* 9 */ "trans_opt ::=",
- /* 10 */ "trans_opt ::= TRANSACTION",
- /* 11 */ "trans_opt ::= TRANSACTION nm",
- /* 12 */ "cmd ::= COMMIT trans_opt",
- /* 13 */ "cmd ::= END trans_opt",
- /* 14 */ "cmd ::= ROLLBACK trans_opt",
- /* 15 */ "cmd ::= create_table create_table_args",
- /* 16 */ "create_table ::= CREATE temp TABLE nm",
- /* 17 */ "temp ::= TEMP",
- /* 18 */ "temp ::=",
- /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP",
- /* 20 */ "create_table_args ::= AS select",
- /* 21 */ "columnlist ::= columnlist COMMA column",
- /* 22 */ "columnlist ::= column",
- /* 23 */ "column ::= columnid type carglist",
- /* 24 */ "columnid ::= nm",
- /* 25 */ "id ::= ID",
- /* 26 */ "ids ::= ID",
- /* 27 */ "ids ::= STRING",
- /* 28 */ "nm ::= ID",
- /* 29 */ "nm ::= STRING",
- /* 30 */ "nm ::= JOIN_KW",
- /* 31 */ "type ::=",
- /* 32 */ "type ::= typename",
- /* 33 */ "type ::= typename LP signed RP",
- /* 34 */ "type ::= typename LP signed COMMA signed RP",
- /* 35 */ "typename ::= ids",
- /* 36 */ "typename ::= typename ids",
- /* 37 */ "signed ::= INTEGER",
- /* 38 */ "signed ::= PLUS INTEGER",
- /* 39 */ "signed ::= MINUS INTEGER",
- /* 40 */ "carglist ::= carglist carg",
- /* 41 */ "carglist ::=",
- /* 42 */ "carg ::= CONSTRAINT nm ccons",
- /* 43 */ "carg ::= ccons",
- /* 44 */ "carg ::= DEFAULT STRING",
- /* 45 */ "carg ::= DEFAULT ID",
- /* 46 */ "carg ::= DEFAULT INTEGER",
- /* 47 */ "carg ::= DEFAULT PLUS INTEGER",
- /* 48 */ "carg ::= DEFAULT MINUS INTEGER",
- /* 49 */ "carg ::= DEFAULT FLOAT",
- /* 50 */ "carg ::= DEFAULT PLUS FLOAT",
- /* 51 */ "carg ::= DEFAULT MINUS FLOAT",
- /* 52 */ "carg ::= DEFAULT NULL",
- /* 53 */ "ccons ::= NULL onconf",
- /* 54 */ "ccons ::= NOT NULL onconf",
- /* 55 */ "ccons ::= PRIMARY KEY sortorder onconf",
- /* 56 */ "ccons ::= UNIQUE onconf",
- /* 57 */ "ccons ::= CHECK LP expr RP onconf",
- /* 58 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
- /* 59 */ "ccons ::= defer_subclause",
- /* 60 */ "ccons ::= COLLATE id",
- /* 61 */ "refargs ::=",
- /* 62 */ "refargs ::= refargs refarg",
- /* 63 */ "refarg ::= MATCH nm",
- /* 64 */ "refarg ::= ON DELETE refact",
- /* 65 */ "refarg ::= ON UPDATE refact",
- /* 66 */ "refarg ::= ON INSERT refact",
- /* 67 */ "refact ::= SET NULL",
- /* 68 */ "refact ::= SET DEFAULT",
- /* 69 */ "refact ::= CASCADE",
- /* 70 */ "refact ::= RESTRICT",
- /* 71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 73 */ "init_deferred_pred_opt ::=",
- /* 74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 76 */ "conslist_opt ::=",
- /* 77 */ "conslist_opt ::= COMMA conslist",
- /* 78 */ "conslist ::= conslist COMMA tcons",
- /* 79 */ "conslist ::= conslist tcons",
- /* 80 */ "conslist ::= tcons",
- /* 81 */ "tcons ::= CONSTRAINT nm",
- /* 82 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf",
- /* 83 */ "tcons ::= UNIQUE LP idxlist RP onconf",
- /* 84 */ "tcons ::= CHECK expr onconf",
- /* 85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
- /* 86 */ "defer_subclause_opt ::=",
- /* 87 */ "defer_subclause_opt ::= defer_subclause",
- /* 88 */ "onconf ::=",
- /* 89 */ "onconf ::= ON CONFLICT resolvetype",
- /* 90 */ "orconf ::=",
- /* 91 */ "orconf ::= OR resolvetype",
- /* 92 */ "resolvetype ::= ROLLBACK",
- /* 93 */ "resolvetype ::= ABORT",
- /* 94 */ "resolvetype ::= FAIL",
- /* 95 */ "resolvetype ::= IGNORE",
- /* 96 */ "resolvetype ::= REPLACE",
- /* 97 */ "cmd ::= DROP TABLE nm",
- /* 98 */ "cmd ::= CREATE temp VIEW nm AS select",
- /* 99 */ "cmd ::= DROP VIEW nm",
- /* 100 */ "cmd ::= select",
- /* 101 */ "select ::= oneselect",
- /* 102 */ "select ::= select multiselect_op oneselect",
- /* 103 */ "multiselect_op ::= UNION",
- /* 104 */ "multiselect_op ::= UNION ALL",
- /* 105 */ "multiselect_op ::= INTERSECT",
- /* 106 */ "multiselect_op ::= EXCEPT",
- /* 107 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 108 */ "distinct ::= DISTINCT",
- /* 109 */ "distinct ::= ALL",
- /* 110 */ "distinct ::=",
- /* 111 */ "sclp ::= selcollist COMMA",
- /* 112 */ "sclp ::=",
- /* 113 */ "selcollist ::= sclp expr as",
- /* 114 */ "selcollist ::= sclp STAR",
- /* 115 */ "selcollist ::= sclp nm DOT STAR",
- /* 116 */ "as ::= AS nm",
- /* 117 */ "as ::= ids",
- /* 118 */ "as ::=",
- /* 119 */ "from ::=",
- /* 120 */ "from ::= FROM seltablist",
- /* 121 */ "stl_prefix ::= seltablist joinop",
- /* 122 */ "stl_prefix ::=",
- /* 123 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
- /* 124 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
- /* 125 */ "seltablist_paren ::= select",
- /* 126 */ "seltablist_paren ::= seltablist",
- /* 127 */ "dbnm ::=",
- /* 128 */ "dbnm ::= DOT nm",
- /* 129 */ "joinop ::= COMMA",
- /* 130 */ "joinop ::= JOIN",
- /* 131 */ "joinop ::= JOIN_KW JOIN",
- /* 132 */ "joinop ::= JOIN_KW nm JOIN",
- /* 133 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 134 */ "on_opt ::= ON expr",
- /* 135 */ "on_opt ::=",
- /* 136 */ "using_opt ::= USING LP idxlist RP",
- /* 137 */ "using_opt ::=",
- /* 138 */ "orderby_opt ::=",
- /* 139 */ "orderby_opt ::= ORDER BY sortlist",
- /* 140 */ "sortlist ::= sortlist COMMA sortitem collate sortorder",
- /* 141 */ "sortlist ::= sortitem collate sortorder",
- /* 142 */ "sortitem ::= expr",
- /* 143 */ "sortorder ::= ASC",
- /* 144 */ "sortorder ::= DESC",
- /* 145 */ "sortorder ::=",
- /* 146 */ "collate ::=",
- /* 147 */ "collate ::= COLLATE id",
- /* 148 */ "groupby_opt ::=",
- /* 149 */ "groupby_opt ::= GROUP BY exprlist",
- /* 150 */ "having_opt ::=",
- /* 151 */ "having_opt ::= HAVING expr",
- /* 152 */ "limit_opt ::=",
- /* 153 */ "limit_opt ::= LIMIT signed",
- /* 154 */ "limit_opt ::= LIMIT signed OFFSET signed",
- /* 155 */ "limit_opt ::= LIMIT signed COMMA signed",
- /* 156 */ "cmd ::= DELETE FROM nm dbnm where_opt",
- /* 157 */ "where_opt ::=",
- /* 158 */ "where_opt ::= WHERE expr",
- /* 159 */ "cmd ::= UPDATE orconf nm dbnm SET setlist where_opt",
- /* 160 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 161 */ "setlist ::= nm EQ expr",
- /* 162 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt VALUES LP itemlist RP",
- /* 163 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt select",
- /* 164 */ "insert_cmd ::= INSERT orconf",
- /* 165 */ "insert_cmd ::= REPLACE",
- /* 166 */ "itemlist ::= itemlist COMMA expr",
- /* 167 */ "itemlist ::= expr",
- /* 168 */ "inscollist_opt ::=",
- /* 169 */ "inscollist_opt ::= LP inscollist RP",
- /* 170 */ "inscollist ::= inscollist COMMA nm",
- /* 171 */ "inscollist ::= nm",
- /* 172 */ "expr ::= LP expr RP",
- /* 173 */ "expr ::= NULL",
- /* 174 */ "expr ::= ID",
- /* 175 */ "expr ::= JOIN_KW",
- /* 176 */ "expr ::= nm DOT nm",
- /* 177 */ "expr ::= nm DOT nm DOT nm",
- /* 178 */ "expr ::= INTEGER",
- /* 179 */ "expr ::= FLOAT",
- /* 180 */ "expr ::= STRING",
- /* 181 */ "expr ::= VARIABLE",
- /* 182 */ "expr ::= ID LP exprlist RP",
- /* 183 */ "expr ::= ID LP STAR RP",
- /* 184 */ "expr ::= expr AND expr",
- /* 185 */ "expr ::= expr OR expr",
- /* 186 */ "expr ::= expr LT expr",
- /* 187 */ "expr ::= expr GT expr",
- /* 188 */ "expr ::= expr LE expr",
- /* 189 */ "expr ::= expr GE expr",
- /* 190 */ "expr ::= expr NE expr",
- /* 191 */ "expr ::= expr EQ expr",
- /* 192 */ "expr ::= expr BITAND expr",
- /* 193 */ "expr ::= expr BITOR expr",
- /* 194 */ "expr ::= expr LSHIFT expr",
- /* 195 */ "expr ::= expr RSHIFT expr",
- /* 196 */ "expr ::= expr likeop expr",
- /* 197 */ "expr ::= expr NOT likeop expr",
- /* 198 */ "likeop ::= LIKE",
- /* 199 */ "likeop ::= GLOB",
- /* 200 */ "expr ::= expr PLUS expr",
- /* 201 */ "expr ::= expr MINUS expr",
- /* 202 */ "expr ::= expr STAR expr",
- /* 203 */ "expr ::= expr SLASH expr",
- /* 204 */ "expr ::= expr REM expr",
- /* 205 */ "expr ::= expr CONCAT expr",
- /* 206 */ "expr ::= expr ISNULL",
- /* 207 */ "expr ::= expr IS NULL",
- /* 208 */ "expr ::= expr NOTNULL",
- /* 209 */ "expr ::= expr NOT NULL",
- /* 210 */ "expr ::= expr IS NOT NULL",
- /* 211 */ "expr ::= NOT expr",
- /* 212 */ "expr ::= BITNOT expr",
- /* 213 */ "expr ::= MINUS expr",
- /* 214 */ "expr ::= PLUS expr",
- /* 215 */ "expr ::= LP select RP",
- /* 216 */ "expr ::= expr BETWEEN expr AND expr",
- /* 217 */ "expr ::= expr NOT BETWEEN expr AND expr",
- /* 218 */ "expr ::= expr IN LP exprlist RP",
- /* 219 */ "expr ::= expr IN LP select RP",
- /* 220 */ "expr ::= expr NOT IN LP exprlist RP",
- /* 221 */ "expr ::= expr NOT IN LP select RP",
- /* 222 */ "expr ::= expr IN nm dbnm",
- /* 223 */ "expr ::= expr NOT IN nm dbnm",
- /* 224 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 225 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 226 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 227 */ "case_else ::= ELSE expr",
- /* 228 */ "case_else ::=",
- /* 229 */ "case_operand ::= expr",
- /* 230 */ "case_operand ::=",
- /* 231 */ "exprlist ::= exprlist COMMA expritem",
- /* 232 */ "exprlist ::= expritem",
- /* 233 */ "expritem ::= expr",
- /* 234 */ "expritem ::=",
- /* 235 */ "cmd ::= CREATE uniqueflag INDEX nm ON nm dbnm LP idxlist RP onconf",
- /* 236 */ "uniqueflag ::= UNIQUE",
- /* 237 */ "uniqueflag ::=",
- /* 238 */ "idxlist_opt ::=",
- /* 239 */ "idxlist_opt ::= LP idxlist RP",
- /* 240 */ "idxlist ::= idxlist COMMA idxitem",
- /* 241 */ "idxlist ::= idxitem",
- /* 242 */ "idxitem ::= nm sortorder",
- /* 243 */ "cmd ::= DROP INDEX nm dbnm",
- /* 244 */ "cmd ::= COPY orconf nm dbnm FROM nm USING DELIMITERS STRING",
- /* 245 */ "cmd ::= COPY orconf nm dbnm FROM nm",
- /* 246 */ "cmd ::= VACUUM",
- /* 247 */ "cmd ::= VACUUM nm",
- /* 248 */ "cmd ::= PRAGMA ids EQ nm",
- /* 249 */ "cmd ::= PRAGMA ids EQ ON",
- /* 250 */ "cmd ::= PRAGMA ids EQ plus_num",
- /* 251 */ "cmd ::= PRAGMA ids EQ minus_num",
- /* 252 */ "cmd ::= PRAGMA ids LP nm RP",
- /* 253 */ "cmd ::= PRAGMA ids",
- /* 254 */ "plus_num ::= plus_opt number",
- /* 255 */ "minus_num ::= MINUS number",
- /* 256 */ "number ::= INTEGER",
- /* 257 */ "number ::= FLOAT",
- /* 258 */ "plus_opt ::= PLUS",
- /* 259 */ "plus_opt ::=",
- /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 261 */ "trigger_decl ::= temp TRIGGER nm trigger_time trigger_event ON nm dbnm foreach_clause when_clause",
- /* 262 */ "trigger_time ::= BEFORE",
- /* 263 */ "trigger_time ::= AFTER",
- /* 264 */ "trigger_time ::= INSTEAD OF",
- /* 265 */ "trigger_time ::=",
- /* 266 */ "trigger_event ::= DELETE",
- /* 267 */ "trigger_event ::= INSERT",
- /* 268 */ "trigger_event ::= UPDATE",
- /* 269 */ "trigger_event ::= UPDATE OF inscollist",
- /* 270 */ "foreach_clause ::=",
- /* 271 */ "foreach_clause ::= FOR EACH ROW",
- /* 272 */ "foreach_clause ::= FOR EACH STATEMENT",
- /* 273 */ "when_clause ::=",
- /* 274 */ "when_clause ::= WHEN expr",
- /* 275 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list",
- /* 276 */ "trigger_cmd_list ::=",
- /* 277 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 279 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 280 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 281 */ "trigger_cmd ::= select",
- /* 282 */ "expr ::= RAISE LP IGNORE RP",
- /* 283 */ "expr ::= RAISE LP ROLLBACK COMMA nm RP",
- /* 284 */ "expr ::= RAISE LP ABORT COMMA nm RP",
- /* 285 */ "expr ::= RAISE LP FAIL COMMA nm RP",
- /* 286 */ "cmd ::= DROP TRIGGER nm dbnm",
- /* 287 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt",
- /* 288 */ "key_opt ::= USING ids",
- /* 289 */ "key_opt ::=",
- /* 290 */ "database_kw_opt ::= DATABASE",
- /* 291 */ "database_kw_opt ::=",
- /* 292 */ "cmd ::= DETACH database_kw_opt nm",
-};
-#endif /* NDEBUG */
-
-
-#if YYSTACKDEPTH<=0
-/*
-** Try to increase the size of the parser stack.
-*/
-static void yyGrowStack(yyParser *p){
- int newSize;
- yyStackEntry *pNew;
-
- newSize = p->yystksz*2 + 100;
- pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
- if( pNew ){
- p->yystack = pNew;
- p->yystksz = newSize;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
- yyTracePrompt, p->yystksz);
- }
-#endif
- }
-}
-#endif
-
-/*
-** This function allocates a new parser.
-** The only argument is a pointer to a function which works like
-** malloc.
-**
-** Inputs:
-** A pointer to the function used to allocate memory.
-**
-** Outputs:
-** A pointer to a parser. This pointer is used in subsequent calls
-** to sqliteParser and sqliteParserFree.
-*/
-void *sqliteParserAlloc(void *(*mallocProc)(size_t)){
- yyParser *pParser;
- pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
- if( pParser ){
- pParser->yyidx = -1;
-#ifdef YYTRACKMAXSTACKDEPTH
- pParser->yyidxMax = 0;
-#endif
-#if YYSTACKDEPTH<=0
- pParser->yystack = NULL;
- pParser->yystksz = 0;
- yyGrowStack(pParser);
-#endif
- }
- return pParser;
-}
-
-/* The following function deletes the value associated with a
-** symbol. The symbol can be either a terminal or nonterminal.
-** "yymajor" is the symbol code, and "yypminor" is a pointer to
-** the value.
-*/
-static void yy_destructor(
- yyParser *yypParser, /* The parser */
- YYCODETYPE yymajor, /* Type code for object to destroy */
- YYMINORTYPE *yypminor /* The object to be destroyed */
-){
- sqliteParserARG_FETCH;
- switch( yymajor ){
- /* Here is inserted the actions which take place when a
- ** terminal or non-terminal is destroyed. This can happen
- ** when the symbol is popped from the stack during a
- ** reduce or during error processing or when a parser is
- ** being destroyed before it is finished parsing.
- **
- ** Note: during a reduce, the only symbols destroyed are those
- ** which appear on the RHS of the rule, but which are not used
- ** inside the C code.
- */
- case 146: /* select */
- case 171: /* oneselect */
- case 189: /* seltablist_paren */
-{
-#line 286 "ext/sqlite/libsqlite/src/parse.y"
-sqliteSelectDelete((yypminor->yy179));
-#line 1131 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- case 158: /* expr */
- case 176: /* where_opt */
- case 178: /* having_opt */
- case 187: /* on_opt */
- case 192: /* sortitem */
- case 204: /* expritem */
-{
-#line 533 "ext/sqlite/libsqlite/src/parse.y"
-sqliteExprDelete((yypminor->yy242));
-#line 1143 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- case 159: /* idxlist_opt */
- case 167: /* idxlist */
- case 188: /* using_opt */
- case 197: /* inscollist_opt */
- case 199: /* inscollist */
-{
-#line 746 "ext/sqlite/libsqlite/src/parse.y"
-sqliteIdListDelete((yypminor->yy320));
-#line 1154 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- case 174: /* selcollist */
- case 177: /* groupby_opt */
- case 179: /* orderby_opt */
- case 181: /* sclp */
- case 191: /* sortlist */
- case 194: /* exprlist */
- case 195: /* setlist */
- case 198: /* itemlist */
- case 202: /* case_exprlist */
-{
-#line 322 "ext/sqlite/libsqlite/src/parse.y"
-sqliteExprListDelete((yypminor->yy322));
-#line 1169 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- case 175: /* from */
- case 183: /* seltablist */
- case 184: /* stl_prefix */
-{
-#line 353 "ext/sqlite/libsqlite/src/parse.y"
-sqliteSrcListDelete((yypminor->yy307));
-#line 1178 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- case 212: /* trigger_cmd_list */
- case 217: /* trigger_cmd */
-{
-#line 828 "ext/sqlite/libsqlite/src/parse.y"
-sqliteDeleteTriggerStep((yypminor->yy19));
-#line 1186 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- case 214: /* trigger_event */
-{
-#line 812 "ext/sqlite/libsqlite/src/parse.y"
-sqliteIdListDelete((yypminor->yy290).b);
-#line 1193 "ext/sqlite/libsqlite/src/parse.c"
-}
- break;
- default: break; /* If no destructor action specified: do nothing */
- }
-}
-
-/*
-** Pop the parser's stack once.
-**
-** If there is a destructor routine associated with the token which
-** is popped from the stack, then call it.
-**
-** Return the major token number for the symbol popped.
-*/
-static int yy_pop_parser_stack(yyParser *pParser){
- YYCODETYPE yymajor;
- yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
-
- if( pParser->yyidx<0 ) return 0;
-#ifndef NDEBUG
- if( yyTraceFILE && pParser->yyidx>=0 ){
- fprintf(yyTraceFILE,"%sPopping %s\n",
- yyTracePrompt,
- yyTokenName[yytos->major]);
- }
-#endif
- yymajor = yytos->major;
- yy_destructor(pParser, yymajor, &yytos->minor);
- pParser->yyidx--;
- return yymajor;
-}
-
-/*
-** Deallocate and destroy a parser. Destructors are all called for
-** all stack elements before shutting the parser down.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser. This should be a pointer
-** obtained from sqliteParserAlloc.
-** <li> A pointer to a function used to reclaim memory obtained
-** from malloc.
-** </ul>
-*/
-void sqliteParserFree(
- void *p, /* The parser to be deleted */
- void (*freeProc)(void*) /* Function used to reclaim memory */
-){
- yyParser *pParser = (yyParser*)p;
- if( pParser==0 ) return;
- while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
-#if YYSTACKDEPTH<=0
- free(pParser->yystack);
-#endif
- (*freeProc)((void*)pParser);
-}
-
-/*
-** Return the peak depth of the stack for a parser.
-*/
-#ifdef YYTRACKMAXSTACKDEPTH
-int sqliteParserStackPeak(void *p){
- yyParser *pParser = (yyParser*)p;
- return pParser->yyidxMax;
-}
-#endif
-
-/*
-** Find the appropriate action for a parser given the terminal
-** look-ahead token iLookAhead.
-**
-** If the look-ahead token is YYNOCODE, then check to see if the action is
-** independent of the look-ahead. If it is, return the action, otherwise
-** return YY_NO_ACTION.
-*/
-static int yy_find_shift_action(
- yyParser *pParser, /* The parser */
- YYCODETYPE iLookAhead /* The look-ahead token */
-){
- int i;
- int stateno = pParser->yystack[pParser->yyidx].stateno;
-
- if( stateno>YY_SHIFT_COUNT
- || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
- return yy_default[stateno];
- }
- assert( iLookAhead!=YYNOCODE );
- i += iLookAhead;
- if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
- if( iLookAhead>0 ){
-#ifdef YYFALLBACK
- YYCODETYPE iFallback; /* Fallback token */
- if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
- && (iFallback = yyFallback[iLookAhead])!=0 ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
- }
-#endif
- return yy_find_shift_action(pParser, iFallback);
- }
-#endif
-#ifdef YYWILDCARD
- {
- int j = i - iLookAhead + YYWILDCARD;
- if(
-#if YY_SHIFT_MIN+YYWILDCARD<0
- j>=0 &&
-#endif
-#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
- j<YY_ACTTAB_COUNT &&
-#endif
- yy_lookahead[j]==YYWILDCARD
- ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
- }
-#endif /* NDEBUG */
- return yy_action[j];
- }
- }
-#endif /* YYWILDCARD */
- }
- return yy_default[stateno];
- }else{
- return yy_action[i];
- }
-}
-
-/*
-** Find the appropriate action for a parser given the non-terminal
-** look-ahead token iLookAhead.
-**
-** If the look-ahead token is YYNOCODE, then check to see if the action is
-** independent of the look-ahead. If it is, return the action, otherwise
-** return YY_NO_ACTION.
-*/
-static int yy_find_reduce_action(
- int stateno, /* Current state number */
- YYCODETYPE iLookAhead /* The look-ahead token */
-){
- int i;
-#ifdef YYERRORSYMBOL
- if( stateno>YY_REDUCE_COUNT ){
- return yy_default[stateno];
- }
-#else
- assert( stateno<=YY_REDUCE_COUNT );
-#endif
- i = yy_reduce_ofst[stateno];
- assert( i!=YY_REDUCE_USE_DFLT );
- assert( iLookAhead!=YYNOCODE );
- i += iLookAhead;
-#ifdef YYERRORSYMBOL
- if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
- return yy_default[stateno];
- }
-#else
- assert( i>=0 && i<YY_ACTTAB_COUNT );
- assert( yy_lookahead[i]==iLookAhead );
-#endif
- return yy_action[i];
-}
-
-/*
-** The following routine is called if the stack overflows.
-*/
-static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
- sqliteParserARG_FETCH;
- yypParser->yyidx--;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will execute if the parser
- ** stack every overflows */
- sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument var */
-}
-
-/*
-** Perform a shift action.
-*/
-static void yy_shift(
- yyParser *yypParser, /* The parser to be shifted */
- int yyNewState, /* The new state to shift in */
- int yyMajor, /* The major token to shift in */
- YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
-){
- yyStackEntry *yytos;
- yypParser->yyidx++;
-#ifdef YYTRACKMAXSTACKDEPTH
- if( yypParser->yyidx>yypParser->yyidxMax ){
- yypParser->yyidxMax = yypParser->yyidx;
- }
-#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yyidx>=YYSTACKDEPTH ){
- yyStackOverflow(yypParser, yypMinor);
- return;
- }
-#else
- if( yypParser->yyidx>=yypParser->yystksz ){
- yyGrowStack(yypParser);
- if( yypParser->yyidx>=yypParser->yystksz ){
- yyStackOverflow(yypParser, yypMinor);
- return;
- }
- }
-#endif
- yytos = &yypParser->yystack[yypParser->yyidx];
- yytos->stateno = (YYACTIONTYPE)yyNewState;
- yytos->major = (YYCODETYPE)yyMajor;
- yytos->minor = *yypMinor;
-#ifndef NDEBUG
- if( yyTraceFILE && yypParser->yyidx>0 ){
- int i;
- fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
- fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
- for(i=1; i<=yypParser->yyidx; i++)
- fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
- fprintf(yyTraceFILE,"\n");
- }
-#endif
-}
-
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static const struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- unsigned char nrhs; /* Number of right-hand side symbols in the rule */
-} yyRuleInfo[] = {
- { 132, 1 },
- { 133, 2 },
- { 133, 1 },
- { 134, 3 },
- { 134, 1 },
- { 136, 1 },
- { 135, 1 },
- { 135, 0 },
- { 137, 3 },
- { 138, 0 },
- { 138, 1 },
- { 138, 2 },
- { 137, 2 },
- { 137, 2 },
- { 137, 2 },
- { 137, 2 },
- { 141, 4 },
- { 143, 1 },
- { 143, 0 },
- { 142, 4 },
- { 142, 2 },
- { 144, 3 },
- { 144, 1 },
- { 147, 3 },
- { 148, 1 },
- { 151, 1 },
- { 152, 1 },
- { 152, 1 },
- { 140, 1 },
- { 140, 1 },
- { 140, 1 },
- { 149, 0 },
- { 149, 1 },
- { 149, 4 },
- { 149, 6 },
- { 153, 1 },
- { 153, 2 },
- { 154, 1 },
- { 154, 2 },
- { 154, 2 },
- { 150, 2 },
- { 150, 0 },
- { 155, 3 },
- { 155, 1 },
- { 155, 2 },
- { 155, 2 },
- { 155, 2 },
- { 155, 3 },
- { 155, 3 },
- { 155, 2 },
- { 155, 3 },
- { 155, 3 },
- { 155, 2 },
- { 156, 2 },
- { 156, 3 },
- { 156, 4 },
- { 156, 2 },
- { 156, 5 },
- { 156, 4 },
- { 156, 1 },
- { 156, 2 },
- { 160, 0 },
- { 160, 2 },
- { 162, 2 },
- { 162, 3 },
- { 162, 3 },
- { 162, 3 },
- { 163, 2 },
- { 163, 2 },
- { 163, 1 },
- { 163, 1 },
- { 161, 3 },
- { 161, 2 },
- { 164, 0 },
- { 164, 2 },
- { 164, 2 },
- { 145, 0 },
- { 145, 2 },
- { 165, 3 },
- { 165, 2 },
- { 165, 1 },
- { 166, 2 },
- { 166, 6 },
- { 166, 5 },
- { 166, 3 },
- { 166, 10 },
- { 168, 0 },
- { 168, 1 },
- { 139, 0 },
- { 139, 3 },
- { 169, 0 },
- { 169, 2 },
- { 170, 1 },
- { 170, 1 },
- { 170, 1 },
- { 170, 1 },
- { 170, 1 },
- { 137, 3 },
- { 137, 6 },
- { 137, 3 },
- { 137, 1 },
- { 146, 1 },
- { 146, 3 },
- { 172, 1 },
- { 172, 2 },
- { 172, 1 },
- { 172, 1 },
- { 171, 9 },
- { 173, 1 },
- { 173, 1 },
- { 173, 0 },
- { 181, 2 },
- { 181, 0 },
- { 174, 3 },
- { 174, 2 },
- { 174, 4 },
- { 182, 2 },
- { 182, 1 },
- { 182, 0 },
- { 175, 0 },
- { 175, 2 },
- { 184, 2 },
- { 184, 0 },
- { 183, 6 },
- { 183, 7 },
- { 189, 1 },
- { 189, 1 },
- { 186, 0 },
- { 186, 2 },
- { 185, 1 },
- { 185, 1 },
- { 185, 2 },
- { 185, 3 },
- { 185, 4 },
- { 187, 2 },
- { 187, 0 },
- { 188, 4 },
- { 188, 0 },
- { 179, 0 },
- { 179, 3 },
- { 191, 5 },
- { 191, 3 },
- { 192, 1 },
- { 157, 1 },
- { 157, 1 },
- { 157, 0 },
- { 193, 0 },
- { 193, 2 },
- { 177, 0 },
- { 177, 3 },
- { 178, 0 },
- { 178, 2 },
- { 180, 0 },
- { 180, 2 },
- { 180, 4 },
- { 180, 4 },
- { 137, 5 },
- { 176, 0 },
- { 176, 2 },
- { 137, 7 },
- { 195, 5 },
- { 195, 3 },
- { 137, 9 },
- { 137, 6 },
- { 196, 2 },
- { 196, 1 },
- { 198, 3 },
- { 198, 1 },
- { 197, 0 },
- { 197, 3 },
- { 199, 3 },
- { 199, 1 },
- { 158, 3 },
- { 158, 1 },
- { 158, 1 },
- { 158, 1 },
- { 158, 3 },
- { 158, 5 },
- { 158, 1 },
- { 158, 1 },
- { 158, 1 },
- { 158, 1 },
- { 158, 4 },
- { 158, 4 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 4 },
- { 200, 1 },
- { 200, 1 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 3 },
- { 158, 2 },
- { 158, 3 },
- { 158, 2 },
- { 158, 3 },
- { 158, 4 },
- { 158, 2 },
- { 158, 2 },
- { 158, 2 },
- { 158, 2 },
- { 158, 3 },
- { 158, 5 },
- { 158, 6 },
- { 158, 5 },
- { 158, 5 },
- { 158, 6 },
- { 158, 6 },
- { 158, 4 },
- { 158, 5 },
- { 158, 5 },
- { 202, 5 },
- { 202, 4 },
- { 203, 2 },
- { 203, 0 },
- { 201, 1 },
- { 201, 0 },
- { 194, 3 },
- { 194, 1 },
- { 204, 1 },
- { 204, 0 },
- { 137, 11 },
- { 205, 1 },
- { 205, 0 },
- { 159, 0 },
- { 159, 3 },
- { 167, 3 },
- { 167, 1 },
- { 206, 2 },
- { 137, 4 },
- { 137, 9 },
- { 137, 6 },
- { 137, 1 },
- { 137, 2 },
- { 137, 4 },
- { 137, 4 },
- { 137, 4 },
- { 137, 4 },
- { 137, 5 },
- { 137, 2 },
- { 207, 2 },
- { 208, 2 },
- { 210, 1 },
- { 210, 1 },
- { 209, 1 },
- { 209, 0 },
- { 137, 5 },
- { 211, 10 },
- { 213, 1 },
- { 213, 1 },
- { 213, 2 },
- { 213, 0 },
- { 214, 1 },
- { 214, 1 },
- { 214, 1 },
- { 214, 3 },
- { 215, 0 },
- { 215, 3 },
- { 215, 3 },
- { 216, 0 },
- { 216, 2 },
- { 212, 3 },
- { 212, 0 },
- { 217, 6 },
- { 217, 8 },
- { 217, 5 },
- { 217, 4 },
- { 217, 1 },
- { 158, 4 },
- { 158, 6 },
- { 158, 6 },
- { 158, 6 },
- { 137, 4 },
- { 137, 6 },
- { 219, 2 },
- { 219, 0 },
- { 218, 1 },
- { 218, 0 },
- { 137, 3 },
-};
-
-static void yy_accept(yyParser*); /* Forward Declaration */
-
-/*
-** Perform a reduce action and the shift that must immediately
-** follow the reduce.
-*/
-static void yy_reduce(
- yyParser *yypParser, /* The parser */
- int yyruleno /* Number of the rule by which to reduce */
-){
- int yygoto; /* The next state */
- int yyact; /* The next action */
- YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
- yyStackEntry *yymsp; /* The top of the parser's stack */
- int yysize; /* Amount to pop the stack */
- sqliteParserARG_FETCH;
- yymsp = &yypParser->yystack[yypParser->yyidx];
-#ifndef NDEBUG
- if( yyTraceFILE && yyruleno>=0
- && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
- fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
- yyRuleName[yyruleno]);
- }
-#endif /* NDEBUG */
-
- /* Silence complaints from purify about yygotominor being uninitialized
- ** in some cases when it is copied into the stack after the following
- ** switch. yygotominor is uninitialized when a rule reduces that does
- ** not set the value of its left-hand side nonterminal. Leaving the
- ** value of the nonterminal uninitialized is utterly harmless as long
- ** as the value is never used. So really the only thing this code
- ** accomplishes is to quieten purify.
- **
- ** 2007-01-16: The wireshark project (www.wireshark.org) reports that
- ** without this code, their parser segfaults. I'm not sure what there
- ** parser is doing to make this happen. This is the second bug report
- ** from wireshark this week. Clearly they are stressing Lemon in ways
- ** that it has not been previously stressed... (SQLite ticket #2172)
- */
- /*memset(&yygotominor, 0, sizeof(yygotominor));*/
- yygotominor = yyzerominor;
-
-
- switch( yyruleno ){
- /* Beginning here are the reduction cases. A typical example
- ** follows:
- ** case 0:
- ** #line <lineno> <grammarfile>
- ** { ... } // User supplied code
- ** #line <lineno> <thisfile>
- ** break;
- */
- case 5: /* cmdx ::= cmd */
-#line 72 "ext/sqlite/libsqlite/src/parse.y"
-{ sqliteExec(pParse); }
-#line 1781 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 6: /* explain ::= EXPLAIN */
-#line 73 "ext/sqlite/libsqlite/src/parse.y"
-{ sqliteBeginParse(pParse, 1); }
-#line 1786 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 7: /* explain ::= */
-#line 74 "ext/sqlite/libsqlite/src/parse.y"
-{ sqliteBeginParse(pParse, 0); }
-#line 1791 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 8: /* cmd ::= BEGIN trans_opt onconf */
-#line 79 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteBeginTransaction(pParse,yymsp[0].minor.yy372);}
-#line 1796 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 12: /* cmd ::= COMMIT trans_opt */
- case 13: /* cmd ::= END trans_opt */ yytestcase(yyruleno==13);
-#line 83 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteCommitTransaction(pParse);}
-#line 1802 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 14: /* cmd ::= ROLLBACK trans_opt */
-#line 85 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteRollbackTransaction(pParse);}
-#line 1807 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 16: /* create_table ::= CREATE temp TABLE nm */
-#line 90 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteStartTable(pParse,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0,yymsp[-2].minor.yy372,0);
-}
-#line 1814 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 17: /* temp ::= TEMP */
- case 74: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==74);
- case 108: /* distinct ::= DISTINCT */ yytestcase(yyruleno==108);
-#line 94 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = 1;}
-#line 1821 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 18: /* temp ::= */
- case 73: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==73);
- case 75: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==75);
- case 86: /* defer_subclause_opt ::= */ yytestcase(yyruleno==86);
- case 109: /* distinct ::= ALL */ yytestcase(yyruleno==109);
- case 110: /* distinct ::= */ yytestcase(yyruleno==110);
-#line 95 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = 0;}
-#line 1831 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 19: /* create_table_args ::= LP columnlist conslist_opt RP */
-#line 96 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteEndTable(pParse,&yymsp[0].minor.yy0,0);
-}
-#line 1838 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 20: /* create_table_args ::= AS select */
-#line 99 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteEndTable(pParse,0,yymsp[0].minor.yy179);
- sqliteSelectDelete(yymsp[0].minor.yy179);
-}
-#line 1846 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 24: /* columnid ::= nm */
-#line 111 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddColumn(pParse,&yymsp[0].minor.yy0);}
-#line 1851 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 25: /* id ::= ID */
- case 26: /* ids ::= ID */ yytestcase(yyruleno==26);
- case 27: /* ids ::= STRING */ yytestcase(yyruleno==27);
- case 28: /* nm ::= ID */ yytestcase(yyruleno==28);
- case 29: /* nm ::= STRING */ yytestcase(yyruleno==29);
- case 30: /* nm ::= JOIN_KW */ yytestcase(yyruleno==30);
- case 35: /* typename ::= ids */ yytestcase(yyruleno==35);
- case 128: /* dbnm ::= DOT nm */ yytestcase(yyruleno==128);
- case 254: /* plus_num ::= plus_opt number */ yytestcase(yyruleno==254);
- case 255: /* minus_num ::= MINUS number */ yytestcase(yyruleno==255);
- case 256: /* number ::= INTEGER */ yytestcase(yyruleno==256);
- case 257: /* number ::= FLOAT */ yytestcase(yyruleno==257);
-#line 117 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy0 = yymsp[0].minor.yy0;}
-#line 1867 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 32: /* type ::= typename */
-#line 160 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddColumnType(pParse,&yymsp[0].minor.yy0,&yymsp[0].minor.yy0);}
-#line 1872 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 33: /* type ::= typename LP signed RP */
-#line 161 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddColumnType(pParse,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);}
-#line 1877 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 34: /* type ::= typename LP signed COMMA signed RP */
-#line 163 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddColumnType(pParse,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);}
-#line 1882 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 36: /* typename ::= typename ids */
- case 242: /* idxitem ::= nm sortorder */ yytestcase(yyruleno==242);
-#line 166 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy0 = yymsp[-1].minor.yy0;}
-#line 1888 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 37: /* signed ::= INTEGER */
- case 38: /* signed ::= PLUS INTEGER */ yytestcase(yyruleno==38);
-#line 168 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); }
-#line 1894 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 39: /* signed ::= MINUS INTEGER */
-#line 170 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = -atoi(yymsp[0].minor.yy0.z); }
-#line 1899 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 44: /* carg ::= DEFAULT STRING */
- case 45: /* carg ::= DEFAULT ID */ yytestcase(yyruleno==45);
- case 46: /* carg ::= DEFAULT INTEGER */ yytestcase(yyruleno==46);
- case 47: /* carg ::= DEFAULT PLUS INTEGER */ yytestcase(yyruleno==47);
- case 49: /* carg ::= DEFAULT FLOAT */ yytestcase(yyruleno==49);
- case 50: /* carg ::= DEFAULT PLUS FLOAT */ yytestcase(yyruleno==50);
-#line 175 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);}
-#line 1909 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 48: /* carg ::= DEFAULT MINUS INTEGER */
- case 51: /* carg ::= DEFAULT MINUS FLOAT */ yytestcase(yyruleno==51);
-#line 179 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);}
-#line 1915 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 54: /* ccons ::= NOT NULL onconf */
-#line 189 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddNotNull(pParse, yymsp[0].minor.yy372);}
-#line 1920 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 55: /* ccons ::= PRIMARY KEY sortorder onconf */
-#line 190 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddPrimaryKey(pParse,0,yymsp[0].minor.yy372);}
-#line 1925 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 56: /* ccons ::= UNIQUE onconf */
-#line 191 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteCreateIndex(pParse,0,0,0,yymsp[0].minor.yy372,0,0);}
-#line 1930 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 57: /* ccons ::= CHECK LP expr RP onconf */
-#line 192 "ext/sqlite/libsqlite/src/parse.y"
-{
- yy_destructor(yypParser,158,&yymsp[-2].minor);
-}
-#line 1937 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 58: /* ccons ::= REFERENCES nm idxlist_opt refargs */
-#line 194 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteCreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy320,yymsp[0].minor.yy372);}
-#line 1942 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 59: /* ccons ::= defer_subclause */
-#line 195 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteDeferForeignKey(pParse,yymsp[0].minor.yy372);}
-#line 1947 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 60: /* ccons ::= COLLATE id */
-#line 196 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteAddCollateType(pParse, sqliteCollateType(yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n));
-}
-#line 1954 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 61: /* refargs ::= */
-#line 206 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Restrict * 0x010101; }
-#line 1959 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 62: /* refargs ::= refargs refarg */
-#line 207 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = (yymsp[-1].minor.yy372 & yymsp[0].minor.yy407.mask) | yymsp[0].minor.yy407.value; }
-#line 1964 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 63: /* refarg ::= MATCH nm */
-#line 209 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy407.value = 0; yygotominor.yy407.mask = 0x000000; }
-#line 1969 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 64: /* refarg ::= ON DELETE refact */
-#line 210 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy407.value = yymsp[0].minor.yy372; yygotominor.yy407.mask = 0x0000ff; }
-#line 1974 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 65: /* refarg ::= ON UPDATE refact */
-#line 211 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy407.value = yymsp[0].minor.yy372<<8; yygotominor.yy407.mask = 0x00ff00; }
-#line 1979 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 66: /* refarg ::= ON INSERT refact */
-#line 212 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy407.value = yymsp[0].minor.yy372<<16; yygotominor.yy407.mask = 0xff0000; }
-#line 1984 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 67: /* refact ::= SET NULL */
-#line 214 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_SetNull; }
-#line 1989 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 68: /* refact ::= SET DEFAULT */
-#line 215 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_SetDflt; }
-#line 1994 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 69: /* refact ::= CASCADE */
-#line 216 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Cascade; }
-#line 1999 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 70: /* refact ::= RESTRICT */
-#line 217 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Restrict; }
-#line 2004 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 71: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- case 72: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==72);
- case 87: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==87);
- case 164: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==164);
-#line 219 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = yymsp[0].minor.yy372;}
-#line 2012 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 82: /* tcons ::= PRIMARY KEY LP idxlist RP onconf */
-#line 236 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteAddPrimaryKey(pParse,yymsp[-2].minor.yy320,yymsp[0].minor.yy372);}
-#line 2017 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 83: /* tcons ::= UNIQUE LP idxlist RP onconf */
-#line 238 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteCreateIndex(pParse,0,0,yymsp[-2].minor.yy320,yymsp[0].minor.yy372,0,0);}
-#line 2022 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 84: /* tcons ::= CHECK expr onconf */
-#line 239 "ext/sqlite/libsqlite/src/parse.y"
-{
- yy_destructor(yypParser,158,&yymsp[-1].minor);
-}
-#line 2029 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 85: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
-#line 241 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteCreateForeignKey(pParse, yymsp[-6].minor.yy320, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy320, yymsp[-1].minor.yy372);
- sqliteDeferForeignKey(pParse, yymsp[0].minor.yy372);
-}
-#line 2037 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 88: /* onconf ::= */
- case 90: /* orconf ::= */ yytestcase(yyruleno==90);
-#line 255 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Default; }
-#line 2043 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 89: /* onconf ::= ON CONFLICT resolvetype */
- case 91: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==91);
-#line 256 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = yymsp[0].minor.yy372; }
-#line 2049 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 92: /* resolvetype ::= ROLLBACK */
-#line 259 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Rollback; }
-#line 2054 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 93: /* resolvetype ::= ABORT */
- case 236: /* uniqueflag ::= UNIQUE */ yytestcase(yyruleno==236);
-#line 260 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Abort; }
-#line 2060 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 94: /* resolvetype ::= FAIL */
-#line 261 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Fail; }
-#line 2065 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 95: /* resolvetype ::= IGNORE */
-#line 262 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Ignore; }
-#line 2070 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 96: /* resolvetype ::= REPLACE */
-#line 263 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_Replace; }
-#line 2075 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 97: /* cmd ::= DROP TABLE nm */
-#line 267 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteDropTable(pParse,&yymsp[0].minor.yy0,0);}
-#line 2080 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 98: /* cmd ::= CREATE temp VIEW nm AS select */
-#line 271 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteCreateView(pParse, &yymsp[-5].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);
-}
-#line 2087 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 99: /* cmd ::= DROP VIEW nm */
-#line 274 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteDropTable(pParse, &yymsp[0].minor.yy0, 1);
-}
-#line 2094 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 100: /* cmd ::= select */
-#line 280 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteSelect(pParse, yymsp[0].minor.yy179, SRT_Callback, 0, 0, 0, 0);
- sqliteSelectDelete(yymsp[0].minor.yy179);
-}
-#line 2102 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 101: /* select ::= oneselect */
- case 125: /* seltablist_paren ::= select */ yytestcase(yyruleno==125);
-#line 290 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy179 = yymsp[0].minor.yy179;}
-#line 2108 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 102: /* select ::= select multiselect_op oneselect */
-#line 291 "ext/sqlite/libsqlite/src/parse.y"
-{
- if( yymsp[0].minor.yy179 ){
- yymsp[0].minor.yy179->op = yymsp[-1].minor.yy372;
- yymsp[0].minor.yy179->pPrior = yymsp[-2].minor.yy179;
- }
- yygotominor.yy179 = yymsp[0].minor.yy179;
-}
-#line 2119 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 103: /* multiselect_op ::= UNION */
-#line 299 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = TK_UNION;}
-#line 2124 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 104: /* multiselect_op ::= UNION ALL */
-#line 300 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = TK_ALL;}
-#line 2129 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 105: /* multiselect_op ::= INTERSECT */
-#line 301 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = TK_INTERSECT;}
-#line 2134 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 106: /* multiselect_op ::= EXCEPT */
-#line 302 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = TK_EXCEPT;}
-#line 2139 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 107: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
-#line 304 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy179 = sqliteSelectNew(yymsp[-6].minor.yy322,yymsp[-5].minor.yy307,yymsp[-4].minor.yy242,yymsp[-3].minor.yy322,yymsp[-2].minor.yy242,yymsp[-1].minor.yy322,yymsp[-7].minor.yy372,yymsp[0].minor.yy124.limit,yymsp[0].minor.yy124.offset);
-}
-#line 2146 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 111: /* sclp ::= selcollist COMMA */
-#line 325 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = yymsp[-1].minor.yy322;}
-#line 2151 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 112: /* sclp ::= */
- case 138: /* orderby_opt ::= */ yytestcase(yyruleno==138);
- case 148: /* groupby_opt ::= */ yytestcase(yyruleno==148);
-#line 326 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = 0;}
-#line 2158 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 113: /* selcollist ::= sclp expr as */
-#line 327 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[-1].minor.yy242,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
-}
-#line 2165 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 114: /* selcollist ::= sclp STAR */
-#line 330 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy322 = sqliteExprListAppend(yymsp[-1].minor.yy322, sqliteExpr(TK_ALL, 0, 0, 0), 0);
-}
-#line 2172 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 115: /* selcollist ::= sclp nm DOT STAR */
-#line 333 "ext/sqlite/libsqlite/src/parse.y"
-{
- Expr *pRight = sqliteExpr(TK_ALL, 0, 0, 0);
- Expr *pLeft = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy0);
- yygotominor.yy322 = sqliteExprListAppend(yymsp[-3].minor.yy322, sqliteExpr(TK_DOT, pLeft, pRight, 0), 0);
-}
-#line 2181 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 116: /* as ::= AS nm */
- case 117: /* as ::= ids */ yytestcase(yyruleno==117);
- case 288: /* key_opt ::= USING ids */ yytestcase(yyruleno==288);
-#line 343 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy0 = yymsp[0].minor.yy0; }
-#line 2188 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 118: /* as ::= */
-#line 345 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy0.n = 0; }
-#line 2193 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 119: /* from ::= */
-#line 357 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy307 = sqliteMalloc(sizeof(*yygotominor.yy307));}
-#line 2198 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 120: /* from ::= FROM seltablist */
-#line 358 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy307 = yymsp[0].minor.yy307;}
-#line 2203 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 121: /* stl_prefix ::= seltablist joinop */
-#line 363 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy307 = yymsp[-1].minor.yy307;
- if( yygotominor.yy307 && yygotominor.yy307->nSrc>0 ) yygotominor.yy307->a[yygotominor.yy307->nSrc-1].jointype = yymsp[0].minor.yy372;
-}
-#line 2211 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 122: /* stl_prefix ::= */
-#line 367 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy307 = 0;}
-#line 2216 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 123: /* seltablist ::= stl_prefix nm dbnm as on_opt using_opt */
-#line 368 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy307 = sqliteSrcListAppend(yymsp[-5].minor.yy307,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0);
- if( yymsp[-2].minor.yy0.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy0);
- if( yymsp[-1].minor.yy242 ){
- if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; }
- else { sqliteExprDelete(yymsp[-1].minor.yy242); }
- }
- if( yymsp[0].minor.yy320 ){
- if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; }
- else { sqliteIdListDelete(yymsp[0].minor.yy320); }
- }
-}
-#line 2232 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 124: /* seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt */
-#line 381 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy307 = sqliteSrcListAppend(yymsp[-6].minor.yy307,0,0);
- yygotominor.yy307->a[yygotominor.yy307->nSrc-1].pSelect = yymsp[-4].minor.yy179;
- if( yymsp[-2].minor.yy0.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy0);
- if( yymsp[-1].minor.yy242 ){
- if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; }
- else { sqliteExprDelete(yymsp[-1].minor.yy242); }
- }
- if( yymsp[0].minor.yy320 ){
- if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; }
- else { sqliteIdListDelete(yymsp[0].minor.yy320); }
- }
-}
-#line 2249 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 126: /* seltablist_paren ::= seltablist */
-#line 402 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy179 = sqliteSelectNew(0,yymsp[0].minor.yy307,0,0,0,0,0,-1,0);
-}
-#line 2256 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 127: /* dbnm ::= */
-#line 407 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
-#line 2261 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 129: /* joinop ::= COMMA */
- case 130: /* joinop ::= JOIN */ yytestcase(yyruleno==130);
-#line 412 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = JT_INNER; }
-#line 2267 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 131: /* joinop ::= JOIN_KW JOIN */
-#line 414 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
-#line 2272 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 132: /* joinop ::= JOIN_KW nm JOIN */
-#line 415 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
-#line 2277 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 133: /* joinop ::= JOIN_KW nm nm JOIN */
-#line 417 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
-#line 2282 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 134: /* on_opt ::= ON expr */
- case 142: /* sortitem ::= expr */ yytestcase(yyruleno==142);
- case 151: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==151);
- case 158: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==158);
- case 227: /* case_else ::= ELSE expr */ yytestcase(yyruleno==227);
- case 229: /* case_operand ::= expr */ yytestcase(yyruleno==229);
- case 233: /* expritem ::= expr */ yytestcase(yyruleno==233);
-#line 421 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = yymsp[0].minor.yy242;}
-#line 2293 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 135: /* on_opt ::= */
- case 150: /* having_opt ::= */ yytestcase(yyruleno==150);
- case 157: /* where_opt ::= */ yytestcase(yyruleno==157);
- case 228: /* case_else ::= */ yytestcase(yyruleno==228);
- case 230: /* case_operand ::= */ yytestcase(yyruleno==230);
- case 234: /* expritem ::= */ yytestcase(yyruleno==234);
-#line 422 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = 0;}
-#line 2303 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 136: /* using_opt ::= USING LP idxlist RP */
- case 169: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==169);
- case 239: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==239);
-#line 426 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy320 = yymsp[-1].minor.yy320;}
-#line 2310 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 137: /* using_opt ::= */
- case 168: /* inscollist_opt ::= */ yytestcase(yyruleno==168);
- case 238: /* idxlist_opt ::= */ yytestcase(yyruleno==238);
-#line 427 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy320 = 0;}
-#line 2317 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 139: /* orderby_opt ::= ORDER BY sortlist */
- case 149: /* groupby_opt ::= GROUP BY exprlist */ yytestcase(yyruleno==149);
-#line 438 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = yymsp[0].minor.yy322;}
-#line 2323 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 140: /* sortlist ::= sortlist COMMA sortitem collate sortorder */
-#line 439 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[-2].minor.yy242,0);
- if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372;
-}
-#line 2331 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 141: /* sortlist ::= sortitem collate sortorder */
-#line 443 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy322 = sqliteExprListAppend(0,yymsp[-2].minor.yy242,0);
- if( yygotominor.yy322 ) yygotominor.yy322->a[0].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372;
-}
-#line 2339 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 143: /* sortorder ::= ASC */
- case 145: /* sortorder ::= */ yytestcase(yyruleno==145);
-#line 452 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = SQLITE_SO_ASC;}
-#line 2345 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 144: /* sortorder ::= DESC */
-#line 453 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = SQLITE_SO_DESC;}
-#line 2350 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 146: /* collate ::= */
-#line 455 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = SQLITE_SO_UNK;}
-#line 2355 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 147: /* collate ::= COLLATE id */
-#line 456 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = sqliteCollateType(yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);}
-#line 2360 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 152: /* limit_opt ::= */
-#line 469 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy124.limit = -1; yygotominor.yy124.offset = 0;}
-#line 2365 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 153: /* limit_opt ::= LIMIT signed */
-#line 470 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = 0;}
-#line 2370 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 154: /* limit_opt ::= LIMIT signed OFFSET signed */
-#line 472 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy124.limit = yymsp[-2].minor.yy372; yygotominor.yy124.offset = yymsp[0].minor.yy372;}
-#line 2375 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 155: /* limit_opt ::= LIMIT signed COMMA signed */
-#line 474 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = yymsp[-2].minor.yy372;}
-#line 2380 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 156: /* cmd ::= DELETE FROM nm dbnm where_opt */
-#line 478 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteDeleteFrom(pParse, sqliteSrcListAppend(0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0), yymsp[0].minor.yy242);
-}
-#line 2387 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 159: /* cmd ::= UPDATE orconf nm dbnm SET setlist where_opt */
-#line 494 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteUpdate(pParse,sqliteSrcListAppend(0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0),yymsp[-1].minor.yy322,yymsp[0].minor.yy242,yymsp[-5].minor.yy372);}
-#line 2392 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 160: /* setlist ::= setlist COMMA nm EQ expr */
-#line 497 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[0].minor.yy242,&yymsp[-2].minor.yy0);}
-#line 2397 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 161: /* setlist ::= nm EQ expr */
-#line 498 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,&yymsp[-2].minor.yy0);}
-#line 2402 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 162: /* cmd ::= insert_cmd INTO nm dbnm inscollist_opt VALUES LP itemlist RP */
-#line 504 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0), yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy320, yymsp[-8].minor.yy372);}
-#line 2407 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 163: /* cmd ::= insert_cmd INTO nm dbnm inscollist_opt select */
-#line 506 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0), 0, yymsp[0].minor.yy179, yymsp[-1].minor.yy320, yymsp[-5].minor.yy372);}
-#line 2412 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 165: /* insert_cmd ::= REPLACE */
-#line 510 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = OE_Replace;}
-#line 2417 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 166: /* itemlist ::= itemlist COMMA expr */
- case 231: /* exprlist ::= exprlist COMMA expritem */ yytestcase(yyruleno==231);
-#line 516 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);}
-#line 2423 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 167: /* itemlist ::= expr */
- case 232: /* exprlist ::= expritem */ yytestcase(yyruleno==232);
-#line 517 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);}
-#line 2429 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 170: /* inscollist ::= inscollist COMMA nm */
- case 240: /* idxlist ::= idxlist COMMA idxitem */ yytestcase(yyruleno==240);
-#line 526 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy0);}
-#line 2435 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 171: /* inscollist ::= nm */
- case 241: /* idxlist ::= idxitem */ yytestcase(yyruleno==241);
-#line 527 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy0);}
-#line 2441 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 172: /* expr ::= LP expr RP */
-#line 535 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = yymsp[-1].minor.yy242; sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
-#line 2446 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 173: /* expr ::= NULL */
-#line 536 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_NULL, 0, 0, &yymsp[0].minor.yy0);}
-#line 2451 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 174: /* expr ::= ID */
- case 175: /* expr ::= JOIN_KW */ yytestcase(yyruleno==175);
-#line 537 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);}
-#line 2457 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 176: /* expr ::= nm DOT nm */
-#line 539 "ext/sqlite/libsqlite/src/parse.y"
-{
- Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy0);
- Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);
- yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp2, 0);
-}
-#line 2466 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 177: /* expr ::= nm DOT nm DOT nm */
-#line 544 "ext/sqlite/libsqlite/src/parse.y"
-{
- Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-4].minor.yy0);
- Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy0);
- Expr *temp3 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);
- Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0);
- yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp4, 0);
-}
-#line 2477 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 178: /* expr ::= INTEGER */
-#line 551 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_INTEGER, 0, 0, &yymsp[0].minor.yy0);}
-#line 2482 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 179: /* expr ::= FLOAT */
-#line 552 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_FLOAT, 0, 0, &yymsp[0].minor.yy0);}
-#line 2487 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 180: /* expr ::= STRING */
-#line 553 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_STRING, 0, 0, &yymsp[0].minor.yy0);}
-#line 2492 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 181: /* expr ::= VARIABLE */
-#line 554 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_VARIABLE, 0, 0, &yymsp[0].minor.yy0);
- if( yygotominor.yy242 ) yygotominor.yy242->iTable = ++pParse->nVar;
-}
-#line 2500 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 182: /* expr ::= ID LP exprlist RP */
-#line 558 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExprFunction(yymsp[-1].minor.yy322, &yymsp[-3].minor.yy0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
-}
-#line 2508 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 183: /* expr ::= ID LP STAR RP */
-#line 562 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExprFunction(0, &yymsp[-3].minor.yy0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
-}
-#line 2516 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 184: /* expr ::= expr AND expr */
-#line 566 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_AND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2521 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 185: /* expr ::= expr OR expr */
-#line 567 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_OR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2526 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 186: /* expr ::= expr LT expr */
-#line 568 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_LT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2531 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 187: /* expr ::= expr GT expr */
-#line 569 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_GT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2536 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 188: /* expr ::= expr LE expr */
-#line 570 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_LE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2541 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 189: /* expr ::= expr GE expr */
-#line 571 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_GE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2546 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 190: /* expr ::= expr NE expr */
-#line 572 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_NE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2551 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 191: /* expr ::= expr EQ expr */
-#line 573 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_EQ, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2556 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 192: /* expr ::= expr BITAND expr */
-#line 574 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_BITAND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2561 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 193: /* expr ::= expr BITOR expr */
-#line 575 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_BITOR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2566 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 194: /* expr ::= expr LSHIFT expr */
-#line 576 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_LSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2571 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 195: /* expr ::= expr RSHIFT expr */
-#line 577 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_RSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2576 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 196: /* expr ::= expr likeop expr */
-#line 578 "ext/sqlite/libsqlite/src/parse.y"
-{
- ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0);
- pList = sqliteExprListAppend(pList, yymsp[-2].minor.yy242, 0);
- yygotominor.yy242 = sqliteExprFunction(pList, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372;
- sqliteExprSpan(yygotominor.yy242, &yymsp[-2].minor.yy242->span, &yymsp[0].minor.yy242->span);
-}
-#line 2587 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 197: /* expr ::= expr NOT likeop expr */
-#line 585 "ext/sqlite/libsqlite/src/parse.y"
-{
- ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0);
- pList = sqliteExprListAppend(pList, yymsp[-3].minor.yy242, 0);
- yygotominor.yy242 = sqliteExprFunction(pList, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372;
- yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy242->span);
-}
-#line 2599 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 198: /* likeop ::= LIKE */
-#line 594 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = TK_LIKE;}
-#line 2604 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 199: /* likeop ::= GLOB */
-#line 595 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy372 = TK_GLOB;}
-#line 2609 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 200: /* expr ::= expr PLUS expr */
-#line 596 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_PLUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2614 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 201: /* expr ::= expr MINUS expr */
-#line 597 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_MINUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2619 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 202: /* expr ::= expr STAR expr */
-#line 598 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_STAR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2624 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 203: /* expr ::= expr SLASH expr */
-#line 599 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_SLASH, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2629 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 204: /* expr ::= expr REM expr */
-#line 600 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_REM, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2634 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 205: /* expr ::= expr CONCAT expr */
-#line 601 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy242 = sqliteExpr(TK_CONCAT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);}
-#line 2639 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 206: /* expr ::= expr ISNULL */
-#line 602 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-1].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2647 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 207: /* expr ::= expr IS NULL */
-#line 606 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-2].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2655 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 208: /* expr ::= expr NOTNULL */
-#line 610 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-1].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2663 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 209: /* expr ::= expr NOT NULL */
-#line 614 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-2].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2671 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 210: /* expr ::= expr IS NOT NULL */
-#line 618 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-3].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2679 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 211: /* expr ::= NOT expr */
-#line 622 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_NOT, yymsp[0].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
-}
-#line 2687 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 212: /* expr ::= BITNOT expr */
-#line 626 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_BITNOT, yymsp[0].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
-}
-#line 2695 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 213: /* expr ::= MINUS expr */
-#line 630 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_UMINUS, yymsp[0].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
-}
-#line 2703 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 214: /* expr ::= PLUS expr */
-#line 634 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_UPLUS, yymsp[0].minor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span);
-}
-#line 2711 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 215: /* expr ::= LP select RP */
-#line 638 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_SELECT, 0, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
- sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
-}
-#line 2720 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 216: /* expr ::= expr BETWEEN expr AND expr */
-#line 643 "ext/sqlite/libsqlite/src/parse.y"
-{
- ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
- pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0);
- yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-4].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pList = pList;
- sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy242->span);
-}
-#line 2731 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 217: /* expr ::= expr NOT BETWEEN expr AND expr */
-#line 650 "ext/sqlite/libsqlite/src/parse.y"
-{
- ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
- pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0);
- yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-5].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pList = pList;
- yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy242->span);
-}
-#line 2743 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 218: /* expr ::= expr IN LP exprlist RP */
-#line 658 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322;
- sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2752 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 219: /* expr ::= expr IN LP select RP */
-#line 663 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
- sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2761 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 220: /* expr ::= expr NOT IN LP exprlist RP */
-#line 668 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322;
- yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2771 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 221: /* expr ::= expr NOT IN LP select RP */
-#line 674 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179;
- yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0);
-}
-#line 2781 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 222: /* expr ::= expr IN nm dbnm */
-#line 680 "ext/sqlite/libsqlite/src/parse.y"
-{
- SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);
- yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-3].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
-}
-#line 2791 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 223: /* expr ::= expr NOT IN nm dbnm */
-#line 686 "ext/sqlite/libsqlite/src/parse.y"
-{
- SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);
- yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
- yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0);
- sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
-}
-#line 2802 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 224: /* expr ::= CASE case_operand case_exprlist case_else END */
-#line 696 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_CASE, yymsp[-3].minor.yy242, yymsp[-1].minor.yy242, 0);
- if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-2].minor.yy322;
- sqliteExprSpan(yygotominor.yy242, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 2811 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 225: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
-#line 703 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322, yymsp[-2].minor.yy242, 0);
- yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0);
-}
-#line 2819 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 226: /* case_exprlist ::= WHEN expr THEN expr */
-#line 707 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy322 = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0);
- yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0);
-}
-#line 2827 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 235: /* cmd ::= CREATE uniqueflag INDEX nm ON nm dbnm LP idxlist RP onconf */
-#line 732 "ext/sqlite/libsqlite/src/parse.y"
-{
- SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-5].minor.yy0, &yymsp[-4].minor.yy0);
- if( yymsp[-9].minor.yy372!=OE_None ) yymsp[-9].minor.yy372 = yymsp[0].minor.yy372;
- if( yymsp[-9].minor.yy372==OE_Default) yymsp[-9].minor.yy372 = OE_Abort;
- sqliteCreateIndex(pParse, &yymsp[-7].minor.yy0, pSrc, yymsp[-2].minor.yy320, yymsp[-9].minor.yy372, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0);
-}
-#line 2837 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 237: /* uniqueflag ::= */
-#line 741 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = OE_None; }
-#line 2842 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 243: /* cmd ::= DROP INDEX nm dbnm */
-#line 758 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteDropIndex(pParse, sqliteSrcListAppend(0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0));
-}
-#line 2849 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 244: /* cmd ::= COPY orconf nm dbnm FROM nm USING DELIMITERS STRING */
-#line 766 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0),&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0,yymsp[-7].minor.yy372);}
-#line 2854 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 245: /* cmd ::= COPY orconf nm dbnm FROM nm */
-#line 768 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0),&yymsp[0].minor.yy0,0,yymsp[-4].minor.yy372);}
-#line 2859 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 246: /* cmd ::= VACUUM */
-#line 772 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteVacuum(pParse,0);}
-#line 2864 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 247: /* cmd ::= VACUUM nm */
-#line 773 "ext/sqlite/libsqlite/src/parse.y"
-{sqliteVacuum(pParse,&yymsp[0].minor.yy0);}
-#line 2869 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 248: /* cmd ::= PRAGMA ids EQ nm */
- case 249: /* cmd ::= PRAGMA ids EQ ON */ yytestcase(yyruleno==249);
- case 250: /* cmd ::= PRAGMA ids EQ plus_num */ yytestcase(yyruleno==250);
-#line 777 "ext/sqlite/libsqlite/src/parse.y"
-{sqlitePragma(pParse,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
-#line 2876 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 251: /* cmd ::= PRAGMA ids EQ minus_num */
-#line 780 "ext/sqlite/libsqlite/src/parse.y"
-{sqlitePragma(pParse,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
-#line 2881 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 252: /* cmd ::= PRAGMA ids LP nm RP */
-#line 781 "ext/sqlite/libsqlite/src/parse.y"
-{sqlitePragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
-#line 2886 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 253: /* cmd ::= PRAGMA ids */
-#line 782 "ext/sqlite/libsqlite/src/parse.y"
-{sqlitePragma(pParse,&yymsp[0].minor.yy0,&yymsp[0].minor.yy0,0);}
-#line 2891 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 260: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
-#line 792 "ext/sqlite/libsqlite/src/parse.y"
-{
- Token all;
- all.z = yymsp[-4].minor.yy0.z;
- all.n = (yymsp[0].minor.yy0.z - yymsp[-4].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqliteFinishTrigger(pParse, yymsp[-1].minor.yy19, &all);
-}
-#line 2901 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 261: /* trigger_decl ::= temp TRIGGER nm trigger_time trigger_event ON nm dbnm foreach_clause when_clause */
-#line 800 "ext/sqlite/libsqlite/src/parse.y"
-{
- SrcList *pTab = sqliteSrcListAppend(0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0);
- sqliteBeginTrigger(pParse, &yymsp[-7].minor.yy0, yymsp[-6].minor.yy372, yymsp[-5].minor.yy290.a, yymsp[-5].minor.yy290.b, pTab, yymsp[-1].minor.yy372, yymsp[0].minor.yy182, yymsp[-9].minor.yy372);
-}
-#line 2909 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 262: /* trigger_time ::= BEFORE */
- case 265: /* trigger_time ::= */ yytestcase(yyruleno==265);
-#line 806 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = TK_BEFORE; }
-#line 2915 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 263: /* trigger_time ::= AFTER */
-#line 807 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = TK_AFTER; }
-#line 2920 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 264: /* trigger_time ::= INSTEAD OF */
-#line 808 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = TK_INSTEAD;}
-#line 2925 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 266: /* trigger_event ::= DELETE */
-#line 813 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy290.a = TK_DELETE; yygotominor.yy290.b = 0; }
-#line 2930 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 267: /* trigger_event ::= INSERT */
-#line 814 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy290.a = TK_INSERT; yygotominor.yy290.b = 0; }
-#line 2935 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 268: /* trigger_event ::= UPDATE */
-#line 815 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = 0;}
-#line 2940 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 269: /* trigger_event ::= UPDATE OF inscollist */
-#line 816 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = yymsp[0].minor.yy320; }
-#line 2945 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 270: /* foreach_clause ::= */
- case 271: /* foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==271);
-#line 819 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = TK_ROW; }
-#line 2951 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 272: /* foreach_clause ::= FOR EACH STATEMENT */
-#line 821 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy372 = TK_STATEMENT; }
-#line 2956 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 273: /* when_clause ::= */
-#line 824 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy182 = 0; }
-#line 2961 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 274: /* when_clause ::= WHEN expr */
-#line 825 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy182 = yymsp[0].minor.yy242; }
-#line 2966 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 275: /* trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list */
-#line 829 "ext/sqlite/libsqlite/src/parse.y"
-{
- yymsp[-2].minor.yy19->pNext = yymsp[0].minor.yy19;
- yygotominor.yy19 = yymsp[-2].minor.yy19;
-}
-#line 2974 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 276: /* trigger_cmd_list ::= */
-#line 833 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy19 = 0; }
-#line 2979 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 277: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
-#line 839 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy19 = sqliteTriggerUpdateStep(&yymsp[-3].minor.yy0, yymsp[-1].minor.yy322, yymsp[0].minor.yy242, yymsp[-4].minor.yy372); }
-#line 2984 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 278: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
-#line 844 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-5].minor.yy0, yymsp[-4].minor.yy320, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy372);}
-#line 2989 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 279: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
-#line 847 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-2].minor.yy0, yymsp[-1].minor.yy320, 0, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);}
-#line 2994 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 280: /* trigger_cmd ::= DELETE FROM nm where_opt */
-#line 851 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy19 = sqliteTriggerDeleteStep(&yymsp[-1].minor.yy0, yymsp[0].minor.yy242);}
-#line 2999 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 281: /* trigger_cmd ::= select */
-#line 854 "ext/sqlite/libsqlite/src/parse.y"
-{yygotominor.yy19 = sqliteTriggerSelectStep(yymsp[0].minor.yy179); }
-#line 3004 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 282: /* expr ::= RAISE LP IGNORE RP */
-#line 857 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, 0);
- yygotominor.yy242->iColumn = OE_Ignore;
- sqliteExprSpan(yygotominor.yy242, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3013 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 283: /* expr ::= RAISE LP ROLLBACK COMMA nm RP */
-#line 862 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- yygotominor.yy242->iColumn = OE_Rollback;
- sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3022 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 284: /* expr ::= RAISE LP ABORT COMMA nm RP */
-#line 867 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- yygotominor.yy242->iColumn = OE_Abort;
- sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3031 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 285: /* expr ::= RAISE LP FAIL COMMA nm RP */
-#line 872 "ext/sqlite/libsqlite/src/parse.y"
-{
- yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- yygotominor.yy242->iColumn = OE_Fail;
- sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3040 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 286: /* cmd ::= DROP TRIGGER nm dbnm */
-#line 879 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0));
-}
-#line 3047 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 287: /* cmd ::= ATTACH database_kw_opt ids AS nm key_opt */
-#line 884 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteAttach(pParse, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);
-}
-#line 3054 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 289: /* key_opt ::= */
-#line 889 "ext/sqlite/libsqlite/src/parse.y"
-{ yygotominor.yy0.z = 0; yygotominor.yy0.n = 0; }
-#line 3059 "ext/sqlite/libsqlite/src/parse.c"
- break;
- case 292: /* cmd ::= DETACH database_kw_opt nm */
-#line 895 "ext/sqlite/libsqlite/src/parse.y"
-{
- sqliteDetach(pParse, &yymsp[0].minor.yy0);
-}
-#line 3066 "ext/sqlite/libsqlite/src/parse.c"
- break;
- default:
- /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
- /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
- /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
- /* (3) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==3);
- /* (4) ecmd ::= SEMI */ yytestcase(yyruleno==4);
- /* (9) trans_opt ::= */ yytestcase(yyruleno==9);
- /* (10) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==10);
- /* (11) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==11);
- /* (15) cmd ::= create_table create_table_args */ yytestcase(yyruleno==15);
- /* (21) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==21);
- /* (22) columnlist ::= column */ yytestcase(yyruleno==22);
- /* (23) column ::= columnid type carglist */ yytestcase(yyruleno==23);
- /* (31) type ::= */ yytestcase(yyruleno==31);
- /* (40) carglist ::= carglist carg */ yytestcase(yyruleno==40);
- /* (41) carglist ::= */ yytestcase(yyruleno==41);
- /* (42) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==42);
- /* (43) carg ::= ccons */ yytestcase(yyruleno==43);
- /* (52) carg ::= DEFAULT NULL */ yytestcase(yyruleno==52);
- /* (53) ccons ::= NULL onconf */ yytestcase(yyruleno==53);
- /* (76) conslist_opt ::= */ yytestcase(yyruleno==76);
- /* (77) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==77);
- /* (78) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==78);
- /* (79) conslist ::= conslist tcons */ yytestcase(yyruleno==79);
- /* (80) conslist ::= tcons */ yytestcase(yyruleno==80);
- /* (81) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==81);
- /* (258) plus_opt ::= PLUS */ yytestcase(yyruleno==258);
- /* (259) plus_opt ::= */ yytestcase(yyruleno==259);
- /* (290) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==290);
- /* (291) database_kw_opt ::= */ yytestcase(yyruleno==291);
- break;
- };
- yygoto = yyRuleInfo[yyruleno].lhs;
- yysize = yyRuleInfo[yyruleno].nrhs;
- yypParser->yyidx -= yysize;
- yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
- if( yyact < YYNSTATE ){
-#ifdef NDEBUG
- /* If we are not debugging and the reduce action popped at least
- ** one element off the stack, then we can push the new element back
- ** onto the stack here, and skip the stack overflow test in yy_shift().
- ** That gives a significant speed improvement. */
- if( yysize ){
- yypParser->yyidx++;
- yymsp -= yysize-1;
- yymsp->stateno = (YYACTIONTYPE)yyact;
- yymsp->major = (YYCODETYPE)yygoto;
- yymsp->minor = yygotominor;
- }else
-#endif
- {
- yy_shift(yypParser,yyact,yygoto,&yygotominor);
- }
- }else{
- assert( yyact == YYNSTATE + YYNRULE + 1 );
- yy_accept(yypParser);
- }
-}
-
-/*
-** The following code executes when the parse fails
-*/
-#ifndef YYNOERRORRECOVERY
-static void yy_parse_failed(
- yyParser *yypParser /* The parser */
-){
- sqliteParserARG_FETCH;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser fails */
- sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-#endif /* YYNOERRORRECOVERY */
-
-/*
-** The following code executes when a syntax error first occurs.
-*/
-static void yy_syntax_error(
- yyParser *yypParser, /* The parser */
- int yymajor, /* The major type of the error token */
- YYMINORTYPE yyminor /* The minor type of the error token */
-){
- sqliteParserARG_FETCH;
-#define TOKEN (yyminor.yy0)
-#line 23 "ext/sqlite/libsqlite/src/parse.y"
-
- if( pParse->zErrMsg==0 ){
- if( TOKEN.z[0] ){
- sqliteErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
- }else{
- sqliteErrorMsg(pParse, "incomplete SQL statement");
- }
- }
-#line 3166 "ext/sqlite/libsqlite/src/parse.c"
- sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/*
-** The following is executed when the parser accepts
-*/
-static void yy_accept(
- yyParser *yypParser /* The parser */
-){
- sqliteParserARG_FETCH;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser accepts */
- sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/* The main parser program.
-** The first argument is a pointer to a structure obtained from
-** "sqliteParserAlloc" which describes the current state of the parser.
-** The second argument is the major token number. The third is
-** the minor token. The fourth optional argument is whatever the
-** user wants (and specified in the grammar) and is available for
-** use by the action routines.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser (an opaque structure.)
-** <li> The major token number.
-** <li> The minor token number.
-** <li> An option argument of a grammar-specified type.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void sqliteParser(
- void *yyp, /* The parser */
- int yymajor, /* The major token code number */
- sqliteParserTOKENTYPE yyminor /* The value for the token */
- sqliteParserARG_PDECL /* Optional %extra_argument parameter */
-){
- YYMINORTYPE yyminorunion;
- int yyact; /* The parser action. */
- int yyendofinput; /* True if we are at the end of input */
-#ifdef YYERRORSYMBOL
- int yyerrorhit = 0; /* True if yymajor has invoked an error */
-#endif
- yyParser *yypParser; /* The parser */
-
- /* (re)initialize the parser, if necessary */
- yypParser = (yyParser*)yyp;
- if( yypParser->yyidx<0 ){
-#if YYSTACKDEPTH<=0
- if( yypParser->yystksz <=0 ){
- /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
- yyminorunion = yyzerominor;
- yyStackOverflow(yypParser, &yyminorunion);
- return;
- }
-#endif
- yypParser->yyidx = 0;
- yypParser->yyerrcnt = -1;
- yypParser->yystack[0].stateno = 0;
- yypParser->yystack[0].major = 0;
- }
- yyminorunion.yy0 = yyminor;
- yyendofinput = (yymajor==0);
- sqliteParserARG_STORE;
-
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
-
- do{
- yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
- if( yyact<YYNSTATE ){
- assert( !yyendofinput ); /* Impossible to shift the $ token */
- yy_shift(yypParser,yyact,yymajor,&yyminorunion);
- yypParser->yyerrcnt--;
- yymajor = YYNOCODE;
- }else if( yyact < YYNSTATE + YYNRULE ){
- yy_reduce(yypParser,yyact-YYNSTATE);
- }else{
- assert( yyact == YY_ERROR_ACTION );
-#ifdef YYERRORSYMBOL
- int yymx;
-#endif
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
- }
-#endif
-#ifdef YYERRORSYMBOL
- /* A syntax error has occurred.
- ** The response to an error depends upon whether or not the
- ** grammar defines an error token "ERROR".
- **
- ** This is what we do if the grammar does define ERROR:
- **
- ** * Call the %syntax_error function.
- **
- ** * Begin popping the stack until we enter a state where
- ** it is legal to shift the error symbol, then shift
- ** the error symbol.
- **
- ** * Set the error count to three.
- **
- ** * Begin accepting and shifting new tokens. No new error
- ** processing will occur until three tokens have been
- ** shifted successfully.
- **
- */
- if( yypParser->yyerrcnt<0 ){
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- }
- yymx = yypParser->yystack[yypParser->yyidx].major;
- if( yymx==YYERRORSYMBOL || yyerrorhit ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sDiscard input token %s\n",
- yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
- yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
- yymajor = YYNOCODE;
- }else{
- while(
- yypParser->yyidx >= 0 &&
- yymx != YYERRORSYMBOL &&
- (yyact = yy_find_reduce_action(
- yypParser->yystack[yypParser->yyidx].stateno,
- YYERRORSYMBOL)) >= YYNSTATE
- ){
- yy_pop_parser_stack(yypParser);
- }
- if( yypParser->yyidx < 0 || yymajor==0 ){
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- yy_parse_failed(yypParser);
- yymajor = YYNOCODE;
- }else if( yymx!=YYERRORSYMBOL ){
- YYMINORTYPE u2;
- u2.YYERRSYMDT = 0;
- yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
- }
- }
- yypParser->yyerrcnt = 3;
- yyerrorhit = 1;
-#elif defined(YYNOERRORRECOVERY)
- /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
- ** do any kind of error recovery. Instead, simply invoke the syntax
- ** error routine and continue going as if nothing had happened.
- **
- ** Applications can set this macro (for example inside %include) if
- ** they intend to abandon the parse upon the first syntax error seen.
- */
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- yymajor = YYNOCODE;
-
-#else /* YYERRORSYMBOL is not defined */
- /* This is what we do if the grammar does not define ERROR:
- **
- ** * Report an error message, and throw away the input token.
- **
- ** * If the input token is $, then fail the parse.
- **
- ** As before, subsequent error messages are suppressed until
- ** three input tokens have been successfully shifted.
- */
- if( yypParser->yyerrcnt<=0 ){
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- }
- yypParser->yyerrcnt = 3;
- yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
- if( yyendofinput ){
- yy_parse_failed(yypParser);
- }
- yymajor = YYNOCODE;
-#endif
- }
- }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
- return;
-}
diff --git a/ext/sqlite/libsqlite/src/parse.h b/ext/sqlite/libsqlite/src/parse.h
deleted file mode 100644
index 188a336c8d..0000000000
--- a/ext/sqlite/libsqlite/src/parse.h
+++ /dev/null
@@ -1,130 +0,0 @@
-#define TK_END_OF_FILE 1
-#define TK_ILLEGAL 2
-#define TK_SPACE 3
-#define TK_UNCLOSED_STRING 4
-#define TK_COMMENT 5
-#define TK_FUNCTION 6
-#define TK_COLUMN 7
-#define TK_AGG_FUNCTION 8
-#define TK_SEMI 9
-#define TK_EXPLAIN 10
-#define TK_BEGIN 11
-#define TK_TRANSACTION 12
-#define TK_COMMIT 13
-#define TK_END 14
-#define TK_ROLLBACK 15
-#define TK_CREATE 16
-#define TK_TABLE 17
-#define TK_TEMP 18
-#define TK_LP 19
-#define TK_RP 20
-#define TK_AS 21
-#define TK_COMMA 22
-#define TK_ID 23
-#define TK_ABORT 24
-#define TK_AFTER 25
-#define TK_ASC 26
-#define TK_ATTACH 27
-#define TK_BEFORE 28
-#define TK_CASCADE 29
-#define TK_CLUSTER 30
-#define TK_CONFLICT 31
-#define TK_COPY 32
-#define TK_DATABASE 33
-#define TK_DEFERRED 34
-#define TK_DELIMITERS 35
-#define TK_DESC 36
-#define TK_DETACH 37
-#define TK_EACH 38
-#define TK_FAIL 39
-#define TK_FOR 40
-#define TK_GLOB 41
-#define TK_IGNORE 42
-#define TK_IMMEDIATE 43
-#define TK_INITIALLY 44
-#define TK_INSTEAD 45
-#define TK_LIKE 46
-#define TK_MATCH 47
-#define TK_KEY 48
-#define TK_OF 49
-#define TK_OFFSET 50
-#define TK_PRAGMA 51
-#define TK_RAISE 52
-#define TK_REPLACE 53
-#define TK_RESTRICT 54
-#define TK_ROW 55
-#define TK_STATEMENT 56
-#define TK_TRIGGER 57
-#define TK_VACUUM 58
-#define TK_VIEW 59
-#define TK_OR 60
-#define TK_AND 61
-#define TK_NOT 62
-#define TK_EQ 63
-#define TK_NE 64
-#define TK_ISNULL 65
-#define TK_NOTNULL 66
-#define TK_IS 67
-#define TK_BETWEEN 68
-#define TK_IN 69
-#define TK_GT 70
-#define TK_GE 71
-#define TK_LT 72
-#define TK_LE 73
-#define TK_BITAND 74
-#define TK_BITOR 75
-#define TK_LSHIFT 76
-#define TK_RSHIFT 77
-#define TK_PLUS 78
-#define TK_MINUS 79
-#define TK_STAR 80
-#define TK_SLASH 81
-#define TK_REM 82
-#define TK_CONCAT 83
-#define TK_UMINUS 84
-#define TK_UPLUS 85
-#define TK_BITNOT 86
-#define TK_STRING 87
-#define TK_JOIN_KW 88
-#define TK_INTEGER 89
-#define TK_CONSTRAINT 90
-#define TK_DEFAULT 91
-#define TK_FLOAT 92
-#define TK_NULL 93
-#define TK_PRIMARY 94
-#define TK_UNIQUE 95
-#define TK_CHECK 96
-#define TK_REFERENCES 97
-#define TK_COLLATE 98
-#define TK_ON 99
-#define TK_DELETE 100
-#define TK_UPDATE 101
-#define TK_INSERT 102
-#define TK_SET 103
-#define TK_DEFERRABLE 104
-#define TK_FOREIGN 105
-#define TK_DROP 106
-#define TK_UNION 107
-#define TK_ALL 108
-#define TK_INTERSECT 109
-#define TK_EXCEPT 110
-#define TK_SELECT 111
-#define TK_DISTINCT 112
-#define TK_DOT 113
-#define TK_FROM 114
-#define TK_JOIN 115
-#define TK_USING 116
-#define TK_ORDER 117
-#define TK_BY 118
-#define TK_GROUP 119
-#define TK_HAVING 120
-#define TK_LIMIT 121
-#define TK_WHERE 122
-#define TK_INTO 123
-#define TK_VALUES 124
-#define TK_VARIABLE 125
-#define TK_CASE 126
-#define TK_WHEN 127
-#define TK_THEN 128
-#define TK_ELSE 129
-#define TK_INDEX 130
diff --git a/ext/sqlite/libsqlite/src/parse.y b/ext/sqlite/libsqlite/src/parse.y
deleted file mode 100644
index cc236a5df8..0000000000
--- a/ext/sqlite/libsqlite/src/parse.y
+++ /dev/null
@@ -1,897 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains SQLite's grammar for SQL. Process this file
-** using the lemon parser generator to generate C code that runs
-** the parser. Lemon will also generate a header file containing
-** numeric codes for all of the tokens.
-**
-** @(#) $Id$
-*/
-%token_prefix TK_
-%token_type {Token}
-%default_type {Token}
-%extra_argument {Parse *pParse}
-%syntax_error {
- if( pParse->zErrMsg==0 ){
- if( TOKEN.z[0] ){
- sqliteErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
- }else{
- sqliteErrorMsg(pParse, "incomplete SQL statement");
- }
- }
-}
-%name sqliteParser
-%include {
-#include "sqliteInt.h"
-#include "parse.h"
-
-/*
-** An instance of this structure holds information about the
-** LIMIT clause of a SELECT statement.
-*/
-struct LimitVal {
- int limit; /* The LIMIT value. -1 if there is no limit */
- int offset; /* The OFFSET. 0 if there is none */
-};
-
-/*
-** An instance of the following structure describes the event of a
-** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
-** TK_DELETE, or TK_INSTEAD. If the event is of the form
-**
-** UPDATE ON (a,b,c)
-**
-** Then the "b" IdList records the list "a,b,c".
-*/
-struct TrigEvent { int a; IdList * b; };
-
-} // end %include
-
-// These are extra tokens used by the lexer but never seen by the
-// parser. We put them in a rule so that the parser generator will
-// add them to the parse.h output file.
-//
-%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
- COLUMN AGG_FUNCTION.
-
-// Input is a single SQL command
-input ::= cmdlist.
-cmdlist ::= cmdlist ecmd.
-cmdlist ::= ecmd.
-ecmd ::= explain cmdx SEMI.
-ecmd ::= SEMI.
-cmdx ::= cmd. { sqliteExec(pParse); }
-explain ::= EXPLAIN. { sqliteBeginParse(pParse, 1); }
-explain ::= . { sqliteBeginParse(pParse, 0); }
-
-///////////////////// Begin and end transactions. ////////////////////////////
-//
-
-cmd ::= BEGIN trans_opt onconf(R). {sqliteBeginTransaction(pParse,R);}
-trans_opt ::= .
-trans_opt ::= TRANSACTION.
-trans_opt ::= TRANSACTION nm.
-cmd ::= COMMIT trans_opt. {sqliteCommitTransaction(pParse);}
-cmd ::= END trans_opt. {sqliteCommitTransaction(pParse);}
-cmd ::= ROLLBACK trans_opt. {sqliteRollbackTransaction(pParse);}
-
-///////////////////// The CREATE TABLE statement ////////////////////////////
-//
-cmd ::= create_table create_table_args.
-create_table ::= CREATE(X) temp(T) TABLE nm(Y). {
- sqliteStartTable(pParse,&X,&Y,T,0);
-}
-%type temp {int}
-temp(A) ::= TEMP. {A = 1;}
-temp(A) ::= . {A = 0;}
-create_table_args ::= LP columnlist conslist_opt RP(X). {
- sqliteEndTable(pParse,&X,0);
-}
-create_table_args ::= AS select(S). {
- sqliteEndTable(pParse,0,S);
- sqliteSelectDelete(S);
-}
-columnlist ::= columnlist COMMA column.
-columnlist ::= column.
-
-// About the only information used for a column is the name of the
-// column. The type is always just "text". But the code will accept
-// an elaborate typename. Perhaps someday we'll do something with it.
-//
-column ::= columnid type carglist.
-columnid ::= nm(X). {sqliteAddColumn(pParse,&X);}
-
-// An IDENTIFIER can be a generic identifier, or one of several
-// keywords. Any non-standard keyword can also be an identifier.
-//
-%type id {Token}
-id(A) ::= ID(X). {A = X;}
-
-// The following directive causes tokens ABORT, AFTER, ASC, etc. to
-// fallback to ID if they will not parse as their original value.
-// This obviates the need for the "id" nonterminal.
-//
-%fallback ID
- ABORT AFTER ASC ATTACH BEFORE BEGIN CASCADE CLUSTER CONFLICT
- COPY DATABASE DEFERRED DELIMITERS DESC DETACH EACH END EXPLAIN FAIL FOR
- GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY
- OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
- TEMP TRIGGER VACUUM VIEW.
-
-// Define operator precedence early so that this is the first occurance
-// of the operator tokens in the grammer. Keeping the operators together
-// causes them to be assigned integer values that are close together,
-// which keeps parser tables smaller.
-//
-%left OR.
-%left AND.
-%right NOT.
-%left EQ NE ISNULL NOTNULL IS LIKE GLOB BETWEEN IN.
-%left GT GE LT LE.
-%left BITAND BITOR LSHIFT RSHIFT.
-%left PLUS MINUS.
-%left STAR SLASH REM.
-%left CONCAT.
-%right UMINUS UPLUS BITNOT.
-
-// And "ids" is an identifer-or-string.
-//
-%type ids {Token}
-ids(A) ::= ID(X). {A = X;}
-ids(A) ::= STRING(X). {A = X;}
-
-// The name of a column or table can be any of the following:
-//
-%type nm {Token}
-nm(A) ::= ID(X). {A = X;}
-nm(A) ::= STRING(X). {A = X;}
-nm(A) ::= JOIN_KW(X). {A = X;}
-
-type ::= .
-type ::= typename(X). {sqliteAddColumnType(pParse,&X,&X);}
-type ::= typename(X) LP signed RP(Y). {sqliteAddColumnType(pParse,&X,&Y);}
-type ::= typename(X) LP signed COMMA signed RP(Y).
- {sqliteAddColumnType(pParse,&X,&Y);}
-%type typename {Token}
-typename(A) ::= ids(X). {A = X;}
-typename(A) ::= typename(X) ids. {A = X;}
-%type signed {int}
-signed(A) ::= INTEGER(X). { A = atoi(X.z); }
-signed(A) ::= PLUS INTEGER(X). { A = atoi(X.z); }
-signed(A) ::= MINUS INTEGER(X). { A = -atoi(X.z); }
-carglist ::= carglist carg.
-carglist ::= .
-carg ::= CONSTRAINT nm ccons.
-carg ::= ccons.
-carg ::= DEFAULT STRING(X). {sqliteAddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT ID(X). {sqliteAddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT INTEGER(X). {sqliteAddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT PLUS INTEGER(X). {sqliteAddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT MINUS INTEGER(X). {sqliteAddDefaultValue(pParse,&X,1);}
-carg ::= DEFAULT FLOAT(X). {sqliteAddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT PLUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,0);}
-carg ::= DEFAULT MINUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,1);}
-carg ::= DEFAULT NULL.
-
-// In addition to the type name, we also care about the primary key and
-// UNIQUE constraints.
-//
-ccons ::= NULL onconf.
-ccons ::= NOT NULL onconf(R). {sqliteAddNotNull(pParse, R);}
-ccons ::= PRIMARY KEY sortorder onconf(R). {sqliteAddPrimaryKey(pParse,0,R);}
-ccons ::= UNIQUE onconf(R). {sqliteCreateIndex(pParse,0,0,0,R,0,0);}
-ccons ::= CHECK LP expr RP onconf.
-ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
- {sqliteCreateForeignKey(pParse,0,&T,TA,R);}
-ccons ::= defer_subclause(D). {sqliteDeferForeignKey(pParse,D);}
-ccons ::= COLLATE id(C). {
- sqliteAddCollateType(pParse, sqliteCollateType(C.z, C.n));
-}
-
-// The next group of rules parses the arguments to a REFERENCES clause
-// that determine if the referential integrity checking is deferred or
-// or immediate and which determine what action to take if a ref-integ
-// check fails.
-//
-%type refargs {int}
-refargs(A) ::= . { A = OE_Restrict * 0x010101; }
-refargs(A) ::= refargs(X) refarg(Y). { A = (X & Y.mask) | Y.value; }
-%type refarg {struct {int value; int mask;}}
-refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; }
-refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; }
-refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; }
-refarg(A) ::= ON INSERT refact(X). { A.value = X<<16; A.mask = 0xff0000; }
-%type refact {int}
-refact(A) ::= SET NULL. { A = OE_SetNull; }
-refact(A) ::= SET DEFAULT. { A = OE_SetDflt; }
-refact(A) ::= CASCADE. { A = OE_Cascade; }
-refact(A) ::= RESTRICT. { A = OE_Restrict; }
-%type defer_subclause {int}
-defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt(X). {A = X;}
-defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X). {A = X;}
-%type init_deferred_pred_opt {int}
-init_deferred_pred_opt(A) ::= . {A = 0;}
-init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;}
-init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;}
-
-// For the time being, the only constraint we care about is the primary
-// key and UNIQUE. Both create indices.
-//
-conslist_opt ::= .
-conslist_opt ::= COMMA conslist.
-conslist ::= conslist COMMA tcons.
-conslist ::= conslist tcons.
-conslist ::= tcons.
-tcons ::= CONSTRAINT nm.
-tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
- {sqliteAddPrimaryKey(pParse,X,R);}
-tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
- {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
-tcons ::= CHECK expr onconf.
-tcons ::= FOREIGN KEY LP idxlist(FA) RP
- REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
- sqliteCreateForeignKey(pParse, FA, &T, TA, R);
- sqliteDeferForeignKey(pParse, D);
-}
-%type defer_subclause_opt {int}
-defer_subclause_opt(A) ::= . {A = 0;}
-defer_subclause_opt(A) ::= defer_subclause(X). {A = X;}
-
-// The following is a non-standard extension that allows us to declare the
-// default behavior when there is a constraint conflict.
-//
-%type onconf {int}
-%type orconf {int}
-%type resolvetype {int}
-onconf(A) ::= . { A = OE_Default; }
-onconf(A) ::= ON CONFLICT resolvetype(X). { A = X; }
-orconf(A) ::= . { A = OE_Default; }
-orconf(A) ::= OR resolvetype(X). { A = X; }
-resolvetype(A) ::= ROLLBACK. { A = OE_Rollback; }
-resolvetype(A) ::= ABORT. { A = OE_Abort; }
-resolvetype(A) ::= FAIL. { A = OE_Fail; }
-resolvetype(A) ::= IGNORE. { A = OE_Ignore; }
-resolvetype(A) ::= REPLACE. { A = OE_Replace; }
-
-////////////////////////// The DROP TABLE /////////////////////////////////////
-//
-cmd ::= DROP TABLE nm(X). {sqliteDropTable(pParse,&X,0);}
-
-///////////////////// The CREATE VIEW statement /////////////////////////////
-//
-cmd ::= CREATE(X) temp(T) VIEW nm(Y) AS select(S). {
- sqliteCreateView(pParse, &X, &Y, S, T);
-}
-cmd ::= DROP VIEW nm(X). {
- sqliteDropTable(pParse, &X, 1);
-}
-
-//////////////////////// The SELECT statement /////////////////////////////////
-//
-cmd ::= select(X). {
- sqliteSelect(pParse, X, SRT_Callback, 0, 0, 0, 0);
- sqliteSelectDelete(X);
-}
-
-%type select {Select*}
-%destructor select {sqliteSelectDelete($$);}
-%type oneselect {Select*}
-%destructor oneselect {sqliteSelectDelete($$);}
-
-select(A) ::= oneselect(X). {A = X;}
-select(A) ::= select(X) multiselect_op(Y) oneselect(Z). {
- if( Z ){
- Z->op = Y;
- Z->pPrior = X;
- }
- A = Z;
-}
-%type multiselect_op {int}
-multiselect_op(A) ::= UNION. {A = TK_UNION;}
-multiselect_op(A) ::= UNION ALL. {A = TK_ALL;}
-multiselect_op(A) ::= INTERSECT. {A = TK_INTERSECT;}
-multiselect_op(A) ::= EXCEPT. {A = TK_EXCEPT;}
-oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
- groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
- A = sqliteSelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset);
-}
-
-// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
-// present and false (0) if it is not.
-//
-%type distinct {int}
-distinct(A) ::= DISTINCT. {A = 1;}
-distinct(A) ::= ALL. {A = 0;}
-distinct(A) ::= . {A = 0;}
-
-// selcollist is a list of expressions that are to become the return
-// values of the SELECT statement. The "*" in statements like
-// "SELECT * FROM ..." is encoded as a special expression with an
-// opcode of TK_ALL.
-//
-%type selcollist {ExprList*}
-%destructor selcollist {sqliteExprListDelete($$);}
-%type sclp {ExprList*}
-%destructor sclp {sqliteExprListDelete($$);}
-sclp(A) ::= selcollist(X) COMMA. {A = X;}
-sclp(A) ::= . {A = 0;}
-selcollist(A) ::= sclp(P) expr(X) as(Y). {
- A = sqliteExprListAppend(P,X,Y.n?&Y:0);
-}
-selcollist(A) ::= sclp(P) STAR. {
- A = sqliteExprListAppend(P, sqliteExpr(TK_ALL, 0, 0, 0), 0);
-}
-selcollist(A) ::= sclp(P) nm(X) DOT STAR. {
- Expr *pRight = sqliteExpr(TK_ALL, 0, 0, 0);
- Expr *pLeft = sqliteExpr(TK_ID, 0, 0, &X);
- A = sqliteExprListAppend(P, sqliteExpr(TK_DOT, pLeft, pRight, 0), 0);
-}
-
-// An option "AS <id>" phrase that can follow one of the expressions that
-// define the result set, or one of the tables in the FROM clause.
-//
-%type as {Token}
-as(X) ::= AS nm(Y). { X = Y; }
-as(X) ::= ids(Y). { X = Y; }
-as(X) ::= . { X.n = 0; }
-
-
-%type seltablist {SrcList*}
-%destructor seltablist {sqliteSrcListDelete($$);}
-%type stl_prefix {SrcList*}
-%destructor stl_prefix {sqliteSrcListDelete($$);}
-%type from {SrcList*}
-%destructor from {sqliteSrcListDelete($$);}
-
-// A complete FROM clause.
-//
-from(A) ::= . {A = sqliteMalloc(sizeof(*A));}
-from(A) ::= FROM seltablist(X). {A = X;}
-
-// "seltablist" is a "Select Table List" - the content of the FROM clause
-// in a SELECT statement. "stl_prefix" is a prefix of this list.
-//
-stl_prefix(A) ::= seltablist(X) joinop(Y). {
- A = X;
- if( A && A->nSrc>0 ) A->a[A->nSrc-1].jointype = Y;
-}
-stl_prefix(A) ::= . {A = 0;}
-seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
- A = sqliteSrcListAppend(X,&Y,&D);
- if( Z.n ) sqliteSrcListAddAlias(A,&Z);
- if( N ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
- else { sqliteExprDelete(N); }
- }
- if( U ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
- else { sqliteIdListDelete(U); }
- }
-}
-seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
- as(Z) on_opt(N) using_opt(U). {
- A = sqliteSrcListAppend(X,0,0);
- A->a[A->nSrc-1].pSelect = S;
- if( Z.n ) sqliteSrcListAddAlias(A,&Z);
- if( N ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
- else { sqliteExprDelete(N); }
- }
- if( U ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
- else { sqliteIdListDelete(U); }
- }
-}
-
-// A seltablist_paren nonterminal represents anything in a FROM that
-// is contained inside parentheses. This can be either a subquery or
-// a grouping of table and subqueries.
-//
-%type seltablist_paren {Select*}
-%destructor seltablist_paren {sqliteSelectDelete($$);}
-seltablist_paren(A) ::= select(S). {A = S;}
-seltablist_paren(A) ::= seltablist(F). {
- A = sqliteSelectNew(0,F,0,0,0,0,0,-1,0);
-}
-
-%type dbnm {Token}
-dbnm(A) ::= . {A.z=0; A.n=0;}
-dbnm(A) ::= DOT nm(X). {A = X;}
-
-%type joinop {int}
-%type joinop2 {int}
-joinop(X) ::= COMMA. { X = JT_INNER; }
-joinop(X) ::= JOIN. { X = JT_INNER; }
-joinop(X) ::= JOIN_KW(A) JOIN. { X = sqliteJoinType(pParse,&A,0,0); }
-joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqliteJoinType(pParse,&A,&B,0); }
-joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
- { X = sqliteJoinType(pParse,&A,&B,&C); }
-
-%type on_opt {Expr*}
-%destructor on_opt {sqliteExprDelete($$);}
-on_opt(N) ::= ON expr(E). {N = E;}
-on_opt(N) ::= . {N = 0;}
-
-%type using_opt {IdList*}
-%destructor using_opt {sqliteIdListDelete($$);}
-using_opt(U) ::= USING LP idxlist(L) RP. {U = L;}
-using_opt(U) ::= . {U = 0;}
-
-
-%type orderby_opt {ExprList*}
-%destructor orderby_opt {sqliteExprListDelete($$);}
-%type sortlist {ExprList*}
-%destructor sortlist {sqliteExprListDelete($$);}
-%type sortitem {Expr*}
-%destructor sortitem {sqliteExprDelete($$);}
-
-orderby_opt(A) ::= . {A = 0;}
-orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;}
-sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). {
- A = sqliteExprListAppend(X,Y,0);
- if( A ) A->a[A->nExpr-1].sortOrder = C+Z;
-}
-sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). {
- A = sqliteExprListAppend(0,Y,0);
- if( A ) A->a[0].sortOrder = C+Z;
-}
-sortitem(A) ::= expr(X). {A = X;}
-
-%type sortorder {int}
-%type collate {int}
-
-sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
-sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
-sortorder(A) ::= . {A = SQLITE_SO_ASC;}
-collate(C) ::= . {C = SQLITE_SO_UNK;}
-collate(C) ::= COLLATE id(X). {C = sqliteCollateType(X.z, X.n);}
-
-%type groupby_opt {ExprList*}
-%destructor groupby_opt {sqliteExprListDelete($$);}
-groupby_opt(A) ::= . {A = 0;}
-groupby_opt(A) ::= GROUP BY exprlist(X). {A = X;}
-
-%type having_opt {Expr*}
-%destructor having_opt {sqliteExprDelete($$);}
-having_opt(A) ::= . {A = 0;}
-having_opt(A) ::= HAVING expr(X). {A = X;}
-
-%type limit_opt {struct LimitVal}
-limit_opt(A) ::= . {A.limit = -1; A.offset = 0;}
-limit_opt(A) ::= LIMIT signed(X). {A.limit = X; A.offset = 0;}
-limit_opt(A) ::= LIMIT signed(X) OFFSET signed(Y).
- {A.limit = X; A.offset = Y;}
-limit_opt(A) ::= LIMIT signed(X) COMMA signed(Y).
- {A.limit = Y; A.offset = X;}
-
-/////////////////////////// The DELETE statement /////////////////////////////
-//
-cmd ::= DELETE FROM nm(X) dbnm(D) where_opt(Y). {
- sqliteDeleteFrom(pParse, sqliteSrcListAppend(0,&X,&D), Y);
-}
-
-%type where_opt {Expr*}
-%destructor where_opt {sqliteExprDelete($$);}
-
-where_opt(A) ::= . {A = 0;}
-where_opt(A) ::= WHERE expr(X). {A = X;}
-
-%type setlist {ExprList*}
-%destructor setlist {sqliteExprListDelete($$);}
-
-////////////////////////// The UPDATE command ////////////////////////////////
-//
-cmd ::= UPDATE orconf(R) nm(X) dbnm(D) SET setlist(Y) where_opt(Z).
- {sqliteUpdate(pParse,sqliteSrcListAppend(0,&X,&D),Y,Z,R);}
-
-setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y).
- {A = sqliteExprListAppend(Z,Y,&X);}
-setlist(A) ::= nm(X) EQ expr(Y). {A = sqliteExprListAppend(0,Y,&X);}
-
-////////////////////////// The INSERT command /////////////////////////////////
-//
-cmd ::= insert_cmd(R) INTO nm(X) dbnm(D) inscollist_opt(F)
- VALUES LP itemlist(Y) RP.
- {sqliteInsert(pParse, sqliteSrcListAppend(0,&X,&D), Y, 0, F, R);}
-cmd ::= insert_cmd(R) INTO nm(X) dbnm(D) inscollist_opt(F) select(S).
- {sqliteInsert(pParse, sqliteSrcListAppend(0,&X,&D), 0, S, F, R);}
-
-%type insert_cmd {int}
-insert_cmd(A) ::= INSERT orconf(R). {A = R;}
-insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
-
-
-%type itemlist {ExprList*}
-%destructor itemlist {sqliteExprListDelete($$);}
-
-itemlist(A) ::= itemlist(X) COMMA expr(Y). {A = sqliteExprListAppend(X,Y,0);}
-itemlist(A) ::= expr(X). {A = sqliteExprListAppend(0,X,0);}
-
-%type inscollist_opt {IdList*}
-%destructor inscollist_opt {sqliteIdListDelete($$);}
-%type inscollist {IdList*}
-%destructor inscollist {sqliteIdListDelete($$);}
-
-inscollist_opt(A) ::= . {A = 0;}
-inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;}
-inscollist(A) ::= inscollist(X) COMMA nm(Y). {A = sqliteIdListAppend(X,&Y);}
-inscollist(A) ::= nm(Y). {A = sqliteIdListAppend(0,&Y);}
-
-/////////////////////////// Expression Processing /////////////////////////////
-//
-
-%type expr {Expr*}
-%destructor expr {sqliteExprDelete($$);}
-
-expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqliteExprSpan(A,&B,&E); }
-expr(A) ::= NULL(X). {A = sqliteExpr(TK_NULL, 0, 0, &X);}
-expr(A) ::= ID(X). {A = sqliteExpr(TK_ID, 0, 0, &X);}
-expr(A) ::= JOIN_KW(X). {A = sqliteExpr(TK_ID, 0, 0, &X);}
-expr(A) ::= nm(X) DOT nm(Y). {
- Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &X);
- Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &Y);
- A = sqliteExpr(TK_DOT, temp1, temp2, 0);
-}
-expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
- Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &X);
- Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &Y);
- Expr *temp3 = sqliteExpr(TK_ID, 0, 0, &Z);
- Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0);
- A = sqliteExpr(TK_DOT, temp1, temp4, 0);
-}
-expr(A) ::= INTEGER(X). {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
-expr(A) ::= FLOAT(X). {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
-expr(A) ::= STRING(X). {A = sqliteExpr(TK_STRING, 0, 0, &X);}
-expr(A) ::= VARIABLE(X). {
- A = sqliteExpr(TK_VARIABLE, 0, 0, &X);
- if( A ) A->iTable = ++pParse->nVar;
-}
-expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
- A = sqliteExprFunction(Y, &X);
- sqliteExprSpan(A,&X,&E);
-}
-expr(A) ::= ID(X) LP STAR RP(E). {
- A = sqliteExprFunction(0, &X);
- sqliteExprSpan(A,&X,&E);
-}
-expr(A) ::= expr(X) AND expr(Y). {A = sqliteExpr(TK_AND, X, Y, 0);}
-expr(A) ::= expr(X) OR expr(Y). {A = sqliteExpr(TK_OR, X, Y, 0);}
-expr(A) ::= expr(X) LT expr(Y). {A = sqliteExpr(TK_LT, X, Y, 0);}
-expr(A) ::= expr(X) GT expr(Y). {A = sqliteExpr(TK_GT, X, Y, 0);}
-expr(A) ::= expr(X) LE expr(Y). {A = sqliteExpr(TK_LE, X, Y, 0);}
-expr(A) ::= expr(X) GE expr(Y). {A = sqliteExpr(TK_GE, X, Y, 0);}
-expr(A) ::= expr(X) NE expr(Y). {A = sqliteExpr(TK_NE, X, Y, 0);}
-expr(A) ::= expr(X) EQ expr(Y). {A = sqliteExpr(TK_EQ, X, Y, 0);}
-expr(A) ::= expr(X) BITAND expr(Y). {A = sqliteExpr(TK_BITAND, X, Y, 0);}
-expr(A) ::= expr(X) BITOR expr(Y). {A = sqliteExpr(TK_BITOR, X, Y, 0);}
-expr(A) ::= expr(X) LSHIFT expr(Y). {A = sqliteExpr(TK_LSHIFT, X, Y, 0);}
-expr(A) ::= expr(X) RSHIFT expr(Y). {A = sqliteExpr(TK_RSHIFT, X, Y, 0);}
-expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE] {
- ExprList *pList = sqliteExprListAppend(0, Y, 0);
- pList = sqliteExprListAppend(pList, X, 0);
- A = sqliteExprFunction(pList, 0);
- if( A ) A->op = OP;
- sqliteExprSpan(A, &X->span, &Y->span);
-}
-expr(A) ::= expr(X) NOT likeop(OP) expr(Y). [LIKE] {
- ExprList *pList = sqliteExprListAppend(0, Y, 0);
- pList = sqliteExprListAppend(pList, X, 0);
- A = sqliteExprFunction(pList, 0);
- if( A ) A->op = OP;
- A = sqliteExpr(TK_NOT, A, 0, 0);
- sqliteExprSpan(A,&X->span,&Y->span);
-}
-%type likeop {int}
-likeop(A) ::= LIKE. {A = TK_LIKE;}
-likeop(A) ::= GLOB. {A = TK_GLOB;}
-expr(A) ::= expr(X) PLUS expr(Y). {A = sqliteExpr(TK_PLUS, X, Y, 0);}
-expr(A) ::= expr(X) MINUS expr(Y). {A = sqliteExpr(TK_MINUS, X, Y, 0);}
-expr(A) ::= expr(X) STAR expr(Y). {A = sqliteExpr(TK_STAR, X, Y, 0);}
-expr(A) ::= expr(X) SLASH expr(Y). {A = sqliteExpr(TK_SLASH, X, Y, 0);}
-expr(A) ::= expr(X) REM expr(Y). {A = sqliteExpr(TK_REM, X, Y, 0);}
-expr(A) ::= expr(X) CONCAT expr(Y). {A = sqliteExpr(TK_CONCAT, X, Y, 0);}
-expr(A) ::= expr(X) ISNULL(E). {
- A = sqliteExpr(TK_ISNULL, X, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) IS NULL(E). {
- A = sqliteExpr(TK_ISNULL, X, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) NOTNULL(E). {
- A = sqliteExpr(TK_NOTNULL, X, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) NOT NULL(E). {
- A = sqliteExpr(TK_NOTNULL, X, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) IS NOT NULL(E). {
- A = sqliteExpr(TK_NOTNULL, X, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= NOT(B) expr(X). {
- A = sqliteExpr(TK_NOT, X, 0, 0);
- sqliteExprSpan(A,&B,&X->span);
-}
-expr(A) ::= BITNOT(B) expr(X). {
- A = sqliteExpr(TK_BITNOT, X, 0, 0);
- sqliteExprSpan(A,&B,&X->span);
-}
-expr(A) ::= MINUS(B) expr(X). [UMINUS] {
- A = sqliteExpr(TK_UMINUS, X, 0, 0);
- sqliteExprSpan(A,&B,&X->span);
-}
-expr(A) ::= PLUS(B) expr(X). [UPLUS] {
- A = sqliteExpr(TK_UPLUS, X, 0, 0);
- sqliteExprSpan(A,&B,&X->span);
-}
-expr(A) ::= LP(B) select(X) RP(E). {
- A = sqliteExpr(TK_SELECT, 0, 0, 0);
- if( A ) A->pSelect = X;
- sqliteExprSpan(A,&B,&E);
-}
-expr(A) ::= expr(W) BETWEEN expr(X) AND expr(Y). {
- ExprList *pList = sqliteExprListAppend(0, X, 0);
- pList = sqliteExprListAppend(pList, Y, 0);
- A = sqliteExpr(TK_BETWEEN, W, 0, 0);
- if( A ) A->pList = pList;
- sqliteExprSpan(A,&W->span,&Y->span);
-}
-expr(A) ::= expr(W) NOT BETWEEN expr(X) AND expr(Y). {
- ExprList *pList = sqliteExprListAppend(0, X, 0);
- pList = sqliteExprListAppend(pList, Y, 0);
- A = sqliteExpr(TK_BETWEEN, W, 0, 0);
- if( A ) A->pList = pList;
- A = sqliteExpr(TK_NOT, A, 0, 0);
- sqliteExprSpan(A,&W->span,&Y->span);
-}
-expr(A) ::= expr(X) IN LP exprlist(Y) RP(E). {
- A = sqliteExpr(TK_IN, X, 0, 0);
- if( A ) A->pList = Y;
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) IN LP select(Y) RP(E). {
- A = sqliteExpr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = Y;
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) NOT IN LP exprlist(Y) RP(E). {
- A = sqliteExpr(TK_IN, X, 0, 0);
- if( A ) A->pList = Y;
- A = sqliteExpr(TK_NOT, A, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) NOT IN LP select(Y) RP(E). {
- A = sqliteExpr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = Y;
- A = sqliteExpr(TK_NOT, A, 0, 0);
- sqliteExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) IN nm(Y) dbnm(D). {
- SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
- A = sqliteExpr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
- sqliteExprSpan(A,&X->span,D.z?&D:&Y);
-}
-expr(A) ::= expr(X) NOT IN nm(Y) dbnm(D). {
- SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
- A = sqliteExpr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
- A = sqliteExpr(TK_NOT, A, 0, 0);
- sqliteExprSpan(A,&X->span,D.z?&D:&Y);
-}
-
-
-/* CASE expressions */
-expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
- A = sqliteExpr(TK_CASE, X, Z, 0);
- if( A ) A->pList = Y;
- sqliteExprSpan(A, &C, &E);
-}
-%type case_exprlist {ExprList*}
-%destructor case_exprlist {sqliteExprListDelete($$);}
-case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
- A = sqliteExprListAppend(X, Y, 0);
- A = sqliteExprListAppend(A, Z, 0);
-}
-case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
- A = sqliteExprListAppend(0, Y, 0);
- A = sqliteExprListAppend(A, Z, 0);
-}
-%type case_else {Expr*}
-case_else(A) ::= ELSE expr(X). {A = X;}
-case_else(A) ::= . {A = 0;}
-%type case_operand {Expr*}
-case_operand(A) ::= expr(X). {A = X;}
-case_operand(A) ::= . {A = 0;}
-
-%type exprlist {ExprList*}
-%destructor exprlist {sqliteExprListDelete($$);}
-%type expritem {Expr*}
-%destructor expritem {sqliteExprDelete($$);}
-
-exprlist(A) ::= exprlist(X) COMMA expritem(Y).
- {A = sqliteExprListAppend(X,Y,0);}
-exprlist(A) ::= expritem(X). {A = sqliteExprListAppend(0,X,0);}
-expritem(A) ::= expr(X). {A = X;}
-expritem(A) ::= . {A = 0;}
-
-///////////////////////////// The CREATE INDEX command ///////////////////////
-//
-cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X)
- ON nm(Y) dbnm(D) LP idxlist(Z) RP(E) onconf(R). {
- SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
- if( U!=OE_None ) U = R;
- if( U==OE_Default) U = OE_Abort;
- sqliteCreateIndex(pParse, &X, pSrc, Z, U, &S, &E);
-}
-
-%type uniqueflag {int}
-uniqueflag(A) ::= UNIQUE. { A = OE_Abort; }
-uniqueflag(A) ::= . { A = OE_None; }
-
-%type idxlist {IdList*}
-%destructor idxlist {sqliteIdListDelete($$);}
-%type idxlist_opt {IdList*}
-%destructor idxlist_opt {sqliteIdListDelete($$);}
-%type idxitem {Token}
-
-idxlist_opt(A) ::= . {A = 0;}
-idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;}
-idxlist(A) ::= idxlist(X) COMMA idxitem(Y). {A = sqliteIdListAppend(X,&Y);}
-idxlist(A) ::= idxitem(Y). {A = sqliteIdListAppend(0,&Y);}
-idxitem(A) ::= nm(X) sortorder. {A = X;}
-
-///////////////////////////// The DROP INDEX command /////////////////////////
-//
-
-cmd ::= DROP INDEX nm(X) dbnm(Y). {
- sqliteDropIndex(pParse, sqliteSrcListAppend(0,&X,&Y));
-}
-
-
-///////////////////////////// The COPY command ///////////////////////////////
-//
-cmd ::= COPY orconf(R) nm(X) dbnm(D) FROM nm(Y) USING DELIMITERS STRING(Z).
- {sqliteCopy(pParse,sqliteSrcListAppend(0,&X,&D),&Y,&Z,R);}
-cmd ::= COPY orconf(R) nm(X) dbnm(D) FROM nm(Y).
- {sqliteCopy(pParse,sqliteSrcListAppend(0,&X,&D),&Y,0,R);}
-
-///////////////////////////// The VACUUM command /////////////////////////////
-//
-cmd ::= VACUUM. {sqliteVacuum(pParse,0);}
-cmd ::= VACUUM nm(X). {sqliteVacuum(pParse,&X);}
-
-///////////////////////////// The PRAGMA command /////////////////////////////
-//
-cmd ::= PRAGMA ids(X) EQ nm(Y). {sqlitePragma(pParse,&X,&Y,0);}
-cmd ::= PRAGMA ids(X) EQ ON(Y). {sqlitePragma(pParse,&X,&Y,0);}
-cmd ::= PRAGMA ids(X) EQ plus_num(Y). {sqlitePragma(pParse,&X,&Y,0);}
-cmd ::= PRAGMA ids(X) EQ minus_num(Y). {sqlitePragma(pParse,&X,&Y,1);}
-cmd ::= PRAGMA ids(X) LP nm(Y) RP. {sqlitePragma(pParse,&X,&Y,0);}
-cmd ::= PRAGMA ids(X). {sqlitePragma(pParse,&X,&X,0);}
-plus_num(A) ::= plus_opt number(X). {A = X;}
-minus_num(A) ::= MINUS number(X). {A = X;}
-number(A) ::= INTEGER(X). {A = X;}
-number(A) ::= FLOAT(X). {A = X;}
-plus_opt ::= PLUS.
-plus_opt ::= .
-
-//////////////////////////// The CREATE TRIGGER command /////////////////////
-
-cmd ::= CREATE(A) trigger_decl BEGIN trigger_cmd_list(S) END(Z). {
- Token all;
- all.z = A.z;
- all.n = (Z.z - A.z) + Z.n;
- sqliteFinishTrigger(pParse, S, &all);
-}
-
-trigger_decl ::= temp(T) TRIGGER nm(B) trigger_time(C) trigger_event(D)
- ON nm(E) dbnm(DB) foreach_clause(F) when_clause(G). {
- SrcList *pTab = sqliteSrcListAppend(0, &E, &DB);
- sqliteBeginTrigger(pParse, &B, C, D.a, D.b, pTab, F, G, T);
-}
-
-%type trigger_time {int}
-trigger_time(A) ::= BEFORE. { A = TK_BEFORE; }
-trigger_time(A) ::= AFTER. { A = TK_AFTER; }
-trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;}
-trigger_time(A) ::= . { A = TK_BEFORE; }
-
-%type trigger_event {struct TrigEvent}
-%destructor trigger_event {sqliteIdListDelete($$.b);}
-trigger_event(A) ::= DELETE. { A.a = TK_DELETE; A.b = 0; }
-trigger_event(A) ::= INSERT. { A.a = TK_INSERT; A.b = 0; }
-trigger_event(A) ::= UPDATE. { A.a = TK_UPDATE; A.b = 0;}
-trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X; }
-
-%type foreach_clause {int}
-foreach_clause(A) ::= . { A = TK_ROW; }
-foreach_clause(A) ::= FOR EACH ROW. { A = TK_ROW; }
-foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; }
-
-%type when_clause {Expr *}
-when_clause(A) ::= . { A = 0; }
-when_clause(A) ::= WHEN expr(X). { A = X; }
-
-%type trigger_cmd_list {TriggerStep *}
-%destructor trigger_cmd_list {sqliteDeleteTriggerStep($$);}
-trigger_cmd_list(A) ::= trigger_cmd(X) SEMI trigger_cmd_list(Y). {
- X->pNext = Y;
- A = X;
-}
-trigger_cmd_list(A) ::= . { A = 0; }
-
-%type trigger_cmd {TriggerStep *}
-%destructor trigger_cmd {sqliteDeleteTriggerStep($$);}
-// UPDATE
-trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z).
- { A = sqliteTriggerUpdateStep(&X, Y, Z, R); }
-
-// INSERT
-trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F)
- VALUES LP itemlist(Y) RP.
-{A = sqliteTriggerInsertStep(&X, F, Y, 0, R);}
-
-trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) select(S).
- {A = sqliteTriggerInsertStep(&X, F, 0, S, R);}
-
-// DELETE
-trigger_cmd(A) ::= DELETE FROM nm(X) where_opt(Y).
- {A = sqliteTriggerDeleteStep(&X, Y);}
-
-// SELECT
-trigger_cmd(A) ::= select(X). {A = sqliteTriggerSelectStep(X); }
-
-// The special RAISE expression that may occur in trigger programs
-expr(A) ::= RAISE(X) LP IGNORE RP(Y). {
- A = sqliteExpr(TK_RAISE, 0, 0, 0);
- A->iColumn = OE_Ignore;
- sqliteExprSpan(A, &X, &Y);
-}
-expr(A) ::= RAISE(X) LP ROLLBACK COMMA nm(Z) RP(Y). {
- A = sqliteExpr(TK_RAISE, 0, 0, &Z);
- A->iColumn = OE_Rollback;
- sqliteExprSpan(A, &X, &Y);
-}
-expr(A) ::= RAISE(X) LP ABORT COMMA nm(Z) RP(Y). {
- A = sqliteExpr(TK_RAISE, 0, 0, &Z);
- A->iColumn = OE_Abort;
- sqliteExprSpan(A, &X, &Y);
-}
-expr(A) ::= RAISE(X) LP FAIL COMMA nm(Z) RP(Y). {
- A = sqliteExpr(TK_RAISE, 0, 0, &Z);
- A->iColumn = OE_Fail;
- sqliteExprSpan(A, &X, &Y);
-}
-
-//////////////////////// DROP TRIGGER statement //////////////////////////////
-cmd ::= DROP TRIGGER nm(X) dbnm(D). {
- sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D));
-}
-
-//////////////////////// ATTACH DATABASE file AS name /////////////////////////
-cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
- sqliteAttach(pParse, &F, &D, &K);
-}
-%type key_opt {Token}
-key_opt(A) ::= USING ids(X). { A = X; }
-key_opt(A) ::= . { A.z = 0; A.n = 0; }
-
-database_kw_opt ::= DATABASE.
-database_kw_opt ::= .
-
-//////////////////////// DETACH DATABASE name /////////////////////////////////
-cmd ::= DETACH database_kw_opt nm(D). {
- sqliteDetach(pParse, &D);
-}
diff --git a/ext/sqlite/libsqlite/src/pragma.c b/ext/sqlite/libsqlite/src/pragma.c
deleted file mode 100644
index 965dbb9da6..0000000000
--- a/ext/sqlite/libsqlite/src/pragma.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
-** 2003 April 6
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code used to implement the PRAGMA command.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include <ctype.h>
-
-/*
-** Interpret the given string as a boolean value.
-*/
-static int getBoolean(const char *z){
- static char *azTrue[] = { "yes", "on", "true" };
- int i;
- if( z[0]==0 ) return 0;
- if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
- return atoi(z);
- }
- for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
- if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
- }
- return 0;
-}
-
-/*
-** Interpret the given string as a safety level. Return 0 for OFF,
-** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
-** unrecognized string argument.
-**
-** Note that the values returned are one less that the values that
-** should be passed into sqliteBtreeSetSafetyLevel(). The is done
-** to support legacy SQL code. The safety level used to be boolean
-** and older scripts may have used numbers 0 for OFF and 1 for ON.
-*/
-static int getSafetyLevel(char *z){
- static const struct {
- const char *zWord;
- int val;
- } aKey[] = {
- { "no", 0 },
- { "off", 0 },
- { "false", 0 },
- { "yes", 1 },
- { "on", 1 },
- { "true", 1 },
- { "full", 2 },
- };
- int i;
- if( z[0]==0 ) return 1;
- if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
- return atoi(z);
- }
- for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
- if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
- }
- return 1;
-}
-
-/*
-** Interpret the given string as a temp db location. Return 1 for file
-** backed temporary databases, 2 for the Red-Black tree in memory database
-** and 0 to use the compile-time default.
-*/
-static int getTempStore(const char *z){
- if( z[0]>='0' && z[0]<='2' ){
- return z[0] - '0';
- }else if( sqliteStrICmp(z, "file")==0 ){
- return 1;
- }else if( sqliteStrICmp(z, "memory")==0 ){
- return 2;
- }else{
- return 0;
- }
-}
-
-/*
-** If the TEMP database is open, close it and mark the database schema
-** as needing reloading. This must be done when using the TEMP_STORE
-** or DEFAULT_TEMP_STORE pragmas.
-*/
-static int changeTempStorage(Parse *pParse, const char *zStorageType){
- int ts = getTempStore(zStorageType);
- sqlite *db = pParse->db;
- if( db->temp_store==ts ) return SQLITE_OK;
- if( db->aDb[1].pBt!=0 ){
- if( db->flags & SQLITE_InTrans ){
- sqliteErrorMsg(pParse, "temporary storage cannot be changed "
- "from within a transaction");
- return SQLITE_ERROR;
- }
- sqliteBtreeClose(db->aDb[1].pBt);
- db->aDb[1].pBt = 0;
- sqliteResetInternalSchema(db, 0);
- }
- db->temp_store = ts;
- return SQLITE_OK;
-}
-
-/*
-** Check to see if zRight and zLeft refer to a pragma that queries
-** or changes one of the flags in db->flags. Return 1 if so and 0 if not.
-** Also, implement the pragma.
-*/
-static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
- static const struct {
- const char *zName; /* Name of the pragma */
- int mask; /* Mask for the db->flags value */
- } aPragma[] = {
- { "vdbe_trace", SQLITE_VdbeTrace },
- { "full_column_names", SQLITE_FullColNames },
- { "short_column_names", SQLITE_ShortColNames },
- { "show_datatypes", SQLITE_ReportTypes },
- { "count_changes", SQLITE_CountRows },
- { "empty_result_callbacks", SQLITE_NullCallback },
- };
- int i;
- for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
- if( sqliteStrICmp(zLeft, aPragma[i].zName)==0 ){
- sqlite *db = pParse->db;
- Vdbe *v;
- if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){
- sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC);
- sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC);
- sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0,
- OP_Callback, 1, 0,
- 0);
- }else if( getBoolean(zRight) ){
- db->flags |= aPragma[i].mask;
- }else{
- db->flags &= ~aPragma[i].mask;
- }
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Process a pragma statement.
-**
-** Pragmas are of this form:
-**
-** PRAGMA id = value
-**
-** The identifier might also be a string. The value is a string, and
-** identifier, or a number. If minusFlag is true, then the value is
-** a number that was preceded by a minus sign.
-*/
-void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
- char *zLeft = 0;
- char *zRight = 0;
- sqlite *db = pParse->db;
- Vdbe *v = sqliteGetVdbe(pParse);
- if( v==0 ) return;
-
- zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
- sqliteDequote(zLeft);
- if( minusFlag ){
- zRight = 0;
- sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
- }else{
- zRight = sqliteStrNDup(pRight->z, pRight->n);
- sqliteDequote(zRight);
- }
- if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
- sqliteFree(zLeft);
- sqliteFree(zRight);
- return;
- }
-
- /*
- ** PRAGMA default_cache_size
- ** PRAGMA default_cache_size=N
- **
- ** The first form reports the current persistent setting for the
- ** page cache size. The value returned is the maximum number of
- ** pages in the page cache. The second form sets both the current
- ** page cache size value and the persistent page cache size value
- ** stored in the database file.
- **
- ** The default cache size is stored in meta-value 2 of page 1 of the
- ** database file. The cache size is actually the absolute value of
- ** this memory location. The sign of meta-value 2 determines the
- ** synchronous setting. A negative value means synchronous is off
- ** and a positive value means synchronous is on.
- */
- if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
- static VdbeOpList getCacheSize[] = {
- { OP_ReadCookie, 0, 2, 0},
- { OP_AbsValue, 0, 0, 0},
- { OP_Dup, 0, 0, 0},
- { OP_Integer, 0, 0, 0},
- { OP_Ne, 0, 6, 0},
- { OP_Integer, 0, 0, 0}, /* 5 */
- { OP_ColumnName, 0, 1, "cache_size"},
- { OP_Callback, 1, 0, 0},
- };
- int addr;
- if( pRight->z==pLeft->z ){
- addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
- sqliteVdbeChangeP1(v, addr+5, MAX_PAGES);
- }else{
- int size = atoi(zRight);
- if( size<0 ) size = -size;
- sqliteBeginWriteOperation(pParse, 0, 0);
- sqliteVdbeAddOp(v, OP_Integer, size, 0);
- sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
- addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
- sqliteVdbeAddOp(v, OP_Negative, 0, 0);
- sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
- sqliteEndWriteOperation(pParse);
- db->cache_size = db->cache_size<0 ? -size : size;
- sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
- }
- }else
-
- /*
- ** PRAGMA cache_size
- ** PRAGMA cache_size=N
- **
- ** The first form reports the current local setting for the
- ** page cache size. The local setting can be different from
- ** the persistent cache size value that is stored in the database
- ** file itself. The value returned is the maximum number of
- ** pages in the page cache. The second form sets the local
- ** page cache size value. It does not change the persistent
- ** cache size stored on the disk so the cache size will revert
- ** to its default value when the database is closed and reopened.
- ** N should be a positive integer.
- */
- if( sqliteStrICmp(zLeft,"cache_size")==0 ){
- static VdbeOpList getCacheSize[] = {
- { OP_ColumnName, 0, 1, "cache_size"},
- { OP_Callback, 1, 0, 0},
- };
- if( pRight->z==pLeft->z ){
- int size = db->cache_size;;
- if( size<0 ) size = -size;
- sqliteVdbeAddOp(v, OP_Integer, size, 0);
- sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
- }else{
- int size = atoi(zRight);
- if( size<0 ) size = -size;
- if( db->cache_size<0 ) size = -size;
- db->cache_size = size;
- sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
- }
- }else
-
- /*
- ** PRAGMA default_synchronous
- ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL
- **
- ** The first form returns the persistent value of the "synchronous" setting
- ** that is stored in the database. This is the synchronous setting that
- ** is used whenever the database is opened unless overridden by a separate
- ** "synchronous" pragma. The second form changes the persistent and the
- ** local synchronous setting to the value given.
- **
- ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls
- ** to make sure data is committed to disk. Write operations are very fast,
- ** but a power failure can leave the database in an inconsistent state.
- ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to
- ** make sure data is being written to disk. The risk of corruption due to
- ** a power loss in this mode is negligible but non-zero. If synchronous
- ** is FULL, extra fsync()s occur to reduce the risk of corruption to near
- ** zero, but with a write performance penalty. The default mode is NORMAL.
- */
- if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
- static VdbeOpList getSync[] = {
- { OP_ColumnName, 0, 1, "synchronous"},
- { OP_ReadCookie, 0, 3, 0},
- { OP_Dup, 0, 0, 0},
- { OP_If, 0, 0, 0}, /* 3 */
- { OP_ReadCookie, 0, 2, 0},
- { OP_Integer, 0, 0, 0},
- { OP_Lt, 0, 5, 0},
- { OP_AddImm, 1, 0, 0},
- { OP_Callback, 1, 0, 0},
- { OP_Halt, 0, 0, 0},
- { OP_AddImm, -1, 0, 0}, /* 10 */
- { OP_Callback, 1, 0, 0}
- };
- if( pRight->z==pLeft->z ){
- int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
- sqliteVdbeChangeP2(v, addr+3, addr+10);
- }else{
- int addr;
- int size = db->cache_size;
- if( size<0 ) size = -size;
- sqliteBeginWriteOperation(pParse, 0, 0);
- sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
- sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
- sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
- db->safety_level = getSafetyLevel(zRight)+1;
- if( db->safety_level==1 ){
- sqliteVdbeAddOp(v, OP_Negative, 0, 0);
- size = -size;
- }
- sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
- sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
- sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
- sqliteEndWriteOperation(pParse);
- db->cache_size = size;
- sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
- sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
- }
- }else
-
- /*
- ** PRAGMA synchronous
- ** PRAGMA synchronous=OFF|ON|NORMAL|FULL
- **
- ** Return or set the local value of the synchronous flag. Changing
- ** the local value does not make changes to the disk file and the
- ** default value will be restored the next time the database is
- ** opened.
- */
- if( sqliteStrICmp(zLeft,"synchronous")==0 ){
- static VdbeOpList getSync[] = {
- { OP_ColumnName, 0, 1, "synchronous"},
- { OP_Callback, 1, 0, 0},
- };
- if( pRight->z==pLeft->z ){
- sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
- sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
- }else{
- int size = db->cache_size;
- if( size<0 ) size = -size;
- db->safety_level = getSafetyLevel(zRight)+1;
- if( db->safety_level==1 ) size = -size;
- db->cache_size = size;
- sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
- sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
- }
- }else
-
-#ifndef NDEBUG
- if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
- if( getBoolean(zRight) ){
- always_code_trigger_setup = 1;
- }else{
- always_code_trigger_setup = 0;
- }
- }else
-#endif
-
- if( flagPragma(pParse, zLeft, zRight) ){
- /* The flagPragma() call also generates any necessary code */
- }else
-
- if( sqliteStrICmp(zLeft, "table_info")==0 ){
- Table *pTab;
- pTab = sqliteFindTable(db, zRight, 0);
- if( pTab ){
- static VdbeOpList tableInfoPreface[] = {
- { OP_ColumnName, 0, 0, "cid"},
- { OP_ColumnName, 1, 0, "name"},
- { OP_ColumnName, 2, 0, "type"},
- { OP_ColumnName, 3, 0, "notnull"},
- { OP_ColumnName, 4, 0, "dflt_value"},
- { OP_ColumnName, 5, 1, "pk"},
- };
- int i;
- sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
- sqliteViewGetColumnNames(pParse, pTab);
- for(i=0; i<pTab->nCol; i++){
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0,
- pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
- sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0,
- pTab->aCol[i].zDflt, P3_STATIC);
- sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
- sqliteVdbeAddOp(v, OP_Callback, 6, 0);
- }
- }
- }else
-
- if( sqliteStrICmp(zLeft, "index_info")==0 ){
- Index *pIdx;
- Table *pTab;
- pIdx = sqliteFindIndex(db, zRight, 0);
- if( pIdx ){
- static VdbeOpList tableInfoPreface[] = {
- { OP_ColumnName, 0, 0, "seqno"},
- { OP_ColumnName, 1, 0, "cid"},
- { OP_ColumnName, 2, 1, "name"},
- };
- int i;
- pTab = pIdx->pTable;
- sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
- for(i=0; i<pIdx->nColumn; i++){
- int cnum = pIdx->aiColumn[i];
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
- assert( pTab->nCol>cnum );
- sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0);
- sqliteVdbeAddOp(v, OP_Callback, 3, 0);
- }
- }
- }else
-
- if( sqliteStrICmp(zLeft, "index_list")==0 ){
- Index *pIdx;
- Table *pTab;
- pTab = sqliteFindTable(db, zRight, 0);
- if( pTab ){
- v = sqliteGetVdbe(pParse);
- pIdx = pTab->pIndex;
- }
- if( pTab && pIdx ){
- int i = 0;
- static VdbeOpList indexListPreface[] = {
- { OP_ColumnName, 0, 0, "seq"},
- { OP_ColumnName, 1, 0, "name"},
- { OP_ColumnName, 2, 1, "unique"},
- };
-
- sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
- while(pIdx){
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0);
- sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
- sqliteVdbeAddOp(v, OP_Callback, 3, 0);
- ++i;
- pIdx = pIdx->pNext;
- }
- }
- }else
-
- if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){
- FKey *pFK;
- Table *pTab;
- pTab = sqliteFindTable(db, zRight, 0);
- if( pTab ){
- v = sqliteGetVdbe(pParse);
- pFK = pTab->pFKey;
- }
- if( pTab && pFK ){
- int i = 0;
- static VdbeOpList indexListPreface[] = {
- { OP_ColumnName, 0, 0, "id"},
- { OP_ColumnName, 1, 0, "seq"},
- { OP_ColumnName, 2, 0, "table"},
- { OP_ColumnName, 3, 0, "from"},
- { OP_ColumnName, 4, 1, "to"},
- };
-
- sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
- while(pFK){
- int j;
- for(j=0; j<pFK->nCol; j++){
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeAddOp(v, OP_Integer, j, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0,
- pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0);
- sqliteVdbeAddOp(v, OP_Callback, 5, 0);
- }
- ++i;
- pFK = pFK->pNextFrom;
- }
- }
- }else
-
- if( sqliteStrICmp(zLeft, "database_list")==0 ){
- int i;
- static VdbeOpList indexListPreface[] = {
- { OP_ColumnName, 0, 0, "seq"},
- { OP_ColumnName, 1, 0, "name"},
- { OP_ColumnName, 2, 1, "file"},
- };
-
- sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt==0 ) continue;
- assert( db->aDb[i].zName!=0 );
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0);
- sqliteVdbeOp3(v, OP_String, 0, 0,
- sqliteBtreeGetFilename(db->aDb[i].pBt), 0);
- sqliteVdbeAddOp(v, OP_Callback, 3, 0);
- }
- }else
-
-
- /*
- ** PRAGMA temp_store
- ** PRAGMA temp_store = "default"|"memory"|"file"
- **
- ** Return or set the local value of the temp_store flag. Changing
- ** the local value does not make changes to the disk file and the default
- ** value will be restored the next time the database is opened.
- **
- ** Note that it is possible for the library compile-time options to
- ** override this setting
- */
- if( sqliteStrICmp(zLeft, "temp_store")==0 ){
- static VdbeOpList getTmpDbLoc[] = {
- { OP_ColumnName, 0, 1, "temp_store"},
- { OP_Callback, 1, 0, 0},
- };
- if( pRight->z==pLeft->z ){
- sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0);
- sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
- }else{
- changeTempStorage(pParse, zRight);
- }
- }else
-
- /*
- ** PRAGMA default_temp_store
- ** PRAGMA default_temp_store = "default"|"memory"|"file"
- **
- ** Return or set the value of the persistent temp_store flag. Any
- ** change does not take effect until the next time the database is
- ** opened.
- **
- ** Note that it is possible for the library compile-time options to
- ** override this setting
- */
- if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){
- static VdbeOpList getTmpDbLoc[] = {
- { OP_ColumnName, 0, 1, "temp_store"},
- { OP_ReadCookie, 0, 5, 0},
- { OP_Callback, 1, 0, 0}};
- if( pRight->z==pLeft->z ){
- sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
- }else{
- sqliteBeginWriteOperation(pParse, 0, 0);
- sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0);
- sqliteVdbeAddOp(v, OP_SetCookie, 0, 5);
- sqliteEndWriteOperation(pParse);
- }
- }else
-
-#ifndef NDEBUG
- if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
- extern void sqliteParserTrace(FILE*, char *);
- if( getBoolean(zRight) ){
- sqliteParserTrace(stdout, "parser: ");
- }else{
- sqliteParserTrace(0, 0);
- }
- }else
-#endif
-
- if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
- int i, j, addr;
-
- /* Code that initializes the integrity check program. Set the
- ** error count 0
- */
- static VdbeOpList initCode[] = {
- { OP_Integer, 0, 0, 0},
- { OP_MemStore, 0, 1, 0},
- { OP_ColumnName, 0, 1, "integrity_check"},
- };
-
- /* Code to do an BTree integrity check on a single database file.
- */
- static VdbeOpList checkDb[] = {
- { OP_SetInsert, 0, 0, "2"},
- { OP_Integer, 0, 0, 0}, /* 1 */
- { OP_OpenRead, 0, 2, 0},
- { OP_Rewind, 0, 7, 0}, /* 3 */
- { OP_Column, 0, 3, 0}, /* 4 */
- { OP_SetInsert, 0, 0, 0},
- { OP_Next, 0, 4, 0}, /* 6 */
- { OP_IntegrityCk, 0, 0, 0}, /* 7 */
- { OP_Dup, 0, 1, 0},
- { OP_String, 0, 0, "ok"},
- { OP_StrEq, 0, 12, 0}, /* 10 */
- { OP_MemIncr, 0, 0, 0},
- { OP_String, 0, 0, "*** in database "},
- { OP_String, 0, 0, 0}, /* 13 */
- { OP_String, 0, 0, " ***\n"},
- { OP_Pull, 3, 0, 0},
- { OP_Concat, 4, 1, 0},
- { OP_Callback, 1, 0, 0},
- };
-
- /* Code that appears at the end of the integrity check. If no error
- ** messages have been generated, output OK. Otherwise output the
- ** error message
- */
- static VdbeOpList endCode[] = {
- { OP_MemLoad, 0, 0, 0},
- { OP_Integer, 0, 0, 0},
- { OP_Ne, 0, 0, 0}, /* 2 */
- { OP_String, 0, 0, "ok"},
- { OP_Callback, 1, 0, 0},
- };
-
- /* Initialize the VDBE program */
- sqliteVdbeAddOpList(v, ArraySize(initCode), initCode);
-
- /* Do an integrity check on each database file */
- for(i=0; i<db->nDb; i++){
- HashElem *x;
-
- /* Do an integrity check of the B-Tree
- */
- addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
- sqliteVdbeChangeP1(v, addr+1, i);
- sqliteVdbeChangeP2(v, addr+3, addr+7);
- sqliteVdbeChangeP2(v, addr+6, addr+4);
- sqliteVdbeChangeP2(v, addr+7, i);
- sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
- sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
-
- /* Make sure all the indices are constructed correctly.
- */
- sqliteCodeVerifySchema(pParse, i);
- for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
- Table *pTab = sqliteHashData(x);
- Index *pIdx;
- int loopTop;
-
- if( pTab->pIndex==0 ) continue;
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0);
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- if( pIdx->tnum==0 ) continue;
- sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0);
- }
- sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- sqliteVdbeAddOp(v, OP_MemStore, 1, 1);
- loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0);
- sqliteVdbeAddOp(v, OP_MemIncr, 1, 0);
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- int k, jmp2;
- static VdbeOpList idxErr[] = {
- { OP_MemIncr, 0, 0, 0},
- { OP_String, 0, 0, "rowid "},
- { OP_Recno, 1, 0, 0},
- { OP_String, 0, 0, " missing from index "},
- { OP_String, 0, 0, 0}, /* 4 */
- { OP_Concat, 4, 0, 0},
- { OP_Callback, 1, 0, 0},
- };
- sqliteVdbeAddOp(v, OP_Recno, 1, 0);
- for(k=0; k<pIdx->nColumn; k++){
- int idx = pIdx->aiColumn[k];
- if( idx==pTab->iPKey ){
- sqliteVdbeAddOp(v, OP_Recno, 1, 0);
- }else{
- sqliteVdbeAddOp(v, OP_Column, 1, idx);
- }
- }
- sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
- if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
- jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0);
- addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr);
- sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
- sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v));
- }
- sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1);
- sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v));
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- static VdbeOpList cntIdx[] = {
- { OP_Integer, 0, 0, 0},
- { OP_MemStore, 2, 1, 0},
- { OP_Rewind, 0, 0, 0}, /* 2 */
- { OP_MemIncr, 2, 0, 0},
- { OP_Next, 0, 0, 0}, /* 4 */
- { OP_MemLoad, 1, 0, 0},
- { OP_MemLoad, 2, 0, 0},
- { OP_Eq, 0, 0, 0}, /* 7 */
- { OP_MemIncr, 0, 0, 0},
- { OP_String, 0, 0, "wrong # of entries in index "},
- { OP_String, 0, 0, 0}, /* 10 */
- { OP_Concat, 2, 0, 0},
- { OP_Callback, 1, 0, 0},
- };
- if( pIdx->tnum==0 ) continue;
- addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
- sqliteVdbeChangeP1(v, addr+2, j+2);
- sqliteVdbeChangeP2(v, addr+2, addr+5);
- sqliteVdbeChangeP1(v, addr+4, j+2);
- sqliteVdbeChangeP2(v, addr+4, addr+3);
- sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
- sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
- }
- }
- }
- addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode);
- sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
- }else
-
- {}
- sqliteFree(zLeft);
- sqliteFree(zRight);
-}
diff --git a/ext/sqlite/libsqlite/src/printf.c b/ext/sqlite/libsqlite/src/printf.c
deleted file mode 100644
index f867d62af6..0000000000
--- a/ext/sqlite/libsqlite/src/printf.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
-** The "printf" code that follows dates from the 1980's. It is in
-** the public domain. The original comments are included here for
-** completeness. They are very out-of-date but might be useful as
-** an historical reference. Most of the "enhancements" have been backed
-** out so that the functionality is now the same as standard printf().
-**
-**************************************************************************
-**
-** The following modules is an enhanced replacement for the "printf" subroutines
-** found in the standard C library. The following enhancements are
-** supported:
-**
-** + Additional functions. The standard set of "printf" functions
-** includes printf, fprintf, sprintf, vprintf, vfprintf, and
-** vsprintf. This module adds the following:
-**
-** * snprintf -- Works like sprintf, but has an extra argument
-** which is the size of the buffer written to.
-**
-** * mprintf -- Similar to sprintf. Writes output to memory
-** obtained from malloc.
-**
-** * xprintf -- Calls a function to dispose of output.
-**
-** * nprintf -- No output, but returns the number of characters
-** that would have been output by printf.
-**
-** * A v- version (ex: vsnprintf) of every function is also
-** supplied.
-**
-** + A few extensions to the formatting notation are supported:
-**
-** * The "=" flag (similar to "-") causes the output to be
-** be centered in the appropriately sized field.
-**
-** * The %b field outputs an integer in binary notation.
-**
-** * The %c field now accepts a precision. The character output
-** is repeated by the number of times the precision specifies.
-**
-** * The %' field works like %c, but takes as its character the
-** next character of the format string, instead of the next
-** argument. For example, printf("%.78'-") prints 78 minus
-** signs, the same as printf("%.78c",'-').
-**
-** + When compiled using GCC on a SPARC, this version of printf is
-** faster than the library printf for SUN OS 4.1.
-**
-** + All functions are fully reentrant.
-**
-*/
-#include "sqliteInt.h"
-
-/*
-** Conversion types fall into various categories as defined by the
-** following enumeration.
-*/
-#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
-#define etFLOAT 2 /* Floating point. %f */
-#define etEXP 3 /* Exponentional notation. %e and %E */
-#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
-#define etSIZE 5 /* Return number of characters processed so far. %n */
-#define etSTRING 6 /* Strings. %s */
-#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
-#define etPERCENT 8 /* Percent symbol. %% */
-#define etCHARX 9 /* Characters. %c */
-#define etERROR 10 /* Used to indicate no such conversion type */
-/* The rest are extensions, not normally found in printf() */
-#define etCHARLIT 11 /* Literal characters. %' */
-#define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */
-#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '',
- NULL pointers replaced by SQL NULL. %Q */
-#define etTOKEN 14 /* a pointer to a Token structure */
-#define etSRCLIST 15 /* a pointer to a SrcList */
-
-
-/*
-** An "etByte" is an 8-bit unsigned value.
-*/
-typedef unsigned char etByte;
-
-/*
-** Each builtin conversion character (ex: the 'd' in "%d") is described
-** by an instance of the following structure
-*/
-typedef struct et_info { /* Information about each format field */
- char fmttype; /* The format field code letter */
- etByte base; /* The base for radix conversion */
- etByte flags; /* One or more of FLAG_ constants below */
- etByte type; /* Conversion paradigm */
- char *charset; /* The character set for conversion */
- char *prefix; /* Prefix on non-zero values in alt format */
-} et_info;
-
-/*
-** Allowed values for et_info.flags
-*/
-#define FLAG_SIGNED 1 /* True if the value to convert is signed */
-#define FLAG_INTERN 2 /* True if for internal use only */
-
-
-/*
-** The following table is searched linearly, so it is good to put the
-** most frequently used conversion types first.
-*/
-static et_info fmtinfo[] = {
- { 'd', 10, 1, etRADIX, "0123456789", 0 },
- { 's', 0, 0, etSTRING, 0, 0 },
- { 'z', 0, 2, etDYNSTRING, 0, 0 },
- { 'q', 0, 0, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
- { 'c', 0, 0, etCHARX, 0, 0 },
- { 'o', 8, 0, etRADIX, "01234567", "0" },
- { 'u', 10, 0, etRADIX, "0123456789", 0 },
- { 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" },
- { 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" },
- { 'f', 0, 1, etFLOAT, 0, 0 },
- { 'e', 0, 1, etEXP, "e", 0 },
- { 'E', 0, 1, etEXP, "E", 0 },
- { 'g', 0, 1, etGENERIC, "e", 0 },
- { 'G', 0, 1, etGENERIC, "E", 0 },
- { 'i', 10, 1, etRADIX, "0123456789", 0 },
- { 'n', 0, 0, etSIZE, 0, 0 },
- { '%', 0, 0, etPERCENT, 0, 0 },
- { 'p', 10, 0, etRADIX, "0123456789", 0 },
- { 'T', 0, 2, etTOKEN, 0, 0 },
- { 'S', 0, 2, etSRCLIST, 0, 0 },
-};
-#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
-
-/*
-** If NOFLOATINGPOINT is defined, then none of the floating point
-** conversions will work.
-*/
-#ifndef etNOFLOATINGPOINT
-/*
-** "*val" is a double such that 0.1 <= *val < 10.0
-** Return the ascii code for the leading digit of *val, then
-** multiply "*val" by 10.0 to renormalize.
-**
-** Example:
-** input: *val = 3.14159
-** output: *val = 1.4159 function return = '3'
-**
-** The counter *cnt is incremented each time. After counter exceeds
-** 16 (the number of significant digits in a 64-bit float) '0' is
-** always returned.
-*/
-static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
- int digit;
- LONGDOUBLE_TYPE d;
- if( (*cnt)++ >= 16 ) return '0';
- digit = (int)*val;
- d = digit;
- digit += '0';
- *val = (*val - d)*10.0;
- return digit;
-}
-#endif
-
-#define etBUFSIZE 1000 /* Size of the output buffer */
-
-/*
-** The root program. All variations call this core.
-**
-** INPUTS:
-** func This is a pointer to a function taking three arguments
-** 1. A pointer to anything. Same as the "arg" parameter.
-** 2. A pointer to the list of characters to be output
-** (Note, this list is NOT null terminated.)
-** 3. An integer number of characters to be output.
-** (Note: This number might be zero.)
-**
-** arg This is the pointer to anything which will be passed as the
-** first argument to "func". Use it for whatever you like.
-**
-** fmt This is the format string, as in the usual print.
-**
-** ap This is a pointer to a list of arguments. Same as in
-** vfprint.
-**
-** OUTPUTS:
-** The return value is the total number of characters sent to
-** the function "func". Returns -1 on a error.
-**
-** Note that the order in which automatic variables are declared below
-** seems to make a big difference in determining how fast this beast
-** will run.
-*/
-static int vxprintf(
- void (*func)(void*,const char*,int), /* Consumer of text */
- void *arg, /* First argument to the consumer */
- int useExtended, /* Allow extended %-conversions */
- const char *fmt, /* Format string */
- va_list ap /* arguments */
-){
- int c; /* Next character in the format string */
- char *bufpt; /* Pointer to the conversion buffer */
- int precision; /* Precision of the current field */
- int length; /* Length of the field */
- int idx; /* A general purpose loop counter */
- int count; /* Total number of characters output */
- int width; /* Width of the current field */
- etByte flag_leftjustify; /* True if "-" flag is present */
- etByte flag_plussign; /* True if "+" flag is present */
- etByte flag_blanksign; /* True if " " flag is present */
- etByte flag_alternateform; /* True if "#" flag is present */
- etByte flag_zeropad; /* True if field width constant starts with zero */
- etByte flag_long; /* True if "l" flag is present */
- unsigned long longvalue; /* Value for integer types */
- LONGDOUBLE_TYPE realvalue; /* Value for real types */
- et_info *infop; /* Pointer to the appropriate info structure */
- char buf[etBUFSIZE]; /* Conversion buffer */
- char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
- etByte errorflag = 0; /* True if an error is encountered */
- etByte xtype; /* Conversion paradigm */
- char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
- static char spaces[] = " ";
-#define etSPACESIZE (sizeof(spaces)-1)
-#ifndef etNOFLOATINGPOINT
- int exp; /* exponent of real numbers */
- double rounder; /* Used for rounding floating point values */
- etByte flag_dp; /* True if decimal point should be shown */
- etByte flag_rtz; /* True if trailing zeros should be removed */
- etByte flag_exp; /* True to force display of the exponent */
- int nsd; /* Number of significant digits returned */
-#endif
-
- func(arg,"",0);
- count = length = 0;
- bufpt = 0;
- for(; (c=(*fmt))!=0; ++fmt){
- if( c!='%' ){
- int amt;
- bufpt = (char *)fmt;
- amt = 1;
- while( (c=(*++fmt))!='%' && c!=0 ) amt++;
- (*func)(arg,bufpt,amt);
- count += amt;
- if( c==0 ) break;
- }
- if( (c=(*++fmt))==0 ){
- errorflag = 1;
- (*func)(arg,"%",1);
- count++;
- break;
- }
- /* Find out what flags are present */
- flag_leftjustify = flag_plussign = flag_blanksign =
- flag_alternateform = flag_zeropad = 0;
- do{
- switch( c ){
- case '-': flag_leftjustify = 1; c = 0; break;
- case '+': flag_plussign = 1; c = 0; break;
- case ' ': flag_blanksign = 1; c = 0; break;
- case '#': flag_alternateform = 1; c = 0; break;
- case '0': flag_zeropad = 1; c = 0; break;
- default: break;
- }
- }while( c==0 && (c=(*++fmt))!=0 );
- /* Get the field width */
- width = 0;
- if( c=='*' ){
- width = va_arg(ap,int);
- if( width<0 ){
- flag_leftjustify = 1;
- width = -width;
- }
- c = *++fmt;
- }else{
- while( c>='0' && c<='9' ){
- width = width*10 + c - '0';
- c = *++fmt;
- }
- }
- if( width > etBUFSIZE-10 ){
- width = etBUFSIZE-10;
- }
- /* Get the precision */
- if( c=='.' ){
- precision = 0;
- c = *++fmt;
- if( c=='*' ){
- precision = va_arg(ap,int);
- if( precision<0 ) precision = -precision;
- c = *++fmt;
- }else{
- while( c>='0' && c<='9' ){
- precision = precision*10 + c - '0';
- c = *++fmt;
- }
- }
- /* Limit the precision to prevent overflowing buf[] during conversion */
- if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
- }else{
- precision = -1;
- }
- /* Get the conversion type modifier */
- if( c=='l' ){
- flag_long = 1;
- c = *++fmt;
- }else{
- flag_long = 0;
- }
- /* Fetch the info entry for the field */
- infop = 0;
- xtype = etERROR;
- for(idx=0; idx<etNINFO; idx++){
- if( c==fmtinfo[idx].fmttype ){
- infop = &fmtinfo[idx];
- if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
- xtype = infop->type;
- }
- break;
- }
- }
- zExtra = 0;
-
- /*
- ** At this point, variables are initialized as follows:
- **
- ** flag_alternateform TRUE if a '#' is present.
- ** flag_plussign TRUE if a '+' is present.
- ** flag_leftjustify TRUE if a '-' is present or if the
- ** field width was negative.
- ** flag_zeropad TRUE if the width began with 0.
- ** flag_long TRUE if the letter 'l' (ell) prefixed
- ** the conversion character.
- ** flag_blanksign TRUE if a ' ' is present.
- ** width The specified field width. This is
- ** always non-negative. Zero is the default.
- ** precision The specified precision. The default
- ** is -1.
- ** xtype The class of the conversion.
- ** infop Pointer to the appropriate info struct.
- */
- switch( xtype ){
- case etRADIX:
- if( flag_long ) longvalue = va_arg(ap,long);
- else longvalue = va_arg(ap,int);
-#if 1
- /* For the format %#x, the value zero is printed "0" not "0x0".
- ** I think this is stupid. */
- if( longvalue==0 ) flag_alternateform = 0;
-#else
- /* More sensible: turn off the prefix for octal (to prevent "00"),
- ** but leave the prefix for hex. */
- if( longvalue==0 && infop->base==8 ) flag_alternateform = 0;
-#endif
- if( infop->flags & FLAG_SIGNED ){
- if( *(long*)&longvalue<0 ){
- longvalue = -*(long*)&longvalue;
- prefix = '-';
- }else if( flag_plussign ) prefix = '+';
- else if( flag_blanksign ) prefix = ' ';
- else prefix = 0;
- }else prefix = 0;
- if( flag_zeropad && precision<width-(prefix!=0) ){
- precision = width-(prefix!=0);
- }
- bufpt = &buf[etBUFSIZE-1];
- {
- register char *cset; /* Use registers for speed */
- register int base;
- cset = infop->charset;
- base = infop->base;
- do{ /* Convert to ascii */
- *(--bufpt) = cset[longvalue%base];
- longvalue = longvalue/base;
- }while( longvalue>0 );
- }
- length = &buf[etBUFSIZE-1]-bufpt;
- for(idx=precision-length; idx>0; idx--){
- *(--bufpt) = '0'; /* Zero pad */
- }
- if( prefix ) *(--bufpt) = prefix; /* Add sign */
- if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
- char *pre, x;
- pre = infop->prefix;
- if( *bufpt!=pre[0] ){
- for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
- }
- }
- length = &buf[etBUFSIZE-1]-bufpt;
- break;
- case etFLOAT:
- case etEXP:
- case etGENERIC:
- realvalue = va_arg(ap,double);
-#ifndef etNOFLOATINGPOINT
- if( precision<0 ) precision = 6; /* Set default precision */
- if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
- if( realvalue<0.0 ){
- realvalue = -realvalue;
- prefix = '-';
- }else{
- if( flag_plussign ) prefix = '+';
- else if( flag_blanksign ) prefix = ' ';
- else prefix = 0;
- }
- if( infop->type==etGENERIC && precision>0 ) precision--;
- rounder = 0.0;
-#if 0
- /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
- for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
-#else
- /* It makes more sense to use 0.5 */
- for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
-#endif
- if( infop->type==etFLOAT ) realvalue += rounder;
- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
- exp = 0;
- if( realvalue>0.0 ){
- while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
- while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
- while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
- while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
- if( exp>350 || exp<-350 ){
- bufpt = "NaN";
- length = 3;
- break;
- }
- }
- bufpt = buf;
- /*
- ** If the field type is etGENERIC, then convert to either etEXP
- ** or etFLOAT, as appropriate.
- */
- flag_exp = xtype==etEXP;
- if( xtype!=etFLOAT ){
- realvalue += rounder;
- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
- }
- if( xtype==etGENERIC ){
- flag_rtz = !flag_alternateform;
- if( exp<-4 || exp>precision ){
- xtype = etEXP;
- }else{
- precision = precision - exp;
- xtype = etFLOAT;
- }
- }else{
- flag_rtz = 0;
- }
- /*
- ** The "exp+precision" test causes output to be of type etEXP if
- ** the precision is too large to fit in buf[].
- */
- nsd = 0;
- if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){
- flag_dp = (precision>0 || flag_alternateform);
- if( prefix ) *(bufpt++) = prefix; /* Sign */
- if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
- else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
- if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
- for(exp++; exp<0 && precision>0; precision--, exp++){
- *(bufpt++) = '0';
- }
- while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
- *(bufpt--) = 0; /* Null terminate */
- if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
- while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
- if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
- }
- bufpt++; /* point to next free slot */
- }else{ /* etEXP or etGENERIC */
- flag_dp = (precision>0 || flag_alternateform);
- if( prefix ) *(bufpt++) = prefix; /* Sign */
- *(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */
- if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
- while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
- bufpt--; /* point to last digit */
- if( flag_rtz && flag_dp ){ /* Remove tail zeros */
- while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
- if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
- }
- bufpt++; /* point to next free slot */
- if( exp || flag_exp ){
- *(bufpt++) = infop->charset[0];
- if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
- else { *(bufpt++) = '+'; }
- if( exp>=100 ){
- *(bufpt++) = (exp/100)+'0'; /* 100's digit */
- exp %= 100;
- }
- *(bufpt++) = exp/10+'0'; /* 10's digit */
- *(bufpt++) = exp%10+'0'; /* 1's digit */
- }
- }
- /* The converted number is in buf[] and zero terminated. Output it.
- ** Note that the number is in the usual order, not reversed as with
- ** integer conversions. */
- length = bufpt-buf;
- bufpt = buf;
-
- /* Special case: Add leading zeros if the flag_zeropad flag is
- ** set and we are not left justified */
- if( flag_zeropad && !flag_leftjustify && length < width){
- int i;
- int nPad = width - length;
- for(i=width; i>=nPad; i--){
- bufpt[i] = bufpt[i-nPad];
- }
- i = prefix!=0;
- while( nPad-- ) bufpt[i++] = '0';
- length = width;
- }
-#endif
- break;
- case etSIZE:
- *(va_arg(ap,int*)) = count;
- length = width = 0;
- break;
- case etPERCENT:
- buf[0] = '%';
- bufpt = buf;
- length = 1;
- break;
- case etCHARLIT:
- case etCHARX:
- c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
- if( precision>=0 ){
- for(idx=1; idx<precision; idx++) buf[idx] = c;
- length = precision;
- }else{
- length =1;
- }
- bufpt = buf;
- break;
- case etSTRING:
- case etDYNSTRING:
- bufpt = va_arg(ap,char*);
- if( bufpt==0 ){
- bufpt = "";
- }else if( xtype==etDYNSTRING ){
- zExtra = bufpt;
- }
- length = strlen(bufpt);
- if( precision>=0 && precision<length ) length = precision;
- break;
- case etSQLESCAPE:
- case etSQLESCAPE2:
- {
- int i, j, n, c, isnull;
- char *arg = va_arg(ap,char*);
- isnull = arg==0;
- if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
- for(i=n=0; (c=arg[i])!=0; i++){
- if( c=='\'' ) n++;
- }
- n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
- if( n>etBUFSIZE ){
- bufpt = zExtra = sqliteMalloc( n );
- if( bufpt==0 ) return -1;
- }else{
- bufpt = buf;
- }
- j = 0;
- if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
- for(i=0; (c=arg[i])!=0; i++){
- bufpt[j++] = c;
- if( c=='\'' ) bufpt[j++] = c;
- }
- if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
- bufpt[j] = 0;
- length = j;
- if( precision>=0 && precision<length ) length = precision;
- }
- break;
- case etTOKEN: {
- Token *pToken = va_arg(ap, Token*);
- (*func)(arg, pToken->z, pToken->n);
- length = width = 0;
- break;
- }
- case etSRCLIST: {
- SrcList *pSrc = va_arg(ap, SrcList*);
- int k = va_arg(ap, int);
- struct SrcList_item *pItem = &pSrc->a[k];
- assert( k>=0 && k<pSrc->nSrc );
- if( pItem->zDatabase && pItem->zDatabase[0] ){
- (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase));
- (*func)(arg, ".", 1);
- }
- (*func)(arg, pItem->zName, strlen(pItem->zName));
- length = width = 0;
- break;
- }
- case etERROR:
- buf[0] = '%';
- buf[1] = c;
- errorflag = 0;
- idx = 1+(c!=0);
- (*func)(arg,"%",idx);
- count += idx;
- if( c==0 ) fmt--;
- break;
- }/* End switch over the format type */
- /*
- ** The text of the conversion is pointed to by "bufpt" and is
- ** "length" characters long. The field width is "width". Do
- ** the output.
- */
- if( !flag_leftjustify ){
- register int nspace;
- nspace = width-length;
- if( nspace>0 ){
- count += nspace;
- while( nspace>=etSPACESIZE ){
- (*func)(arg,spaces,etSPACESIZE);
- nspace -= etSPACESIZE;
- }
- if( nspace>0 ) (*func)(arg,spaces,nspace);
- }
- }
- if( length>0 ){
- (*func)(arg,bufpt,length);
- count += length;
- }
- if( flag_leftjustify ){
- register int nspace;
- nspace = width-length;
- if( nspace>0 ){
- count += nspace;
- while( nspace>=etSPACESIZE ){
- (*func)(arg,spaces,etSPACESIZE);
- nspace -= etSPACESIZE;
- }
- if( nspace>0 ) (*func)(arg,spaces,nspace);
- }
- }
- if( zExtra ){
- sqliteFree(zExtra);
- }
- }/* End for loop over the format string */
- return errorflag ? -1 : count;
-} /* End of function */
-
-
-/* This structure is used to store state information about the
-** write to memory that is currently in progress.
-*/
-struct sgMprintf {
- char *zBase; /* A base allocation */
- char *zText; /* The string collected so far */
- int nChar; /* Length of the string so far */
- int nTotal; /* Output size if unconstrained */
- int nAlloc; /* Amount of space allocated in zText */
- void *(*xRealloc)(void*,int); /* Function used to realloc memory */
-};
-
-/*
-** This function implements the callback from vxprintf.
-**
-** This routine add nNewChar characters of text in zNewText to
-** the sgMprintf structure pointed to by "arg".
-*/
-static void mout(void *arg, const char *zNewText, int nNewChar){
- struct sgMprintf *pM = (struct sgMprintf*)arg;
- pM->nTotal += nNewChar;
- if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
- if( pM->xRealloc==0 ){
- nNewChar = pM->nAlloc - pM->nChar - 1;
- }else{
- pM->nAlloc = pM->nChar + nNewChar*2 + 1;
- if( pM->zText==pM->zBase ){
- pM->zText = pM->xRealloc(0, pM->nAlloc);
- if( pM->zText && pM->nChar ){
- memcpy(pM->zText, pM->zBase, pM->nChar);
- }
- }else{
- pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
- }
- }
- }
- if( pM->zText ){
- if( nNewChar>0 ){
- memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
- pM->nChar += nNewChar;
- }
- pM->zText[pM->nChar] = 0;
- }
-}
-
-/*
-** This routine is a wrapper around xprintf() that invokes mout() as
-** the consumer.
-*/
-static char *base_vprintf(
- void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */
- int useInternal, /* Use internal %-conversions if true */
- char *zInitBuf, /* Initially write here, before mallocing */
- int nInitBuf, /* Size of zInitBuf[] */
- const char *zFormat, /* format string */
- va_list ap /* arguments */
-){
- struct sgMprintf sM;
- sM.zBase = sM.zText = zInitBuf;
- sM.nChar = sM.nTotal = 0;
- sM.nAlloc = nInitBuf;
- sM.xRealloc = xRealloc;
- vxprintf(mout, &sM, useInternal, zFormat, ap);
- if( xRealloc ){
- if( sM.zText==sM.zBase ){
- sM.zText = xRealloc(0, sM.nChar+1);
- memcpy(sM.zText, sM.zBase, sM.nChar+1);
- }else if( sM.nAlloc>sM.nChar+10 ){
- sM.zText = xRealloc(sM.zText, sM.nChar+1);
- }
- }
- return sM.zText;
-}
-
-/*
-** Realloc that is a real function, not a macro.
-*/
-static void *printf_realloc(void *old, int size){
- return sqliteRealloc(old,size);
-}
-
-/*
-** Print into memory obtained from sqliteMalloc(). Use the internal
-** %-conversion extensions.
-*/
-char *sqliteVMPrintf(const char *zFormat, va_list ap){
- char zBase[1000];
- return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
-}
-
-/*
-** Print into memory obtained from sqliteMalloc(). Use the internal
-** %-conversion extensions.
-*/
-char *sqliteMPrintf(const char *zFormat, ...){
- va_list ap;
- char *z;
- char zBase[1000];
- va_start(ap, zFormat);
- z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
- va_end(ap);
- return z;
-}
-
-/*
-** Print into memory obtained from malloc(). Do not use the internal
-** %-conversion extensions. This routine is for use by external users.
-*/
-char *sqlite_mprintf(const char *zFormat, ...){
- va_list ap;
- char *z;
- char zBuf[200];
-
- va_start(ap,zFormat);
- z = base_vprintf((void*(*)(void*,int))realloc, 0,
- zBuf, sizeof(zBuf), zFormat, ap);
- va_end(ap);
- return z;
-}
-
-/* This is the varargs version of sqlite_mprintf.
-*/
-char *sqlite_vmprintf(const char *zFormat, va_list ap){
- char zBuf[200];
- return base_vprintf((void*(*)(void*,int))realloc, 0,
- zBuf, sizeof(zBuf), zFormat, ap);
-}
-
-/*
-** sqlite_snprintf() works like snprintf() except that it ignores the
-** current locale settings. This is important for SQLite because we
-** are not able to use a "," as the decimal point in place of "." as
-** specified by some locales.
-*/
-char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){
- char *z;
- va_list ap;
-
- va_start(ap,zFormat);
- z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
- va_end(ap);
- return z;
-}
-
-/*
-** The following four routines implement the varargs versions of the
-** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h
-** header files for a more detailed description of how these interfaces
-** work.
-**
-** These routines are all just simple wrappers.
-*/
-int sqlite_exec_printf(
- sqlite *db, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- sqlite_callback xCallback, /* Callback function */
- void *pArg, /* 1st argument to callback function */
- char **errmsg, /* Error msg written here */
- ... /* Arguments to the format string. */
-){
- va_list ap;
- int rc;
-
- va_start(ap, errmsg);
- rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap);
- va_end(ap);
- return rc;
-}
-int sqlite_exec_vprintf(
- sqlite *db, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- sqlite_callback xCallback, /* Callback function */
- void *pArg, /* 1st argument to callback function */
- char **errmsg, /* Error msg written here */
- va_list ap /* Arguments to the format string. */
-){
- char *zSql;
- int rc;
-
- zSql = sqlite_vmprintf(sqlFormat, ap);
- rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg);
- free(zSql);
- return rc;
-}
-int sqlite_get_table_printf(
- sqlite *db, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncol, /* Number of result columns written here */
- char **errmsg, /* Error msg written here */
- ... /* Arguments to the format string */
-){
- va_list ap;
- int rc;
-
- va_start(ap, errmsg);
- rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap);
- va_end(ap);
- return rc;
-}
-int sqlite_get_table_vprintf(
- sqlite *db, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg, /* Error msg written here */
- va_list ap /* Arguments to the format string */
-){
- char *zSql;
- int rc;
-
- zSql = sqlite_vmprintf(sqlFormat, ap);
- rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg);
- free(zSql);
- return rc;
-}
diff --git a/ext/sqlite/libsqlite/src/random.c b/ext/sqlite/libsqlite/src/random.c
deleted file mode 100644
index dd8bdd4c58..0000000000
--- a/ext/sqlite/libsqlite/src/random.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code to implement a pseudo-random number
-** generator (PRNG) for SQLite.
-**
-** Random numbers are used by some of the database backends in order
-** to generate random integer keys for tables or random filenames.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include "os.h"
-
-
-/*
-** Get a single 8-bit random value from the RC4 PRNG. The Mutex
-** must be held while executing this routine.
-**
-** Why not just use a library random generator like lrand48() for this?
-** Because the OP_NewRecno opcode in the VDBE depends on having a very
-** good source of random numbers. The lrand48() library function may
-** well be good enough. But maybe not. Or maybe lrand48() has some
-** subtle problems on some systems that could cause problems. It is hard
-** to know. To minimize the risk of problems due to bad lrand48()
-** implementations, SQLite uses this random number generator based
-** on RC4, which we know works very well.
-*/
-static int randomByte(){
- unsigned char t;
-
- /* All threads share a single random number generator.
- ** This structure is the current state of the generator.
- */
- static struct {
- unsigned char isInit; /* True if initialized */
- unsigned char i, j; /* State variables */
- unsigned char s[256]; /* State variables */
- } prng;
-
- /* Initialize the state of the random number generator once,
- ** the first time this routine is called. The seed value does
- ** not need to contain a lot of randomness since we are not
- ** trying to do secure encryption or anything like that...
- **
- ** Nothing in this file or anywhere else in SQLite does any kind of
- ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
- ** number generator) not as an encryption device.
- */
- if( !prng.isInit ){
- int i;
- char k[256];
- prng.j = 0;
- prng.i = 0;
- sqliteOsRandomSeed(k);
- for(i=0; i<256; i++){
- prng.s[i] = i;
- }
- for(i=0; i<256; i++){
- prng.j += prng.s[i] + k[i];
- t = prng.s[prng.j];
- prng.s[prng.j] = prng.s[i];
- prng.s[i] = t;
- }
- prng.isInit = 1;
- }
-
- /* Generate and return single random byte
- */
- prng.i++;
- t = prng.s[prng.i];
- prng.j += t;
- prng.s[prng.i] = prng.s[prng.j];
- prng.s[prng.j] = t;
- t += prng.s[prng.i];
- return prng.s[t];
-}
-
-/*
-** Return N random bytes.
-*/
-void sqliteRandomness(int N, void *pBuf){
- unsigned char *zBuf = pBuf;
- sqliteOsEnterMutex();
- while( N-- ){
- *(zBuf++) = randomByte();
- }
- sqliteOsLeaveMutex();
-}
diff --git a/ext/sqlite/libsqlite/src/select.c b/ext/sqlite/libsqlite/src/select.c
deleted file mode 100644
index c19c2bac86..0000000000
--- a/ext/sqlite/libsqlite/src/select.c
+++ /dev/null
@@ -1,2434 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains C code routines that are called by the parser
-** to handle SELECT statements in SQLite.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-
-/*
-** Allocate a new Select structure and return a pointer to that
-** structure.
-*/
-Select *sqliteSelectNew(
- ExprList *pEList, /* which columns to include in the result */
- SrcList *pSrc, /* the FROM clause -- which tables to scan */
- Expr *pWhere, /* the WHERE clause */
- ExprList *pGroupBy, /* the GROUP BY clause */
- Expr *pHaving, /* the HAVING clause */
- ExprList *pOrderBy, /* the ORDER BY clause */
- int isDistinct, /* true if the DISTINCT keyword is present */
- int nLimit, /* LIMIT value. -1 means not used */
- int nOffset /* OFFSET value. 0 means no offset */
-){
- Select *pNew;
- pNew = sqliteMalloc( sizeof(*pNew) );
- if( pNew==0 ){
- sqliteExprListDelete(pEList);
- sqliteSrcListDelete(pSrc);
- sqliteExprDelete(pWhere);
- sqliteExprListDelete(pGroupBy);
- sqliteExprDelete(pHaving);
- sqliteExprListDelete(pOrderBy);
- }else{
- if( pEList==0 ){
- pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
- }
- pNew->pEList = pEList;
- pNew->pSrc = pSrc;
- pNew->pWhere = pWhere;
- pNew->pGroupBy = pGroupBy;
- pNew->pHaving = pHaving;
- pNew->pOrderBy = pOrderBy;
- pNew->isDistinct = isDistinct;
- pNew->op = TK_SELECT;
- pNew->nLimit = nLimit;
- pNew->nOffset = nOffset;
- pNew->iLimit = -1;
- pNew->iOffset = -1;
- }
- return pNew;
-}
-
-/*
-** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
-** type of join. Return an integer constant that expresses that type
-** in terms of the following bit values:
-**
-** JT_INNER
-** JT_OUTER
-** JT_NATURAL
-** JT_LEFT
-** JT_RIGHT
-**
-** A full outer join is the combination of JT_LEFT and JT_RIGHT.
-**
-** If an illegal or unsupported join type is seen, then still return
-** a join type, but put an error in the pParse structure.
-*/
-int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
- int jointype = 0;
- Token *apAll[3];
- Token *p;
- static struct {
- const char *zKeyword;
- int nChar;
- int code;
- } keywords[] = {
- { "natural", 7, JT_NATURAL },
- { "left", 4, JT_LEFT|JT_OUTER },
- { "right", 5, JT_RIGHT|JT_OUTER },
- { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER },
- { "outer", 5, JT_OUTER },
- { "inner", 5, JT_INNER },
- { "cross", 5, JT_INNER },
- };
- int i, j;
- apAll[0] = pA;
- apAll[1] = pB;
- apAll[2] = pC;
- for(i=0; i<3 && apAll[i]; i++){
- p = apAll[i];
- for(j=0; j<sizeof(keywords)/sizeof(keywords[0]); j++){
- if( p->n==keywords[j].nChar
- && sqliteStrNICmp(p->z, keywords[j].zKeyword, p->n)==0 ){
- jointype |= keywords[j].code;
- break;
- }
- }
- if( j>=sizeof(keywords)/sizeof(keywords[0]) ){
- jointype |= JT_ERROR;
- break;
- }
- }
- if(
- (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
- (jointype & JT_ERROR)!=0
- ){
- static Token dummy = { 0, 0 };
- char *zSp1 = " ", *zSp2 = " ";
- if( pB==0 ){ pB = &dummy; zSp1 = 0; }
- if( pC==0 ){ pC = &dummy; zSp2 = 0; }
- sqliteSetNString(&pParse->zErrMsg, "unknown or unsupported join type: ", 0,
- pA->z, pA->n, zSp1, 1, pB->z, pB->n, zSp2, 1, pC->z, pC->n, 0);
- pParse->nErr++;
- jointype = JT_INNER;
- }else if( jointype & JT_RIGHT ){
- sqliteErrorMsg(pParse,
- "RIGHT and FULL OUTER JOINs are not currently supported");
- jointype = JT_INNER;
- }
- return jointype;
-}
-
-/*
-** Return the index of a column in a table. Return -1 if the column
-** is not contained in the table.
-*/
-static int columnIndex(Table *pTab, const char *zCol){
- int i;
- for(i=0; i<pTab->nCol; i++){
- if( sqliteStrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
- }
- return -1;
-}
-
-/*
-** Add a term to the WHERE expression in *ppExpr that requires the
-** zCol column to be equal in the two tables pTab1 and pTab2.
-*/
-static void addWhereTerm(
- const char *zCol, /* Name of the column */
- const Table *pTab1, /* First table */
- const Table *pTab2, /* Second table */
- Expr **ppExpr /* Add the equality term to this expression */
-){
- Token dummy;
- Expr *pE1a, *pE1b, *pE1c;
- Expr *pE2a, *pE2b, *pE2c;
- Expr *pE;
-
- dummy.z = zCol;
- dummy.n = strlen(zCol);
- dummy.dyn = 0;
- pE1a = sqliteExpr(TK_ID, 0, 0, &dummy);
- pE2a = sqliteExpr(TK_ID, 0, 0, &dummy);
- dummy.z = pTab1->zName;
- dummy.n = strlen(dummy.z);
- pE1b = sqliteExpr(TK_ID, 0, 0, &dummy);
- dummy.z = pTab2->zName;
- dummy.n = strlen(dummy.z);
- pE2b = sqliteExpr(TK_ID, 0, 0, &dummy);
- pE1c = sqliteExpr(TK_DOT, pE1b, pE1a, 0);
- pE2c = sqliteExpr(TK_DOT, pE2b, pE2a, 0);
- pE = sqliteExpr(TK_EQ, pE1c, pE2c, 0);
- ExprSetProperty(pE, EP_FromJoin);
- if( *ppExpr ){
- *ppExpr = sqliteExpr(TK_AND, *ppExpr, pE, 0);
- }else{
- *ppExpr = pE;
- }
-}
-
-/*
-** Set the EP_FromJoin property on all terms of the given expression.
-**
-** The EP_FromJoin property is used on terms of an expression to tell
-** the LEFT OUTER JOIN processing logic that this term is part of the
-** join restriction specified in the ON or USING clause and not a part
-** of the more general WHERE clause. These terms are moved over to the
-** WHERE clause during join processing but we need to remember that they
-** originated in the ON or USING clause.
-*/
-static void setJoinExpr(Expr *p){
- while( p ){
- ExprSetProperty(p, EP_FromJoin);
- setJoinExpr(p->pLeft);
- p = p->pRight;
- }
-}
-
-/*
-** This routine processes the join information for a SELECT statement.
-** ON and USING clauses are converted into extra terms of the WHERE clause.
-** NATURAL joins also create extra WHERE clause terms.
-**
-** This routine returns the number of errors encountered.
-*/
-static int sqliteProcessJoin(Parse *pParse, Select *p){
- SrcList *pSrc;
- int i, j;
- pSrc = p->pSrc;
- for(i=0; i<pSrc->nSrc-1; i++){
- struct SrcList_item *pTerm = &pSrc->a[i];
- struct SrcList_item *pOther = &pSrc->a[i+1];
-
- if( pTerm->pTab==0 || pOther->pTab==0 ) continue;
-
- /* When the NATURAL keyword is present, add WHERE clause terms for
- ** every column that the two tables have in common.
- */
- if( pTerm->jointype & JT_NATURAL ){
- Table *pTab;
- if( pTerm->pOn || pTerm->pUsing ){
- sqliteErrorMsg(pParse, "a NATURAL join may not have "
- "an ON or USING clause", 0);
- return 1;
- }
- pTab = pTerm->pTab;
- for(j=0; j<pTab->nCol; j++){
- if( columnIndex(pOther->pTab, pTab->aCol[j].zName)>=0 ){
- addWhereTerm(pTab->aCol[j].zName, pTab, pOther->pTab, &p->pWhere);
- }
- }
- }
-
- /* Disallow both ON and USING clauses in the same join
- */
- if( pTerm->pOn && pTerm->pUsing ){
- sqliteErrorMsg(pParse, "cannot have both ON and USING "
- "clauses in the same join");
- return 1;
- }
-
- /* Add the ON clause to the end of the WHERE clause, connected by
- ** and AND operator.
- */
- if( pTerm->pOn ){
- setJoinExpr(pTerm->pOn);
- if( p->pWhere==0 ){
- p->pWhere = pTerm->pOn;
- }else{
- p->pWhere = sqliteExpr(TK_AND, p->pWhere, pTerm->pOn, 0);
- }
- pTerm->pOn = 0;
- }
-
- /* Create extra terms on the WHERE clause for each column named
- ** in the USING clause. Example: If the two tables to be joined are
- ** A and B and the USING clause names X, Y, and Z, then add this
- ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
- ** Report an error if any column mentioned in the USING clause is
- ** not contained in both tables to be joined.
- */
- if( pTerm->pUsing ){
- IdList *pList;
- int j;
- assert( i<pSrc->nSrc-1 );
- pList = pTerm->pUsing;
- for(j=0; j<pList->nId; j++){
- if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 ||
- columnIndex(pOther->pTab, pList->a[j].zName)<0 ){
- sqliteErrorMsg(pParse, "cannot join using column %s - column "
- "not present in both tables", pList->a[j].zName);
- return 1;
- }
- addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere);
- }
- }
- }
- return 0;
-}
-
-/*
-** Delete the given Select structure and all of its substructures.
-*/
-void sqliteSelectDelete(Select *p){
- if( p==0 ) return;
- sqliteExprListDelete(p->pEList);
- sqliteSrcListDelete(p->pSrc);
- sqliteExprDelete(p->pWhere);
- sqliteExprListDelete(p->pGroupBy);
- sqliteExprDelete(p->pHaving);
- sqliteExprListDelete(p->pOrderBy);
- sqliteSelectDelete(p->pPrior);
- sqliteFree(p->zSelect);
- sqliteFree(p);
-}
-
-/*
-** Delete the aggregate information from the parse structure.
-*/
-static void sqliteAggregateInfoReset(Parse *pParse){
- sqliteFree(pParse->aAgg);
- pParse->aAgg = 0;
- pParse->nAgg = 0;
- pParse->useAgg = 0;
-}
-
-/*
-** Insert code into "v" that will push the record on the top of the
-** stack into the sorter.
-*/
-static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
- char *zSortOrder;
- int i;
- zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
- if( zSortOrder==0 ) return;
- for(i=0; i<pOrderBy->nExpr; i++){
- int order = pOrderBy->a[i].sortOrder;
- int type;
- int c;
- if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
- type = SQLITE_SO_TEXT;
- }else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){
- type = SQLITE_SO_NUM;
- }else if( pParse->db->file_format>=4 ){
- type = sqliteExprType(pOrderBy->a[i].pExpr);
- }else{
- type = SQLITE_SO_NUM;
- }
- if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){
- c = type==SQLITE_SO_TEXT ? 'A' : '+';
- }else{
- c = type==SQLITE_SO_TEXT ? 'D' : '-';
- }
- zSortOrder[i] = c;
- sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
- }
- zSortOrder[pOrderBy->nExpr] = 0;
- sqliteVdbeOp3(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, P3_DYNAMIC);
- sqliteVdbeAddOp(v, OP_SortPut, 0, 0);
-}
-
-/*
-** This routine adds a P3 argument to the last VDBE opcode that was
-** inserted. The P3 argument added is a string suitable for the
-** OP_MakeKey or OP_MakeIdxKey opcodes. The string consists of
-** characters 't' or 'n' depending on whether or not the various
-** fields of the key to be generated should be treated as numeric
-** or as text. See the OP_MakeKey and OP_MakeIdxKey opcode
-** documentation for additional information about the P3 string.
-** See also the sqliteAddIdxKeyType() routine.
-*/
-void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
- int nColumn = pEList->nExpr;
- char *zType = sqliteMalloc( nColumn+1 );
- int i;
- if( zType==0 ) return;
- for(i=0; i<nColumn; i++){
- zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
- }
- zType[i] = 0;
- sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
-}
-
-/*
-** Add code to implement the OFFSET and LIMIT
-*/
-static void codeLimiter(
- Vdbe *v, /* Generate code into this VM */
- Select *p, /* The SELECT statement being coded */
- int iContinue, /* Jump here to skip the current record */
- int iBreak, /* Jump here to end the loop */
- int nPop /* Number of times to pop stack when jumping */
-){
- if( p->iOffset>=0 ){
- int addr = sqliteVdbeCurrentAddr(v) + 2;
- if( nPop>0 ) addr++;
- sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
- if( nPop>0 ){
- sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
- }
- sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
- }
- if( p->iLimit>=0 ){
- sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
- }
-}
-
-/*
-** This routine generates the code for the inside of the inner loop
-** of a SELECT.
-**
-** If srcTab and nColumn are both zero, then the pEList expressions
-** are evaluated in order to get the data for this row. If nColumn>0
-** then data is pulled from srcTab and pEList is used only to get the
-** datatypes for each column.
-*/
-static int selectInnerLoop(
- Parse *pParse, /* The parser context */
- Select *p, /* The complete select statement being coded */
- ExprList *pEList, /* List of values being extracted */
- int srcTab, /* Pull data from this table */
- int nColumn, /* Number of columns in the source table */
- ExprList *pOrderBy, /* If not NULL, sort results using this key */
- int distinct, /* If >=0, make sure results are distinct */
- int eDest, /* How to dispose of the results */
- int iParm, /* An argument to the disposal method */
- int iContinue, /* Jump here to continue with next row */
- int iBreak /* Jump here to break out of the inner loop */
-){
- Vdbe *v = pParse->pVdbe;
- int i;
- int hasDistinct; /* True if the DISTINCT keyword is present */
-
- if( v==0 ) return 0;
- assert( pEList!=0 );
-
- /* If there was a LIMIT clause on the SELECT statement, then do the check
- ** to see if this row should be output.
- */
- hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
- if( pOrderBy==0 && !hasDistinct ){
- codeLimiter(v, p, iContinue, iBreak, 0);
- }
-
- /* Pull the requested columns.
- */
- if( nColumn>0 ){
- for(i=0; i<nColumn; i++){
- sqliteVdbeAddOp(v, OP_Column, srcTab, i);
- }
- }else{
- nColumn = pEList->nExpr;
- for(i=0; i<pEList->nExpr; i++){
- sqliteExprCode(pParse, pEList->a[i].pExpr);
- }
- }
-
- /* If the DISTINCT keyword was present on the SELECT statement
- ** and this row has been seen before, then do not make this row
- ** part of the result.
- */
- if( hasDistinct ){
-#if NULL_ALWAYS_DISTINCT
- sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
-#endif
- sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
- if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList);
- sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
- if( pOrderBy==0 ){
- codeLimiter(v, p, iContinue, iBreak, nColumn);
- }
- }
-
- switch( eDest ){
- /* In this mode, write each query result to the key of the temporary
- ** table iParm.
- */
- case SRT_Union: {
- sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
- break;
- }
-
- /* Store the result as data using a unique key.
- */
- case SRT_Table:
- case SRT_TempTable: {
- sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
- if( pOrderBy ){
- pushOntoSorter(pParse, v, pOrderBy);
- }else{
- sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
- sqliteVdbeAddOp(v, OP_Pull, 1, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);
- }
- break;
- }
-
- /* Construct a record from the query result, but instead of
- ** saving that record, use it as a key to delete elements from
- ** the temporary table iParm.
- */
- case SRT_Except: {
- int addr;
- addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
- sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3);
- sqliteVdbeAddOp(v, OP_Delete, iParm, 0);
- break;
- }
-
- /* If we are creating a set for an "expr IN (SELECT ...)" construct,
- ** then there should be a single item on the stack. Write this
- ** item into the set table with bogus data.
- */
- case SRT_Set: {
- int addr1 = sqliteVdbeCurrentAddr(v);
- int addr2;
- assert( nColumn==1 );
- sqliteVdbeAddOp(v, OP_NotNull, -1, addr1+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- addr2 = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
- if( pOrderBy ){
- pushOntoSorter(pParse, v, pOrderBy);
- }else{
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
- }
- sqliteVdbeChangeP2(v, addr2, sqliteVdbeCurrentAddr(v));
- break;
- }
-
- /* If this is a scalar select that is part of an expression, then
- ** store the results in the appropriate memory cell and break out
- ** of the scan loop.
- */
- case SRT_Mem: {
- assert( nColumn==1 );
- if( pOrderBy ){
- pushOntoSorter(pParse, v, pOrderBy);
- }else{
- sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
- sqliteVdbeAddOp(v, OP_Goto, 0, iBreak);
- }
- break;
- }
-
- /* Send the data to the callback function.
- */
- case SRT_Callback:
- case SRT_Sorter: {
- if( pOrderBy ){
- sqliteVdbeAddOp(v, OP_SortMakeRec, nColumn, 0);
- pushOntoSorter(pParse, v, pOrderBy);
- }else{
- assert( eDest==SRT_Callback );
- sqliteVdbeAddOp(v, OP_Callback, nColumn, 0);
- }
- break;
- }
-
- /* Invoke a subroutine to handle the results. The subroutine itself
- ** is responsible for popping the results off of the stack.
- */
- case SRT_Subroutine: {
- if( pOrderBy ){
- sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
- pushOntoSorter(pParse, v, pOrderBy);
- }else{
- sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);
- }
- break;
- }
-
- /* Discard the results. This is used for SELECT statements inside
- ** the body of a TRIGGER. The purpose of such selects is to call
- ** user-defined functions that have side effects. We do not care
- ** about the actual results of the select.
- */
- default: {
- assert( eDest==SRT_Discard );
- sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
- break;
- }
- }
- return 0;
-}
-
-/*
-** If the inner loop was generated using a non-null pOrderBy argument,
-** then the results were placed in a sorter. After the loop is terminated
-** we need to run the sorter and output the results. The following
-** routine generates the code needed to do that.
-*/
-static void generateSortTail(
- Select *p, /* The SELECT statement */
- Vdbe *v, /* Generate code into this VDBE */
- int nColumn, /* Number of columns of data */
- int eDest, /* Write the sorted results here */
- int iParm /* Optional parameter associated with eDest */
-){
- int end1 = sqliteVdbeMakeLabel(v);
- int end2 = sqliteVdbeMakeLabel(v);
- int addr;
- if( eDest==SRT_Sorter ) return;
- sqliteVdbeAddOp(v, OP_Sort, 0, 0);
- addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
- codeLimiter(v, p, addr, end2, 1);
- switch( eDest ){
- case SRT_Callback: {
- sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
- break;
- }
- case SRT_Table:
- case SRT_TempTable: {
- sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
- sqliteVdbeAddOp(v, OP_Pull, 1, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);
- break;
- }
- case SRT_Set: {
- assert( nColumn==1 );
- sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
- break;
- }
- case SRT_Mem: {
- assert( nColumn==1 );
- sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
- sqliteVdbeAddOp(v, OP_Goto, 0, end1);
- break;
- }
- case SRT_Subroutine: {
- int i;
- for(i=0; i<nColumn; i++){
- sqliteVdbeAddOp(v, OP_Column, -1-i, i);
- }
- sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- break;
- }
- default: {
- /* Do nothing */
- break;
- }
- }
- sqliteVdbeAddOp(v, OP_Goto, 0, addr);
- sqliteVdbeResolveLabel(v, end2);
- sqliteVdbeAddOp(v, OP_Pop, 1, 0);
- sqliteVdbeResolveLabel(v, end1);
- sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
-}
-
-/*
-** Generate code that will tell the VDBE the datatypes of
-** columns in the result set.
-**
-** This routine only generates code if the "PRAGMA show_datatypes=on"
-** has been executed. The datatypes are reported out in the azCol
-** parameter to the callback function. The first N azCol[] entries
-** are the names of the columns, and the second N entries are the
-** datatypes for the columns.
-**
-** The "datatype" for a result that is a column of a type is the
-** datatype definition extracted from the CREATE TABLE statement.
-** The datatype for an expression is either TEXT or NUMERIC. The
-** datatype for a ROWID field is INTEGER.
-*/
-static void generateColumnTypes(
- Parse *pParse, /* Parser context */
- SrcList *pTabList, /* List of tables */
- ExprList *pEList /* Expressions defining the result set */
-){
- Vdbe *v = pParse->pVdbe;
- int i, j;
- for(i=0; i<pEList->nExpr; i++){
- Expr *p = pEList->a[i].pExpr;
- char *zType = 0;
- if( p==0 ) continue;
- if( p->op==TK_COLUMN && pTabList ){
- Table *pTab;
- int iCol = p->iColumn;
- for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
- assert( j<pTabList->nSrc );
- pTab = pTabList->a[j].pTab;
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
- if( iCol<0 ){
- zType = "INTEGER";
- }else{
- zType = pTab->aCol[iCol].zType;
- }
- }else{
- if( sqliteExprType(p)==SQLITE_SO_TEXT ){
- zType = "TEXT";
- }else{
- zType = "NUMERIC";
- }
- }
- sqliteVdbeOp3(v, OP_ColumnName, i + pEList->nExpr, 0, zType, 0);
- }
-}
-
-/*
-** Generate code that will tell the VDBE the names of columns
-** in the result set. This information is used to provide the
-** azCol[] values in the callback.
-*/
-static void generateColumnNames(
- Parse *pParse, /* Parser context */
- SrcList *pTabList, /* List of tables */
- ExprList *pEList /* Expressions defining the result set */
-){
- Vdbe *v = pParse->pVdbe;
- int i, j;
- sqlite *db = pParse->db;
- int fullNames, shortNames;
-
- assert( v!=0 );
- if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;
- pParse->colNamesSet = 1;
- fullNames = (db->flags & SQLITE_FullColNames)!=0;
- shortNames = (db->flags & SQLITE_ShortColNames)!=0;
- for(i=0; i<pEList->nExpr; i++){
- Expr *p;
- int p2 = i==pEList->nExpr-1;
- p = pEList->a[i].pExpr;
- if( p==0 ) continue;
- if( pEList->a[i].zName ){
- char *zName = pEList->a[i].zName;
- sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
- continue;
- }
- if( p->op==TK_COLUMN && pTabList ){
- Table *pTab;
- char *zCol;
- int iCol = p->iColumn;
- for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
- assert( j<pTabList->nSrc );
- pTab = pTabList->a[j].pTab;
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
- if( iCol<0 ){
- zCol = "_ROWID_";
- }else{
- zCol = pTab->aCol[iCol].zName;
- }
- if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
- int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
- sqliteVdbeCompressSpace(v, addr);
- }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
- char *zName = 0;
- char *zTab;
-
- zTab = pTabList->a[j].zAlias;
- if( fullNames || zTab==0 ) zTab = pTab->zName;
- sqliteSetString(&zName, zTab, ".", zCol, 0);
- sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, P3_DYNAMIC);
- }else{
- sqliteVdbeOp3(v, OP_ColumnName, i, p2, zCol, 0);
- }
- }else if( p->span.z && p->span.z[0] ){
- int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
- sqliteVdbeCompressSpace(v, addr);
- }else{
- char zName[30];
- assert( p->op!=TK_COLUMN || pTabList==0 );
- sprintf(zName, "column%d", i+1);
- sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
- }
- }
-}
-
-/*
-** Name of the connection operator, used for error messages.
-*/
-static const char *selectOpName(int id){
- char *z;
- switch( id ){
- case TK_ALL: z = "UNION ALL"; break;
- case TK_INTERSECT: z = "INTERSECT"; break;
- case TK_EXCEPT: z = "EXCEPT"; break;
- default: z = "UNION"; break;
- }
- return z;
-}
-
-/*
-** Forward declaration
-*/
-static int fillInColumnList(Parse*, Select*);
-
-/*
-** Given a SELECT statement, generate a Table structure that describes
-** the result set of that SELECT.
-*/
-Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
- Table *pTab;
- int i, j;
- ExprList *pEList;
- Column *aCol;
-
- if( fillInColumnList(pParse, pSelect) ){
- return 0;
- }
- pTab = sqliteMalloc( sizeof(Table) );
- if( pTab==0 ){
- return 0;
- }
- pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0;
- pEList = pSelect->pEList;
- pTab->nCol = pEList->nExpr;
- assert( pTab->nCol>0 );
- pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
- for(i=0; i<pTab->nCol; i++){
- Expr *p, *pR;
- if( pEList->a[i].zName ){
- aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
- }else if( (p=pEList->a[i].pExpr)->op==TK_DOT
- && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
- int cnt;
- sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
- for(j=cnt=0; j<i; j++){
- if( sqliteStrICmp(aCol[j].zName, aCol[i].zName)==0 ){
- int n;
- char zBuf[30];
- sprintf(zBuf,"_%d",++cnt);
- n = strlen(zBuf);
- sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf, n,0);
- j = -1;
- }
- }
- }else if( p->span.z && p->span.z[0] ){
- sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
- }else{
- char zBuf[30];
- sprintf(zBuf, "column%d", i+1);
- aCol[i].zName = sqliteStrDup(zBuf);
- }
- sqliteDequote(aCol[i].zName);
- }
- pTab->iPKey = -1;
- return pTab;
-}
-
-/*
-** For the given SELECT statement, do three things.
-**
-** (1) Fill in the pTabList->a[].pTab fields in the SrcList that
-** defines the set of tables that should be scanned. For views,
-** fill pTabList->a[].pSelect with a copy of the SELECT statement
-** that implements the view. A copy is made of the view's SELECT
-** statement so that we can freely modify or delete that statement
-** without worrying about messing up the presistent representation
-** of the view.
-**
-** (2) Add terms to the WHERE clause to accomodate the NATURAL keyword
-** on joins and the ON and USING clause of joins.
-**
-** (3) Scan the list of columns in the result set (pEList) looking
-** for instances of the "*" operator or the TABLE.* operator.
-** If found, expand each "*" to be every column in every table
-** and TABLE.* to be every column in TABLE.
-**
-** Return 0 on success. If there are problems, leave an error message
-** in pParse and return non-zero.
-*/
-static int fillInColumnList(Parse *pParse, Select *p){
- int i, j, k, rc;
- SrcList *pTabList;
- ExprList *pEList;
- Table *pTab;
-
- if( p==0 || p->pSrc==0 ) return 1;
- pTabList = p->pSrc;
- pEList = p->pEList;
-
- /* Look up every table in the table list.
- */
- for(i=0; i<pTabList->nSrc; i++){
- if( pTabList->a[i].pTab ){
- /* This routine has run before! No need to continue */
- return 0;
- }
- if( pTabList->a[i].zName==0 ){
- /* A sub-query in the FROM clause of a SELECT */
- assert( pTabList->a[i].pSelect!=0 );
- if( pTabList->a[i].zAlias==0 ){
- char zFakeName[60];
- sprintf(zFakeName, "sqlite_subquery_%p_",
- (void*)pTabList->a[i].pSelect);
- sqliteSetString(&pTabList->a[i].zAlias, zFakeName, 0);
- }
- pTabList->a[i].pTab = pTab =
- sqliteResultSetOfSelect(pParse, pTabList->a[i].zAlias,
- pTabList->a[i].pSelect);
- if( pTab==0 ){
- return 1;
- }
- /* The isTransient flag indicates that the Table structure has been
- ** dynamically allocated and may be freed at any time. In other words,
- ** pTab is not pointing to a persistent table structure that defines
- ** part of the schema. */
- pTab->isTransient = 1;
- }else{
- /* An ordinary table or view name in the FROM clause */
- pTabList->a[i].pTab = pTab =
- sqliteLocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase);
- if( pTab==0 ){
- return 1;
- }
- if( pTab->pSelect ){
- /* We reach here if the named table is a really a view */
- if( sqliteViewGetColumnNames(pParse, pTab) ){
- return 1;
- }
- /* If pTabList->a[i].pSelect!=0 it means we are dealing with a
- ** view within a view. The SELECT structure has already been
- ** copied by the outer view so we can skip the copy step here
- ** in the inner view.
- */
- if( pTabList->a[i].pSelect==0 ){
- pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect);
- }
- }
- }
- }
-
- /* Process NATURAL keywords, and ON and USING clauses of joins.
- */
- if( sqliteProcessJoin(pParse, p) ) return 1;
-
- /* For every "*" that occurs in the column list, insert the names of
- ** all columns in all tables. And for every TABLE.* insert the names
- ** of all columns in TABLE. The parser inserted a special expression
- ** with the TK_ALL operator for each "*" that it found in the column list.
- ** The following code just has to locate the TK_ALL expressions and expand
- ** each one to the list of all columns in all tables.
- **
- ** The first loop just checks to see if there are any "*" operators
- ** that need expanding.
- */
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = pEList->a[k].pExpr;
- if( pE->op==TK_ALL ) break;
- if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
- && pE->pLeft && pE->pLeft->op==TK_ID ) break;
- }
- rc = 0;
- if( k<pEList->nExpr ){
- /*
- ** If we get here it means the result set contains one or more "*"
- ** operators that need to be expanded. Loop through each expression
- ** in the result set and expand them one by one.
- */
- struct ExprList_item *a = pEList->a;
- ExprList *pNew = 0;
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = a[k].pExpr;
- if( pE->op!=TK_ALL &&
- (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
- /* This particular expression does not need to be expanded.
- */
- pNew = sqliteExprListAppend(pNew, a[k].pExpr, 0);
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- a[k].pExpr = 0;
- a[k].zName = 0;
- }else{
- /* This expression is a "*" or a "TABLE.*" and needs to be
- ** expanded. */
- int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName; /* text of name of TABLE */
- if( pE->op==TK_DOT && pE->pLeft ){
- zTName = sqliteTableNameFromToken(&pE->pLeft->token);
- }else{
- zTName = 0;
- }
- for(i=0; i<pTabList->nSrc; i++){
- Table *pTab = pTabList->a[i].pTab;
- char *zTabName = pTabList->a[i].zAlias;
- if( zTabName==0 || zTabName[0]==0 ){
- zTabName = pTab->zName;
- }
- if( zTName && (zTabName==0 || zTabName[0]==0 ||
- sqliteStrICmp(zTName, zTabName)!=0) ){
- continue;
- }
- tableSeen = 1;
- for(j=0; j<pTab->nCol; j++){
- Expr *pExpr, *pLeft, *pRight;
- char *zName = pTab->aCol[j].zName;
-
- if( i>0 && (pTabList->a[i-1].jointype & JT_NATURAL)!=0 &&
- columnIndex(pTabList->a[i-1].pTab, zName)>=0 ){
- /* In a NATURAL join, omit the join columns from the
- ** table on the right */
- continue;
- }
- if( i>0 && sqliteIdListIndex(pTabList->a[i-1].pUsing, zName)>=0 ){
- /* In a join with a USING clause, omit columns in the
- ** using clause from the table on the right. */
- continue;
- }
- pRight = sqliteExpr(TK_ID, 0, 0, 0);
- if( pRight==0 ) break;
- pRight->token.z = zName;
- pRight->token.n = strlen(zName);
- pRight->token.dyn = 0;
- if( zTabName && pTabList->nSrc>1 ){
- pLeft = sqliteExpr(TK_ID, 0, 0, 0);
- pExpr = sqliteExpr(TK_DOT, pLeft, pRight, 0);
- if( pExpr==0 ) break;
- pLeft->token.z = zTabName;
- pLeft->token.n = strlen(zTabName);
- pLeft->token.dyn = 0;
- sqliteSetString((char**)&pExpr->span.z, zTabName, ".", zName, 0);
- pExpr->span.n = strlen(pExpr->span.z);
- pExpr->span.dyn = 1;
- pExpr->token.z = 0;
- pExpr->token.n = 0;
- pExpr->token.dyn = 0;
- }else{
- pExpr = pRight;
- pExpr->span = pExpr->token;
- }
- pNew = sqliteExprListAppend(pNew, pExpr, 0);
- }
- }
- if( !tableSeen ){
- if( zTName ){
- sqliteErrorMsg(pParse, "no such table: %s", zTName);
- }else{
- sqliteErrorMsg(pParse, "no tables specified");
- }
- rc = 1;
- }
- sqliteFree(zTName);
- }
- }
- sqliteExprListDelete(pEList);
- p->pEList = pNew;
- }
- return rc;
-}
-
-/*
-** This routine recursively unlinks the Select.pSrc.a[].pTab pointers
-** in a select structure. It just sets the pointers to NULL. This
-** routine is recursive in the sense that if the Select.pSrc.a[].pSelect
-** pointer is not NULL, this routine is called recursively on that pointer.
-**
-** This routine is called on the Select structure that defines a
-** VIEW in order to undo any bindings to tables. This is necessary
-** because those tables might be DROPed by a subsequent SQL command.
-** If the bindings are not removed, then the Select.pSrc->a[].pTab field
-** will be left pointing to a deallocated Table structure after the
-** DROP and a coredump will occur the next time the VIEW is used.
-*/
-void sqliteSelectUnbind(Select *p){
- int i;
- SrcList *pSrc = p->pSrc;
- Table *pTab;
- if( p==0 ) return;
- for(i=0; i<pSrc->nSrc; i++){
- if( (pTab = pSrc->a[i].pTab)!=0 ){
- if( pTab->isTransient ){
- sqliteDeleteTable(0, pTab);
- }
- pSrc->a[i].pTab = 0;
- if( pSrc->a[i].pSelect ){
- sqliteSelectUnbind(pSrc->a[i].pSelect);
- }
- }
- }
-}
-
-/*
-** This routine associates entries in an ORDER BY expression list with
-** columns in a result. For each ORDER BY expression, the opcode of
-** the top-level node is changed to TK_COLUMN and the iColumn value of
-** the top-level node is filled in with column number and the iTable
-** value of the top-level node is filled with iTable parameter.
-**
-** If there are prior SELECT clauses, they are processed first. A match
-** in an earlier SELECT takes precedence over a later SELECT.
-**
-** Any entry that does not match is flagged as an error. The number
-** of errors is returned.
-**
-** This routine does NOT correctly initialize the Expr.dataType field
-** of the ORDER BY expressions. The multiSelectSortOrder() routine
-** must be called to do that after the individual select statements
-** have all been analyzed. This routine is unable to compute Expr.dataType
-** because it must be called before the individual select statements
-** have been analyzed.
-*/
-static int matchOrderbyToColumn(
- Parse *pParse, /* A place to leave error messages */
- Select *pSelect, /* Match to result columns of this SELECT */
- ExprList *pOrderBy, /* The ORDER BY values to match against columns */
- int iTable, /* Insert this value in iTable */
- int mustComplete /* If TRUE all ORDER BYs must match */
-){
- int nErr = 0;
- int i, j;
- ExprList *pEList;
-
- if( pSelect==0 || pOrderBy==0 ) return 1;
- if( mustComplete ){
- for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
- }
- if( fillInColumnList(pParse, pSelect) ){
- return 1;
- }
- if( pSelect->pPrior ){
- if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){
- return 1;
- }
- }
- pEList = pSelect->pEList;
- for(i=0; i<pOrderBy->nExpr; i++){
- Expr *pE = pOrderBy->a[i].pExpr;
- int iCol = -1;
- if( pOrderBy->a[i].done ) continue;
- if( sqliteExprIsInteger(pE, &iCol) ){
- if( iCol<=0 || iCol>pEList->nExpr ){
- sqliteErrorMsg(pParse,
- "ORDER BY position %d should be between 1 and %d",
- iCol, pEList->nExpr);
- nErr++;
- break;
- }
- if( !mustComplete ) continue;
- iCol--;
- }
- for(j=0; iCol<0 && j<pEList->nExpr; j++){
- if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){
- char *zName, *zLabel;
- zName = pEList->a[j].zName;
- assert( pE->token.z );
- zLabel = sqliteStrNDup(pE->token.z, pE->token.n);
- sqliteDequote(zLabel);
- if( sqliteStrICmp(zName, zLabel)==0 ){
- iCol = j;
- }
- sqliteFree(zLabel);
- }
- if( iCol<0 && sqliteExprCompare(pE, pEList->a[j].pExpr) ){
- iCol = j;
- }
- }
- if( iCol>=0 ){
- pE->op = TK_COLUMN;
- pE->iColumn = iCol;
- pE->iTable = iTable;
- pOrderBy->a[i].done = 1;
- }
- if( iCol<0 && mustComplete ){
- sqliteErrorMsg(pParse,
- "ORDER BY term number %d does not match any result column", i+1);
- nErr++;
- break;
- }
- }
- return nErr;
-}
-
-/*
-** Get a VDBE for the given parser context. Create a new one if necessary.
-** If an error occurs, return NULL and leave a message in pParse.
-*/
-Vdbe *sqliteGetVdbe(Parse *pParse){
- Vdbe *v = pParse->pVdbe;
- if( v==0 ){
- v = pParse->pVdbe = sqliteVdbeCreate(pParse->db);
- }
- return v;
-}
-
-/*
-** This routine sets the Expr.dataType field on all elements of
-** the pOrderBy expression list. The pOrderBy list will have been
-** set up by matchOrderbyToColumn(). Hence each expression has
-** a TK_COLUMN as its root node. The Expr.iColumn refers to a
-** column in the result set. The datatype is set to SQLITE_SO_TEXT
-** if the corresponding column in p and every SELECT to the left of
-** p has a datatype of SQLITE_SO_TEXT. If the cooressponding column
-** in p or any of the left SELECTs is SQLITE_SO_NUM, then the datatype
-** of the order-by expression is set to SQLITE_SO_NUM.
-**
-** Examples:
-**
-** CREATE TABLE one(a INTEGER, b TEXT);
-** CREATE TABLE two(c VARCHAR(5), d FLOAT);
-**
-** SELECT b, b FROM one UNION SELECT d, c FROM two ORDER BY 1, 2;
-**
-** The primary sort key will use SQLITE_SO_NUM because the "d" in
-** the second SELECT is numeric. The 1st column of the first SELECT
-** is text but that does not matter because a numeric always overrides
-** a text.
-**
-** The secondary key will use the SQLITE_SO_TEXT sort order because
-** both the (second) "b" in the first SELECT and the "c" in the second
-** SELECT have a datatype of text.
-*/
-static void multiSelectSortOrder(Select *p, ExprList *pOrderBy){
- int i;
- ExprList *pEList;
- if( pOrderBy==0 ) return;
- if( p==0 ){
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].pExpr->dataType = SQLITE_SO_TEXT;
- }
- return;
- }
- multiSelectSortOrder(p->pPrior, pOrderBy);
- pEList = p->pEList;
- for(i=0; i<pOrderBy->nExpr; i++){
- Expr *pE = pOrderBy->a[i].pExpr;
- if( pE->dataType==SQLITE_SO_NUM ) continue;
- assert( pE->iColumn>=0 );
- if( pEList->nExpr>pE->iColumn ){
- pE->dataType = sqliteExprType(pEList->a[pE->iColumn].pExpr);
- }
- }
-}
-
-/*
-** Compute the iLimit and iOffset fields of the SELECT based on the
-** nLimit and nOffset fields. nLimit and nOffset hold the integers
-** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords. Or that hold -1 and 0 if those keywords are omitted.
-** iLimit and iOffset are the integer memory register numbers for
-** counters used to compute the limit and offset. If there is no
-** limit and/or offset, then iLimit and iOffset are negative.
-**
-** This routine changes the values if iLimit and iOffset only if
-** a limit or offset is defined by nLimit and nOffset. iLimit and
-** iOffset should have been preset to appropriate default values
-** (usually but not always -1) prior to calling this routine.
-** Only if nLimit>=0 or nOffset>0 do the limit registers get
-** redefined. The UNION ALL operator uses this property to force
-** the reuse of the same limit and offset registers across multiple
-** SELECT statements.
-*/
-static void computeLimitRegisters(Parse *pParse, Select *p){
- /*
- ** If the comparison is p->nLimit>0 then "LIMIT 0" shows
- ** all rows. It is the same as no limit. If the comparision is
- ** p->nLimit>=0 then "LIMIT 0" show no rows at all.
- ** "LIMIT -1" always shows all rows. There is some
- ** contraversy about what the correct behavior should be.
- ** The current implementation interprets "LIMIT 0" to mean
- ** no rows.
- */
- if( p->nLimit>=0 ){
- int iMem = pParse->nMem++;
- Vdbe *v = sqliteGetVdbe(pParse);
- if( v==0 ) return;
- sqliteVdbeAddOp(v, OP_Integer, -p->nLimit, 0);
- sqliteVdbeAddOp(v, OP_MemStore, iMem, 1);
- p->iLimit = iMem;
- }
- if( p->nOffset>0 ){
- int iMem = pParse->nMem++;
- Vdbe *v = sqliteGetVdbe(pParse);
- if( v==0 ) return;
- sqliteVdbeAddOp(v, OP_Integer, -p->nOffset, 0);
- sqliteVdbeAddOp(v, OP_MemStore, iMem, 1);
- p->iOffset = iMem;
- }
-}
-
-/*
-** This routine is called to process a query that is really the union
-** or intersection of two or more separate queries.
-**
-** "p" points to the right-most of the two queries. the query on the
-** left is p->pPrior. The left query could also be a compound query
-** in which case this routine will be called recursively.
-**
-** The results of the total query are to be written into a destination
-** of type eDest with parameter iParm.
-**
-** Example 1: Consider a three-way compound SQL statement.
-**
-** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
-**
-** This statement is parsed up as follows:
-**
-** SELECT c FROM t3
-** |
-** `-----> SELECT b FROM t2
-** |
-** `------> SELECT a FROM t1
-**
-** The arrows in the diagram above represent the Select.pPrior pointer.
-** So if this routine is called with p equal to the t3 query, then
-** pPrior will be the t2 query. p->op will be TK_UNION in this case.
-**
-** Notice that because of the way SQLite parses compound SELECTs, the
-** individual selects always group from left to right.
-*/
-static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
- int rc; /* Success code from a subroutine */
- Select *pPrior; /* Another SELECT immediately to our left */
- Vdbe *v; /* Generate code to this VDBE */
-
- /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
- ** the last SELECT in the series may have an ORDER BY or LIMIT.
- */
- if( p==0 || p->pPrior==0 ) return 1;
- pPrior = p->pPrior;
- if( pPrior->pOrderBy ){
- sqliteErrorMsg(pParse,"ORDER BY clause should come after %s not before",
- selectOpName(p->op));
- return 1;
- }
- if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){
- sqliteErrorMsg(pParse,"LIMIT clause should come after %s not before",
- selectOpName(p->op));
- return 1;
- }
-
- /* Make sure we have a valid query engine. If not, create a new one.
- */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) return 1;
-
- /* Create the destination temporary table if necessary
- */
- if( eDest==SRT_TempTable ){
- sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
- eDest = SRT_Table;
- }
-
- /* Generate code for the left and right SELECT statements.
- */
- switch( p->op ){
- case TK_ALL: {
- if( p->pOrderBy==0 ){
- pPrior->nLimit = p->nLimit;
- pPrior->nOffset = p->nOffset;
- rc = sqliteSelect(pParse, pPrior, eDest, iParm, 0, 0, 0);
- if( rc ) return rc;
- p->pPrior = 0;
- p->iLimit = pPrior->iLimit;
- p->iOffset = pPrior->iOffset;
- p->nLimit = -1;
- p->nOffset = 0;
- rc = sqliteSelect(pParse, p, eDest, iParm, 0, 0, 0);
- p->pPrior = pPrior;
- if( rc ) return rc;
- break;
- }
- /* For UNION ALL ... ORDER BY fall through to the next case */
- }
- case TK_EXCEPT:
- case TK_UNION: {
- int unionTab; /* Cursor number of the temporary table holding result */
- int op; /* One of the SRT_ operations to apply to self */
- int priorOp; /* The SRT_ operation to apply to prior selects */
- int nLimit, nOffset; /* Saved values of p->nLimit and p->nOffset */
- ExprList *pOrderBy; /* The ORDER BY clause for the right SELECT */
-
- priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union;
- if( eDest==priorOp && p->pOrderBy==0 && p->nLimit<0 && p->nOffset==0 ){
- /* We can reuse a temporary table generated by a SELECT to our
- ** right.
- */
- unionTab = iParm;
- }else{
- /* We will need to create our own temporary table to hold the
- ** intermediate results.
- */
- unionTab = pParse->nTab++;
- if( p->pOrderBy
- && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){
- return 1;
- }
- if( p->op!=TK_ALL ){
- sqliteVdbeAddOp(v, OP_OpenTemp, unionTab, 1);
- sqliteVdbeAddOp(v, OP_KeyAsData, unionTab, 1);
- }else{
- sqliteVdbeAddOp(v, OP_OpenTemp, unionTab, 0);
- }
- }
-
- /* Code the SELECT statements to our left
- */
- rc = sqliteSelect(pParse, pPrior, priorOp, unionTab, 0, 0, 0);
- if( rc ) return rc;
-
- /* Code the current SELECT statement
- */
- switch( p->op ){
- case TK_EXCEPT: op = SRT_Except; break;
- case TK_UNION: op = SRT_Union; break;
- case TK_ALL: op = SRT_Table; break;
- }
- p->pPrior = 0;
- pOrderBy = p->pOrderBy;
- p->pOrderBy = 0;
- nLimit = p->nLimit;
- p->nLimit = -1;
- nOffset = p->nOffset;
- p->nOffset = 0;
- rc = sqliteSelect(pParse, p, op, unionTab, 0, 0, 0);
- p->pPrior = pPrior;
- p->pOrderBy = pOrderBy;
- p->nLimit = nLimit;
- p->nOffset = nOffset;
- if( rc ) return rc;
-
- /* Convert the data in the temporary table into whatever form
- ** it is that we currently need.
- */
- if( eDest!=priorOp || unionTab!=iParm ){
- int iCont, iBreak, iStart;
- assert( p->pEList );
- if( eDest==SRT_Callback ){
- generateColumnNames(pParse, 0, p->pEList);
- generateColumnTypes(pParse, p->pSrc, p->pEList);
- }
- iBreak = sqliteVdbeMakeLabel(v);
- iCont = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak);
- computeLimitRegisters(pParse, p);
- iStart = sqliteVdbeCurrentAddr(v);
- multiSelectSortOrder(p, p->pOrderBy);
- rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
- p->pOrderBy, -1, eDest, iParm,
- iCont, iBreak);
- if( rc ) return 1;
- sqliteVdbeResolveLabel(v, iCont);
- sqliteVdbeAddOp(v, OP_Next, unionTab, iStart);
- sqliteVdbeResolveLabel(v, iBreak);
- sqliteVdbeAddOp(v, OP_Close, unionTab, 0);
- if( p->pOrderBy ){
- generateSortTail(p, v, p->pEList->nExpr, eDest, iParm);
- }
- }
- break;
- }
- case TK_INTERSECT: {
- int tab1, tab2;
- int iCont, iBreak, iStart;
- int nLimit, nOffset;
-
- /* INTERSECT is different from the others since it requires
- ** two temporary tables. Hence it has its own case. Begin
- ** by allocating the tables we will need.
- */
- tab1 = pParse->nTab++;
- tab2 = pParse->nTab++;
- if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){
- return 1;
- }
- sqliteVdbeAddOp(v, OP_OpenTemp, tab1, 1);
- sqliteVdbeAddOp(v, OP_KeyAsData, tab1, 1);
-
- /* Code the SELECTs to our left into temporary table "tab1".
- */
- rc = sqliteSelect(pParse, pPrior, SRT_Union, tab1, 0, 0, 0);
- if( rc ) return rc;
-
- /* Code the current SELECT into temporary table "tab2"
- */
- sqliteVdbeAddOp(v, OP_OpenTemp, tab2, 1);
- sqliteVdbeAddOp(v, OP_KeyAsData, tab2, 1);
- p->pPrior = 0;
- nLimit = p->nLimit;
- p->nLimit = -1;
- nOffset = p->nOffset;
- p->nOffset = 0;
- rc = sqliteSelect(pParse, p, SRT_Union, tab2, 0, 0, 0);
- p->pPrior = pPrior;
- p->nLimit = nLimit;
- p->nOffset = nOffset;
- if( rc ) return rc;
-
- /* Generate code to take the intersection of the two temporary
- ** tables.
- */
- assert( p->pEList );
- if( eDest==SRT_Callback ){
- generateColumnNames(pParse, 0, p->pEList);
- generateColumnTypes(pParse, p->pSrc, p->pEList);
- }
- iBreak = sqliteVdbeMakeLabel(v);
- iCont = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak);
- computeLimitRegisters(pParse, p);
- iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0);
- sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont);
- multiSelectSortOrder(p, p->pOrderBy);
- rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
- p->pOrderBy, -1, eDest, iParm,
- iCont, iBreak);
- if( rc ) return 1;
- sqliteVdbeResolveLabel(v, iCont);
- sqliteVdbeAddOp(v, OP_Next, tab1, iStart);
- sqliteVdbeResolveLabel(v, iBreak);
- sqliteVdbeAddOp(v, OP_Close, tab2, 0);
- sqliteVdbeAddOp(v, OP_Close, tab1, 0);
- if( p->pOrderBy ){
- generateSortTail(p, v, p->pEList->nExpr, eDest, iParm);
- }
- break;
- }
- }
- assert( p->pEList && pPrior->pEList );
- if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
- sqliteErrorMsg(pParse, "SELECTs to the left and right of %s"
- " do not have the same number of result columns", selectOpName(p->op));
- return 1;
- }
- return 0;
-}
-
-/*
-** Scan through the expression pExpr. Replace every reference to
-** a column in table number iTable with a copy of the iColumn-th
-** entry in pEList. (But leave references to the ROWID column
-** unchanged.)
-**
-** This routine is part of the flattening procedure. A subquery
-** whose result set is defined by pEList appears as entry in the
-** FROM clause of a SELECT such that the VDBE cursor assigned to that
-** FORM clause entry is iTable. This routine make the necessary
-** changes to pExpr so that it refers directly to the source table
-** of the subquery rather the result set of the subquery.
-*/
-static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
-static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
- if( pExpr==0 ) return;
- if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
- if( pExpr->iColumn<0 ){
- pExpr->op = TK_NULL;
- }else{
- Expr *pNew;
- assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
- assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
- pNew = pEList->a[pExpr->iColumn].pExpr;
- assert( pNew!=0 );
- pExpr->op = pNew->op;
- pExpr->dataType = pNew->dataType;
- assert( pExpr->pLeft==0 );
- pExpr->pLeft = sqliteExprDup(pNew->pLeft);
- assert( pExpr->pRight==0 );
- pExpr->pRight = sqliteExprDup(pNew->pRight);
- assert( pExpr->pList==0 );
- pExpr->pList = sqliteExprListDup(pNew->pList);
- pExpr->iTable = pNew->iTable;
- pExpr->iColumn = pNew->iColumn;
- pExpr->iAgg = pNew->iAgg;
- sqliteTokenCopy(&pExpr->token, &pNew->token);
- sqliteTokenCopy(&pExpr->span, &pNew->span);
- }
- }else{
- substExpr(pExpr->pLeft, iTable, pEList);
- substExpr(pExpr->pRight, iTable, pEList);
- substExprList(pExpr->pList, iTable, pEList);
- }
-}
-static void
-substExprList(ExprList *pList, int iTable, ExprList *pEList){
- int i;
- if( pList==0 ) return;
- for(i=0; i<pList->nExpr; i++){
- substExpr(pList->a[i].pExpr, iTable, pEList);
- }
-}
-
-/*
-** This routine attempts to flatten subqueries in order to speed
-** execution. It returns 1 if it makes changes and 0 if no flattening
-** occurs.
-**
-** To understand the concept of flattening, consider the following
-** query:
-**
-** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
-**
-** The default way of implementing this query is to execute the
-** subquery first and store the results in a temporary table, then
-** run the outer query on that temporary table. This requires two
-** passes over the data. Furthermore, because the temporary table
-** has no indices, the WHERE clause on the outer query cannot be
-** optimized.
-**
-** This routine attempts to rewrite queries such as the above into
-** a single flat select, like this:
-**
-** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
-**
-** The code generated for this simpification gives the same result
-** but only has to scan the data once. And because indices might
-** exist on the table t1, a complete scan of the data might be
-** avoided.
-**
-** Flattening is only attempted if all of the following are true:
-**
-** (1) The subquery and the outer query do not both use aggregates.
-**
-** (2) The subquery is not an aggregate or the outer query is not a join.
-**
-** (3) The subquery is not the right operand of a left outer join, or
-** the subquery is not itself a join. (Ticket #306)
-**
-** (4) The subquery is not DISTINCT or the outer query is not a join.
-**
-** (5) The subquery is not DISTINCT or the outer query does not use
-** aggregates.
-**
-** (6) The subquery does not use aggregates or the outer query is not
-** DISTINCT.
-**
-** (7) The subquery has a FROM clause.
-**
-** (8) The subquery does not use LIMIT or the outer query is not a join.
-**
-** (9) The subquery does not use LIMIT or the outer query does not use
-** aggregates.
-**
-** (10) The subquery does not use aggregates or the outer query does not
-** use LIMIT.
-**
-** (11) The subquery and the outer query do not both have ORDER BY clauses.
-**
-** (12) The subquery is not the right term of a LEFT OUTER JOIN or the
-** subquery has no WHERE clause. (added by ticket #350)
-**
-** In this routine, the "p" parameter is a pointer to the outer query.
-** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
-** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
-**
-** If flattening is not attempted, this routine is a no-op and returns 0.
-** If flattening is attempted this routine returns 1.
-**
-** All of the expression analysis must occur on both the outer query and
-** the subquery before this routine runs.
-*/
-static int flattenSubquery(
- Parse *pParse, /* The parsing context */
- Select *p, /* The parent or outer SELECT statement */
- int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
- int isAgg, /* True if outer SELECT uses aggregate functions */
- int subqueryIsAgg /* True if the subquery uses aggregate functions */
-){
- Select *pSub; /* The inner query or "subquery" */
- SrcList *pSrc; /* The FROM clause of the outer query */
- SrcList *pSubSrc; /* The FROM clause of the subquery */
- ExprList *pList; /* The result set of the outer query */
- int iParent; /* VDBE cursor number of the pSub result set temp table */
- int i;
- Expr *pWhere;
-
- /* Check to see if flattening is permitted. Return 0 if not.
- */
- if( p==0 ) return 0;
- pSrc = p->pSrc;
- assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
- pSub = pSrc->a[iFrom].pSelect;
- assert( pSub!=0 );
- if( isAgg && subqueryIsAgg ) return 0;
- if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
- pSubSrc = pSub->pSrc;
- assert( pSubSrc );
- if( pSubSrc->nSrc==0 ) return 0;
- if( (pSub->isDistinct || pSub->nLimit>=0) && (pSrc->nSrc>1 || isAgg) ){
- return 0;
- }
- if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;
- if( p->pOrderBy && pSub->pOrderBy ) return 0;
-
- /* Restriction 3: If the subquery is a join, make sure the subquery is
- ** not used as the right operand of an outer join. Examples of why this
- ** is not allowed:
- **
- ** t1 LEFT OUTER JOIN (t2 JOIN t3)
- **
- ** If we flatten the above, we would get
- **
- ** (t1 LEFT OUTER JOIN t2) JOIN t3
- **
- ** which is not at all the same thing.
- */
- if( pSubSrc->nSrc>1 && iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 ){
- return 0;
- }
-
- /* Restriction 12: If the subquery is the right operand of a left outer
- ** join, make sure the subquery has no WHERE clause.
- ** An examples of why this is not allowed:
- **
- ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
- **
- ** If we flatten the above, we would get
- **
- ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
- **
- ** But the t2.x>0 test will always fail on a NULL row of t2, which
- ** effectively converts the OUTER JOIN into an INNER JOIN.
- */
- if( iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0
- && pSub->pWhere!=0 ){
- return 0;
- }
-
- /* If we reach this point, it means flattening is permitted for the
- ** iFrom-th entry of the FROM clause in the outer query.
- */
-
- /* Move all of the FROM elements of the subquery into the
- ** the FROM clause of the outer query. Before doing this, remember
- ** the cursor number for the original outer query FROM element in
- ** iParent. The iParent cursor will never be used. Subsequent code
- ** will scan expressions looking for iParent references and replace
- ** those references with expressions that resolve to the subquery FROM
- ** elements we are now copying in.
- */
- iParent = pSrc->a[iFrom].iCursor;
- {
- int nSubSrc = pSubSrc->nSrc;
- int jointype = pSrc->a[iFrom].jointype;
-
- if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){
- sqliteDeleteTable(0, pSrc->a[iFrom].pTab);
- }
- sqliteFree(pSrc->a[iFrom].zDatabase);
- sqliteFree(pSrc->a[iFrom].zName);
- sqliteFree(pSrc->a[iFrom].zAlias);
- if( nSubSrc>1 ){
- int extra = nSubSrc - 1;
- for(i=1; i<nSubSrc; i++){
- pSrc = sqliteSrcListAppend(pSrc, 0, 0);
- }
- p->pSrc = pSrc;
- for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){
- pSrc->a[i] = pSrc->a[i-extra];
- }
- }
- for(i=0; i<nSubSrc; i++){
- pSrc->a[i+iFrom] = pSubSrc->a[i];
- memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
- }
- pSrc->a[iFrom+nSubSrc-1].jointype = jointype;
- }
-
- /* Now begin substituting subquery result set expressions for
- ** references to the iParent in the outer query.
- **
- ** Example:
- **
- ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
- ** \ \_____________ subquery __________/ /
- ** \_____________________ outer query ______________________________/
- **
- ** We look at every expression in the outer query and every place we see
- ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
- */
- substExprList(p->pEList, iParent, pSub->pEList);
- pList = p->pEList;
- for(i=0; i<pList->nExpr; i++){
- Expr *pExpr;
- if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){
- pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n);
- }
- }
- if( isAgg ){
- substExprList(p->pGroupBy, iParent, pSub->pEList);
- substExpr(p->pHaving, iParent, pSub->pEList);
- }
- if( pSub->pOrderBy ){
- assert( p->pOrderBy==0 );
- p->pOrderBy = pSub->pOrderBy;
- pSub->pOrderBy = 0;
- }else if( p->pOrderBy ){
- substExprList(p->pOrderBy, iParent, pSub->pEList);
- }
- if( pSub->pWhere ){
- pWhere = sqliteExprDup(pSub->pWhere);
- }else{
- pWhere = 0;
- }
- if( subqueryIsAgg ){
- assert( p->pHaving==0 );
- p->pHaving = p->pWhere;
- p->pWhere = pWhere;
- substExpr(p->pHaving, iParent, pSub->pEList);
- if( pSub->pHaving ){
- Expr *pHaving = sqliteExprDup(pSub->pHaving);
- if( p->pHaving ){
- p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0);
- }else{
- p->pHaving = pHaving;
- }
- }
- assert( p->pGroupBy==0 );
- p->pGroupBy = sqliteExprListDup(pSub->pGroupBy);
- }else if( p->pWhere==0 ){
- p->pWhere = pWhere;
- }else{
- substExpr(p->pWhere, iParent, pSub->pEList);
- if( pWhere ){
- p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0);
- }
- }
-
- /* The flattened query is distinct if either the inner or the
- ** outer query is distinct.
- */
- p->isDistinct = p->isDistinct || pSub->isDistinct;
-
- /* Transfer the limit expression from the subquery to the outer
- ** query.
- */
- if( pSub->nLimit>=0 ){
- if( p->nLimit<0 ){
- p->nLimit = pSub->nLimit;
- }else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){
- p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset;
- }
- }
- p->nOffset += pSub->nOffset;
-
- /* Finially, delete what is left of the subquery and return
- ** success.
- */
- sqliteSelectDelete(pSub);
- return 1;
-}
-
-/*
-** Analyze the SELECT statement passed in as an argument to see if it
-** is a simple min() or max() query. If it is and this query can be
-** satisfied using a single seek to the beginning or end of an index,
-** then generate the code for this SELECT and return 1. If this is not a
-** simple min() or max() query, then return 0;
-**
-** A simply min() or max() query looks like this:
-**
-** SELECT min(a) FROM table;
-** SELECT max(a) FROM table;
-**
-** The query may have only a single table in its FROM argument. There
-** can be no GROUP BY or HAVING or WHERE clauses. The result set must
-** be the min() or max() of a single column of the table. The column
-** in the min() or max() function must be indexed.
-**
-** The parameters to this routine are the same as for sqliteSelect().
-** See the header comment on that routine for additional information.
-*/
-static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
- Expr *pExpr;
- int iCol;
- Table *pTab;
- Index *pIdx;
- int base;
- Vdbe *v;
- int seekOp;
- int cont;
- ExprList *pEList, *pList, eList;
- struct ExprList_item eListItem;
- SrcList *pSrc;
-
-
- /* Check to see if this query is a simple min() or max() query. Return
- ** zero if it is not.
- */
- if( p->pGroupBy || p->pHaving || p->pWhere ) return 0;
- pSrc = p->pSrc;
- if( pSrc->nSrc!=1 ) return 0;
- pEList = p->pEList;
- if( pEList->nExpr!=1 ) return 0;
- pExpr = pEList->a[0].pExpr;
- if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
- pList = pExpr->pList;
- if( pList==0 || pList->nExpr!=1 ) return 0;
- if( pExpr->token.n!=3 ) return 0;
- if( sqliteStrNICmp(pExpr->token.z,"min",3)==0 ){
- seekOp = OP_Rewind;
- }else if( sqliteStrNICmp(pExpr->token.z,"max",3)==0 ){
- seekOp = OP_Last;
- }else{
- return 0;
- }
- pExpr = pList->a[0].pExpr;
- if( pExpr->op!=TK_COLUMN ) return 0;
- iCol = pExpr->iColumn;
- pTab = pSrc->a[0].pTab;
-
- /* If we get to here, it means the query is of the correct form.
- ** Check to make sure we have an index and make pIdx point to the
- ** appropriate index. If the min() or max() is on an INTEGER PRIMARY
- ** key column, no index is necessary so set pIdx to NULL. If no
- ** usable index is found, return 0.
- */
- if( iCol<0 ){
- pIdx = 0;
- }else{
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->nColumn>=1 );
- if( pIdx->aiColumn[0]==iCol ) break;
- }
- if( pIdx==0 ) return 0;
- }
-
- /* Identify column types if we will be using the callback. This
- ** step is skipped if the output is going to a table or a memory cell.
- ** The column names have already been generated in the calling function.
- */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) return 0;
- if( eDest==SRT_Callback ){
- generateColumnTypes(pParse, p->pSrc, p->pEList);
- }
-
- /* If the output is destined for a temporary table, open that table.
- */
- if( eDest==SRT_TempTable ){
- sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
- }
-
- /* Generating code to find the min or the max. Basically all we have
- ** to do is find the first or the last entry in the chosen index. If
- ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
- ** or last entry in the main table.
- */
- sqliteCodeVerifySchema(pParse, pTab->iDb);
- base = pSrc->a[0].iCursor;
- computeLimitRegisters(pParse, p);
- if( pSrc->a[0].pSelect==0 ){
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenRead, base, pTab->tnum, pTab->zName, 0);
- }
- cont = sqliteVdbeMakeLabel(v);
- if( pIdx==0 ){
- sqliteVdbeAddOp(v, seekOp, base, 0);
- }else{
- sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
- if( seekOp==OP_Rewind ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
- sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
- seekOp = OP_MoveTo;
- }
- sqliteVdbeAddOp(v, seekOp, base+1, 0);
- sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
- sqliteVdbeAddOp(v, OP_Close, base+1, 0);
- sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
- }
- eList.nExpr = 1;
- memset(&eListItem, 0, sizeof(eListItem));
- eList.a = &eListItem;
- eList.a[0].pExpr = pExpr;
- selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
- sqliteVdbeResolveLabel(v, cont);
- sqliteVdbeAddOp(v, OP_Close, base, 0);
-
- return 1;
-}
-
-/*
-** Generate code for the given SELECT statement.
-**
-** The results are distributed in various ways depending on the
-** value of eDest and iParm.
-**
-** eDest Value Result
-** ------------ -------------------------------------------
-** SRT_Callback Invoke the callback for each row of the result.
-**
-** SRT_Mem Store first result in memory cell iParm
-**
-** SRT_Set Store results as keys of a table with cursor iParm
-**
-** SRT_Union Store results as a key in a temporary table iParm
-**
-** SRT_Except Remove results from the temporary table iParm.
-**
-** SRT_Table Store results in temporary table iParm
-**
-** The table above is incomplete. Additional eDist value have be added
-** since this comment was written. See the selectInnerLoop() function for
-** a complete listing of the allowed values of eDest and their meanings.
-**
-** This routine returns the number of errors. If any errors are
-** encountered, then an appropriate error message is left in
-** pParse->zErrMsg.
-**
-** This routine does NOT free the Select structure passed in. The
-** calling function needs to do that.
-**
-** The pParent, parentTab, and *pParentAgg fields are filled in if this
-** SELECT is a subquery. This routine may try to combine this SELECT
-** with its parent to form a single flat query. In so doing, it might
-** change the parent query from a non-aggregate to an aggregate query.
-** For that reason, the pParentAgg flag is passed as a pointer, so it
-** can be changed.
-**
-** Example 1: The meaning of the pParent parameter.
-**
-** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
-** \ \_______ subquery _______/ /
-** \ /
-** \____________________ outer query ___________________/
-**
-** This routine is called for the outer query first. For that call,
-** pParent will be NULL. During the processing of the outer query, this
-** routine is called recursively to handle the subquery. For the recursive
-** call, pParent will point to the outer query. Because the subquery is
-** the second element in a three-way join, the parentTab parameter will
-** be 1 (the 2nd value of a 0-indexed array.)
-*/
-int sqliteSelect(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- int eDest, /* How to dispose of the results */
- int iParm, /* A parameter used by the eDest disposal method */
- Select *pParent, /* Another SELECT for which this is a sub-query */
- int parentTab, /* Index in pParent->pSrc of this query */
- int *pParentAgg /* True if pParent uses aggregate functions */
-){
- int i;
- WhereInfo *pWInfo;
- Vdbe *v;
- int isAgg = 0; /* True for select lists like "count(*)" */
- ExprList *pEList; /* List of columns to extract. */
- SrcList *pTabList; /* List of tables to select from */
- Expr *pWhere; /* The WHERE clause. May be NULL */
- ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */
- ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
- Expr *pHaving; /* The HAVING clause. May be NULL */
- int isDistinct; /* True if the DISTINCT keyword is present */
- int distinct; /* Table to use for the distinct set */
- int rc = 1; /* Value to return from this function */
-
- if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1;
- if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
-
- /* If there is are a sequence of queries, do the earlier ones first.
- */
- if( p->pPrior ){
- return multiSelect(pParse, p, eDest, iParm);
- }
-
- /* Make local copies of the parameters for this query.
- */
- pTabList = p->pSrc;
- pWhere = p->pWhere;
- pOrderBy = p->pOrderBy;
- pGroupBy = p->pGroupBy;
- pHaving = p->pHaving;
- isDistinct = p->isDistinct;
-
- /* Allocate VDBE cursors for each table in the FROM clause
- */
- sqliteSrcListAssignCursors(pParse, pTabList);
-
- /*
- ** Do not even attempt to generate any code if we have already seen
- ** errors before this routine starts.
- */
- if( pParse->nErr>0 ) goto select_end;
-
- /* Expand any "*" terms in the result set. (For example the "*" in
- ** "SELECT * FROM t1") The fillInColumnlist() routine also does some
- ** other housekeeping - see the header comment for details.
- */
- if( fillInColumnList(pParse, p) ){
- goto select_end;
- }
- pWhere = p->pWhere;
- pEList = p->pEList;
- if( pEList==0 ) goto select_end;
-
- /* If writing to memory or generating a set
- ** only a single column may be output.
- */
- if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
- sqliteErrorMsg(pParse, "only a single result allowed for "
- "a SELECT that is part of an expression");
- goto select_end;
- }
-
- /* ORDER BY is ignored for some destinations.
- */
- switch( eDest ){
- case SRT_Union:
- case SRT_Except:
- case SRT_Discard:
- pOrderBy = 0;
- break;
- default:
- break;
- }
-
- /* At this point, we should have allocated all the cursors that we
- ** need to handle subquerys and temporary tables.
- **
- ** Resolve the column names and do a semantics check on all the expressions.
- */
- for(i=0; i<pEList->nExpr; i++){
- if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){
- goto select_end;
- }
- if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
- goto select_end;
- }
- }
- if( pWhere ){
- if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){
- goto select_end;
- }
- if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
- goto select_end;
- }
- }
- if( pHaving ){
- if( pGroupBy==0 ){
- sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- goto select_end;
- }
- if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){
- goto select_end;
- }
- if( sqliteExprCheck(pParse, pHaving, 1, &isAgg) ){
- goto select_end;
- }
- }
- if( pOrderBy ){
- for(i=0; i<pOrderBy->nExpr; i++){
- int iCol;
- Expr *pE = pOrderBy->a[i].pExpr;
- if( sqliteExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
- sqliteExprDelete(pE);
- pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
- }
- if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
- goto select_end;
- }
- if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
- goto select_end;
- }
- if( sqliteExprIsConstant(pE) ){
- if( sqliteExprIsInteger(pE, &iCol)==0 ){
- sqliteErrorMsg(pParse,
- "ORDER BY terms must not be non-integer constants");
- goto select_end;
- }else if( iCol<=0 || iCol>pEList->nExpr ){
- sqliteErrorMsg(pParse,
- "ORDER BY column number %d out of range - should be "
- "between 1 and %d", iCol, pEList->nExpr);
- goto select_end;
- }
- }
- }
- }
- if( pGroupBy ){
- for(i=0; i<pGroupBy->nExpr; i++){
- int iCol;
- Expr *pE = pGroupBy->a[i].pExpr;
- if( sqliteExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
- sqliteExprDelete(pE);
- pE = pGroupBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
- }
- if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
- goto select_end;
- }
- if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
- goto select_end;
- }
- if( sqliteExprIsConstant(pE) ){
- if( sqliteExprIsInteger(pE, &iCol)==0 ){
- sqliteErrorMsg(pParse,
- "GROUP BY terms must not be non-integer constants");
- goto select_end;
- }else if( iCol<=0 || iCol>pEList->nExpr ){
- sqliteErrorMsg(pParse,
- "GROUP BY column number %d out of range - should be "
- "between 1 and %d", iCol, pEList->nExpr);
- goto select_end;
- }
- }
- }
- }
-
- /* Begin generating code.
- */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) goto select_end;
-
- /* Identify column names if we will be using them in a callback. This
- ** step is skipped if the output is going to some other destination.
- */
- if( eDest==SRT_Callback ){
- generateColumnNames(pParse, pTabList, pEList);
- }
-
- /* Generate code for all sub-queries in the FROM clause
- */
- for(i=0; i<pTabList->nSrc; i++){
- const char *zSavedAuthContext;
- int needRestoreContext;
-
- if( pTabList->a[i].pSelect==0 ) continue;
- if( pTabList->a[i].zName!=0 ){
- zSavedAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = pTabList->a[i].zName;
- needRestoreContext = 1;
- }else{
- needRestoreContext = 0;
- }
- sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable,
- pTabList->a[i].iCursor, p, i, &isAgg);
- if( needRestoreContext ){
- pParse->zAuthContext = zSavedAuthContext;
- }
- pTabList = p->pSrc;
- pWhere = p->pWhere;
- if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){
- pOrderBy = p->pOrderBy;
- }
- pGroupBy = p->pGroupBy;
- pHaving = p->pHaving;
- isDistinct = p->isDistinct;
- }
-
- /* Check for the special case of a min() or max() function by itself
- ** in the result set.
- */
- if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
- rc = 0;
- goto select_end;
- }
-
- /* Check to see if this is a subquery that can be "flattened" into its parent.
- ** If flattening is a possiblity, do so and return immediately.
- */
- if( pParent && pParentAgg &&
- flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){
- if( isAgg ) *pParentAgg = 1;
- return rc;
- }
-
- /* Set the limiter.
- */
- computeLimitRegisters(pParse, p);
-
- /* Identify column types if we will be using a callback. This
- ** step is skipped if the output is going to a destination other
- ** than a callback.
- **
- ** We have to do this separately from the creation of column names
- ** above because if the pTabList contains views then they will not
- ** have been resolved and we will not know the column types until
- ** now.
- */
- if( eDest==SRT_Callback ){
- generateColumnTypes(pParse, pTabList, pEList);
- }
-
- /* If the output is destined for a temporary table, open that table.
- */
- if( eDest==SRT_TempTable ){
- sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
- }
-
- /* Do an analysis of aggregate expressions.
- */
- sqliteAggregateInfoReset(pParse);
- if( isAgg || pGroupBy ){
- assert( pParse->nAgg==0 );
- isAgg = 1;
- for(i=0; i<pEList->nExpr; i++){
- if( sqliteExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){
- goto select_end;
- }
- }
- if( pGroupBy ){
- for(i=0; i<pGroupBy->nExpr; i++){
- if( sqliteExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){
- goto select_end;
- }
- }
- }
- if( pHaving && sqliteExprAnalyzeAggregates(pParse, pHaving) ){
- goto select_end;
- }
- if( pOrderBy ){
- for(i=0; i<pOrderBy->nExpr; i++){
- if( sqliteExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){
- goto select_end;
- }
- }
- }
- }
-
- /* Reset the aggregator
- */
- if( isAgg ){
- sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg);
- for(i=0; i<pParse->nAgg; i++){
- FuncDef *pFunc;
- if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){
- sqliteVdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_POINTER);
- }
- }
- if( pGroupBy==0 ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_AggFocus, 0, 0);
- }
- }
-
- /* Initialize the memory cell to NULL
- */
- if( eDest==SRT_Mem ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
- }
-
- /* Open a temporary table to use for the distinct set.
- */
- if( isDistinct ){
- distinct = pParse->nTab++;
- sqliteVdbeAddOp(v, OP_OpenTemp, distinct, 1);
- }else{
- distinct = -1;
- }
-
- /* Begin the database scan
- */
- pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0,
- pGroupBy ? 0 : &pOrderBy);
- if( pWInfo==0 ) goto select_end;
-
- /* Use the standard inner loop if we are not dealing with
- ** aggregates
- */
- if( !isAgg ){
- if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
- iParm, pWInfo->iContinue, pWInfo->iBreak) ){
- goto select_end;
- }
- }
-
- /* If we are dealing with aggregates, then do the special aggregate
- ** processing.
- */
- else{
- AggExpr *pAgg;
- if( pGroupBy ){
- int lbl1;
- for(i=0; i<pGroupBy->nExpr; i++){
- sqliteExprCode(pParse, pGroupBy->a[i].pExpr);
- }
- sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0);
- if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pGroupBy);
- lbl1 = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1);
- for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
- if( pAgg->isAgg ) continue;
- sqliteExprCode(pParse, pAgg->pExpr);
- sqliteVdbeAddOp(v, OP_AggSet, 0, i);
- }
- sqliteVdbeResolveLabel(v, lbl1);
- }
- for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
- Expr *pE;
- int nExpr;
- FuncDef *pDef;
- if( !pAgg->isAgg ) continue;
- assert( pAgg->pFunc!=0 );
- assert( pAgg->pFunc->xStep!=0 );
- pDef = pAgg->pFunc;
- pE = pAgg->pExpr;
- assert( pE!=0 );
- assert( pE->op==TK_AGG_FUNCTION );
- nExpr = sqliteExprCodeExprList(pParse, pE->pList, pDef->includeTypes);
- sqliteVdbeAddOp(v, OP_Integer, i, 0);
- sqliteVdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER);
- }
- }
-
- /* End the database scan loop.
- */
- sqliteWhereEnd(pWInfo);
-
- /* If we are processing aggregates, we need to set up a second loop
- ** over all of the aggregate values and process them.
- */
- if( isAgg ){
- int endagg = sqliteVdbeMakeLabel(v);
- int startagg;
- startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg);
- pParse->useAgg = 1;
- if( pHaving ){
- sqliteExprIfFalse(pParse, pHaving, startagg, 1);
- }
- if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
- iParm, startagg, endagg) ){
- goto select_end;
- }
- sqliteVdbeAddOp(v, OP_Goto, 0, startagg);
- sqliteVdbeResolveLabel(v, endagg);
- sqliteVdbeAddOp(v, OP_Noop, 0, 0);
- pParse->useAgg = 0;
- }
-
- /* If there is an ORDER BY clause, then we need to sort the results
- ** and send them to the callback one by one.
- */
- if( pOrderBy ){
- generateSortTail(p, v, pEList->nExpr, eDest, iParm);
- }
-
- /* If this was a subquery, we have now converted the subquery into a
- ** temporary table. So delete the subquery structure from the parent
- ** to prevent this subquery from being evaluated again and to force the
- ** the use of the temporary table.
- */
- if( pParent ){
- assert( pParent->pSrc->nSrc>parentTab );
- assert( pParent->pSrc->a[parentTab].pSelect==p );
- sqliteSelectDelete(p);
- pParent->pSrc->a[parentTab].pSelect = 0;
- }
-
- /* The SELECT was successfully coded. Set the return code to 0
- ** to indicate no errors.
- */
- rc = 0;
-
- /* Control jumps to here if an error is encountered above, or upon
- ** successful coding of the SELECT.
- */
-select_end:
- sqliteAggregateInfoReset(pParse);
- return rc;
-}
diff --git a/ext/sqlite/libsqlite/src/sqlite.h.in b/ext/sqlite/libsqlite/src/sqlite.h.in
deleted file mode 100644
index a823f5b2e6..0000000000
--- a/ext/sqlite/libsqlite/src/sqlite.h.in
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This header file defines the interface that the SQLite library
-** presents to client programs.
-**
-** @(#) $Id$
-*/
-#ifndef _SQLITE_H_
-#define _SQLITE_H_
-#include <stdarg.h> /* Needed for the definition of va_list */
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** The version of the SQLite library.
-*/
-#ifdef SQLITE_VERSION
-# undef SQLITE_VERSION
-#else
-# define SQLITE_VERSION "--VERS--"
-#endif
-
-/*
-** The version string is also compiled into the library so that a program
-** can check to make sure that the lib*.a file and the *.h file are from
-** the same version.
-*/
-extern const char sqlite_version[];
-
-/*
-** The SQLITE_UTF8 macro is defined if the library expects to see
-** UTF-8 encoded data. The SQLITE_ISO8859 macro is defined if the
-** iso8859 encoded should be used.
-*/
-#define SQLITE_--ENCODING-- 1
-
-/*
-** The following constant holds one of two strings, "UTF-8" or "iso8859",
-** depending on which character encoding the SQLite library expects to
-** see. The character encoding makes a difference for the LIKE and GLOB
-** operators and for the LENGTH() and SUBSTR() functions.
-*/
-extern const char sqlite_encoding[];
-
-/*
-** Each open sqlite database is represented by an instance of the
-** following opaque structure.
-*/
-typedef struct sqlite sqlite;
-
-/*
-** A function to open a new sqlite database.
-**
-** If the database does not exist and mode indicates write
-** permission, then a new database is created. If the database
-** does not exist and mode does not indicate write permission,
-** then the open fails, an error message generated (if errmsg!=0)
-** and the function returns 0.
-**
-** If mode does not indicates user write permission, then the
-** database is opened read-only.
-**
-** The Truth: As currently implemented, all databases are opened
-** for writing all the time. Maybe someday we will provide the
-** ability to open a database readonly. The mode parameters is
-** provided in anticipation of that enhancement.
-*/
-sqlite *sqlite_open(const char *filename, int mode, char **errmsg);
-
-/*
-** A function to close the database.
-**
-** Call this function with a pointer to a structure that was previously
-** returned from sqlite_open() and the corresponding database will by closed.
-*/
-void sqlite_close(sqlite *);
-
-/*
-** The type for a callback function.
-*/
-typedef int (*sqlite_callback)(void*,int,char**, char**);
-
-/*
-** A function to executes one or more statements of SQL.
-**
-** If one or more of the SQL statements are queries, then
-** the callback function specified by the 3rd parameter is
-** invoked once for each row of the query result. This callback
-** should normally return 0. If the callback returns a non-zero
-** value then the query is aborted, all subsequent SQL statements
-** are skipped and the sqlite_exec() function returns the SQLITE_ABORT.
-**
-** The 4th parameter is an arbitrary pointer that is passed
-** to the callback function as its first parameter.
-**
-** The 2nd parameter to the callback function is the number of
-** columns in the query result. The 3rd parameter to the callback
-** is an array of strings holding the values for each column.
-** The 4th parameter to the callback is an array of strings holding
-** the names of each column.
-**
-** The callback function may be NULL, even for queries. A NULL
-** callback is not an error. It just means that no callback
-** will be invoked.
-**
-** If an error occurs while parsing or evaluating the SQL (but
-** not while executing the callback) then an appropriate error
-** message is written into memory obtained from malloc() and
-** *errmsg is made to point to that message. The calling function
-** is responsible for freeing the memory that holds the error
-** message. Use sqlite_freemem() for this. If errmsg==NULL,
-** then no error message is ever written.
-**
-** The return value is is SQLITE_OK if there are no errors and
-** some other return code if there is an error. The particular
-** return value depends on the type of error.
-**
-** If the query could not be executed because a database file is
-** locked or busy, then this function returns SQLITE_BUSY. (This
-** behavior can be modified somewhat using the sqlite_busy_handler()
-** and sqlite_busy_timeout() functions below.)
-*/
-int sqlite_exec(
- sqlite*, /* An open database */
- const char *sql, /* SQL to be executed */
- sqlite_callback, /* Callback function */
- void *, /* 1st argument to callback function */
- char **errmsg /* Error msg written here */
-);
-
-/*
-** Return values for sqlite_exec() and sqlite_step()
-*/
-#define SQLITE_OK 0 /* Successful result */
-#define SQLITE_ERROR 1 /* SQL error or missing database */
-#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
-#define SQLITE_PERM 3 /* Access permission denied */
-#define SQLITE_ABORT 4 /* Callback routine requested an abort */
-#define SQLITE_BUSY 5 /* The database file is locked */
-#define SQLITE_LOCKED 6 /* A table in the database is locked */
-#define SQLITE_NOMEM 7 /* A malloc() failed */
-#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
-#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
-#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
-#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
-#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
-#define SQLITE_FULL 13 /* Insertion failed because database is full */
-#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
-#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
-#define SQLITE_SCHEMA 17 /* The database schema changed */
-#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
-#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
-#define SQLITE_MISMATCH 20 /* Data type mismatch */
-#define SQLITE_MISUSE 21 /* Library used incorrectly */
-#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
-#define SQLITE_AUTH 23 /* Authorization denied */
-#define SQLITE_FORMAT 24 /* Auxiliary database format error */
-#define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */
-#define SQLITE_NOTADB 26 /* File opened that is not a database file */
-#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
-#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
-
-/*
-** Each entry in an SQLite table has a unique integer key. (The key is
-** the value of the INTEGER PRIMARY KEY column if there is such a column,
-** otherwise the key is generated at random. The unique key is always
-** available as the ROWID, OID, or _ROWID_ column.) The following routine
-** returns the integer key of the most recent insert in the database.
-**
-** This function is similar to the mysql_insert_id() function from MySQL.
-*/
-int sqlite_last_insert_rowid(sqlite*);
-
-/*
-** This function returns the number of database rows that were changed
-** (or inserted or deleted) by the most recent called sqlite_exec().
-**
-** All changes are counted, even if they were later undone by a
-** ROLLBACK or ABORT. Except, changes associated with creating and
-** dropping tables are not counted.
-**
-** If a callback invokes sqlite_exec() recursively, then the changes
-** in the inner, recursive call are counted together with the changes
-** in the outer call.
-**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. (This is much faster than going
-** through and deleting individual elements form the table.) Because of
-** this optimization, the change count for "DELETE FROM table" will be
-** zero regardless of the number of elements that were originally in the
-** table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead.
-*/
-int sqlite_changes(sqlite*);
-
-/*
-** This function returns the number of database rows that were changed
-** by the last INSERT, UPDATE, or DELETE statment executed by sqlite_exec(),
-** or by the last VM to run to completion. The change count is not updated
-** by SQL statements other than INSERT, UPDATE or DELETE.
-**
-** Changes are counted, even if they are later undone by a ROLLBACK or
-** ABORT. Changes associated with trigger programs that execute as a
-** result of the INSERT, UPDATE, or DELETE statement are not counted.
-**
-** If a callback invokes sqlite_exec() recursively, then the changes
-** in the inner, recursive call are counted together with the changes
-** in the outer call.
-**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. (This is much faster than going
-** through and deleting individual elements form the table.) Because of
-** this optimization, the change count for "DELETE FROM table" will be
-** zero regardless of the number of elements that were originally in the
-** table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-int sqlite_last_statement_changes(sqlite*);
-
-/* If the parameter to this routine is one of the return value constants
-** defined above, then this routine returns a constant text string which
-** descripts (in English) the meaning of the return value.
-*/
-const char *sqlite_error_string(int);
-#define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */
-
-/* This function causes any pending database operation to abort and
-** return at its earliest opportunity. This routine is typically
-** called in response to a user action such as pressing "Cancel"
-** or Ctrl-C where the user wants a long query operation to halt
-** immediately.
-*/
-void sqlite_interrupt(sqlite*);
-
-
-/* This function returns true if the given input string comprises
-** one or more complete SQL statements.
-**
-** The algorithm is simple. If the last token other than spaces
-** and comments is a semicolon, then return true. otherwise return
-** false.
-*/
-int sqlite_complete(const char *sql);
-
-/*
-** This routine identifies a callback function that is invoked
-** whenever an attempt is made to open a database table that is
-** currently locked by another process or thread. If the busy callback
-** is NULL, then sqlite_exec() returns SQLITE_BUSY immediately if
-** it finds a locked table. If the busy callback is not NULL, then
-** sqlite_exec() invokes the callback with three arguments. The
-** second argument is the name of the locked table and the third
-** argument is the number of times the table has been busy. If the
-** busy callback returns 0, then sqlite_exec() immediately returns
-** SQLITE_BUSY. If the callback returns non-zero, then sqlite_exec()
-** tries to open the table again and the cycle repeats.
-**
-** The default busy callback is NULL.
-**
-** Sqlite is re-entrant, so the busy handler may start a new query.
-** (It is not clear why anyone would every want to do this, but it
-** is allowed, in theory.) But the busy handler may not close the
-** database. Closing the database from a busy handler will delete
-** data structures out from under the executing query and will
-** probably result in a coredump.
-*/
-void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*);
-
-/*
-** This routine sets a busy handler that sleeps for a while when a
-** table is locked. The handler will sleep multiple times until
-** at least "ms" milleseconds of sleeping have been done. After
-** "ms" milleseconds of sleeping, the handler returns 0 which
-** causes sqlite_exec() to return SQLITE_BUSY.
-**
-** Calling this routine with an argument less than or equal to zero
-** turns off all busy handlers.
-*/
-void sqlite_busy_timeout(sqlite*, int ms);
-
-/*
-** This next routine is really just a wrapper around sqlite_exec().
-** Instead of invoking a user-supplied callback for each row of the
-** result, this routine remembers each row of the result in memory
-** obtained from malloc(), then returns all of the result after the
-** query has finished.
-**
-** As an example, suppose the query result where this table:
-**
-** Name | Age
-** -----------------------
-** Alice | 43
-** Bob | 28
-** Cindy | 21
-**
-** If the 3rd argument were &azResult then after the function returns
-** azResult will contain the following data:
-**
-** azResult[0] = "Name";
-** azResult[1] = "Age";
-** azResult[2] = "Alice";
-** azResult[3] = "43";
-** azResult[4] = "Bob";
-** azResult[5] = "28";
-** azResult[6] = "Cindy";
-** azResult[7] = "21";
-**
-** Notice that there is an extra row of data containing the column
-** headers. But the *nrow return value is still 3. *ncolumn is
-** set to 2. In general, the number of values inserted into azResult
-** will be ((*nrow) + 1)*(*ncolumn).
-**
-** After the calling function has finished using the result, it should
-** pass the result data pointer to sqlite_free_table() in order to
-** release the memory that was malloc-ed. Because of the way the
-** malloc() happens, the calling function must not try to call
-** malloc() directly. Only sqlite_free_table() is able to release
-** the memory properly and safely.
-**
-** The return value of this routine is the same as from sqlite_exec().
-*/
-int sqlite_get_table(
- sqlite*, /* An open database */
- const char *sql, /* SQL to be executed */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg /* Error msg written here */
-);
-
-/*
-** Call this routine to free the memory that sqlite_get_table() allocated.
-*/
-void sqlite_free_table(char **result);
-
-/*
-** The following routines are wrappers around sqlite_exec() and
-** sqlite_get_table(). The only difference between the routines that
-** follow and the originals is that the second argument to the
-** routines that follow is really a printf()-style format
-** string describing the SQL to be executed. Arguments to the format
-** string appear at the end of the argument list.
-**
-** All of the usual printf formatting options apply. In addition, there
-** is a "%q" option. %q works like %s in that it substitutes a null-terminated
-** string from the argument list. But %q also doubles every '\'' character.
-** %q is designed for use inside a string literal. By doubling each '\''
-** character it escapes that character and allows it to be inserted into
-** the string.
-**
-** For example, so some string variable contains text as follows:
-**
-** char *zText = "It's a happy day!";
-**
-** We can use this text in an SQL statement as follows:
-**
-** sqlite_exec_printf(db, "INSERT INTO table VALUES('%q')",
-** callback1, 0, 0, zText);
-**
-** Because the %q format string is used, the '\'' character in zText
-** is escaped and the SQL generated is as follows:
-**
-** INSERT INTO table1 VALUES('It''s a happy day!')
-**
-** This is correct. Had we used %s instead of %q, the generated SQL
-** would have looked like this:
-**
-** INSERT INTO table1 VALUES('It's a happy day!');
-**
-** This second example is an SQL syntax error. As a general rule you
-** should always use %q instead of %s when inserting text into a string
-** literal.
-*/
-int sqlite_exec_printf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- sqlite_callback, /* Callback function */
- void *, /* 1st argument to callback function */
- char **errmsg, /* Error msg written here */
- ... /* Arguments to the format string. */
-);
-int sqlite_exec_vprintf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- sqlite_callback, /* Callback function */
- void *, /* 1st argument to callback function */
- char **errmsg, /* Error msg written here */
- va_list ap /* Arguments to the format string. */
-);
-int sqlite_get_table_printf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg, /* Error msg written here */
- ... /* Arguments to the format string */
-);
-int sqlite_get_table_vprintf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg, /* Error msg written here */
- va_list ap /* Arguments to the format string */
-);
-char *sqlite_mprintf(const char*,...);
-char *sqlite_vmprintf(const char*, va_list);
-
-/*
-** Windows systems should call this routine to free memory that
-** is returned in the in the errmsg parameter of sqlite_open() when
-** SQLite is a DLL. For some reason, it does not work to call free()
-** directly.
-*/
-void sqlite_freemem(void *p);
-
-/*
-** Windows systems need functions to call to return the sqlite_version
-** and sqlite_encoding strings.
-*/
-const char *sqlite_libversion(void);
-const char *sqlite_libencoding(void);
-
-/*
-** A pointer to the following structure is used to communicate with
-** the implementations of user-defined functions.
-*/
-typedef struct sqlite_func sqlite_func;
-
-/*
-** Use the following routines to create new user-defined functions. See
-** the documentation for details.
-*/
-int sqlite_create_function(
- sqlite*, /* Database where the new function is registered */
- const char *zName, /* Name of the new function */
- int nArg, /* Number of arguments. -1 means any number */
- void (*xFunc)(sqlite_func*,int,const char**), /* C code to implement */
- void *pUserData /* Available via the sqlite_user_data() call */
-);
-int sqlite_create_aggregate(
- sqlite*, /* Database where the new function is registered */
- const char *zName, /* Name of the function */
- int nArg, /* Number of arguments */
- void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */
- void (*xFinalize)(sqlite_func*), /* Called once to get final result */
- void *pUserData /* Available via the sqlite_user_data() call */
-);
-
-/*
-** Use the following routine to define the datatype returned by a
-** user-defined function. The second argument can be one of the
-** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it
-** can be an integer greater than or equal to zero. When the datatype
-** parameter is non-negative, the type of the result will be the
-** same as the datatype-th argument. If datatype==SQLITE_NUMERIC
-** then the result is always numeric. If datatype==SQLITE_TEXT then
-** the result is always text. If datatype==SQLITE_ARGS then the result
-** is numeric if any argument is numeric and is text otherwise.
-*/
-int sqlite_function_type(
- sqlite *db, /* The database there the function is registered */
- const char *zName, /* Name of the function */
- int datatype /* The datatype for this function */
-);
-#define SQLITE_NUMERIC (-1)
-/* #define SQLITE_TEXT (-2) // See below */
-#define SQLITE_ARGS (-3)
-
-/*
-** SQLite version 3 defines SQLITE_TEXT differently. To allow both
-** version 2 and version 3 to be included, undefine them both if a
-** conflict is seen. Define SQLITE2_TEXT to be the version 2 value.
-*/
-#ifdef SQLITE_TEXT
-# undef SQLITE_TEXT
-#else
-# define SQLITE_TEXT (-2)
-#endif
-#define SQLITE2_TEXT (-2)
-
-
-
-/*
-** The user function implementations call one of the following four routines
-** in order to return their results. The first parameter to each of these
-** routines is a copy of the first argument to xFunc() or xFinialize().
-** The second parameter to these routines is the result to be returned.
-** A NULL can be passed as the second parameter to sqlite_set_result_string()
-** in order to return a NULL result.
-**
-** The 3rd argument to _string and _error is the number of characters to
-** take from the string. If this argument is negative, then all characters
-** up to and including the first '\000' are used.
-**
-** The sqlite_set_result_string() function allocates a buffer to hold the
-** result and returns a pointer to this buffer. The calling routine
-** (that is, the implmentation of a user function) can alter the content
-** of this buffer if desired.
-*/
-char *sqlite_set_result_string(sqlite_func*,const char*,int);
-void sqlite_set_result_int(sqlite_func*,int);
-void sqlite_set_result_double(sqlite_func*,double);
-void sqlite_set_result_error(sqlite_func*,const char*,int);
-
-/*
-** The pUserData parameter to the sqlite_create_function() and
-** sqlite_create_aggregate() routines used to register user functions
-** is available to the implementation of the function using this
-** call.
-*/
-void *sqlite_user_data(sqlite_func*);
-
-/*
-** Aggregate functions use the following routine to allocate
-** a structure for storing their state. The first time this routine
-** is called for a particular aggregate, a new structure of size nBytes
-** is allocated, zeroed, and returned. On subsequent calls (for the
-** same aggregate instance) the same buffer is returned. The implementation
-** of the aggregate can use the returned buffer to accumulate data.
-**
-** The buffer allocated is freed automatically be SQLite.
-*/
-void *sqlite_aggregate_context(sqlite_func*, int nBytes);
-
-/*
-** The next routine returns the number of calls to xStep for a particular
-** aggregate function instance. The current call to xStep counts so this
-** routine always returns at least 1.
-*/
-int sqlite_aggregate_count(sqlite_func*);
-
-/*
-** This routine registers a callback with the SQLite library. The
-** callback is invoked (at compile-time, not at run-time) for each
-** attempt to access a column of a table in the database. The callback
-** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire
-** SQL statement should be aborted with an error and SQLITE_IGNORE
-** if the column should be treated as a NULL value.
-*/
-int sqlite_set_authorizer(
- sqlite*,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pUserData
-);
-
-/*
-** The second parameter to the access authorization function above will
-** be one of the values below. These values signify what kind of operation
-** is to be authorized. The 3rd and 4th parameters to the authorization
-** function will be parameters or NULL depending on which of the following
-** codes is used as the second parameter. The 5th parameter is the name
-** of the database ("main", "temp", etc.) if applicable. The 6th parameter
-** is the name of the inner-most trigger or view that is responsible for
-** the access attempt or NULL if this access attempt is directly from
-** input SQL code.
-**
-** Arg-3 Arg-4
-*/
-#define SQLITE_COPY 0 /* Table Name File Name */
-#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
-#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
-#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
-#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
-#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
-#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
-#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
-#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
-#define SQLITE_DELETE 9 /* Table Name NULL */
-#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
-#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
-#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
-#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
-#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
-#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
-#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
-#define SQLITE_DROP_VIEW 17 /* View Name NULL */
-#define SQLITE_INSERT 18 /* Table Name NULL */
-#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
-#define SQLITE_READ 20 /* Table Name Column Name */
-#define SQLITE_SELECT 21 /* NULL NULL */
-#define SQLITE_TRANSACTION 22 /* NULL NULL */
-#define SQLITE_UPDATE 23 /* Table Name Column Name */
-#define SQLITE_ATTACH 24 /* Filename NULL */
-#define SQLITE_DETACH 25 /* Database Name NULL */
-
-
-/*
-** The return value of the authorization function should be one of the
-** following constants:
-*/
-/* #define SQLITE_OK 0 // Allow access (This is actually defined above) */
-#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
-#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
-
-/*
-** Register a function that is called at every invocation of sqlite_exec()
-** or sqlite_compile(). This function can be used (for example) to generate
-** a log file of all SQL executed against a database.
-*/
-void *sqlite_trace(sqlite*, void(*xTrace)(void*,const char*), void*);
-
-/*** The Callback-Free API
-**
-** The following routines implement a new way to access SQLite that does not
-** involve the use of callbacks.
-**
-** An sqlite_vm is an opaque object that represents a single SQL statement
-** that is ready to be executed.
-*/
-typedef struct sqlite_vm sqlite_vm;
-
-/*
-** To execute an SQLite query without the use of callbacks, you first have
-** to compile the SQL using this routine. The 1st parameter "db" is a pointer
-** to an sqlite object obtained from sqlite_open(). The 2nd parameter
-** "zSql" is the text of the SQL to be compiled. The remaining parameters
-** are all outputs.
-**
-** *pzTail is made to point to the first character past the end of the first
-** SQL statement in zSql. This routine only compiles the first statement
-** in zSql, so *pzTail is left pointing to what remains uncompiled.
-**
-** *ppVm is left pointing to a "virtual machine" that can be used to execute
-** the compiled statement. Or if there is an error, *ppVm may be set to NULL.
-** If the input text contained no SQL (if the input is and empty string or
-** a comment) then *ppVm is set to NULL.
-**
-** If any errors are detected during compilation, an error message is written
-** into space obtained from malloc() and *pzErrMsg is made to point to that
-** error message. The calling routine is responsible for freeing the text
-** of this message when it has finished with it. Use sqlite_freemem() to
-** free the message. pzErrMsg may be NULL in which case no error message
-** will be generated.
-**
-** On success, SQLITE_OK is returned. Otherwise and error code is returned.
-*/
-int sqlite_compile(
- sqlite *db, /* The open database */
- const char *zSql, /* SQL statement to be compiled */
- const char **pzTail, /* OUT: uncompiled tail of zSql */
- sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */
- char **pzErrmsg /* OUT: Error message. */
-);
-
-/*
-** After an SQL statement has been compiled, it is handed to this routine
-** to be executed. This routine executes the statement as far as it can
-** go then returns. The return value will be one of SQLITE_DONE,
-** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE.
-**
-** SQLITE_DONE means that the execute of the SQL statement is complete
-** an no errors have occurred. sqlite_step() should not be called again
-** for the same virtual machine. *pN is set to the number of columns in
-** the result set and *pazColName is set to an array of strings that
-** describe the column names and datatypes. The name of the i-th column
-** is (*pazColName)[i] and the datatype of the i-th column is
-** (*pazColName)[i+*pN]. *pazValue is set to NULL.
-**
-** SQLITE_ERROR means that the virtual machine encountered a run-time
-** error. sqlite_step() should not be called again for the same
-** virtual machine. *pN is set to 0 and *pazColName and *pazValue are set
-** to NULL. Use sqlite_finalize() to obtain the specific error code
-** and the error message text for the error.
-**
-** SQLITE_BUSY means that an attempt to open the database failed because
-** another thread or process is holding a lock. The calling routine
-** can try again to open the database by calling sqlite_step() again.
-** The return code will only be SQLITE_BUSY if no busy handler is registered
-** using the sqlite_busy_handler() or sqlite_busy_timeout() routines. If
-** a busy handler callback has been registered but returns 0, then this
-** routine will return SQLITE_ERROR and sqltie_finalize() will return
-** SQLITE_BUSY when it is called.
-**
-** SQLITE_ROW means that a single row of the result is now available.
-** The data is contained in *pazValue. The value of the i-th column is
-** (*azValue)[i]. *pN and *pazColName are set as described in SQLITE_DONE.
-** Invoke sqlite_step() again to advance to the next row.
-**
-** SQLITE_MISUSE is returned if sqlite_step() is called incorrectly.
-** For example, if you call sqlite_step() after the virtual machine
-** has halted (after a prior call to sqlite_step() has returned SQLITE_DONE)
-** or if you call sqlite_step() with an incorrectly initialized virtual
-** machine or a virtual machine that has been deleted or that is associated
-** with an sqlite structure that has been closed.
-*/
-int sqlite_step(
- sqlite_vm *pVm, /* The virtual machine to execute */
- int *pN, /* OUT: Number of columns in result */
- const char ***pazValue, /* OUT: Column data */
- const char ***pazColName /* OUT: Column names and datatypes */
-);
-
-/*
-** This routine is called to delete a virtual machine after it has finished
-** executing. The return value is the result code. SQLITE_OK is returned
-** if the statement executed successfully and some other value is returned if
-** there was any kind of error. If an error occurred and pzErrMsg is not
-** NULL, then an error message is written into memory obtained from malloc()
-** and *pzErrMsg is made to point to that error message. The calling routine
-** should use sqlite_freemem() to delete this message when it has finished
-** with it.
-**
-** This routine can be called at any point during the execution of the
-** virtual machine. If the virtual machine has not completed execution
-** when this routine is called, that is like encountering an error or
-** an interrupt. (See sqlite_interrupt().) Incomplete updates may be
-** rolled back and transactions cancelled, depending on the circumstances,
-** and the result code returned will be SQLITE_ABORT.
-*/
-int sqlite_finalize(sqlite_vm*, char **pzErrMsg);
-
-/*
-** This routine deletes the virtual machine, writes any error message to
-** *pzErrMsg and returns an SQLite return code in the same way as the
-** sqlite_finalize() function.
-**
-** Additionally, if ppVm is not NULL, *ppVm is left pointing to a new virtual
-** machine loaded with the compiled version of the original query ready for
-** execution.
-**
-** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-int sqlite_reset(sqlite_vm*, char **pzErrMsg);
-
-/*
-** If the SQL that was handed to sqlite_compile contains variables that
-** are represeted in the SQL text by a question mark ('?'). This routine
-** is used to assign values to those variables.
-**
-** The first parameter is a virtual machine obtained from sqlite_compile().
-** The 2nd "idx" parameter determines which variable in the SQL statement
-** to bind the value to. The left most '?' is 1. The 3rd parameter is
-** the value to assign to that variable. The 4th parameter is the number
-** of bytes in the value, including the terminating \000 for strings.
-** Finally, the 5th "copy" parameter is TRUE if SQLite should make its
-** own private copy of this value, or false if the space that the 3rd
-** parameter points to will be unchanging and can be used directly by
-** SQLite.
-**
-** Unbound variables are treated as having a value of NULL. To explicitly
-** set a variable to NULL, call this routine with the 3rd parameter as a
-** NULL pointer.
-**
-** If the 4th "len" parameter is -1, then strlen() is used to find the
-** length.
-**
-** This routine can only be called immediately after sqlite_compile()
-** or sqlite_reset() and before any calls to sqlite_step().
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy);
-
-/*
-** This routine configures a callback function - the progress callback - that
-** is invoked periodically during long running calls to sqlite_exec(),
-** sqlite_step() and sqlite_get_table(). An example use for this API is to keep
-** a GUI updated during a large query.
-**
-** The progress callback is invoked once for every N virtual machine opcodes,
-** where N is the second argument to this function. The progress callback
-** itself is identified by the third argument to this function. The fourth
-** argument to this function is a void pointer passed to the progress callback
-** function each time it is invoked.
-**
-** If a call to sqlite_exec(), sqlite_step() or sqlite_get_table() results
-** in less than N opcodes being executed, then the progress callback is not
-** invoked.
-**
-** Calling this routine overwrites any previously installed progress callback.
-** To remove the progress callback altogether, pass NULL as the third
-** argument to this function.
-**
-** If the progress callback returns a result other than 0, then the current
-** query is immediately terminated and any database changes rolled back. If the
-** query was part of a larger transaction, then the transaction is not rolled
-** back and remains active. The sqlite_exec() call returns SQLITE_ABORT.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-void sqlite_progress_handler(sqlite*, int, int(*)(void*), void*);
-
-/*
-** Register a callback function to be invoked whenever a new transaction
-** is committed. The pArg argument is passed through to the callback.
-** callback. If the callback function returns non-zero, then the commit
-** is converted into a rollback.
-**
-** If another function was previously registered, its pArg value is returned.
-** Otherwise NULL is returned.
-**
-** Registering a NULL function disables the callback.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-void *sqlite_commit_hook(sqlite*, int(*)(void*), void*);
-
-/*
-** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine
-** is the same as sqlite_open().
-**
-** The code to implement this API is not available in the public release
-** of SQLite.
-*/
-sqlite *sqlite_open_encrypted(
- const char *zFilename, /* Name of the encrypted database */
- const void *pKey, /* Pointer to the key */
- int nKey, /* Number of bytes in the key */
- int *pErrcode, /* Write error code here */
- char **pzErrmsg /* Write error message here */
-);
-
-/*
-** Change the key on an open database. If the current database is not
-** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
-** database is decrypted.
-**
-** The code to implement this API is not available in the public release
-** of SQLite.
-*/
-int sqlite_rekey(
- sqlite *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The new key */
-);
-
-/*
-** Encode a binary buffer "in" of size n bytes so that it contains
-** no instances of characters '\'' or '\000'. The output is
-** null-terminated and can be used as a string value in an INSERT
-** or UPDATE statement. Use sqlite_decode_binary() to convert the
-** string back into its original binary.
-**
-** The result is written into a preallocated output buffer "out".
-** "out" must be able to hold at least 2 +(257*n)/254 bytes.
-** In other words, the output will be expanded by as much as 3
-** bytes for every 254 bytes of input plus 2 bytes of fixed overhead.
-** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.)
-**
-** The return value is the number of characters in the encoded
-** string, excluding the "\000" terminator.
-**
-** If out==NULL then no output is generated but the routine still returns
-** the number of characters that would have been generated if out had
-** not been NULL.
-*/
-int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
-
-/*
-** Decode the string "in" into binary data and write it into "out".
-** This routine reverses the encoding created by sqlite_encode_binary().
-** The output will always be a few bytes less than the input. The number
-** of bytes of output is returned. If the input is not a well-formed
-** encoding, -1 is returned.
-**
-** The "in" and "out" parameters may point to the same buffer in order
-** to decode a string in place.
-*/
-int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-
-#endif /* _SQLITE_H_ */
diff --git a/ext/sqlite/libsqlite/src/sqlite.w32.h b/ext/sqlite/libsqlite/src/sqlite.w32.h
deleted file mode 100644
index fb5d68221a..0000000000
--- a/ext/sqlite/libsqlite/src/sqlite.w32.h
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This header file defines the interface that the SQLite library
-** presents to client programs.
-**
-** @(#) $Id$
-*/
-#ifndef _SQLITE_H_
-#define _SQLITE_H_
-#include <stdarg.h> /* Needed for the definition of va_list */
-
-/*
-** Make sure we can call this stuff from C++.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
-** The version of the SQLite library.
-*/
-#define SQLITE_VERSION "2.8.17"
-
-/*
-** The version string is also compiled into the library so that a program
-** can check to make sure that the lib*.a file and the *.h file are from
-** the same version.
-*/
-extern const char sqlite_version[];
-
-/*
-** The SQLITE_UTF8 macro is defined if the library expects to see
-** UTF-8 encoded data. The SQLITE_ISO8859 macro is defined if the
-** iso8859 encoded should be used.
-*/
-#define SQLITE_ISO8859 1
-
-/*
-** The following constant holds one of two strings, "UTF-8" or "iso8859",
-** depending on which character encoding the SQLite library expects to
-** see. The character encoding makes a difference for the LIKE and GLOB
-** operators and for the LENGTH() and SUBSTR() functions.
-*/
-extern const char sqlite_encoding[];
-
-/*
-** Each open sqlite database is represented by an instance of the
-** following opaque structure.
-*/
-typedef struct sqlite sqlite;
-
-/*
-** A function to open a new sqlite database.
-**
-** If the database does not exist and mode indicates write
-** permission, then a new database is created. If the database
-** does not exist and mode does not indicate write permission,
-** then the open fails, an error message generated (if errmsg!=0)
-** and the function returns 0.
-**
-** If mode does not indicates user write permission, then the
-** database is opened read-only.
-**
-** The Truth: As currently implemented, all databases are opened
-** for writing all the time. Maybe someday we will provide the
-** ability to open a database readonly. The mode parameters is
-** provided in anticipation of that enhancement.
-*/
-sqlite *sqlite_open(const char *filename, int mode, char **errmsg);
-
-/*
-** A function to close the database.
-**
-** Call this function with a pointer to a structure that was previously
-** returned from sqlite_open() and the corresponding database will by closed.
-*/
-void sqlite_close(sqlite *);
-
-/*
-** The type for a callback function.
-*/
-typedef int (*sqlite_callback)(void*,int,char**, char**);
-
-/*
-** A function to executes one or more statements of SQL.
-**
-** If one or more of the SQL statements are queries, then
-** the callback function specified by the 3rd parameter is
-** invoked once for each row of the query result. This callback
-** should normally return 0. If the callback returns a non-zero
-** value then the query is aborted, all subsequent SQL statements
-** are skipped and the sqlite_exec() function returns the SQLITE_ABORT.
-**
-** The 4th parameter is an arbitrary pointer that is passed
-** to the callback function as its first parameter.
-**
-** The 2nd parameter to the callback function is the number of
-** columns in the query result. The 3rd parameter to the callback
-** is an array of strings holding the values for each column.
-** The 4th parameter to the callback is an array of strings holding
-** the names of each column.
-**
-** The callback function may be NULL, even for queries. A NULL
-** callback is not an error. It just means that no callback
-** will be invoked.
-**
-** If an error occurs while parsing or evaluating the SQL (but
-** not while executing the callback) then an appropriate error
-** message is written into memory obtained from malloc() and
-** *errmsg is made to point to that message. The calling function
-** is responsible for freeing the memory that holds the error
-** message. Use sqlite_freemem() for this. If errmsg==NULL,
-** then no error message is ever written.
-**
-** The return value is is SQLITE_OK if there are no errors and
-** some other return code if there is an error. The particular
-** return value depends on the type of error.
-**
-** If the query could not be executed because a database file is
-** locked or busy, then this function returns SQLITE_BUSY. (This
-** behavior can be modified somewhat using the sqlite_busy_handler()
-** and sqlite_busy_timeout() functions below.)
-*/
-int sqlite_exec(
- sqlite*, /* An open database */
- const char *sql, /* SQL to be executed */
- sqlite_callback, /* Callback function */
- void *, /* 1st argument to callback function */
- char **errmsg /* Error msg written here */
-);
-
-/*
-** Return values for sqlite_exec() and sqlite_step()
-*/
-#define SQLITE_OK 0 /* Successful result */
-#define SQLITE_ERROR 1 /* SQL error or missing database */
-#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
-#define SQLITE_PERM 3 /* Access permission denied */
-#define SQLITE_ABORT 4 /* Callback routine requested an abort */
-#define SQLITE_BUSY 5 /* The database file is locked */
-#define SQLITE_LOCKED 6 /* A table in the database is locked */
-#define SQLITE_NOMEM 7 /* A malloc() failed */
-#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
-#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
-#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
-#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
-#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
-#define SQLITE_FULL 13 /* Insertion failed because database is full */
-#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
-#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
-#define SQLITE_SCHEMA 17 /* The database schema changed */
-#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
-#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
-#define SQLITE_MISMATCH 20 /* Data type mismatch */
-#define SQLITE_MISUSE 21 /* Library used incorrectly */
-#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
-#define SQLITE_AUTH 23 /* Authorization denied */
-#define SQLITE_FORMAT 24 /* Auxiliary database format error */
-#define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */
-#define SQLITE_NOTADB 26 /* File opened that is not a database file */
-#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
-#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
-
-/*
-** Each entry in an SQLite table has a unique integer key. (The key is
-** the value of the INTEGER PRIMARY KEY column if there is such a column,
-** otherwise the key is generated at random. The unique key is always
-** available as the ROWID, OID, or _ROWID_ column.) The following routine
-** returns the integer key of the most recent insert in the database.
-**
-** This function is similar to the mysql_insert_id() function from MySQL.
-*/
-int sqlite_last_insert_rowid(sqlite*);
-
-/*
-** This function returns the number of database rows that were changed
-** (or inserted or deleted) by the most recent called sqlite_exec().
-**
-** All changes are counted, even if they were later undone by a
-** ROLLBACK or ABORT. Except, changes associated with creating and
-** dropping tables are not counted.
-**
-** If a callback invokes sqlite_exec() recursively, then the changes
-** in the inner, recursive call are counted together with the changes
-** in the outer call.
-**
-** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. (This is much faster than going
-** through and deleting individual elements form the table.) Because of
-** this optimization, the change count for "DELETE FROM table" will be
-** zero regardless of the number of elements that were originally in the
-** table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead.
-*/
-int sqlite_changes(sqlite*);
-
-/* If the parameter to this routine is one of the return value constants
-** defined above, then this routine returns a constant text string which
-** descripts (in English) the meaning of the return value.
-*/
-const char *sqlite_error_string(int);
-#define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */
-
-/* This function causes any pending database operation to abort and
-** return at its earliest opportunity. This routine is typically
-** called in response to a user action such as pressing "Cancel"
-** or Ctrl-C where the user wants a long query operation to halt
-** immediately.
-*/
-void sqlite_interrupt(sqlite*);
-
-
-/* This function returns true if the given input string comprises
-** one or more complete SQL statements.
-**
-** The algorithm is simple. If the last token other than spaces
-** and comments is a semicolon, then return true. otherwise return
-** false.
-*/
-int sqlite_complete(const char *sql);
-
-/*
-** This routine identifies a callback function that is invoked
-** whenever an attempt is made to open a database table that is
-** currently locked by another process or thread. If the busy callback
-** is NULL, then sqlite_exec() returns SQLITE_BUSY immediately if
-** it finds a locked table. If the busy callback is not NULL, then
-** sqlite_exec() invokes the callback with three arguments. The
-** second argument is the name of the locked table and the third
-** argument is the number of times the table has been busy. If the
-** busy callback returns 0, then sqlite_exec() immediately returns
-** SQLITE_BUSY. If the callback returns non-zero, then sqlite_exec()
-** tries to open the table again and the cycle repeats.
-**
-** The default busy callback is NULL.
-**
-** Sqlite is re-entrant, so the busy handler may start a new query.
-** (It is not clear why anyone would every want to do this, but it
-** is allowed, in theory.) But the busy handler may not close the
-** database. Closing the database from a busy handler will delete
-** data structures out from under the executing query and will
-** probably result in a coredump.
-*/
-void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*);
-
-/*
-** This routine sets a busy handler that sleeps for a while when a
-** table is locked. The handler will sleep multiple times until
-** at least "ms" milleseconds of sleeping have been done. After
-** "ms" milleseconds of sleeping, the handler returns 0 which
-** causes sqlite_exec() to return SQLITE_BUSY.
-**
-** Calling this routine with an argument less than or equal to zero
-** turns off all busy handlers.
-*/
-void sqlite_busy_timeout(sqlite*, int ms);
-
-/*
-** This next routine is really just a wrapper around sqlite_exec().
-** Instead of invoking a user-supplied callback for each row of the
-** result, this routine remembers each row of the result in memory
-** obtained from malloc(), then returns all of the result after the
-** query has finished.
-**
-** As an example, suppose the query result where this table:
-**
-** Name | Age
-** -----------------------
-** Alice | 43
-** Bob | 28
-** Cindy | 21
-**
-** If the 3rd argument were &azResult then after the function returns
-** azResult will contain the following data:
-**
-** azResult[0] = "Name";
-** azResult[1] = "Age";
-** azResult[2] = "Alice";
-** azResult[3] = "43";
-** azResult[4] = "Bob";
-** azResult[5] = "28";
-** azResult[6] = "Cindy";
-** azResult[7] = "21";
-**
-** Notice that there is an extra row of data containing the column
-** headers. But the *nrow return value is still 3. *ncolumn is
-** set to 2. In general, the number of values inserted into azResult
-** will be ((*nrow) + 1)*(*ncolumn).
-**
-** After the calling function has finished using the result, it should
-** pass the result data pointer to sqlite_free_table() in order to
-** release the memory that was malloc-ed. Because of the way the
-** malloc() happens, the calling function must not try to call
-** malloc() directly. Only sqlite_free_table() is able to release
-** the memory properly and safely.
-**
-** The return value of this routine is the same as from sqlite_exec().
-*/
-int sqlite_get_table(
- sqlite*, /* An open database */
- const char *sql, /* SQL to be executed */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg /* Error msg written here */
-);
-
-/*
-** Call this routine to free the memory that sqlite_get_table() allocated.
-*/
-void sqlite_free_table(char **result);
-
-/*
-** The following routines are wrappers around sqlite_exec() and
-** sqlite_get_table(). The only difference between the routines that
-** follow and the originals is that the second argument to the
-** routines that follow is really a printf()-style format
-** string describing the SQL to be executed. Arguments to the format
-** string appear at the end of the argument list.
-**
-** All of the usual printf formatting options apply. In addition, there
-** is a "%q" option. %q works like %s in that it substitutes a null-terminated
-** string from the argument list. But %q also doubles every '\'' character.
-** %q is designed for use inside a string literal. By doubling each '\''
-** character it escapes that character and allows it to be inserted into
-** the string.
-**
-** For example, so some string variable contains text as follows:
-**
-** char *zText = "It's a happy day!";
-**
-** We can use this text in an SQL statement as follows:
-**
-** sqlite_exec_printf(db, "INSERT INTO table VALUES('%q')",
-** callback1, 0, 0, zText);
-**
-** Because the %q format string is used, the '\'' character in zText
-** is escaped and the SQL generated is as follows:
-**
-** INSERT INTO table1 VALUES('It''s a happy day!')
-**
-** This is correct. Had we used %s instead of %q, the generated SQL
-** would have looked like this:
-**
-** INSERT INTO table1 VALUES('It's a happy day!');
-**
-** This second example is an SQL syntax error. As a general rule you
-** should always use %q instead of %s when inserting text into a string
-** literal.
-*/
-int sqlite_exec_printf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- sqlite_callback, /* Callback function */
- void *, /* 1st argument to callback function */
- char **errmsg, /* Error msg written here */
- ... /* Arguments to the format string. */
-);
-int sqlite_exec_vprintf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- sqlite_callback, /* Callback function */
- void *, /* 1st argument to callback function */
- char **errmsg, /* Error msg written here */
- va_list ap /* Arguments to the format string. */
-);
-int sqlite_get_table_printf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg, /* Error msg written here */
- ... /* Arguments to the format string */
-);
-int sqlite_get_table_vprintf(
- sqlite*, /* An open database */
- const char *sqlFormat, /* printf-style format string for the SQL */
- char ***resultp, /* Result written to a char *[] that this points to */
- int *nrow, /* Number of result rows written here */
- int *ncolumn, /* Number of result columns written here */
- char **errmsg, /* Error msg written here */
- va_list ap /* Arguments to the format string */
-);
-char *sqlite_mprintf(const char*,...);
-char *sqlite_vmprintf(const char*, va_list);
-
-/*
-** Windows systems should call this routine to free memory that
-** is returned in the in the errmsg parameter of sqlite_open() when
-** SQLite is a DLL. For some reason, it does not work to call free()
-** directly.
-*/
-void sqlite_freemem(void *p);
-
-/*
-** Windows systems need functions to call to return the sqlite_version
-** and sqlite_encoding strings.
-*/
-const char *sqlite_libversion(void);
-const char *sqlite_libencoding(void);
-
-/*
-** A pointer to the following structure is used to communicate with
-** the implementations of user-defined functions.
-*/
-typedef struct sqlite_func sqlite_func;
-
-/*
-** Use the following routines to create new user-defined functions. See
-** the documentation for details.
-*/
-int sqlite_create_function(
- sqlite*, /* Database where the new function is registered */
- const char *zName, /* Name of the new function */
- int nArg, /* Number of arguments. -1 means any number */
- void (*xFunc)(sqlite_func*,int,const char**), /* C code to implement */
- void *pUserData /* Available via the sqlite_user_data() call */
-);
-int sqlite_create_aggregate(
- sqlite*, /* Database where the new function is registered */
- const char *zName, /* Name of the function */
- int nArg, /* Number of arguments */
- void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */
- void (*xFinalize)(sqlite_func*), /* Called once to get final result */
- void *pUserData /* Available via the sqlite_user_data() call */
-);
-
-/*
-** Use the following routine to define the datatype returned by a
-** user-defined function. The second argument can be one of the
-** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it
-** can be an integer greater than or equal to zero. The datatype
-** will be numeric or text (the only two types supported) if the
-** argument is SQLITE_NUMERIC or SQLITE_TEXT. If the argument is
-** SQLITE_ARGS, then the datatype is numeric if any argument to the
-** function is numeric and is text otherwise. If the second argument
-** is an integer, then the datatype of the result is the same as the
-** parameter to the function that corresponds to that integer.
-*/
-int sqlite_function_type(
- sqlite *db, /* The database there the function is registered */
- const char *zName, /* Name of the function */
- int datatype /* The datatype for this function */
-);
-#define SQLITE_NUMERIC (-1)
-#define SQLITE_TEXT (-2)
-#define SQLITE_ARGS (-3)
-
-/*
-** The user function implementations call one of the following four routines
-** in order to return their results. The first parameter to each of these
-** routines is a copy of the first argument to xFunc() or xFinialize().
-** The second parameter to these routines is the result to be returned.
-** A NULL can be passed as the second parameter to sqlite_set_result_string()
-** in order to return a NULL result.
-**
-** The 3rd argument to _string and _error is the number of characters to
-** take from the string. If this argument is negative, then all characters
-** up to and including the first '\000' are used.
-**
-** The sqlite_set_result_string() function allocates a buffer to hold the
-** result and returns a pointer to this buffer. The calling routine
-** (that is, the implmentation of a user function) can alter the content
-** of this buffer if desired.
-*/
-char *sqlite_set_result_string(sqlite_func*,const char*,int);
-void sqlite_set_result_int(sqlite_func*,int);
-void sqlite_set_result_double(sqlite_func*,double);
-void sqlite_set_result_error(sqlite_func*,const char*,int);
-
-/*
-** The pUserData parameter to the sqlite_create_function() and
-** sqlite_create_aggregate() routines used to register user functions
-** is available to the implementation of the function using this
-** call.
-*/
-void *sqlite_user_data(sqlite_func*);
-
-/*
-** Aggregate functions use the following routine to allocate
-** a structure for storing their state. The first time this routine
-** is called for a particular aggregate, a new structure of size nBytes
-** is allocated, zeroed, and returned. On subsequent calls (for the
-** same aggregate instance) the same buffer is returned. The implementation
-** of the aggregate can use the returned buffer to accumulate data.
-**
-** The buffer allocated is freed automatically be SQLite.
-*/
-void *sqlite_aggregate_context(sqlite_func*, int nBytes);
-
-/*
-** The next routine returns the number of calls to xStep for a particular
-** aggregate function instance. The current call to xStep counts so this
-** routine always returns at least 1.
-*/
-int sqlite_aggregate_count(sqlite_func*);
-
-/*
-** This routine registers a callback with the SQLite library. The
-** callback is invoked (at compile-time, not at run-time) for each
-** attempt to access a column of a table in the database. The callback
-** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire
-** SQL statement should be aborted with an error and SQLITE_IGNORE
-** if the column should be treated as a NULL value.
-*/
-int sqlite_set_authorizer(
- sqlite*,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pUserData
-);
-
-/*
-** The second parameter to the access authorization function above will
-** be one of the values below. These values signify what kind of operation
-** is to be authorized. The 3rd and 4th parameters to the authorization
-** function will be parameters or NULL depending on which of the following
-** codes is used as the second parameter. The 5th parameter is the name
-** of the database ("main", "temp", etc.) if applicable. The 6th parameter
-** is the name of the inner-most trigger or view that is responsible for
-** the access attempt or NULL if this access attempt is directly from
-** input SQL code.
-**
-** Arg-3 Arg-4
-*/
-#define SQLITE_COPY 0 /* Table Name File Name */
-#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
-#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
-#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
-#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
-#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
-#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
-#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
-#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
-#define SQLITE_DELETE 9 /* Table Name NULL */
-#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
-#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
-#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
-#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
-#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
-#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
-#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
-#define SQLITE_DROP_VIEW 17 /* View Name NULL */
-#define SQLITE_INSERT 18 /* Table Name NULL */
-#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
-#define SQLITE_READ 20 /* Table Name Column Name */
-#define SQLITE_SELECT 21 /* NULL NULL */
-#define SQLITE_TRANSACTION 22 /* NULL NULL */
-#define SQLITE_UPDATE 23 /* Table Name Column Name */
-#define SQLITE_ATTACH 24 /* Filename NULL */
-#define SQLITE_DETACH 25 /* Database Name NULL */
-
-
-/*
-** The return value of the authorization function should be one of the
-** following constants:
-*/
-/* #define SQLITE_OK 0 // Allow access (This is actually defined above) */
-#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
-#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
-
-/*
-** Register a function that is called at every invocation of sqlite_exec()
-** or sqlite_compile(). This function can be used (for example) to generate
-** a log file of all SQL executed against a database.
-*/
-void *sqlite_trace(sqlite*, void(*xTrace)(void*,const char*), void*);
-
-/*** The Callback-Free API
-**
-** The following routines implement a new way to access SQLite that does not
-** involve the use of callbacks.
-**
-** An sqlite_vm is an opaque object that represents a single SQL statement
-** that is ready to be executed.
-*/
-typedef struct sqlite_vm sqlite_vm;
-
-/*
-** To execute an SQLite query without the use of callbacks, you first have
-** to compile the SQL using this routine. The 1st parameter "db" is a pointer
-** to an sqlite object obtained from sqlite_open(). The 2nd parameter
-** "zSql" is the text of the SQL to be compiled. The remaining parameters
-** are all outputs.
-**
-** *pzTail is made to point to the first character past the end of the first
-** SQL statement in zSql. This routine only compiles the first statement
-** in zSql, so *pzTail is left pointing to what remains uncompiled.
-**
-** *ppVm is left pointing to a "virtual machine" that can be used to execute
-** the compiled statement. Or if there is an error, *ppVm may be set to NULL.
-** If the input text contained no SQL (if the input is and empty string or
-** a comment) then *ppVm is set to NULL.
-**
-** If any errors are detected during compilation, an error message is written
-** into space obtained from malloc() and *pzErrMsg is made to point to that
-** error message. The calling routine is responsible for freeing the text
-** of this message when it has finished with it. Use sqlite_freemem() to
-** free the message. pzErrMsg may be NULL in which case no error message
-** will be generated.
-**
-** On success, SQLITE_OK is returned. Otherwise and error code is returned.
-*/
-int sqlite_compile(
- sqlite *db, /* The open database */
- const char *zSql, /* SQL statement to be compiled */
- const char **pzTail, /* OUT: uncompiled tail of zSql */
- sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */
- char **pzErrmsg /* OUT: Error message. */
-);
-
-/*
-** After an SQL statement has been compiled, it is handed to this routine
-** to be executed. This routine executes the statement as far as it can
-** go then returns. The return value will be one of SQLITE_DONE,
-** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE.
-**
-** SQLITE_DONE means that the execute of the SQL statement is complete
-** an no errors have occurred. sqlite_step() should not be called again
-** for the same virtual machine. *pN is set to the number of columns in
-** the result set and *pazColName is set to an array of strings that
-** describe the column names and datatypes. The name of the i-th column
-** is (*pazColName)[i] and the datatype of the i-th column is
-** (*pazColName)[i+*pN]. *pazValue is set to NULL.
-**
-** SQLITE_ERROR means that the virtual machine encountered a run-time
-** error. sqlite_step() should not be called again for the same
-** virtual machine. *pN is set to 0 and *pazColName and *pazValue are set
-** to NULL. Use sqlite_finalize() to obtain the specific error code
-** and the error message text for the error.
-**
-** SQLITE_BUSY means that an attempt to open the database failed because
-** another thread or process is holding a lock. The calling routine
-** can try again to open the database by calling sqlite_step() again.
-** The return code will only be SQLITE_BUSY if no busy handler is registered
-** using the sqlite_busy_handler() or sqlite_busy_timeout() routines. If
-** a busy handler callback has been registered but returns 0, then this
-** routine will return SQLITE_ERROR and sqltie_finalize() will return
-** SQLITE_BUSY when it is called.
-**
-** SQLITE_ROW means that a single row of the result is now available.
-** The data is contained in *pazValue. The value of the i-th column is
-** (*azValue)[i]. *pN and *pazColName are set as described in SQLITE_DONE.
-** Invoke sqlite_step() again to advance to the next row.
-**
-** SQLITE_MISUSE is returned if sqlite_step() is called incorrectly.
-** For example, if you call sqlite_step() after the virtual machine
-** has halted (after a prior call to sqlite_step() has returned SQLITE_DONE)
-** or if you call sqlite_step() with an incorrectly initialized virtual
-** machine or a virtual machine that has been deleted or that is associated
-** with an sqlite structure that has been closed.
-*/
-int sqlite_step(
- sqlite_vm *pVm, /* The virtual machine to execute */
- int *pN, /* OUT: Number of columns in result */
- const char ***pazValue, /* OUT: Column data */
- const char ***pazColName /* OUT: Column names and datatypes */
-);
-
-/*
-** This routine is called to delete a virtual machine after it has finished
-** executing. The return value is the result code. SQLITE_OK is returned
-** if the statement executed successfully and some other value is returned if
-** there was any kind of error. If an error occurred and pzErrMsg is not
-** NULL, then an error message is written into memory obtained from malloc()
-** and *pzErrMsg is made to point to that error message. The calling routine
-** should use sqlite_freemem() to delete this message when it has finished
-** with it.
-**
-** This routine can be called at any point during the execution of the
-** virtual machine. If the virtual machine has not completed execution
-** when this routine is called, that is like encountering an error or
-** an interrupt. (See sqlite_interrupt().) Incomplete updates may be
-** rolled back and transactions cancelled, depending on the circumstances,
-** and the result code returned will be SQLITE_ABORT.
-*/
-int sqlite_finalize(sqlite_vm*, char **pzErrMsg);
-
-/*
-** This routine deletes the virtual machine, writes any error message to
-** *pzErrMsg and returns an SQLite return code in the same way as the
-** sqlite_finalize() function.
-**
-** Additionally, if ppVm is not NULL, *ppVm is left pointing to a new virtual
-** machine loaded with the compiled version of the original query ready for
-** execution.
-**
-** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-int sqlite_reset(sqlite_vm*, char **pzErrMsg);
-
-/*
-** If the SQL that was handed to sqlite_compile contains variables that
-** are represeted in the SQL text by a question mark ('?'). This routine
-** is used to assign values to those variables.
-**
-** The first parameter is a virtual machine obtained from sqlite_compile().
-** The 2nd "idx" parameter determines which variable in the SQL statement
-** to bind the value to. The left most '?' is 1. The 3rd parameter is
-** the value to assign to that variable. The 4th parameter is the number
-** of bytes in the value, including the terminating \000 for strings.
-** Finally, the 5th "copy" parameter is TRUE if SQLite should make its
-** own private copy of this value, or false if the space that the 3rd
-** parameter points to will be unchanging and can be used directly by
-** SQLite.
-**
-** Unbound variables are treated as having a value of NULL. To explicitly
-** set a variable to NULL, call this routine with the 3rd parameter as a
-** NULL pointer.
-**
-** If the 4th "len" parameter is -1, then strlen() is used to find the
-** length.
-**
-** This routine can only be called immediately after sqlite_compile()
-** or sqlite_reset() and before any calls to sqlite_step().
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
-*/
-int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy);
-
-/*
-** This routine configures a callback function - the progress callback - that
-** is invoked periodically during long running calls to sqlite_exec(),
-** sqlite_step() and sqlite_get_table(). An example use for this API is to keep
-** a GUI updated during a large query.
-**
-** The progress callback is invoked once for every N virtual machine opcodes,
-** where N is the second argument to this function. The progress callback
-** itself is identified by the third argument to this function. The fourth
-** argument to this function is a void pointer passed to the progress callback
-** function each time it is invoked.
-**
-** If a call to sqlite_exec(), sqlite_step() or sqlite_get_table() results
-** in less than N opcodes being executed, then the progress callback is not
-** invoked.
-**
-** Calling this routine overwrites any previously installed progress callback.
-** To remove the progress callback altogether, pass NULL as the third
-** argument to this function.
-**
-** If the progress callback returns a result other than 0, then the current
-** query is immediately terminated and any database changes rolled back. If the
-** query was part of a larger transaction, then the transaction is not rolled
-** back and remains active. The sqlite_exec() call returns SQLITE_ABORT.
-*/
-void sqlite_progress_handler(sqlite*, int, int(*)(void*), void*);
-
-#ifdef __cplusplus
-} /* End of the 'extern "C"' block */
-#endif
-
-#endif /* _SQLITE_H_ */
diff --git a/ext/sqlite/libsqlite/src/sqliteInt.h b/ext/sqlite/libsqlite/src/sqliteInt.h
deleted file mode 100644
index e7b4a84e99..0000000000
--- a/ext/sqlite/libsqlite/src/sqliteInt.h
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** Internal interface definitions for SQLite.
-**
-** @(#) $Id$
-*/
-#include "config.h"
-#include "sqlite.h"
-#include "hash.h"
-#include "parse.h"
-#include "btree.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/*
-** The maximum number of in-memory pages to use for the main database
-** table and for temporary tables.
-*/
-#define MAX_PAGES 2000
-#define TEMP_PAGES 500
-
-/*
-** If the following macro is set to 1, then NULL values are considered
-** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT
-** compound queries. No other SQL database engine (among those tested)
-** works this way except for OCELOT. But the SQL92 spec implies that
-** this is how things should work.
-**
-** If the following macro is set to 0, then NULLs are indistinct for
-** SELECT DISTINCT and for UNION.
-*/
-#define NULL_ALWAYS_DISTINCT 0
-
-/*
-** If the following macro is set to 1, then NULL values are considered
-** distinct when determining whether or not two entries are the same
-** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL,
-** OCELOT, and Firebird all work. The SQL92 spec explicitly says this
-** is the way things are suppose to work.
-**
-** If the following macro is set to 0, the NULLs are indistinct for
-** a UNIQUE index. In this mode, you can only have a single NULL entry
-** for a column declared UNIQUE. This is the way Informix and SQL Server
-** work.
-*/
-#define NULL_DISTINCT_FOR_UNIQUE 1
-
-/*
-** The maximum number of attached databases. This must be at least 2
-** in order to support the main database file (0) and the file used to
-** hold temporary tables (1). And it must be less than 256 because
-** an unsigned character is used to stored the database index.
-*/
-#define MAX_ATTACHED 10
-
-/*
-** The next macro is used to determine where TEMP tables and indices
-** are stored. Possible values:
-**
-** 0 Always use a temporary files
-** 1 Use a file unless overridden by "PRAGMA temp_store"
-** 2 Use memory unless overridden by "PRAGMA temp_store"
-** 3 Always use memory
-*/
-#ifndef TEMP_STORE
-# define TEMP_STORE 1
-#endif
-
-/*
-** When building SQLite for embedded systems where memory is scarce,
-** you can define one or more of the following macros to omit extra
-** features of the library and thus keep the size of the library to
-** a minimum.
-*/
-/* #define SQLITE_OMIT_AUTHORIZATION 1 */
-/* #define SQLITE_OMIT_INMEMORYDB 1 */
-/* #define SQLITE_OMIT_VACUUM 1 */
-/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */
-/* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */
-
-/*
-** Integers of known sizes. These typedefs might change for architectures
-** where the sizes very. Preprocessor macros are available so that the
-** types can be conveniently redefined at compile-type. Like this:
-**
-** cc '-DUINTPTR_TYPE=long long int' ...
-*/
-#ifndef UINT32_TYPE
-# define UINT32_TYPE unsigned int
-#endif
-#ifndef UINT16_TYPE
-# define UINT16_TYPE unsigned short int
-#endif
-#ifndef INT16_TYPE
-# define INT16_TYPE short int
-#endif
-#ifndef UINT8_TYPE
-# define UINT8_TYPE unsigned char
-#endif
-#ifndef INT8_TYPE
-# define INT8_TYPE signed char
-#endif
-#ifndef INTPTR_TYPE
-# if SQLITE_PTR_SZ==4
-# define INTPTR_TYPE int
-# else
-# define INTPTR_TYPE long long
-# endif
-#endif
-typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
-typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
-typedef INT16_TYPE i16; /* 2-byte signed integer */
-typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
-typedef UINT8_TYPE i8; /* 1-byte signed integer */
-typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */
-typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */
-
-/*
-** Defer sourcing vdbe.h until after the "u8" typedef is defined.
-*/
-#include "vdbe.h"
-
-/*
-** Most C compilers these days recognize "long double", don't they?
-** Just in case we encounter one that does not, we will create a macro
-** for long double so that it can be easily changed to just "double".
-*/
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
-#endif
-
-/*
-** This macro casts a pointer to an integer. Useful for doing
-** pointer arithmetic.
-*/
-#define Addr(X) ((uptr)X)
-
-/*
-** The maximum number of bytes of data that can be put into a single
-** row of a single table. The upper bound on this limit is 16777215
-** bytes (or 16MB-1). We have arbitrarily set the limit to just 1MB
-** here because the overflow page chain is inefficient for really big
-** records and we want to discourage people from thinking that
-** multi-megabyte records are OK. If your needs are different, you can
-** change this define and recompile to increase or decrease the record
-** size.
-**
-** The 16777198 is computed as follows: 238 bytes of payload on the
-** original pages plus 16448 overflow pages each holding 1020 bytes of
-** data.
-*/
-#define MAX_BYTES_PER_ROW 1048576
-/* #define MAX_BYTES_PER_ROW 16777198 */
-
-/*
-** If memory allocation problems are found, recompile with
-**
-** -DMEMORY_DEBUG=1
-**
-** to enable some sanity checking on malloc() and free(). To
-** check for memory leaks, recompile with
-**
-** -DMEMORY_DEBUG=2
-**
-** and a line of text will be written to standard error for
-** each malloc() and free(). This output can be analyzed
-** by an AWK script to determine if there are any leaks.
-*/
-#ifdef MEMORY_DEBUG
-# define sqliteMalloc(X) sqliteMalloc_(X,1,__FILE__,__LINE__)
-# define sqliteMallocRaw(X) sqliteMalloc_(X,0,__FILE__,__LINE__)
-# define sqliteFree(X) sqliteFree_(X,__FILE__,__LINE__)
-# define sqliteRealloc(X,Y) sqliteRealloc_(X,Y,__FILE__,__LINE__)
-# define sqliteStrDup(X) sqliteStrDup_(X,__FILE__,__LINE__)
-# define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__)
- void sqliteStrRealloc(char**);
-#else
-# define sqliteRealloc_(X,Y) sqliteRealloc(X,Y)
-# define sqliteStrRealloc(X)
-#endif
-
-/*
-** This variable gets set if malloc() ever fails. After it gets set,
-** the SQLite library shuts down permanently.
-*/
-extern int sqlite_malloc_failed;
-
-/*
-** The following global variables are used for testing and debugging
-** only. They only work if MEMORY_DEBUG is defined.
-*/
-#ifdef MEMORY_DEBUG
-extern int sqlite_nMalloc; /* Number of sqliteMalloc() calls */
-extern int sqlite_nFree; /* Number of sqliteFree() calls */
-extern int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */
-#endif
-
-/*
-** Name of the master database table. The master database table
-** is a special table that holds the names and attributes of all
-** user tables and indices.
-*/
-#define MASTER_NAME "sqlite_master"
-#define TEMP_MASTER_NAME "sqlite_temp_master"
-
-/*
-** The name of the schema table.
-*/
-#define SCHEMA_TABLE(x) (x?TEMP_MASTER_NAME:MASTER_NAME)
-
-/*
-** A convenience macro that returns the number of elements in
-** an array.
-*/
-#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
-
-/*
-** Forward references to structures
-*/
-typedef struct Column Column;
-typedef struct Table Table;
-typedef struct Index Index;
-typedef struct Instruction Instruction;
-typedef struct Expr Expr;
-typedef struct ExprList ExprList;
-typedef struct Parse Parse;
-typedef struct Token Token;
-typedef struct IdList IdList;
-typedef struct SrcList SrcList;
-typedef struct WhereInfo WhereInfo;
-typedef struct WhereLevel WhereLevel;
-typedef struct Select Select;
-typedef struct AggExpr AggExpr;
-typedef struct FuncDef FuncDef;
-typedef struct Trigger Trigger;
-typedef struct TriggerStep TriggerStep;
-typedef struct TriggerStack TriggerStack;
-typedef struct FKey FKey;
-typedef struct Db Db;
-typedef struct AuthContext AuthContext;
-
-/*
-** Each database file to be accessed by the system is an instance
-** of the following structure. There are normally two of these structures
-** in the sqlite.aDb[] array. aDb[0] is the main database file and
-** aDb[1] is the database file used to hold temporary tables. Additional
-** databases may be attached.
-*/
-struct Db {
- char *zName; /* Name of this database */
- Btree *pBt; /* The B*Tree structure for this database file */
- int schema_cookie; /* Database schema version number for this file */
- Hash tblHash; /* All tables indexed by name */
- Hash idxHash; /* All (named) indices indexed by name */
- Hash trigHash; /* All triggers indexed by name */
- Hash aFKey; /* Foreign keys indexed by to-table */
- u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
- u16 flags; /* Flags associated with this database */
- void *pAux; /* Auxiliary data. Usually NULL */
- void (*xFreeAux)(void*); /* Routine to free pAux */
-};
-
-/*
-** These macros can be used to test, set, or clear bits in the
-** Db.flags field.
-*/
-#define DbHasProperty(D,I,P) (((D)->aDb[I].flags&(P))==(P))
-#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].flags&(P))!=0)
-#define DbSetProperty(D,I,P) (D)->aDb[I].flags|=(P)
-#define DbClearProperty(D,I,P) (D)->aDb[I].flags&=~(P)
-
-/*
-** Allowed values for the DB.flags field.
-**
-** The DB_Locked flag is set when the first OP_Transaction or OP_Checkpoint
-** opcode is emitted for a database. This prevents multiple occurances
-** of those opcodes for the same database in the same program. Similarly,
-** the DB_Cookie flag is set when the OP_VerifyCookie opcode is emitted,
-** and prevents duplicate OP_VerifyCookies from taking up space and slowing
-** down execution.
-**
-** The DB_SchemaLoaded flag is set after the database schema has been
-** read into internal hash tables.
-**
-** DB_UnresetViews means that one or more views have column names that
-** have been filled out. If the schema changes, these column names might
-** changes and so the view will need to be reset.
-*/
-#define DB_Locked 0x0001 /* OP_Transaction opcode has been emitted */
-#define DB_Cookie 0x0002 /* OP_VerifyCookie opcode has been emiited */
-#define DB_SchemaLoaded 0x0004 /* The schema has been loaded */
-#define DB_UnresetViews 0x0008 /* Some views have defined column names */
-
-
-/*
-** Each database is an instance of the following structure.
-**
-** The sqlite.file_format is initialized by the database file
-** and helps determines how the data in the database file is
-** represented. This field allows newer versions of the library
-** to read and write older databases. The various file formats
-** are as follows:
-**
-** file_format==1 Version 2.1.0.
-** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY.
-** file_format==3 Version 2.6.0. Fix empty-string index bug.
-** file_format==4 Version 2.7.0. Add support for separate numeric and
-** text datatypes.
-**
-** The sqlite.temp_store determines where temporary database files
-** are stored. If 1, then a file is created to hold those tables. If
-** 2, then they are held in memory. 0 means use the default value in
-** the TEMP_STORE macro.
-**
-** The sqlite.lastRowid records the last insert rowid generated by an
-** insert statement. Inserts on views do not affect its value. Each
-** trigger has its own context, so that lastRowid can be updated inside
-** triggers as usual. The previous value will be restored once the trigger
-** exits. Upon entering a before or instead of trigger, lastRowid is no
-** longer (since after version 2.8.12) reset to -1.
-**
-** The sqlite.nChange does not count changes within triggers and keeps no
-** context. It is reset at start of sqlite_exec.
-** The sqlite.lsChange represents the number of changes made by the last
-** insert, update, or delete statement. It remains constant throughout the
-** length of a statement and is then updated by OP_SetCounts. It keeps a
-** context stack just like lastRowid so that the count of changes
-** within a trigger is not seen outside the trigger. Changes to views do not
-** affect the value of lsChange.
-** The sqlite.csChange keeps track of the number of current changes (since
-** the last statement) and is used to update sqlite_lsChange.
-*/
-struct sqlite {
- int nDb; /* Number of backends currently in use */
- Db *aDb; /* All backends */
- Db aDbStatic[2]; /* Static space for the 2 default backends */
- int flags; /* Miscellanous flags. See below */
- u8 file_format; /* What file format version is this database? */
- u8 safety_level; /* How aggressive at synching data to disk */
- u8 want_to_close; /* Close after all VDBEs are deallocated */
- u8 temp_store; /* 1=file, 2=memory, 0=compile-time default */
- u8 onError; /* Default conflict algorithm */
- int next_cookie; /* Next value of aDb[0].schema_cookie */
- int cache_size; /* Number of pages to use in the cache */
- int nTable; /* Number of tables in the database */
- void *pBusyArg; /* 1st Argument to the busy callback */
- int (*xBusyCallback)(void *,const char*,int); /* The busy callback */
- void *pCommitArg; /* Argument to xCommitCallback() */
- int (*xCommitCallback)(void*);/* Invoked at every commit. */
- Hash aFunc; /* All functions that can be in SQL exprs */
- int lastRowid; /* ROWID of most recent insert (see above) */
- int priorNewRowid; /* Last randomly generated ROWID */
- int magic; /* Magic number for detect library misuse */
- int nChange; /* Number of rows changed (see above) */
- int lsChange; /* Last statement change count (see above) */
- int csChange; /* Current statement change count (see above) */
- struct sqliteInitInfo { /* Information used during initialization */
- int iDb; /* When back is being initialized */
- int newTnum; /* Rootpage of table being initialized */
- u8 busy; /* TRUE if currently initializing */
- } init;
- struct Vdbe *pVdbe; /* List of active virtual machines */
- void (*xTrace)(void*,const char*); /* Trace function */
- void *pTraceArg; /* Argument to the trace function */
-#ifndef SQLITE_OMIT_AUTHORIZATION
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
- /* Access authorization function */
- void *pAuthArg; /* 1st argument to the access auth function */
-#endif
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- int (*xProgress)(void *); /* The progress callback */
- void *pProgressArg; /* Argument to the progress callback */
- int nProgressOps; /* Number of opcodes for progress callback */
-#endif
-};
-
-/*
-** Possible values for the sqlite.flags and or Db.flags fields.
-**
-** On sqlite.flags, the SQLITE_InTrans value means that we have
-** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement
-** transaction is active on that particular database file.
-*/
-#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
-#define SQLITE_Initialized 0x00000002 /* True after initialization */
-#define SQLITE_Interrupt 0x00000004 /* Cancel current operation */
-#define SQLITE_InTrans 0x00000008 /* True if in a transaction */
-#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */
-#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
-#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
- /* DELETE, or UPDATE and return */
- /* the count using a callback. */
-#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
- /* result set is empty */
-#define SQLITE_ReportTypes 0x00000200 /* Include information on datatypes */
- /* in 4th argument of callback */
-
-/*
-** Possible values for the sqlite.magic field.
-** The numbers are obtained at random and have no special meaning, other
-** than being distinct from one another.
-*/
-#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */
-#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */
-#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
-#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
-
-/*
-** Each SQL function is defined by an instance of the following
-** structure. A pointer to this structure is stored in the sqlite.aFunc
-** hash table. When multiple functions have the same name, the hash table
-** points to a linked list of these structures.
-*/
-struct FuncDef {
- void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */
- void (*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */
- void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */
- signed char nArg; /* Number of arguments. -1 means unlimited */
- signed char dataType; /* Arg that determines datatype. -1=NUMERIC, */
- /* -2=TEXT. -3=SQLITE_ARGS */
- u8 includeTypes; /* Add datatypes to args of xFunc and xStep */
- void *pUserData; /* User data parameter */
- FuncDef *pNext; /* Next function with same name */
-};
-
-/*
-** information about each column of an SQL table is held in an instance
-** of this structure.
-*/
-struct Column {
- char *zName; /* Name of this column */
- char *zDflt; /* Default value of this column */
- char *zType; /* Data type for this column */
- u8 notNull; /* True if there is a NOT NULL constraint */
- u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */
- u8 sortOrder; /* Some combination of SQLITE_SO_... values */
- u8 dottedName; /* True if zName contains a "." character */
-};
-
-/*
-** The allowed sort orders.
-**
-** The TEXT and NUM values use bits that do not overlap with DESC and ASC.
-** That way the two can be combined into a single number.
-*/
-#define SQLITE_SO_UNK 0 /* Use the default collating type. (SCT_NUM) */
-#define SQLITE_SO_TEXT 2 /* Sort using memcmp() */
-#define SQLITE_SO_NUM 4 /* Sort using sqliteCompare() */
-#define SQLITE_SO_TYPEMASK 6 /* Mask to extract the collating sequence */
-#define SQLITE_SO_ASC 0 /* Sort in ascending order */
-#define SQLITE_SO_DESC 1 /* Sort in descending order */
-#define SQLITE_SO_DIRMASK 1 /* Mask to extract the sort direction */
-
-/*
-** Each SQL table is represented in memory by an instance of the
-** following structure.
-**
-** Table.zName is the name of the table. The case of the original
-** CREATE TABLE statement is stored, but case is not significant for
-** comparisons.
-**
-** Table.nCol is the number of columns in this table. Table.aCol is a
-** pointer to an array of Column structures, one for each column.
-**
-** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
-** the column that is that key. Otherwise Table.iPKey is negative. Note
-** that the datatype of the PRIMARY KEY must be INTEGER for this field to
-** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
-** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table. Table.hasPrimKey is true if
-** the table has any PRIMARY KEY, INTEGER or otherwise.
-**
-** Table.tnum is the page number for the root BTree page of the table in the
-** database file. If Table.iDb is the index of the database table backend
-** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
-** holds temporary tables and indices. If Table.isTransient
-** is true, then the table is stored in a file that is automatically deleted
-** when the VDBE cursor to the table is closed. In this case Table.tnum
-** refers VDBE cursor number that holds the table open, not to the root
-** page number. Transient tables are used to hold the results of a
-** sub-query that appears instead of a real table name in the FROM clause
-** of a SELECT statement.
-*/
-struct Table {
- char *zName; /* Name of the table */
- int nCol; /* Number of columns in this table */
- Column *aCol; /* Information about each column */
- int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */
- Index *pIndex; /* List of SQL indexes on this table. */
- int tnum; /* Root BTree node for this table (see note above) */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- u8 readOnly; /* True if this table should not be written by the user */
- u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */
- u8 isTransient; /* True if automatically deleted when VDBE finishes */
- u8 hasPrimKey; /* True if there exists a primary key */
- u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
- Trigger *pTrigger; /* List of SQL triggers on this table */
- FKey *pFKey; /* Linked list of all foreign keys in this table */
-};
-
-/*
-** Each foreign key constraint is an instance of the following structure.
-**
-** A foreign key is associated with two tables. The "from" table is
-** the table that contains the REFERENCES clause that creates the foreign
-** key. The "to" table is the table that is named in the REFERENCES clause.
-** Consider this example:
-**
-** CREATE TABLE ex1(
-** a INTEGER PRIMARY KEY,
-** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x)
-** );
-**
-** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
-**
-** Each REFERENCES clause generates an instance of the following structure
-** which is attached to the from-table. The to-table need not exist when
-** the from-table is created. The existance of the to-table is not checked
-** until an attempt is made to insert data into the from-table.
-**
-** The sqlite.aFKey hash table stores pointers to this structure
-** given the name of a to-table. For each to-table, all foreign keys
-** associated with that table are on a linked list using the FKey.pNextTo
-** field.
-*/
-struct FKey {
- Table *pFrom; /* The table that constains the REFERENCES clause */
- FKey *pNextFrom; /* Next foreign key in pFrom */
- char *zTo; /* Name of table that the key points to */
- FKey *pNextTo; /* Next foreign key that points to zTo */
- int nCol; /* Number of columns in this key */
- struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
- int iFrom; /* Index of column in pFrom */
- char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */
- } *aCol; /* One entry for each of nCol column s */
- u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
- u8 updateConf; /* How to resolve conflicts that occur on UPDATE */
- u8 deleteConf; /* How to resolve conflicts that occur on DELETE */
- u8 insertConf; /* How to resolve conflicts that occur on INSERT */
-};
-
-/*
-** SQLite supports many different ways to resolve a contraint
-** error. ROLLBACK processing means that a constraint violation
-** causes the operation in process to fail and for the current transaction
-** to be rolled back. ABORT processing means the operation in process
-** fails and any prior changes from that one operation are backed out,
-** but the transaction is not rolled back. FAIL processing means that
-** the operation in progress stops and returns an error code. But prior
-** changes due to the same operation are not backed out and no rollback
-** occurs. IGNORE means that the particular row that caused the constraint
-** error is not inserted or updated. Processing continues and no error
-** is returned. REPLACE means that preexisting database rows that caused
-** a UNIQUE constraint violation are removed so that the new insert or
-** update can proceed. Processing continues and no error is reported.
-**
-** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
-** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
-** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
-** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
-** referenced table row is propagated into the row that holds the
-** foreign key.
-**
-** The following symbolic values are used to record which type
-** of action to take.
-*/
-#define OE_None 0 /* There is no constraint to check */
-#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
-#define OE_Abort 2 /* Back out changes but do no rollback transaction */
-#define OE_Fail 3 /* Stop the operation but leave all prior changes */
-#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */
-#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */
-
-#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
-#define OE_SetNull 7 /* Set the foreign key value to NULL */
-#define OE_SetDflt 8 /* Set the foreign key value to its default */
-#define OE_Cascade 9 /* Cascade the changes */
-
-#define OE_Default 99 /* Do whatever the default action is */
-
-/*
-** Each SQL index is represented in memory by an
-** instance of the following structure.
-**
-** The columns of the table that are to be indexed are described
-** by the aiColumn[] field of this structure. For example, suppose
-** we have the following table and index:
-**
-** CREATE TABLE Ex1(c1 int, c2 int, c3 text);
-** CREATE INDEX Ex2 ON Ex1(c3,c1);
-**
-** In the Table structure describing Ex1, nCol==3 because there are
-** three columns in the table. In the Index structure describing
-** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
-** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
-** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
-** The second column to be indexed (c1) has an index of 0 in
-** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
-**
-** The Index.onError field determines whether or not the indexed columns
-** must be unique and what to do if they are not. When Index.onError=OE_None,
-** it means this is not a unique index. Otherwise it is a unique index
-** and the value of Index.onError indicate the which conflict resolution
-** algorithm to employ whenever an attempt is made to insert a non-unique
-** element.
-*/
-struct Index {
- char *zName; /* Name of this index */
- int nColumn; /* Number of columns in the table used by this index */
- int *aiColumn; /* Which columns are used by this index. 1st is 0 */
- Table *pTable; /* The SQL table being indexed */
- int tnum; /* Page containing root of this index in database file */
- u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
- u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */
- Index *pNext; /* The next index associated with the same table */
-};
-
-/*
-** Each token coming out of the lexer is an instance of
-** this structure. Tokens are also used as part of an expression.
-**
-** Note if Token.z==0 then Token.dyn and Token.n are undefined and
-** may contain random values. Do not make any assuptions about Token.dyn
-** and Token.n when Token.z==0.
-*/
-struct Token {
- const char *z; /* Text of the token. Not NULL-terminated! */
- unsigned dyn : 1; /* True for malloced memory, false for static */
- unsigned n : 31; /* Number of characters in this token */
-};
-
-/*
-** Each node of an expression in the parse tree is an instance
-** of this structure.
-**
-** Expr.op is the opcode. The integer parser token codes are reused
-** as opcodes here. For example, the parser defines TK_GE to be an integer
-** code representing the ">=" operator. This same integer code is reused
-** to represent the greater-than-or-equal-to operator in the expression
-** tree.
-**
-** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list
-** of argument if the expression is a function.
-**
-** Expr.token is the operator token for this node. For some expressions
-** that have subexpressions, Expr.token can be the complete text that gave
-** rise to the Expr. In the latter case, the token is marked as being
-** a compound token.
-**
-** An expression of the form ID or ID.ID refers to a column in a table.
-** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
-** the integer cursor number of a VDBE cursor pointing to that table and
-** Expr.iColumn is the column number for the specific column. If the
-** expression is used as a result in an aggregate SELECT, then the
-** value is also stored in the Expr.iAgg column in the aggregate so that
-** it can be accessed after all aggregates are computed.
-**
-** If the expression is a function, the Expr.iTable is an integer code
-** representing which function. If the expression is an unbound variable
-** marker (a question mark character '?' in the original SQL) then the
-** Expr.iTable holds the index number for that variable.
-**
-** The Expr.pSelect field points to a SELECT statement. The SELECT might
-** be the right operand of an IN operator. Or, if a scalar SELECT appears
-** in an expression the opcode is TK_SELECT and Expr.pSelect is the only
-** operand.
-*/
-struct Expr {
- u8 op; /* Operation performed by this node */
- u8 dataType; /* Either SQLITE_SO_TEXT or SQLITE_SO_NUM */
- u8 iDb; /* Database referenced by this expression */
- u8 flags; /* Various flags. See below */
- Expr *pLeft, *pRight; /* Left and right subnodes */
- ExprList *pList; /* A list of expressions used as function arguments
- ** or in "<expr> IN (<expr-list)" */
- Token token; /* An operand token */
- Token span; /* Complete text of the expression */
- int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the
- ** iColumn-th field of the iTable-th table. */
- int iAgg; /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull
- ** result from the iAgg-th element of the aggregator */
- Select *pSelect; /* When the expression is a sub-select. Also the
- ** right side of "<expr> IN (<select>)" */
-};
-
-/*
-** The following are the meanings of bits in the Expr.flags field.
-*/
-#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
-
-/*
-** These macros can be used to test, set, or clear bits in the
-** Expr.flags field.
-*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
-
-/*
-** A list of expressions. Each expression may optionally have a
-** name. An expr/name combination can be used in several ways, such
-** as the list of "expr AS ID" fields following a "SELECT" or in the
-** list of "ID = expr" items in an UPDATE. A list of expressions can
-** also be used as the argument to a function, in which case the a.zName
-** field is not used.
-*/
-struct ExprList {
- int nExpr; /* Number of expressions on the list */
- int nAlloc; /* Number of entries allocated below */
- struct ExprList_item {
- Expr *pExpr; /* The list of expressions */
- char *zName; /* Token associated with this expression */
- u8 sortOrder; /* 1 for DESC or 0 for ASC */
- u8 isAgg; /* True if this is an aggregate like count(*) */
- u8 done; /* A flag to indicate when processing is finished */
- } *a; /* One entry for each expression */
-};
-
-/*
-** An instance of this structure can hold a simple list of identifiers,
-** such as the list "a,b,c" in the following statements:
-**
-** INSERT INTO t(a,b,c) VALUES ...;
-** CREATE INDEX idx ON t(a,b,c);
-** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...;
-**
-** The IdList.a.idx field is used when the IdList represents the list of
-** column names after a table name in an INSERT statement. In the statement
-**
-** INSERT INTO t(a,b,c) ...
-**
-** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
-*/
-struct IdList {
- int nId; /* Number of identifiers on the list */
- int nAlloc; /* Number of entries allocated for a[] below */
- struct IdList_item {
- char *zName; /* Name of the identifier */
- int idx; /* Index in some Table.aCol[] of a column named zName */
- } *a;
-};
-
-/*
-** The following structure describes the FROM clause of a SELECT statement.
-** Each table or subquery in the FROM clause is a separate element of
-** the SrcList.a[] array.
-**
-** With the addition of multiple database support, the following structure
-** can also be used to describe a particular table such as the table that
-** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL,
-** such a table must be a simple name: ID. But in SQLite, the table can
-** now be identified by a database name, a dot, then the table name: ID.ID.
-*/
-struct SrcList {
- i16 nSrc; /* Number of tables or subqueries in the FROM clause */
- i16 nAlloc; /* Number of entries allocated in a[] below */
- struct SrcList_item {
- char *zDatabase; /* Name of database holding this table */
- char *zName; /* Name of the table */
- char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int jointype; /* Type of join between this table and the next */
- int iCursor; /* The VDBE cursor number used to access this table */
- Expr *pOn; /* The ON clause of a join */
- IdList *pUsing; /* The USING clause of a join */
- } a[1]; /* One entry for each identifier on the list */
-};
-
-/*
-** Permitted values of the SrcList.a.jointype field
-*/
-#define JT_INNER 0x0001 /* Any kind of inner or cross join */
-#define JT_NATURAL 0x0002 /* True for a "natural" join */
-#define JT_LEFT 0x0004 /* Left outer join */
-#define JT_RIGHT 0x0008 /* Right outer join */
-#define JT_OUTER 0x0010 /* The "OUTER" keyword is present */
-#define JT_ERROR 0x0020 /* unknown or unsupported join type */
-
-/*
-** For each nested loop in a WHERE clause implementation, the WhereInfo
-** structure contains a single instance of this structure. This structure
-** is intended to be private the the where.c module and should not be
-** access or modified by other modules.
-*/
-struct WhereLevel {
- int iMem; /* Memory cell used by this level */
- Index *pIdx; /* Index used */
- int iCur; /* Cursor number used for this index */
- int score; /* How well this indexed scored */
- int brk; /* Jump here to break out of the loop */
- int cont; /* Jump here to continue with the next loop cycle */
- int op, p1, p2; /* Opcode used to terminate the loop */
- int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
- int top; /* First instruction of interior of the loop */
- int inOp, inP1, inP2;/* Opcode used to implement an IN operator */
- int bRev; /* Do the scan in the reverse direction */
-};
-
-/*
-** The WHERE clause processing routine has two halves. The
-** first part does the start of the WHERE loop and the second
-** half does the tail of the WHERE loop. An instance of
-** this structure is returned by the first half and passed
-** into the second half to give some continuity.
-*/
-struct WhereInfo {
- Parse *pParse;
- SrcList *pTabList; /* List of tables in the join */
- int iContinue; /* Jump here to continue with next record */
- int iBreak; /* Jump here to break out of the loop */
- int nLevel; /* Number of nested loop */
- int savedNTab; /* Value of pParse->nTab before WhereBegin() */
- int peakNTab; /* Value of pParse->nTab after WhereBegin() */
- WhereLevel a[1]; /* Information about each nest loop in the WHERE */
-};
-
-/*
-** An instance of the following structure contains all information
-** needed to generate code for a single SELECT statement.
-**
-** The zSelect field is used when the Select structure must be persistent.
-** Normally, the expression tree points to tokens in the original input
-** string that encodes the select. But if the Select structure must live
-** longer than its input string (for example when it is used to describe
-** a VIEW) we have to make a copy of the input string so that the nodes
-** of the expression tree will have something to point to. zSelect is used
-** to hold that copy.
-**
-** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0.
-** If there is a LIMIT clause, the parser sets nLimit to the value of the
-** limit and nOffset to the value of the offset (or 0 if there is not
-** offset). But later on, nLimit and nOffset become the memory locations
-** in the VDBE that record the limit and offset counters.
-*/
-struct Select {
- ExprList *pEList; /* The fields of the result */
- u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
- u8 isDistinct; /* True if the DISTINCT keyword is present */
- SrcList *pSrc; /* The FROM clause */
- Expr *pWhere; /* The WHERE clause */
- ExprList *pGroupBy; /* The GROUP BY clause */
- Expr *pHaving; /* The HAVING clause */
- ExprList *pOrderBy; /* The ORDER BY clause */
- Select *pPrior; /* Prior select in a compound select statement */
- int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */
- int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
- char *zSelect; /* Complete text of the SELECT command */
-};
-
-/*
-** The results of a select can be distributed in several ways.
-*/
-#define SRT_Callback 1 /* Invoke a callback with each row of result */
-#define SRT_Mem 2 /* Store result in a memory cell */
-#define SRT_Set 3 /* Store result as unique keys in a table */
-#define SRT_Union 5 /* Store result as keys in a table */
-#define SRT_Except 6 /* Remove result from a UNION table */
-#define SRT_Table 7 /* Store result as data with a unique key */
-#define SRT_TempTable 8 /* Store result in a trasient table */
-#define SRT_Discard 9 /* Do not save the results anywhere */
-#define SRT_Sorter 10 /* Store results in the sorter */
-#define SRT_Subroutine 11 /* Call a subroutine to handle results */
-
-/*
-** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
-** we have to do some additional analysis of expressions. An instance
-** of the following structure holds information about a single subexpression
-** somewhere in the SELECT statement. An array of these structures holds
-** all the information we need to generate code for aggregate
-** expressions.
-**
-** Note that when analyzing a SELECT containing aggregates, both
-** non-aggregate field variables and aggregate functions are stored
-** in the AggExpr array of the Parser structure.
-**
-** The pExpr field points to an expression that is part of either the
-** field list, the GROUP BY clause, the HAVING clause or the ORDER BY
-** clause. The expression will be freed when those clauses are cleaned
-** up. Do not try to delete the expression attached to AggExpr.pExpr.
-**
-** If AggExpr.pExpr==0, that means the expression is "count(*)".
-*/
-struct AggExpr {
- int isAgg; /* if TRUE contains an aggregate function */
- Expr *pExpr; /* The expression */
- FuncDef *pFunc; /* Information about the aggregate function */
-};
-
-/*
-** An SQL parser context. A copy of this structure is passed through
-** the parser and down into all the parser action routine in order to
-** carry around information that is global to the entire parse.
-*/
-struct Parse {
- sqlite *db; /* The main database structure */
- int rc; /* Return code from execution */
- char *zErrMsg; /* An error message */
- Token sErrToken; /* The token at which the error occurred */
- Token sFirstToken; /* The first token parsed */
- Token sLastToken; /* The last token parsed */
- const char *zTail; /* All SQL text past the last semicolon parsed */
- Table *pNewTable; /* A table being constructed by CREATE TABLE */
- Vdbe *pVdbe; /* An engine for executing database bytecode */
- u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
- u8 explain; /* True if the EXPLAIN flag is found on the query */
- u8 nameClash; /* A permanent table name clashes with temp table name */
- u8 useAgg; /* If true, extract field values from the aggregator
- ** while generating expressions. Normally false */
- int nErr; /* Number of errors seen */
- int nTab; /* Number of previously allocated VDBE cursors */
- int nMem; /* Number of memory cells used so far */
- int nSet; /* Number of sets used so far */
- int nAgg; /* Number of aggregate expressions */
- int nVar; /* Number of '?' variables seen in the SQL so far */
- AggExpr *aAgg; /* An array of aggregate expressions */
- const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
- Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
- TriggerStack *trigStack; /* Trigger actions being coded */
-};
-
-/*
-** An instance of the following structure can be declared on a stack and used
-** to save the Parse.zAuthContext value so that it can be restored later.
-*/
-struct AuthContext {
- const char *zAuthContext; /* Put saved Parse.zAuthContext here */
- Parse *pParse; /* The Parse structure */
-};
-
-/*
-** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete
-*/
-#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
-#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
-#define OPFLAG_CSCHANGE 4 /* Set to update db->csChange */
-
-/*
- * Each trigger present in the database schema is stored as an instance of
- * struct Trigger.
- *
- * Pointers to instances of struct Trigger are stored in two ways.
- * 1. In the "trigHash" hash table (part of the sqlite* that represents the
- * database). This allows Trigger structures to be retrieved by name.
- * 2. All triggers associated with a single table form a linked list, using the
- * pNext member of struct Trigger. A pointer to the first element of the
- * linked list is stored as the "pTrigger" member of the associated
- * struct Table.
- *
- * The "step_list" member points to the first element of a linked list
- * containing the SQL statements specified as the trigger program.
- */
-struct Trigger {
- char *name; /* The name of the trigger */
- char *table; /* The table or view to which the trigger applies */
- u8 iDb; /* Database containing this trigger */
- u8 iTabDb; /* Database containing Trigger.table */
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
- u8 tr_tm; /* One of TK_BEFORE, TK_AFTER */
- Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */
- IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
- the <column-list> is stored here */
- int foreach; /* One of TK_ROW or TK_STATEMENT */
- Token nameToken; /* Token containing zName. Use during parsing only */
-
- TriggerStep *step_list; /* Link list of trigger program steps */
- Trigger *pNext; /* Next trigger associated with the table */
-};
-
-/*
- * An instance of struct TriggerStep is used to store a single SQL statement
- * that is a part of a trigger-program.
- *
- * Instances of struct TriggerStep are stored in a singly linked list (linked
- * using the "pNext" member) referenced by the "step_list" member of the
- * associated struct Trigger instance. The first element of the linked list is
- * the first step of the trigger-program.
- *
- * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
- * "SELECT" statement. The meanings of the other members is determined by the
- * value of "op" as follows:
- *
- * (op == TK_INSERT)
- * orconf -> stores the ON CONFLICT algorithm
- * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
- * this stores a pointer to the SELECT statement. Otherwise NULL.
- * target -> A token holding the name of the table to insert into.
- * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
- * this stores values to be inserted. Otherwise NULL.
- * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
- * statement, then this stores the column-names to be
- * inserted into.
- *
- * (op == TK_DELETE)
- * target -> A token holding the name of the table to delete from.
- * pWhere -> The WHERE clause of the DELETE statement if one is specified.
- * Otherwise NULL.
- *
- * (op == TK_UPDATE)
- * target -> A token holding the name of the table to update rows of.
- * pWhere -> The WHERE clause of the UPDATE statement if one is specified.
- * Otherwise NULL.
- * pExprList -> A list of the columns to update and the expressions to update
- * them to. See sqliteUpdate() documentation of "pChanges"
- * argument.
- *
- */
-struct TriggerStep {
- int op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
- int orconf; /* OE_Rollback etc. */
- Trigger *pTrig; /* The trigger that this step is a part of */
-
- Select *pSelect; /* Valid for SELECT and sometimes
- INSERT steps (when pExprList == 0) */
- Token target; /* Valid for DELETE, UPDATE, INSERT steps */
- Expr *pWhere; /* Valid for DELETE, UPDATE steps */
- ExprList *pExprList; /* Valid for UPDATE statements and sometimes
- INSERT steps (when pSelect == 0) */
- IdList *pIdList; /* Valid for INSERT statements only */
-
- TriggerStep * pNext; /* Next in the link-list */
-};
-
-/*
- * An instance of struct TriggerStack stores information required during code
- * generation of a single trigger program. While the trigger program is being
- * coded, its associated TriggerStack instance is pointed to by the
- * "pTriggerStack" member of the Parse structure.
- *
- * The pTab member points to the table that triggers are being coded on. The
- * newIdx member contains the index of the vdbe cursor that points at the temp
- * table that stores the new.* references. If new.* references are not valid
- * for the trigger being coded (for example an ON DELETE trigger), then newIdx
- * is set to -1. The oldIdx member is analogous to newIdx, for old.* references.
- *
- * The ON CONFLICT policy to be used for the trigger program steps is stored
- * as the orconf member. If this is OE_Default, then the ON CONFLICT clause
- * specified for individual triggers steps is used.
- *
- * struct TriggerStack has a "pNext" member, to allow linked lists to be
- * constructed. When coding nested triggers (triggers fired by other triggers)
- * each nested trigger stores its parent trigger's TriggerStack as the "pNext"
- * pointer. Once the nested trigger has been coded, the pNext value is restored
- * to the pTriggerStack member of the Parse stucture and coding of the parent
- * trigger continues.
- *
- * Before a nested trigger is coded, the linked list pointed to by the
- * pTriggerStack is scanned to ensure that the trigger is not about to be coded
- * recursively. If this condition is detected, the nested trigger is not coded.
- */
-struct TriggerStack {
- Table *pTab; /* Table that triggers are currently being coded on */
- int newIdx; /* Index of vdbe cursor to "new" temp table */
- int oldIdx; /* Index of vdbe cursor to "old" temp table */
- int orconf; /* Current orconf policy */
- int ignoreJump; /* where to jump to for a RAISE(IGNORE) */
- Trigger *pTrigger; /* The trigger currently being coded */
- TriggerStack *pNext; /* Next trigger down on the trigger stack */
-};
-
-/*
-** The following structure contains information used by the sqliteFix...
-** routines as they walk the parse tree to make database references
-** explicit.
-*/
-typedef struct DbFixer DbFixer;
-struct DbFixer {
- Parse *pParse; /* The parsing context. Error messages written here */
- const char *zDb; /* Make sure all objects are contained in this database */
- const char *zType; /* Type of the container - used for error messages */
- const Token *pName; /* Name of the container - used for error messages */
-};
-
-/*
- * This global flag is set for performance testing of triggers. When it is set
- * SQLite will perform the overhead of building new and old trigger references
- * even when no triggers exist
- */
-extern int always_code_trigger_setup;
-
-/*
-** Internal function prototypes
-*/
-int sqliteStrICmp(const char *, const char *);
-int sqliteStrNICmp(const char *, const char *, int);
-int sqliteHashNoCase(const char *, int);
-int sqliteIsNumber(const char*);
-int sqliteCompare(const char *, const char *);
-int sqliteSortCompare(const char *, const char *);
-void sqliteRealToSortable(double r, char *);
-#ifdef MEMORY_DEBUG
- void *sqliteMalloc_(int,int,char*,int);
- void sqliteFree_(void*,char*,int);
- void *sqliteRealloc_(void*,int,char*,int);
- char *sqliteStrDup_(const char*,char*,int);
- char *sqliteStrNDup_(const char*, int,char*,int);
- void sqliteCheckMemory(void*,int);
-#else
- void *sqliteMalloc(int);
- void *sqliteMallocRaw(int);
- void sqliteFree(void*);
- void *sqliteRealloc(void*,int);
- char *sqliteStrDup(const char*);
- char *sqliteStrNDup(const char*, int);
-# define sqliteCheckMemory(a,b)
-#endif
-char *sqliteMPrintf(const char*, ...);
-char *sqliteVMPrintf(const char*, va_list);
-void sqliteSetString(char **, ...);
-void sqliteSetNString(char **, ...);
-void sqliteErrorMsg(Parse*, const char*, ...);
-void sqliteDequote(char*);
-int sqliteKeywordCode(const char*, int);
-int sqliteRunParser(Parse*, const char*, char **);
-void sqliteExec(Parse*);
-Expr *sqliteExpr(int, Expr*, Expr*, Token*);
-void sqliteExprSpan(Expr*,Token*,Token*);
-Expr *sqliteExprFunction(ExprList*, Token*);
-void sqliteExprDelete(Expr*);
-ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*);
-void sqliteExprListDelete(ExprList*);
-int sqliteInit(sqlite*, char**);
-void sqlitePragma(Parse*,Token*,Token*,int);
-void sqliteResetInternalSchema(sqlite*, int);
-void sqliteBeginParse(Parse*,int);
-void sqliteRollbackInternalChanges(sqlite*);
-void sqliteCommitInternalChanges(sqlite*);
-Table *sqliteResultSetOfSelect(Parse*,char*,Select*);
-void sqliteOpenMasterTable(Vdbe *v, int);
-void sqliteStartTable(Parse*,Token*,Token*,int,int);
-void sqliteAddColumn(Parse*,Token*);
-void sqliteAddNotNull(Parse*, int);
-void sqliteAddPrimaryKey(Parse*, IdList*, int);
-void sqliteAddColumnType(Parse*,Token*,Token*);
-void sqliteAddDefaultValue(Parse*,Token*,int);
-int sqliteCollateType(const char*, int);
-void sqliteAddCollateType(Parse*, int);
-void sqliteEndTable(Parse*,Token*,Select*);
-void sqliteCreateView(Parse*,Token*,Token*,Select*,int);
-int sqliteViewGetColumnNames(Parse*,Table*);
-void sqliteDropTable(Parse*, Token*, int);
-void sqliteDeleteTable(sqlite*, Table*);
-void sqliteInsert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
-IdList *sqliteIdListAppend(IdList*, Token*);
-int sqliteIdListIndex(IdList*,const char*);
-SrcList *sqliteSrcListAppend(SrcList*, Token*, Token*);
-void sqliteSrcListAddAlias(SrcList*, Token*);
-void sqliteSrcListAssignCursors(Parse*, SrcList*);
-void sqliteIdListDelete(IdList*);
-void sqliteSrcListDelete(SrcList*);
-void sqliteCreateIndex(Parse*,Token*,SrcList*,IdList*,int,Token*,Token*);
-void sqliteDropIndex(Parse*, SrcList*);
-void sqliteAddKeyType(Vdbe*, ExprList*);
-void sqliteAddIdxKeyType(Vdbe*, Index*);
-int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*);
-Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
- int,int,int);
-void sqliteSelectDelete(Select*);
-void sqliteSelectUnbind(Select*);
-Table *sqliteSrcListLookup(Parse*, SrcList*);
-int sqliteIsReadOnly(Parse*, Table*, int);
-void sqliteDeleteFrom(Parse*, SrcList*, Expr*);
-void sqliteUpdate(Parse*, SrcList*, ExprList*, Expr*, int);
-WhereInfo *sqliteWhereBegin(Parse*, SrcList*, Expr*, int, ExprList**);
-void sqliteWhereEnd(WhereInfo*);
-void sqliteExprCode(Parse*, Expr*);
-int sqliteExprCodeExprList(Parse*, ExprList*, int);
-void sqliteExprIfTrue(Parse*, Expr*, int, int);
-void sqliteExprIfFalse(Parse*, Expr*, int, int);
-Table *sqliteFindTable(sqlite*,const char*, const char*);
-Table *sqliteLocateTable(Parse*,const char*, const char*);
-Index *sqliteFindIndex(sqlite*,const char*, const char*);
-void sqliteUnlinkAndDeleteIndex(sqlite*,Index*);
-void sqliteCopy(Parse*, SrcList*, Token*, Token*, int);
-void sqliteVacuum(Parse*, Token*);
-int sqliteRunVacuum(char**, sqlite*);
-int sqliteGlobCompare(const unsigned char*,const unsigned char*);
-int sqliteLikeCompare(const unsigned char*,const unsigned char*);
-char *sqliteTableNameFromToken(Token*);
-int sqliteExprCheck(Parse*, Expr*, int, int*);
-int sqliteExprType(Expr*);
-int sqliteExprCompare(Expr*, Expr*);
-int sqliteFuncId(Token*);
-int sqliteExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
-int sqliteExprAnalyzeAggregates(Parse*, Expr*);
-Vdbe *sqliteGetVdbe(Parse*);
-void sqliteRandomness(int, void*);
-void sqliteRollbackAll(sqlite*);
-void sqliteCodeVerifySchema(Parse*, int);
-void sqliteBeginTransaction(Parse*, int);
-void sqliteCommitTransaction(Parse*);
-void sqliteRollbackTransaction(Parse*);
-int sqliteExprIsConstant(Expr*);
-int sqliteExprIsInteger(Expr*, int*);
-int sqliteIsRowid(const char*);
-void sqliteGenerateRowDelete(sqlite*, Vdbe*, Table*, int, int);
-void sqliteGenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*);
-void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
-void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int, int);
-int sqliteOpenTableAndIndices(Parse*, Table*, int);
-void sqliteBeginWriteOperation(Parse*, int, int);
-void sqliteEndWriteOperation(Parse*);
-Expr *sqliteExprDup(Expr*);
-void sqliteTokenCopy(Token*, Token*);
-ExprList *sqliteExprListDup(ExprList*);
-SrcList *sqliteSrcListDup(SrcList*);
-IdList *sqliteIdListDup(IdList*);
-Select *sqliteSelectDup(Select*);
-FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
-void sqliteRegisterBuiltinFunctions(sqlite*);
-void sqliteRegisterDateTimeFunctions(sqlite*);
-int sqliteSafetyOn(sqlite*);
-int sqliteSafetyOff(sqlite*);
-int sqliteSafetyCheck(sqlite*);
-void sqliteChangeCookie(sqlite*, Vdbe*);
-void sqliteBeginTrigger(Parse*, Token*,int,int,IdList*,SrcList*,int,Expr*,int);
-void sqliteFinishTrigger(Parse*, TriggerStep*, Token*);
-void sqliteDropTrigger(Parse*, SrcList*);
-void sqliteDropTriggerPtr(Parse*, Trigger*, int);
-int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
-int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
- int, int);
-void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
-void sqliteDeleteTriggerStep(TriggerStep*);
-TriggerStep *sqliteTriggerSelectStep(Select*);
-TriggerStep *sqliteTriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
-TriggerStep *sqliteTriggerUpdateStep(Token*, ExprList*, Expr*, int);
-TriggerStep *sqliteTriggerDeleteStep(Token*, Expr*);
-void sqliteDeleteTrigger(Trigger*);
-int sqliteJoinType(Parse*, Token*, Token*, Token*);
-void sqliteCreateForeignKey(Parse*, IdList*, Token*, IdList*, int);
-void sqliteDeferForeignKey(Parse*, int);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- void sqliteAuthRead(Parse*,Expr*,SrcList*);
- int sqliteAuthCheck(Parse*,int, const char*, const char*, const char*);
- void sqliteAuthContextPush(Parse*, AuthContext*, const char*);
- void sqliteAuthContextPop(AuthContext*);
-#else
-# define sqliteAuthRead(a,b,c)
-# define sqliteAuthCheck(a,b,c,d,e) SQLITE_OK
-# define sqliteAuthContextPush(a,b,c)
-# define sqliteAuthContextPop(a) ((void)(a))
-#endif
-void sqliteAttach(Parse*, Token*, Token*, Token*);
-void sqliteDetach(Parse*, Token*);
-int sqliteBtreeFactory(const sqlite *db, const char *zFilename,
- int mode, int nPg, Btree **ppBtree);
-int sqliteFixInit(DbFixer*, Parse*, int, const char*, const Token*);
-int sqliteFixSrcList(DbFixer*, SrcList*);
-int sqliteFixSelect(DbFixer*, Select*);
-int sqliteFixExpr(DbFixer*, Expr*);
-int sqliteFixExprList(DbFixer*, ExprList*);
-int sqliteFixTriggerStep(DbFixer*, TriggerStep*);
-double sqliteAtoF(const char *z, const char **);
-char *sqlite_snprintf(int,char*,const char*,...);
-int sqliteFitsIn32Bits(const char *);
diff --git a/ext/sqlite/libsqlite/src/sqlite_config.w32.h b/ext/sqlite/libsqlite/src/sqlite_config.w32.h
deleted file mode 100644
index 3903ffe95e..0000000000
--- a/ext/sqlite/libsqlite/src/sqlite_config.w32.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "config.w32.h"
-#if ZTS
-# define THREADSAFE 1
-#endif
-#if !ZEND_DEBUG && !defined(NDEBUG)
-# define NDEBUG
-#endif
-#define SQLITE_PTR_SZ 4 \ No newline at end of file
diff --git a/ext/sqlite/libsqlite/src/table.c b/ext/sqlite/libsqlite/src/table.c
deleted file mode 100644
index 48c852d487..0000000000
--- a/ext/sqlite/libsqlite/src/table.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains the sqlite_get_table() and sqlite_free_table()
-** interface routines. These are just wrappers around the main
-** interface routine of sqlite_exec().
-**
-** These routines are in a separate files so that they will not be linked
-** if they are not used.
-*/
-#include <stdlib.h>
-#include <string.h>
-#include "sqliteInt.h"
-
-/*
-** This structure is used to pass data from sqlite_get_table() through
-** to the callback function is uses to build the result.
-*/
-typedef struct TabResult {
- char **azResult;
- char *zErrMsg;
- int nResult;
- int nAlloc;
- int nRow;
- int nColumn;
- long nData;
- int rc;
-} TabResult;
-
-/*
-** This routine is called once for each row in the result table. Its job
-** is to fill in the TabResult structure appropriately, allocating new
-** memory as necessary.
-*/
-static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
- TabResult *p = (TabResult*)pArg;
- int need;
- int i;
- char *z;
-
- /* Make sure there is enough space in p->azResult to hold everything
- ** we need to remember from this invocation of the callback.
- */
- if( p->nRow==0 && argv!=0 ){
- need = nCol*2;
- }else{
- need = nCol;
- }
- if( p->nData + need >= p->nAlloc ){
- char **azNew;
- p->nAlloc = p->nAlloc*2 + need + 1;
- azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc );
- if( azNew==0 ){
- p->rc = SQLITE_NOMEM;
- return 1;
- }
- p->azResult = azNew;
- }
-
- /* If this is the first row, then generate an extra row containing
- ** the names of all columns.
- */
- if( p->nRow==0 ){
- p->nColumn = nCol;
- for(i=0; i<nCol; i++){
- if( colv[i]==0 ){
- z = 0;
- }else{
- z = malloc( strlen(colv[i])+1 );
- if( z==0 ){
- p->rc = SQLITE_NOMEM;
- return 1;
- }
- strcpy(z, colv[i]);
- }
- p->azResult[p->nData++] = z;
- }
- }else if( p->nColumn!=nCol ){
- sqliteSetString(&p->zErrMsg,
- "sqlite_get_table() called with two or more incompatible queries",
- (char*)0);
- p->rc = SQLITE_ERROR;
- return 1;
- }
-
- /* Copy over the row data
- */
- if( argv!=0 ){
- for(i=0; i<nCol; i++){
- if( argv[i]==0 ){
- z = 0;
- }else{
- z = malloc( strlen(argv[i])+1 );
- if( z==0 ){
- p->rc = SQLITE_NOMEM;
- return 1;
- }
- strcpy(z, argv[i]);
- }
- p->azResult[p->nData++] = z;
- }
- p->nRow++;
- }
- return 0;
-}
-
-/*
-** Query the database. But instead of invoking a callback for each row,
-** malloc() for space to hold the result and return the entire results
-** at the conclusion of the call.
-**
-** The result that is written to ***pazResult is held in memory obtained
-** from malloc(). But the caller cannot free this memory directly.
-** Instead, the entire table should be passed to sqlite_free_table() when
-** the calling procedure is finished using it.
-*/
-int sqlite_get_table(
- sqlite *db, /* The database on which the SQL executes */
- const char *zSql, /* The SQL to be executed */
- char ***pazResult, /* Write the result table here */
- int *pnRow, /* Write the number of rows in the result here */
- int *pnColumn, /* Write the number of columns of result here */
- char **pzErrMsg /* Write error messages here */
-){
- int rc;
- TabResult res;
- if( pazResult==0 ){ return SQLITE_ERROR; }
- *pazResult = 0;
- if( pnColumn ) *pnColumn = 0;
- if( pnRow ) *pnRow = 0;
- res.zErrMsg = 0;
- res.nResult = 0;
- res.nRow = 0;
- res.nColumn = 0;
- res.nData = 1;
- res.nAlloc = 20;
- res.rc = SQLITE_OK;
- res.azResult = malloc( sizeof(char*)*res.nAlloc );
- if( res.azResult==0 ){
- return SQLITE_NOMEM;
- }
- res.azResult[0] = 0;
- rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg);
- if( res.azResult ){
- res.azResult[0] = (char*)res.nData;
- }
- if( rc==SQLITE_ABORT ){
- sqlite_free_table(&res.azResult[1]);
- if( res.zErrMsg ){
- if( pzErrMsg ){
- free(*pzErrMsg);
- *pzErrMsg = res.zErrMsg;
- sqliteStrRealloc(pzErrMsg);
- }else{
- sqliteFree(res.zErrMsg);
- }
- }
- return res.rc;
- }
- sqliteFree(res.zErrMsg);
- if( rc!=SQLITE_OK ){
- sqlite_free_table(&res.azResult[1]);
- return rc;
- }
- if( res.nAlloc>res.nData ){
- char **azNew;
- azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) );
- if( azNew==0 ){
- sqlite_free_table(&res.azResult[1]);
- return SQLITE_NOMEM;
- }
- res.nAlloc = res.nData+1;
- res.azResult = azNew;
- }
- *pazResult = &res.azResult[1];
- if( pnColumn ) *pnColumn = res.nColumn;
- if( pnRow ) *pnRow = res.nRow;
- return rc;
-}
-
-/*
-** This routine frees the space the sqlite_get_table() malloced.
-*/
-void sqlite_free_table(
- char **azResult /* Result returned from from sqlite_get_table() */
-){
- if( azResult ){
- int i, n;
- azResult--;
- if( azResult==0 ) return;
- n = (int)(long)azResult[0];
- for(i=1; i<n; i++){ if( azResult[i] ) free(azResult[i]); }
- free(azResult);
- }
-}
diff --git a/ext/sqlite/libsqlite/src/tokenize.c b/ext/sqlite/libsqlite/src/tokenize.c
deleted file mode 100644
index 978c53418d..0000000000
--- a/ext/sqlite/libsqlite/src/tokenize.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** An tokenizer for SQL
-**
-** This file contains C code that splits an SQL input string up into
-** individual tokens and sends those tokens one-by-one over to the
-** parser for analysis.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include "os.h"
-#include <ctype.h>
-#include <stdlib.h>
-
-/*
-** All the keywords of the SQL language are stored as in a hash
-** table composed of instances of the following structure.
-*/
-typedef struct Keyword Keyword;
-struct Keyword {
- char *zName; /* The keyword name */
- u8 tokenType; /* Token value for this keyword */
- u8 len; /* Length of this keyword */
- u8 iNext; /* Index in aKeywordTable[] of next with same hash */
-};
-
-/*
-** These are the keywords
-*/
-static Keyword aKeywordTable[] = {
- { "ABORT", TK_ABORT, },
- { "AFTER", TK_AFTER, },
- { "ALL", TK_ALL, },
- { "AND", TK_AND, },
- { "AS", TK_AS, },
- { "ASC", TK_ASC, },
- { "ATTACH", TK_ATTACH, },
- { "BEFORE", TK_BEFORE, },
- { "BEGIN", TK_BEGIN, },
- { "BETWEEN", TK_BETWEEN, },
- { "BY", TK_BY, },
- { "CASCADE", TK_CASCADE, },
- { "CASE", TK_CASE, },
- { "CHECK", TK_CHECK, },
- { "CLUSTER", TK_CLUSTER, },
- { "COLLATE", TK_COLLATE, },
- { "COMMIT", TK_COMMIT, },
- { "CONFLICT", TK_CONFLICT, },
- { "CONSTRAINT", TK_CONSTRAINT, },
- { "COPY", TK_COPY, },
- { "CREATE", TK_CREATE, },
- { "CROSS", TK_JOIN_KW, },
- { "DATABASE", TK_DATABASE, },
- { "DEFAULT", TK_DEFAULT, },
- { "DEFERRED", TK_DEFERRED, },
- { "DEFERRABLE", TK_DEFERRABLE, },
- { "DELETE", TK_DELETE, },
- { "DELIMITERS", TK_DELIMITERS, },
- { "DESC", TK_DESC, },
- { "DETACH", TK_DETACH, },
- { "DISTINCT", TK_DISTINCT, },
- { "DROP", TK_DROP, },
- { "END", TK_END, },
- { "EACH", TK_EACH, },
- { "ELSE", TK_ELSE, },
- { "EXCEPT", TK_EXCEPT, },
- { "EXPLAIN", TK_EXPLAIN, },
- { "FAIL", TK_FAIL, },
- { "FOR", TK_FOR, },
- { "FOREIGN", TK_FOREIGN, },
- { "FROM", TK_FROM, },
- { "FULL", TK_JOIN_KW, },
- { "GLOB", TK_GLOB, },
- { "GROUP", TK_GROUP, },
- { "HAVING", TK_HAVING, },
- { "IGNORE", TK_IGNORE, },
- { "IMMEDIATE", TK_IMMEDIATE, },
- { "IN", TK_IN, },
- { "INDEX", TK_INDEX, },
- { "INITIALLY", TK_INITIALLY, },
- { "INNER", TK_JOIN_KW, },
- { "INSERT", TK_INSERT, },
- { "INSTEAD", TK_INSTEAD, },
- { "INTERSECT", TK_INTERSECT, },
- { "INTO", TK_INTO, },
- { "IS", TK_IS, },
- { "ISNULL", TK_ISNULL, },
- { "JOIN", TK_JOIN, },
- { "KEY", TK_KEY, },
- { "LEFT", TK_JOIN_KW, },
- { "LIKE", TK_LIKE, },
- { "LIMIT", TK_LIMIT, },
- { "MATCH", TK_MATCH, },
- { "NATURAL", TK_JOIN_KW, },
- { "NOT", TK_NOT, },
- { "NOTNULL", TK_NOTNULL, },
- { "NULL", TK_NULL, },
- { "OF", TK_OF, },
- { "OFFSET", TK_OFFSET, },
- { "ON", TK_ON, },
- { "OR", TK_OR, },
- { "ORDER", TK_ORDER, },
- { "OUTER", TK_JOIN_KW, },
- { "PRAGMA", TK_PRAGMA, },
- { "PRIMARY", TK_PRIMARY, },
- { "RAISE", TK_RAISE, },
- { "REFERENCES", TK_REFERENCES, },
- { "REPLACE", TK_REPLACE, },
- { "RESTRICT", TK_RESTRICT, },
- { "RIGHT", TK_JOIN_KW, },
- { "ROLLBACK", TK_ROLLBACK, },
- { "ROW", TK_ROW, },
- { "SELECT", TK_SELECT, },
- { "SET", TK_SET, },
- { "STATEMENT", TK_STATEMENT, },
- { "TABLE", TK_TABLE, },
- { "TEMP", TK_TEMP, },
- { "TEMPORARY", TK_TEMP, },
- { "THEN", TK_THEN, },
- { "TRANSACTION", TK_TRANSACTION, },
- { "TRIGGER", TK_TRIGGER, },
- { "UNION", TK_UNION, },
- { "UNIQUE", TK_UNIQUE, },
- { "UPDATE", TK_UPDATE, },
- { "USING", TK_USING, },
- { "VACUUM", TK_VACUUM, },
- { "VALUES", TK_VALUES, },
- { "VIEW", TK_VIEW, },
- { "WHEN", TK_WHEN, },
- { "WHERE", TK_WHERE, },
-};
-
-/*
-** This is the hash table
-*/
-#define KEY_HASH_SIZE 101
-static u8 aiHashTable[KEY_HASH_SIZE];
-
-
-/*
-** This function looks up an identifier to determine if it is a
-** keyword. If it is a keyword, the token code of that keyword is
-** returned. If the input is not a keyword, TK_ID is returned.
-*/
-int sqliteKeywordCode(const char *z, int n){
- int h, i;
- Keyword *p;
- static char needInit = 1;
- if( needInit ){
- /* Initialize the keyword hash table */
- sqliteOsEnterMutex();
- if( needInit ){
- int nk;
- nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
- for(i=0; i<nk; i++){
- aKeywordTable[i].len = strlen(aKeywordTable[i].zName);
- h = sqliteHashNoCase(aKeywordTable[i].zName, aKeywordTable[i].len);
- h %= KEY_HASH_SIZE;
- aKeywordTable[i].iNext = aiHashTable[h];
- aiHashTable[h] = i+1;
- }
- needInit = 0;
- }
- sqliteOsLeaveMutex();
- }
- h = sqliteHashNoCase(z, n) % KEY_HASH_SIZE;
- for(i=aiHashTable[h]; i; i=p->iNext){
- p = &aKeywordTable[i-1];
- if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){
- return p->tokenType;
- }
- }
- return TK_ID;
-}
-
-
-/*
-** If X is a character that can be used in an identifier and
-** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then
-** X is always an identifier character. (Hence all UTF-8
-** characters can be part of an identifier). isIdChar[X] will
-** be 0 for every character in the lower 128 ASCII characters
-** that cannot be used as part of an identifier.
-**
-** In this implementation, an identifier can be a string of
-** alphabetic characters, digits, and "_" plus any character
-** with the high-order bit set. The latter rule means that
-** any sequence of UTF-8 characters or characters taken from
-** an extended ISO8859 character set can form an identifier.
-*/
-static const char isIdChar[] = {
-/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
-};
-
-
-/*
-** Return the length of the token that begins at z[0].
-** Store the token type in *tokenType before returning.
-*/
-static int sqliteGetToken(const unsigned char *z, int *tokenType){
- int i;
- switch( *z ){
- case ' ': case '\t': case '\n': case '\f': case '\r': {
- for(i=1; isspace(z[i]); i++){}
- *tokenType = TK_SPACE;
- return i;
- }
- case '-': {
- if( z[1]=='-' ){
- for(i=2; z[i] && z[i]!='\n'; i++){}
- *tokenType = TK_COMMENT;
- return i;
- }
- *tokenType = TK_MINUS;
- return 1;
- }
- case '(': {
- *tokenType = TK_LP;
- return 1;
- }
- case ')': {
- *tokenType = TK_RP;
- return 1;
- }
- case ';': {
- *tokenType = TK_SEMI;
- return 1;
- }
- case '+': {
- *tokenType = TK_PLUS;
- return 1;
- }
- case '*': {
- *tokenType = TK_STAR;
- return 1;
- }
- case '/': {
- if( z[1]!='*' || z[2]==0 ){
- *tokenType = TK_SLASH;
- return 1;
- }
- for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){}
- if( z[i] ) i++;
- *tokenType = TK_COMMENT;
- return i;
- }
- case '%': {
- *tokenType = TK_REM;
- return 1;
- }
- case '=': {
- *tokenType = TK_EQ;
- return 1 + (z[1]=='=');
- }
- case '<': {
- if( z[1]=='=' ){
- *tokenType = TK_LE;
- return 2;
- }else if( z[1]=='>' ){
- *tokenType = TK_NE;
- return 2;
- }else if( z[1]=='<' ){
- *tokenType = TK_LSHIFT;
- return 2;
- }else{
- *tokenType = TK_LT;
- return 1;
- }
- }
- case '>': {
- if( z[1]=='=' ){
- *tokenType = TK_GE;
- return 2;
- }else if( z[1]=='>' ){
- *tokenType = TK_RSHIFT;
- return 2;
- }else{
- *tokenType = TK_GT;
- return 1;
- }
- }
- case '!': {
- if( z[1]!='=' ){
- *tokenType = TK_ILLEGAL;
- return 2;
- }else{
- *tokenType = TK_NE;
- return 2;
- }
- }
- case '|': {
- if( z[1]!='|' ){
- *tokenType = TK_BITOR;
- return 1;
- }else{
- *tokenType = TK_CONCAT;
- return 2;
- }
- }
- case ',': {
- *tokenType = TK_COMMA;
- return 1;
- }
- case '&': {
- *tokenType = TK_BITAND;
- return 1;
- }
- case '~': {
- *tokenType = TK_BITNOT;
- return 1;
- }
- case '\'': case '"': {
- int delim = z[0];
- for(i=1; z[i]; i++){
- if( z[i]==delim ){
- if( z[i+1]==delim ){
- i++;
- }else{
- break;
- }
- }
- }
- if( z[i] ) i++;
- *tokenType = TK_STRING;
- return i;
- }
- case '.': {
- *tokenType = TK_DOT;
- return 1;
- }
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- *tokenType = TK_INTEGER;
- for(i=1; isdigit(z[i]); i++){}
- if( z[i]=='.' && isdigit(z[i+1]) ){
- i += 2;
- while( isdigit(z[i]) ){ i++; }
- *tokenType = TK_FLOAT;
- }
- if( (z[i]=='e' || z[i]=='E') &&
- ( isdigit(z[i+1])
- || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
- )
- ){
- i += 2;
- while( isdigit(z[i]) ){ i++; }
- *tokenType = TK_FLOAT;
- }
- return i;
- }
- case '[': {
- for(i=1; z[i] && z[i-1]!=']'; i++){}
- *tokenType = TK_ID;
- return i;
- }
- case '?': {
- *tokenType = TK_VARIABLE;
- return 1;
- }
- default: {
- if( (*z&0x80)==0 && !isIdChar[*z] ){
- break;
- }
- for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){}
- *tokenType = sqliteKeywordCode((char*)z, i);
- return i;
- }
- }
- *tokenType = TK_ILLEGAL;
- return 1;
-}
-
-/*
-** Run the parser on the given SQL string. The parser structure is
-** passed in. An SQLITE_ status code is returned. If an error occurs
-** and pzErrMsg!=NULL then an error message might be written into
-** memory obtained from malloc() and *pzErrMsg made to point to that
-** error message. Or maybe not.
-*/
-int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
- int nErr = 0;
- int i;
- void *pEngine;
- int tokenType;
- int lastTokenParsed = -1;
- sqlite *db = pParse->db;
- extern void *sqliteParserAlloc(void*(*)(int));
- extern void sqliteParserFree(void*, void(*)(void*));
- extern int sqliteParser(void*, int, Token, Parse*);
-
- db->flags &= ~SQLITE_Interrupt;
- pParse->rc = SQLITE_OK;
- i = 0;
- pEngine = sqliteParserAlloc((void*(*)(int))malloc);
- if( pEngine==0 ){
- sqliteSetString(pzErrMsg, "out of memory", (char*)0);
- return 1;
- }
- pParse->sLastToken.dyn = 0;
- pParse->zTail = zSql;
- while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
- assert( i>=0 );
- pParse->sLastToken.z = &zSql[i];
- assert( pParse->sLastToken.dyn==0 );
- pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
- i += pParse->sLastToken.n;
- switch( tokenType ){
- case TK_SPACE:
- case TK_COMMENT: {
- if( (db->flags & SQLITE_Interrupt)!=0 ){
- pParse->rc = SQLITE_INTERRUPT;
- sqliteSetString(pzErrMsg, "interrupt", (char*)0);
- goto abort_parse;
- }
- break;
- }
- case TK_ILLEGAL: {
- sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1,
- pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
- nErr++;
- goto abort_parse;
- }
- case TK_SEMI: {
- pParse->zTail = &zSql[i];
- /* Fall thru into the default case */
- }
- default: {
- sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
- lastTokenParsed = tokenType;
- if( pParse->rc!=SQLITE_OK ){
- goto abort_parse;
- }
- break;
- }
- }
- }
-abort_parse:
- if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
- if( lastTokenParsed!=TK_SEMI ){
- sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
- pParse->zTail = &zSql[i];
- }
- sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
- }
- sqliteParserFree(pEngine, free);
- if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
- sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc),
- (char*)0);
- }
- if( pParse->zErrMsg ){
- if( pzErrMsg && *pzErrMsg==0 ){
- *pzErrMsg = pParse->zErrMsg;
- }else{
- sqliteFree(pParse->zErrMsg);
- }
- pParse->zErrMsg = 0;
- if( !nErr ) nErr++;
- }
- if( pParse->pVdbe && pParse->nErr>0 ){
- sqliteVdbeDelete(pParse->pVdbe);
- pParse->pVdbe = 0;
- }
- if( pParse->pNewTable ){
- sqliteDeleteTable(pParse->db, pParse->pNewTable);
- pParse->pNewTable = 0;
- }
- if( pParse->pNewTrigger ){
- sqliteDeleteTrigger(pParse->pNewTrigger);
- pParse->pNewTrigger = 0;
- }
- if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
- pParse->rc = SQLITE_ERROR;
- }
- return nErr;
-}
-
-/*
-** Token types used by the sqlite_complete() routine. See the header
-** comments on that procedure for additional information.
-*/
-#define tkEXPLAIN 0
-#define tkCREATE 1
-#define tkTEMP 2
-#define tkTRIGGER 3
-#define tkEND 4
-#define tkSEMI 5
-#define tkWS 6
-#define tkOTHER 7
-
-/*
-** Return TRUE if the given SQL string ends in a semicolon.
-**
-** Special handling is require for CREATE TRIGGER statements.
-** Whenever the CREATE TRIGGER keywords are seen, the statement
-** must end with ";END;".
-**
-** This implementation uses a state machine with 7 states:
-**
-** (0) START At the beginning or end of an SQL statement. This routine
-** returns 1 if it ends in the START state and 0 if it ends
-** in any other state.
-**
-** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
-** a statement.
-**
-** (2) CREATE The keyword CREATE has been seen at the beginning of a
-** statement, possibly preceeded by EXPLAIN and/or followed by
-** TEMP or TEMPORARY
-**
-** (3) NORMAL We are in the middle of statement which ends with a single
-** semicolon.
-**
-** (4) TRIGGER We are in the middle of a trigger definition that must be
-** ended by a semicolon, the keyword END, and another semicolon.
-**
-** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
-** the end of a trigger definition.
-**
-** (6) END We've seen the ";END" of the ";END;" that occurs at the end
-** of a trigger difinition.
-**
-** Transitions between states above are determined by tokens extracted
-** from the input. The following tokens are significant:
-**
-** (0) tkEXPLAIN The "explain" keyword.
-** (1) tkCREATE The "create" keyword.
-** (2) tkTEMP The "temp" or "temporary" keyword.
-** (3) tkTRIGGER The "trigger" keyword.
-** (4) tkEND The "end" keyword.
-** (5) tkSEMI A semicolon.
-** (6) tkWS Whitespace
-** (7) tkOTHER Any other SQL token.
-**
-** Whitespace never causes a state transition and is always ignored.
-*/
-int sqlite_complete(const char *zSql){
- u8 state = 0; /* Current state, using numbers defined in header comment */
- u8 token; /* Value of the next token */
-
- /* The following matrix defines the transition from one state to another
- ** according to what token is seen. trans[state][token] returns the
- ** next state.
- */
- static const u8 trans[7][8] = {
- /* Token: */
- /* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
- /* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
- /* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },
- /* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, },
- /* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, },
- /* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, },
- /* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, },
- /* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, },
- };
-
- while( *zSql ){
- switch( *zSql ){
- case ';': { /* A semicolon */
- token = tkSEMI;
- break;
- }
- case ' ':
- case '\r':
- case '\t':
- case '\n':
- case '\f': { /* White space is ignored */
- token = tkWS;
- break;
- }
- case '/': { /* C-style comments */
- if( zSql[1]!='*' ){
- token = tkOTHER;
- break;
- }
- zSql += 2;
- while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
- if( zSql[0]==0 ) return 0;
- zSql++;
- token = tkWS;
- break;
- }
- case '-': { /* SQL-style comments from "--" to end of line */
- if( zSql[1]!='-' ){
- token = tkOTHER;
- break;
- }
- while( *zSql && *zSql!='\n' ){ zSql++; }
- if( *zSql==0 ) return state==0;
- token = tkWS;
- break;
- }
- case '[': { /* Microsoft-style identifiers in [...] */
- zSql++;
- while( *zSql && *zSql!=']' ){ zSql++; }
- if( *zSql==0 ) return 0;
- token = tkOTHER;
- break;
- }
- case '"': /* single- and double-quoted strings */
- case '\'': {
- int c = *zSql;
- zSql++;
- while( *zSql && *zSql!=c ){ zSql++; }
- if( *zSql==0 ) return 0;
- token = tkOTHER;
- break;
- }
- default: {
- if( isIdChar[(u8)*zSql] ){
- /* Keywords and unquoted identifiers */
- int nId;
- for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){}
- switch( *zSql ){
- case 'c': case 'C': {
- if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){
- token = tkCREATE;
- }else{
- token = tkOTHER;
- }
- break;
- }
- case 't': case 'T': {
- if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){
- token = tkTRIGGER;
- }else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){
- token = tkTEMP;
- }else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){
- token = tkTEMP;
- }else{
- token = tkOTHER;
- }
- break;
- }
- case 'e': case 'E': {
- if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){
- token = tkEND;
- }else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){
- token = tkEXPLAIN;
- }else{
- token = tkOTHER;
- }
- break;
- }
- default: {
- token = tkOTHER;
- break;
- }
- }
- zSql += nId-1;
- }else{
- /* Operators and special symbols */
- token = tkOTHER;
- }
- break;
- }
- }
- state = trans[state][token];
- zSql++;
- }
- return state==0;
-}
diff --git a/ext/sqlite/libsqlite/src/trigger.c b/ext/sqlite/libsqlite/src/trigger.c
deleted file mode 100644
index 8442bb5dd8..0000000000
--- a/ext/sqlite/libsqlite/src/trigger.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-*
-*/
-#include "sqliteInt.h"
-
-/*
-** Delete a linked list of TriggerStep structures.
-*/
-void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
- while( pTriggerStep ){
- TriggerStep * pTmp = pTriggerStep;
- pTriggerStep = pTriggerStep->pNext;
-
- if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
- sqliteExprDelete(pTmp->pWhere);
- sqliteExprListDelete(pTmp->pExprList);
- sqliteSelectDelete(pTmp->pSelect);
- sqliteIdListDelete(pTmp->pIdList);
-
- sqliteFree(pTmp);
- }
-}
-
-/*
-** This is called by the parser when it sees a CREATE TRIGGER statement
-** up to the point of the BEGIN before the trigger actions. A Trigger
-** structure is generated based on the information available and stored
-** in pParse->pNewTrigger. After the trigger actions have been parsed, the
-** sqliteFinishTrigger() function is called to complete the trigger
-** construction process.
-*/
-void sqliteBeginTrigger(
- Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
- Token *pName, /* The name of the trigger */
- int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
- int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
- IdList *pColumns, /* column list if this is an UPDATE OF trigger */
- SrcList *pTableName,/* The name of the table/view the trigger applies to */
- int foreach, /* One of TK_ROW or TK_STATEMENT */
- Expr *pWhen, /* WHEN clause */
- int isTemp /* True if the TEMPORARY keyword is present */
-){
- Trigger *nt;
- Table *tab;
- char *zName = 0; /* Name of the trigger */
- sqlite *db = pParse->db;
- int iDb; /* When database to store the trigger in */
- DbFixer sFix;
-
- /* Check that:
- ** 1. the trigger name does not already exist.
- ** 2. the table (or view) does exist in the same database as the trigger.
- ** 3. that we are not trying to create a trigger on the sqlite_master table
- ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
- ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
- */
- if( sqlite_malloc_failed ) goto trigger_cleanup;
- assert( pTableName->nSrc==1 );
- if( db->init.busy
- && sqliteFixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
- && sqliteFixSrcList(&sFix, pTableName)
- ){
- goto trigger_cleanup;
- }
- tab = sqliteSrcListLookup(pParse, pTableName);
- if( !tab ){
- goto trigger_cleanup;
- }
- iDb = isTemp ? 1 : tab->iDb;
- if( iDb>=2 && !db->init.busy ){
- sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
- "database %s", db->aDb[tab->iDb].zName);
- goto trigger_cleanup;
- }
-
- zName = sqliteStrNDup(pName->z, pName->n);
- sqliteDequote(zName);
- if( sqliteHashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){
- sqliteErrorMsg(pParse, "trigger %T already exists", pName);
- goto trigger_cleanup;
- }
- if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
- sqliteErrorMsg(pParse, "cannot create trigger on system table");
- pParse->nErr++;
- goto trigger_cleanup;
- }
- if( tab->pSelect && tr_tm != TK_INSTEAD ){
- sqliteErrorMsg(pParse, "cannot create %s trigger on view: %S",
- (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
- goto trigger_cleanup;
- }
- if( !tab->pSelect && tr_tm == TK_INSTEAD ){
- sqliteErrorMsg(pParse, "cannot create INSTEAD OF"
- " trigger on table: %S", pTableName, 0);
- goto trigger_cleanup;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code = SQLITE_CREATE_TRIGGER;
- const char *zDb = db->aDb[tab->iDb].zName;
- const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
- if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
- if( sqliteAuthCheck(pParse, code, zName, tab->zName, zDbTrig) ){
- goto trigger_cleanup;
- }
- if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0, zDb)){
- goto trigger_cleanup;
- }
- }
-#endif
-
- /* INSTEAD OF triggers can only appear on views and BEGIN triggers
- ** cannot appear on views. So we might as well translate every
- ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code
- ** elsewhere.
- */
- if (tr_tm == TK_INSTEAD){
- tr_tm = TK_BEFORE;
- }
-
- /* Build the Trigger object */
- nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
- if( nt==0 ) goto trigger_cleanup;
- nt->name = zName;
- zName = 0;
- nt->table = sqliteStrDup(pTableName->a[0].zName);
- if( sqlite_malloc_failed ) goto trigger_cleanup;
- nt->iDb = iDb;
- nt->iTabDb = tab->iDb;
- nt->op = op;
- nt->tr_tm = tr_tm;
- nt->pWhen = sqliteExprDup(pWhen);
- nt->pColumns = sqliteIdListDup(pColumns);
- nt->foreach = foreach;
- sqliteTokenCopy(&nt->nameToken,pName);
- assert( pParse->pNewTrigger==0 );
- pParse->pNewTrigger = nt;
-
-trigger_cleanup:
- sqliteFree(zName);
- sqliteSrcListDelete(pTableName);
- sqliteIdListDelete(pColumns);
- sqliteExprDelete(pWhen);
-}
-
-/*
-** This routine is called after all of the trigger actions have been parsed
-** in order to complete the process of building the trigger.
-*/
-void sqliteFinishTrigger(
- Parse *pParse, /* Parser context */
- TriggerStep *pStepList, /* The triggered program */
- Token *pAll /* Token that describes the complete CREATE TRIGGER */
-){
- Trigger *nt = 0; /* The trigger whose construction is finishing up */
- sqlite *db = pParse->db; /* The database */
- DbFixer sFix;
-
- if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
- nt = pParse->pNewTrigger;
- pParse->pNewTrigger = 0;
- nt->step_list = pStepList;
- while( pStepList ){
- pStepList->pTrig = nt;
- pStepList = pStepList->pNext;
- }
- if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken)
- && sqliteFixTriggerStep(&sFix, nt->step_list) ){
- goto triggerfinish_cleanup;
- }
-
- /* if we are not initializing, and this trigger is not on a TEMP table,
- ** build the sqlite_master entry
- */
- if( !db->init.busy ){
- static VdbeOpList insertTrig[] = {
- { OP_NewRecno, 0, 0, 0 },
- { OP_String, 0, 0, "trigger" },
- { OP_String, 0, 0, 0 }, /* 2: trigger name */
- { OP_String, 0, 0, 0 }, /* 3: table name */
- { OP_Integer, 0, 0, 0 },
- { OP_String, 0, 0, 0 }, /* 5: SQL */
- { OP_MakeRecord, 5, 0, 0 },
- { OP_PutIntKey, 0, 0, 0 },
- };
- int addr;
- Vdbe *v;
-
- /* Make an entry in the sqlite_master table */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) goto triggerfinish_cleanup;
- sqliteBeginWriteOperation(pParse, 0, 0);
- sqliteOpenMasterTable(v, nt->iDb);
- addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
- sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
- sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
- sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
- if( nt->iDb==0 ){
- sqliteChangeCookie(db, v);
- }
- sqliteVdbeAddOp(v, OP_Close, 0, 0);
- sqliteEndWriteOperation(pParse);
- }
-
- if( !pParse->explain ){
- Table *pTab;
- sqliteHashInsert(&db->aDb[nt->iDb].trigHash,
- nt->name, strlen(nt->name)+1, nt);
- pTab = sqliteLocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
- assert( pTab!=0 );
- nt->pNext = pTab->pTrigger;
- pTab->pTrigger = nt;
- nt = 0;
- }
-
-triggerfinish_cleanup:
- sqliteDeleteTrigger(nt);
- sqliteDeleteTrigger(pParse->pNewTrigger);
- pParse->pNewTrigger = 0;
- sqliteDeleteTriggerStep(pStepList);
-}
-
-/*
-** Make a copy of all components of the given trigger step. This has
-** the effect of copying all Expr.token.z values into memory obtained
-** from sqliteMalloc(). As initially created, the Expr.token.z values
-** all point to the input string that was fed to the parser. But that
-** string is ephemeral - it will go away as soon as the sqlite_exec()
-** call that started the parser exits. This routine makes a persistent
-** copy of all the Expr.token.z strings so that the TriggerStep structure
-** will be valid even after the sqlite_exec() call returns.
-*/
-static void sqlitePersistTriggerStep(TriggerStep *p){
- if( p->target.z ){
- p->target.z = sqliteStrNDup(p->target.z, p->target.n);
- p->target.dyn = 1;
- }
- if( p->pSelect ){
- Select *pNew = sqliteSelectDup(p->pSelect);
- sqliteSelectDelete(p->pSelect);
- p->pSelect = pNew;
- }
- if( p->pWhere ){
- Expr *pNew = sqliteExprDup(p->pWhere);
- sqliteExprDelete(p->pWhere);
- p->pWhere = pNew;
- }
- if( p->pExprList ){
- ExprList *pNew = sqliteExprListDup(p->pExprList);
- sqliteExprListDelete(p->pExprList);
- p->pExprList = pNew;
- }
- if( p->pIdList ){
- IdList *pNew = sqliteIdListDup(p->pIdList);
- sqliteIdListDelete(p->pIdList);
- p->pIdList = pNew;
- }
-}
-
-/*
-** Turn a SELECT statement (that the pSelect parameter points to) into
-** a trigger step. Return a pointer to a TriggerStep structure.
-**
-** The parser calls this routine when it finds a SELECT statement in
-** body of a TRIGGER.
-*/
-TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
- TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
- if( pTriggerStep==0 ) return 0;
-
- pTriggerStep->op = TK_SELECT;
- pTriggerStep->pSelect = pSelect;
- pTriggerStep->orconf = OE_Default;
- sqlitePersistTriggerStep(pTriggerStep);
-
- return pTriggerStep;
-}
-
-/*
-** Build a trigger step out of an INSERT statement. Return a pointer
-** to the new trigger step.
-**
-** The parser calls this routine when it sees an INSERT inside the
-** body of a trigger.
-*/
-TriggerStep *sqliteTriggerInsertStep(
- Token *pTableName, /* Name of the table into which we insert */
- IdList *pColumn, /* List of columns in pTableName to insert into */
- ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
- Select *pSelect, /* A SELECT statement that supplies values */
- int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
-){
- TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
- if( pTriggerStep==0 ) return 0;
-
- assert(pEList == 0 || pSelect == 0);
- assert(pEList != 0 || pSelect != 0);
-
- pTriggerStep->op = TK_INSERT;
- pTriggerStep->pSelect = pSelect;
- pTriggerStep->target = *pTableName;
- pTriggerStep->pIdList = pColumn;
- pTriggerStep->pExprList = pEList;
- pTriggerStep->orconf = orconf;
- sqlitePersistTriggerStep(pTriggerStep);
-
- return pTriggerStep;
-}
-
-/*
-** Construct a trigger step that implements an UPDATE statement and return
-** a pointer to that trigger step. The parser calls this routine when it
-** sees an UPDATE statement inside the body of a CREATE TRIGGER.
-*/
-TriggerStep *sqliteTriggerUpdateStep(
- Token *pTableName, /* Name of the table to be updated */
- ExprList *pEList, /* The SET clause: list of column and new values */
- Expr *pWhere, /* The WHERE clause */
- int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
-){
- TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
- if( pTriggerStep==0 ) return 0;
-
- pTriggerStep->op = TK_UPDATE;
- pTriggerStep->target = *pTableName;
- pTriggerStep->pExprList = pEList;
- pTriggerStep->pWhere = pWhere;
- pTriggerStep->orconf = orconf;
- sqlitePersistTriggerStep(pTriggerStep);
-
- return pTriggerStep;
-}
-
-/*
-** Construct a trigger step that implements a DELETE statement and return
-** a pointer to that trigger step. The parser calls this routine when it
-** sees a DELETE statement inside the body of a CREATE TRIGGER.
-*/
-TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
- TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
- if( pTriggerStep==0 ) return 0;
-
- pTriggerStep->op = TK_DELETE;
- pTriggerStep->target = *pTableName;
- pTriggerStep->pWhere = pWhere;
- pTriggerStep->orconf = OE_Default;
- sqlitePersistTriggerStep(pTriggerStep);
-
- return pTriggerStep;
-}
-
-/*
-** Recursively delete a Trigger structure
-*/
-void sqliteDeleteTrigger(Trigger *pTrigger){
- if( pTrigger==0 ) return;
- sqliteDeleteTriggerStep(pTrigger->step_list);
- sqliteFree(pTrigger->name);
- sqliteFree(pTrigger->table);
- sqliteExprDelete(pTrigger->pWhen);
- sqliteIdListDelete(pTrigger->pColumns);
- if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
- sqliteFree(pTrigger);
-}
-
-/*
- * This function is called to drop a trigger from the database schema.
- *
- * This may be called directly from the parser and therefore identifies
- * the trigger by name. The sqliteDropTriggerPtr() routine does the
- * same job as this routine except it take a spointer to the trigger
- * instead of the trigger name.
- *
- * Note that this function does not delete the trigger entirely. Instead it
- * removes it from the internal schema and places it in the trigDrop hash
- * table. This is so that the trigger can be restored into the database schema
- * if the transaction is rolled back.
- */
-void sqliteDropTrigger(Parse *pParse, SrcList *pName){
- Trigger *pTrigger;
- int i;
- const char *zDb;
- const char *zName;
- int nName;
- sqlite *db = pParse->db;
-
- if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
- assert( pName->nSrc==1 );
- zDb = pName->a[0].zDatabase;
- zName = pName->a[0].zName;
- nName = strlen(zName);
- for(i=0; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
- pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
- if( pTrigger ) break;
- }
- if( !pTrigger ){
- sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
- goto drop_trigger_cleanup;
- }
- sqliteDropTriggerPtr(pParse, pTrigger, 0);
-
-drop_trigger_cleanup:
- sqliteSrcListDelete(pName);
-}
-
-/*
-** Drop a trigger given a pointer to that trigger. If nested is false,
-** then also generate code to remove the trigger from the SQLITE_MASTER
-** table.
-*/
-void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
- Table *pTable;
- Vdbe *v;
- sqlite *db = pParse->db;
-
- assert( pTrigger->iDb<db->nDb );
- if( pTrigger->iDb>=2 ){
- sqliteErrorMsg(pParse, "triggers may not be removed from "
- "auxiliary database %s", db->aDb[pTrigger->iDb].zName);
- return;
- }
- pTable = sqliteFindTable(db, pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
- assert(pTable);
- assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int code = SQLITE_DROP_TRIGGER;
- const char *zDb = db->aDb[pTrigger->iDb].zName;
- const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
- if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
- if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
- sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
- return;
- }
- }
-#endif
-
- /* Generate code to destroy the database record of the trigger.
- */
- if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
- int base;
- static VdbeOpList dropTrigger[] = {
- { OP_Rewind, 0, ADDR(9), 0},
- { OP_String, 0, 0, 0}, /* 1 */
- { OP_Column, 0, 1, 0},
- { OP_Ne, 0, ADDR(8), 0},
- { OP_String, 0, 0, "trigger"},
- { OP_Column, 0, 0, 0},
- { OP_Ne, 0, ADDR(8), 0},
- { OP_Delete, 0, 0, 0},
- { OP_Next, 0, ADDR(1), 0}, /* 8 */
- };
-
- sqliteBeginWriteOperation(pParse, 0, 0);
- sqliteOpenMasterTable(v, pTrigger->iDb);
- base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
- sqliteVdbeChangeP3(v, base+1, pTrigger->name, 0);
- if( pTrigger->iDb==0 ){
- sqliteChangeCookie(db, v);
- }
- sqliteVdbeAddOp(v, OP_Close, 0, 0);
- sqliteEndWriteOperation(pParse);
- }
-
- /*
- * If this is not an "explain", then delete the trigger structure.
- */
- if( !pParse->explain ){
- const char *zName = pTrigger->name;
- int nName = strlen(zName);
- if( pTable->pTrigger == pTrigger ){
- pTable->pTrigger = pTrigger->pNext;
- }else{
- Trigger *cc = pTable->pTrigger;
- while( cc ){
- if( cc->pNext == pTrigger ){
- cc->pNext = cc->pNext->pNext;
- break;
- }
- cc = cc->pNext;
- }
- assert(cc);
- }
- sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
- sqliteDeleteTrigger(pTrigger);
- }
-}
-
-/*
-** pEList is the SET clause of an UPDATE statement. Each entry
-** in pEList is of the format <id>=<expr>. If any of the entries
-** in pEList have an <id> which matches an identifier in pIdList,
-** then return TRUE. If pIdList==NULL, then it is considered a
-** wildcard that matches anything. Likewise if pEList==NULL then
-** it matches anything so always return true. Return false only
-** if there is no match.
-*/
-static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
- int e;
- if( !pIdList || !pEList ) return 1;
- for(e=0; e<pEList->nExpr; e++){
- if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
- }
- return 0;
-}
-
-/* A global variable that is TRUE if we should always set up temp tables for
- * for triggers, even if there are no triggers to code. This is used to test
- * how much overhead the triggers algorithm is causing.
- *
- * This flag can be set or cleared using the "trigger_overhead_test" pragma.
- * The pragma is not documented since it is not really part of the interface
- * to SQLite, just the test procedure.
-*/
-int always_code_trigger_setup = 0;
-
-/*
- * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
- * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
- * found in the list specified as pTrigger.
- */
-int sqliteTriggersExist(
- Parse *pParse, /* Used to check for recursive triggers */
- Trigger *pTrigger, /* A list of triggers associated with a table */
- int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
- int tr_tm, /* one of TK_BEFORE, TK_AFTER */
- int foreach, /* one of TK_ROW or TK_STATEMENT */
- ExprList *pChanges /* Columns that change in an UPDATE statement */
-){
- Trigger * pTriggerCursor;
-
- if( always_code_trigger_setup ){
- return 1;
- }
-
- pTriggerCursor = pTrigger;
- while( pTriggerCursor ){
- if( pTriggerCursor->op == op &&
- pTriggerCursor->tr_tm == tr_tm &&
- pTriggerCursor->foreach == foreach &&
- checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
- TriggerStack * ss;
- ss = pParse->trigStack;
- while( ss && ss->pTrigger != pTrigger ){
- ss = ss->pNext;
- }
- if( !ss )return 1;
- }
- pTriggerCursor = pTriggerCursor->pNext;
- }
-
- return 0;
-}
-
-/*
-** Convert the pStep->target token into a SrcList and return a pointer
-** to that SrcList.
-**
-** This routine adds a specific database name, if needed, to the target when
-** forming the SrcList. This prevents a trigger in one database from
-** referring to a target in another database. An exception is when the
-** trigger is in TEMP in which case it can refer to any other database it
-** wants.
-*/
-static SrcList *targetSrcList(
- Parse *pParse, /* The parsing context */
- TriggerStep *pStep /* The trigger containing the target token */
-){
- Token sDb; /* Dummy database name token */
- int iDb; /* Index of the database to use */
- SrcList *pSrc; /* SrcList to be returned */
-
- iDb = pStep->pTrig->iDb;
- if( iDb==0 || iDb>=2 ){
- assert( iDb<pParse->db->nDb );
- sDb.z = pParse->db->aDb[iDb].zName;
- sDb.n = strlen(sDb.z);
- pSrc = sqliteSrcListAppend(0, &sDb, &pStep->target);
- } else {
- pSrc = sqliteSrcListAppend(0, &pStep->target, 0);
- }
- return pSrc;
-}
-
-/*
-** Generate VDBE code for zero or more statements inside the body of a
-** trigger.
-*/
-static int codeTriggerProgram(
- Parse *pParse, /* The parser context */
- TriggerStep *pStepList, /* List of statements inside the trigger body */
- int orconfin /* Conflict algorithm. (OE_Abort, etc) */
-){
- TriggerStep * pTriggerStep = pStepList;
- int orconf;
-
- while( pTriggerStep ){
- int saveNTab = pParse->nTab;
-
- orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
- pParse->trigStack->orconf = orconf;
- switch( pTriggerStep->op ){
- case TK_SELECT: {
- Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
- assert(ss);
- assert(ss->pSrc);
- sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
- sqliteSelectDelete(ss);
- break;
- }
- case TK_UPDATE: {
- SrcList *pSrc;
- pSrc = targetSrcList(pParse, pTriggerStep);
- sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
- sqliteUpdate(pParse, pSrc,
- sqliteExprListDup(pTriggerStep->pExprList),
- sqliteExprDup(pTriggerStep->pWhere), orconf);
- sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
- break;
- }
- case TK_INSERT: {
- SrcList *pSrc;
- pSrc = targetSrcList(pParse, pTriggerStep);
- sqliteInsert(pParse, pSrc,
- sqliteExprListDup(pTriggerStep->pExprList),
- sqliteSelectDup(pTriggerStep->pSelect),
- sqliteIdListDup(pTriggerStep->pIdList), orconf);
- break;
- }
- case TK_DELETE: {
- SrcList *pSrc;
- sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
- pSrc = targetSrcList(pParse, pTriggerStep);
- sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
- sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
- break;
- }
- default:
- assert(0);
- }
- pParse->nTab = saveNTab;
- pTriggerStep = pTriggerStep->pNext;
- }
-
- return 0;
-}
-
-/*
-** This is called to code FOR EACH ROW triggers.
-**
-** When the code that this function generates is executed, the following
-** must be true:
-**
-** 1. No cursors may be open in the main database. (But newIdx and oldIdx
-** can be indices of cursors in temporary tables. See below.)
-**
-** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
-** a temporary vdbe cursor (index newIdx) must be open and pointing at
-** a row containing values to be substituted for new.* expressions in the
-** trigger program(s).
-**
-** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
-** a temporary vdbe cursor (index oldIdx) must be open and pointing at
-** a row containing values to be substituted for old.* expressions in the
-** trigger program(s).
-**
-*/
-int sqliteCodeRowTrigger(
- Parse *pParse, /* Parse context */
- int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
- ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
- int tr_tm, /* One of TK_BEFORE, TK_AFTER */
- Table *pTab, /* The table to code triggers from */
- int newIdx, /* The indice of the "new" row to access */
- int oldIdx, /* The indice of the "old" row to access */
- int orconf, /* ON CONFLICT policy */
- int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
-){
- Trigger * pTrigger;
- TriggerStack * pTriggerStack;
-
- assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
- assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
-
- assert(newIdx != -1 || oldIdx != -1);
-
- pTrigger = pTab->pTrigger;
- while( pTrigger ){
- int fire_this = 0;
-
- /* determine whether we should code this trigger */
- if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
- pTrigger->foreach == TK_ROW ){
- fire_this = 1;
- pTriggerStack = pParse->trigStack;
- while( pTriggerStack ){
- if( pTriggerStack->pTrigger == pTrigger ){
- fire_this = 0;
- }
- pTriggerStack = pTriggerStack->pNext;
- }
- if( op == TK_UPDATE && pTrigger->pColumns &&
- !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
- fire_this = 0;
- }
- }
-
- if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
- int endTrigger;
- SrcList dummyTablist;
- Expr * whenExpr;
- AuthContext sContext;
-
- dummyTablist.nSrc = 0;
-
- /* Push an entry on to the trigger stack */
- pTriggerStack->pTrigger = pTrigger;
- pTriggerStack->newIdx = newIdx;
- pTriggerStack->oldIdx = oldIdx;
- pTriggerStack->pTab = pTab;
- pTriggerStack->pNext = pParse->trigStack;
- pTriggerStack->ignoreJump = ignoreJump;
- pParse->trigStack = pTriggerStack;
- sqliteAuthContextPush(pParse, &sContext, pTrigger->name);
-
- /* code the WHEN clause */
- endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
- whenExpr = sqliteExprDup(pTrigger->pWhen);
- if( sqliteExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
- pParse->trigStack = pParse->trigStack->pNext;
- sqliteFree(pTriggerStack);
- sqliteExprDelete(whenExpr);
- return 1;
- }
- sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
- sqliteExprDelete(whenExpr);
-
- sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPush, 0, 0);
- codeTriggerProgram(pParse, pTrigger->step_list, orconf);
- sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPop, 0, 0);
-
- /* Pop the entry off the trigger stack */
- pParse->trigStack = pParse->trigStack->pNext;
- sqliteAuthContextPop(&sContext);
- sqliteFree(pTriggerStack);
-
- sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
- }
- pTrigger = pTrigger->pNext;
- }
-
- return 0;
-}
diff --git a/ext/sqlite/libsqlite/src/update.c b/ext/sqlite/libsqlite/src/update.c
deleted file mode 100644
index f20cc9b531..0000000000
--- a/ext/sqlite/libsqlite/src/update.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains C code routines that are called by the parser
-** to handle UPDATE statements.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** Process an UPDATE statement.
-**
-** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
-** \_______/ \________/ \______/ \________________/
-* onError pTabList pChanges pWhere
-*/
-void sqliteUpdate(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* The table in which we should change things */
- ExprList *pChanges, /* Things to be changed */
- Expr *pWhere, /* The WHERE clause. May be null */
- int onError /* How to handle constraint errors */
-){
- int i, j; /* Loop counters */
- Table *pTab; /* The table to be updated */
- int loopStart; /* VDBE instruction address of the start of the loop */
- int jumpInst; /* Addr of VDBE instruction to jump out of loop */
- WhereInfo *pWInfo; /* Information about the WHERE clause */
- Vdbe *v; /* The virtual database engine */
- Index *pIdx; /* For looping over indices */
- int nIdx; /* Number of indices that need updating */
- int nIdxTotal; /* Total number of indices */
- int iCur; /* VDBE Cursor number of pTab */
- sqlite *db; /* The database structure */
- Index **apIdx = 0; /* An array of indices that need updating too */
- char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
- int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
- ** an expression for the i-th column of the table.
- ** aXRef[i]==-1 if the i-th column is not changed. */
- int chngRecno; /* True if the record number is being changed */
- Expr *pRecnoExpr; /* Expression defining the new record number */
- int openAll; /* True if all indices need to be opened */
- int isView; /* Trying to update a view */
- int iStackDepth; /* Index of memory cell holding stack depth */
- AuthContext sContext; /* The authorization context */
-
- int before_triggers; /* True if there are any BEFORE triggers */
- int after_triggers; /* True if there are any AFTER triggers */
- int row_triggers_exist = 0; /* True if any row triggers exist */
-
- int newIdx = -1; /* index of trigger "new" temp table */
- int oldIdx = -1; /* index of trigger "old" temp table */
-
- sContext.pParse = 0;
- if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
- db = pParse->db;
- assert( pTabList->nSrc==1 );
- iStackDepth = pParse->nMem++;
-
- /* Locate the table which we want to update.
- */
- pTab = sqliteSrcListLookup(pParse, pTabList);
- if( pTab==0 ) goto update_cleanup;
- before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
- TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
- after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
- TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
- row_triggers_exist = before_triggers || after_triggers;
- isView = pTab->pSelect!=0;
- if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
- goto update_cleanup;
- }
- if( isView ){
- if( sqliteViewGetColumnNames(pParse, pTab) ){
- goto update_cleanup;
- }
- }
- aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
- if( aXRef==0 ) goto update_cleanup;
- for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
-
- /* If there are FOR EACH ROW triggers, allocate cursors for the
- ** special OLD and NEW tables
- */
- if( row_triggers_exist ){
- newIdx = pParse->nTab++;
- oldIdx = pParse->nTab++;
- }
-
- /* Allocate a cursors for the main database table and for all indices.
- ** The index cursors might not be used, but if they are used they
- ** need to occur right after the database cursor. So go ahead and
- ** allocate enough space, just in case.
- */
- pTabList->a[0].iCursor = iCur = pParse->nTab++;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- pParse->nTab++;
- }
-
- /* Resolve the column names in all the expressions of the
- ** of the UPDATE statement. Also find the column index
- ** for each column to be updated in the pChanges array. For each
- ** column to be updated, make sure we have authorization to change
- ** that column.
- */
- chngRecno = 0;
- for(i=0; i<pChanges->nExpr; i++){
- if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
- goto update_cleanup;
- }
- if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
- goto update_cleanup;
- }
- for(j=0; j<pTab->nCol; j++){
- if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
- if( j==pTab->iPKey ){
- chngRecno = 1;
- pRecnoExpr = pChanges->a[i].pExpr;
- }
- aXRef[j] = i;
- break;
- }
- }
- if( j>=pTab->nCol ){
- if( sqliteIsRowid(pChanges->a[i].zName) ){
- chngRecno = 1;
- pRecnoExpr = pChanges->a[i].pExpr;
- }else{
- sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
- goto update_cleanup;
- }
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- {
- int rc;
- rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
- pTab->aCol[j].zName, db->aDb[pTab->iDb].zName);
- if( rc==SQLITE_DENY ){
- goto update_cleanup;
- }else if( rc==SQLITE_IGNORE ){
- aXRef[j] = -1;
- }
- }
-#endif
- }
-
- /* Allocate memory for the array apIdx[] and fill it with pointers to every
- ** index that needs to be updated. Indices only need updating if their
- ** key includes one of the columns named in pChanges or if the record
- ** number of the original table entry is changing.
- */
- for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
- if( chngRecno ){
- i = 0;
- }else {
- for(i=0; i<pIdx->nColumn; i++){
- if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
- }
- }
- if( i<pIdx->nColumn ) nIdx++;
- }
- if( nIdxTotal>0 ){
- apIdx = sqliteMalloc( sizeof(Index*) * nIdx + nIdxTotal );
- if( apIdx==0 ) goto update_cleanup;
- aIdxUsed = (char*)&apIdx[nIdx];
- }
- for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- if( chngRecno ){
- i = 0;
- }else{
- for(i=0; i<pIdx->nColumn; i++){
- if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
- }
- }
- if( i<pIdx->nColumn ){
- apIdx[nIdx++] = pIdx;
- aIdxUsed[j] = 1;
- }else{
- aIdxUsed[j] = 0;
- }
- }
-
- /* Resolve the column names in all the expressions in the
- ** WHERE clause.
- */
- if( pWhere ){
- if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
- goto update_cleanup;
- }
- if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
- goto update_cleanup;
- }
- }
-
- /* Start the view context
- */
- if( isView ){
- sqliteAuthContextPush(pParse, &sContext, pTab->zName);
- }
-
- /* Begin generating code.
- */
- v = sqliteGetVdbe(pParse);
- if( v==0 ) goto update_cleanup;
- sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
-
- /* If we are trying to update a view, construct that view into
- ** a temporary table.
- */
- if( isView ){
- Select *pView;
- pView = sqliteSelectDup(pTab->pSelect);
- sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
- sqliteSelectDelete(pView);
- }
-
- /* Begin the database scan
- */
- pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
- if( pWInfo==0 ) goto update_cleanup;
-
- /* Remember the index of every item to be updated.
- */
- sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
-
- /* End the database scan loop.
- */
- sqliteWhereEnd(pWInfo);
-
- /* Initialize the count of updated rows
- */
- if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
- sqliteVdbeAddOp(v, OP_Integer, 0, 0);
- }
-
- if( row_triggers_exist ){
- /* Create pseudo-tables for NEW and OLD
- */
- sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
- sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
-
- /* The top of the update loop for when there are triggers.
- */
- sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
- sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
- sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
- loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
- sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
- jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
-
- /* Open a cursor and make it point to the record that is
- ** being updated.
- */
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
- }
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
-
- /* Generate the OLD table
- */
- sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
- sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
-
- /* Generate the NEW table
- */
- if( chngRecno ){
- sqliteExprCode(pParse, pRecnoExpr);
- }else{
- sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
- }
- for(i=0; i<pTab->nCol; i++){
- if( i==pTab->iPKey ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- continue;
- }
- j = aXRef[i];
- if( j<0 ){
- sqliteVdbeAddOp(v, OP_Column, iCur, i);
- }else{
- sqliteExprCode(pParse, pChanges->a[j].pExpr);
- }
- }
- sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
- sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
- if( !isView ){
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- }
-
- /* Fire the BEFORE and INSTEAD OF triggers
- */
- if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
- newIdx, oldIdx, onError, loopStart) ){
- goto update_cleanup;
- }
- }
-
- if( !isView ){
- /*
- ** Open every index that needs updating. Note that if any
- ** index could potentially invoke a REPLACE conflict resolution
- ** action, then we need to open all indices because we might need
- ** to be deleting some records.
- */
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum);
- if( onError==OE_Replace ){
- openAll = 1;
- }else{
- openAll = 0;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->onError==OE_Replace ){
- openAll = 1;
- break;
- }
- }
- }
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] ){
- sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
- sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum);
- assert( pParse->nTab>iCur+i+1 );
- }
- }
-
- /* Loop over every record that needs updating. We have to load
- ** the old data for each record to be updated because some columns
- ** might not change and we will need to copy the old value.
- ** Also, the old data is needed to delete the old index entires.
- ** So make the cursor point at the old record.
- */
- if( !row_triggers_exist ){
- sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
- jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- }
- sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
-
- /* If the record number will change, push the record number as it
- ** will be after the update. (The old record number is currently
- ** on top of the stack.)
- */
- if( chngRecno ){
- sqliteExprCode(pParse, pRecnoExpr);
- sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
- }
-
- /* Compute new data for this record.
- */
- for(i=0; i<pTab->nCol; i++){
- if( i==pTab->iPKey ){
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- continue;
- }
- j = aXRef[i];
- if( j<0 ){
- sqliteVdbeAddOp(v, OP_Column, iCur, i);
- }else{
- sqliteExprCode(pParse, pChanges->a[j].pExpr);
- }
- }
-
- /* Do constraint checks
- */
- sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
- onError, loopStart);
-
- /* Delete the old indices for the current record.
- */
- sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);
-
- /* If changing the record number, delete the old record.
- */
- if( chngRecno ){
- sqliteVdbeAddOp(v, OP_Delete, iCur, 0);
- }
-
- /* Create the new index entries and the new record.
- */
- sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
- }
-
- /* Increment the row counter
- */
- if( db->flags & SQLITE_CountRows && !pParse->trigStack){
- sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
- }
-
- /* If there are triggers, close all the cursors after each iteration
- ** through the loop. The fire the after triggers.
- */
- if( row_triggers_exist ){
- if( !isView ){
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] )
- sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
- }
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- pParse->nTab = iCur;
- }
- if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
- newIdx, oldIdx, onError, loopStart) ){
- goto update_cleanup;
- }
- }
-
- /* Repeat the above with the next record to be updated, until
- ** all record selected by the WHERE clause have been updated.
- */
- sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
- sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
- sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
-
- /* Close all tables if there were no FOR EACH ROW triggers */
- if( !row_triggers_exist ){
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] ){
- sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
- }
- }
- sqliteVdbeAddOp(v, OP_Close, iCur, 0);
- pParse->nTab = iCur;
- }else{
- sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
- sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
- }
-
- sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
- sqliteEndWriteOperation(pParse);
-
- /*
- ** Return the number of rows that were changed.
- */
- if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
- sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows updated", P3_STATIC);
- sqliteVdbeAddOp(v, OP_Callback, 1, 0);
- }
-
-update_cleanup:
- sqliteAuthContextPop(&sContext);
- sqliteFree(apIdx);
- sqliteFree(aXRef);
- sqliteSrcListDelete(pTabList);
- sqliteExprListDelete(pChanges);
- sqliteExprDelete(pWhere);
- return;
-}
diff --git a/ext/sqlite/libsqlite/src/util.c b/ext/sqlite/libsqlite/src/util.c
deleted file mode 100644
index 4fa09b3759..0000000000
--- a/ext/sqlite/libsqlite/src/util.c
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** Utility functions used throughout sqlite.
-**
-** This file contains functions for allocating memory, comparing
-** strings, and stuff like that.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include <stdarg.h>
-#include <ctype.h>
-
-/*
-** If malloc() ever fails, this global variable gets set to 1.
-** This causes the library to abort and never again function.
-*/
-int sqlite_malloc_failed = 0;
-
-/*
-** If MEMORY_DEBUG is defined, then use versions of malloc() and
-** free() that track memory usage and check for buffer overruns.
-*/
-#ifdef MEMORY_DEBUG
-
-/*
-** For keeping track of the number of mallocs and frees. This
-** is used to check for memory leaks.
-*/
-int sqlite_nMalloc; /* Number of sqliteMalloc() calls */
-int sqlite_nFree; /* Number of sqliteFree() calls */
-int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */
-#if MEMORY_DEBUG>1
-static int memcnt = 0;
-#endif
-
-/*
-** Number of 32-bit guard words
-*/
-#define N_GUARD 1
-
-/*
-** Allocate new memory and set it to zero. Return NULL if
-** no memory is available.
-*/
-void *sqliteMalloc_(int n, int bZero, char *zFile, int line){
- void *p;
- int *pi;
- int i, k;
- if( sqlite_iMallocFail>=0 ){
- sqlite_iMallocFail--;
- if( sqlite_iMallocFail==0 ){
- sqlite_malloc_failed++;
-#if MEMORY_DEBUG>1
- fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
- n, zFile,line);
-#endif
- sqlite_iMallocFail--;
- return 0;
- }
- }
- if( n==0 ) return 0;
- k = (n+sizeof(int)-1)/sizeof(int);
- pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
- if( pi==0 ){
- sqlite_malloc_failed++;
- return 0;
- }
- sqlite_nMalloc++;
- for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
- pi[N_GUARD] = n;
- for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344;
- p = &pi[N_GUARD+1];
- memset(p, bZero==0, n);
-#if MEMORY_DEBUG>1
- fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n",
- ++memcnt, n, (int)p, zFile,line);
-#endif
- return p;
-}
-
-/*
-** Check to see if the given pointer was obtained from sqliteMalloc()
-** and is able to hold at least N bytes. Raise an exception if this
-** is not the case.
-**
-** This routine is used for testing purposes only.
-*/
-void sqliteCheckMemory(void *p, int N){
- int *pi = p;
- int n, i, k;
- pi -= N_GUARD+1;
- for(i=0; i<N_GUARD; i++){
- assert( pi[i]==0xdead1122 );
- }
- n = pi[N_GUARD];
- assert( N>=0 && N<n );
- k = (n+sizeof(int)-1)/sizeof(int);
- for(i=0; i<N_GUARD; i++){
- assert( pi[k+N_GUARD+1+i]==0xdead3344 );
- }
-}
-
-/*
-** Free memory previously obtained from sqliteMalloc()
-*/
-void sqliteFree_(void *p, char *zFile, int line){
- if( p ){
- int *pi, i, k, n;
- pi = p;
- pi -= N_GUARD+1;
- sqlite_nFree++;
- for(i=0; i<N_GUARD; i++){
- if( pi[i]!=0xdead1122 ){
- fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p);
- return;
- }
- }
- n = pi[N_GUARD];
- k = (n+sizeof(int)-1)/sizeof(int);
- for(i=0; i<N_GUARD; i++){
- if( pi[k+N_GUARD+1+i]!=0xdead3344 ){
- fprintf(stderr,"High-end memory corruption at 0x%x\n", (int)p);
- return;
- }
- }
- memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int));
-#if MEMORY_DEBUG>1
- fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n",
- ++memcnt, n, (int)p, zFile,line);
-#endif
- free(pi);
- }
-}
-
-/*
-** Resize a prior allocation. If p==0, then this routine
-** works just like sqliteMalloc(). If n==0, then this routine
-** works just like sqliteFree().
-*/
-void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){
- int *oldPi, *pi, i, k, oldN, oldK;
- void *p;
- if( oldP==0 ){
- return sqliteMalloc_(n,1,zFile,line);
- }
- if( n==0 ){
- sqliteFree_(oldP,zFile,line);
- return 0;
- }
- oldPi = oldP;
- oldPi -= N_GUARD+1;
- if( oldPi[0]!=0xdead1122 ){
- fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)oldP);
- return 0;
- }
- oldN = oldPi[N_GUARD];
- oldK = (oldN+sizeof(int)-1)/sizeof(int);
- for(i=0; i<N_GUARD; i++){
- if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){
- fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n",
- (int)oldP);
- return 0;
- }
- }
- k = (n + sizeof(int) - 1)/sizeof(int);
- pi = malloc( (k+N_GUARD*2+1)*sizeof(int) );
- if( pi==0 ){
- sqlite_malloc_failed++;
- return 0;
- }
- for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
- pi[N_GUARD] = n;
- for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344;
- p = &pi[N_GUARD+1];
- memcpy(p, oldP, n>oldN ? oldN : n);
- if( n>oldN ){
- memset(&((char*)p)[oldN], 0, n-oldN);
- }
- memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int));
- free(oldPi);
-#if MEMORY_DEBUG>1
- fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n",
- ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);
-#endif
- return p;
-}
-
-/*
-** Make a duplicate of a string into memory obtained from malloc()
-** Free the original string using sqliteFree().
-**
-** This routine is called on all strings that are passed outside of
-** the SQLite library. That way clients can free the string using free()
-** rather than having to call sqliteFree().
-*/
-void sqliteStrRealloc(char **pz){
- char *zNew;
- if( pz==0 || *pz==0 ) return;
- zNew = malloc( strlen(*pz) + 1 );
- if( zNew==0 ){
- sqlite_malloc_failed++;
- sqliteFree(*pz);
- *pz = 0;
- }
- strcpy(zNew, *pz);
- sqliteFree(*pz);
- *pz = zNew;
-}
-
-/*
-** Make a copy of a string in memory obtained from sqliteMalloc()
-*/
-char *sqliteStrDup_(const char *z, char *zFile, int line){
- char *zNew;
- if( z==0 ) return 0;
- zNew = sqliteMalloc_(strlen(z)+1, 0, zFile, line);
- if( zNew ) strcpy(zNew, z);
- return zNew;
-}
-char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){
- char *zNew;
- if( z==0 ) return 0;
- zNew = sqliteMalloc_(n+1, 0, zFile, line);
- if( zNew ){
- memcpy(zNew, z, n);
- zNew[n] = 0;
- }
- return zNew;
-}
-#endif /* MEMORY_DEBUG */
-
-/*
-** The following versions of malloc() and free() are for use in a
-** normal build.
-*/
-#if !defined(MEMORY_DEBUG)
-
-/*
-** Allocate new memory and set it to zero. Return NULL if
-** no memory is available. See also sqliteMallocRaw().
-*/
-void *sqliteMalloc(int n){
- void *p;
- if( (p = malloc(n))==0 ){
- if( n>0 ) sqlite_malloc_failed++;
- }else{
- memset(p, 0, n);
- }
- return p;
-}
-
-/*
-** Allocate new memory but do not set it to zero. Return NULL if
-** no memory is available. See also sqliteMalloc().
-*/
-void *sqliteMallocRaw(int n){
- void *p;
- if( (p = malloc(n))==0 ){
- if( n>0 ) sqlite_malloc_failed++;
- }
- return p;
-}
-
-/*
-** Free memory previously obtained from sqliteMalloc()
-*/
-void sqliteFree(void *p){
- if( p ){
- free(p);
- }
-}
-
-/*
-** Resize a prior allocation. If p==0, then this routine
-** works just like sqliteMalloc(). If n==0, then this routine
-** works just like sqliteFree().
-*/
-void *sqliteRealloc(void *p, int n){
- void *p2;
- if( p==0 ){
- return sqliteMalloc(n);
- }
- if( n==0 ){
- sqliteFree(p);
- return 0;
- }
- p2 = realloc(p, n);
- if( p2==0 ){
- sqlite_malloc_failed++;
- }
- return p2;
-}
-
-/*
-** Make a copy of a string in memory obtained from sqliteMalloc()
-*/
-char *sqliteStrDup(const char *z){
- char *zNew;
- if( z==0 ) return 0;
- zNew = sqliteMallocRaw(strlen(z)+1);
- if( zNew ) strcpy(zNew, z);
- return zNew;
-}
-char *sqliteStrNDup(const char *z, int n){
- char *zNew;
- if( z==0 ) return 0;
- zNew = sqliteMallocRaw(n+1);
- if( zNew ){
- memcpy(zNew, z, n);
- zNew[n] = 0;
- }
- return zNew;
-}
-#endif /* !defined(MEMORY_DEBUG) */
-
-/*
-** Create a string from the 2nd and subsequent arguments (up to the
-** first NULL argument), store the string in memory obtained from
-** sqliteMalloc() and make the pointer indicated by the 1st argument
-** point to that string. The 1st argument must either be NULL or
-** point to memory obtained from sqliteMalloc().
-*/
-void sqliteSetString(char **pz, ...){
- va_list ap;
- int nByte;
- const char *z;
- char *zResult;
-
- if( pz==0 ) return;
- nByte = 1;
- va_start(ap, pz);
- while( (z = va_arg(ap, const char*))!=0 ){
- nByte += strlen(z);
- }
- va_end(ap);
- sqliteFree(*pz);
- *pz = zResult = sqliteMallocRaw( nByte );
- if( zResult==0 ){
- return;
- }
- *zResult = 0;
- va_start(ap, pz);
- while( (z = va_arg(ap, const char*))!=0 ){
- strcpy(zResult, z);
- zResult += strlen(zResult);
- }
- va_end(ap);
-#ifdef MEMORY_DEBUG
-#if MEMORY_DEBUG>1
- fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
-#endif
-#endif
-}
-
-/*
-** Works like sqliteSetString, but each string is now followed by
-** a length integer which specifies how much of the source string
-** to copy (in bytes). -1 means use the whole string. The 1st
-** argument must either be NULL or point to memory obtained from
-** sqliteMalloc().
-*/
-void sqliteSetNString(char **pz, ...){
- va_list ap;
- int nByte;
- const char *z;
- char *zResult;
- int n;
-
- if( pz==0 ) return;
- nByte = 0;
- va_start(ap, pz);
- while( (z = va_arg(ap, const char*))!=0 ){
- n = va_arg(ap, int);
- if( n<=0 ) n = strlen(z);
- nByte += n;
- }
- va_end(ap);
- sqliteFree(*pz);
- *pz = zResult = sqliteMallocRaw( nByte + 1 );
- if( zResult==0 ) return;
- va_start(ap, pz);
- while( (z = va_arg(ap, const char*))!=0 ){
- n = va_arg(ap, int);
- if( n<=0 ) n = strlen(z);
- strncpy(zResult, z, n);
- zResult += n;
- }
- *zResult = 0;
-#ifdef MEMORY_DEBUG
-#if MEMORY_DEBUG>1
- fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
-#endif
-#endif
- va_end(ap);
-}
-
-/*
-** Add an error message to pParse->zErrMsg and increment pParse->nErr.
-** The following formatting characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
-*/
-void sqliteErrorMsg(Parse *pParse, const char *zFormat, ...){
- va_list ap;
- pParse->nErr++;
- sqliteFree(pParse->zErrMsg);
- va_start(ap, zFormat);
- pParse->zErrMsg = sqliteVMPrintf(zFormat, ap);
- va_end(ap);
-}
-
-/*
-** Convert an SQL-style quoted string into a normal string by removing
-** the quote characters. The conversion is done in-place. If the
-** input does not begin with a quote character, then this routine
-** is a no-op.
-**
-** 2002-Feb-14: This routine is extended to remove MS-Access style
-** brackets from around identifers. For example: "[a-b-c]" becomes
-** "a-b-c".
-*/
-void sqliteDequote(char *z){
- int quote;
- int i, j;
- if( z==0 ) return;
- quote = z[0];
- switch( quote ){
- case '\'': break;
- case '"': break;
- case '[': quote = ']'; break;
- default: return;
- }
- for(i=1, j=0; z[i]; i++){
- if( z[i]==quote ){
- if( z[i+1]==quote ){
- z[j++] = quote;
- i++;
- }else{
- z[j++] = 0;
- break;
- }
- }else{
- z[j++] = z[i];
- }
- }
-}
-
-/* An array to map all upper-case characters into their corresponding
-** lower-case character.
-*/
-static unsigned char UpperToLower[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
- 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
- 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
- 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
- 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
- 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
- 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
- 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
-};
-
-/*
-** This function computes a hash on the name of a keyword.
-** Case is not significant.
-*/
-int sqliteHashNoCase(const char *z, int n){
- int h = 0;
- if( n<=0 ) n = strlen(z);
- while( n > 0 ){
- h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++];
- n--;
- }
- return h & 0x7fffffff;
-}
-
-/*
-** Some systems have stricmp(). Others have strcasecmp(). Because
-** there is no consistency, we will define our own.
-*/
-int sqliteStrICmp(const char *zLeft, const char *zRight){
- register unsigned char *a, *b;
- a = (unsigned char *)zLeft;
- b = (unsigned char *)zRight;
- while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
- return UpperToLower[*a] - UpperToLower[*b];
-}
-int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){
- register unsigned char *a, *b;
- a = (unsigned char *)zLeft;
- b = (unsigned char *)zRight;
- while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
- return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
-}
-
-/*
-** Return TRUE if z is a pure numeric string. Return FALSE if the
-** string contains any character which is not part of a number.
-**
-** Am empty string is considered non-numeric.
-*/
-int sqliteIsNumber(const char *z){
- if( *z=='-' || *z=='+' ) z++;
- if( !isdigit(*z) ){
- return 0;
- }
- z++;
- while( isdigit(*z) ){ z++; }
- if( *z=='.' ){
- z++;
- if( !isdigit(*z) ) return 0;
- while( isdigit(*z) ){ z++; }
- }
- if( *z=='e' || *z=='E' ){
- z++;
- if( *z=='+' || *z=='-' ) z++;
- if( !isdigit(*z) ) return 0;
- while( isdigit(*z) ){ z++; }
- }
- return *z==0;
-}
-
-/*
-** The string z[] is an ascii representation of a real number.
-** Convert this string to a double.
-**
-** This routine assumes that z[] really is a valid number. If it
-** is not, the result is undefined.
-**
-** This routine is used instead of the library atof() function because
-** the library atof() might want to use "," as the decimal point instead
-** of "." depending on how locale is set. But that would cause problems
-** for SQL. So this routine always uses "." regardless of locale.
-*/
-double sqliteAtoF(const char *z, const char **pzEnd){
- int sign = 1;
- LONGDOUBLE_TYPE v1 = 0.0;
- if( *z=='-' ){
- sign = -1;
- z++;
- }else if( *z=='+' ){
- z++;
- }
- while( isdigit(*z) ){
- v1 = v1*10.0 + (*z - '0');
- z++;
- }
- if( *z=='.' ){
- LONGDOUBLE_TYPE divisor = 1.0;
- z++;
- while( isdigit(*z) ){
- v1 = v1*10.0 + (*z - '0');
- divisor *= 10.0;
- z++;
- }
- v1 /= divisor;
- }
- if( *z=='e' || *z=='E' ){
- int esign = 1;
- int eval = 0;
- LONGDOUBLE_TYPE scale = 1.0;
- z++;
- if( *z=='-' ){
- esign = -1;
- z++;
- }else if( *z=='+' ){
- z++;
- }
- while( isdigit(*z) ){
- eval = eval*10 + *z - '0';
- z++;
- }
- while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; }
- while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; }
- while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; }
- while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; }
- if( esign<0 ){
- v1 /= scale;
- }else{
- v1 *= scale;
- }
- }
- if( pzEnd ) *pzEnd = z;
- return sign<0 ? -v1 : v1;
-}
-
-/*
-** The string zNum represents an integer. There might be some other
-** information following the integer too, but that part is ignored.
-** If the integer that the prefix of zNum represents will fit in a
-** 32-bit signed integer, return TRUE. Otherwise return FALSE.
-**
-** This routine returns FALSE for the string -2147483648 even that
-** that number will, in theory fit in a 32-bit integer. But positive
-** 2147483648 will not fit in 32 bits. So it seems safer to return
-** false.
-*/
-int sqliteFitsIn32Bits(const char *zNum){
- int i, c;
- if( *zNum=='-' || *zNum=='+' ) zNum++;
- for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
- return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
-}
-
-/* This comparison routine is what we use for comparison operations
-** between numeric values in an SQL expression. "Numeric" is a little
-** bit misleading here. What we mean is that the strings have a
-** type of "numeric" from the point of view of SQL. The strings
-** do not necessarily contain numbers. They could contain text.
-**
-** If the input strings both look like actual numbers then they
-** compare in numerical order. Numerical strings are always less
-** than non-numeric strings so if one input string looks like a
-** number and the other does not, then the one that looks like
-** a number is the smaller. Non-numeric strings compare in
-** lexigraphical order (the same order as strcmp()).
-*/
-int sqliteCompare(const char *atext, const char *btext){
- int result;
- int isNumA, isNumB;
- if( atext==0 ){
- return -1;
- }else if( btext==0 ){
- return 1;
- }
- isNumA = sqliteIsNumber(atext);
- isNumB = sqliteIsNumber(btext);
- if( isNumA ){
- if( !isNumB ){
- result = -1;
- }else{
- double rA, rB;
- rA = sqliteAtoF(atext, 0);
- rB = sqliteAtoF(btext, 0);
- if( rA<rB ){
- result = -1;
- }else if( rA>rB ){
- result = +1;
- }else{
- result = 0;
- }
- }
- }else if( isNumB ){
- result = +1;
- }else {
- result = strcmp(atext, btext);
- }
- return result;
-}
-
-/*
-** This routine is used for sorting. Each key is a list of one or more
-** null-terminated elements. The list is terminated by two nulls in
-** a row. For example, the following text is a key with three elements
-**
-** Aone\000Dtwo\000Athree\000\000
-**
-** All elements begin with one of the characters "+-AD" and end with "\000"
-** with zero or more text elements in between. Except, NULL elements
-** consist of the special two-character sequence "N\000".
-**
-** Both arguments will have the same number of elements. This routine
-** returns negative, zero, or positive if the first argument is less
-** than, equal to, or greater than the first. (Result is a-b).
-**
-** Each element begins with one of the characters "+", "-", "A", "D".
-** This character determines the sort order and collating sequence:
-**
-** + Sort numerically in ascending order
-** - Sort numerically in descending order
-** A Sort as strings in ascending order
-** D Sort as strings in descending order.
-**
-** For the "+" and "-" sorting, pure numeric strings (strings for which the
-** isNum() function above returns TRUE) always compare less than strings
-** that are not pure numerics. Non-numeric strings compare in memcmp()
-** order. This is the same sort order as the sqliteCompare() function
-** above generates.
-**
-** The last point is a change from version 2.6.3 to version 2.7.0. In
-** version 2.6.3 and earlier, substrings of digits compare in numerical
-** and case was used only to break a tie.
-**
-** Elements that begin with 'A' or 'D' compare in memcmp() order regardless
-** of whether or not they look like a number.
-**
-** Note that the sort order imposed by the rules above is the same
-** from the ordering defined by the "<", "<=", ">", and ">=" operators
-** of expressions and for indices. This was not the case for version
-** 2.6.3 and earlier.
-*/
-int sqliteSortCompare(const char *a, const char *b){
- int res = 0;
- int isNumA, isNumB;
- int dir = 0;
-
- while( res==0 && *a && *b ){
- if( a[0]=='N' || b[0]=='N' ){
- if( a[0]==b[0] ){
- a += 2;
- b += 2;
- continue;
- }
- if( a[0]=='N' ){
- dir = b[0];
- res = -1;
- }else{
- dir = a[0];
- res = +1;
- }
- break;
- }
- assert( a[0]==b[0] );
- if( (dir=a[0])=='A' || a[0]=='D' ){
- res = strcmp(&a[1],&b[1]);
- if( res ) break;
- }else{
- isNumA = sqliteIsNumber(&a[1]);
- isNumB = sqliteIsNumber(&b[1]);
- if( isNumA ){
- double rA, rB;
- if( !isNumB ){
- res = -1;
- break;
- }
- rA = sqliteAtoF(&a[1], 0);
- rB = sqliteAtoF(&b[1], 0);
- if( rA<rB ){
- res = -1;
- break;
- }
- if( rA>rB ){
- res = +1;
- break;
- }
- }else if( isNumB ){
- res = +1;
- break;
- }else{
- res = strcmp(&a[1],&b[1]);
- if( res ) break;
- }
- }
- a += strlen(&a[1]) + 2;
- b += strlen(&b[1]) + 2;
- }
- if( dir=='-' || dir=='D' ) res = -res;
- return res;
-}
-
-/*
-** Some powers of 64. These constants are needed in the
-** sqliteRealToSortable() routine below.
-*/
-#define _64e3 (64.0 * 64.0 * 64.0)
-#define _64e4 (64.0 * 64.0 * 64.0 * 64.0)
-#define _64e15 (_64e3 * _64e4 * _64e4 * _64e4)
-#define _64e16 (_64e4 * _64e4 * _64e4 * _64e4)
-#define _64e63 (_64e15 * _64e16 * _64e16 * _64e16)
-#define _64e64 (_64e16 * _64e16 * _64e16 * _64e16)
-
-/*
-** The following procedure converts a double-precision floating point
-** number into a string. The resulting string has the property that
-** two such strings comparied using strcmp() or memcmp() will give the
-** same results as a numeric comparison of the original floating point
-** numbers.
-**
-** This routine is used to generate database keys from floating point
-** numbers such that the keys sort in the same order as the original
-** floating point numbers even though the keys are compared using
-** memcmp().
-**
-** The calling function should have allocated at least 14 characters
-** of space for the buffer z[].
-*/
-void sqliteRealToSortable(double r, char *z){
- int neg;
- int exp;
- int cnt = 0;
-
- /* This array maps integers between 0 and 63 into base-64 digits.
- ** The digits must be chosen such at their ASCII codes are increasing.
- ** This means we can not use the traditional base-64 digit set. */
- static const char zDigit[] =
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "|~";
- if( r<0.0 ){
- neg = 1;
- r = -r;
- *z++ = '-';
- } else {
- neg = 0;
- *z++ = '0';
- }
- exp = 0;
-
- if( r==0.0 ){
- exp = -1024;
- }else if( r<(0.5/64.0) ){
- while( r < 0.5/_64e64 && exp > -961 ){ r *= _64e64; exp -= 64; }
- while( r < 0.5/_64e16 && exp > -1009 ){ r *= _64e16; exp -= 16; }
- while( r < 0.5/_64e4 && exp > -1021 ){ r *= _64e4; exp -= 4; }
- while( r < 0.5/64.0 && exp > -1024 ){ r *= 64.0; exp -= 1; }
- }else if( r>=0.5 ){
- while( r >= 0.5*_64e63 && exp < 960 ){ r *= 1.0/_64e64; exp += 64; }
- while( r >= 0.5*_64e15 && exp < 1008 ){ r *= 1.0/_64e16; exp += 16; }
- while( r >= 0.5*_64e3 && exp < 1020 ){ r *= 1.0/_64e4; exp += 4; }
- while( r >= 0.5 && exp < 1023 ){ r *= 1.0/64.0; exp += 1; }
- }
- if( neg ){
- exp = -exp;
- r = -r;
- }
- exp += 1024;
- r += 0.5;
- if( exp<0 ) return;
- if( exp>=2048 || r>=1.0 ){
- strcpy(z, "~~~~~~~~~~~~");
- return;
- }
- *z++ = zDigit[(exp>>6)&0x3f];
- *z++ = zDigit[exp & 0x3f];
- while( r>0.0 && cnt<10 ){
- int digit;
- r *= 64.0;
- digit = (int)r;
- assert( digit>=0 && digit<64 );
- *z++ = zDigit[digit & 0x3f];
- r -= digit;
- cnt++;
- }
- *z = 0;
-}
-
-#ifdef SQLITE_UTF8
-/*
-** X is a pointer to the first byte of a UTF-8 character. Increment
-** X so that it points to the next character. This only works right
-** if X points to a well-formed UTF-8 string.
-*/
-#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
-#define sqliteCharVal(X) sqlite_utf8_to_int(X)
-
-#else /* !defined(SQLITE_UTF8) */
-/*
-** For iso8859 encoding, the next character is just the next byte.
-*/
-#define sqliteNextChar(X) (++(X));
-#define sqliteCharVal(X) ((int)*(X))
-
-#endif /* defined(SQLITE_UTF8) */
-
-
-#ifdef SQLITE_UTF8
-/*
-** Convert the UTF-8 character to which z points into a 31-bit
-** UCS character. This only works right if z points to a well-formed
-** UTF-8 string.
-*/
-static int sqlite_utf8_to_int(const unsigned char *z){
- int c;
- static const int initVal[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
- 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
- 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
- 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
- 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 1, 2,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0,
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 254,
- 255,
- };
- c = initVal[*(z++)];
- while( (0xc0&*z)==0x80 ){
- c = (c<<6) | (0x3f&*(z++));
- }
- return c;
-}
-#endif
-
-/*
-** Compare two UTF-8 strings for equality where the first string can
-** potentially be a "glob" expression. Return true (1) if they
-** are the same and false (0) if they are different.
-**
-** Globbing rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** With the [...] and [^...] matching, a ']' character can be included
-** in the list by making it the first character after '[' or '^'. A
-** range of characters can be specified using '-'. Example:
-** "[a-z]" matches any single lower-case letter. To match a '-', make
-** it the last character in the list.
-**
-** This routine is usually quick, but can be N**2 in the worst case.
-**
-** Hints: to match '*' or '?', put them in "[]". Like this:
-**
-** abc[*]xyz Matches "abc*xyz" only
-*/
-int
-sqliteGlobCompare(const unsigned char *zPattern, const unsigned char *zString){
- register int c;
- int invert;
- int seen;
- int c2;
-
- while( (c = *zPattern)!=0 ){
- switch( c ){
- case '*':
- while( (c=zPattern[1]) == '*' || c == '?' ){
- if( c=='?' ){
- if( *zString==0 ) return 0;
- sqliteNextChar(zString);
- }
- zPattern++;
- }
- if( c==0 ) return 1;
- if( c=='[' ){
- while( *zString && sqliteGlobCompare(&zPattern[1],zString)==0 ){
- sqliteNextChar(zString);
- }
- return *zString!=0;
- }else{
- while( (c2 = *zString)!=0 ){
- while( c2 != 0 && c2 != c ){ c2 = *++zString; }
- if( c2==0 ) return 0;
- if( sqliteGlobCompare(&zPattern[1],zString) ) return 1;
- sqliteNextChar(zString);
- }
- return 0;
- }
- case '?': {
- if( *zString==0 ) return 0;
- sqliteNextChar(zString);
- zPattern++;
- break;
- }
- case '[': {
- int prior_c = 0;
- seen = 0;
- invert = 0;
- c = sqliteCharVal(zString);
- if( c==0 ) return 0;
- c2 = *++zPattern;
- if( c2=='^' ){ invert = 1; c2 = *++zPattern; }
- if( c2==']' ){
- if( c==']' ) seen = 1;
- c2 = *++zPattern;
- }
- while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){
- if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){
- zPattern++;
- c2 = sqliteCharVal(zPattern);
- if( c>=prior_c && c<=c2 ) seen = 1;
- prior_c = 0;
- }else if( c==c2 ){
- seen = 1;
- prior_c = c2;
- }else{
- prior_c = c2;
- }
- sqliteNextChar(zPattern);
- }
- if( c2==0 || (seen ^ invert)==0 ) return 0;
- sqliteNextChar(zString);
- zPattern++;
- break;
- }
- default: {
- if( c != *zString ) return 0;
- zPattern++;
- zString++;
- break;
- }
- }
- }
- return *zString==0;
-}
-
-/*
-** Compare two UTF-8 strings for equality using the "LIKE" operator of
-** SQL. The '%' character matches any sequence of 0 or more
-** characters and '_' matches any single character. Case is
-** not significant.
-**
-** This routine is just an adaptation of the sqliteGlobCompare()
-** routine above.
-*/
-int
-sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString){
- register int c;
- int c2;
-
- while( (c = UpperToLower[*zPattern])!=0 ){
- switch( c ){
- case '%': {
- while( (c=zPattern[1]) == '%' || c == '_' ){
- if( c=='_' ){
- if( *zString==0 ) return 0;
- sqliteNextChar(zString);
- }
- zPattern++;
- }
- if( c==0 ) return 1;
- c = UpperToLower[c];
- while( (c2=UpperToLower[*zString])!=0 ){
- while( c2 != 0 && c2 != c ){ c2 = UpperToLower[*++zString]; }
- if( c2==0 ) return 0;
- if( sqliteLikeCompare(&zPattern[1],zString) ) return 1;
- sqliteNextChar(zString);
- }
- return 0;
- }
- case '_': {
- if( *zString==0 ) return 0;
- sqliteNextChar(zString);
- zPattern++;
- break;
- }
- default: {
- if( c != UpperToLower[*zString] ) return 0;
- zPattern++;
- zString++;
- break;
- }
- }
- }
- return *zString==0;
-}
-
-/*
-** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY.
-** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN
-** when this routine is called.
-**
-** This routine is a attempt to detect if two threads use the
-** same sqlite* pointer at the same time. There is a race
-** condition so it is possible that the error is not detected.
-** But usually the problem will be seen. The result will be an
-** error which can be used to debug the application that is
-** using SQLite incorrectly.
-**
-** Ticket #202: If db->magic is not a valid open value, take care not
-** to modify the db structure at all. It could be that db is a stale
-** pointer. In other words, it could be that there has been a prior
-** call to sqlite_close(db) and db has been deallocated. And we do
-** not want to write into deallocated memory.
-*/
-int sqliteSafetyOn(sqlite *db){
- if( db->magic==SQLITE_MAGIC_OPEN ){
- db->magic = SQLITE_MAGIC_BUSY;
- return 0;
- }else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR
- || db->want_to_close ){
- db->magic = SQLITE_MAGIC_ERROR;
- db->flags |= SQLITE_Interrupt;
- }
- return 1;
-}
-
-/*
-** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN.
-** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY
-** when this routine is called.
-*/
-int sqliteSafetyOff(sqlite *db){
- if( db->magic==SQLITE_MAGIC_BUSY ){
- db->magic = SQLITE_MAGIC_OPEN;
- return 0;
- }else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR
- || db->want_to_close ){
- db->magic = SQLITE_MAGIC_ERROR;
- db->flags |= SQLITE_Interrupt;
- }
- return 1;
-}
-
-/*
-** Check to make sure we are not currently executing an sqlite_exec().
-** If we are currently in an sqlite_exec(), return true and set
-** sqlite.magic to SQLITE_MAGIC_ERROR. This will cause a complete
-** shutdown of the database.
-**
-** This routine is used to try to detect when API routines are called
-** at the wrong time or in the wrong sequence.
-*/
-int sqliteSafetyCheck(sqlite *db){
- if( db->pVdbe!=0 ){
- db->magic = SQLITE_MAGIC_ERROR;
- return 1;
- }
- return 0;
-}
diff --git a/ext/sqlite/libsqlite/src/vacuum.c b/ext/sqlite/libsqlite/src/vacuum.c
deleted file mode 100644
index a3fb196124..0000000000
--- a/ext/sqlite/libsqlite/src/vacuum.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
-** 2003 April 6
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code used to implement the VACUUM command.
-**
-** Most of the code in this file may be omitted by defining the
-** SQLITE_OMIT_VACUUM macro.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include "os.h"
-
-/*
-** A structure for holding a dynamic string - a string that can grow
-** without bound.
-*/
-typedef struct dynStr dynStr;
-struct dynStr {
- char *z; /* Text of the string in space obtained from sqliteMalloc() */
- int nAlloc; /* Amount of space allocated to z[] */
- int nUsed; /* Next unused slot in z[] */
-};
-
-/*
-** A structure that holds the vacuum context
-*/
-typedef struct vacuumStruct vacuumStruct;
-struct vacuumStruct {
- sqlite *dbOld; /* Original database */
- sqlite *dbNew; /* New database */
- char **pzErrMsg; /* Write errors here */
- int rc; /* Set to non-zero on an error */
- const char *zTable; /* Name of a table being copied */
- const char *zPragma; /* Pragma to execute with results */
- dynStr s1, s2; /* Two dynamic strings */
-};
-
-#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
-/*
-** Append text to a dynamic string
-*/
-static void appendText(dynStr *p, const char *zText, int nText){
- if( nText<0 ) nText = strlen(zText);
- if( p->z==0 || p->nUsed + nText + 1 >= p->nAlloc ){
- char *zNew;
- p->nAlloc = p->nUsed + nText + 1000;
- zNew = sqliteRealloc(p->z, p->nAlloc);
- if( zNew==0 ){
- sqliteFree(p->z);
- memset(p, 0, sizeof(*p));
- return;
- }
- p->z = zNew;
- }
- memcpy(&p->z[p->nUsed], zText, nText+1);
- p->nUsed += nText;
-}
-
-/*
-** Append text to a dynamic string, having first put the text in quotes.
-*/
-static void appendQuoted(dynStr *p, const char *zText){
- int i, j;
- appendText(p, "'", 1);
- for(i=j=0; zText[i]; i++){
- if( zText[i]=='\'' ){
- appendText(p, &zText[j], i-j+1);
- j = i + 1;
- appendText(p, "'", 1);
- }
- }
- if( j<i ){
- appendText(p, &zText[j], i-j);
- }
- appendText(p, "'", 1);
-}
-
-/*
-** Execute statements of SQL. If an error occurs, write the error
-** message into *pzErrMsg and return non-zero.
-*/
-static int execsql(char **pzErrMsg, sqlite *db, const char *zSql){
- char *zErrMsg = 0;
- int rc;
-
- /* printf("***** executing *****\n%s\n", zSql); */
- rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
- if( zErrMsg ){
- sqliteSetString(pzErrMsg, zErrMsg, (char*)0);
- sqlite_freemem(zErrMsg);
- }
- return rc;
-}
-
-/*
-** This is the second stage callback. Each invocation contains all the
-** data for a single row of a single table in the original database. This
-** routine must write that information into the new database.
-*/
-static int vacuumCallback2(void *pArg, int argc, char **argv, char **NotUsed){
- vacuumStruct *p = (vacuumStruct*)pArg;
- const char *zSep = "(";
- int i;
-
- if( argv==0 ) return 0;
- p->s2.nUsed = 0;
- appendText(&p->s2, "INSERT INTO ", -1);
- appendQuoted(&p->s2, p->zTable);
- appendText(&p->s2, " VALUES", -1);
- for(i=0; i<argc; i++){
- appendText(&p->s2, zSep, 1);
- zSep = ",";
- if( argv[i]==0 ){
- appendText(&p->s2, "NULL", 4);
- }else{
- appendQuoted(&p->s2, argv[i]);
- }
- }
- appendText(&p->s2,")", 1);
- p->rc = execsql(p->pzErrMsg, p->dbNew, p->s2.z);
- return p->rc;
-}
-
-/*
-** This is the first stage callback. Each invocation contains three
-** arguments where are taken from the SQLITE_MASTER table of the original
-** database: (1) the entry type, (2) the entry name, and (3) the SQL for
-** the entry. In all cases, execute the SQL of the third argument.
-** For tables, run a query to select all entries in that table and
-** transfer them to the second-stage callback.
-*/
-static int vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed){
- vacuumStruct *p = (vacuumStruct*)pArg;
- int rc = 0;
- assert( argc==3 );
- if( argv==0 ) return 0;
- assert( argv[0]!=0 );
- assert( argv[1]!=0 );
- assert( argv[2]!=0 );
- rc = execsql(p->pzErrMsg, p->dbNew, argv[2]);
- if( rc==SQLITE_OK && strcmp(argv[0],"table")==0 ){
- char *zErrMsg = 0;
- p->s1.nUsed = 0;
- appendText(&p->s1, "SELECT * FROM ", -1);
- appendQuoted(&p->s1, argv[1]);
- p->zTable = argv[1];
- rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg);
- if( zErrMsg ){
- sqliteSetString(p->pzErrMsg, zErrMsg, (char*)0);
- sqlite_freemem(zErrMsg);
- }
- }
- if( rc!=SQLITE_ABORT ) p->rc = rc;
- return rc;
-}
-
-/*
-** Generate a random name of 20 character in length.
-*/
-static void randomName(unsigned char *zBuf){
- static const unsigned char zChars[] =
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789";
- int i;
- sqliteRandomness(20, zBuf);
- for(i=0; i<20; i++){
- zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ];
- }
-}
-#endif
-
-/*
-** The non-standard VACUUM command is used to clean up the database,
-** collapse free space, etc. It is modelled after the VACUUM command
-** in PostgreSQL.
-**
-** In version 1.0.x of SQLite, the VACUUM command would call
-** gdbm_reorganize() on all the database tables. But beginning
-** with 2.0.0, SQLite no longer uses GDBM so this command has
-** become a no-op.
-*/
-void sqliteVacuum(Parse *pParse, Token *pTableName){
- Vdbe *v = sqliteGetVdbe(pParse);
- sqliteVdbeAddOp(v, OP_Vacuum, 0, 0);
- return;
-}
-
-/*
-** This routine implements the OP_Vacuum opcode of the VDBE.
-*/
-int sqliteRunVacuum(char **pzErrMsg, sqlite *db){
-#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
- const char *zFilename; /* full pathname of the database file */
- int nFilename; /* number of characters in zFilename[] */
- char *zTemp = 0; /* a temporary file in same directory as zFilename */
- sqlite *dbNew = 0; /* The new vacuumed database */
- int rc = SQLITE_OK; /* Return code from service routines */
- int i; /* Loop counter */
- char *zErrMsg; /* Error message */
- vacuumStruct sVac; /* Information passed to callbacks */
-
- if( db->flags & SQLITE_InTrans ){
- sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",
- (char*)0);
- return SQLITE_ERROR;
- }
- if( db->flags & SQLITE_Interrupt ){
- return SQLITE_INTERRUPT;
- }
- memset(&sVac, 0, sizeof(sVac));
-
- /* Get the full pathname of the database file and create two
- ** temporary filenames in the same directory as the original file.
- */
- zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);
- if( zFilename==0 ){
- /* This only happens with the in-memory database. VACUUM is a no-op
- ** there, so just return */
- return SQLITE_OK;
- }
- nFilename = strlen(zFilename);
- zTemp = sqliteMalloc( nFilename+100 );
- if( zTemp==0 ) return SQLITE_NOMEM;
- strcpy(zTemp, zFilename);
- for(i=0; i<10; i++){
- zTemp[nFilename] = '-';
- randomName((unsigned char*)&zTemp[nFilename+1]);
- if( !sqliteOsFileExists(zTemp) ) break;
- }
- if( i>=10 ){
- sqliteSetString(pzErrMsg, "unable to create a temporary database file "
- "in the same directory as the original database", (char*)0);
- goto end_of_vacuum;
- }
-
-
- dbNew = sqlite_open(zTemp, 0, &zErrMsg);
- if( dbNew==0 ){
- sqliteSetString(pzErrMsg, "unable to open a temporary database at ",
- zTemp, " - ", zErrMsg, (char*)0);
- goto end_of_vacuum;
- }
- if( (rc = execsql(pzErrMsg, db, "BEGIN"))!=0 ) goto end_of_vacuum;
- if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){
- goto end_of_vacuum;
- }
-
- sVac.dbOld = db;
- sVac.dbNew = dbNew;
- sVac.pzErrMsg = pzErrMsg;
- if( rc==SQLITE_OK ){
- rc = sqlite_exec(db,
- "SELECT type, name, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type!='view' "
- "UNION ALL "
- "SELECT type, name, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type=='view'",
- vacuumCallback1, &sVac, &zErrMsg);
- }
- if( rc==SQLITE_OK ){
- int meta1[SQLITE_N_BTREE_META];
- int meta2[SQLITE_N_BTREE_META];
- sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
- sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
- meta2[1] = meta1[1]+1;
- meta2[3] = meta1[3];
- meta2[4] = meta1[4];
- meta2[6] = meta1[6];
- rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
- }
- if( rc==SQLITE_OK ){
- rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
- sqlite_exec(db, "COMMIT", 0, 0, 0);
- sqliteResetInternalSchema(db, 0);
- }
-
-end_of_vacuum:
- if( rc && zErrMsg!=0 ){
- sqliteSetString(pzErrMsg, "unable to vacuum database - ",
- zErrMsg, (char*)0);
- }
- sqlite_exec(db, "ROLLBACK", 0, 0, 0);
- if( (dbNew && (dbNew->flags & SQLITE_Interrupt))
- || (db->flags & SQLITE_Interrupt) ){
- rc = SQLITE_INTERRUPT;
- }
- if( dbNew ) sqlite_close(dbNew);
- sqliteOsDelete(zTemp);
- sqliteFree(zTemp);
- sqliteFree(sVac.s1.z);
- sqliteFree(sVac.s2.z);
- if( zErrMsg ) sqlite_freemem(zErrMsg);
- if( rc==SQLITE_ABORT && sVac.rc!=SQLITE_INTERRUPT ) sVac.rc = SQLITE_ERROR;
- return sVac.rc;
-#endif
-}
diff --git a/ext/sqlite/libsqlite/src/vdbe.c b/ext/sqlite/libsqlite/src/vdbe.c
deleted file mode 100644
index cdbea0ed6b..0000000000
--- a/ext/sqlite/libsqlite/src/vdbe.c
+++ /dev/null
@@ -1,4921 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** The code in this file implements execution method of the
-** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
-** handles housekeeping details such as creating and deleting
-** VDBE instances. This file is solely interested in executing
-** the VDBE program.
-**
-** In the external interface, an "sqlite_vm*" is an opaque pointer
-** to a VDBE.
-**
-** The SQL parser generates a program which is then executed by
-** the VDBE to do the work of the SQL statement. VDBE programs are
-** similar in form to assembly language. The program consists of
-** a linear sequence of operations. Each operation has an opcode
-** and 3 operands. Operands P1 and P2 are integers. Operand P3
-** is a null-terminated string. The P2 operand must be non-negative.
-** Opcodes will typically ignore one or more operands. Many opcodes
-** ignore all three operands.
-**
-** Computation results are stored on a stack. Each entry on the
-** stack is either an integer, a null-terminated string, a floating point
-** number, or the SQL "NULL" value. An inplicit conversion from one
-** type to the other occurs as necessary.
-**
-** Most of the code in this file is taken up by the sqliteVdbeExec()
-** function which does the work of interpreting a VDBE program.
-** But other routines are also provided to help in building up
-** a program instruction by instruction.
-**
-** Various scripts scan this source file in order to generate HTML
-** documentation, headers files, or other derived files. The formatting
-** of the code in this file is, therefore, important. See other comments
-** in this file for details. If in doubt, do not deviate from existing
-** commenting and indentation practices when changing or adding code.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-#include "os.h"
-#include <ctype.h>
-#include "vdbeInt.h"
-
-/*
-** The following global variable is incremented every time a cursor
-** moves, either by the OP_MoveTo or the OP_Next opcode. The test
-** procedures use this information to make sure that indices are
-** working correctly. This variable has no function other than to
-** help verify the correct operation of the library.
-*/
-int sqlite_search_count = 0;
-
-/*
-** When this global variable is positive, it gets decremented once before
-** each instruction in the VDBE. When reaches zero, the SQLITE_Interrupt
-** of the db.flags field is set in order to simulate an interrupt.
-**
-** This facility is used for testing purposes only. It does not function
-** in an ordinary build.
-*/
-int sqlite_interrupt_count = 0;
-
-/*
-** Advance the virtual machine to the next output row.
-**
-** The return vale will be either SQLITE_BUSY, SQLITE_DONE,
-** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE.
-**
-** SQLITE_BUSY means that the virtual machine attempted to open
-** a locked database and there is no busy callback registered.
-** Call sqlite_step() again to retry the open. *pN is set to 0
-** and *pazColName and *pazValue are both set to NULL.
-**
-** SQLITE_DONE means that the virtual machine has finished
-** executing. sqlite_step() should not be called again on this
-** virtual machine. *pN and *pazColName are set appropriately
-** but *pazValue is set to NULL.
-**
-** SQLITE_ROW means that the virtual machine has generated another
-** row of the result set. *pN is set to the number of columns in
-** the row. *pazColName is set to the names of the columns followed
-** by the column datatypes. *pazValue is set to the values of each
-** column in the row. The value of the i-th column is (*pazValue)[i].
-** The name of the i-th column is (*pazColName)[i] and the datatype
-** of the i-th column is (*pazColName)[i+*pN].
-**
-** SQLITE_ERROR means that a run-time error (such as a constraint
-** violation) has occurred. The details of the error will be returned
-** by the next call to sqlite_finalize(). sqlite_step() should not
-** be called again on the VM.
-**
-** SQLITE_MISUSE means that the this routine was called inappropriately.
-** Perhaps it was called on a virtual machine that had already been
-** finalized or on one that had previously returned SQLITE_ERROR or
-** SQLITE_DONE. Or it could be the case the the same database connection
-** is being used simulataneously by two or more threads.
-*/
-int sqlite_step(
- sqlite_vm *pVm, /* The virtual machine to execute */
- int *pN, /* OUT: Number of columns in result */
- const char ***pazValue, /* OUT: Column data */
- const char ***pazColName /* OUT: Column names and datatypes */
-){
- Vdbe *p = (Vdbe*)pVm;
- sqlite *db;
- int rc;
-
- if( !p || p->magic!=VDBE_MAGIC_RUN ){
- return SQLITE_MISUSE;
- }
- db = p->db;
- if( sqliteSafetyOn(db) ){
- p->rc = SQLITE_MISUSE;
- return SQLITE_MISUSE;
- }
- if( p->explain ){
- rc = sqliteVdbeList(p);
- }else{
- rc = sqliteVdbeExec(p);
- }
- if( rc==SQLITE_DONE || rc==SQLITE_ROW ){
- if( pazColName ) *pazColName = (const char**)p->azColName;
- if( pN ) *pN = p->nResColumn;
- }else{
- if( pazColName) *pazColName = 0;
- if( pN ) *pN = 0;
- }
- if( pazValue ){
- if( rc==SQLITE_ROW ){
- *pazValue = (const char**)p->azResColumn;
- }else{
- *pazValue = 0;
- }
- }
- if( sqliteSafetyOff(db) ){
- return SQLITE_MISUSE;
- }
- return rc;
-}
-
-/*
-** Insert a new aggregate element and make it the element that
-** has focus.
-**
-** Return 0 on success and 1 if memory is exhausted.
-*/
-static int AggInsert(Agg *p, char *zKey, int nKey){
- AggElem *pElem, *pOld;
- int i;
- Mem *pMem;
- pElem = sqliteMalloc( sizeof(AggElem) + nKey +
- (p->nMem-1)*sizeof(pElem->aMem[0]) );
- if( pElem==0 ) return 1;
- pElem->zKey = (char*)&pElem->aMem[p->nMem];
- memcpy(pElem->zKey, zKey, nKey);
- pElem->nKey = nKey;
- pOld = sqliteHashInsert(&p->hash, pElem->zKey, pElem->nKey, pElem);
- if( pOld!=0 ){
- assert( pOld==pElem ); /* Malloc failed on insert */
- sqliteFree(pOld);
- return 0;
- }
- for(i=0, pMem=pElem->aMem; i<p->nMem; i++, pMem++){
- pMem->flags = MEM_Null;
- }
- p->pCurrent = pElem;
- return 0;
-}
-
-/*
-** Get the AggElem currently in focus
-*/
-#define AggInFocus(P) ((P).pCurrent ? (P).pCurrent : _AggInFocus(&(P)))
-static AggElem *_AggInFocus(Agg *p){
- HashElem *pElem = sqliteHashFirst(&p->hash);
- if( pElem==0 ){
- AggInsert(p,"",1);
- pElem = sqliteHashFirst(&p->hash);
- }
- return pElem ? sqliteHashData(pElem) : 0;
-}
-
-/*
-** Convert the given stack entity into a string if it isn't one
-** already.
-*/
-#define Stringify(P) if(((P)->flags & MEM_Str)==0){hardStringify(P);}
-static int hardStringify(Mem *pStack){
- int fg = pStack->flags;
- if( fg & MEM_Real ){
- sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%.15g",pStack->r);
- }else if( fg & MEM_Int ){
- sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%d",pStack->i);
- }else{
- pStack->zShort[0] = 0;
- }
- pStack->z = pStack->zShort;
- pStack->n = strlen(pStack->zShort)+1;
- pStack->flags = MEM_Str | MEM_Short;
- return 0;
-}
-
-/*
-** Convert the given stack entity into a string that has been obtained
-** from sqliteMalloc(). This is different from Stringify() above in that
-** Stringify() will use the NBFS bytes of static string space if the string
-** will fit but this routine always mallocs for space.
-** Return non-zero if we run out of memory.
-*/
-#define Dynamicify(P) (((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P):0)
-static int hardDynamicify(Mem *pStack){
- int fg = pStack->flags;
- char *z;
- if( (fg & MEM_Str)==0 ){
- hardStringify(pStack);
- }
- assert( (fg & MEM_Dyn)==0 );
- z = sqliteMallocRaw( pStack->n );
- if( z==0 ) return 1;
- memcpy(z, pStack->z, pStack->n);
- pStack->z = z;
- pStack->flags |= MEM_Dyn;
- return 0;
-}
-
-/*
-** An ephemeral string value (signified by the MEM_Ephem flag) contains
-** a pointer to a dynamically allocated string where some other entity
-** is responsible for deallocating that string. Because the stack entry
-** does not control the string, it might be deleted without the stack
-** entry knowing it.
-**
-** This routine converts an ephemeral string into a dynamically allocated
-** string that the stack entry itself controls. In other words, it
-** converts an MEM_Ephem string into an MEM_Dyn string.
-*/
-#define Deephemeralize(P) \
- if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
-static int hardDeephem(Mem *pStack){
- char *z;
- assert( (pStack->flags & MEM_Ephem)!=0 );
- z = sqliteMallocRaw( pStack->n );
- if( z==0 ) return 1;
- memcpy(z, pStack->z, pStack->n);
- pStack->z = z;
- pStack->flags &= ~MEM_Ephem;
- pStack->flags |= MEM_Dyn;
- return 0;
-}
-
-/*
-** Release the memory associated with the given stack level. This
-** leaves the Mem.flags field in an inconsistent state.
-*/
-#define Release(P) if((P)->flags&MEM_Dyn){ sqliteFree((P)->z); }
-
-/*
-** Pop the stack N times.
-*/
-static void popStack(Mem **ppTos, int N){
- Mem *pTos = *ppTos;
- while( N>0 ){
- N--;
- Release(pTos);
- pTos--;
- }
- *ppTos = pTos;
-}
-
-/*
-** Return TRUE if zNum is a 32-bit signed integer and write
-** the value of the integer into *pNum. If zNum is not an integer
-** or is an integer that is too large to be expressed with just 32
-** bits, then return false.
-**
-** Under Linux (RedHat 7.2) this routine is much faster than atoi()
-** for converting strings into integers.
-*/
-static int toInt(const char *zNum, int *pNum){
- int v = 0;
- int neg;
- int i, c;
- if( *zNum=='-' ){
- neg = 1;
- zNum++;
- }else if( *zNum=='+' ){
- neg = 0;
- zNum++;
- }else{
- neg = 0;
- }
- for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
- v = v*10 + c - '0';
- }
- *pNum = neg ? -v : v;
- return c==0 && i>0 && (i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0));
-}
-
-/*
-** Convert the given stack entity into a integer if it isn't one
-** already.
-**
-** Any prior string or real representation is invalidated.
-** NULLs are converted into 0.
-*/
-#define Integerify(P) if(((P)->flags&MEM_Int)==0){ hardIntegerify(P); }
-static void hardIntegerify(Mem *pStack){
- if( pStack->flags & MEM_Real ){
- pStack->i = (int)pStack->r;
- Release(pStack);
- }else if( pStack->flags & MEM_Str ){
- toInt(pStack->z, &pStack->i);
- Release(pStack);
- }else{
- pStack->i = 0;
- }
- pStack->flags = MEM_Int;
-}
-
-/*
-** Get a valid Real representation for the given stack element.
-**
-** Any prior string or integer representation is retained.
-** NULLs are converted into 0.0.
-*/
-#define Realify(P) if(((P)->flags&MEM_Real)==0){ hardRealify(P); }
-static void hardRealify(Mem *pStack){
- if( pStack->flags & MEM_Str ){
- pStack->r = sqliteAtoF(pStack->z, 0);
- }else if( pStack->flags & MEM_Int ){
- pStack->r = pStack->i;
- }else{
- pStack->r = 0.0;
- }
- pStack->flags |= MEM_Real;
-}
-
-/*
-** The parameters are pointers to the head of two sorted lists
-** of Sorter structures. Merge these two lists together and return
-** a single sorted list. This routine forms the core of the merge-sort
-** algorithm.
-**
-** In the case of a tie, left sorts in front of right.
-*/
-static Sorter *Merge(Sorter *pLeft, Sorter *pRight){
- Sorter sHead;
- Sorter *pTail;
- pTail = &sHead;
- pTail->pNext = 0;
- while( pLeft && pRight ){
- int c = sqliteSortCompare(pLeft->zKey, pRight->zKey);
- if( c<=0 ){
- pTail->pNext = pLeft;
- pLeft = pLeft->pNext;
- }else{
- pTail->pNext = pRight;
- pRight = pRight->pNext;
- }
- pTail = pTail->pNext;
- }
- if( pLeft ){
- pTail->pNext = pLeft;
- }else if( pRight ){
- pTail->pNext = pRight;
- }
- return sHead.pNext;
-}
-
-/*
-** The following routine works like a replacement for the standard
-** library routine fgets(). The difference is in how end-of-line (EOL)
-** is handled. Standard fgets() uses LF for EOL under unix, CRLF
-** under windows, and CR under mac. This routine accepts any of these
-** character sequences as an EOL mark. The EOL mark is replaced by
-** a single LF character in zBuf.
-*/
-static char *vdbe_fgets(char *zBuf, int nBuf, FILE *in){
- int i, c;
- for(i=0; i<nBuf-1 && (c=getc(in))!=EOF; i++){
- zBuf[i] = c;
- if( c=='\r' || c=='\n' ){
- if( c=='\r' ){
- zBuf[i] = '\n';
- c = getc(in);
- if( c!=EOF && c!='\n' ) ungetc(c, in);
- }
- i++;
- break;
- }
- }
- zBuf[i] = 0;
- return i>0 ? zBuf : 0;
-}
-
-/*
-** Make sure there is space in the Vdbe structure to hold at least
-** mxCursor cursors. If there is not currently enough space, then
-** allocate more.
-**
-** If a memory allocation error occurs, return 1. Return 0 if
-** everything works.
-*/
-static int expandCursorArraySize(Vdbe *p, int mxCursor){
- if( mxCursor>=p->nCursor ){
- Cursor *aCsr = sqliteRealloc( p->aCsr, (mxCursor+1)*sizeof(Cursor) );
- if( aCsr==0 ) return 1;
- p->aCsr = aCsr;
- memset(&p->aCsr[p->nCursor], 0, sizeof(Cursor)*(mxCursor+1-p->nCursor));
- p->nCursor = mxCursor+1;
- }
- return 0;
-}
-
-#ifdef VDBE_PROFILE
-/*
-** The following routine only works on pentium-class processors.
-** It uses the RDTSC opcode to read cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-__inline__ unsigned long long int hwtime(void){
- unsigned long long int x;
- __asm__("rdtsc\n\t"
- "mov %%edx, %%ecx\n\t"
- :"=A" (x));
- return x;
-}
-#endif
-
-/*
-** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
-** sqlite_interrupt() routine has been called. If it has been, then
-** processing of the VDBE program is interrupted.
-**
-** This macro added to every instruction that does a jump in order to
-** implement a loop. This test used to be on every single instruction,
-** but that meant we more testing that we needed. By only testing the
-** flag on jump instructions, we get a (small) speed improvement.
-*/
-#define CHECK_FOR_INTERRUPT \
- if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt;
-
-
-/*
-** Execute as much of a VDBE program as we can then return.
-**
-** sqliteVdbeMakeReady() must be called before this routine in order to
-** close the program with a final OP_Halt and to set up the callbacks
-** and the error message pointer.
-**
-** Whenever a row or result data is available, this routine will either
-** invoke the result callback (if there is one) or return with
-** SQLITE_ROW.
-**
-** If an attempt is made to open a locked database, then this routine
-** will either invoke the busy callback (if there is one) or it will
-** return SQLITE_BUSY.
-**
-** If an error occurs, an error message is written to memory obtained
-** from sqliteMalloc() and p->zErrMsg is made to point to that memory.
-** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
-**
-** If the callback ever returns non-zero, then the program exits
-** immediately. There will be no error message but the p->rc field is
-** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
-**
-** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this
-** routine to return SQLITE_ERROR.
-**
-** Other fatal errors return SQLITE_ERROR.
-**
-** After this routine has finished, sqliteVdbeFinalize() should be
-** used to clean up the mess that was left behind.
-*/
-int sqliteVdbeExec(
- Vdbe *p /* The VDBE */
-){
- int pc; /* The program counter */
- Op *pOp; /* Current operation */
- int rc = SQLITE_OK; /* Value to return */
- sqlite *db = p->db; /* The database */
- Mem *pTos; /* Top entry in the operand stack */
- char zBuf[100]; /* Space to sprintf() an integer */
-#ifdef VDBE_PROFILE
- unsigned long long start; /* CPU clock count at start of opcode */
- int origPc; /* Program counter at start of opcode */
-#endif
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- int nProgressOps = 0; /* Opcodes executed since progress callback. */
-#endif
-
- if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
- assert( db->magic==SQLITE_MAGIC_BUSY );
- assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
- p->rc = SQLITE_OK;
- assert( p->explain==0 );
- if( sqlite_malloc_failed ) goto no_mem;
- pTos = p->pTos;
- if( p->popStack ){
- popStack(&pTos, p->popStack);
- p->popStack = 0;
- }
- CHECK_FOR_INTERRUPT;
- for(pc=p->pc; rc==SQLITE_OK; pc++){
- assert( pc>=0 && pc<p->nOp );
- assert( pTos<=&p->aStack[pc] );
-#ifdef VDBE_PROFILE
- origPc = pc;
- start = hwtime();
-#endif
- pOp = &p->aOp[pc];
-
- /* Only allow tracing if NDEBUG is not defined.
- */
-#ifndef NDEBUG
- if( p->trace ){
- sqliteVdbePrintOp(p->trace, pc, pOp);
- }
-#endif
-
- /* Check to see if we need to simulate an interrupt. This only happens
- ** if we have a special test build.
- */
-#ifdef SQLITE_TEST
- if( sqlite_interrupt_count>0 ){
- sqlite_interrupt_count--;
- if( sqlite_interrupt_count==0 ){
- sqlite_interrupt(db);
- }
- }
-#endif
-
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- /* Call the progress callback if it is configured and the required number
- ** of VDBE ops have been executed (either since this invocation of
- ** sqliteVdbeExec() or since last time the progress callback was called).
- ** If the progress callback returns non-zero, exit the virtual machine with
- ** a return code SQLITE_ABORT.
- */
- if( db->xProgress ){
- if( db->nProgressOps==nProgressOps ){
- if( db->xProgress(db->pProgressArg)!=0 ){
- rc = SQLITE_ABORT;
- continue; /* skip to the next iteration of the for loop */
- }
- nProgressOps = 0;
- }
- nProgressOps++;
- }
-#endif
-
- switch( pOp->opcode ){
-
-/*****************************************************************************
-** What follows is a massive switch statement where each case implements a
-** separate instruction in the virtual machine. If we follow the usual
-** indentation conventions, each case should be indented by 6 spaces. But
-** that is a lot of wasted space on the left margin. So the code within
-** the switch statement will break with convention and be flush-left. Another
-** big comment (similar to this one) will mark the point in the code where
-** we transition back to normal indentation.
-**
-** The formatting of each case is important. The makefile for SQLite
-** generates two C files "opcodes.h" and "opcodes.c" by scanning this
-** file looking for lines that begin with "case OP_". The opcodes.h files
-** will be filled with #defines that give unique integer values to each
-** opcode and the opcodes.c file is filled with an array of strings where
-** each string is the symbolic name for the corresponding opcode.
-**
-** Documentation about VDBE opcodes is generated by scanning this file
-** for lines of that contain "Opcode:". That line and all subsequent
-** comment lines are used in the generation of the opcode.html documentation
-** file.
-**
-** SUMMARY:
-**
-** Formatting is important to scripts that scan this file.
-** Do not deviate from the formatting style currently in use.
-**
-*****************************************************************************/
-
-/* Opcode: Goto * P2 *
-**
-** An unconditional jump to address P2.
-** The next instruction executed will be
-** the one at index P2 from the beginning of
-** the program.
-*/
-case OP_Goto: {
- CHECK_FOR_INTERRUPT;
- pc = pOp->p2 - 1;
- break;
-}
-
-/* Opcode: Gosub * P2 *
-**
-** Push the current address plus 1 onto the return address stack
-** and then jump to address P2.
-**
-** The return address stack is of limited depth. If too many
-** OP_Gosub operations occur without intervening OP_Returns, then
-** the return address stack will fill up and processing will abort
-** with a fatal error.
-*/
-case OP_Gosub: {
- if( p->returnDepth>=sizeof(p->returnStack)/sizeof(p->returnStack[0]) ){
- sqliteSetString(&p->zErrMsg, "return address stack overflow", (char*)0);
- p->rc = SQLITE_INTERNAL;
- return SQLITE_ERROR;
- }
- p->returnStack[p->returnDepth++] = pc+1;
- pc = pOp->p2 - 1;
- break;
-}
-
-/* Opcode: Return * * *
-**
-** Jump immediately to the next instruction after the last unreturned
-** OP_Gosub. If an OP_Return has occurred for all OP_Gosubs, then
-** processing aborts with a fatal error.
-*/
-case OP_Return: {
- if( p->returnDepth<=0 ){
- sqliteSetString(&p->zErrMsg, "return address stack underflow", (char*)0);
- p->rc = SQLITE_INTERNAL;
- return SQLITE_ERROR;
- }
- p->returnDepth--;
- pc = p->returnStack[p->returnDepth] - 1;
- break;
-}
-
-/* Opcode: Halt P1 P2 *
-**
-** Exit immediately. All open cursors, Lists, Sorts, etc are closed
-** automatically.
-**
-** P1 is the result code returned by sqlite_exec(). For a normal
-** halt, this should be SQLITE_OK (0). For errors, it can be some
-** other value. If P1!=0 then P2 will determine whether or not to
-** rollback the current transaction. Do not rollback if P2==OE_Fail.
-** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back
-** out all changes that have occurred during this execution of the
-** VDBE, but do not rollback the transaction.
-**
-** There is an implied "Halt 0 0 0" instruction inserted at the very end of
-** every program. So a jump past the last instruction of the program
-** is the same as executing Halt.
-*/
-case OP_Halt: {
- p->magic = VDBE_MAGIC_HALT;
- p->pTos = pTos;
- if( pOp->p1!=SQLITE_OK ){
- p->rc = pOp->p1;
- p->errorAction = pOp->p2;
- if( pOp->p3 ){
- sqliteSetString(&p->zErrMsg, pOp->p3, (char*)0);
- }
- return SQLITE_ERROR;
- }else{
- p->rc = SQLITE_OK;
- return SQLITE_DONE;
- }
-}
-
-/* Opcode: Integer P1 * P3
-**
-** The integer value P1 is pushed onto the stack. If P3 is not zero
-** then it is assumed to be a string representation of the same integer.
-*/
-case OP_Integer: {
- pTos++;
- pTos->i = pOp->p1;
- pTos->flags = MEM_Int;
- if( pOp->p3 ){
- pTos->z = pOp->p3;
- pTos->flags |= MEM_Str | MEM_Static;
- pTos->n = strlen(pOp->p3)+1;
- }
- break;
-}
-
-/* Opcode: String * * P3
-**
-** The string value P3 is pushed onto the stack. If P3==0 then a
-** NULL is pushed onto the stack.
-*/
-case OP_String: {
- char *z = pOp->p3;
- pTos++;
- if( z==0 ){
- pTos->flags = MEM_Null;
- }else{
- pTos->z = z;
- pTos->n = strlen(z) + 1;
- pTos->flags = MEM_Str | MEM_Static;
- }
- break;
-}
-
-/* Opcode: Variable P1 * *
-**
-** Push the value of variable P1 onto the stack. A variable is
-** an unknown in the original SQL string as handed to sqlite_compile().
-** Any occurance of the '?' character in the original SQL is considered
-** a variable. Variables in the SQL string are number from left to
-** right beginning with 1. The values of variables are set using the
-** sqlite_bind() API.
-*/
-case OP_Variable: {
- int j = pOp->p1 - 1;
- pTos++;
- if( j>=0 && j<p->nVar && p->azVar[j]!=0 ){
- pTos->z = p->azVar[j];
- pTos->n = p->anVar[j];
- pTos->flags = MEM_Str | MEM_Static;
- }else{
- pTos->flags = MEM_Null;
- }
- break;
-}
-
-/* Opcode: Pop P1 * *
-**
-** P1 elements are popped off of the top of stack and discarded.
-*/
-case OP_Pop: {
- assert( pOp->p1>=0 );
- popStack(&pTos, pOp->p1);
- assert( pTos>=&p->aStack[-1] );
- break;
-}
-
-/* Opcode: Dup P1 P2 *
-**
-** A copy of the P1-th element of the stack
-** is made and pushed onto the top of the stack.
-** The top of the stack is element 0. So the
-** instruction "Dup 0 0 0" will make a copy of the
-** top of the stack.
-**
-** If the content of the P1-th element is a dynamically
-** allocated string, then a new copy of that string
-** is made if P2==0. If P2!=0, then just a pointer
-** to the string is copied.
-**
-** Also see the Pull instruction.
-*/
-case OP_Dup: {
- Mem *pFrom = &pTos[-pOp->p1];
- assert( pFrom<=pTos && pFrom>=p->aStack );
- pTos++;
- memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
- if( pTos->flags & MEM_Str ){
- if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
- pTos->flags &= ~MEM_Dyn;
- pTos->flags |= MEM_Ephem;
- }else if( pTos->flags & MEM_Short ){
- memcpy(pTos->zShort, pFrom->zShort, pTos->n);
- pTos->z = pTos->zShort;
- }else if( (pTos->flags & MEM_Static)==0 ){
- pTos->z = sqliteMallocRaw(pFrom->n);
- if( sqlite_malloc_failed ) goto no_mem;
- memcpy(pTos->z, pFrom->z, pFrom->n);
- pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
- pTos->flags |= MEM_Dyn;
- }
- }
- break;
-}
-
-/* Opcode: Pull P1 * *
-**
-** The P1-th element is removed from its current location on
-** the stack and pushed back on top of the stack. The
-** top of the stack is element 0, so "Pull 0 0 0" is
-** a no-op. "Pull 1 0 0" swaps the top two elements of
-** the stack.
-**
-** See also the Dup instruction.
-*/
-case OP_Pull: {
- Mem *pFrom = &pTos[-pOp->p1];
- int i;
- Mem ts;
-
- ts = *pFrom;
- Deephemeralize(pTos);
- for(i=0; i<pOp->p1; i++, pFrom++){
- Deephemeralize(&pFrom[1]);
- *pFrom = pFrom[1];
- assert( (pFrom->flags & MEM_Ephem)==0 );
- if( pFrom->flags & MEM_Short ){
- assert( pFrom->flags & MEM_Str );
- assert( pFrom->z==pFrom[1].zShort );
- pFrom->z = pFrom->zShort;
- }
- }
- *pTos = ts;
- if( pTos->flags & MEM_Short ){
- assert( pTos->flags & MEM_Str );
- assert( pTos->z==pTos[-pOp->p1].zShort );
- pTos->z = pTos->zShort;
- }
- break;
-}
-
-/* Opcode: Push P1 * *
-**
-** Overwrite the value of the P1-th element down on the
-** stack (P1==0 is the top of the stack) with the value
-** of the top of the stack. Then pop the top of the stack.
-*/
-case OP_Push: {
- Mem *pTo = &pTos[-pOp->p1];
-
- assert( pTo>=p->aStack );
- Deephemeralize(pTos);
- Release(pTo);
- *pTo = *pTos;
- if( pTo->flags & MEM_Short ){
- assert( pTo->z==pTos->zShort );
- pTo->z = pTo->zShort;
- }
- pTos--;
- break;
-}
-
-
-/* Opcode: ColumnName P1 P2 P3
-**
-** P3 becomes the P1-th column name (first is 0). An array of pointers
-** to all column names is passed as the 4th parameter to the callback.
-** If P2==1 then this is the last column in the result set and thus the
-** number of columns in the result set will be P1. There must be at least
-** one OP_ColumnName with a P2==1 before invoking OP_Callback and the
-** number of columns specified in OP_Callback must one more than the P1
-** value of the OP_ColumnName that has P2==1.
-*/
-case OP_ColumnName: {
- assert( pOp->p1>=0 && pOp->p1<p->nOp );
- p->azColName[pOp->p1] = pOp->p3;
- p->nCallback = 0;
- if( pOp->p2 ) p->nResColumn = pOp->p1+1;
- break;
-}
-
-/* Opcode: Callback P1 * *
-**
-** Pop P1 values off the stack and form them into an array. Then
-** invoke the callback function using the newly formed array as the
-** 3rd parameter.
-*/
-case OP_Callback: {
- int i;
- char **azArgv = p->zArgv;
- Mem *pCol;
-
- pCol = &pTos[1-pOp->p1];
- assert( pCol>=p->aStack );
- for(i=0; i<pOp->p1; i++, pCol++){
- if( pCol->flags & MEM_Null ){
- azArgv[i] = 0;
- }else{
- Stringify(pCol);
- azArgv[i] = pCol->z;
- }
- }
- azArgv[i] = 0;
- p->nCallback++;
- p->azResColumn = azArgv;
- assert( p->nResColumn==pOp->p1 );
- p->popStack = pOp->p1;
- p->pc = pc + 1;
- p->pTos = pTos;
- return SQLITE_ROW;
-}
-
-/* Opcode: Concat P1 P2 P3
-**
-** Look at the first P1 elements of the stack. Append them all
-** together with the lowest element first. Use P3 as a separator.
-** Put the result on the top of the stack. The original P1 elements
-** are popped from the stack if P2==0 and retained if P2==1. If
-** any element of the stack is NULL, then the result is NULL.
-**
-** If P3 is NULL, then use no separator. When P1==1, this routine
-** makes a copy of the top stack element into memory obtained
-** from sqliteMalloc().
-*/
-case OP_Concat: {
- char *zNew;
- int nByte;
- int nField;
- int i, j;
- char *zSep;
- int nSep;
- Mem *pTerm;
-
- nField = pOp->p1;
- zSep = pOp->p3;
- if( zSep==0 ) zSep = "";
- nSep = strlen(zSep);
- assert( &pTos[1-nField] >= p->aStack );
- nByte = 1 - nSep;
- pTerm = &pTos[1-nField];
- for(i=0; i<nField; i++, pTerm++){
- if( pTerm->flags & MEM_Null ){
- nByte = -1;
- break;
- }else{
- Stringify(pTerm);
- nByte += pTerm->n - 1 + nSep;
- }
- }
- if( nByte<0 ){
- if( pOp->p2==0 ){
- popStack(&pTos, nField);
- }
- pTos++;
- pTos->flags = MEM_Null;
- break;
- }
- zNew = sqliteMallocRaw( nByte );
- if( zNew==0 ) goto no_mem;
- j = 0;
- pTerm = &pTos[1-nField];
- for(i=j=0; i<nField; i++, pTerm++){
- assert( pTerm->flags & MEM_Str );
- memcpy(&zNew[j], pTerm->z, pTerm->n-1);
- j += pTerm->n-1;
- if( nSep>0 && i<nField-1 ){
- memcpy(&zNew[j], zSep, nSep);
- j += nSep;
- }
- }
- zNew[j] = 0;
- if( pOp->p2==0 ){
- popStack(&pTos, nField);
- }
- pTos++;
- pTos->n = nByte;
- pTos->flags = MEM_Str|MEM_Dyn;
- pTos->z = zNew;
- break;
-}
-
-/* Opcode: Add * * *
-**
-** Pop the top two elements from the stack, add them together,
-** and push the result back onto the stack. If either element
-** is a string then it is converted to a double using the atof()
-** function before the addition.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: Multiply * * *
-**
-** Pop the top two elements from the stack, multiply them together,
-** and push the result back onto the stack. If either element
-** is a string then it is converted to a double using the atof()
-** function before the multiplication.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: Subtract * * *
-**
-** Pop the top two elements from the stack, subtract the
-** first (what was on top of the stack) from the second (the
-** next on stack)
-** and push the result back onto the stack. If either element
-** is a string then it is converted to a double using the atof()
-** function before the subtraction.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: Divide * * *
-**
-** Pop the top two elements from the stack, divide the
-** first (what was on top of the stack) from the second (the
-** next on stack)
-** and push the result back onto the stack. If either element
-** is a string then it is converted to a double using the atof()
-** function before the division. Division by zero returns NULL.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: Remainder * * *
-**
-** Pop the top two elements from the stack, divide the
-** first (what was on top of the stack) from the second (the
-** next on stack)
-** and push the remainder after division onto the stack. If either element
-** is a string then it is converted to a double using the atof()
-** function before the division. Division by zero returns NULL.
-** If either operand is NULL, the result is NULL.
-*/
-case OP_Add:
-case OP_Subtract:
-case OP_Multiply:
-case OP_Divide:
-case OP_Remainder: {
- Mem *pNos = &pTos[-1];
- assert( pNos>=p->aStack );
- if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
- Release(pTos);
- pTos--;
- Release(pTos);
- pTos->flags = MEM_Null;
- }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){
- int a, b;
- a = pTos->i;
- b = pNos->i;
- switch( pOp->opcode ){
- case OP_Add: b += a; break;
- case OP_Subtract: b -= a; break;
- case OP_Multiply: b *= a; break;
- case OP_Divide: {
- if( a==0 ) goto divide_by_zero;
- b /= a;
- break;
- }
- default: {
- if( a==0 ) goto divide_by_zero;
- b %= a;
- break;
- }
- }
- Release(pTos);
- pTos--;
- Release(pTos);
- pTos->i = b;
- pTos->flags = MEM_Int;
- }else{
- double a, b;
- Realify(pTos);
- Realify(pNos);
- a = pTos->r;
- b = pNos->r;
- switch( pOp->opcode ){
- case OP_Add: b += a; break;
- case OP_Subtract: b -= a; break;
- case OP_Multiply: b *= a; break;
- case OP_Divide: {
- if( a==0.0 ) goto divide_by_zero;
- b /= a;
- break;
- }
- default: {
- int ia = (int)a;
- int ib = (int)b;
- if( ia==0.0 ) goto divide_by_zero;
- b = ib % ia;
- break;
- }
- }
- Release(pTos);
- pTos--;
- Release(pTos);
- pTos->r = b;
- pTos->flags = MEM_Real;
- }
- break;
-
-divide_by_zero:
- Release(pTos);
- pTos--;
- Release(pTos);
- pTos->flags = MEM_Null;
- break;
-}
-
-/* Opcode: Function P1 * P3
-**
-** Invoke a user function (P3 is a pointer to a Function structure that
-** defines the function) with P1 string arguments taken from the stack.
-** Pop all arguments from the stack and push back the result.
-**
-** See also: AggFunc
-*/
-case OP_Function: {
- int n, i;
- Mem *pArg;
- char **azArgv;
- sqlite_func ctx;
-
- n = pOp->p1;
- pArg = &pTos[1-n];
- azArgv = p->zArgv;
- for(i=0; i<n; i++, pArg++){
- if( pArg->flags & MEM_Null ){
- azArgv[i] = 0;
- }else{
- Stringify(pArg);
- azArgv[i] = pArg->z;
- }
- }
- ctx.pFunc = (FuncDef*)pOp->p3;
- ctx.s.flags = MEM_Null;
- ctx.s.z = 0;
- ctx.isError = 0;
- ctx.isStep = 0;
- if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- (*ctx.pFunc->xFunc)(&ctx, n, (const char**)azArgv);
- if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- popStack(&pTos, n);
- pTos++;
- *pTos = ctx.s;
- if( pTos->flags & MEM_Short ){
- pTos->z = pTos->zShort;
- }
- if( ctx.isError ){
- sqliteSetString(&p->zErrMsg,
- (pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0);
- rc = SQLITE_ERROR;
- }
- break;
-}
-
-/* Opcode: BitAnd * * *
-**
-** Pop the top two elements from the stack. Convert both elements
-** to integers. Push back onto the stack the bit-wise AND of the
-** two elements.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: BitOr * * *
-**
-** Pop the top two elements from the stack. Convert both elements
-** to integers. Push back onto the stack the bit-wise OR of the
-** two elements.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: ShiftLeft * * *
-**
-** Pop the top two elements from the stack. Convert both elements
-** to integers. Push back onto the stack the top element shifted
-** left by N bits where N is the second element on the stack.
-** If either operand is NULL, the result is NULL.
-*/
-/* Opcode: ShiftRight * * *
-**
-** Pop the top two elements from the stack. Convert both elements
-** to integers. Push back onto the stack the top element shifted
-** right by N bits where N is the second element on the stack.
-** If either operand is NULL, the result is NULL.
-*/
-case OP_BitAnd:
-case OP_BitOr:
-case OP_ShiftLeft:
-case OP_ShiftRight: {
- Mem *pNos = &pTos[-1];
- int a, b;
-
- assert( pNos>=p->aStack );
- if( (pTos->flags | pNos->flags) & MEM_Null ){
- popStack(&pTos, 2);
- pTos++;
- pTos->flags = MEM_Null;
- break;
- }
- Integerify(pTos);
- Integerify(pNos);
- a = pTos->i;
- b = pNos->i;
- switch( pOp->opcode ){
- case OP_BitAnd: a &= b; break;
- case OP_BitOr: a |= b; break;
- case OP_ShiftLeft: a <<= b; break;
- case OP_ShiftRight: a >>= b; break;
- default: /* CANT HAPPEN */ break;
- }
- assert( (pTos->flags & MEM_Dyn)==0 );
- assert( (pNos->flags & MEM_Dyn)==0 );
- pTos--;
- Release(pTos);
- pTos->i = a;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: AddImm P1 * *
-**
-** Add the value P1 to whatever is on top of the stack. The result
-** is always an integer.
-**
-** To force the top of the stack to be an integer, just add 0.
-*/
-case OP_AddImm: {
- assert( pTos>=p->aStack );
- Integerify(pTos);
- pTos->i += pOp->p1;
- break;
-}
-
-/* Opcode: ForceInt P1 P2 *
-**
-** Convert the top of the stack into an integer. If the current top of
-** the stack is not numeric (meaning that is is a NULL or a string that
-** does not look like an integer or floating point number) then pop the
-** stack and jump to P2. If the top of the stack is numeric then
-** convert it into the least integer that is greater than or equal to its
-** current value if P1==0, or to the least integer that is strictly
-** greater than its current value if P1==1.
-*/
-case OP_ForceInt: {
- int v;
- assert( pTos>=p->aStack );
- if( (pTos->flags & (MEM_Int|MEM_Real))==0
- && ((pTos->flags & MEM_Str)==0 || sqliteIsNumber(pTos->z)==0) ){
- Release(pTos);
- pTos--;
- pc = pOp->p2 - 1;
- break;
- }
- if( pTos->flags & MEM_Int ){
- v = pTos->i + (pOp->p1!=0);
- }else{
- Realify(pTos);
- v = (int)pTos->r;
- if( pTos->r>(double)v ) v++;
- if( pOp->p1 && pTos->r==(double)v ) v++;
- }
- Release(pTos);
- pTos->i = v;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: MustBeInt P1 P2 *
-**
-** Force the top of the stack to be an integer. If the top of the
-** stack is not an integer and cannot be converted into an integer
-** with out data loss, then jump immediately to P2, or if P2==0
-** raise an SQLITE_MISMATCH exception.
-**
-** If the top of the stack is not an integer and P2 is not zero and
-** P1 is 1, then the stack is popped. In all other cases, the depth
-** of the stack is unchanged.
-*/
-case OP_MustBeInt: {
- assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Int ){
- /* Do nothing */
- }else if( pTos->flags & MEM_Real ){
- int i = (int)pTos->r;
- double r = (double)i;
- if( r!=pTos->r ){
- goto mismatch;
- }
- pTos->i = i;
- }else if( pTos->flags & MEM_Str ){
- int v;
- if( !toInt(pTos->z, &v) ){
- double r;
- if( !sqliteIsNumber(pTos->z) ){
- goto mismatch;
- }
- Realify(pTos);
- v = (int)pTos->r;
- r = (double)v;
- if( r!=pTos->r ){
- goto mismatch;
- }
- }
- pTos->i = v;
- }else{
- goto mismatch;
- }
- Release(pTos);
- pTos->flags = MEM_Int;
- break;
-
-mismatch:
- if( pOp->p2==0 ){
- rc = SQLITE_MISMATCH;
- goto abort_due_to_error;
- }else{
- if( pOp->p1 ) popStack(&pTos, 1);
- pc = pOp->p2 - 1;
- }
- break;
-}
-
-/* Opcode: Eq P1 P2 *
-**
-** Pop the top two elements from the stack. If they are equal, then
-** jump to instruction P2. Otherwise, continue to the next instruction.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** If both values are numeric, they are converted to doubles using atof()
-** and compared for equality that way. Otherwise the strcmp() library
-** routine is used for the comparison. For a pure text comparison
-** use OP_StrEq.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: Ne P1 P2 *
-**
-** Pop the top two elements from the stack. If they are not equal, then
-** jump to instruction P2. Otherwise, continue to the next instruction.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** If both values are numeric, they are converted to doubles using atof()
-** and compared in that format. Otherwise the strcmp() library
-** routine is used for the comparison. For a pure text comparison
-** use OP_StrNe.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: Lt P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the
-** next on stack) is less than the first (the top of stack), then
-** jump to instruction P2. Otherwise, continue to the next instruction.
-** In other words, jump if NOS<TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** If both values are numeric, they are converted to doubles using atof()
-** and compared in that format. Numeric values are always less than
-** non-numeric values. If both operands are non-numeric, the strcmp() library
-** routine is used for the comparison. For a pure text comparison
-** use OP_StrLt.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: Le P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the
-** next on stack) is less than or equal to the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS<=TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** If both values are numeric, they are converted to doubles using atof()
-** and compared in that format. Numeric values are always less than
-** non-numeric values. If both operands are non-numeric, the strcmp() library
-** routine is used for the comparison. For a pure text comparison
-** use OP_StrLe.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: Gt P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the
-** next on stack) is greater than the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS>TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** If both values are numeric, they are converted to doubles using atof()
-** and compared in that format. Numeric values are always less than
-** non-numeric values. If both operands are non-numeric, the strcmp() library
-** routine is used for the comparison. For a pure text comparison
-** use OP_StrGt.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: Ge P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the next
-** on stack) is greater than or equal to the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS>=TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** If both values are numeric, they are converted to doubles using atof()
-** and compared in that format. Numeric values are always less than
-** non-numeric values. If both operands are non-numeric, the strcmp() library
-** routine is used for the comparison. For a pure text comparison
-** use OP_StrGe.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-case OP_Eq:
-case OP_Ne:
-case OP_Lt:
-case OP_Le:
-case OP_Gt:
-case OP_Ge: {
- Mem *pNos = &pTos[-1];
- int c, v;
- int ft, fn;
- assert( pNos>=p->aStack );
- ft = pTos->flags;
- fn = pNos->flags;
- if( (ft | fn) & MEM_Null ){
- popStack(&pTos, 2);
- if( pOp->p2 ){
- if( pOp->p1 ) pc = pOp->p2-1;
- }else{
- pTos++;
- pTos->flags = MEM_Null;
- }
- break;
- }else if( (ft & fn & MEM_Int)==MEM_Int ){
- c = pNos->i - pTos->i;
- }else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(pNos->z,&v) ){
- c = v - pTos->i;
- }else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(pTos->z,&v) ){
- c = pNos->i - v;
- }else{
- Stringify(pTos);
- Stringify(pNos);
- c = sqliteCompare(pNos->z, pTos->z);
- }
- switch( pOp->opcode ){
- case OP_Eq: c = c==0; break;
- case OP_Ne: c = c!=0; break;
- case OP_Lt: c = c<0; break;
- case OP_Le: c = c<=0; break;
- case OP_Gt: c = c>0; break;
- default: c = c>=0; break;
- }
- popStack(&pTos, 2);
- if( pOp->p2 ){
- if( c ) pc = pOp->p2-1;
- }else{
- pTos++;
- pTos->i = c;
- pTos->flags = MEM_Int;
- }
- break;
-}
-/* INSERT NO CODE HERE!
-**
-** The opcode numbers are extracted from this source file by doing
-**
-** grep '^case OP_' vdbe.c | ... >opcodes.h
-**
-** The opcodes are numbered in the order that they appear in this file.
-** But in order for the expression generating code to work right, the
-** string comparison operators that follow must be numbered exactly 6
-** greater than the numeric comparison opcodes above. So no other
-** cases can appear between the two.
-*/
-/* Opcode: StrEq P1 P2 *
-**
-** Pop the top two elements from the stack. If they are equal, then
-** jump to instruction P2. Otherwise, continue to the next instruction.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** The strcmp() library routine is used for the comparison. For a
-** numeric comparison, use OP_Eq.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: StrNe P1 P2 *
-**
-** Pop the top two elements from the stack. If they are not equal, then
-** jump to instruction P2. Otherwise, continue to the next instruction.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** The strcmp() library routine is used for the comparison. For a
-** numeric comparison, use OP_Ne.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: StrLt P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the
-** next on stack) is less than the first (the top of stack), then
-** jump to instruction P2. Otherwise, continue to the next instruction.
-** In other words, jump if NOS<TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** The strcmp() library routine is used for the comparison. For a
-** numeric comparison, use OP_Lt.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: StrLe P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the
-** next on stack) is less than or equal to the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS<=TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** The strcmp() library routine is used for the comparison. For a
-** numeric comparison, use OP_Le.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: StrGt P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the
-** next on stack) is greater than the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS>TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** The strcmp() library routine is used for the comparison. For a
-** numeric comparison, use OP_Gt.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-/* Opcode: StrGe P1 P2 *
-**
-** Pop the top two elements from the stack. If second element (the next
-** on stack) is greater than or equal to the first (the top of stack),
-** then jump to instruction P2. In other words, jump if NOS>=TOS.
-**
-** If either operand is NULL (and thus if the result is unknown) then
-** take the jump if P1 is true.
-**
-** The strcmp() library routine is used for the comparison. For a
-** numeric comparison, use OP_Ge.
-**
-** If P2 is zero, do not jump. Instead, push an integer 1 onto the
-** stack if the jump would have been taken, or a 0 if not. Push a
-** NULL if either operand was NULL.
-*/
-case OP_StrEq:
-case OP_StrNe:
-case OP_StrLt:
-case OP_StrLe:
-case OP_StrGt:
-case OP_StrGe: {
- Mem *pNos = &pTos[-1];
- int c;
- assert( pNos>=p->aStack );
- if( (pNos->flags | pTos->flags) & MEM_Null ){
- popStack(&pTos, 2);
- if( pOp->p2 ){
- if( pOp->p1 ) pc = pOp->p2-1;
- }else{
- pTos++;
- pTos->flags = MEM_Null;
- }
- break;
- }else{
- Stringify(pTos);
- Stringify(pNos);
- c = strcmp(pNos->z, pTos->z);
- }
- /* The asserts on each case of the following switch are there to verify
- ** that string comparison opcodes are always exactly 6 greater than the
- ** corresponding numeric comparison opcodes. The code generator depends
- ** on this fact.
- */
- switch( pOp->opcode ){
- case OP_StrEq: c = c==0; assert( pOp->opcode-6==OP_Eq ); break;
- case OP_StrNe: c = c!=0; assert( pOp->opcode-6==OP_Ne ); break;
- case OP_StrLt: c = c<0; assert( pOp->opcode-6==OP_Lt ); break;
- case OP_StrLe: c = c<=0; assert( pOp->opcode-6==OP_Le ); break;
- case OP_StrGt: c = c>0; assert( pOp->opcode-6==OP_Gt ); break;
- default: c = c>=0; assert( pOp->opcode-6==OP_Ge ); break;
- }
- popStack(&pTos, 2);
- if( pOp->p2 ){
- if( c ) pc = pOp->p2-1;
- }else{
- pTos++;
- pTos->flags = MEM_Int;
- pTos->i = c;
- }
- break;
-}
-
-/* Opcode: And * * *
-**
-** Pop two values off the stack. Take the logical AND of the
-** two values and push the resulting boolean value back onto the
-** stack.
-*/
-/* Opcode: Or * * *
-**
-** Pop two values off the stack. Take the logical OR of the
-** two values and push the resulting boolean value back onto the
-** stack.
-*/
-case OP_And:
-case OP_Or: {
- Mem *pNos = &pTos[-1];
- int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
-
- assert( pNos>=p->aStack );
- if( pTos->flags & MEM_Null ){
- v1 = 2;
- }else{
- Integerify(pTos);
- v1 = pTos->i==0;
- }
- if( pNos->flags & MEM_Null ){
- v2 = 2;
- }else{
- Integerify(pNos);
- v2 = pNos->i==0;
- }
- if( pOp->opcode==OP_And ){
- static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
- v1 = and_logic[v1*3+v2];
- }else{
- static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
- v1 = or_logic[v1*3+v2];
- }
- popStack(&pTos, 2);
- pTos++;
- if( v1==2 ){
- pTos->flags = MEM_Null;
- }else{
- pTos->i = v1==0;
- pTos->flags = MEM_Int;
- }
- break;
-}
-
-/* Opcode: Negative * * *
-**
-** Treat the top of the stack as a numeric quantity. Replace it
-** with its additive inverse. If the top of the stack is NULL
-** its value is unchanged.
-*/
-/* Opcode: AbsValue * * *
-**
-** Treat the top of the stack as a numeric quantity. Replace it
-** with its absolute value. If the top of the stack is NULL
-** its value is unchanged.
-*/
-case OP_Negative:
-case OP_AbsValue: {
- assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Real ){
- Release(pTos);
- if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
- pTos->r = -pTos->r;
- }
- pTos->flags = MEM_Real;
- }else if( pTos->flags & MEM_Int ){
- Release(pTos);
- if( pOp->opcode==OP_Negative || pTos->i<0 ){
- pTos->i = -pTos->i;
- }
- pTos->flags = MEM_Int;
- }else if( pTos->flags & MEM_Null ){
- /* Do nothing */
- }else{
- Realify(pTos);
- Release(pTos);
- if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
- pTos->r = -pTos->r;
- }
- pTos->flags = MEM_Real;
- }
- break;
-}
-
-/* Opcode: Not * * *
-**
-** Interpret the top of the stack as a boolean value. Replace it
-** with its complement. If the top of the stack is NULL its value
-** is unchanged.
-*/
-case OP_Not: {
- assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
- Integerify(pTos);
- Release(pTos);
- pTos->i = !pTos->i;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: BitNot * * *
-**
-** Interpret the top of the stack as an value. Replace it
-** with its ones-complement. If the top of the stack is NULL its
-** value is unchanged.
-*/
-case OP_BitNot: {
- assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
- Integerify(pTos);
- Release(pTos);
- pTos->i = ~pTos->i;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: Noop * * *
-**
-** Do nothing. This instruction is often useful as a jump
-** destination.
-*/
-case OP_Noop: {
- break;
-}
-
-/* Opcode: If P1 P2 *
-**
-** Pop a single boolean from the stack. If the boolean popped is
-** true, then jump to p2. Otherwise continue to the next instruction.
-** An integer is false if zero and true otherwise. A string is
-** false if it has zero length and true otherwise.
-**
-** If the value popped of the stack is NULL, then take the jump if P1
-** is true and fall through if P1 is false.
-*/
-/* Opcode: IfNot P1 P2 *
-**
-** Pop a single boolean from the stack. If the boolean popped is
-** false, then jump to p2. Otherwise continue to the next instruction.
-** An integer is false if zero and true otherwise. A string is
-** false if it has zero length and true otherwise.
-**
-** If the value popped of the stack is NULL, then take the jump if P1
-** is true and fall through if P1 is false.
-*/
-case OP_If:
-case OP_IfNot: {
- int c;
- assert( pTos>=p->aStack );
- if( pTos->flags & MEM_Null ){
- c = pOp->p1;
- }else{
- Integerify(pTos);
- c = pTos->i;
- if( pOp->opcode==OP_IfNot ) c = !c;
- }
- assert( (pTos->flags & MEM_Dyn)==0 );
- pTos--;
- if( c ) pc = pOp->p2-1;
- break;
-}
-
-/* Opcode: IsNull P1 P2 *
-**
-** If any of the top abs(P1) values on the stack are NULL, then jump
-** to P2. Pop the stack P1 times if P1>0. If P1<0 leave the stack
-** unchanged.
-*/
-case OP_IsNull: {
- int i, cnt;
- Mem *pTerm;
- cnt = pOp->p1;
- if( cnt<0 ) cnt = -cnt;
- pTerm = &pTos[1-cnt];
- assert( pTerm>=p->aStack );
- for(i=0; i<cnt; i++, pTerm++){
- if( pTerm->flags & MEM_Null ){
- pc = pOp->p2-1;
- break;
- }
- }
- if( pOp->p1>0 ) popStack(&pTos, cnt);
- break;
-}
-
-/* Opcode: NotNull P1 P2 *
-**
-** Jump to P2 if the top P1 values on the stack are all not NULL. Pop the
-** stack if P1 times if P1 is greater than zero. If P1 is less than
-** zero then leave the stack unchanged.
-*/
-case OP_NotNull: {
- int i, cnt;
- cnt = pOp->p1;
- if( cnt<0 ) cnt = -cnt;
- assert( &pTos[1-cnt] >= p->aStack );
- for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
- if( i>=cnt ) pc = pOp->p2-1;
- if( pOp->p1>0 ) popStack(&pTos, cnt);
- break;
-}
-
-/* Opcode: MakeRecord P1 P2 *
-**
-** Convert the top P1 entries of the stack into a single entry
-** suitable for use as a data record in a database table. The
-** details of the format are irrelavant as long as the OP_Column
-** opcode can decode the record later. Refer to source code
-** comments for the details of the record format.
-**
-** If P2 is true (non-zero) and one or more of the P1 entries
-** that go into building the record is NULL, then add some extra
-** bytes to the record to make it distinct for other entries created
-** during the same run of the VDBE. The extra bytes added are a
-** counter that is reset with each run of the VDBE, so records
-** created this way will not necessarily be distinct across runs.
-** But they should be distinct for transient tables (created using
-** OP_OpenTemp) which is what they are intended for.
-**
-** (Later:) The P2==1 option was intended to make NULLs distinct
-** for the UNION operator. But I have since discovered that NULLs
-** are indistinct for UNION. So this option is never used.
-*/
-case OP_MakeRecord: {
- char *zNewRecord;
- int nByte;
- int nField;
- int i, j;
- int idxWidth;
- u32 addr;
- Mem *pRec;
- int addUnique = 0; /* True to cause bytes to be added to make the
- ** generated record distinct */
- char zTemp[NBFS]; /* Temp space for small records */
-
- /* Assuming the record contains N fields, the record format looks
- ** like this:
- **
- ** -------------------------------------------------------------------
- ** | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) |
- ** -------------------------------------------------------------------
- **
- ** All data fields are converted to strings before being stored and
- ** are stored with their null terminators. NULL entries omit the
- ** null terminator. Thus an empty string uses 1 byte and a NULL uses
- ** zero bytes. Data(0) is taken from the lowest element of the stack
- ** and data(N-1) is the top of the stack.
- **
- ** Each of the idx() entries is either 1, 2, or 3 bytes depending on
- ** how big the total record is. Idx(0) contains the offset to the start
- ** of data(0). Idx(k) contains the offset to the start of data(k).
- ** Idx(N) contains the total number of bytes in the record.
- */
- nField = pOp->p1;
- pRec = &pTos[1-nField];
- assert( pRec>=p->aStack );
- nByte = 0;
- for(i=0; i<nField; i++, pRec++){
- if( pRec->flags & MEM_Null ){
- addUnique = pOp->p2;
- }else{
- Stringify(pRec);
- nByte += pRec->n;
- }
- }
- if( addUnique ) nByte += sizeof(p->uniqueCnt);
- if( nByte + nField + 1 < 256 ){
- idxWidth = 1;
- }else if( nByte + 2*nField + 2 < 65536 ){
- idxWidth = 2;
- }else{
- idxWidth = 3;
- }
- nByte += idxWidth*(nField + 1);
- if( nByte>MAX_BYTES_PER_ROW ){
- rc = SQLITE_TOOBIG;
- goto abort_due_to_error;
- }
- if( nByte<=NBFS ){
- zNewRecord = zTemp;
- }else{
- zNewRecord = sqliteMallocRaw( nByte );
- if( zNewRecord==0 ) goto no_mem;
- }
- j = 0;
- addr = idxWidth*(nField+1) + addUnique*sizeof(p->uniqueCnt);
- for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){
- zNewRecord[j++] = addr & 0xff;
- if( idxWidth>1 ){
- zNewRecord[j++] = (addr>>8)&0xff;
- if( idxWidth>2 ){
- zNewRecord[j++] = (addr>>16)&0xff;
- }
- }
- if( (pRec->flags & MEM_Null)==0 ){
- addr += pRec->n;
- }
- }
- zNewRecord[j++] = addr & 0xff;
- if( idxWidth>1 ){
- zNewRecord[j++] = (addr>>8)&0xff;
- if( idxWidth>2 ){
- zNewRecord[j++] = (addr>>16)&0xff;
- }
- }
- if( addUnique ){
- memcpy(&zNewRecord[j], &p->uniqueCnt, sizeof(p->uniqueCnt));
- p->uniqueCnt++;
- j += sizeof(p->uniqueCnt);
- }
- for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){
- if( (pRec->flags & MEM_Null)==0 ){
- memcpy(&zNewRecord[j], pRec->z, pRec->n);
- j += pRec->n;
- }
- }
- popStack(&pTos, nField);
- pTos++;
- pTos->n = nByte;
- if( nByte<=NBFS ){
- assert( zNewRecord==zTemp );
- memcpy(pTos->zShort, zTemp, nByte);
- pTos->z = pTos->zShort;
- pTos->flags = MEM_Str | MEM_Short;
- }else{
- assert( zNewRecord!=zTemp );
- pTos->z = zNewRecord;
- pTos->flags = MEM_Str | MEM_Dyn;
- }
- break;
-}
-
-/* Opcode: MakeKey P1 P2 P3
-**
-** Convert the top P1 entries of the stack into a single entry suitable
-** for use as the key in an index. The top P1 records are
-** converted to strings and merged. The null-terminators
-** are retained and used as separators.
-** The lowest entry in the stack is the first field and the top of the
-** stack becomes the last.
-**
-** If P2 is not zero, then the original entries remain on the stack
-** and the new key is pushed on top. If P2 is zero, the original
-** data is popped off the stack first then the new key is pushed
-** back in its place.
-**
-** P3 is a string that is P1 characters long. Each character is either
-** an 'n' or a 't' to indicates if the argument should be intepreted as
-** numeric or text type. The first character of P3 corresponds to the
-** lowest element on the stack. If P3 is NULL then all arguments are
-** assumed to be of the numeric type.
-**
-** The type makes a difference in that text-type fields may not be
-** introduced by 'b' (as described in the next paragraph). The
-** first character of a text-type field must be either 'a' (if it is NULL)
-** or 'c'. Numeric fields will be introduced by 'b' if their content
-** looks like a well-formed number. Otherwise the 'a' or 'c' will be
-** used.
-**
-** The key is a concatenation of fields. Each field is terminated by
-** a single 0x00 character. A NULL field is introduced by an 'a' and
-** is followed immediately by its 0x00 terminator. A numeric field is
-** introduced by a single character 'b' and is followed by a sequence
-** of characters that represent the number such that a comparison of
-** the character string using memcpy() sorts the numbers in numerical
-** order. The character strings for numbers are generated using the
-** sqliteRealToSortable() function. A text field is introduced by a
-** 'c' character and is followed by the exact text of the field. The
-** use of an 'a', 'b', or 'c' character at the beginning of each field
-** guarantees that NULLs sort before numbers and that numbers sort
-** before text. 0x00 characters do not occur except as separators
-** between fields.
-**
-** See also: MakeIdxKey, SortMakeKey
-*/
-/* Opcode: MakeIdxKey P1 P2 P3
-**
-** Convert the top P1 entries of the stack into a single entry suitable
-** for use as the key in an index. In addition, take one additional integer
-** off of the stack, treat that integer as a four-byte record number, and
-** append the four bytes to the key. Thus a total of P1+1 entries are
-** popped from the stack for this instruction and a single entry is pushed
-** back. The first P1 entries that are popped are strings and the last
-** entry (the lowest on the stack) is an integer record number.
-**
-** The converstion of the first P1 string entries occurs just like in
-** MakeKey. Each entry is separated from the others by a null.
-** The entire concatenation is null-terminated. The lowest entry
-** in the stack is the first field and the top of the stack becomes the
-** last.
-**
-** If P2 is not zero and one or more of the P1 entries that go into the
-** generated key is NULL, then jump to P2 after the new key has been
-** pushed on the stack. In other words, jump to P2 if the key is
-** guaranteed to be unique. This jump can be used to skip a subsequent
-** uniqueness test.
-**
-** P3 is a string that is P1 characters long. Each character is either
-** an 'n' or a 't' to indicates if the argument should be numeric or
-** text. The first character corresponds to the lowest element on the
-** stack. If P3 is null then all arguments are assumed to be numeric.
-**
-** See also: MakeKey, SortMakeKey
-*/
-case OP_MakeIdxKey:
-case OP_MakeKey: {
- char *zNewKey;
- int nByte;
- int nField;
- int addRowid;
- int i, j;
- int containsNull = 0;
- Mem *pRec;
- char zTemp[NBFS];
-
- addRowid = pOp->opcode==OP_MakeIdxKey;
- nField = pOp->p1;
- pRec = &pTos[1-nField];
- assert( pRec>=p->aStack );
- nByte = 0;
- for(j=0, i=0; i<nField; i++, j++, pRec++){
- int flags = pRec->flags;
- int len;
- char *z;
- if( flags & MEM_Null ){
- nByte += 2;
- containsNull = 1;
- }else if( pOp->p3 && pOp->p3[j]=='t' ){
- Stringify(pRec);
- pRec->flags &= ~(MEM_Int|MEM_Real);
- nByte += pRec->n+1;
- }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(pRec->z) ){
- if( (flags & (MEM_Real|MEM_Int))==MEM_Int ){
- pRec->r = pRec->i;
- }else if( (flags & (MEM_Real|MEM_Int))==0 ){
- pRec->r = sqliteAtoF(pRec->z, 0);
- }
- Release(pRec);
- z = pRec->zShort;
- sqliteRealToSortable(pRec->r, z);
- len = strlen(z);
- pRec->z = 0;
- pRec->flags = MEM_Real;
- pRec->n = len+1;
- nByte += pRec->n+1;
- }else{
- nByte += pRec->n+1;
- }
- }
- if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){
- rc = SQLITE_TOOBIG;
- goto abort_due_to_error;
- }
- if( addRowid ) nByte += sizeof(u32);
- if( nByte<=NBFS ){
- zNewKey = zTemp;
- }else{
- zNewKey = sqliteMallocRaw( nByte );
- if( zNewKey==0 ) goto no_mem;
- }
- j = 0;
- pRec = &pTos[1-nField];
- for(i=0; i<nField; i++, pRec++){
- if( pRec->flags & MEM_Null ){
- zNewKey[j++] = 'a';
- zNewKey[j++] = 0;
- }else if( pRec->flags==MEM_Real ){
- zNewKey[j++] = 'b';
- memcpy(&zNewKey[j], pRec->zShort, pRec->n);
- j += pRec->n;
- }else{
- assert( pRec->flags & MEM_Str );
- zNewKey[j++] = 'c';
- memcpy(&zNewKey[j], pRec->z, pRec->n);
- j += pRec->n;
- }
- }
- if( addRowid ){
- u32 iKey;
- pRec = &pTos[-nField];
- assert( pRec>=p->aStack );
- Integerify(pRec);
- iKey = intToKey(pRec->i);
- memcpy(&zNewKey[j], &iKey, sizeof(u32));
- popStack(&pTos, nField+1);
- if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;
- }else{
- if( pOp->p2==0 ) popStack(&pTos, nField);
- }
- pTos++;
- pTos->n = nByte;
- if( nByte<=NBFS ){
- assert( zNewKey==zTemp );
- pTos->z = pTos->zShort;
- memcpy(pTos->zShort, zTemp, nByte);
- pTos->flags = MEM_Str | MEM_Short;
- }else{
- pTos->z = zNewKey;
- pTos->flags = MEM_Str | MEM_Dyn;
- }
- break;
-}
-
-/* Opcode: IncrKey * * *
-**
-** The top of the stack should contain an index key generated by
-** The MakeKey opcode. This routine increases the least significant
-** byte of that key by one. This is used so that the MoveTo opcode
-** will move to the first entry greater than the key rather than to
-** the key itself.
-*/
-case OP_IncrKey: {
- assert( pTos>=p->aStack );
- /* The IncrKey opcode is only applied to keys generated by
- ** MakeKey or MakeIdxKey and the results of those operands
- ** are always dynamic strings or zShort[] strings. So we
- ** are always free to modify the string in place.
- */
- assert( pTos->flags & (MEM_Dyn|MEM_Short) );
- pTos->z[pTos->n-1]++;
- break;
-}
-
-/* Opcode: Checkpoint P1 * *
-**
-** Begin a checkpoint. A checkpoint is the beginning of a operation that
-** is part of a larger transaction but which might need to be rolled back
-** itself without effecting the containing transaction. A checkpoint will
-** be automatically committed or rollback when the VDBE halts.
-**
-** The checkpoint is begun on the database file with index P1. The main
-** database file has an index of 0 and the file used for temporary tables
-** has an index of 1.
-*/
-case OP_Checkpoint: {
- int i = pOp->p1;
- if( i>=0 && i<db->nDb && db->aDb[i].pBt && db->aDb[i].inTrans==1 ){
- rc = sqliteBtreeBeginCkpt(db->aDb[i].pBt);
- if( rc==SQLITE_OK ) db->aDb[i].inTrans = 2;
- }
- break;
-}
-
-/* Opcode: Transaction P1 * *
-**
-** Begin a transaction. The transaction ends when a Commit or Rollback
-** opcode is encountered. Depending on the ON CONFLICT setting, the
-** transaction might also be rolled back if an error is encountered.
-**
-** P1 is the index of the database file on which the transaction is
-** started. Index 0 is the main database file and index 1 is the
-** file used for temporary tables.
-**
-** A write lock is obtained on the database file when a transaction is
-** started. No other process can read or write the file while the
-** transaction is underway. Starting a transaction also creates a
-** rollback journal. A transaction must be started before any changes
-** can be made to the database.
-*/
-case OP_Transaction: {
- int busy = 1;
- int i = pOp->p1;
- assert( i>=0 && i<db->nDb );
- if( db->aDb[i].inTrans ) break;
- while( db->aDb[i].pBt!=0 && busy ){
- rc = sqliteBtreeBeginTrans(db->aDb[i].pBt);
- switch( rc ){
- case SQLITE_BUSY: {
- if( db->xBusyCallback==0 ){
- p->pc = pc;
- p->undoTransOnError = 1;
- p->rc = SQLITE_BUSY;
- p->pTos = pTos;
- return SQLITE_BUSY;
- }else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){
- sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
- busy = 0;
- }
- break;
- }
- case SQLITE_READONLY: {
- rc = SQLITE_OK;
- /* Fall thru into the next case */
- }
- case SQLITE_OK: {
- p->inTempTrans = 0;
- busy = 0;
- break;
- }
- default: {
- goto abort_due_to_error;
- }
- }
- }
- db->aDb[i].inTrans = 1;
- p->undoTransOnError = 1;
- break;
-}
-
-/* Opcode: Commit * * *
-**
-** Cause all modifications to the database that have been made since the
-** last Transaction to actually take effect. No additional modifications
-** are allowed until another transaction is started. The Commit instruction
-** deletes the journal file and releases the write lock on the database.
-** A read lock continues to be held if there are still cursors open.
-*/
-case OP_Commit: {
- int i;
- if( db->xCommitCallback!=0 ){
- if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- if( db->xCommitCallback(db->pCommitArg)!=0 ){
- rc = SQLITE_CONSTRAINT;
- }
- if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- }
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- if( db->aDb[i].inTrans ){
- rc = sqliteBtreeCommit(db->aDb[i].pBt);
- db->aDb[i].inTrans = 0;
- }
- }
- if( rc==SQLITE_OK ){
- sqliteCommitInternalChanges(db);
- }else{
- sqliteRollbackAll(db);
- }
- break;
-}
-
-/* Opcode: Rollback P1 * *
-**
-** Cause all modifications to the database that have been made since the
-** last Transaction to be undone. The database is restored to its state
-** before the Transaction opcode was executed. No additional modifications
-** are allowed until another transaction is started.
-**
-** P1 is the index of the database file that is committed. An index of 0
-** is used for the main database and an index of 1 is used for the file used
-** to hold temporary tables.
-**
-** This instruction automatically closes all cursors and releases both
-** the read and write locks on the indicated database.
-*/
-case OP_Rollback: {
- sqliteRollbackAll(db);
- break;
-}
-
-/* Opcode: ReadCookie P1 P2 *
-**
-** Read cookie number P2 from database P1 and push it onto the stack.
-** P2==0 is the schema version. P2==1 is the database format.
-** P2==2 is the recommended pager cache size, and so forth. P1==0 is
-** the main database file and P1==1 is the database file used to store
-** temporary tables.
-**
-** There must be a read-lock on the database (either a transaction
-** must be started or there must be an open cursor) before
-** executing this instruction.
-*/
-case OP_ReadCookie: {
- int aMeta[SQLITE_N_BTREE_META];
- assert( pOp->p2<SQLITE_N_BTREE_META );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( db->aDb[pOp->p1].pBt!=0 );
- rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
- pTos++;
- pTos->i = aMeta[1+pOp->p2];
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: SetCookie P1 P2 *
-**
-** Write the top of the stack into cookie number P2 of database P1.
-** P2==0 is the schema version. P2==1 is the database format.
-** P2==2 is the recommended pager cache size, and so forth. P1==0 is
-** the main database file and P1==1 is the database file used to store
-** temporary tables.
-**
-** A transaction must be started before executing this opcode.
-*/
-case OP_SetCookie: {
- int aMeta[SQLITE_N_BTREE_META];
- assert( pOp->p2<SQLITE_N_BTREE_META );
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( db->aDb[pOp->p1].pBt!=0 );
- assert( pTos>=p->aStack );
- Integerify(pTos)
- rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
- if( rc==SQLITE_OK ){
- aMeta[1+pOp->p2] = pTos->i;
- rc = sqliteBtreeUpdateMeta(db->aDb[pOp->p1].pBt, aMeta);
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: VerifyCookie P1 P2 *
-**
-** Check the value of global database parameter number 0 (the
-** schema version) and make sure it is equal to P2.
-** P1 is the database number which is 0 for the main database file
-** and 1 for the file holding temporary tables and some higher number
-** for auxiliary databases.
-**
-** The cookie changes its value whenever the database schema changes.
-** This operation is used to detect when that the cookie has changed
-** and that the current process needs to reread the schema.
-**
-** Either a transaction needs to have been started or an OP_Open needs
-** to be executed (to establish a read lock) before this opcode is
-** invoked.
-*/
-case OP_VerifyCookie: {
- int aMeta[SQLITE_N_BTREE_META];
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
- if( rc==SQLITE_OK && aMeta[1]!=pOp->p2 ){
- sqliteSetString(&p->zErrMsg, "database schema has changed", (char*)0);
- rc = SQLITE_SCHEMA;
- }
- break;
-}
-
-/* Opcode: OpenRead P1 P2 P3
-**
-** Open a read-only cursor for the database table whose root page is
-** P2 in a database file. The database file is determined by an
-** integer from the top of the stack. 0 means the main database and
-** 1 means the database used for temporary tables. Give the new
-** cursor an identifier of P1. The P1 values need not be contiguous
-** but all P1 values should be small integers. It is an error for
-** P1 to be negative.
-**
-** If P2==0 then take the root page number from the next of the stack.
-**
-** There will be a read lock on the database whenever there is an
-** open cursor. If the database was unlocked prior to this instruction
-** then a read lock is acquired as part of this instruction. A read
-** lock allows other processes to read the database but prohibits
-** any other process from modifying the database. The read lock is
-** released when all cursors are closed. If this instruction attempts
-** to get a read lock but fails, the script terminates with an
-** SQLITE_BUSY error code.
-**
-** The P3 value is the name of the table or index being opened.
-** The P3 value is not actually used by this opcode and may be
-** omitted. But the code generator usually inserts the index or
-** table name into P3 to make the code easier to read.
-**
-** See also OpenWrite.
-*/
-/* Opcode: OpenWrite P1 P2 P3
-**
-** Open a read/write cursor named P1 on the table or index whose root
-** page is P2. If P2==0 then take the root page number from the stack.
-**
-** The P3 value is the name of the table or index being opened.
-** The P3 value is not actually used by this opcode and may be
-** omitted. But the code generator usually inserts the index or
-** table name into P3 to make the code easier to read.
-**
-** This instruction works just like OpenRead except that it opens the cursor
-** in read/write mode. For a given table, there can be one or more read-only
-** cursors or a single read/write cursor but not both.
-**
-** See also OpenRead.
-*/
-case OP_OpenRead:
-case OP_OpenWrite: {
- int busy = 0;
- int i = pOp->p1;
- int p2 = pOp->p2;
- int wrFlag;
- Btree *pX;
- int iDb;
-
- assert( pTos>=p->aStack );
- Integerify(pTos);
- iDb = pTos->i;
- pTos--;
- assert( iDb>=0 && iDb<db->nDb );
- pX = db->aDb[iDb].pBt;
- assert( pX!=0 );
- wrFlag = pOp->opcode==OP_OpenWrite;
- if( p2<=0 ){
- assert( pTos>=p->aStack );
- Integerify(pTos);
- p2 = pTos->i;
- pTos--;
- if( p2<2 ){
- sqliteSetString(&p->zErrMsg, "root page number less than 2", (char*)0);
- rc = SQLITE_INTERNAL;
- break;
- }
- }
- assert( i>=0 );
- if( expandCursorArraySize(p, i) ) goto no_mem;
- sqliteVdbeCleanupCursor(&p->aCsr[i]);
- memset(&p->aCsr[i], 0, sizeof(Cursor));
- p->aCsr[i].nullRow = 1;
- if( pX==0 ) break;
- do{
- rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
- switch( rc ){
- case SQLITE_BUSY: {
- if( db->xBusyCallback==0 ){
- p->pc = pc;
- p->rc = SQLITE_BUSY;
- p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
- return SQLITE_BUSY;
- }else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){
- sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
- busy = 0;
- }
- break;
- }
- case SQLITE_OK: {
- busy = 0;
- break;
- }
- default: {
- goto abort_due_to_error;
- }
- }
- }while( busy );
- break;
-}
-
-/* Opcode: OpenTemp P1 P2 *
-**
-** Open a new cursor to a transient table.
-** The transient cursor is always opened read/write even if
-** the main database is read-only. The transient table is deleted
-** automatically when the cursor is closed.
-**
-** The cursor points to a BTree table if P2==0 and to a BTree index
-** if P2==1. A BTree table must have an integer key and can have arbitrary
-** data. A BTree index has no data but can have an arbitrary key.
-**
-** This opcode is used for tables that exist for the duration of a single
-** SQL statement only. Tables created using CREATE TEMPORARY TABLE
-** are opened using OP_OpenRead or OP_OpenWrite. "Temporary" in the
-** context of this opcode means for the duration of a single SQL statement
-** whereas "Temporary" in the context of CREATE TABLE means for the duration
-** of the connection to the database. Same word; different meanings.
-*/
-case OP_OpenTemp: {
- int i = pOp->p1;
- Cursor *pCx;
- assert( i>=0 );
- if( expandCursorArraySize(p, i) ) goto no_mem;
- pCx = &p->aCsr[i];
- sqliteVdbeCleanupCursor(pCx);
- memset(pCx, 0, sizeof(*pCx));
- pCx->nullRow = 1;
- rc = sqliteBtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt);
-
- if( rc==SQLITE_OK ){
- rc = sqliteBtreeBeginTrans(pCx->pBt);
- }
- if( rc==SQLITE_OK ){
- if( pOp->p2 ){
- int pgno;
- rc = sqliteBtreeCreateIndex(pCx->pBt, &pgno);
- if( rc==SQLITE_OK ){
- rc = sqliteBtreeCursor(pCx->pBt, pgno, 1, &pCx->pCursor);
- }
- }else{
- rc = sqliteBtreeCursor(pCx->pBt, 2, 1, &pCx->pCursor);
- }
- }
- break;
-}
-
-/* Opcode: OpenPseudo P1 * *
-**
-** Open a new cursor that points to a fake table that contains a single
-** row of data. Any attempt to write a second row of data causes the
-** first row to be deleted. All data is deleted when the cursor is
-** closed.
-**
-** A pseudo-table created by this opcode is useful for holding the
-** NEW or OLD tables in a trigger.
-*/
-case OP_OpenPseudo: {
- int i = pOp->p1;
- Cursor *pCx;
- assert( i>=0 );
- if( expandCursorArraySize(p, i) ) goto no_mem;
- pCx = &p->aCsr[i];
- sqliteVdbeCleanupCursor(pCx);
- memset(pCx, 0, sizeof(*pCx));
- pCx->nullRow = 1;
- pCx->pseudoTable = 1;
- break;
-}
-
-/* Opcode: Close P1 * *
-**
-** Close a cursor previously opened as P1. If P1 is not
-** currently open, this instruction is a no-op.
-*/
-case OP_Close: {
- int i = pOp->p1;
- if( i>=0 && i<p->nCursor ){
- sqliteVdbeCleanupCursor(&p->aCsr[i]);
- }
- break;
-}
-
-/* Opcode: MoveTo P1 P2 *
-**
-** Pop the top of the stack and use its value as a key. Reposition
-** cursor P1 so that it points to an entry with a matching key. If
-** the table contains no record with a matching key, then the cursor
-** is left pointing at the first record that is greater than the key.
-** If there are no records greater than the key and P2 is not zero,
-** then an immediate jump to P2 is made.
-**
-** See also: Found, NotFound, Distinct, MoveLt
-*/
-/* Opcode: MoveLt P1 P2 *
-**
-** Pop the top of the stack and use its value as a key. Reposition
-** cursor P1 so that it points to the entry with the largest key that is
-** less than the key popped from the stack.
-** If there are no records less than than the key and P2
-** is not zero then an immediate jump to P2 is made.
-**
-** See also: MoveTo
-*/
-case OP_MoveLt:
-case OP_MoveTo: {
- int i = pOp->p1;
- Cursor *pC;
-
- assert( pTos>=p->aStack );
- assert( i>=0 && i<p->nCursor );
- pC = &p->aCsr[i];
- if( pC->pCursor!=0 ){
- int res, oc;
- pC->nullRow = 0;
- if( pTos->flags & MEM_Int ){
- int iKey = intToKey(pTos->i);
- if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
- pC->movetoTarget = iKey;
- pC->deferredMoveto = 1;
- Release(pTos);
- pTos--;
- break;
- }
- sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
- pC->lastRecno = pTos->i;
- pC->recnoIsValid = res==0;
- }else{
- Stringify(pTos);
- sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
- pC->recnoIsValid = 0;
- }
- pC->deferredMoveto = 0;
- sqlite_search_count++;
- oc = pOp->opcode;
- if( oc==OP_MoveTo && res<0 ){
- sqliteBtreeNext(pC->pCursor, &res);
- pC->recnoIsValid = 0;
- if( res && pOp->p2>0 ){
- pc = pOp->p2 - 1;
- }
- }else if( oc==OP_MoveLt ){
- if( res>=0 ){
- sqliteBtreePrevious(pC->pCursor, &res);
- pC->recnoIsValid = 0;
- }else{
- /* res might be negative because the table is empty. Check to
- ** see if this is the case.
- */
- int keysize;
- res = sqliteBtreeKeySize(pC->pCursor,&keysize)!=0 || keysize==0;
- }
- if( res && pOp->p2>0 ){
- pc = pOp->p2 - 1;
- }
- }
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: Distinct P1 P2 *
-**
-** Use the top of the stack as a string key. If a record with that key does
-** not exist in the table of cursor P1, then jump to P2. If the record
-** does already exist, then fall thru. The cursor is left pointing
-** at the record if it exists. The key is not popped from the stack.
-**
-** This operation is similar to NotFound except that this operation
-** does not pop the key from the stack.
-**
-** See also: Found, NotFound, MoveTo, IsUnique, NotExists
-*/
-/* Opcode: Found P1 P2 *
-**
-** Use the top of the stack as a string key. If a record with that key
-** does exist in table of P1, then jump to P2. If the record
-** does not exist, then fall thru. The cursor is left pointing
-** to the record if it exists. The key is popped from the stack.
-**
-** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
-*/
-/* Opcode: NotFound P1 P2 *
-**
-** Use the top of the stack as a string key. If a record with that key
-** does not exist in table of P1, then jump to P2. If the record
-** does exist, then fall thru. The cursor is left pointing to the
-** record if it exists. The key is popped from the stack.
-**
-** The difference between this operation and Distinct is that
-** Distinct does not pop the key from the stack.
-**
-** See also: Distinct, Found, MoveTo, NotExists, IsUnique
-*/
-case OP_Distinct:
-case OP_NotFound:
-case OP_Found: {
- int i = pOp->p1;
- int alreadyExists = 0;
- Cursor *pC;
- assert( pTos>=p->aStack );
- assert( i>=0 && i<p->nCursor );
- if( (pC = &p->aCsr[i])->pCursor!=0 ){
- int res, rx;
- Stringify(pTos);
- rx = sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
- alreadyExists = rx==SQLITE_OK && res==0;
- pC->deferredMoveto = 0;
- }
- if( pOp->opcode==OP_Found ){
- if( alreadyExists ) pc = pOp->p2 - 1;
- }else{
- if( !alreadyExists ) pc = pOp->p2 - 1;
- }
- if( pOp->opcode!=OP_Distinct ){
- Release(pTos);
- pTos--;
- }
- break;
-}
-
-/* Opcode: IsUnique P1 P2 *
-**
-** The top of the stack is an integer record number. Call this
-** record number R. The next on the stack is an index key created
-** using MakeIdxKey. Call it K. This instruction pops R from the
-** stack but it leaves K unchanged.
-**
-** P1 is an index. So all but the last four bytes of K are an
-** index string. The last four bytes of K are a record number.
-**
-** This instruction asks if there is an entry in P1 where the
-** index string matches K but the record number is different
-** from R. If there is no such entry, then there is an immediate
-** jump to P2. If any entry does exist where the index string
-** matches K but the record number is not R, then the record
-** number for that entry is pushed onto the stack and control
-** falls through to the next instruction.
-**
-** See also: Distinct, NotFound, NotExists, Found
-*/
-case OP_IsUnique: {
- int i = pOp->p1;
- Mem *pNos = &pTos[-1];
- BtCursor *pCrsr;
- int R;
-
- /* Pop the value R off the top of the stack
- */
- assert( pNos>=p->aStack );
- Integerify(pTos);
- R = pTos->i;
- pTos--;
- assert( i>=0 && i<=p->nCursor );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int res, rc;
- int v; /* The record number on the P1 entry that matches K */
- char *zKey; /* The value of K */
- int nKey; /* Number of bytes in K */
-
- /* Make sure K is a string and make zKey point to K
- */
- Stringify(pNos);
- zKey = pNos->z;
- nKey = pNos->n;
- assert( nKey >= 4 );
-
- /* Search for an entry in P1 where all but the last four bytes match K.
- ** If there is no such entry, jump immediately to P2.
- */
- assert( p->aCsr[i].deferredMoveto==0 );
- rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- if( res<0 ){
- rc = sqliteBtreeNext(pCrsr, &res);
- if( res ){
- pc = pOp->p2 - 1;
- break;
- }
- }
- rc = sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- if( res>0 ){
- pc = pOp->p2 - 1;
- break;
- }
-
- /* At this point, pCrsr is pointing to an entry in P1 where all but
- ** the last for bytes of the key match K. Check to see if the last
- ** four bytes of the key are different from R. If the last four
- ** bytes equal R then jump immediately to P2.
- */
- sqliteBtreeKey(pCrsr, nKey - 4, 4, (char*)&v);
- v = keyToInt(v);
- if( v==R ){
- pc = pOp->p2 - 1;
- break;
- }
-
- /* The last four bytes of the key are different from R. Convert the
- ** last four bytes of the key into an integer and push it onto the
- ** stack. (These bytes are the record number of an entry that
- ** violates a UNIQUE constraint.)
- */
- pTos++;
- pTos->i = v;
- pTos->flags = MEM_Int;
- }
- break;
-}
-
-/* Opcode: NotExists P1 P2 *
-**
-** Use the top of the stack as a integer key. If a record with that key
-** does not exist in table of P1, then jump to P2. If the record
-** does exist, then fall thru. The cursor is left pointing to the
-** record if it exists. The integer key is popped from the stack.
-**
-** The difference between this operation and NotFound is that this
-** operation assumes the key is an integer and NotFound assumes it
-** is a string.
-**
-** See also: Distinct, Found, MoveTo, NotFound, IsUnique
-*/
-case OP_NotExists: {
- int i = pOp->p1;
- BtCursor *pCrsr;
- assert( pTos>=p->aStack );
- assert( i>=0 && i<p->nCursor );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int res, rx, iKey;
- assert( pTos->flags & MEM_Int );
- iKey = intToKey(pTos->i);
- rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
- p->aCsr[i].lastRecno = pTos->i;
- p->aCsr[i].recnoIsValid = res==0;
- p->aCsr[i].nullRow = 0;
- if( rx!=SQLITE_OK || res!=0 ){
- pc = pOp->p2 - 1;
- p->aCsr[i].recnoIsValid = 0;
- }
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: NewRecno P1 * *
-**
-** Get a new integer record number used as the key to a table.
-** The record number is not previously used as a key in the database
-** table that cursor P1 points to. The new record number is pushed
-** onto the stack.
-*/
-case OP_NewRecno: {
- int i = pOp->p1;
- int v = 0;
- Cursor *pC;
- assert( i>=0 && i<p->nCursor );
- if( (pC = &p->aCsr[i])->pCursor==0 ){
- v = 0;
- }else{
- /* The next rowid or record number (different terms for the same
- ** thing) is obtained in a two-step algorithm.
- **
- ** First we attempt to find the largest existing rowid and add one
- ** to that. But if the largest existing rowid is already the maximum
- ** positive integer, we have to fall through to the second
- ** probabilistic algorithm
- **
- ** The second algorithm is to select a rowid at random and see if
- ** it already exists in the table. If it does not exist, we have
- ** succeeded. If the random rowid does exist, we select a new one
- ** and try again, up to 1000 times.
- **
- ** For a table with less than 2 billion entries, the probability
- ** of not finding a unused rowid is about 1.0e-300. This is a
- ** non-zero probability, but it is still vanishingly small and should
- ** never cause a problem. You are much, much more likely to have a
- ** hardware failure than for this algorithm to fail.
- **
- ** The analysis in the previous paragraph assumes that you have a good
- ** source of random numbers. Is a library function like lrand48()
- ** good enough? Maybe. Maybe not. It's hard to know whether there
- ** might be subtle bugs is some implementations of lrand48() that
- ** could cause problems. To avoid uncertainty, SQLite uses its own
- ** random number generator based on the RC4 algorithm.
- **
- ** To promote locality of reference for repetitive inserts, the
- ** first few attempts at chosing a random rowid pick values just a little
- ** larger than the previous rowid. This has been shown experimentally
- ** to double the speed of the COPY operation.
- */
- int res, rx, cnt, x;
- cnt = 0;
- if( !pC->useRandomRowid ){
- if( pC->nextRowidValid ){
- v = pC->nextRowid;
- }else{
- rx = sqliteBtreeLast(pC->pCursor, &res);
- if( res ){
- v = 1;
- }else{
- sqliteBtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v);
- v = keyToInt(v);
- if( v==0x7fffffff ){
- pC->useRandomRowid = 1;
- }else{
- v++;
- }
- }
- }
- if( v<0x7fffffff ){
- pC->nextRowidValid = 1;
- pC->nextRowid = v+1;
- }else{
- pC->nextRowidValid = 0;
- }
- }
- if( pC->useRandomRowid ){
- v = db->priorNewRowid;
- cnt = 0;
- do{
- if( v==0 || cnt>2 ){
- sqliteRandomness(sizeof(v), &v);
- if( cnt<5 ) v &= 0xffffff;
- }else{
- unsigned char r;
- sqliteRandomness(1, &r);
- v += r + 1;
- }
- if( v==0 ) continue;
- x = intToKey(v);
- rx = sqliteBtreeMoveto(pC->pCursor, &x, sizeof(int), &res);
- cnt++;
- }while( cnt<1000 && rx==SQLITE_OK && res==0 );
- db->priorNewRowid = v;
- if( rx==SQLITE_OK && res==0 ){
- rc = SQLITE_FULL;
- goto abort_due_to_error;
- }
- }
- pC->recnoIsValid = 0;
- pC->deferredMoveto = 0;
- }
- pTos++;
- pTos->i = v;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: PutIntKey P1 P2 *
-**
-** Write an entry into the table of cursor P1. A new entry is
-** created if it doesn't already exist or the data for an existing
-** entry is overwritten. The data is the value on the top of the
-** stack. The key is the next value down on the stack. The key must
-** be an integer. The stack is popped twice by this instruction.
-**
-** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
-** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set,
-** then the current statement change count is incremented (otherwise not).
-** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is
-** stored for subsequent return by the sqlite_last_insert_rowid() function
-** (otherwise it's unmodified).
-*/
-/* Opcode: PutStrKey P1 * *
-**
-** Write an entry into the table of cursor P1. A new entry is
-** created if it doesn't already exist or the data for an existing
-** entry is overwritten. The data is the value on the top of the
-** stack. The key is the next value down on the stack. The key must
-** be a string. The stack is popped twice by this instruction.
-**
-** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
-*/
-case OP_PutIntKey:
-case OP_PutStrKey: {
- Mem *pNos = &pTos[-1];
- int i = pOp->p1;
- Cursor *pC;
- assert( pNos>=p->aStack );
- assert( i>=0 && i<p->nCursor );
- if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
- char *zKey;
- int nKey, iKey;
- if( pOp->opcode==OP_PutStrKey ){
- Stringify(pNos);
- nKey = pNos->n;
- zKey = pNos->z;
- }else{
- assert( pNos->flags & MEM_Int );
- nKey = sizeof(int);
- iKey = intToKey(pNos->i);
- zKey = (char*)&iKey;
- if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
- if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
- if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
- if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
- pC->nextRowidValid = 0;
- }
- }
- if( pTos->flags & MEM_Null ){
- pTos->z = 0;
- pTos->n = 0;
- }else{
- assert( pTos->flags & MEM_Str );
- }
- if( pC->pseudoTable ){
- /* PutStrKey does not work for pseudo-tables.
- ** The following assert makes sure we are not trying to use
- ** PutStrKey on a pseudo-table
- */
- assert( pOp->opcode==OP_PutIntKey );
- sqliteFree(pC->pData);
- pC->iKey = iKey;
- pC->nData = pTos->n;
- if( pTos->flags & MEM_Dyn ){
- pC->pData = pTos->z;
- pTos->flags = MEM_Null;
- }else{
- pC->pData = sqliteMallocRaw( pC->nData );
- if( pC->pData ){
- memcpy(pC->pData, pTos->z, pC->nData);
- }
- }
- pC->nullRow = 0;
- }else{
- rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
- }
- pC->recnoIsValid = 0;
- pC->deferredMoveto = 0;
- }
- popStack(&pTos, 2);
- break;
-}
-
-/* Opcode: Delete P1 P2 *
-**
-** Delete the record at which the P1 cursor is currently pointing.
-**
-** The cursor will be left pointing at either the next or the previous
-** record in the table. If it is left pointing at the next record, then
-** the next Next instruction will be a no-op. Hence it is OK to delete
-** a record from within an Next loop.
-**
-** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
-** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set,
-** then the current statement change count is incremented (otherwise not).
-**
-** If P1 is a pseudo-table, then this instruction is a no-op.
-*/
-case OP_Delete: {
- int i = pOp->p1;
- Cursor *pC;
- assert( i>=0 && i<p->nCursor );
- pC = &p->aCsr[i];
- if( pC->pCursor!=0 ){
- sqliteVdbeCursorMoveto(pC);
- rc = sqliteBtreeDelete(pC->pCursor);
- pC->nextRowidValid = 0;
- }
- if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
- if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
- break;
-}
-
-/* Opcode: SetCounts * * *
-**
-** Called at end of statement. Updates lsChange (last statement change count)
-** and resets csChange (current statement change count) to 0.
-*/
-case OP_SetCounts: {
- db->lsChange=db->csChange;
- db->csChange=0;
- break;
-}
-
-/* Opcode: KeyAsData P1 P2 *
-**
-** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
-** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
-** data off of the key rather than the data. This is used for
-** processing compound selects.
-*/
-case OP_KeyAsData: {
- int i = pOp->p1;
- assert( i>=0 && i<p->nCursor );
- p->aCsr[i].keyAsData = pOp->p2;
- break;
-}
-
-/* Opcode: RowData P1 * *
-**
-** Push onto the stack the complete row data for cursor P1.
-** There is no interpretation of the data. It is just copied
-** onto the stack exactly as it is found in the database file.
-**
-** If the cursor is not pointing to a valid row, a NULL is pushed
-** onto the stack.
-*/
-/* Opcode: RowKey P1 * *
-**
-** Push onto the stack the complete row key for cursor P1.
-** There is no interpretation of the key. It is just copied
-** onto the stack exactly as it is found in the database file.
-**
-** If the cursor is not pointing to a valid row, a NULL is pushed
-** onto the stack.
-*/
-case OP_RowKey:
-case OP_RowData: {
- int i = pOp->p1;
- Cursor *pC;
- int n;
-
- pTos++;
- assert( i>=0 && i<p->nCursor );
- pC = &p->aCsr[i];
- if( pC->nullRow ){
- pTos->flags = MEM_Null;
- }else if( pC->pCursor!=0 ){
- BtCursor *pCrsr = pC->pCursor;
- sqliteVdbeCursorMoveto(pC);
- if( pC->nullRow ){
- pTos->flags = MEM_Null;
- break;
- }else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
- sqliteBtreeKeySize(pCrsr, &n);
- }else{
- sqliteBtreeDataSize(pCrsr, &n);
- }
- pTos->n = n;
- if( n<=NBFS ){
- pTos->flags = MEM_Str | MEM_Short;
- pTos->z = pTos->zShort;
- }else{
- char *z = sqliteMallocRaw( n );
- if( z==0 ) goto no_mem;
- pTos->flags = MEM_Str | MEM_Dyn;
- pTos->z = z;
- }
- if( pC->keyAsData || pOp->opcode==OP_RowKey ){
- sqliteBtreeKey(pCrsr, 0, n, pTos->z);
- }else{
- sqliteBtreeData(pCrsr, 0, n, pTos->z);
- }
- }else if( pC->pseudoTable ){
- pTos->n = pC->nData;
- pTos->z = pC->pData;
- pTos->flags = MEM_Str|MEM_Ephem;
- }else{
- pTos->flags = MEM_Null;
- }
- break;
-}
-
-/* Opcode: Column P1 P2 *
-**
-** Interpret the data that cursor P1 points to as
-** a structure built using the MakeRecord instruction.
-** (See the MakeRecord opcode for additional information about
-** the format of the data.)
-** Push onto the stack the value of the P2-th column contained
-** in the data.
-**
-** If the KeyAsData opcode has previously executed on this cursor,
-** then the field might be extracted from the key rather than the
-** data.
-**
-** If P1 is negative, then the record is stored on the stack rather
-** than in a table. For P1==-1, the top of the stack is used.
-** For P1==-2, the next on the stack is used. And so forth. The
-** value pushed is always just a pointer into the record which is
-** stored further down on the stack. The column value is not copied.
-*/
-case OP_Column: {
- int amt, offset, end, payloadSize;
- int i = pOp->p1;
- int p2 = pOp->p2;
- Cursor *pC;
- char *zRec;
- BtCursor *pCrsr;
- int idxWidth;
- unsigned char aHdr[10];
-
- assert( i<p->nCursor );
- pTos++;
- if( i<0 ){
- assert( &pTos[i]>=p->aStack );
- assert( pTos[i].flags & MEM_Str );
- zRec = pTos[i].z;
- payloadSize = pTos[i].n;
- }else if( (pC = &p->aCsr[i])->pCursor!=0 ){
- sqliteVdbeCursorMoveto(pC);
- zRec = 0;
- pCrsr = pC->pCursor;
- if( pC->nullRow ){
- payloadSize = 0;
- }else if( pC->keyAsData ){
- sqliteBtreeKeySize(pCrsr, &payloadSize);
- }else{
- sqliteBtreeDataSize(pCrsr, &payloadSize);
- }
- }else if( pC->pseudoTable ){
- payloadSize = pC->nData;
- zRec = pC->pData;
- assert( payloadSize==0 || zRec!=0 );
- }else{
- payloadSize = 0;
- }
-
- /* Figure out how many bytes in the column data and where the column
- ** data begins.
- */
- if( payloadSize==0 ){
- pTos->flags = MEM_Null;
- break;
- }else if( payloadSize<256 ){
- idxWidth = 1;
- }else if( payloadSize<65536 ){
- idxWidth = 2;
- }else{
- idxWidth = 3;
- }
-
- /* Figure out where the requested column is stored and how big it is.
- */
- if( payloadSize < idxWidth*(p2+1) ){
- rc = SQLITE_CORRUPT;
- goto abort_due_to_error;
- }
- if( zRec ){
- memcpy(aHdr, &zRec[idxWidth*p2], idxWidth*2);
- }else if( pC->keyAsData ){
- sqliteBtreeKey(pCrsr, idxWidth*p2, idxWidth*2, (char*)aHdr);
- }else{
- sqliteBtreeData(pCrsr, idxWidth*p2, idxWidth*2, (char*)aHdr);
- }
- offset = aHdr[0];
- end = aHdr[idxWidth];
- if( idxWidth>1 ){
- offset |= aHdr[1]<<8;
- end |= aHdr[idxWidth+1]<<8;
- if( idxWidth>2 ){
- offset |= aHdr[2]<<16;
- end |= aHdr[idxWidth+2]<<16;
- }
- }
- amt = end - offset;
- if( amt<0 || offset<0 || end>payloadSize ){
- rc = SQLITE_CORRUPT;
- goto abort_due_to_error;
- }
-
- /* amt and offset now hold the offset to the start of data and the
- ** amount of data. Go get the data and put it on the stack.
- */
- pTos->n = amt;
- if( amt==0 ){
- pTos->flags = MEM_Null;
- }else if( zRec ){
- pTos->flags = MEM_Str | MEM_Ephem;
- pTos->z = &zRec[offset];
- }else{
- if( amt<=NBFS ){
- pTos->flags = MEM_Str | MEM_Short;
- pTos->z = pTos->zShort;
- }else{
- char *z = sqliteMallocRaw( amt );
- if( z==0 ) goto no_mem;
- pTos->flags = MEM_Str | MEM_Dyn;
- pTos->z = z;
- }
- if( pC->keyAsData ){
- sqliteBtreeKey(pCrsr, offset, amt, pTos->z);
- }else{
- sqliteBtreeData(pCrsr, offset, amt, pTos->z);
- }
- }
- break;
-}
-
-/* Opcode: Recno P1 * *
-**
-** Push onto the stack an integer which is the first 4 bytes of the
-** the key to the current entry in a sequential scan of the database
-** file P1. The sequential scan should have been started using the
-** Next opcode.
-*/
-case OP_Recno: {
- int i = pOp->p1;
- Cursor *pC;
- int v;
-
- assert( i>=0 && i<p->nCursor );
- pC = &p->aCsr[i];
- sqliteVdbeCursorMoveto(pC);
- pTos++;
- if( pC->recnoIsValid ){
- v = pC->lastRecno;
- }else if( pC->pseudoTable ){
- v = keyToInt(pC->iKey);
- }else if( pC->nullRow || pC->pCursor==0 ){
- pTos->flags = MEM_Null;
- break;
- }else{
- assert( pC->pCursor!=0 );
- sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v);
- v = keyToInt(v);
- }
- pTos->i = v;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: FullKey P1 * *
-**
-** Extract the complete key from the record that cursor P1 is currently
-** pointing to and push the key onto the stack as a string.
-**
-** Compare this opcode to Recno. The Recno opcode extracts the first
-** 4 bytes of the key and pushes those bytes onto the stack as an
-** integer. This instruction pushes the entire key as a string.
-**
-** This opcode may not be used on a pseudo-table.
-*/
-case OP_FullKey: {
- int i = pOp->p1;
- BtCursor *pCrsr;
-
- assert( p->aCsr[i].keyAsData );
- assert( !p->aCsr[i].pseudoTable );
- assert( i>=0 && i<p->nCursor );
- pTos++;
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int amt;
- char *z;
-
- sqliteVdbeCursorMoveto(&p->aCsr[i]);
- sqliteBtreeKeySize(pCrsr, &amt);
- if( amt<=0 ){
- rc = SQLITE_CORRUPT;
- goto abort_due_to_error;
- }
- if( amt>NBFS ){
- z = sqliteMallocRaw( amt );
- if( z==0 ) goto no_mem;
- pTos->flags = MEM_Str | MEM_Dyn;
- }else{
- z = pTos->zShort;
- pTos->flags = MEM_Str | MEM_Short;
- }
- sqliteBtreeKey(pCrsr, 0, amt, z);
- pTos->z = z;
- pTos->n = amt;
- }
- break;
-}
-
-/* Opcode: NullRow P1 * *
-**
-** Move the cursor P1 to a null row. Any OP_Column operations
-** that occur while the cursor is on the null row will always push
-** a NULL onto the stack.
-*/
-case OP_NullRow: {
- int i = pOp->p1;
-
- assert( i>=0 && i<p->nCursor );
- p->aCsr[i].nullRow = 1;
- p->aCsr[i].recnoIsValid = 0;
- break;
-}
-
-/* Opcode: Last P1 P2 *
-**
-** The next use of the Recno or Column or Next instruction for P1
-** will refer to the last entry in the database table or index.
-** If the table or index is empty and P2>0, then jump immediately to P2.
-** If P2 is 0 or if the table or index is not empty, fall through
-** to the following instruction.
-*/
-case OP_Last: {
- int i = pOp->p1;
- Cursor *pC;
- BtCursor *pCrsr;
-
- assert( i>=0 && i<p->nCursor );
- pC = &p->aCsr[i];
- if( (pCrsr = pC->pCursor)!=0 ){
- int res;
- rc = sqliteBtreeLast(pCrsr, &res);
- pC->nullRow = res;
- pC->deferredMoveto = 0;
- if( res && pOp->p2>0 ){
- pc = pOp->p2 - 1;
- }
- }else{
- pC->nullRow = 0;
- }
- break;
-}
-
-/* Opcode: Rewind P1 P2 *
-**
-** The next use of the Recno or Column or Next instruction for P1
-** will refer to the first entry in the database table or index.
-** If the table or index is empty and P2>0, then jump immediately to P2.
-** If P2 is 0 or if the table or index is not empty, fall through
-** to the following instruction.
-*/
-case OP_Rewind: {
- int i = pOp->p1;
- Cursor *pC;
- BtCursor *pCrsr;
-
- assert( i>=0 && i<p->nCursor );
- pC = &p->aCsr[i];
- if( (pCrsr = pC->pCursor)!=0 ){
- int res;
- rc = sqliteBtreeFirst(pCrsr, &res);
- pC->atFirst = res==0;
- pC->nullRow = res;
- pC->deferredMoveto = 0;
- if( res && pOp->p2>0 ){
- pc = pOp->p2 - 1;
- }
- }else{
- pC->nullRow = 0;
- }
- break;
-}
-
-/* Opcode: Next P1 P2 *
-**
-** Advance cursor P1 so that it points to the next key/data pair in its
-** table or index. If there are no more key/value pairs then fall through
-** to the following instruction. But if the cursor advance was successful,
-** jump immediately to P2.
-**
-** See also: Prev
-*/
-/* Opcode: Prev P1 P2 *
-**
-** Back up cursor P1 so that it points to the previous key/data pair in its
-** table or index. If there is no previous key/value pairs then fall through
-** to the following instruction. But if the cursor backup was successful,
-** jump immediately to P2.
-*/
-case OP_Prev:
-case OP_Next: {
- Cursor *pC;
- BtCursor *pCrsr;
-
- CHECK_FOR_INTERRUPT;
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- pC = &p->aCsr[pOp->p1];
- if( (pCrsr = pC->pCursor)!=0 ){
- int res;
- if( pC->nullRow ){
- res = 1;
- }else{
- assert( pC->deferredMoveto==0 );
- rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) :
- sqliteBtreePrevious(pCrsr, &res);
- pC->nullRow = res;
- }
- if( res==0 ){
- pc = pOp->p2 - 1;
- sqlite_search_count++;
- }
- }else{
- pC->nullRow = 1;
- }
- pC->recnoIsValid = 0;
- break;
-}
-
-/* Opcode: IdxPut P1 P2 P3
-**
-** The top of the stack holds a SQL index key made using the
-** MakeIdxKey instruction. This opcode writes that key into the
-** index P1. Data for the entry is nil.
-**
-** If P2==1, then the key must be unique. If the key is not unique,
-** the program aborts with a SQLITE_CONSTRAINT error and the database
-** is rolled back. If P3 is not null, then it becomes part of the
-** error message returned with the SQLITE_CONSTRAINT.
-*/
-case OP_IdxPut: {
- int i = pOp->p1;
- BtCursor *pCrsr;
- assert( pTos>=p->aStack );
- assert( i>=0 && i<p->nCursor );
- assert( pTos->flags & MEM_Str );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int nKey = pTos->n;
- const char *zKey = pTos->z;
- if( pOp->p2 ){
- int res, n;
- assert( nKey >= 4 );
- rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- while( res!=0 ){
- int c;
- sqliteBtreeKeySize(pCrsr, &n);
- if( n==nKey
- && sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, 4, &c)==SQLITE_OK
- && c==0
- ){
- rc = SQLITE_CONSTRAINT;
- if( pOp->p3 && pOp->p3[0] ){
- sqliteSetString(&p->zErrMsg, pOp->p3, (char*)0);
- }
- goto abort_due_to_error;
- }
- if( res<0 ){
- sqliteBtreeNext(pCrsr, &res);
- res = +1;
- }else{
- break;
- }
- }
- }
- rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0);
- assert( p->aCsr[i].deferredMoveto==0 );
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: IdxDelete P1 * *
-**
-** The top of the stack is an index key built using the MakeIdxKey opcode.
-** This opcode removes that entry from the index.
-*/
-case OP_IdxDelete: {
- int i = pOp->p1;
- BtCursor *pCrsr;
- assert( pTos>=p->aStack );
- assert( pTos->flags & MEM_Str );
- assert( i>=0 && i<p->nCursor );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int rx, res;
- rx = sqliteBtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
- if( rx==SQLITE_OK && res==0 ){
- rc = sqliteBtreeDelete(pCrsr);
- }
- assert( p->aCsr[i].deferredMoveto==0 );
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: IdxRecno P1 * *
-**
-** Push onto the stack an integer which is the last 4 bytes of the
-** the key to the current entry in index P1. These 4 bytes should
-** be the record number of the table entry to which this index entry
-** points.
-**
-** See also: Recno, MakeIdxKey.
-*/
-case OP_IdxRecno: {
- int i = pOp->p1;
- BtCursor *pCrsr;
-
- assert( i>=0 && i<p->nCursor );
- pTos++;
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int v;
- int sz;
- assert( p->aCsr[i].deferredMoveto==0 );
- sqliteBtreeKeySize(pCrsr, &sz);
- if( sz<sizeof(u32) ){
- pTos->flags = MEM_Null;
- }else{
- sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v);
- v = keyToInt(v);
- pTos->i = v;
- pTos->flags = MEM_Int;
- }
- }else{
- pTos->flags = MEM_Null;
- }
- break;
-}
-
-/* Opcode: IdxGT P1 P2 *
-**
-** Compare the top of the stack against the key on the index entry that
-** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
-** index entry. If the index entry is greater than the top of the stack
-** then jump to P2. Otherwise fall through to the next instruction.
-** In either case, the stack is popped once.
-*/
-/* Opcode: IdxGE P1 P2 *
-**
-** Compare the top of the stack against the key on the index entry that
-** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
-** index entry. If the index entry is greater than or equal to
-** the top of the stack
-** then jump to P2. Otherwise fall through to the next instruction.
-** In either case, the stack is popped once.
-*/
-/* Opcode: IdxLT P1 P2 *
-**
-** Compare the top of the stack against the key on the index entry that
-** cursor P1 is currently pointing to. Ignore the last 4 bytes of the
-** index entry. If the index entry is less than the top of the stack
-** then jump to P2. Otherwise fall through to the next instruction.
-** In either case, the stack is popped once.
-*/
-case OP_IdxLT:
-case OP_IdxGT:
-case OP_IdxGE: {
- int i= pOp->p1;
- BtCursor *pCrsr;
-
- assert( i>=0 && i<p->nCursor );
- assert( pTos>=p->aStack );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int res, rc;
-
- Stringify(pTos);
- assert( p->aCsr[i].deferredMoveto==0 );
- rc = sqliteBtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res);
- if( rc!=SQLITE_OK ){
- break;
- }
- if( pOp->opcode==OP_IdxLT ){
- res = -res;
- }else if( pOp->opcode==OP_IdxGE ){
- res++;
- }
- if( res>0 ){
- pc = pOp->p2 - 1 ;
- }
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: IdxIsNull P1 P2 *
-**
-** The top of the stack contains an index entry such as might be generated
-** by the MakeIdxKey opcode. This routine looks at the first P1 fields of
-** that key. If any of the first P1 fields are NULL, then a jump is made
-** to address P2. Otherwise we fall straight through.
-**
-** The index entry is always popped from the stack.
-*/
-case OP_IdxIsNull: {
- int i = pOp->p1;
- int k, n;
- const char *z;
-
- assert( pTos>=p->aStack );
- assert( pTos->flags & MEM_Str );
- z = pTos->z;
- n = pTos->n;
- for(k=0; k<n && i>0; i--){
- if( z[k]=='a' ){
- pc = pOp->p2-1;
- break;
- }
- while( k<n && z[k] ){ k++; }
- k++;
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: Destroy P1 P2 *
-**
-** Delete an entire database table or index whose root page in the database
-** file is given by P1.
-**
-** The table being destroyed is in the main database file if P2==0. If
-** P2==1 then the table to be clear is in the auxiliary database file
-** that is used to store tables create using CREATE TEMPORARY TABLE.
-**
-** See also: Clear
-*/
-case OP_Destroy: {
- rc = sqliteBtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1);
- break;
-}
-
-/* Opcode: Clear P1 P2 *
-**
-** Delete all contents of the database table or index whose root page
-** in the database file is given by P1. But, unlike Destroy, do not
-** remove the table or index from the database file.
-**
-** The table being clear is in the main database file if P2==0. If
-** P2==1 then the table to be clear is in the auxiliary database file
-** that is used to store tables create using CREATE TEMPORARY TABLE.
-**
-** See also: Destroy
-*/
-case OP_Clear: {
- rc = sqliteBtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
- break;
-}
-
-/* Opcode: CreateTable * P2 P3
-**
-** Allocate a new table in the main database file if P2==0 or in the
-** auxiliary database file if P2==1. Push the page number
-** for the root page of the new table onto the stack.
-**
-** The root page number is also written to a memory location that P3
-** points to. This is the mechanism is used to write the root page
-** number into the parser's internal data structures that describe the
-** new table.
-**
-** The difference between a table and an index is this: A table must
-** have a 4-byte integer key and can have arbitrary data. An index
-** has an arbitrary key but no data.
-**
-** See also: CreateIndex
-*/
-/* Opcode: CreateIndex * P2 P3
-**
-** Allocate a new index in the main database file if P2==0 or in the
-** auxiliary database file if P2==1. Push the page number of the
-** root page of the new index onto the stack.
-**
-** See documentation on OP_CreateTable for additional information.
-*/
-case OP_CreateIndex:
-case OP_CreateTable: {
- int pgno;
- assert( pOp->p3!=0 && pOp->p3type==P3_POINTER );
- assert( pOp->p2>=0 && pOp->p2<db->nDb );
- assert( db->aDb[pOp->p2].pBt!=0 );
- if( pOp->opcode==OP_CreateTable ){
- rc = sqliteBtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno);
- }else{
- rc = sqliteBtreeCreateIndex(db->aDb[pOp->p2].pBt, &pgno);
- }
- pTos++;
- if( rc==SQLITE_OK ){
- pTos->i = pgno;
- pTos->flags = MEM_Int;
- *(u32*)pOp->p3 = pgno;
- pOp->p3 = 0;
- }else{
- pTos->flags = MEM_Null;
- }
- break;
-}
-
-/* Opcode: IntegrityCk P1 P2 *
-**
-** Do an analysis of the currently open database. Push onto the
-** stack the text of an error message describing any problems.
-** If there are no errors, push a "ok" onto the stack.
-**
-** P1 is the index of a set that contains the root page numbers
-** for all tables and indices in the main database file. The set
-** is cleared by this opcode. In other words, after this opcode
-** has executed, the set will be empty.
-**
-** If P2 is not zero, the check is done on the auxiliary database
-** file, not the main database file.
-**
-** This opcode is used for testing purposes only.
-*/
-case OP_IntegrityCk: {
- int nRoot;
- int *aRoot;
- int iSet = pOp->p1;
- Set *pSet;
- int j;
- HashElem *i;
- char *z;
-
- assert( iSet>=0 && iSet<p->nSet );
- pTos++;
- pSet = &p->aSet[iSet];
- nRoot = sqliteHashCount(&pSet->hash);
- aRoot = sqliteMallocRaw( sizeof(int)*(nRoot+1) );
- if( aRoot==0 ) goto no_mem;
- for(j=0, i=sqliteHashFirst(&pSet->hash); i; i=sqliteHashNext(i), j++){
- toInt((char*)sqliteHashKey(i), &aRoot[j]);
- }
- aRoot[j] = 0;
- sqliteHashClear(&pSet->hash);
- pSet->prev = 0;
- z = sqliteBtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
- if( z==0 || z[0]==0 ){
- if( z ) sqliteFree(z);
- pTos->z = "ok";
- pTos->n = 3;
- pTos->flags = MEM_Str | MEM_Static;
- }else{
- pTos->z = z;
- pTos->n = strlen(z) + 1;
- pTos->flags = MEM_Str | MEM_Dyn;
- }
- sqliteFree(aRoot);
- break;
-}
-
-/* Opcode: ListWrite * * *
-**
-** Write the integer on the top of the stack
-** into the temporary storage list.
-*/
-case OP_ListWrite: {
- Keylist *pKeylist;
- assert( pTos>=p->aStack );
- pKeylist = p->pList;
- if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
- pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
- if( pKeylist==0 ) goto no_mem;
- pKeylist->nKey = 1000;
- pKeylist->nRead = 0;
- pKeylist->nUsed = 0;
- pKeylist->pNext = p->pList;
- p->pList = pKeylist;
- }
- Integerify(pTos);
- pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: ListRewind * * *
-**
-** Rewind the temporary buffer back to the beginning.
-*/
-case OP_ListRewind: {
- /* What this opcode codes, really, is reverse the order of the
- ** linked list of Keylist structures so that they are read out
- ** in the same order that they were read in. */
- Keylist *pRev, *pTop;
- pRev = 0;
- while( p->pList ){
- pTop = p->pList;
- p->pList = pTop->pNext;
- pTop->pNext = pRev;
- pRev = pTop;
- }
- p->pList = pRev;
- break;
-}
-
-/* Opcode: ListRead * P2 *
-**
-** Attempt to read an integer from the temporary storage buffer
-** and push it onto the stack. If the storage buffer is empty,
-** push nothing but instead jump to P2.
-*/
-case OP_ListRead: {
- Keylist *pKeylist;
- CHECK_FOR_INTERRUPT;
- pKeylist = p->pList;
- if( pKeylist!=0 ){
- assert( pKeylist->nRead>=0 );
- assert( pKeylist->nRead<pKeylist->nUsed );
- assert( pKeylist->nRead<pKeylist->nKey );
- pTos++;
- pTos->i = pKeylist->aKey[pKeylist->nRead++];
- pTos->flags = MEM_Int;
- if( pKeylist->nRead>=pKeylist->nUsed ){
- p->pList = pKeylist->pNext;
- sqliteFree(pKeylist);
- }
- }else{
- pc = pOp->p2 - 1;
- }
- break;
-}
-
-/* Opcode: ListReset * * *
-**
-** Reset the temporary storage buffer so that it holds nothing.
-*/
-case OP_ListReset: {
- if( p->pList ){
- sqliteVdbeKeylistFree(p->pList);
- p->pList = 0;
- }
- break;
-}
-
-/* Opcode: ListPush * * *
-**
-** Save the current Vdbe list such that it can be restored by a ListPop
-** opcode. The list is empty after this is executed.
-*/
-case OP_ListPush: {
- p->keylistStackDepth++;
- assert(p->keylistStackDepth > 0);
- p->keylistStack = sqliteRealloc(p->keylistStack,
- sizeof(Keylist *) * p->keylistStackDepth);
- if( p->keylistStack==0 ) goto no_mem;
- p->keylistStack[p->keylistStackDepth - 1] = p->pList;
- p->pList = 0;
- break;
-}
-
-/* Opcode: ListPop * * *
-**
-** Restore the Vdbe list to the state it was in when ListPush was last
-** executed.
-*/
-case OP_ListPop: {
- assert(p->keylistStackDepth > 0);
- p->keylistStackDepth--;
- sqliteVdbeKeylistFree(p->pList);
- p->pList = p->keylistStack[p->keylistStackDepth];
- p->keylistStack[p->keylistStackDepth] = 0;
- if( p->keylistStackDepth == 0 ){
- sqliteFree(p->keylistStack);
- p->keylistStack = 0;
- }
- break;
-}
-
-/* Opcode: ContextPush * * *
-**
-** Save the current Vdbe context such that it can be restored by a ContextPop
-** opcode. The context stores the last insert row id, the last statement change
-** count, and the current statement change count.
-*/
-case OP_ContextPush: {
- p->contextStackDepth++;
- assert(p->contextStackDepth > 0);
- p->contextStack = sqliteRealloc(p->contextStack,
- sizeof(Context) * p->contextStackDepth);
- if( p->contextStack==0 ) goto no_mem;
- p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid;
- p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange;
- p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange;
- break;
-}
-
-/* Opcode: ContextPop * * *
-**
-** Restore the Vdbe context to the state it was in when contextPush was last
-** executed. The context stores the last insert row id, the last statement
-** change count, and the current statement change count.
-*/
-case OP_ContextPop: {
- assert(p->contextStackDepth > 0);
- p->contextStackDepth--;
- p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid;
- p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange;
- p->db->csChange = p->contextStack[p->contextStackDepth].csChange;
- if( p->contextStackDepth == 0 ){
- sqliteFree(p->contextStack);
- p->contextStack = 0;
- }
- break;
-}
-
-/* Opcode: SortPut * * *
-**
-** The TOS is the key and the NOS is the data. Pop both from the stack
-** and put them on the sorter. The key and data should have been
-** made using SortMakeKey and SortMakeRec, respectively.
-*/
-case OP_SortPut: {
- Mem *pNos = &pTos[-1];
- Sorter *pSorter;
- assert( pNos>=p->aStack );
- if( Dynamicify(pTos) || Dynamicify(pNos) ) goto no_mem;
- pSorter = sqliteMallocRaw( sizeof(Sorter) );
- if( pSorter==0 ) goto no_mem;
- pSorter->pNext = p->pSort;
- p->pSort = pSorter;
- assert( pTos->flags & MEM_Dyn );
- pSorter->nKey = pTos->n;
- pSorter->zKey = pTos->z;
- assert( pNos->flags & MEM_Dyn );
- pSorter->nData = pNos->n;
- pSorter->pData = pNos->z;
- pTos -= 2;
- break;
-}
-
-/* Opcode: SortMakeRec P1 * *
-**
-** The top P1 elements are the arguments to a callback. Form these
-** elements into a single data entry that can be stored on a sorter
-** using SortPut and later fed to a callback using SortCallback.
-*/
-case OP_SortMakeRec: {
- char *z;
- char **azArg;
- int nByte;
- int nField;
- int i;
- Mem *pRec;
-
- nField = pOp->p1;
- pRec = &pTos[1-nField];
- assert( pRec>=p->aStack );
- nByte = 0;
- for(i=0; i<nField; i++, pRec++){
- if( (pRec->flags & MEM_Null)==0 ){
- Stringify(pRec);
- nByte += pRec->n;
- }
- }
- nByte += sizeof(char*)*(nField+1);
- azArg = sqliteMallocRaw( nByte );
- if( azArg==0 ) goto no_mem;
- z = (char*)&azArg[nField+1];
- for(pRec=&pTos[1-nField], i=0; i<nField; i++, pRec++){
- if( pRec->flags & MEM_Null ){
- azArg[i] = 0;
- }else{
- azArg[i] = z;
- memcpy(z, pRec->z, pRec->n);
- z += pRec->n;
- }
- }
- popStack(&pTos, nField);
- pTos++;
- pTos->n = nByte;
- pTos->z = (char*)azArg;
- pTos->flags = MEM_Str | MEM_Dyn;
- break;
-}
-
-/* Opcode: SortMakeKey * * P3
-**
-** Convert the top few entries of the stack into a sort key. The
-** number of stack entries consumed is the number of characters in
-** the string P3. One character from P3 is prepended to each entry.
-** The first character of P3 is prepended to the element lowest in
-** the stack and the last character of P3 is prepended to the top of
-** the stack. All stack entries are separated by a \000 character
-** in the result. The whole key is terminated by two \000 characters
-** in a row.
-**
-** "N" is substituted in place of the P3 character for NULL values.
-**
-** See also the MakeKey and MakeIdxKey opcodes.
-*/
-case OP_SortMakeKey: {
- char *zNewKey;
- int nByte;
- int nField;
- int i, j, k;
- Mem *pRec;
-
- nField = strlen(pOp->p3);
- pRec = &pTos[1-nField];
- nByte = 1;
- for(i=0; i<nField; i++, pRec++){
- if( pRec->flags & MEM_Null ){
- nByte += 2;
- }else{
- Stringify(pRec);
- nByte += pRec->n+2;
- }
- }
- zNewKey = sqliteMallocRaw( nByte );
- if( zNewKey==0 ) goto no_mem;
- j = 0;
- k = 0;
- for(pRec=&pTos[1-nField], i=0; i<nField; i++, pRec++){
- if( pRec->flags & MEM_Null ){
- zNewKey[j++] = 'N';
- zNewKey[j++] = 0;
- k++;
- }else{
- zNewKey[j++] = pOp->p3[k++];
- memcpy(&zNewKey[j], pRec->z, pRec->n-1);
- j += pRec->n-1;
- zNewKey[j++] = 0;
- }
- }
- zNewKey[j] = 0;
- assert( j<nByte );
- popStack(&pTos, nField);
- pTos++;
- pTos->n = nByte;
- pTos->flags = MEM_Str|MEM_Dyn;
- pTos->z = zNewKey;
- break;
-}
-
-/* Opcode: Sort * * *
-**
-** Sort all elements on the sorter. The algorithm is a
-** mergesort.
-*/
-case OP_Sort: {
- int i;
- Sorter *pElem;
- Sorter *apSorter[NSORT];
- for(i=0; i<NSORT; i++){
- apSorter[i] = 0;
- }
- while( p->pSort ){
- pElem = p->pSort;
- p->pSort = pElem->pNext;
- pElem->pNext = 0;
- for(i=0; i<NSORT-1; i++){
- if( apSorter[i]==0 ){
- apSorter[i] = pElem;
- break;
- }else{
- pElem = Merge(apSorter[i], pElem);
- apSorter[i] = 0;
- }
- }
- if( i>=NSORT-1 ){
- apSorter[NSORT-1] = Merge(apSorter[NSORT-1],pElem);
- }
- }
- pElem = 0;
- for(i=0; i<NSORT; i++){
- pElem = Merge(apSorter[i], pElem);
- }
- p->pSort = pElem;
- break;
-}
-
-/* Opcode: SortNext * P2 *
-**
-** Push the data for the topmost element in the sorter onto the
-** stack, then remove the element from the sorter. If the sorter
-** is empty, push nothing on the stack and instead jump immediately
-** to instruction P2.
-*/
-case OP_SortNext: {
- Sorter *pSorter = p->pSort;
- CHECK_FOR_INTERRUPT;
- if( pSorter!=0 ){
- p->pSort = pSorter->pNext;
- pTos++;
- pTos->z = pSorter->pData;
- pTos->n = pSorter->nData;
- pTos->flags = MEM_Str|MEM_Dyn;
- sqliteFree(pSorter->zKey);
- sqliteFree(pSorter);
- }else{
- pc = pOp->p2 - 1;
- }
- break;
-}
-
-/* Opcode: SortCallback P1 * *
-**
-** The top of the stack contains a callback record built using
-** the SortMakeRec operation with the same P1 value as this
-** instruction. Pop this record from the stack and invoke the
-** callback on it.
-*/
-case OP_SortCallback: {
- assert( pTos>=p->aStack );
- assert( pTos->flags & MEM_Str );
- p->nCallback++;
- p->pc = pc+1;
- p->azResColumn = (char**)pTos->z;
- assert( p->nResColumn==pOp->p1 );
- p->popStack = 1;
- p->pTos = pTos;
- return SQLITE_ROW;
-}
-
-/* Opcode: SortReset * * *
-**
-** Remove any elements that remain on the sorter.
-*/
-case OP_SortReset: {
- sqliteVdbeSorterReset(p);
- break;
-}
-
-/* Opcode: FileOpen * * P3
-**
-** Open the file named by P3 for reading using the FileRead opcode.
-** If P3 is "stdin" then open standard input for reading.
-*/
-case OP_FileOpen: {
- assert( pOp->p3!=0 );
- if( p->pFile ){
- if( p->pFile!=stdin ) fclose(p->pFile);
- p->pFile = 0;
- }
- if( sqliteStrICmp(pOp->p3,"stdin")==0 ){
- p->pFile = stdin;
- }else{
- p->pFile = fopen(pOp->p3, "r");
- }
- if( p->pFile==0 ){
- sqliteSetString(&p->zErrMsg,"unable to open file: ", pOp->p3, (char*)0);
- rc = SQLITE_ERROR;
- }
- break;
-}
-
-/* Opcode: FileRead P1 P2 P3
-**
-** Read a single line of input from the open file (the file opened using
-** FileOpen). If we reach end-of-file, jump immediately to P2. If
-** we are able to get another line, split the line apart using P3 as
-** a delimiter. There should be P1 fields. If the input line contains
-** more than P1 fields, ignore the excess. If the input line contains
-** fewer than P1 fields, assume the remaining fields contain NULLs.
-**
-** Input ends if a line consists of just "\.". A field containing only
-** "\N" is a null field. The backslash \ character can be used be used
-** to escape newlines or the delimiter.
-*/
-case OP_FileRead: {
- int n, eol, nField, i, c, nDelim;
- char *zDelim, *z;
- CHECK_FOR_INTERRUPT;
- if( p->pFile==0 ) goto fileread_jump;
- nField = pOp->p1;
- if( nField<=0 ) goto fileread_jump;
- if( nField!=p->nField || p->azField==0 ){
- char **azField = sqliteRealloc(p->azField, sizeof(char*)*nField+1);
- if( azField==0 ){ goto no_mem; }
- p->azField = azField;
- p->nField = nField;
- }
- n = 0;
- eol = 0;
- while( eol==0 ){
- if( p->zLine==0 || n+200>p->nLineAlloc ){
- char *zLine;
- p->nLineAlloc = p->nLineAlloc*2 + 300;
- zLine = sqliteRealloc(p->zLine, p->nLineAlloc);
- if( zLine==0 ){
- p->nLineAlloc = 0;
- sqliteFree(p->zLine);
- p->zLine = 0;
- goto no_mem;
- }
- p->zLine = zLine;
- }
- if( vdbe_fgets(&p->zLine[n], p->nLineAlloc-n, p->pFile)==0 ){
- eol = 1;
- p->zLine[n] = 0;
- }else{
- int c;
- while( (c = p->zLine[n])!=0 ){
- if( c=='\\' ){
- if( p->zLine[n+1]==0 ) break;
- n += 2;
- }else if( c=='\n' ){
- p->zLine[n] = 0;
- eol = 1;
- break;
- }else{
- n++;
- }
- }
- }
- }
- if( n==0 ) goto fileread_jump;
- z = p->zLine;
- if( z[0]=='\\' && z[1]=='.' && z[2]==0 ){
- goto fileread_jump;
- }
- zDelim = pOp->p3;
- if( zDelim==0 ) zDelim = "\t";
- c = zDelim[0];
- nDelim = strlen(zDelim);
- p->azField[0] = z;
- for(i=1; *z!=0 && i<=nField; i++){
- int from, to;
- from = to = 0;
- if( z[0]=='\\' && z[1]=='N'
- && (z[2]==0 || strncmp(&z[2],zDelim,nDelim)==0) ){
- if( i<=nField ) p->azField[i-1] = 0;
- z += 2 + nDelim;
- if( i<nField ) p->azField[i] = z;
- continue;
- }
- while( z[from] ){
- if( z[from]=='\\' && z[from+1]!=0 ){
- int tx = z[from+1];
- switch( tx ){
- case 'b': tx = '\b'; break;
- case 'f': tx = '\f'; break;
- case 'n': tx = '\n'; break;
- case 'r': tx = '\r'; break;
- case 't': tx = '\t'; break;
- case 'v': tx = '\v'; break;
- default: break;
- }
- z[to++] = tx;
- from += 2;
- continue;
- }
- if( z[from]==c && strncmp(&z[from],zDelim,nDelim)==0 ) break;
- z[to++] = z[from++];
- }
- if( z[from] ){
- z[to] = 0;
- z += from + nDelim;
- if( i<nField ) p->azField[i] = z;
- }else{
- z[to] = 0;
- z = "";
- }
- }
- while( i<nField ){
- p->azField[i++] = 0;
- }
- break;
-
- /* If we reach end-of-file, or if anything goes wrong, jump here.
- ** This code will cause a jump to P2 */
-fileread_jump:
- pc = pOp->p2 - 1;
- break;
-}
-
-/* Opcode: FileColumn P1 * *
-**
-** Push onto the stack the P1-th column of the most recently read line
-** from the input file.
-*/
-case OP_FileColumn: {
- int i = pOp->p1;
- char *z;
- assert( i>=0 && i<p->nField );
- if( p->azField ){
- z = p->azField[i];
- }else{
- z = 0;
- }
- pTos++;
- if( z ){
- pTos->n = strlen(z) + 1;
- pTos->z = z;
- pTos->flags = MEM_Str | MEM_Ephem;
- }else{
- pTos->flags = MEM_Null;
- }
- break;
-}
-
-/* Opcode: MemStore P1 P2 *
-**
-** Write the top of the stack into memory location P1.
-** P1 should be a small integer since space is allocated
-** for all memory locations between 0 and P1 inclusive.
-**
-** After the data is stored in the memory location, the
-** stack is popped once if P2 is 1. If P2 is zero, then
-** the original data remains on the stack.
-*/
-case OP_MemStore: {
- int i = pOp->p1;
- Mem *pMem;
- assert( pTos>=p->aStack );
- if( i>=p->nMem ){
- int nOld = p->nMem;
- Mem *aMem;
- p->nMem = i + 5;
- aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
- if( aMem==0 ) goto no_mem;
- if( aMem!=p->aMem ){
- int j;
- for(j=0; j<nOld; j++){
- if( aMem[j].flags & MEM_Short ){
- aMem[j].z = aMem[j].zShort;
- }
- }
- }
- p->aMem = aMem;
- if( nOld<p->nMem ){
- memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
- }
- }
- Deephemeralize(pTos);
- pMem = &p->aMem[i];
- Release(pMem);
- *pMem = *pTos;
- if( pMem->flags & MEM_Dyn ){
- if( pOp->p2 ){
- pTos->flags = MEM_Null;
- }else{
- pMem->z = sqliteMallocRaw( pMem->n );
- if( pMem->z==0 ) goto no_mem;
- memcpy(pMem->z, pTos->z, pMem->n);
- }
- }else if( pMem->flags & MEM_Short ){
- pMem->z = pMem->zShort;
- }
- if( pOp->p2 ){
- Release(pTos);
- pTos--;
- }
- break;
-}
-
-/* Opcode: MemLoad P1 * *
-**
-** Push a copy of the value in memory location P1 onto the stack.
-**
-** If the value is a string, then the value pushed is a pointer to
-** the string that is stored in the memory location. If the memory
-** location is subsequently changed (using OP_MemStore) then the
-** value pushed onto the stack will change too.
-*/
-case OP_MemLoad: {
- int i = pOp->p1;
- assert( i>=0 && i<p->nMem );
- pTos++;
- memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
- if( pTos->flags & MEM_Str ){
- pTos->flags |= MEM_Ephem;
- pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
- }
- break;
-}
-
-/* Opcode: MemIncr P1 P2 *
-**
-** Increment the integer valued memory cell P1 by 1. If P2 is not zero
-** and the result after the increment is greater than zero, then jump
-** to P2.
-**
-** This instruction throws an error if the memory cell is not initially
-** an integer.
-*/
-case OP_MemIncr: {
- int i = pOp->p1;
- Mem *pMem;
- assert( i>=0 && i<p->nMem );
- pMem = &p->aMem[i];
- assert( pMem->flags==MEM_Int );
- pMem->i++;
- if( pOp->p2>0 && pMem->i>0 ){
- pc = pOp->p2 - 1;
- }
- break;
-}
-
-/* Opcode: AggReset * P2 *
-**
-** Reset the aggregator so that it no longer contains any data.
-** Future aggregator elements will contain P2 values each.
-*/
-case OP_AggReset: {
- sqliteVdbeAggReset(&p->agg);
- p->agg.nMem = pOp->p2;
- p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) );
- if( p->agg.apFunc==0 ) goto no_mem;
- break;
-}
-
-/* Opcode: AggInit * P2 P3
-**
-** Initialize the function parameters for an aggregate function.
-** The aggregate will operate out of aggregate column P2.
-** P3 is a pointer to the FuncDef structure for the function.
-*/
-case OP_AggInit: {
- int i = pOp->p2;
- assert( i>=0 && i<p->agg.nMem );
- p->agg.apFunc[i] = (FuncDef*)pOp->p3;
- break;
-}
-
-/* Opcode: AggFunc * P2 P3
-**
-** Execute the step function for an aggregate. The
-** function has P2 arguments. P3 is a pointer to the FuncDef
-** structure that specifies the function.
-**
-** The top of the stack must be an integer which is the index of
-** the aggregate column that corresponds to this aggregate function.
-** Ideally, this index would be another parameter, but there are
-** no free parameters left. The integer is popped from the stack.
-*/
-case OP_AggFunc: {
- int n = pOp->p2;
- int i;
- Mem *pMem, *pRec;
- char **azArgv = p->zArgv;
- sqlite_func ctx;
-
- assert( n>=0 );
- assert( pTos->flags==MEM_Int );
- pRec = &pTos[-n];
- assert( pRec>=p->aStack );
- for(i=0; i<n; i++, pRec++){
- if( pRec->flags & MEM_Null ){
- azArgv[i] = 0;
- }else{
- Stringify(pRec);
- azArgv[i] = pRec->z;
- }
- }
- i = pTos->i;
- assert( i>=0 && i<p->agg.nMem );
- ctx.pFunc = (FuncDef*)pOp->p3;
- pMem = &p->agg.pCurrent->aMem[i];
- ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */
- ctx.pAgg = pMem->z;
- ctx.cnt = ++pMem->i;
- ctx.isError = 0;
- ctx.isStep = 1;
- (ctx.pFunc->xStep)(&ctx, n, (const char**)azArgv);
- pMem->z = ctx.pAgg;
- pMem->flags = MEM_AggCtx;
- popStack(&pTos, n+1);
- if( ctx.isError ){
- rc = SQLITE_ERROR;
- }
- break;
-}
-
-/* Opcode: AggFocus * P2 *
-**
-** Pop the top of the stack and use that as an aggregator key. If
-** an aggregator with that same key already exists, then make the
-** aggregator the current aggregator and jump to P2. If no aggregator
-** with the given key exists, create one and make it current but
-** do not jump.
-**
-** The order of aggregator opcodes is important. The order is:
-** AggReset AggFocus AggNext. In other words, you must execute
-** AggReset first, then zero or more AggFocus operations, then
-** zero or more AggNext operations. You must not execute an AggFocus
-** in between an AggNext and an AggReset.
-*/
-case OP_AggFocus: {
- AggElem *pElem;
- char *zKey;
- int nKey;
-
- assert( pTos>=p->aStack );
- Stringify(pTos);
- zKey = pTos->z;
- nKey = pTos->n;
- pElem = sqliteHashFind(&p->agg.hash, zKey, nKey);
- if( pElem ){
- p->agg.pCurrent = pElem;
- pc = pOp->p2 - 1;
- }else{
- AggInsert(&p->agg, zKey, nKey);
- if( sqlite_malloc_failed ) goto no_mem;
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: AggSet * P2 *
-**
-** Move the top of the stack into the P2-th field of the current
-** aggregate. String values are duplicated into new memory.
-*/
-case OP_AggSet: {
- AggElem *pFocus = AggInFocus(p->agg);
- Mem *pMem;
- int i = pOp->p2;
- assert( pTos>=p->aStack );
- if( pFocus==0 ) goto no_mem;
- assert( i>=0 && i<p->agg.nMem );
- Deephemeralize(pTos);
- pMem = &pFocus->aMem[i];
- Release(pMem);
- *pMem = *pTos;
- if( pMem->flags & MEM_Dyn ){
- pTos->flags = MEM_Null;
- }else if( pMem->flags & MEM_Short ){
- pMem->z = pMem->zShort;
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: AggGet * P2 *
-**
-** Push a new entry onto the stack which is a copy of the P2-th field
-** of the current aggregate. Strings are not duplicated so
-** string values will be ephemeral.
-*/
-case OP_AggGet: {
- AggElem *pFocus = AggInFocus(p->agg);
- Mem *pMem;
- int i = pOp->p2;
- if( pFocus==0 ) goto no_mem;
- assert( i>=0 && i<p->agg.nMem );
- pTos++;
- pMem = &pFocus->aMem[i];
- *pTos = *pMem;
- if( pTos->flags & MEM_Str ){
- pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
- pTos->flags |= MEM_Ephem;
- }
- if( pTos->flags & MEM_AggCtx ){
- Release(pTos);
- pTos->flags = MEM_Null;
- }
- break;
-}
-
-/* Opcode: AggNext * P2 *
-**
-** Make the next aggregate value the current aggregate. The prior
-** aggregate is deleted. If all aggregate values have been consumed,
-** jump to P2.
-**
-** The order of aggregator opcodes is important. The order is:
-** AggReset AggFocus AggNext. In other words, you must execute
-** AggReset first, then zero or more AggFocus operations, then
-** zero or more AggNext operations. You must not execute an AggFocus
-** in between an AggNext and an AggReset.
-*/
-case OP_AggNext: {
- CHECK_FOR_INTERRUPT;
- if( p->agg.pSearch==0 ){
- p->agg.pSearch = sqliteHashFirst(&p->agg.hash);
- }else{
- p->agg.pSearch = sqliteHashNext(p->agg.pSearch);
- }
- if( p->agg.pSearch==0 ){
- pc = pOp->p2 - 1;
- } else {
- int i;
- sqlite_func ctx;
- Mem *aMem;
- p->agg.pCurrent = sqliteHashData(p->agg.pSearch);
- aMem = p->agg.pCurrent->aMem;
- for(i=0; i<p->agg.nMem; i++){
- int freeCtx;
- if( p->agg.apFunc[i]==0 ) continue;
- if( p->agg.apFunc[i]->xFinalize==0 ) continue;
- ctx.s.flags = MEM_Null;
- ctx.s.z = aMem[i].zShort;
- ctx.pAgg = (void*)aMem[i].z;
- freeCtx = aMem[i].z && aMem[i].z!=aMem[i].zShort;
- ctx.cnt = aMem[i].i;
- ctx.isStep = 0;
- ctx.pFunc = p->agg.apFunc[i];
- (*p->agg.apFunc[i]->xFinalize)(&ctx);
- if( freeCtx ){
- sqliteFree( aMem[i].z );
- }
- aMem[i] = ctx.s;
- if( aMem[i].flags & MEM_Short ){
- aMem[i].z = aMem[i].zShort;
- }
- }
- }
- break;
-}
-
-/* Opcode: SetInsert P1 * P3
-**
-** If Set P1 does not exist then create it. Then insert value
-** P3 into that set. If P3 is NULL, then insert the top of the
-** stack into the set.
-*/
-case OP_SetInsert: {
- int i = pOp->p1;
- if( p->nSet<=i ){
- int k;
- Set *aSet = sqliteRealloc(p->aSet, (i+1)*sizeof(p->aSet[0]) );
- if( aSet==0 ) goto no_mem;
- p->aSet = aSet;
- for(k=p->nSet; k<=i; k++){
- sqliteHashInit(&p->aSet[k].hash, SQLITE_HASH_BINARY, 1);
- }
- p->nSet = i+1;
- }
- if( pOp->p3 ){
- sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p);
- }else{
- assert( pTos>=p->aStack );
- Stringify(pTos);
- sqliteHashInsert(&p->aSet[i].hash, pTos->z, pTos->n, p);
- Release(pTos);
- pTos--;
- }
- if( sqlite_malloc_failed ) goto no_mem;
- break;
-}
-
-/* Opcode: SetFound P1 P2 *
-**
-** Pop the stack once and compare the value popped off with the
-** contents of set P1. If the element popped exists in set P1,
-** then jump to P2. Otherwise fall through.
-*/
-case OP_SetFound: {
- int i = pOp->p1;
- assert( pTos>=p->aStack );
- Stringify(pTos);
- if( i>=0 && i<p->nSet && sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)){
- pc = pOp->p2 - 1;
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: SetNotFound P1 P2 *
-**
-** Pop the stack once and compare the value popped off with the
-** contents of set P1. If the element popped does not exists in
-** set P1, then jump to P2. Otherwise fall through.
-*/
-case OP_SetNotFound: {
- int i = pOp->p1;
- assert( pTos>=p->aStack );
- Stringify(pTos);
- if( i<0 || i>=p->nSet ||
- sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)==0 ){
- pc = pOp->p2 - 1;
- }
- Release(pTos);
- pTos--;
- break;
-}
-
-/* Opcode: SetFirst P1 P2 *
-**
-** Read the first element from set P1 and push it onto the stack. If the
-** set is empty, push nothing and jump immediately to P2. This opcode is
-** used in combination with OP_SetNext to loop over all elements of a set.
-*/
-/* Opcode: SetNext P1 P2 *
-**
-** Read the next element from set P1 and push it onto the stack. If there
-** are no more elements in the set, do not do the push and fall through.
-** Otherwise, jump to P2 after pushing the next set element.
-*/
-case OP_SetFirst:
-case OP_SetNext: {
- Set *pSet;
- CHECK_FOR_INTERRUPT;
- if( pOp->p1<0 || pOp->p1>=p->nSet ){
- if( pOp->opcode==OP_SetFirst ) pc = pOp->p2 - 1;
- break;
- }
- pSet = &p->aSet[pOp->p1];
- if( pOp->opcode==OP_SetFirst ){
- pSet->prev = sqliteHashFirst(&pSet->hash);
- if( pSet->prev==0 ){
- pc = pOp->p2 - 1;
- break;
- }
- }else{
- if( pSet->prev ){
- pSet->prev = sqliteHashNext(pSet->prev);
- }
- if( pSet->prev==0 ){
- break;
- }else{
- pc = pOp->p2 - 1;
- }
- }
- pTos++;
- pTos->z = sqliteHashKey(pSet->prev);
- pTos->n = sqliteHashKeysize(pSet->prev);
- pTos->flags = MEM_Str | MEM_Ephem;
- break;
-}
-
-/* Opcode: Vacuum * * *
-**
-** Vacuum the entire database. This opcode will cause other virtual
-** machines to be created and run. It may not be called from within
-** a transaction.
-*/
-case OP_Vacuum: {
- if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- rc = sqliteRunVacuum(&p->zErrMsg, db);
- if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- break;
-}
-
-/* Opcode: StackDepth * * *
-**
-** Push an integer onto the stack which is the depth of the stack prior
-** to that integer being pushed.
-*/
-case OP_StackDepth: {
- int depth = (&pTos[1]) - p->aStack;
- pTos++;
- pTos->i = depth;
- pTos->flags = MEM_Int;
- break;
-}
-
-/* Opcode: StackReset * * *
-**
-** Pop a single integer off of the stack. Then pop the stack
-** as many times as necessary to get the depth of the stack down
-** to the value of the integer that was popped.
-*/
-case OP_StackReset: {
- int depth, goal;
- assert( pTos>=p->aStack );
- Integerify(pTos);
- goal = pTos->i;
- depth = (&pTos[1]) - p->aStack;
- assert( goal<depth );
- popStack(&pTos, depth-goal);
- break;
-}
-
-/* An other opcode is illegal...
-*/
-default: {
- sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode);
- sqliteSetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
- rc = SQLITE_INTERNAL;
- break;
-}
-
-/*****************************************************************************
-** The cases of the switch statement above this line should all be indented
-** by 6 spaces. But the left-most 6 spaces have been removed to improve the
-** readability. From this point on down, the normal indentation rules are
-** restored.
-*****************************************************************************/
- }
-
-#ifdef VDBE_PROFILE
- {
- long long elapse = hwtime() - start;
- pOp->cycles += elapse;
- pOp->cnt++;
-#if 0
- fprintf(stdout, "%10lld ", elapse);
- sqliteVdbePrintOp(stdout, origPc, &p->aOp[origPc]);
-#endif
- }
-#endif
-
- /* The following code adds nothing to the actual functionality
- ** of the program. It is only here for testing and debugging.
- ** On the other hand, it does burn CPU cycles every time through
- ** the evaluator loop. So we can leave it out when NDEBUG is defined.
- */
-#ifndef NDEBUG
- /* Sanity checking on the top element of the stack */
- if( pTos>=p->aStack ){
- assert( pTos->flags!=0 ); /* Must define some type */
- if( pTos->flags & MEM_Str ){
- int x = pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
- assert( x!=0 ); /* Strings must define a string subtype */
- assert( (x & (x-1))==0 ); /* Only one string subtype can be defined */
- assert( pTos->z!=0 ); /* Strings must have a value */
- /* Mem.z points to Mem.zShort iff the subtype is MEM_Short */
- assert( (pTos->flags & MEM_Short)==0 || pTos->z==pTos->zShort );
- assert( (pTos->flags & MEM_Short)!=0 || pTos->z!=pTos->zShort );
- }else{
- /* Cannot define a string subtype for non-string objects */
- assert( (pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 );
- }
- /* MEM_Null excludes all other types */
- assert( pTos->flags==MEM_Null || (pTos->flags&MEM_Null)==0 );
- }
- if( pc<-1 || pc>=p->nOp ){
- sqliteSetString(&p->zErrMsg, "jump destination out of range", (char*)0);
- rc = SQLITE_INTERNAL;
- }
- if( p->trace && pTos>=p->aStack ){
- int i;
- fprintf(p->trace, "Stack:");
- for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){
- if( pTos[i].flags & MEM_Null ){
- fprintf(p->trace, " NULL");
- }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
- fprintf(p->trace, " si:%d", pTos[i].i);
- }else if( pTos[i].flags & MEM_Int ){
- fprintf(p->trace, " i:%d", pTos[i].i);
- }else if( pTos[i].flags & MEM_Real ){
- fprintf(p->trace, " r:%g", pTos[i].r);
- }else if( pTos[i].flags & MEM_Str ){
- int j, k;
- char zBuf[100];
- zBuf[0] = ' ';
- if( pTos[i].flags & MEM_Dyn ){
- zBuf[1] = 'z';
- assert( (pTos[i].flags & (MEM_Static|MEM_Ephem))==0 );
- }else if( pTos[i].flags & MEM_Static ){
- zBuf[1] = 't';
- assert( (pTos[i].flags & (MEM_Dyn|MEM_Ephem))==0 );
- }else if( pTos[i].flags & MEM_Ephem ){
- zBuf[1] = 'e';
- assert( (pTos[i].flags & (MEM_Static|MEM_Dyn))==0 );
- }else{
- zBuf[1] = 's';
- }
- zBuf[2] = '[';
- k = 3;
- for(j=0; j<20 && j<pTos[i].n; j++){
- int c = pTos[i].z[j];
- if( c==0 && j==pTos[i].n-1 ) break;
- if( isprint(c) && !isspace(c) ){
- zBuf[k++] = c;
- }else{
- zBuf[k++] = '.';
- }
- }
- zBuf[k++] = ']';
- zBuf[k++] = 0;
- fprintf(p->trace, "%s", zBuf);
- }else{
- fprintf(p->trace, " ???");
- }
- }
- if( rc!=0 ) fprintf(p->trace," rc=%d",rc);
- fprintf(p->trace,"\n");
- }
-#endif
- } /* The end of the for(;;) loop the loops through opcodes */
-
- /* If we reach this point, it means that execution is finished.
- */
-vdbe_halt:
- CHECK_FOR_INTERRUPT
- if( rc ){
- p->rc = rc;
- rc = SQLITE_ERROR;
- }else{
- rc = SQLITE_DONE;
- }
- p->magic = VDBE_MAGIC_HALT;
- p->pTos = pTos;
- return rc;
-
- /* Jump to here if a malloc() fails. It's hard to get a malloc()
- ** to fail on a modern VM computer, so this code is untested.
- */
-no_mem:
- sqliteSetString(&p->zErrMsg, "out of memory", (char*)0);
- rc = SQLITE_NOMEM;
- goto vdbe_halt;
-
- /* Jump to here for an SQLITE_MISUSE error.
- */
-abort_due_to_misuse:
- rc = SQLITE_MISUSE;
- /* Fall thru into abort_due_to_error */
-
- /* Jump to here for any other kind of fatal error. The "rc" variable
- ** should hold the error number.
- */
-abort_due_to_error:
- if( p->zErrMsg==0 ){
- if( sqlite_malloc_failed ) rc = SQLITE_NOMEM;
- sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
- }
- goto vdbe_halt;
-
- /* Jump to here if the sqlite_interrupt() API sets the interrupt
- ** flag.
- */
-abort_due_to_interrupt:
- assert( db->flags & SQLITE_Interrupt );
- db->flags &= ~SQLITE_Interrupt;
- if( db->magic!=SQLITE_MAGIC_BUSY ){
- rc = SQLITE_MISUSE;
- }else{
- rc = SQLITE_INTERRUPT;
- }
- sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
- goto vdbe_halt;
-}
diff --git a/ext/sqlite/libsqlite/src/vdbe.h b/ext/sqlite/libsqlite/src/vdbe.h
deleted file mode 100644
index 6428598075..0000000000
--- a/ext/sqlite/libsqlite/src/vdbe.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** Header file for the Virtual DataBase Engine (VDBE)
-**
-** This header defines the interface to the virtual database engine
-** or VDBE. The VDBE implements an abstract machine that runs a
-** simple program to access and modify the underlying database.
-**
-** $Id$
-*/
-#ifndef _SQLITE_VDBE_H_
-#define _SQLITE_VDBE_H_
-#include <stdio.h>
-
-/*
-** A single VDBE is an opaque structure named "Vdbe". Only routines
-** in the source file sqliteVdbe.c are allowed to see the insides
-** of this structure.
-*/
-typedef struct Vdbe Vdbe;
-
-/*
-** A single instruction of the virtual machine has an opcode
-** and as many as three operands. The instruction is recorded
-** as an instance of the following structure:
-*/
-struct VdbeOp {
- u8 opcode; /* What operation to perform */
- int p1; /* First operand */
- int p2; /* Second parameter (often the jump destination) */
- char *p3; /* Third parameter */
- int p3type; /* P3_STATIC, P3_DYNAMIC or P3_POINTER */
-#ifdef VDBE_PROFILE
- int cnt; /* Number of times this instruction was executed */
- long long cycles; /* Total time spend executing this instruction */
-#endif
-};
-typedef struct VdbeOp VdbeOp;
-
-/*
-** A smaller version of VdbeOp used for the VdbeAddOpList() function because
-** it takes up less space.
-*/
-struct VdbeOpList {
- u8 opcode; /* What operation to perform */
- signed char p1; /* First operand */
- short int p2; /* Second parameter (often the jump destination) */
- char *p3; /* Third parameter */
-};
-typedef struct VdbeOpList VdbeOpList;
-
-/*
-** Allowed values of VdbeOp.p3type
-*/
-#define P3_NOTUSED 0 /* The P3 parameter is not used */
-#define P3_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
-#define P3_STATIC (-2) /* Pointer to a static string */
-#define P3_POINTER (-3) /* P3 is a pointer to some structure or object */
-
-/*
-** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
-** sqliteVdbeAddOpList() knows that the address is relative. Calling
-** the macro again restores the address.
-*/
-#define ADDR(X) (-1-(X))
-
-/*
-** The makefile scans the vdbe.c source file and creates the "opcodes.h"
-** header file that defines a number for each opcode used by the VDBE.
-*/
-#include "opcodes.h"
-
-/*
-** Prototypes for the VDBE interface. See comments on the implementation
-** for a description of what each of these routines does.
-*/
-Vdbe *sqliteVdbeCreate(sqlite*);
-void sqliteVdbeCreateCallback(Vdbe*, int*);
-int sqliteVdbeAddOp(Vdbe*,int,int,int);
-int sqliteVdbeOp3(Vdbe*,int,int,int,const char *zP3,int);
-int sqliteVdbeCode(Vdbe*,...);
-int sqliteVdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
-void sqliteVdbeChangeP1(Vdbe*, int addr, int P1);
-void sqliteVdbeChangeP2(Vdbe*, int addr, int P2);
-void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
-void sqliteVdbeDequoteP3(Vdbe*, int addr);
-int sqliteVdbeFindOp(Vdbe*, int, int);
-VdbeOp *sqliteVdbeGetOp(Vdbe*, int);
-int sqliteVdbeMakeLabel(Vdbe*);
-void sqliteVdbeDelete(Vdbe*);
-void sqliteVdbeMakeReady(Vdbe*,int,int);
-int sqliteVdbeExec(Vdbe*);
-int sqliteVdbeList(Vdbe*);
-int sqliteVdbeFinalize(Vdbe*,char**);
-void sqliteVdbeResolveLabel(Vdbe*, int);
-int sqliteVdbeCurrentAddr(Vdbe*);
-void sqliteVdbeTrace(Vdbe*,FILE*);
-void sqliteVdbeCompressSpace(Vdbe*,int);
-int sqliteVdbeReset(Vdbe*,char **);
-int sqliteVdbeSetVariables(Vdbe*,int,const char**);
-
-#endif
diff --git a/ext/sqlite/libsqlite/src/vdbeInt.h b/ext/sqlite/libsqlite/src/vdbeInt.h
deleted file mode 100644
index 79b6b51a58..0000000000
--- a/ext/sqlite/libsqlite/src/vdbeInt.h
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
-** 2003 September 6
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This is the header file for information that is private to the
-** VDBE. This information used to all be at the top of the single
-** source code file "vdbe.c". When that file became too big (over
-** 6000 lines long) it was split up into several smaller files and
-** this header information was factored out.
-*/
-
-/*
-** When converting from the native format to the key format and back
-** again, in addition to changing the byte order we invert the high-order
-** bit of the most significant byte. This causes negative numbers to
-** sort before positive numbers in the memcmp() function.
-*/
-#define keyToInt(X) (sqliteVdbeByteSwap(X) ^ 0x80000000)
-#define intToKey(X) (sqliteVdbeByteSwap((X) ^ 0x80000000))
-
-/*
-** The makefile scans this source file and creates the following
-** array of string constants which are the names of all VDBE opcodes.
-** This array is defined in a separate source code file named opcode.c
-** which is automatically generated by the makefile.
-*/
-extern char *sqliteOpcodeNames[];
-
-/*
-** SQL is translated into a sequence of instructions to be
-** executed by a virtual machine. Each instruction is an instance
-** of the following structure.
-*/
-typedef struct VdbeOp Op;
-
-/*
-** Boolean values
-*/
-typedef unsigned char Bool;
-
-/*
-** A cursor is a pointer into a single BTree within a database file.
-** The cursor can seek to a BTree entry with a particular key, or
-** loop over all entries of the Btree. You can also insert new BTree
-** entries or retrieve the key or data from the entry that the cursor
-** is currently pointing to.
-**
-** Every cursor that the virtual machine has open is represented by an
-** instance of the following structure.
-**
-** If the Cursor.isTriggerRow flag is set it means that this cursor is
-** really a single row that represents the NEW or OLD pseudo-table of
-** a row trigger. The data for the row is stored in Cursor.pData and
-** the rowid is in Cursor.iKey.
-*/
-struct Cursor {
- BtCursor *pCursor; /* The cursor structure of the backend */
- int lastRecno; /* Last recno from a Next or NextIdx operation */
- int nextRowid; /* Next rowid returned by OP_NewRowid */
- Bool recnoIsValid; /* True if lastRecno is valid */
- Bool keyAsData; /* The OP_Column command works on key instead of data */
- Bool atFirst; /* True if pointing to first entry */
- Bool useRandomRowid; /* Generate new record numbers semi-randomly */
- Bool nullRow; /* True if pointing to a row with no data */
- Bool nextRowidValid; /* True if the nextRowid field is valid */
- Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
- Bool deferredMoveto; /* A call to sqliteBtreeMoveto() is needed */
- int movetoTarget; /* Argument to the deferred sqliteBtreeMoveto() */
- Btree *pBt; /* Separate file holding temporary table */
- int nData; /* Number of bytes in pData */
- char *pData; /* Data for a NEW or OLD pseudo-table */
- int iKey; /* Key for the NEW or OLD pseudo-table row */
-};
-typedef struct Cursor Cursor;
-
-/*
-** A sorter builds a list of elements to be sorted. Each element of
-** the list is an instance of the following structure.
-*/
-typedef struct Sorter Sorter;
-struct Sorter {
- int nKey; /* Number of bytes in the key */
- char *zKey; /* The key by which we will sort */
- int nData; /* Number of bytes in the data */
- char *pData; /* The data associated with this key */
- Sorter *pNext; /* Next in the list */
-};
-
-/*
-** Number of buckets used for merge-sort.
-*/
-#define NSORT 30
-
-/*
-** Number of bytes of string storage space available to each stack
-** layer without having to malloc. NBFS is short for Number of Bytes
-** For Strings.
-*/
-#define NBFS 32
-
-/*
-** A single level of the stack or a single memory cell
-** is an instance of the following structure.
-*/
-struct Mem {
- int i; /* Integer value */
- int n; /* Number of characters in string value, including '\0' */
- int flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
- double r; /* Real value */
- char *z; /* String value */
- char zShort[NBFS]; /* Space for short strings */
-};
-typedef struct Mem Mem;
-
-/*
-** Allowed values for Mem.flags
-*/
-#define MEM_Null 0x0001 /* Value is NULL */
-#define MEM_Str 0x0002 /* Value is a string */
-#define MEM_Int 0x0004 /* Value is an integer */
-#define MEM_Real 0x0008 /* Value is a real number */
-#define MEM_Dyn 0x0010 /* Need to call sqliteFree() on Mem.z */
-#define MEM_Static 0x0020 /* Mem.z points to a static string */
-#define MEM_Ephem 0x0040 /* Mem.z points to an ephemeral string */
-#define MEM_Short 0x0080 /* Mem.z points to Mem.zShort */
-
-/* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
-** It indicates that the corresponding AggElem.aMem.z points to a
-** aggregate function context that needs to be finalized.
-*/
-#define MEM_AggCtx 0x0100 /* Mem.z points to an agg function context */
-
-/*
-** The "context" argument for a installable function. A pointer to an
-** instance of this structure is the first argument to the routines used
-** implement the SQL functions.
-**
-** There is a typedef for this structure in sqlite.h. So all routines,
-** even the public interface to SQLite, can use a pointer to this structure.
-** But this file is the only place where the internal details of this
-** structure are known.
-**
-** This structure is defined inside of vdbe.c because it uses substructures
-** (Mem) which are only defined there.
-*/
-struct sqlite_func {
- FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
- Mem s; /* The return value is stored here */
- void *pAgg; /* Aggregate context */
- u8 isError; /* Set to true for an error */
- u8 isStep; /* Current in the step function */
- int cnt; /* Number of times that the step function has been called */
-};
-
-/*
-** An Agg structure describes an Aggregator. Each Agg consists of
-** zero or more Aggregator elements (AggElem). Each AggElem contains
-** a key and one or more values. The values are used in processing
-** aggregate functions in a SELECT. The key is used to implement
-** the GROUP BY clause of a select.
-*/
-typedef struct Agg Agg;
-typedef struct AggElem AggElem;
-struct Agg {
- int nMem; /* Number of values stored in each AggElem */
- AggElem *pCurrent; /* The AggElem currently in focus */
- HashElem *pSearch; /* The hash element for pCurrent */
- Hash hash; /* Hash table of all aggregate elements */
- FuncDef **apFunc; /* Information about aggregate functions */
-};
-struct AggElem {
- char *zKey; /* The key to this AggElem */
- int nKey; /* Number of bytes in the key, including '\0' at end */
- Mem aMem[1]; /* The values for this AggElem */
-};
-
-/*
-** A Set structure is used for quick testing to see if a value
-** is part of a small set. Sets are used to implement code like
-** this:
-** x.y IN ('hi','hoo','hum')
-*/
-typedef struct Set Set;
-struct Set {
- Hash hash; /* A set is just a hash table */
- HashElem *prev; /* Previously accessed hash elemen */
-};
-
-/*
-** A Keylist is a bunch of keys into a table. The keylist can
-** grow without bound. The keylist stores the ROWIDs of database
-** records that need to be deleted or updated.
-*/
-typedef struct Keylist Keylist;
-struct Keylist {
- int nKey; /* Number of slots in aKey[] */
- int nUsed; /* Next unwritten slot in aKey[] */
- int nRead; /* Next unread slot in aKey[] */
- Keylist *pNext; /* Next block of keys */
- int aKey[1]; /* One or more keys. Extra space allocated as needed */
-};
-
-/*
-** A Context stores the last insert rowid, the last statement change count,
-** and the current statement change count (i.e. changes since last statement).
-** Elements of Context structure type make up the ContextStack, which is
-** updated by the ContextPush and ContextPop opcodes (used by triggers)
-*/
-typedef struct Context Context;
-struct Context {
- int lastRowid; /* Last insert rowid (from db->lastRowid) */
- int lsChange; /* Last statement change count (from db->lsChange) */
- int csChange; /* Current statement change count (from db->csChange) */
-};
-
-/*
-** An instance of the virtual machine. This structure contains the complete
-** state of the virtual machine.
-**
-** The "sqlite_vm" structure pointer that is returned by sqlite_compile()
-** is really a pointer to an instance of this structure.
-*/
-struct Vdbe {
- sqlite *db; /* The whole database */
- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
- FILE *trace; /* Write an execution trace here, if not NULL */
- int nOp; /* Number of instructions in the program */
- int nOpAlloc; /* Number of slots allocated for aOp[] */
- Op *aOp; /* Space to hold the virtual machine's program */
- int nLabel; /* Number of labels used */
- int nLabelAlloc; /* Number of slots allocated in aLabel[] */
- int *aLabel; /* Space to hold the labels */
- Mem *aStack; /* The operand stack, except string values */
- Mem *pTos; /* Top entry in the operand stack */
- char **zArgv; /* Text values used by the callback */
- char **azColName; /* Becomes the 4th parameter to callbacks */
- int nCursor; /* Number of slots in aCsr[] */
- Cursor *aCsr; /* One element of this array for each open cursor */
- Sorter *pSort; /* A linked list of objects to be sorted */
- FILE *pFile; /* At most one open file handler */
- int nField; /* Number of file fields */
- char **azField; /* Data for each file field */
- int nVar; /* Number of entries in azVariable[] */
- char **azVar; /* Values for the OP_Variable opcode */
- int *anVar; /* Length of each value in azVariable[] */
- u8 *abVar; /* TRUE if azVariable[i] needs to be sqliteFree()ed */
- char *zLine; /* A single line from the input file */
- int nLineAlloc; /* Number of spaces allocated for zLine */
- int magic; /* Magic number for sanity checking */
- int nMem; /* Number of memory locations currently allocated */
- Mem *aMem; /* The memory locations */
- Agg agg; /* Aggregate information */
- int nSet; /* Number of sets allocated */
- Set *aSet; /* An array of sets */
- int nCallback; /* Number of callbacks invoked so far */
- Keylist *pList; /* A list of ROWIDs */
- int keylistStackDepth; /* The size of the "keylist" stack */
- Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
- int contextStackDepth; /* The size of the "context" stack */
- Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
- int pc; /* The program counter */
- int rc; /* Value to return */
- unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
- int errorAction; /* Recovery action to do in case of an error */
- int undoTransOnError; /* If error, either ROLLBACK or COMMIT */
- int inTempTrans; /* True if temp database is transactioned */
- int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */
- int returnDepth; /* Next unused element in returnStack[] */
- int nResColumn; /* Number of columns in one row of the result set */
- char **azResColumn; /* Values for one row of result */
- int popStack; /* Pop the stack this much on entry to VdbeExec() */
- char *zErrMsg; /* Error message written here */
- u8 explain; /* True if EXPLAIN present on SQL command */
-};
-
-/*
-** The following are allowed values for Vdbe.magic
-*/
-#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
-#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
-#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
-#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
-
-/*
-** Function prototypes
-*/
-void sqliteVdbeCleanupCursor(Cursor*);
-void sqliteVdbeSorterReset(Vdbe*);
-void sqliteVdbeAggReset(Agg*);
-void sqliteVdbeKeylistFree(Keylist*);
-void sqliteVdbePopStack(Vdbe*,int);
-int sqliteVdbeCursorMoveto(Cursor*);
-int sqliteVdbeByteSwap(int);
-#if !defined(NDEBUG) || defined(VDBE_PROFILE)
-void sqliteVdbePrintOp(FILE*, int, Op*);
-#endif
diff --git a/ext/sqlite/libsqlite/src/vdbeaux.c b/ext/sqlite/libsqlite/src/vdbeaux.c
deleted file mode 100644
index c206bad4ab..0000000000
--- a/ext/sqlite/libsqlite/src/vdbeaux.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*
-** 2003 September 6
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code used for creating, destroying, and populating
-** a VDBE (or an "sqlite_vm" as it is known to the outside world.) Prior
-** to version 2.8.7, all this code was combined into the vdbe.c source file.
-** But that file was getting too big so this subroutines were split out.
-*/
-#include "sqliteInt.h"
-#include "os.h"
-#include <ctype.h>
-#include "vdbeInt.h"
-
-
-/*
-** When debugging the code generator in a symbolic debugger, one can
-** set the sqlite_vdbe_addop_trace to 1 and all opcodes will be printed
-** as they are added to the instruction stream.
-*/
-#ifndef NDEBUG
-int sqlite_vdbe_addop_trace = 0;
-#endif
-
-
-/*
-** Create a new virtual database engine.
-*/
-Vdbe *sqliteVdbeCreate(sqlite *db){
- Vdbe *p;
- p = sqliteMalloc( sizeof(Vdbe) );
- if( p==0 ) return 0;
- p->db = db;
- if( db->pVdbe ){
- db->pVdbe->pPrev = p;
- }
- p->pNext = db->pVdbe;
- p->pPrev = 0;
- db->pVdbe = p;
- p->magic = VDBE_MAGIC_INIT;
- return p;
-}
-
-/*
-** Turn tracing on or off
-*/
-void sqliteVdbeTrace(Vdbe *p, FILE *trace){
- p->trace = trace;
-}
-
-/*
-** Add a new instruction to the list of instructions current in the
-** VDBE. Return the address of the new instruction.
-**
-** Parameters:
-**
-** p Pointer to the VDBE
-**
-** op The opcode for this instruction
-**
-** p1, p2 First two of the three possible operands.
-**
-** Use the sqliteVdbeResolveLabel() function to fix an address and
-** the sqliteVdbeChangeP3() function to change the value of the P3
-** operand.
-*/
-int sqliteVdbeAddOp(Vdbe *p, int op, int p1, int p2){
- int i;
- VdbeOp *pOp;
-
- i = p->nOp;
- p->nOp++;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( i>=p->nOpAlloc ){
- int oldSize = p->nOpAlloc;
- Op *aNew;
- p->nOpAlloc = p->nOpAlloc*2 + 100;
- aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
- if( aNew==0 ){
- p->nOpAlloc = oldSize;
- return 0;
- }
- p->aOp = aNew;
- memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
- }
- pOp = &p->aOp[i];
- pOp->opcode = op;
- pOp->p1 = p1;
- if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){
- p2 = p->aLabel[-1-p2];
- }
- pOp->p2 = p2;
- pOp->p3 = 0;
- pOp->p3type = P3_NOTUSED;
-#ifndef NDEBUG
- if( sqlite_vdbe_addop_trace ) sqliteVdbePrintOp(0, i, &p->aOp[i]);
-#endif
- return i;
-}
-
-/*
-** Add an opcode that includes the p3 value.
-*/
-int sqliteVdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3, int p3type){
- int addr = sqliteVdbeAddOp(p, op, p1, p2);
- sqliteVdbeChangeP3(p, addr, zP3, p3type);
- return addr;
-}
-
-/*
-** Add multiple opcodes. The list is terminated by an opcode of 0.
-*/
-int sqliteVdbeCode(Vdbe *p, ...){
- int addr;
- va_list ap;
- int opcode, p1, p2;
- va_start(ap, p);
- addr = p->nOp;
- while( (opcode = va_arg(ap,int))!=0 ){
- p1 = va_arg(ap,int);
- p2 = va_arg(ap,int);
- sqliteVdbeAddOp(p, opcode, p1, p2);
- }
- va_end(ap);
- return addr;
-}
-
-
-
-/*
-** Create a new symbolic label for an instruction that has yet to be
-** coded. The symbolic label is really just a negative number. The
-** label can be used as the P2 value of an operation. Later, when
-** the label is resolved to a specific address, the VDBE will scan
-** through its operation list and change all values of P2 which match
-** the label into the resolved address.
-**
-** The VDBE knows that a P2 value is a label because labels are
-** always negative and P2 values are suppose to be non-negative.
-** Hence, a negative P2 value is a label that has yet to be resolved.
-*/
-int sqliteVdbeMakeLabel(Vdbe *p){
- int i;
- i = p->nLabel++;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( i>=p->nLabelAlloc ){
- int *aNew;
- p->nLabelAlloc = p->nLabelAlloc*2 + 10;
- aNew = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
- if( aNew==0 ){
- sqliteFree(p->aLabel);
- }
- p->aLabel = aNew;
- }
- if( p->aLabel==0 ){
- p->nLabel = 0;
- p->nLabelAlloc = 0;
- return 0;
- }
- p->aLabel[i] = -1;
- return -1-i;
-}
-
-/*
-** Resolve label "x" to be the address of the next instruction to
-** be inserted. The parameter "x" must have been obtained from
-** a prior call to sqliteVdbeMakeLabel().
-*/
-void sqliteVdbeResolveLabel(Vdbe *p, int x){
- int j;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( x<0 && (-x)<=p->nLabel && p->aOp ){
- if( p->aLabel[-1-x]==p->nOp ) return;
- assert( p->aLabel[-1-x]<0 );
- p->aLabel[-1-x] = p->nOp;
- for(j=0; j<p->nOp; j++){
- if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp;
- }
- }
-}
-
-/*
-** Return the address of the next instruction to be inserted.
-*/
-int sqliteVdbeCurrentAddr(Vdbe *p){
- assert( p->magic==VDBE_MAGIC_INIT );
- return p->nOp;
-}
-
-/*
-** Add a whole list of operations to the operation stack. Return the
-** address of the first operation added.
-*/
-int sqliteVdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
- int addr;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp >= p->nOpAlloc ){
- int oldSize = p->nOpAlloc;
- Op *aNew;
- p->nOpAlloc = p->nOpAlloc*2 + nOp + 10;
- aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
- if( aNew==0 ){
- p->nOpAlloc = oldSize;
- return 0;
- }
- p->aOp = aNew;
- memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
- }
- addr = p->nOp;
- if( nOp>0 ){
- int i;
- VdbeOpList const *pIn = aOp;
- for(i=0; i<nOp; i++, pIn++){
- int p2 = pIn->p2;
- VdbeOp *pOut = &p->aOp[i+addr];
- pOut->opcode = pIn->opcode;
- pOut->p1 = pIn->p1;
- pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;
- pOut->p3 = pIn->p3;
- pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;
-#ifndef NDEBUG
- if( sqlite_vdbe_addop_trace ){
- sqliteVdbePrintOp(0, i+addr, &p->aOp[i+addr]);
- }
-#endif
- }
- p->nOp += nOp;
- }
- return addr;
-}
-
-/*
-** Change the value of the P1 operand for a specific instruction.
-** This routine is useful when a large program is loaded from a
-** static array using sqliteVdbeAddOpList but we want to make a
-** few minor changes to the program.
-*/
-void sqliteVdbeChangeP1(Vdbe *p, int addr, int val){
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p && addr>=0 && p->nOp>addr && p->aOp ){
- p->aOp[addr].p1 = val;
- }
-}
-
-/*
-** Change the value of the P2 operand for a specific instruction.
-** This routine is useful for setting a jump destination.
-*/
-void sqliteVdbeChangeP2(Vdbe *p, int addr, int val){
- assert( val>=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p && addr>=0 && p->nOp>addr && p->aOp ){
- p->aOp[addr].p2 = val;
- }
-}
-
-/*
-** Change the value of the P3 operand for a specific instruction.
-** This routine is useful when a large program is loaded from a
-** static array using sqliteVdbeAddOpList but we want to make a
-** few minor changes to the program.
-**
-** If n>=0 then the P3 operand is dynamic, meaning that a copy of
-** the string is made into memory obtained from sqliteMalloc().
-** A value of n==0 means copy bytes of zP3 up to and including the
-** first null byte. If n>0 then copy n+1 bytes of zP3.
-**
-** If n==P3_STATIC it means that zP3 is a pointer to a constant static
-** string and we can just copy the pointer. n==P3_POINTER means zP3 is
-** a pointer to some object other than a string.
-**
-** If addr<0 then change P3 on the most recently inserted instruction.
-*/
-void sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
- Op *pOp;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p==0 || p->aOp==0 ) return;
- if( addr<0 || addr>=p->nOp ){
- addr = p->nOp - 1;
- if( addr<0 ) return;
- }
- pOp = &p->aOp[addr];
- if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){
- sqliteFree(pOp->p3);
- pOp->p3 = 0;
- }
- if( zP3==0 ){
- pOp->p3 = 0;
- pOp->p3type = P3_NOTUSED;
- }else if( n<0 ){
- pOp->p3 = (char*)zP3;
- pOp->p3type = n;
- }else{
- sqliteSetNString(&pOp->p3, zP3, n, 0);
- pOp->p3type = P3_DYNAMIC;
- }
-}
-
-/*
-** If the P3 operand to the specified instruction appears
-** to be a quoted string token, then this procedure removes
-** the quotes.
-**
-** The quoting operator can be either a grave ascent (ASCII 0x27)
-** or a double quote character (ASCII 0x22). Two quotes in a row
-** resolve to be a single actual quote character within the string.
-*/
-void sqliteVdbeDequoteP3(Vdbe *p, int addr){
- Op *pOp;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p->aOp==0 ) return;
- if( addr<0 || addr>=p->nOp ){
- addr = p->nOp - 1;
- if( addr<0 ) return;
- }
- pOp = &p->aOp[addr];
- if( pOp->p3==0 || pOp->p3[0]==0 ) return;
- if( pOp->p3type==P3_POINTER ) return;
- if( pOp->p3type!=P3_DYNAMIC ){
- pOp->p3 = sqliteStrDup(pOp->p3);
- pOp->p3type = P3_DYNAMIC;
- }
- sqliteDequote(pOp->p3);
-}
-
-/*
-** On the P3 argument of the given instruction, change all
-** strings of whitespace characters into a single space and
-** delete leading and trailing whitespace.
-*/
-void sqliteVdbeCompressSpace(Vdbe *p, int addr){
- unsigned char *z;
- int i, j;
- Op *pOp;
- assert( p->magic==VDBE_MAGIC_INIT );
- if( p->aOp==0 || addr<0 || addr>=p->nOp ) return;
- pOp = &p->aOp[addr];
- if( pOp->p3type==P3_POINTER ){
- return;
- }
- if( pOp->p3type!=P3_DYNAMIC ){
- pOp->p3 = sqliteStrDup(pOp->p3);
- pOp->p3type = P3_DYNAMIC;
- }
- z = (unsigned char*)pOp->p3;
- if( z==0 ) return;
- i = j = 0;
- while( isspace(z[i]) ){ i++; }
- while( z[i] ){
- if( isspace(z[i]) ){
- z[j++] = ' ';
- while( isspace(z[++i]) ){}
- }else{
- z[j++] = z[i++];
- }
- }
- while( j>0 && isspace(z[j-1]) ){ j--; }
- z[j] = 0;
-}
-
-/*
-** Search for the current program for the given opcode and P2
-** value. Return the address plus 1 if found and 0 if not found.
-*/
-int sqliteVdbeFindOp(Vdbe *p, int op, int p2){
- int i;
- assert( p->magic==VDBE_MAGIC_INIT );
- for(i=0; i<p->nOp; i++){
- if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;
- }
- return 0;
-}
-
-/*
-** Return the opcode for a given address.
-*/
-VdbeOp *sqliteVdbeGetOp(Vdbe *p, int addr){
- assert( p->magic==VDBE_MAGIC_INIT );
- assert( addr>=0 && addr<p->nOp );
- return &p->aOp[addr];
-}
-
-/*
-** The following group or routines are employed by installable functions
-** to return their results.
-**
-** The sqlite_set_result_string() routine can be used to return a string
-** value or to return a NULL. To return a NULL, pass in NULL for zResult.
-** A copy is made of the string before this routine returns so it is safe
-** to pass in an ephemeral string.
-**
-** sqlite_set_result_error() works like sqlite_set_result_string() except
-** that it signals a fatal error. The string argument, if any, is the
-** error message. If the argument is NULL a generic substitute error message
-** is used.
-**
-** The sqlite_set_result_int() and sqlite_set_result_double() set the return
-** value of the user function to an integer or a double.
-**
-** These routines are defined here in vdbe.c because they depend on knowing
-** the internals of the sqlite_func structure which is only defined in
-** this source file.
-*/
-char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){
- assert( !p->isStep );
- if( p->s.flags & MEM_Dyn ){
- sqliteFree(p->s.z);
- }
- if( zResult==0 ){
- p->s.flags = MEM_Null;
- n = 0;
- p->s.z = 0;
- p->s.n = 0;
- }else{
- if( n<0 ) n = strlen(zResult);
- if( n<NBFS-1 ){
- memcpy(p->s.zShort, zResult, n);
- p->s.zShort[n] = 0;
- p->s.flags = MEM_Str | MEM_Short;
- p->s.z = p->s.zShort;
- }else{
- p->s.z = sqliteMallocRaw( n+1 );
- if( p->s.z ){
- memcpy(p->s.z, zResult, n);
- p->s.z[n] = 0;
- }
- p->s.flags = MEM_Str | MEM_Dyn;
- }
- p->s.n = n+1;
- }
- return p->s.z;
-}
-void sqlite_set_result_int(sqlite_func *p, int iResult){
- assert( !p->isStep );
- if( p->s.flags & MEM_Dyn ){
- sqliteFree(p->s.z);
- }
- p->s.i = iResult;
- p->s.flags = MEM_Int;
-}
-void sqlite_set_result_double(sqlite_func *p, double rResult){
- assert( !p->isStep );
- if( p->s.flags & MEM_Dyn ){
- sqliteFree(p->s.z);
- }
- p->s.r = rResult;
- p->s.flags = MEM_Real;
-}
-void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){
- assert( !p->isStep );
- sqlite_set_result_string(p, zMsg, n);
- p->isError = 1;
-}
-
-/*
-** Extract the user data from a sqlite_func structure and return a
-** pointer to it.
-*/
-void *sqlite_user_data(sqlite_func *p){
- assert( p && p->pFunc );
- return p->pFunc->pUserData;
-}
-
-/*
-** Allocate or return the aggregate context for a user function. A new
-** context is allocated on the first call. Subsequent calls return the
-** same context that was returned on prior calls.
-**
-** This routine is defined here in vdbe.c because it depends on knowing
-** the internals of the sqlite_func structure which is only defined in
-** this source file.
-*/
-void *sqlite_aggregate_context(sqlite_func *p, int nByte){
- assert( p && p->pFunc && p->pFunc->xStep );
- if( p->pAgg==0 ){
- if( nByte<=NBFS ){
- p->pAgg = (void*)p->s.z;
- memset(p->pAgg, 0, nByte);
- }else{
- p->pAgg = sqliteMalloc( nByte );
- }
- }
- return p->pAgg;
-}
-
-/*
-** Return the number of times the Step function of a aggregate has been
-** called.
-**
-** This routine is defined here in vdbe.c because it depends on knowing
-** the internals of the sqlite_func structure which is only defined in
-** this source file.
-*/
-int sqlite_aggregate_count(sqlite_func *p){
- assert( p && p->pFunc && p->pFunc->xStep );
- return p->cnt;
-}
-
-#if !defined(NDEBUG) || defined(VDBE_PROFILE)
-/*
-** Print a single opcode. This routine is used for debugging only.
-*/
-void sqliteVdbePrintOp(FILE *pOut, int pc, Op *pOp){
- char *zP3;
- char zPtr[40];
- if( pOp->p3type==P3_POINTER ){
- sprintf(zPtr, "ptr(%#lx)", (long)pOp->p3);
- zP3 = zPtr;
- }else{
- zP3 = pOp->p3;
- }
- if( pOut==0 ) pOut = stdout;
- fprintf(pOut,"%4d %-12s %4d %4d %s\n",
- pc, sqliteOpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3 ? zP3 : "");
- fflush(pOut);
-}
-#endif
-
-/*
-** Give a listing of the program in the virtual machine.
-**
-** The interface is the same as sqliteVdbeExec(). But instead of
-** running the code, it invokes the callback once for each instruction.
-** This feature is used to implement "EXPLAIN".
-*/
-int sqliteVdbeList(
- Vdbe *p /* The VDBE */
-){
- sqlite *db = p->db;
- int i;
- int rc = SQLITE_OK;
- static char *azColumnNames[] = {
- "addr", "opcode", "p1", "p2", "p3",
- "int", "text", "int", "int", "text",
- 0
- };
-
- assert( p->popStack==0 );
- assert( p->explain );
- p->azColName = azColumnNames;
- p->azResColumn = p->zArgv;
- for(i=0; i<5; i++) p->zArgv[i] = p->aStack[i].zShort;
- i = p->pc;
- if( i>=p->nOp ){
- p->rc = SQLITE_OK;
- rc = SQLITE_DONE;
- }else if( db->flags & SQLITE_Interrupt ){
- db->flags &= ~SQLITE_Interrupt;
- if( db->magic!=SQLITE_MAGIC_BUSY ){
- p->rc = SQLITE_MISUSE;
- }else{
- p->rc = SQLITE_INTERRUPT;
- }
- rc = SQLITE_ERROR;
- sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
- }else{
- sprintf(p->zArgv[0],"%d",i);
- sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
- sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
- if( p->aOp[i].p3type==P3_POINTER ){
- sprintf(p->aStack[4].zShort, "ptr(%#lx)", (long)p->aOp[i].p3);
- p->zArgv[4] = p->aStack[4].zShort;
- }else{
- p->zArgv[4] = p->aOp[i].p3;
- }
- p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
- p->pc = i+1;
- p->azResColumn = p->zArgv;
- p->nResColumn = 5;
- p->rc = SQLITE_OK;
- rc = SQLITE_ROW;
- }
- return rc;
-}
-
-/*
-** Prepare a virtual machine for execution. This involves things such
-** as allocating stack space and initializing the program counter.
-** After the VDBE has be prepped, it can be executed by one or more
-** calls to sqliteVdbeExec().
-*/
-void sqliteVdbeMakeReady(
- Vdbe *p, /* The VDBE */
- int nVar, /* Number of '?' see in the SQL statement */
- int isExplain /* True if the EXPLAIN keywords is present */
-){
- int n;
-
- assert( p!=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
-
- /* Add a HALT instruction to the very end of the program.
- */
- if( p->nOp==0 || (p->aOp && p->aOp[p->nOp-1].opcode!=OP_Halt) ){
- sqliteVdbeAddOp(p, OP_Halt, 0, 0);
- }
-
- /* No instruction ever pushes more than a single element onto the
- ** stack. And the stack never grows on successive executions of the
- ** same loop. So the total number of instructions is an upper bound
- ** on the maximum stack depth required.
- **
- ** Allocation all the stack space we will ever need.
- */
- if( p->aStack==0 ){
- p->nVar = nVar;
- assert( nVar>=0 );
- n = isExplain ? 10 : p->nOp;
- p->aStack = sqliteMalloc(
- n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zArgv */
- + p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */
- );
- p->zArgv = (char**)&p->aStack[n];
- p->azColName = (char**)&p->zArgv[n];
- p->azVar = (char**)&p->azColName[n];
- p->anVar = (int*)&p->azVar[p->nVar];
- p->abVar = (u8*)&p->anVar[p->nVar];
- }
-
- sqliteHashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0);
- p->agg.pSearch = 0;
-#ifdef MEMORY_DEBUG
- if( sqliteOsFileExists("vdbe_trace") ){
- p->trace = stdout;
- }
-#endif
- p->pTos = &p->aStack[-1];
- p->pc = 0;
- p->rc = SQLITE_OK;
- p->uniqueCnt = 0;
- p->returnDepth = 0;
- p->errorAction = OE_Abort;
- p->undoTransOnError = 0;
- p->popStack = 0;
- p->explain |= isExplain;
- p->magic = VDBE_MAGIC_RUN;
-#ifdef VDBE_PROFILE
- {
- int i;
- for(i=0; i<p->nOp; i++){
- p->aOp[i].cnt = 0;
- p->aOp[i].cycles = 0;
- }
- }
-#endif
-}
-
-
-/*
-** Remove any elements that remain on the sorter for the VDBE given.
-*/
-void sqliteVdbeSorterReset(Vdbe *p){
- while( p->pSort ){
- Sorter *pSorter = p->pSort;
- p->pSort = pSorter->pNext;
- sqliteFree(pSorter->zKey);
- sqliteFree(pSorter->pData);
- sqliteFree(pSorter);
- }
-}
-
-/*
-** Reset an Agg structure. Delete all its contents.
-**
-** For installable aggregate functions, if the step function has been
-** called, make sure the finalizer function has also been called. The
-** finalizer might need to free memory that was allocated as part of its
-** private context. If the finalizer has not been called yet, call it
-** now.
-*/
-void sqliteVdbeAggReset(Agg *pAgg){
- int i;
- HashElem *p;
- for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){
- AggElem *pElem = sqliteHashData(p);
- assert( pAgg->apFunc!=0 );
- for(i=0; i<pAgg->nMem; i++){
- Mem *pMem = &pElem->aMem[i];
- if( pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
- sqlite_func ctx;
- ctx.pFunc = pAgg->apFunc[i];
- ctx.s.flags = MEM_Null;
- ctx.pAgg = pMem->z;
- ctx.cnt = pMem->i;
- ctx.isStep = 0;
- ctx.isError = 0;
- (*pAgg->apFunc[i]->xFinalize)(&ctx);
- if( pMem->z!=0 && pMem->z!=pMem->zShort ){
- sqliteFree(pMem->z);
- }
- if( ctx.s.flags & MEM_Dyn ){
- sqliteFree(ctx.s.z);
- }
- }else if( pMem->flags & MEM_Dyn ){
- sqliteFree(pMem->z);
- }
- }
- sqliteFree(pElem);
- }
- sqliteHashClear(&pAgg->hash);
- sqliteFree(pAgg->apFunc);
- pAgg->apFunc = 0;
- pAgg->pCurrent = 0;
- pAgg->pSearch = 0;
- pAgg->nMem = 0;
-}
-
-/*
-** Delete a keylist
-*/
-void sqliteVdbeKeylistFree(Keylist *p){
- while( p ){
- Keylist *pNext = p->pNext;
- sqliteFree(p);
- p = pNext;
- }
-}
-
-/*
-** Close a cursor and release all the resources that cursor happens
-** to hold.
-*/
-void sqliteVdbeCleanupCursor(Cursor *pCx){
- if( pCx->pCursor ){
- sqliteBtreeCloseCursor(pCx->pCursor);
- }
- if( pCx->pBt ){
- sqliteBtreeClose(pCx->pBt);
- }
- sqliteFree(pCx->pData);
- memset(pCx, 0, sizeof(Cursor));
-}
-
-/*
-** Close all cursors
-*/
-static void closeAllCursors(Vdbe *p){
- int i;
- for(i=0; i<p->nCursor; i++){
- sqliteVdbeCleanupCursor(&p->aCsr[i]);
- }
- sqliteFree(p->aCsr);
- p->aCsr = 0;
- p->nCursor = 0;
-}
-
-/*
-** Clean up the VM after execution.
-**
-** This routine will automatically close any cursors, lists, and/or
-** sorters that were left open. It also deletes the values of
-** variables in the azVariable[] array.
-*/
-static void Cleanup(Vdbe *p){
- int i;
- if( p->aStack ){
- Mem *pTos = p->pTos;
- while( pTos>=p->aStack ){
- if( pTos->flags & MEM_Dyn ){
- sqliteFree(pTos->z);
- }
- pTos--;
- }
- p->pTos = pTos;
- }
- closeAllCursors(p);
- if( p->aMem ){
- for(i=0; i<p->nMem; i++){
- if( p->aMem[i].flags & MEM_Dyn ){
- sqliteFree(p->aMem[i].z);
- }
- }
- }
- sqliteFree(p->aMem);
- p->aMem = 0;
- p->nMem = 0;
- if( p->pList ){
- sqliteVdbeKeylistFree(p->pList);
- p->pList = 0;
- }
- sqliteVdbeSorterReset(p);
- if( p->pFile ){
- if( p->pFile!=stdin ) fclose(p->pFile);
- p->pFile = 0;
- }
- if( p->azField ){
- sqliteFree(p->azField);
- p->azField = 0;
- }
- p->nField = 0;
- if( p->zLine ){
- sqliteFree(p->zLine);
- p->zLine = 0;
- }
- p->nLineAlloc = 0;
- sqliteVdbeAggReset(&p->agg);
- if( p->aSet ){
- for(i=0; i<p->nSet; i++){
- sqliteHashClear(&p->aSet[i].hash);
- }
- }
- sqliteFree(p->aSet);
- p->aSet = 0;
- p->nSet = 0;
- if( p->keylistStack ){
- int ii;
- for(ii = 0; ii < p->keylistStackDepth; ii++){
- sqliteVdbeKeylistFree(p->keylistStack[ii]);
- }
- sqliteFree(p->keylistStack);
- p->keylistStackDepth = 0;
- p->keylistStack = 0;
- }
- sqliteFree(p->contextStack);
- p->contextStack = 0;
- sqliteFree(p->zErrMsg);
- p->zErrMsg = 0;
-}
-
-/*
-** Clean up a VDBE after execution but do not delete the VDBE just yet.
-** Write any error messages into *pzErrMsg. Return the result code.
-**
-** After this routine is run, the VDBE should be ready to be executed
-** again.
-*/
-int sqliteVdbeReset(Vdbe *p, char **pzErrMsg){
- sqlite *db = p->db;
- int i;
-
- if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
- sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
- return SQLITE_MISUSE;
- }
- if( p->zErrMsg ){
- if( pzErrMsg && *pzErrMsg==0 ){
- *pzErrMsg = p->zErrMsg;
- }else{
- sqliteFree(p->zErrMsg);
- }
- p->zErrMsg = 0;
- }else if( p->rc ){
- sqliteSetString(pzErrMsg, sqlite_error_string(p->rc), (char*)0);
- }
- Cleanup(p);
- if( p->rc!=SQLITE_OK ){
- switch( p->errorAction ){
- case OE_Abort: {
- if( !p->undoTransOnError ){
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt ){
- sqliteBtreeRollbackCkpt(db->aDb[i].pBt);
- }
- }
- break;
- }
- /* Fall through to ROLLBACK */
- }
- case OE_Rollback: {
- sqliteRollbackAll(db);
- db->flags &= ~SQLITE_InTrans;
- db->onError = OE_Default;
- break;
- }
- default: {
- if( p->undoTransOnError ){
- sqliteRollbackAll(db);
- db->flags &= ~SQLITE_InTrans;
- db->onError = OE_Default;
- }
- break;
- }
- }
- sqliteRollbackInternalChanges(db);
- }
- for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt && db->aDb[i].inTrans==2 ){
- sqliteBtreeCommitCkpt(db->aDb[i].pBt);
- db->aDb[i].inTrans = 1;
- }
- }
- assert( p->pTos<&p->aStack[p->pc] || sqlite_malloc_failed==1 );
-#ifdef VDBE_PROFILE
- {
- FILE *out = fopen("vdbe_profile.out", "a");
- if( out ){
- int i;
- fprintf(out, "---- ");
- for(i=0; i<p->nOp; i++){
- fprintf(out, "%02x", p->aOp[i].opcode);
- }
- fprintf(out, "\n");
- for(i=0; i<p->nOp; i++){
- fprintf(out, "%6d %10lld %8lld ",
- p->aOp[i].cnt,
- p->aOp[i].cycles,
- p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
- );
- sqliteVdbePrintOp(out, i, &p->aOp[i]);
- }
- fclose(out);
- }
- }
-#endif
- p->magic = VDBE_MAGIC_INIT;
- return p->rc;
-}
-
-/*
-** Clean up and delete a VDBE after execution. Return an integer which is
-** the result code. Write any error message text into *pzErrMsg.
-*/
-int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
- int rc;
- sqlite *db;
-
- if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
- sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
- return SQLITE_MISUSE;
- }
- db = p->db;
- rc = sqliteVdbeReset(p, pzErrMsg);
- sqliteVdbeDelete(p);
- if( db->want_to_close && db->pVdbe==0 ){
- sqlite_close(db);
- }
- if( rc==SQLITE_SCHEMA ){
- sqliteResetInternalSchema(db, 0);
- }
- return rc;
-}
-
-/*
-** Set the values of all variables. Variable $1 in the original SQL will
-** be the string azValue[0]. $2 will have the value azValue[1]. And
-** so forth. If a value is out of range (for example $3 when nValue==2)
-** then its value will be NULL.
-**
-** This routine overrides any prior call.
-*/
-int sqlite_bind(sqlite_vm *pVm, int i, const char *zVal, int len, int copy){
- Vdbe *p = (Vdbe*)pVm;
- if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 ){
- return SQLITE_MISUSE;
- }
- if( i<1 || i>p->nVar ){
- return SQLITE_RANGE;
- }
- i--;
- if( p->abVar[i] ){
- sqliteFree(p->azVar[i]);
- }
- if( zVal==0 ){
- copy = 0;
- len = 0;
- }
- if( len<0 ){
- len = strlen(zVal)+1;
- }
- if( copy ){
- p->azVar[i] = sqliteMalloc( len );
- if( p->azVar[i] ) memcpy(p->azVar[i], zVal, len);
- }else{
- p->azVar[i] = (char*)zVal;
- }
- p->abVar[i] = copy;
- p->anVar[i] = len;
- return SQLITE_OK;
-}
-
-
-/*
-** Delete an entire VDBE.
-*/
-void sqliteVdbeDelete(Vdbe *p){
- int i;
- if( p==0 ) return;
- Cleanup(p);
- if( p->pPrev ){
- p->pPrev->pNext = p->pNext;
- }else{
- assert( p->db->pVdbe==p );
- p->db->pVdbe = p->pNext;
- }
- if( p->pNext ){
- p->pNext->pPrev = p->pPrev;
- }
- p->pPrev = p->pNext = 0;
- if( p->nOpAlloc==0 ){
- p->aOp = 0;
- p->nOp = 0;
- }
- for(i=0; i<p->nOp; i++){
- if( p->aOp[i].p3type==P3_DYNAMIC ){
- sqliteFree(p->aOp[i].p3);
- }
- }
- for(i=0; i<p->nVar; i++){
- if( p->abVar[i] ) sqliteFree(p->azVar[i]);
- }
- sqliteFree(p->aOp);
- sqliteFree(p->aLabel);
- sqliteFree(p->aStack);
- p->magic = VDBE_MAGIC_DEAD;
- sqliteFree(p);
-}
-
-/*
-** Convert an integer in between the native integer format and
-** the bigEndian format used as the record number for tables.
-**
-** The bigEndian format (most significant byte first) is used for
-** record numbers so that records will sort into the correct order
-** even though memcmp() is used to compare the keys. On machines
-** whose native integer format is little endian (ex: i486) the
-** order of bytes is reversed. On native big-endian machines
-** (ex: Alpha, Sparc, Motorola) the byte order is the same.
-**
-** This function is its own inverse. In other words
-**
-** X == byteSwap(byteSwap(X))
-*/
-int sqliteVdbeByteSwap(int x){
- union {
- char zBuf[sizeof(int)];
- int i;
- } ux;
- ux.zBuf[3] = x&0xff;
- ux.zBuf[2] = (x>>8)&0xff;
- ux.zBuf[1] = (x>>16)&0xff;
- ux.zBuf[0] = (x>>24)&0xff;
- return ux.i;
-}
-
-/*
-** If a MoveTo operation is pending on the given cursor, then do that
-** MoveTo now. Return an error code. If no MoveTo is pending, this
-** routine does nothing and returns SQLITE_OK.
-*/
-int sqliteVdbeCursorMoveto(Cursor *p){
- if( p->deferredMoveto ){
- int res;
- extern int sqlite_search_count;
- sqliteBtreeMoveto(p->pCursor, (char*)&p->movetoTarget, sizeof(int), &res);
- p->lastRecno = keyToInt(p->movetoTarget);
- p->recnoIsValid = res==0;
- if( res<0 ){
- sqliteBtreeNext(p->pCursor, &res);
- }
- sqlite_search_count++;
- p->deferredMoveto = 0;
- }
- return SQLITE_OK;
-}
diff --git a/ext/sqlite/libsqlite/src/where.c b/ext/sqlite/libsqlite/src/where.c
deleted file mode 100644
index cffeccbed7..0000000000
--- a/ext/sqlite/libsqlite/src/where.c
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This module contains C code that generates VDBE code used to process
-** the WHERE clause of SQL statements.
-**
-** $Id$
-*/
-#include "sqliteInt.h"
-
-/*
-** The query generator uses an array of instances of this structure to
-** help it analyze the subexpressions of the WHERE clause. Each WHERE
-** clause subexpression is separated from the others by an AND operator.
-*/
-typedef struct ExprInfo ExprInfo;
-struct ExprInfo {
- Expr *p; /* Pointer to the subexpression */
- u8 indexable; /* True if this subexprssion is usable by an index */
- short int idxLeft; /* p->pLeft is a column in this table number. -1 if
- ** p->pLeft is not the column of any table */
- short int idxRight; /* p->pRight is a column in this table number. -1 if
- ** p->pRight is not the column of any table */
- unsigned prereqLeft; /* Bitmask of tables referenced by p->pLeft */
- unsigned prereqRight; /* Bitmask of tables referenced by p->pRight */
- unsigned prereqAll; /* Bitmask of tables referenced by p */
-};
-
-/*
-** An instance of the following structure keeps track of a mapping
-** between VDBE cursor numbers and bitmasks. The VDBE cursor numbers
-** are small integers contained in SrcList_item.iCursor and Expr.iTable
-** fields. For any given WHERE clause, we want to track which cursors
-** are being used, so we assign a single bit in a 32-bit word to track
-** that cursor. Then a 32-bit integer is able to show the set of all
-** cursors being used.
-*/
-typedef struct ExprMaskSet ExprMaskSet;
-struct ExprMaskSet {
- int n; /* Number of assigned cursor values */
- int ix[31]; /* Cursor assigned to each bit */
-};
-
-/*
-** Determine the number of elements in an array.
-*/
-#define ARRAYSIZE(X) (sizeof(X)/sizeof(X[0]))
-
-/*
-** This routine is used to divide the WHERE expression into subexpressions
-** separated by the AND operator.
-**
-** aSlot[] is an array of subexpressions structures.
-** There are nSlot spaces left in this array. This routine attempts to
-** split pExpr into subexpressions and fills aSlot[] with those subexpressions.
-** The return value is the number of slots filled.
-*/
-static int exprSplit(int nSlot, ExprInfo *aSlot, Expr *pExpr){
- int cnt = 0;
- if( pExpr==0 || nSlot<1 ) return 0;
- if( nSlot==1 || pExpr->op!=TK_AND ){
- aSlot[0].p = pExpr;
- return 1;
- }
- if( pExpr->pLeft->op!=TK_AND ){
- aSlot[0].p = pExpr->pLeft;
- cnt = 1 + exprSplit(nSlot-1, &aSlot[1], pExpr->pRight);
- }else{
- cnt = exprSplit(nSlot, aSlot, pExpr->pLeft);
- cnt += exprSplit(nSlot-cnt, &aSlot[cnt], pExpr->pRight);
- }
- return cnt;
-}
-
-/*
-** Initialize an expression mask set
-*/
-#define initMaskSet(P) memset(P, 0, sizeof(*P))
-
-/*
-** Return the bitmask for the given cursor. Assign a new bitmask
-** if this is the first time the cursor has been seen.
-*/
-static int getMask(ExprMaskSet *pMaskSet, int iCursor){
- int i;
- for(i=0; i<pMaskSet->n; i++){
- if( pMaskSet->ix[i]==iCursor ) return 1<<i;
- }
- if( i==pMaskSet->n && i<ARRAYSIZE(pMaskSet->ix) ){
- pMaskSet->n++;
- pMaskSet->ix[i] = iCursor;
- return 1<<i;
- }
- return 0;
-}
-
-/*
-** Destroy an expression mask set
-*/
-#define freeMaskSet(P) /* NO-OP */
-
-/*
-** This routine walks (recursively) an expression tree and generates
-** a bitmask indicating which tables are used in that expression
-** tree.
-**
-** In order for this routine to work, the calling function must have
-** previously invoked sqliteExprResolveIds() on the expression. See
-** the header comment on that routine for additional information.
-** The sqliteExprResolveIds() routines looks for column names and
-** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
-** the VDBE cursor number of the table.
-*/
-static int exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){
- unsigned int mask = 0;
- if( p==0 ) return 0;
- if( p->op==TK_COLUMN ){
- mask = getMask(pMaskSet, p->iTable);
- if( mask==0 ) mask = -1;
- return mask;
- }
- if( p->pRight ){
- mask = exprTableUsage(pMaskSet, p->pRight);
- }
- if( p->pLeft ){
- mask |= exprTableUsage(pMaskSet, p->pLeft);
- }
- if( p->pList ){
- int i;
- for(i=0; i<p->pList->nExpr; i++){
- mask |= exprTableUsage(pMaskSet, p->pList->a[i].pExpr);
- }
- }
- return mask;
-}
-
-/*
-** Return TRUE if the given operator is one of the operators that is
-** allowed for an indexable WHERE clause. The allowed operators are
-** "=", "<", ">", "<=", ">=", and "IN".
-*/
-static int allowedOp(int op){
- switch( op ){
- case TK_LT:
- case TK_LE:
- case TK_GT:
- case TK_GE:
- case TK_EQ:
- case TK_IN:
- return 1;
- default:
- return 0;
- }
-}
-
-/*
-** The input to this routine is an ExprInfo structure with only the
-** "p" field filled in. The job of this routine is to analyze the
-** subexpression and populate all the other fields of the ExprInfo
-** structure.
-*/
-static void exprAnalyze(ExprMaskSet *pMaskSet, ExprInfo *pInfo){
- Expr *pExpr = pInfo->p;
- pInfo->prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
- pInfo->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
- pInfo->prereqAll = exprTableUsage(pMaskSet, pExpr);
- pInfo->indexable = 0;
- pInfo->idxLeft = -1;
- pInfo->idxRight = -1;
- if( allowedOp(pExpr->op) && (pInfo->prereqRight & pInfo->prereqLeft)==0 ){
- if( pExpr->pRight && pExpr->pRight->op==TK_COLUMN ){
- pInfo->idxRight = pExpr->pRight->iTable;
- pInfo->indexable = 1;
- }
- if( pExpr->pLeft->op==TK_COLUMN ){
- pInfo->idxLeft = pExpr->pLeft->iTable;
- pInfo->indexable = 1;
- }
- }
-}
-
-/*
-** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the
-** left-most table in the FROM clause of that same SELECT statement and
-** the table has a cursor number of "base".
-**
-** This routine attempts to find an index for pTab that generates the
-** correct record sequence for the given ORDER BY clause. The return value
-** is a pointer to an index that does the job. NULL is returned if the
-** table has no index that will generate the correct sort order.
-**
-** If there are two or more indices that generate the correct sort order
-** and pPreferredIdx is one of those indices, then return pPreferredIdx.
-**
-** nEqCol is the number of columns of pPreferredIdx that are used as
-** equality constraints. Any index returned must have exactly this same
-** set of columns. The ORDER BY clause only matches index columns beyond the
-** the first nEqCol columns.
-**
-** All terms of the ORDER BY clause must be either ASC or DESC. The
-** *pbRev value is set to 1 if the ORDER BY clause is all DESC and it is
-** set to 0 if the ORDER BY clause is all ASC.
-*/
-static Index *findSortingIndex(
- Table *pTab, /* The table to be sorted */
- int base, /* Cursor number for pTab */
- ExprList *pOrderBy, /* The ORDER BY clause */
- Index *pPreferredIdx, /* Use this index, if possible and not NULL */
- int nEqCol, /* Number of index columns used with == constraints */
- int *pbRev /* Set to 1 if ORDER BY is DESC */
-){
- int i, j;
- Index *pMatch;
- Index *pIdx;
- int sortOrder;
-
- assert( pOrderBy!=0 );
- assert( pOrderBy->nExpr>0 );
- sortOrder = pOrderBy->a[0].sortOrder & SQLITE_SO_DIRMASK;
- for(i=0; i<pOrderBy->nExpr; i++){
- Expr *p;
- if( (pOrderBy->a[i].sortOrder & SQLITE_SO_DIRMASK)!=sortOrder ){
- /* Indices can only be used if all ORDER BY terms are either
- ** DESC or ASC. Indices cannot be used on a mixture. */
- return 0;
- }
- if( (pOrderBy->a[i].sortOrder & SQLITE_SO_TYPEMASK)!=SQLITE_SO_UNK ){
- /* Do not sort by index if there is a COLLATE clause */
- return 0;
- }
- p = pOrderBy->a[i].pExpr;
- if( p->op!=TK_COLUMN || p->iTable!=base ){
- /* Can not use an index sort on anything that is not a column in the
- ** left-most table of the FROM clause */
- return 0;
- }
- }
-
- /* If we get this far, it means the ORDER BY clause consists only of
- ** ascending columns in the left-most table of the FROM clause. Now
- ** check for a matching index.
- */
- pMatch = 0;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int nExpr = pOrderBy->nExpr;
- if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;
- for(i=j=0; i<nEqCol; i++){
- if( pPreferredIdx->aiColumn[i]!=pIdx->aiColumn[i] ) break;
- if( j<nExpr && pOrderBy->a[j].pExpr->iColumn==pIdx->aiColumn[i] ){ j++; }
- }
- if( i<nEqCol ) continue;
- for(i=0; i+j<nExpr; i++){
- if( pOrderBy->a[i+j].pExpr->iColumn!=pIdx->aiColumn[i+nEqCol] ) break;
- }
- if( i+j>=nExpr ){
- pMatch = pIdx;
- if( pIdx==pPreferredIdx ) break;
- }
- }
- if( pMatch && pbRev ){
- *pbRev = sortOrder==SQLITE_SO_DESC;
- }
- return pMatch;
-}
-
-/*
-** Disable a term in the WHERE clause. Except, do not disable the term
-** if it controls a LEFT OUTER JOIN and it did not originate in the ON
-** or USING clause of that join.
-**
-** Consider the term t2.z='ok' in the following queries:
-**
-** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
-** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
-** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
-**
-** The t2.z='ok' is disabled in the in (2) because it did not originate
-** in the ON clause. The term is disabled in (3) because it is not part
-** of a LEFT OUTER JOIN. In (1), the term is not disabled.
-**
-** Disabling a term causes that term to not be tested in the inner loop
-** of the join. Disabling is an optimization. We would get the correct
-** results if nothing were ever disabled, but joins might run a little
-** slower. The trick is to disable as much as we can without disabling
-** too much. If we disabled in (1), we'd get the wrong answer.
-** See ticket #813.
-*/
-static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
- Expr *pExpr = *ppExpr;
- if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
- *ppExpr = 0;
- }
-}
-
-/*
-** Generate the beginning of the loop used for WHERE clause processing.
-** The return value is a pointer to an (opaque) structure that contains
-** information needed to terminate the loop. Later, the calling routine
-** should invoke sqliteWhereEnd() with the return value of this function
-** in order to complete the WHERE clause processing.
-**
-** If an error occurs, this routine returns NULL.
-**
-** The basic idea is to do a nested loop, one loop for each table in
-** the FROM clause of a select. (INSERT and UPDATE statements are the
-** same as a SELECT with only a single table in the FROM clause.) For
-** example, if the SQL is this:
-**
-** SELECT * FROM t1, t2, t3 WHERE ...;
-**
-** Then the code generated is conceptually like the following:
-**
-** foreach row1 in t1 do \ Code generated
-** foreach row2 in t2 do |-- by sqliteWhereBegin()
-** foreach row3 in t3 do /
-** ...
-** end \ Code generated
-** end |-- by sqliteWhereEnd()
-** end /
-**
-** There are Btree cursors associated with each table. t1 uses cursor
-** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor.
-** And so forth. This routine generates code to open those VDBE cursors
-** and sqliteWhereEnd() generates the code to close them.
-**
-** If the WHERE clause is empty, the foreach loops must each scan their
-** entire tables. Thus a three-way join is an O(N^3) operation. But if
-** the tables have indices and there are terms in the WHERE clause that
-** refer to those indices, a complete table scan can be avoided and the
-** code will run much faster. Most of the work of this routine is checking
-** to see if there are indices that can be used to speed up the loop.
-**
-** Terms of the WHERE clause are also used to limit which rows actually
-** make it to the "..." in the middle of the loop. After each "foreach",
-** terms of the WHERE clause that use only terms in that loop and outer
-** loops are evaluated and if false a jump is made around all subsequent
-** inner loops (or around the "..." if the test occurs within the inner-
-** most loop)
-**
-** OUTER JOINS
-**
-** An outer join of tables t1 and t2 is conceptally coded as follows:
-**
-** foreach row1 in t1 do
-** flag = 0
-** foreach row2 in t2 do
-** start:
-** ...
-** flag = 1
-** end
-** if flag==0 then
-** move the row2 cursor to a null row
-** goto start
-** fi
-** end
-**
-** ORDER BY CLAUSE PROCESSING
-**
-** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
-** if there is one. If there is no ORDER BY clause or if this routine
-** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
-**
-** If an index can be used so that the natural output order of the table
-** scan is correct for the ORDER BY clause, then that index is used and
-** *ppOrderBy is set to NULL. This is an optimization that prevents an
-** unnecessary sort of the result set if an index appropriate for the
-** ORDER BY clause already exists.
-**
-** If the where clause loops cannot be arranged to provide the correct
-** output order, then the *ppOrderBy is unchanged.
-*/
-WhereInfo *sqliteWhereBegin(
- Parse *pParse, /* The parser context */
- SrcList *pTabList, /* A list of all tables to be scanned */
- Expr *pWhere, /* The WHERE clause */
- int pushKey, /* If TRUE, leave the table key on the stack */
- ExprList **ppOrderBy /* An ORDER BY clause, or NULL */
-){
- int i; /* Loop counter */
- WhereInfo *pWInfo; /* Will become the return value of this function */
- Vdbe *v = pParse->pVdbe; /* The virtual database engine */
- int brk, cont = 0; /* Addresses used during code generation */
- int nExpr; /* Number of subexpressions in the WHERE clause */
- int loopMask; /* One bit set for each outer loop */
- int haveKey; /* True if KEY is on the stack */
- ExprMaskSet maskSet; /* The expression mask set */
- int iDirectEq[32]; /* Term of the form ROWID==X for the N-th table */
- int iDirectLt[32]; /* Term of the form ROWID<X or ROWID<=X */
- int iDirectGt[32]; /* Term of the form ROWID>X or ROWID>=X */
- ExprInfo aExpr[101]; /* The WHERE clause is divided into these expressions */
-
- /* pushKey is only allowed if there is a single table (as in an INSERT or
- ** UPDATE statement)
- */
- assert( pushKey==0 || pTabList->nSrc==1 );
-
- /* Split the WHERE clause into separate subexpressions where each
- ** subexpression is separated by an AND operator. If the aExpr[]
- ** array fills up, the last entry might point to an expression which
- ** contains additional unfactored AND operators.
- */
- initMaskSet(&maskSet);
- memset(aExpr, 0, sizeof(aExpr));
- nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);
- if( nExpr==ARRAYSIZE(aExpr) ){
- sqliteErrorMsg(pParse, "WHERE clause too complex - no more "
- "than %d terms allowed", (int)ARRAYSIZE(aExpr)-1);
- return 0;
- }
-
- /* Allocate and initialize the WhereInfo structure that will become the
- ** return value.
- */
- pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
- if( sqlite_malloc_failed ){
- sqliteFree(pWInfo);
- return 0;
- }
- pWInfo->pParse = pParse;
- pWInfo->pTabList = pTabList;
- pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab;
- pWInfo->iBreak = sqliteVdbeMakeLabel(v);
-
- /* Special case: a WHERE clause that is constant. Evaluate the
- ** expression and either jump over all of the code or fall thru.
- */
- if( pWhere && (pTabList->nSrc==0 || sqliteExprIsConstant(pWhere)) ){
- sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
- pWhere = 0;
- }
-
- /* Analyze all of the subexpressions.
- */
- for(i=0; i<nExpr; i++){
- exprAnalyze(&maskSet, &aExpr[i]);
-
- /* If we are executing a trigger body, remove all references to
- ** new.* and old.* tables from the prerequisite masks.
- */
- if( pParse->trigStack ){
- int x;
- if( (x = pParse->trigStack->newIdx) >= 0 ){
- int mask = ~getMask(&maskSet, x);
- aExpr[i].prereqRight &= mask;
- aExpr[i].prereqLeft &= mask;
- aExpr[i].prereqAll &= mask;
- }
- if( (x = pParse->trigStack->oldIdx) >= 0 ){
- int mask = ~getMask(&maskSet, x);
- aExpr[i].prereqRight &= mask;
- aExpr[i].prereqLeft &= mask;
- aExpr[i].prereqAll &= mask;
- }
- }
- }
-
- /* Figure out what index to use (if any) for each nested loop.
- ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested
- ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner
- ** loop.
- **
- ** If terms exist that use the ROWID of any table, then set the
- ** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table
- ** to the index of the term containing the ROWID. We always prefer
- ** to use a ROWID which can directly access a table rather than an
- ** index which requires reading an index first to get the rowid then
- ** doing a second read of the actual database table.
- **
- ** Actually, if there are more than 32 tables in the join, only the
- ** first 32 tables are candidates for indices. This is (again) due
- ** to the limit of 32 bits in an integer bitmask.
- */
- loopMask = 0;
- for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++){
- int j;
- int iCur = pTabList->a[i].iCursor; /* The cursor for this table */
- int mask = getMask(&maskSet, iCur); /* Cursor mask for this table */
- Table *pTab = pTabList->a[i].pTab;
- Index *pIdx;
- Index *pBestIdx = 0;
- int bestScore = 0;
-
- /* Check to see if there is an expression that uses only the
- ** ROWID field of this table. For terms of the form ROWID==expr
- ** set iDirectEq[i] to the index of the term. For terms of the
- ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index.
- ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i].
- **
- ** (Added:) Treat ROWID IN expr like ROWID=expr.
- */
- pWInfo->a[i].iCur = -1;
- iDirectEq[i] = -1;
- iDirectLt[i] = -1;
- iDirectGt[i] = -1;
- for(j=0; j<nExpr; j++){
- if( aExpr[j].idxLeft==iCur && aExpr[j].p->pLeft->iColumn<0
- && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
- switch( aExpr[j].p->op ){
- case TK_IN:
- case TK_EQ: iDirectEq[i] = j; break;
- case TK_LE:
- case TK_LT: iDirectLt[i] = j; break;
- case TK_GE:
- case TK_GT: iDirectGt[i] = j; break;
- }
- }
- if( aExpr[j].idxRight==iCur && aExpr[j].p->pRight->iColumn<0
- && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){
- switch( aExpr[j].p->op ){
- case TK_EQ: iDirectEq[i] = j; break;
- case TK_LE:
- case TK_LT: iDirectGt[i] = j; break;
- case TK_GE:
- case TK_GT: iDirectLt[i] = j; break;
- }
- }
- }
- if( iDirectEq[i]>=0 ){
- loopMask |= mask;
- pWInfo->a[i].pIdx = 0;
- continue;
- }
-
- /* Do a search for usable indices. Leave pBestIdx pointing to
- ** the "best" index. pBestIdx is left set to NULL if no indices
- ** are usable.
- **
- ** The best index is determined as follows. For each of the
- ** left-most terms that is fixed by an equality operator, add
- ** 8 to the score. The right-most term of the index may be
- ** constrained by an inequality. Add 1 if for an "x<..." constraint
- ** and add 2 for an "x>..." constraint. Chose the index that
- ** gives the best score.
- **
- ** This scoring system is designed so that the score can later be
- ** used to determine how the index is used. If the score&7 is 0
- ** then all constraints are equalities. If score&1 is not 0 then
- ** there is an inequality used as a termination key. (ex: "x<...")
- ** If score&2 is not 0 then there is an inequality used as the
- ** start key. (ex: "x>..."). A score or 4 is the special case
- ** of an IN operator constraint. (ex: "x IN ...").
- **
- ** The IN operator (as in "<expr> IN (...)") is treated the same as
- ** an equality comparison except that it can only be used on the
- ** left-most column of an index and other terms of the WHERE clause
- ** cannot be used in conjunction with the IN operator to help satisfy
- ** other columns of the index.
- */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int eqMask = 0; /* Index columns covered by an x=... term */
- int ltMask = 0; /* Index columns covered by an x<... term */
- int gtMask = 0; /* Index columns covered by an x>... term */
- int inMask = 0; /* Index columns covered by an x IN .. term */
- int nEq, m, score;
-
- if( pIdx->nColumn>32 ) continue; /* Ignore indices too many columns */
- for(j=0; j<nExpr; j++){
- if( aExpr[j].idxLeft==iCur
- && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
- int iColumn = aExpr[j].p->pLeft->iColumn;
- int k;
- for(k=0; k<pIdx->nColumn; k++){
- if( pIdx->aiColumn[k]==iColumn ){
- switch( aExpr[j].p->op ){
- case TK_IN: {
- if( k==0 ) inMask |= 1;
- break;
- }
- case TK_EQ: {
- eqMask |= 1<<k;
- break;
- }
- case TK_LE:
- case TK_LT: {
- ltMask |= 1<<k;
- break;
- }
- case TK_GE:
- case TK_GT: {
- gtMask |= 1<<k;
- break;
- }
- default: {
- /* CANT_HAPPEN */
- assert( 0 );
- break;
- }
- }
- break;
- }
- }
- }
- if( aExpr[j].idxRight==iCur
- && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){
- int iColumn = aExpr[j].p->pRight->iColumn;
- int k;
- for(k=0; k<pIdx->nColumn; k++){
- if( pIdx->aiColumn[k]==iColumn ){
- switch( aExpr[j].p->op ){
- case TK_EQ: {
- eqMask |= 1<<k;
- break;
- }
- case TK_LE:
- case TK_LT: {
- gtMask |= 1<<k;
- break;
- }
- case TK_GE:
- case TK_GT: {
- ltMask |= 1<<k;
- break;
- }
- default: {
- /* CANT_HAPPEN */
- assert( 0 );
- break;
- }
- }
- break;
- }
- }
- }
- }
-
- /* The following loop ends with nEq set to the number of columns
- ** on the left of the index with == constraints.
- */
- for(nEq=0; nEq<pIdx->nColumn; nEq++){
- m = (1<<(nEq+1))-1;
- if( (m & eqMask)!=m ) break;
- }
- score = nEq*8; /* Base score is 8 times number of == constraints */
- m = 1<<nEq;
- if( m & ltMask ) score++; /* Increase score for a < constraint */
- if( m & gtMask ) score+=2; /* Increase score for a > constraint */
- if( score==0 && inMask ) score = 4; /* Default score for IN constraint */
- if( score>bestScore ){
- pBestIdx = pIdx;
- bestScore = score;
- }
- }
- pWInfo->a[i].pIdx = pBestIdx;
- pWInfo->a[i].score = bestScore;
- pWInfo->a[i].bRev = 0;
- loopMask |= mask;
- if( pBestIdx ){
- pWInfo->a[i].iCur = pParse->nTab++;
- pWInfo->peakNTab = pParse->nTab;
- }
- }
-
- /* Check to see if the ORDER BY clause is or can be satisfied by the
- ** use of an index on the first table.
- */
- if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
- Index *pSortIdx;
- Index *pIdx;
- Table *pTab;
- int bRev = 0;
-
- pTab = pTabList->a[0].pTab;
- pIdx = pWInfo->a[0].pIdx;
- if( pIdx && pWInfo->a[0].score==4 ){
- /* If there is already an IN index on the left-most table,
- ** it will not give the correct sort order.
- ** So, pretend that no suitable index is found.
- */
- pSortIdx = 0;
- }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
- /* If the left-most column is accessed using its ROWID, then do
- ** not try to sort by index.
- */
- pSortIdx = 0;
- }else{
- int nEqCol = (pWInfo->a[0].score+4)/8;
- pSortIdx = findSortingIndex(pTab, pTabList->a[0].iCursor,
- *ppOrderBy, pIdx, nEqCol, &bRev);
- }
- if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
- if( pIdx==0 ){
- pWInfo->a[0].pIdx = pSortIdx;
- pWInfo->a[0].iCur = pParse->nTab++;
- pWInfo->peakNTab = pParse->nTab;
- }
- pWInfo->a[0].bRev = bRev;
- *ppOrderBy = 0;
- }
- }
-
- /* Open all tables in the pTabList and all indices used by those tables.
- */
- for(i=0; i<pTabList->nSrc; i++){
- Table *pTab;
- Index *pIx;
-
- pTab = pTabList->a[i].pTab;
- if( pTab->isTransient || pTab->pSelect ) continue;
- sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenRead, pTabList->a[i].iCursor, pTab->tnum,
- pTab->zName, P3_STATIC);
- sqliteCodeVerifySchema(pParse, pTab->iDb);
- if( (pIx = pWInfo->a[i].pIdx)!=0 ){
- sqliteVdbeAddOp(v, OP_Integer, pIx->iDb, 0);
- sqliteVdbeOp3(v, OP_OpenRead, pWInfo->a[i].iCur, pIx->tnum, pIx->zName,0);
- }
- }
-
- /* Generate the code to do the search
- */
- loopMask = 0;
- for(i=0; i<pTabList->nSrc; i++){
- int j, k;
- int iCur = pTabList->a[i].iCursor;
- Index *pIdx;
- WhereLevel *pLevel = &pWInfo->a[i];
-
- /* If this is the right table of a LEFT OUTER JOIN, allocate and
- ** initialize a memory cell that records if this table matches any
- ** row of the left table of the join.
- */
- if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){
- if( !pParse->nMem ) pParse->nMem++;
- pLevel->iLeftJoin = pParse->nMem++;
- sqliteVdbeAddOp(v, OP_String, 0, 0);
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
- }
-
- pIdx = pLevel->pIdx;
- pLevel->inOp = OP_Noop;
- if( i<ARRAYSIZE(iDirectEq) && iDirectEq[i]>=0 ){
- /* Case 1: We can directly reference a single row using an
- ** equality comparison against the ROWID field. Or
- ** we reference multiple rows using a "rowid IN (...)"
- ** construct.
- */
- k = iDirectEq[i];
- assert( k<nExpr );
- assert( aExpr[k].p!=0 );
- assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
- brk = pLevel->brk = sqliteVdbeMakeLabel(v);
- if( aExpr[k].idxLeft==iCur ){
- Expr *pX = aExpr[k].p;
- if( pX->op!=TK_IN ){
- sqliteExprCode(pParse, aExpr[k].p->pRight);
- }else if( pX->pList ){
- sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
- pLevel->inOp = OP_SetNext;
- pLevel->inP1 = pX->iTable;
- pLevel->inP2 = sqliteVdbeCurrentAddr(v);
- }else{
- assert( pX->pSelect );
- sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
- sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
- pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
- pLevel->inOp = OP_Next;
- pLevel->inP1 = pX->iTable;
- }
- }else{
- sqliteExprCode(pParse, aExpr[k].p->pLeft);
- }
- disableTerm(pLevel, &aExpr[k].p);
- cont = pLevel->cont = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
- haveKey = 0;
- sqliteVdbeAddOp(v, OP_NotExists, iCur, brk);
- pLevel->op = OP_Noop;
- }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
- /* Case 2: There is an index and all terms of the WHERE clause that
- ** refer to the index use the "==" or "IN" operators.
- */
- int start;
- int testOp;
- int nColumn = (pLevel->score+4)/8;
- brk = pLevel->brk = sqliteVdbeMakeLabel(v);
- for(j=0; j<nColumn; j++){
- for(k=0; k<nExpr; k++){
- Expr *pX = aExpr[k].p;
- if( pX==0 ) continue;
- if( aExpr[k].idxLeft==iCur
- && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
- && pX->pLeft->iColumn==pIdx->aiColumn[j]
- ){
- if( pX->op==TK_EQ ){
- sqliteExprCode(pParse, pX->pRight);
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- if( pX->op==TK_IN && nColumn==1 ){
- if( pX->pList ){
- sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
- pLevel->inOp = OP_SetNext;
- pLevel->inP1 = pX->iTable;
- pLevel->inP2 = sqliteVdbeCurrentAddr(v);
- }else{
- assert( pX->pSelect );
- sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
- sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
- pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
- pLevel->inOp = OP_Next;
- pLevel->inP1 = pX->iTable;
- }
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- }
- if( aExpr[k].idxRight==iCur
- && aExpr[k].p->op==TK_EQ
- && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
- && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, aExpr[k].p->pLeft);
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- }
- }
- pLevel->iMem = pParse->nMem++;
- cont = pLevel->cont = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_NotNull, -nColumn, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, brk);
- sqliteVdbeAddOp(v, OP_MakeKey, nColumn, 0);
- sqliteAddIdxKeyType(v, pIdx);
- if( nColumn==pIdx->nColumn || pLevel->bRev ){
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
- testOp = OP_IdxGT;
- }else{
- sqliteVdbeAddOp(v, OP_Dup, 0, 0);
- sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
- testOp = OP_IdxGE;
- }
- if( pLevel->bRev ){
- /* Scan in reverse order */
- sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
- sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
- start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqliteVdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
- pLevel->op = OP_Prev;
- }else{
- /* Scan in the forward order */
- sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
- start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);
- pLevel->op = OP_Next;
- }
- sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
- sqliteVdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
- sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
- if( i==pTabList->nSrc-1 && pushKey ){
- haveKey = 1;
- }else{
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
- haveKey = 0;
- }
- pLevel->p1 = pLevel->iCur;
- pLevel->p2 = start;
- }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
- /* Case 3: We have an inequality comparison against the ROWID field.
- */
- int testOp = OP_Noop;
- int start;
-
- brk = pLevel->brk = sqliteVdbeMakeLabel(v);
- cont = pLevel->cont = sqliteVdbeMakeLabel(v);
- if( iDirectGt[i]>=0 ){
- k = iDirectGt[i];
- assert( k<nExpr );
- assert( aExpr[k].p!=0 );
- assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
- if( aExpr[k].idxLeft==iCur ){
- sqliteExprCode(pParse, aExpr[k].p->pRight);
- }else{
- sqliteExprCode(pParse, aExpr[k].p->pLeft);
- }
- sqliteVdbeAddOp(v, OP_ForceInt,
- aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
- disableTerm(pLevel, &aExpr[k].p);
- }else{
- sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
- }
- if( iDirectLt[i]>=0 ){
- k = iDirectLt[i];
- assert( k<nExpr );
- assert( aExpr[k].p!=0 );
- assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
- if( aExpr[k].idxLeft==iCur ){
- sqliteExprCode(pParse, aExpr[k].p->pRight);
- }else{
- sqliteExprCode(pParse, aExpr[k].p->pLeft);
- }
- /* sqliteVdbeAddOp(v, OP_MustBeInt, 0, sqliteVdbeCurrentAddr(v)+1); */
- pLevel->iMem = pParse->nMem++;
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
- if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){
- testOp = OP_Ge;
- }else{
- testOp = OP_Gt;
- }
- disableTerm(pLevel, &aExpr[k].p);
- }
- start = sqliteVdbeCurrentAddr(v);
- pLevel->op = OP_Next;
- pLevel->p1 = iCur;
- pLevel->p2 = start;
- if( testOp!=OP_Noop ){
- sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
- sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqliteVdbeAddOp(v, testOp, 0, brk);
- }
- haveKey = 0;
- }else if( pIdx==0 ){
- /* Case 4: There is no usable index. We must do a complete
- ** scan of the entire database table.
- */
- int start;
-
- brk = pLevel->brk = sqliteVdbeMakeLabel(v);
- cont = pLevel->cont = sqliteVdbeMakeLabel(v);
- sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
- start = sqliteVdbeCurrentAddr(v);
- pLevel->op = OP_Next;
- pLevel->p1 = iCur;
- pLevel->p2 = start;
- haveKey = 0;
- }else{
- /* Case 5: The WHERE clause term that refers to the right-most
- ** column of the index is an inequality. For example, if
- ** the index is on (x,y,z) and the WHERE clause is of the
- ** form "x=5 AND y<10" then this case is used. Only the
- ** right-most column can be an inequality - the rest must
- ** use the "==" operator.
- **
- ** This case is also used when there are no WHERE clause
- ** constraints but an index is selected anyway, in order
- ** to force the output order to conform to an ORDER BY.
- */
- int score = pLevel->score;
- int nEqColumn = score/8;
- int start;
- int leFlag, geFlag;
- int testOp;
-
- /* Evaluate the equality constraints
- */
- for(j=0; j<nEqColumn; j++){
- for(k=0; k<nExpr; k++){
- if( aExpr[k].p==0 ) continue;
- if( aExpr[k].idxLeft==iCur
- && aExpr[k].p->op==TK_EQ
- && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
- && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, aExpr[k].p->pRight);
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- if( aExpr[k].idxRight==iCur
- && aExpr[k].p->op==TK_EQ
- && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
- && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, aExpr[k].p->pLeft);
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- }
- }
-
- /* Duplicate the equality term values because they will all be
- ** used twice: once to make the termination key and once to make the
- ** start key.
- */
- for(j=0; j<nEqColumn; j++){
- sqliteVdbeAddOp(v, OP_Dup, nEqColumn-1, 0);
- }
-
- /* Labels for the beginning and end of the loop
- */
- cont = pLevel->cont = sqliteVdbeMakeLabel(v);
- brk = pLevel->brk = sqliteVdbeMakeLabel(v);
-
- /* Generate the termination key. This is the key value that
- ** will end the search. There is no termination key if there
- ** are no equality terms and no "X<..." term.
- **
- ** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
- ** key computed here really ends up being the start key.
- */
- if( (score & 1)!=0 ){
- for(k=0; k<nExpr; k++){
- Expr *pExpr = aExpr[k].p;
- if( pExpr==0 ) continue;
- if( aExpr[k].idxLeft==iCur
- && (pExpr->op==TK_LT || pExpr->op==TK_LE)
- && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
- && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, pExpr->pRight);
- leFlag = pExpr->op==TK_LE;
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- if( aExpr[k].idxRight==iCur
- && (pExpr->op==TK_GT || pExpr->op==TK_GE)
- && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
- && pExpr->pRight->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, pExpr->pLeft);
- leFlag = pExpr->op==TK_GE;
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- }
- testOp = OP_IdxGE;
- }else{
- testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
- leFlag = 1;
- }
- if( testOp!=OP_Noop ){
- int nCol = nEqColumn + (score & 1);
- pLevel->iMem = pParse->nMem++;
- sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, nCol, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, brk);
- sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);
- sqliteAddIdxKeyType(v, pIdx);
- if( leFlag ){
- sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
- }
- if( pLevel->bRev ){
- sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
- }else{
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
- }
- }else if( pLevel->bRev ){
- sqliteVdbeAddOp(v, OP_Last, pLevel->iCur, brk);
- }
-
- /* Generate the start key. This is the key that defines the lower
- ** bound on the search. There is no start key if there are no
- ** equality terms and if there is no "X>..." term. In
- ** that case, generate a "Rewind" instruction in place of the
- ** start key search.
- **
- ** 2002-Dec-04: In the case of a reverse-order search, the so-called
- ** "start" key really ends up being used as the termination key.
- */
- if( (score & 2)!=0 ){
- for(k=0; k<nExpr; k++){
- Expr *pExpr = aExpr[k].p;
- if( pExpr==0 ) continue;
- if( aExpr[k].idxLeft==iCur
- && (pExpr->op==TK_GT || pExpr->op==TK_GE)
- && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
- && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, pExpr->pRight);
- geFlag = pExpr->op==TK_GE;
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- if( aExpr[k].idxRight==iCur
- && (pExpr->op==TK_LT || pExpr->op==TK_LE)
- && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
- && pExpr->pRight->iColumn==pIdx->aiColumn[j]
- ){
- sqliteExprCode(pParse, pExpr->pLeft);
- geFlag = pExpr->op==TK_LE;
- disableTerm(pLevel, &aExpr[k].p);
- break;
- }
- }
- }else{
- geFlag = 1;
- }
- if( nEqColumn>0 || (score&2)!=0 ){
- int nCol = nEqColumn + ((score&2)!=0);
- sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);
- sqliteVdbeAddOp(v, OP_Pop, nCol, 0);
- sqliteVdbeAddOp(v, OP_Goto, 0, brk);
- sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);
- sqliteAddIdxKeyType(v, pIdx);
- if( !geFlag ){
- sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
- }
- if( pLevel->bRev ){
- pLevel->iMem = pParse->nMem++;
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
- testOp = OP_IdxLT;
- }else{
- sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
- }
- }else if( pLevel->bRev ){
- testOp = OP_Noop;
- }else{
- sqliteVdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
- }
-
- /* Generate the the top of the loop. If there is a termination
- ** key we have to test for that key and abort at the top of the
- ** loop.
- */
- start = sqliteVdbeCurrentAddr(v);
- if( testOp!=OP_Noop ){
- sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
- sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);
- }
- sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
- sqliteVdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
- sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
- if( i==pTabList->nSrc-1 && pushKey ){
- haveKey = 1;
- }else{
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
- haveKey = 0;
- }
-
- /* Record the instruction used to terminate the loop.
- */
- pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
- pLevel->p1 = pLevel->iCur;
- pLevel->p2 = start;
- }
- loopMask |= getMask(&maskSet, iCur);
-
- /* Insert code to test every subexpression that can be completely
- ** computed using the current set of tables.
- */
- for(j=0; j<nExpr; j++){
- if( aExpr[j].p==0 ) continue;
- if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
- if( pLevel->iLeftJoin && !ExprHasProperty(aExpr[j].p,EP_FromJoin) ){
- continue;
- }
- if( haveKey ){
- haveKey = 0;
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
- }
- sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
- aExpr[j].p = 0;
- }
- brk = cont;
-
- /* For a LEFT OUTER JOIN, generate code that will record the fact that
- ** at least one row of the right table has matched the left table.
- */
- if( pLevel->iLeftJoin ){
- pLevel->top = sqliteVdbeCurrentAddr(v);
- sqliteVdbeAddOp(v, OP_Integer, 1, 0);
- sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
- for(j=0; j<nExpr; j++){
- if( aExpr[j].p==0 ) continue;
- if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
- if( haveKey ){
- /* Cannot happen. "haveKey" can only be true if pushKey is true
- ** an pushKey can only be true for DELETE and UPDATE and there are
- ** no outer joins with DELETE and UPDATE.
- */
- haveKey = 0;
- sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
- }
- sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
- aExpr[j].p = 0;
- }
- }
- }
- pWInfo->iContinue = cont;
- if( pushKey && !haveKey ){
- sqliteVdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
- }
- freeMaskSet(&maskSet);
- return pWInfo;
-}
-
-/*
-** Generate the end of the WHERE loop. See comments on
-** sqliteWhereBegin() for additional information.
-*/
-void sqliteWhereEnd(WhereInfo *pWInfo){
- Vdbe *v = pWInfo->pParse->pVdbe;
- int i;
- WhereLevel *pLevel;
- SrcList *pTabList = pWInfo->pTabList;
-
- for(i=pTabList->nSrc-1; i>=0; i--){
- pLevel = &pWInfo->a[i];
- sqliteVdbeResolveLabel(v, pLevel->cont);
- if( pLevel->op!=OP_Noop ){
- sqliteVdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2);
- }
- sqliteVdbeResolveLabel(v, pLevel->brk);
- if( pLevel->inOp!=OP_Noop ){
- sqliteVdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2);
- }
- if( pLevel->iLeftJoin ){
- int addr;
- addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);
- sqliteVdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0));
- sqliteVdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);
- if( pLevel->iCur>=0 ){
- sqliteVdbeAddOp(v, OP_NullRow, pLevel->iCur, 0);
- }
- sqliteVdbeAddOp(v, OP_Goto, 0, pLevel->top);
- }
- }
- sqliteVdbeResolveLabel(v, pWInfo->iBreak);
- for(i=0; i<pTabList->nSrc; i++){
- Table *pTab = pTabList->a[i].pTab;
- assert( pTab!=0 );
- if( pTab->isTransient || pTab->pSelect ) continue;
- pLevel = &pWInfo->a[i];
- sqliteVdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);
- if( pLevel->pIdx!=0 ){
- sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0);
- }
- }
-#if 0 /* Never reuse a cursor */
- if( pWInfo->pParse->nTab==pWInfo->peakNTab ){
- pWInfo->pParse->nTab = pWInfo->savedNTab;
- }
-#endif
- sqliteFree(pWInfo);
- return;
-}
diff --git a/ext/sqlite/package.xml b/ext/sqlite/package.xml
deleted file mode 100644
index e0093f1256..0000000000
--- a/ext/sqlite/package.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<!DOCTYPE package SYSTEM "../pear/package.dtd">
-<package>
- <name>SQLite</name>
- <summary>SQLite database bindings</summary>
- <maintainers>
- <maintainer>
- <user>wez</user>
- <name>Wez Furlong</name>
- <email>wez@php.net</email>
- <role>lead</role>
- </maintainer>
- <maintainer>
- <user>tal</user>
- <name>Tal Peer</name>
- <email>tal@php.net</email>
- <role>developer</role>
- </maintainer>
- <maintainer>
- <user>helly</user>
- <name>Marcus Börger</name>
- <email>helly@php.net</email>
- <role>lead</role>
- </maintainer>
- <maintainer>
- <user>iliaa</user>
- <name>Ilia Alshanetsky</name>
- <email>ilia@php.net</email>
- <role>developer</role>
- </maintainer>
- </maintainers>
- <description>
-SQLite is a C library that implements an embeddable SQL database engine.
-Programs that link with the SQLite library can have SQL database access
-without running a separate RDBMS process.
-This extension allows you to access SQLite databases from within PHP.
-
-Windows binary available from:
-http://snaps.php.net/win32/PECL_STABLE/php_sqlite.dll
- </description>
- <license>PHP</license>
- <release>
- <state>stable</state>
- <version>2.0-dev</version>
- <date>TBA</date>
- <notes>
- Added:
- OO API (Marcus).
- </notes>
- <filelist>
- <file role="src" name="config.m4"/>
- <file role="src" name="config.w32"/>
- <file role="src" name="sqlite.c"/>
- <file role="src" name="sqlite.dsp"/>
- <file role="src" name="php_sqlite.h"/>
- <file role="src" name="php_sqlite.def"/>
- <file role="doc" name="CREDITS"/>
- <file role="doc" name="README"/>
- <file role="doc" name="TODO"/>
- <file role="doc" name="sqlite.php"/>
- <file role="test" name="tests/sqlite_001.phpt"/>
- <file role="test" name="tests/sqlite_002.phpt"/>
- <file role="test" name="tests/sqlite_003.phpt"/>
- <file role="test" name="tests/sqlite_004.phpt"/>
- <file role="test" name="tests/sqlite_005.phpt"/>
- <file role="test" name="tests/sqlite_006.phpt"/>
- <file role="test" name="tests/sqlite_007.phpt"/>
- <file role="test" name="tests/sqlite_008.phpt"/>
- <file role="test" name="tests/sqlite_009.phpt"/>
- <file role="test" name="tests/sqlite_010.phpt"/>
- <file role="test" name="tests/sqlite_011.phpt"/>
- <file role="test" name="tests/sqlite_012.phpt"/>
- <file role="test" name="tests/sqlite_013.phpt"/>
- <file role="test" name="tests/sqlite_014.phpt"/>
- <file role="test" name="tests/sqlite_015.phpt"/>
- <file role="test" name="tests/sqlite_016.phpt"/>
- <file role="test" name="tests/sqlite_017.phpt"/>
- <file role="test" name="tests/blankdb.inc"/>
-
- <dir name="libsqlite">
- <file role="doc" name="README"/>
- <file role="src" name="VERSION"/>
-
- <dir name="src">
- <file role="src" name="attach.c"/>
- <file role="src" name="auth.c"/>
- <file role="src" name="btree.c"/>
- <file role="src" name="btree_rb.c"/>
- <file role="src" name="build.c"/>
- <file role="src" name="copy.c"/>
- <file role="src" name="delete.c"/>
- <file role="src" name="encode.c"/>
- <file role="src" name="expr.c"/>
- <file role="src" name="func.c"/>
- <file role="src" name="hash.c"/>
- <file role="src" name="insert.c"/>
- <file role="src" name="main.c"/>
- <file role="src" name="opcodes.c"/>
- <file role="src" name="os.c"/>
- <file role="src" name="pager.c"/>
- <file role="src" name="parse.c"/>
- <file role="src" name="parse.y"/>
- <file role="src" name="pragma.c"/>
- <file role="src" name="printf.c"/>
- <file role="src" name="random.c"/>
- <file role="src" name="select.c"/>
- <file role="src" name="table.c"/>
- <file role="src" name="tokenize.c"/>
- <file role="src" name="trigger.c"/>
- <file role="src" name="update.c"/>
- <file role="src" name="util.c"/>
- <file role="src" name="vacuum.c"/>
- <file role="src" name="vdbe.c"/>
- <file role="src" name="where.c"/>
- <file role="src" name="btree.h"/>
- <file role="src" name="hash.h"/>
- <file role="src" name="opcodes.h"/>
- <file role="src" name="os.h"/>
- <file role="src" name="pager.h"/>
- <file role="src" name="parse.h"/>
- <file role="src" name="sqlite_config.w32.h"/>
- <file role="src" name="sqlite.h.in"/>
- <file role="src" name="sqliteInt.h"/>
- <file role="src" name="sqlite.w32.h"/>
- <file role="src" name="vdbe.h"/>
- </dir>
- </dir>
- </filelist>
- <deps>
- <dep type="php" rel="ge" version="5" />
- </deps>
- </release>
-</package>
-<!--
-vim:et:ts=1:sw=1
--->
diff --git a/ext/sqlite/pdo_sqlite2.c b/ext/sqlite/pdo_sqlite2.c
deleted file mode 100644
index f72a472fad..0000000000
--- a/ext/sqlite/pdo_sqlite2.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Wez Furlong <wez@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "php.h"
-
-#ifdef PHP_SQLITE2_HAVE_PDO
-#include "sqlite.h"
-#include "pdo/php_pdo.h"
-#include "pdo/php_pdo_driver.h"
-#include "zend_exceptions.h"
-
-#define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
-#define php_sqlite_decode_binary(in, out) sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out)
-
-
-typedef struct {
- const char *file;
- int line;
- unsigned int errcode;
- char *errmsg;
-} pdo_sqlite2_error_info;
-
-typedef struct {
- sqlite *db;
- pdo_sqlite2_error_info einfo;
-} pdo_sqlite2_db_handle;
-
-typedef struct {
- pdo_sqlite2_db_handle *H;
- sqlite_vm *vm;
- const char **rowdata, **colnames;
- int ncols;
- unsigned pre_fetched:1;
- unsigned done:1;
- pdo_sqlite2_error_info einfo;
-} pdo_sqlite2_stmt;
-
-extern int _pdo_sqlite2_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *errmsg, const char *file, int line TSRMLS_DC);
-#define pdo_sqlite2_error(msg, s) _pdo_sqlite2_error(s, NULL, msg, __FILE__, __LINE__ TSRMLS_CC)
-#define pdo_sqlite2_error_stmt(msg, s) _pdo_sqlite2_error(stmt->dbh, stmt, msg, __FILE__, __LINE__ TSRMLS_CC)
-
-extern struct pdo_stmt_methods sqlite2_stmt_methods;
-
-static int pdo_sqlite2_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
-{
- pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
-
- if (S->vm) {
- char *errmsg = NULL;
- sqlite_finalize(S->vm, &errmsg);
- if (errmsg) {
- sqlite_freemem(errmsg);
- }
- S->vm = NULL;
- }
- if (S->einfo.errmsg) {
- pefree(S->einfo.errmsg, stmt->dbh->is_persistent);
- }
- efree(S);
- return 1;
-}
-
-static int pdo_sqlite2_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
-{
- pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
- char *errmsg = NULL;
- const char *tail;
-
- if (stmt->executed && !S->done) {
- sqlite_finalize(S->vm, &errmsg);
- pdo_sqlite2_error_stmt(errmsg, stmt);
- errmsg = NULL;
- S->vm = NULL;
- }
-
- S->einfo.errcode = sqlite_compile(S->H->db, stmt->active_query_string, &tail, &S->vm, &errmsg);
- if (S->einfo.errcode != SQLITE_OK) {
- pdo_sqlite2_error_stmt(errmsg, stmt);
- return 0;
- }
-
- S->done = 0;
- S->einfo.errcode = sqlite_step(S->vm, &S->ncols, &S->rowdata, &S->colnames);
- switch (S->einfo.errcode) {
- case SQLITE_ROW:
- S->pre_fetched = 1;
- stmt->column_count = S->ncols;
- return 1;
-
- case SQLITE_DONE:
- stmt->column_count = S->ncols;
- stmt->row_count = sqlite_changes(S->H->db);
- S->einfo.errcode = sqlite_reset(S->vm, &errmsg);
- if (S->einfo.errcode != SQLITE_OK) {
- pdo_sqlite2_error_stmt(errmsg, stmt);
- }
- S->done = 1;
- return 1;
-
- case SQLITE_ERROR:
- case SQLITE_MISUSE:
- case SQLITE_BUSY:
- default:
- pdo_sqlite2_error_stmt(errmsg, stmt);
- return 0;
- }
-}
-
-static int pdo_sqlite2_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
- enum pdo_param_event event_type TSRMLS_DC)
-{
- return 1;
-}
-
-static int pdo_sqlite2_stmt_fetch(pdo_stmt_t *stmt,
- enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
-{
- pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
- char *errmsg = NULL;
-
- if (!S->vm) {
- return 0;
- }
- if (S->pre_fetched) {
- S->pre_fetched = 0;
- return 1;
- }
- if (S->done) {
- return 0;
- }
-
- S->einfo.errcode = sqlite_step(S->vm, &S->ncols, &S->rowdata, &S->colnames);
- switch (S->einfo.errcode) {
- case SQLITE_ROW:
- return 1;
-
- case SQLITE_DONE:
- S->done = 1;
- S->einfo.errcode = sqlite_reset(S->vm, &errmsg);
- if (S->einfo.errcode != SQLITE_OK) {
- pdo_sqlite2_error_stmt(errmsg, stmt);
- errmsg = NULL;
- }
- return 0;
-
- default:
- pdo_sqlite2_error_stmt(errmsg, stmt);
- return 0;
- }
-}
-
-static int pdo_sqlite2_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
-{
- pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
-
- if(colno >= S->ncols) {
- /* error invalid column */
- pdo_sqlite2_error_stmt(NULL, stmt);
- return 0;
- }
-
- stmt->columns[colno].name = estrdup(S->colnames[colno]);
- stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
- stmt->columns[colno].maxlen = 0xffffffff;
- stmt->columns[colno].precision = 0;
- stmt->columns[colno].param_type = PDO_PARAM_STR;
-
- return 1;
-}
-
-static int pdo_sqlite2_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
-{
- pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
- if (!S->vm) {
- return 0;
- }
- if(colno >= S->ncols) {
- /* error invalid column */
- pdo_sqlite2_error_stmt(NULL, stmt);
- return 0;
- }
- if (S->rowdata[colno]) {
- if (S->rowdata[colno][0] == '\x01') {
- /* encoded */
- *caller_frees = 1;
- *ptr = emalloc(strlen(S->rowdata[colno]));
- *len = php_sqlite_decode_binary(S->rowdata[colno]+1, *ptr);
- (*(char**)ptr)[*len] = '\0';
- } else {
- *ptr = (char*)S->rowdata[colno];
- *len = strlen(*ptr);
- }
- } else {
- *ptr = NULL;
- *len = 0;
- }
- return 1;
-}
-
-struct pdo_stmt_methods sqlite2_stmt_methods = {
- pdo_sqlite2_stmt_dtor,
- pdo_sqlite2_stmt_execute,
- pdo_sqlite2_stmt_fetch,
- pdo_sqlite2_stmt_describe,
- pdo_sqlite2_stmt_get_col,
- pdo_sqlite2_stmt_param_hook,
- NULL, /* set_attr */
- NULL, /* get_attr */
- NULL
-};
-
-
-int _pdo_sqlite2_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *errmsg, const char *file, int line TSRMLS_DC) /* {{{ */
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
- pdo_sqlite2_error_info *einfo = &H->einfo;
- pdo_sqlite2_stmt *S;
-
- if (stmt) {
- S = stmt->driver_data;
- einfo = &S->einfo;
- }
-
- einfo->file = file;
- einfo->line = line;
-
- if (einfo->errmsg) {
- pefree(einfo->errmsg, dbh->is_persistent);
- einfo->errmsg = NULL;
- }
-
- if (einfo->errcode != SQLITE_OK) {
- if (errmsg) {
- einfo->errmsg = pestrdup(errmsg, dbh->is_persistent);
- sqlite_freemem(errmsg);
- } else {
- einfo->errmsg = pestrdup(sqlite_error_string(einfo->errcode), dbh->is_persistent);
- }
- } else { /* no error */
- strcpy(*pdo_err, PDO_ERR_NONE);
- return 0;
- }
- switch (einfo->errcode) {
- case SQLITE_NOTFOUND:
- strcpy(*pdo_err, "42S02");
- break;
-
- case SQLITE_INTERRUPT:
- strcpy(*pdo_err, "01002");
- break;
-
- case SQLITE_NOLFS:
- strcpy(*pdo_err, "HYC00");
- break;
-
- case SQLITE_TOOBIG:
- strcpy(*pdo_err, "22001");
- break;
-
- case SQLITE_CONSTRAINT:
- strcpy(*pdo_err, "23000");
- break;
-
- case SQLITE_ERROR:
- default:
- strcpy(*pdo_err, "HY000");
- break;
- }
-
- if (!dbh->methods) {
- zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
- *pdo_err, einfo->errcode, einfo->errmsg);
- }
-
- return einfo->errcode;
-}
-/* }}} */
-
-static int pdo_sqlite2_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- pdo_sqlite2_error_info *einfo = &H->einfo;
- pdo_sqlite2_stmt *S;
-
- if (stmt) {
- S = stmt->driver_data;
- einfo = &S->einfo;
- }
-
- if (einfo->errcode) {
- add_next_index_long(info, einfo->errcode);
- if (einfo->errmsg) {
- add_next_index_string(info, einfo->errmsg, 1);
- }
- }
-
- return 1;
-}
-
-static int sqlite2_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
-
- if (H) {
- if (H->db) {
- sqlite_close(H->db);
- H->db = NULL;
- }
- if (H->einfo.errmsg) {
- pefree(H->einfo.errmsg, dbh->is_persistent);
- H->einfo.errmsg = NULL;
- }
- pefree(H, dbh->is_persistent);
- dbh->driver_data = NULL;
- }
- return 0;
-}
-/* }}} */
-
-static int sqlite2_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- pdo_sqlite2_stmt *S = ecalloc(1, sizeof(pdo_sqlite2_stmt));
-
- S->H = H;
- stmt->driver_data = S;
- stmt->methods = &sqlite2_stmt_methods;
- stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
-
- if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
- H->einfo.errcode = SQLITE_ERROR;
- pdo_sqlite2_error(NULL, dbh);
- return 0;
- }
-
- return 1;
-}
-
-static long sqlite2_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- char *errmsg = NULL;
-
- if ((H->einfo.errcode = sqlite_exec(H->db, sql, NULL, NULL, &errmsg)) != SQLITE_OK) {
- pdo_sqlite2_error(errmsg, dbh);
- return -1;
- } else {
- return sqlite_changes(H->db);
- }
-}
-
-static char *pdo_sqlite2_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- char *id;
-
- id = php_pdo_int64_to_str(sqlite_last_insert_rowid(H->db) TSRMLS_CC);
- *len = strlen(id);
- return id;
-}
-
-static int sqlite2_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
-{
- char *ret;
-
- if (unquotedlen && (unquoted[0] == '\x01' || memchr(unquoted, '\0', unquotedlen) != NULL)) {
- /* binary string */
- int len;
- ret = safe_emalloc(1 + unquotedlen / 254, 257, 5);
- ret[0] = '\'';
- ret[1] = '\x01';
- len = php_sqlite_encode_binary(unquoted, unquotedlen, ret+2);
- ret[len + 2] = '\'';
- ret[len + 3] = '\0';
- *quoted = ret;
- *quotedlen = len + 3;
- /* fprintf(stderr, "Quoting:%d:%.*s:\n", *quotedlen, *quotedlen, *quoted); */
- return 1;
- } else if (unquotedlen) {
- ret = sqlite_mprintf("'%q'", unquoted);
- if (ret) {
- *quoted = estrdup(ret);
- *quotedlen = strlen(ret);
- sqlite_freemem(ret);
- return 1;
- }
- return 0;
- } else {
- *quoted = estrdup("''");
- *quotedlen = 2;
- return 1;
- }
-}
-
-static int sqlite2_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- char *errmsg = NULL;
-
- if (sqlite_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
- pdo_sqlite2_error(errmsg, dbh);
- return 0;
- }
- return 1;
-}
-
-static int sqlite2_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- char *errmsg = NULL;
-
- if (sqlite_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
- pdo_sqlite2_error(errmsg, dbh);
- return 0;
- }
- return 1;
-}
-
-static int sqlite2_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
- char *errmsg = NULL;
-
- if (sqlite_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
- pdo_sqlite2_error(errmsg, dbh);
- return 0;
- }
- return 1;
-}
-
-static int pdo_sqlite2_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
-{
- switch (attr) {
- case PDO_ATTR_CLIENT_VERSION:
- case PDO_ATTR_SERVER_VERSION:
- ZVAL_STRING(return_value, (char *)sqlite_libversion(), 1);
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static int pdo_sqlite2_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
-{
- pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
-
- switch (attr) {
- case PDO_ATTR_TIMEOUT:
- convert_to_long(val);
- sqlite_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
- return 1;
- }
- return 0;
-}
-
-static PHP_FUNCTION(sqlite2_create_function)
-{
- /* TODO: implement this stuff */
-}
-
-static const zend_function_entry dbh_methods[] = {
- PHP_FE(sqlite2_create_function, NULL)
- {NULL, NULL, NULL}
-};
-
-static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
-{
- switch (kind) {
- case PDO_DBH_DRIVER_METHOD_KIND_DBH:
- return dbh_methods;
-
- default:
- return NULL;
- }
-}
-
-static struct pdo_dbh_methods sqlite2_methods = {
- sqlite2_handle_closer,
- sqlite2_handle_preparer,
- sqlite2_handle_doer,
- sqlite2_handle_quoter,
- sqlite2_handle_begin,
- sqlite2_handle_commit,
- sqlite2_handle_rollback,
- pdo_sqlite2_set_attr,
- pdo_sqlite2_last_insert_id,
- pdo_sqlite2_fetch_error_func,
- pdo_sqlite2_get_attribute,
- NULL, /* check_liveness: not needed */
- get_driver_methods
-};
-
-static char *make_filename_safe(const char *filename TSRMLS_DC)
-{
- if (*filename && strncmp(filename, ":memory:", sizeof(":memory:")-1)) {
- char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
-
- if (!fullpath) {
- return NULL;
- }
-
- if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- efree(fullpath);
- return NULL;
- }
-
- if (php_check_open_basedir(fullpath TSRMLS_CC)) {
- efree(fullpath);
- return NULL;
- }
- return fullpath;
- }
- return estrdup(filename);
-}
-
-static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
- const char *arg5, const char *arg6)
-{
- char *filename;
- switch (access_type) {
- case SQLITE_COPY: {
- TSRMLS_FETCH();
- filename = make_filename_safe(arg4 TSRMLS_CC);
- if (!filename) {
- return SQLITE_DENY;
- }
- efree(filename);
- return SQLITE_OK;
- }
-
- case SQLITE_ATTACH: {
- TSRMLS_FETCH();
- filename = make_filename_safe(arg3 TSRMLS_CC);
- if (!filename) {
- return SQLITE_DENY;
- }
- efree(filename);
- return SQLITE_OK;
- }
-
- default:
- /* access allowed */
- return SQLITE_OK;
- }
-}
-
-static int pdo_sqlite2_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
-{
- pdo_sqlite2_db_handle *H;
- int ret = 0;
- long timeout = 60;
- char *filename;
- char *errmsg = NULL;
-
- H = pecalloc(1, sizeof(pdo_sqlite2_db_handle), dbh->is_persistent);
-
- H->einfo.errcode = 0;
- H->einfo.errmsg = NULL;
- dbh->driver_data = H;
-
- filename = make_filename_safe(dbh->data_source TSRMLS_CC);
-
- if (!filename) {
- zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
- "safe_mode/open_basedir prohibits opening %s",
- dbh->data_source);
- goto cleanup;
- }
-
- H->db = sqlite_open(filename, 0666, &errmsg);
- efree(filename);
-
- if (!H->db) {
- H->einfo.errcode = SQLITE_ERROR;
- pdo_sqlite2_error(errmsg, dbh);
- goto cleanup;
- }
-
- sqlite_set_authorizer(H->db, authorizer, NULL);
-
- if (driver_options) {
- timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
- }
- sqlite_busy_timeout(H->db, timeout * 1000);
-
- dbh->alloc_own_columns = 1;
- dbh->max_escaped_char_length = 2;
-
- ret = 1;
-
-cleanup:
- dbh->methods = &sqlite2_methods;
-
- return ret;
-}
-/* }}} */
-
-pdo_driver_t pdo_sqlite2_driver = {
- PDO_DRIVER_HEADER(sqlite2),
- pdo_sqlite2_handle_factory
-};
-
-
-
-#endif
-
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
diff --git a/ext/sqlite/php_sqlite.def b/ext/sqlite/php_sqlite.def
deleted file mode 100644
index 9dab74ad94..0000000000
--- a/ext/sqlite/php_sqlite.def
+++ /dev/null
@@ -1,43 +0,0 @@
-EXPORTS
-sqlite_open
-sqlite_close
-sqlite_exec
-sqlite_last_insert_rowid
-sqlite_changes
-sqlite_error_string
-sqlite_interrupt
-sqlite_complete
-sqlite_busy_handler
-sqlite_busy_timeout
-sqlite_get_table
-sqlite_free_table
-sqlite_exec_printf
-sqlite_exec_vprintf
-sqlite_get_table_printf
-sqlite_get_table_vprintf
-sqlite_mprintf
-sqlite_vmprintf
-sqlite_freemem
-sqlite_libversion
-sqlite_libencoding
-sqlite_create_function
-sqlite_create_aggregate
-sqlite_function_type
-sqlite_set_result_string
-sqlite_set_result_int
-sqlite_set_result_double
-sqlite_set_result_error
-sqlite_user_data
-sqlite_aggregate_context
-sqlite_aggregate_count
-sqlite_set_authorizer
-sqlite_trace
-sqlite_compile
-sqlite_step
-sqlite_finalize
-; some experimental stuff
-sqlite_last_statement_changes
-sqlite_reset
-sqlite_bind
-sqlite_progress_handler
-sqlite_commit_hook
diff --git a/ext/sqlite/php_sqlite.h b/ext/sqlite/php_sqlite.h
deleted file mode 100644
index b3dfd29850..0000000000
--- a/ext/sqlite/php_sqlite.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Wez Furlong <wez@thebrainroom.com> |
- | Tal Peer <tal@php.net> |
- | Marcus Boerger <helly@php.net> |
- +----------------------------------------------------------------------+
-
- $Id$
-*/
-
-#ifndef PHP_SQLITE_H
-#define PHP_SQLITE_H
-
-extern zend_module_entry sqlite_module_entry;
-#define phpext_sqlite_ptr &sqlite_module_entry
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-PHP_MINIT_FUNCTION(sqlite);
-PHP_MSHUTDOWN_FUNCTION(sqlite);
-PHP_RSHUTDOWN_FUNCTION(sqlite);
-PHP_MINFO_FUNCTION(sqlite);
-
-PHP_FUNCTION(sqlite_open);
-PHP_FUNCTION(sqlite_popen);
-PHP_FUNCTION(sqlite_close);
-PHP_FUNCTION(sqlite_query);
-PHP_FUNCTION(sqlite_exec);
-PHP_FUNCTION(sqlite_unbuffered_query);
-PHP_FUNCTION(sqlite_array_query);
-PHP_FUNCTION(sqlite_single_query);
-
-PHP_FUNCTION(sqlite_fetch_array);
-PHP_FUNCTION(sqlite_fetch_object);
-PHP_FUNCTION(sqlite_fetch_single);
-PHP_FUNCTION(sqlite_fetch_all);
-PHP_FUNCTION(sqlite_current);
-PHP_FUNCTION(sqlite_column);
-
-PHP_FUNCTION(sqlite_num_rows);
-PHP_FUNCTION(sqlite_num_fields);
-PHP_FUNCTION(sqlite_field_name);
-PHP_FUNCTION(sqlite_seek);
-PHP_FUNCTION(sqlite_rewind);
-PHP_FUNCTION(sqlite_next);
-PHP_FUNCTION(sqlite_prev);
-PHP_FUNCTION(sqlite_key);
-
-PHP_FUNCTION(sqlite_valid);
-PHP_FUNCTION(sqlite_has_prev);
-
-PHP_FUNCTION(sqlite_libversion);
-PHP_FUNCTION(sqlite_libencoding);
-
-PHP_FUNCTION(sqlite_changes);
-PHP_FUNCTION(sqlite_last_insert_rowid);
-
-PHP_FUNCTION(sqlite_escape_string);
-
-PHP_FUNCTION(sqlite_busy_timeout);
-
-PHP_FUNCTION(sqlite_last_error);
-PHP_FUNCTION(sqlite_error_string);
-
-PHP_FUNCTION(sqlite_create_aggregate);
-PHP_FUNCTION(sqlite_create_function);
-PHP_FUNCTION(sqlite_udf_decode_binary);
-PHP_FUNCTION(sqlite_udf_encode_binary);
-
-PHP_FUNCTION(sqlite_factory);
-
-PHP_FUNCTION(sqlite_fetch_column_types);
-
-ZEND_BEGIN_MODULE_GLOBALS(sqlite)
- long assoc_case;
-ZEND_END_MODULE_GLOBALS(sqlite)
-
-#ifdef ZTS
-#define SQLITE_G(v) TSRMG(sqlite_globals_id, zend_sqlite_globals *, v)
-#else
-#define SQLITE_G(v) (sqlite_globals.v)
-#endif
-
-#endif
-
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- */
diff --git a/ext/sqlite/sess_sqlite.c b/ext/sqlite/sess_sqlite.c
deleted file mode 100644
index cb69aa5cbd..0000000000
--- a/ext/sqlite/sess_sqlite.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: John Coggeshall <john@php.net> |
- | Wez Furlong <wez@thebrainroom.com> |
- +----------------------------------------------------------------------+
- */
-
-/* $Id$ */
-
-#include "php.h"
-
-#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
-
-#include "ext/session/php_session.h"
-#include "ext/standard/php_lcg.h"
-#include <sqlite.h>
-#define SQLITE_RETVAL(__r) ((__r) == SQLITE_OK ? SUCCESS : FAILURE)
-#define PS_SQLITE_DATA sqlite *db = (sqlite*)PS_GET_MOD_DATA()
-extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
-extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
-
-PS_FUNCS(sqlite);
-
-ps_module ps_mod_sqlite = {
- PS_MOD(sqlite)
-};
-
-PS_OPEN_FUNC(sqlite)
-{
- char *errmsg = NULL;
- sqlite *db;
-
- /* TODO: do we need a safe_mode check here? */
- db = sqlite_open(save_path, 0666, &errmsg);
- if (db == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "SQLite: failed to open/create session database `%s' - %s", save_path, errmsg);
- sqlite_freemem(errmsg);
- return FAILURE;
- }
-
- /* allow up to 1 minute when busy */
- sqlite_busy_timeout(db, 60000);
-
- sqlite_exec(db, "PRAGMA default_synchronous = OFF", NULL, NULL, NULL);
- sqlite_exec(db, "PRAGMA count_changes = OFF", NULL, NULL, NULL);
-
- /* This will fail if the table already exists, but that's not a big problem. I'm
- unclear as to how to check for a table's existence in SQLite -- that would be better here. */
- sqlite_exec(db,
- "CREATE TABLE session_data ("
- " sess_id PRIMARY KEY,"
- " value TEXT, "
- " updated INTEGER "
- ")", NULL, NULL, NULL);
-
- PS_SET_MOD_DATA(db);
-
- return SUCCESS;
-}
-
-PS_CLOSE_FUNC(sqlite)
-{
- PS_SQLITE_DATA;
-
- sqlite_close(db);
-
- return SUCCESS;
-}
-
-PS_READ_FUNC(sqlite)
-{
- PS_SQLITE_DATA;
- char *query;
- const char *tail;
- sqlite_vm *vm;
- int colcount, result;
- const char **rowdata, **colnames;
- char *error;
-
- *val = NULL;
- *vallen = 0;
-
- query = sqlite_mprintf("SELECT value FROM session_data WHERE sess_id='%q' LIMIT 1", key);
- if (query == NULL) {
- /* no memory */
- return FAILURE;
- }
-
- if (sqlite_compile(db, query, &tail, &vm, &error) != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: Could not compile session read query: %s", error);
- sqlite_freemem(error);
- sqlite_freemem(query);
- return FAILURE;
- }
-
- switch ((result = sqlite_step(vm, &colcount, &rowdata, &colnames))) {
- case SQLITE_ROW:
- if (rowdata[0] != NULL) {
- *vallen = strlen(rowdata[0]);
- if (*vallen) {
- *val = emalloc(*vallen);
- *vallen = sqlite_decode_binary(rowdata[0], *val);
- (*val)[*vallen] = '\0';
- } else {
- *val = STR_EMPTY_ALLOC();
- }
- }
- break;
- default:
- sqlite_freemem(error);
- error = NULL;
- }
-
- if (SQLITE_OK != sqlite_finalize(vm, &error)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session read: error %s", error);
- sqlite_freemem(error);
- error = NULL;
- }
-
- sqlite_freemem(query);
-
- return *val == NULL ? FAILURE : SUCCESS;
-}
-
-PS_WRITE_FUNC(sqlite)
-{
- PS_SQLITE_DATA;
- char *error;
- time_t t;
- char *binary;
- int binlen;
- int rv;
-
- t = time(NULL);
-
- binary = safe_emalloc(1 + vallen / 254, 257, 3);
- binlen = sqlite_encode_binary((const unsigned char*)val, vallen, binary);
-
- rv = sqlite_exec_printf(db, "REPLACE INTO session_data VALUES('%q', '%q', %d)", NULL, NULL, &error, key, binary, t);
- if (rv != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session write query failed: %s", error);
- sqlite_freemem(error);
- }
- efree(binary);
-
- return SQLITE_RETVAL(rv);
-}
-
-PS_DESTROY_FUNC(sqlite)
-{
- int rv;
- PS_SQLITE_DATA;
-
- rv = sqlite_exec_printf(db, "DELETE FROM session_data WHERE sess_id='%q'", NULL, NULL, NULL, key);
-
- return SQLITE_RETVAL(rv);
-}
-
-PS_GC_FUNC(sqlite)
-{
- PS_SQLITE_DATA;
- int rv;
- time_t t = time(NULL);
-
- rv = sqlite_exec_printf(db,
- "DELETE FROM session_data WHERE (%d - updated) > %d",
- NULL, NULL, NULL, t, maxlifetime);
-
- /* because SQLite does not actually clear the deleted data from the database
- * we need to occassionaly do so manually to prevent the sessions database
- * from growing endlessly.
- */
- if ((int) ((float) PS(gc_divisor) * PS(gc_divisor) * php_combined_lcg(TSRMLS_C)) < PS(gc_probability)) {
- rv = sqlite_exec_printf(db, "VACUUM", NULL, NULL, NULL);
- }
- return SQLITE_RETVAL(rv);
-}
-
-#endif /* HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
diff --git a/ext/sqlite/sqlite.c b/ext/sqlite/sqlite.c
deleted file mode 100644
index a7070a9b06..0000000000
--- a/ext/sqlite/sqlite.c
+++ /dev/null
@@ -1,3448 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Wez Furlong <wez@thebrainroom.com> |
- | Tal Peer <tal@php.net> |
- | Marcus Boerger <helly@php.net> |
- +----------------------------------------------------------------------+
-
- $Id$
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define PHP_SQLITE_MODULE_VERSION "2.0-dev"
-
-#include "php.h"
-#include "php_ini.h"
-#include "ext/standard/info.h"
-#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
-#include "ext/session/php_session.h"
-#endif
-#include "php_sqlite.h"
-
-#if HAVE_TIME_H
-# include <time.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <sqlite.h>
-
-#include "zend_exceptions.h"
-#include "zend_interfaces.h"
-
-#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
-extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
-extern PHPAPI zend_class_entry *spl_ce_Countable;
-#endif
-
-#if PHP_SQLITE2_HAVE_PDO
-# include "pdo/php_pdo.h"
-# include "pdo/php_pdo_driver.h"
-extern pdo_driver_t pdo_sqlite2_driver;
-#endif
-
-#ifndef safe_emalloc
-# define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
-#endif
-
-ZEND_DECLARE_MODULE_GLOBALS(sqlite)
-static PHP_GINIT_FUNCTION(sqlite);
-
-#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
-extern ps_module ps_mod_sqlite;
-#define ps_sqlite_ptr &ps_mod_sqlite
-#endif
-
-extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
-extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
-
-#define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
-#define php_sqlite_decode_binary(in, out) in && *in ? sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out) : 0
-
-static int sqlite_count_elements(zval *object, long *count TSRMLS_DC);
-
-static int le_sqlite_db, le_sqlite_result, le_sqlite_pdb;
-
-static inline void php_sqlite_strtoupper(char *s)
-{
- while (*s!='\0') {
- *s = toupper(*s);
- s++;
- }
-}
-
-static inline void php_sqlite_strtolower(char *s)
-{
- while (*s!='\0') {
- *s = tolower(*s);
- s++;
- }
-}
-
-/* {{{ PHP_INI
- */
-PHP_INI_BEGIN()
-STD_PHP_INI_ENTRY_EX("sqlite.assoc_case", "0", PHP_INI_ALL, OnUpdateLong, assoc_case, zend_sqlite_globals, sqlite_globals, display_link_numbers)
-PHP_INI_END()
-/* }}} */
-
-#define DB_FROM_ZVAL(db, zv) ZEND_FETCH_RESOURCE2(db, struct php_sqlite_db *, zv, -1, "sqlite database", le_sqlite_db, le_sqlite_pdb)
-
-#define DB_FROM_OBJECT(db, object) \
- { \
- sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
- db = obj->u.db; \
- if (!db) { \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The database wasn't opened"); \
- RETURN_NULL(); \
- } \
- }
-
-#define RES_FROM_OBJECT_RESTORE_ERH(res, object, error_handling) \
- { \
- sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
- res = obj->u.res; \
- if (!res) { \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No result set available"); \
- if (error_handling) \
- zend_restore_error_handling(error_handling TSRMLS_CC); \
- RETURN_NULL(); \
- } \
- }
-
-#define RES_FROM_OBJECT(res, object) RES_FROM_OBJECT_RESTORE_ERH(res, object, NULL)
-
-#define PHP_SQLITE_EMPTY_QUERY \
- if (!sql_len || !*sql) { \
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute empty query."); \
- RETURN_FALSE; \
- }
-
-struct php_sqlite_result {
- struct php_sqlite_db *db;
- sqlite_vm *vm;
- int buffered;
- int ncolumns;
- int nrows;
- int curr_row;
- char **col_names;
- int alloc_rows;
- int mode;
- char **table;
-};
-
-struct php_sqlite_db {
- sqlite *db;
- int last_err_code;
- zend_bool is_persistent;
- long rsrc_id;
-
- HashTable callbacks;
-};
-
-struct php_sqlite_agg_functions {
- struct php_sqlite_db *db;
- int is_valid;
- zval *step;
- zval *fini;
-};
-
-static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC);
-static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC);
-
-enum { PHPSQLITE_ASSOC = 1, PHPSQLITE_NUM = 2, PHPSQLITE_BOTH = PHPSQLITE_ASSOC|PHPSQLITE_NUM };
-
-/* {{{ arginfo */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_popen, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, mode)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_open, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, mode)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_factory, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, mode)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_busy_timeout, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, ms)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_busy_timeout, 0, 0, 1)
- ZEND_ARG_INFO(0, ms)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_close, 0, 0, 1)
- ZEND_ARG_INFO(0, db)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_unbuffered_query, 0, 0, 2)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_unbuffered_query, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_column_types, 0, 0, 2)
- ZEND_ARG_INFO(0, table_name)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, result_type)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_column_types, 0, 0, 1)
- ZEND_ARG_INFO(0, table_name)
- ZEND_ARG_INFO(0, result_type)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_query, 0, 0, 2)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_query, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_exec, 0, 0, 2)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_exec, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(1, error_message)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_all, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_all, 0, 0, 0)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_array, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_array, 0, 0, 0)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_object, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, class_name)
- ZEND_ARG_INFO(0, ctor_params)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_object, 0, 0, 0)
- ZEND_ARG_INFO(0, class_name)
- ZEND_ARG_INFO(0, ctor_params)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_array_query, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_array_query, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_single_query, 0, 0, 2)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, first_row_only)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_single_query, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, first_row_only)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_fetch_single, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_fetch_single, 0, 0, 0)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_current, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_current, 0, 0, 0)
- ZEND_ARG_INFO(0, result_type)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_column, 0, 0, 2)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, index_or_name)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_column, 0, 0, 1)
- ZEND_ARG_INFO(0, index_or_name)
- ZEND_ARG_INFO(0, decode_binary)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_libversion, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_libencoding, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_changes, 0, 0, 1)
- ZEND_ARG_INFO(0, db)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_changes, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_last_insert_rowid, 0, 0, 1)
- ZEND_ARG_INFO(0, db)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_last_insert_rowid, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_num_rows, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_num_rows, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_valid, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_valid, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_has_prev, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_has_prev, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_num_fields, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_num_fields, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_field_name, 0, 0, 2)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, field_index)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_field_name, 0, 0, 1)
- ZEND_ARG_INFO(0, field_index)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_seek, 0, 0, 2)
- ZEND_ARG_INFO(0, result)
- ZEND_ARG_INFO(0, row)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_seek, 0, 0, 1)
- ZEND_ARG_INFO(0, row)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_rewind, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_rewind, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_next, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_next, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_key, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_key, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_prev, 0, 0, 1)
- ZEND_ARG_INFO(0, result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_prev, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_escape_string, 0, 0, 1)
- ZEND_ARG_INFO(0, item)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_last_error, 0, 0, 1)
- ZEND_ARG_INFO(0, db)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sqlite_method_last_error, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_error_string, 0, 0, 1)
- ZEND_ARG_INFO(0, error_code)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_create_aggregate, 0, 0, 4)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, funcname)
- ZEND_ARG_INFO(0, step_func)
- ZEND_ARG_INFO(0, finalize_func)
- ZEND_ARG_INFO(0, num_args)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_create_aggregate, 0, 0, 3)
- ZEND_ARG_INFO(0, funcname)
- ZEND_ARG_INFO(0, step_func)
- ZEND_ARG_INFO(0, finalize_func)
- ZEND_ARG_INFO(0, num_args)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_create_function, 0, 0, 3)
- ZEND_ARG_INFO(0, db)
- ZEND_ARG_INFO(0, funcname)
- ZEND_ARG_INFO(0, callback)
- ZEND_ARG_INFO(0, num_args)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_method_create_function, 0, 0, 2)
- ZEND_ARG_INFO(0, funcname)
- ZEND_ARG_INFO(0, callback)
- ZEND_ARG_INFO(0, num_args)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_udf_encode_binary, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sqlite_udf_decode_binary, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
-ZEND_END_ARG_INFO()
-/* }}} */
-
-const zend_function_entry sqlite_functions[] = {
- PHP_FE(sqlite_open, arginfo_sqlite_open)
- PHP_FE(sqlite_popen, arginfo_sqlite_popen)
- PHP_FE(sqlite_close, arginfo_sqlite_close)
- PHP_FE(sqlite_query, arginfo_sqlite_query)
- PHP_FE(sqlite_exec, arginfo_sqlite_exec)
- PHP_FE(sqlite_array_query, arginfo_sqlite_array_query)
- PHP_FE(sqlite_single_query, arginfo_sqlite_single_query)
- PHP_FE(sqlite_fetch_array, arginfo_sqlite_fetch_array)
- PHP_FE(sqlite_fetch_object, arginfo_sqlite_fetch_object)
- PHP_FE(sqlite_fetch_single, arginfo_sqlite_fetch_single)
- PHP_FALIAS(sqlite_fetch_string, sqlite_fetch_single, arginfo_sqlite_fetch_single)
- PHP_FE(sqlite_fetch_all, arginfo_sqlite_fetch_all)
- PHP_FE(sqlite_current, arginfo_sqlite_current)
- PHP_FE(sqlite_column, arginfo_sqlite_column)
- PHP_FE(sqlite_libversion, arginfo_sqlite_libversion)
- PHP_FE(sqlite_libencoding, arginfo_sqlite_libencoding)
- PHP_FE(sqlite_changes, arginfo_sqlite_changes)
- PHP_FE(sqlite_last_insert_rowid, arginfo_sqlite_last_insert_rowid)
- PHP_FE(sqlite_num_rows, arginfo_sqlite_num_rows)
- PHP_FE(sqlite_num_fields, arginfo_sqlite_num_fields)
- PHP_FE(sqlite_field_name, arginfo_sqlite_field_name)
- PHP_FE(sqlite_seek, arginfo_sqlite_seek)
- PHP_FE(sqlite_rewind, arginfo_sqlite_rewind)
- PHP_FE(sqlite_next, arginfo_sqlite_next)
- PHP_FE(sqlite_prev, arginfo_sqlite_prev)
- PHP_FE(sqlite_valid, arginfo_sqlite_valid)
- PHP_FALIAS(sqlite_has_more, sqlite_valid, arginfo_sqlite_valid)
- PHP_FE(sqlite_has_prev, arginfo_sqlite_has_prev)
- PHP_FE(sqlite_escape_string, arginfo_sqlite_escape_string)
- PHP_FE(sqlite_busy_timeout, arginfo_sqlite_busy_timeout)
- PHP_FE(sqlite_last_error, arginfo_sqlite_last_error)
- PHP_FE(sqlite_error_string, arginfo_sqlite_error_string)
- PHP_FE(sqlite_unbuffered_query, arginfo_sqlite_unbuffered_query)
- PHP_FE(sqlite_create_aggregate, arginfo_sqlite_create_aggregate)
- PHP_FE(sqlite_create_function, arginfo_sqlite_create_function)
- PHP_FE(sqlite_factory, arginfo_sqlite_factory)
- PHP_FE(sqlite_udf_encode_binary, arginfo_sqlite_udf_encode_binary)
- PHP_FE(sqlite_udf_decode_binary, arginfo_sqlite_udf_decode_binary)
- PHP_FE(sqlite_fetch_column_types, arginfo_sqlite_fetch_column_types)
- {NULL, NULL, NULL}
-};
-
-const zend_function_entry sqlite_funcs_db[] = {
- PHP_ME_MAPPING(__construct, sqlite_open, arginfo_sqlite_open, 0)
-/* PHP_ME_MAPPING(close, sqlite_close, NULL, 0)*/
- PHP_ME_MAPPING(query, sqlite_query, arginfo_sqlite_method_query, 0)
- PHP_ME_MAPPING(queryExec, sqlite_exec, arginfo_sqlite_method_exec, 0)
- PHP_ME_MAPPING(arrayQuery, sqlite_array_query, arginfo_sqlite_method_array_query, 0)
- PHP_ME_MAPPING(singleQuery, sqlite_single_query, arginfo_sqlite_method_single_query, 0)
- PHP_ME_MAPPING(unbufferedQuery, sqlite_unbuffered_query, arginfo_sqlite_method_unbuffered_query, 0)
- PHP_ME_MAPPING(lastInsertRowid, sqlite_last_insert_rowid, arginfo_sqlite_method_last_insert_rowid, 0)
- PHP_ME_MAPPING(changes, sqlite_changes, arginfo_sqlite_method_changes, 0)
- PHP_ME_MAPPING(createAggregate, sqlite_create_aggregate, arginfo_sqlite_method_create_aggregate, 0)
- PHP_ME_MAPPING(createFunction, sqlite_create_function, arginfo_sqlite_method_create_function, 0)
- PHP_ME_MAPPING(busyTimeout, sqlite_busy_timeout, arginfo_sqlite_method_busy_timeout, 0)
- PHP_ME_MAPPING(lastError, sqlite_last_error, arginfo_sqlite_method_last_error, 0)
- PHP_ME_MAPPING(fetchColumnTypes, sqlite_fetch_column_types, arginfo_sqlite_method_fetch_column_types, 0)
-/* PHP_ME_MAPPING(error_string, sqlite_error_string, NULL, 0) static */
-/* PHP_ME_MAPPING(escape_string, sqlite_escape_string, NULL, 0) static */
- {NULL, NULL, NULL}
-};
-
-const zend_function_entry sqlite_funcs_query[] = {
- PHP_ME_MAPPING(fetch, sqlite_fetch_array, arginfo_sqlite_method_fetch_array, 0)
- PHP_ME_MAPPING(fetchObject, sqlite_fetch_object, arginfo_sqlite_method_fetch_object, 0)
- PHP_ME_MAPPING(fetchSingle, sqlite_fetch_single, arginfo_sqlite_method_fetch_single, 0)
- PHP_ME_MAPPING(fetchAll, sqlite_fetch_all, arginfo_sqlite_method_fetch_all, 0)
- PHP_ME_MAPPING(column, sqlite_column, arginfo_sqlite_method_column, 0)
- PHP_ME_MAPPING(numFields, sqlite_num_fields, arginfo_sqlite_method_num_fields, 0)
- PHP_ME_MAPPING(fieldName, sqlite_field_name, arginfo_sqlite_method_field_name, 0)
- /* iterator */
- PHP_ME_MAPPING(current, sqlite_current, arginfo_sqlite_method_current, 0)
- PHP_ME_MAPPING(key, sqlite_key, arginfo_sqlite_method_key, 0)
- PHP_ME_MAPPING(next, sqlite_next, arginfo_sqlite_method_next, 0)
- PHP_ME_MAPPING(valid, sqlite_valid, arginfo_sqlite_method_valid, 0)
- PHP_ME_MAPPING(rewind, sqlite_rewind, arginfo_sqlite_method_rewind, 0)
- /* countable */
- PHP_ME_MAPPING(count, sqlite_num_rows, arginfo_sqlite_method_num_rows, 0)
- /* additional */
- PHP_ME_MAPPING(prev, sqlite_prev, arginfo_sqlite_method_prev, 0)
- PHP_ME_MAPPING(hasPrev, sqlite_has_prev, arginfo_sqlite_method_has_prev, 0)
- PHP_ME_MAPPING(numRows, sqlite_num_rows, arginfo_sqlite_method_num_rows, 0)
- PHP_ME_MAPPING(seek, sqlite_seek, arginfo_sqlite_method_seek, 0)
- {NULL, NULL, NULL}
-};
-
-const zend_function_entry sqlite_funcs_ub_query[] = {
- PHP_ME_MAPPING(fetch, sqlite_fetch_array, arginfo_sqlite_method_fetch_array, 0)
- PHP_ME_MAPPING(fetchObject, sqlite_fetch_object, arginfo_sqlite_method_fetch_object, 0)
- PHP_ME_MAPPING(fetchSingle, sqlite_fetch_single, arginfo_sqlite_method_fetch_single, 0)
- PHP_ME_MAPPING(fetchAll, sqlite_fetch_all, arginfo_sqlite_method_fetch_all, 0)
- PHP_ME_MAPPING(column, sqlite_column, arginfo_sqlite_method_column, 0)
- PHP_ME_MAPPING(numFields, sqlite_num_fields, arginfo_sqlite_method_num_fields, 0)
- PHP_ME_MAPPING(fieldName, sqlite_field_name, arginfo_sqlite_method_field_name, 0)
- /* iterator */
- PHP_ME_MAPPING(current, sqlite_current, arginfo_sqlite_method_current, 0)
- PHP_ME_MAPPING(next, sqlite_next, arginfo_sqlite_method_next, 0)
- PHP_ME_MAPPING(valid, sqlite_valid, arginfo_sqlite_method_valid, 0)
- {NULL, NULL, NULL}
-};
-
-const zend_function_entry sqlite_funcs_exception[] = {
- {NULL, NULL, NULL}
-};
-
-/* Dependancies */
-static const zend_module_dep sqlite_deps[] = {
-#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
- ZEND_MOD_REQUIRED("spl")
-#endif
-#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
- ZEND_MOD_REQUIRED("session")
-#endif
-#ifdef PHP_SQLITE2_HAVE_PDO
- ZEND_MOD_REQUIRED("pdo")
-#endif
- {NULL, NULL, NULL}
-};
-
-zend_module_entry sqlite_module_entry = {
-#if ZEND_MODULE_API_NO >= 20050922
- STANDARD_MODULE_HEADER_EX, NULL,
- sqlite_deps,
-#elif ZEND_MODULE_API_NO >= 20010901
- STANDARD_MODULE_HEADER,
-#endif
- "SQLite",
- sqlite_functions,
- PHP_MINIT(sqlite),
- PHP_MSHUTDOWN(sqlite),
- NULL,
- PHP_RSHUTDOWN(sqlite),
- PHP_MINFO(sqlite),
-#if ZEND_MODULE_API_NO >= 20010901
- PHP_SQLITE_MODULE_VERSION,
-#endif
-#if ZEND_MODULE_API_NO >= 20060613
- PHP_MODULE_GLOBALS(sqlite),
- PHP_GINIT(sqlite),
- NULL,
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
-#else
- STANDARD_MODULE_PROPERTIES
-#endif
-};
-
-
-#ifdef COMPILE_DL_SQLITE
-ZEND_GET_MODULE(sqlite)
-#endif
-
-static int php_sqlite_callback_invalidator(struct php_sqlite_agg_functions *funcs TSRMLS_DC)
-{
- if (!funcs->is_valid) {
- return 0;
- }
-
- if (funcs->step) {
- zval_ptr_dtor(&funcs->step);
- funcs->step = NULL;
- }
-
- if (funcs->fini) {
- zval_ptr_dtor(&funcs->fini);
- funcs->fini = NULL;
- }
-
- funcs->is_valid = 0;
-
- return 0;
-}
-
-
-static void php_sqlite_callback_dtor(void *pDest)
-{
- struct php_sqlite_agg_functions *funcs = (struct php_sqlite_agg_functions*)pDest;
-
- if (funcs->is_valid) {
- TSRMLS_FETCH();
-
- php_sqlite_callback_invalidator(funcs TSRMLS_CC);
- }
-}
-
-static ZEND_RSRC_DTOR_FUNC(php_sqlite_db_dtor)
-{
- if (rsrc->ptr) {
- struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
-
- sqlite_close(db->db);
-
- zend_hash_destroy(&db->callbacks);
-
- pefree(db, db->is_persistent);
-
- rsrc->ptr = NULL;
- }
-}
-
-static void real_result_dtor(struct php_sqlite_result *res TSRMLS_DC)
-{
- int i, j, base;
-
- if (res->vm) {
- sqlite_finalize(res->vm, NULL);
- }
-
- if (res->table) {
- if (!res->buffered && res->nrows) {
- res->nrows = 1; /* only one row is stored */
- }
- for (i = 0; i < res->nrows; i++) {
- base = i * res->ncolumns;
- for (j = 0; j < res->ncolumns; j++) {
- if (res->table[base + j] != NULL) {
- efree(res->table[base + j]);
- }
- }
- }
- efree(res->table);
- }
- if (res->col_names) {
- for (j = 0; j < res->ncolumns; j++) {
- efree(res->col_names[j]);
- }
- efree(res->col_names);
- }
-
- if (res->db) {
- zend_list_delete(res->db->rsrc_id);
- }
- efree(res);
-}
-
-static int _clean_unfinished_results(zend_rsrc_list_entry *le, void *db TSRMLS_DC)
-{
- if (Z_TYPE_P(le) == le_sqlite_result) {
- struct php_sqlite_result *res = (struct php_sqlite_result *)le->ptr;
- if (res->db->rsrc_id == ((struct php_sqlite_db*)db)->rsrc_id) {
- return ZEND_HASH_APPLY_REMOVE;
- }
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-
-static ZEND_RSRC_DTOR_FUNC(php_sqlite_result_dtor)
-{
- struct php_sqlite_result *res = (struct php_sqlite_result *)rsrc->ptr;
- real_result_dtor(res TSRMLS_CC);
-}
-
-static int php_sqlite_forget_persistent_id_numbers(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
- struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
-
- if (Z_TYPE_P(rsrc) != le_sqlite_pdb) {
- return 0;
- }
-
- /* prevent bad mojo if someone tries to use a previously registered function in the next request */
- zend_hash_apply(&db->callbacks, (apply_func_t)php_sqlite_callback_invalidator TSRMLS_CC);
-
- db->rsrc_id = FAILURE;
-
- /* don't leave pending commits hanging around */
- sqlite_exec(db->db, "ROLLBACK", NULL, NULL, NULL);
-
- return 0;
-}
-
-PHP_RSHUTDOWN_FUNCTION(sqlite)
-{
- zend_hash_apply(&EG(persistent_list), (apply_func_t)php_sqlite_forget_persistent_id_numbers TSRMLS_CC);
- return SUCCESS;
-}
-
-/* {{{ PHP Function interface */
-static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, const char **argv)
-{
- zval *retval = NULL;
- zval ***zargs = NULL;
- zval funcname;
- int i, res;
- char *callable = NULL, *errbuf=NULL;
- TSRMLS_FETCH();
-
- /* sanity check the args */
- if (argc == 0) {
- sqlite_set_result_error(func, "not enough parameters", -1);
- return;
- }
-
- ZVAL_STRING(&funcname, (char*)argv[0], 1);
-
- if (!zend_make_callable(&funcname, &callable TSRMLS_CC)) {
- spprintf(&errbuf, 0, "function `%s' is not a function name", callable);
- sqlite_set_result_error(func, errbuf, -1);
- efree(errbuf);
- efree(callable);
- zval_dtor(&funcname);
- return;
- }
-
- if (argc > 1) {
- zargs = (zval ***)safe_emalloc((argc - 1), sizeof(zval **), 0);
-
- for (i = 0; i < argc-1; i++) {
- zargs[i] = emalloc(sizeof(zval *));
- MAKE_STD_ZVAL(*zargs[i]);
- ZVAL_STRING(*zargs[i], (char*)argv[i+1], 1);
- }
- }
-
- res = call_user_function_ex(EG(function_table),
- NULL,
- &funcname,
- &retval,
- argc-1,
- zargs,
- 0, NULL TSRMLS_CC);
-
- zval_dtor(&funcname);
-
- if (res == SUCCESS) {
- if (retval == NULL) {
- sqlite_set_result_string(func, NULL, 0);
- } else {
- switch (Z_TYPE_P(retval)) {
- case IS_STRING:
- sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
- break;
- case IS_LONG:
- case IS_BOOL:
- sqlite_set_result_int(func, Z_LVAL_P(retval));
- break;
- case IS_DOUBLE:
- sqlite_set_result_double(func, Z_DVAL_P(retval));
- break;
- case IS_NULL:
- default:
- sqlite_set_result_string(func, NULL, 0);
- }
- }
- } else {
- char *errbuf;
- spprintf(&errbuf, 0, "call_user_function_ex failed for function %s()", callable);
- sqlite_set_result_error(func, errbuf, -1);
- efree(errbuf);
- }
-
- efree(callable);
-
- if (retval) {
- zval_ptr_dtor(&retval);
- }
-
- if (zargs) {
- for (i = 0; i < argc-1; i++) {
- zval_ptr_dtor(zargs[i]);
- efree(zargs[i]);
- }
- efree(zargs);
- }
-}
-/* }}} */
-
-/* {{{ callback for sqlite_create_function */
-static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv)
-{
- zval *retval = NULL;
- zval ***zargs = NULL;
- int i, res;
- struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
- TSRMLS_FETCH();
-
- if (!funcs->is_valid) {
- sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
- return;
- }
-
- if (argc > 0) {
- zargs = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
-
- for (i = 0; i < argc; i++) {
- zargs[i] = emalloc(sizeof(zval *));
- MAKE_STD_ZVAL(*zargs[i]);
-
- if (argv[i] == NULL) {
- ZVAL_NULL(*zargs[i]);
- } else {
- ZVAL_STRING(*zargs[i], (char*)argv[i], 1);
- }
- }
- }
-
- res = call_user_function_ex(EG(function_table),
- NULL,
- funcs->step,
- &retval,
- argc,
- zargs,
- 0, NULL TSRMLS_CC);
-
- if (res == SUCCESS) {
- if (retval == NULL) {
- sqlite_set_result_string(func, NULL, 0);
- } else {
- switch (Z_TYPE_P(retval)) {
- case IS_STRING:
- /* TODO: for binary results, need to encode the string */
- sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
- break;
- case IS_LONG:
- case IS_BOOL:
- sqlite_set_result_int(func, Z_LVAL_P(retval));
- break;
- case IS_DOUBLE:
- sqlite_set_result_double(func, Z_DVAL_P(retval));
- break;
- case IS_NULL:
- default:
- sqlite_set_result_string(func, NULL, 0);
- }
- }
- } else {
- sqlite_set_result_error(func, "call_user_function_ex failed", -1);
- }
-
- if (retval) {
- zval_ptr_dtor(&retval);
- }
-
- if (zargs) {
- for (i = 0; i < argc; i++) {
- zval_ptr_dtor(zargs[i]);
- efree(zargs[i]);
- }
- efree(zargs);
- }
-}
-/* }}} */
-
-/* {{{ callback for sqlite_create_aggregate: step function */
-static void php_sqlite_agg_step_function_callback(sqlite_func *func, int argc, const char **argv)
-{
- zval *retval = NULL;
- zval ***zargs;
- zval **context_p;
- int i, res, zargc;
- struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
- TSRMLS_FETCH();
-
- if (!funcs->is_valid) {
- sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
- return;
- }
-
- /* sanity check the args */
- if (argc < 1) {
- return;
- }
-
- zargc = argc + 1;
- zargs = (zval ***)safe_emalloc(zargc, sizeof(zval **), 0);
-
- /* first arg is always the context zval */
- context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
-
- if (*context_p == NULL) {
- MAKE_STD_ZVAL(*context_p);
- Z_SET_ISREF_PP(context_p);
- Z_TYPE_PP(context_p) = IS_NULL;
- }
-
- zargs[0] = context_p;
-
- /* copy the other args */
- for (i = 0; i < argc; i++) {
- zargs[i+1] = emalloc(sizeof(zval *));
- MAKE_STD_ZVAL(*zargs[i+1]);
- if (argv[i] == NULL) {
- ZVAL_NULL(*zargs[i+1]);
- } else {
- ZVAL_STRING(*zargs[i+1], (char*)argv[i], 1);
- }
- }
-
- res = call_user_function_ex(EG(function_table),
- NULL,
- funcs->step,
- &retval,
- zargc,
- zargs,
- 0, NULL TSRMLS_CC);
-
- if (res != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "call_user_function_ex failed");
- }
-
- if (retval) {
- zval_ptr_dtor(&retval);
- }
-
- if (zargs) {
- for (i = 1; i < zargc; i++) {
- zval_ptr_dtor(zargs[i]);
- efree(zargs[i]);
- }
- efree(zargs);
- }
-}
-/* }}} */
-
-/* {{{ callback for sqlite_create_aggregate: finalize function */
-static void php_sqlite_agg_fini_function_callback(sqlite_func *func)
-{
- zval *retval = NULL;
- int res;
- struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
- zval **context_p;
- TSRMLS_FETCH();
-
- if (!funcs->is_valid) {
- sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
- return;
- }
-
- context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
-
- res = call_user_function_ex(EG(function_table),
- NULL,
- funcs->fini,
- &retval,
- 1,
- &context_p,
- 0, NULL TSRMLS_CC);
-
- if (res == SUCCESS) {
- if (retval == NULL) {
- sqlite_set_result_string(func, NULL, 0);
- } else {
- switch (Z_TYPE_P(retval)) {
- case IS_STRING:
- /* TODO: for binary results, need to encode the string */
- sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
- break;
- case IS_LONG:
- case IS_BOOL:
- sqlite_set_result_int(func, Z_LVAL_P(retval));
- break;
- case IS_DOUBLE:
- sqlite_set_result_double(func, Z_DVAL_P(retval));
- break;
- case IS_NULL:
- default:
- sqlite_set_result_string(func, NULL, 0);
- }
- }
- } else {
- sqlite_set_result_error(func, "call_user_function_ex failed", -1);
- }
-
- if (retval) {
- zval_ptr_dtor(&retval);
- }
-
- zval_ptr_dtor(context_p);
-}
-/* }}} */
-
-/* {{{ Authorization Callback */
-static int php_sqlite_authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
- const char *arg5, const char *arg6)
-{
- switch (access_type) {
- case SQLITE_COPY:
- if (strncmp(arg4, ":memory:", sizeof(":memory:") - 1)) {
- TSRMLS_FETCH();
- if (PG(safe_mode) && (!php_checkuid(arg4, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return SQLITE_DENY;
- }
-
- if (php_check_open_basedir(arg4 TSRMLS_CC)) {
- return SQLITE_DENY;
- }
- }
- return SQLITE_OK;
-#ifdef SQLITE_ATTACH
- case SQLITE_ATTACH:
- if (strncmp(arg3, ":memory:", sizeof(":memory:") - 1)) {
- TSRMLS_FETCH();
- if (PG(safe_mode) && (!php_checkuid(arg3, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return SQLITE_DENY;
- }
-
- if (php_check_open_basedir(arg3 TSRMLS_CC)) {
- return SQLITE_DENY;
- }
- }
- return SQLITE_OK;
-#endif
-
- default:
- /* access allowed */
- return SQLITE_OK;
- }
-}
-/* }}} */
-
-/* {{{ OO init/structure stuff */
-#define REGISTER_SQLITE_CLASS(name, c_name, parent) \
- { \
- zend_class_entry ce; \
- INIT_CLASS_ENTRY(ce, "SQLite" # name, sqlite_funcs_ ## c_name); \
- ce.create_object = sqlite_object_new_ ## c_name; \
- sqlite_ce_ ## c_name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
- memcpy(&sqlite_object_handlers_ ## c_name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
- sqlite_object_handlers_ ## c_name.clone_obj = NULL; \
- sqlite_ce_ ## c_name->ce_flags |= ZEND_ACC_FINAL_CLASS; \
- }
-
-zend_class_entry *sqlite_ce_db, *sqlite_ce_exception;
-zend_class_entry *sqlite_ce_query, *sqlite_ce_ub_query;
-
-static zend_object_handlers sqlite_object_handlers_db;
-static zend_object_handlers sqlite_object_handlers_query;
-static zend_object_handlers sqlite_object_handlers_ub_query;
-static zend_object_handlers sqlite_object_handlers_exception;
-
-typedef enum {
- is_db,
- is_result
-} sqlite_obj_type;
-
-typedef struct _sqlite_object {
- zend_object std;
- sqlite_obj_type type;
- union {
- struct php_sqlite_db *db;
- struct php_sqlite_result *res;
- void *ptr;
- } u;
-} sqlite_object;
-
-static int sqlite_free_persistent(zend_rsrc_list_entry *le, void *ptr TSRMLS_DC)
-{
- return le->ptr == ptr ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_KEEP;
-}
-
-static void sqlite_object_free_storage(void *object TSRMLS_DC)
-{
- sqlite_object *intern = (sqlite_object *)object;
-
- zend_object_std_dtor(&intern->std TSRMLS_CC);
-
- if (intern->u.ptr) {
- if (intern->type == is_db) {
- if (intern->u.db->rsrc_id) {
- zend_list_delete(intern->u.db->rsrc_id);
- zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) sqlite_free_persistent, &intern->u.ptr TSRMLS_CC);
- }
- } else {
- real_result_dtor(intern->u.res TSRMLS_CC);
- }
- }
-
- efree(object);
-}
-
-static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
-{
- sqlite_object *intern;
- zval *tmp;
-
- intern = emalloc(sizeof(sqlite_object));
- memset(intern, 0, sizeof(sqlite_object));
-
- zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
-
- retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) sqlite_object_free_storage, NULL TSRMLS_CC);
- retval->handlers = handlers;
-}
-
-static zend_object_value sqlite_object_new_db(zend_class_entry *class_type TSRMLS_DC)
-{
- zend_object_value retval;
-
- sqlite_object_new(class_type, &sqlite_object_handlers_db, &retval TSRMLS_CC);
- return retval;
-}
-
-static zend_object_value sqlite_object_new_query(zend_class_entry *class_type TSRMLS_DC)
-{
- zend_object_value retval;
-
- sqlite_object_new(class_type, &sqlite_object_handlers_query, &retval TSRMLS_CC);
- return retval;
-}
-
-static zend_object_value sqlite_object_new_ub_query(zend_class_entry *class_type TSRMLS_DC)
-{
- zend_object_value retval;
-
- sqlite_object_new(class_type, &sqlite_object_handlers_ub_query, &retval TSRMLS_CC);
- return retval;
-}
-
-static zend_object_value sqlite_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
-{
- zend_object_value retval;
-
- sqlite_object_new(class_type, &sqlite_object_handlers_exception, &retval TSRMLS_CC);
- return retval;
-}
-
-#define SQLITE_REGISTER_OBJECT(_type, _object, _ptr) \
- { \
- sqlite_object *obj; \
- obj = (sqlite_object*)zend_object_store_get_object(_object TSRMLS_CC); \
- obj->type = is_ ## _type; \
- obj->u._type = _ptr; \
- }
-
-static zend_class_entry *sqlite_get_ce_query(const zval *object TSRMLS_DC)
-{
- return sqlite_ce_query;
-}
-
-static zend_class_entry *sqlite_get_ce_ub_query(const zval *object TSRMLS_DC)
-{
- return sqlite_ce_ub_query;
-}
-
-static zval * sqlite_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
-{
- if (!object) {
- ALLOC_ZVAL(object);
- }
- Z_TYPE_P(object) = IS_OBJECT;
- object_init_ex(object, pce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
- return object;
-}
-
-typedef struct _sqlite_object_iterator {
- zend_object_iterator it;
- struct php_sqlite_result *res;
- zval *value;
-} sqlite_object_iterator;
-
-void sqlite_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)
-{
- zval *object = (zval*)((sqlite_object_iterator*)iter)->it.data;
-
- if (((sqlite_object_iterator*)iter)->value) {
- zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
- ((sqlite_object_iterator*)iter)->value = NULL;
- }
- zval_ptr_dtor(&object);
- efree(iter);
-}
-
-void sqlite_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
-{
- struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
-
- if (((sqlite_object_iterator*)iter)->value) {
- zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
- ((sqlite_object_iterator*)iter)->value = NULL;
- }
- if (res) {
- res->curr_row = 0;
- }
-}
-
-int sqlite_iterator_valid(zend_object_iterator *iter TSRMLS_DC)
-{
- struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
-
- if (res && res->curr_row < res->nrows && res->nrows) { /* curr_row may be -1 */
- return SUCCESS;
- } else {
- return FAILURE;
- }
-}
-
-void sqlite_iterator_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
-{
- struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
-
- *data = &((sqlite_object_iterator*)iter)->value;
- if (res && !**data) {
- MAKE_STD_ZVAL(**data);
- php_sqlite_fetch_array(res, res->mode, 1, 0, **data TSRMLS_CC);
- }
-
-}
-
-int sqlite_iterator_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
-{
- struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
-
- *str_key = NULL;
- *str_key_len = 0;
- *int_key = res ? res->curr_row : 0;
- return HASH_KEY_IS_LONG;
-}
-
-void sqlite_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
-{
- struct php_sqlite_result *res = ((sqlite_object_iterator*)iter)->res;
-
- if (((sqlite_object_iterator*)iter)->value) {
- zval_ptr_dtor(&((sqlite_object_iterator*)iter)->value);
- ((sqlite_object_iterator*)iter)->value = NULL;
- }
- if (res) {
- if (!res->buffered && res->vm) {
- php_sqlite_fetch(res TSRMLS_CC);
- }
- if (res->curr_row >= res->nrows) {
- /* php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available"); */
- return;
- }
-
- res->curr_row++;
- }
-}
-
-zend_object_iterator_funcs sqlite_ub_query_iterator_funcs = {
- sqlite_iterator_dtor,
- sqlite_iterator_valid,
- sqlite_iterator_get_current_data,
- sqlite_iterator_get_current_key,
- sqlite_iterator_move_forward,
- NULL
-};
-
-zend_object_iterator_funcs sqlite_query_iterator_funcs = {
- sqlite_iterator_dtor,
- sqlite_iterator_valid,
- sqlite_iterator_get_current_data,
- sqlite_iterator_get_current_key,
- sqlite_iterator_move_forward,
- sqlite_iterator_rewind
-};
-
-zend_object_iterator *sqlite_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
-{
- sqlite_object_iterator *iterator = emalloc(sizeof(sqlite_object_iterator));
-
- sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
-
- if (by_ref) {
- zend_error(E_RECOVERABLE_ERROR, "An iterator cannot be used with foreach by reference");
- }
- Z_ADDREF_P(object);
- iterator->it.data = (void*)object;
- iterator->it.funcs = ce->iterator_funcs.funcs;
- iterator->res = obj->u.res;
- iterator->value = NULL;
- return (zend_object_iterator*)iterator;
-}
-/* }}} */
-
-static PHP_GINIT_FUNCTION(sqlite)
-{
- sqlite_globals->assoc_case = 0;
-}
-
-PHP_MINIT_FUNCTION(sqlite)
-{
- REGISTER_SQLITE_CLASS(Database, db, NULL);
- REGISTER_SQLITE_CLASS(Result, query, NULL);
- REGISTER_SQLITE_CLASS(Unbuffered, ub_query, NULL);
-#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
- REGISTER_SQLITE_CLASS(Exception, exception, spl_ce_RuntimeException);
-#else
- REGISTER_SQLITE_CLASS(Exception, exception, zend_exception_get_default(TSRMLS_C));
-#endif
-
- sqlite_ce_db->ce_flags &= ~ZEND_ACC_FINAL_CLASS;
- sqlite_ce_db->constructor->common.fn_flags |= ZEND_ACC_FINAL;
-
- sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query;
- sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query;
- sqlite_object_handlers_ub_query.count_elements = sqlite_count_elements;
-
- sqlite_ce_ub_query->get_iterator = sqlite_get_iterator;
- sqlite_ce_ub_query->iterator_funcs.funcs = &sqlite_ub_query_iterator_funcs;
-
-#if defined(HAVE_SPL) && ((PHP_MAJOR_VERSION > 5) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1))
- zend_class_implements(sqlite_ce_query TSRMLS_CC, 2, zend_ce_iterator, spl_ce_Countable);
-#else
- zend_class_implements(sqlite_ce_query TSRMLS_CC, 1, zend_ce_iterator);
-#endif
- sqlite_ce_query->get_iterator = sqlite_get_iterator;
- sqlite_ce_query->iterator_funcs.funcs = &sqlite_query_iterator_funcs;
-
- REGISTER_INI_ENTRIES();
-
-#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
- php_session_register_module(ps_sqlite_ptr);
-#endif
-
- le_sqlite_db = zend_register_list_destructors_ex(php_sqlite_db_dtor, NULL, "sqlite database", module_number);
- le_sqlite_pdb = zend_register_list_destructors_ex(NULL, php_sqlite_db_dtor, "sqlite database (persistent)", module_number);
- le_sqlite_result = zend_register_list_destructors_ex(php_sqlite_result_dtor, NULL, "sqlite result", module_number);
-
- REGISTER_LONG_CONSTANT("SQLITE_BOTH", PHPSQLITE_BOTH, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_NUM", PHPSQLITE_NUM, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_ASSOC", PHPSQLITE_ASSOC, CONST_CS|CONST_PERSISTENT);
-
- REGISTER_LONG_CONSTANT("SQLITE_OK", SQLITE_OK, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_ERROR", SQLITE_ERROR, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_INTERNAL", SQLITE_INTERNAL, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_PERM", SQLITE_PERM, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_ABORT", SQLITE_ABORT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_BUSY", SQLITE_BUSY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_LOCKED", SQLITE_LOCKED, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_NOMEM", SQLITE_NOMEM, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_READONLY", SQLITE_READONLY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_INTERRUPT", SQLITE_INTERRUPT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_IOERR", SQLITE_IOERR, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_CORRUPT", SQLITE_CORRUPT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_NOTFOUND", SQLITE_NOTFOUND, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_FULL", SQLITE_FULL, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_CANTOPEN", SQLITE_CANTOPEN, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_PROTOCOL", SQLITE_PROTOCOL, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_EMPTY", SQLITE_EMPTY, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_SCHEMA", SQLITE_SCHEMA, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_TOOBIG", SQLITE_TOOBIG, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_CONSTRAINT", SQLITE_CONSTRAINT, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_MISMATCH", SQLITE_MISMATCH, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_MISUSE", SQLITE_MISUSE, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_NOLFS", SQLITE_NOLFS, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_AUTH", SQLITE_AUTH, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_NOTADB", SQLITE_NOTADB, CONST_CS|CONST_PERSISTENT);
-#ifdef SQLITE_FORMAT
- REGISTER_LONG_CONSTANT("SQLITE_FORMAT", SQLITE_FORMAT, CONST_CS|CONST_PERSISTENT);
-#endif
- REGISTER_LONG_CONSTANT("SQLITE_ROW", SQLITE_ROW, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("SQLITE_DONE", SQLITE_DONE, CONST_CS|CONST_PERSISTENT);
-
-#ifdef PHP_SQLITE2_HAVE_PDO
- if (FAILURE == php_pdo_register_driver(&pdo_sqlite2_driver)) {
- return FAILURE;
- }
-#endif
-
- return SUCCESS;
-}
-
-PHP_MSHUTDOWN_FUNCTION(sqlite)
-{
- UNREGISTER_INI_ENTRIES();
-
-#ifdef PHP_SQLITE2_HAVE_PDO
- php_pdo_unregister_driver(&pdo_sqlite2_driver);
-#endif
-
- return SUCCESS;
-}
-
-PHP_MINFO_FUNCTION(sqlite)
-{
- php_info_print_table_start();
- php_info_print_table_header(2, "SQLite support", "enabled");
- php_info_print_table_row(2, "PECL Module version", PHP_SQLITE_MODULE_VERSION " $Id$");
- php_info_print_table_row(2, "SQLite Library", sqlite_libversion());
- php_info_print_table_row(2, "SQLite Encoding", sqlite_libencoding());
- php_info_print_table_end();
-
- DISPLAY_INI_ENTRIES();
-}
-
-static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg, zval *object TSRMLS_DC)
-{
- char *errtext = NULL;
- sqlite *sdb = NULL;
- struct php_sqlite_db *db = NULL;
-
- sdb = sqlite_open(filename, mode, &errtext);
-
- if (sdb == NULL) {
-
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
-
- if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
- }
-
- sqlite_freemem(errtext);
-
- /* if object is not an object then we're called from the factory() function */
- if (object && Z_TYPE_P(object) != IS_OBJECT) {
- RETVAL_NULL();
- } else {
- RETVAL_FALSE;
- }
- return NULL;
- }
-
- db = (struct php_sqlite_db *)pemalloc(sizeof(struct php_sqlite_db), persistent_id ? 1 : 0);
- db->is_persistent = persistent_id ? 1 : 0;
- db->last_err_code = SQLITE_OK;
- db->db = sdb;
-
- zend_hash_init(&db->callbacks, 0, NULL, php_sqlite_callback_dtor, db->is_persistent);
-
- /* register the PHP functions */
- sqlite_create_function(sdb, "php", -1, php_sqlite_generic_function_callback, 0);
-
- /* set default busy handler; keep retrying up until 1 minute has passed,
- * then fail with a busy status code */
- sqlite_busy_timeout(sdb, 60000);
-
- /* authorizer hook so we can enforce safe mode
- * Note: the declaration of php_sqlite_authorizer is correct for 2.8.2 of libsqlite,
- * and IS backwards binary compatible with earlier versions */
- if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
- sqlite_set_authorizer(sdb, php_sqlite_authorizer, NULL);
- }
-
- db->rsrc_id = ZEND_REGISTER_RESOURCE(object ? NULL : return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db);
- if (object) {
- /* if object is not an object then we're called from the factory() function */
- if (Z_TYPE_P(object) != IS_OBJECT) {
- sqlite_instanciate(sqlite_ce_db, object TSRMLS_CC);
- }
- /* and now register the object */
- SQLITE_REGISTER_OBJECT(db, object, db)
- }
-
- if (persistent_id) {
- zend_rsrc_list_entry le;
-
- Z_TYPE(le) = le_sqlite_pdb;
- le.ptr = db;
-
- if (FAILURE == zend_hash_update(&EG(persistent_list), persistent_id,
- strlen(persistent_id)+1,
- (void *)&le, sizeof(le), NULL)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent resource");
- }
- }
-
- return db;
-}
-
-/* {{{ proto resource sqlite_popen(string filename [, int mode [, string &error_message]])
- Opens a persistent handle to a SQLite database. Will create the database if it does not exist. */
-PHP_FUNCTION(sqlite_popen)
-{
- long mode = 0666;
- char *filename, *fullpath, *hashkey;
- int filename_len, hashkeylen;
- zval *errmsg = NULL;
- struct php_sqlite_db *db = NULL;
- zend_rsrc_list_entry *le;
-
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
- &filename, &filename_len, &mode, &errmsg)) {
- return;
- }
- if (errmsg) {
- zval_dtor(errmsg);
- ZVAL_NULL(errmsg);
- }
-
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
- if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
- /* resolve the fully-qualified path name to use as the hash key */
- if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
- RETURN_FALSE;
- }
-
- if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
- php_check_open_basedir(fullpath TSRMLS_CC)) {
- efree(fullpath);
- RETURN_FALSE;
- }
- } else {
- fullpath = estrndup(filename, filename_len);
- }
-
- hashkeylen = spprintf(&hashkey, 0, "sqlite_pdb_%s:%ld", fullpath, mode);
-
- /* do we have an existing persistent connection ? */
- if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, hashkeylen+1, (void*)&le)) {
- if (Z_TYPE_P(le) == le_sqlite_pdb) {
- db = (struct php_sqlite_db*)le->ptr;
-
- if (db->rsrc_id == FAILURE) {
- /* give it a valid resource id for this request */
- db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
- } else {
- int type;
- /* sanity check to ensure that the resource is still a valid regular resource
- * number */
- if (zend_list_find(db->rsrc_id, &type) == db) {
- /* already accessed this request; map it */
- zend_list_addref(db->rsrc_id);
- ZVAL_RESOURCE(return_value, db->rsrc_id);
- } else {
- db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
- }
- }
-
- /* all set */
- goto done;
- }
-
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Some other type of persistent resource is using this hash key!?");
- RETVAL_FALSE;
- goto done;
- }
-
- /* now we need to open the database */
- php_sqlite_open(fullpath, (int)mode, hashkey, return_value, errmsg, NULL TSRMLS_CC);
-done:
- efree(fullpath);
- efree(hashkey);
-}
-/* }}} */
-
-/* {{{ proto resource sqlite_open(string filename [, int mode [, string &error_message]])
- Opens a SQLite database. Will create the database if it does not exist. */
-PHP_FUNCTION(sqlite_open)
-{
- long mode = 0666;
- char *filename, *fullpath = NULL;
- int filename_len;
- zval *errmsg = NULL;
- zval *object = getThis();
- zend_error_handling error_handling;
-
- zend_replace_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception, &error_handling TSRMLS_CC);
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
- &filename, &filename_len, &mode, &errmsg)) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- return;
- }
- if (errmsg) {
- zval_dtor(errmsg);
- ZVAL_NULL(errmsg);
- }
-
- if (strlen(filename) != filename_len) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- RETURN_FALSE;
- }
-
- if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
- /* resolve the fully-qualified path name to use as the hash key */
- if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- if (object) {
- RETURN_NULL();
- } else {
- RETURN_FALSE;
- }
- }
-
- if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
- php_check_open_basedir(fullpath TSRMLS_CC)) {
- efree(fullpath);
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- if (object) {
- RETURN_NULL();
- } else {
- RETURN_FALSE;
- }
- }
- }
-
- php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, object TSRMLS_CC);
-
- if (fullpath) {
- efree(fullpath);
- }
- zend_restore_error_handling(&error_handling TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto object sqlite_factory(string filename [, int mode [, string &error_message]])
- Opens a SQLite database and creates an object for it. Will create the database if it does not exist. */
-PHP_FUNCTION(sqlite_factory)
-{
- long mode = 0666;
- char *filename, *fullpath = NULL;
- int filename_len;
- zval *errmsg = NULL;
- zend_error_handling error_handling;
-
- zend_replace_error_handling(EH_THROW, sqlite_ce_exception, &error_handling TSRMLS_CC);
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
- &filename, &filename_len, &mode, &errmsg)) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- RETURN_NULL();
- }
- if (errmsg) {
- zval_dtor(errmsg);
- ZVAL_NULL(errmsg);
- }
-
- if (strlen(filename) != filename_len) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- RETURN_FALSE;
- }
-
- if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
- /* resolve the fully-qualified path name to use as the hash key */
- if (!(fullpath = expand_filepath(filename, NULL TSRMLS_CC))) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- RETURN_NULL();
- }
-
- if ((PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) ||
- php_check_open_basedir(fullpath TSRMLS_CC)) {
- efree(fullpath);
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- RETURN_NULL();
- }
- }
-
- php_sqlite_open(fullpath ? fullpath : filename, (int)mode, NULL, return_value, errmsg, return_value TSRMLS_CC);
- if (fullpath) {
- efree(fullpath);
- }
- zend_restore_error_handling(&error_handling TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto void sqlite_busy_timeout(resource db, int ms)
- Set busy timeout duration. If ms <= 0, all busy handlers are disabled. */
-PHP_FUNCTION(sqlite_busy_timeout)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- long ms;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ms)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- sqlite_busy_timeout(db->db, ms);
-}
-/* }}} */
-
-/* {{{ proto void sqlite_close(resource db)
- Closes an open sqlite database. */
-PHP_FUNCTION(sqlite_close)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- zval *object = getThis();
-
- if (object) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Ignored, you must destruct the object instead");
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- zend_hash_apply_with_argument(&EG(regular_list),
- (apply_func_arg_t) _clean_unfinished_results,
- db TSRMLS_CC);
-
- zend_list_delete(Z_RESVAL_P(zdb));
-}
-/* }}} */
-
-/* {{{ php_sqlite_fetch */
-static int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
-{
- const char **rowdata, **colnames;
- int ret, i, base;
- char *errtext = NULL;
-
-next_row:
- ret = sqlite_step(rres->vm, &rres->ncolumns, &rowdata, &colnames);
- if (!rres->nrows) {
- /* first row - lets copy the column names */
- rres->col_names = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
- for (i = 0; i < rres->ncolumns; i++) {
- rres->col_names[i] = estrdup((char*)colnames[i]);
-
- if (SQLITE_G(assoc_case) == 1) {
- php_sqlite_strtoupper(rres->col_names[i]);
- } else if (SQLITE_G(assoc_case) == 2) {
- php_sqlite_strtolower(rres->col_names[i]);
- }
- }
- if (!rres->buffered) {
- /* non buffered mode - also fetch memory for on single row */
- rres->table = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
- }
- }
-
- switch (ret) {
- case SQLITE_ROW:
- if (rres->buffered) {
- /* add the row to our collection */
- if (rres->nrows + 1 >= rres->alloc_rows) {
- rres->alloc_rows = rres->alloc_rows ? rres->alloc_rows * 2 : 16;
- rres->table = safe_erealloc(rres->table, rres->alloc_rows, rres->ncolumns*sizeof(char *), 0);
- }
- base = rres->nrows * rres->ncolumns;
- for (i = 0; i < rres->ncolumns; i++) {
- if (rowdata[i]) {
- rres->table[base + i] = estrdup(rowdata[i]);
- } else {
- rres->table[base + i] = NULL;
- }
- }
- rres->nrows++;
- goto next_row;
- } else {
- /* non buffered: only fetch one row but first free data if not first row */
- if (rres->nrows++) {
- for (i = 0; i < rres->ncolumns; i++) {
- if (rres->table[i]) {
- efree(rres->table[i]);
- }
- }
- }
- for (i = 0; i < rres->ncolumns; i++) {
- if (rowdata[i]) {
- rres->table[i] = estrdup(rowdata[i]);
- } else {
- rres->table[i] = NULL;
- }
- }
- }
- ret = SQLITE_OK;
- break;
-
- case SQLITE_BUSY:
- case SQLITE_ERROR:
- case SQLITE_MISUSE:
- case SQLITE_DONE:
- default:
- if (rres->vm) {
- ret = sqlite_finalize(rres->vm, &errtext);
- }
- rres->vm = NULL;
- if (ret != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- sqlite_freemem(errtext);
- }
- break;
- }
- rres->db->last_err_code = ret;
-
- return ret;
-}
-/* }}} */
-
-/* {{{ sqlite_query */
-void sqlite_query(zval *object, struct php_sqlite_db *db, char *sql, long sql_len, int mode, int buffered, zval *return_value, struct php_sqlite_result **prres, zval *errmsg TSRMLS_DC)
-{
- struct php_sqlite_result res, *rres;
- int ret;
- char *errtext = NULL;
- const char *tail;
-
- memset(&res, 0, sizeof(res));
- res.buffered = buffered;
- res.mode = mode;
-
- ret = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
- db->last_err_code = ret;
-
- if (ret != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
- }
- sqlite_freemem(errtext);
- goto terminate;
- } else if (!res.vm) { /* empty query */
-terminate:
- if (return_value) {
- RETURN_FALSE;
- } else {
- return;
- }
- }
-
- if (!prres) {
- rres = NULL;
- prres = &rres;
- }
- if (!*prres) {
- *prres = (struct php_sqlite_result*)emalloc(sizeof(**prres));
- }
- memcpy(*prres, &res, sizeof(**prres));
- (*prres)->db = db;
- zend_list_addref(db->rsrc_id);
-
-
- /* now the result set is ready for stepping: get first row */
- if (php_sqlite_fetch((*prres) TSRMLS_CC) != SQLITE_OK) {
- real_result_dtor((*prres) TSRMLS_CC);
- *prres = NULL;
- if (return_value) {
- RETURN_FALSE;
- } else {
- return;
- }
- }
-
- (*prres)->curr_row = 0;
-
- if (object) {
- sqlite_object *obj;
- if (buffered) {
- sqlite_instanciate(sqlite_ce_query, return_value TSRMLS_CC);
- } else {
- sqlite_instanciate(sqlite_ce_ub_query, return_value TSRMLS_CC);
- }
- obj = (sqlite_object *) zend_object_store_get_object(return_value TSRMLS_CC);
- obj->type = is_result;
- obj->u.res = (*prres);
- } else if (return_value) {
- ZEND_REGISTER_RESOURCE(object ? NULL : return_value, (*prres), le_sqlite_result);
- }
-}
-/* }}} */
-
-/* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type [, string &error_message]])
- Executes a query that does not prefetch and buffer all data. */
-PHP_FUNCTION(sqlite_unbuffered_query)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- char *sql;
- int sql_len;
- long mode = PHPSQLITE_BOTH;
- char *errtext = NULL;
- zval *errmsg = NULL;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- if (errmsg) {
- zval_dtor(errmsg);
- ZVAL_NULL(errmsg);
- }
-
- PHP_SQLITE_EMPTY_QUERY;
-
- /* avoid doing work if we can */
- if (!return_value_used) {
- db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
-
- if (db->last_err_code != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
- }
- sqlite_freemem(errtext);
- }
- return;
- }
-
- sqlite_query(object, db, sql, sql_len, (int)mode, 0, return_value, NULL, errmsg TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto resource sqlite_fetch_column_types(string table_name, resource db [, int result_type])
- Return an array of column types from a particular table. */
-PHP_FUNCTION(sqlite_fetch_column_types)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- char *tbl, *sql;
- int tbl_len;
- char *errtext = NULL;
- zval *object = getThis();
- struct php_sqlite_result res;
- const char **rowdata, **colnames, *tail;
- int i, ncols;
- long result_type = PHPSQLITE_ASSOC;
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &tbl, &tbl_len, &result_type)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &tbl, &tbl_len, &zdb, &result_type) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &tbl, &tbl_len, &result_type)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- if (!(sql = sqlite_mprintf("SELECT * FROM '%q' LIMIT 1", tbl))) {
- RETURN_FALSE;
- }
-
- sqlite_exec(db->db, "PRAGMA show_datatypes = ON", NULL, NULL, NULL);
-
- db->last_err_code = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
-
- sqlite_freemem(sql);
-
- if (db->last_err_code != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- sqlite_freemem(errtext);
- RETVAL_FALSE;
- goto done;
- }
-
- sqlite_step(res.vm, &ncols, &rowdata, &colnames);
-
- array_init(return_value);
-
- for (i = 0; i < ncols; i++) {
- if (result_type == PHPSQLITE_ASSOC) {
- char *colname = estrdup((char *)colnames[i]);
-
- if (SQLITE_G(assoc_case) == 1) {
- php_sqlite_strtoupper(colname);
- } else if (SQLITE_G(assoc_case) == 2) {
- php_sqlite_strtolower(colname);
- }
-
- add_assoc_string(return_value, colname, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
- efree(colname);
- }
- if (result_type == PHPSQLITE_NUM) {
- add_index_string(return_value, i, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
- }
- }
- if (res.vm) {
- sqlite_finalize(res.vm, NULL);
- }
-done:
- sqlite_exec(db->db, "PRAGMA show_datatypes = OFF", NULL, NULL, NULL);
-}
-/* }}} */
-
-/* {{{ proto resource sqlite_query(string query, resource db [, int result_type [, string &error_message]])
- Executes a query against a given database and returns a result handle. */
-PHP_FUNCTION(sqlite_query)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- char *sql;
- int sql_len;
- long mode = PHPSQLITE_BOTH;
- char *errtext = NULL;
- zval *errmsg = NULL;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- if (errmsg) {
- zval_dtor(errmsg);
- ZVAL_NULL(errmsg);
- }
-
- PHP_SQLITE_EMPTY_QUERY;
-
- /* avoid doing work if we can */
- if (!return_value_used) {
- db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
-
- if (db->last_err_code != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
- }
- sqlite_freemem(errtext);
- }
- return;
- }
-
- sqlite_query(object, db, sql, sql_len, (int)mode, 1, return_value, NULL, errmsg TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto boolean sqlite_exec(string query, resource db[, string &error_message])
- Executes a result-less query against a given database */
-PHP_FUNCTION(sqlite_exec)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- char *sql;
- int sql_len;
- char *errtext = NULL;
- zval *errmsg = NULL;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &sql, &sql_len, &errmsg)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if(FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &zdb, &sql, &sql_len, &errmsg)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- if (errmsg) {
- zval_dtor(errmsg);
- ZVAL_NULL(errmsg);
- }
-
- PHP_SQLITE_EMPTY_QUERY;
-
- db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
-
- if (db->last_err_code != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
- }
- sqlite_freemem(errtext);
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ php_sqlite_fetch_array */
-static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC)
-{
- int j, n = res->ncolumns, buffered = res->buffered;
- const char **rowdata, **colnames;
-
- /* check range of the row */
- if (res->curr_row >= res->nrows) {
- /* no more */
- RETURN_FALSE;
- }
- colnames = (const char**)res->col_names;
- if (res->buffered) {
- rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
- } else {
- rowdata = (const char**)res->table;
- }
-
- /* now populate the result */
- array_init(return_value);
-
- for (j = 0; j < n; j++) {
- zval *decoded;
- MAKE_STD_ZVAL(decoded);
-
- if (rowdata[j] == NULL) {
- ZVAL_NULL(decoded);
- } else if (decode_binary && rowdata[j][0] == '\x01') {
- Z_STRVAL_P(decoded) = emalloc(strlen(rowdata[j]));
- Z_STRLEN_P(decoded) = php_sqlite_decode_binary(rowdata[j]+1, Z_STRVAL_P(decoded));
- Z_STRVAL_P(decoded)[Z_STRLEN_P(decoded)] = '\0';
- Z_TYPE_P(decoded) = IS_STRING;
- if (!buffered) {
- efree((char*)rowdata[j]);
- rowdata[j] = NULL;
- }
- } else {
- ZVAL_STRING(decoded, (char*)rowdata[j], buffered);
- if (!buffered) {
- rowdata[j] = NULL;
- }
- }
-
- if (mode & PHPSQLITE_NUM) {
- if (mode & PHPSQLITE_ASSOC) {
- add_index_zval(return_value, j, decoded);
- Z_ADDREF_P(decoded);
- add_assoc_zval(return_value, (char*)colnames[j], decoded);
- } else {
- add_next_index_zval(return_value, decoded);
- }
- } else {
- add_assoc_zval(return_value, (char*)colnames[j], decoded);
- }
- }
-
- if (move_next) {
- if (!res->buffered) {
- /* non buffered: fetch next row */
- php_sqlite_fetch(res TSRMLS_CC);
- }
- /* advance the row pointer */
- res->curr_row++;
- }
-}
-/* }}} */
-
-/* {{{ php_sqlite_fetch_column */
-static void php_sqlite_fetch_column(struct php_sqlite_result *res, zval *which, zend_bool decode_binary, zval *return_value TSRMLS_DC)
-{
- int j;
- const char **rowdata, **colnames;
-
- /* check range of the row */
- if (res->curr_row >= res->nrows) {
- /* no more */
- RETURN_FALSE;
- }
- colnames = (const char**)res->col_names;
-
- if (Z_TYPE_P(which) == IS_LONG) {
- j = Z_LVAL_P(which);
- } else {
- convert_to_string_ex(&which);
- for (j = 0; j < res->ncolumns; j++) {
- if (!strcasecmp((char*)colnames[j], Z_STRVAL_P(which))) {
- break;
- }
- }
- }
- if (j < 0 || j >= res->ncolumns) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such column %d", j);
- RETURN_FALSE;
- }
-
- if (res->buffered) {
- rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
- } else {
- rowdata = (const char**)res->table;
- }
-
- if (rowdata[j] == NULL) {
- RETURN_NULL();
- } else if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') {
- int l = strlen(rowdata[j]);
- char *decoded = emalloc(l);
- l = php_sqlite_decode_binary(rowdata[j]+1, decoded);
- decoded[l] = '\0';
- RETVAL_STRINGL(decoded, l, 0);
- if (!res->buffered) {
- efree((char*)rowdata[j]);
- rowdata[j] = NULL;
- }
- } else {
- RETVAL_STRING((char*)rowdata[j], res->buffered);
- if (!res->buffered) {
- rowdata[j] = NULL;
- }
- }
-}
-/* }}} */
-
-/* {{{ proto array sqlite_fetch_all(resource result [, int result_type [, bool decode_binary]])
- Fetches all rows from a result set as an array of arrays. */
-PHP_FUNCTION(sqlite_fetch_all)
-{
- zval *zres, *ent;
- long mode = PHPSQLITE_BOTH;
- zend_bool decode_binary = 1;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- if (!ZEND_NUM_ARGS()) {
- mode = res->mode;
- }
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- if (ZEND_NUM_ARGS() < 2) {
- mode = res->mode;
- }
- }
-
- if (res->curr_row >= res->nrows && res->nrows) {
- if (!res->buffered) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "One or more rowsets were already returned; returning NULL this time");
- } else {
- res->curr_row = 0;
- }
- }
-
- array_init(return_value);
-
- while (res->curr_row < res->nrows) {
- MAKE_STD_ZVAL(ent);
- php_sqlite_fetch_array(res, mode, decode_binary, 1, ent TSRMLS_CC);
- add_next_index_zval(return_value, ent);
- }
-}
-/* }}} */
-
-/* {{{ proto array sqlite_fetch_array(resource result [, int result_type [, bool decode_binary]])
- Fetches the next row from a result set as an array. */
-PHP_FUNCTION(sqlite_fetch_array)
-{
- zval *zres;
- long mode = PHPSQLITE_BOTH;
- zend_bool decode_binary = 1;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- if (!ZEND_NUM_ARGS()) {
- mode = res->mode;
- }
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- if (ZEND_NUM_ARGS() < 2) {
- mode = res->mode;
- }
- }
-
- php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto object sqlite_fetch_object(resource result [, string class_name [, NULL|array ctor_params [, bool decode_binary]]])
- Fetches the next row from a result set as an object. */
- /* note that you can do array(&$val) for param ctor_params */
-PHP_FUNCTION(sqlite_fetch_object)
-{
- zval *zres;
- zend_bool decode_binary = 1;
- struct php_sqlite_result *res;
- zval *object = getThis();
- char *class_name = NULL;
- int class_name_len;
- zend_class_entry *ce;
- zval dataset;
- zend_fcall_info fci;
- zend_fcall_info_cache fcc;
- zval *retval_ptr;
- zval *ctor_params = NULL;
- zend_error_handling error_handling;
-
- zend_replace_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception, &error_handling TSRMLS_CC);
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szb", &class_name, &class_name_len, &ctor_params, &decode_binary)) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- return;
- }
- RES_FROM_OBJECT_RESTORE_ERH(res, object, &error_handling);
- if (!class_name) {
- ce = zend_standard_class_def;
- } else {
- ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
- }
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|szb", &zres, &class_name, &class_name_len, &ctor_params, &decode_binary)) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- if (!class_name) {
- ce = zend_standard_class_def;
- } else {
- ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
- }
- }
-
- if (!ce) {
- zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not find class '%s'", class_name);
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- return;
- }
-
- if (res->curr_row < res->nrows) {
- php_sqlite_fetch_array(res, PHPSQLITE_ASSOC, decode_binary, 1, &dataset TSRMLS_CC);
- } else {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
- RETURN_FALSE;
- }
-
- object_and_properties_init(return_value, ce, NULL);
- zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
-
- zend_restore_error_handling(&error_handling TSRMLS_CC);
-
- if (ce->constructor) {
- fci.size = sizeof(fci);
- fci.function_table = &ce->function_table;
- fci.function_name = NULL;
- fci.symbol_table = NULL;
- fci.object_ptr = return_value;
- fci.retval_ptr_ptr = &retval_ptr;
- if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
- if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
- HashTable *ht = Z_ARRVAL_P(ctor_params);
- Bucket *p;
-
- fci.param_count = 0;
- fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
- p = ht->pListHead;
- while (p != NULL) {
- fci.params[fci.param_count++] = (zval**)p->pData;
- p = p->pListNext;
- }
- } else {
- /* Two problems why we throw exceptions here: PHP is typeless
- * and hence passing one argument that's not an array could be
- * by mistake and the other way round is possible, too. The
- * single value is an array. Also we'd have to make that one
- * argument passed by reference.
- */
- zend_throw_exception(sqlite_ce_exception, "Parameter ctor_params must be an array", 0 TSRMLS_CC);
- return;
- }
- } else {
- fci.param_count = 0;
- fci.params = NULL;
- }
- fci.no_separation = 1;
-
- fcc.initialized = 1;
- fcc.function_handler = ce->constructor;
- fcc.calling_scope = EG(scope);
- fcc.called_scope = Z_OBJCE_P(return_value);
- fcc.object_ptr = return_value;
-
- if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
- zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Could not execute %s::%s()", class_name, ce->constructor->common.function_name);
- } else {
- if (retval_ptr) {
- zval_ptr_dtor(&retval_ptr);
- }
- }
- if (fci.params) {
- efree(fci.params);
- }
- } else if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
- zend_throw_exception_ex(sqlite_ce_exception, 0 TSRMLS_CC, "Class %s does not have a constructor, use NULL for parameter ctor_params or omit it", class_name);
- }
-}
-/* }}} */
-
-/* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type [, bool decode_binary]])
- Executes a query against a given database and returns an array of arrays. */
-PHP_FUNCTION(sqlite_array_query)
-{
- zval *zdb, *ent;
- struct php_sqlite_db *db;
- struct php_sqlite_result *rres;
- char *sql;
- int sql_len;
- long mode = PHPSQLITE_BOTH;
- char *errtext = NULL;
- zend_bool decode_binary = 1;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- PHP_SQLITE_EMPTY_QUERY;
-
- /* avoid doing work if we can */
- if (!return_value_used) {
- db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
-
- if (db->last_err_code != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- sqlite_freemem(errtext);
- }
- return;
- }
-
- rres = (struct php_sqlite_result *)ecalloc(1, sizeof(*rres));
- sqlite_query(NULL, db, sql, sql_len, (int)mode, 0, NULL, &rres, NULL TSRMLS_CC);
- if (db->last_err_code != SQLITE_OK) {
- if (rres) {
- efree(rres);
- }
- RETURN_FALSE;
- }
-
- array_init(return_value);
-
- while (rres->curr_row < rres->nrows) {
- MAKE_STD_ZVAL(ent);
- php_sqlite_fetch_array(rres, mode, decode_binary, 1, ent TSRMLS_CC);
- add_next_index_zval(return_value, ent);
- }
- real_result_dtor(rres TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ php_sqlite_fetch_single */
-static void php_sqlite_fetch_single(struct php_sqlite_result *res, zend_bool decode_binary, zval *return_value TSRMLS_DC)
-{
- const char **rowdata;
- char *decoded;
- int decoded_len;
-
- /* check range of the row */
- if (res->curr_row >= res->nrows) {
- /* no more */
- RETURN_FALSE;
- }
-
- if (res->buffered) {
- rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
- } else {
- rowdata = (const char**)res->table;
- }
-
- if (decode_binary && rowdata[0] != NULL && rowdata[0][0] == '\x01') {
- decoded = emalloc(strlen(rowdata[0]));
- decoded_len = php_sqlite_decode_binary(rowdata[0]+1, decoded);
- if (!res->buffered) {
- efree((char*)rowdata[0]);
- rowdata[0] = NULL;
- }
- } else if (rowdata[0]) {
- decoded_len = strlen((char*)rowdata[0]);
- if (res->buffered) {
- decoded = estrndup((char*)rowdata[0], decoded_len);
- } else {
- decoded = (char*)rowdata[0];
- rowdata[0] = NULL;
- }
- } else {
- decoded = NULL;
- decoded_len = 0;
- }
-
- if (!res->buffered) {
- /* non buffered: fetch next row */
- php_sqlite_fetch(res TSRMLS_CC);
- }
- /* advance the row pointer */
- res->curr_row++;
-
- if (decoded == NULL) {
- RETURN_NULL();
- } else {
- RETURN_STRINGL(decoded, decoded_len, 0);
- }
-}
-/* }}} */
-
-
-/* {{{ proto array sqlite_single_query(resource db, string query [, bool first_row_only [, bool decode_binary]])
- Executes a query and returns either an array for one single column or the value of the first row. */
-PHP_FUNCTION(sqlite_single_query)
-{
- zval *zdb, *ent;
- struct php_sqlite_db *db;
- struct php_sqlite_result *rres;
- char *sql;
- int sql_len;
- char *errtext = NULL;
- zend_bool decode_binary = 1;
- zend_bool srow = 1;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", &sql, &sql_len, &srow, &decode_binary)) {
- return;
- }
- RES_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|bb", &sql, &sql_len, &zdb, &srow, &decode_binary) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|bb", &zdb, &sql, &sql_len, &srow, &decode_binary)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- PHP_SQLITE_EMPTY_QUERY;
-
- /* avoid doing work if we can */
- if (!return_value_used) {
- db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
-
- if (db->last_err_code != SQLITE_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
- sqlite_freemem(errtext);
- }
- return;
- }
-
- rres = (struct php_sqlite_result *)ecalloc(1, sizeof(*rres));
- sqlite_query(NULL, db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, &rres, NULL TSRMLS_CC);
- if (db->last_err_code != SQLITE_OK) {
- if (rres) {
- efree(rres);
- }
- RETURN_FALSE;
- }
-
- if (!srow) {
- array_init(return_value);
- }
-
- while (rres->curr_row < rres->nrows) {
- MAKE_STD_ZVAL(ent);
- php_sqlite_fetch_single(rres, decode_binary, ent TSRMLS_CC);
-
- /* if set and we only have 1 row in the result set, return the result as a string. */
- if (srow) {
- if (rres->curr_row == 1 && rres->curr_row >= rres->nrows) {
- *return_value = *ent;
- zval_copy_ctor(return_value);
- zval_dtor(ent);
- FREE_ZVAL(ent);
- break;
- } else {
- srow = 0;
- array_init(return_value);
- }
- }
- add_next_index_zval(return_value, ent);
- }
-
- real_result_dtor(rres TSRMLS_CC);
-}
-/* }}} */
-
-
-/* {{{ proto string sqlite_fetch_single(resource result [, bool decode_binary])
- Fetches the first column of a result set as a string. */
-PHP_FUNCTION(sqlite_fetch_single)
-{
- zval *zres;
- zend_bool decode_binary = 1;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &decode_binary)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- php_sqlite_fetch_single(res, decode_binary, return_value TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto array sqlite_current(resource result [, int result_type [, bool decode_binary]])
- Fetches the current row from a result set as an array. */
-PHP_FUNCTION(sqlite_current)
-{
- zval *zres;
- long mode = PHPSQLITE_BOTH;
- zend_bool decode_binary = 1;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (ZEND_NUM_ARGS() && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- if (!ZEND_NUM_ARGS()) {
- mode = res->mode;
- }
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- if (ZEND_NUM_ARGS() < 2) {
- mode = res->mode;
- }
- }
-
- php_sqlite_fetch_array(res, mode, decode_binary, 0, return_value TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary])
- Fetches a column from the current row of a result set. */
-PHP_FUNCTION(sqlite_column)
-{
- zval *zres;
- zval *which;
- zend_bool decode_binary = 1;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &which, &decode_binary)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- php_sqlite_fetch_column(res, which, decode_binary, return_value TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ proto string sqlite_libversion()
- Returns the version of the linked SQLite library. */
-PHP_FUNCTION(sqlite_libversion)
-{
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RETURN_STRING((char*)sqlite_libversion(), 1);
-}
-/* }}} */
-
-/* {{{ proto string sqlite_libencoding()
- Returns the encoding (iso8859 or UTF-8) of the linked SQLite library. */
-PHP_FUNCTION(sqlite_libencoding)
-{
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RETURN_STRING((char*)sqlite_libencoding(), 1);
-}
-/* }}} */
-
-/* {{{ proto int sqlite_changes(resource db)
- Returns the number of rows that were changed by the most recent SQL statement. */
-PHP_FUNCTION(sqlite_changes)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- RETURN_LONG(sqlite_changes(db->db));
-}
-/* }}} */
-
-/* {{{ proto int sqlite_last_insert_rowid(resource db)
- Returns the rowid of the most recently inserted row. */
-PHP_FUNCTION(sqlite_last_insert_rowid)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- RETURN_LONG(sqlite_last_insert_rowid(db->db));
-}
-/* }}} */
-
-static int sqlite_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
-{
- sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC);
-
- if (obj->u.res == NULL) {
- zend_throw_exception(sqlite_ce_exception, "Row count is not available for this query", 0 TSRMLS_CC);
- return FAILURE;
- }
-
- if (obj->u.res->buffered) {
- * count = obj->u.res->nrows;
- return SUCCESS;
- } else {
- zend_throw_exception(sqlite_ce_exception, "Row count is not available for unbuffered queries", 0 TSRMLS_CC);
- return FAILURE;
- }
-} /* }}} */
-
-/* {{{ proto int sqlite_num_rows(resource result)
- Returns the number of rows in a buffered result set. */
-PHP_FUNCTION(sqlite_num_rows)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if (res->buffered) {
- RETURN_LONG(res->nrows);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Row count is not available for unbuffered queries");
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_valid(resource result)
- Returns whether more rows are available. */
-PHP_FUNCTION(sqlite_valid)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- RETURN_BOOL(res->curr_row < res->nrows && res->nrows); /* curr_row may be -1 */
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_has_prev(resource result)
- * Returns whether a previous row is available. */
-PHP_FUNCTION(sqlite_has_prev)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if(!res->buffered) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_has_prev on unbuffered querys");
- RETURN_FALSE;
- }
-
- RETURN_BOOL(res->curr_row);
-}
-/* }}} */
-
-/* {{{ proto int sqlite_num_fields(resource result)
- Returns the number of fields in a result set. */
-PHP_FUNCTION(sqlite_num_fields)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- RETURN_LONG(res->ncolumns);
-}
-/* }}} */
-
-/* {{{ proto string sqlite_field_name(resource result, int field_index)
- Returns the name of a particular field of a result set. */
-PHP_FUNCTION(sqlite_field_name)
-{
- zval *zres;
- struct php_sqlite_result *res;
- long field;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &field)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &field)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if (field < 0 || field >= res->ncolumns) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %ld out of range", field);
- RETURN_FALSE;
- }
-
- RETURN_STRING(res->col_names[field], 1);
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_seek(resource result, int row)
- Seek to a particular row number of a buffered result set. */
-PHP_FUNCTION(sqlite_seek)
-{
- zval *zres;
- struct php_sqlite_result *res;
- long row;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &row)) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if (!res->buffered) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
- RETURN_FALSE;
- }
-
- if (row < 0 || row >= res->nrows) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "row %ld out of range", row);
- RETURN_FALSE;
- }
-
- res->curr_row = row;
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_rewind(resource result)
- Seek to the first row number of a buffered result set. */
-PHP_FUNCTION(sqlite_rewind)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if (!res->buffered) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rewind an unbuffered result set");
- RETURN_FALSE;
- }
-
- if (!res->nrows) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "no rows received");
- RETURN_FALSE;
- }
-
- res->curr_row = 0;
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_next(resource result)
- Seek to the next row number of a result set. */
-PHP_FUNCTION(sqlite_next)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if (!res->buffered && res->vm) {
- php_sqlite_fetch(res TSRMLS_CC);
- }
-
- if (res->curr_row >= res->nrows) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available");
- RETURN_FALSE;
- }
-
- res->curr_row++;
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto int sqlite_key(resource result)
- Return the current row index of a buffered result. */
-PHP_FUNCTION(sqlite_key)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- RETURN_LONG(res->curr_row);
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_prev(resource result)
- * Seek to the previous row number of a result set. */
-PHP_FUNCTION(sqlite_prev)
-{
- zval *zres;
- struct php_sqlite_result *res;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- RES_FROM_OBJECT(res, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
- return;
- }
- ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
- }
-
- if (!res->buffered) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "you cannot use sqlite_prev on unbuffered querys");
- RETURN_FALSE;
- }
-
- if (res->curr_row <= 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "no previous row available");
- RETURN_FALSE;
- }
-
- res->curr_row--;
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string sqlite_escape_string(string item)
- Escapes a string for use as a query parameter. */
-PHP_FUNCTION(sqlite_escape_string)
-{
- char *string = NULL;
- int stringlen;
- char *ret;
-
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &stringlen)) {
- return;
- }
-
- if (stringlen && (string[0] == '\x01' || memchr(string, '\0', stringlen) != NULL)) {
- /* binary string */
- int enclen;
-
- ret = safe_emalloc(1 + stringlen / 254, 257, 3);
- ret[0] = '\x01';
- enclen = php_sqlite_encode_binary(string, stringlen, ret+1);
- RETVAL_STRINGL(ret, enclen+1, 0);
-
- } else if (stringlen) {
- ret = sqlite_mprintf("%q", string);
- if (ret) {
- RETVAL_STRING(ret, 1);
- sqlite_freemem(ret);
- }
- } else {
- RETURN_EMPTY_STRING();
- }
-}
-/* }}} */
-
-/* {{{ proto int sqlite_last_error(resource db)
- Returns the error code of the last error for a database. */
-PHP_FUNCTION(sqlite_last_error)
-{
- zval *zdb;
- struct php_sqlite_db *db;
- zval *object = getThis();
-
- if (object) {
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- RETURN_LONG(db->last_err_code);
-}
-/* }}} */
-
-/* {{{ proto string sqlite_error_string(int error_code)
- Returns the textual description of an error code. */
-PHP_FUNCTION(sqlite_error_string)
-{
- long code;
- const char *msg;
-
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
- return;
- }
-
- msg = sqlite_error_string(code);
-
- if (msg) {
- RETURN_STRING((char*)msg, 1);
- } else {
- RETURN_NULL();
- }
-}
-/* }}} */
-
-/* manages duplicate registrations of a particular function, and
- * also handles the case where the db is using a persistent connection */
-enum callback_prep_t { DO_REG, SKIP_REG, ERR };
-
-static enum callback_prep_t prep_callback_struct(struct php_sqlite_db *db, int is_agg,
- char *funcname,
- zval *step, zval *fini, struct php_sqlite_agg_functions **funcs)
-{
- struct php_sqlite_agg_functions *alloc_funcs, func_tmp;
- char *hashkey;
- int hashkeylen;
- enum callback_prep_t ret;
-
- hashkeylen = spprintf(&hashkey, 0, "%s-%s", is_agg ? "agg" : "reg", funcname);
-
- /* is it already registered ? */
- if (SUCCESS == zend_hash_find(&db->callbacks, hashkey, hashkeylen+1, (void*)&alloc_funcs)) {
- /* override the previous definition */
-
- if (alloc_funcs->is_valid) {
- /* release these */
-
- if (alloc_funcs->step) {
- zval_ptr_dtor(&alloc_funcs->step);
- alloc_funcs->step = NULL;
- }
-
- if (alloc_funcs->fini) {
- zval_ptr_dtor(&alloc_funcs->fini);
- alloc_funcs->fini = NULL;
- }
- }
-
- ret = SKIP_REG;
- } else {
- /* add a new one */
- func_tmp.db = db;
-
- ret = SUCCESS == zend_hash_update(&db->callbacks, hashkey, hashkeylen+1,
- (void*)&func_tmp, sizeof(func_tmp), (void**)&alloc_funcs) ? DO_REG : ERR;
- }
-
- efree(hashkey);
-
- MAKE_STD_ZVAL(alloc_funcs->step);
- *(alloc_funcs->step) = *step;
- zval_copy_ctor(alloc_funcs->step);
- INIT_PZVAL(alloc_funcs->step);
-
- if (is_agg) {
- MAKE_STD_ZVAL(alloc_funcs->fini);
- *(alloc_funcs->fini) = *fini;
- zval_copy_ctor(alloc_funcs->fini);
- INIT_PZVAL(alloc_funcs->fini);
- } else {
- alloc_funcs->fini = NULL;
- }
- alloc_funcs->is_valid = 1;
- *funcs = alloc_funcs;
-
- return ret;
-}
-
-
-/* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args])
- Registers an aggregate function for queries. */
-PHP_FUNCTION(sqlite_create_aggregate)
-{
- char *funcname = NULL;
- int funcname_len;
- zval *zstep, *zfinal, *zdb;
- struct php_sqlite_db *db;
- struct php_sqlite_agg_functions *funcs;
- char *callable = NULL;
- long num_args = -1;
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- if (!zend_is_callable(zstep, 0, &callable TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable);
- efree(callable);
- return;
- }
- efree(callable);
-
- if (!zend_is_callable(zfinal, 0, &callable TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "finalize function `%s' is not callable", callable);
- efree(callable);
- return;
- }
- efree(callable);
-
-
- if (prep_callback_struct(db, 1, funcname, zstep, zfinal, &funcs) == DO_REG) {
- sqlite_create_aggregate(db->db, funcname, num_args,
- php_sqlite_agg_step_function_callback,
- php_sqlite_agg_fini_function_callback, funcs);
- }
-
-
-}
-/* }}} */
-
-/* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args])
- Registers a "regular" function for queries. */
-PHP_FUNCTION(sqlite_create_function)
-{
- char *funcname = NULL;
- int funcname_len;
- zval *zcall, *zdb;
- struct php_sqlite_db *db;
- struct php_sqlite_agg_functions *funcs;
- char *callable = NULL;
- long num_args = -1;
-
- zval *object = getThis();
-
- if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &funcname, &funcname_len, &zcall, &num_args)) {
- return;
- }
- DB_FROM_OBJECT(db, object);
- } else {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) {
- return;
- }
- DB_FROM_ZVAL(db, &zdb);
- }
-
- if (!zend_is_callable(zcall, 0, &callable TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "function `%s' is not callable", callable);
- efree(callable);
- return;
- }
- efree(callable);
-
- if (prep_callback_struct(db, 0, funcname, zcall, NULL, &funcs) == DO_REG) {
- sqlite_create_function(db->db, funcname, num_args, php_sqlite_function_callback, funcs);
- }
-}
-/* }}} */
-
-/* {{{ proto string sqlite_udf_encode_binary(string data)
- Apply binary encoding (if required) to a string to return from an UDF. */
-PHP_FUNCTION(sqlite_udf_encode_binary)
-{
- char *data = NULL;
- int datalen;
-
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
- return;
- }
-
- if (data == NULL) {
- RETURN_NULL();
- }
- if (datalen && (data[0] == '\x01' || memchr(data, '\0', datalen) != NULL)) {
- /* binary string */
- int enclen;
- char *ret;
-
- ret = safe_emalloc(1 + datalen / 254, 257, 3);
- ret[0] = '\x01';
- enclen = php_sqlite_encode_binary(data, datalen, ret+1);
- RETVAL_STRINGL(ret, enclen+1, 0);
- } else {
- RETVAL_STRINGL(data, datalen, 1);
- }
-}
-/* }}} */
-
-/* {{{ proto string sqlite_udf_decode_binary(string data)
- Decode binary encoding on a string parameter passed to an UDF. */
-PHP_FUNCTION(sqlite_udf_decode_binary)
-{
- char *data = NULL;
- int datalen;
-
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
- return;
- }
-
- if (data == NULL) {
- RETURN_NULL();
- }
- if (datalen && data[0] == '\x01') {
- /* encoded string */
- int enclen;
- char *ret;
-
- ret = emalloc(datalen);
- enclen = php_sqlite_decode_binary(data+1, ret);
- ret[enclen] = '\0';
- RETVAL_STRINGL(ret, enclen, 0);
- } else {
- RETVAL_STRINGL(data, datalen, 1);
- }
-}
-/* }}} */
-
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
diff --git a/ext/sqlite/sqlite.dsp b/ext/sqlite/sqlite.dsp
deleted file mode 100644
index f6dfb437c2..0000000000
--- a/ext/sqlite/sqlite.dsp
+++ /dev/null
@@ -1,339 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sqlite" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=sqlite - Win32 Debug_TS
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "sqlite.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "sqlite.mak" CFG="sqlite - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "sqlite - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "sqlite - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "sqlite - Win32 Release_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release_TS"
-# PROP BASE Intermediate_Dir "Release_TS"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release_TS"
-# PROP Intermediate_Dir "Release_TS"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SQLITE_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\win32" /I "..\..\..\php_build" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_SQLITE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SQLITE=1 /D "PHP_SQLITE_EXPORTS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x407 /d "NDEBUG"
-# ADD RSC /l 0x407 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 php5ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS\php_sqlite.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" /libpath:"..\..\..\php_build\release"
-
-!ELSEIF "$(CFG)" == "sqlite - Win32 Debug_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug_TS"
-# PROP BASE Intermediate_Dir "Debug_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug_TS"
-# PROP Intermediate_Dir "Debug_TS"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SQLITE_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\win32" /I "..\..\..\php_build" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_SQLITE" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_SQLITE=1 /D "PHP_SQLITE_EXPORTS" /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x407 /d "_DEBUG"
-# ADD RSC /l 0x407 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 php5ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS\php_sqlite.dll" /pdbtype:sept /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\release"
-
-!ENDIF
-
-# Begin Target
-
-# Name "sqlite - Win32 Release_TS"
-# Name "sqlite - Win32 Debug_TS"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Group "libsqlite"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\libsqlite\src\attach.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\auth.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\btree.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\btree.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\btree_rb.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\build.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\config.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\copy.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\date.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\delete.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\encode.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\expr.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\func.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\hash.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\hash.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\insert.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\main.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\opcodes.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\opcodes.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\os.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\os.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\pager.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\pager.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\parse.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\parse.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\pragma.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\printf.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\random.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\select.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\sqlite.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\sqlite.w32.h
-
-!IF "$(CFG)" == "sqlite - Win32 Release_TS"
-
-# Begin Custom Build
-InputDir=.\libsqlite\src
-InputPath=.\libsqlite\src\sqlite.w32.h
-
-"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\sqlite.h
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "sqlite - Win32 Debug_TS"
-
-# Begin Custom Build
-InputDir=.\libsqlite\src
-InputPath=.\libsqlite\src\sqlite.w32.h
-
-"$(InputDir)\sqlite.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\sqlite.h
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\sqlite_config.w32.h
-
-!IF "$(CFG)" == "sqlite - Win32 Release_TS"
-
-# Begin Custom Build
-InputDir=.\libsqlite\src
-InputPath=.\libsqlite\src\sqlite_config.w32.h
-
-"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\config.h
-
-# End Custom Build
-
-!ELSEIF "$(CFG)" == "sqlite - Win32 Debug_TS"
-
-# Begin Custom Build
-InputDir=.\libsqlite\src
-InputPath=.\libsqlite\src\sqlite_config.w32.h
-
-"$(InputDir)\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
- copy $(InputPath) $(InputDir)\config.h
-
-# End Custom Build
-
-!ENDIF
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\sqliteInt.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\table.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\tokenize.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\trigger.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\update.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\util.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\vacuum.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\vdbe.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\vdbe.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\vdbeaux.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\libsqlite\src\where.c
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\php_sqlite.def
-# End Source File
-# Begin Source File
-
-SOURCE=.\sqlite.c
-# ADD CPP /I "libsqlite\src"
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\php_sqlite.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/ext/sqlite/sqlite.php b/ext/sqlite/sqlite.php
deleted file mode 100644
index 527504b72b..0000000000
--- a/ext/sqlite/sqlite.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-if (!extension_loaded("sqlite")) {
- dl("sqlite.so");
- if (!extension_loaded("sqlite")) {
- exit("Please enable SQLite support\n");
- }
-}
-
-debug_zval_dump(sqlite_libversion());
-debug_zval_dump(sqlite_libencoding());
-
-$s = sqlite_open("weztest.sqlite", 0666, $err);
-
-debug_zval_dump($err);
-debug_zval_dump($s);
-
-$r = sqlite_query("create table foo (a INTEGER PRIMARY KEY, b INTEGER )", $s);
-debug_zval_dump(sqlite_last_error($s));
-debug_zval_dump(sqlite_error_string(sqlite_last_error($s)));
-
-$r = sqlite_query("select *, php('md5', sql) as o from sqlite_master", $s);
-debug_zval_dump($r);
-debug_zval_dump(sqlite_num_rows($r));
-debug_zval_dump(sqlite_num_fields($r));
-
-for ($j = 0; $j < sqlite_num_fields($r); $j++) {
- echo "Field $j is " . sqlite_field_name($r, $j) . "\n";
-}
-
-while ($row = sqlite_fetch_array($r, SQLITE_ASSOC)) {
- print_r($row);
-}
-
-sqlite_close($s);
-
-?>
diff --git a/ext/sqlite/tests/blankdb.inc b/ext/sqlite/tests/blankdb.inc
deleted file mode 100644
index 5ca4841176..0000000000
--- a/ext/sqlite/tests/blankdb.inc
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php #vim:ft=php
-$db = sqlite_open(":memory:");
-?>
diff --git a/ext/sqlite/tests/blankdb_oo.inc b/ext/sqlite/tests/blankdb_oo.inc
deleted file mode 100644
index 1139d17c8b..0000000000
--- a/ext/sqlite/tests/blankdb_oo.inc
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php #vim:ft=php
-$db = new SQLiteDatabase(":memory:");
-?>
diff --git a/ext/sqlite/tests/bug26911.phpt b/ext/sqlite/tests/bug26911.phpt
deleted file mode 100644
index 74c2167722..0000000000
--- a/ext/sqlite/tests/bug26911.phpt
+++ /dev/null
@@ -1,12 +0,0 @@
---TEST--
-Bug #26911 (crash when fetching data from empty queries)
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
- $db = sqlite_open(":memory:");
- $a = sqlite_query($db, " ");
- echo "I am ok\n";
-?>
---EXPECT--
-I am ok
diff --git a/ext/sqlite/tests/bug28112.phpt b/ext/sqlite/tests/bug28112.phpt
deleted file mode 100644
index f3e9b8b9ec..0000000000
--- a/ext/sqlite/tests/bug28112.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Bug #28112 (sqlite_query() crashing apache on malformed query)
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-
-if (!($db = sqlite_open(":memory:", 666, $error))) die ("Couldn't open the database");
-sqlite_query($db, "create table frob (foo INTEGER PRIMARY KEY, bar text);");
-$res = @sqlite_array_query($db, "");
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-===DONE===
diff --git a/ext/sqlite/tests/bug35248.phpt b/ext/sqlite/tests/bug35248.phpt
deleted file mode 100644
index 4898a4142e..0000000000
--- a/ext/sqlite/tests/bug35248.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-Bug #35248 (sqlite_query does not return parse error message)
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
- $db = sqlite_open(":memory:");
- $res = @sqlite_query($db, "asdfesdfa", SQLITE_NUM, $err);
- var_dump($err);
- $res = @sqlite_unbuffered_query($db, "asdfesdfa", SQLITE_NUM, $err);
- var_dump($err);
-?>
---EXPECT--
-string(30) "near "asdfesdfa": syntax error"
-string(30) "near "asdfesdfa": syntax error"
diff --git a/ext/sqlite/tests/bug38759.phpt b/ext/sqlite/tests/bug38759.phpt
deleted file mode 100644
index ae5959d4bd..0000000000
--- a/ext/sqlite/tests/bug38759.phpt
+++ /dev/null
@@ -1,18 +0,0 @@
---TEST--
-Bug #38759 (sqlite2 empty query causes segfault)
---SKIPIF--
-<?php
-if (!extension_loaded("pdo")) print "skip";
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-
-$dbh = new PDO('sqlite2::memory:');
-var_dump($dbh->query(" "));
-
-echo "Done\n";
-?>
---EXPECTF--
-bool(false)
-Done
diff --git a/ext/sqlite/tests/bug48679.phpt b/ext/sqlite/tests/bug48679.phpt
deleted file mode 100644
index 4b0c3f45cf..0000000000
--- a/ext/sqlite/tests/bug48679.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Bug #48679 (sqlite2 count on unbuffered query causes segfault)
---SKIPIF--
-<?php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-
-try {
- $x = new sqliteunbuffered;
- count($x);
-} catch (SQLiteException $e) {
- var_dump($e->getMessage());
-}
-echo "Done\n";
-?>
---EXPECT--
-string(41) "Row count is not available for this query"
-Done
diff --git a/ext/sqlite/tests/pdo/common.phpt b/ext/sqlite/tests/pdo/common.phpt
deleted file mode 100644
index 42e736ae93..0000000000
--- a/ext/sqlite/tests/pdo/common.phpt
+++ /dev/null
@@ -1,12 +0,0 @@
---TEST--
-SQLite2
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded('pdo') || !extension_loaded('sqlite')) print 'skip'; ?>
---REDIRECTTEST--
-return array(
- 'ENV' => array(
- 'PDOTEST_DSN' => 'sqlite2::memory:'
- ),
- 'TESTS' => 'ext/pdo/tests'
- );
diff --git a/ext/sqlite/tests/sqlite_001.phpt b/ext/sqlite/tests/sqlite_001.phpt
deleted file mode 100644
index 61d8896570..0000000000
--- a/ext/sqlite/tests/sqlite_001.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-sqlite: sqlite_open/close
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-require_once('blankdb.inc');
-echo "$db\n";
-sqlite_close($db);
-echo "Done\n";
-?>
---EXPECTF--
-Resource id #%d
-Done
diff --git a/ext/sqlite/tests/sqlite_002.phpt b/ext/sqlite/tests/sqlite_002.phpt
deleted file mode 100644
index c9fd0e1bca..0000000000
--- a/ext/sqlite/tests/sqlite_002.phpt
+++ /dev/null
@@ -1,32 +0,0 @@
---TEST--
-sqlite: Simple insert/select
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))", $db);
-sqlite_query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)", $db);
-$r = sqlite_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r));
-sqlite_close($db);
-?>
---EXPECT--
-array(6) {
- [0]=>
- string(10) "2002-01-02"
- ["c1"]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- ["c2"]=>
- string(8) "12:49:00"
- [2]=>
- NULL
- ["c3"]=>
- NULL
-}
diff --git a/ext/sqlite/tests/sqlite_003.phpt b/ext/sqlite/tests/sqlite_003.phpt
deleted file mode 100644
index adb891b726..0000000000
--- a/ext/sqlite/tests/sqlite_003.phpt
+++ /dev/null
@@ -1,52 +0,0 @@
---TEST--
-sqlite: Simple insert/select, different result represenatation
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))", $db);
-sqlite_query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)", $db);
-$r = sqlite_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r, SQLITE_BOTH));
-$r = sqlite_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r, SQLITE_NUM));
-$r = sqlite_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r, SQLITE_ASSOC));
-sqlite_close($db);
-?>
---EXPECT--
-array(6) {
- [0]=>
- string(10) "2002-01-02"
- ["c1"]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- ["c2"]=>
- string(8) "12:49:00"
- [2]=>
- NULL
- ["c3"]=>
- NULL
-}
-array(3) {
- [0]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- [2]=>
- NULL
-}
-array(3) {
- ["c1"]=>
- string(10) "2002-01-02"
- ["c2"]=>
- string(8) "12:49:00"
- ["c3"]=>
- NULL
-}
diff --git a/ext/sqlite/tests/sqlite_004.phpt b/ext/sqlite/tests/sqlite_004.phpt
deleted file mode 100644
index 4010066578..0000000000
--- a/ext/sqlite/tests/sqlite_004.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-sqlite: binary encoding
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$strings = array(
- "hello",
- "hello\x01o",
- "\x01hello there",
- "hello\x00there",
- ""
-);
-
-sqlite_query("CREATE TABLE strings(a)", $db);
-
-foreach ($strings as $str) {
- sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($str) . "')", $db);
-}
-
-$i = 0;
-$r = sqlite_query("SELECT * from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- if ($row[0] !== $strings[$i]) {
- echo "FAIL!\n";
- var_dump($row[0]);
- var_dump($strings[$i]);
- } else {
- echo "OK!\n";
- }
- $i++;
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-OK!
-OK!
-OK!
-OK!
-OK!
-DONE!
diff --git a/ext/sqlite/tests/sqlite_005.phpt b/ext/sqlite/tests/sqlite_005.phpt
deleted file mode 100644
index e0eeab5589..0000000000
--- a/ext/sqlite/tests/sqlite_005.phpt
+++ /dev/null
@@ -1,50 +0,0 @@
---TEST--
-sqlite: aggregate functions
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($str) . "')", $db);
-}
-
-function cat_step(&$context, $string)
-{
- $context .= $string;
-}
-
-function cat_fin(&$context)
-{
- return $context;
-}
-
-sqlite_create_aggregate($db, "cat", "cat_step", "cat_fin");
-
-$r = sqlite_query("SELECT cat(a) from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- var_dump($row);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(11) "onetwothree"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_006.phpt b/ext/sqlite/tests/sqlite_006.phpt
deleted file mode 100644
index 4e6e5f19ed..0000000000
--- a/ext/sqlite/tests/sqlite_006.phpt
+++ /dev/null
@@ -1,55 +0,0 @@
---TEST--
-sqlite: regular functions
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- array("one", "uno"),
- array("two", "dos"),
- array("three", "tres"),
- );
-
-sqlite_query("CREATE TABLE strings(a,b)", $db);
-
-function implode_args()
-{
- $args = func_get_args();
- $sep = array_shift($args);
- return implode($sep, $args);
-}
-
-foreach ($data as $row) {
- sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($row[0]) . "','" . sqlite_escape_string($row[1]) . "')", $db);
-}
-
-sqlite_create_function($db, "implode", "implode_args");
-
-$r = sqlite_query("SELECT implode('-', a, b) from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- var_dump($row);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(7) "one-uno"
-}
-array(1) {
- [0]=>
- string(7) "two-dos"
-}
-array(1) {
- [0]=>
- string(10) "three-tres"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_007.phpt b/ext/sqlite/tests/sqlite_007.phpt
deleted file mode 100644
index 5a1e536188..0000000000
--- a/ext/sqlite/tests/sqlite_007.phpt
+++ /dev/null
@@ -1,52 +0,0 @@
---TEST--
-sqlite: Simple insert/select (unbuffered)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))", $db);
-sqlite_query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)", $db);
-$r = sqlite_unbuffered_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r, SQLITE_BOTH));
-$r = sqlite_unbuffered_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r, SQLITE_NUM));
-$r = sqlite_unbuffered_query("SELECT * from foo", $db);
-var_dump(sqlite_fetch_array($r, SQLITE_ASSOC));
-sqlite_close($db);
-?>
---EXPECT--
-array(6) {
- [0]=>
- string(10) "2002-01-02"
- ["c1"]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- ["c2"]=>
- string(8) "12:49:00"
- [2]=>
- NULL
- ["c3"]=>
- NULL
-}
-array(3) {
- [0]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- [2]=>
- NULL
-}
-array(3) {
- ["c1"]=>
- string(10) "2002-01-02"
- ["c2"]=>
- string(8) "12:49:00"
- ["c3"]=>
- NULL
-}
diff --git a/ext/sqlite/tests/sqlite_008.phpt b/ext/sqlite/tests/sqlite_008.phpt
deleted file mode 100644
index ee485c76a1..0000000000
--- a/ext/sqlite/tests/sqlite_008.phpt
+++ /dev/null
@@ -1,46 +0,0 @@
---TEST--
-sqlite: fetch all (buffered)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-$r = sqlite_query("SELECT a from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- var_dump($row);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_009.phpt b/ext/sqlite/tests/sqlite_009.phpt
deleted file mode 100644
index bdad770b57..0000000000
--- a/ext/sqlite/tests/sqlite_009.phpt
+++ /dev/null
@@ -1,46 +0,0 @@
---TEST--
-sqlite: fetch all (unbuffered)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-$r = sqlite_unbuffered_query("SELECT a from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- var_dump($row);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_010.phpt b/ext/sqlite/tests/sqlite_010.phpt
deleted file mode 100644
index 152fde4cf0..0000000000
--- a/ext/sqlite/tests/sqlite_010.phpt
+++ /dev/null
@@ -1,81 +0,0 @@
---TEST--
-sqlite: fetch all (iterator)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-$r = sqlite_unbuffered_query("SELECT a from strings", $db);
-while (sqlite_valid($r)) {
- var_dump(sqlite_current($r, SQLITE_NUM));
- sqlite_next($r);
-}
-$r = sqlite_query("SELECT a from strings", $db);
-while (sqlite_valid($r)) {
- var_dump(sqlite_current($r, SQLITE_NUM));
- sqlite_next($r);
-}
-sqlite_rewind($r);
-while (sqlite_valid($r)) {
- var_dump(sqlite_current($r, SQLITE_NUM));
- sqlite_next($r);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_011.phpt b/ext/sqlite/tests/sqlite_011.phpt
deleted file mode 100644
index 9c1bf3990f..0000000000
--- a/ext/sqlite/tests/sqlite_011.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-sqlite: returned associative column names
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query("CREATE TABLE foo (c1 char, c2 char, c3 char)", $db);
-sqlite_query("CREATE TABLE bar (c1 char, c2 char, c3 char)", $db);
-sqlite_query("INSERT INTO foo VALUES ('1', '2', '3')", $db);
-sqlite_query("INSERT INTO bar VALUES ('4', '5', '6')", $db);
-$r = sqlite_query("SELECT * from foo, bar", $db, SQLITE_ASSOC);
-var_dump(sqlite_fetch_array($r));
-sqlite_close($db);
-?>
---EXPECT--
-array(6) {
- ["foo.c1"]=>
- string(1) "1"
- ["foo.c2"]=>
- string(1) "2"
- ["foo.c3"]=>
- string(1) "3"
- ["bar.c1"]=>
- string(1) "4"
- ["bar.c2"]=>
- string(1) "5"
- ["bar.c3"]=>
- string(1) "6"
-}
diff --git a/ext/sqlite/tests/sqlite_012.phpt b/ext/sqlite/tests/sqlite_012.phpt
deleted file mode 100644
index 14d9ea4f53..0000000000
--- a/ext/sqlite/tests/sqlite_012.phpt
+++ /dev/null
@@ -1,38 +0,0 @@
---TEST--
-sqlite: read field names
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query("CREATE TABLE strings(foo VARCHAR, bar VARCHAR, baz VARCHAR)", $db);
-
-echo "Buffered\n";
-$r = sqlite_query("SELECT * from strings", $db);
-for($i=0; $i<sqlite_num_fields($r); $i++) {
- var_dump(sqlite_field_name($r, $i));
-}
-echo "Unbuffered\n";
-$r = sqlite_unbuffered_query("SELECT * from strings", $db);
-for($i=0; $i<sqlite_num_fields($r); $i++) {
- var_dump(sqlite_field_name($r, $i));
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-Buffered
-string(3) "foo"
-string(3) "bar"
-string(3) "baz"
-Unbuffered
-string(3) "foo"
-string(3) "bar"
-string(3) "baz"
-DONE!
diff --git a/ext/sqlite/tests/sqlite_013.phpt b/ext/sqlite/tests/sqlite_013.phpt
deleted file mode 100644
index 95b047a75c..0000000000
--- a/ext/sqlite/tests/sqlite_013.phpt
+++ /dev/null
@@ -1,78 +0,0 @@
---TEST--
-sqlite: fetch column
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- array (0 => 'one', 1 => 'two'),
- array (0 => 'three', 1 => 'four')
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR, b VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')", $db);
-}
-
-echo "====BUFFERED====\n";
-$r = sqlite_query("SELECT a, b from strings", $db);
-while (sqlite_valid($r)) {
- var_dump(sqlite_current($r, SQLITE_NUM));
- var_dump(sqlite_column($r, 0));
- var_dump(sqlite_column($r, 1));
- var_dump(sqlite_column($r, 'a'));
- var_dump(sqlite_column($r, 'b'));
- sqlite_next($r);
-}
-echo "====UNBUFFERED====\n";
-$r = sqlite_unbuffered_query("SELECT a, b from strings", $db);
-while (sqlite_valid($r)) {
- var_dump(sqlite_column($r, 0));
- var_dump(sqlite_column($r, 'b'));
- var_dump(sqlite_column($r, 1));
- var_dump(sqlite_column($r, 'a'));
- sqlite_next($r);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-====BUFFERED====
-array(2) {
- [0]=>
- string(3) "one"
- [1]=>
- string(3) "two"
-}
-string(3) "one"
-string(3) "two"
-string(3) "one"
-string(3) "two"
-array(2) {
- [0]=>
- string(5) "three"
- [1]=>
- string(4) "four"
-}
-string(5) "three"
-string(4) "four"
-string(5) "three"
-string(4) "four"
-====UNBUFFERED====
-string(3) "one"
-string(3) "two"
-NULL
-NULL
-string(5) "three"
-string(4) "four"
-NULL
-NULL
-DONE!
diff --git a/ext/sqlite/tests/sqlite_014.phpt b/ext/sqlite/tests/sqlite_014.phpt
deleted file mode 100644
index 967fcc10fa..0000000000
--- a/ext/sqlite/tests/sqlite_014.phpt
+++ /dev/null
@@ -1,120 +0,0 @@
---TEST--
-sqlite: fetch all (fetch_all)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-echo "unbuffered twice\n";
-$r = sqlite_unbuffered_query("SELECT a from strings", $db, SQLITE_NUM);
-var_dump(sqlite_fetch_all($r));
-var_dump(sqlite_fetch_all($r));
-
-echo "unbuffered with fetch_array\n";
-$r = sqlite_unbuffered_query("SELECT a from strings", $db, SQLITE_NUM);
-var_dump(sqlite_fetch_array($r));
-var_dump(sqlite_fetch_all($r));
-
-echo "buffered\n";
-$r = sqlite_query("SELECT a from strings", $db, SQLITE_NUM);
-var_dump(sqlite_fetch_all($r));
-var_dump(sqlite_fetch_array($r));
-var_dump(sqlite_fetch_all($r));
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECTF--
-unbuffered twice
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-
-Warning: sqlite_fetch_all(): One or more rowsets were already returned; returning NULL this time in %ssqlite_014.php on line %d
-array(0) {
-}
-unbuffered with fetch_array
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(2) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [1]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-buffered
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-bool(false)
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_015.phpt b/ext/sqlite/tests/sqlite_015.phpt
deleted file mode 100644
index 8de42a84b9..0000000000
--- a/ext/sqlite/tests/sqlite_015.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-sqlite: fetch all (array_query)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-$res = sqlite_array_query("SELECT a from strings", $db, SQLITE_NUM);
-var_dump($res);
-
-$db = null;
-
-echo "DONE!\n";
-?>
---EXPECTF--
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_016.phpt b/ext/sqlite/tests/sqlite_016.phpt
deleted file mode 100644
index 9ca9de135f..0000000000
--- a/ext/sqlite/tests/sqlite_016.phpt
+++ /dev/null
@@ -1,45 +0,0 @@
---TEST--
-sqlite: fetch single
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- array (0 => 'one', 1 => 'two'),
- array (0 => 'three', 1 => 'four')
- );
-
-sqlite_query("CREATE TABLE strings(a VARCHAR, b VARCHAR)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')", $db);
-}
-
-echo "====BUFFERED====\n";
-$r = sqlite_query("SELECT a, b from strings", $db);
-while (sqlite_valid($r)) {
- var_dump(sqlite_fetch_single($r));
-}
-echo "====UNBUFFERED====\n";
-$r = sqlite_unbuffered_query("SELECT a, b from strings", $db);
-while (sqlite_valid($r)) {
- var_dump(sqlite_fetch_single($r));
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-====BUFFERED====
-string(3) "one"
-string(5) "three"
-====UNBUFFERED====
-string(3) "one"
-string(5) "three"
-DONE!
diff --git a/ext/sqlite/tests/sqlite_017.phpt b/ext/sqlite/tests/sqlite_017.phpt
deleted file mode 100644
index 9058622f99..0000000000
--- a/ext/sqlite/tests/sqlite_017.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-sqlite: UDF binary handling functions
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-
-$data = array(
- "hello there",
- "this has a \x00 char in the middle",
- "\x01 this has an 0x01 at the start",
- "this has \x01 in the middle"
- );
-
-foreach ($data as $item) {
- $coded = sqlite_udf_encode_binary($item);
- echo bin2hex($coded) . "\n";
- $decoded = sqlite_udf_decode_binary($coded);
- if ($item != $decoded) {
- echo "FAIL! $item decoded is $decoded\n";
- }
-}
-
-echo "OK!\n";
-
-?>
---EXPECT--
-68656c6c6f207468657265
-0101736768721f6760721f601fff1f626760711f686d1f7367641f6c6863636b64
-0102ff1e726667711e665f711e5f6c1e2e762e2f1e5f721e7266631e71725f7072
-7468697320686173200120696e20746865206d6964646c65
-OK!
diff --git a/ext/sqlite/tests/sqlite_018.phpt b/ext/sqlite/tests/sqlite_018.phpt
deleted file mode 100644
index 8d80649be8..0000000000
--- a/ext/sqlite/tests/sqlite_018.phpt
+++ /dev/null
@@ -1,14 +0,0 @@
---TEST--
-sqlite: crash on bad queries inside sqlite_array_query()
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_array_query($db, "SELECT foo FROM foobar");
-sqlite_close($db);
-?>
---EXPECTF--
-Warning: sqlite_array_query(): no such table: foobar in %s on line %d
diff --git a/ext/sqlite/tests/sqlite_019.phpt b/ext/sqlite/tests/sqlite_019.phpt
deleted file mode 100644
index 74dcff99fa..0000000000
--- a/ext/sqlite/tests/sqlite_019.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-sqlite: single query
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query($db, "CREATE TABLE test_db ( id INTEGER PRIMARY KEY, data VARCHAR(100) )");
-for ($i = 0; $i < 10; $i++) {
- sqlite_query($db, "INSERT INTO test_db (data) VALUES('{$i}data')");
-}
-sqlite_query($db, "INSERT INTO test_db (data) VALUES(NULL)");
-
-var_dump(sqlite_single_query($db, "SELECT id FROM test_db WHERE id=5"));
-var_dump(sqlite_single_query($db, "SELECT * FROM test_db WHERE id=4"));
-var_dump(sqlite_single_query($db, "SELECT data FROM test_db WHERE id=6"));
-var_dump(sqlite_single_query($db, "SELECT * FROM test_db WHERE id < 5"));
-var_dump(sqlite_single_query($db, "SELECT * FROM test db WHERE id < 4"));
-var_dump(sqlite_single_query($db, "SELECT * FROM test_db WHERE id=999999"));
-var_dump(sqlite_single_query($db, "SELECT id FROM test_db WHERE id=5", FALSE));
-
-sqlite_close($db);
-?>
---EXPECTF--
-string(1) "5"
-string(1) "4"
-string(5) "5data"
-array(4) {
- [0]=>
- string(1) "1"
- [1]=>
- string(1) "2"
- [2]=>
- string(1) "3"
- [3]=>
- string(1) "4"
-}
-
-Warning: sqlite_single_query(): no such table: test in %s on line %d
-bool(false)
-NULL
-array(1) {
- [0]=>
- string(1) "5"
-}
diff --git a/ext/sqlite/tests/sqlite_022.phpt b/ext/sqlite/tests/sqlite_022.phpt
deleted file mode 100644
index 76921d56f6..0000000000
--- a/ext/sqlite/tests/sqlite_022.phpt
+++ /dev/null
@@ -1,101 +0,0 @@
---TEST--
-sqlite: sqlite_seek
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-$res = sqlite_query("SELECT a FROM strings", $db, SQLITE_NUM);
-for ($idx = -1; $idx < 4; $idx++) {
- echo "====SEEK:$idx====\n";
- sqlite_seek($res, $idx);
- var_dump(sqlite_current($res));
-}
-echo "====AGAIN====\n";
-for ($idx = -1; $idx < 4; $idx++) {
- echo "====SEEK:$idx====\n";
- sqlite_seek($res, $idx);
- var_dump(sqlite_current($res));
-}
-
-sqlite_close($db);
-
-echo "====DONE!====\n";
-?>
---EXPECTF--
-====SEEK:-1====
-
-Warning: sqlite_seek(): row -1 out of range in %ssqlite_022.php on line %d
-array(1) {
- [0]=>
- string(3) "one"
-}
-====SEEK:0====
-array(1) {
- [0]=>
- string(3) "one"
-}
-====SEEK:1====
-array(1) {
- [0]=>
- string(3) "two"
-}
-====SEEK:2====
-array(1) {
- [0]=>
- string(5) "three"
-}
-====SEEK:3====
-
-Warning: sqlite_seek(): row 3 out of range in %ssqlite_022.php on line %d
-array(1) {
- [0]=>
- string(5) "three"
-}
-====AGAIN====
-====SEEK:-1====
-
-Warning: sqlite_seek(): row -1 out of range in %ssqlite_022.php on line %d
-array(1) {
- [0]=>
- string(5) "three"
-}
-====SEEK:0====
-array(1) {
- [0]=>
- string(3) "one"
-}
-====SEEK:1====
-array(1) {
- [0]=>
- string(3) "two"
-}
-====SEEK:2====
-array(1) {
- [0]=>
- string(5) "three"
-}
-====SEEK:3====
-
-Warning: sqlite_seek(): row 3 out of range in %ssqlite_022.php on line %d
-array(1) {
- [0]=>
- string(5) "three"
-}
-====DONE!====
diff --git a/ext/sqlite/tests/sqlite_023.phpt b/ext/sqlite/tests/sqlite_023.phpt
deleted file mode 100644
index fbb8dc8da8..0000000000
--- a/ext/sqlite/tests/sqlite_023.phpt
+++ /dev/null
@@ -1,105 +0,0 @@
---TEST--
-sqlite: sqlite_[has_]prev
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('$str')", $db);
-}
-
-$r = sqlite_query("SELECT a FROM strings", $db, SQLITE_NUM);
-
-echo "====TRAVERSE====\n";
-for(sqlite_rewind($r); sqlite_valid($r); sqlite_next($r)) {
- var_dump(sqlite_current($r));
-
-}
-echo "====REVERSE====\n";
-do {
- sqlite_prev($r);
- var_dump(sqlite_current($r));
-} while(sqlite_has_prev($r));
-
-echo "====UNBUFFERED====\n";
-
-$r = sqlite_unbuffered_query("SELECT a FROM strings", $db, SQLITE_NUM);
-
-echo "====TRAVERSE====\n";
-for(sqlite_rewind($r); sqlite_valid($r); sqlite_next($r)) {
- var_dump(sqlite_current($r));
-
-}
-echo "====REVERSE====\n";
-do {
- sqlite_prev($r);
- var_dump(sqlite_current($r));
-} while(sqlite_has_prev($r));
-
-sqlite_close($db);
-
-echo "====DONE!====\n";
-?>
---EXPECTF--
-====TRAVERSE====
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-====REVERSE====
-array(1) {
- [0]=>
- string(5) "three"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(3) "one"
-}
-====UNBUFFERED====
-====TRAVERSE====
-
-Warning: sqlite_rewind(): Cannot rewind an unbuffered result set in %ssqlite_023.php on line %d
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-====REVERSE====
-
-Warning: sqlite_prev(): you cannot use sqlite_prev on unbuffered querys in %ssqlite_023.php on line %d
-bool(false)
-
-Warning: sqlite_has_prev(): you cannot use sqlite_has_prev on unbuffered querys in %ssqlite_023.php on line %d
-====DONE!====
diff --git a/ext/sqlite/tests/sqlite_024.phpt b/ext/sqlite/tests/sqlite_024.phpt
deleted file mode 100644
index b7198c0155..0000000000
--- a/ext/sqlite/tests/sqlite_024.phpt
+++ /dev/null
@@ -1,76 +0,0 @@
---TEST--
-sqlite: sqlite_fetch_object
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-class class24 {
- function __construct() {
- echo __METHOD__ . "\n";
- }
-}
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query($db, "CREATE TABLE strings(a)");
-
-foreach ($data as $str) {
- sqlite_query($db, "INSERT INTO strings VALUES('$str')");
-}
-
-echo "====class24====\n";
-$res = sqlite_query($db, "SELECT a FROM strings", SQLITE_ASSOC);
-while (sqlite_valid($res)) {
- var_dump(sqlite_fetch_object($res, 'class24'));
-}
-
-echo "====stdclass====\n";
-$res = sqlite_query($db, "SELECT a FROM strings", SQLITE_ASSOC);
-while (sqlite_valid($res)) {
- var_dump(sqlite_fetch_object($res));
-}
-
-sqlite_close($db);
-
-echo "====DONE!====\n";
-?>
---EXPECTF--
-====class24====
-class24::__construct
-object(class24)#%d (1) {
- ["a"]=>
- string(3) "one"
-}
-class24::__construct
-object(class24)#%d (1) {
- ["a"]=>
- string(3) "two"
-}
-class24::__construct
-object(class24)#%d (1) {
- ["a"]=>
- string(5) "three"
-}
-====stdclass====
-object(stdClass)#%d (1) {
- ["a"]=>
- string(3) "one"
-}
-object(stdClass)#%d (1) {
- ["a"]=>
- string(3) "two"
-}
-object(stdClass)#%d (1) {
- ["a"]=>
- string(5) "three"
-}
-====DONE!====
diff --git a/ext/sqlite/tests/sqlite_025.phpt b/ext/sqlite/tests/sqlite_025.phpt
deleted file mode 100644
index 0a257610cc..0000000000
--- a/ext/sqlite/tests/sqlite_025.phpt
+++ /dev/null
@@ -1,38 +0,0 @@
---TEST--
-sqlite: sqlite_fetch_object in a loop
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query($db, "CREATE TABLE strings(a)");
-
-foreach (array("one", "two", "three") as $str) {
- sqlite_query($db, "INSERT INTO strings VALUES('$str')");
-}
-
-$res = sqlite_query("SELECT * FROM strings", $db);
-
-while (($obj = sqlite_fetch_object($res))) {
- var_dump($obj);
-}
-
-sqlite_close($db);
-?>
---EXPECTF--
-object(stdClass)#1 (1) {
- ["a"]=>
- string(3) "one"
-}
-object(stdClass)#2 (1) {
- ["a"]=>
- string(3) "two"
-}
-object(stdClass)#1 (1) {
- ["a"]=>
- string(5) "three"
-} \ No newline at end of file
diff --git a/ext/sqlite/tests/sqlite_026.phpt b/ext/sqlite/tests/sqlite_026.phpt
deleted file mode 100644
index c508979a27..0000000000
--- a/ext/sqlite/tests/sqlite_026.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-sqlite: sqlite_fetch_column_types
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-sqlite_query($db, "CREATE TABLE strings(a, b INTEGER, c VARCHAR(10), d)");
-sqlite_query($db, "INSERT INTO strings VALUES('1', '2', '3', 'abc')");
-
-var_dump(sqlite_fetch_column_types($db, "strings"));
-
-sqlite_close($db);
-?>
---EXPECT--
-array(4) {
- ["a"]=>
- string(0) ""
- ["b"]=>
- string(7) "INTEGER"
- ["c"]=>
- string(11) "VARCHAR(10)"
- ["d"]=>
- string(0) ""
-}
diff --git a/ext/sqlite/tests/sqlite_027.phpt b/ext/sqlite/tests/sqlite_027.phpt
deleted file mode 100644
index 7919f2c3f7..0000000000
--- a/ext/sqlite/tests/sqlite_027.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-sqlite: crash inside sqlite_escape_string() & sqlite_udf_encode_binary
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---INI--
-memory_limit=-1
---FILE--
-<?php
- var_dump(strlen(sqlite_escape_string(str_repeat("\0", 20000000))));
- var_dump(strlen(sqlite_udf_encode_binary(str_repeat("\0", 20000000))));
-?>
---EXPECT--
-int(20000002)
-int(20000002)
diff --git a/ext/sqlite/tests/sqlite_closures_001.phpt b/ext/sqlite/tests/sqlite_closures_001.phpt
deleted file mode 100644
index 8a90d1e5e0..0000000000
--- a/ext/sqlite/tests/sqlite_closures_001.phpt
+++ /dev/null
@@ -1,54 +0,0 @@
---TEST--
-sqlite: aggregate functions with closures
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-sqlite_query("CREATE TABLE strings(a)", $db);
-
-foreach ($data as $str) {
- sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($str) . "')", $db);
-}
-
-function cat_step(&$context, $string)
-{
- $context .= $string;
-}
-
-function cat_fin(&$context)
-{
- return $context;
-}
-
-sqlite_create_aggregate($db, "cat", function (&$context, $string) {
- $context .= $string;
-}, function (&$context) {
- return $context;
-});
-
-$r = sqlite_query("SELECT cat(a) from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- var_dump($row);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(11) "onetwothree"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_closures_002.phpt b/ext/sqlite/tests/sqlite_closures_002.phpt
deleted file mode 100644
index e880bb1733..0000000000
--- a/ext/sqlite/tests/sqlite_closures_002.phpt
+++ /dev/null
@@ -1,52 +0,0 @@
---TEST--
-sqlite: regular functions with closures
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb.inc";
-
-$data = array(
- array("one", "uno"),
- array("two", "dos"),
- array("three", "tres"),
- );
-
-sqlite_query("CREATE TABLE strings(a,b)", $db);
-
-foreach ($data as $row) {
- sqlite_query("INSERT INTO strings VALUES('" . sqlite_escape_string($row[0]) . "','" . sqlite_escape_string($row[1]) . "')", $db);
-}
-
-sqlite_create_function($db, "implode", function () {
- $args = func_get_args();
- $sep = array_shift($args);
- return implode($sep, $args);
-});
-
-$r = sqlite_query("SELECT implode('-', a, b) from strings", $db);
-while ($row = sqlite_fetch_array($r, SQLITE_NUM)) {
- var_dump($row);
-}
-
-sqlite_close($db);
-
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(7) "one-uno"
-}
-array(1) {
- [0]=>
- string(7) "two-dos"
-}
-array(1) {
- [0]=>
- string(10) "three-tres"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_exec_basic.phpt b/ext/sqlite/tests/sqlite_exec_basic.phpt
deleted file mode 100644
index e7e13db044..0000000000
--- a/ext/sqlite/tests/sqlite_exec_basic.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-Test sqlite_exec() function : basic functionality
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
---FILE--
-<?php
-/* Prototype : boolean sqlite_exec(string query, resource db[, string &error_message])
- * Description: Executes a result-less query against a given database
- * Source code: ext/sqlite/sqlite.c
- * Alias to functions:
- */
-
-echo "*** Testing sqlite_exec() : basic functionality ***\n";
-
-// set up variables
-$query = 'CREATE TABLE foobar (id INTEGER PRIMARY KEY, name CHAR(255));';
-$error_message = null;
-
-// procedural
-$db = sqlite_open(':memory:');
-var_dump( sqlite_exec($db, $query) );
-sqlite_close($db);
-
-// oo-style
-$db = new SQLiteDatabase(':memory:');
-var_dump( $db->queryExec($query, $error_message) );
-
-?>
-===DONE===
---EXPECTF--
-*** Testing sqlite_exec() : basic functionality ***
-bool(true)
-bool(true)
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_exec_error.phpt b/ext/sqlite/tests/sqlite_exec_error.phpt
deleted file mode 100644
index 74cfa9a3e8..0000000000
--- a/ext/sqlite/tests/sqlite_exec_error.phpt
+++ /dev/null
@@ -1,44 +0,0 @@
---TEST--
-Test sqlite_exec() function : error behaviour and functionality
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
---FILE--
-<?php
-/* Prototype : boolean sqlite_exec(string query, resource db[, string &error_message])
- * Description: Executes a result-less query against a given database
- * Source code: ext/sqlite/sqlite.c
- * Alias to functions:
- */
-
-echo "*** Testing sqlite_exec() : error functionality ***\n";
-
-// set up variables
-$fail = 'CRE ATE TABLE';
-$error_message = null;
-
-// procedural
-$db = sqlite_open(':memory:');
-var_dump( sqlite_exec($db, $fail, $error_message) );
-var_dump( $error_message );
-var_dump( sqlite_exec($db) );
-sqlite_close($db);
-
-// oo-style
-$db = new SQLiteDatabase(':memory:');
-var_dump( $db->queryExec($fail, $error_message, 'fooparam') );
-
-?>
-===DONE===
---EXPECTF--
-*** Testing sqlite_exec() : error functionality ***
-
-Warning: sqlite_exec(): near "CRE": syntax error in %s on line %d
-bool(false)
-%string|unicode%(24) "near "CRE": syntax error"
-
-Warning: sqlite_exec() expects at least 2 parameters, 1 given in %s on line %d
-NULL
-
-Warning: SQLiteDatabase::queryExec() expects at most 2 parameters, 3 given in %s on line %d
-NULL
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_last_error_basic.phpt b/ext/sqlite/tests/sqlite_last_error_basic.phpt
deleted file mode 100644
index f3a7b8320e..0000000000
--- a/ext/sqlite/tests/sqlite_last_error_basic.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-Test sqlite_last_error() function : basic functionality
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
---FILE--
-<?php
-/* Prototype : int sqlite_last_error(resource db)
- * Description: Returns the error code of the last error for a database.
- * Source code: ext/sqlite/sqlite.c
- * Alias to functions:
- */
-
-echo "*** Testing sqlite_last_error() : basic functionality ***\n";
-
-// set up variables
-$query = 'CREATE TAB LE foobar (id INTEGER PRIMARY KEY, name CHAR(255));';
-$query_ok = 'CREATE TABLE foobar (id INTEGER, name CHAR(255));';
-
-// procedural
-$db = sqlite_open(':memory:');
-var_dump( sqlite_last_error($db) === SQLITE_OK );
-sqlite_exec($db, $query);
-var_dump( sqlite_last_error($db) === SQLITE_ERROR );
-sqlite_exec($db, $query_ok);
-var_dump( sqlite_last_error($db) === SQLITE_OK );
-sqlite_close($db);
-
-// oo-style
-$db = new SQLiteDatabase(':memory:');
-$db->queryExec($query);
-var_dump( $db->lastError() === SQLITE_ERROR );
-$db->queryExec($query_ok);
-var_dump( $db->lastError() === SQLITE_OK );
-
-?>
-===DONE===
---EXPECTF--
-*** Testing sqlite_last_error() : basic functionality ***
-bool(true)
-
-Warning: sqlite_exec(): near "TAB": syntax error in %s on line %d
-bool(true)
-bool(true)
-
-Warning: SQLiteDatabase::queryExec(): near "TAB": syntax error in %s on line %d
-bool(true)
-bool(true)
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_last_error_error.phpt b/ext/sqlite/tests/sqlite_last_error_error.phpt
deleted file mode 100644
index c930048365..0000000000
--- a/ext/sqlite/tests/sqlite_last_error_error.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-Test sqlite_last_error() function : error conditions
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
---FILE--
-<?php
-/* Prototype : int sqlite_last_error(resource db)
- * Description: Returns the error code of the last error for a database.
- * Source code: ext/sqlite/sqlite.c
- * Alias to functions:
- */
-
-echo "*** Testing sqlite_last_error() : error conditions ***\n";
-
-// Zero arguments
-echo "\n-- Testing sqlite_last_error() function with Zero arguments --\n";
-var_dump( sqlite_last_error() );
-
-//Test sqlite_last_error with one more than the expected number of arguments
-echo "\n-- Testing sqlite_last_error() function with more than expected no. of arguments --\n";
-
-$db = sqlite_open(':memory:');
-$extra_arg = 10;
-var_dump( sqlite_last_error($db, $extra_arg) );
-sqlite_close($db);
-
-$db = new SQLiteDatabase(':memory:');
-var_dump( $db->lastError($extra_arg) );
-
-?>
-===DONE===
---EXPECTF--
-*** Testing sqlite_last_error() : error conditions ***
-
--- Testing sqlite_last_error() function with Zero arguments --
-
-Warning: sqlite_last_error() expects exactly 1 parameter, 0 given in %s on line %d
-NULL
-
--- Testing sqlite_last_error() function with more than expected no. of arguments --
-
-Warning: sqlite_last_error() expects exactly 1 parameter, 2 given in %s on line %d
-NULL
-
-Warning: SQLiteDatabase::lastError() expects exactly 0 parameters, 1 given in %s on line %d
-NULL
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_oo_001.phpt b/ext/sqlite/tests/sqlite_oo_001.phpt
deleted file mode 100644
index 672ddb17b6..0000000000
--- a/ext/sqlite/tests/sqlite_oo_001.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-sqlite-oo: sqlite_open/close
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-require_once('blankdb_oo.inc');
-var_dump($db);
-$db = NULL;
-echo "Done\n";
-?>
---EXPECTF--
-object(SQLiteDatabase)#%d (0) {
-}
-Done
diff --git a/ext/sqlite/tests/sqlite_oo_002.phpt b/ext/sqlite/tests/sqlite_oo_002.phpt
deleted file mode 100644
index 00a568a2a8..0000000000
--- a/ext/sqlite/tests/sqlite_oo_002.phpt
+++ /dev/null
@@ -1,41 +0,0 @@
---TEST--
-sqlite-oo: Simple insert/select
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-require_once('blankdb_oo.inc');
-var_dump($db);
-
-var_dump($db->query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))"));
-var_dump($db->query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)"));
-$r = $db->query("SELECT * from foo");
-var_dump($r);
-var_dump($r->fetch());
-?>
---EXPECTF--
-object(SQLiteDatabase)#%d (0) {
-}
-object(SQLiteResult)#%d (0) {
-}
-object(SQLiteResult)#%d (0) {
-}
-object(SQLiteResult)#%d (0) {
-}
-array(6) {
- [0]=>
- string(10) "2002-01-02"
- ["c1"]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- ["c2"]=>
- string(8) "12:49:00"
- [2]=>
- NULL
- ["c3"]=>
- NULL
-}
diff --git a/ext/sqlite/tests/sqlite_oo_003.phpt b/ext/sqlite/tests/sqlite_oo_003.phpt
deleted file mode 100644
index f9ca65c611..0000000000
--- a/ext/sqlite/tests/sqlite_oo_003.phpt
+++ /dev/null
@@ -1,51 +0,0 @@
---TEST--
-sqlite-oo: Simple insert/select, different result representation
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE foo(c1 date, c2 time, c3 varchar(64))");
-$db->query("INSERT INTO foo VALUES ('2002-01-02', '12:49:00', NULL)");
-$r = $db->query("SELECT * from foo");
-var_dump($r->fetch(SQLITE_BOTH));
-$r = $db->query("SELECT * from foo");
-var_dump($r->fetch(SQLITE_NUM));
-$r = $db->query("SELECT * from foo");
-var_dump($r->fetch(SQLITE_ASSOC));
-?>
---EXPECT--
-array(6) {
- [0]=>
- string(10) "2002-01-02"
- ["c1"]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- ["c2"]=>
- string(8) "12:49:00"
- [2]=>
- NULL
- ["c3"]=>
- NULL
-}
-array(3) {
- [0]=>
- string(10) "2002-01-02"
- [1]=>
- string(8) "12:49:00"
- [2]=>
- NULL
-}
-array(3) {
- ["c1"]=>
- string(10) "2002-01-02"
- ["c2"]=>
- string(8) "12:49:00"
- ["c3"]=>
- NULL
-}
diff --git a/ext/sqlite/tests/sqlite_oo_008.phpt b/ext/sqlite/tests/sqlite_oo_008.phpt
deleted file mode 100644
index 8e99a1deaf..0000000000
--- a/ext/sqlite/tests/sqlite_oo_008.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-sqlite-oo: fetch all (buffered)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-$r = $db->query("SELECT a from strings");
-while ($row = $r->fetch(SQLITE_NUM)) {
- var_dump($row);
-}
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_009.phpt b/ext/sqlite/tests/sqlite_oo_009.phpt
deleted file mode 100644
index c2a55556c1..0000000000
--- a/ext/sqlite/tests/sqlite_oo_009.phpt
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-sqlite-oo: fetch all (unbuffered)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-$r = $db->unbufferedQuery("SELECT a from strings");
-while ($row = $r->fetch(SQLITE_NUM)) {
- var_dump($row);
-}
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_010.phpt b/ext/sqlite/tests/sqlite_oo_010.phpt
deleted file mode 100644
index 8d6f3c0a99..0000000000
--- a/ext/sqlite/tests/sqlite_oo_010.phpt
+++ /dev/null
@@ -1,44 +0,0 @@
---TEST--
-sqlite-oo: fetch all (iterator)
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
-while ($row = $r->valid()) {
- var_dump($r->current());
- $r->next();
-}
-echo "DONE!\n";
-?>
---EXPECT--
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_011.phpt b/ext/sqlite/tests/sqlite_oo_011.phpt
deleted file mode 100644
index 4b5a37044c..0000000000
--- a/ext/sqlite/tests/sqlite_oo_011.phpt
+++ /dev/null
@@ -1,33 +0,0 @@
---TEST--
-sqlite-oo: returned associative column names
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE foo (c1 char, c2 char, c3 char)");
-$db->query("CREATE TABLE bar (c1 char, c2 char, c3 char)");
-$db->query("INSERT INTO foo VALUES ('1', '2', '3')");
-$db->query("INSERT INTO bar VALUES ('4', '5', '6')");
-$r = $db->query("SELECT * from foo, bar", SQLITE_ASSOC);
-var_dump($r->fetch());
-?>
---EXPECT--
-array(6) {
- ["foo.c1"]=>
- string(1) "1"
- ["foo.c2"]=>
- string(1) "2"
- ["foo.c3"]=>
- string(1) "3"
- ["bar.c1"]=>
- string(1) "4"
- ["bar.c2"]=>
- string(1) "5"
- ["bar.c3"]=>
- string(1) "6"
-}
diff --git a/ext/sqlite/tests/sqlite_oo_012.phpt b/ext/sqlite/tests/sqlite_oo_012.phpt
deleted file mode 100644
index 408feb9d17..0000000000
--- a/ext/sqlite/tests/sqlite_oo_012.phpt
+++ /dev/null
@@ -1,35 +0,0 @@
---TEST--
-sqlite-oo: read field names
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE strings(foo VARCHAR, bar VARCHAR, baz VARCHAR)");
-
-echo "Buffered\n";
-$r = $db->query("SELECT * from strings");
-for($i=0; $i<$r->numFields(); $i++) {
- var_dump($r->fieldName($i));
-}
-echo "Unbuffered\n";
-$r = $db->unbufferedQuery("SELECT * from strings");
-for($i=0; $i<$r->numFields(); $i++) {
- var_dump($r->fieldName($i));
-}
-echo "DONE!\n";
-?>
---EXPECT--
-Buffered
-string(3) "foo"
-string(3) "bar"
-string(3) "baz"
-Unbuffered
-string(3) "foo"
-string(3) "bar"
-string(3) "baz"
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_013.phpt b/ext/sqlite/tests/sqlite_oo_013.phpt
deleted file mode 100644
index 0c19505f23..0000000000
--- a/ext/sqlite/tests/sqlite_oo_013.phpt
+++ /dev/null
@@ -1,75 +0,0 @@
---TEST--
-sqlite-oo: fetch column
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- array (0 => 'one', 1 => 'two'),
- array (0 => 'three', 1 => 'four')
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')");
-}
-
-echo "====BUFFERED====\n";
-$r = $db->query("SELECT a, b from strings");
-while ($r->valid()) {
- var_dump($r->current(SQLITE_NUM));
- var_dump($r->column(0));
- var_dump($r->column(1));
- var_dump($r->column('a'));
- var_dump($r->column('b'));
- $r->next();
-}
-echo "====UNBUFFERED====\n";
-$r = $db->unbufferedQuery("SELECT a, b from strings");
-while ($r->valid()) {
- var_dump($r->column(0));
- var_dump($r->column('b'));
- var_dump($r->column(1));
- var_dump($r->column('a'));
- $r->next();
-}
-echo "DONE!\n";
-?>
---EXPECT--
-====BUFFERED====
-array(2) {
- [0]=>
- string(3) "one"
- [1]=>
- string(3) "two"
-}
-string(3) "one"
-string(3) "two"
-string(3) "one"
-string(3) "two"
-array(2) {
- [0]=>
- string(5) "three"
- [1]=>
- string(4) "four"
-}
-string(5) "three"
-string(4) "four"
-string(5) "three"
-string(4) "four"
-====UNBUFFERED====
-string(3) "one"
-string(3) "two"
-NULL
-NULL
-string(5) "three"
-string(4) "four"
-NULL
-NULL
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_014.phpt b/ext/sqlite/tests/sqlite_oo_014.phpt
deleted file mode 100644
index 9735a5442c..0000000000
--- a/ext/sqlite/tests/sqlite_oo_014.phpt
+++ /dev/null
@@ -1,118 +0,0 @@
---TEST--
-sqlite-oo: fetch all
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-echo "unbuffered twice\n";
-$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
-var_dump($r->fetchAll());
-var_dump($r->fetchAll());
-
-echo "unbuffered with fetch_array\n";
-$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
-var_dump($r->fetch());
-var_dump($r->fetchAll());
-
-echo "buffered\n";
-$r = $db->query("SELECT a from strings", SQLITE_NUM);
-var_dump($r->fetchAll());
-var_dump($r->fetch());
-var_dump($r->fetchAll());
-
-echo "DONE!\n";
-?>
---EXPECTF--
-unbuffered twice
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-
-Warning: SQLiteUnbuffered::fetchAll(): One or more rowsets were already returned; returning NULL this time in %ssqlite_oo_014.php on line %d
-array(0) {
-}
-unbuffered with fetch_array
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(2) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [1]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-buffered
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-bool(false)
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_015.phpt b/ext/sqlite/tests/sqlite_oo_015.phpt
deleted file mode 100644
index 893e6f14ab..0000000000
--- a/ext/sqlite/tests/sqlite_oo_015.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-sqlite-oo: array_query
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-$res = $db->arrayQuery("SELECT a from strings", SQLITE_NUM);
-var_dump($res);
-
-echo "DONE!\n";
-?>
---EXPECTF--
-array(3) {
- [0]=>
- array(1) {
- [0]=>
- string(3) "one"
- }
- [1]=>
- array(1) {
- [0]=>
- string(3) "two"
- }
- [2]=>
- array(1) {
- [0]=>
- string(5) "three"
- }
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_016.phpt b/ext/sqlite/tests/sqlite_oo_016.phpt
deleted file mode 100644
index d831b48326..0000000000
--- a/ext/sqlite/tests/sqlite_oo_016.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-sqlite-oo: fetch single
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- array (0 => 'one', 1 => 'two'),
- array (0 => 'three', 1 => 'four')
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')");
-}
-
-echo "====BUFFERED====\n";
-$r = $db->query("SELECT a, b from strings");
-while ($r->valid()) {
- var_dump($r->fetchSingle());
-}
-echo "====UNBUFFERED====\n";
-$r = $db->unbufferedQuery("SELECT a, b from strings");
-while ($r->valid()) {
- var_dump($r->fetchSingle());
-}
-echo "DONE!\n";
-?>
---EXPECT--
-====BUFFERED====
-string(3) "one"
-string(5) "three"
-====UNBUFFERED====
-string(3) "one"
-string(5) "three"
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_020.phpt b/ext/sqlite/tests/sqlite_oo_020.phpt
deleted file mode 100644
index a855101fbd..0000000000
--- a/ext/sqlite/tests/sqlite_oo_020.phpt
+++ /dev/null
@@ -1,66 +0,0 @@
---TEST--
-sqlite-oo: factory and exception
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-$dbname = tempnam(dirname(__FILE__), "phpsql");
-function cleanup() {
- global $db, $dbname;
-
- $db = NULL;
- unlink($dbname);
-}
-register_shutdown_function("cleanup");
-
-try {
- $db = sqlite_factory();
-} catch(SQLiteException $err) {
- echo "Message: ".$err->getMessage()."\n";
- echo "File: ".$err->getFile()."\n";
- //echo "Line: ".$err->getLine()."\n";
- //print_r($err->getTrace());
- //echo "BackTrace: ".$err->getTraceAsString()."\n";
-}
-
-$db = sqlite_factory($dbname);
-
-$data = array(
- array (0 => 'one', 1 => 'two'),
- array (0 => 'three', 1 => 'four')
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR, b VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('${str[0]}','${str[1]}')");
-}
-
-$r = $db->unbufferedQuery("SELECT a, b from strings");
-while ($r->valid()) {
- var_dump($r->current(SQLITE_NUM));
- $r->next();
-}
-$r = null;
-$db = null;
-echo "DONE!\n";
-?>
---EXPECTF--
-Message: sqlite_factory() expects at least 1 parameter, 0 given
-File: %ssqlite_oo_020.php
-array(2) {
- [0]=>
- string(3) "one"
- [1]=>
- string(3) "two"
-}
-array(2) {
- [0]=>
- string(5) "three"
- [1]=>
- string(4) "four"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_021.phpt b/ext/sqlite/tests/sqlite_oo_021.phpt
deleted file mode 100644
index 850e4dc9a3..0000000000
--- a/ext/sqlite/tests/sqlite_oo_021.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-sqlite-oo: single query
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE test_db ( id INTEGER PRIMARY KEY, data VARCHAR(100) )");
-for ($i = 0; $i < 10; $i++) {
- $db->query("INSERT INTO test_db (data) VALUES('{$i}data')");
-}
-$db->query("INSERT INTO test_db (data) VALUES(NULL)");
-
-var_dump($db->singleQuery("SELECT id FROM test_db WHERE id=5"));
-var_dump($db->singleQuery("SELECT * FROM test_db WHERE id=4"));
-var_dump($db->singleQuery("SELECT data FROM test_db WHERE id=6"));
-var_dump($db->singleQuery("SELECT * FROM test_db WHERE id < 5"));
-var_dump($db->singleQuery("SELECT * FROM test db WHERE id < 4"));
-var_dump($db->singleQuery("SELECT * FROM test_db WHERE id=999999"));
-var_dump($db->singleQuery("SELECT id FROM test_db WHERE id=5", FALSE));
-
-echo "DONE!\n";
-?>
---EXPECTF--
-string(1) "5"
-string(1) "4"
-string(5) "5data"
-array(4) {
- [0]=>
- string(1) "1"
- [1]=>
- string(1) "2"
- [2]=>
- string(1) "3"
- [3]=>
- string(1) "4"
-}
-
-Warning: SQLiteDatabase::singleQuery(): no such table: test in %s on line %d
-bool(false)
-NULL
-array(1) {
- [0]=>
- string(1) "5"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_022.phpt b/ext/sqlite/tests/sqlite_oo_022.phpt
deleted file mode 100644
index 988904f774..0000000000
--- a/ext/sqlite/tests/sqlite_oo_022.phpt
+++ /dev/null
@@ -1,98 +0,0 @@
---TEST--
-sqlite-oo: sqlite::seek
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-$res = $db->query("SELECT a FROM strings", SQLITE_NUM);
-for ($idx = -1; $idx < 4; $idx++) {
- echo "====SEEK:$idx====\n";
- $res->seek($idx);
- var_dump($res->current());
-}
-echo "====AGAIN====\n";
-for ($idx = -1; $idx < 4; $idx++) {
- echo "====SEEK:$idx====\n";
- $res->seek($idx);
- var_dump($res->current());
-}
-echo "====DONE!====\n";
-?>
---EXPECTF--
-====SEEK:-1====
-
-Warning: SQLiteResult::seek(): row -1 out of range in %ssqlite_oo_022.php on line %d
-array(1) {
- [0]=>
- string(3) "one"
-}
-====SEEK:0====
-array(1) {
- [0]=>
- string(3) "one"
-}
-====SEEK:1====
-array(1) {
- [0]=>
- string(3) "two"
-}
-====SEEK:2====
-array(1) {
- [0]=>
- string(5) "three"
-}
-====SEEK:3====
-
-Warning: SQLiteResult::seek(): row 3 out of range in %ssqlite_oo_022.php on line %d
-array(1) {
- [0]=>
- string(5) "three"
-}
-====AGAIN====
-====SEEK:-1====
-
-Warning: SQLiteResult::seek(): row -1 out of range in %ssqlite_oo_022.php on line %d
-array(1) {
- [0]=>
- string(5) "three"
-}
-====SEEK:0====
-array(1) {
- [0]=>
- string(3) "one"
-}
-====SEEK:1====
-array(1) {
- [0]=>
- string(3) "two"
-}
-====SEEK:2====
-array(1) {
- [0]=>
- string(5) "three"
-}
-====SEEK:3====
-
-Warning: SQLiteResult::seek(): row 3 out of range in %ssqlite_oo_022.php on line %d
-array(1) {
- [0]=>
- string(5) "three"
-}
-====DONE!====
diff --git a/ext/sqlite/tests/sqlite_oo_024.phpt b/ext/sqlite/tests/sqlite_oo_024.phpt
deleted file mode 100644
index f974ad8a8d..0000000000
--- a/ext/sqlite/tests/sqlite_oo_024.phpt
+++ /dev/null
@@ -1,74 +0,0 @@
---TEST--
-sqlite-oo: sqlite::fetch_object
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-class class24 {
- function __construct() {
- echo __METHOD__ . "\n";
- }
-}
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-echo "====class24====\n";
-$res = $db->query("SELECT a FROM strings", SQLITE_ASSOC);
-while ($res->valid()) {
- var_dump($res->fetchObject('class24'));
-}
-
-echo "====stdclass====\n";
-$res = $db->query("SELECT a FROM strings", SQLITE_ASSOC);
-while ($res->valid()) {
- var_dump($res->fetchObject());
-}
-
-echo "====DONE!====\n";
-?>
---EXPECTF--
-====class24====
-class24::__construct
-object(class24)#%d (1) {
- ["a"]=>
- string(3) "one"
-}
-class24::__construct
-object(class24)#%d (1) {
- ["a"]=>
- string(3) "two"
-}
-class24::__construct
-object(class24)#%d (1) {
- ["a"]=>
- string(5) "three"
-}
-====stdclass====
-object(stdClass)#%d (1) {
- ["a"]=>
- string(3) "one"
-}
-object(stdClass)#%d (1) {
- ["a"]=>
- string(3) "two"
-}
-object(stdClass)#%d (1) {
- ["a"]=>
- string(5) "three"
-}
-====DONE!====
diff --git a/ext/sqlite/tests/sqlite_oo_025.phpt b/ext/sqlite/tests/sqlite_oo_025.phpt
deleted file mode 100644
index 3cb42d7647..0000000000
--- a/ext/sqlite/tests/sqlite_oo_025.phpt
+++ /dev/null
@@ -1,103 +0,0 @@
---TEST--
-sqlite-oo: sqlite / foreach
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-echo "====UNBUFFERED====\n";
-$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
-//var_dump(class_implements($r));
-foreach($r as $row) {
- var_dump($row);
-}
-echo "====NO-MORE====\n";
-foreach($r as $row) {
- var_dump($row);
-}
-echo "====DIRECT====\n";
-foreach($db->unbufferedQuery("SELECT a from strings", SQLITE_NUM) as $row) {
- var_dump($row);
-}
-echo "====BUFFERED====\n";
-$r = $db->query("SELECT a from strings", SQLITE_NUM);
-//var_dump(class_implements($r));
-foreach($r as $row) {
- var_dump($row);
-}
-foreach($r as $row) {
- var_dump($row);
-}
-echo "DONE!\n";
-?>
---EXPECT--
-====UNBUFFERED====
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-====NO-MORE====
-====DIRECT====
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-====BUFFERED====
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-array(1) {
- [0]=>
- string(3) "one"
-}
-array(1) {
- [0]=>
- string(3) "two"
-}
-array(1) {
- [0]=>
- string(5) "three"
-}
-DONE!
diff --git a/ext/sqlite/tests/sqlite_oo_026.phpt b/ext/sqlite/tests/sqlite_oo_026.phpt
deleted file mode 100644
index 4beacbb888..0000000000
--- a/ext/sqlite/tests/sqlite_oo_026.phpt
+++ /dev/null
@@ -1,56 +0,0 @@
---TEST--
-sqlite-oo: unbuffered
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array(
- "one",
- "two",
- "three"
- );
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
-}
-
-echo "====FOREACH====\n";
-$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
-foreach($r as $idx => $row) {
- var_dump($row[0]);
- var_dump($row[0]);
-}
-echo "====FOR====\n";
-$r = $db->unbufferedQuery("SELECT a from strings", SQLITE_NUM);
-for(;$r->valid(); $r->next()) {
- $v = $r->column(0);
- var_dump($v);
- $c = $r->column(0);
- var_dump(is_null($c) || $c==$v);
-}
-echo "===DONE===\n";
-?>
---EXPECT--
-====FOREACH====
-string(3) "one"
-string(3) "one"
-string(3) "two"
-string(3) "two"
-string(5) "three"
-string(5) "three"
-====FOR====
-string(3) "one"
-bool(true)
-string(3) "two"
-bool(true)
-string(5) "three"
-bool(true)
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_oo_027.phpt b/ext/sqlite/tests/sqlite_oo_027.phpt
deleted file mode 100644
index 069c7c97ea..0000000000
--- a/ext/sqlite/tests/sqlite_oo_027.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-sqlite-oo: changes
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$data = array("one", "two", "three");
-
-$db->query("CREATE TABLE strings(a VARCHAR)");
-
-foreach ($data as $str) {
- $db->query("INSERT INTO strings VALUES('$str')");
- echo $db->changes() . "\n";
-}
-
-$db->query("UPDATE strings SET a='foo' WHERE a!='two'");
-echo $db->changes() . "\n";
-
-$db->query("DELETE FROM strings WHERE 1");
-echo $db->changes() . "\n";
-
-$str = '';
-foreach ($data as $s) {
- $str .= "INSERT INTO strings VALUES('".$s."');";
-}
-$db->query($str);
-echo $db->changes() . "\n";
-
-?>
---EXPECT--
-1
-1
-1
-2
-3
-3
diff --git a/ext/sqlite/tests/sqlite_oo_028.phpt b/ext/sqlite/tests/sqlite_oo_028.phpt
deleted file mode 100644
index fe7f8c6f68..0000000000
--- a/ext/sqlite/tests/sqlite_oo_028.phpt
+++ /dev/null
@@ -1,25 +0,0 @@
---TEST--
-sqlite-oo: sqlite_fetch_column_types
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE strings(a, b INTEGER, c VARCHAR(10), d)");
-$db->query("INSERT INTO strings VALUES('1', '2', '3', 'abc')");
-
-var_dump($db->fetchColumnTypes("strings"));
-?>
---EXPECT--
-array(4) {
- ["a"]=>
- string(0) ""
- ["b"]=>
- string(7) "INTEGER"
- ["c"]=>
- string(11) "VARCHAR(10)"
- ["d"]=>
- string(0) ""
-}
diff --git a/ext/sqlite/tests/sqlite_oo_029.phpt b/ext/sqlite/tests/sqlite_oo_029.phpt
deleted file mode 100644
index 4b2b1992b8..0000000000
--- a/ext/sqlite/tests/sqlite_oo_029.phpt
+++ /dev/null
@@ -1,53 +0,0 @@
---TEST--
-sqlite-oo: call method with $this
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE strings(key VARCHAR(10), var VARCHAR(10))");
-$db->query("INSERT INTO strings VALUES('foo', 'foo')");
-
-class sqlite_help
-{
- function __construct($db){
- $this->db = $db;
- $this->db->createFunction('link_keywords', array(&$this, 'linkers'), 1);
- }
-
- function getSingle($key)
- {
- return $this->db->singleQuery('SELECT link_keywords(var) FROM strings WHERE key=\''.$key.'\'', 1);
- }
-
- function linkers($str)
- {
- $str = str_replace('foo', 'bar', $str);
- return $str;
- }
-
- function free()
- {
- unset($this->db);
- }
-
- function __destruct()
- {
- echo "DESTRUCTED\n";
- }
-}
-
-$obj = new sqlite_help($db);
-echo $obj->getSingle('foo')."\n";
-$obj->free();
-unset($obj);
-
-?>
-===DONE===
---EXPECT--
-bar
-===DONE===
-DESTRUCTED
diff --git a/ext/sqlite/tests/sqlite_oo_030.phpt b/ext/sqlite/tests/sqlite_oo_030.phpt
deleted file mode 100644
index 95b91f61fc..0000000000
--- a/ext/sqlite/tests/sqlite_oo_030.phpt
+++ /dev/null
@@ -1,44 +0,0 @@
---TEST--
-sqlite-oo: calling static methods
---INI--
-sqlite.assoc_case=0
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-
-require_once('blankdb_oo.inc');
-
-class foo {
- static function bar($param = NULL) {
- return $param;
- }
-}
-
-function baz($param = NULL) {
- return $param;
-}
-
-var_dump($db->singleQuery("select php('baz')", 1));
-var_dump($db->singleQuery("select php('baz', 1)", 1));
-var_dump($db->singleQuery("select php('baz', \"PHP\")", 1));
-var_dump($db->singleQuery("select php('foo::bar')", 1));
-var_dump($db->singleQuery("select php('foo::bar', 1)", 1));
-var_dump($db->singleQuery("select php('foo::bar', \"PHP\")", 1));
-var_dump($db->singleQuery("select php('foo::bar(\"PHP\")')", 1));
-
-?>
-===DONE===
---EXPECTF--
-NULL
-string(1) "1"
-string(3) "PHP"
-NULL
-string(1) "1"
-string(3) "PHP"
-
-Warning: SQLiteDatabase::singleQuery(): function `foo::bar("PHP")' is not a function name in %ssqlite_oo_030.php on line %d
-bool(false)
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_popen_basic.phpt b/ext/sqlite/tests/sqlite_popen_basic.phpt
deleted file mode 100644
index a3beaa10c8..0000000000
--- a/ext/sqlite/tests/sqlite_popen_basic.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-SQLite: sqlite_popen() basic tests
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip"; ?>
---FILE--
-<?php
-/* Prototype : resource sqlite_popen(string filename [, int mode [, string &error_message]])
- * Description: Opens a persistent handle to a SQLite database. Will create the database if it does not exist.
- * Source code: ext/sqlite/sqlite.c
- * Alias to functions:
-*/
-
- $db1 = sqlite_popen(":memory:");
- $db2 = sqlite_popen(":memory:");
-
- var_dump($db1);
- var_dump($db2);
-
- list($resourceId1) = sscanf((string) $db1, "resource(%d) of type (sqlite database (persistent))");
- list($resourceId2) = sscanf((string) $db2, "resource(%d) of type (sqlite database (persistent))");
-
- var_dump($resourceId1 === $resourceId2);
-?>
---EXPECTF--
-resource(%d) of type (sqlite database (persistent))
-resource(%d) of type (sqlite database (persistent))
-bool(true)
diff --git a/ext/sqlite/tests/sqlite_popen_error.phpt b/ext/sqlite/tests/sqlite_popen_error.phpt
deleted file mode 100644
index aefb678c20..0000000000
--- a/ext/sqlite/tests/sqlite_popen_error.phpt
+++ /dev/null
@@ -1,34 +0,0 @@
---TEST--
-Test sqlite_popen() function : error conditions
---SKIPIF--
-<?php if (!extension_loaded("sqlite")) print "skip sqlite extension not loaded"; ?>
---FILE--
-<?php
-/* Prototype : resource sqlite_popen(string filename [, int mode [, string &error_message]])
- * Description: Opens a persistent handle to a SQLite database. Will create the database if it does not exist.
- * Source code: ext/sqlite/sqlite.c
- * Alias to functions:
- */
-
-$message = '';
-
-echo "*** Testing sqlite_popen() : error conditions ***\n";
-
-var_dump( sqlite_popen() );
-var_dump( sqlite_popen(":memory:", 0666, $message, 'foobar') );
-var_dump( sqlite_popen("", 0666, $message) );
-var_dump( $message );
-
-?>
-===DONE===
---EXPECTF--
-*** Testing sqlite_popen() : error conditions ***
-
-Warning: sqlite_popen() expects at least 1 parameter, 0 given in %s on line %d
-NULL
-
-Warning: sqlite_popen() expects at most 3 parameters, 4 given in %s on line %d
-NULL
-bool(false)
-NULL
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_session_001.phpt b/ext/sqlite/tests/sqlite_session_001.phpt
deleted file mode 100644
index 2fb2007c32..0000000000
--- a/ext/sqlite/tests/sqlite_session_001.phpt
+++ /dev/null
@@ -1,46 +0,0 @@
---TEST--
-sqlite, session storage test
---CREDITS--
-Mats Lindh <mats at lindh.no>
-#Testfest php.no
---INI--
-session.save_handler = sqlite
---SKIPIF--
-if (!extension_loaded("session"))
-{
- die("skip Session module not loaded");
-}
-if (!extension_loaded("sqlite"))
-{
- die("skip Session module not loaded");
-}
---FILE--
-<?php
-/* Description: Tests that sqlite can be used as a session save handler
-* Source code: ext/sqlite/sess_sqlite.c
-*/
-
-ob_start();
-session_save_path(__DIR__ . "/sessiondb.sdb");
-
-// create the session and set a session value
-session_start();
-$_SESSION["test"] = "foo_bar";
-
-// close the session and unset the value
-session_write_close();
-unset($_SESSION["test"]);
-var_dump(isset($_SESSION["test"]));
-
-// start the session again and check that we have the proper value
-session_start();
-var_dump($_SESSION["test"]);
-ob_end_flush();
-?>
---EXPECTF--
-bool(false)
-%unicode|string%(7) "foo_bar"
---CLEAN--
-<?php
- unlink(__DIR__ . "/sessiondb.sdb")
-?>
diff --git a/ext/sqlite/tests/sqlite_session_002.phpt b/ext/sqlite/tests/sqlite_session_002.phpt
deleted file mode 100644
index 546ba1cd14..0000000000
--- a/ext/sqlite/tests/sqlite_session_002.phpt
+++ /dev/null
@@ -1,54 +0,0 @@
---TEST--
-sqlite, session destroy test
---CREDITS--
-Mats Lindh <mats at lindh.no>
-#Testfest php.no
---INI--
-session.save_handler = sqlite
---SKIPIF--
-if (!extension_loaded("session"))
-{
- die("skip Session module not loaded");
-}
-if (!extension_loaded("sqlite"))
-{
- die("skip sqlite module not loaded");
-}
---FILE--
-<?php
-/* Description: Tests that sqlite will destroy a session when used as a session handler
-* Source code: ext/sqlite/sess_sqlite.c
-*/
-ob_start();
-session_save_path(__DIR__ . "/sessiondb.sdb");
-
-// start a session and save a value to it before commiting the session to the database
-session_start();
-$_SESSION["test"] = "foo_bar";
-session_write_close();
-
-// remove the session value
-unset($_SESSION["test"]);
-var_dump(isset($_SESSION["test"]));
-
-// start the session again and destroy it
-session_start();
-var_dump($_SESSION["test"]);
-session_destroy();
-session_write_close();
-
-unset($_SESSION["test"]);
-
-// check that the session has been destroyed
-session_start();
-var_dump(isset($_SESSION["test"]));
-ob_end_flush();
-?>
---EXPECTF--
-bool(false)
-%unicode|string%(7) "foo_bar"
-bool(false)
---CLEAN--
-<?php
- unlink(__DIR__ . "/sessiondb.sdb")
-?>
diff --git a/ext/sqlite/tests/sqlite_spl_001.phpt b/ext/sqlite/tests/sqlite_spl_001.phpt
deleted file mode 100644
index 2a1a2b49c4..0000000000
--- a/ext/sqlite/tests/sqlite_spl_001.phpt
+++ /dev/null
@@ -1,125 +0,0 @@
---TEST--
-sqlite-spl: Iteration
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-if (!extension_loaded("spl")) print "skip SPL is not present";
-?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE menu(id_l int PRIMARY KEY, id_r int UNIQUE, key VARCHAR(10))");
-$db->query("INSERT INTO menu VALUES( 1, 12, 'A')");
-$db->query("INSERT INTO menu VALUES( 2, 9, 'B')");
-$db->query("INSERT INTO menu VALUES(10, 11, 'F')");
-$db->query("INSERT INTO menu VALUES( 3, 6, 'C')");
-$db->query("INSERT INTO menu VALUES( 7, 8, 'E')");
-$db->query("INSERT INTO menu VALUES( 4, 5, 'D')");
-
-class SqliteNestedsetElement
-{
- protected $id_l;
- protected $id_r;
- protected $key;
-
- function __construct($db)
- {
- $this->db = $db;
- }
-
- function getLeft()
- {
- return $this->id_l;
- }
-
- function getRight()
- {
- return $this->id_r;
- }
-
- function __toString()
- {
- return $this->key;
- }
-
- function key()
- {
- return $this->key;
- }
-}
-
-class SqliteNestedset implements RecursiveIterator
-{
- protected $id;
- protected $id_l;
- protected $id_r;
- protected $entry;
-
- function __construct($db, $id_l = 1)
- {
- $this->db = $db;
- $this->id_l = $id_l;
- $this->id_r = $this->db->singleQuery('SELECT id_r FROM menu WHERE id_l='.$id_l, 1);
- $this->id = $id_l;
- }
-
- function rewind()
- {
- $this->id = $this->id_l;
- $this->fetch();
- }
-
- function valid()
- {
- return is_object($this->entry);
- }
-
- function current()
- {
- return $this->entry->__toString();
- }
-
- function key()
- {
- return $this->entry->key();;
- }
-
- function next()
- {
- $this->id = $this->entry->getRight() + 1;
- $this->fetch();
- }
-
- protected function fetch()
- {
- $res = $this->db->unbufferedQuery('SELECT * FROM menu WHERE id_l='.$this->id);
- $this->entry = $res->fetchObject('SqliteNestedsetElement', array(&$this->db));
- unset($res);
- }
-
- function hasChildren()
- {
- return $this->entry->getLeft() + 1 < $this->entry->getRight();
- }
-
- function getChildren()
- {
- return new SqliteNestedset($this->db, $this->entry->getLeft() + 1, $this->entry->getRight() - 1);
- }
-}
-
-$menu_iterator = new RecursiveIteratorIterator(new SqliteNestedset($db), RecursiveIteratorIterator::SELF_FIRST);
-foreach($menu_iterator as $entry) {
- echo $menu_iterator->getDepth() . $entry . "\n";
-}
-?>
-===DONE===
---EXPECT--
-0A
-1B
-2C
-3D
-2E
-1F
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_spl_002.phpt b/ext/sqlite/tests/sqlite_spl_002.phpt
deleted file mode 100644
index c60ca01e02..0000000000
--- a/ext/sqlite/tests/sqlite_spl_002.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-sqlite-spl: Countable
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-if (!extension_loaded("spl")) print "skip SPL is not present";
-?>
---FILE--
-<?php
-include "blankdb_oo.inc";
-
-$db->query("CREATE TABLE menu(id_l int PRIMARY KEY, id_r int UNIQUE, key VARCHAR(10))");
-$db->query("INSERT INTO menu VALUES( 1, 12, 'A')");
-$db->query("INSERT INTO menu VALUES( 2, 9, 'B')");
-$db->query("INSERT INTO menu VALUES(10, 11, 'F')");
-$db->query("INSERT INTO menu VALUES( 3, 6, 'C')");
-$db->query("INSERT INTO menu VALUES( 7, 8, 'E')");
-$db->query("INSERT INTO menu VALUES( 4, 5, 'D')");
-
-$res = $db->query("SELECT * from menu");
-
-var_dump($res->count());
-var_dump(count($res));
-?>
-===DONE===
---EXPECT--
-int(6)
-int(6)
-===DONE===
diff --git a/ext/sqlite/tests/sqlite_spl_003.phpt b/ext/sqlite/tests/sqlite_spl_003.phpt
deleted file mode 100644
index 267ceff50c..0000000000
--- a/ext/sqlite/tests/sqlite_spl_003.phpt
+++ /dev/null
@@ -1,28 +0,0 @@
---TEST--
-sqlite-spl: Exception
---SKIPIF--
-<?php # vim:ft=php
-if (!extension_loaded("sqlite")) print "skip";
-if (!extension_loaded("spl")) print "skip SPL is not present";
-?>
---FILE--
-<?php
-
-try
-{
- $db = sqlite_factory();
-}
-catch(SQLiteException $e)
-{
- $parents = class_parents($e);
- if (array_key_exists('RuntimeException', $parents))
- {
- echo "GOOD\n";
- }
-}
-
-?>
-===DONE===
---EXPECT--
-GOOD
-===DONE===
diff --git a/ext/sqlite/tests/sqlitedatabase_arrayquery.phpt b/ext/sqlite/tests/sqlitedatabase_arrayquery.phpt
deleted file mode 100644
index 1e3084cebe..0000000000
--- a/ext/sqlite/tests/sqlitedatabase_arrayquery.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Testing SQLiteDatabase::ArrayQuery with NULL-byte string
---SKIPIF--
-<?php
-if (!extension_loaded("sqlite")) print "skip";
-?>
---FILE--
-<?php
-
-$method = new ReflectionMethod('sqlitedatabase::arrayquery');
-
-$class = $method->getDeclaringClass()->newInstanceArgs(array(':memory:'));
-
-$p = "\0";
-
-$method->invokeArgs($class, array_fill(0, 2, $p));
-$method->invokeArgs($class, array_fill(0, 1, $p));
-
-?>
---EXPECTF--
-Warning: SQLiteDatabase::arrayQuery() expects parameter 2 to be long, string given in %s on line %d
-
-Warning: SQLiteDatabase::arrayQuery(): Cannot execute empty query. in %s on line %d
diff --git a/ext/sqlite3/libsqlite/sqlite3.c b/ext/sqlite3/libsqlite/sqlite3.c
index a3d542a40c..d96367e212 100644
--- a/ext/sqlite3/libsqlite/sqlite3.c
+++ b/ext/sqlite3/libsqlite/sqlite3.c
@@ -23307,7 +23307,7 @@ static int os2OpenSharedMemory( os2File *fd, int szRegion ) {
sqlite3_mutex_leave(pNode->mutex);
} else {
- /* Error occured. Free our link object. */
+ /* Error occurred. Free our link object. */
sqlite3_free(pLink);
}
@@ -28994,7 +28994,7 @@ static int fillInUnixFile(
unixEnterMutex();
rc = findInodeInfo(pNew, &pNew->pInode);
if( rc!=SQLITE_OK ){
- /* If an error occured in findInodeInfo(), close the file descriptor
+ /* If an error occurred in findInodeInfo(), close the file descriptor
** immediately, before releasing the mutex. findInodeInfo() may fail
** in two scenarios:
**
@@ -32173,7 +32173,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
- ** whether an error has actually occured, it is also necessary to call
+ ** whether an error has actually occurred, it is also necessary to call
** GetLastError().
*/
dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -32273,7 +32273,7 @@ static int winWrite(
int amt, /* Number of bytes to write */
sqlite3_int64 offset /* Offset into the file to begin writing at */
){
- int rc; /* True if error has occured, else false */
+ int rc; /* True if error has occurred, else false */
winFile *pFile = (winFile*)id; /* File handle */
assert( amt>0 );
@@ -37068,7 +37068,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** * A write transaction is active.
** * An EXCLUSIVE or greater lock is held on the database file.
** * All writing and syncing of journal and database data has finished.
-** If no error occured, all that remains is to finalize the journal to
+** If no error occurred, all that remains is to finalize the journal to
** commit the transaction. If an error did occur, the caller will need
** to rollback the transaction.
**
@@ -54279,7 +54279,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occured and pPage has an overflow cell, call balance()
+ /* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
** variables.
@@ -57935,7 +57935,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
}
sqlite3DbFree(v->db, sIter.apSub);
- /* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
+ /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
** If malloc failed, then the while() loop above may not have iterated
** through all opcodes and hasAbort may be set incorrectly. Return
** true for this case to prevent the assert() in the callers frame
@@ -59562,7 +59562,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
/* If p->iStatement is greater than zero, then this Vdbe opened a
** statement transaction that should be closed here. The only exception
- ** is that an IO error may have occured, causing an emergency rollback.
+ ** is that an IO error may have occurred, causing an emergency rollback.
** In this case (db->nStatement==0), and there is nothing to do.
*/
if( db->nStatement && p->iStatement ){
@@ -59697,7 +59697,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
**
** Even if the statement is read-only, it is important to perform
** a statement or transaction rollback operation. If the error
- ** occured while writing to the journal, sub-journal or database
+ ** occurred while writing to the journal, sub-journal or database
** file as part of an effort to free up cache space (see function
** pagerStress() in pager.c), the rollback is required to restore
** the pager to a consistent state.
@@ -61245,7 +61245,7 @@ end_of_step:
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
/* If this statement was prepared using sqlite3_prepare_v2(), and an
- ** error has occured, then return the error code in p->rc to the
+ ** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
rc = db->errCode = p->rc;
@@ -113286,7 +113286,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
}else{
int rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK ){
- /* If no row was found and no error has occured, then the %_content
+ /* If no row was found and no error has occurred, then the %_content
** table is missing a row that is present in the full-text index.
** The data structures are corrupt.
*/
diff --git a/ext/sqlite3/php_sqlite3.h b/ext/sqlite3/php_sqlite3.h
index 87a9335382..b079d47410 100644
--- a/ext/sqlite3/php_sqlite3.h
+++ b/ext/sqlite3/php_sqlite3.h
@@ -21,7 +21,7 @@
#ifndef PHP_SQLITE3_H
#define PHP_SQLITE3_H
-#define PHP_SQLITE3_VERSION "0.7-dev"
+#define PHP_SQLITE3_VERSION "0.7"
extern zend_module_entry sqlite3_module_entry;
#define phpext_sqlite3_ptr &sqlite3_module_entry
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index d3314d3f86..0bb8616d96 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -103,7 +103,7 @@ PHP_METHOD(sqlite3, open)
db_obj = (php_sqlite3_db_object *)zend_object_store_get_object(object TSRMLS_CC);
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &filename, &filename_len, &flags, &encryption_key, &encryption_key_len)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ls", &filename, &filename_len, &flags, &encryption_key, &encryption_key_len)) {
zend_restore_error_handling(&error_handling TSRMLS_CC);
return;
}
@@ -1097,7 +1097,7 @@ static int php_sqlite3_stream_close(php_stream *stream, int close_handle TSRMLS_
php_stream_sqlite3_data *sqlite3_stream = (php_stream_sqlite3_data *) stream->abstract;
if (sqlite3_blob_close(sqlite3_stream->blob) != SQLITE_OK) {
- /* Error occured, but it still closed */
+ /* Error occurred, but it still closed */
}
efree(sqlite3_stream);
@@ -2121,7 +2121,6 @@ static void php_sqlite3_result_object_free_storage(void *object TSRMLS_DC) /* {{
static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- zval *tmp;
zend_object_value retval;
php_sqlite3_db_object *intern;
@@ -2134,7 +2133,7 @@ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSR
zend_llist_init(&(intern->free_list), sizeof(php_sqlite3_free_list *), (llist_dtor_func_t)php_sqlite3_free_list_dtor, 0);
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,(void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &sqlite3_object_handlers;
@@ -2145,7 +2144,6 @@ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSR
static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- zval *tmp;
zend_object_value retval;
php_sqlite3_stmt *intern;
@@ -2156,7 +2154,7 @@ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_typ
intern->db_obj_zval = NULL;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,(void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_stmt_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &sqlite3_stmt_object_handlers;
@@ -2167,7 +2165,6 @@ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_typ
static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- zval *tmp;
zend_object_value retval;
php_sqlite3_result *intern;
@@ -2180,7 +2177,7 @@ static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_t
intern->stmt_obj_zval = NULL;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,(void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_result_object_free_storage, NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) &sqlite3_result_object_handlers;
diff --git a/ext/sqlite3/tests/bug53463.phpt b/ext/sqlite3/tests/bug53463.phpt
index dcfc13d5ba..744a214612 100644
--- a/ext/sqlite3/tests/bug53463.phpt
+++ b/ext/sqlite3/tests/bug53463.phpt
@@ -27,4 +27,4 @@ echo "Done\n";
--EXPECT--
string(8) "whatever"
bool(false)
-Done \ No newline at end of file
+Done
diff --git a/ext/sqlite3/tests/sqlite3_15_open_error.phpt b/ext/sqlite3/tests/sqlite3_15_open_error.phpt
index 9b0496f889..fc05b87802 100644
--- a/ext/sqlite3/tests/sqlite3_15_open_error.phpt
+++ b/ext/sqlite3/tests/sqlite3_15_open_error.phpt
@@ -5,14 +5,14 @@ SQLite3::open error test
if(substr(PHP_OS, 0, 3) == 'WIN' ) {
die('skip non windows test');
}
-require_once(dirname(__FILE__) . '/skipif.inc');
+require_once(__DIR__ . '/skipif.inc');
if (posix_geteuid() == 0) {
die('SKIP Cannot run test as root.');
}
?>
--FILE--
<?php
-$unreadable = dirname(__FILE__) . '/unreadable.db';
+$unreadable = __DIR__ . '/unreadable.db';
touch($unreadable);
chmod($unreadable, 0200);
try {
diff --git a/ext/standard/array.c b/ext/standard/array.c
index e804ff8fc0..94c5e7e6ee 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -118,6 +118,8 @@ PHP_MINIT_FUNCTION(array) /* {{{ */
REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SORT_FLAG_CASE", PHP_SORT_FLAG_CASE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT);
@@ -141,13 +143,17 @@ PHP_MSHUTDOWN_FUNCTION(array) /* {{{ */
static void php_set_compare_func(int sort_type TSRMLS_DC) /* {{{ */
{
- switch (sort_type) {
+ switch (sort_type & ~PHP_SORT_FLAG_CASE) {
case PHP_SORT_NUMERIC:
ARRAYG(compare_func) = numeric_compare_function;
break;
case PHP_SORT_STRING:
- ARRAYG(compare_func) = string_compare_function;
+ ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_case_compare_function : string_compare_function;
+ break;
+
+ case PHP_SORT_NATURAL:
+ ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_natural_case_compare_function : string_natural_compare_function;
break;
#if HAVE_STRCOLL
@@ -180,7 +186,7 @@ static int php_array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{
Z_LVAL(first) = f->h;
} else {
Z_TYPE(first) = IS_STRING;
- Z_STRVAL(first) = f->arKey;
+ Z_STRVAL(first) = (char*)f->arKey;
Z_STRLEN(first) = f->nKeyLength - 1;
}
@@ -189,7 +195,7 @@ static int php_array_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{
Z_LVAL(second) = s->h;
} else {
Z_TYPE(second) = IS_STRING;
- Z_STRVAL(second) = s->arKey;
+ Z_STRVAL(second) = (char*)s->arKey;
Z_STRLEN(second) = s->nKeyLength - 1;
}
@@ -629,7 +635,7 @@ static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{
PHP_FUNCTION(usort)
{
zval *array;
- int refcount;
+ unsigned int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
PHP_ARRAY_CMP_FUNC_BACKUP();
@@ -672,7 +678,7 @@ PHP_FUNCTION(usort)
PHP_FUNCTION(uasort)
{
zval *array;
- int refcount;
+ unsigned int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
PHP_ARRAY_CMP_FUNC_BACKUP();
@@ -768,7 +774,7 @@ static int php_array_user_key_compare(const void *a, const void *b TSRMLS_DC) /*
PHP_FUNCTION(uksort)
{
zval *array;
- int refcount;
+ unsigned int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
PHP_ARRAY_CMP_FUNC_BACKUP();
@@ -1556,7 +1562,7 @@ PHP_FUNCTION(array_fill)
num--;
zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, &val, sizeof(zval *), NULL);
- zval_add_ref(&val);
+ zval_add_ref(&val);
while (num--) {
if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val, sizeof(zval *), NULL) == SUCCESS) {
@@ -1665,24 +1671,28 @@ PHP_FUNCTION(range)
high = (unsigned char *)Z_STRVAL_P(zhigh);
if (*low > *high) { /* Negative Steps */
+ unsigned char ch = *low;
+
if (lstep <= 0) {
err = 1;
goto err;
}
- for (; *low >= *high; (*low) -= (unsigned int)lstep) {
- add_next_index_stringl(return_value, (const char *)low, 1, 1);
- if (((signed int)*low - lstep) < 0) {
+ for (; ch >= *high; ch -= (unsigned int)lstep) {
+ add_next_index_stringl(return_value, (const char *)&ch, 1, 1);
+ if (((signed int)ch - lstep) < 0) {
break;
}
}
} else if (*high > *low) { /* Positive Steps */
+ unsigned char ch = *low;
+
if (lstep <= 0) {
err = 1;
goto err;
}
- for (; *low <= *high; (*low) += (unsigned int)lstep) {
- add_next_index_stringl(return_value, (const char *)low, 1, 1);
- if (((signed int)*low + lstep) > 255) {
+ for (; ch <= *high; ch += (unsigned int)lstep) {
+ add_next_index_stringl(return_value, (const char *)&ch, 1, 1);
+ if (((signed int)ch + lstep) > 255) {
break;
}
}
@@ -3761,7 +3771,7 @@ PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC) /* {{{
efree(args); \
RETURN_FALSE;
-/* {{{ proto bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* {{{ proto bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
Sort multiple arrays at once similar to how ORDER BY clause works in SQL */
PHP_FUNCTION(array_multisort)
{
@@ -3811,7 +3821,7 @@ PHP_FUNCTION(array_multisort)
parse_state[k] = 1;
}
} else if (Z_TYPE_PP(args[i]) == IS_LONG) {
- switch (Z_LVAL_PP(args[i])) {
+ switch (Z_LVAL_PP(args[i]) & ~PHP_SORT_FLAG_CASE) {
case PHP_SORT_ASC:
case PHP_SORT_DESC:
/* flag allowed here */
@@ -3828,6 +3838,7 @@ PHP_FUNCTION(array_multisort)
case PHP_SORT_REGULAR:
case PHP_SORT_NUMERIC:
case PHP_SORT_STRING:
+ case PHP_SORT_NATURAL:
#if HAVE_STRCOLL
case PHP_SORT_LOCALE_STRING:
#endif
@@ -4484,13 +4495,12 @@ PHP_FUNCTION(array_combine)
RETURN_FALSE;
}
+ array_init_size(return_value, num_keys);
+
if (!num_keys) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Both parameters should have at least 1 element");
- RETURN_FALSE;
+ return;
}
- array_init_size(return_value, num_keys);
-
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos_keys);
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&entry_keys, &pos_keys) == SUCCESS &&
diff --git a/ext/standard/assert.c b/ext/standard/assert.c
index 80634fa988..15fbefd51c 100644
--- a/ext/standard/assert.c
+++ b/ext/standard/assert.c
@@ -136,20 +136,20 @@ PHP_MINFO_FUNCTION(assert) /* {{{ */
}
/* }}} */
-/* {{{ proto int assert(string|bool assertion)
+/* {{{ proto int assert(string|bool assertion[, string description])
Checks if assertion is false */
PHP_FUNCTION(assert)
{
zval **assertion;
- int val;
+ int val, description_len = 0;
char *myeval = NULL;
- char *compiled_string_description;
+ char *compiled_string_description, *description = NULL;
if (! ASSERTG(active)) {
RETURN_TRUE;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &assertion) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|s", &assertion, &description, &description_len) == FAILURE) {
return;
}
@@ -167,7 +167,11 @@ PHP_FUNCTION(assert)
compiled_string_description = zend_make_compiled_string_description("assert code" TSRMLS_CC);
if (zend_eval_stringl(myeval, Z_STRLEN_PP(assertion), &retval, compiled_string_description TSRMLS_CC) == FAILURE) {
efree(compiled_string_description);
- php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s", PHP_EOL, myeval);
+ if (description_len == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s", PHP_EOL, myeval);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s:\"%s\"", PHP_EOL, description, myeval);
+ }
if (ASSERTG(bail)) {
zend_bailout();
}
@@ -196,11 +200,11 @@ PHP_FUNCTION(assert)
}
if (ASSERTG(callback)) {
- zval *args[3];
+ zval **args = safe_emalloc(description_len == 0 ? 3 : 4, sizeof(zval **), 0);
zval *retval;
int i;
uint lineno = zend_get_executed_lineno(TSRMLS_C);
- char *filename = zend_get_executed_filename(TSRMLS_C);
+ const char *filename = zend_get_executed_filename(TSRMLS_C);
MAKE_STD_ZVAL(args[0]);
MAKE_STD_ZVAL(args[1]);
@@ -214,19 +218,38 @@ PHP_FUNCTION(assert)
ZVAL_FALSE(retval);
/* XXX do we want to check for error here? */
- call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 3, args TSRMLS_CC);
+ if (description_len == 0) {
+ call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 3, args TSRMLS_CC);
+ for (i = 0; i <= 2; i++) {
+ zval_ptr_dtor(&(args[i]));
+ }
+ } else {
+ MAKE_STD_ZVAL(args[3]);
+ ZVAL_STRINGL(args[3], SAFE_STRING(description), description_len, 1);
- for (i = 0; i <= 2; i++) {
- zval_ptr_dtor(&(args[i]));
+ call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 4, args TSRMLS_CC);
+ for (i = 0; i <= 3; i++) {
+ zval_ptr_dtor(&(args[i]));
+ }
}
+
+ efree(args);
zval_ptr_dtor(&retval);
}
if (ASSERTG(warning)) {
- if (myeval) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion \"%s\" failed", myeval);
+ if (description_len == 0) {
+ if (myeval) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion \"%s\" failed", myeval);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion failed");
+ }
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion failed");
+ if (myeval) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: \"%s\" failed", description, myeval);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s failed", description);
+ }
}
}
@@ -321,3 +344,4 @@ PHP_FUNCTION(assert_options)
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
+
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 4858b6e375..0f60b711a6 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -34,7 +34,6 @@
#include "zend_operators.h"
#include "ext/standard/php_dns.h"
#include "ext/standard/php_uuencode.h"
-#include "safe_mode.h"
#ifdef PHP_WIN32
#include "win32/php_win32_globals.h"
@@ -119,11 +118,6 @@ PHPAPI php_basic_globals basic_globals;
static zend_class_entry *incomplete_class_entry = NULL;
-typedef struct _php_shutdown_function_entry {
- zval **arguments;
- int arg_count;
-} php_shutdown_function_entry;
-
typedef struct _user_tick_function_entry {
zval **arguments;
int arg_count;
@@ -142,6 +136,13 @@ ZEND_BEGIN_ARG_INFO(arginfo_set_time_limit, 0)
ZEND_ARG_INFO(0, seconds)
ZEND_END_ARG_INFO()
/* }}} */
+
+/* {{{ main/sapi.c */
+ZEND_BEGIN_ARG_INFO(arginfo_header_register_callback, 0)
+ ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO()
+/* }}} */
+
/* {{{ main/output.c */
ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_start, 0, 0, 0)
ZEND_ARG_INFO(0, user_function)
@@ -855,11 +856,6 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_config_get_hash, 0)
ZEND_END_ARG_INFO()
#endif
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_import_request_variables, 0, 0, 1)
- ZEND_ARG_INFO(0, types)
- ZEND_ARG_INFO(0, prefix)
-ZEND_END_ARG_INFO()
#ifdef HAVE_GETLOADAVG
ZEND_BEGIN_ARG_INFO(arginfo_sys_getloadavg, 0)
@@ -1002,11 +998,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_check_record, 0, 0, 1)
ZEND_END_ARG_INFO()
# if defined(PHP_WIN32) || HAVE_FULL_DNS_FUNCS
-ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_record, 1, 0, 1)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_record, 0, 0, 1)
ZEND_ARG_INFO(0, hostname)
ZEND_ARG_INFO(0, type)
- ZEND_ARG_INFO(1, authns) /* ARRAY_INFO(1, authns, 1) */
- ZEND_ARG_INFO(1, addtl) /* ARRAY_INFO(1, addtl, 1) */
+ ZEND_ARG_ARRAY_INFO(1, authns, 1)
+ ZEND_ARG_ARRAY_INFO(1, addtl, 1)
+ ZEND_ARG_INFO(0, raw)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_mx, 0, 0, 2)
@@ -1209,8 +1206,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_fstat, 0)
ZEND_ARG_INFO(0, fp)
ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_copy, 0, 0, 2)
+ZEND_BEGIN_ARG_INFO(arginfo_copy, 0)
ZEND_ARG_INFO(0, source_file)
ZEND_ARG_INFO(0, destination_file)
ZEND_ARG_INFO(0, context)
@@ -1479,6 +1475,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_headers_list, 0)
ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_http_response_code, 0, 0, 0)
+ ZEND_ARG_INFO(0, response_code)
+ZEND_END_ARG_INFO()
/* }}} */
/* {{{ html.c */
ZEND_BEGIN_ARG_INFO_EX(arginfo_htmlspecialchars, 0, 0, 1)
@@ -1517,6 +1517,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_http_build_query, 0, 0, 1)
ZEND_ARG_INFO(0, formdata)
ZEND_ARG_INFO(0, prefix)
ZEND_ARG_INFO(0, arg_separator)
+ ZEND_ARG_INFO(0, enc_type)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ image.c */
@@ -2112,6 +2113,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_stream_set_write_buffer, 0)
ZEND_ARG_INFO(0, fp)
ZEND_ARG_INFO(0, buffer)
ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_stream_set_chunk_size, 0)
+ ZEND_ARG_INFO(0, fp)
+ ZEND_ARG_INFO(0, chunk_size)
+ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_socket_enable_crypto, 0, 0, 2)
ZEND_ARG_INFO(0, stream)
@@ -2132,6 +2138,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_bin2hex, 0)
ZEND_ARG_INFO(0, data)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO(arginfo_hex2bin, 0)
+ ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_strspn, 0, 0, 2)
ZEND_ARG_INFO(0, str)
ZEND_ARG_INFO(0, mask)
@@ -2472,9 +2482,6 @@ ZEND_END_ARG_INFO()
/* }}} */
/* {{{ syslog.c */
#ifdef HAVE_SYSLOG_H
-ZEND_BEGIN_ARG_INFO(arginfo_define_syslog_variables, 0)
-ZEND_END_ARG_INFO()
-
ZEND_BEGIN_ARG_INFO(arginfo_openlog, 0)
ZEND_ARG_INFO(0, ident)
ZEND_ARG_INFO(0, option)
@@ -2675,6 +2682,7 @@ ZEND_END_ARG_INFO()
const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(constant, arginfo_constant)
PHP_FE(bin2hex, arginfo_bin2hex)
+ PHP_FE(hex2bin, arginfo_hex2bin)
PHP_FE(sleep, arginfo_sleep)
PHP_FE(usleep, arginfo_usleep)
#if HAVE_NANOSLEEP
@@ -2702,6 +2710,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(iptcparse, arginfo_iptcparse)
PHP_FE(iptcembed, arginfo_iptcembed)
PHP_FE(getimagesize, arginfo_getimagesize)
+ PHP_FE(getimagesizefromstring, arginfo_getimagesize)
PHP_FE(image_type_to_mime_type, arginfo_image_type_to_mime_type)
PHP_FE(image_type_to_extension, arginfo_image_type_to_extension)
@@ -2835,8 +2844,8 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(rand, arginfo_rand)
PHP_FE(srand, arginfo_srand)
- PHP_FE(getrandmax, arginfo_getrandmax)
- PHP_FE(mt_rand, arginfo_mt_rand)
+ PHP_FE(getrandmax, arginfo_getrandmax)
+ PHP_FE(mt_rand, arginfo_mt_rand)
PHP_FE(mt_srand, arginfo_mt_srand)
PHP_FE(mt_getrandmax, arginfo_mt_getrandmax)
@@ -2945,14 +2954,14 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(convert_cyr_string, arginfo_convert_cyr_string)
PHP_FE(get_current_user, arginfo_get_current_user)
PHP_FE(set_time_limit, arginfo_set_time_limit)
+ PHP_FE(header_register_callback, arginfo_header_register_callback)
PHP_FE(get_cfg_var, arginfo_get_cfg_var)
PHP_DEP_FALIAS(magic_quotes_runtime, set_magic_quotes_runtime, arginfo_set_magic_quotes_runtime)
PHP_DEP_FE(set_magic_quotes_runtime, arginfo_set_magic_quotes_runtime)
- PHP_FE(get_magic_quotes_gpc, arginfo_get_magic_quotes_gpc)
- PHP_FE(get_magic_quotes_runtime, arginfo_get_magic_quotes_runtime)
+ PHP_FE(get_magic_quotes_gpc, arginfo_get_magic_quotes_gpc)
+ PHP_FE(get_magic_quotes_runtime, arginfo_get_magic_quotes_runtime)
- PHP_FE(import_request_variables, arginfo_import_request_variables)
PHP_FE(error_log, arginfo_error_log)
PHP_FE(error_get_last, arginfo_error_get_last)
PHP_FE(call_user_func, arginfo_call_user_func)
@@ -2995,6 +3004,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(header_remove, arginfo_header_remove)
PHP_FE(headers_sent, arginfo_headers_sent)
PHP_FE(headers_list, arginfo_headers_list)
+ PHP_FE(http_response_code, arginfo_http_response_code)
PHP_FE(connection_aborted, arginfo_connection_aborted)
PHP_FE(connection_status, arginfo_connection_status)
@@ -3115,6 +3125,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(stream_set_read_buffer, arginfo_stream_set_read_buffer)
PHP_FE(stream_set_write_buffer, arginfo_stream_set_write_buffer)
PHP_FALIAS(set_file_buffer, stream_set_write_buffer, arginfo_stream_set_write_buffer)
+ PHP_FE(stream_set_chunk_size, arginfo_stream_set_chunk_size)
PHP_DEP_FALIAS(set_socket_blocking, stream_set_blocking, arginfo_stream_set_blocking)
PHP_FE(stream_set_blocking, arginfo_stream_set_blocking)
@@ -3230,7 +3241,6 @@ const zend_function_entry basic_functions[] = { /* {{{ */
PHP_FE(openlog, arginfo_openlog)
PHP_FE(syslog, arginfo_syslog)
PHP_FE(closelog, arginfo_closelog)
- PHP_DEP_FE(define_syslog_variables, arginfo_define_syslog_variables)
#endif
/* functions from lcg.c */
@@ -3364,41 +3374,6 @@ const zend_function_entry basic_functions[] = { /* {{{ */
};
/* }}} */
-static PHP_INI_MH(OnUpdateSafeModeProtectedEnvVars) /* {{{ */
-{
- char *protected_vars, *protected_var;
- char *token_buf;
- int dummy = 1;
-
- protected_vars = estrndup(new_value, new_value_length);
- zend_hash_clean(&BG(sm_protected_env_vars));
-
- protected_var = php_strtok_r(protected_vars, ", ", &token_buf);
- while (protected_var) {
- zend_hash_update(&BG(sm_protected_env_vars), protected_var, strlen(protected_var), &dummy, sizeof(int), NULL);
- protected_var = php_strtok_r(NULL, ", ", &token_buf);
- }
- efree(protected_vars);
- return SUCCESS;
-}
-/* }}} */
-
-static PHP_INI_MH(OnUpdateSafeModeAllowedEnvVars) /* {{{ */
-{
- if (BG(sm_allowed_env_vars)) {
- free(BG(sm_allowed_env_vars));
- }
- BG(sm_allowed_env_vars) = zend_strndup(new_value, new_value_length);
- return SUCCESS;
-}
-/* }}} */
-
-PHP_INI_BEGIN() /* {{{ */
- PHP_INI_ENTRY_EX("safe_mode_protected_env_vars", SAFE_MODE_PROTECTED_ENV_VARS, PHP_INI_SYSTEM, OnUpdateSafeModeProtectedEnvVars, NULL)
- PHP_INI_ENTRY_EX("safe_mode_allowed_env_vars", SAFE_MODE_ALLOWED_ENV_VARS, PHP_INI_SYSTEM, OnUpdateSafeModeAllowedEnvVars, NULL)
-PHP_INI_END()
-/* }}} */
-
static const zend_module_dep standard_deps[] = { /* {{{ */
ZEND_MOD_OPTIONAL("session")
ZEND_MOD_END
@@ -3475,8 +3450,10 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p TSRMLS_DC) /*
BG(left) = -1;
BG(user_tick_functions) = NULL;
BG(user_filter_map) = NULL;
- zend_hash_init(&BG(sm_protected_env_vars), 5, NULL, NULL, 1);
- BG(sm_allowed_env_vars) = NULL;
+ BG(serialize_lock) = 0;
+
+ memset(&BG(serialize), 0, sizeof(BG(serialize)));
+ memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
memset(&BG(url_adapt_state_ex), 0, sizeof(BG(url_adapt_state_ex)));
@@ -3492,10 +3469,6 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p TSRMLS_DC) /*
static void basic_globals_dtor(php_basic_globals *basic_globals_p TSRMLS_DC) /* {{{ */
{
- zend_hash_destroy(&BG(sm_protected_env_vars));
- if (BG(sm_allowed_env_vars)) {
- free(BG(sm_allowed_env_vars));
- }
if (BG(url_adapt_state_ex).tags) {
zend_hash_destroy(BG(url_adapt_state_ex).tags);
free(BG(url_adapt_state_ex).tags);
@@ -3576,6 +3549,8 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
REGISTER_LONG_CONSTANT("PHP_URL_PATH", PHP_URL_PATH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PHP_URL_QUERY", PHP_URL_QUERY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PHP_URL_FRAGMENT", PHP_URL_FRAGMENT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("PHP_QUERY_RFC1738", PHP_QUERY_RFC1738, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("PHP_QUERY_RFC3986", PHP_QUERY_RFC3986, CONST_CS | CONST_PERSISTENT);
#define REGISTER_MATH_CONSTANT(x) REGISTER_DOUBLE_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
REGISTER_MATH_CONSTANT(M_E);
@@ -3607,8 +3582,6 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
test_class_startup();
#endif
- REGISTER_INI_ENTRIES();
-
register_phpinfo_constants(INIT_FUNC_ARGS_PASSTHRU);
register_html_constants(INIT_FUNC_ARGS_PASSTHRU);
register_string_constants(INIT_FUNC_ARGS_PASSTHRU);
@@ -3691,8 +3664,6 @@ PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
#endif
- UNREGISTER_INI_ENTRIES();
-
PHP_MSHUTDOWN(browscap)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
PHP_MSHUTDOWN(array)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
PHP_MSHUTDOWN(assert)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
@@ -3713,6 +3684,11 @@ PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */
PHP_RINIT_FUNCTION(basic) /* {{{ */
{
memset(BG(strtok_table), 0, 256);
+
+ BG(serialize_lock) = 0;
+ memset(&BG(serialize), 0, sizeof(BG(serialize)));
+ memset(&BG(unserialize), 0, sizeof(BG(unserialize)));
+
BG(strtok_string) = NULL;
BG(strtok_zval) = NULL;
BG(strtok_last) = NULL;
@@ -3739,9 +3715,6 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
PHP_RINIT(dir)(INIT_FUNC_ARGS_PASSTHRU);
PHP_RINIT(url_scanner_ex)(INIT_FUNC_ARGS_PASSTHRU);
- /* Reset magic_quotes_runtime */
- PG(magic_quotes_runtime) = INI_BOOL("magic_quotes_runtime");
-
/* Setup default context */
FG(default_context) = NULL;
@@ -3751,8 +3724,6 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
/* Default to global filters only */
FG(stream_filters) = NULL;
- FG(wrapper_errors) = NULL;
-
return SUCCESS;
}
/* }}} */
@@ -3865,7 +3836,7 @@ PHP_NAMED_FUNCTION(php_inet_ntop)
}
if (!inet_ntop(af, address, buffer, sizeof(buffer))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "An unknown error occured");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "An unknown error occurred");
RETURN_FALSE;
}
@@ -4085,39 +4056,6 @@ PHP_FUNCTION(putenv)
}
#endif
- if (PG(safe_mode)) {
- /* Check the protected list */
- if (zend_hash_exists(&BG(sm_protected_env_vars), pe.key, pe.key_len)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Safe Mode warning: Cannot override protected environment variable '%s'", pe.key);
- efree(pe.putenv_string);
- efree(pe.key);
- RETURN_FALSE;
- }
-
- /* Check the allowed list */
- if (BG(sm_allowed_env_vars) && *BG(sm_allowed_env_vars)) {
- char *allowed_env_vars = estrdup(BG(sm_allowed_env_vars));
- char *strtok_buf = NULL;
- char *allowed_prefix = php_strtok_r(allowed_env_vars, ", ", &strtok_buf);
- zend_bool allowed = 0;
-
- while (allowed_prefix) {
- if (!strncmp(allowed_prefix, pe.key, strlen(allowed_prefix))) {
- allowed = 1;
- break;
- }
- allowed_prefix = php_strtok_r(NULL, ", ", &strtok_buf);
- }
- efree(allowed_env_vars);
- if (!allowed) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Safe Mode warning: Cannot set environment variable '%s' - it's not in the allowed list", pe.key);
- efree(pe.putenv_string);
- efree(pe.key);
- RETURN_FALSE;
- }
- }
- }
-
zend_hash_del(&BG(putenv_ht), pe.key, pe.key_len+1);
/* find previous value */
@@ -4574,7 +4512,7 @@ PHP_FUNCTION(get_current_user)
return;
}
- RETURN_STRING(php_get_current_user(), 1);
+ RETURN_STRING(php_get_current_user(TSRMLS_C), 1);
}
/* }}} */
@@ -4630,7 +4568,7 @@ PHP_FUNCTION(get_cfg_var)
/* }}} */
/* {{{ proto bool set_magic_quotes_runtime(int new_setting)
- Set the current active configuration setting of magic_quotes_runtime and return previous */
+ magic_quotes_runtime is not supported anymore */
PHP_FUNCTION(set_magic_quotes_runtime)
{
zend_bool new_setting;
@@ -4638,9 +4576,11 @@ PHP_FUNCTION(set_magic_quotes_runtime)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &new_setting) == FAILURE) {
return;
}
-
- PG(magic_quotes_runtime) = new_setting;
- RETURN_TRUE;
+
+ if (new_setting) {
+ php_error_docref(NULL TSRMLS_CC, E_CORE_ERROR, "magic_quotes_runtime is not supported anymore");
+ }
+ RETURN_FALSE;
}
/* }}} */
@@ -4648,7 +4588,10 @@ PHP_FUNCTION(set_magic_quotes_runtime)
Get the current active configuration setting of magic_quotes_runtime */
PHP_FUNCTION(get_magic_quotes_runtime)
{
- RETURN_LONG(PG(magic_quotes_runtime));
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ RETURN_FALSE;
}
/* }}} */
@@ -4656,7 +4599,10 @@ PHP_FUNCTION(get_magic_quotes_runtime)
Get the current active configuration setting of magic_quotes_gpc */
PHP_FUNCTION(get_magic_quotes_gpc)
{
- RETURN_LONG(PG(magic_quotes_gpc));
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ RETURN_FALSE;
}
/* }}} */
@@ -4683,7 +4629,7 @@ PHP_FUNCTION(error_log)
int opt_err = 0, argc = ZEND_NUM_ARGS();
long erropt = 0;
- if (zend_parse_parameters(argc TSRMLS_CC, "s|lss", &message, &message_len, &erropt, &opt, &opt_len, &headers, &headers_len) == FAILURE) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "s|lps", &message, &message_len, &erropt, &opt, &opt_len, &headers, &headers_len) == FAILURE) {
return;
}
@@ -4691,12 +4637,6 @@ PHP_FUNCTION(error_log)
opt_err = erropt;
}
- if (opt_err == 3 && opt) {
- if (strlen(opt) != opt_len) {
- RETURN_FALSE;
- }
- }
-
if (_php_error_log_ex(opt_err, message, message_len, opt, headers TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
@@ -4730,7 +4670,7 @@ PHPAPI int _php_error_log_ex(int opt_err, char *message, int message_len, char *
break;
case 3: /*save to a file */
- stream = php_stream_open_wrapper(opt, "a", IGNORE_URL_WIN | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(opt, "a", IGNORE_URL_WIN | REPORT_ERRORS, NULL);
if (!stream) {
return FAILURE;
}
@@ -4740,7 +4680,7 @@ PHPAPI int _php_error_log_ex(int opt_err, char *message, int message_len, char *
case 4: /* send to SAPI */
if (sapi_module.log_message) {
- sapi_module.log_message(message);
+ sapi_module.log_message(message TSRMLS_CC);
} else {
return FAILURE;
}
@@ -5159,6 +5099,38 @@ PHP_FUNCTION(register_shutdown_function)
}
/* }}} */
+PHPAPI zend_bool register_user_shutdown_function(char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry TSRMLS_DC) /* {{{ */
+{
+ if (!BG(user_shutdown_function_names)) {
+ ALLOC_HASHTABLE(BG(user_shutdown_function_names));
+ zend_hash_init(BG(user_shutdown_function_names), 0, NULL, (void (*)(void *)) user_shutdown_function_dtor, 0);
+ }
+
+ return zend_hash_update(BG(user_shutdown_function_names), function_name, function_len, shutdown_function_entry, sizeof(php_shutdown_function_entry), NULL) != FAILURE;
+}
+/* }}} */
+
+PHPAPI zend_bool remove_user_shutdown_function(char *function_name, size_t function_len TSRMLS_DC) /* {{{ */
+{
+ if (BG(user_shutdown_function_names)) {
+ return zend_hash_del_key_or_index(BG(user_shutdown_function_names), function_name, function_len, 0, HASH_DEL_KEY) != FAILURE;
+ }
+
+ return 0;
+}
+/* }}} */
+
+PHPAPI zend_bool append_user_shutdown_function(php_shutdown_function_entry shutdown_function_entry TSRMLS_DC) /* {{{ */
+{
+ if (!BG(user_shutdown_function_names)) {
+ ALLOC_HASHTABLE(BG(user_shutdown_function_names));
+ zend_hash_init(BG(user_shutdown_function_names), 0, NULL, (void (*)(void *)) user_shutdown_function_dtor, 0);
+ }
+
+ return zend_hash_next_index_insert(BG(user_shutdown_function_names), &shutdown_function_entry, sizeof(php_shutdown_function_entry), NULL) != FAILURE;
+}
+/* }}} */
+
ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini) /* {{{ */
{
syntax_highlighter_ini->highlight_comment = INI_STR("highlight.comment");
@@ -5174,15 +5146,11 @@ ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highl
PHP_FUNCTION(highlight_file)
{
char *filename;
- int filename_len;
+ int filename_len, ret;
zend_syntax_highlighter_ini syntax_highlighter_ini;
zend_bool i = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &filename_len, &i) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &filename, &filename_len, &i) == FAILURE) {
RETURN_FALSE;
}
@@ -5190,37 +5158,24 @@ PHP_FUNCTION(highlight_file)
RETURN_FALSE;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (i) {
- php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
+ php_output_start_default(TSRMLS_C);
}
php_get_highlight_struct(&syntax_highlighter_ini);
- if (highlight_file(filename, &syntax_highlighter_ini TSRMLS_CC) == FAILURE) {
- if (i) {
- int res = php_ob_get_buffer(return_value TSRMLS_CC);
+ ret = highlight_file(filename, &syntax_highlighter_ini TSRMLS_CC);
- /* flush the buffer only if there is something to flush */
- if (res == SUCCESS && Z_STRLEN_P(return_value) > 0) {
- php_end_ob_buffer (1, 0 TSRMLS_CC);
- zval_dtor(return_value);
- } else {
- php_end_ob_buffer (0, 0 TSRMLS_CC);
- if (res == SUCCESS) {
- zval_dtor(return_value);
- }
- }
+ if (ret == FAILURE) {
+ if (i) {
+ php_output_end(TSRMLS_C);
}
RETURN_FALSE;
}
if (i) {
- php_ob_get_buffer (return_value TSRMLS_CC);
- php_end_ob_buffer (0, 0 TSRMLS_CC);
+ php_output_get_contents(return_value TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
} else {
RETURN_TRUE;
}
@@ -5236,33 +5191,30 @@ PHP_FUNCTION(php_strip_whitespace)
zend_lex_state original_lex_state;
zend_file_handle file_handle = {0};
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
RETURN_FALSE;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
+ php_output_start_default(TSRMLS_C);
file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.filename = filename;
file_handle.free_filename = 0;
file_handle.opened_path = NULL;
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
- if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) {
+ if (open_file_for_scanning(&file_handle TSRMLS_CC) == FAILURE) {
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ php_output_end(TSRMLS_C);
RETURN_EMPTY_STRING();
}
- php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
-
zend_strip(TSRMLS_C);
zend_destroy_file_handle(&file_handle TSRMLS_CC);
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
- php_ob_get_buffer(return_value TSRMLS_CC);
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ php_output_get_contents(return_value TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
}
/* }}} */
@@ -5282,7 +5234,7 @@ PHP_FUNCTION(highlight_string)
convert_to_string_ex(expr);
if (i) {
- php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
+ php_output_start_default(TSRMLS_C);
}
EG(error_reporting) = E_ERROR;
@@ -5295,7 +5247,7 @@ PHP_FUNCTION(highlight_string)
efree(hicompiled_string_description);
EG(error_reporting) = old_error_reporting;
if (i) {
- php_end_ob_buffer (1, 0 TSRMLS_CC);
+ php_output_end(TSRMLS_C);
}
RETURN_FALSE;
}
@@ -5304,8 +5256,8 @@ PHP_FUNCTION(highlight_string)
EG(error_reporting) = old_error_reporting;
if (i) {
- php_ob_get_buffer (return_value TSRMLS_CC);
- php_end_ob_buffer (0, 0 TSRMLS_CC);
+ php_output_get_contents(return_value TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
} else {
RETURN_TRUE;
}
@@ -5440,18 +5392,14 @@ PHP_FUNCTION(ini_set)
}
#define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini))
- /* safe_mode & basedir check */
- if (PG(safe_mode) || PG(open_basedir)) {
+ /* open basedir check */
+ if (PG(open_basedir)) {
if (_CHECK_PATH(varname, varname_len, "error_log") ||
_CHECK_PATH(varname, varname_len, "java.class.path") ||
_CHECK_PATH(varname, varname_len, "java.home") ||
_CHECK_PATH(varname, varname_len, "mail.log") ||
_CHECK_PATH(varname, varname_len, "java.library.path") ||
_CHECK_PATH(varname, varname_len, "vpopmail.directory")) {
- if (PG(safe_mode) && (!php_checkuid(new_value, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- zval_dtor(return_value);
- RETURN_FALSE;
- }
if (php_check_open_basedir(new_value TSRMLS_CC)) {
zval_dtor(return_value);
RETURN_FALSE;
@@ -5459,17 +5407,6 @@ PHP_FUNCTION(ini_set)
}
}
- /* checks that ensure the user does not overwrite certain ini settings when safe_mode is enabled */
- if (PG(safe_mode)) {
- if (!strncmp("max_execution_time", varname, sizeof("max_execution_time")) ||
- !strncmp("memory_limit", varname, sizeof("memory_limit")) ||
- !strncmp("child_terminate", varname, sizeof("child_terminate"))
- ) {
- zval_dtor(return_value);
- RETURN_FALSE;
- }
- }
-
if (zend_alter_ini_entry_ex(varname, varname_len + 1, new_value, new_value_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC) == FAILURE) {
zval_dtor(return_value);
RETURN_FALSE;
@@ -5504,11 +5441,6 @@ PHP_FUNCTION(set_include_path)
return;
}
- /* No nulls allowed in paths */
- if (strlen(new_value) != new_value_len) {
- RETURN_FALSE;
- }
-
old_value = zend_ini_string("include_path", sizeof("include_path"), 0);
/* copy to return here, because alter might free it! */
if (old_value) {
@@ -5567,14 +5499,14 @@ PHP_FUNCTION(print_r)
}
if (do_return) {
- php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
+ php_output_start_default(TSRMLS_C);
}
zend_print_zval_r(var, 0 TSRMLS_CC);
if (do_return) {
- php_ob_get_buffer (return_value TSRMLS_CC);
- php_end_ob_buffer (0, 0 TSRMLS_CC);
+ php_output_get_contents(return_value TSRMLS_CC);
+ php_output_discard(TSRMLS_C);
} else {
RETURN_TRUE;
}
@@ -5819,10 +5751,6 @@ PHP_FUNCTION(is_uploaded_file)
return;
}
- if (strlen(path) != path_len) {
- RETURN_FALSE;
- }
-
if (zend_hash_exists(SG(rfc1867_uploaded_files), path, path_len + 1)) {
RETURN_TRUE;
} else {
@@ -5855,22 +5783,10 @@ PHP_FUNCTION(move_uploaded_file)
RETURN_FALSE;
}
- if (PG(safe_mode) && (!php_checkuid(new_path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(new_path TSRMLS_CC)) {
RETURN_FALSE;
}
- if (strlen(path) != path_len) {
- RETURN_FALSE;
- }
-
- if (strlen(new_path) != new_path_len) {
- RETURN_FALSE;
- }
-
if (VCWD_RENAME(path, new_path) == 0) {
successful = 1;
#ifndef PHP_WIN32
@@ -6004,7 +5920,7 @@ PHP_FUNCTION(parse_ini_file)
zend_file_handle fh;
zend_ini_parser_cb_t ini_parser_cb;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &filename, &filename_len, &process_sections, &scanner_mode) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|bl", &filename, &filename_len, &process_sections, &scanner_mode) == FAILURE) {
RETURN_FALSE;
}
@@ -6013,10 +5929,6 @@ PHP_FUNCTION(parse_ini_file)
RETURN_FALSE;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
/* Set callback function */
if (process_sections) {
BG(active_ini_file_section) = NULL;
@@ -6093,104 +6005,6 @@ PHP_FUNCTION(config_get_hash) /* {{{ */
/* }}} */
#endif
-static int copy_request_variable(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
-{
- zval *prefix, new_key;
- int prefix_len;
- zval **var = (zval **) pDest;
-
- if (num_args != 1) {
- return 0;
- }
-
- prefix = va_arg(args, zval *);
- prefix_len = Z_STRLEN_P(prefix);
-
- if (!prefix_len && !hash_key->nKeyLength) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Numeric key detected - possible security hazard");
- return 0;
- }
-
- if (hash_key->nKeyLength) {
- php_prefix_varname(&new_key, prefix, hash_key->arKey, hash_key->nKeyLength - 1, 0 TSRMLS_CC);
- } else {
- zval num;
-
- ZVAL_LONG(&num, hash_key->h);
- convert_to_string(&num);
- php_prefix_varname(&new_key, prefix, Z_STRVAL(num), Z_STRLEN(num), 0 TSRMLS_CC);
- zval_dtor(&num);
- }
-
- if (php_varname_check(Z_STRVAL(new_key), Z_STRLEN(new_key), 0 TSRMLS_CC) == FAILURE) {
- zval_dtor(&new_key);
- return 0;
- }
-
- zend_delete_global_variable(Z_STRVAL(new_key), Z_STRLEN(new_key) TSRMLS_CC);
- ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), Z_STRVAL(new_key), Z_STRLEN(new_key) + 1, *var, Z_REFCOUNT_PP(var) + 1, 0);
-
- zval_dtor(&new_key);
- return 0;
-}
-/* }}} */
-
-/* {{{ proto bool import_request_variables(string types [, string prefix])
- Import GET/POST/Cookie variables into the global scope */
-PHP_FUNCTION(import_request_variables)
-{
- char *types;
- int types_len;
- zval *prefix = NULL;
- char *p;
- zend_bool ok = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &types, &types_len, &prefix) == FAILURE) {
- return;
- }
-
- if (ZEND_NUM_ARGS() > 1) {
- convert_to_string(prefix);
-
- if (Z_STRLEN_P(prefix) == 0) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "No prefix specified - possible security hazard");
- }
- } else {
- MAKE_STD_ZVAL(prefix);
- ZVAL_EMPTY_STRING(prefix);
- }
-
- for (p = types; p && *p; p++) {
- switch (*p) {
-
- case 'g':
- case 'G':
- zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC, (apply_func_args_t) copy_request_variable, 1, prefix);
- ok = 1;
- break;
-
- case 'p':
- case 'P':
- zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC, (apply_func_args_t) copy_request_variable, 1, prefix);
- zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_FILES]) TSRMLS_CC, (apply_func_args_t) copy_request_variable, 1, prefix);
- ok = 1;
- break;
-
- case 'c':
- case 'C':
- zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC, (apply_func_args_t) copy_request_variable, 1, prefix);
- ok = 1;
- break;
- }
- }
-
- if (ZEND_NUM_ARGS() < 2) {
- zval_ptr_dtor(&prefix);
- }
- RETURN_BOOL(ok);
-}
-/* }}} */
-
#ifdef HAVE_GETLOADAVG
/* {{{ proto array sys_getloadavg()
*/
@@ -6198,6 +6012,10 @@ PHP_FUNCTION(sys_getloadavg)
{
double load[3];
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
if (getloadavg(load, 3) == -1) {
RETURN_FALSE;
} else {
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index bbd2c3942c..04fea70051 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -69,13 +69,13 @@ PHP_FUNCTION(getopt);
PHP_FUNCTION(get_current_user);
PHP_FUNCTION(set_time_limit);
+PHP_FUNCTION(header_register_callback);
+
PHP_FUNCTION(get_cfg_var);
PHP_FUNCTION(set_magic_quotes_runtime);
PHP_FUNCTION(get_magic_quotes_runtime);
PHP_FUNCTION(get_magic_quotes_gpc);
-PHP_FUNCTION(import_request_variables);
-
PHP_FUNCTION(error_log);
PHP_FUNCTION(error_get_last);
@@ -178,9 +178,6 @@ typedef struct _php_basic_globals {
zend_llist *user_tick_functions;
zval *active_ini_file_section;
-
- HashTable sm_protected_env_vars;
- char *sm_allowed_env_vars;
/* pageinfo.c */
long page_uid;
@@ -203,11 +200,19 @@ typedef struct _php_basic_globals {
zend_bool mt_rand_is_seeded; /* Whether mt_rand() has been seeded */
/* syslog.c */
- int syslog_started;
char *syslog_device;
/* var.c */
zend_class_entry *incomplete_class;
+ unsigned serialize_lock; /* whether to use the locally supplied var_hash instead (__sleep/__wakeup) */
+ struct {
+ void *var_hash;
+ unsigned level;
+ } serialize;
+ struct {
+ void *var_hash;
+ unsigned level;
+ } unserialize;
/* url_scanner_ex.re */
url_adapt_state_ex_t url_adapt_state_ex;
@@ -244,12 +249,16 @@ typedef struct {
} putenv_entry;
#endif
-/* Values are comma-delimited
- */
-#define SAFE_MODE_PROTECTED_ENV_VARS "LD_LIBRARY_PATH"
-#define SAFE_MODE_ALLOWED_ENV_VARS "PHP_"
-
PHPAPI double php_get_nan(void);
PHPAPI double php_get_inf(void);
+typedef struct _php_shutdown_function_entry {
+ zval **arguments;
+ int arg_count;
+} php_shutdown_function_entry;
+
+PHPAPI extern zend_bool register_user_shutdown_function(char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry TSRMLS_DC);
+PHPAPI extern zend_bool remove_user_shutdown_function(char *function_name, size_t function_len TSRMLS_DC);
+PHPAPI extern zend_bool append_user_shutdown_function(php_shutdown_function_entry shutdown_function_entry TSRMLS_DC);
+
#endif /* BASIC_FUNCTIONS_H */
diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c
index b0f8d642c0..ae5e90cf9b 100644
--- a/ext/standard/browscap.c
+++ b/ext/standard/browscap.c
@@ -333,10 +333,10 @@ PHP_INI_MH(OnChangeBrowscap)
PHP_MINIT_FUNCTION(browscap) /* {{{ */
{
char *browscap = INI_STR("browscap");
-
+
#ifdef ZTS
ts_allocate_id(&browscap_globals_id, sizeof(browser_data),
- (ts_allocate_ctor)browscap_globals_ctor, NULL);
+ browscap_globals_ctor, NULL);
#endif
/* ctor call not really needed for non-ZTS */
diff --git a/ext/standard/config.m4 b/ext/standard/config.m4
index e28c351b5b..c33ae1e05c 100644
--- a/ext/standard/config.m4
+++ b/ext/standard/config.m4
@@ -1,7 +1,5 @@
dnl $Id$ -*- autoconf -*-
-divert(3)dnl
-
dnl
dnl Check if flush should be called explicitly after buffered io
dnl
@@ -342,8 +340,6 @@ dnl
AC_CHECK_FUNCS(getcwd getwd asinh acosh atanh log1p hypot glob strfmon nice fpclass isinf isnan mempcpy strpncpy)
AC_FUNC_FNMATCH
-divert(5)dnl
-
dnl
dnl Check if there is a support means of creating a new process
dnl and defining which handles it receives
diff --git a/ext/standard/credits.c b/ext/standard/credits.c
index 5070d57934..e87cdcad8b 100644
--- a/ext/standard/credits.c
+++ b/ext/standard/credits.c
@@ -68,6 +68,7 @@ PHPAPI void php_print_credits(int flag TSRMLS_DC) /* {{{ */
CREDIT_LINE("Server API (SAPI) Abstraction Layer", "Andi Gutmans, Shane Caraveo, Zeev Suraski");
CREDIT_LINE("Streams Abstraction Layer", "Wez Furlong, Sara Golemon");
CREDIT_LINE("PHP Data Objects Layer", "Wez Furlong, Marcus Boerger, Sterling Hughes, George Schlossnagle, Ilia Alshanetsky");
+ CREDIT_LINE("Output Handler", "Zeev Suraski, Thies C. Arntzen, Marcus Boerger, Michael Wallner");
php_info_print_table_end();
}
diff --git a/ext/standard/credits_ext.h b/ext/standard/credits_ext.h
index ec233a2738..7bdb41e608 100644
--- a/ext/standard/credits_ext.h
+++ b/ext/standard/credits_ext.h
@@ -17,8 +17,8 @@ CREDIT_LINE("COM and .Net", "Wez Furlong");
CREDIT_LINE("ctype", "Hartmut Holzgraefe");
CREDIT_LINE("cURL", "Sterling Hughes");
CREDIT_LINE("Date/Time Support", "Derick Rethans");
-CREDIT_LINE("DBA", "Sascha Schumann, Marcus Boerger");
CREDIT_LINE("DB-LIB (MS SQL, Sybase)", "Wez Furlong, Frank M. Kromann");
+CREDIT_LINE("DBA", "Sascha Schumann, Marcus Boerger");
CREDIT_LINE("DOM", "Christian Stocker, Rob Richards, Marcus Boerger");
CREDIT_LINE("enchant", "Pierre-Alain Joye, Ilia Alshanetsky");
CREDIT_LINE("ereg", "Rasmus Lerdorf, Jim Winstead, Jaakko Hyvätti");
@@ -41,9 +41,9 @@ CREDIT_LINE("mcrypt", "Sascha Schumann, Derick Rethans");
CREDIT_LINE("MS SQL", "Frank M. Kromann");
CREDIT_LINE("Multibyte String Functions", "Tsukada Takuya, Rui Hirokawa");
CREDIT_LINE("MySQL driver for PDO", "George Schlossnagle, Wez Furlong, Ilia Alshanetsky, Johannes Schlueter");
-CREDIT_LINE("MySQLi", "Zak Greant, Georg Richter, Andrey Hristov, Ulf Wendel");
-CREDIT_LINE("MySQLnd", "Georg Richter, Andrey Hristov, Ulf Wendel");
CREDIT_LINE("MySQL", "Zeev Suraski, Zak Greant, Georg Richter");
+CREDIT_LINE("MySQLi", "Zak Greant, Georg Richter, Andrey Hristov, Ulf Wendel");
+CREDIT_LINE("MySQLnd", "Andrey Hristov, Ulf Wendel, Georg Richter");
CREDIT_LINE("OCI8", "Stig Bakken, Thies C. Arntzen, Andy Sautins, David Benson, Maxim Maletsky, Harald Radi, Antony Dovgal, Andi Gutmans, Wez Furlong, Christopher Jones, Oracle Corporation");
CREDIT_LINE("ODBC driver for PDO", "Wez Furlong");
CREDIT_LINE("ODBC", "Stig Bakken, Andreas Karajannis, Frank M. Kromann, Daniel R. Kalowsky");
@@ -64,13 +64,12 @@ CREDIT_LINE("Reflection", "Marcus Boerger, Timm Friebe, George Schlossnagle, And
CREDIT_LINE("Sessions", "Sascha Schumann, Andrei Zmievski");
CREDIT_LINE("Shared Memory Operations", "Slava Poliakov, Ilia Alshanetsky");
CREDIT_LINE("SimpleXML", "Sterling Hughes, Marcus Boerger, Rob Richards");
-CREDIT_LINE("SNMP", "Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne");
+CREDIT_LINE("SNMP", "Rasmus Lerdorf, Harrie Hazewinkel, Mike Jackson, Steven Lawrance, Johann Hanne, Boris Lytochkin");
CREDIT_LINE("SOAP", "Brad Lafountain, Shane Caraveo, Dmitry Stogov");
CREDIT_LINE("Sockets", "Chris Vandomelen, Sterling Hughes, Daniel Beulshausen, Jason Greene");
CREDIT_LINE("SPL", "Marcus Boerger, Etienne Kneuss");
-CREDIT_LINE("SQLite3", "Scott MacVicar, Ilia Alshanetsky");
CREDIT_LINE("SQLite 3.x driver for PDO", "Wez Furlong");
-CREDIT_LINE("SQLite", "Wez Furlong, Tal Peer, Marcus Boerger, Ilia Alshanetsky");
+CREDIT_LINE("SQLite3", "Scott MacVicar, Ilia Alshanetsky, Brad Dewar");
CREDIT_LINE("Sybase-CT", "Zeev Suraski, Tom May, Timm Friebe");
CREDIT_LINE("System V Message based IPC", "Wez Furlong");
CREDIT_LINE("System V Semaphores", "Tom May");
@@ -78,10 +77,10 @@ CREDIT_LINE("System V Shared Memory", "Christian Cartus");
CREDIT_LINE("tidy", "John Coggeshall, Ilia Alshanetsky");
CREDIT_LINE("tokenizer", "Andrei Zmievski, Johannes Schlueter");
CREDIT_LINE("WDDX", "Andrei Zmievski");
+CREDIT_LINE("XML", "Stig Bakken, Thies C. Arntzen, Sterling Hughes");
CREDIT_LINE("XMLReader", "Rob Richards");
CREDIT_LINE("xmlrpc", "Dan Libby");
-CREDIT_LINE("XML", "Stig Bakken, Thies C. Arntzen, Sterling Hughes");
CREDIT_LINE("XMLWriter", "Rob Richards, Pierre-Alain Joye");
CREDIT_LINE("XSL", "Christian Stocker, Rob Richards");
CREDIT_LINE("Zip", "Pierre-Alain Joye");
-CREDIT_LINE("Zlib", "Rasmus Lerdorf, Stefan Roehrich, Zeev Suraski, Jade Nicoletti");
+CREDIT_LINE("Zlib", "Rasmus Lerdorf, Stefan Roehrich, Zeev Suraski, Jade Nicoletti, Michael Wallner");
diff --git a/ext/standard/crypt_sha256.c b/ext/standard/crypt_sha256.c
index 0923aae308..d334e3d477 100644
--- a/ext/standard/crypt_sha256.c
+++ b/ext/standard/crypt_sha256.c
@@ -471,7 +471,7 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b
sha256_init_ctx(&alt_ctx);
/* For every character in the password add the entire password. */
- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) {
+ for (cnt = 0; cnt < (size_t) (16 + alt_result[0]); ++cnt) {
sha256_process_bytes(salt, salt_len, &alt_ctx);
}
diff --git a/ext/standard/crypt_sha512.c b/ext/standard/crypt_sha512.c
index cbc97a328c..0955532131 100644
--- a/ext/standard/crypt_sha512.c
+++ b/ext/standard/crypt_sha512.c
@@ -506,7 +506,7 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen)
sha512_init_ctx(&alt_ctx);
/* For every character in the password add the entire password. */
- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) {
+ for (cnt = 0; cnt < (size_t) (16 + alt_result[0]); ++cnt) {
sha512_process_bytes(salt, salt_len, &alt_ctx);
}
diff --git a/ext/standard/cyr_convert.c b/ext/standard/cyr_convert.c
index d2b3e4e072..d4b282ecd7 100644
--- a/ext/standard/cyr_convert.c
+++ b/ext/standard/cyr_convert.c
@@ -282,7 +282,7 @@ PHP_FUNCTION(convert_cyr_string)
str = (unsigned char*) estrndup(input, input_len);
php_convert_cyr_string(str, input_len, fr_cs[0], to_cs[0] TSRMLS_CC);
- RETVAL_STRING((char *)str, 0)
+ RETVAL_STRING((char *)str, 0);
}
/* }}} */
diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c
index ccf794257e..96de8e128c 100644
--- a/ext/standard/datetime.c
+++ b/ext/standard/datetime.c
@@ -64,21 +64,12 @@ PHPAPI char *php_std_date(time_t t TSRMLS_DC)
return str;
}
- if (PG(y2k_compliance)) {
- snprintf(str, 80, "%s, %02d %s %04d %02d:%02d:%02d GMT",
- day_short_names[tm1->tm_wday],
- tm1->tm_mday,
- mon_short_names[tm1->tm_mon],
- tm1->tm_year + 1900,
- tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
- } else {
- snprintf(str, 80, "%s, %02d-%s-%02d %02d:%02d:%02d GMT",
- day_full_names[tm1->tm_wday],
- tm1->tm_mday,
- mon_short_names[tm1->tm_mon],
- ((tm1->tm_year) % 100),
- tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
- }
+ snprintf(str, 80, "%s, %02d %s %04d %02d:%02d:%02d GMT",
+ day_short_names[tm1->tm_wday],
+ tm1->tm_mday,
+ mon_short_names[tm1->tm_mon],
+ tm1->tm_year + 1900,
+ tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
str[79] = 0;
return (str);
diff --git a/ext/standard/dir.c b/ext/standard/dir.c
index 37c3bc88c6..d921f7c3f5 100644
--- a/ext/standard/dir.c
+++ b/ext/standard/dir.c
@@ -148,6 +148,10 @@ PHP_MINIT_FUNCTION(dir)
pathsep_str[1] = '\0';
REGISTER_STRING_CONSTANT("PATH_SEPARATOR", pathsep_str, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SCANDIR_SORT_ASCENDING", PHP_SCANDIR_SORT_ASCENDING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SCANDIR_SORT_DESCENDING", PHP_SCANDIR_SORT_DESCENDING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SCANDIR_SORT_NONE", PHP_SCANDIR_SORT_NONE, CONST_CS | CONST_PERSISTENT);
+
#ifdef HAVE_GLOB
#ifdef GLOB_BRACE
@@ -221,7 +225,7 @@ static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
context = php_stream_context_from_zval(zcontext, 0);
- dirp = php_stream_opendir(dirname, ENFORCE_SAFE_MODE|REPORT_ERRORS, context);
+ dirp = php_stream_opendir(dirname, REPORT_ERRORS, context);
if (dirp == NULL) {
RETURN_FALSE;
@@ -321,15 +325,11 @@ PHP_FUNCTION(chdir)
char *str;
int ret, str_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &str, &str_len) == FAILURE) {
RETURN_FALSE;
}
- if (strlen(str) != str_len) {
- RETURN_FALSE;
- }
-
- if ((PG(safe_mode) && !php_checkuid(str, NULL, CHECKUID_CHECK_FILE_AND_DIR)) || php_check_open_basedir(str TSRMLS_CC)) {
+ if (php_check_open_basedir(str TSRMLS_CC)) {
RETURN_FALSE;
}
ret = VCWD_CHDIR(str);
@@ -436,14 +436,10 @@ PHP_FUNCTION(glob)
int ret;
zend_bool basedir_limit = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &pattern, &pattern_len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &pattern, &pattern_len, &flags) == FAILURE) {
return;
}
- if (strlen(pattern) != pattern_len) {
- RETURN_FALSE;
- }
-
if (pattern_len >= MAXPATHLEN) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
RETURN_FALSE;
@@ -495,7 +491,7 @@ PHP_FUNCTION(glob)
/* now catch the FreeBSD style of "no matches" */
if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
no_results:
- if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
struct stat s;
if (0 != VCWD_STAT(pattern, &s) || S_IFDIR != (s.st_mode & S_IFMT)) {
@@ -508,11 +504,8 @@ no_results:
array_init(return_value);
for (n = 0; n < globbuf.gl_pathc; n++) {
- if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
- if (PG(safe_mode) && (!php_checkuid_ex(globbuf.gl_pathv[n], NULL, CHECKUID_CHECK_FILE_AND_DIR, CHECKUID_NO_ERRORS))) {
- basedir_limit = 1;
- continue;
- } else if (php_check_open_basedir_ex(globbuf.gl_pathv[n], 0 TSRMLS_CC)) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
+ if (php_check_open_basedir_ex(globbuf.gl_pathv[n], 0 TSRMLS_CC)) {
basedir_limit = 1;
continue;
}
@@ -561,14 +554,10 @@ PHP_FUNCTION(scandir)
zval *zcontext = NULL;
php_stream_context *context = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &dirn, &dirn_len, &flags, &zcontext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lr", &dirn, &dirn_len, &flags, &zcontext) == FAILURE) {
return;
}
- if (strlen(dirn) != dirn_len) {
- RETURN_FALSE;
- }
-
if (dirn_len < 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Directory name cannot be empty");
RETURN_FALSE;
@@ -578,8 +567,10 @@ PHP_FUNCTION(scandir)
context = php_stream_context_from_zval(zcontext, 0);
}
- if (!flags) {
+ if (flags == PHP_SCANDIR_SORT_ASCENDING) {
n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasort);
+ } else if (flags == PHP_SCANDIR_SORT_NONE) {
+ n = php_stream_scandir(dirn, &namelist, context, NULL);
} else {
n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasortr);
}
diff --git a/ext/standard/dl.c b/ext/standard/dl.c
index 15efb9b5e2..2251ed0e0f 100644
--- a/ext/standard/dl.c
+++ b/ext/standard/dl.c
@@ -63,9 +63,6 @@ PHPAPI PHP_FUNCTION(dl)
if (!PG(enable_dl)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extensions aren't enabled");
RETURN_FALSE;
- } else if (PG(safe_mode)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extensions aren't allowed when running in Safe Mode");
- RETURN_FALSE;
}
if (filename_len >= MAXPATHLEN) {
diff --git a/ext/standard/dns.c b/ext/standard/dns.c
index 939de2e635..53483ff58b 100644
--- a/ext/standard/dns.c
+++ b/ext/standard/dns.c
@@ -413,7 +413,7 @@ PHP_FUNCTION(dns_check_record)
#if HAVE_FULL_DNS_FUNCS
/* {{{ php_parserr */
-static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, zval **subarray)
+static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, int raw, zval **subarray)
{
u_short type, class, dlen;
u_long ttl;
@@ -449,6 +449,16 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
array_init(*subarray);
add_assoc_string(*subarray, "host", name, 1);
+ add_assoc_string(*subarray, "class", "IN", 1);
+ add_assoc_long(*subarray, "ttl", ttl);
+
+ if (raw) {
+ add_assoc_long(*subarray, "type", type);
+ add_assoc_stringl(*subarray, "data", (char*) cp, (uint) dlen, 1);
+ cp += dlen;
+ return cp;
+ }
+
switch (type) {
case DNS_T_A:
add_assoc_string(*subarray, "type", "A", 1);
@@ -689,12 +699,12 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
add_assoc_string(*subarray, "replacement", name, 1);
break;
default:
+ zval_ptr_dtor(subarray);
+ *subarray = NULL;
cp += dlen;
+ break;
}
- add_assoc_string(*subarray, "class", "IN", 1);
- add_assoc_long(*subarray, "ttl", ttl);
-
return cp;
}
/* }}} */
@@ -721,8 +731,10 @@ PHP_FUNCTION(dns_get_record)
u_char *cp = NULL, *end = NULL;
int n, qd, an, ns = 0, ar = 0;
int type, first_query = 1, store_results = 1;
+ zend_bool raw = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lzz", &hostname, &hostname_len, &type_param, &authns, &addtl) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz!z!b",
+ &hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
return;
}
@@ -735,9 +747,17 @@ PHP_FUNCTION(dns_get_record)
array_init(addtl);
}
- if (type_param & ~PHP_DNS_ALL && type_param != PHP_DNS_ANY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
- RETURN_FALSE;
+ if (!raw) {
+ if ((type_param & ~PHP_DNS_ALL) && (type_param != PHP_DNS_ANY)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
+ RETURN_FALSE;
+ }
+ } else {
+ if ((type_param < 1) || (type_param > 0xFFFF)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Numeric DNS record type must be between 1 and 65535, '%ld' given", type_param);
+ RETURN_FALSE;
+ }
}
/* Initialize the return array */
@@ -748,13 +768,29 @@ PHP_FUNCTION(dns_get_record)
* store_results is used to skip storing the results retrieved in step
* NUMTYPES+1 when results were already fetched.
* - In case of PHP_DNS_ANY we use the directly fetch DNS_T_ANY. (step NUMTYPES+1 )
+ * - In case of raw mode, we query only the requestd type instead of looping type by type
+ * before going with the additional info stuff.
*/
- for (type = (type_param == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
+
+ if (raw) {
+ type = -1;
+ } else if (type_param == PHP_DNS_ANY) {
+ type = PHP_DNS_NUM_TYPES + 1;
+ } else {
+ type = 0;
+ }
+
+ for ( ;
type < (addtl ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query;
type++
) {
first_query = 0;
switch (type) {
+ case -1: /* raw */
+ type_to_fetch = type_param;
+ /* skip over the rest and go directly to additional records */
+ type = PHP_DNS_NUM_TYPES - 1;
+ break;
case 0:
type_to_fetch = type_param&PHP_DNS_A ? DNS_T_A : 0;
break;
@@ -848,7 +884,7 @@ PHP_FUNCTION(dns_get_record)
while (an-- && cp && cp < end) {
zval *retval;
- cp = php_parserr(cp, &answer, type_to_fetch, store_results, &retval);
+ cp = php_parserr(cp, &answer, type_to_fetch, store_results, raw, &retval);
if (retval != NULL && store_results) {
add_next_index_zval(return_value, retval);
}
@@ -861,7 +897,7 @@ PHP_FUNCTION(dns_get_record)
while (ns-- > 0 && cp && cp < end) {
zval *retval = NULL;
- cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, &retval);
+ cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, raw, &retval);
if (retval != NULL) {
add_next_index_zval(authns, retval);
}
@@ -873,7 +909,7 @@ PHP_FUNCTION(dns_get_record)
while (ar-- > 0 && cp && cp < end) {
zval *retval = NULL;
- cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval);
+ cp = php_parserr(cp, &answer, DNS_T_ANY, 1, raw, &retval);
if (retval != NULL) {
add_next_index_zval(addtl, retval);
}
diff --git a/ext/standard/dns_win32.c b/ext/standard/dns_win32.c
index e20b19d0ac..2dbf3e2e1d 100644
--- a/ext/standard/dns_win32.c
+++ b/ext/standard/dns_win32.c
@@ -138,7 +138,7 @@ PHP_FUNCTION(dns_check_record)
/* }}} */
/* {{{ php_parserr */
-static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **subarray)
+static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, int raw, zval **subarray)
{
int type;
u_long ttl;
@@ -158,6 +158,15 @@ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **s
array_init(*subarray);
add_assoc_string(*subarray, "host", pRec->pName, 1);
+ add_assoc_string(*subarray, "class", "IN", 1);
+ add_assoc_long(*subarray, "ttl", ttl);
+
+ if (raw) {
+ add_assoc_long(*subarray, "type", type);
+ add_assoc_stringl(*subarray, "data", (char*) &pRec->Data, (uint) pRec->wDataLength, 1);
+ return;
+ }
+
switch (type) {
case DNS_TYPE_A: {
IN_ADDR ipaddr;
@@ -308,9 +317,9 @@ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **s
}
break;
+#if _MSC_VER >= 1500
case DNS_TYPE_NAPTR:
{
-#if _MSC_VER >= 1500
DNS_NAPTR_DATA * data_naptr = &pRec->Data.Naptr;
add_assoc_string(*subarray, "type", "NAPTR", 1);
@@ -320,16 +329,17 @@ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **s
add_assoc_string(*subarray, "services", data_naptr->pService, 1);
add_assoc_string(*subarray, "regex", data_naptr->pRegularExpression, 1);
add_assoc_string(*subarray, "replacement", data_naptr->pReplacement, 1);
-#endif
}
break;
+#endif
default:
- break;
+ /* unkown type */
+ zval_ptr_dtor(subarray);
+ *subarray = NULL;
+ return;
}
- add_assoc_string(*subarray, "class", "IN", 1);
- add_assoc_long(*subarray, "ttl", ttl);
}
/* }}} */
@@ -342,8 +352,10 @@ PHP_FUNCTION(dns_get_record)
long type_param = PHP_DNS_ANY;
zval *authns = NULL, *addtl = NULL;
int type, type_to_fetch, first_query = 1, store_results = 1;
+ zend_bool raw = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lzz", &hostname, &hostname_len, &type_param, &authns, &addtl) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz!z!b",
+ &hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
return;
}
@@ -356,15 +368,31 @@ PHP_FUNCTION(dns_get_record)
array_init(addtl);
}
- if (type_param & ~PHP_DNS_ALL && type_param != PHP_DNS_ANY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
- RETURN_FALSE;
+ if (!raw) {
+ if ((type_param & ~PHP_DNS_ALL) && (type_param != PHP_DNS_ANY)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
+ RETURN_FALSE;
+ }
+ } else {
+ if ((type_param < 1) || (type_param > 0xFFFF)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Numeric DNS record type must be between 1 and 65535, '%ld' given", type_param);
+ RETURN_FALSE;
+ }
}
/* Initialize the return array */
array_init(return_value);
- for (type = (type_param == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
+ if (raw) {
+ type = -1;
+ } else if (type_param == PHP_DNS_ANY) {
+ type = PHP_DNS_NUM_TYPES + 1;
+ } else {
+ type = 0;
+ }
+
+ for ( ;
type < (addtl ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query;
type++
) {
@@ -373,6 +401,11 @@ PHP_FUNCTION(dns_get_record)
first_query = 0;
switch (type) {
+ case -1: /* raw */
+ type_to_fetch = type_param;
+ /* skip over the rest and go directly to additional records */
+ type = PHP_DNS_NUM_TYPES - 1;
+ break;
case 0:
type_to_fetch = type_param&PHP_DNS_A ? DNS_TYPE_A : 0;
break;
@@ -436,7 +469,7 @@ PHP_FUNCTION(dns_get_record)
zval *retval = NULL;
if (pRec->Flags.S.Section == DnsSectionAnswer) {
- php_parserr(pRec, type_to_fetch, store_results, &retval);
+ php_parserr(pRec, type_to_fetch, store_results, raw, &retval);
if (retval != NULL && store_results) {
add_next_index_zval(return_value, retval);
}
@@ -444,7 +477,7 @@ PHP_FUNCTION(dns_get_record)
if (authns && pRec->Flags.S.Section == DnsSectionAuthority) {
- php_parserr(pRec, type_to_fetch, store_results, &retval);
+ php_parserr(pRec, type_to_fetch, 1, raw, &retval);
if (retval != NULL) {
add_next_index_zval(authns, retval);
}
@@ -459,7 +492,7 @@ PHP_FUNCTION(dns_get_record)
# endif
#endif
if (addtl && pRec->Flags.S.Section == DnsSectionAdditional) {
- php_parserr(pRec, type_to_fetch, store_results, &retval);
+ php_parserr(pRec, type_to_fetch, 1, raw, &retval);
if (retval != NULL) {
add_next_index_zval(addtl, retval);
}
diff --git a/ext/standard/exec.c b/ext/standard/exec.c
index 0a291d4564..a5ca84bb6b 100644
--- a/ext/standard/exec.c
+++ b/ext/standard/exec.c
@@ -22,7 +22,6 @@
#include "php.h"
#include <ctype.h>
#include "php_string.h"
-#include "safe_mode.h"
#include "ext/standard/head.h"
#include "ext/standard/file.h"
#include "basic_functions.h"
@@ -61,53 +60,23 @@
PHPAPI int php_exec(int type, char *cmd, zval *array, zval *return_value TSRMLS_DC)
{
FILE *fp;
- char *buf, *tmp=NULL;
+ char *buf;
int l = 0, pclose_return;
- char *cmd_p, *b, *c, *d=NULL;
+ char *b, *d=NULL;
php_stream *stream;
size_t buflen, bufl = 0;
#if PHP_SIGCHILD
void (*sig_handler)() = NULL;
#endif
- if (PG(safe_mode)) {
- if ((c = strchr(cmd, ' '))) {
- *c = '\0';
- c++;
- }
- if (strstr(cmd, "..")) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No '..' components allowed in path");
- goto err;
- }
-
- b = strrchr(cmd, PHP_DIR_SEPARATOR);
-
-#ifdef PHP_WIN32
- if (b && *b == '\\' && b == cmd) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid absolute path.");
- goto err;
- }
-#endif
-
- spprintf(&d, 0, "%s%s%s%s%s", PG(safe_mode_exec_dir), (b ? "" : "/"), (b ? b : cmd), (c ? " " : ""), (c ? c : ""));
- if (c) {
- *(c - 1) = ' ';
- }
- cmd_p = php_escape_shell_cmd(d);
- efree(d);
- d = cmd_p;
- } else {
- cmd_p = cmd;
- }
-
#if PHP_SIGCHILD
sig_handler = signal (SIGCHLD, SIG_DFL);
#endif
#ifdef PHP_WIN32
- fp = VCWD_POPEN(cmd_p, "rb");
+ fp = VCWD_POPEN(cmd, "rb");
#else
- fp = VCWD_POPEN(cmd_p, "r");
+ fp = VCWD_POPEN(cmd, "r");
#endif
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd);
@@ -140,7 +109,7 @@ PHPAPI int php_exec(int type, char *cmd, zval *array, zval *return_value TSRMLS_
if (type == 1) {
PHPWRITE(buf, bufl);
- if (OG(ob_nesting_level) < 1) {
+ if (php_output_get_level(TSRMLS_C) < 1) {
sapi_flush(TSRMLS_C);
}
} else if (type == 2) {
@@ -170,14 +139,7 @@ PHPAPI int php_exec(int type, char *cmd, zval *array, zval *return_value TSRMLS_
}
/* Return last line from the shell command */
- if (PG(magic_quotes_runtime)) {
- int len;
-
- tmp = php_addslashes(buf, bufl, &len, 0 TSRMLS_CC);
- RETVAL_STRINGL(tmp, len, 0);
- } else {
- RETVAL_STRINGL(buf, bufl, 1);
- }
+ RETVAL_STRINGL(buf, bufl, 1);
} else { /* should return NULL, but for BC we return "" */
RETVAL_EMPTY_STRING();
}
@@ -484,11 +446,6 @@ PHP_FUNCTION(shell_exec)
return;
}
- if (PG(safe_mode)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot execute using backquotes in Safe Mode");
- RETURN_FALSE;
- }
-
#ifdef PHP_WIN32
if ((in=VCWD_POPEN(command, "rt"))==NULL) {
#else
@@ -520,7 +477,7 @@ PHP_FUNCTION(proc_nice)
}
errno = 0;
- nice(pri);
+ php_ignore_value(nice(pri));
if (errno) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only a super user may attempt to increase the priority of a process");
RETURN_FALSE;
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 7147e98258..cce0143fff 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -70,7 +70,6 @@
#endif
#include "ext/standard/head.h"
-#include "safe_mode.h"
#include "php_string.h"
#include "file.h"
@@ -136,10 +135,10 @@ php_file_globals file_globals;
/* {{{ ZTS-stuff / Globals / Prototypes */
-/* sharing globals is *evil* */
+/* sharing globals is *evil* */
static int le_stream_context = FAILURE;
-PHPAPI int php_le_stream_context(void)
+PHPAPI int php_le_stream_context(TSRMLS_D)
{
return le_stream_context;
}
@@ -171,7 +170,7 @@ static void file_globals_dtor(php_file_globals *file_globals_p TSRMLS_DC)
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("user_agent", NULL, PHP_INI_ALL, OnUpdateString, user_agent, php_file_globals, file_globals)
- PHP_INI_ENTRY("from", NULL, PHP_INI_ALL, NULL)
+ STD_PHP_INI_ENTRY("from", NULL, PHP_INI_ALL, OnUpdateString, from_address, php_file_globals, file_globals)
STD_PHP_INI_ENTRY("default_socket_timeout", "60", PHP_INI_ALL, OnUpdateLong, default_socket_timeout, php_file_globals, file_globals)
STD_PHP_INI_ENTRY("auto_detect_line_endings", "0", PHP_INI_ALL, OnUpdateLong, auto_detect_line_endings, php_file_globals, file_globals)
PHP_INI_END()
@@ -238,10 +237,12 @@ PHP_MINIT_FUNCTION(file)
REGISTER_LONG_CONSTANT("STREAM_PF_INET", AF_INET, CONST_CS|CONST_PERSISTENT);
#endif
-#ifdef PF_INET6
+#if HAVE_IPV6
+# ifdef PF_INET6
REGISTER_LONG_CONSTANT("STREAM_PF_INET6", PF_INET6, CONST_CS|CONST_PERSISTENT);
-#elif defined(AF_INET6)
+# elif defined(AF_INET6)
REGISTER_LONG_CONSTANT("STREAM_PF_INET6", AF_INET6, CONST_CS|CONST_PERSISTENT);
+# endif
#endif
#ifdef PF_UNIX
@@ -383,16 +384,12 @@ PHP_FUNCTION(get_meta_tags)
memset(&md, 0, sizeof(md));
/* Parse arguments */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &filename_len, &use_include_path) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &filename, &filename_len, &use_include_path) == FAILURE) {
return;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
md.stream = php_stream_open_wrapper(filename, "rb",
- (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ (use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
NULL);
if (!md.stream) {
RETURN_FALSE;
@@ -427,13 +424,7 @@ PHP_FUNCTION(get_meta_tags)
have_name = 1;
} else if (saw_content) {
STR_FREE(value);
- /* Get the CONTENT attr (Single word attr, non-quoted) */
- if (PG(magic_quotes_runtime)) {
- value = php_addslashes(md.token_data, 0, &md.token_len, 0 TSRMLS_CC);
- } else {
- value = estrndup(md.token_data, md.token_len);
- }
-
+ value = estrndup(md.token_data, md.token_len);
have_content = 1;
}
@@ -467,13 +458,7 @@ PHP_FUNCTION(get_meta_tags)
have_name = 1;
} else if (saw_content) {
STR_FREE(value);
- /* Get the CONTENT attr (Single word attr, non-quoted) */
- if (PG(magic_quotes_runtime)) {
- value = php_addslashes(md.token_data, 0, &md.token_len, 0 TSRMLS_CC);
- } else {
- value = estrndup(md.token_data, md.token_len);
- }
-
+ value = estrndup(md.token_data, md.token_len);
have_content = 1;
}
@@ -540,14 +525,10 @@ PHP_FUNCTION(file_get_contents)
php_stream_context *context = NULL;
/* Parse arguments */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
return;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
RETURN_FALSE;
@@ -556,7 +537,7 @@ PHP_FUNCTION(file_get_contents)
context = php_stream_context_from_zval(zcontext, 0);
stream = php_stream_open_wrapper_ex(filename, "rb",
- (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ (use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
NULL, context);
if (!stream) {
RETURN_FALSE;
@@ -569,11 +550,6 @@ PHP_FUNCTION(file_get_contents)
}
if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
-
- if (PG(magic_quotes_runtime)) {
- contents = php_addslashes(contents, len, &len, 1 TSRMLS_CC); /* 1 = free source string */
- }
-
RETVAL_STRINGL(contents, len, 0);
} else if (len == 0) {
RETVAL_EMPTY_STRING();
@@ -600,14 +576,10 @@ PHP_FUNCTION(file_put_contents)
php_stream *srcstream = NULL;
char mode[3] = "wb";
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|lr!", &filename, &filename_len, &data, &flags, &zcontext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/|lr!", &filename, &filename_len, &data, &flags, &zcontext) == FAILURE) {
return;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (Z_TYPE_P(data) == IS_RESOURCE) {
php_stream_from_zval(srcstream, &data);
}
@@ -628,7 +600,7 @@ PHP_FUNCTION(file_put_contents)
}
mode[2] = '\0';
- stream = php_stream_open_wrapper_ex(filename, mode, ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+ stream = php_stream_open_wrapper_ex(filename, mode, ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
if (stream == NULL) {
RETURN_FALSE;
}
@@ -736,9 +708,9 @@ PHP_FUNCTION(file)
{
char *filename;
int filename_len;
- char *slashed, *target_buf=NULL, *p, *s, *e;
+ char *target_buf=NULL, *p, *s, *e;
register int i = 0;
- int target_len, len;
+ int target_len;
char eol_marker = '\n';
long flags = 0;
zend_bool use_include_path;
@@ -749,14 +721,9 @@ PHP_FUNCTION(file)
php_stream_context *context = NULL;
/* Parse arguments */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) {
return;
}
-
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (flags < 0 || flags > (PHP_FILE_USE_INCLUDE_PATH | PHP_FILE_IGNORE_NEW_LINES | PHP_FILE_SKIP_EMPTY_LINES | PHP_FILE_NO_DEFAULT_CONTEXT)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%ld' flag is not supported", flags);
RETURN_FALSE;
@@ -768,7 +735,7 @@ PHP_FUNCTION(file)
context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
- stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+ stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
if (!stream) {
RETURN_FALSE;
}
@@ -795,13 +762,7 @@ PHP_FUNCTION(file)
do {
p++;
parse_eol:
- if (PG(magic_quotes_runtime)) {
- /* s is in target_buf which is freed at the end of the function */
- slashed = php_addslashes(s, (p-s), &len, 0 TSRMLS_CC);
- add_index_stringl(return_value, i++, slashed, len, 0);
- } else {
- add_index_stringl(return_value, i++, estrndup(s, p-s), p-s, 0);
- }
+ add_index_stringl(return_value, i++, estrndup(s, p-s), p-s, 0);
s = p;
} while ((p = memchr(p, eol_marker, (e-p))));
} else {
@@ -814,13 +775,7 @@ parse_eol:
s = ++p;
continue;
}
- if (PG(magic_quotes_runtime)) {
- /* s is in target_buf which is freed at the end of the function */
- slashed = php_addslashes(s, (p-s-windows_eol), &len, 0 TSRMLS_CC);
- add_index_stringl(return_value, i++, slashed, len, 0);
- } else {
- add_index_stringl(return_value, i++, estrndup(s, p-s-windows_eol), p-s-windows_eol, 0);
- }
+ add_index_stringl(return_value, i++, estrndup(s, p-s-windows_eol), p-s-windows_eol, 0);
s = ++p;
} while ((p = memchr(p, eol_marker, (e-p))));
}
@@ -850,22 +805,10 @@ PHP_FUNCTION(tempnam)
char *p;
int fd;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
return;
}
- if (strlen(dir) != dir_len) {
- RETURN_FALSE;
- }
-
- if (strlen(prefix) != prefix_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) &&(!php_checkuid(dir, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(dir TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -916,17 +859,13 @@ PHP_NAMED_FUNCTION(php_if_fopen)
php_stream *stream;
php_stream_context *context = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
RETURN_FALSE;
}
context = php_stream_context_from_zval(zcontext, 0);
- stream = php_stream_open_wrapper_ex(filename, mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+ stream = php_stream_open_wrapper_ex(filename, mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
if (stream == NULL) {
RETURN_FALSE;
@@ -955,7 +894,7 @@ PHPAPI PHP_FUNCTION(fclose)
}
if (!stream->is_persistent) {
- zend_list_delete(stream->rsrc_id);
+ php_stream_close(stream);
} else {
php_stream_pclose(stream);
}
@@ -972,9 +911,9 @@ PHP_FUNCTION(popen)
int command_len, mode_len;
FILE *fp;
php_stream *stream;
- char *posix_mode, *b, *buf = 0, *tmp;
+ char *posix_mode;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &command, &command_len, &mode, &mode_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &command, &command_len, &mode, &mode_len) == FAILURE) {
return;
}
@@ -987,49 +926,14 @@ PHP_FUNCTION(popen)
}
}
#endif
- if (PG(safe_mode)){
- b = strchr(command, ' ');
- if (!b) {
- b = strrchr(command, '/');
- } else {
- char *c;
-
- c = command;
- while((*b != '/') && (b != c)) {
- b--;
- }
- if (b == c) {
- b = NULL;
- }
- }
- if (b) {
- spprintf(&buf, 0, "%s%s", PG(safe_mode_exec_dir), b);
- } else {
- spprintf(&buf, 0, "%s/%s", PG(safe_mode_exec_dir), command);
- }
-
- tmp = php_escape_shell_cmd(buf);
- fp = VCWD_POPEN(tmp, posix_mode);
- efree(tmp);
-
- if (!fp) {
- php_error_docref2(NULL TSRMLS_CC, buf, posix_mode, E_WARNING, "%s", strerror(errno));
- efree(posix_mode);
- efree(buf);
- RETURN_FALSE;
- }
-
- efree(buf);
-
- } else {
- fp = VCWD_POPEN(command, posix_mode);
- if (!fp) {
- php_error_docref2(NULL TSRMLS_CC, command, posix_mode, E_WARNING, "%s", strerror(errno));
- efree(posix_mode);
- RETURN_FALSE;
- }
+ fp = VCWD_POPEN(command, posix_mode);
+ if (!fp) {
+ php_error_docref2(NULL TSRMLS_CC, command, posix_mode, E_WARNING, "%s", strerror(errno));
+ efree(posix_mode);
+ RETURN_FALSE;
}
+
stream = php_stream_fopen_from_pipe(fp, mode);
if (stream == NULL) {
@@ -1117,16 +1021,11 @@ PHPAPI PHP_FUNCTION(fgets)
}
}
- if (PG(magic_quotes_runtime)) {
- Z_STRVAL_P(return_value) = php_addslashes(buf, line_len, &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
- Z_TYPE_P(return_value) = IS_STRING;
- } else {
- ZVAL_STRINGL(return_value, buf, line_len, 0);
- /* resize buffer if it's much larger than the result.
- * Only needed if the user requested a buffer size. */
- if (argc > 1 && Z_STRLEN_P(return_value) < len / 2) {
- Z_STRVAL_P(return_value) = erealloc(buf, line_len + 1);
- }
+ ZVAL_STRINGL(return_value, buf, line_len, 0);
+ /* resize buffer if it's much larger than the result.
+ * Only needed if the user requested a buffer size. */
+ if (argc > 1 && Z_STRLEN_P(return_value) < len / 2) {
+ Z_STRVAL_P(return_value) = erealloc(buf, line_len + 1);
}
return;
@@ -1287,11 +1186,6 @@ PHPAPI PHP_FUNCTION(fwrite)
PHP_STREAM_TO_ZVAL(stream, &arg1);
- if (PG(magic_quotes_runtime)) {
- buffer = estrndup(arg2, num_bytes);
- php_stripslashes(buffer, &num_bytes TSRMLS_CC);
- }
-
ret = php_stream_write(stream, buffer ? buffer : arg2, num_bytes);
if (buffer) {
efree(buffer);
@@ -1391,10 +1285,6 @@ PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC)
{
int ret;
- if (PG(safe_mode) && (!php_checkuid(dir, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return -1;
- }
-
if (php_check_open_basedir(dir TSRMLS_CC)) {
return -1;
}
@@ -1423,11 +1313,7 @@ PHP_FUNCTION(mkdir)
zend_bool recursive = 0;
php_stream_context *context;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbr", &dir, &dir_len, &mode, &recursive, &zcontext) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(dir) != dir_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lbr", &dir, &dir_len, &mode, &recursive, &zcontext) == FAILURE) {
RETURN_FALSE;
}
@@ -1450,10 +1336,6 @@ PHP_FUNCTION(rmdir)
RETURN_FALSE;
}
- if (strlen(dir) != dir_len) {
- RETURN_FALSE;
- }
-
context = php_stream_context_from_zval(zcontext, 0);
RETURN_BOOL(php_stream_rmdir(dir, REPORT_ERRORS, context));
@@ -1472,17 +1354,13 @@ PHP_FUNCTION(readfile)
php_stream *stream;
php_stream_context *context = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
RETURN_FALSE;
}
context = php_stream_context_from_zval(zcontext, 0);
- stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+ stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
if (stream) {
size = php_stream_passthru(stream);
php_stream_close(stream);
@@ -1549,15 +1427,7 @@ PHP_FUNCTION(rename)
php_stream_wrapper *wrapper;
php_stream_context *context;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|r", &old_name, &old_name_len, &new_name, &new_name_len, &zcontext) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(old_name) != old_name_len) {
- RETURN_FALSE;
- }
-
- if (strlen(new_name) != new_name_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|r", &old_name, &old_name_len, &new_name, &new_name_len, &zcontext) == FAILURE) {
RETURN_FALSE;
}
@@ -1594,11 +1464,7 @@ PHP_FUNCTION(unlink)
zval *zcontext = NULL;
php_stream_context *context = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &filename, &filename_len, &zcontext) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &filename, &filename_len, &zcontext) == FAILURE) {
RETURN_FALSE;
}
@@ -1615,7 +1481,7 @@ PHP_FUNCTION(unlink)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s does not allow unlinking", wrapper->wops->label ? wrapper->wops->label : "Wrapper");
RETURN_FALSE;
}
- RETURN_BOOL(wrapper->wops->unlink(wrapper, filename, ENFORCE_SAFE_MODE | REPORT_ERRORS, context TSRMLS_CC));
+ RETURN_BOOL(wrapper->wops->unlink(wrapper, filename, REPORT_ERRORS, context TSRMLS_CC));
}
/* }}} */
@@ -1734,22 +1600,10 @@ PHP_FUNCTION(copy)
zval *zcontext = NULL;
php_stream_context *context;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|r", &source, &source_len, &target, &target_len, &zcontext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|r", &source, &source_len, &target, &target_len, &zcontext) == FAILURE) {
return;
}
- if (strlen(source) != source_len) {
- RETURN_FALSE;
- }
-
- if (strlen(target) != target_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) &&(!php_checkuid(source, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(source TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -1768,27 +1622,27 @@ PHP_FUNCTION(copy)
*/
PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC)
{
- return php_copy_file_ctx(src, dest, ENFORCE_SAFE_MODE, NULL TSRMLS_CC);
+ return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC);
}
/* }}} */
/* {{{ php_copy_file_ex
*/
-PHPAPI int php_copy_file_ex(char *src, char *dest, int src_chk TSRMLS_DC)
+PHPAPI int php_copy_file_ex(char *src, char *dest, int src_flg TSRMLS_DC)
{
- return php_copy_file_ctx(src, dest, ENFORCE_SAFE_MODE, NULL TSRMLS_CC);
+ return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC);
}
/* }}} */
/* {{{ php_copy_file_ctx
*/
-PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_chk, php_stream_context *context TSRMLS_DC)
+PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_flg, php_stream_context *ctx TSRMLS_DC)
{
php_stream *srcstream = NULL, *deststream = NULL;
int ret = FAILURE;
php_stream_statbuf src_s, dest_s;
- switch (php_stream_stat_path_ex(src, 0, &src_s, context)) {
+ switch (php_stream_stat_path_ex(src, 0, &src_s, ctx)) {
case -1:
/* non-statable stream */
goto safe_to_copy;
@@ -1803,7 +1657,7 @@ PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_chk, php_stream_cont
return FAILURE;
}
- switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET, &dest_s, context)) {
+ switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET, &dest_s, ctx)) {
case -1:
/* non-statable stream */
goto safe_to_copy;
@@ -1853,13 +1707,13 @@ no_stat:
}
safe_to_copy:
- srcstream = php_stream_open_wrapper_ex(src, "rb", src_chk | REPORT_ERRORS, NULL, context);
+ srcstream = php_stream_open_wrapper_ex(src, "rb", src_flg | REPORT_ERRORS, NULL, ctx);
if (!srcstream) {
return ret;
}
- deststream = php_stream_open_wrapper_ex(dest, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+ deststream = php_stream_open_wrapper_ex(dest, "wb", REPORT_ERRORS, NULL, ctx);
if (srcstream && deststream) {
ret = php_stream_copy_to_stream_ex(srcstream, deststream, PHP_STREAM_COPY_ALL, NULL);
@@ -1898,11 +1752,6 @@ PHPAPI PHP_FUNCTION(fread)
/* needed because recv/read/gzread doesnt put a null at the end*/
Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
-
- if (PG(magic_quotes_runtime)) {
- Z_STRVAL_P(return_value) = php_addslashes(Z_STRVAL_P(return_value),
- Z_STRLEN_P(return_value), &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
- }
Z_TYPE_P(return_value) = IS_STRING;
}
/* }}} */
@@ -1918,7 +1767,7 @@ static const char *php_fgetcsv_lookup_trailing_spaces(const char *ptr, size_t le
case -2:
case -1:
inc_len = 1;
- php_mblen(NULL, 0);
+ php_ignore_value(php_mblen(NULL, 0));
break;
case 0:
goto quit_loop;
@@ -1955,13 +1804,10 @@ PHP_FUNCTION(fputcsv)
char enclosure = '"'; /* allow this to be set as parameter */
const char escape_char = '\\';
php_stream *stream;
+ zval *fp = NULL, *fields = NULL;
int ret;
- zval *fp = NULL, *fields = NULL, **field_tmp = NULL, field;
char *delimiter_str = NULL, *enclosure_str = NULL;
int delimiter_str_len = 0, enclosure_str_len = 0;
- HashPosition pos;
- int count, i = 0;
- smart_str csvline = {0};
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|ss",
&fp, &fields, &delimiter_str, &delimiter_str_len,
@@ -1995,6 +1841,19 @@ PHP_FUNCTION(fputcsv)
PHP_STREAM_TO_ZVAL(stream, &fp);
+ ret = php_fputcsv(stream, fields, delimiter, enclosure, escape_char TSRMLS_CC);
+ RETURN_LONG(ret);
+}
+/* }}} */
+
+/* {{{ PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC) */
+PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC)
+{
+ int count, i = 0, ret;
+ zval **field_tmp = NULL, field;
+ smart_str csvline = {0};
+ HashPosition pos;
+
count = zend_hash_num_elements(Z_ARRVAL_P(fields));
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(fields), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(fields), (void **) &field_tmp, &pos) == SUCCESS) {
@@ -2048,19 +1907,11 @@ PHP_FUNCTION(fputcsv)
smart_str_appendc(&csvline, '\n');
smart_str_0(&csvline);
- if (!PG(magic_quotes_runtime)) {
- ret = php_stream_write(stream, csvline.c, csvline.len);
- } else {
- char *buffer = estrndup(csvline.c, csvline.len);
- int len = csvline.len;
- php_stripslashes(buffer, &len TSRMLS_CC);
- ret = php_stream_write(stream, buffer, len);
- efree(buffer);
- }
+ ret = php_stream_write(stream, csvline.c, csvline.len);
smart_str_free(&csvline);
- RETURN_LONG(ret);
+ return ret;
}
/* }}} */
@@ -2172,7 +2023,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char
zend_bool first_field = 1;
/* initialize internal state */
- php_mblen(NULL, 0);
+ php_ignore_value(php_mblen(NULL, 0));
/* Now into new section that parses buf for delimiter/enclosure fields */
@@ -2197,6 +2048,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char
char *comp_end, *hunk_begin;
tptr = temp;
+
inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
if (inc_len == 1) {
char *tmp = bptr;
@@ -2286,7 +2138,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char
case -2:
case -1:
- php_mblen(NULL, 0);
+ php_ignore_value(php_mblen(NULL, 0));
/* break is omitted intentionally */
case 1:
/* we need to determine if the enclosure is
@@ -2354,7 +2206,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char
case -2:
case -1:
inc_len = 1;
- php_mblen(NULL, 0);
+ php_ignore_value(php_mblen(NULL, 0));
/* break is omitted intentionally */
case 1:
if (*bptr == delimiter) {
@@ -2385,7 +2237,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char
case -2:
case -1:
inc_len = 1;
- php_mblen(NULL, 0);
+ php_ignore_value(php_mblen(NULL, 0));
/* break is omitted intentionally */
case 1:
if (*bptr == delimiter) {
@@ -2430,19 +2282,11 @@ PHP_FUNCTION(realpath)
int filename_len;
char resolved_path_buff[MAXPATHLEN];
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (VCWD_REALPATH(filename, resolved_path_buff)) {
- if (PG(safe_mode) && (!php_checkuid(resolved_path_buff, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(resolved_path_buff TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -2576,18 +2420,10 @@ PHP_FUNCTION(fnmatch)
int pattern_len, filename_len;
long flags = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &pattern, &pattern_len, &filename, &filename_len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|l", &pattern, &pattern_len, &filename, &filename_len, &flags) == FAILURE) {
return;
}
- if (strlen(pattern) != pattern_len) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (filename_len >= MAXPATHLEN) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename exceeds the maximum allowed length of %d characters", MAXPATHLEN);
RETURN_FALSE;
diff --git a/ext/standard/file.h b/ext/standard/file.h
index 05e5eb91b6..2d2406e0d5 100644
--- a/ext/standard/file.h
+++ b/ext/standard/file.h
@@ -72,14 +72,15 @@ PHP_FUNCTION(sys_get_temp_dir);
PHP_MINIT_FUNCTION(user_streams);
-PHPAPI int php_le_stream_context(void);
+PHPAPI int php_le_stream_context(TSRMLS_D);
PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC);
PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC);
PHPAPI int php_copy_file_ex(char *src, char *dest, int src_chk TSRMLS_DC);
-PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_chk, php_stream_context *context TSRMLS_DC);
+PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_chk, php_stream_context *ctx TSRMLS_DC);
PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC);
PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC);
PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char escape_char, size_t buf_len, char *buf, zval *return_value TSRMLS_DC);
+PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC);
#define META_DEF_BUFSIZE 8192
@@ -119,6 +120,7 @@ typedef struct {
long auto_detect_line_endings;
long default_socket_timeout;
char *user_agent; /* for the http wrapper */
+ char *from_address; /* for the ftp and http wrappers */
char *user_stream_current_filename; /* for simple recursion protection */
php_stream_context *default_context;
HashTable *stream_wrappers; /* per-request copy of url_stream_wrappers_hash */
diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c
index 349526ecfd..142ca9bdcf 100644
--- a/ext/standard/filestat.c
+++ b/ext/standard/filestat.c
@@ -19,7 +19,6 @@
/* $Id$ */
#include "php.h"
-#include "safe_mode.h"
#include "fopen_wrappers.h"
#include "php_globals.h"
@@ -236,7 +235,7 @@ PHP_FUNCTION(disk_total_space)
char *path;
int path_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &path, &path_len) == FAILURE) {
return;
}
@@ -371,7 +370,7 @@ PHP_FUNCTION(disk_free_space)
char *path;
int path_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &path, &path_len) == FAILURE) {
return;
}
@@ -379,10 +378,6 @@ PHP_FUNCTION(disk_free_space)
RETURN_FALSE;
}
- if (strlen(path) != path_len) {
- RETURN_FALSE;
- }
-
if (php_disk_free_space(path, &bytesfree TSRMLS_CC) == SUCCESS) {
RETURN_DOUBLE(bytesfree);
}
@@ -391,25 +386,8 @@ PHP_FUNCTION(disk_free_space)
/* }}} */
#if !defined(WINDOWS) && !defined(NETWARE)
-static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
+PHPAPI int php_get_gid_by_name(const char *name, gid_t *gid TSRMLS_DC)
{
- char *filename;
- int filename_len;
- zval *group;
- gid_t gid;
- int ret;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/", &filename, &filename_len, &group) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
- if (Z_TYPE_P(group) == IS_LONG) {
- gid = (gid_t)Z_LVAL_P(group);
- } else if (Z_TYPE_P(group) == IS_STRING) {
#if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
struct group gr;
struct group *retgrptr;
@@ -417,32 +395,85 @@ static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
char *grbuf;
if (grbuflen < 1) {
- RETURN_FALSE;
+ return FAILURE;
}
grbuf = emalloc(grbuflen);
- if (getgrnam_r(Z_STRVAL_P(group), &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
+ if (getgrnam_r(name, &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
efree(grbuf);
- RETURN_FALSE;
+ return FAILURE;
}
efree(grbuf);
- gid = gr.gr_gid;
+ *gid = gr.gr_gid;
#else
- struct group *gr = getgrnam(Z_STRVAL_P(group));
+ struct group *gr = getgrnam(name);
if (!gr) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
- RETURN_FALSE;
+ return FAILURE;
}
- gid = gr->gr_gid;
+ *gid = gr->gr_gid;
#endif
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
+ return SUCCESS;
+}
+#endif
+
+static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
+{
+ char *filename;
+ int filename_len;
+ zval *group;
+#if !defined(WINDOWS)
+ gid_t gid;
+ int ret;
+#endif
+ php_stream_wrapper *wrapper;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/", &filename, &filename_len, &group) == FAILURE) {
RETURN_FALSE;
}
- if (PG(safe_mode) &&(!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
+ wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
+ if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
+ if(wrapper && wrapper->wops->stream_metadata) {
+ int option;
+ void *value;
+ if (Z_TYPE_P(group) == IS_LONG) {
+ option = PHP_STREAM_META_GROUP;
+ value = &Z_LVAL_P(group);
+ } else if (Z_TYPE_P(group) == IS_STRING) {
+ option = PHP_STREAM_META_GROUP_NAME;
+ value = Z_STRVAL_P(group);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
+ RETURN_FALSE;
+ }
+ if(wrapper->wops->stream_metadata(wrapper, filename, option, value, NULL TSRMLS_CC)) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ } else {
+#if !defined(WINDOWS)
+/* On Windows, we expect regular chgrp to fail silently by default */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call chgrp() for a non-standard stream");
+#endif
+ RETURN_FALSE;
+ }
+ }
+
+#if defined(WINDOWS)
+ /* We have no native chgrp on Windows, nothing left to do if stream doesn't have own implementation */
+ RETURN_FALSE;
+#else
+ if (Z_TYPE_P(group) == IS_LONG) {
+ gid = (gid_t)Z_LVAL_P(group);
+ } else if (Z_TYPE_P(group) == IS_STRING) {
+ if(php_get_gid_by_name(Z_STRVAL_P(group), &gid TSRMLS_CC) != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_P(group));
+ RETURN_FALSE;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(group));
RETURN_FALSE;
}
@@ -463,20 +494,16 @@ static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
RETURN_FALSE;
}
RETURN_TRUE;
+#endif
}
/* }}} */
-#endif
#ifndef NETWARE
/* {{{ proto bool chgrp(string filename, mixed group)
Change file group */
PHP_FUNCTION(chgrp)
{
-#if !defined(WINDOWS)
php_do_chgrp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-#else
- RETURN_FALSE;
-#endif
}
/* }}} */
@@ -496,25 +523,8 @@ PHP_FUNCTION(lchgrp)
#endif /* !NETWARE */
#if !defined(WINDOWS) && !defined(NETWARE)
-static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
+PHPAPI uid_t php_get_uid_by_name(const char *name, uid_t *uid TSRMLS_DC)
{
- char *filename;
- int filename_len;
- zval *user;
- uid_t uid;
- int ret;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/", &filename, &filename_len, &user) == FAILURE) {
- return;
- }
-
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
- if (Z_TYPE_P(user) == IS_LONG) {
- uid = (uid_t)Z_LVAL_P(user);
- } else if (Z_TYPE_P(user) == IS_STRING) {
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
struct passwd pw;
struct passwd *retpwptr = NULL;
@@ -522,35 +532,89 @@ static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
char *pwbuf;
if (pwbuflen < 1) {
- RETURN_FALSE;
+ return FAILURE;
}
pwbuf = emalloc(pwbuflen);
- if (getpwnam_r(Z_STRVAL_P(user), &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
+ if (getpwnam_r(name, &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
efree(pwbuf);
- RETURN_FALSE;
+ return FAILURE;
}
efree(pwbuf);
- uid = pw.pw_uid;
+ *uid = pw.pw_uid;
#else
- struct passwd *pw = getpwnam(Z_STRVAL_P(user));
+ struct passwd *pw = getpwnam(name);
if (!pw) {
+ return FAILURE;
+ }
+ *uid = pw->pw_uid;
+#endif
+ return SUCCESS;
+}
+#endif
+
+static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
+{
+ char *filename;
+ int filename_len;
+ zval *user;
+#if !defined(WINDOWS)
+ uid_t uid;
+ int ret;
+#endif
+ php_stream_wrapper *wrapper;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/", &filename, &filename_len, &user) == FAILURE) {
+ return;
+ }
+
+ wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
+ if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
+ if(wrapper && wrapper->wops->stream_metadata) {
+ int option;
+ void *value;
+ if (Z_TYPE_P(user) == IS_LONG) {
+ option = PHP_STREAM_META_OWNER;
+ value = &Z_LVAL_P(user);
+ } else if (Z_TYPE_P(user) == IS_STRING) {
+ option = PHP_STREAM_META_OWNER_NAME;
+ value = Z_STRVAL_P(user);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(user));
+ RETURN_FALSE;
+ }
+ if(wrapper->wops->stream_metadata(wrapper, filename, option, value, NULL TSRMLS_CC)) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ } else {
+#if !defined(WINDOWS)
+/* On Windows, we expect regular chown to fail silently by default */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call chown() for a non-standard stream");
+#endif
+ RETURN_FALSE;
+ }
+ }
+
+#if defined(WINDOWS)
+ /* We have no native chown on Windows, nothing left to do if stream doesn't have own implementation */
+ RETURN_FALSE;
+#else
+
+ if (Z_TYPE_P(user) == IS_LONG) {
+ uid = (uid_t)Z_LVAL_P(user);
+ } else if (Z_TYPE_P(user) == IS_STRING) {
+ if(php_get_uid_by_name(Z_STRVAL_P(user), &uid TSRMLS_CC) != SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_P(user));
RETURN_FALSE;
}
- uid = pw->pw_uid;
-#endif
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 2 should be string or integer, %s given", zend_zval_type_name(user));
RETURN_FALSE;
}
- if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
- RETURN_FALSE;
- }
-
/* Check the basedir */
if (php_check_open_basedir(filename TSRMLS_CC)) {
RETURN_FALSE;
@@ -567,21 +631,18 @@ static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
RETURN_FALSE;
}
+ RETURN_TRUE;
+#endif
}
/* }}} */
-#endif
+
#ifndef NETWARE
/* {{{ proto bool chown (string filename, mixed user)
Change file owner */
PHP_FUNCTION(chown)
{
-#if !defined(WINDOWS)
- RETVAL_TRUE;
php_do_chown(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-#else
- RETURN_FALSE;
-#endif
}
/* }}} */
@@ -610,17 +671,24 @@ PHP_FUNCTION(chmod)
long mode;
int ret;
mode_t imode;
+ php_stream_wrapper *wrapper;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &filename, &filename_len, &mode) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl", &filename, &filename_len, &mode) == FAILURE) {
return;
}
- if (PG(safe_mode) &&(!php_checkuid(filename, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS))) {
- RETURN_FALSE;
- }
-
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
+ wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
+ if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
+ if(wrapper && wrapper->wops->stream_metadata) {
+ if(wrapper->wops->stream_metadata(wrapper, filename, PHP_STREAM_META_ACCESS, &mode, NULL TSRMLS_CC)) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call chmod() for a non-standard stream");
+ RETURN_FALSE;
+ }
}
/* Check the basedir */
@@ -629,26 +697,6 @@ PHP_FUNCTION(chmod)
}
imode = (mode_t) mode;
- /* In safe mode, do not allow to setuid files.
- * Setuiding files could allow users to gain privileges
- * that safe mode doesn't give them. */
-
- if (PG(safe_mode)) {
- php_stream_statbuf ssb;
- if (php_stream_stat_path_ex(filename, 0, &ssb, NULL)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "stat failed for %s", filename);
- RETURN_FALSE;
- }
- if ((imode & 04000) != 0 && (ssb.sb.st_mode & 04000) == 0) {
- imode ^= 04000;
- }
- if ((imode & 02000) != 0 && (ssb.sb.st_mode & 02000) == 0) {
- imode ^= 02000;
- }
- if ((imode & 01000) != 0 && (ssb.sb.st_mode & 01000) == 0) {
- imode ^= 01000;
- }
- }
ret = VCWD_CHMOD(filename, imode);
if (ret == -1) {
@@ -671,12 +719,13 @@ PHP_FUNCTION(touch)
FILE *file;
struct utimbuf newtimebuf;
struct utimbuf *newtime = &newtimebuf;
+ php_stream_wrapper *wrapper;
- if (zend_parse_parameters(argc TSRMLS_CC, "s|ll", &filename, &filename_len, &filetime, &fileatime) == FAILURE) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "p|ll", &filename, &filename_len, &filetime, &fileatime) == FAILURE) {
return;
}
- if (strlen(filename) != filename_len) {
+ if (!filename_len) {
RETURN_FALSE;
}
@@ -700,9 +749,28 @@ PHP_FUNCTION(touch)
WRONG_PARAM_COUNT;
}
- /* Safe-mode */
- if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
+ wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
+ if(wrapper != &php_plain_files_wrapper || strncasecmp("file://", filename, 7) == 0) {
+ if(wrapper && wrapper->wops->stream_metadata) {
+ if(wrapper->wops->stream_metadata(wrapper, filename, PHP_STREAM_META_TOUCH, newtime, NULL TSRMLS_CC)) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ } else {
+ php_stream *stream;
+ if(argc > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not call touch() for a non-standard stream");
+ RETURN_FALSE;
+ }
+ stream = php_stream_open_wrapper_ex(filename, "c", REPORT_ERRORS, NULL, NULL);
+ if(stream != NULL) {
+ php_stream_pclose(stream);
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+ }
}
/* Check the basedir */
@@ -735,9 +803,8 @@ PHP_FUNCTION(touch)
PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len TSRMLS_DC)
{
/* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL
- * as it may contain outdated data (e.g. "nlink" for a directory when deleting a file
+ * as it may contains outdated data (e.g. "nlink" for a directory when deleting a file
* in this directory, as shown by lstat_stat_variation9.phpt) */
-
if (BG(CurrentStatFile)) {
efree(BG(CurrentStatFile));
BG(CurrentStatFile) = NULL;
@@ -764,7 +831,7 @@ PHP_FUNCTION(clearstatcache)
char *filename = NULL;
int filename_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &clear_realpath_cache, &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bp", &clear_realpath_cache, &filename, &filename_len) == FAILURE) {
return;
}
@@ -792,34 +859,15 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ
};
char *local;
php_stream_wrapper *wrapper;
- char safe_mode_buf[MAXPATHLEN];
if (!filename_length) {
RETURN_FALSE;
}
- if (strlen(filename) != filename_length) {
+ if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0 TSRMLS_CC)) == &php_plain_files_wrapper && php_check_open_basedir(local TSRMLS_CC)) {
RETURN_FALSE;
}
- if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0 TSRMLS_CC)) == &php_plain_files_wrapper) {
- if (php_check_open_basedir(local TSRMLS_CC)) {
- RETURN_FALSE;
- } else if (PG(safe_mode)) {
- if (type == FS_IS_X) {
- if (strstr(local, "..")) {
- RETURN_FALSE;
- } else {
- char *b = strrchr(local, PHP_DIR_SEPARATOR);
- snprintf(safe_mode_buf, MAXPATHLEN, "%s%s%s", PG(safe_mode_exec_dir), (b ? "" : "/"), (b ? b : local));
- local = (char *)&safe_mode_buf;
- }
- } else if (!php_checkuid_ex(local, NULL, CHECKUID_ALLOW_FILE_NOT_EXISTS, CHECKUID_NO_ERRORS)) {
- RETURN_FALSE;
- }
- }
- }
-
if (IS_ACCESS_CHECK(type)) {
if (wrapper == &php_plain_files_wrapper) {
@@ -1034,7 +1082,7 @@ void name(INTERNAL_FUNCTION_PARAMETERS) { \
char *filename; \
int filename_len; \
\
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { \
return; \
} \
\
diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c
index f26e5d8803..5623a3755b 100644
--- a/ext/standard/formatted_print.c
+++ b/ext/standard/formatted_print.c
@@ -37,10 +37,7 @@
#define ADJ_WIDTH 1
#define ADJ_PRECISION 2
#define NUM_BUF_SIZE 500
-#define NDIG 80
-#define FLOAT_DIGITS 6
#define FLOAT_PRECISION 6
-#define MAX_FLOAT_DIGITS 38
#define MAX_FLOAT_PRECISION 53
#if 0
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
index 3dd43b8e4e..b73ab719c7 100644
--- a/ext/standard/fsock.c
+++ b/ext/standard/fsock.c
@@ -76,7 +76,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
ZVAL_STRING(zerrstr, "", 1);
}
- stream = php_stream_xport_create(hostname, hostname_len, ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS,
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err);
if (port > 0) {
diff --git a/ext/standard/ftok.c b/ext/standard/ftok.c
index 88ecf38aa2..4f67d1ec8a 100644
--- a/ext/standard/ftok.c
+++ b/ext/standard/ftok.c
@@ -35,14 +35,10 @@ PHP_FUNCTION(ftok)
int pathname_len, proj_len;
key_t k;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &pathname, &pathname_len, &proj, &proj_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &pathname, &pathname_len, &proj, &proj_len) == FAILURE) {
return;
}
- if (strlen(pathname) != pathname_len) {
- RETURN_FALSE;
- }
-
if (pathname_len == 0){
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pathname is invalid");
RETURN_LONG(-1);
@@ -51,9 +47,9 @@ PHP_FUNCTION(ftok)
if (proj_len != 1){
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Project identifier is invalid");
RETURN_LONG(-1);
- }
+ }
- if ((PG(safe_mode) && (!php_checkuid(pathname, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(pathname TSRMLS_CC)) {
+ if (php_check_open_basedir(pathname TSRMLS_CC)) {
RETURN_LONG(-1);
}
diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c
index fcc18956f3..16ff550ecb 100644
--- a/ext/standard/ftp_fopen_wrapper.c
+++ b/ext/standard/ftp_fopen_wrapper.c
@@ -269,9 +269,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, char *path
} else {
/* if the user has configured who they are,
send that as the password */
- char *from_address = php_ini_string("from", sizeof("from"), 0);
- if (from_address[0] != '\0') {
- php_stream_printf(stream TSRMLS_CC, "PASS %s\r\n", from_address);
+ if (FG(from_address)) {
+ php_stream_printf(stream TSRMLS_CC, "PASS %s\r\n", FG(from_address));
} else {
php_stream_write_string(stream, "PASS anonymous\r\n");
}
diff --git a/ext/standard/head.c b/ext/standard/head.c
index 3f2872c6c9..dfeb0e0f18 100644
--- a/ext/standard/head.c
+++ b/ext/standard/head.c
@@ -31,7 +31,6 @@
#endif
#include "php_globals.h"
-#include "safe_mode.h"
/* Implementation of the language Header() function */
@@ -123,7 +122,7 @@ PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, t
} else {
snprintf(cookie, len + 100, "Set-Cookie: %s=%s", name, value ? encoded_value : "");
if (expires > 0) {
- char *p;
+ const char *p;
strlcat(cookie, "; expires=", len + 100);
dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, expires, 0 TSRMLS_CC);
/* check to make sure that the year does not exceed 4 digits in length */
@@ -221,15 +220,15 @@ PHP_FUNCTION(setrawcookie)
PHP_FUNCTION(headers_sent)
{
zval *arg1 = NULL, *arg2 = NULL;
- char *file="";
+ const char *file="";
int line=0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|zz", &arg1, &arg2) == FAILURE)
return;
if (SG(headers_sent)) {
- line = php_get_output_start_lineno(TSRMLS_C);
- file = php_get_output_start_filename(TSRMLS_C);
+ line = php_output_get_start_lineno(TSRMLS_C);
+ file = php_output_get_start_filename(TSRMLS_C);
}
switch(ZEND_NUM_ARGS()) {
@@ -281,6 +280,38 @@ PHP_FUNCTION(headers_list)
}
/* }}} */
+/* {{{ proto long http_response_code([int response_code])
+ Sets a response code, or returns the current HTTP response code */
+PHP_FUNCTION(http_response_code)
+{
+ long response_code = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &response_code) == FAILURE) {
+ return;
+ }
+
+ if (response_code)
+ {
+ long old_response_code;
+
+ old_response_code = SG(sapi_headers).http_response_code;
+ SG(sapi_headers).http_response_code = response_code;
+
+ if (old_response_code) {
+ RETURN_LONG(old_response_code);
+ }
+
+ RETURN_TRUE;
+ }
+
+ if (!SG(sapi_headers).http_response_code) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(SG(sapi_headers).http_response_code);
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/head.h b/ext/standard/head.h
index d4e23867a8..ddc29cdd9b 100644
--- a/ext/standard/head.h
+++ b/ext/standard/head.h
@@ -28,6 +28,7 @@ PHP_FUNCTION(setcookie);
PHP_FUNCTION(setrawcookie);
PHP_FUNCTION(headers_sent);
PHP_FUNCTION(headers_list);
+PHP_FUNCTION(http_response_code);
PHPAPI int php_header(TSRMLS_D);
PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, time_t expires, char *path, int path_len, char *domain, int domain_len, int secure, int url_encode, int httponly TSRMLS_DC);
diff --git a/ext/standard/html.c b/ext/standard/html.c
index 058708e28b..65e63f41cc 100644
--- a/ext/standard/html.c
+++ b/ext/standard/html.c
@@ -13,8 +13,9 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Rasmus Lerdorf <rasmus@php.net> |
- | Jaakko Hyvätti <jaakko.hyvatti@iki.fi> |
- | Wez Furlong <wez@thebrainroom.com> |
+ | Jaakko Hyvätti <jaakko.hyvatti@iki.fi> |
+ | Wez Furlong <wez@thebrainroom.com> |
+ | Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
@@ -23,12 +24,18 @@
/*
* HTML entity resources:
*
- * http://msdn.microsoft.com/workshop/author/dhtml/reference/charsets/charset2.asp
- * http://msdn.microsoft.com/workshop/author/dhtml/reference/charsets/charset3.asp
* http://www.unicode.org/Public/MAPPINGS/OBSOLETE/UNI2SGML.TXT
*
+ * XHTML 1.0 DTD
* http://www.w3.org/TR/2002/REC-xhtml1-20020801/dtds.html#h-A2
- *
+ *
+ * From HTML 4.01 strict DTD:
+ * http://www.w3.org/TR/html4/HTMLlat1.ent
+ * http://www.w3.org/TR/html4/HTMLsymbol.ent
+ * http://www.w3.org/TR/html4/HTMLspecial.ent
+ *
+ * HTML 5:
+ * http://dev.w3.org/html5/spec/Overview.html#named-character-references
*/
#include "php.h"
@@ -37,7 +44,7 @@
#else
#include <php_config.h>
#endif
-#include "html.h"
+#include "php_standard.h"
#include "php_string.h"
#include "SAPI.h"
#if HAVE_LOCALE_H
@@ -47,763 +54,343 @@
#include <langinfo.h>
#endif
-#if HAVE_MBSTRING
-# include "ext/mbstring/mbstring.h"
-ZEND_EXTERN_MODULE_GLOBALS(mbstring)
-#endif
+#include <zend_hash.h>
+#include "html_tables.h"
-enum entity_charset { cs_terminator, cs_8859_1, cs_cp1252,
- cs_8859_15, cs_utf_8, cs_big5, cs_gb2312,
- cs_big5hkscs, cs_sjis, cs_eucjp, cs_koi8r,
- cs_cp1251, cs_8859_5, cs_cp866, cs_macroman
- };
-typedef const char *const entity_table_t;
-
-/* codepage 1252 is a Windows extension to iso-8859-1. */
-static entity_table_t ent_cp_1252[] = {
- "euro", NULL, "sbquo", "fnof", "bdquo", "hellip", "dagger",
- "Dagger", "circ", "permil", "Scaron", "lsaquo", "OElig",
- NULL, NULL, NULL, NULL, "lsquo", "rsquo", "ldquo", "rdquo",
- "bull", "ndash", "mdash", "tilde", "trade", "scaron", "rsaquo",
- "oelig", NULL, NULL, "Yuml"
-};
-
-static entity_table_t ent_iso_8859_1[] = {
- "nbsp", "iexcl", "cent", "pound", "curren", "yen", "brvbar",
- "sect", "uml", "copy", "ordf", "laquo", "not", "shy", "reg",
- "macr", "deg", "plusmn", "sup2", "sup3", "acute", "micro",
- "para", "middot", "cedil", "sup1", "ordm", "raquo", "frac14",
- "frac12", "frac34", "iquest", "Agrave", "Aacute", "Acirc",
- "Atilde", "Auml", "Aring", "AElig", "Ccedil", "Egrave",
- "Eacute", "Ecirc", "Euml", "Igrave", "Iacute", "Icirc",
- "Iuml", "ETH", "Ntilde", "Ograve", "Oacute", "Ocirc", "Otilde",
- "Ouml", "times", "Oslash", "Ugrave", "Uacute", "Ucirc", "Uuml",
- "Yacute", "THORN", "szlig", "agrave", "aacute", "acirc",
- "atilde", "auml", "aring", "aelig", "ccedil", "egrave",
- "eacute", "ecirc", "euml", "igrave", "iacute", "icirc",
- "iuml", "eth", "ntilde", "ograve", "oacute", "ocirc", "otilde",
- "ouml", "divide", "oslash", "ugrave", "uacute", "ucirc",
- "uuml", "yacute", "thorn", "yuml"
-};
-
-static entity_table_t ent_iso_8859_15[] = {
- "nbsp", "iexcl", "cent", "pound", "euro", "yen", "Scaron",
- "sect", "scaron", "copy", "ordf", "laquo", "not", "shy", "reg",
- "macr", "deg", "plusmn", "sup2", "sup3", NULL, /* Zcaron */
- "micro", "para", "middot", NULL, /* zcaron */ "sup1", "ordm",
- "raquo", "OElig", "oelig", "Yuml", "iquest", "Agrave", "Aacute",
- "Acirc", "Atilde", "Auml", "Aring", "AElig", "Ccedil", "Egrave",
- "Eacute", "Ecirc", "Euml", "Igrave", "Iacute", "Icirc",
- "Iuml", "ETH", "Ntilde", "Ograve", "Oacute", "Ocirc", "Otilde",
- "Ouml", "times", "Oslash", "Ugrave", "Uacute", "Ucirc", "Uuml",
- "Yacute", "THORN", "szlig", "agrave", "aacute", "acirc",
- "atilde", "auml", "aring", "aelig", "ccedil", "egrave",
- "eacute", "ecirc", "euml", "igrave", "iacute", "icirc",
- "iuml", "eth", "ntilde", "ograve", "oacute", "ocirc", "otilde",
- "ouml", "divide", "oslash", "ugrave", "uacute", "ucirc",
- "uuml", "yacute", "thorn", "yuml"
-};
-
-static entity_table_t ent_uni_338_402[] = {
- /* 338 (0x0152) */
- "OElig", "oelig", NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 352 (0x0160) */
- "Scaron", "scaron", NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 376 (0x0178) */
- "Yuml", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 400 (0x0190) */
- NULL, NULL, "fnof"
-};
-
-static entity_table_t ent_uni_spacing[] = {
- /* 710 */
- "circ",
- /* 711 - 730 */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 731 - 732 */
- NULL, "tilde"
-};
-
-static entity_table_t ent_uni_greek[] = {
- /* 913 */
- "Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta",
- "Iota", "Kappa", "Lambda", "Mu", "Nu", "Xi", "Omicron", "Pi", "Rho",
- NULL, "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega",
- /* 938 - 944 are not mapped */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta",
- "iota", "kappa", "lambda", "mu", "nu", "xi", "omicron", "pi", "rho",
- "sigmaf", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
- /* 970 - 976 are not mapped */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "thetasym", "upsih",
- NULL, NULL, NULL,
- "piv"
-};
-
-static entity_table_t ent_uni_punct[] = {
- /* 8194 */
- "ensp", "emsp", NULL, NULL, NULL, NULL, NULL,
- "thinsp", NULL, NULL, "zwnj", "zwj", "lrm", "rlm",
- NULL, NULL, NULL, "ndash", "mdash", NULL, NULL, NULL,
- /* 8216 */
- "lsquo", "rsquo", "sbquo", NULL, "ldquo", "rdquo", "bdquo", NULL,
- "dagger", "Dagger", "bull", NULL, NULL, NULL, "hellip",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "permil", NULL,
- /* 8242 */
- "prime", "Prime", NULL, NULL, NULL, NULL, NULL, "lsaquo", "rsaquo", NULL,
- NULL, NULL, "oline", NULL, NULL, NULL, NULL, NULL,
- "frasl"
-};
-
-static entity_table_t ent_uni_euro[] = {
- "euro"
-};
-
-static entity_table_t ent_uni_8465_8501[] = {
- /* 8465 */
- "image", NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8472 */
- "weierp", NULL, NULL, NULL,
- /* 8476 */
- "real", NULL, NULL, NULL, NULL, NULL,
- /* 8482 */
- "trade", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8501 */
- "alefsym",
-};
-
-static entity_table_t ent_uni_8592_9002[] = {
- /* 8592 (0x2190) */
- "larr", "uarr", "rarr", "darr", "harr", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8608 (0x21a0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8624 (0x21b0) */
- NULL, NULL, NULL, NULL, NULL, "crarr", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8640 (0x21c0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8656 (0x21d0) */
- "lArr", "uArr", "rArr", "dArr", "hArr", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8672 (0x21e0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8704 (0x2200) */
- "forall", NULL, "part", "exist", NULL, "empty", NULL, "nabla",
- "isin", "notin", NULL, "ni", NULL, NULL, NULL, "prod",
- /* 8720 (0x2210) */
- NULL, "sum", "minus", NULL, NULL, NULL, NULL, "lowast",
- NULL, NULL, "radic", NULL, NULL, "prop", "infin", NULL,
- /* 8736 (0x2220) */
- "ang", NULL, NULL, NULL, NULL, NULL, NULL, "and",
- "or", "cap", "cup", "int", NULL, NULL, NULL, NULL,
- /* 8752 (0x2230) */
- NULL, NULL, NULL, NULL, "there4", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, "sim", NULL, NULL, NULL,
- /* 8768 (0x2240) */
- NULL, NULL, NULL, NULL, NULL, "cong", NULL, NULL,
- "asymp", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8784 (0x2250) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8800 (0x2260) */
- "ne", "equiv", NULL, NULL, "le", "ge", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8816 (0x2270) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8832 (0x2280) */
- NULL, NULL, "sub", "sup", "nsub", NULL, "sube", "supe",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8848 (0x2290) */
- NULL, NULL, NULL, NULL, NULL, "oplus", NULL, "otimes",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8864 (0x22a0) */
- NULL, NULL, NULL, NULL, NULL, "perp", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8880 (0x22b0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8896 (0x22c0) */
- NULL, NULL, NULL, NULL, NULL, "sdot", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8912 (0x22d0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8928 (0x22e0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8944 (0x22f0) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8960 (0x2300) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "lceil", "rceil", "lfloor", "rfloor", NULL, NULL, NULL, NULL,
- /* 8976 (0x2310) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- /* 8992 (0x2320) */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, "lang", "rang"
-};
-
-static entity_table_t ent_uni_9674[] = {
- /* 9674 */
- "loz"
-};
-
-static entity_table_t ent_uni_9824_9830[] = {
- /* 9824 */
- "spades", NULL, NULL, "clubs", NULL, "hearts", "diams"
-};
-
-static entity_table_t ent_koi8r[] = {
- "#1105", /* "jo "*/
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, "#1025", /* "JO" */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "#1102", "#1072", "#1073", "#1094", "#1076", "#1077", "#1092",
- "#1075", "#1093", "#1080", "#1081", "#1082", "#1083", "#1084",
- "#1085", "#1086", "#1087", "#1103", "#1088", "#1089", "#1090",
- "#1091", "#1078", "#1074", "#1100", "#1099", "#1079", "#1096",
- "#1101", "#1097", "#1095", "#1098", "#1070", "#1040", "#1041",
- "#1062", "#1044", "#1045", "#1060", "#1043", "#1061", "#1048",
- "#1049", "#1050", "#1051", "#1052", "#1053", "#1054", "#1055",
- "#1071", "#1056", "#1057", "#1058", "#1059", "#1046", "#1042",
- "#1068", "#1067", "#1047", "#1064", "#1069", "#1065", "#1063",
- "#1066"
-};
-
-static entity_table_t ent_cp_1251[] = {
- "#1026", "#1027", "#8218", "#1107", "#8222", "hellip", "dagger",
- "Dagger", "euro", "permil", "#1033", "#8249", "#1034", "#1036",
- "#1035", "#1039", "#1106", "#8216", "#8217", "#8219", "#8220",
- "bull", "ndash", "mdash", NULL, "trade", "#1113", "#8250",
- "#1114", "#1116", "#1115", "#1119", "nbsp", "#1038", "#1118",
- "#1032", "curren", "#1168", "brvbar", "sect", "#1025", "copy",
- "#1028", "laquo", "not", "shy", "reg", "#1031", "deg", "plusmn",
- "#1030", "#1110", "#1169", "micro", "para", "middot", "#1105",
- "#8470", "#1108", "raquo", "#1112", "#1029", "#1109", "#1111",
- "#1040", "#1041", "#1042", "#1043", "#1044", "#1045", "#1046",
- "#1047", "#1048", "#1049", "#1050", "#1051", "#1052", "#1053",
- "#1054", "#1055", "#1056", "#1057", "#1058", "#1059", "#1060",
- "#1061", "#1062", "#1063", "#1064", "#1065", "#1066", "#1067",
- "#1068", "#1069", "#1070", "#1071", "#1072", "#1073", "#1074",
- "#1075", "#1076", "#1077", "#1078", "#1079", "#1080", "#1081",
- "#1082", "#1083", "#1084", "#1085", "#1086", "#1087", "#1088",
- "#1089", "#1090", "#1091", "#1092", "#1093", "#1094", "#1095",
- "#1096", "#1097", "#1098", "#1099", "#1100", "#1101", "#1102",
- "#1103"
-};
-
-static entity_table_t ent_iso_8859_5[] = {
- "#1056", "#1057", "#1058", "#1059", "#1060", "#1061", "#1062",
- "#1063", "#1064", "#1065", "#1066", "#1067", "#1068", "#1069",
- "#1070", "#1071", "#1072", "#1073", "#1074", "#1075", "#1076",
- "#1077", "#1078", "#1079", "#1080", "#1081", "#1082", "#1083",
- "#1084", "#1085", "#1086", "#1087", "#1088", "#1089", "#1090",
- "#1091", "#1092", "#1093", "#1094", "#1095", "#1096", "#1097",
- "#1098", "#1099", "#1100", "#1101", "#1102", "#1103", "#1104",
- "#1105", "#1106", "#1107", "#1108", "#1109", "#1110", "#1111",
- "#1112", "#1113", "#1114", "#1115", "#1116", "#1117", "#1118",
- "#1119"
-};
-
-static entity_table_t ent_cp_866[] = {
-
- "#9492", "#9524", "#9516", "#9500", "#9472", "#9532", "#9566",
- "#9567", "#9562", "#9556", "#9577", "#9574", "#9568", "#9552",
- "#9580", "#9575", "#9576", "#9572", "#9573", "#9561", "#9560",
- "#9554", "#9555", "#9579", "#9578", "#9496", "#9484", "#9608",
- "#9604", "#9612", "#9616", "#9600", "#1088", "#1089", "#1090",
- "#1091", "#1092", "#1093", "#1094", "#1095", "#1096", "#1097",
- "#1098", "#1099", "#1100", "#1101", "#1102", "#1103", "#1025",
- "#1105", "#1028", "#1108", "#1031", "#1111", "#1038", "#1118",
- "#176", "#8729", "#183", "#8730", "#8470", "#164", "#9632",
- "#160"
-};
-
-/* MacRoman has a couple of low-ascii chars that need mapping too */
-/* Vertical tab (ASCII 11) is often used to store line breaks inside */
-/* DB exports, this mapping changes it to a space */
-static entity_table_t ent_macroman[] = {
- "sp", NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, "quot", NULL,
- NULL, NULL, "amp", NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, "lt", NULL, "gt", NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, "Auml", "Aring", "Ccedil", "Eacute", "Ntilde", "Ouml",
- "Uuml", "aacute", "agrave", "acirc", "auml", "atilde", "aring",
- "ccedil", "eacute", "egrave", "ecirc", "euml", "iacute", "igrave",
- "icirc", "iuml", "ntilde", "oacute", "ograve", "ocirc", "ouml",
- "otilde", "uacute", "ugrave", "ucirc", "uuml", "dagger", "deg",
- "cent", "pound", "sect", "bull", "para", "szlig", "reg",
- "copy", "trade", "acute", "uml", "ne", "AElig", "Oslash",
- "infin", "plusmn", "le", "ge", "yen", "micro", "part",
- "sum", "prod", "pi", "int", "ordf", "ordm", "Omega",
- "aelig", "oslash", "iquest", "iexcl", "not", "radic", "fnof",
- "asymp", "#8710", "laquo", "raquo", "hellip", "nbsp", "Agrave",
- "Atilde", "Otilde", "OElig", "oelig", "ndash", "mdash", "ldquo",
- "rdquo", "lsquo", "rsquo", "divide", "loz", "yuml", "Yuml",
- "frasl", "euro", "lsaquo", "rsaquo", "#xFB01", "#xFB02", "Dagger",
- "middot", "sbquo", "bdquo", "permil", "Acirc", "Ecirc", "Aacute",
- "Euml", "Egrave", "Iacute", "Icirc", "Iuml", "Igrave", "Oacute",
- "Ocirc", "#xF8FF", "Ograve", "Uacute", "Ucirc", "Ugrave", "#305",
- "circ", "tilde", "macr", "#728", "#729", "#730", "cedil",
- "#733", "#731", "#711"
-};
-
-struct html_entity_map {
- enum entity_charset charset; /* charset identifier */
- unsigned int basechar; /* char code at start of table */
- unsigned int endchar; /* last char code in the table */
- entity_table_t *table; /* the table of mappings */
-};
-
-static const struct html_entity_map entity_map[] = {
- { cs_cp1252, 0x80, 0x9f, ent_cp_1252 },
- { cs_cp1252, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_8859_1, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_8859_15, 0xa0, 0xff, ent_iso_8859_15 },
- { cs_utf_8, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_utf_8, 338, 402, ent_uni_338_402 },
- { cs_utf_8, 710, 732, ent_uni_spacing },
- { cs_utf_8, 913, 982, ent_uni_greek },
- { cs_utf_8, 8194, 8260, ent_uni_punct },
- { cs_utf_8, 8364, 8364, ent_uni_euro },
- { cs_utf_8, 8465, 8501, ent_uni_8465_8501 },
- { cs_utf_8, 8592, 9002, ent_uni_8592_9002 },
- { cs_utf_8, 9674, 9674, ent_uni_9674 },
- { cs_utf_8, 9824, 9830, ent_uni_9824_9830 },
- { cs_big5, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_gb2312, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_big5hkscs, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_sjis, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_eucjp, 0xa0, 0xff, ent_iso_8859_1 },
- { cs_koi8r, 0xa3, 0xff, ent_koi8r },
- { cs_cp1251, 0x80, 0xff, ent_cp_1251 },
- { cs_8859_5, 0xc0, 0xff, ent_iso_8859_5 },
- { cs_cp866, 0xc0, 0xff, ent_cp_866 },
- { cs_macroman, 0x0b, 0xff, ent_macroman },
- { cs_terminator }
-};
-
-static const struct {
- const char *codeset;
- enum entity_charset charset;
-} charset_map[] = {
- { "ISO-8859-1", cs_8859_1 },
- { "ISO8859-1", cs_8859_1 },
- { "ISO-8859-15", cs_8859_15 },
- { "ISO8859-15", cs_8859_15 },
- { "utf-8", cs_utf_8 },
- { "cp1252", cs_cp1252 },
- { "Windows-1252", cs_cp1252 },
- { "1252", cs_cp1252 },
- { "BIG5", cs_big5 },
- { "950", cs_big5 },
- { "GB2312", cs_gb2312 },
- { "936", cs_gb2312 },
- { "BIG5-HKSCS", cs_big5hkscs },
- { "Shift_JIS", cs_sjis },
- { "SJIS", cs_sjis },
- { "932", cs_sjis },
- { "EUCJP", cs_eucjp },
- { "EUC-JP", cs_eucjp },
- { "KOI8-R", cs_koi8r },
- { "koi8-ru", cs_koi8r },
- { "koi8r", cs_koi8r },
- { "cp1251", cs_cp1251 },
- { "Windows-1251", cs_cp1251 },
- { "win-1251", cs_cp1251 },
- { "iso8859-5", cs_8859_5 },
- { "iso-8859-5", cs_8859_5 },
- { "cp866", cs_cp866 },
- { "866", cs_cp866 },
- { "ibm866", cs_cp866 },
- { "MacRoman", cs_macroman },
- { NULL }
-};
-
-static const struct {
- unsigned short charcode;
- char *entity;
- int entitylen;
- int flags;
-} basic_entities[] = {
- { '"', "&quot;", 6, ENT_HTML_QUOTE_DOUBLE },
- { '\'', "&#039;", 6, ENT_HTML_QUOTE_SINGLE },
- { '\'', "&#39;", 5, ENT_HTML_QUOTE_SINGLE },
- { '<', "&lt;", 4, 0 },
- { '>', "&gt;", 4, 0 },
- { 0, NULL, 0, 0 }
-};
-
-struct basic_entities_dec {
- unsigned short charcode;
- char entity[8];
- int entitylen;
-};
-
-#define MB_RETURN { \
- *newpos = pos; \
- mbseq[mbpos] = '\0'; \
- *mbseqlen = mbpos; \
- return this_char; }
-
-#define MB_WRITE(mbchar) { \
- mbspace--; \
- if (mbspace == 0) { \
- MB_RETURN; \
- } \
- mbseq[mbpos++] = (mbchar); }
-
-/* skip one byte and return */
-#define MB_FAILURE(pos) do { \
- *newpos = pos + 1; \
+/* Macro for disabling flag of translation of non-basic entities where this isn't supported.
+ * Not appropriate for html_entity_decode/htmlspecialchars_decode */
+#define LIMIT_ALL(all, doctype, charset) do { \
+ (all) = (all) && !CHARSET_PARTIAL_SUPPORT((charset)) && ((doctype) != ENT_HTML_DOC_XML1); \
+} while (0)
+
+#define MB_FAILURE(pos, advance) do { \
+ *cursor = pos + (advance); \
*status = FAILURE; \
return 0; \
} while (0)
-#define CHECK_LEN(pos, chars_need) \
- if (chars_need < 1) { \
- if((str_len - (pos)) < chars_need) { \
- *newpos = pos; \
- *status = FAILURE; \
- return 0; \
- } \
- } else { \
- if((str_len - (pos)) < chars_need) { \
- *newpos = pos + 1; \
- *status = FAILURE; \
- return 0; \
- } \
- }
+#define CHECK_LEN(pos, chars_need) ((str_len - (pos)) >= (chars_need))
+
+/* valid as single byte character or leading byte */
+#define utf8_lead(c) ((c) < 0x80 || ((c) >= 0xC2 && (c) <= 0xF4))
+/* whether it's actually valid depends on other stuff;
+ * this macro cannot check for non-shortest forms, surrogates or
+ * code points above 0x10FFFF */
+#define utf8_trail(c) ((c) >= 0x80 && (c) <= 0xBF)
+
+#define gb2312_lead(c) ((c) != 0x8E && (c) != 0x8F && (c) != 0xA0 && (c) != 0xFF)
+#define gb2312_trail(c) ((c) >= 0xA1 && (c) <= 0xFE)
+
+#define sjis_lead(c) ((c) != 0x80 && (c) != 0xA0 && (c) < 0xFD)
+#define sjis_trail(c) ((c) >= 0x40 && (c) != 0x7F && (c) < 0xFD)
/* {{{ get_next_char
*/
-inline static unsigned int get_next_char(enum entity_charset charset,
- unsigned char * str,
- int str_len,
- int * newpos,
- unsigned char * mbseq,
- int * mbseqlen,
+static inline unsigned int get_next_char(
+ enum entity_charset charset,
+ const unsigned char *str,
+ size_t str_len,
+ size_t *cursor,
int *status)
{
- int pos = *newpos;
- int mbpos = 0;
- int mbspace = *mbseqlen;
+ size_t pos = *cursor;
unsigned int this_char = 0;
- unsigned char next_char;
*status = SUCCESS;
+ assert(pos <= str_len);
- if (mbspace <= 0) {
- *mbseqlen = 0;
- CHECK_LEN(pos, 1);
- *newpos = pos + 1;
- return str[pos];
- }
+ if (!CHECK_LEN(pos, 1))
+ MB_FAILURE(pos, 1);
switch (charset) {
- case cs_utf_8:
- {
- unsigned char c;
- CHECK_LEN(pos, 1);
- c = str[pos];
- if (c < 0x80) {
- MB_WRITE(c);
- this_char = c;
- pos++;
- } else if (c < 0xc2) {
- MB_FAILURE(pos);
- } else if (c < 0xe0) {
- CHECK_LEN(pos, 2);
- if (str[pos + 1] < 0x80 || str[pos + 1] > 0xbf) {
- MB_FAILURE(pos);
- }
- this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f);
- if (this_char < 0x80) {
- MB_FAILURE(pos);
- }
- MB_WRITE((unsigned char)c);
- MB_WRITE((unsigned char)str[pos + 1]);
- pos += 2;
- } else if (c < 0xf0) {
- CHECK_LEN(pos, 3);
- if (str[pos + 1] < 0x80 || str[pos + 1] > 0xbf) {
- MB_FAILURE(pos);
- }
- if (str[pos + 2] < 0x80 || str[pos + 2] > 0xbf) {
- MB_FAILURE(pos);
- }
- this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f);
- if (this_char < 0x800) {
- MB_FAILURE(pos);
- } else if (this_char >= 0xd800 && this_char <= 0xdfff) {
- MB_FAILURE(pos);
- }
- MB_WRITE((unsigned char)c);
- MB_WRITE((unsigned char)str[pos + 1]);
- MB_WRITE((unsigned char)str[pos + 2]);
- pos += 3;
- } else if (c < 0xf5) {
- CHECK_LEN(pos, 4);
- if (str[pos + 1] < 0x80 || str[pos + 1] > 0xbf) {
- MB_FAILURE(pos);
- }
- if (str[pos + 2] < 0x80 || str[pos + 2] > 0xbf) {
- MB_FAILURE(pos);
- }
- if (str[pos + 3] < 0x80 || str[pos + 3] > 0xbf) {
- MB_FAILURE(pos);
- }
- this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f);
- if (this_char < 0x10000 || this_char > 0x10FFFF) {
- MB_FAILURE(pos);
- }
- MB_WRITE((unsigned char)c);
- MB_WRITE((unsigned char)str[pos + 1]);
- MB_WRITE((unsigned char)str[pos + 2]);
- MB_WRITE((unsigned char)str[pos + 3]);
- pos += 4;
+ case cs_utf_8:
+ {
+ /* We'll follow strategy 2. from section 3.6.1 of UTR #36:
+ * "In a reported illegal byte sequence, do not include any
+ * non-initial byte that encodes a valid character or is a leading
+ * byte for a valid sequence." */
+ unsigned char c;
+ c = str[pos];
+ if (c < 0x80) {
+ this_char = c;
+ pos++;
+ } else if (c < 0xc2) {
+ MB_FAILURE(pos, 1);
+ } else if (c < 0xe0) {
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+
+ if (!utf8_trail(str[pos + 1])) {
+ MB_FAILURE(pos, utf8_lead(str[pos + 1]) ? 1 : 2);
+ }
+ this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f);
+ if (this_char < 0x80) { /* non-shortest form */
+ MB_FAILURE(pos, 2);
+ }
+ pos += 2;
+ } else if (c < 0xf0) {
+ size_t avail = str_len - pos;
+
+ if (avail < 3 ||
+ !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2])) {
+ if (avail < 2 || utf8_lead(str[pos + 1]))
+ MB_FAILURE(pos, 1);
+ else if (avail < 3 || utf8_lead(str[pos + 2]))
+ MB_FAILURE(pos, 2);
+ else
+ MB_FAILURE(pos, 3);
+ }
+
+ this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f);
+ if (this_char < 0x800) { /* non-shortest form */
+ MB_FAILURE(pos, 3);
+ } else if (this_char >= 0xd800 && this_char <= 0xdfff) { /* surrogate */
+ MB_FAILURE(pos, 3);
+ }
+ pos += 3;
+ } else if (c < 0xf5) {
+ size_t avail = str_len - pos;
+
+ if (avail < 4 ||
+ !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2]) ||
+ !utf8_trail(str[pos + 3])) {
+ if (avail < 2 || utf8_lead(str[pos + 1]))
+ MB_FAILURE(pos, 1);
+ else if (avail < 3 || utf8_lead(str[pos + 2]))
+ MB_FAILURE(pos, 2);
+ else if (avail < 4 || utf8_lead(str[pos + 3]))
+ MB_FAILURE(pos, 3);
+ else
+ MB_FAILURE(pos, 4);
+ }
+
+ this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f);
+ if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */
+ MB_FAILURE(pos, 4);
+ }
+ pos += 4;
+ } else {
+ MB_FAILURE(pos, 1);
+ }
+ }
+ break;
+
+ case cs_big5:
+ /* reference http://demo.icu-project.org/icu-bin/convexp?conv=big5 */
+ {
+ unsigned char c = str[pos];
+ if (c >= 0x81 && c <= 0xFE) {
+ unsigned char next;
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+
+ next = str[pos + 1];
+
+ if ((next >= 0x40 && next <= 0x7E) ||
+ (next >= 0xA1 && next <= 0xFE)) {
+ this_char = (c << 8) | next;
} else {
- MB_FAILURE(pos);
+ MB_FAILURE(pos, 1);
}
+ pos += 2;
+ } else {
+ this_char = c;
+ pos += 1;
}
- break;
- case cs_big5:
- case cs_gb2312:
- case cs_big5hkscs:
- {
- CHECK_LEN(pos, 1);
- this_char = str[pos++];
- /* check if this is the first of a 2-byte sequence */
- if (this_char >= 0x81 && this_char <= 0xfe) {
- /* peek at the next char */
- CHECK_LEN(pos, 1);
- next_char = str[pos++];
- if ((next_char >= 0x40 && next_char <= 0x7e) ||
- (next_char >= 0xa1 && next_char <= 0xfe)) {
- /* yes, this a wide char */
- MB_WRITE(this_char);
- MB_WRITE(next_char);
- this_char = (this_char << 8) | next_char;
- } else {
- MB_FAILURE(pos);
- }
+ }
+ break;
+
+ case cs_big5hkscs:
+ {
+ unsigned char c = str[pos];
+ if (c >= 0x81 && c <= 0xFE) {
+ unsigned char next;
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+
+ next = str[pos + 1];
+
+ if ((next >= 0x40 && next <= 0x7E) ||
+ (next >= 0xA1 && next <= 0xFE)) {
+ this_char = (c << 8) | next;
+ } else if (next != 0x80 && next != 0xFF) {
+ MB_FAILURE(pos, 1);
} else {
- MB_WRITE(this_char);
+ MB_FAILURE(pos, 2);
}
+ pos += 2;
+ } else {
+ this_char = c;
+ pos += 1;
}
- break;
- case cs_sjis:
- {
- CHECK_LEN(pos, 1);
- this_char = str[pos++];
- /* check if this is the first of a 2-byte sequence */
- if ((this_char >= 0x81 && this_char <= 0x9f) ||
- (this_char >= 0xe0 && this_char <= 0xfc)) {
- /* peek at the next char */
- CHECK_LEN(pos, 1);
- next_char = str[pos++];
- if ((next_char >= 0x40 && next_char <= 0x7e) ||
- (next_char >= 0x80 && next_char <= 0xfc))
- {
- /* yes, this a wide char */
- MB_WRITE(this_char);
- MB_WRITE(next_char);
- this_char = (this_char << 8) | next_char;
- } else {
- MB_FAILURE(pos);
- }
+ }
+ break;
+
+ case cs_gb2312: /* EUC-CN */
+ {
+ unsigned char c = str[pos];
+ if (c >= 0xA1 && c <= 0xFE) {
+ unsigned char next;
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+
+ next = str[pos + 1];
+
+ if (gb2312_trail(next)) {
+ this_char = (c << 8) | next;
+ } else if (gb2312_lead(next)) {
+ MB_FAILURE(pos, 1);
} else {
- MB_WRITE(this_char);
+ MB_FAILURE(pos, 2);
}
- break;
+ pos += 2;
+ } else if (gb2312_lead(c)) {
+ this_char = c;
+ pos += 1;
+ } else {
+ MB_FAILURE(pos, 1);
}
- case cs_eucjp:
- {
- CHECK_LEN(pos, 1);
- this_char = str[pos++];
- /* check if this is the first of a multi-byte sequence */
- if (this_char >= 0xa1 && this_char <= 0xfe) {
- /* peek at the next char */
- CHECK_LEN(pos, 1);
- next_char = str[pos++];
- if (next_char >= 0xa1 && next_char <= 0xfe) {
- /* yes, this a jis kanji char */
- MB_WRITE(this_char);
- MB_WRITE(next_char);
- this_char = (this_char << 8) | next_char;
- } else {
- MB_FAILURE(pos);
- }
- } else if (this_char == 0x8e) {
- /* peek at the next char */
- CHECK_LEN(pos, 1);
- next_char = str[pos++];
- if (next_char >= 0xa1 && next_char <= 0xdf) {
- /* JIS X 0201 kana */
- MB_WRITE(this_char);
- MB_WRITE(next_char);
- this_char = (this_char << 8) | next_char;
- } else {
- MB_FAILURE(pos);
- }
- } else if (this_char == 0x8f) {
- /* peek at the next two char */
- unsigned char next2_char;
- CHECK_LEN(pos, 2);
- next_char = str[pos];
- next2_char = str[pos + 1];
- pos += 2;
- if ((next_char >= 0xa1 && next_char <= 0xfe) &&
- (next2_char >= 0xa1 && next2_char <= 0xfe)) {
- /* JIS X 0212 hojo-kanji */
- MB_WRITE(this_char);
- MB_WRITE(next_char);
- MB_WRITE(next2_char);
- this_char = (this_char << 16) | (next_char << 8) | next2_char;
- } else {
- MB_FAILURE(pos);
- }
+ }
+ break;
+
+ case cs_sjis:
+ {
+ unsigned char c = str[pos];
+ if ((c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xFC)) {
+ unsigned char next;
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+
+ next = str[pos + 1];
+
+ if (sjis_trail(next)) {
+ this_char = (c << 8) | next;
+ } else if (sjis_lead(next)) {
+ MB_FAILURE(pos, 1);
} else {
- MB_WRITE(this_char);
+ MB_FAILURE(pos, 2);
}
- break;
+ pos += 2;
+ } else if (c < 0x80 || (c >= 0xA1 && c <= 0xDF)) {
+ this_char = c;
+ pos += 1;
+ } else {
+ MB_FAILURE(pos, 1);
}
- default:
- /* single-byte charsets */
- CHECK_LEN(pos, 1);
- this_char = str[pos++];
- MB_WRITE(this_char);
- break;
+ }
+ break;
+
+ case cs_eucjp:
+ {
+ unsigned char c = str[pos];
+
+ if (c >= 0xA1 && c <= 0xFE) {
+ unsigned next;
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+ next = str[pos + 1];
+
+ if (next >= 0xA1 && next <= 0xFE) {
+ /* this a jis kanji char */
+ this_char = (c << 8) | next;
+ } else {
+ MB_FAILURE(pos, (next != 0xA0 && next != 0xFF) ? 1 : 2);
+ }
+ pos += 2;
+ } else if (c == 0x8E) {
+ unsigned next;
+ if (!CHECK_LEN(pos, 2))
+ MB_FAILURE(pos, 1);
+
+ next = str[pos + 1];
+ if (next >= 0xA1 && next <= 0xDF) {
+ /* JIS X 0201 kana */
+ this_char = (c << 8) | next;
+ } else {
+ MB_FAILURE(pos, (next != 0xA0 && next != 0xFF) ? 1 : 2);
+ }
+ pos += 2;
+ } else if (c == 0x8F) {
+ size_t avail = str_len - pos;
+
+ if (avail < 3 || !(str[pos + 1] >= 0xA1 && str[pos + 1] <= 0xFE) ||
+ !(str[pos + 2] >= 0xA1 && str[pos + 2] <= 0xFE)) {
+ if (avail < 2 || (str[pos + 1] != 0xA0 && str[pos + 1] != 0xFF))
+ MB_FAILURE(pos, 1);
+ else if (avail < 3 || (str[pos + 2] != 0xA0 && str[pos + 2] != 0xFF))
+ MB_FAILURE(pos, 2);
+ else
+ MB_FAILURE(pos, 3);
+ } else {
+ /* JIS X 0212 hojo-kanji */
+ this_char = (c << 16) | (str[pos + 1] << 8) | str[pos + 2];
+ }
+ pos += 3;
+ } else if (c != 0xA0 && c != 0xFF) {
+ /* character encoded in 1 code unit */
+ this_char = c;
+ pos += 1;
+ } else {
+ MB_FAILURE(pos, 1);
+ }
+ }
+ break;
+ default:
+ /* single-byte charsets */
+ this_char = str[pos++];
+ break;
}
- MB_RETURN;
+
+ *cursor = pos;
+ return this_char;
+}
+/* }}} */
+
+/* {{{ php_next_utf8_char
+ * Public interface for get_next_char used with UTF-8 */
+ PHPAPI unsigned int php_next_utf8_char(
+ const unsigned char *str,
+ size_t str_len,
+ size_t *cursor,
+ int *status)
+{
+ return get_next_char(cs_utf_8, str, str_len, cursor, status);
}
/* }}} */
/* {{{ entity_charset determine_charset
* returns the charset identifier based on current locale or a hint.
- * defaults to iso-8859-1 */
+ * defaults to UTF-8 */
static enum entity_charset determine_charset(char *charset_hint TSRMLS_DC)
{
int i;
- enum entity_charset charset = cs_8859_1;
+ enum entity_charset charset = cs_utf_8;
int len = 0;
- zval *uf_result = NULL;
+ const zend_encoding *zenc;
- /* Guarantee default behaviour for backwards compatibility */
+ /* Default is now UTF-8 */
if (charset_hint == NULL)
- return cs_8859_1;
+ return cs_utf_8;
if ((len = strlen(charset_hint)) != 0) {
goto det_charset;
}
-#if HAVE_MBSTRING
-#if !defined(COMPILE_DL_MBSTRING)
- /* XXX: Ugly things. Why don't we look for a more sophisticated way? */
- switch (MBSTRG(current_internal_encoding)) {
- case mbfl_no_encoding_8859_1:
- return cs_8859_1;
-
- case mbfl_no_encoding_utf8:
- return cs_utf_8;
-
- case mbfl_no_encoding_euc_jp:
- case mbfl_no_encoding_eucjp_win:
- return cs_eucjp;
-
- case mbfl_no_encoding_sjis:
- case mbfl_no_encoding_sjis_open:
- case mbfl_no_encoding_cp932:
- return cs_sjis;
-
- case mbfl_no_encoding_cp1252:
- return cs_cp1252;
-
- case mbfl_no_encoding_8859_15:
- return cs_8859_15;
-
- case mbfl_no_encoding_big5:
- return cs_big5;
-
- case mbfl_no_encoding_euc_cn:
- case mbfl_no_encoding_hz:
- case mbfl_no_encoding_cp936:
- return cs_gb2312;
-
- case mbfl_no_encoding_koi8r:
- return cs_koi8r;
-
- case mbfl_no_encoding_cp866:
- return cs_cp866;
-
- case mbfl_no_encoding_cp1251:
- return cs_cp1251;
-
- case mbfl_no_encoding_8859_5:
- return cs_8859_5;
-
- default:
- ;
- }
-#else
- {
- zval nm_mb_internal_encoding;
-
- ZVAL_STRING(&nm_mb_internal_encoding, "mb_internal_encoding", 0);
-
- if (call_user_function_ex(CG(function_table), NULL, &nm_mb_internal_encoding, &uf_result, 0, NULL, 1, NULL TSRMLS_CC) != FAILURE) {
- charset_hint = Z_STRVAL_P(uf_result);
- len = Z_STRLEN_P(uf_result);
-
- if (charset_hint != NULL && len != 0) {
- if (len == 4) { /* sizeof(none|auto|pass)-1 */
- if (!memcmp("pass", charset_hint, sizeof("pass") - 1) ||
- !memcmp("auto", charset_hint, sizeof("auto") - 1) ||
- !memcmp("none", charset_hint, sizeof("none") - 1)) {
-
- charset_hint = NULL;
- len = 0;
- }
- } else {
- /* Jump to det_charset only if mbstring isn't one of above eq pass, auto, none.
- Otherwise try default_charset next */
- goto det_charset;
- }
+ zenc = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ if (zenc != NULL) {
+ charset_hint = (char *)zend_multibyte_get_encoding_name(zenc);
+ if (charset_hint != NULL && (len=strlen(charset_hint)) != 0) {
+ if ((len == 4) /* sizeof (none|auto|pass) */ &&
+ (!memcmp("pass", charset_hint, 4) ||
+ !memcmp("auto", charset_hint, 4) ||
+ !memcmp("auto", charset_hint, 4))) {
+ charset_hint = NULL;
+ len = 0;
+ } else {
+ goto det_charset;
}
}
}
-#endif
-#endif
charset_hint = SG(default_charset);
if (charset_hint != NULL && (len=strlen(charset_hint)) != 0) {
@@ -860,22 +447,21 @@ det_charset:
}
}
if (!found) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "charset `%s' not supported, assuming iso-8859-1",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "charset `%s' not supported, assuming utf-8",
charset_hint);
}
}
- if (uf_result != NULL) {
- zval_ptr_dtor(&uf_result);
- }
return charset;
}
/* }}} */
/* {{{ php_utf32_utf8 */
-size_t php_utf32_utf8(unsigned char *buf, unsigned k)
+static inline size_t php_utf32_utf8(unsigned char *buf, unsigned k)
{
size_t retval = 0;
+ /* assert(0x0 <= k <= 0x10FFFF); */
+
if (k < 0x80) {
buf[0] = k;
retval = 1;
@@ -888,387 +474,957 @@ size_t php_utf32_utf8(unsigned char *buf, unsigned k)
buf[1] = 0x80 | ((k >> 6) & 0x3f);
buf[2] = 0x80 | (k & 0x3f);
retval = 3;
- } else if (k < 0x200000) {
+ } else {
buf[0] = 0xf0 | (k >> 18);
buf[1] = 0x80 | ((k >> 12) & 0x3f);
buf[2] = 0x80 | ((k >> 6) & 0x3f);
buf[3] = 0x80 | (k & 0x3f);
retval = 4;
- } else if (k < 0x4000000) {
- buf[0] = 0xf8 | (k >> 24);
- buf[1] = 0x80 | ((k >> 18) & 0x3f);
- buf[2] = 0x80 | ((k >> 12) & 0x3f);
- buf[3] = 0x80 | ((k >> 6) & 0x3f);
- buf[4] = 0x80 | (k & 0x3f);
- retval = 5;
- } else {
- buf[0] = 0xfc | (k >> 30);
- buf[1] = 0x80 | ((k >> 24) & 0x3f);
- buf[2] = 0x80 | ((k >> 18) & 0x3f);
- buf[3] = 0x80 | ((k >> 12) & 0x3f);
- buf[4] = 0x80 | ((k >> 6) & 0x3f);
- buf[5] = 0x80 | (k & 0x3f);
- retval = 6;
}
- buf[retval] = '\0';
+ /* UTF-8 has been restricted to max 4 bytes since RFC 3629 */
return retval;
}
/* }}} */
-/* {{{ php_unescape_html_entities
- */
-PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset TSRMLS_DC)
+/* {{{ php_mb2_int_to_char
+ * Convert back big endian int representation of sequence of one or two 8-bit code units. */
+static inline size_t php_mb2_int_to_char(unsigned char *buf, unsigned k)
{
- int retlen;
- int j, k;
- char *replaced, *ret, *p, *q, *lim, *next;
- enum entity_charset charset = determine_charset(hint_charset TSRMLS_CC);
- unsigned char replacement[15];
- int replacement_len;
+ assert(k <= 0xFFFFU);
+ /* one or two bytes */
+ if (k <= 0xFFU) { /* 1 */
+ buf[0] = k;
+ return 1U;
+ } else { /* 2 */
+ buf[0] = k >> 8;
+ buf[1] = k & 0xFFU;
+ return 2U;
+ }
+}
+/* }}} */
- ret = estrndup(old, oldlen);
- retlen = oldlen;
- if (!retlen) {
- goto empty_source;
+/* {{{ php_mb3_int_to_char
+ * Convert back big endian int representation of sequence of one to three 8-bit code units.
+ * For EUC-JP. */
+static inline size_t php_mb3_int_to_char(unsigned char *buf, unsigned k)
+{
+ assert(k <= 0xFFFFFFU);
+ /* one to three bytes */
+ if (k <= 0xFFU) { /* 1 */
+ buf[0] = k;
+ return 1U;
+ } else if (k <= 0xFFFFU) { /* 2 */
+ buf[0] = k >> 8;
+ buf[1] = k & 0xFFU;
+ return 2U;
+ } else {
+ buf[0] = k >> 16;
+ buf[1] = (k >> 8) & 0xFFU;
+ buf[2] = k & 0xFFU;
+ return 3U;
}
+}
+/* }}} */
+
+
+/* {{{ unimap_bsearc_cmp
+ * Binary search of unicode code points in unicode <--> charset mapping.
+ * Returns the code point in the target charset (whose mapping table was given) or 0 if
+ * the unicode code point is not in the table.
+ */
+static inline unsigned char unimap_bsearch(const uni_to_enc *table, unsigned code_key_a, size_t num)
+{
+ const uni_to_enc *l = table,
+ *h = &table[num-1],
+ *m;
+ unsigned short code_key;
+
+ /* we have no mappings outside the BMP */
+ if (code_key_a > 0xFFFFU)
+ return 0;
+
+ code_key = (unsigned short) code_key_a;
- if (all) {
- /* look for a match in the maps for this charset */
- for (j = 0; entity_map[j].charset != cs_terminator; j++) {
- if (entity_map[j].charset != charset)
- continue;
+ while (l <= h) {
+ m = l + (h - l) / 2;
+ if (code_key < m->un_code_point)
+ h = m - 1;
+ else if (code_key > m->un_code_point)
+ l = m + 1;
+ else
+ return m->cs_code;
+ }
+ return 0;
+}
+/* }}} */
- for (k = entity_map[j].basechar; k <= entity_map[j].endchar; k++) {
- unsigned char entity[32];
- int entity_length = 0;
+/* {{{ map_from_unicode */
+static inline int map_from_unicode(unsigned code, enum entity_charset charset, unsigned *res)
+{
+ unsigned char found;
+ const uni_to_enc *table;
+ size_t table_size;
- if (entity_map[j].table[k - entity_map[j].basechar] == NULL)
- continue;
+ switch (charset) {
+ case cs_8859_1:
+ /* identity mapping of code points to unicode */
+ if (code > 0xFF) {
+ return FAILURE;
+ }
+ *res = code;
+ break;
- entity_length = slprintf(entity, sizeof(entity), "&%s;", entity_map[j].table[k - entity_map[j].basechar]);
- if (entity_length >= sizeof(entity)) {
- continue;
- }
+ case cs_8859_5:
+ if (code <= 0xA0 || code == 0xAD /* soft hyphen */) {
+ *res = code;
+ } else if (code == 0x2116) {
+ *res = 0xF0; /* numero sign */
+ } else if (code == 0xA7) {
+ *res = 0xFD; /* section sign */
+ } else if (code >= 0x0401 && code <= 0x044F) {
+ if (code == 0x040D || code == 0x0450 || code == 0x045D)
+ return FAILURE;
+ *res = code - 0x360;
+ } else {
+ return FAILURE;
+ }
+ break;
+
+ case cs_8859_15:
+ if (code < 0xA4 || (code > 0xBE && code <= 0xFF)) {
+ *res = code;
+ } else { /* between A4 and 0xBE */
+ found = unimap_bsearch(unimap_iso885915,
+ code, sizeof(unimap_iso885915) / sizeof(*unimap_iso885915));
+ if (found)
+ *res = found;
+ else
+ return FAILURE;
+ }
+ break;
- /* When we have MBCS entities in the tables above, this will need to handle it */
- replacement_len = 0;
- switch (charset) {
- case cs_8859_1:
- case cs_cp1252:
- case cs_8859_15:
- case cs_cp1251:
- case cs_8859_5:
- case cs_cp866:
- case cs_koi8r:
- replacement[0] = k;
- replacement[1] = '\0';
- replacement_len = 1;
- break;
-
- case cs_big5:
- case cs_gb2312:
- case cs_big5hkscs:
- case cs_sjis:
- case cs_eucjp:
- /* we cannot properly handle those multibyte encodings
- * with php_str_to_str. skip it. */
- continue;
+ case cs_cp1252:
+ if (code <= 0x7F || (code >= 0xA0 && code <= 0xFF)) {
+ *res = code;
+ } else {
+ found = unimap_bsearch(unimap_win1252,
+ code, sizeof(unimap_win1252) / sizeof(*unimap_win1252));
+ if (found)
+ *res = found;
+ else
+ return FAILURE;
+ }
+ break;
- case cs_utf_8:
- replacement_len = php_utf32_utf8(replacement, k);
- break;
+ case cs_macroman:
+ if (code == 0x7F)
+ return FAILURE;
+ table = unimap_macroman;
+ table_size = sizeof(unimap_macroman) / sizeof(*unimap_macroman);
+ goto table_over_7F;
+ case cs_cp1251:
+ table = unimap_win1251;
+ table_size = sizeof(unimap_win1251) / sizeof(*unimap_win1251);
+ goto table_over_7F;
+ case cs_koi8r:
+ table = unimap_koi8r;
+ table_size = sizeof(unimap_koi8r) / sizeof(*unimap_koi8r);
+ goto table_over_7F;
+ case cs_cp866:
+ table = unimap_cp866;
+ table_size = sizeof(unimap_cp866) / sizeof(*unimap_cp866);
+
+table_over_7F:
+ if (code <= 0x7F) {
+ *res = code;
+ } else {
+ found = unimap_bsearch(table, code, table_size);
+ if (found)
+ *res = found;
+ else
+ return FAILURE;
+ }
+ break;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot yet handle MBCS!");
- efree(ret);
- return NULL;
- }
+ /* from here on, only map the possible characters in the ASCII range.
+ * to improve support here, it's a matter of building the unicode mappings.
+ * See <http://www.unicode.org/Public/6.0.0/ucd/Unihan.zip> */
+ case cs_sjis:
+ case cs_eucjp:
+ /* we interpret 0x5C as the Yen symbol. This is not universal.
+ * See <http://www.w3.org/Submission/japanese-xml/#ambiguity_of_yen> */
+ if (code >= 0x20 && code <= 0x7D) {
+ if (code == 0x5C)
+ return FAILURE;
+ *res = code;
+ } else {
+ return FAILURE;
+ }
+ break;
- if (php_memnstr(ret, entity, entity_length, ret+retlen)) {
- replaced = php_str_to_str(ret, retlen, entity, entity_length, replacement, replacement_len, &retlen);
- efree(ret);
- ret = replaced;
- }
- }
+ case cs_big5:
+ case cs_big5hkscs:
+ case cs_gb2312:
+ if (code >= 0x20 && code <= 0x7D) {
+ *res = code;
+ } else {
+ return FAILURE;
}
+ break;
+
+ default:
+ return FAILURE;
}
- for (j = 0; basic_entities[j].charcode != 0; j++) {
+ return SUCCESS;
+}
+/* }}} */
- if (basic_entities[j].flags && (quote_style & basic_entities[j].flags) == 0)
- continue;
-
- replacement[0] = (unsigned char)basic_entities[j].charcode;
- replacement[1] = '\0';
+/* {{{ */
+static inline void map_to_unicode(unsigned code, const enc_to_uni *table, unsigned *res)
+{
+ /* only single byte encodings are currently supported; assumed code <= 0xFF */
+ *res = table->inner[ENT_ENC_TO_UNI_STAGE1(code)]->uni_cp[ENT_ENC_TO_UNI_STAGE2(code)];
+}
+/* }}} */
+
+/* {{{ unicode_cp_is_allowed */
+static inline int unicode_cp_is_allowed(unsigned uni_cp, int document_type)
+{
+ /* XML 1.0 HTML 4.01 HTML 5
+ * 0x09..0x0A 0x09..0x0A 0x09..0x0A
+ * 0x0D 0x0D 0x0C..0x0D
+ * 0x0020..0xD7FF 0x20..0x7E 0x20..0x7E
+ * 0x00A0..0xD7FF 0x00A0..0xD7FF
+ * 0xE000..0xFFFD 0xE000..0x10FFFF 0xE000..0xFDCF
+ * 0x010000..0x10FFFF 0xFDF0..0x10FFFF (*)
+ *
+ * (*) exclude code points where ((code & 0xFFFF) >= 0xFFFE)
+ *
+ * References:
+ * XML 1.0: <http://www.w3.org/TR/REC-xml/#charsets>
+ * HTML 4.01: <http://www.w3.org/TR/1999/PR-html40-19990824/sgml/sgmldecl.html>
+ * HTML 5: <http://dev.w3.org/html5/spec/Overview.html#preprocessing-the-input-stream>
+ *
+ * Not sure this is the relevant part for HTML 5, though. I opted to
+ * disallow the characters that would result in a parse error when
+ * preprocessing of the input stream. See also section 8.1.3.
+ *
+ * It's unclear if XHTML 1.0 allows C1 characters. I'll opt to apply to
+ * XHTML 1.0 the same rules as for XML 1.0.
+ * See <http://cmsmcq.com/2007/C1.xml>.
+ */
+
+ switch (document_type) {
+ case ENT_HTML_DOC_HTML401:
+ return (uni_cp >= 0x20 && uni_cp <= 0x7E) ||
+ (uni_cp == 0x0A || uni_cp == 0x09 || uni_cp == 0x0D) ||
+ (uni_cp >= 0xA0 && uni_cp <= 0xD7FF) ||
+ (uni_cp >= 0xE000 && uni_cp <= 0x10FFFF);
+ case ENT_HTML_DOC_HTML5:
+ return (uni_cp >= 0x20 && uni_cp <= 0x7E) ||
+ (uni_cp >= 0x09 && uni_cp <= 0x0D && uni_cp != 0x0B) || /* form feed U+0C allowed */
+ (uni_cp >= 0xA0 && uni_cp <= 0xD7FF) ||
+ (uni_cp >= 0xE000 && uni_cp <= 0x10FFFF &&
+ ((uni_cp & 0xFFFF) < 0xFFFE) && /* last two of each plane (nonchars) disallowed */
+ (uni_cp < 0xFDD0 || uni_cp > 0xFDEF)); /* U+FDD0-U+FDEF (nonchars) disallowed */
+ case ENT_HTML_DOC_XHTML:
+ case ENT_HTML_DOC_XML1:
+ return (uni_cp >= 0x20 && uni_cp <= 0xD7FF) ||
+ (uni_cp == 0x0A || uni_cp == 0x09 || uni_cp == 0x0D) ||
+ (uni_cp >= 0xE000 && uni_cp <= 0x10FFFF && uni_cp != 0xFFFE && uni_cp != 0xFFFF);
+ default:
+ return 1;
+ }
+}
+/* }}} */
+
+/* {{{ unicode_cp_is_allowed */
+static inline int numeric_entity_is_allowed(unsigned uni_cp, int document_type)
+{
+ /* less restrictive than unicode_cp_is_allowed */
+ switch (document_type) {
+ case ENT_HTML_DOC_HTML401:
+ /* all non-SGML characters (those marked with UNUSED in DESCSET) should be
+ * representable with numeric entities */
+ return uni_cp <= 0x10FFFF;
+ case ENT_HTML_DOC_HTML5:
+ /* 8.1.4. The numeric character reference forms described above are allowed to
+ * reference any Unicode code point other than U+0000, U+000D, permanently
+ * undefined Unicode characters (noncharacters), and control characters other
+ * than space characters (U+0009, U+000A, U+000C and U+000D) */
+ /* seems to allow surrogate characters, then */
+ return (uni_cp >= 0x20 && uni_cp <= 0x7E) ||
+ (uni_cp >= 0x09 && uni_cp <= 0x0C && uni_cp != 0x0B) || /* form feed U+0C allowed, but not U+0D */
+ (uni_cp >= 0xA0 && uni_cp <= 0x10FFFF &&
+ ((uni_cp & 0xFFFF) < 0xFFFE) && /* last two of each plane (nonchars) disallowed */
+ (uni_cp < 0xFDD0 || uni_cp > 0xFDEF)); /* U+FDD0-U+FDEF (nonchars) disallowed */
+ case ENT_HTML_DOC_XHTML:
+ case ENT_HTML_DOC_XML1:
+ /* OTOH, XML 1.0 requires "character references to match the production for Char
+ * See <http://www.w3.org/TR/REC-xml/#NT-CharRef> */
+ return unicode_cp_is_allowed(uni_cp, document_type);
+ default:
+ return 1;
+ }
+}
+/* }}} */
+
+/* {{{ process_numeric_entity
+ * Auxiliary function to traverse_for_entities.
+ * On input, *buf should point to the first character after # and on output, it's the last
+ * byte read, no matter if there was success or insuccess.
+ */
+static inline int process_numeric_entity(const char **buf, unsigned *code_point)
+{
+ long code_l;
+ int hexadecimal = (**buf == 'x' || **buf == 'X'); /* TODO: XML apparently disallows "X" */
+ char *endptr;
+
+ if (hexadecimal && (**buf != '\0'))
+ (*buf)++;
+
+ /* strtol allows whitespace and other stuff in the beginning
+ * we're not interested */
+ if ((hexadecimal && !isxdigit(**buf)) ||
+ (!hexadecimal && !isdigit(**buf))) {
+ return FAILURE;
+ }
+
+ code_l = strtol(*buf, &endptr, hexadecimal ? 16 : 10);
+ /* we're guaranteed there were valid digits, so *endptr > buf */
+ *buf = endptr;
+
+ if (**buf != ';')
+ return FAILURE;
+
+ /* many more are invalid, but that depends on whether it's HTML
+ * (and which version) or XML. */
+ if (code_l > 0x10FFFFL)
+ return FAILURE;
+
+ if (code_point != NULL)
+ *code_point = (unsigned)code_l;
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ process_named_entity */
+static inline int process_named_entity_html(const char **buf, const char **start, size_t *length)
+{
+ *start = *buf;
+
+ /* "&" is represented by a 0x26 in all supported encodings. That means
+ * the byte after represents a character or is the leading byte of an
+ * sequence of 8-bit code units. If in the ranges below, it represents
+ * necessarily a alpha character because none of the supported encodings
+ * has an overlap with ASCII in the leading byte (only on the second one) */
+ while ((**buf >= 'a' && **buf <= 'z') ||
+ (**buf >= 'A' && **buf <= 'Z') ||
+ (**buf >= '0' && **buf <= '9')) {
+ (*buf)++;
+ }
+
+ if (**buf != ';')
+ return FAILURE;
+
+ /* cast to size_t OK as the quantity is always non-negative */
+ *length = *buf - *start;
+
+ if (*length == 0)
+ return FAILURE;
+
+ return SUCCESS;
+}
+/* }}} */
- if (php_memnstr(ret, basic_entities[j].entity, basic_entities[j].entitylen, ret+retlen)) {
- replaced = php_str_to_str(ret, retlen, basic_entities[j].entity, basic_entities[j].entitylen, replacement, 1, &retlen);
- efree(ret);
- ret = replaced;
+/* {{{ resolve_named_entity_html */
+static inline int resolve_named_entity_html(const char *start, size_t length, const entity_ht *ht, unsigned *uni_cp1, unsigned *uni_cp2)
+{
+ const entity_cp_map *s;
+ ulong hash = zend_inline_hash_func(start, length);
+
+ s = ht->buckets[hash % ht->num_elems];
+ while (s->entity) {
+ if (s->entity_len == length) {
+ if (memcmp(start, s->entity, length) == 0) {
+ *uni_cp1 = s->codepoint1;
+ *uni_cp2 = s->codepoint2;
+ return SUCCESS;
+ }
}
+ s++;
}
+ return FAILURE;
+}
+/* }}} */
- /* replace numeric entities & "&amp;" */
- lim = ret + retlen;
- for (p = ret, q = ret; p < lim;) {
- int code;
+static inline size_t write_octet_sequence(unsigned char *buf, enum entity_charset charset, unsigned code) {
+ /* code is not necessarily a unicode code point */
+ switch (charset) {
+ case cs_utf_8:
+ return php_utf32_utf8(buf, code);
+
+ case cs_8859_1:
+ case cs_cp1252:
+ case cs_8859_15:
+ case cs_koi8r:
+ case cs_cp1251:
+ case cs_8859_5:
+ case cs_cp866:
+ case cs_macroman:
+ /* single byte stuff */
+ *buf = code;
+ return 1;
+
+ case cs_big5:
+ case cs_big5hkscs:
+ case cs_sjis:
+ case cs_gb2312:
+ /* we don't have complete unicode mappings for these yet in entity_decode,
+ * and we opt to pass through the octet sequences for these in htmlentities
+ * instead of converting to an int and then converting back. */
+#if 0
+ return php_mb2_int_to_char(buf, code);
+#else
+#ifdef ZEND_DEBUG
+ assert(code <= 0xFFU);
+#endif
+ *buf = code;
+ return 1;
+#endif
- if (p[0] == '&') {
- if (p + 2 < lim) {
- if (p[1] == '#') {
- int invalid_code = 0;
+ case cs_eucjp:
+#if 0 /* idem */
+ return php_mb2_int_to_char(buf, code);
+#else
+#ifdef ZEND_DEBUG
+ assert(code <= 0xFFU);
+#endif
+ *buf = code;
+ return 1;
+#endif
- if (p[2] == 'x' || p[2] == 'X') {
- code = strtol(p + 3, &next, 16);
- } else {
- code = strtol(p + 2, &next, 10);
- }
+ default:
+ assert(0);
+ return 0;
+ }
+}
- if ((code == '\'' && !(quote_style & ENT_HTML_QUOTE_SINGLE)) ||
- (code == '"' && !(quote_style & ENT_HTML_QUOTE_DOUBLE))) {
- invalid_code = 1;
- }
+/* {{{ traverse_for_entities
+ * Auxiliary function to php_unescape_html_entities().
+ * - The argument "all" determines if all numeric entities are decode or only those
+ * that correspond to quotes (depending on quote_style).
+ */
+/* maximum expansion (factor 1.2) for HTML 5 with &nGt; and &nLt; */
+/* +2 is 1 because of rest (probably unnecessary), 1 because of terminating 0 */
+#define TRAVERSE_FOR_ENTITIES_EXPAND_SIZE(oldlen) ((oldlen) + (oldlen) / 5 + 2)
+static void traverse_for_entities(
+ const char *old,
+ size_t oldlen,
+ char *ret, /* should have allocated TRAVERSE_FOR_ENTITIES_EXPAND_SIZE(olden) */
+ size_t *retlen,
+ int all,
+ int flags,
+ const entity_ht *inv_map,
+ enum entity_charset charset)
+{
+ const char *p,
+ *lim;
+ char *q;
+ int doctype = flags & ENT_HTML_DOC_TYPE_MASK;
+
+ lim = old + oldlen; /* terminator address */
+ assert(*lim == '\0');
+
+ for (p = old, q = ret; p < lim;) {
+ unsigned code, code2 = 0;
+ const char *next = NULL; /* when set, next > p, otherwise possible inf loop */
+
+ /* Shift JIS, Big5 and HKSCS use multi-byte encodings where an
+ * ASCII range byte can be part of a multi-byte sequence.
+ * However, they start at 0x40, therefore if we find a 0x26 byte,
+ * we're sure it represents the '&' character. */
+
+ /* assumes there are no single-char entities */
+ if (p[0] != '&' || (p + 3 >= lim)) {
+ *(q++) = *(p++);
+ continue;
+ }
- if (next != NULL && *next == ';' && !invalid_code) {
- switch (charset) {
- case cs_utf_8:
- q += php_utf32_utf8(q, code);
- break;
-
- case cs_8859_1:
- case cs_8859_5:
- case cs_8859_15:
- if ((code >= 0x80 && code < 0xa0) || code > 0xff) {
- invalid_code = 1;
- } else {
- *(q++) = code;
- }
- break;
-
- case cs_cp1252:
- if (code > 0xff) {
- invalid_code = 1;
- } else {
- *(q++) = code;
- }
- break;
-
- case cs_cp1251:
- case cs_cp866:
- case cs_big5:
- case cs_big5hkscs:
- case cs_sjis:
- case cs_eucjp:
- if (code >= 0x80) {
- invalid_code = 1;
- } else {
- *(q++) = code;
- }
- break;
-
- case cs_gb2312:
- if (code >= 0x81) {
- invalid_code = 1;
- } else {
- *(q++) = code;
- }
- break;
-
- default:
- /* for backwards compatilibity */
- invalid_code = 1;
- break;
- }
- if (invalid_code) {
- for (; p <= next; p++) {
- *(q++) = *p;
- }
- }
- p = next + 1;
- } else {
- *(q++) = *(p++);
- *(q++) = *(p++);
- }
- } else if (p + 4 < lim &&
- p[1] == 'a' && p[2] == 'm' &&p[3] == 'p' &&
- p[4] == ';') {
- *(q++) = '&';
- p += 5;
+ /* now p[3] is surely valid and is no terminator */
+
+ /* numerical entity */
+ if (p[1] == '#') {
+ next = &p[2];
+ if (process_numeric_entity(&next, &code) == FAILURE)
+ goto invalid_code;
+
+ /* If we're in htmlspecialchars_decode, we're only decoding entities
+ * that represent &, <, >, " and '. Is this one of them? */
+ if (!all && (code > 63U ||
+ stage3_table_be_apos_00000[code].data.ent.entity == NULL))
+ goto invalid_code;
+
+ /* are we allowed to decode this entity in this document type?
+ * HTML 5 is the only that has a character that cannot be used in
+ * a numeric entity but is allowed literally (U+000D). The
+ * unoptimized version would be ... || !numeric_entity_is_allowed(code) */
+ if (!unicode_cp_is_allowed(code, doctype) ||
+ (doctype == ENT_HTML_DOC_HTML5 && code == 0x0D))
+ goto invalid_code;
+ } else {
+ const char *start;
+ size_t ent_len;
+
+ next = &p[1];
+ start = next;
+
+ if (process_named_entity_html(&next, &start, &ent_len) == FAILURE)
+ goto invalid_code;
+
+ if (resolve_named_entity_html(start, ent_len, inv_map, &code, &code2) == FAILURE) {
+ if (doctype == ENT_HTML_DOC_XHTML && ent_len == 4 && start[0] == 'a'
+ && start[1] == 'p' && start[2] == 'o' && start[3] == 's') {
+ /* uses html4 inv_map, which doesn't include apos;. This is a
+ * hack to support it */
+ code = (unsigned) '\'';
} else {
- *(q++) = *(p++);
- *(q++) = *(p++);
+ goto invalid_code;
}
- } else {
- *(q++) = *(p++);
}
- } else {
- *(q++) = *(p++);
+ }
+
+ assert(*next == ';');
+
+ if (((code == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) ||
+ (code == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE)))
+ /* && code2 == '\0' always true for current maps */)
+ goto invalid_code;
+
+ /* UTF-8 doesn't need mapping (ISO-8859-1 doesn't either, but
+ * the call is needed to ensure the codepoint <= U+00FF) */
+ if (charset != cs_utf_8) {
+ /* replace unicode code point */
+ if (map_from_unicode(code, charset, &code) == FAILURE || code2 != 0)
+ goto invalid_code; /* not representable in target charset */
+ }
+
+ q += write_octet_sequence(q, charset, code);
+ if (code2) {
+ q += write_octet_sequence(q, charset, code2);
+ }
+
+ /* jump over the valid entity; may go beyond size of buffer; np */
+ p = next + 1;
+ continue;
+
+invalid_code:
+ for (; p < next; p++) {
+ *(q++) = *p;
}
}
+
*q = '\0';
- retlen = (size_t)(q - ret);
+ *retlen = (size_t)(q - ret);
+}
+/* }}} */
+
+/* {{{ unescape_inverse_map */
+static const entity_ht *unescape_inverse_map(int all, int flags)
+{
+ int document_type = flags & ENT_HTML_DOC_TYPE_MASK;
+
+ if (all) {
+ switch (document_type) {
+ case ENT_HTML_DOC_HTML401:
+ case ENT_HTML_DOC_XHTML: /* but watch out for &apos;...*/
+ return &ent_ht_html4;
+ case ENT_HTML_DOC_HTML5:
+ return &ent_ht_html5;
+ default:
+ return &ent_ht_be_apos;
+ }
+ } else {
+ switch (document_type) {
+ case ENT_HTML_DOC_HTML401:
+ return &ent_ht_be_noapos;
+ default:
+ return &ent_ht_be_apos;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ determine_entity_table
+ * Entity table to use. Note that entity tables are defined in terms of
+ * unicode code points */
+static entity_table_opt determine_entity_table(int all, int doctype)
+{
+ entity_table_opt retval = {NULL};
+
+ assert(!(doctype == ENT_HTML_DOC_XML1 && all));
+
+ if (all) {
+ retval.ms_table = (doctype == ENT_HTML_DOC_HTML5) ?
+ entity_ms_table_html5 : entity_ms_table_html4;
+ } else {
+ retval.table = (doctype == ENT_HTML_DOC_HTML401) ?
+ stage3_table_be_noapos_00000 : stage3_table_be_apos_00000;
+ }
+ return retval;
+}
+/* }}} */
+
+/* {{{ php_unescape_html_entities
+ * The parameter "all" should be true to decode all possible entities, false to decode
+ * only the basic ones, i.e., those in basic_entities_ex + the numeric entities
+ * that correspond to quotes.
+ */
+PHPAPI char *php_unescape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC)
+{
+ size_t retlen;
+ char *ret;
+ enum entity_charset charset;
+ const entity_ht *inverse_map = NULL;
+ size_t new_size = TRAVERSE_FOR_ENTITIES_EXPAND_SIZE(oldlen);
+
+ if (all) {
+ charset = determine_charset(hint_charset TSRMLS_CC);
+ } else {
+ charset = cs_8859_1; /* charset shouldn't matter, use ISO-8859-1 for performance */
+ }
+
+ /* don't use LIMIT_ALL! */
+
+ if (oldlen > new_size) {
+ /* overflow, refuse to do anything */
+ ret = estrndup((char*)old, oldlen);
+ retlen = oldlen;
+ goto empty_source;
+ }
+ ret = emalloc(new_size);
+ *ret = '\0';
+ retlen = oldlen;
+ if (retlen == 0) {
+ goto empty_source;
+ }
+
+ inverse_map = unescape_inverse_map(all, flags);
+
+ /* replace numeric entities */
+ traverse_for_entities(old, oldlen, ret, &retlen, all, flags, inverse_map, charset);
+
empty_source:
*newlen = retlen;
return ret;
}
/* }}} */
-PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset TSRMLS_DC)
+PHPAPI char *php_escape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC)
+{
+ return php_escape_html_entities_ex(old, oldlen, newlen, all, flags, hint_charset, 1 TSRMLS_CC);
+}
+
+/* {{{ find_entity_for_char */
+static inline void find_entity_for_char(
+ unsigned int k,
+ enum entity_charset charset,
+ const entity_stage1_row *table,
+ const unsigned char **entity,
+ size_t *entity_len,
+ unsigned char *old,
+ size_t oldlen,
+ size_t *cursor)
{
- return php_escape_html_entities_ex(old, oldlen, newlen, all, quote_style, hint_charset, 1 TSRMLS_CC);
+ unsigned stage1_idx = ENT_STAGE1_INDEX(k);
+ const entity_stage3_row *c;
+
+ if (stage1_idx > 0x1D) {
+ *entity = NULL;
+ *entity_len = 0;
+ return;
+ }
+
+ c = &table[stage1_idx][ENT_STAGE2_INDEX(k)][ENT_STAGE3_INDEX(k)];
+
+ if (!c->ambiguous) {
+ *entity = (const unsigned char *)c->data.ent.entity;
+ *entity_len = c->data.ent.entity_len;
+ } else {
+ /* peek at next char */
+ size_t cursor_before = *cursor;
+ int status = SUCCESS;
+ unsigned next_char;
+
+ if (!(*cursor < oldlen))
+ goto no_suitable_2nd;
+
+ next_char = get_next_char(charset, old, oldlen, cursor, &status);
+
+ if (status == FAILURE)
+ goto no_suitable_2nd;
+
+ {
+ const entity_multicodepoint_row *s, *e;
+
+ s = &c->data.multicodepoint_table[1];
+ e = s - 1 + c->data.multicodepoint_table[0].leading_entry.size;
+ /* we could do a binary search but it's not worth it since we have
+ * at most two entries... */
+ for ( ; s <= e; s++) {
+ if (s->normal_entry.second_cp == next_char) {
+ *entity = s->normal_entry.entity;
+ *entity_len = s->normal_entry.entity_len;
+ return;
+ }
+ }
+ }
+no_suitable_2nd:
+ *cursor = cursor_before;
+ *entity = (const unsigned char *)
+ c->data.multicodepoint_table[0].leading_entry.default_entity;
+ *entity_len = c->data.multicodepoint_table[0].leading_entry.default_entity_len;
+ }
}
+/* }}} */
+/* {{{ find_entity_for_char_basic */
+static inline void find_entity_for_char_basic(
+ unsigned int k,
+ const entity_stage3_row *table,
+ const unsigned char **entity,
+ size_t *entity_len)
+{
+ if (k >= 64U) {
+ *entity = NULL;
+ *entity_len = 0;
+ return;
+ }
+
+ *entity = table[k].data.ent.entity;
+ *entity_len = table[k].data.ent.entity_len;
+}
+/* }}} */
/* {{{ php_escape_html_entities
*/
-PHPAPI char *php_escape_html_entities_ex(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset, zend_bool double_encode TSRMLS_DC)
+PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset, zend_bool double_encode TSRMLS_DC)
{
- int i, j, maxlen, len;
+ size_t cursor, maxlen, len;
char *replaced;
enum entity_charset charset = determine_charset(hint_charset TSRMLS_CC);
- int matches_map;
-
- maxlen = 2 * oldlen;
- if (maxlen < 128)
- maxlen = 128;
- replaced = emalloc (maxlen);
- len = 0;
- i = 0;
- while (i < oldlen) {
- unsigned char mbsequence[16]; /* allow up to 15 characters in a multibyte sequence */
- int mbseqlen = sizeof(mbsequence);
- int status = SUCCESS;
- unsigned int this_char = get_next_char(charset, old, oldlen, &i, mbsequence, &mbseqlen, &status);
-
- if(status == FAILURE) {
- /* invalid MB sequence */
- if (quote_style & ENT_HTML_IGNORE_ERRORS) {
- continue;
- }
- efree(replaced);
- if(!PG(display_errors)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid multibyte sequence in argument");
- }
- *newlen = 0;
- return STR_EMPTY_ALLOC();
+ int doctype = flags & ENT_HTML_DOC_TYPE_MASK;
+ entity_table_opt entity_table;
+ const enc_to_uni *to_uni_table = NULL;
+ const entity_ht *inv_map = NULL; /* used for !double_encode */
+ /* only used if flags includes ENT_HTML_IGNORE_ERRORS or ENT_HTML_SUBSTITUTE_DISALLOWED_CHARS */
+ const unsigned char *replacement;
+ size_t replacement_len;
+
+ if (all) { /* replace with all named entities */
+ if (CHARSET_PARTIAL_SUPPORT(charset)) {
+ php_error_docref0(NULL TSRMLS_CC, E_STRICT, "Only basic entities "
+ "substitution is supported for multi-byte encodings other than UTF-8; "
+ "functionality is equivalent to htmlspecialchars");
}
- matches_map = 0;
+ LIMIT_ALL(all, doctype, charset);
+ }
+ entity_table = determine_entity_table(all, doctype);
+ if (all && !CHARSET_UNICODE_COMPAT(charset)) {
+ to_uni_table = enc_to_uni_index[charset];
+ }
- if (len + 16 > maxlen)
- replaced = erealloc (replaced, maxlen += 128);
+ if (!double_encode) {
+ /* first arg is 1 because we want to identify valid named entities
+ * even if we are only encoding the basic ones */
+ inv_map = unescape_inverse_map(1, flags);
+ }
- if (all) {
- /* look for a match in the maps for this charset */
- unsigned char *rep = NULL;
+ if (flags & (ENT_HTML_SUBSTITUTE_ERRORS | ENT_HTML_SUBSTITUTE_DISALLOWED_CHARS)) {
+ if (charset == cs_utf_8) {
+ replacement = (const unsigned char*)"\xEF\xBF\xBD";
+ replacement_len = sizeof("\xEF\xBF\xBD") - 1;
+ } else {
+ replacement = (const unsigned char*)"&#xFFFD;";
+ replacement_len = sizeof("&#xFFFD;") - 1;
+ }
+ }
+ /* initial estimate */
+ if (oldlen < 64) {
+ maxlen = 128;
+ } else {
+ maxlen = 2 * oldlen;
+ if (maxlen < oldlen) {
+ zend_error_noreturn(E_ERROR, "Input string is too long");
+ return NULL;
+ }
+ }
- for (j = 0; entity_map[j].charset != cs_terminator; j++) {
- if (entity_map[j].charset == charset
- && this_char >= entity_map[j].basechar
- && this_char <= entity_map[j].endchar) {
- rep = (unsigned char*)entity_map[j].table[this_char - entity_map[j].basechar];
- if (rep == NULL) {
- /* there is no entity for this position; fall through and
- * just output the character itself */
- break;
- }
+ replaced = emalloc(maxlen + 1); /* adding 1 is safe: maxlen is even */
+ len = 0;
+ cursor = 0;
+ while (cursor < oldlen) {
+ const unsigned char *mbsequence = NULL;
+ size_t mbseqlen = 0,
+ cursor_before = cursor;
+ int status = SUCCESS;
+ unsigned int this_char = get_next_char(charset, old, oldlen, &cursor, &status);
+
+ /* guarantee we have at least 40 bytes to write.
+ * In HTML5, entities may take up to 33 bytes */
+ if (len > maxlen - 40) { /* maxlen can never be smaller than 128 */
+ replaced = safe_erealloc(replaced, maxlen , 1, 128 + 1);
+ maxlen += 128;
+ }
- matches_map = 1;
- break;
- }
+ if (status == FAILURE) {
+ /* invalid MB sequence */
+ if (flags & ENT_HTML_IGNORE_ERRORS) {
+ continue;
+ } else if (flags & ENT_HTML_SUBSTITUTE_ERRORS) {
+ memcpy(&replaced[len], replacement, replacement_len);
+ len += replacement_len;
+ continue;
+ } else {
+ efree(replaced);
+ *newlen = 0;
+ return STR_EMPTY_ALLOC();
}
+ } else { /* SUCCESS */
+ mbsequence = &old[cursor_before];
+ mbseqlen = cursor - cursor_before;
+ }
- if (matches_map) {
- int l = strlen(rep);
- /* increase the buffer size */
- if (len + 2 + l >= maxlen) {
- replaced = erealloc(replaced, maxlen += 128);
+ if (this_char != '&') { /* no entity on this position */
+ const unsigned char *rep = NULL;
+ size_t rep_len = 0;
+
+ if (((this_char == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) ||
+ (this_char == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE))))
+ goto pass_char_through;
+
+ if (all) { /* false that CHARSET_PARTIAL_SUPPORT(charset) */
+ if (to_uni_table != NULL) {
+ /* !CHARSET_UNICODE_COMPAT therefore not UTF-8; since UTF-8
+ * is the only multibyte encoding with !CHARSET_PARTIAL_SUPPORT,
+ * we're using a single byte encoding */
+ map_to_unicode(this_char, to_uni_table, &this_char);
+ if (this_char == 0xFFFF) /* no mapping; pass through */
+ goto pass_char_through;
}
+ /* the cursor may advance */
+ find_entity_for_char(this_char, charset, entity_table.ms_table, &rep,
+ &rep_len, old, oldlen, &cursor);
+ } else {
+ find_entity_for_char_basic(this_char, entity_table.table, &rep, &rep_len);
+ }
+ if (rep != NULL) {
replaced[len++] = '&';
- strlcpy(replaced + len, rep, maxlen);
- len += l;
+ memcpy(&replaced[len], rep, rep_len);
+ len += rep_len;
replaced[len++] = ';';
- }
- }
- if (!matches_map) {
- int is_basic = 0;
-
- if (this_char == '&') {
- if (double_encode) {
-encode_amp:
- memcpy(replaced + len, "&amp;", sizeof("&amp;") - 1);
- len += sizeof("&amp;") - 1;
- } else {
- char *e = memchr(old + i, ';', oldlen - i);
- char *s = old + i;
-
- if (!e || (e - s) > 10) { /* minor optimization to avoid "entities" over 10 chars in length */
- goto encode_amp;
+ } else {
+ /* we did not find an entity for this char.
+ * check for its validity, if its valid pass it unchanged */
+ if (flags & ENT_HTML_SUBSTITUTE_DISALLOWED_CHARS) {
+ if (CHARSET_UNICODE_COMPAT(charset)) {
+ if (!unicode_cp_is_allowed(this_char, doctype)) {
+ mbsequence = replacement;
+ mbseqlen = replacement_len;
+ }
+ } else if (to_uni_table) {
+ if (!all) /* otherwise we already did this */
+ map_to_unicode(this_char, to_uni_table, &this_char);
+ if (!unicode_cp_is_allowed(this_char, doctype)) {
+ mbsequence = replacement;
+ mbseqlen = replacement_len;
+ }
} else {
- if (*s == '#') { /* numeric entities */
- s++;
- /* Hex (&#x5A;) */
- if (*s == 'x' || *s == 'X') {
- s++;
- while (s < e) {
- if (!isxdigit((int)*(unsigned char *)s++)) {
- goto encode_amp;
- }
- }
- /* Dec (&#90;)*/
- } else {
- while (s < e) {
- if (!isdigit((int)*(unsigned char *)s++)) {
- goto encode_amp;
- }
- }
- }
- } else { /* text entities */
- while (s < e) {
- if (!isalnum((int)*(unsigned char *)s++)) {
- goto encode_amp;
- }
- }
+ /* not a unicode code point, unless, coincidentally, it's in
+ * the 0x20..0x7D range (except 0x5C in sjis). We know nothing
+ * about other code points, because we have no tables. Since
+ * Unicode code points in that range are not disallowed in any
+ * document type, we could do nothing. However, conversion
+ * tables frequently map 0x00-0x1F to the respective C0 code
+ * points. Let's play it safe and admit that's the case */
+ if (this_char <= 0x7D &&
+ !unicode_cp_is_allowed(this_char, doctype)) {
+ mbsequence = replacement;
+ mbseqlen = replacement_len;
}
- replaced[len++] = '&';
- }
- }
- is_basic = 1;
- } else {
- for (j = 0; basic_entities[j].charcode != 0; j++) {
- if ((basic_entities[j].charcode != this_char) ||
- (basic_entities[j].flags &&
- (quote_style & basic_entities[j].flags) == 0)) {
- continue;
}
-
- memcpy(replaced + len, basic_entities[j].entity, basic_entities[j].entitylen);
- len += basic_entities[j].entitylen;
-
- is_basic = 1;
- break;
}
- }
-
- if (!is_basic) {
- /* a wide char without a named entity; pass through the original sequence */
+pass_char_through:
if (mbseqlen > 1) {
memcpy(replaced + len, mbsequence, mbseqlen);
len += mbseqlen;
} else {
- replaced[len++] = (unsigned char)this_char;
+ replaced[len++] = mbsequence[0];
}
}
+ } else { /* this_char == '&' */
+ if (double_encode) {
+encode_amp:
+ memcpy(&replaced[len], "&amp;", sizeof("&amp;") - 1);
+ len += sizeof("&amp;") - 1;
+ } else { /* no double encode */
+ /* check if entity is valid */
+ size_t ent_len; /* not counting & or ; */
+ /* peek at next char */
+ if (old[cursor] == '#') { /* numeric entity */
+ unsigned code_point;
+ int valid;
+ char *pos = (char*)&old[cursor+1];
+ valid = process_numeric_entity((const char **)&pos, &code_point);
+ if (valid == FAILURE)
+ goto encode_amp;
+ if (flags & ENT_HTML_SUBSTITUTE_DISALLOWED_CHARS) {
+ if (!numeric_entity_is_allowed(code_point, doctype))
+ goto encode_amp;
+ }
+ ent_len = pos - (char*)&old[cursor];
+ } else { /* named entity */
+ /* check for vality of named entity */
+ const char *start = &old[cursor],
+ *next = start;
+ unsigned dummy1, dummy2;
+
+ if (process_named_entity_html(&next, &start, &ent_len) == FAILURE)
+ goto encode_amp;
+ if (resolve_named_entity_html(start, ent_len, inv_map, &dummy1, &dummy2) == FAILURE) {
+ if (!(doctype == ENT_HTML_DOC_XHTML && ent_len == 4 && start[0] == 'a'
+ && start[1] == 'p' && start[2] == 'o' && start[3] == 's')) {
+ /* uses html4 inv_map, which doesn't include apos;. This is a
+ * hack to support it */
+ goto encode_amp;
+ }
+ }
+ }
+ /* checks passed; copy entity to result */
+ /* entity size is unbounded, we may need more memory */
+ /* at this point maxlen - len >= 40 */
+ if (maxlen - len < ent_len + 2 /* & and ; */) {
+ /* ent_len < oldlen, which is certainly <= SIZE_MAX/2 */
+ replaced = safe_erealloc(replaced, maxlen, 1, ent_len + 128 + 1);
+ maxlen += ent_len + 128;
+ }
+ replaced[len++] = '&';
+ memcpy(&replaced[len], &old[cursor], ent_len);
+ len += ent_len;
+ replaced[len++] = ';';
+ cursor += ent_len + 1;
+ }
}
}
replaced[len] = '\0';
*newlen = len;
return replaced;
-
-
}
/* }}} */
@@ -1278,17 +1434,17 @@ static void php_html_entities(INTERNAL_FUNCTION_PARAMETERS, int all)
{
char *str, *hint_charset = NULL;
int str_len, hint_charset_len = 0;
- int len;
- long quote_style = ENT_COMPAT;
+ size_t new_len;
+ long flags = ENT_COMPAT;
char *replaced;
zend_bool double_encode = 1;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!b", &str, &str_len, &quote_style, &hint_charset, &hint_charset_len, &double_encode) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!b", &str, &str_len, &flags, &hint_charset, &hint_charset_len, &double_encode) == FAILURE) {
return;
}
- replaced = php_escape_html_entities_ex(str, str_len, &len, all, quote_style, hint_charset, double_encode TSRMLS_CC);
- RETVAL_STRINGL(replaced, len, 0);
+ replaced = php_escape_html_entities_ex(str, str_len, &new_len, all, (int) flags, hint_charset, double_encode TSRMLS_CC);
+ RETVAL_STRINGL(replaced, (int)new_len, 0);
}
/* }}} */
@@ -1305,6 +1461,12 @@ void register_html_constants(INIT_FUNC_ARGS)
REGISTER_LONG_CONSTANT("ENT_QUOTES", ENT_QUOTES, CONST_PERSISTENT|CONST_CS);
REGISTER_LONG_CONSTANT("ENT_NOQUOTES", ENT_NOQUOTES, CONST_PERSISTENT|CONST_CS);
REGISTER_LONG_CONSTANT("ENT_IGNORE", ENT_IGNORE, CONST_PERSISTENT|CONST_CS);
+ REGISTER_LONG_CONSTANT("ENT_SUBSTITUTE", ENT_SUBSTITUTE, CONST_PERSISTENT|CONST_CS);
+ REGISTER_LONG_CONSTANT("ENT_DISALLOWED", ENT_DISALLOWED, CONST_PERSISTENT|CONST_CS);
+ REGISTER_LONG_CONSTANT("ENT_HTML401", ENT_HTML401, CONST_PERSISTENT|CONST_CS);
+ REGISTER_LONG_CONSTANT("ENT_XML1", ENT_XML1, CONST_PERSISTENT|CONST_CS);
+ REGISTER_LONG_CONSTANT("ENT_XHTML", ENT_XHTML, CONST_PERSISTENT|CONST_CS);
+ REGISTER_LONG_CONSTANT("ENT_HTML5", ENT_HTML5, CONST_PERSISTENT|CONST_CS);
}
/* }}} */
@@ -1320,65 +1482,21 @@ PHP_FUNCTION(htmlspecialchars)
Convert special HTML entities back to characters */
PHP_FUNCTION(htmlspecialchars_decode)
{
- char *str, *new_str, *e, *p;
- int len, j, i, new_len;
+ char *str;
+ int str_len;
+ size_t new_len = 0;
long quote_style = ENT_COMPAT;
- struct basic_entities_dec basic_entities_dec[8];
+ char *replaced;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &len, &quote_style) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &quote_style) == FAILURE) {
return;
}
- new_str = estrndup(str, len);
- new_len = len;
- e = new_str + new_len;
-
- if (!(p = memchr(new_str, '&', new_len))) {
- RETURN_STRINGL(new_str, new_len, 0);
- }
-
- for (j = 0, i = 0; basic_entities[i].charcode != 0; i++) {
- if (basic_entities[i].flags && !(quote_style & basic_entities[i].flags)) {
- continue;
- }
- basic_entities_dec[j].charcode = basic_entities[i].charcode;
- memcpy(basic_entities_dec[j].entity, basic_entities[i].entity, basic_entities[i].entitylen + 1);
- basic_entities_dec[j].entitylen = basic_entities[i].entitylen;
- j++;
+ replaced = php_unescape_html_entities(str, str_len, &new_len, 0 /*!all*/, quote_style, NULL TSRMLS_CC);
+ if (replaced) {
+ RETURN_STRINGL(replaced, (int)new_len, 0);
}
- basic_entities_dec[j].charcode = '&';
- basic_entities_dec[j].entitylen = sizeof("&amp;") - 1;
- memcpy(basic_entities_dec[j].entity, "&amp;", sizeof("&amp;"));
- i = j + 1;
-
- do {
- int l = e - p;
-
- for (j = 0; j < i; j++) {
- if (basic_entities_dec[j].entitylen > l) {
- continue;
- }
- if (!memcmp(p, basic_entities_dec[j].entity, basic_entities_dec[j].entitylen)) {
- int e_len = basic_entities_dec[j].entitylen - 1;
-
- *p++ = basic_entities_dec[j].charcode;
- memmove(p, p + e_len, (e - p - e_len));
- e -= e_len;
- goto done;
- }
- }
- p++;
-
-done:
- if (p >= e) {
- break;
- }
- } while ((p = memchr(p, '&', (e - p))));
-
- new_len = e - new_str;
-
- new_str[new_len] = '\0';
- RETURN_STRINGL(new_str, new_len, 0);
+ RETURN_FALSE;
}
/* }}} */
@@ -1387,7 +1505,8 @@ done:
PHP_FUNCTION(html_entity_decode)
{
char *str, *hint_charset = NULL;
- int str_len, hint_charset_len = 0, len;
+ int str_len, hint_charset_len = 0;
+ size_t new_len = 0;
long quote_style = ENT_COMPAT;
char *replaced;
@@ -1396,9 +1515,9 @@ PHP_FUNCTION(html_entity_decode)
return;
}
- replaced = php_unescape_html_entities(str, str_len, &len, 1, quote_style, hint_charset TSRMLS_CC);
+ replaced = php_unescape_html_entities(str, str_len, &new_len, 1 /*all*/, quote_style, hint_charset TSRMLS_CC);
if (replaced) {
- RETURN_STRINGL(replaced, len, 0);
+ RETURN_STRINGL(replaced, (int)new_len, 0);
}
RETURN_FALSE;
}
@@ -1413,86 +1532,168 @@ PHP_FUNCTION(htmlentities)
}
/* }}} */
-/* {{{ proto array get_html_translation_table([int table [, int quote_style [, string charset_hint]]])
+/* {{{ write_s3row_data */
+static inline void write_s3row_data(
+ const entity_stage3_row *r,
+ unsigned orig_cp,
+ enum entity_charset charset,
+ zval *arr)
+{
+ char key[9] = ""; /* two unicode code points in UTF-8 */
+ char entity[LONGEST_ENTITY_LENGTH + 2] = {'&'};
+ size_t written_k1;
+
+ written_k1 = write_octet_sequence(key, charset, orig_cp);
+
+ if (!r->ambiguous) {
+ size_t l = r->data.ent.entity_len;
+ memcpy(&entity[1], r->data.ent.entity, l);
+ entity[l + 1] = ';';
+ add_assoc_stringl_ex(arr, key, written_k1 + 1, entity, l + 2, 1);
+ } else {
+ unsigned i,
+ num_entries;
+ const entity_multicodepoint_row *mcpr = r->data.multicodepoint_table;
+
+ if (mcpr[0].leading_entry.default_entity != NULL) {
+ size_t l = mcpr[0].leading_entry.default_entity_len;
+ memcpy(&entity[1], mcpr[0].leading_entry.default_entity, l);
+ entity[l + 1] = ';';
+ add_assoc_stringl_ex(arr, key, written_k1 + 1, entity, l + 2, 1);
+ }
+ num_entries = mcpr[0].leading_entry.size;
+ for (i = 1; i <= num_entries; i++) {
+ size_t l,
+ written_k2;
+ unsigned uni_cp,
+ spe_cp;
+
+ uni_cp = mcpr[i].normal_entry.second_cp;
+ l = mcpr[i].normal_entry.entity_len;
+
+ if (!CHARSET_UNICODE_COMPAT(charset)) {
+ if (map_from_unicode(uni_cp, charset, &spe_cp) == FAILURE)
+ continue; /* non representable in this charset */
+ } else {
+ spe_cp = uni_cp;
+ }
+
+ written_k2 = write_octet_sequence(&key[written_k1], charset, spe_cp);
+ memcpy(&entity[1], mcpr[i].normal_entry.entity, l);
+ entity[l + 1] = ';';
+ entity[l + 1] = '\0';
+ add_assoc_stringl_ex(arr, key, written_k1 + written_k2 + 1, entity, l + 1, 1);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto array get_html_translation_table([int table [, int flags [, string charset_hint]]])
Returns the internal translation table used by htmlspecialchars and htmlentities */
PHP_FUNCTION(get_html_translation_table)
{
- long which = HTML_SPECIALCHARS, quote_style = ENT_COMPAT;
- unsigned int i;
- int j;
- unsigned char ind[5]; /* max # of 8-bit code units (4; for UTF-8) + 1 for \0 */
- void *dummy;
+ long all = HTML_SPECIALCHARS,
+ flags = ENT_COMPAT;
+ int doctype;
+ entity_table_opt entity_table;
+ const enc_to_uni *to_uni_table;
char *charset_hint = NULL;
int charset_hint_len;
enum entity_charset charset;
+ /* in this function we have to jump through some loops because we're
+ * getting the translated table from data structures that are optimized for
+ * random access, not traversal */
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lls",
- &which, &quote_style, &charset_hint, &charset_hint_len) == FAILURE) {
+ &all, &flags, &charset_hint, &charset_hint_len) == FAILURE) {
return;
}
charset = determine_charset(charset_hint TSRMLS_CC);
+ doctype = flags & ENT_HTML_DOC_TYPE_MASK;
+ LIMIT_ALL(all, doctype, charset);
array_init(return_value);
+
+ entity_table = determine_entity_table(all, doctype);
+ if (all && !CHARSET_UNICODE_COMPAT(charset)) {
+ to_uni_table = enc_to_uni_index[charset];
+ }
- switch (which) {
- case HTML_ENTITIES:
- for (j = 0; entity_map[j].charset != cs_terminator; j++) {
- if (entity_map[j].charset != charset)
- continue;
- for (i = 0; i <= entity_map[j].endchar - entity_map[j].basechar; i++) {
- char buffer[16];
- unsigned k;
- size_t written;
+ if (all) { /* HTML_ENTITIES (actually, any non-zero value for 1st param) */
+ const entity_stage1_row *ms_table = entity_table.ms_table;
+
+ if (CHARSET_UNICODE_COMPAT(charset)) {
+ unsigned i, j, k,
+ max_i, max_j, max_k;
+ /* no mapping to unicode required */
+ if (CHARSET_SINGLE_BYTE(charset)) {
+ max_i = 1; max_j = 1; max_k = 64;
+ } else {
+ max_i = 0x1E; max_j = 64; max_k = 64;
+ }
- if (entity_map[j].table[i] == NULL)
+ for (i = 0; i < max_i; i++) {
+ if (ms_table[i] == empty_stage2_table)
continue;
-
- k = i + entity_map[j].basechar;
-
- switch (charset) {
- case cs_utf_8:
- written = php_utf32_utf8(ind, k);
- ind[written] = '\0';
- break;
- case cs_big5:
- case cs_gb2312:
- case cs_big5hkscs:
- case cs_sjis:
- /* we have no mappings for these, but if we had... */
- /* break through */
- default: /* one byte */
- written = 1;
- ind[0] = (unsigned char)k;
- ind[1] = '\0';
- break;
+ for (j = 0; j < max_j; j++) {
+ if (ms_table[i][j] == empty_stage3_table)
+ continue;
+ for (k = 0; k < max_k; k++) {
+ const entity_stage3_row *r = &ms_table[i][j][k];
+ unsigned code;
+
+ if (r->data.ent.entity == NULL)
+ continue;
+
+ code = ENT_CODE_POINT_FROM_STAGES(i, j, k);
+ if (((code == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) ||
+ (code == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE))))
+ continue;
+ write_s3row_data(r, code, charset, return_value);
+ }
}
+ }
+ } else {
+ /* we have to iterate through the set of code points for this
+ * encoding and map them to unicode code points */
+ unsigned i;
+ for (i = 0; i <= 0xFF; i++) {
+ const entity_stage3_row *r;
+ unsigned uni_cp;
+
+ /* can be done before mapping, they're invariant */
+ if (((i == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) ||
+ (i == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE))))
+ continue;
- snprintf(buffer, sizeof(buffer), "&%s;", entity_map[j].table[i]);
- if (zend_hash_find(Z_ARRVAL_P(return_value), (const char*)ind, written+1, &dummy) == FAILURE) {
- /* in case of the single quote, which is repeated, the first one wins,
- * so don't replace the existint mapping */
- add_assoc_string(return_value, (const char*)ind, buffer, 1);
- }
+ map_to_unicode(i, to_uni_table, &uni_cp);
+ r = &ms_table[ENT_STAGE1_INDEX(uni_cp)][ENT_STAGE2_INDEX(uni_cp)][ENT_STAGE3_INDEX(uni_cp)];
+ if (r->data.ent.entity == NULL)
+ continue;
+
+ write_s3row_data(r, i, charset, return_value);
}
}
- /* break thru */
+ } else {
+ /* we could use sizeof(stage3_table_be_apos_00000) as well */
+ unsigned j,
+ numelems = sizeof(stage3_table_be_noapos_00000) /
+ sizeof(*stage3_table_be_noapos_00000);
+
+ for (j = 0; j < numelems; j++) {
+ const entity_stage3_row *r = &entity_table.table[j];
+ if (r->data.ent.entity == NULL)
+ continue;
- case HTML_SPECIALCHARS:
- add_assoc_stringl(return_value, "&", "&amp;", sizeof("&amp;") - 1, 1);
- for (j = 0; basic_entities[j].charcode != 0; j++) {
- if (basic_entities[j].flags && (quote_style & basic_entities[j].flags) == 0)
+ if (((j == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) ||
+ (j == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE))))
continue;
-
- ind[0] = (unsigned char)basic_entities[j].charcode;
- ind[1] = '\0';
- if (zend_hash_find(Z_ARRVAL_P(return_value), (const char*)ind, 2, &dummy) == FAILURE) {
- add_assoc_stringl(return_value, ind, basic_entities[j].entity,
- basic_entities[j].entitylen, 1);
- }
- }
- break;
+ /* charset is indifferent, used cs_8859_1 for efficiency */
+ write_s3row_data(r, j, cs_8859_1, return_value);
+ }
}
}
/* }}} */
diff --git a/ext/standard/html.h b/ext/standard/html.h
index 2ce087eb4d..30905684a5 100644
--- a/ext/standard/html.h
+++ b/ext/standard/html.h
@@ -21,15 +21,30 @@
#ifndef HTML_H
#define HTML_H
-#define ENT_HTML_QUOTE_NONE 0
-#define ENT_HTML_QUOTE_SINGLE 1
-#define ENT_HTML_QUOTE_DOUBLE 2
-#define ENT_HTML_IGNORE_ERRORS 4
-
-#define ENT_COMPAT ENT_HTML_QUOTE_DOUBLE
-#define ENT_QUOTES (ENT_HTML_QUOTE_DOUBLE | ENT_HTML_QUOTE_SINGLE)
-#define ENT_NOQUOTES ENT_HTML_QUOTE_NONE
-#define ENT_IGNORE ENT_HTML_IGNORE_ERRORS
+#define ENT_HTML_QUOTE_NONE 0
+#define ENT_HTML_QUOTE_SINGLE 1
+#define ENT_HTML_QUOTE_DOUBLE 2
+#define ENT_HTML_IGNORE_ERRORS 4
+#define ENT_HTML_SUBSTITUTE_ERRORS 8
+#define ENT_HTML_DOC_TYPE_MASK (16|32)
+#define ENT_HTML_DOC_HTML401 0
+#define ENT_HTML_DOC_XML1 16
+#define ENT_HTML_DOC_XHTML 32
+#define ENT_HTML_DOC_HTML5 (16|32)
+/* reserve bit 6 */
+#define ENT_HTML_SUBSTITUTE_DISALLOWED_CHARS 128
+
+
+#define ENT_COMPAT ENT_HTML_QUOTE_DOUBLE
+#define ENT_QUOTES (ENT_HTML_QUOTE_DOUBLE | ENT_HTML_QUOTE_SINGLE)
+#define ENT_NOQUOTES ENT_HTML_QUOTE_NONE
+#define ENT_IGNORE ENT_HTML_IGNORE_ERRORS
+#define ENT_SUBSTITUTE ENT_HTML_SUBSTITUTE_ERRORS
+#define ENT_HTML401 0
+#define ENT_XML1 16
+#define ENT_XHTML 32
+#define ENT_HTML5 (16|32)
+#define ENT_DISALLOWED 128
void register_html_constants(INIT_FUNC_ARGS);
@@ -39,8 +54,9 @@ PHP_FUNCTION(htmlspecialchars_decode);
PHP_FUNCTION(html_entity_decode);
PHP_FUNCTION(get_html_translation_table);
-PHPAPI char *php_escape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset TSRMLS_DC);
-PHPAPI char *php_escape_html_entities_ex(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset, zend_bool double_encode TSRMLS_DC);
-PHPAPI char *php_unescape_html_entities(unsigned char *old, int oldlen, int *newlen, int all, int quote_style, char *hint_charset TSRMLS_DC);
+PHPAPI char *php_escape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC);
+PHPAPI char *php_escape_html_entities_ex(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset, zend_bool double_encode TSRMLS_DC);
+PHPAPI char *php_unescape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC);
+PHPAPI unsigned int php_next_utf8_char(const unsigned char *str, size_t str_len, size_t *cursor, int *status);
#endif /* HTML_H */
diff --git a/ext/standard/html_tables.h b/ext/standard/html_tables.h
new file mode 100644
index 0000000000..bf66af36fa
--- /dev/null
+++ b/ext/standard/html_tables.h
@@ -0,0 +1,6235 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef HTML_TABLES_H
+#define HTML_TABLES_H
+
+/**************************************************************************
+***************************************************************************
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY IT. **
+***************************************************************************
+** Please change html_tables/html_table_gen.php instead and then **
+** run it in order to generate this file **
+***************************************************************************
+**************************************************************************/
+
+enum entity_charset { cs_utf_8, cs_8859_1, cs_cp1252, cs_8859_15, cs_cp1251,
+ cs_8859_5, cs_cp866, cs_macroman, cs_koi8r, cs_big5,
+ cs_gb2312, cs_big5hkscs, cs_sjis, cs_eucjp,
+ cs_numelems /* used to count the number of charsets */
+ };
+#define CHARSET_UNICODE_COMPAT(cs) ((cs) <= cs_8859_1)
+#define CHARSET_SINGLE_BYTE(cs) ((cs) > cs_utf_8 && (cs) < cs_big5)
+#define CHARSET_PARTIAL_SUPPORT(cs) ((cs) >= cs_big5)
+
+static const struct {
+ const char *codeset;
+ enum entity_charset charset;
+} charset_map[] = {
+ { "ISO-8859-1", cs_8859_1 },
+ { "ISO8859-1", cs_8859_1 },
+ { "ISO-8859-15", cs_8859_15 },
+ { "ISO8859-15", cs_8859_15 },
+ { "utf-8", cs_utf_8 },
+ { "cp1252", cs_cp1252 },
+ { "Windows-1252", cs_cp1252 },
+ { "1252", cs_cp1252 },
+ { "BIG5", cs_big5 },
+ { "950", cs_big5 },
+ { "GB2312", cs_gb2312 },
+ { "936", cs_gb2312 },
+ { "BIG5-HKSCS", cs_big5hkscs },
+ { "Shift_JIS", cs_sjis },
+ { "SJIS", cs_sjis },
+ { "932", cs_sjis },
+ { "SJIS-win", cs_sjis },
+ { "CP932", cs_sjis },
+ { "EUCJP", cs_eucjp },
+ { "EUC-JP", cs_eucjp },
+ { "eucJP-win", cs_eucjp },
+ { "KOI8-R", cs_koi8r },
+ { "koi8-ru", cs_koi8r },
+ { "koi8r", cs_koi8r },
+ { "cp1251", cs_cp1251 },
+ { "Windows-1251", cs_cp1251 },
+ { "win-1251", cs_cp1251 },
+ { "iso8859-5", cs_8859_5 },
+ { "iso-8859-5", cs_8859_5 },
+ { "cp866", cs_cp866 },
+ { "866", cs_cp866 },
+ { "ibm866", cs_cp866 },
+ { "MacRoman", cs_macroman },
+ { NULL }
+};
+
+/* longest entity name length excluding & and ; */
+#define LONGEST_ENTITY_LENGTH 31
+
+/* Definitions for mappings *to* Unicode.
+ * The origin charset must have at most 256 code points.
+ * The multi-byte encodings are not supported */
+typedef struct {
+ unsigned short uni_cp[64];
+} enc_to_uni_stage2;
+
+typedef struct {
+ const enc_to_uni_stage2 *inner[4];
+} enc_to_uni;
+
+/* bits 7-8 bits (only single bytes encodings supported )*/
+#define ENT_ENC_TO_UNI_STAGE1(k) ((k & 0xC0) >> 6)
+/* bits 1-6 */
+#define ENT_ENC_TO_UNI_STAGE2(k) ((k) & 0x3F)
+
+/* {{{ Mappings *to* Unicode for ISO-8859-1 */
+
+/* {{{ Stage 2 tables for ISO-8859-1 */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso88591_00 = { {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005,
+ 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B,
+ 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
+ 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D,
+ 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
+ 0x003C, 0x003D, 0x003E, 0x003F,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso88591_40 = { {
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045,
+ 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B,
+ 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051,
+ 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D,
+ 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063,
+ 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075,
+ 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B,
+ 0x007C, 0x007D, 0x007E, 0x007F,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso88591_80 = { {
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085,
+ 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B,
+ 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091,
+ 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D,
+ 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3,
+ 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9,
+ 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
+ 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB,
+ 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso88591_C0 = { {
+ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5,
+ 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB,
+ 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1,
+ 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
+ 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD,
+ 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3,
+ 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9,
+ 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
+ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5,
+ 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB,
+ 0x00FC, 0x00FD, 0x00FE, 0x00FF,
+} };
+
+/* end of stage 2 tables for ISO-8859-1 }}} */
+
+/* {{{ Stage 1 table for ISO-8859-1 */
+static const enc_to_uni enc_to_uni_iso88591 = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_iso88591_80,
+ &enc_to_uni_s2_iso88591_C0 }
+};
+/* end of stage 1 table for ISO-8859-1 }}} */
+
+/* {{{ Mappings *to* Unicode for ISO-8859-5 */
+
+/* {{{ Stage 2 tables for ISO-8859-5 */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso88595_80 = { {
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085,
+ 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B,
+ 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091,
+ 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D,
+ 0x009E, 0x009F, 0x00A0, 0x0401, 0x0402, 0x0403,
+ 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
+ 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F,
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+ 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B,
+ 0x041C, 0x041D, 0x041E, 0x041F,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso88595_C0 = { {
+ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
+ 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B,
+ 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431,
+ 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D,
+ 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443,
+ 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455,
+ 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B,
+ 0x045C, 0x00A7, 0x045E, 0x045F,
+} };
+
+/* end of stage 2 tables for ISO-8859-5 }}} */
+
+/* {{{ Stage 1 table for ISO-8859-5 */
+static const enc_to_uni enc_to_uni_iso88595 = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_iso88595_80,
+ &enc_to_uni_s2_iso88595_C0 }
+};
+/* end of stage 1 table for ISO-8859-5 }}} */
+
+/* {{{ Mappings *to* Unicode for ISO-8859-15 */
+
+/* {{{ Stage 2 tables for ISO-8859-15 */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_iso885915_80 = { {
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085,
+ 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B,
+ 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0091,
+ 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D,
+ 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3,
+ 0x20AC, 0x00A5, 0x0160, 0x00A7, 0x0161, 0x00A9,
+ 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5,
+ 0x00B6, 0x00B7, 0x017E, 0x00B9, 0x00BA, 0x00BB,
+ 0x0152, 0x0153, 0x0178, 0x00BF,
+} };
+
+/* end of stage 2 tables for ISO-8859-15 }}} */
+
+/* {{{ Stage 1 table for ISO-8859-15 */
+static const enc_to_uni enc_to_uni_iso885915 = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_iso885915_80,
+ &enc_to_uni_s2_iso88591_C0 }
+};
+/* end of stage 1 table for ISO-8859-15 }}} */
+
+/* {{{ Mappings *to* Unicode for Windows-1252 */
+
+/* {{{ Stage 2 tables for Windows-1252 */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_win1252_80 = { {
+ 0x20AC, 0xFFFF, 0x201A, 0x0192, 0x201E, 0x2026,
+ 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039,
+ 0x0152, 0xFFFF, 0x017D, 0xFFFF, 0xFFFF, 0x2018,
+ 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFF,
+ 0x017E, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3,
+ 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9,
+ 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
+ 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB,
+ 0x00BC, 0x00BD, 0x00BE, 0x00BF,
+} };
+
+/* end of stage 2 tables for Windows-1252 }}} */
+
+/* {{{ Stage 1 table for Windows-1252 */
+static const enc_to_uni enc_to_uni_win1252 = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_win1252_80,
+ &enc_to_uni_s2_iso88591_C0 }
+};
+/* end of stage 1 table for Windows-1252 }}} */
+
+/* {{{ Mappings *to* Unicode for Windows-1251 */
+
+/* {{{ Stage 2 tables for Windows-1251 */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_win1251_80 = { {
+ 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026,
+ 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039,
+ 0x040A, 0x040C, 0x040B, 0x040F, 0x0452, 0x2018,
+ 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0xFFFF, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C,
+ 0x045B, 0x045F, 0x00A0, 0x040E, 0x045E, 0x0408,
+ 0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9,
+ 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
+ 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5,
+ 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB,
+ 0x0458, 0x0405, 0x0455, 0x0457,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_win1251_C0 = { {
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+ 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B,
+ 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421,
+ 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D,
+ 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433,
+ 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439,
+ 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
+ 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B,
+ 0x044C, 0x044D, 0x044E, 0x044F,
+} };
+
+/* end of stage 2 tables for Windows-1251 }}} */
+
+/* {{{ Stage 1 table for Windows-1251 */
+static const enc_to_uni enc_to_uni_win1251 = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_win1251_80,
+ &enc_to_uni_s2_win1251_C0 }
+};
+/* end of stage 1 table for Windows-1251 }}} */
+
+/* {{{ Mappings *to* Unicode for KOI8-R */
+
+/* {{{ Stage 2 tables for KOI8-R */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_koi8r_80 = { {
+ 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518,
+ 0x251C, 0x2524, 0x252C, 0x2534, 0x253C, 0x2580,
+ 0x2584, 0x2588, 0x258C, 0x2590, 0x2591, 0x2592,
+ 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
+ 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2,
+ 0x00B7, 0x00F7, 0x2550, 0x2551, 0x2552, 0x0451,
+ 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558,
+ 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E,
+ 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563,
+ 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569,
+ 0x256A, 0x256B, 0x256C, 0x00A9,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_koi8r_C0 = { {
+ 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435,
+ 0x0444, 0x0433, 0x0445, 0x0438, 0x0439, 0x043A,
+ 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x044F,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
+ 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449,
+ 0x0447, 0x044A, 0x042E, 0x0410, 0x0411, 0x0426,
+ 0x0414, 0x0415, 0x0424, 0x0413, 0x0425, 0x0418,
+ 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
+ 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423,
+ 0x0416, 0x0412, 0x042C, 0x042B, 0x0417, 0x0428,
+ 0x042D, 0x0429, 0x0427, 0x042A,
+} };
+
+/* end of stage 2 tables for KOI8-R }}} */
+
+/* {{{ Stage 1 table for KOI8-R */
+static const enc_to_uni enc_to_uni_koi8r = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_koi8r_80,
+ &enc_to_uni_s2_koi8r_C0 }
+};
+/* end of stage 1 table for KOI8-R }}} */
+
+/* {{{ Mappings *to* Unicode for CP-866 */
+
+/* {{{ Stage 2 tables for CP-866 */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_cp866_80 = { {
+ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+ 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B,
+ 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421,
+ 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
+ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D,
+ 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433,
+ 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439,
+ 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
+ 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561,
+ 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557,
+ 0x255D, 0x255C, 0x255B, 0x2510,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_cp866_C0 = { {
+ 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C,
+ 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566,
+ 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564,
+ 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
+ 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C,
+ 0x2590, 0x2580, 0x0440, 0x0441, 0x0442, 0x0443,
+ 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457,
+ 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A,
+ 0x2116, 0x00A4, 0x25A0, 0x00A0,
+} };
+
+/* end of stage 2 tables for CP-866 }}} */
+
+/* {{{ Stage 1 table for CP-866 */
+static const enc_to_uni enc_to_uni_cp866 = { {
+ &enc_to_uni_s2_iso88591_00,
+ &enc_to_uni_s2_iso88591_40,
+ &enc_to_uni_s2_cp866_80,
+ &enc_to_uni_s2_cp866_C0 }
+};
+/* end of stage 1 table for CP-866 }}} */
+
+/* {{{ Mappings *to* Unicode for MacRoman */
+
+/* {{{ Stage 2 tables for MacRoman */
+
+static const enc_to_uni_stage2 enc_to_uni_s2_macroman_00 = { {
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0x0020, 0x0021, 0x0022, 0x0023,
+ 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029,
+ 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+ 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B,
+ 0x003C, 0x003D, 0x003E, 0x003F,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_macroman_40 = { {
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045,
+ 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B,
+ 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051,
+ 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D,
+ 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063,
+ 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
+ 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075,
+ 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B,
+ 0x007C, 0x007D, 0x007E, 0xFFFF,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_macroman_80 = { {
+ 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6,
+ 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3,
+ 0x00E5, 0x00E7, 0x00E9, 0x00E8, 0x00EA, 0x00EB,
+ 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3,
+ 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9,
+ 0x00FB, 0x00FC, 0x2020, 0x00B0, 0x00A2, 0x00A3,
+ 0x00A7, 0x2022, 0x00B6, 0x00DF, 0x00AE, 0x00A9,
+ 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8,
+ 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5,
+ 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA,
+ 0x00BA, 0x03A9, 0x00E6, 0x00F8,
+} };
+
+static const enc_to_uni_stage2 enc_to_uni_s2_macroman_C0 = { {
+ 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248,
+ 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0,
+ 0x00C3, 0x00D5, 0x0152, 0x0153, 0x2013, 0x2014,
+ 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA,
+ 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A,
+ 0xFB01, 0xFB02, 0x2021, 0x00B7, 0x201A, 0x201E,
+ 0x2030, 0x00C2, 0x00CA, 0x00C1, 0x00CB, 0x00C8,
+ 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4,
+ 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131,
+ 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA,
+ 0x00B8, 0x02DD, 0x02DB, 0x02C7,
+} };
+
+/* end of stage 2 tables for MacRoman }}} */
+
+/* {{{ Stage 1 table for MacRoman */
+static const enc_to_uni enc_to_uni_macroman = { {
+ &enc_to_uni_s2_macroman_00,
+ &enc_to_uni_s2_macroman_40,
+ &enc_to_uni_s2_macroman_80,
+ &enc_to_uni_s2_macroman_C0 }
+};
+/* end of stage 1 table for MacRoman }}} */
+
+/* {{{ Index of tables for encoding conversion */
+static const enc_to_uni *const enc_to_uni_index[cs_numelems] = {
+ NULL,
+ &enc_to_uni_iso88591,
+ &enc_to_uni_win1252,
+ &enc_to_uni_iso885915,
+ &enc_to_uni_win1251,
+ &enc_to_uni_iso88595,
+ &enc_to_uni_cp866,
+ &enc_to_uni_macroman,
+ &enc_to_uni_koi8r,
+};
+/* }}} */
+
+/* Definitions for mappings *from* Unicode */
+
+typedef struct {
+ unsigned short un_code_point; /* we don't need bigger */
+ unsigned char cs_code; /* currently, we only have maps to single-byte encodings */
+} uni_to_enc;
+
+/* {{{ Mappings *from* Unicode for ISO-8859-15 */
+static const uni_to_enc unimap_iso885915[] = {
+ { 0x00A5, 0xA5 }, /* yen sign */
+ { 0x00A7, 0xA7 }, /* section sign */
+ { 0x00A9, 0xA9 }, /* copyright sign */
+ { 0x00AA, 0xAA }, /* feminine ordinal indicator */
+ { 0x00AB, 0xAB }, /* left-pointing double angle quotation mark */
+ { 0x00AC, 0xAC }, /* not sign */
+ { 0x00AD, 0xAD }, /* soft hyphen */
+ { 0x00AE, 0xAE }, /* registered sign */
+ { 0x00AF, 0xAF }, /* macron */
+ { 0x00B0, 0xB0 }, /* degree sign */
+ { 0x00B1, 0xB1 }, /* plus-minus sign */
+ { 0x00B2, 0xB2 }, /* superscript two */
+ { 0x00B3, 0xB3 }, /* superscript three */
+ { 0x00B5, 0xB5 }, /* micro sign */
+ { 0x00B6, 0xB6 }, /* pilcrow sign */
+ { 0x00B7, 0xB7 }, /* middle dot */
+ { 0x00B9, 0xB9 }, /* superscript one */
+ { 0x00BA, 0xBA }, /* masculine ordinal indicator */
+ { 0x00BB, 0xBB }, /* right-pointing double angle quotation mark */
+ { 0x0152, 0xBC }, /* latin capital ligature oe */
+ { 0x0153, 0xBD }, /* latin small ligature oe */
+ { 0x0160, 0xA6 }, /* latin capital letter s with caron */
+ { 0x0161, 0xA8 }, /* latin small letter s with caron */
+ { 0x0178, 0xBE }, /* latin capital letter y with diaeresis */
+ { 0x017D, 0xB4 }, /* latin capital letter z with caron */
+ { 0x017E, 0xB8 }, /* latin small letter z with caron */
+ { 0x20AC, 0xA4 }, /* euro sign */
+};
+/* {{{ end of mappings *from* Unicode for ISO-8859-15 */
+
+/* {{{ Mappings *from* Unicode for Windows-1252 */
+static const uni_to_enc unimap_win1252[] = {
+ { 0x0152, 0x8C }, /* latin capital ligature oe */
+ { 0x0153, 0x9C }, /* latin small ligature oe */
+ { 0x0160, 0x8A }, /* latin capital letter s with caron */
+ { 0x0161, 0x9A }, /* latin small letter s with caron */
+ { 0x0178, 0x9F }, /* latin capital letter y with diaeresis */
+ { 0x017D, 0x8E }, /* latin capital letter z with caron */
+ { 0x017E, 0x9E }, /* latin small letter z with caron */
+ { 0x0192, 0x83 }, /* latin small letter f with hook */
+ { 0x02C6, 0x88 }, /* modifier letter circumflex accent */
+ { 0x02DC, 0x98 }, /* small tilde */
+ { 0x2013, 0x96 }, /* en dash */
+ { 0x2014, 0x97 }, /* em dash */
+ { 0x2018, 0x91 }, /* left single quotation mark */
+ { 0x2019, 0x92 }, /* right single quotation mark */
+ { 0x201A, 0x82 }, /* single low-9 quotation mark */
+ { 0x201C, 0x93 }, /* left double quotation mark */
+ { 0x201D, 0x94 }, /* right double quotation mark */
+ { 0x201E, 0x84 }, /* double low-9 quotation mark */
+ { 0x2020, 0x86 }, /* dagger */
+ { 0x2021, 0x87 }, /* double dagger */
+ { 0x2022, 0x95 }, /* bullet */
+ { 0x2026, 0x85 }, /* horizontal ellipsis */
+ { 0x2030, 0x89 }, /* per mille sign */
+ { 0x2039, 0x8B }, /* single left-pointing angle quotation mark */
+ { 0x203A, 0x9B }, /* single right-pointing angle quotation mark */
+ { 0x20AC, 0x80 }, /* euro sign */
+ { 0x2122, 0x99 }, /* trade mark sign */
+};
+/* {{{ end of mappings *from* Unicode for Windows-1252 */
+
+/* {{{ Mappings *from* Unicode for Windows-1251 */
+static const uni_to_enc unimap_win1251[] = {
+ { 0x00A0, 0xA0 }, /* no-break space */
+ { 0x00A4, 0xA4 }, /* currency sign */
+ { 0x00A6, 0xA6 }, /* broken bar */
+ { 0x00A7, 0xA7 }, /* section sign */
+ { 0x00A9, 0xA9 }, /* copyright sign */
+ { 0x00AB, 0xAB }, /* left-pointing double angle quotation mark */
+ { 0x00AC, 0xAC }, /* not sign */
+ { 0x00AD, 0xAD }, /* soft hyphen */
+ { 0x00AE, 0xAE }, /* registered sign */
+ { 0x00B0, 0xB0 }, /* degree sign */
+ { 0x00B1, 0xB1 }, /* plus-minus sign */
+ { 0x00B5, 0xB5 }, /* micro sign */
+ { 0x00B6, 0xB6 }, /* pilcrow sign */
+ { 0x00B7, 0xB7 }, /* middle dot */
+ { 0x00BB, 0xBB }, /* right-pointing double angle quotation mark */
+ { 0x0401, 0xA8 }, /* cyrillic capital letter io */
+ { 0x0402, 0x80 }, /* cyrillic capital letter dje */
+ { 0x0403, 0x81 }, /* cyrillic capital letter gje */
+ { 0x0404, 0xAA }, /* cyrillic capital letter ukrainian ie */
+ { 0x0405, 0xBD }, /* cyrillic capital letter dze */
+ { 0x0406, 0xB2 }, /* cyrillic capital letter byelorussian-ukrainian i */
+ { 0x0407, 0xAF }, /* cyrillic capital letter yi */
+ { 0x0408, 0xA3 }, /* cyrillic capital letter je */
+ { 0x0409, 0x8A }, /* cyrillic capital letter lje */
+ { 0x040A, 0x8C }, /* cyrillic capital letter nje */
+ { 0x040B, 0x8E }, /* cyrillic capital letter tshe */
+ { 0x040C, 0x8D }, /* cyrillic capital letter kje */
+ { 0x040E, 0xA1 }, /* cyrillic capital letter short u */
+ { 0x040F, 0x8F }, /* cyrillic capital letter dzhe */
+ { 0x0410, 0xC0 }, /* cyrillic capital letter a */
+ { 0x0411, 0xC1 }, /* cyrillic capital letter be */
+ { 0x0412, 0xC2 }, /* cyrillic capital letter ve */
+ { 0x0413, 0xC3 }, /* cyrillic capital letter ghe */
+ { 0x0414, 0xC4 }, /* cyrillic capital letter de */
+ { 0x0415, 0xC5 }, /* cyrillic capital letter ie */
+ { 0x0416, 0xC6 }, /* cyrillic capital letter zhe */
+ { 0x0417, 0xC7 }, /* cyrillic capital letter ze */
+ { 0x0418, 0xC8 }, /* cyrillic capital letter i */
+ { 0x0419, 0xC9 }, /* cyrillic capital letter short i */
+ { 0x041A, 0xCA }, /* cyrillic capital letter ka */
+ { 0x041B, 0xCB }, /* cyrillic capital letter el */
+ { 0x041C, 0xCC }, /* cyrillic capital letter em */
+ { 0x041D, 0xCD }, /* cyrillic capital letter en */
+ { 0x041E, 0xCE }, /* cyrillic capital letter o */
+ { 0x041F, 0xCF }, /* cyrillic capital letter pe */
+ { 0x0420, 0xD0 }, /* cyrillic capital letter er */
+ { 0x0421, 0xD1 }, /* cyrillic capital letter es */
+ { 0x0422, 0xD2 }, /* cyrillic capital letter te */
+ { 0x0423, 0xD3 }, /* cyrillic capital letter u */
+ { 0x0424, 0xD4 }, /* cyrillic capital letter ef */
+ { 0x0425, 0xD5 }, /* cyrillic capital letter ha */
+ { 0x0426, 0xD6 }, /* cyrillic capital letter tse */
+ { 0x0427, 0xD7 }, /* cyrillic capital letter che */
+ { 0x0428, 0xD8 }, /* cyrillic capital letter sha */
+ { 0x0429, 0xD9 }, /* cyrillic capital letter shcha */
+ { 0x042A, 0xDA }, /* cyrillic capital letter hard sign */
+ { 0x042B, 0xDB }, /* cyrillic capital letter yeru */
+ { 0x042C, 0xDC }, /* cyrillic capital letter soft sign */
+ { 0x042D, 0xDD }, /* cyrillic capital letter e */
+ { 0x042E, 0xDE }, /* cyrillic capital letter yu */
+ { 0x042F, 0xDF }, /* cyrillic capital letter ya */
+ { 0x0430, 0xE0 }, /* cyrillic small letter a */
+ { 0x0431, 0xE1 }, /* cyrillic small letter be */
+ { 0x0432, 0xE2 }, /* cyrillic small letter ve */
+ { 0x0433, 0xE3 }, /* cyrillic small letter ghe */
+ { 0x0434, 0xE4 }, /* cyrillic small letter de */
+ { 0x0435, 0xE5 }, /* cyrillic small letter ie */
+ { 0x0436, 0xE6 }, /* cyrillic small letter zhe */
+ { 0x0437, 0xE7 }, /* cyrillic small letter ze */
+ { 0x0438, 0xE8 }, /* cyrillic small letter i */
+ { 0x0439, 0xE9 }, /* cyrillic small letter short i */
+ { 0x043A, 0xEA }, /* cyrillic small letter ka */
+ { 0x043B, 0xEB }, /* cyrillic small letter el */
+ { 0x043C, 0xEC }, /* cyrillic small letter em */
+ { 0x043D, 0xED }, /* cyrillic small letter en */
+ { 0x043E, 0xEE }, /* cyrillic small letter o */
+ { 0x043F, 0xEF }, /* cyrillic small letter pe */
+ { 0x0440, 0xF0 }, /* cyrillic small letter er */
+ { 0x0441, 0xF1 }, /* cyrillic small letter es */
+ { 0x0442, 0xF2 }, /* cyrillic small letter te */
+ { 0x0443, 0xF3 }, /* cyrillic small letter u */
+ { 0x0444, 0xF4 }, /* cyrillic small letter ef */
+ { 0x0445, 0xF5 }, /* cyrillic small letter ha */
+ { 0x0446, 0xF6 }, /* cyrillic small letter tse */
+ { 0x0447, 0xF7 }, /* cyrillic small letter che */
+ { 0x0448, 0xF8 }, /* cyrillic small letter sha */
+ { 0x0449, 0xF9 }, /* cyrillic small letter shcha */
+ { 0x044A, 0xFA }, /* cyrillic small letter hard sign */
+ { 0x044B, 0xFB }, /* cyrillic small letter yeru */
+ { 0x044C, 0xFC }, /* cyrillic small letter soft sign */
+ { 0x044D, 0xFD }, /* cyrillic small letter e */
+ { 0x044E, 0xFE }, /* cyrillic small letter yu */
+ { 0x044F, 0xFF }, /* cyrillic small letter ya */
+ { 0x0451, 0xB8 }, /* cyrillic small letter io */
+ { 0x0452, 0x90 }, /* cyrillic small letter dje */
+ { 0x0453, 0x83 }, /* cyrillic small letter gje */
+ { 0x0454, 0xBA }, /* cyrillic small letter ukrainian ie */
+ { 0x0455, 0xBE }, /* cyrillic small letter dze */
+ { 0x0456, 0xB3 }, /* cyrillic small letter byelorussian-ukrainian i */
+ { 0x0457, 0xBF }, /* cyrillic small letter yi */
+ { 0x0458, 0xBC }, /* cyrillic small letter je */
+ { 0x0459, 0x9A }, /* cyrillic small letter lje */
+ { 0x045A, 0x9C }, /* cyrillic small letter nje */
+ { 0x045B, 0x9E }, /* cyrillic small letter tshe */
+ { 0x045C, 0x9D }, /* cyrillic small letter kje */
+ { 0x045E, 0xA2 }, /* cyrillic small letter short u */
+ { 0x045F, 0x9F }, /* cyrillic small letter dzhe */
+ { 0x0490, 0xA5 }, /* cyrillic capital letter ghe with upturn */
+ { 0x0491, 0xB4 }, /* cyrillic small letter ghe with upturn */
+ { 0x2013, 0x96 }, /* en dash */
+ { 0x2014, 0x97 }, /* em dash */
+ { 0x2018, 0x91 }, /* left single quotation mark */
+ { 0x2019, 0x92 }, /* right single quotation mark */
+ { 0x201A, 0x82 }, /* single low-9 quotation mark */
+ { 0x201C, 0x93 }, /* left double quotation mark */
+ { 0x201D, 0x94 }, /* right double quotation mark */
+ { 0x201E, 0x84 }, /* double low-9 quotation mark */
+ { 0x2020, 0x86 }, /* dagger */
+ { 0x2021, 0x87 }, /* double dagger */
+ { 0x2022, 0x95 }, /* bullet */
+ { 0x2026, 0x85 }, /* horizontal ellipsis */
+ { 0x2030, 0x89 }, /* per mille sign */
+ { 0x2039, 0x8B }, /* single left-pointing angle quotation mark */
+ { 0x203A, 0x9B }, /* single right-pointing angle quotation mark */
+ { 0x20AC, 0x88 }, /* euro sign */
+ { 0x2116, 0xB9 }, /* numero sign */
+ { 0x2122, 0x99 }, /* trade mark sign */
+};
+/* {{{ end of mappings *from* Unicode for Windows-1251 */
+
+/* {{{ Mappings *from* Unicode for KOI8-R */
+static const uni_to_enc unimap_koi8r[] = {
+ { 0x00A0, 0x9A }, /* no-break space */
+ { 0x00A9, 0xBF }, /* copyright sign */
+ { 0x00B0, 0x9C }, /* degree sign */
+ { 0x00B2, 0x9D }, /* superscript two */
+ { 0x00B7, 0x9E }, /* middle dot */
+ { 0x00F7, 0x9F }, /* division sign */
+ { 0x0401, 0xB3 }, /* cyrillic capital letter io */
+ { 0x0410, 0xE1 }, /* cyrillic capital letter a */
+ { 0x0411, 0xE2 }, /* cyrillic capital letter be */
+ { 0x0412, 0xF7 }, /* cyrillic capital letter ve */
+ { 0x0413, 0xE7 }, /* cyrillic capital letter ghe */
+ { 0x0414, 0xE4 }, /* cyrillic capital letter de */
+ { 0x0415, 0xE5 }, /* cyrillic capital letter ie */
+ { 0x0416, 0xF6 }, /* cyrillic capital letter zhe */
+ { 0x0417, 0xFA }, /* cyrillic capital letter ze */
+ { 0x0418, 0xE9 }, /* cyrillic capital letter i */
+ { 0x0419, 0xEA }, /* cyrillic capital letter short i */
+ { 0x041A, 0xEB }, /* cyrillic capital letter ka */
+ { 0x041B, 0xEC }, /* cyrillic capital letter el */
+ { 0x041C, 0xED }, /* cyrillic capital letter em */
+ { 0x041D, 0xEE }, /* cyrillic capital letter en */
+ { 0x041E, 0xEF }, /* cyrillic capital letter o */
+ { 0x041F, 0xF0 }, /* cyrillic capital letter pe */
+ { 0x0420, 0xF2 }, /* cyrillic capital letter er */
+ { 0x0421, 0xF3 }, /* cyrillic capital letter es */
+ { 0x0422, 0xF4 }, /* cyrillic capital letter te */
+ { 0x0423, 0xF5 }, /* cyrillic capital letter u */
+ { 0x0424, 0xE6 }, /* cyrillic capital letter ef */
+ { 0x0425, 0xE8 }, /* cyrillic capital letter ha */
+ { 0x0426, 0xE3 }, /* cyrillic capital letter tse */
+ { 0x0427, 0xFE }, /* cyrillic capital letter che */
+ { 0x0428, 0xFB }, /* cyrillic capital letter sha */
+ { 0x0429, 0xFD }, /* cyrillic capital letter shcha */
+ { 0x042A, 0xFF }, /* cyrillic capital letter hard sign */
+ { 0x042B, 0xF9 }, /* cyrillic capital letter yeru */
+ { 0x042C, 0xF8 }, /* cyrillic capital letter soft sign */
+ { 0x042D, 0xFC }, /* cyrillic capital letter e */
+ { 0x042E, 0xE0 }, /* cyrillic capital letter yu */
+ { 0x042F, 0xF1 }, /* cyrillic capital letter ya */
+ { 0x0430, 0xC1 }, /* cyrillic small letter a */
+ { 0x0431, 0xC2 }, /* cyrillic small letter be */
+ { 0x0432, 0xD7 }, /* cyrillic small letter ve */
+ { 0x0433, 0xC7 }, /* cyrillic small letter ghe */
+ { 0x0434, 0xC4 }, /* cyrillic small letter de */
+ { 0x0435, 0xC5 }, /* cyrillic small letter ie */
+ { 0x0436, 0xD6 }, /* cyrillic small letter zhe */
+ { 0x0437, 0xDA }, /* cyrillic small letter ze */
+ { 0x0438, 0xC9 }, /* cyrillic small letter i */
+ { 0x0439, 0xCA }, /* cyrillic small letter short i */
+ { 0x043A, 0xCB }, /* cyrillic small letter ka */
+ { 0x043B, 0xCC }, /* cyrillic small letter el */
+ { 0x043C, 0xCD }, /* cyrillic small letter em */
+ { 0x043D, 0xCE }, /* cyrillic small letter en */
+ { 0x043E, 0xCF }, /* cyrillic small letter o */
+ { 0x043F, 0xD0 }, /* cyrillic small letter pe */
+ { 0x0440, 0xD2 }, /* cyrillic small letter er */
+ { 0x0441, 0xD3 }, /* cyrillic small letter es */
+ { 0x0442, 0xD4 }, /* cyrillic small letter te */
+ { 0x0443, 0xD5 }, /* cyrillic small letter u */
+ { 0x0444, 0xC6 }, /* cyrillic small letter ef */
+ { 0x0445, 0xC8 }, /* cyrillic small letter ha */
+ { 0x0446, 0xC3 }, /* cyrillic small letter tse */
+ { 0x0447, 0xDE }, /* cyrillic small letter che */
+ { 0x0448, 0xDB }, /* cyrillic small letter sha */
+ { 0x0449, 0xDD }, /* cyrillic small letter shcha */
+ { 0x044A, 0xDF }, /* cyrillic small letter hard sign */
+ { 0x044B, 0xD9 }, /* cyrillic small letter yeru */
+ { 0x044C, 0xD8 }, /* cyrillic small letter soft sign */
+ { 0x044D, 0xDC }, /* cyrillic small letter e */
+ { 0x044E, 0xC0 }, /* cyrillic small letter yu */
+ { 0x044F, 0xD1 }, /* cyrillic small letter ya */
+ { 0x0451, 0xA3 }, /* cyrillic small letter io */
+ { 0x2219, 0x95 }, /* bullet operator */
+ { 0x221A, 0x96 }, /* square root */
+ { 0x2248, 0x97 }, /* almost equal to */
+ { 0x2264, 0x98 }, /* less-than or equal to */
+ { 0x2265, 0x99 }, /* greater-than or equal to */
+ { 0x2320, 0x93 }, /* top half integral */
+ { 0x2321, 0x9B }, /* bottom half integral */
+ { 0x2500, 0x80 }, /* box drawings light horizontal */
+ { 0x2502, 0x81 }, /* box drawings light vertical */
+ { 0x250C, 0x82 }, /* box drawings light down and right */
+ { 0x2510, 0x83 }, /* box drawings light down and left */
+ { 0x2514, 0x84 }, /* box drawings light up and right */
+ { 0x2518, 0x85 }, /* box drawings light up and left */
+ { 0x251C, 0x86 }, /* box drawings light vertical and right */
+ { 0x2524, 0x87 }, /* box drawings light vertical and left */
+ { 0x252C, 0x88 }, /* box drawings light down and horizontal */
+ { 0x2534, 0x89 }, /* box drawings light up and horizontal */
+ { 0x253C, 0x8A }, /* box drawings light vertical and horizontal */
+ { 0x2550, 0xA0 }, /* box drawings double horizontal */
+ { 0x2551, 0xA1 }, /* box drawings double vertical */
+ { 0x2552, 0xA2 }, /* box drawings down single and right double */
+ { 0x2553, 0xA4 }, /* box drawings down double and right single */
+ { 0x2554, 0xA5 }, /* box drawings double down and right */
+ { 0x2555, 0xA6 }, /* box drawings down single and left double */
+ { 0x2556, 0xA7 }, /* box drawings down double and left single */
+ { 0x2557, 0xA8 }, /* box drawings double down and left */
+ { 0x2558, 0xA9 }, /* box drawings up single and right double */
+ { 0x2559, 0xAA }, /* box drawings up double and right single */
+ { 0x255A, 0xAB }, /* box drawings double up and right */
+ { 0x255B, 0xAC }, /* box drawings up single and left double */
+ { 0x255C, 0xAD }, /* box drawings up double and left single */
+ { 0x255D, 0xAE }, /* box drawings double up and left */
+ { 0x255E, 0xAF }, /* box drawings vertical single and right double */
+ { 0x255F, 0xB0 }, /* box drawings vertical double and right single */
+ { 0x2560, 0xB1 }, /* box drawings double vertical and right */
+ { 0x2561, 0xB2 }, /* box drawings vertical single and left double */
+ { 0x2562, 0xB4 }, /* box drawings vertical double and left single */
+ { 0x2563, 0xB5 }, /* box drawings double vertical and left */
+ { 0x2564, 0xB6 }, /* box drawings down single and horizontal double */
+ { 0x2565, 0xB7 }, /* box drawings down double and horizontal single */
+ { 0x2566, 0xB8 }, /* box drawings double down and horizontal */
+ { 0x2567, 0xB9 }, /* box drawings up single and horizontal double */
+ { 0x2568, 0xBA }, /* box drawings up double and horizontal single */
+ { 0x2569, 0xBB }, /* box drawings double up and horizontal */
+ { 0x256A, 0xBC }, /* box drawings vertical single and horizontal double */
+ { 0x256B, 0xBD }, /* box drawings vertical double and horizontal single */
+ { 0x256C, 0xBE }, /* box drawings double vertical and horizontal */
+ { 0x2580, 0x8B }, /* upper half block */
+ { 0x2584, 0x8C }, /* lower half block */
+ { 0x2588, 0x8D }, /* full block */
+ { 0x258C, 0x8E }, /* left half block */
+ { 0x2590, 0x8F }, /* right half block */
+ { 0x2591, 0x90 }, /* light shade */
+ { 0x2592, 0x91 }, /* medium shade */
+ { 0x2593, 0x92 }, /* dark shade */
+ { 0x25A0, 0x94 }, /* black square */
+};
+/* {{{ end of mappings *from* Unicode for KOI8-R */
+
+/* {{{ Mappings *from* Unicode for CP-866 */
+static const uni_to_enc unimap_cp866[] = {
+ { 0x00A0, 0xFF }, /* no-break space */
+ { 0x00A4, 0xFD }, /* currency sign */
+ { 0x00B0, 0xF8 }, /* degree sign */
+ { 0x00B7, 0xFA }, /* middle dot */
+ { 0x0401, 0xF0 }, /* cyrillic capital letter io */
+ { 0x0404, 0xF2 }, /* cyrillic capital letter ukrainian ie */
+ { 0x0407, 0xF4 }, /* cyrillic capital letter yi */
+ { 0x040E, 0xF6 }, /* cyrillic capital letter short u */
+ { 0x0410, 0x80 }, /* cyrillic capital letter a */
+ { 0x0411, 0x81 }, /* cyrillic capital letter be */
+ { 0x0412, 0x82 }, /* cyrillic capital letter ve */
+ { 0x0413, 0x83 }, /* cyrillic capital letter ghe */
+ { 0x0414, 0x84 }, /* cyrillic capital letter de */
+ { 0x0415, 0x85 }, /* cyrillic capital letter ie */
+ { 0x0416, 0x86 }, /* cyrillic capital letter zhe */
+ { 0x0417, 0x87 }, /* cyrillic capital letter ze */
+ { 0x0418, 0x88 }, /* cyrillic capital letter i */
+ { 0x0419, 0x89 }, /* cyrillic capital letter short i */
+ { 0x041A, 0x8A }, /* cyrillic capital letter ka */
+ { 0x041B, 0x8B }, /* cyrillic capital letter el */
+ { 0x041C, 0x8C }, /* cyrillic capital letter em */
+ { 0x041D, 0x8D }, /* cyrillic capital letter en */
+ { 0x041E, 0x8E }, /* cyrillic capital letter o */
+ { 0x041F, 0x8F }, /* cyrillic capital letter pe */
+ { 0x0420, 0x90 }, /* cyrillic capital letter er */
+ { 0x0421, 0x91 }, /* cyrillic capital letter es */
+ { 0x0422, 0x92 }, /* cyrillic capital letter te */
+ { 0x0423, 0x93 }, /* cyrillic capital letter u */
+ { 0x0424, 0x94 }, /* cyrillic capital letter ef */
+ { 0x0425, 0x95 }, /* cyrillic capital letter ha */
+ { 0x0426, 0x96 }, /* cyrillic capital letter tse */
+ { 0x0427, 0x97 }, /* cyrillic capital letter che */
+ { 0x0428, 0x98 }, /* cyrillic capital letter sha */
+ { 0x0429, 0x99 }, /* cyrillic capital letter shcha */
+ { 0x042A, 0x9A }, /* cyrillic capital letter hard sign */
+ { 0x042B, 0x9B }, /* cyrillic capital letter yeru */
+ { 0x042C, 0x9C }, /* cyrillic capital letter soft sign */
+ { 0x042D, 0x9D }, /* cyrillic capital letter e */
+ { 0x042E, 0x9E }, /* cyrillic capital letter yu */
+ { 0x042F, 0x9F }, /* cyrillic capital letter ya */
+ { 0x0430, 0xA0 }, /* cyrillic small letter a */
+ { 0x0431, 0xA1 }, /* cyrillic small letter be */
+ { 0x0432, 0xA2 }, /* cyrillic small letter ve */
+ { 0x0433, 0xA3 }, /* cyrillic small letter ghe */
+ { 0x0434, 0xA4 }, /* cyrillic small letter de */
+ { 0x0435, 0xA5 }, /* cyrillic small letter ie */
+ { 0x0436, 0xA6 }, /* cyrillic small letter zhe */
+ { 0x0437, 0xA7 }, /* cyrillic small letter ze */
+ { 0x0438, 0xA8 }, /* cyrillic small letter i */
+ { 0x0439, 0xA9 }, /* cyrillic small letter short i */
+ { 0x043A, 0xAA }, /* cyrillic small letter ka */
+ { 0x043B, 0xAB }, /* cyrillic small letter el */
+ { 0x043C, 0xAC }, /* cyrillic small letter em */
+ { 0x043D, 0xAD }, /* cyrillic small letter en */
+ { 0x043E, 0xAE }, /* cyrillic small letter o */
+ { 0x043F, 0xAF }, /* cyrillic small letter pe */
+ { 0x0440, 0xE0 }, /* cyrillic small letter er */
+ { 0x0441, 0xE1 }, /* cyrillic small letter es */
+ { 0x0442, 0xE2 }, /* cyrillic small letter te */
+ { 0x0443, 0xE3 }, /* cyrillic small letter u */
+ { 0x0444, 0xE4 }, /* cyrillic small letter ef */
+ { 0x0445, 0xE5 }, /* cyrillic small letter ha */
+ { 0x0446, 0xE6 }, /* cyrillic small letter tse */
+ { 0x0447, 0xE7 }, /* cyrillic small letter che */
+ { 0x0448, 0xE8 }, /* cyrillic small letter sha */
+ { 0x0449, 0xE9 }, /* cyrillic small letter shcha */
+ { 0x044A, 0xEA }, /* cyrillic small letter hard sign */
+ { 0x044B, 0xEB }, /* cyrillic small letter yeru */
+ { 0x044C, 0xEC }, /* cyrillic small letter soft sign */
+ { 0x044D, 0xED }, /* cyrillic small letter e */
+ { 0x044E, 0xEE }, /* cyrillic small letter yu */
+ { 0x044F, 0xEF }, /* cyrillic small letter ya */
+ { 0x0451, 0xF1 }, /* cyrillic small letter io */
+ { 0x0454, 0xF3 }, /* cyrillic small letter ukrainian ie */
+ { 0x0457, 0xF5 }, /* cyrillic small letter yi */
+ { 0x045E, 0xF7 }, /* cyrillic small letter short u */
+ { 0x2116, 0xFC }, /* numero sign */
+ { 0x2219, 0xF9 }, /* bullet operator */
+ { 0x221A, 0xFB }, /* square root */
+ { 0x2500, 0xC4 }, /* box drawings light horizontal */
+ { 0x2502, 0xB3 }, /* box drawings light vertical */
+ { 0x250C, 0xDA }, /* box drawings light down and right */
+ { 0x2510, 0xBF }, /* box drawings light down and left */
+ { 0x2514, 0xC0 }, /* box drawings light up and right */
+ { 0x2518, 0xD9 }, /* box drawings light up and left */
+ { 0x251C, 0xC3 }, /* box drawings light vertical and right */
+ { 0x2524, 0xB4 }, /* box drawings light vertical and left */
+ { 0x252C, 0xC2 }, /* box drawings light down and horizontal */
+ { 0x2534, 0xC1 }, /* box drawings light up and horizontal */
+ { 0x253C, 0xC5 }, /* box drawings light vertical and horizontal */
+ { 0x2550, 0xCD }, /* box drawings double horizontal */
+ { 0x2551, 0xBA }, /* box drawings double vertical */
+ { 0x2552, 0xD5 }, /* box drawings down single and right double */
+ { 0x2553, 0xD6 }, /* box drawings down double and right single */
+ { 0x2554, 0xC9 }, /* box drawings double down and right */
+ { 0x2555, 0xB8 }, /* box drawings down single and left double */
+ { 0x2556, 0xB7 }, /* box drawings down double and left single */
+ { 0x2557, 0xBB }, /* box drawings double down and left */
+ { 0x2558, 0xD4 }, /* box drawings up single and right double */
+ { 0x2559, 0xD3 }, /* box drawings up double and right single */
+ { 0x255A, 0xC8 }, /* box drawings double up and right */
+ { 0x255B, 0xBE }, /* box drawings up single and left double */
+ { 0x255C, 0xBD }, /* box drawings up double and left single */
+ { 0x255D, 0xBC }, /* box drawings double up and left */
+ { 0x255E, 0xC6 }, /* box drawings vertical single and right double */
+ { 0x255F, 0xC7 }, /* box drawings vertical double and right single */
+ { 0x2560, 0xCC }, /* box drawings double vertical and right */
+ { 0x2561, 0xB5 }, /* box drawings vertical single and left double */
+ { 0x2562, 0xB6 }, /* box drawings vertical double and left single */
+ { 0x2563, 0xB9 }, /* box drawings double vertical and left */
+ { 0x2564, 0xD1 }, /* box drawings down single and horizontal double */
+ { 0x2565, 0xD2 }, /* box drawings down double and horizontal single */
+ { 0x2566, 0xCB }, /* box drawings double down and horizontal */
+ { 0x2567, 0xCF }, /* box drawings up single and horizontal double */
+ { 0x2568, 0xD0 }, /* box drawings up double and horizontal single */
+ { 0x2569, 0xCA }, /* box drawings double up and horizontal */
+ { 0x256A, 0xD8 }, /* box drawings vertical single and horizontal double */
+ { 0x256B, 0xD7 }, /* box drawings vertical double and horizontal single */
+ { 0x256C, 0xCE }, /* box drawings double vertical and horizontal */
+ { 0x2580, 0xDF }, /* upper half block */
+ { 0x2584, 0xDC }, /* lower half block */
+ { 0x2588, 0xDB }, /* full block */
+ { 0x258C, 0xDD }, /* left half block */
+ { 0x2590, 0xDE }, /* right half block */
+ { 0x2591, 0xB0 }, /* light shade */
+ { 0x2592, 0xB1 }, /* medium shade */
+ { 0x2593, 0xB2 }, /* dark shade */
+ { 0x25A0, 0xFE }, /* black square */
+};
+/* {{{ end of mappings *from* Unicode for CP-866 */
+
+/* {{{ Mappings *from* Unicode for MacRoman */
+static const uni_to_enc unimap_macroman[] = {
+ { 0x00A0, 0xCA }, /* no-break space */
+ { 0x00A1, 0xC1 }, /* inverted exclamation mark */
+ { 0x00A2, 0xA2 }, /* cent sign */
+ { 0x00A3, 0xA3 }, /* pound sign */
+ { 0x00A5, 0xB4 }, /* yen sign */
+ { 0x00A7, 0xA4 }, /* section sign */
+ { 0x00A8, 0xAC }, /* diaeresis */
+ { 0x00A9, 0xA9 }, /* copyright sign */
+ { 0x00AA, 0xBB }, /* feminine ordinal indicator */
+ { 0x00AB, 0xC7 }, /* left-pointing double angle quotation mark */
+ { 0x00AC, 0xC2 }, /* not sign */
+ { 0x00AE, 0xA8 }, /* registered sign */
+ { 0x00AF, 0xF8 }, /* macron */
+ { 0x00B0, 0xA1 }, /* degree sign */
+ { 0x00B1, 0xB1 }, /* plus-minus sign */
+ { 0x00B4, 0xAB }, /* acute accent */
+ { 0x00B5, 0xB5 }, /* micro sign */
+ { 0x00B6, 0xA6 }, /* pilcrow sign */
+ { 0x00B7, 0xE1 }, /* middle dot */
+ { 0x00B8, 0xFC }, /* cedilla */
+ { 0x00BA, 0xBC }, /* masculine ordinal indicator */
+ { 0x00BB, 0xC8 }, /* right-pointing double angle quotation mark */
+ { 0x00BF, 0xC0 }, /* inverted question mark */
+ { 0x00C0, 0xCB }, /* latin capital letter a with grave */
+ { 0x00C1, 0xE7 }, /* latin capital letter a with acute */
+ { 0x00C2, 0xE5 }, /* latin capital letter a with circumflex */
+ { 0x00C3, 0xCC }, /* latin capital letter a with tilde */
+ { 0x00C4, 0x80 }, /* latin capital letter a with diaeresis */
+ { 0x00C5, 0x81 }, /* latin capital letter a with ring above */
+ { 0x00C6, 0xAE }, /* latin capital letter ae */
+ { 0x00C7, 0x82 }, /* latin capital letter c with cedilla */
+ { 0x00C8, 0xE9 }, /* latin capital letter e with grave */
+ { 0x00C9, 0x83 }, /* latin capital letter e with acute */
+ { 0x00CA, 0xE6 }, /* latin capital letter e with circumflex */
+ { 0x00CB, 0xE8 }, /* latin capital letter e with diaeresis */
+ { 0x00CC, 0xED }, /* latin capital letter i with grave */
+ { 0x00CD, 0xEA }, /* latin capital letter i with acute */
+ { 0x00CE, 0xEB }, /* latin capital letter i with circumflex */
+ { 0x00CF, 0xEC }, /* latin capital letter i with diaeresis */
+ { 0x00D1, 0x84 }, /* latin capital letter n with tilde */
+ { 0x00D2, 0xF1 }, /* latin capital letter o with grave */
+ { 0x00D3, 0xEE }, /* latin capital letter o with acute */
+ { 0x00D4, 0xEF }, /* latin capital letter o with circumflex */
+ { 0x00D5, 0xCD }, /* latin capital letter o with tilde */
+ { 0x00D6, 0x85 }, /* latin capital letter o with diaeresis */
+ { 0x00D8, 0xAF }, /* latin capital letter o with stroke */
+ { 0x00D9, 0xF4 }, /* latin capital letter u with grave */
+ { 0x00DA, 0xF2 }, /* latin capital letter u with acute */
+ { 0x00DB, 0xF3 }, /* latin capital letter u with circumflex */
+ { 0x00DC, 0x86 }, /* latin capital letter u with diaeresis */
+ { 0x00DF, 0xA7 }, /* latin small letter sharp s */
+ { 0x00E0, 0x88 }, /* latin small letter a with grave */
+ { 0x00E1, 0x87 }, /* latin small letter a with acute */
+ { 0x00E2, 0x89 }, /* latin small letter a with circumflex */
+ { 0x00E3, 0x8B }, /* latin small letter a with tilde */
+ { 0x00E4, 0x8A }, /* latin small letter a with diaeresis */
+ { 0x00E5, 0x8C }, /* latin small letter a with ring above */
+ { 0x00E6, 0xBE }, /* latin small letter ae */
+ { 0x00E7, 0x8D }, /* latin small letter c with cedilla */
+ { 0x00E8, 0x8F }, /* latin small letter e with grave */
+ { 0x00E9, 0x8E }, /* latin small letter e with acute */
+ { 0x00EA, 0x90 }, /* latin small letter e with circumflex */
+ { 0x00EB, 0x91 }, /* latin small letter e with diaeresis */
+ { 0x00EC, 0x93 }, /* latin small letter i with grave */
+ { 0x00ED, 0x92 }, /* latin small letter i with acute */
+ { 0x00EE, 0x94 }, /* latin small letter i with circumflex */
+ { 0x00EF, 0x95 }, /* latin small letter i with diaeresis */
+ { 0x00F1, 0x96 }, /* latin small letter n with tilde */
+ { 0x00F2, 0x98 }, /* latin small letter o with grave */
+ { 0x00F3, 0x97 }, /* latin small letter o with acute */
+ { 0x00F4, 0x99 }, /* latin small letter o with circumflex */
+ { 0x00F5, 0x9B }, /* latin small letter o with tilde */
+ { 0x00F6, 0x9A }, /* latin small letter o with diaeresis */
+ { 0x00F7, 0xD6 }, /* division sign */
+ { 0x00F8, 0xBF }, /* latin small letter o with stroke */
+ { 0x00F9, 0x9D }, /* latin small letter u with grave */
+ { 0x00FA, 0x9C }, /* latin small letter u with acute */
+ { 0x00FB, 0x9E }, /* latin small letter u with circumflex */
+ { 0x00FC, 0x9F }, /* latin small letter u with diaeresis */
+ { 0x00FF, 0xD8 }, /* latin small letter y with diaeresis */
+ { 0x0131, 0xF5 }, /* latin small letter dotless i */
+ { 0x0152, 0xCE }, /* latin capital ligature oe */
+ { 0x0153, 0xCF }, /* latin small ligature oe */
+ { 0x0178, 0xD9 }, /* latin capital letter y with diaeresis */
+ { 0x0192, 0xC4 }, /* latin small letter f with hook */
+ { 0x02C6, 0xF6 }, /* modifier letter circumflex accent */
+ { 0x02C7, 0xFF }, /* caron */
+ { 0x02D8, 0xF9 }, /* breve */
+ { 0x02D9, 0xFA }, /* dot above */
+ { 0x02DA, 0xFB }, /* ring above */
+ { 0x02DB, 0xFE }, /* ogonek */
+ { 0x02DC, 0xF7 }, /* small tilde */
+ { 0x02DD, 0xFD }, /* double acute accent */
+ { 0x03A9, 0xBD }, /* greek capital letter omega */
+ { 0x03C0, 0xB9 }, /* greek small letter pi */
+ { 0x2013, 0xD0 }, /* en dash */
+ { 0x2014, 0xD1 }, /* em dash */
+ { 0x2018, 0xD4 }, /* left single quotation mark */
+ { 0x2019, 0xD5 }, /* right single quotation mark */
+ { 0x201A, 0xE2 }, /* single low-9 quotation mark */
+ { 0x201C, 0xD2 }, /* left double quotation mark */
+ { 0x201D, 0xD3 }, /* right double quotation mark */
+ { 0x201E, 0xE3 }, /* double low-9 quotation mark */
+ { 0x2020, 0xA0 }, /* dagger */
+ { 0x2021, 0xE0 }, /* double dagger */
+ { 0x2022, 0xA5 }, /* bullet */
+ { 0x2026, 0xC9 }, /* horizontal ellipsis */
+ { 0x2030, 0xE4 }, /* per mille sign */
+ { 0x2039, 0xDC }, /* single left-pointing angle quotation mark */
+ { 0x203A, 0xDD }, /* single right-pointing angle quotation mark */
+ { 0x2044, 0xDA }, /* fraction slash */
+ { 0x20AC, 0xDB }, /* euro sign */
+ { 0x2122, 0xAA }, /* trade mark sign */
+ { 0x2202, 0xB6 }, /* partial differential */
+ { 0x2206, 0xC6 }, /* increment */
+ { 0x220F, 0xB8 }, /* n-ary product */
+ { 0x2211, 0xB7 }, /* n-ary summation */
+ { 0x221A, 0xC3 }, /* square root */
+ { 0x221E, 0xB0 }, /* infinity */
+ { 0x222B, 0xBA }, /* integral */
+ { 0x2248, 0xC5 }, /* almost equal to */
+ { 0x2260, 0xAD }, /* not equal to */
+ { 0x2264, 0xB2 }, /* less-than or equal to */
+ { 0x2265, 0xB3 }, /* greater-than or equal to */
+ { 0x25CA, 0xD7 }, /* lozenge */
+ { 0xF8FF, 0xF0 }, /* apple logo */
+ { 0xFB01, 0xDE }, /* latin small ligature fi */
+ { 0xFB02, 0xDF }, /* latin small ligature fl */
+};
+/* {{{ end of mappings *from* Unicode for MacRoman */
+
+/* HTML 5 has many more named entities.
+ * Some of them map to two unicode code points, not one.
+ * We're going to use a three-stage table (with an extra one for the entities
+ * with two code points). */
+
+#define ENT_STAGE1_INDEX(k) (((k) & 0xFFF000) >> 12) /* > 1D, we have no mapping */
+#define ENT_STAGE2_INDEX(k) (((k) & 0xFC0) >> 6)
+#define ENT_STAGE3_INDEX(k) ((k) & 0x3F)
+#define ENT_CODE_POINT_FROM_STAGES(i,j,k) (((i) << 12) | ((j) << 6) | (k))
+
+/* Table should be organized with a leading row telling the size of
+ * the table and the default entity (maybe NULL) and the rest being
+ * normal rows ordered by code point so that we can do a binary search */
+typedef union {
+ struct {
+ unsigned size; /* number of remaining entries in the table */
+ const char *default_entity;
+ unsigned short default_entity_len;
+ } leading_entry;
+ struct {
+ unsigned second_cp; /* second code point */
+ const char *entity;
+ unsigned short entity_len;
+ } normal_entry;
+} entity_multicodepoint_row;
+
+/* blocks of these should start at code points k where k % 0xFC0 == 0 */
+typedef struct {
+ char ambiguous; /* if 0 look into entity */
+ union {
+ struct {
+ const char *entity; /* may be NULL */
+ unsigned short entity_len;
+ } ent;
+ const entity_multicodepoint_row *multicodepoint_table;
+ } data;
+} entity_stage3_row;
+
+/* Calculate k & 0x3F Use as offset */
+typedef const entity_stage3_row *entity_stage2_row; /* 64 elements */
+
+/* Calculate k & 0xFC0 >> 6. Use as offset */
+typedef const entity_stage3_row *const *entity_stage1_row; /* 64 elements */
+
+/* For stage 1, Calculate k & 0xFFF000 >> 3*4.
+ * If larger than 1D, we have no mapping. Otherwise lookup that index */
+
+typedef struct {
+ const entity_stage1_row *ms_table;
+ /* for tables with only basic entities, this member is to be accessed
+ * directly for better performance: */
+ const entity_stage3_row *table;
+} entity_table_opt;
+
+/* Replaced "GT" > "gt" and "QUOT" > "quot" for consistency's sake. */
+
+/* {{{ Start of HTML5 multi-stage table for codepoint -> entity */
+
+/* {{{ Start of double code point tables for HTML5 */
+
+static const entity_multicodepoint_row multi_cp_html5_0003C[] = {
+ { {01, "lt", 2} },
+ { {0x020D2, "nvlt", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0003D[] = {
+ { {01, "equals", 6} },
+ { {0x020E5, "bne", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0003E[] = {
+ { {01, "gt", 2} },
+ { {0x020D2, "nvgt", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_00066[] = {
+ { {01, NULL , 0} },
+ { {0x0006A, "fjlig", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0205F[] = {
+ { {01, "MediumSpace", 11} },
+ { {0x0200A, "ThickSpace", 10} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0219D[] = {
+ { {01, "rarrw", 5} },
+ { {0x00338, "nrarrw", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02202[] = {
+ { {01, "part", 4} },
+ { {0x00338, "npart", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02220[] = {
+ { {01, "angle", 5} },
+ { {0x020D2, "nang", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02229[] = {
+ { {01, "cap", 3} },
+ { {0x0FE00, "caps", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0222A[] = {
+ { {01, "cup", 3} },
+ { {0x0FE00, "cups", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0223C[] = {
+ { {01, "sim", 3} },
+ { {0x020D2, "nvsim", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0223D[] = {
+ { {01, "bsim", 4} },
+ { {0x00331, "race", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0223E[] = {
+ { {01, "ac", 2} },
+ { {0x00333, "acE", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02242[] = {
+ { {01, "esim", 4} },
+ { {0x00338, "nesim", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0224B[] = {
+ { {01, "apid", 4} },
+ { {0x00338, "napid", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0224D[] = {
+ { {01, "CupCap", 6} },
+ { {0x020D2, "nvap", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0224E[] = {
+ { {01, "bump", 4} },
+ { {0x00338, "nbump", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0224F[] = {
+ { {01, "HumpEqual", 9} },
+ { {0x00338, "nbumpe", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02250[] = {
+ { {01, "esdot", 5} },
+ { {0x00338, "nedot", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02261[] = {
+ { {01, "Congruent", 9} },
+ { {0x020E5, "bnequiv", 7} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02264[] = {
+ { {01, "leq", 3} },
+ { {0x020D2, "nvle", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02265[] = {
+ { {01, "ge", 2} },
+ { {0x020D2, "nvge", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02266[] = {
+ { {01, "lE", 2} },
+ { {0x00338, "nlE", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02267[] = {
+ { {01, "geqq", 4} },
+ { {0x00338, "NotGreaterFullEqual", 19} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02268[] = {
+ { {01, "lneqq", 5} },
+ { {0x0FE00, "lvertneqq", 9} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02269[] = {
+ { {01, "gneqq", 5} },
+ { {0x0FE00, "gvertneqq", 9} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0226A[] = {
+ { {02, "ll", 2} },
+ { {0x00338, "nLtv", 4} },
+ { {0x020D2, "nLt", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0226B[] = {
+ { {02, "gg", 2} },
+ { {0x00338, "NotGreaterGreater", 17} },
+ { {0x020D2, "nGt", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0227F[] = {
+ { {01, "SucceedsTilde", 13} },
+ { {0x00338, "NotSucceedsTilde", 16} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02282[] = {
+ { {01, "sub", 3} },
+ { {0x020D2, "vnsub", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02283[] = {
+ { {01, "sup", 3} },
+ { {0x020D2, "nsupset", 7} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0228A[] = {
+ { {01, "subsetneq", 9} },
+ { {0x0FE00, "vsubne", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0228B[] = {
+ { {01, "supsetneq", 9} },
+ { {0x0FE00, "vsupne", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_0228F[] = {
+ { {01, "sqsub", 5} },
+ { {0x00338, "NotSquareSubset", 15} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02290[] = {
+ { {01, "sqsupset", 8} },
+ { {0x00338, "NotSquareSuperset", 17} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02293[] = {
+ { {01, "sqcap", 5} },
+ { {0x0FE00, "sqcaps", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02294[] = {
+ { {01, "sqcup", 5} },
+ { {0x0FE00, "sqcups", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022B4[] = {
+ { {01, "LeftTriangleEqual", 17} },
+ { {0x020D2, "nvltrie", 7} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022B5[] = {
+ { {01, "RightTriangleEqual", 18} },
+ { {0x020D2, "nvrtrie", 7} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022D8[] = {
+ { {01, "Ll", 2} },
+ { {0x00338, "nLl", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022D9[] = {
+ { {01, "Gg", 2} },
+ { {0x00338, "nGg", 3} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022DA[] = {
+ { {01, "lesseqgtr", 9} },
+ { {0x0FE00, "lesg", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022DB[] = {
+ { {01, "gtreqless", 9} },
+ { {0x0FE00, "gesl", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022F5[] = {
+ { {01, "isindot", 7} },
+ { {0x00338, "notindot", 8} },
+};
+static const entity_multicodepoint_row multi_cp_html5_022F9[] = {
+ { {01, "isinE", 5} },
+ { {0x00338, "notinE", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02933[] = {
+ { {01, "rarrc", 5} },
+ { {0x00338, "nrarrc", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_029CF[] = {
+ { {01, "LeftTriangleBar", 15} },
+ { {0x00338, "NotLeftTriangleBar", 18} },
+};
+static const entity_multicodepoint_row multi_cp_html5_029D0[] = {
+ { {01, "RightTriangleBar", 16} },
+ { {0x00338, "NotRightTriangleBar", 19} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02A6D[] = {
+ { {01, "congdot", 7} },
+ { {0x00338, "ncongdot", 8} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02A70[] = {
+ { {01, "apE", 3} },
+ { {0x00338, "napE", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02A7D[] = {
+ { {01, "les", 3} },
+ { {0x00338, "nles", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02A7E[] = {
+ { {01, "ges", 3} },
+ { {0x00338, "nges", 4} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AA1[] = {
+ { {01, "LessLess", 8} },
+ { {0x00338, "NotNestedLessLess", 17} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AA2[] = {
+ { {01, "GreaterGreater", 14} },
+ { {0x00338, "NotNestedGreaterGreater", 23} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AAC[] = {
+ { {01, "smte", 4} },
+ { {0x0FE00, "smtes", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AAD[] = {
+ { {01, "late", 4} },
+ { {0x0FE00, "lates", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AAF[] = {
+ { {01, "preceq", 6} },
+ { {0x00338, "NotPrecedesEqual", 16} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AB0[] = {
+ { {01, "SucceedsEqual", 13} },
+ { {0x00338, "NotSucceedsEqual", 16} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AC5[] = {
+ { {01, "subE", 4} },
+ { {0x00338, "nsubE", 5} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AC6[] = {
+ { {01, "supseteqq", 9} },
+ { {0x00338, "nsupseteqq", 10} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02ACB[] = {
+ { {01, "subsetneqq", 10} },
+ { {0x0FE00, "vsubnE", 6} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02ACC[] = {
+ { {01, "supnE", 5} },
+ { {0x0FE00, "varsupsetneqq", 13} },
+};
+static const entity_multicodepoint_row multi_cp_html5_02AFD[] = {
+ { {01, NULL , 0} },
+ { {0x0FE00, "varsupsetneqq", 13} },
+};
+
+/* End of double code point tables }}} */
+
+/* {{{ Stage 3 Tables for HTML5 */
+
+static const entity_stage3_row empty_stage3_table[] = {
+ /* 64 elements */
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+static const entity_stage3_row stage3_table_html5_00000[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Tab", 3} } }, {0, { {"NewLine", 7} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"excl", 4} } }, {0, { {"quot", 4} } }, {0, { {"num", 3} } },
+ {0, { {"dollar", 6} } }, {0, { {"percnt", 6} } }, {0, { {"amp", 3} } }, {0, { {"apos", 4} } },
+ {0, { {"lpar", 4} } }, {0, { {"rpar", 4} } }, {0, { {"ast", 3} } }, {0, { {"plus", 4} } },
+ {0, { {"comma", 5} } }, {0, { {NULL, 0} } }, {0, { {"period", 6} } }, {0, { {"sol", 3} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"colon", 5} } }, {0, { {"semi", 4} } },
+ {1, { {(void *)multi_cp_html5_0003C} } }, {1, { {(void *)multi_cp_html5_0003D} } }, {1, { {(void *)multi_cp_html5_0003E} } }, {0, { {"quest", 5} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00040[] = {
+ {0, { {"commat", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lbrack", 6} } },
+ {0, { {"bsol", 4} } }, {0, { {"rsqb", 4} } }, {0, { {"Hat", 3} } }, {0, { {"lowbar", 6} } },
+ {0, { {"grave", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_00066} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lbrace", 6} } },
+ {0, { {"vert", 4} } }, {0, { {"rcub", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00080[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"nbsp", 4} } }, {0, { {"iexcl", 5} } }, {0, { {"cent", 4} } }, {0, { {"pound", 5} } },
+ {0, { {"curren", 6} } }, {0, { {"yen", 3} } }, {0, { {"brvbar", 6} } }, {0, { {"sect", 4} } },
+ {0, { {"DoubleDot", 9} } }, {0, { {"copy", 4} } }, {0, { {"ordf", 4} } }, {0, { {"laquo", 5} } },
+ {0, { {"not", 3} } }, {0, { {"shy", 3} } }, {0, { {"reg", 3} } }, {0, { {"macr", 4} } },
+ {0, { {"deg", 3} } }, {0, { {"plusmn", 6} } }, {0, { {"sup2", 4} } }, {0, { {"sup3", 4} } },
+ {0, { {"DiacriticalAcute", 16} } }, {0, { {"micro", 5} } }, {0, { {"para", 4} } }, {0, { {"CenterDot", 9} } },
+ {0, { {"Cedilla", 7} } }, {0, { {"sup1", 4} } }, {0, { {"ordm", 4} } }, {0, { {"raquo", 5} } },
+ {0, { {"frac14", 6} } }, {0, { {"half", 4} } }, {0, { {"frac34", 6} } }, {0, { {"iquest", 6} } },
+};
+
+static const entity_stage3_row stage3_table_html5_000C0[] = {
+ {0, { {"Agrave", 6} } }, {0, { {"Aacute", 6} } }, {0, { {"Acirc", 5} } }, {0, { {"Atilde", 6} } },
+ {0, { {"Auml", 4} } }, {0, { {"Aring", 5} } }, {0, { {"AElig", 5} } }, {0, { {"Ccedil", 6} } },
+ {0, { {"Egrave", 6} } }, {0, { {"Eacute", 6} } }, {0, { {"Ecirc", 5} } }, {0, { {"Euml", 4} } },
+ {0, { {"Igrave", 6} } }, {0, { {"Iacute", 6} } }, {0, { {"Icirc", 5} } }, {0, { {"Iuml", 4} } },
+ {0, { {"ETH", 3} } }, {0, { {"Ntilde", 6} } }, {0, { {"Ograve", 6} } }, {0, { {"Oacute", 6} } },
+ {0, { {"Ocirc", 5} } }, {0, { {"Otilde", 6} } }, {0, { {"Ouml", 4} } }, {0, { {"times", 5} } },
+ {0, { {"Oslash", 6} } }, {0, { {"Ugrave", 6} } }, {0, { {"Uacute", 6} } }, {0, { {"Ucirc", 5} } },
+ {0, { {"Uuml", 4} } }, {0, { {"Yacute", 6} } }, {0, { {"THORN", 5} } }, {0, { {"szlig", 5} } },
+ {0, { {"agrave", 6} } }, {0, { {"aacute", 6} } }, {0, { {"acirc", 5} } }, {0, { {"atilde", 6} } },
+ {0, { {"auml", 4} } }, {0, { {"aring", 5} } }, {0, { {"aelig", 5} } }, {0, { {"ccedil", 6} } },
+ {0, { {"egrave", 6} } }, {0, { {"eacute", 6} } }, {0, { {"ecirc", 5} } }, {0, { {"euml", 4} } },
+ {0, { {"igrave", 6} } }, {0, { {"iacute", 6} } }, {0, { {"icirc", 5} } }, {0, { {"iuml", 4} } },
+ {0, { {"eth", 3} } }, {0, { {"ntilde", 6} } }, {0, { {"ograve", 6} } }, {0, { {"oacute", 6} } },
+ {0, { {"ocirc", 5} } }, {0, { {"otilde", 6} } }, {0, { {"ouml", 4} } }, {0, { {"divide", 6} } },
+ {0, { {"oslash", 6} } }, {0, { {"ugrave", 6} } }, {0, { {"uacute", 6} } }, {0, { {"ucirc", 5} } },
+ {0, { {"uuml", 4} } }, {0, { {"yacute", 6} } }, {0, { {"thorn", 5} } }, {0, { {"yuml", 4} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00100[] = {
+ {0, { {"Amacr", 5} } }, {0, { {"amacr", 5} } }, {0, { {"Abreve", 6} } }, {0, { {"abreve", 6} } },
+ {0, { {"Aogon", 5} } }, {0, { {"aogon", 5} } }, {0, { {"Cacute", 6} } }, {0, { {"cacute", 6} } },
+ {0, { {"Ccirc", 5} } }, {0, { {"ccirc", 5} } }, {0, { {"Cdot", 4} } }, {0, { {"cdot", 4} } },
+ {0, { {"Ccaron", 6} } }, {0, { {"ccaron", 6} } }, {0, { {"Dcaron", 6} } }, {0, { {"dcaron", 6} } },
+ {0, { {"Dstrok", 6} } }, {0, { {"dstrok", 6} } }, {0, { {"Emacr", 5} } }, {0, { {"emacr", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"Edot", 4} } }, {0, { {"edot", 4} } },
+ {0, { {"Eogon", 5} } }, {0, { {"eogon", 5} } }, {0, { {"Ecaron", 6} } }, {0, { {"ecaron", 6} } },
+ {0, { {"Gcirc", 5} } }, {0, { {"gcirc", 5} } }, {0, { {"Gbreve", 6} } }, {0, { {"gbreve", 6} } },
+ {0, { {"Gdot", 4} } }, {0, { {"gdot", 4} } }, {0, { {"Gcedil", 6} } }, {0, { {NULL, 0} } },
+ {0, { {"Hcirc", 5} } }, {0, { {"hcirc", 5} } }, {0, { {"Hstrok", 6} } }, {0, { {"hstrok", 6} } },
+ {0, { {"Itilde", 6} } }, {0, { {"itilde", 6} } }, {0, { {"Imacr", 5} } }, {0, { {"imacr", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"Iogon", 5} } }, {0, { {"iogon", 5} } },
+ {0, { {"Idot", 4} } }, {0, { {"inodot", 6} } }, {0, { {"IJlig", 5} } }, {0, { {"ijlig", 5} } },
+ {0, { {"Jcirc", 5} } }, {0, { {"jcirc", 5} } }, {0, { {"Kcedil", 6} } }, {0, { {"kcedil", 6} } },
+ {0, { {"kgreen", 6} } }, {0, { {"Lacute", 6} } }, {0, { {"lacute", 6} } }, {0, { {"Lcedil", 6} } },
+ {0, { {"lcedil", 6} } }, {0, { {"Lcaron", 6} } }, {0, { {"lcaron", 6} } }, {0, { {"Lmidot", 6} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00140[] = {
+ {0, { {"lmidot", 6} } }, {0, { {"Lstrok", 6} } }, {0, { {"lstrok", 6} } }, {0, { {"Nacute", 6} } },
+ {0, { {"nacute", 6} } }, {0, { {"Ncedil", 6} } }, {0, { {"ncedil", 6} } }, {0, { {"Ncaron", 6} } },
+ {0, { {"ncaron", 6} } }, {0, { {"napos", 5} } }, {0, { {"ENG", 3} } }, {0, { {"eng", 3} } },
+ {0, { {"Omacr", 5} } }, {0, { {"omacr", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Odblac", 6} } }, {0, { {"odblac", 6} } }, {0, { {"OElig", 5} } }, {0, { {"oelig", 5} } },
+ {0, { {"Racute", 6} } }, {0, { {"racute", 6} } }, {0, { {"Rcedil", 6} } }, {0, { {"rcedil", 6} } },
+ {0, { {"Rcaron", 6} } }, {0, { {"rcaron", 6} } }, {0, { {"Sacute", 6} } }, {0, { {"sacute", 6} } },
+ {0, { {"Scirc", 5} } }, {0, { {"scirc", 5} } }, {0, { {"Scedil", 6} } }, {0, { {"scedil", 6} } },
+ {0, { {"Scaron", 6} } }, {0, { {"scaron", 6} } }, {0, { {"Tcedil", 6} } }, {0, { {"tcedil", 6} } },
+ {0, { {"Tcaron", 6} } }, {0, { {"tcaron", 6} } }, {0, { {"Tstrok", 6} } }, {0, { {"tstrok", 6} } },
+ {0, { {"Utilde", 6} } }, {0, { {"utilde", 6} } }, {0, { {"Umacr", 5} } }, {0, { {"umacr", 5} } },
+ {0, { {"Ubreve", 6} } }, {0, { {"ubreve", 6} } }, {0, { {"Uring", 5} } }, {0, { {"uring", 5} } },
+ {0, { {"Udblac", 6} } }, {0, { {"udblac", 6} } }, {0, { {"Uogon", 5} } }, {0, { {"uogon", 5} } },
+ {0, { {"Wcirc", 5} } }, {0, { {"wcirc", 5} } }, {0, { {"Ycirc", 5} } }, {0, { {"ycirc", 5} } },
+ {0, { {"Yuml", 4} } }, {0, { {"Zacute", 6} } }, {0, { {"zacute", 6} } }, {0, { {"Zdot", 4} } },
+ {0, { {"zdot", 4} } }, {0, { {"Zcaron", 6} } }, {0, { {"zcaron", 6} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00180[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"fnof", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"imped", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_001C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"gacute", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00200[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"jmath", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_002C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"circ", 4} } }, {0, { {"Hacek", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Breve", 5} } }, {0, { {"dot", 3} } }, {0, { {"ring", 4} } }, {0, { {"ogon", 4} } },
+ {0, { {"DiacriticalTilde", 16} } }, {0, { {"DiacriticalDoubleAcute", 22} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00300[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"DownBreve", 9} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00380[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Alpha", 5} } }, {0, { {"Beta", 4} } }, {0, { {"Gamma", 5} } },
+ {0, { {"Delta", 5} } }, {0, { {"Epsilon", 7} } }, {0, { {"Zeta", 4} } }, {0, { {"Eta", 3} } },
+ {0, { {"Theta", 5} } }, {0, { {"Iota", 4} } }, {0, { {"Kappa", 5} } }, {0, { {"Lambda", 6} } },
+ {0, { {"Mu", 2} } }, {0, { {"Nu", 2} } }, {0, { {"Xi", 2} } }, {0, { {"Omicron", 7} } },
+ {0, { {"Pi", 2} } }, {0, { {"Rho", 3} } }, {0, { {NULL, 0} } }, {0, { {"Sigma", 5} } },
+ {0, { {"Tau", 3} } }, {0, { {"Upsilon", 7} } }, {0, { {"Phi", 3} } }, {0, { {"Chi", 3} } },
+ {0, { {"Psi", 3} } }, {0, { {"Omega", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"alpha", 5} } }, {0, { {"beta", 4} } }, {0, { {"gamma", 5} } },
+ {0, { {"delta", 5} } }, {0, { {"epsi", 4} } }, {0, { {"zeta", 4} } }, {0, { {"eta", 3} } },
+ {0, { {"theta", 5} } }, {0, { {"iota", 4} } }, {0, { {"kappa", 5} } }, {0, { {"lambda", 6} } },
+ {0, { {"mu", 2} } }, {0, { {"nu", 2} } }, {0, { {"xi", 2} } }, {0, { {"omicron", 7} } },
+};
+
+static const entity_stage3_row stage3_table_html5_003C0[] = {
+ {0, { {"pi", 2} } }, {0, { {"rho", 3} } }, {0, { {"sigmav", 6} } }, {0, { {"sigma", 5} } },
+ {0, { {"tau", 3} } }, {0, { {"upsi", 4} } }, {0, { {"phi", 3} } }, {0, { {"chi", 3} } },
+ {0, { {"psi", 3} } }, {0, { {"omega", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"thetasym", 8} } }, {0, { {"upsih", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"straightphi", 11} } }, {0, { {"piv", 3} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Gammad", 6} } }, {0, { {"gammad", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"varkappa", 8} } }, {0, { {"rhov", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"straightepsilon", 15} } }, {0, { {"backepsilon", 11} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00400[] = {
+ {0, { {NULL, 0} } }, {0, { {"IOcy", 4} } }, {0, { {"DJcy", 4} } }, {0, { {"GJcy", 4} } },
+ {0, { {"Jukcy", 5} } }, {0, { {"DScy", 4} } }, {0, { {"Iukcy", 5} } }, {0, { {"YIcy", 4} } },
+ {0, { {"Jsercy", 6} } }, {0, { {"LJcy", 4} } }, {0, { {"NJcy", 4} } }, {0, { {"TSHcy", 5} } },
+ {0, { {"KJcy", 4} } }, {0, { {NULL, 0} } }, {0, { {"Ubrcy", 5} } }, {0, { {"DZcy", 4} } },
+ {0, { {"Acy", 3} } }, {0, { {"Bcy", 3} } }, {0, { {"Vcy", 3} } }, {0, { {"Gcy", 3} } },
+ {0, { {"Dcy", 3} } }, {0, { {"IEcy", 4} } }, {0, { {"ZHcy", 4} } }, {0, { {"Zcy", 3} } },
+ {0, { {"Icy", 3} } }, {0, { {"Jcy", 3} } }, {0, { {"Kcy", 3} } }, {0, { {"Lcy", 3} } },
+ {0, { {"Mcy", 3} } }, {0, { {"Ncy", 3} } }, {0, { {"Ocy", 3} } }, {0, { {"Pcy", 3} } },
+ {0, { {"Rcy", 3} } }, {0, { {"Scy", 3} } }, {0, { {"Tcy", 3} } }, {0, { {"Ucy", 3} } },
+ {0, { {"Fcy", 3} } }, {0, { {"KHcy", 4} } }, {0, { {"TScy", 4} } }, {0, { {"CHcy", 4} } },
+ {0, { {"SHcy", 4} } }, {0, { {"SHCHcy", 6} } }, {0, { {"HARDcy", 6} } }, {0, { {"Ycy", 3} } },
+ {0, { {"SOFTcy", 6} } }, {0, { {"Ecy", 3} } }, {0, { {"YUcy", 4} } }, {0, { {"YAcy", 4} } },
+ {0, { {"acy", 3} } }, {0, { {"bcy", 3} } }, {0, { {"vcy", 3} } }, {0, { {"gcy", 3} } },
+ {0, { {"dcy", 3} } }, {0, { {"iecy", 4} } }, {0, { {"zhcy", 4} } }, {0, { {"zcy", 3} } },
+ {0, { {"icy", 3} } }, {0, { {"jcy", 3} } }, {0, { {"kcy", 3} } }, {0, { {"lcy", 3} } },
+ {0, { {"mcy", 3} } }, {0, { {"ncy", 3} } }, {0, { {"ocy", 3} } }, {0, { {"pcy", 3} } },
+};
+
+static const entity_stage3_row stage3_table_html5_00440[] = {
+ {0, { {"rcy", 3} } }, {0, { {"scy", 3} } }, {0, { {"tcy", 3} } }, {0, { {"ucy", 3} } },
+ {0, { {"fcy", 3} } }, {0, { {"khcy", 4} } }, {0, { {"tscy", 4} } }, {0, { {"chcy", 4} } },
+ {0, { {"shcy", 4} } }, {0, { {"shchcy", 6} } }, {0, { {"hardcy", 6} } }, {0, { {"ycy", 3} } },
+ {0, { {"softcy", 6} } }, {0, { {"ecy", 3} } }, {0, { {"yucy", 4} } }, {0, { {"yacy", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"iocy", 4} } }, {0, { {"djcy", 4} } }, {0, { {"gjcy", 4} } },
+ {0, { {"jukcy", 5} } }, {0, { {"dscy", 4} } }, {0, { {"iukcy", 5} } }, {0, { {"yicy", 4} } },
+ {0, { {"jsercy", 6} } }, {0, { {"ljcy", 4} } }, {0, { {"njcy", 4} } }, {0, { {"tshcy", 5} } },
+ {0, { {"kjcy", 4} } }, {0, { {NULL, 0} } }, {0, { {"ubrcy", 5} } }, {0, { {"dzcy", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02000[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"ensp", 4} } }, {0, { {"emsp", 4} } },
+ {0, { {"emsp13", 6} } }, {0, { {"emsp14", 6} } }, {0, { {NULL, 0} } }, {0, { {"numsp", 5} } },
+ {0, { {"puncsp", 6} } }, {0, { {"ThinSpace", 9} } }, {0, { {"hairsp", 6} } }, {0, { {"ZeroWidthSpace", 14} } },
+ {0, { {"zwnj", 4} } }, {0, { {"zwj", 3} } }, {0, { {"lrm", 3} } }, {0, { {"rlm", 3} } },
+ {0, { {"hyphen", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"ndash", 5} } },
+ {0, { {"mdash", 5} } }, {0, { {"horbar", 6} } }, {0, { {"Verbar", 6} } }, {0, { {NULL, 0} } },
+ {0, { {"OpenCurlyQuote", 14} } }, {0, { {"rsquo", 5} } }, {0, { {"sbquo", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"OpenCurlyDoubleQuote", 20} } }, {0, { {"rdquo", 5} } }, {0, { {"bdquo", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"dagger", 6} } }, {0, { {"Dagger", 6} } }, {0, { {"bull", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"nldr", 4} } }, {0, { {"hellip", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"permil", 6} } }, {0, { {"pertenk", 7} } }, {0, { {"prime", 5} } }, {0, { {"Prime", 5} } },
+ {0, { {"tprime", 6} } }, {0, { {"backprime", 9} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"lsaquo", 6} } }, {0, { {"rsaquo", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"oline", 5} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02040[] = {
+ {0, { {NULL, 0} } }, {0, { {"caret", 5} } }, {0, { {NULL, 0} } }, {0, { {"hybull", 6} } },
+ {0, { {"frasl", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"bsemi", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"qprime", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_0205F} } },
+ {0, { {"NoBreak", 7} } }, {0, { {"af", 2} } }, {0, { {"InvisibleTimes", 14} } }, {0, { {"ic", 2} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02080[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"euro", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_020C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"TripleDot", 9} } },
+ {0, { {"DotDot", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02100[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"complexes", 9} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"incare", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"gscr", 4} } }, {0, { {"HilbertSpace", 12} } },
+ {0, { {"Hfr", 3} } }, {0, { {"Hopf", 4} } }, {0, { {"planckh", 7} } }, {0, { {"planck", 6} } },
+ {0, { {"imagline", 8} } }, {0, { {"Ifr", 3} } }, {0, { {"lagran", 6} } }, {0, { {"ell", 3} } },
+ {0, { {NULL, 0} } }, {0, { {"naturals", 8} } }, {0, { {"numero", 6} } }, {0, { {"copysr", 6} } },
+ {0, { {"wp", 2} } }, {0, { {"primes", 6} } }, {0, { {"rationals", 9} } }, {0, { {"realine", 7} } },
+ {0, { {"Rfr", 3} } }, {0, { {"Ropf", 4} } }, {0, { {"rx", 2} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"trade", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"Zopf", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"mho", 3} } },
+ {0, { {"Zfr", 3} } }, {0, { {"iiota", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Bscr", 4} } }, {0, { {"Cfr", 3} } }, {0, { {NULL, 0} } }, {0, { {"escr", 4} } },
+ {0, { {"expectation", 11} } }, {0, { {"Fouriertrf", 10} } }, {0, { {NULL, 0} } }, {0, { {"Mellintrf", 9} } },
+ {0, { {"orderof", 7} } }, {0, { {"aleph", 5} } }, {0, { {"beth", 4} } }, {0, { {"gimel", 5} } },
+ {0, { {"daleth", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02140[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"CapitalDifferentialD", 20} } }, {0, { {"DifferentialD", 13} } }, {0, { {"exponentiale", 12} } },
+ {0, { {"ImaginaryI", 10} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"frac13", 6} } },
+ {0, { {"frac23", 6} } }, {0, { {"frac15", 6} } }, {0, { {"frac25", 6} } }, {0, { {"frac35", 6} } },
+ {0, { {"frac45", 6} } }, {0, { {"frac16", 6} } }, {0, { {"frac56", 6} } }, {0, { {"frac18", 6} } },
+ {0, { {"frac38", 6} } }, {0, { {"frac58", 6} } }, {0, { {"frac78", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02180[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"larr", 4} } }, {0, { {"uarr", 4} } }, {0, { {"srarr", 5} } }, {0, { {"darr", 4} } },
+ {0, { {"harr", 4} } }, {0, { {"UpDownArrow", 11} } }, {0, { {"nwarrow", 7} } }, {0, { {"UpperRightArrow", 15} } },
+ {0, { {"LowerRightArrow", 15} } }, {0, { {"swarr", 5} } }, {0, { {"nleftarrow", 10} } }, {0, { {"nrarr", 5} } },
+ {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_0219D} } }, {0, { {"Larr", 4} } }, {0, { {"Uarr", 4} } },
+ {0, { {"twoheadrightarrow", 17} } }, {0, { {"Darr", 4} } }, {0, { {"larrtl", 6} } }, {0, { {"rarrtl", 6} } },
+ {0, { {"LeftTeeArrow", 12} } }, {0, { {"UpTeeArrow", 10} } }, {0, { {"map", 3} } }, {0, { {"DownTeeArrow", 12} } },
+ {0, { {NULL, 0} } }, {0, { {"larrhk", 6} } }, {0, { {"rarrhk", 6} } }, {0, { {"larrlp", 6} } },
+ {0, { {"looparrowright", 14} } }, {0, { {"harrw", 5} } }, {0, { {"nleftrightarrow", 15} } }, {0, { {NULL, 0} } },
+ {0, { {"Lsh", 3} } }, {0, { {"rsh", 3} } }, {0, { {"ldsh", 4} } }, {0, { {"rdsh", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"crarr", 5} } }, {0, { {"curvearrowleft", 14} } }, {0, { {"curarr", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"olarr", 5} } }, {0, { {"orarr", 5} } },
+ {0, { {"leftharpoonup", 13} } }, {0, { {"leftharpoondown", 15} } }, {0, { {"RightUpVector", 13} } }, {0, { {"uharl", 5} } },
+};
+
+static const entity_stage3_row stage3_table_html5_021C0[] = {
+ {0, { {"rharu", 5} } }, {0, { {"rhard", 5} } }, {0, { {"RightDownVector", 15} } }, {0, { {"dharl", 5} } },
+ {0, { {"rightleftarrows", 15} } }, {0, { {"udarr", 5} } }, {0, { {"lrarr", 5} } }, {0, { {"llarr", 5} } },
+ {0, { {"upuparrows", 10} } }, {0, { {"rrarr", 5} } }, {0, { {"downdownarrows", 14} } }, {0, { {"leftrightharpoons", 17} } },
+ {0, { {"rightleftharpoons", 17} } }, {0, { {"nLeftarrow", 10} } }, {0, { {"nhArr", 5} } }, {0, { {"nrArr", 5} } },
+ {0, { {"DoubleLeftArrow", 15} } }, {0, { {"DoubleUpArrow", 13} } }, {0, { {"Implies", 7} } }, {0, { {"Downarrow", 9} } },
+ {0, { {"hArr", 4} } }, {0, { {"Updownarrow", 11} } }, {0, { {"nwArr", 5} } }, {0, { {"neArr", 5} } },
+ {0, { {"seArr", 5} } }, {0, { {"swArr", 5} } }, {0, { {"lAarr", 5} } }, {0, { {"rAarr", 5} } },
+ {0, { {NULL, 0} } }, {0, { {"zigrarr", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"LeftArrowBar", 12} } }, {0, { {"RightArrowBar", 13} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"DownArrowUpArrow", 16} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"loarr", 5} } }, {0, { {"roarr", 5} } }, {0, { {"hoarr", 5} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02200[] = {
+ {0, { {"forall", 6} } }, {0, { {"comp", 4} } }, {1, { {(void *)multi_cp_html5_02202} } }, {0, { {"Exists", 6} } },
+ {0, { {"nexist", 6} } }, {0, { {"empty", 5} } }, {0, { {NULL, 0} } }, {0, { {"nabla", 5} } },
+ {0, { {"isinv", 5} } }, {0, { {"notin", 5} } }, {0, { {NULL, 0} } }, {0, { {"ReverseElement", 14} } },
+ {0, { {"notniva", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"prod", 4} } },
+ {0, { {"Coproduct", 9} } }, {0, { {"sum", 3} } }, {0, { {"minus", 5} } }, {0, { {"MinusPlus", 9} } },
+ {0, { {"plusdo", 6} } }, {0, { {NULL, 0} } }, {0, { {"ssetmn", 6} } }, {0, { {"lowast", 6} } },
+ {0, { {"compfn", 6} } }, {0, { {NULL, 0} } }, {0, { {"Sqrt", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"prop", 4} } }, {0, { {"infin", 5} } }, {0, { {"angrt", 5} } },
+ {1, { {(void *)multi_cp_html5_02220} } }, {0, { {"angmsd", 6} } }, {0, { {"angsph", 6} } }, {0, { {"mid", 3} } },
+ {0, { {"nshortmid", 9} } }, {0, { {"shortparallel", 13} } }, {0, { {"nparallel", 9} } }, {0, { {"and", 3} } },
+ {0, { {"or", 2} } }, {1, { {(void *)multi_cp_html5_02229} } }, {1, { {(void *)multi_cp_html5_0222A} } }, {0, { {"Integral", 8} } },
+ {0, { {"Int", 3} } }, {0, { {"tint", 4} } }, {0, { {"ContourIntegral", 15} } }, {0, { {"DoubleContourIntegral", 21} } },
+ {0, { {"Cconint", 7} } }, {0, { {"cwint", 5} } }, {0, { {"cwconint", 8} } }, {0, { {"awconint", 8} } },
+ {0, { {"there4", 6} } }, {0, { {"Because", 7} } }, {0, { {"ratio", 5} } }, {0, { {"Colon", 5} } },
+ {0, { {"minusd", 6} } }, {0, { {NULL, 0} } }, {0, { {"mDDot", 5} } }, {0, { {"homtht", 6} } },
+ {1, { {(void *)multi_cp_html5_0223C} } }, {1, { {(void *)multi_cp_html5_0223D} } }, {1, { {(void *)multi_cp_html5_0223E} } }, {0, { {"acd", 3} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02240[] = {
+ {0, { {"wr", 2} } }, {0, { {"NotTilde", 8} } }, {1, { {(void *)multi_cp_html5_02242} } }, {0, { {"simeq", 5} } },
+ {0, { {"nsime", 5} } }, {0, { {"TildeFullEqual", 14} } }, {0, { {"simne", 5} } }, {0, { {"ncong", 5} } },
+ {0, { {"approx", 6} } }, {0, { {"napprox", 7} } }, {0, { {"ape", 3} } }, {1, { {(void *)multi_cp_html5_0224B} } },
+ {0, { {"bcong", 5} } }, {1, { {(void *)multi_cp_html5_0224D} } }, {1, { {(void *)multi_cp_html5_0224E} } }, {1, { {(void *)multi_cp_html5_0224F} } },
+ {1, { {(void *)multi_cp_html5_02250} } }, {0, { {"doteqdot", 8} } }, {0, { {"fallingdotseq", 13} } }, {0, { {"risingdotseq", 12} } },
+ {0, { {"coloneq", 7} } }, {0, { {"eqcolon", 7} } }, {0, { {"ecir", 4} } }, {0, { {"circeq", 6} } },
+ {0, { {NULL, 0} } }, {0, { {"wedgeq", 6} } }, {0, { {"veeeq", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"triangleq", 9} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"equest", 6} } },
+ {0, { {"NotEqual", 8} } }, {1, { {(void *)multi_cp_html5_02261} } }, {0, { {"NotCongruent", 12} } }, {0, { {NULL, 0} } },
+ {1, { {(void *)multi_cp_html5_02264} } }, {1, { {(void *)multi_cp_html5_02265} } }, {1, { {(void *)multi_cp_html5_02266} } }, {1, { {(void *)multi_cp_html5_02267} } },
+ {1, { {(void *)multi_cp_html5_02268} } }, {1, { {(void *)multi_cp_html5_02269} } }, {1, { {(void *)multi_cp_html5_0226A} } }, {1, { {(void *)multi_cp_html5_0226B} } },
+ {0, { {"between", 7} } }, {0, { {"NotCupCap", 9} } }, {0, { {"NotLess", 7} } }, {0, { {"ngtr", 4} } },
+ {0, { {"NotLessEqual", 12} } }, {0, { {"ngeq", 4} } }, {0, { {"LessTilde", 9} } }, {0, { {"GreaterTilde", 12} } },
+ {0, { {"nlsim", 5} } }, {0, { {"ngsim", 5} } }, {0, { {"lessgtr", 7} } }, {0, { {"gl", 2} } },
+ {0, { {"ntlg", 4} } }, {0, { {"NotGreaterLess", 14} } }, {0, { {"prec", 4} } }, {0, { {"succ", 4} } },
+ {0, { {"PrecedesSlantEqual", 18} } }, {0, { {"succcurlyeq", 11} } }, {0, { {"precsim", 7} } }, {1, { {(void *)multi_cp_html5_0227F} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02280[] = {
+ {0, { {"npr", 3} } }, {0, { {"NotSucceeds", 11} } }, {1, { {(void *)multi_cp_html5_02282} } }, {1, { {(void *)multi_cp_html5_02283} } },
+ {0, { {"nsub", 4} } }, {0, { {"nsup", 4} } }, {0, { {"SubsetEqual", 11} } }, {0, { {"supe", 4} } },
+ {0, { {"NotSubsetEqual", 14} } }, {0, { {"NotSupersetEqual", 16} } }, {1, { {(void *)multi_cp_html5_0228A} } }, {1, { {(void *)multi_cp_html5_0228B} } },
+ {0, { {NULL, 0} } }, {0, { {"cupdot", 6} } }, {0, { {"UnionPlus", 9} } }, {1, { {(void *)multi_cp_html5_0228F} } },
+ {1, { {(void *)multi_cp_html5_02290} } }, {0, { {"SquareSubsetEqual", 17} } }, {0, { {"SquareSupersetEqual", 19} } }, {1, { {(void *)multi_cp_html5_02293} } },
+ {1, { {(void *)multi_cp_html5_02294} } }, {0, { {"CirclePlus", 10} } }, {0, { {"ominus", 6} } }, {0, { {"CircleTimes", 11} } },
+ {0, { {"osol", 4} } }, {0, { {"CircleDot", 9} } }, {0, { {"ocir", 4} } }, {0, { {"oast", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"odash", 5} } }, {0, { {"boxplus", 7} } }, {0, { {"boxminus", 8} } },
+ {0, { {"timesb", 6} } }, {0, { {"sdotb", 5} } }, {0, { {"vdash", 5} } }, {0, { {"dashv", 5} } },
+ {0, { {"DownTee", 7} } }, {0, { {"perp", 4} } }, {0, { {NULL, 0} } }, {0, { {"models", 6} } },
+ {0, { {"DoubleRightTee", 14} } }, {0, { {"Vdash", 5} } }, {0, { {"Vvdash", 6} } }, {0, { {"VDash", 5} } },
+ {0, { {"nvdash", 6} } }, {0, { {"nvDash", 6} } }, {0, { {"nVdash", 6} } }, {0, { {"nVDash", 6} } },
+ {0, { {"prurel", 6} } }, {0, { {NULL, 0} } }, {0, { {"vartriangleleft", 15} } }, {0, { {"vrtri", 5} } },
+ {1, { {(void *)multi_cp_html5_022B4} } }, {1, { {(void *)multi_cp_html5_022B5} } }, {0, { {"origof", 6} } }, {0, { {"imof", 4} } },
+ {0, { {"mumap", 5} } }, {0, { {"hercon", 6} } }, {0, { {"intcal", 6} } }, {0, { {"veebar", 6} } },
+ {0, { {NULL, 0} } }, {0, { {"barvee", 6} } }, {0, { {"angrtvb", 7} } }, {0, { {"lrtri", 5} } },
+};
+
+static const entity_stage3_row stage3_table_html5_022C0[] = {
+ {0, { {"xwedge", 6} } }, {0, { {"xvee", 4} } }, {0, { {"bigcap", 6} } }, {0, { {"bigcup", 6} } },
+ {0, { {"diamond", 7} } }, {0, { {"sdot", 4} } }, {0, { {"Star", 4} } }, {0, { {"divonx", 6} } },
+ {0, { {"bowtie", 6} } }, {0, { {"ltimes", 6} } }, {0, { {"rtimes", 6} } }, {0, { {"lthree", 6} } },
+ {0, { {"rthree", 6} } }, {0, { {"backsimeq", 9} } }, {0, { {"curlyvee", 8} } }, {0, { {"curlywedge", 10} } },
+ {0, { {"Sub", 3} } }, {0, { {"Supset", 6} } }, {0, { {"Cap", 3} } }, {0, { {"Cup", 3} } },
+ {0, { {"pitchfork", 9} } }, {0, { {"epar", 4} } }, {0, { {"lessdot", 7} } }, {0, { {"gtrdot", 6} } },
+ {1, { {(void *)multi_cp_html5_022D8} } }, {1, { {(void *)multi_cp_html5_022D9} } }, {1, { {(void *)multi_cp_html5_022DA} } }, {1, { {(void *)multi_cp_html5_022DB} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"curlyeqprec", 11} } }, {0, { {"cuesc", 5} } },
+ {0, { {"NotPrecedesSlantEqual", 21} } }, {0, { {"NotSucceedsSlantEqual", 21} } }, {0, { {"NotSquareSubsetEqual", 20} } }, {0, { {"NotSquareSupersetEqual", 22} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lnsim", 5} } }, {0, { {"gnsim", 5} } },
+ {0, { {"precnsim", 8} } }, {0, { {"scnsim", 6} } }, {0, { {"nltri", 5} } }, {0, { {"ntriangleright", 14} } },
+ {0, { {"nltrie", 6} } }, {0, { {"NotRightTriangleEqual", 21} } }, {0, { {"vellip", 6} } }, {0, { {"ctdot", 5} } },
+ {0, { {"utdot", 5} } }, {0, { {"dtdot", 5} } }, {0, { {"disin", 5} } }, {0, { {"isinsv", 6} } },
+ {0, { {"isins", 5} } }, {1, { {(void *)multi_cp_html5_022F5} } }, {0, { {"notinvc", 7} } }, {0, { {"notinvb", 7} } },
+ {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_022F9} } }, {0, { {"nisd", 4} } }, {0, { {"xnis", 4} } },
+ {0, { {"nis", 3} } }, {0, { {"notnivc", 7} } }, {0, { {"notnivb", 7} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02300[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"barwed", 6} } }, {0, { {"doublebarwedge", 14} } }, {0, { {NULL, 0} } },
+ {0, { {"lceil", 5} } }, {0, { {"RightCeiling", 12} } }, {0, { {"LeftFloor", 9} } }, {0, { {"RightFloor", 10} } },
+ {0, { {"drcrop", 6} } }, {0, { {"dlcrop", 6} } }, {0, { {"urcrop", 6} } }, {0, { {"ulcrop", 6} } },
+ {0, { {"bnot", 4} } }, {0, { {NULL, 0} } }, {0, { {"profline", 8} } }, {0, { {"profsurf", 8} } },
+ {0, { {NULL, 0} } }, {0, { {"telrec", 6} } }, {0, { {"target", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"ulcorner", 8} } }, {0, { {"urcorner", 8} } }, {0, { {"llcorner", 8} } }, {0, { {"drcorn", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"frown", 5} } }, {0, { {"smile", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"cylcty", 6} } }, {0, { {"profalar", 8} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"topbot", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"ovbar", 5} } }, {0, { {NULL, 0} } }, {0, { {"solbar", 6} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02340[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"angzarr", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02380[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lmoust", 6} } }, {0, { {"rmoust", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"OverBracket", 11} } }, {0, { {"bbrk", 4} } }, {0, { {"bbrktbrk", 8} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_023C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"OverParenthesis", 15} } }, {0, { {"UnderParenthesis", 16} } }, {0, { {"OverBrace", 9} } }, {0, { {"UnderBrace", 10} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"trpezium", 8} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"elinters", 8} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02400[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"blank", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_024C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"oS", 2} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02500[] = {
+ {0, { {"HorizontalLine", 14} } }, {0, { {NULL, 0} } }, {0, { {"boxv", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxdr", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxdl", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxur", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxul", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxvr", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxvl", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxhd", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxhu", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxvh", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02540[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"boxH", 4} } }, {0, { {"boxV", 4} } }, {0, { {"boxdR", 5} } }, {0, { {"boxDr", 5} } },
+ {0, { {"boxDR", 5} } }, {0, { {"boxdL", 5} } }, {0, { {"boxDl", 5} } }, {0, { {"boxDL", 5} } },
+ {0, { {"boxuR", 5} } }, {0, { {"boxUr", 5} } }, {0, { {"boxUR", 5} } }, {0, { {"boxuL", 5} } },
+ {0, { {"boxUl", 5} } }, {0, { {"boxUL", 5} } }, {0, { {"boxvR", 5} } }, {0, { {"boxVr", 5} } },
+ {0, { {"boxVR", 5} } }, {0, { {"boxvL", 5} } }, {0, { {"boxVl", 5} } }, {0, { {"boxVL", 5} } },
+ {0, { {"boxHd", 5} } }, {0, { {"boxhD", 5} } }, {0, { {"boxHD", 5} } }, {0, { {"boxHu", 5} } },
+ {0, { {"boxhU", 5} } }, {0, { {"boxHU", 5} } }, {0, { {"boxvH", 5} } }, {0, { {"boxVh", 5} } },
+ {0, { {"boxVH", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02580[] = {
+ {0, { {"uhblk", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lhblk", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"block", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"blk14", 5} } }, {0, { {"blk12", 5} } }, {0, { {"blk34", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Square", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"squarf", 6} } }, {0, { {"EmptyVerySmallSquare", 20} } },
+ {0, { {NULL, 0} } }, {0, { {"rect", 4} } }, {0, { {"marker", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"fltns", 5} } }, {0, { {NULL, 0} } }, {0, { {"bigtriangleup", 13} } },
+ {0, { {"blacktriangle", 13} } }, {0, { {"triangle", 8} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"blacktriangleright", 18} } }, {0, { {"rtri", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"bigtriangledown", 15} } }, {0, { {"blacktriangledown", 17} } }, {0, { {"triangledown", 12} } },
+};
+
+static const entity_stage3_row stage3_table_html5_025C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"blacktriangleleft", 17} } }, {0, { {"ltri", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lozenge", 7} } }, {0, { {"cir", 3} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"tridot", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"bigcirc", 7} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"ultri", 5} } }, {0, { {"urtri", 5} } }, {0, { {"lltri", 5} } }, {0, { {"EmptySmallSquare", 16} } },
+ {0, { {"FilledSmallSquare", 17} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02600[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"starf", 5} } }, {0, { {"star", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"phone", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02640[] = {
+ {0, { {"female", 6} } }, {0, { {NULL, 0} } }, {0, { {"male", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"spadesuit", 9} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"clubs", 5} } },
+ {0, { {NULL, 0} } }, {0, { {"hearts", 6} } }, {0, { {"diamondsuit", 11} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"sung", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"flat", 4} } }, {0, { {"natur", 5} } }, {0, { {"sharp", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02700[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"check", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"cross", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"maltese", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"sext", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02740[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"VerticalSeparator", 17} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lbbrk", 5} } }, {0, { {"rbbrk", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_027C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"bsolhsub", 8} } }, {0, { {"suphsol", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"LeftDoubleBracket", 17} } }, {0, { {"RightDoubleBracket", 18} } },
+ {0, { {"langle", 6} } }, {0, { {"RightAngleBracket", 17} } }, {0, { {"Lang", 4} } }, {0, { {"Rang", 4} } },
+ {0, { {"loang", 5} } }, {0, { {"roang", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"longleftarrow", 13} } }, {0, { {"LongRightArrow", 14} } }, {0, { {"LongLeftRightArrow", 18} } },
+ {0, { {"xlArr", 5} } }, {0, { {"DoubleLongRightArrow", 20} } }, {0, { {"xhArr", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"xmap", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"dzigrarr", 8} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02900[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"nvlArr", 6} } }, {0, { {"nvrArr", 6} } },
+ {0, { {"nvHarr", 6} } }, {0, { {"Map", 3} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lbarr", 5} } }, {0, { {"bkarow", 6} } }, {0, { {"lBarr", 5} } }, {0, { {"dbkarow", 7} } },
+ {0, { {"drbkarow", 8} } }, {0, { {"DDotrahd", 8} } }, {0, { {"UpArrowBar", 10} } }, {0, { {"DownArrowBar", 12} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"Rarrtl", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"latail", 6} } }, {0, { {"ratail", 6} } }, {0, { {"lAtail", 6} } },
+ {0, { {"rAtail", 6} } }, {0, { {"larrfs", 6} } }, {0, { {"rarrfs", 6} } }, {0, { {"larrbfs", 7} } },
+ {0, { {"rarrbfs", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"nwarhk", 6} } },
+ {0, { {"nearhk", 6} } }, {0, { {"searhk", 6} } }, {0, { {"swarhk", 6} } }, {0, { {"nwnear", 6} } },
+ {0, { {"toea", 4} } }, {0, { {"seswar", 6} } }, {0, { {"swnwar", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_02933} } },
+ {0, { {NULL, 0} } }, {0, { {"cudarrr", 7} } }, {0, { {"ldca", 4} } }, {0, { {"rdca", 4} } },
+ {0, { {"cudarrl", 7} } }, {0, { {"larrpl", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"curarrm", 7} } }, {0, { {"cularrp", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02940[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"rarrpl", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"harrcir", 7} } }, {0, { {"Uarrocir", 8} } }, {0, { {"lurdshar", 8} } }, {0, { {"ldrushar", 8} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"LeftRightVector", 15} } }, {0, { {"RightUpDownVector", 17} } },
+ {0, { {"DownLeftRightVector", 19} } }, {0, { {"LeftUpDownVector", 16} } }, {0, { {"LeftVectorBar", 13} } }, {0, { {"RightVectorBar", 14} } },
+ {0, { {"RightUpVectorBar", 16} } }, {0, { {"RightDownVectorBar", 18} } }, {0, { {"DownLeftVectorBar", 17} } }, {0, { {"DownRightVectorBar", 18} } },
+ {0, { {"LeftUpVectorBar", 15} } }, {0, { {"LeftDownVectorBar", 17} } }, {0, { {"LeftTeeVector", 13} } }, {0, { {"RightTeeVector", 14} } },
+ {0, { {"RightUpTeeVector", 16} } }, {0, { {"RightDownTeeVector", 18} } }, {0, { {"DownLeftTeeVector", 17} } }, {0, { {"DownRightTeeVector", 18} } },
+ {0, { {"LeftUpTeeVector", 15} } }, {0, { {"LeftDownTeeVector", 17} } }, {0, { {"lHar", 4} } }, {0, { {"uHar", 4} } },
+ {0, { {"rHar", 4} } }, {0, { {"dHar", 4} } }, {0, { {"luruhar", 7} } }, {0, { {"ldrdhar", 7} } },
+ {0, { {"ruluhar", 7} } }, {0, { {"rdldhar", 7} } }, {0, { {"lharul", 6} } }, {0, { {"llhard", 6} } },
+ {0, { {"rharul", 6} } }, {0, { {"lrhard", 6} } }, {0, { {"udhar", 5} } }, {0, { {"ReverseUpEquilibrium", 20} } },
+ {0, { {"RoundImplies", 12} } }, {0, { {"erarr", 5} } }, {0, { {"simrarr", 7} } }, {0, { {"larrsim", 7} } },
+ {0, { {"rarrsim", 7} } }, {0, { {"rarrap", 6} } }, {0, { {"ltlarr", 6} } }, {0, { {NULL, 0} } },
+ {0, { {"gtrarr", 6} } }, {0, { {"subrarr", 7} } }, {0, { {NULL, 0} } }, {0, { {"suplarr", 7} } },
+ {0, { {"lfisht", 6} } }, {0, { {"rfisht", 6} } }, {0, { {"ufisht", 6} } }, {0, { {"dfisht", 6} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02980[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"lopar", 5} } }, {0, { {"ropar", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lbrke", 5} } },
+ {0, { {"rbrke", 5} } }, {0, { {"lbrkslu", 7} } }, {0, { {"rbrksld", 7} } }, {0, { {"lbrksld", 7} } },
+ {0, { {"rbrkslu", 7} } }, {0, { {"langd", 5} } }, {0, { {"rangd", 5} } }, {0, { {"lparlt", 6} } },
+ {0, { {"rpargt", 6} } }, {0, { {"gtlPar", 6} } }, {0, { {"ltrPar", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"vzigzag", 7} } }, {0, { {NULL, 0} } },
+ {0, { {"vangrt", 6} } }, {0, { {"angrtvbd", 8} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"ange", 4} } }, {0, { {"range", 5} } }, {0, { {"dwangle", 7} } }, {0, { {"uwangle", 7} } },
+ {0, { {"angmsdaa", 8} } }, {0, { {"angmsdab", 8} } }, {0, { {"angmsdac", 8} } }, {0, { {"angmsdad", 8} } },
+ {0, { {"angmsdae", 8} } }, {0, { {"angmsdaf", 8} } }, {0, { {"angmsdag", 8} } }, {0, { {"angmsdah", 8} } },
+ {0, { {"bemptyv", 7} } }, {0, { {"demptyv", 7} } }, {0, { {"cemptyv", 7} } }, {0, { {"raemptyv", 8} } },
+ {0, { {"laemptyv", 8} } }, {0, { {"ohbar", 5} } }, {0, { {"omid", 4} } }, {0, { {"opar", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"operp", 5} } }, {0, { {NULL, 0} } }, {0, { {"olcross", 7} } },
+ {0, { {"odsold", 6} } }, {0, { {NULL, 0} } }, {0, { {"olcir", 5} } }, {0, { {"ofcir", 5} } },
+};
+
+static const entity_stage3_row stage3_table_html5_029C0[] = {
+ {0, { {"olt", 3} } }, {0, { {"ogt", 3} } }, {0, { {"cirscir", 7} } }, {0, { {"cirE", 4} } },
+ {0, { {"solb", 4} } }, {0, { {"bsolb", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"boxbox", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"trisb", 5} } }, {0, { {"rtriltri", 8} } }, {1, { {(void *)multi_cp_html5_029CF} } },
+ {1, { {(void *)multi_cp_html5_029D0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"iinfin", 6} } }, {0, { {"infintie", 8} } }, {0, { {"nvinfin", 7} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"eparsl", 6} } },
+ {0, { {"smeparsl", 8} } }, {0, { {"eqvparsl", 8} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lozf", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"RuleDelayed", 11} } }, {0, { {NULL, 0} } }, {0, { {"dsol", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02A00[] = {
+ {0, { {"xodot", 5} } }, {0, { {"bigoplus", 8} } }, {0, { {"bigotimes", 9} } }, {0, { {NULL, 0} } },
+ {0, { {"biguplus", 8} } }, {0, { {NULL, 0} } }, {0, { {"bigsqcup", 8} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"iiiint", 6} } }, {0, { {"fpartint", 8} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"cirfnint", 8} } }, {0, { {"awint", 5} } }, {0, { {"rppolint", 8} } }, {0, { {"scpolint", 8} } },
+ {0, { {"npolint", 7} } }, {0, { {"pointint", 8} } }, {0, { {"quatint", 7} } }, {0, { {"intlarhk", 8} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"pluscir", 7} } }, {0, { {"plusacir", 8} } },
+ {0, { {"simplus", 7} } }, {0, { {"plusdu", 6} } }, {0, { {"plussim", 7} } }, {0, { {"plustwo", 7} } },
+ {0, { {NULL, 0} } }, {0, { {"mcomma", 6} } }, {0, { {"minusdu", 7} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"loplus", 6} } }, {0, { {"roplus", 6} } }, {0, { {"Cross", 5} } },
+ {0, { {"timesd", 6} } }, {0, { {"timesbar", 8} } }, {0, { {NULL, 0} } }, {0, { {"smashp", 6} } },
+ {0, { {"lotimes", 7} } }, {0, { {"rotimes", 7} } }, {0, { {"otimesas", 8} } }, {0, { {"Otimes", 6} } },
+ {0, { {"odiv", 4} } }, {0, { {"triplus", 7} } }, {0, { {"triminus", 8} } }, {0, { {"tritime", 7} } },
+ {0, { {"iprod", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"amalg", 5} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02A40[] = {
+ {0, { {"capdot", 6} } }, {0, { {NULL, 0} } }, {0, { {"ncup", 4} } }, {0, { {"ncap", 4} } },
+ {0, { {"capand", 6} } }, {0, { {"cupor", 5} } }, {0, { {"cupcap", 6} } }, {0, { {"capcup", 6} } },
+ {0, { {"cupbrcap", 8} } }, {0, { {"capbrcup", 8} } }, {0, { {"cupcup", 6} } }, {0, { {"capcap", 6} } },
+ {0, { {"ccups", 5} } }, {0, { {"ccaps", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"ccupssm", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"And", 3} } },
+ {0, { {"Or", 2} } }, {0, { {"andand", 6} } }, {0, { {"oror", 4} } }, {0, { {"orslope", 7} } },
+ {0, { {"andslope", 8} } }, {0, { {NULL, 0} } }, {0, { {"andv", 4} } }, {0, { {"orv", 3} } },
+ {0, { {"andd", 4} } }, {0, { {"ord", 3} } }, {0, { {NULL, 0} } }, {0, { {"wedbar", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"sdote", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"simdot", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_02A6D} } }, {0, { {"easter", 6} } }, {0, { {"apacir", 6} } },
+ {1, { {(void *)multi_cp_html5_02A70} } }, {0, { {"eplus", 5} } }, {0, { {"pluse", 5} } }, {0, { {"Esim", 4} } },
+ {0, { {"Colone", 6} } }, {0, { {"Equal", 5} } }, {0, { {NULL, 0} } }, {0, { {"ddotseq", 7} } },
+ {0, { {"equivDD", 7} } }, {0, { {"ltcir", 5} } }, {0, { {"gtcir", 5} } }, {0, { {"ltquest", 7} } },
+ {0, { {"gtquest", 7} } }, {1, { {(void *)multi_cp_html5_02A7D} } }, {1, { {(void *)multi_cp_html5_02A7E} } }, {0, { {"lesdot", 6} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02A80[] = {
+ {0, { {"gesdot", 6} } }, {0, { {"lesdoto", 7} } }, {0, { {"gesdoto", 7} } }, {0, { {"lesdotor", 8} } },
+ {0, { {"gesdotol", 8} } }, {0, { {"lap", 3} } }, {0, { {"gap", 3} } }, {0, { {"lne", 3} } },
+ {0, { {"gne", 3} } }, {0, { {"lnap", 4} } }, {0, { {"gnap", 4} } }, {0, { {"lesseqqgtr", 10} } },
+ {0, { {"gEl", 3} } }, {0, { {"lsime", 5} } }, {0, { {"gsime", 5} } }, {0, { {"lsimg", 5} } },
+ {0, { {"gsiml", 5} } }, {0, { {"lgE", 3} } }, {0, { {"glE", 3} } }, {0, { {"lesges", 6} } },
+ {0, { {"gesles", 6} } }, {0, { {"els", 3} } }, {0, { {"egs", 3} } }, {0, { {"elsdot", 6} } },
+ {0, { {"egsdot", 6} } }, {0, { {"el", 2} } }, {0, { {"eg", 2} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"siml", 4} } }, {0, { {"simg", 4} } }, {0, { {"simlE", 5} } },
+ {0, { {"simgE", 5} } }, {1, { {(void *)multi_cp_html5_02AA1} } }, {1, { {(void *)multi_cp_html5_02AA2} } }, {0, { {NULL, 0} } },
+ {0, { {"glj", 3} } }, {0, { {"gla", 3} } }, {0, { {"ltcc", 4} } }, {0, { {"gtcc", 4} } },
+ {0, { {"lescc", 5} } }, {0, { {"gescc", 5} } }, {0, { {"smt", 3} } }, {0, { {"lat", 3} } },
+ {1, { {(void *)multi_cp_html5_02AAC} } }, {1, { {(void *)multi_cp_html5_02AAD} } }, {0, { {"bumpE", 5} } }, {1, { {(void *)multi_cp_html5_02AAF} } },
+ {1, { {(void *)multi_cp_html5_02AB0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"prE", 3} } },
+ {0, { {"scE", 3} } }, {0, { {"precneqq", 8} } }, {0, { {"scnE", 4} } }, {0, { {"precapprox", 10} } },
+ {0, { {"succapprox", 10} } }, {0, { {"precnapprox", 11} } }, {0, { {"succnapprox", 11} } }, {0, { {"Pr", 2} } },
+ {0, { {"Sc", 2} } }, {0, { {"subdot", 6} } }, {0, { {"supdot", 6} } }, {0, { {"subplus", 7} } },
+};
+
+static const entity_stage3_row stage3_table_html5_02AC0[] = {
+ {0, { {"supplus", 7} } }, {0, { {"submult", 7} } }, {0, { {"supmult", 7} } }, {0, { {"subedot", 7} } },
+ {0, { {"supedot", 7} } }, {1, { {(void *)multi_cp_html5_02AC5} } }, {1, { {(void *)multi_cp_html5_02AC6} } }, {0, { {"subsim", 6} } },
+ {0, { {"supsim", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_02ACB} } },
+ {1, { {(void *)multi_cp_html5_02ACC} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"csub", 4} } },
+ {0, { {"csup", 4} } }, {0, { {"csube", 5} } }, {0, { {"csupe", 5} } }, {0, { {"subsup", 6} } },
+ {0, { {"supsub", 6} } }, {0, { {"subsub", 6} } }, {0, { {"supsup", 6} } }, {0, { {"suphsub", 7} } },
+ {0, { {"supdsub", 7} } }, {0, { {"forkv", 5} } }, {0, { {"topfork", 7} } }, {0, { {"mlcp", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Dashv", 5} } }, {0, { {NULL, 0} } }, {0, { {"Vdashl", 6} } }, {0, { {"Barv", 4} } },
+ {0, { {"vBar", 4} } }, {0, { {"vBarv", 5} } }, {0, { {NULL, 0} } }, {0, { {"Vbar", 4} } },
+ {0, { {"Not", 3} } }, {0, { {"bNot", 4} } }, {0, { {"rnmid", 5} } }, {0, { {"cirmid", 6} } },
+ {0, { {"midcir", 6} } }, {0, { {"topcir", 6} } }, {0, { {"nhpar", 5} } }, {0, { {"parsim", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {1, { {(void *)multi_cp_html5_02AFD} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_0FB00[] = {
+ {0, { {"fflig", 5} } }, {0, { {"filig", 5} } }, {0, { {"fllig", 5} } }, {0, { {"ffilig", 6} } },
+ {0, { {"ffllig", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_1D480[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Ascr", 4} } }, {0, { {NULL, 0} } }, {0, { {"Cscr", 4} } }, {0, { {"Dscr", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"Gscr", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Jscr", 4} } }, {0, { {"Kscr", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Nscr", 4} } }, {0, { {"Oscr", 4} } }, {0, { {"Pscr", 4} } },
+ {0, { {"Qscr", 4} } }, {0, { {NULL, 0} } }, {0, { {"Sscr", 4} } }, {0, { {"Tscr", 4} } },
+ {0, { {"Uscr", 4} } }, {0, { {"Vscr", 4} } }, {0, { {"Wscr", 4} } }, {0, { {"Xscr", 4} } },
+ {0, { {"Yscr", 4} } }, {0, { {"Zscr", 4} } }, {0, { {"ascr", 4} } }, {0, { {"bscr", 4} } },
+ {0, { {"cscr", 4} } }, {0, { {"dscr", 4} } }, {0, { {NULL, 0} } }, {0, { {"fscr", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"hscr", 4} } }, {0, { {"iscr", 4} } }, {0, { {"jscr", 4} } },
+};
+
+static const entity_stage3_row stage3_table_html5_1D4C0[] = {
+ {0, { {"kscr", 4} } }, {0, { {"lscr", 4} } }, {0, { {"mscr", 4} } }, {0, { {"nscr", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"pscr", 4} } }, {0, { {"qscr", 4} } }, {0, { {"rscr", 4} } },
+ {0, { {"sscr", 4} } }, {0, { {"tscr", 4} } }, {0, { {"uscr", 4} } }, {0, { {"vscr", 4} } },
+ {0, { {"wscr", 4} } }, {0, { {"xscr", 4} } }, {0, { {"yscr", 4} } }, {0, { {"zscr", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_1D500[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Afr", 3} } }, {0, { {"Bfr", 3} } }, {0, { {NULL, 0} } }, {0, { {"Dfr", 3} } },
+ {0, { {"Efr", 3} } }, {0, { {"Ffr", 3} } }, {0, { {"Gfr", 3} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Jfr", 3} } }, {0, { {"Kfr", 3} } }, {0, { {"Lfr", 3} } },
+ {0, { {"Mfr", 3} } }, {0, { {"Nfr", 3} } }, {0, { {"Ofr", 3} } }, {0, { {"Pfr", 3} } },
+ {0, { {"Qfr", 3} } }, {0, { {NULL, 0} } }, {0, { {"Sfr", 3} } }, {0, { {"Tfr", 3} } },
+ {0, { {"Ufr", 3} } }, {0, { {"Vfr", 3} } }, {0, { {"Wfr", 3} } }, {0, { {"Xfr", 3} } },
+ {0, { {"Yfr", 3} } }, {0, { {NULL, 0} } }, {0, { {"afr", 3} } }, {0, { {"bfr", 3} } },
+ {0, { {"cfr", 3} } }, {0, { {"dfr", 3} } }, {0, { {"efr", 3} } }, {0, { {"ffr", 3} } },
+ {0, { {"gfr", 3} } }, {0, { {"hfr", 3} } }, {0, { {"ifr", 3} } }, {0, { {"jfr", 3} } },
+ {0, { {"kfr", 3} } }, {0, { {"lfr", 3} } }, {0, { {"mfr", 3} } }, {0, { {"nfr", 3} } },
+ {0, { {"ofr", 3} } }, {0, { {"pfr", 3} } }, {0, { {"qfr", 3} } }, {0, { {"rfr", 3} } },
+ {0, { {"sfr", 3} } }, {0, { {"tfr", 3} } }, {0, { {"ufr", 3} } }, {0, { {"vfr", 3} } },
+ {0, { {"wfr", 3} } }, {0, { {"xfr", 3} } }, {0, { {"yfr", 3} } }, {0, { {"zfr", 3} } },
+ {0, { {"Aopf", 4} } }, {0, { {"Bopf", 4} } }, {0, { {NULL, 0} } }, {0, { {"Dopf", 4} } },
+ {0, { {"Eopf", 4} } }, {0, { {"Fopf", 4} } }, {0, { {"Gopf", 4} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html5_1D540[] = {
+ {0, { {"Iopf", 4} } }, {0, { {"Jopf", 4} } }, {0, { {"Kopf", 4} } }, {0, { {"Lopf", 4} } },
+ {0, { {"Mopf", 4} } }, {0, { {NULL, 0} } }, {0, { {"Oopf", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"Sopf", 4} } }, {0, { {"Topf", 4} } },
+ {0, { {"Uopf", 4} } }, {0, { {"Vopf", 4} } }, {0, { {"Wopf", 4} } }, {0, { {"Xopf", 4} } },
+ {0, { {"Yopf", 4} } }, {0, { {NULL, 0} } }, {0, { {"aopf", 4} } }, {0, { {"bopf", 4} } },
+ {0, { {"copf", 4} } }, {0, { {"dopf", 4} } }, {0, { {"eopf", 4} } }, {0, { {"fopf", 4} } },
+ {0, { {"gopf", 4} } }, {0, { {"hopf", 4} } }, {0, { {"iopf", 4} } }, {0, { {"jopf", 4} } },
+ {0, { {"kopf", 4} } }, {0, { {"lopf", 4} } }, {0, { {"mopf", 4} } }, {0, { {"nopf", 4} } },
+ {0, { {"oopf", 4} } }, {0, { {"popf", 4} } }, {0, { {"qopf", 4} } }, {0, { {"ropf", 4} } },
+ {0, { {"sopf", 4} } }, {0, { {"topf", 4} } }, {0, { {"uopf", 4} } }, {0, { {"vopf", 4} } },
+ {0, { {"wopf", 4} } }, {0, { {"xopf", 4} } }, {0, { {"yopf", 4} } }, {0, { {"zopf", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+/* end of stage 3 Tables for HTML5 }}} */
+
+/* {{{ Stage 2 Tables for HTML5 */
+
+static const entity_stage2_row empty_stage2_table[] = {
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+static const entity_stage2_row stage2_table_html5_00000[] = {
+ stage3_table_html5_00000, stage3_table_html5_00040, stage3_table_html5_00080, stage3_table_html5_000C0,
+ stage3_table_html5_00100, stage3_table_html5_00140, stage3_table_html5_00180, stage3_table_html5_001C0,
+ stage3_table_html5_00200, empty_stage3_table, empty_stage3_table, stage3_table_html5_002C0,
+ stage3_table_html5_00300, empty_stage3_table, stage3_table_html5_00380, stage3_table_html5_003C0,
+ stage3_table_html5_00400, stage3_table_html5_00440, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+static const entity_stage2_row stage2_table_html5_02000[] = {
+ stage3_table_html5_02000, stage3_table_html5_02040, stage3_table_html5_02080, stage3_table_html5_020C0,
+ stage3_table_html5_02100, stage3_table_html5_02140, stage3_table_html5_02180, stage3_table_html5_021C0,
+ stage3_table_html5_02200, stage3_table_html5_02240, stage3_table_html5_02280, stage3_table_html5_022C0,
+ stage3_table_html5_02300, stage3_table_html5_02340, stage3_table_html5_02380, stage3_table_html5_023C0,
+ stage3_table_html5_02400, empty_stage3_table, empty_stage3_table, stage3_table_html5_024C0,
+ stage3_table_html5_02500, stage3_table_html5_02540, stage3_table_html5_02580, stage3_table_html5_025C0,
+ stage3_table_html5_02600, stage3_table_html5_02640, empty_stage3_table, empty_stage3_table,
+ stage3_table_html5_02700, stage3_table_html5_02740, empty_stage3_table, stage3_table_html5_027C0,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ stage3_table_html5_02900, stage3_table_html5_02940, stage3_table_html5_02980, stage3_table_html5_029C0,
+ stage3_table_html5_02A00, stage3_table_html5_02A40, stage3_table_html5_02A80, stage3_table_html5_02AC0,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+static const entity_stage2_row stage2_table_html5_0F000[] = {
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ stage3_table_html5_0FB00, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+static const entity_stage2_row stage2_table_html5_1D000[] = {
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, stage3_table_html5_1D480, stage3_table_html5_1D4C0,
+ stage3_table_html5_1D500, stage3_table_html5_1D540, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+/* end of stage 2 tables for HTML5 }}} */
+
+static const entity_stage1_row entity_ms_table_html5[] = {
+ stage2_table_html5_00000,
+ empty_stage2_table,
+ stage2_table_html5_02000,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ stage2_table_html5_0F000,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ stage2_table_html5_1D000,
+};
+
+/* end of HTML5 multi-stage table for codepoint -> entity }}} */
+
+/* {{{ HTML5 hash table for entity -> codepoint */
+
+typedef struct {
+ const char *entity;
+ unsigned short entity_len;
+ unsigned int codepoint1;
+ unsigned int codepoint2;
+} entity_cp_map;
+
+typedef const entity_cp_map *entity_ht_bucket;
+
+typedef struct {
+ unsigned num_elems; /* power of 2 */
+ const entity_ht_bucket *buckets; /* .num_elems elements */
+} entity_ht;
+
+static const entity_cp_map ht_bucket_empty[] = { {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_000[] = { {"realpart", 8, 0x0211C, 0}, {"varr", 4, 0x02195, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_001[] = { {"angrt", 5, 0x0221F, 0}, {"iogon", 5, 0x0012F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_003[] = { {"lessdot", 7, 0x022D6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_005[] = { {"simrarr", 7, 0x02972, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_007[] = { {"Zscr", 4, 0x1D4B5, 0}, {"midast", 6, 0x0002A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_00D[] = { {"copf", 4, 0x1D554, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_00F[] = { {"female", 6, 0x02640, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_017[] = { {"NegativeThickSpace", 18, 0x0200B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_020[] = { {"copy", 4, 0x000A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_022[] = { {"angst", 5, 0x000C5, 0}, {"searr", 5, 0x02198, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_024[] = { {"sqcups", 6, 0x02294, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_027[] = { {"Acirc", 5, 0x000C2, 0}, {"gtdot", 5, 0x022D7, 0}, {"varpi", 5, 0x003D6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_028[] = { {"UpTee", 5, 0x022A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_029[] = { {"TildeTilde", 10, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_02A[] = { {"mfr", 3, 0x1D52A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_02B[] = { {"RightVectorBar", 14, 0x02953, 0}, {"gesdot", 6, 0x02A80, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_02C[] = { {"Uarrocir", 8, 0x02949, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_02E[] = { {"RightTriangleBar", 16, 0x029D0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_030[] = { {"Ocy", 3, 0x0041E, 0}, {"int", 3, 0x0222B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_034[] = { {"preccurlyeq", 11, 0x0227C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_038[] = { {"sccue", 5, 0x0227D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_040[] = { {"DoubleContourIntegral", 21, 0x0222F, 0}, {"nexist", 6, 0x02204, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_047[] = { {"acirc", 5, 0x000E2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_04C[] = { {"setmn", 5, 0x02216, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_04E[] = { {"Dopf", 4, 0x1D53B, 0}, {"LeftTee", 7, 0x022A3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_051[] = { {"SquareSuperset", 14, 0x02290, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_059[] = { {"udhar", 5, 0x0296E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_05D[] = { {"Equal", 5, 0x02A75, 0}, {"pscr", 4, 0x1D4C5, 0}, {"xvee", 4, 0x022C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_05F[] = { {"approx", 6, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_060[] = { {"HARDcy", 6, 0x0042A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_061[] = { {"nGg", 3, 0x022D9, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_063[] = { {"yopf", 4, 0x1D56A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_064[] = { {"prcue", 5, 0x0227C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_065[] = { {"loarr", 5, 0x021FD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_069[] = { {"mho", 3, 0x02127, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_06A[] = { {"otimesas", 8, 0x02A36, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_06D[] = { {"capcap", 6, 0x02A4B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_06E[] = { {"eplus", 5, 0x02A71, 0}, {"nGt", 3, 0x0226B, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_06F[] = { {"Bumpeq", 6, 0x0224E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_071[] = { {"submult", 7, 0x02AC1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_073[] = { {"subplus", 7, 0x02ABF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_074[] = { {"auml", 4, 0x000E4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_07A[] = { {"RightDoubleBracket", 18, 0x027E7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_07B[] = { {"varkappa", 8, 0x003F0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_07C[] = { {"plusdo", 6, 0x02214, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_07F[] = { {"mid", 3, 0x02223, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_082[] = { {"plusdu", 6, 0x02A25, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_084[] = { {"notniva", 7, 0x0220C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_085[] = { {"notnivb", 7, 0x022FE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_086[] = { {"notnivc", 7, 0x022FD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_088[] = { {"varepsilon", 10, 0x003F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_089[] = { {"nspar", 5, 0x02226, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_08C[] = { {"Ofr", 3, 0x1D512, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_08E[] = { {"Omega", 5, 0x003A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_090[] = { {"equals", 6, 0x0003D, 0}, {"harrcir", 7, 0x02948, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_094[] = { {"Succeeds", 8, 0x0227B, 0}, {"cupdot", 6, 0x0228D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_097[] = { {"lsqb", 4, 0x0005B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_09E[] = { {"Qscr", 4, 0x1D4AC, 0}, {"urcorn", 6, 0x0231D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0A4[] = { {"Zopf", 4, 0x02124, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0A6[] = { {"triangleleft", 12, 0x025C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0AB[] = { {"supdsub", 7, 0x02AD8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0AC[] = { {"chcy", 4, 0x00447, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0AD[] = { {"sqsupset", 8, 0x02290, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0AE[] = { {"omega", 5, 0x003C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0AF[] = { {"rthree", 6, 0x022CC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0B0[] = { {"THORN", 5, 0x000DE, 0}, {"clubsuit", 8, 0x02663, 0}, {"filig", 5, 0x0FB01, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0B2[] = { {"ocir", 4, 0x0229A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0B8[] = { {"ShortDownArrow", 14, 0x02193, 0}, {"atilde", 6, 0x000E3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0B9[] = { {"DownLeftTeeVector", 17, 0x0295E, 0}, {"LeftTeeArrow", 12, 0x021A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0BA[] = { {"GreaterFullEqual", 16, 0x02267, 0}, {"emsp", 4, 0x02003, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0C0[] = { {"lozf", 4, 0x029EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0C4[] = { {"ThinSpace", 9, 0x02009, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0CE[] = { {"fnof", 4, 0x00192, 0}, {"multimap", 8, 0x022B8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0D1[] = { {"Zacute", 6, 0x00179, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0D2[] = { {"mdash", 5, 0x02014, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0D3[] = { {"minusb", 6, 0x0229F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0D5[] = { {"minusd", 6, 0x02238, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0DF[] = { {"varsigma", 8, 0x003C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0E5[] = { {"ntilde", 6, 0x000F1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0E6[] = { {"Lambda", 6, 0x0039B, 0}, {"integers", 8, 0x02124, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0E8[] = { {"gesles", 6, 0x02A94, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0EC[] = { {"NotSubset", 9, 0x02282, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0EF[] = { {"NotLeftTriangleEqual", 20, 0x022EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0F3[] = { {"LessLess", 8, 0x02AA1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0F4[] = { {"gscr", 4, 0x0210A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0FA[] = { {"popf", 4, 0x1D561, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0FB[] = { {"Agrave", 6, 0x000C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0FD[] = { {"nvinfin", 7, 0x029DE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_0FE[] = { {"gacute", 6, 0x001F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_100[] = { {"diam", 4, 0x022C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_101[] = { {"nesim", 5, 0x02242, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_103[] = { {"YIcy", 4, 0x00407, 0}, {"bcy", 3, 0x00431, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_105[] = { {"Exists", 6, 0x02203, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_106[] = { {"vert", 4, 0x0007C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_109[] = { {"ropar", 5, 0x02986, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_10A[] = { {"topfork", 7, 0x02ADA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_10B[] = { {"nLl", 3, 0x022D8, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_10D[] = { {"notin", 5, 0x02209, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_10E[] = { {"SucceedsSlantEqual", 18, 0x0227D, 0}, {"toea", 4, 0x02928, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_10F[] = { {"ImaginaryI", 10, 0x02148, 0}, {"srarr", 5, 0x02192, 0}, {"ulcorner", 8, 0x0231C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_110[] = { {"LeftArrowBar", 12, 0x021E4, 0}, {"ldsh", 4, 0x021B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_111[] = { {"DownBreve", 9, 0x00311, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_113[] = { {"nLt", 3, 0x0226A, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_116[] = { {"vltri", 5, 0x022B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_11B[] = { {"VDash", 5, 0x022AB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_11C[] = { {"Dstrok", 6, 0x00110, 0}, {"Intersection", 12, 0x022C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_11E[] = { {"lrhar", 5, 0x021CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_121[] = { {"RightTee", 8, 0x022A2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_124[] = { {"RightArrowLeftArrow", 19, 0x021C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_129[] = { {"Ccirc", 5, 0x00108, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_12A[] = { {"ntrianglelefteq", 15, 0x022EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_12C[] = { {"leftharpoonup", 13, 0x021BC, 0}, {"scap", 4, 0x02AB8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_12E[] = { {"darr", 4, 0x02193, 0}, {"qfr", 3, 0x1D52E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_12F[] = { {"cdot", 4, 0x0010B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_130[] = { {"supseteqq", 9, 0x02AC6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_134[] = { {"Scy", 3, 0x00421, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_135[] = { {"Hscr", 4, 0x0210B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_137[] = { {"LowerRightArrow", 15, 0x02198, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_13A[] = { {"divide", 6, 0x000F7, 0}, {"tcedil", 6, 0x00163, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_13B[] = { {"LeftArrow", 9, 0x02190, 0}, {"Qopf", 4, 0x0211A, 0}, {"vDash", 5, 0x022A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_145[] = { {"dash", 4, 0x02010, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_147[] = { {"oror", 4, 0x02A56, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_149[] = { {"ccirc", 5, 0x00109, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_14B[] = { {"LongLeftArrow", 13, 0x027F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_14C[] = { {"straightphi", 11, 0x003D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_14E[] = { {"xlarr", 5, 0x027F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_14F[] = { {"DJcy", 4, 0x00402, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_158[] = { {"nbsp", 4, 0x000A0, 0}, {"succcurlyeq", 11, 0x0227D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_159[] = { {"njcy", 4, 0x0045A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_15B[] = { {"Leftarrow", 9, 0x021D0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_15E[] = { {"dtrif", 5, 0x025BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_15F[] = { {"bfr", 3, 0x1D51F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_161[] = { {"GreaterTilde", 12, 0x02273, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_164[] = { {"hamilt", 6, 0x0210B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_165[] = { {"Dcy", 3, 0x00414, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_168[] = { {"LeftUpVector", 12, 0x021BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_16A[] = { {"bigoplus", 8, 0x02A01, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_170[] = { {"nwarhk", 6, 0x02923, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_173[] = { {"diams", 5, 0x02666, 0}, {"suphsol", 7, 0x027C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_17A[] = { {"boxminus", 8, 0x0229F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_17B[] = { {"leftarrow", 9, 0x02190, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_17C[] = { {"andd", 4, 0x02A5C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_17F[] = { {"NonBreakingSpace", 16, 0x000A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_181[] = { {"xutri", 5, 0x025B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_189[] = { {"Longleftrightarrow", 18, 0x027FA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_18B[] = { {"Longleftarrow", 13, 0x027F8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_18C[] = { {"gtrapprox", 9, 0x02A86, 0}, {"phmmat", 6, 0x02133, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_18E[] = { {"andv", 4, 0x02A5A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_18F[] = { {"equiv", 5, 0x02261, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_190[] = { {"Sfr", 3, 0x1D516, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_191[] = { {"gopf", 4, 0x1D558, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_193[] = { {"sqsub", 5, 0x0228F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_195[] = { {"approxeq", 8, 0x0224A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_19A[] = { {"Del", 3, 0x02207, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_19C[] = { {"nrightarrow", 11, 0x0219B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_19F[] = { {"SquareUnion", 11, 0x02294, 0}, {"strns", 5, 0x000AF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A0[] = { {"Itilde", 6, 0x00128, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A1[] = { {"sqsup", 5, 0x02290, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A2[] = { {"Ouml", 4, 0x000D6, 0}, {"PrecedesTilde", 13, 0x0227E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A3[] = { {"AMP", 3, 0x00026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A4[] = { {"plusmn", 6, 0x000B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A5[] = { {"xcup", 4, 0x022C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1A8[] = { {"radic", 5, 0x0221A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1AB[] = { {"longleftarrow", 13, 0x027F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1AC[] = { {"lrcorner", 8, 0x0231F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1AD[] = { {"notni", 5, 0x0220C, 0}, {"updownarrow", 11, 0x02195, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1AE[] = { {"szlig", 5, 0x000DF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1AF[] = { {"ugrave", 6, 0x000F9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1B0[] = { {"imof", 4, 0x022B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1B2[] = { {"csub", 4, 0x02ACF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1B5[] = { {"gsim", 4, 0x02273, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1B9[] = { {"leftleftarrows", 14, 0x021C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1BD[] = { {"backcong", 8, 0x0224C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1BE[] = { {"clubs", 5, 0x02663, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1C0[] = { {"csup", 4, 0x02AD0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1C1[] = { {"Dfr", 3, 0x1D507, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1C4[] = { {"profline", 8, 0x02312, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1C6[] = { {"Zdot", 4, 0x0017B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1C9[] = { {"ClockwiseContourIntegral", 24, 0x02232, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1CA[] = { {"roplus", 6, 0x02A2E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1CD[] = { {"Rang", 4, 0x027EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1CE[] = { {"bcong", 5, 0x0224C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D0[] = { {"tshcy", 5, 0x0045B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D1[] = { {"eDot", 4, 0x02251, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D2[] = { {"Hopf", 4, 0x0210D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D4[] = { {"lpar", 4, 0x00028, 0}, {"odash", 5, 0x0229D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D5[] = { {"capbrcup", 8, 0x02A49, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D6[] = { {"ucy", 3, 0x00443, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D8[] = { {"ofcir", 5, 0x029BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1D9[] = { {"Breve", 5, 0x002D8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1DA[] = { {"barvee", 6, 0x022BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1DF[] = { {"backsim", 7, 0x0223D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1E0[] = { {"ange", 4, 0x029A4, 0}, {"half", 4, 0x000BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1E1[] = { {"tscr", 4, 0x1D4C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1E5[] = { {"realine", 7, 0x0211B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1E6[] = { {"Oacute", 6, 0x000D3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1E7[] = { {"dfisht", 6, 0x0297F, 0}, {"swnwar", 6, 0x0292A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1E8[] = { {"tscy", 4, 0x00446, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1EB[] = { {"lsquor", 6, 0x0201A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1EF[] = { {"naturals", 8, 0x02115, 0}, {"utrif", 5, 0x025B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1F0[] = { {"DiacriticalTilde", 16, 0x002DC, 0}, {"RightUpVectorBar", 16, 0x02954, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1F2[] = { {"rHar", 4, 0x02964, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1F4[] = { {"curlyeqprec", 11, 0x022DE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1F8[] = { {"dtri", 4, 0x025BF, 0}, {"euml", 4, 0x000EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1F9[] = { {"breve", 5, 0x002D8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1FA[] = { {"Barwed", 6, 0x02306, 0}, {"nvlArr", 6, 0x02902, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1FC[] = { {"dcaron", 6, 0x0010F, 0}, {"natural", 7, 0x0266E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1FE[] = { {"nsupseteqq", 10, 0x02AC6, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_1FF[] = { {"nedot", 5, 0x02250, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_205[] = { {"bigtriangledown", 15, 0x025BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_207[] = { {"fcy", 3, 0x00444, 0}, {"marker", 6, 0x025AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_20E[] = { {"Union", 5, 0x022C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_212[] = { {"varpropto", 9, 0x0221D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_213[] = { {"CloseCurlyDoubleQuote", 21, 0x0201D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_219[] = { {"DoubleLongRightArrow", 20, 0x027F9, 0}, {"GreaterGreater", 14, 0x02AA2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_21D[] = { {"Umacr", 5, 0x0016A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_220[] = { {"Colon", 5, 0x02237, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_222[] = { {"Hat", 3, 0x0005E, 0}, {"Uscr", 4, 0x1D4B0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_227[] = { {"SHCHcy", 6, 0x00429, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_229[] = { {"nLeftarrow", 10, 0x021CD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_22B[] = { {"Ecirc", 5, 0x000CA, 0}, {"Jukcy", 5, 0x00404, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_22C[] = { {"nbumpe", 6, 0x0224F, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_22D[] = { {"NotLess", 7, 0x0226E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_22F[] = { {"gtlPar", 6, 0x02995, 0}, {"suphsub", 7, 0x02AD7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_230[] = { {"gtreqqless", 10, 0x02A8C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_232[] = { {"ufr", 3, 0x1D532, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_234[] = { {"cirscir", 7, 0x029C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_239[] = { {"LeftDownTeeVector", 17, 0x02961, 0}, {"duhar", 5, 0x0296F, 0}, {"nrtrie", 6, 0x022ED, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_23C[] = { {"llhard", 6, 0x0296B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_23D[] = { {"umacr", 5, 0x0016B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_23E[] = { {"lates", 5, 0x02AAD, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_240[] = { {"colon", 5, 0x0003A, 0}, {"iacute", 6, 0x000ED, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_241[] = { {"NotPrecedes", 11, 0x02280, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_242[] = { {"cirfnint", 8, 0x02A10, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_246[] = { {"barwedge", 8, 0x02305, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_249[] = { {"nleftarrow", 10, 0x0219A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_24A[] = { {"Ubrcy", 5, 0x0040E, 0}, {"leftthreetimes", 14, 0x022CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_24B[] = { {"andand", 6, 0x02A55, 0}, {"ecirc", 5, 0x000EA, 0}, {"jukcy", 5, 0x00454, 0}, {"quatint", 7, 0x02A16, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_24D[] = { {"lharul", 6, 0x0296A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_251[] = { {"smtes", 5, 0x02AAC, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_252[] = { {"UnionPlus", 9, 0x0228E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_257[] = { {"NotLeftTriangle", 15, 0x022EA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_25A[] = { {"bne", 3, 0x0003D, 0x020E5}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_25B[] = { {"gtrsim", 6, 0x02273, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_25C[] = { {"Rarr", 4, 0x021A0, 0}, {"ldquor", 6, 0x0201E, 0}, {"phiv", 4, 0x003D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_25D[] = { {"because", 7, 0x02235, 0}, {"gEl", 3, 0x02A8C, 0}, {"setminus", 8, 0x02216, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_263[] = { {"ffr", 3, 0x1D523, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_26A[] = { {"ubrcy", 5, 0x0045E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_26B[] = { {"elinters", 8, 0x023E7, 0}, {"plusb", 5, 0x0229E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_26E[] = { {"pluse", 5, 0x02A72, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_274[] = { {"CapitalDifferentialD", 20, 0x02145, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_277[] = { {"daleth", 6, 0x02138, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_278[] = { {"kscr", 4, 0x1D4C0, 0}, {"ogon", 4, 0x002DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_27C[] = { {"SHcy", 4, 0x00428, 0}, {"equest", 6, 0x0225F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_27E[] = { {"rbarr", 5, 0x0290D, 0}, {"topf", 4, 0x1D565, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_283[] = { {"tritime", 7, 0x02A3B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_28A[] = { {"bot", 3, 0x022A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_294[] = { {"Wfr", 3, 0x1D51A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_297[] = { {"HumpEqual", 9, 0x0224F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_298[] = { {"rightleftharpoons", 17, 0x021CC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_29D[] = { {"frasl", 5, 0x02044, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_29F[] = { {"UnderBracket", 12, 0x023B5, 0}, {"ovbar", 5, 0x0233D, 0}, {"upharpoonright", 14, 0x021BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2A0[] = { {"euro", 4, 0x020AC, 0}, {"nhArr", 5, 0x021CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2A9[] = { {"NotSupersetEqual", 16, 0x02289, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2AE[] = { {"cularr", 6, 0x021B6, 0}, {"scnE", 4, 0x02AB6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2B1[] = { {"napid", 5, 0x0224B, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2B2[] = { {"harr", 4, 0x02194, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2B3[] = { {"gdot", 4, 0x00121, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2B9[] = { {"Lscr", 4, 0x02112, 0}, {"zeta", 4, 0x003B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2BF[] = { {"ENG", 3, 0x0014A, 0}, {"Uopf", 4, 0x1D54C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2C4[] = { {"esdot", 5, 0x02250, 0}, {"scsim", 5, 0x0227F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2C5[] = { {"Hfr", 3, 0x0210C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2CE[] = { {"RightArrow", 10, 0x02192, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2CF[] = { {"Sqrt", 4, 0x0221A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2D3[] = { {"xodot", 5, 0x02A00, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2DA[] = { {"ycy", 3, 0x0044B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2DB[] = { {"hkswarow", 8, 0x02926, 0}, {"urtri", 5, 0x025F9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2DC[] = { {"roang", 5, 0x027ED, 0}, {"tosa", 4, 0x02929, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2E3[] = { {"CircleMinus", 11, 0x02296, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2E4[] = { {"Lcaron", 6, 0x0013D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2EB[] = { {"ShortLeftArrow", 14, 0x02190, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2EC[] = { {"Dot", 3, 0x000A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2EE[] = { {"Rightarrow", 10, 0x021D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2F0[] = { {"prsim", 5, 0x0227E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2F2[] = { {"notinE", 6, 0x022F9, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_2F8[] = { {"becaus", 6, 0x02235, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_300[] = { {"NotEqualTilde", 13, 0x02242, 0x00338}, {"nparallel", 9, 0x02226, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_301[] = { {"capcup", 6, 0x02A47, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_304[] = { {"simeq", 5, 0x02243, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_305[] = { {"forall", 6, 0x02200, 0}, {"straightepsilon", 15, 0x003F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_308[] = { {"ruluhar", 7, 0x02968, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_30B[] = { {"jcy", 3, 0x00439, 0}, {"ltcc", 4, 0x02AA6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_30F[] = { {"bscr", 4, 0x1D4B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_311[] = { {"ExponentialE", 12, 0x02147, 0}, {"weierp", 6, 0x02118, 0}, {"yen", 3, 0x000A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_313[] = { {"blacksquare", 11, 0x025AA, 0}, {"uml", 3, 0x000A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_315[] = { {"backsimeq", 9, 0x022CD, 0}, {"kopf", 4, 0x1D55C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_319[] = { {"NotPrecedesEqual", 16, 0x02AAF, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_31A[] = { {"simgE", 5, 0x02AA0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_31B[] = { {"tridot", 6, 0x025EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_326[] = { {"DoubleLongLeftArrow", 19, 0x027F8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_329[] = { {"models", 6, 0x022A7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_32A[] = { {"emptyv", 6, 0x02205, 0}, {"eqslantgtr", 10, 0x02A96, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_32D[] = { {"Gcirc", 5, 0x0011C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_330[] = { {"bernou", 6, 0x0212C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_331[] = { {"HumpDownHump", 12, 0x0224E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_336[] = { {"yfr", 3, 0x1D536, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_338[] = { {"blacktriangle", 13, 0x025B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_33B[] = { {"yacy", 4, 0x0044F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_33F[] = { {"lsime", 5, 0x02A8D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_340[] = { {"NotTildeEqual", 13, 0x02244, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_341[] = { {"lsimg", 5, 0x02A8F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_347[] = { {"ncap", 4, 0x02A43, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_34D[] = { {"DD", 2, 0x02145, 0}, {"gcirc", 5, 0x0011D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_350[] = { {"Cscr", 4, 0x1D49E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_356[] = { {"Lopf", 4, 0x1D543, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_358[] = { {"lBarr", 5, 0x0290E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_359[] = { {"Leftrightarrow", 14, 0x021D4, 0}, {"gtrdot", 6, 0x022D7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_35D[] = { {"NotSquareSubset", 15, 0x0228F, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_35F[] = { {"sqsubset", 8, 0x0228F, 0}, {"subsetneq", 9, 0x0228A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_361[] = { {"doublebarwedge", 14, 0x02306, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_363[] = { {"blacktriangleleft", 17, 0x025C2, 0}, {"hellip", 6, 0x02026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_365[] = { {"xscr", 4, 0x1D4CD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_367[] = { {"LessFullEqual", 13, 0x02266, 0}, {"jfr", 3, 0x1D527, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_369[] = { {"GreaterSlantEqual", 17, 0x02A7E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_36A[] = { {"Uring", 5, 0x0016E, 0}, {"VeryThinSpace", 13, 0x0200A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_36B[] = { {"roarr", 5, 0x021FE, 0}, {"scaron", 6, 0x00161, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_36D[] = { {"Lcy", 3, 0x0041B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_36E[] = { {"RightDownVector", 15, 0x021C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_36F[] = { {"Sub", 3, 0x022D0, 0}, {"pitchfork", 9, 0x022D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_372[] = { {"nvsim", 5, 0x0223C, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_374[] = { {"xrArr", 5, 0x027F9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_378[] = { {"CloseCurlyQuote", 15, 0x02019, 0}, {"uwangle", 7, 0x029A7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_37A[] = { {"Sum", 3, 0x02211, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_37C[] = { {"iuml", 4, 0x000EF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_37D[] = { {"Sup", 3, 0x022D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_37E[] = { {"planck", 6, 0x0210F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_37F[] = { {"Egrave", 6, 0x000C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_380[] = { {"curlywedge", 10, 0x022CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_382[] = { {"TildeFullEqual", 14, 0x02245, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_383[] = { {"searhk", 6, 0x02925, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_386[] = { {"ETH", 3, 0x000D0, 0}, {"napos", 5, 0x00149, 0}, {"upsi", 4, 0x003C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_387[] = { {"twoheadleftarrow", 16, 0x0219E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_38A[] = { {"Assign", 6, 0x02254, 0}, {"uring", 5, 0x0016F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_38D[] = { {"SquareIntersection", 18, 0x02293, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_38E[] = { {"lmidot", 6, 0x00140, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_391[] = { {"kcedil", 6, 0x00137, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_394[] = { {"curren", 6, 0x000A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_397[] = { {"acute", 5, 0x000B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_398[] = { {"curlyeqsucc", 11, 0x022DF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_39C[] = { {"Omicron", 7, 0x0039F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_39F[] = { {"uarr", 4, 0x02191, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3A0[] = { {"Hstrok", 6, 0x00126, 0}, {"UnderBrace", 10, 0x023DF, 0}, {"tdot", 4, 0x020DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3A1[] = { {"qint", 4, 0x02A0C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3A4[] = { {"sfrown", 6, 0x02322, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3A5[] = { {"trpezium", 8, 0x023E2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3A6[] = { {"Yscr", 4, 0x1D4B4, 0}, {"cedil", 5, 0x000B8, 0}, {"planckh", 7, 0x0210E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3A7[] = { {"lang", 4, 0x027E8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3AC[] = { {"bopf", 4, 0x1D553, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3B2[] = { {"lbbrk", 5, 0x02772, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3B4[] = { {"khcy", 4, 0x00445, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3BF[] = { {"Epsilon", 7, 0x00395, 0}, {"simlE", 5, 0x02A9F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3C0[] = { {"GT", 2, 0x0003E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3C4[] = { {"nap", 3, 0x02249, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3C9[] = { {"Lfr", 3, 0x1D50F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3CD[] = { {"succapprox", 10, 0x02AB8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3D0[] = { {"bsim", 4, 0x0223D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3D3[] = { {"Gg", 2, 0x022D9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3D9[] = { {"angrtvb", 7, 0x022BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3DE[] = { {"xcirc", 5, 0x025EF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3E0[] = { {"Gt", 2, 0x0226B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3E1[] = { {"LeftRightVector", 15, 0x0294E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3E3[] = { {"circledast", 10, 0x0229B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3E4[] = { {"telrec", 6, 0x02315, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3E6[] = { {"SucceedsTilde", 13, 0x0227F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3E9[] = { {"nLtv", 4, 0x0226A, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3ED[] = { {"Copf", 4, 0x02102, 0}, {"napprox", 7, 0x02249, 0}, {"nsupseteq", 9, 0x02289, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3F1[] = { {"VerticalTilde", 13, 0x02240, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3F2[] = { {"parallel", 8, 0x02225, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3F7[] = { {"precnapprox", 11, 0x02AB9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3FC[] = { {"oscr", 4, 0x02134, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_3FE[] = { {"supsetneqq", 10, 0x02ACC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_402[] = { {"xopf", 4, 0x1D569, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_405[] = { {"mumap", 5, 0x022B8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_407[] = { {"varsupsetneqq", 13, 0x02ACC, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_409[] = { {"ReverseEquilibrium", 18, 0x021CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_40E[] = { {"Ubreve", 6, 0x0016C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_40F[] = { {"YUcy", 4, 0x0042E, 0}, {"ncy", 3, 0x0043D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_413[] = { {"ltimes", 6, 0x022C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_41A[] = { {"UpperRightArrow", 15, 0x02197, 0}, {"nvap", 4, 0x0224D, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_41B[] = { {"Im", 2, 0x02111, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_421[] = { {"simne", 5, 0x02246, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_423[] = { {"ccups", 5, 0x02A4C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_424[] = { {"nlArr", 5, 0x021CD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_425[] = { {"rarrsim", 7, 0x02974, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_426[] = { {"Ncaron", 6, 0x00147, 0}, {"vsupnE", 6, 0x02ACC, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_429[] = { {"succeq", 6, 0x02AB0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_42C[] = { {"Gammad", 6, 0x003DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_42F[] = { {"Icirc", 5, 0x000CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_430[] = { {"backepsilon", 11, 0x003F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_432[] = { {"ddarr", 5, 0x021CA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_436[] = { {"larr", 4, 0x02190, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_439[] = { {"divideontimes", 13, 0x022C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_43C[] = { {"succsim", 7, 0x0227F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_43D[] = { {"Pscr", 4, 0x1D4AB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_43E[] = { {"puncsp", 6, 0x02008, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_43F[] = { {"gtreqless", 9, 0x022DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_440[] = { {"intcal", 6, 0x022BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_441[] = { {"nsime", 5, 0x02244, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_443[] = { {"Yopf", 4, 0x1D550, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_446[] = { {"angsph", 6, 0x02222, 0}, {"vsupne", 6, 0x0228B, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_447[] = { {"NotNestedLessLess", 17, 0x02AA1, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_44A[] = { {"PrecedesSlantEqual", 18, 0x0227C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_44F[] = { {"icirc", 5, 0x000EE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_450[] = { {"DownLeftVectorBar", 17, 0x02956, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_454[] = { {"Auml", 4, 0x000C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_457[] = { {"LJcy", 4, 0x00409, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_458[] = { {"sqsube", 6, 0x02291, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_45D[] = { {"nprec", 5, 0x02280, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_45F[] = { {"ngE", 3, 0x02267, 0x00338}, {"smile", 5, 0x02323, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_465[] = { {"LT", 2, 0x0003C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_466[] = { {"ldrdhar", 7, 0x02967, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_469[] = { {"utri", 4, 0x025B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_46A[] = { {"Sacute", 6, 0x0015A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_46B[] = { {"late", 4, 0x02AAD, 0}, {"nfr", 3, 0x1D52B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_46D[] = { {"NotNestedGreaterGreater", 23, 0x02AA2, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_46F[] = { {"nwarr", 5, 0x02196, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_470[] = { {"biguplus", 8, 0x02A04, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_471[] = { {"Pcy", 3, 0x0041F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_472[] = { {"bigtriangleup", 13, 0x025B3, 0}, {"rationals", 9, 0x0211A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_473[] = { {"congdot", 7, 0x02A6D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_475[] = { {"PlusMinus", 9, 0x000B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_479[] = { {"IOcy", 4, 0x00401, 0}, {"Scedil", 6, 0x0015E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_47C[] = { {"eqcirc", 6, 0x02256, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_47D[] = { {"Ll", 2, 0x022D8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_47F[] = { {"Cayleys", 7, 0x0212D, 0}, {"nge", 3, 0x02271, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_480[] = { {"NotGreater", 10, 0x0226F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_485[] = { {"Lt", 2, 0x0226A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_488[] = { {"rotimes", 7, 0x02A35, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_48C[] = { {"caps", 4, 0x02229, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_48E[] = { {"ngt", 3, 0x0226F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_48F[] = { {"Cross", 5, 0x02A2F, 0}, {"bumpeq", 6, 0x0224F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_490[] = { {"VerticalSeparator", 17, 0x02758, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_491[] = { {"plankv", 6, 0x0210F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_493[] = { {"fscr", 4, 0x1D4BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_495[] = { {"bsol", 4, 0x0005C, 0}, {"sqsubseteq", 10, 0x02291, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_496[] = { {"boxH", 4, 0x02550, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_498[] = { {"rightarrowtail", 14, 0x021A3, 0}, {"ufisht", 6, 0x0297E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_499[] = { {"oopf", 4, 0x1D560, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_49F[] = { {"lobrk", 5, 0x027E6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4A2[] = { {"Acy", 3, 0x00410, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4A4[] = { {"NotSubsetEqual", 14, 0x02288, 0}, {"boxV", 4, 0x02551, 0}, {"dHar", 4, 0x02965, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4A6[] = { {"precnsim", 8, 0x022E8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4A7[] = { {"Mu", 2, 0x0039C, 0}, {"aelig", 5, 0x000E6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4AA[] = { {"gescc", 5, 0x02AA9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4AB[] = { {"origof", 6, 0x022B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4AE[] = { {"upsih", 5, 0x003D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4AF[] = { {"cross", 5, 0x02717, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4B2[] = { {"LeftFloor", 9, 0x0230A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4B6[] = { {"boxh", 4, 0x02500, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4B8[] = { {"NotGreaterEqual", 15, 0x02271, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4BC[] = { {"profalar", 8, 0x0232E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4C0[] = { {"nsmid", 5, 0x02224, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4C2[] = { {"hbar", 4, 0x0210F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4C3[] = { {"udarr", 5, 0x021C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4C4[] = { {"boxv", 4, 0x02502, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4C5[] = { {"olarr", 5, 0x021BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4C8[] = { {"Nu", 2, 0x0039D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4CB[] = { {"NotCongruent", 12, 0x02262, 0}, {"bkarow", 6, 0x0290D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4CD[] = { {"Pfr", 3, 0x1D513, 0}, {"forkv", 5, 0x02AD9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4CF[] = { {"nis", 3, 0x022FC, 0}, {"trianglerighteq", 15, 0x022B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4D0[] = { {"ngeq", 4, 0x02271, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4D2[] = { {"cudarrl", 7, 0x02938, 0}, {"nges", 4, 0x02A7E, 0x00338}, {"niv", 3, 0x0220B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4D3[] = { {"SubsetEqual", 11, 0x02286, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4D4[] = { {"Gscr", 4, 0x1D4A2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4D5[] = { {"complexes", 9, 0x02102, 0}, {"eDDot", 5, 0x02A77, 0}, {"nvge", 4, 0x02265, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4D8[] = { {"cudarrr", 7, 0x02935, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4DA[] = { {"Popf", 4, 0x02119, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4DE[] = { {"LongRightArrow", 14, 0x027F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4DF[] = { {"supseteq", 8, 0x02287, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4E3[] = { {"dollar", 6, 0x00024, 0}, {"gnsim", 5, 0x022E7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4E4[] = { {"nvgt", 4, 0x0003E, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4E6[] = { {"Or", 2, 0x02A54, 0}, {"Vert", 4, 0x02016, 0}, {"lneqq", 5, 0x02268, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4E7[] = { {"nLeftrightarrow", 15, 0x021CE, 0}, {"nbump", 5, 0x0224E, 0x00338}, {"ntriangleright", 14, 0x022EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4E8[] = { {"ecir", 4, 0x02256, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4E9[] = { {"npolint", 7, 0x02A14, 0}, {"plus", 4, 0x0002B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4ED[] = { {"centerdot", 9, 0x000B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4F1[] = { {"zacute", 6, 0x0017A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4F7[] = { {"odiv", 4, 0x02A38, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4F9[] = { {"cap", 3, 0x02229, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4FB[] = { {"ensp", 4, 0x02002, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_4FE[] = { {"Afr", 3, 0x1D504, 0}, {"Pi", 2, 0x003A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_500[] = { {"iquest", 6, 0x000BF, 0}, {"ltri", 4, 0x025C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_504[] = { {"nlE", 3, 0x02266, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_506[] = { {"Phi", 3, 0x003A6, 0}, {"lambda", 6, 0x003BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_507[] = { {"Pr", 2, 0x02ABB, 0}, {"Vdashl", 6, 0x02AE6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_509[] = { {"SuchThat", 8, 0x0220B, 0}, {"Supset", 6, 0x022D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_50E[] = { {"Darr", 4, 0x021A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_50F[] = { {"Cdot", 4, 0x0010A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_513[] = { {"rcy", 3, 0x00440, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_516[] = { {"orderof", 7, 0x02134, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_518[] = { {"leqq", 4, 0x02266, 0}, {"precsim", 7, 0x0227E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_519[] = { {"RightTriangle", 13, 0x022B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_51B[] = { {"agrave", 6, 0x000E0, 0}, {"succnapprox", 11, 0x02ABA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_51C[] = { {"Tab", 3, 0x00009, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_524[] = { {"nle", 3, 0x02270, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_525[] = { {"spades", 6, 0x02660, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_526[] = { {"gtcc", 4, 0x02AA7, 0}, {"llcorner", 8, 0x0231E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_52F[] = { {"Oslash", 6, 0x000D8, 0}, {"Tau", 3, 0x003A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_530[] = { {"fopf", 4, 0x1D557, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_532[] = { {"Mellintrf", 9, 0x02133, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_533[] = { {"nlt", 3, 0x0226E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_534[] = { {"lparlt", 6, 0x02993, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_53B[] = { {"Ccaron", 6, 0x0010C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_53C[] = { {"Re", 2, 0x0211C, 0}, {"dstrok", 6, 0x00111, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_53F[] = { {"leftharpoondown", 15, 0x021BD, 0}, {"ssetmn", 6, 0x02216, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_542[] = { {"lrhard", 6, 0x0296D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_543[] = { {"reg", 3, 0x000AE, 0}, {"sharp", 5, 0x0266F, 0}, {"yicy", 4, 0x00457, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_545[] = { {"ShortUpArrow", 12, 0x02191, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_548[] = { {"plusacir", 8, 0x02A23, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_54F[] = { {"cent", 4, 0x000A2, 0}, {"natur", 5, 0x0266E, 0}, {"varphi", 6, 0x003D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_550[] = { {"lesg", 4, 0x022DA, 0x0FE00}, {"supnE", 5, 0x02ACC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_551[] = { {"ohbar", 5, 0x029B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_557[] = { {"NotLessGreater", 14, 0x02278, 0}, {"nleqslant", 9, 0x02A7D, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_55B[] = { {"Sc", 2, 0x02ABC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_55D[] = { {"NotSucceedsEqual", 16, 0x02AB0, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_55F[] = { {"DZcy", 4, 0x0040F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_564[] = { {"vartheta", 8, 0x003D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_565[] = { {"ltrie", 5, 0x022B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_566[] = { {"Otilde", 6, 0x000D5, 0}, {"ltrif", 5, 0x025C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_56C[] = { {"Lsh", 3, 0x021B0, 0}, {"hookleftarrow", 13, 0x021A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_56F[] = { {"rfr", 3, 0x1D52F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_570[] = { {"supne", 5, 0x0228B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_571[] = { {"Gopf", 4, 0x1D53E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_572[] = { {"UpEquilibrium", 13, 0x0296E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_575[] = { {"Tcy", 3, 0x00422, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_576[] = { {"ffilig", 6, 0x0FB03, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_577[] = { {"fork", 4, 0x022D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_578[] = { {"oplus", 5, 0x02295, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_57A[] = { {"nvle", 4, 0x02264, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_57B[] = { {"HilbertSpace", 12, 0x0210B, 0}, {"subedot", 7, 0x02AC3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_57C[] = { {"TripleDot", 9, 0x020DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_580[] = { {"sscr", 4, 0x1D4C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_582[] = { {"osol", 4, 0x02298, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_583[] = { {"plustwo", 7, 0x02A27, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_586[] = { {"LessGreater", 11, 0x02276, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_588[] = { {"lrarr", 5, 0x021C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_589[] = { {"nvlt", 4, 0x0003C, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_58D[] = { {"questeq", 7, 0x0225F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_58E[] = { {"LessTilde", 9, 0x02272, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_58F[] = { {"djcy", 4, 0x00452, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_590[] = { {"xoplus", 6, 0x02A01, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_595[] = { {"primes", 6, 0x02119, 0}, {"solb", 4, 0x029C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_596[] = { {"not", 3, 0x000AC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_59A[] = { {"angzarr", 7, 0x0237C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_59D[] = { {"nearr", 5, 0x02197, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_59F[] = { {"lowast", 6, 0x02217, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5A0[] = { {"cfr", 3, 0x1D520, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5A3[] = { {"ltcir", 5, 0x02A79, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5A6[] = { {"Ecy", 3, 0x0042D, 0}, {"gesdotol", 8, 0x02A84, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5A9[] = { {"longleftrightarrow", 18, 0x027F7, 0}, {"para", 4, 0x000B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5AC[] = { {"Uacute", 6, 0x000DA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5AD[] = { {"blank", 5, 0x02423, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5AE[] = { {"rho", 3, 0x003C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5B0[] = { {"dharl", 5, 0x021C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5B1[] = { {"rsquor", 6, 0x02019, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5B5[] = { {"NotSquareSubsetEqual", 20, 0x022E2, 0}, {"npr", 3, 0x02280, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5B6[] = { {"dharr", 5, 0x021C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5B7[] = { {"NewLine", 7, 0x0000A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5BB[] = { {"odot", 4, 0x02299, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5BC[] = { {"part", 4, 0x02202, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5BD[] = { {"cuvee", 5, 0x022CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5BF[] = { {"lesdoto", 7, 0x02A81, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5C0[] = { {"itilde", 6, 0x00129, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5C1[] = { {"Tscr", 4, 0x1D4AF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5C2[] = { {"nsubE", 5, 0x02AC5, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5C4[] = { {"ratio", 5, 0x02236, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5D0[] = { {"Conint", 6, 0x0222F, 0}, {"LeftDownVectorBar", 17, 0x02959, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5D1[] = { {"Tfr", 3, 0x1D517, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5D3[] = { {"fllig", 5, 0x0FB02, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5D5[] = { {"thksim", 6, 0x0223C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5D8[] = { {"Euml", 4, 0x000CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5D9[] = { {"chi", 3, 0x003C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5DB[] = { {"ncup", 4, 0x02A42, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5DD[] = { {"SOFTcy", 6, 0x0042C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5DF[] = { {"bnequiv", 7, 0x02261, 0x020E5}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5E2[] = { {"nsube", 5, 0x02288, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5E4[] = { {"mapstoleft", 10, 0x021A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5E7[] = { {"NotLessSlantEqual", 17, 0x02A7D, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5EA[] = { {"ldrushar", 8, 0x0294B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5ED[] = { {"Equilibrium", 11, 0x021CC, 0}, {"Uogon", 5, 0x00172, 0}, {"supsetneq", 9, 0x0228B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5F0[] = { {"Vbar", 4, 0x02AEB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5F3[] = { {"vnsub", 5, 0x02282, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5F6[] = { {"Square", 6, 0x025A1, 0}, {"lessapprox", 10, 0x02A85, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5F8[] = { {"And", 3, 0x02A53, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5FA[] = { {"gesdoto", 7, 0x02A82, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_5FD[] = { {"gap", 3, 0x02A86, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_601[] = { {"nsucc", 5, 0x02281, 0}, {"thicksim", 8, 0x0223C, 0}, {"vnsup", 5, 0x02283, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_602[] = { {"Efr", 3, 0x1D508, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_603[] = { {"Igrave", 6, 0x000CC, 0}, {"cir", 3, 0x025CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_606[] = { {"Xi", 2, 0x0039E, 0}, {"oacute", 6, 0x000F3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_609[] = { {"nsc", 3, 0x02281, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_60D[] = { {"uogon", 5, 0x00173, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_613[] = { {"rharul", 6, 0x0296C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_615[] = { {"RuleDelayed", 11, 0x029F4, 0}, {"apacir", 6, 0x02A6F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_617[] = { {"jscr", 4, 0x1D4BF, 0}, {"vcy", 3, 0x00432, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_61A[] = { {"barwed", 6, 0x02305, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_61D[] = { {"sopf", 4, 0x1D564, 0}, {"thkap", 5, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_61F[] = { {"lesseqgtr", 9, 0x022DA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_622[] = { {"rdquor", 6, 0x0201D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_624[] = { {"Lstrok", 6, 0x00141, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_626[] = { {"Product", 7, 0x0220F, 0}, {"sqsupe", 6, 0x02292, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_628[] = { {"awconint", 8, 0x02233, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_62C[] = { {"hearts", 6, 0x02665, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_630[] = { {"rlm", 3, 0x0200F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_632[] = { {"comma", 5, 0x0002C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_636[] = { {"PartialD", 8, 0x02202, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_63A[] = { {"wedbar", 6, 0x02A5F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_63C[] = { {"oline", 5, 0x0203E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_63D[] = { {"OverBracket", 11, 0x023B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_63E[] = { {"RBarr", 5, 0x02910, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_641[] = { {"uharl", 5, 0x021BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_642[] = { {"leftrightsquigarrow", 19, 0x021AD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_645[] = { {"RightFloor", 10, 0x0230B, 0}, {"intprod", 7, 0x02A3C, 0}, {"vee", 3, 0x02228, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_646[] = { {"zigrarr", 7, 0x021DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_647[] = { {"uharr", 5, 0x021BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_648[] = { {"gcy", 3, 0x00433, 0}, {"varsubsetneq", 12, 0x0228A, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_649[] = { {"leqslant", 8, 0x02A7D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_64A[] = { {"Odblac", 6, 0x00150, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_651[] = { {"minus", 5, 0x02212, 0}, {"scpolint", 8, 0x02A13, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_652[] = { {"lrtri", 5, 0x022BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_653[] = { {"DiacriticalGrave", 16, 0x00060, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_655[] = { {"num", 3, 0x00023, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_657[] = { {"quest", 5, 0x0003F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_658[] = { {"Kscr", 4, 0x1D4A6, 0}, {"UnderBar", 8, 0x0005F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_659[] = { {"lsquo", 5, 0x02018, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_65C[] = { {"rArr", 4, 0x021D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_65E[] = { {"Topf", 4, 0x1D54B, 0}, {"heartsuit", 9, 0x02665, 0}, {"rBarr", 5, 0x0290F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_660[] = { {"emptyset", 8, 0x02205, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_669[] = { {"UnderParenthesis", 16, 0x023DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_670[] = { {"dotplus", 7, 0x02214, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_671[] = { {"Psi", 3, 0x003A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_672[] = { {"GJcy", 4, 0x00403, 0}, {"exist", 5, 0x02203, 0}, {"simplus", 7, 0x02A24, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_673[] = { {"vfr", 3, 0x1D533, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_676[] = { {"tprime", 6, 0x02034, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_678[] = { {"leftrightharpoons", 17, 0x021CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_679[] = { {"rbrksld", 7, 0x0298E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_67D[] = { {"Ecaron", 6, 0x0011A, 0}, {"gel", 3, 0x022DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_680[] = { {"capdot", 6, 0x02A40, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_682[] = { {"geq", 3, 0x02265, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_684[] = { {"LowerLeftArrow", 14, 0x02199, 0}, {"ges", 3, 0x02A7E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_685[] = { {"Colone", 6, 0x02A74, 0}, {"NotLessEqual", 12, 0x02270, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_68A[] = { {"nrarr", 5, 0x0219B, 0}, {"rbrkslu", 7, 0x02990, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_68C[] = { {"flat", 4, 0x0266D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_691[] = { {"there4", 6, 0x02234, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_693[] = { {"Gdot", 4, 0x00120, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_694[] = { {"ijlig", 5, 0x00133, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_696[] = { {"blacklozenge", 12, 0x029EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_699[] = { {"Zeta", 4, 0x00396, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6A3[] = { {"duarr", 5, 0x021F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6A4[] = { {"DotEqual", 8, 0x02250, 0}, {"dtdot", 5, 0x022F1, 0}, {"gfr", 3, 0x1D524, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6A8[] = { {"cirE", 4, 0x029C3, 0}, {"period", 6, 0x0002E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6A9[] = { {"lmoust", 6, 0x023B0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6AA[] = { {"Icy", 3, 0x00418, 0}, {"Rcaron", 6, 0x00158, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6AB[] = { {"LeftCeiling", 11, 0x02308, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6AE[] = { {"ascr", 4, 0x1D4B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6B0[] = { {"boxtimes", 8, 0x022A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6B4[] = { {"jopf", 4, 0x1D55B, 0}, {"ntriangleleft", 13, 0x022EA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6B6[] = { {"eqcolon", 7, 0x02255, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6B8[] = { {"rbbrk", 5, 0x02773, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6B9[] = { {"homtht", 6, 0x0223B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6BA[] = { {"ggg", 3, 0x022D9, 0}, {"seswar", 6, 0x02929, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6BC[] = { {"perp", 4, 0x022A5, 0}, {"shcy", 4, 0x00448, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6BF[] = { {"phone", 5, 0x0260E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C0[] = { {"NotDoubleVerticalBar", 20, 0x02226, 0}, {"ngtr", 4, 0x0226F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C4[] = { {"ThickSpace", 10, 0x0205F, 0x0200A}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C5[] = { {"ForAll", 6, 0x02200, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C6[] = { {"circ", 4, 0x002C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C7[] = { {"Verbar", 6, 0x02016, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C8[] = { {"cire", 4, 0x02257, 0}, {"lesges", 6, 0x02A93, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6C9[] = { {"slarr", 5, 0x02190, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6CC[] = { {"RightDownTeeVector", 18, 0x0295D, 0}, {"triangleq", 9, 0x0225C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6CE[] = { {"checkmark", 9, 0x02713, 0}, {"quot", 4, 0x00022, 0}, {"suplarr", 7, 0x0297B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6D1[] = { {"Backslash", 9, 0x02216, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6D2[] = { {"fallingdotseq", 13, 0x02252, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6D4[] = { {"swArr", 5, 0x021D9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6D5[] = { {"Xfr", 3, 0x1D51B, 0}, {"lbrke", 5, 0x0298B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6D9[] = { {"jmath", 5, 0x00237, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6DA[] = { {"lmoustache", 10, 0x023B0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6DB[] = { {"DownTee", 7, 0x022A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6DC[] = { {"reals", 5, 0x0211D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6DE[] = { {"quaternions", 11, 0x0210D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6E7[] = { {"vzigzag", 7, 0x0299A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6EB[] = { {"pound", 5, 0x000A3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6EE[] = { {"permil", 6, 0x02030, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6EF[] = { {"Bscr", 4, 0x0212C, 0}, {"lfisht", 6, 0x0297C, 0}, {"vartriangleleft", 15, 0x022B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6F5[] = { {"Kopf", 4, 0x1D542, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6F7[] = { {"Tilde", 5, 0x0223C, 0}, {"gtrarr", 6, 0x02978, 0}, {"lAarr", 5, 0x021DA, 0}, {"opar", 4, 0x029B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_6FB[] = { {"triangle", 8, 0x025B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_704[] = { {"lcaron", 6, 0x0013E, 0}, {"wscr", 4, 0x1D4CC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_705[] = { {"asympeq", 7, 0x0224D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_706[] = { {"Ifr", 3, 0x02111, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_707[] = { {"DoubleDot", 9, 0x000A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_709[] = { {"nVdash", 6, 0x022AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_70C[] = { {"hairsp", 6, 0x0200A, 0}, {"leftrightarrows", 15, 0x021C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_70E[] = { {"lbrace", 6, 0x0007B, 0}, {"rightarrow", 10, 0x02192, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_70F[] = { {"Dagger", 6, 0x02021, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_712[] = { {"rsh", 3, 0x021B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_714[] = { {"eqslantless", 11, 0x02A95, 0}, {"gnapprox", 8, 0x02A8A, 0}, {"lbrack", 6, 0x0005B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_715[] = { {"uHar", 4, 0x02963, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_717[] = { {"tilde", 5, 0x002DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_719[] = { {"complement", 10, 0x02201, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_71B[] = { {"zcy", 3, 0x00437, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_71E[] = { {"boxDL", 5, 0x02557, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_71F[] = { {"micro", 5, 0x000B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_723[] = { {"horbar", 6, 0x02015, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_724[] = { {"boxDR", 5, 0x02554, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_727[] = { {"bsolhsub", 8, 0x027C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_729[] = { {"ac", 2, 0x0223E, 0}, {"nvdash", 6, 0x022AC, 0}, {"precapprox", 10, 0x02AB7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_72C[] = { {"af", 2, 0x02061, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_72D[] = { {"bullet", 6, 0x02022, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_72E[] = { {"demptyv", 7, 0x029B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_733[] = { {"geqq", 4, 0x02267, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_734[] = { {"uuarr", 5, 0x021C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_735[] = { {"Ocirc", 5, 0x000D4, 0}, {"utdot", 5, 0x022F0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_736[] = { {"ap", 2, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_738[] = { {"bNot", 4, 0x02AED, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_73B[] = { {"CirclePlus", 10, 0x02295, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_73D[] = { {"glE", 3, 0x02A92, 0}, {"midcir", 6, 0x02AF0, 0}, {"rppolint", 8, 0x02A12, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_73E[] = { {"boxDl", 5, 0x02556, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_73F[] = { {"sdot", 4, 0x022C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_744[] = { {"boxDr", 5, 0x02553, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_745[] = { {"Xscr", 4, 0x1D4B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_749[] = { {"dlcrop", 6, 0x0230D, 0}, {"gtrless", 7, 0x02277, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_74B[] = { {"aopf", 4, 0x1D552, 0}, {"operp", 5, 0x029B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_74C[] = { {"kcy", 3, 0x0043A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_74F[] = { {"larrfs", 6, 0x0291D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_751[] = { {"rcub", 4, 0x0007D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_754[] = { {"nrtri", 5, 0x022EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_755[] = { {"nparsl", 6, 0x02AFD, 0x020E5}, {"ocirc", 5, 0x000F4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_759[] = { {"gla", 3, 0x02AA5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_75C[] = { {"Iuml", 4, 0x000CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_75F[] = { {"mcomma", 6, 0x02A29, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_762[] = { {"glj", 3, 0x02AA4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_763[] = { {"Map", 3, 0x02905, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_765[] = { {"copysr", 6, 0x02117, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_766[] = { {"DownTeeArrow", 12, 0x021A7, 0}, {"Upsi", 4, 0x003D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_768[] = { {"awint", 5, 0x02A11, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_76E[] = { {"DownRightVector", 15, 0x021C1, 0}, {"NotEqual", 8, 0x02260, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_770[] = { {"gesl", 4, 0x022DB, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_772[] = { {"NotCupCap", 9, 0x0226D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_776[] = { {"blacktriangleright", 18, 0x025B8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_777[] = { {"zfr", 3, 0x1D537, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_779[] = { {"leftrightarrow", 14, 0x02194, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_77A[] = { {"Abreve", 6, 0x00102, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_77F[] = { {"Uarr", 4, 0x0219F, 0}, {"gnE", 3, 0x02269, 0}, {"supmult", 7, 0x02AC2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_781[] = { {"supplus", 7, 0x02AC0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_783[] = { {"nabla", 5, 0x02207, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_787[] = { {"Lang", 4, 0x027EA, 0}, {"laquo", 5, 0x000AB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_789[] = { {"larrhk", 6, 0x021A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_78C[] = { {"Bopf", 4, 0x1D539, 0}, {"lowbar", 6, 0x0005F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_78D[] = { {"cup", 3, 0x0222A, 0}, {"dd", 2, 0x02146, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_78E[] = { {"nsce", 4, 0x02AB0, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_790[] = { {"nshortparallel", 14, 0x02226, 0}, {"nsupE", 5, 0x02AC6, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_794[] = { {"OpenCurlyQuote", 14, 0x02018, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_797[] = { {"bsolb", 5, 0x029C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_798[] = { {"DScy", 4, 0x00405, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_79A[] = { {"boxHD", 5, 0x02566, 0}, {"ltrPar", 6, 0x02996, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_79B[] = { {"nscr", 4, 0x1D4C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_79D[] = { {"lEg", 3, 0x02A8B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_79F[] = { {"egrave", 6, 0x000E8, 0}, {"gne", 3, 0x02A88, 0}, {"larrsim", 7, 0x02973, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7A0[] = { {"COPY", 4, 0x000A9, 0}, {"bdquo", 5, 0x0201E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7A1[] = { {"wopf", 4, 0x1D568, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7A2[] = { {"NotRightTriangleEqual", 21, 0x022ED, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7A5[] = { {"robrk", 5, 0x027E7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7A8[] = { {"kfr", 3, 0x1D528, 0}, {"nlsim", 5, 0x02274, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7AA[] = { {"xhArr", 5, 0x027FA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7AB[] = { {"boxHU", 5, 0x02569, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7AC[] = { {"lHar", 4, 0x02962, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7AE[] = { {"Mcy", 3, 0x0041C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7AF[] = { {"ee", 2, 0x02147, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7B0[] = { {"nsupe", 5, 0x02289, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7B1[] = { {"eg", 2, 0x02A9A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7B5[] = { {"trade", 5, 0x02122, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7B6[] = { {"el", 2, 0x02A99, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7B7[] = { {"nsucceq", 7, 0x02AB0, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7B8[] = { {"langle", 6, 0x027E8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7BA[] = { {"boxHd", 5, 0x02564, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7BB[] = { {"Subset", 6, 0x022D0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7BD[] = { {"DownArrowBar", 12, 0x02913, 0}, {"topbot", 6, 0x02336, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7BE[] = { {"OverBrace", 9, 0x023DE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7BF[] = { {"Eta", 3, 0x00397, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7C0[] = { {"hstrok", 6, 0x00127, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7C1[] = { {"Hacek", 5, 0x002C7, 0}, {"diamond", 7, 0x022C4, 0}, {"isinsv", 6, 0x022F3, 0}, {"rtriltri", 8, 0x029CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7C9[] = { {"nvltrie", 7, 0x022B4, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7CB[] = { {"boxHu", 5, 0x02567, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7CD[] = { {"fpartint", 8, 0x02A0D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7CE[] = { {"Proportional", 12, 0x0221D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7D1[] = { {"NotSuperset", 11, 0x02283, 0x020D2}, {"gE", 2, 0x02267, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7D2[] = { {"scnsim", 6, 0x022E9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7D5[] = { {"uparrow", 7, 0x02191, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7D6[] = { {"ltlarr", 6, 0x02976, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7D9[] = { {"rtimes", 6, 0x022CA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7DA[] = { {"ncong", 5, 0x02247, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7DC[] = { {"Oscr", 4, 0x1D4AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7E0[] = { {"vArr", 4, 0x021D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7E2[] = { {"Xopf", 4, 0x1D54F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7E4[] = { {"notinva", 7, 0x02209, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7E5[] = { {"notinvb", 7, 0x022F7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7E6[] = { {"notinvc", 7, 0x022F6, 0}, {"nsqsube", 7, 0x022E2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7EC[] = { {"Tcaron", 6, 0x00164, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7EF[] = { {"upsilon", 7, 0x003C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7F1[] = { {"ge", 2, 0x02265, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7F3[] = { {"gg", 2, 0x0226B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7F6[] = { {"KJcy", 4, 0x0040C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7F8[] = { {"gl", 2, 0x02277, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7FB[] = { {"dblac", 5, 0x002DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_7FC[] = { {"lAtail", 6, 0x0291B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_800[] = { {"gt", 2, 0x0003E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_802[] = { {"lotimes", 7, 0x02A34, 0}, {"seArr", 5, 0x021D8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_803[] = { {"Lacute", 6, 0x00139, 0}, {"Laplacetrf", 10, 0x02112, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_808[] = { {"uuml", 4, 0x000FC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_809[] = { {"Amacr", 5, 0x00100, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_80A[] = { {"Mfr", 3, 0x1D510, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_810[] = { {"Int", 3, 0x0222C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_811[] = { {"Vvdash", 6, 0x022AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_812[] = { {"Lcedil", 6, 0x0013B, 0}, {"larrlp", 6, 0x021AB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_816[] = { {"Larr", 4, 0x0219E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_819[] = { {"CircleTimes", 11, 0x02297, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_81C[] = { {"NotReverseElement", 17, 0x0220C, 0}, {"latail", 6, 0x02919, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_81D[] = { {"ntrianglerighteq", 16, 0x022ED, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_821[] = { {"blk12", 5, 0x02592, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_822[] = { {"intlarhk", 8, 0x02A17, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_823[] = { {"blk14", 5, 0x02591, 0}, {"ccupssm", 7, 0x02A50, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_824[] = { {"hercon", 6, 0x022B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_828[] = { {"bigotimes", 9, 0x02A02, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_829[] = { {"amacr", 5, 0x00101, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_82D[] = { {"nrarrc", 6, 0x02933, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_82E[] = { {"ubreve", 6, 0x0016D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_830[] = { {"Yacute", 6, 0x000DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_831[] = { {"ic", 2, 0x02063, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_832[] = { {"escr", 4, 0x0212F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_837[] = { {"ii", 2, 0x02148, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_838[] = { {"DownArrowUpArrow", 16, 0x021F5, 0}, {"nopf", 4, 0x1D55F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_83C[] = { {"in", 2, 0x02208, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_83E[] = { {"bumpE", 5, 0x02AAE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_83F[] = { {"rightharpoonup", 14, 0x021C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_841[] = { {"nrarrw", 6, 0x0219D, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_842[] = { {"it", 2, 0x02062, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_846[] = { {"ncaron", 6, 0x00148, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_84A[] = { {"succnsim", 8, 0x022E9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_84C[] = { {"gammad", 6, 0x003DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_84F[] = { {"yucy", 4, 0x0044E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_850[] = { {"ocy", 3, 0x0043E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_855[] = { {"hybull", 6, 0x02043, 0}, {"rpargt", 6, 0x02994, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_857[] = { {"csube", 5, 0x02AD1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_85B[] = { {"iiota", 5, 0x02129, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_85C[] = { {"nsim", 4, 0x02241, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_85E[] = { {"LeftTriangleEqual", 17, 0x022B4, 0}, {"bumpe", 5, 0x0224F, 0}, {"nearhk", 6, 0x02924, 0}, {"nhpar", 5, 0x02AF2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_861[] = { {"risingdotseq", 12, 0x02253, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_865[] = { {"blk34", 5, 0x02593, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_866[] = { {"LeftTriangle", 12, 0x022B2, 0}, {"vBarv", 5, 0x02AE9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_867[] = { {"AElig", 5, 0x000C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_868[] = { {"DoubleUpDownArrow", 17, 0x021D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_86A[] = { {"cwint", 5, 0x02231, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_86B[] = { {"rtrie", 5, 0x022B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_86C[] = { {"rtrif", 5, 0x025B8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_873[] = { {"Fscr", 4, 0x02131, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_876[] = { {"lE", 2, 0x02266, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_879[] = { {"Oopf", 4, 0x1D546, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_87B[] = { {"spar", 4, 0x02225, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_87E[] = { {"uplus", 5, 0x0228E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_88A[] = { {"sacute", 6, 0x0015B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_88C[] = { {"fltns", 5, 0x025B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_88E[] = { {"rrarr", 5, 0x021C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_892[] = { {"larrpl", 6, 0x02939, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_895[] = { {"ultri", 5, 0x025F8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_896[] = { {"le", 2, 0x02264, 0}, {"xuplus", 6, 0x02A04, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_897[] = { {"ljcy", 4, 0x00459, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_898[] = { {"lg", 2, 0x02276, 0}, {"vsubnE", 6, 0x02ACB, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_899[] = { {"scedil", 6, 0x0015F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_89D[] = { {"ll", 2, 0x0226A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8A5[] = { {"lt", 2, 0x0003C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8AC[] = { {"ofr", 3, 0x1D52C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8B3[] = { {"nexists", 7, 0x02204, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8B6[] = { {"smallsetminus", 13, 0x02216, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8B7[] = { {"InvisibleComma", 14, 0x02063, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8B8[] = { {"dotminus", 8, 0x02238, 0}, {"vsubne", 6, 0x0228A, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8B9[] = { {"iocy", 4, 0x00451, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8BA[] = { {"gsime", 5, 0x02A8E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8BC[] = { {"Rarrtl", 6, 0x02916, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8BD[] = { {"cirmid", 6, 0x02AEF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8C0[] = { {"ominus", 6, 0x02296, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8C1[] = { {"gsiml", 5, 0x02A90, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8C2[] = { {"Prime", 5, 0x02033, 0}, {"mp", 2, 0x02213, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8C4[] = { {"tint", 4, 0x0222D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8C7[] = { {"mu", 2, 0x003BC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8CF[] = { {"dbkarow", 7, 0x0290F, 0}, {"eopf", 4, 0x1D556, 0}, {"ogt", 3, 0x029C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8D0[] = { {"Precedes", 8, 0x0227A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8D3[] = { {"UpTeeArrow", 10, 0x021A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8D6[] = { {"varsupsetneq", 12, 0x0228B, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8D8[] = { {"ne", 2, 0x02260, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8DC[] = { {"ni", 2, 0x0220B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8DD[] = { {"mDDot", 5, 0x0223A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8DE[] = { {"cularrp", 7, 0x0293D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8DF[] = { {"rnmid", 5, 0x02AEE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8E0[] = { {"hardcy", 6, 0x0044A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8E2[] = { {"prime", 5, 0x02032, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8E3[] = { {"Bcy", 3, 0x00411, 0}, {"REG", 3, 0x000AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8E7[] = { {"oS", 2, 0x024C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8E8[] = { {"nu", 2, 0x003BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8E9[] = { {"ohm", 3, 0x003A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8EB[] = { {"langd", 5, 0x02991, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8F3[] = { {"backprime", 9, 0x02035, 0}, {"esim", 4, 0x02242, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8FB[] = { {"veeeq", 5, 0x0225A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8FE[] = { {"RightCeiling", 12, 0x02309, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_8FF[] = { {"crarr", 5, 0x021B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_904[] = { {"eqsim", 5, 0x02242, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_906[] = { {"or", 2, 0x02228, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_907[] = { {"OverParenthesis", 15, 0x023DC, 0}, {"UpperLeftArrow", 14, 0x02196, 0}, {"nleftrightarrow", 15, 0x021AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_909[] = { {"expectation", 11, 0x02130, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_90C[] = { {"coprod", 6, 0x02210, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_90E[] = { {"Qfr", 3, 0x1D514, 0}, {"dArr", 4, 0x021D3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_910[] = { {"Fopf", 4, 0x1D53D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_913[] = { {"Cconint", 7, 0x02230, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_916[] = { {"larrtl", 6, 0x021A2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_918[] = { {"Aacute", 6, 0x000C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_919[] = { {"DownLeftRightVector", 19, 0x02950, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_91B[] = { {"circleddash", 11, 0x0229D, 0}, {"thinsp", 6, 0x02009, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_91E[] = { {"Longrightarrow", 14, 0x027F9, 0}, {"pi", 2, 0x003C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_91F[] = { {"hookrightarrow", 14, 0x021AA, 0}, {"rscr", 4, 0x1D4C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_920[] = { {"scE", 3, 0x02AB4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_922[] = { {"pm", 2, 0x000B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_923[] = { {"ZHcy", 4, 0x00416, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_927[] = { {"pr", 2, 0x0227A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_929[] = { {"LongLeftRightArrow", 18, 0x027F7, 0}, {"supset", 6, 0x02283, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_92A[] = { {"UpArrowBar", 10, 0x02912, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_92C[] = { {"Utilde", 6, 0x00168, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_92E[] = { {"xlArr", 5, 0x027F8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_930[] = { {"DoubleUpArrow", 13, 0x021D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_936[] = { {"alefsym", 7, 0x02135, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_939[] = { {"Scirc", 5, 0x0015C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_93B[] = { {"xotime", 6, 0x02A02, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_93F[] = { {"Bfr", 3, 0x1D505, 0}, {"rdca", 4, 0x02937, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_940[] = { {"sce", 3, 0x02AB0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_945[] = { {"Nacute", 6, 0x00143, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_947[] = { {"amalg", 5, 0x02A3F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_94D[] = { {"UpDownArrow", 11, 0x02195, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_94F[] = { {"EqualTilde", 10, 0x02242, 0}, {"boxUL", 5, 0x0255D, 0}, {"oslash", 6, 0x000F8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_950[] = { {"lnap", 4, 0x02A89, 0}, {"thorn", 5, 0x000FE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_952[] = { {"ssmile", 6, 0x02323, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_953[] = { {"ndash", 5, 0x02013, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_954[] = { {"Ncedil", 6, 0x00145, 0}, {"scy", 3, 0x00441, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_955[] = { {"boxUR", 5, 0x0255A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_956[] = { {"Aring", 5, 0x000C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_959[] = { {"scirc", 5, 0x0015D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_95B[] = { {"ccaron", 6, 0x0010D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_95D[] = { {"dotsquare", 9, 0x022A1, 0}, {"nshortmid", 9, 0x02224, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_95F[] = { {"rsquo", 5, 0x02019, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_960[] = { {"Sscr", 4, 0x1D4AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_963[] = { {"bigwedge", 8, 0x022C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_964[] = { {"Bernoullis", 10, 0x0212C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_969[] = { {"harrw", 5, 0x021AD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_96C[] = { {"SquareSubset", 12, 0x0228F, 0}, {"boxVH", 5, 0x0256C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_96F[] = { {"boxUl", 5, 0x0255C, 0}, {"rx", 2, 0x0211E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_970[] = { {"boxVL", 5, 0x02563, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_974[] = { {"olt", 3, 0x029C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_975[] = { {"boxUr", 5, 0x02559, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_976[] = { {"aring", 5, 0x000E5, 0}, {"boxVR", 5, 0x02560, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_97B[] = { {"sc", 2, 0x0227B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_97C[] = { {"NestedGreaterGreater", 20, 0x0226B, 0}, {"oast", 4, 0x0229B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_97F[] = { {"star", 4, 0x02606, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_981[] = { {"LeftTeeVector", 13, 0x0295A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_983[] = { {"bigsqcup", 8, 0x02A06, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_985[] = { {"dcy", 3, 0x00434, 0}, {"preceq", 6, 0x02AAF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_986[] = { {"otilde", 6, 0x000F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_988[] = { {"luruhar", 7, 0x02966, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_98C[] = { {"boxVh", 5, 0x0256B, 0}, {"capand", 6, 0x02A44, 0}, {"yuml", 4, 0x000FF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_98D[] = { {"Updownarrow", 11, 0x021D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_98F[] = { {"TildeEqual", 10, 0x02243, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_990[] = { {"boxVl", 5, 0x02562, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_996[] = { {"boxVr", 5, 0x0255F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_997[] = { {"HorizontalLine", 14, 0x02500, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_99B[] = { {"xmap", 4, 0x027FC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_99C[] = { {"sigmaf", 6, 0x003C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_99E[] = { {"EmptySmallSquare", 16, 0x025FB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_99F[] = { {"dzcy", 4, 0x0045F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9A0[] = { {"cups", 4, 0x0222A, 0x0FE00}, {"zwj", 3, 0x0200D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9A1[] = { {"beta", 4, 0x003B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9A6[] = { {"supsim", 6, 0x02AC8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9A8[] = { {"beth", 4, 0x02136, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9AA[] = { {"Iukcy", 5, 0x00406, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9AC[] = { {"eparsl", 6, 0x029E3, 0}, {"sigmav", 6, 0x003C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9B0[] = { {"lhard", 5, 0x021BD, 0}, {"sfr", 3, 0x1D530, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9B4[] = { {"nsqsupe", 7, 0x022E3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9B5[] = { {"Jsercy", 6, 0x00408, 0}, {"deg", 3, 0x000B0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9B6[] = { {"Ucy", 3, 0x00423, 0}, {"iscr", 4, 0x1D4BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9B7[] = { {"efDot", 5, 0x02252, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9BB[] = { {"uhblk", 5, 0x02580, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9BC[] = { {"ropf", 4, 0x1D563, 0}, {"vprop", 5, 0x0221D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9BD[] = { {"isinE", 5, 0x022F9, 0}, {"raemptyv", 8, 0x029B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9C1[] = { {"lharu", 5, 0x021BC, 0}, {"ncongdot", 8, 0x02A6D, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9C2[] = { {"subnE", 5, 0x02ACB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9C3[] = { {"ngsim", 5, 0x02275, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9C5[] = { {"starf", 5, 0x02605, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9C9[] = { {"Ograve", 6, 0x000D2, 0}, {"hksearow", 8, 0x02925, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9CA[] = { {"iukcy", 5, 0x00456, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9CC[] = { {"uacute", 6, 0x000FA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9CF[] = { {"asymp", 5, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9D5[] = { {"lneq", 4, 0x02A87, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9D6[] = { {"Otimes", 6, 0x02A37, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9DA[] = { {"NotTildeTilde", 13, 0x02249, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9DB[] = { {"Integral", 8, 0x0222B, 0}, {"rbrke", 5, 0x0298C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9DD[] = { {"nsub", 4, 0x02284, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9DE[] = { {"rlhar", 5, 0x021CC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9E1[] = { {"dfr", 3, 0x1D521, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9E2[] = { {"subne", 5, 0x0228A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9E5[] = { {"varnothing", 10, 0x02205, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9E7[] = { {"Fcy", 3, 0x00424, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9E9[] = { {"DoubleLeftTee", 13, 0x02AE4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9EB[] = { {"isins", 5, 0x022F4, 0}, {"nsup", 4, 0x02285, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9ED[] = { {"circlearrowleft", 15, 0x021BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9EE[] = { {"isinv", 5, 0x02208, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9EF[] = { {"IEcy", 4, 0x00415, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F0[] = { {"conint", 6, 0x0222E, 0}, {"vBar", 4, 0x02AE8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F1[] = { {"edot", 4, 0x00117, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F2[] = { {"Kappa", 5, 0x0039A, 0}, {"MediumSpace", 11, 0x0205F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F3[] = { {"lbrksld", 7, 0x0298F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F4[] = { {"sect", 4, 0x000A7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F5[] = { {"nldr", 4, 0x02025, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F7[] = { {"Jscr", 4, 0x1D4A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9F9[] = { {"shy", 3, 0x000AD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9FA[] = { {"ulcrop", 6, 0x0230F, 0}, {"veebar", 6, 0x022BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_9FD[] = { {"Sopf", 4, 0x1D54A, 0}, {"cuwed", 5, 0x022CF, 0}, {"rAarr", 5, 0x021DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A01[] = { {"erarr", 5, 0x02971, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A04[] = { {"lbrkslu", 7, 0x0298D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A05[] = { {"NotSucceeds", 11, 0x02281, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A06[] = { {"nsccue", 6, 0x022E1, 0}, {"subrarr", 7, 0x02979, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A08[] = { {"looparrowright", 14, 0x021AC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A0C[] = { {"wp", 2, 0x02118, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A0D[] = { {"Emacr", 5, 0x00112, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A0E[] = { {"sim", 3, 0x0223C, 0}, {"wr", 2, 0x02240, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A10[] = { {"Udblac", 6, 0x00170, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A12[] = { {"Ufr", 3, 0x1D518, 0}, {"kappa", 5, 0x003BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A14[] = { {"notindot", 8, 0x022F5, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A15[] = { {"nleq", 4, 0x02270, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A16[] = { {"NestedLessLess", 14, 0x0226A, 0}, {"square", 6, 0x025A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A17[] = { {"nles", 4, 0x02A7D, 0x00338}, {"squarf", 6, 0x025AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A21[] = { {"order", 5, 0x02134, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A23[] = { {"igrave", 6, 0x000EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A24[] = { {"precneqq", 8, 0x02AB5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A25[] = { {"csupe", 5, 0x02AD2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A26[] = { {"xi", 2, 0x003BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A28[] = { {"NotHumpEqual", 12, 0x0224F, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A2A[] = { {"ord", 3, 0x02A5D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A2D[] = { {"emacr", 5, 0x00113, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A30[] = { {"nwnear", 6, 0x02927, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A32[] = { {"nprcue", 6, 0x022E0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A36[] = { {"NotExists", 9, 0x02204, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A37[] = { {"die", 3, 0x000A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A39[] = { {"ddotseq", 7, 0x02A77, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A3B[] = { {"Dashv", 5, 0x02AE4, 0}, {"Ucirc", 5, 0x000DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A3C[] = { {"orv", 3, 0x02A5B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A3D[] = { {"Because", 7, 0x02235, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A41[] = { {"kgreen", 6, 0x00138, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A43[] = { {"Ffr", 3, 0x1D509, 0}, {"LeftVector", 10, 0x021BC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A44[] = { {"lstrok", 6, 0x00142, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A45[] = { {"twixt", 5, 0x0226C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A48[] = { {"compfn", 6, 0x02218, 0}, {"div", 3, 0x000F7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A4F[] = { {"drcrop", 6, 0x0230C, 0}, {"shortmid", 8, 0x02223, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A53[] = { {"iopf", 4, 0x1D55A, 0}, {"triangledown", 12, 0x025BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A54[] = { {"IJlig", 5, 0x00132, 0}, {"thetasym", 8, 0x003D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A56[] = { {"Sigma", 5, 0x003A3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A57[] = { {"equivDD", 7, 0x02A78, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A5A[] = { {"Cacute", 6, 0x00106, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A5B[] = { {"dashv", 5, 0x022A3, 0}, {"ucirc", 5, 0x000FB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A61[] = { {"gneqq", 5, 0x02269, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A62[] = { {"gvertneqq", 9, 0x02269, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A63[] = { {"RightDownVectorBar", 18, 0x02955, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A64[] = { {"NotLessLess", 11, 0x0226A, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A69[] = { {"Ccedil", 6, 0x000C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A6A[] = { {"odblac", 6, 0x00151, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A6B[] = { {"mstpos", 6, 0x0223E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A6D[] = { {"cemptyv", 7, 0x029B2, 0}, {"rarrap", 6, 0x02975, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A6F[] = { {"rmoust", 6, 0x023B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A70[] = { {"elsdot", 6, 0x02A97, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A76[] = { {"sigma", 5, 0x003C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A78[] = { {"Implies", 7, 0x021D2, 0}, {"isin", 4, 0x02208, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A7A[] = { {"bottom", 6, 0x022A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A7E[] = { {"ShortRightArrow", 15, 0x02192, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A81[] = { {"cupcap", 6, 0x02A46, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A82[] = { {"NotSquareSuperset", 17, 0x02290, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A84[] = { {"LeftArrowRightArrow", 19, 0x021C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A85[] = { {"FilledVerySmallSquare", 21, 0x025AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A86[] = { {"LeftUpTeeVector", 15, 0x02960, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A89[] = { {"DoubleRightArrow", 16, 0x021D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A8D[] = { {"raquo", 5, 0x000BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A8E[] = { {"Ascr", 4, 0x1D49C, 0}, {"ReverseUpEquilibrium", 20, 0x0296F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A92[] = { {"hArr", 4, 0x021D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A94[] = { {"Jopf", 4, 0x1D541, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A96[] = { {"npar", 4, 0x02226, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A98[] = { {"SupersetEqual", 13, 0x02287, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A99[] = { {"ffllig", 6, 0x0FB04, 0}, {"smt", 3, 0x02AAA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A9A[] = { {"twoheadrightarrow", 17, 0x021A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A9D[] = { {"ecaron", 6, 0x0011B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_A9F[] = { {"NotRightTriangleBar", 19, 0x029D0, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AA3[] = { {"apid", 4, 0x0224B, 0}, {"vscr", 4, 0x1D4CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AA4[] = { {"supdot", 6, 0x02ABE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AA5[] = { {"colone", 6, 0x02254, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AA7[] = { {"dwangle", 7, 0x029A6, 0}, {"shchcy", 6, 0x00449, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AAC[] = { {"ltdot", 5, 0x022D6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AB2[] = { {"downharpoonright", 16, 0x021C2, 0}, {"gjcy", 4, 0x00453, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AB4[] = { {"wfr", 3, 0x1D534, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AB5[] = { {"rfisht", 6, 0x0297D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ABA[] = { {"Ycy", 3, 0x0042B, 0}, {"swarrow", 7, 0x02199, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AC0[] = { {"nharr", 5, 0x021AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AC4[] = { {"frac12", 6, 0x000BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AC5[] = { {"frac13", 6, 0x02153, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AC6[] = { {"frac14", 6, 0x000BC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AC7[] = { {"GreaterEqual", 12, 0x02265, 0}, {"frac15", 6, 0x02155, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AC8[] = { {"Gamma", 5, 0x00393, 0}, {"frac16", 6, 0x02159, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ACA[] = { {"dzigrarr", 8, 0x027FF, 0}, {"frac18", 6, 0x0215B, 0}, {"rcaron", 6, 0x00159, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ACC[] = { {"DownRightTeeVector", 18, 0x0295F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ACF[] = { {"nvrtrie", 7, 0x022B5, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AD2[] = { {"iota", 4, 0x003B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AD3[] = { {"sol", 3, 0x0002F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AD4[] = { {"rbrace", 6, 0x0007D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ADA[] = { {"rbrack", 6, 0x0005D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ADD[] = { {"rsqb", 4, 0x0005D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ADF[] = { {"oint", 4, 0x0222E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AE4[] = { {"Wscr", 4, 0x1D4B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AE5[] = { {"hfr", 3, 0x1D525, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AE6[] = { {"frac23", 6, 0x02154, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AE7[] = { {"dlcorn", 6, 0x0231E, 0}, {"verbar", 6, 0x0007C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AE8[] = { {"frac25", 6, 0x02156, 0}, {"gamma", 5, 0x003B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AE9[] = { {"nVDash", 6, 0x022AF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AEB[] = { {"Jcy", 3, 0x00419, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AF5[] = { {"nwarrow", 7, 0x02196, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AF6[] = { {"OverBar", 7, 0x0203E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AF7[] = { {"rightsquigarrow", 15, 0x0219D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AFA[] = { {"iexcl", 5, 0x000A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AFD[] = { {"sqcap", 5, 0x02293, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_AFE[] = { {"pertenk", 7, 0x02031, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B08[] = { {"PrecedesEqual", 13, 0x02AAF, 0}, {"frac34", 6, 0x000BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B09[] = { {"Therefore", 9, 0x02234, 0}, {"frac35", 6, 0x02157, 0}, {"nvDash", 6, 0x022AD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B0A[] = { {"odsold", 6, 0x029BC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B0C[] = { {"dot", 3, 0x002D9, 0}, {"frac38", 6, 0x0215C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B10[] = { {"sqcaps", 6, 0x02293, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B11[] = { {"ZeroWidthSpace", 14, 0x0200B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B15[] = { {"rarrfs", 6, 0x0291E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B16[] = { {"Yfr", 3, 0x1D51C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B1E[] = { {"CircleDot", 9, 0x02299, 0}, {"gtcir", 5, 0x02A7A, 0}, {"squ", 3, 0x025A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B1F[] = { {"angmsd", 6, 0x02221, 0}, {"nsubseteq", 9, 0x02288, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B23[] = { {"iprod", 5, 0x02A3C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B24[] = { {"bprime", 6, 0x02035, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B27[] = { {"supsub", 6, 0x02AD4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B29[] = { {"SquareSupersetEqual", 19, 0x02292, 0}, {"therefore", 9, 0x02234, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B2A[] = { {"frac45", 6, 0x02158, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B2B[] = { {"Aopf", 4, 0x1D538, 0}, {"NotGreaterFullEqual", 19, 0x02267, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B2C[] = { {"Tstrok", 6, 0x00166, 0}, {"rightleftarrows", 15, 0x021C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B2D[] = { {"Fouriertrf", 10, 0x02131, 0}, {"epar", 4, 0x022D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B2E[] = { {"omid", 4, 0x029B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B2F[] = { {"OpenCurlyDoubleQuote", 20, 0x0201C, 0}, {"dagger", 6, 0x02020, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B33[] = { {"semi", 4, 0x0003B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B35[] = { {"supsup", 6, 0x02AD6, 0}, {"zeetrf", 6, 0x02128, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B36[] = { {"DifferentialD", 13, 0x02146, 0}, {"topcir", 6, 0x02AF1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B3A[] = { {"mscr", 4, 0x1D4C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B3D[] = { {"Wcirc", 5, 0x00174, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B3E[] = { {"boxdL", 5, 0x02555, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B40[] = { {"Gbreve", 6, 0x0011E, 0}, {"vopf", 4, 0x1D567, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B42[] = { {"lap", 3, 0x02A85, 0}, {"llarr", 5, 0x021C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B44[] = { {"boxdR", 5, 0x02552, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B46[] = { {"RightAngleBracket", 17, 0x027E9, 0}, {"lat", 3, 0x02AAB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B47[] = { {"Jfr", 3, 0x1D50D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B4C[] = { {"frac56", 6, 0x0215A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B4E[] = { {"frac58", 6, 0x0215D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B4F[] = { {"rarrhk", 6, 0x021AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B50[] = { {"lesdot", 6, 0x02A7F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B51[] = { {"ApplyFunction", 13, 0x02061, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B52[] = { {"NotGreaterTilde", 15, 0x02275, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B53[] = { {"Cedilla", 7, 0x000B8, 0}, {"curvearrowright", 15, 0x021B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B56[] = { {"rdsh", 4, 0x021B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B58[] = { {"larrb", 5, 0x021E4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B5C[] = { {"vrtri", 5, 0x022B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B5D[] = { {"nequiv", 6, 0x02262, 0}, {"wcirc", 5, 0x00175, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B5E[] = { {"boxdl", 5, 0x02510, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B63[] = { {"DoubleDownArrow", 15, 0x021D3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B64[] = { {"boxdr", 5, 0x0250C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B67[] = { {"pluscir", 7, 0x02A22, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B69[] = { {"longmapsto", 10, 0x027FC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B6B[] = { {"gnap", 4, 0x02A8A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B6D[] = { {"bigodot", 7, 0x02A00, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B72[] = { {"thickapprox", 11, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B73[] = { {"DotDot", 6, 0x020DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B77[] = { {"incare", 6, 0x02105, 0}, {"rarrbfs", 7, 0x02920, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B78[] = { {"apos", 4, 0x00027, 0}, {"tbrk", 4, 0x023B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B7A[] = { {"grave", 5, 0x00060, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B7B[] = { {"Nscr", 4, 0x1D4A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B7E[] = { {"rangle", 6, 0x027E9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B7F[] = { {"uArr", 4, 0x021D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B81[] = { {"Wopf", 4, 0x1D54E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B82[] = { {"doteq", 5, 0x02250, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B87[] = { {"times", 5, 0x000D7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B8D[] = { {"fflig", 5, 0x0FB00, 0}, {"lcy", 3, 0x0043B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B8F[] = { {"sub", 3, 0x02282, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B90[] = { {"frac78", 6, 0x0215E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B94[] = { {"xrarr", 5, 0x027F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B98[] = { {"UpArrowDownArrow", 16, 0x021C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B99[] = { {"bbrktbrk", 8, 0x023B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B9A[] = { {"abreve", 6, 0x00103, 0}, {"lsaquo", 6, 0x02039, 0}, {"sum", 3, 0x02211, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B9C[] = { {"Eacute", 6, 0x000C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_B9D[] = { {"sup", 3, 0x02283, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BA5[] = { {"ContourIntegral", 15, 0x0222E, 0}, {"DiacriticalDot", 14, 0x002D9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BA9[] = { {"trisb", 5, 0x029CD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BAE[] = { {"Hcirc", 5, 0x00124, 0}, {"lceil", 5, 0x02308, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BB2[] = { {"Zcaron", 6, 0x0017D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BB5[] = { {"looparrowleft", 13, 0x021AB, 0}, {"oelig", 5, 0x00153, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BB6[] = { {"LessSlantEqual", 14, 0x02A7D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BB7[] = { {"NegativeThinSpace", 17, 0x0200B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BBA[] = { {"boxhD", 5, 0x02565, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BBC[] = { {"omicron", 7, 0x003BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BBD[] = { {"leg", 3, 0x022DA, 0}, {"rightthreetimes", 15, 0x022CC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BBF[] = { {"NotSucceedsSlantEqual", 21, 0x022E1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC1[] = { {"angmsdaa", 8, 0x029A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC2[] = { {"angmsdab", 8, 0x029A9, 0}, {"rAtail", 6, 0x0291C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC3[] = { {"angmsdac", 8, 0x029AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC4[] = { {"angmsdad", 8, 0x029AB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC5[] = { {"angmsdae", 8, 0x029AC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC6[] = { {"angmsdaf", 8, 0x029AD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC7[] = { {"angmsdag", 8, 0x029AE, 0}, {"leq", 3, 0x02264, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC8[] = { {"angmsdah", 8, 0x029AF, 0}, {"solbar", 6, 0x0233F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BC9[] = { {"Racute", 6, 0x00154, 0}, {"les", 3, 0x02A7D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BCB[] = { {"boxhU", 5, 0x02568, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BCE[] = { {"hcirc", 5, 0x00125, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BD1[] = { {"dscr", 4, 0x1D4B9, 0}, {"smashp", 6, 0x02A33, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BD7[] = { {"mopf", 4, 0x1D55E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BD8[] = { {"Rcedil", 6, 0x00156, 0}, {"dscy", 4, 0x00455, 0}, {"prap", 4, 0x02AB7, 0}, {"rarrlp", 6, 0x021AC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BD9[] = { {"Aogon", 5, 0x00104, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BDA[] = { {"boxhd", 5, 0x0252C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BDB[] = { {"subset", 6, 0x02282, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BDD[] = { {"lgE", 3, 0x02A91, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BDF[] = { {"epsilon", 7, 0x003B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BE1[] = { {"curarrm", 7, 0x0293C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BE2[] = { {"ratail", 6, 0x0291A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BE4[] = { {"DoubleLongLeftRightArrow", 24, 0x027FA, 0}, {"rhov", 4, 0x003F1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BE7[] = { {"LeftDoubleBracket", 17, 0x027E6, 0}, {"Lleftarrow", 10, 0x021DA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BE8[] = { {"Uuml", 4, 0x000DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BE9[] = { {"lfr", 3, 0x1D529, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BEA[] = { {"minusdu", 7, 0x02A2A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BEB[] = { {"boxhu", 5, 0x02534, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BEF[] = { {"Ncy", 3, 0x0041D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BF0[] = { {"gneq", 4, 0x02A88, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BF1[] = { {"rangd", 5, 0x02992, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BF2[] = { {"range", 5, 0x029A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BF3[] = { {"lfloor", 6, 0x0230A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BF7[] = { {"NotSucceedsTilde", 16, 0x0227F, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BF9[] = { {"aogon", 5, 0x00105, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BFA[] = { {"NotGreaterSlantEqual", 20, 0x02A7E, 0x00338}, {"NotSquareSupersetEqual", 22, 0x022E3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_BFC[] = { {"profsurf", 8, 0x02313, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C02[] = { {"wedgeq", 6, 0x02259, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C0B[] = { {"Alpha", 5, 0x00391, 0}, {"DiacriticalDoubleAcute", 22, 0x002DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C0C[] = { {"lltri", 5, 0x025FA, 0}, {"tcaron", 6, 0x00165, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C11[] = { {"Imacr", 5, 0x0012A, 0}, {"subseteq", 8, 0x02286, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C12[] = { {"Escr", 4, 0x02130, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C16[] = { {"lArr", 4, 0x021D0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C18[] = { {"Nopf", 4, 0x02115, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C1A[] = { {"rpar", 4, 0x00029, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C1D[] = { {"divonx", 6, 0x022C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C1E[] = { {"olcir", 5, 0x029BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C23[] = { {"lacute", 6, 0x0013A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C27[] = { {"zscr", 4, 0x1D4CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C2B[] = { {"alpha", 5, 0x003B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C31[] = { {"imacr", 5, 0x0012B, 0}, {"vellip", 6, 0x022EE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C32[] = { {"lcedil", 6, 0x0013C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C33[] = { {"sime", 4, 0x02243, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C34[] = { {"empty", 5, 0x02205, 0}, {"imped", 5, 0x001B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C35[] = { {"simg", 4, 0x02A9E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C36[] = { {"kjcy", 4, 0x0045C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C3A[] = { {"siml", 4, 0x02A9D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C3E[] = { {"LessEqualGreater", 16, 0x022DA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C3F[] = { {"Ycirc", 5, 0x00176, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C40[] = { {"RoundImplies", 12, 0x02970, 0}, {"nvrArr", 6, 0x02903, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C43[] = { {"check", 5, 0x02713, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C44[] = { {"nlarr", 5, 0x0219A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C46[] = { {"middot", 6, 0x000B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C48[] = { {"par", 3, 0x02225, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C4A[] = { {"NotGreaterGreater", 17, 0x0226B, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C4B[] = { {"Nfr", 3, 0x1D511, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C4F[] = { {"nwArr", 5, 0x021D6, 0}, {"prec", 4, 0x0227A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C50[] = { {"Barv", 4, 0x02AE7, 0}, {"yacute", 6, 0x000FD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C54[] = { {"DoubleLeftRightArrow", 20, 0x021D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C58[] = { {"Coproduct", 9, 0x02210, 0}, {"rarrpl", 6, 0x02945, 0}, {"subsim", 6, 0x02AC7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C5A[] = { {"ntgl", 4, 0x02279, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C5B[] = { {"LeftTriangleBar", 15, 0x029CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C5F[] = { {"ycirc", 5, 0x00177, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C69[] = { {"doteqdot", 8, 0x02251, 0}, {"nang", 4, 0x02220, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C6B[] = { {"bigcap", 6, 0x022C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C6C[] = { {"CHcy", 4, 0x00427, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C6E[] = { {"dopf", 4, 0x1D555, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C72[] = { {"inodot", 6, 0x00131, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C76[] = { {"nvHarr", 6, 0x02904, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C77[] = { {"laemptyv", 8, 0x029B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C78[] = { {"bigcirc", 7, 0x025EF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C7A[] = { {"scnap", 5, 0x02ABA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C7B[] = { {"DownLeftVector", 14, 0x021BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C80[] = { {"race", 4, 0x0223D, 0x00331}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C82[] = { {"vartriangleright", 16, 0x022B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C89[] = { {"napE", 4, 0x02A70, 0x00338}, {"supedot", 7, 0x02AC4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C8E[] = { {"acE", 3, 0x0223E, 0x00333}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C91[] = { {"pcy", 3, 0x0043F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C93[] = { {"qprime", 6, 0x02057, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C94[] = { {"RightTeeVector", 14, 0x0295B, 0}, {"curlyvee", 8, 0x022CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C95[] = { {"swarhk", 6, 0x02926, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_C98[] = { {"Atilde", 6, 0x000C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CA6[] = { {"bbrk", 4, 0x023B5, 0}, {"prnap", 5, 0x02AB9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CA8[] = { {"image", 5, 0x02111, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CA9[] = { {"sext", 4, 0x02736, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CAA[] = { {"ldquo", 5, 0x0201C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CAC[] = { {"NotLeftTriangleBar", 18, 0x029CF, 0x00338}, {"epsiv", 5, 0x003F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CAD[] = { {"CenterDot", 9, 0x000B7, 0}, {"acd", 3, 0x0223F, 0}, {"upuparrows", 10, 0x021C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CAF[] = { {"Eopf", 4, 0x1D53C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CB0[] = { {"Jcirc", 5, 0x00134, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CB2[] = { {"smid", 4, 0x02223, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CB4[] = { {"bull", 4, 0x02022, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CB6[] = { {"rhard", 5, 0x021C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CB7[] = { {"nsupset", 7, 0x02283, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CBA[] = { {"npre", 4, 0x02AAF, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CBE[] = { {"qscr", 4, 0x1D4C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CC2[] = { {"acy", 3, 0x00430, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CC4[] = { {"lnE", 3, 0x02268, 0}, {"zopf", 4, 0x1D56B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CC5[] = { {"Ntilde", 6, 0x000D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CC7[] = { {"rharu", 5, 0x021C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CC8[] = { {"kappav", 6, 0x003F0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CC9[] = { {"timesb", 6, 0x022A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CCB[] = { {"iiiint", 6, 0x02A0C, 0}, {"timesd", 6, 0x02A30, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CD0[] = { {"jcirc", 5, 0x00135, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CD2[] = { {"nsimeq", 6, 0x02244, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CD3[] = { {"Esim", 4, 0x02A73, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CD9[] = { {"Cap", 3, 0x022D2, 0}, {"bump", 4, 0x0224E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CDA[] = { {"lvnE", 4, 0x02268, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CDC[] = { {"rarrtl", 6, 0x021A3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CE4[] = { {"lne", 3, 0x02A87, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CE6[] = { {"commat", 6, 0x00040, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CE8[] = { {"hslash", 6, 0x0210F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CE9[] = { {"lthree", 6, 0x022CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CED[] = { {"Gcedil", 6, 0x00122, 0}, {"pfr", 3, 0x1D52D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CF1[] = { {"RightTriangleEqual", 18, 0x022B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CF2[] = { {"ngeqslant", 9, 0x02A7E, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CF3[] = { {"Rcy", 3, 0x00420, 0}, {"gimel", 5, 0x02137, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CF4[] = { {"curarr", 6, 0x021B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CFA[] = { {"ntlg", 4, 0x02278, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_CFF[] = { {"Rscr", 4, 0x0211B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D00[] = { {"urcrop", 6, 0x0230E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D06[] = { {"Poincareplane", 13, 0x0210C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D07[] = { {"NoBreak", 7, 0x02060, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D0B[] = { {"lcub", 4, 0x0007B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D0E[] = { {"nltri", 5, 0x022EA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D10[] = { {"blacktriangledown", 17, 0x025BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D11[] = { {"fjlig", 5, 0x00066, 0x0006A}, {"percnt", 6, 0x00025, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D12[] = { {"rightharpoondown", 16, 0x021C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D13[] = { {"LeftAngleBracket", 16, 0x027E8, 0}, {"npreceq", 7, 0x02AAF, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D15[] = { {"cupcup", 6, 0x02A4A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D18[] = { {"LeftVectorBar", 13, 0x02952, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D19[] = { {"NJcy", 4, 0x0040A, 0}, {"triangleright", 13, 0x025B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D1A[] = { {"Tcedil", 6, 0x00162, 0}, {"loz", 3, 0x025CA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D1E[] = { {"afr", 3, 0x1D51E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D1F[] = { {"NotLessTilde", 12, 0x02274, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D20[] = { {"NotElement", 10, 0x02209, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D22[] = { {"NotHumpDownHump", 15, 0x0224E, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D24[] = { {"SquareSubsetEqual", 17, 0x02291, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D26[] = { {"nleqq", 5, 0x02266, 0x00338}, {"phi", 3, 0x003C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D2A[] = { {"NotRightTriangle", 16, 0x022EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D32[] = { {"lhblk", 5, 0x02584, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D34[] = { {"caret", 5, 0x02041, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D35[] = { {"bsemi", 5, 0x0204F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D38[] = { {"aacute", 6, 0x000E1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D39[] = { {"mapsto", 6, 0x021A6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D3A[] = { {"Congruent", 9, 0x02261, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D3B[] = { {"Vdash", 5, 0x022A9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D3E[] = { {"longrightarrow", 14, 0x027F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D42[] = { {"iinfin", 6, 0x029DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D44[] = { {"EmptyVerySmallSquare", 20, 0x025AB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D49[] = { {"real", 4, 0x0211C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D4C[] = { {"SucceedsEqual", 13, 0x02AB0, 0}, {"utilde", 6, 0x00169, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D4F[] = { {"Rfr", 3, 0x0211C, 0}, {"tau", 3, 0x003C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D51[] = { {"Wedge", 5, 0x022C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D54[] = { {"piv", 3, 0x003D6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D55[] = { {"hscr", 4, 0x1D4BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D56[] = { {"subdot", 6, 0x02ABD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D57[] = { {"dsol", 4, 0x029F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D5A[] = { {"prnE", 4, 0x02AB5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D5B[] = { {"qopf", 4, 0x1D562, 0}, {"vdash", 5, 0x022A2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D5F[] = { {"Star", 4, 0x022C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D63[] = { {"sqsupseteq", 10, 0x02292, 0}, {"zhcy", 4, 0x00436, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D65[] = { {"nacute", 6, 0x00144, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D69[] = { {"lessgtr", 7, 0x02276, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D6A[] = { {"nless", 5, 0x0226E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D6C[] = { {"RightTeeArrow", 13, 0x021A6, 0}, {"Yuml", 4, 0x00178, 0}, {"target", 6, 0x02316, 0}, {"upharpoonleft", 13, 0x021BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D6F[] = { {"between", 7, 0x0226C, 0}, {"boxuL", 5, 0x0255B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D70[] = { {"TSHcy", 5, 0x0040B, 0}, {"lrm", 3, 0x0200E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D71[] = { {"excl", 4, 0x00021, 0}, {"hyphen", 6, 0x02010, 0}, {"mlcp", 4, 0x02ADB, 0}, {"wedge", 5, 0x02227, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D74[] = { {"ncedil", 6, 0x00146, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D75[] = { {"boxuR", 5, 0x02558, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D76[] = { {"Not", 3, 0x02AEC, 0}, {"epsi", 4, 0x003B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D7C[] = { {"disin", 5, 0x022F2, 0}, {"nRightarrow", 11, 0x021CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D7D[] = { {"cylcty", 6, 0x0232D, 0}, {"neArr", 5, 0x021D7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D7E[] = { {"prnsim", 6, 0x022E8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D80[] = { {"Cfr", 3, 0x0212D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D81[] = { {"Beta", 4, 0x00392, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D85[] = { {"leftarrowtail", 13, 0x021A2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D87[] = { {"parsl", 5, 0x02AFD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D89[] = { {"xwedge", 6, 0x022C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D8A[] = { {"olcross", 7, 0x029BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D8C[] = { {"boxvH", 5, 0x0256A, 0}, {"lsh", 3, 0x021B0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D8D[] = { {"circledR", 8, 0x000AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D8E[] = { {"Rho", 3, 0x003A1, 0}, {"circledS", 8, 0x024C8, 0}, {"cupor", 5, 0x02A45, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D8F[] = { {"Ugrave", 6, 0x000D9, 0}, {"boxul", 5, 0x02518, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D90[] = { {"boxvL", 5, 0x02561, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D91[] = { {"sqcup", 5, 0x02294, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D93[] = { {"rect", 4, 0x025AD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D94[] = { {"mldr", 4, 0x02026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D95[] = { {"boxur", 5, 0x02514, 0}, {"digamma", 7, 0x003DD, 0}, {"tcy", 3, 0x00442, 0}, {"urcorner", 8, 0x0231D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D96[] = { {"DoubleLeftArrow", 15, 0x021D0, 0}, {"Iscr", 4, 0x02110, 0}, {"boxvR", 5, 0x0255E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D98[] = { {"ulcorn", 6, 0x0231C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D9A[] = { {"prod", 4, 0x0220F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_D9C[] = { {"Ropf", 4, 0x0211D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DA0[] = { {"rmoustache", 10, 0x023B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DA5[] = { {"NegativeMediumSpace", 19, 0x0200B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DA6[] = { {"prop", 4, 0x0221D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DA8[] = { {"TScy", 4, 0x00426, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DA9[] = { {"xsqcup", 6, 0x02A06, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DAC[] = { {"bemptyv", 7, 0x029B0, 0}, {"boxvh", 5, 0x0253C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DB0[] = { {"boxvl", 5, 0x02524, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DB3[] = { {"NotTildeFullEqual", 17, 0x02247, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DB4[] = { {"subE", 4, 0x02AC5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DB6[] = { {"boxvr", 5, 0x0251C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DB7[] = { {"bigvee", 6, 0x022C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DB9[] = { {"Chi", 3, 0x003A7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DBC[] = { {"circeq", 6, 0x02257, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DBE[] = { {"emsp13", 6, 0x02004, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DBF[] = { {"emsp14", 6, 0x02005, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DC2[] = { {"ouml", 4, 0x000F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DC3[] = { {"RightArrowBar", 13, 0x021E5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DC6[] = { {"ecy", 3, 0x0044D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DC8[] = { {"succneqq", 8, 0x02AB6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DCA[] = { {"npart", 5, 0x02202, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DCF[] = { {"Element", 7, 0x02208, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DD1[] = { {"Edot", 4, 0x00116, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DD3[] = { {"RightUpDownVector", 17, 0x0294F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DD4[] = { {"sube", 4, 0x02286, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DD5[] = { {"jsercy", 6, 0x00458, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DD7[] = { {"varrho", 6, 0x003F1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DD9[] = { {"subsub", 6, 0x02AD5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DDC[] = { {"Dcaron", 6, 0x0010E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DDD[] = { {"Eogon", 5, 0x00118, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DE4[] = { {"geqslant", 8, 0x02A7E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DE6[] = { {"rdldhar", 7, 0x02969, 0}, {"zdot", 4, 0x0017C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DE7[] = { {"subsup", 6, 0x02AD3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DE9[] = { {"ograve", 6, 0x000F2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DEB[] = { {"ReverseElement", 14, 0x0220B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DED[] = { {"drcorn", 6, 0x0231F, 0}, {"rang", 4, 0x027E9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DF1[] = { {"tfr", 3, 0x1D531, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DF2[] = { {"hopf", 4, 0x1D559, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DF3[] = { {"succ", 4, 0x0227B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DF6[] = { {"otimes", 6, 0x02297, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DF7[] = { {"Vcy", 3, 0x00412, 0}, {"ltquest", 7, 0x02A7B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DF9[] = { {"lozenge", 7, 0x025CA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DFB[] = { {"LeftDownVector", 14, 0x021C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_DFD[] = { {"eogon", 5, 0x00119, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E03[] = { {"amp", 3, 0x00026, 0}, {"lopar", 5, 0x02985, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E04[] = { {"loplus", 6, 0x02A2D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E08[] = { {"NotTilde", 8, 0x02241, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E09[] = { {"CounterClockwiseContourIntegral", 31, 0x02233, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E0C[] = { {"InvisibleTimes", 14, 0x02062, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E11[] = { {"lesdotor", 8, 0x02A83, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E18[] = { {"and", 3, 0x02227, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E1B[] = { {"RightUpVector", 13, 0x021BE, 0}, {"ang", 3, 0x02220, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E1C[] = { {"DoubleRightTee", 14, 0x022A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E1D[] = { {"LeftUpVectorBar", 15, 0x02958, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E1E[] = { {"smte", 4, 0x02AAC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E20[] = { {"Iacute", 6, 0x000CD, 0}, {"triminus", 8, 0x02A3A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E22[] = { {"efr", 3, 0x1D522, 0}, {"iiint", 5, 0x0222D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E23[] = { {"ctdot", 5, 0x022EF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E24[] = { {"mnplus", 6, 0x02213, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E25[] = { {"Vee", 3, 0x022C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E28[] = { {"Gcy", 3, 0x00413, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E2A[] = { {"lurdshar", 8, 0x0294A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E2C[] = { {"smeparsl", 8, 0x029E4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E2F[] = { {"DoubleVerticalBar", 17, 0x02225, 0}, {"iecy", 4, 0x00435, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E30[] = { {"udblac", 6, 0x00171, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E32[] = { {"gtquest", 7, 0x02A7C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E33[] = { {"Iopf", 4, 0x1D540, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E35[] = { {"bsime", 5, 0x022CD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E36[] = { {"RightVector", 11, 0x021C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E37[] = { {"NotGreaterLess", 14, 0x02279, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E3B[] = { {"apE", 3, 0x02A70, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E41[] = { {"CupCap", 6, 0x0224D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E42[] = { {"uscr", 4, 0x1D4CA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E43[] = { {"erDot", 5, 0x02253, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E44[] = { {"egs", 3, 0x02A96, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E48[] = { {"rlarr", 5, 0x021C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E4C[] = { {"prE", 3, 0x02AB3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E4E[] = { {"QUOT", 4, 0x00022, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E53[] = { {"Vfr", 3, 0x1D519, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E55[] = { {"cupbrcap", 8, 0x02A48, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E57[] = { {"intercal", 8, 0x022BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E58[] = { {"imath", 5, 0x00131, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E59[] = { {"RightUpTeeVector", 16, 0x0295C, 0}, {"trie", 4, 0x0225C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E5B[] = { {"ape", 3, 0x0224A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E5D[] = { {"softcy", 6, 0x0044C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E5E[] = { {"rarrb", 5, 0x021E5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E5F[] = { {"FilledSmallSquare", 17, 0x025FC, 0}, {"rarrc", 5, 0x02933, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E60[] = { {"Superset", 8, 0x02283, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E61[] = { {"hoarr", 5, 0x021FF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E63[] = { {"DownRightVectorBar", 18, 0x02957, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E64[] = { {"brvbar", 6, 0x000A6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E65[] = { {"ecolon", 6, 0x02255, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E66[] = { {"GreaterLess", 11, 0x02277, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E6A[] = { {"nrArr", 5, 0x021CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E6C[] = { {"pre", 3, 0x02AAF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E6F[] = { {"aleph", 5, 0x02135, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E70[] = { {"DiacriticalAcute", 16, 0x000B4, 0}, {"SmallCircle", 11, 0x02218, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E71[] = { {"parsim", 6, 0x02AF3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E73[] = { {"rarrw", 5, 0x0219D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E78[] = { {"caron", 5, 0x002C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E7A[] = { {"cacute", 6, 0x00107, 0}, {"lagran", 6, 0x02112, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E7C[] = { {"rarr", 4, 0x02192, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E80[] = { {"Rrightarrow", 11, 0x021DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E83[] = { {"Vscr", 4, 0x1D4B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E84[] = { {"Gfr", 3, 0x1D50A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E89[] = { {"ccedil", 6, 0x000E7, 0}, {"propto", 6, 0x0221D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E8E[] = { {"zwnj", 4, 0x0200C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E91[] = { {"psi", 3, 0x003C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E99[] = { {"infin", 5, 0x0221E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_E9C[] = { {"circledcirc", 11, 0x0229A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EA1[] = { {"Proportion", 10, 0x02237, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EA2[] = { {"subseteqq", 9, 0x02AC5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EA4[] = { {"nGtv", 4, 0x0226B, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EA8[] = { {"macr", 4, 0x000AF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EA9[] = { {"orslope", 7, 0x02A57, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EB1[] = { {"frown", 5, 0x02322, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EB2[] = { {"Iota", 4, 0x00399, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EB4[] = { {"rceil", 5, 0x02309, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EB7[] = { {"spadesuit", 9, 0x02660, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EB8[] = { {"sstarf", 6, 0x022C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ECA[] = { {"icy", 3, 0x00438, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ECD[] = { {"ast", 3, 0x0002A, 0}, {"nmid", 4, 0x02224, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ECF[] = { {"bowtie", 6, 0x022C8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ED1[] = { {"thetav", 6, 0x003D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ED7[] = { {"vangrt", 6, 0x0299C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ED8[] = { {"numsp", 5, 0x02007, 0}, {"triplus", 7, 0x02A39, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_ED9[] = { {"lscr", 4, 0x1D4C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EDA[] = { {"pointint", 8, 0x02A15, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EDB[] = { {"Theta", 5, 0x00398, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EDF[] = { {"rightrightarrows", 16, 0x021C9, 0}, {"uopf", 4, 0x1D566, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EE2[] = { {"ell", 3, 0x02113, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EE4[] = { {"cuepr", 5, 0x022DE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EE5[] = { {"NotVerticalBar", 14, 0x02224, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EE7[] = { {"xnis", 4, 0x022FB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EE9[] = { {"els", 3, 0x02A95, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EEF[] = { {"DDotrahd", 8, 0x02911, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EF1[] = { {"larrbfs", 7, 0x0291F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EF2[] = { {"Rsh", 3, 0x021B1, 0}, {"boxplus", 7, 0x0229E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EF4[] = { {"swarr", 5, 0x02199, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EF5[] = { {"gvnE", 4, 0x02269, 0x0FE00}, {"xfr", 3, 0x1D535, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EF9[] = { {"ldca", 4, 0x02936, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EFB[] = { {"NotPrecedesSlantEqual", 21, 0x022E0, 0}, {"YAcy", 4, 0x0042F, 0}, {"Zcy", 3, 0x00417, 0}, {"andslope", 8, 0x02A58, 0}, {"numero", 6, 0x02116, 0}, {"theta", 5, 0x003B8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EFE[] = { {"mapstoup", 8, 0x021A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_EFF[] = { {"bigcup", 6, 0x022C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F03[] = { {"nesear", 6, 0x02928, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F05[] = { {"lesssim", 7, 0x02272, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F08[] = { {"DownArrow", 9, 0x02193, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F0B[] = { {"orarr", 5, 0x021BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F0F[] = { {"ccaps", 5, 0x02A4D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F10[] = { {"xdtri", 5, 0x025BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F11[] = { {"xcap", 4, 0x022C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F13[] = { {"downdownarrows", 14, 0x021CA, 0}, {"nisd", 4, 0x022FA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F14[] = { {"VerticalBar", 11, 0x02223, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F15[] = { {"TRADE", 5, 0x02122, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F17[] = { {"Omacr", 5, 0x0014C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F18[] = { {"top", 3, 0x022A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F19[] = { {"LeftRightArrow", 14, 0x02194, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F1A[] = { {"Mscr", 4, 0x02133, 0}, {"iff", 3, 0x021D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F1F[] = { {"downharpoonleft", 15, 0x021C3, 0}, {"eng", 3, 0x0014B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F20[] = { {"Vopf", 4, 0x1D54D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F26[] = { {"ifr", 3, 0x1D526, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F28[] = { {"Downarrow", 9, 0x021D3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F2C[] = { {"Kcy", 3, 0x0041A, 0}, {"angle", 5, 0x02220, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F2F[] = { {"lescc", 5, 0x02AA8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F30[] = { {"lesseqqgtr", 10, 0x02A8B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F31[] = { {"bigstar", 7, 0x02605, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F33[] = { {"ddagger", 7, 0x02021, 0}, {"nltrie", 6, 0x022EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F37[] = { {"omacr", 5, 0x0014D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F38[] = { {"cuesc", 5, 0x022DF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F40[] = { {"circlearrowright", 16, 0x021BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F41[] = { {"ngeqq", 5, 0x02267, 0x00338}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F44[] = { {"squf", 4, 0x025AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F46[] = { {"rtri", 4, 0x025B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F47[] = { {"VerticalLine", 12, 0x0007C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F48[] = { {"downarrow", 9, 0x02193, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F4B[] = { {"Scaron", 6, 0x00160, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F4C[] = { {"tstrok", 6, 0x00167, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F50[] = { {"wreath", 6, 0x02240, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F51[] = { {"exponentiale", 12, 0x02147, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F55[] = { {"Idot", 4, 0x00130, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F57[] = { {"Zfr", 3, 0x02128, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F58[] = { {"bnot", 4, 0x02310, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F5B[] = { {"infintie", 8, 0x029DD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F5D[] = { {"angrtvbd", 8, 0x0299D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F5F[] = { {"prurel", 6, 0x022B0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F60[] = { {"gbreve", 6, 0x0011F, 0}, {"rsaquo", 6, 0x0203A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F62[] = { {"sung", 4, 0x0266A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F67[] = { {"lvertneqq", 9, 0x02268, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F68[] = { {"lnsim", 5, 0x022E6, 0}, {"searrow", 7, 0x02198, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F69[] = { {"nsubset", 7, 0x02282, 0x020D2}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F6D[] = { {"Cup", 3, 0x022D3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F6E[] = { {"Lmidot", 6, 0x0013F, 0}, {"sup1", 4, 0x000B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F6F[] = { {"Delta", 5, 0x00394, 0}, {"sbquo", 5, 0x0201A, 0}, {"sup2", 4, 0x000B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F70[] = { {"cscr", 4, 0x1D4B8, 0}, {"nsubseteqq", 10, 0x02AC5, 0x00338}, {"sup3", 4, 0x000B3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F71[] = { {"Kcedil", 6, 0x00136, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F72[] = { {"plussim", 7, 0x02A26, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F74[] = { {"KHcy", 4, 0x00425, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F75[] = { {"OElig", 5, 0x00152, 0}, {"simdot", 6, 0x02A6A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F76[] = { {"lopf", 4, 0x1D55D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F77[] = { {"boxbox", 6, 0x029C9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F78[] = { {"bepsi", 5, 0x003F6, 0}, {"lbarr", 5, 0x0290C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F79[] = { {"lnapprox", 8, 0x02A89, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F81[] = { {"sdotb", 5, 0x022A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F82[] = { {"measuredangle", 13, 0x02221, 0}, {"supE", 4, 0x02AC6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F83[] = { {"map", 3, 0x021A6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F84[] = { {"sdote", 5, 0x02A66, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F86[] = { {"diamondsuit", 11, 0x02666, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F88[] = { {"Kfr", 3, 0x1D50E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F8B[] = { {"imagline", 8, 0x02110, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F8F[] = { {"delta", 5, 0x003B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F91[] = { {"mapstodown", 10, 0x021A7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F93[] = { {"eqvparsl", 8, 0x029E5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F95[] = { {"UpArrow", 7, 0x02191, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F9A[] = { {"imagpart", 8, 0x02111, 0}, {"lsim", 4, 0x02272, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F9C[] = { {"trianglelefteq", 14, 0x022B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_F9F[] = { {"isindot", 7, 0x022F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FA0[] = { {"LeftUpDownVector", 16, 0x02951, 0}, {"curvearrowleft", 14, 0x021B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FA1[] = { {"Diamond", 7, 0x022C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FA2[] = { {"supe", 4, 0x02287, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FA3[] = { {"nearrow", 7, 0x02197, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FA9[] = { {"easter", 6, 0x02A6E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB0[] = { {"rdquo", 5, 0x0201D, 0}, {"subsetneqq", 10, 0x02ACB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB1[] = { {"Dscr", 4, 0x1D49F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB4[] = { {"comp", 4, 0x02201, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB5[] = { {"Uparrow", 7, 0x021D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB6[] = { {"coloneq", 7, 0x02254, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB7[] = { {"Mopf", 4, 0x1D544, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FB9[] = { {"rfloor", 6, 0x0230B, 0}, {"varsubsetneqq", 13, 0x02ACB, 0x0FE00}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FBC[] = { {"eacute", 6, 0x000E9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FC2[] = { {"shortparallel", 13, 0x02225, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FC4[] = { {"male", 4, 0x02642, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FC6[] = { {"yscr", 4, 0x1D4CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FCA[] = { {"xharr", 5, 0x027F7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FCC[] = { {"cong", 4, 0x02245, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FCE[] = { {"mcy", 3, 0x0043C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FCF[] = { {"Upsilon", 7, 0x003A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FD0[] = { {"block", 5, 0x02588, 0}, {"maltese", 7, 0x02720, 0}, {"ordf", 4, 0x000AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FD2[] = { {"zcaron", 6, 0x0017E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FD3[] = { {"malt", 4, 0x02720, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FD6[] = { {"loang", 5, 0x027EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FD7[] = { {"ordm", 4, 0x000BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FDD[] = { {"NegativeVeryThinSpace", 21, 0x0200B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FDF[] = { {"eta", 3, 0x003B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FE1[] = { {"Iogon", 5, 0x0012E, 0}, {"drbkarow", 8, 0x02910, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FE6[] = { {"eth", 3, 0x000F0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FE9[] = { {"racute", 6, 0x00155, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FEA[] = { {"cwconint", 8, 0x02232, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FEB[] = { {"egsdot", 6, 0x02A98, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FF5[] = { {"MinusPlus", 9, 0x02213, 0}, {"ring", 4, 0x002DA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FF8[] = { {"rcedil", 6, 0x00157, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FFC[] = { {"timesbar", 8, 0x02A31, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html5_FFE[] = { {"GreaterEqualLess", 16, 0x022DB, 0}, {NULL, 0, 0, 0} };
+
+static const entity_cp_map *const ht_buckets_html5[] = {
+ ht_bucket_html5_000, ht_bucket_html5_001, ht_bucket_empty, ht_bucket_html5_003,
+ ht_bucket_empty, ht_bucket_html5_005, ht_bucket_empty, ht_bucket_html5_007,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_00D, ht_bucket_empty, ht_bucket_html5_00F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_017,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_020, ht_bucket_empty, ht_bucket_html5_022, ht_bucket_empty,
+ ht_bucket_html5_024, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_027,
+ ht_bucket_html5_028, ht_bucket_html5_029, ht_bucket_html5_02A, ht_bucket_html5_02B,
+ ht_bucket_html5_02C, ht_bucket_empty, ht_bucket_html5_02E, ht_bucket_empty,
+ ht_bucket_html5_030, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_034, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_038, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_040, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_047,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_04C, ht_bucket_empty, ht_bucket_html5_04E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_051, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_059, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_05D, ht_bucket_empty, ht_bucket_html5_05F,
+ ht_bucket_html5_060, ht_bucket_html5_061, ht_bucket_empty, ht_bucket_html5_063,
+ ht_bucket_html5_064, ht_bucket_html5_065, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_069, ht_bucket_html5_06A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_06D, ht_bucket_html5_06E, ht_bucket_html5_06F,
+ ht_bucket_empty, ht_bucket_html5_071, ht_bucket_empty, ht_bucket_html5_073,
+ ht_bucket_html5_074, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_07A, ht_bucket_html5_07B,
+ ht_bucket_html5_07C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_07F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_082, ht_bucket_empty,
+ ht_bucket_html5_084, ht_bucket_html5_085, ht_bucket_html5_086, ht_bucket_empty,
+ ht_bucket_html5_088, ht_bucket_html5_089, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_08C, ht_bucket_empty, ht_bucket_html5_08E, ht_bucket_empty,
+ ht_bucket_html5_090, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_094, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_097,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_09E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_0A4, ht_bucket_empty, ht_bucket_html5_0A6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_0AB,
+ ht_bucket_html5_0AC, ht_bucket_html5_0AD, ht_bucket_html5_0AE, ht_bucket_html5_0AF,
+ ht_bucket_html5_0B0, ht_bucket_empty, ht_bucket_html5_0B2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_0B8, ht_bucket_html5_0B9, ht_bucket_html5_0BA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_0C0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_0C4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_0CE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_0D1, ht_bucket_html5_0D2, ht_bucket_html5_0D3,
+ ht_bucket_empty, ht_bucket_html5_0D5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_0DF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_0E5, ht_bucket_html5_0E6, ht_bucket_empty,
+ ht_bucket_html5_0E8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_0EC, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_0EF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_0F3,
+ ht_bucket_html5_0F4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_0FA, ht_bucket_html5_0FB,
+ ht_bucket_empty, ht_bucket_html5_0FD, ht_bucket_html5_0FE, ht_bucket_empty,
+ ht_bucket_html5_100, ht_bucket_html5_101, ht_bucket_empty, ht_bucket_html5_103,
+ ht_bucket_empty, ht_bucket_html5_105, ht_bucket_html5_106, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_109, ht_bucket_html5_10A, ht_bucket_html5_10B,
+ ht_bucket_empty, ht_bucket_html5_10D, ht_bucket_html5_10E, ht_bucket_html5_10F,
+ ht_bucket_html5_110, ht_bucket_html5_111, ht_bucket_empty, ht_bucket_html5_113,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_116, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_11B,
+ ht_bucket_html5_11C, ht_bucket_empty, ht_bucket_html5_11E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_121, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_124, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_129, ht_bucket_html5_12A, ht_bucket_empty,
+ ht_bucket_html5_12C, ht_bucket_empty, ht_bucket_html5_12E, ht_bucket_html5_12F,
+ ht_bucket_html5_130, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_134, ht_bucket_html5_135, ht_bucket_empty, ht_bucket_html5_137,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_13A, ht_bucket_html5_13B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_145, ht_bucket_empty, ht_bucket_html5_147,
+ ht_bucket_empty, ht_bucket_html5_149, ht_bucket_empty, ht_bucket_html5_14B,
+ ht_bucket_html5_14C, ht_bucket_empty, ht_bucket_html5_14E, ht_bucket_html5_14F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_158, ht_bucket_html5_159, ht_bucket_empty, ht_bucket_html5_15B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_15E, ht_bucket_html5_15F,
+ ht_bucket_empty, ht_bucket_html5_161, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_164, ht_bucket_html5_165, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_168, ht_bucket_empty, ht_bucket_html5_16A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_170, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_173,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_17A, ht_bucket_html5_17B,
+ ht_bucket_html5_17C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_17F,
+ ht_bucket_empty, ht_bucket_html5_181, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_189, ht_bucket_empty, ht_bucket_html5_18B,
+ ht_bucket_html5_18C, ht_bucket_empty, ht_bucket_html5_18E, ht_bucket_html5_18F,
+ ht_bucket_html5_190, ht_bucket_html5_191, ht_bucket_empty, ht_bucket_html5_193,
+ ht_bucket_empty, ht_bucket_html5_195, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_19A, ht_bucket_empty,
+ ht_bucket_html5_19C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_19F,
+ ht_bucket_html5_1A0, ht_bucket_html5_1A1, ht_bucket_html5_1A2, ht_bucket_html5_1A3,
+ ht_bucket_html5_1A4, ht_bucket_html5_1A5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_1A8, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_1AB,
+ ht_bucket_html5_1AC, ht_bucket_html5_1AD, ht_bucket_html5_1AE, ht_bucket_html5_1AF,
+ ht_bucket_html5_1B0, ht_bucket_empty, ht_bucket_html5_1B2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_1B5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_1B9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_1BD, ht_bucket_html5_1BE, ht_bucket_empty,
+ ht_bucket_html5_1C0, ht_bucket_html5_1C1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_1C4, ht_bucket_empty, ht_bucket_html5_1C6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_1C9, ht_bucket_html5_1CA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_1CD, ht_bucket_html5_1CE, ht_bucket_empty,
+ ht_bucket_html5_1D0, ht_bucket_html5_1D1, ht_bucket_html5_1D2, ht_bucket_empty,
+ ht_bucket_html5_1D4, ht_bucket_html5_1D5, ht_bucket_html5_1D6, ht_bucket_empty,
+ ht_bucket_html5_1D8, ht_bucket_html5_1D9, ht_bucket_html5_1DA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_1DF,
+ ht_bucket_html5_1E0, ht_bucket_html5_1E1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_1E5, ht_bucket_html5_1E6, ht_bucket_html5_1E7,
+ ht_bucket_html5_1E8, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_1EB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_1EF,
+ ht_bucket_html5_1F0, ht_bucket_empty, ht_bucket_html5_1F2, ht_bucket_empty,
+ ht_bucket_html5_1F4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_1F8, ht_bucket_html5_1F9, ht_bucket_html5_1FA, ht_bucket_empty,
+ ht_bucket_html5_1FC, ht_bucket_empty, ht_bucket_html5_1FE, ht_bucket_html5_1FF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_205, ht_bucket_empty, ht_bucket_html5_207,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_20E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_212, ht_bucket_html5_213,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_219, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_21D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_220, ht_bucket_empty, ht_bucket_html5_222, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_227,
+ ht_bucket_empty, ht_bucket_html5_229, ht_bucket_empty, ht_bucket_html5_22B,
+ ht_bucket_html5_22C, ht_bucket_html5_22D, ht_bucket_empty, ht_bucket_html5_22F,
+ ht_bucket_html5_230, ht_bucket_empty, ht_bucket_html5_232, ht_bucket_empty,
+ ht_bucket_html5_234, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_239, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_23C, ht_bucket_html5_23D, ht_bucket_html5_23E, ht_bucket_empty,
+ ht_bucket_html5_240, ht_bucket_html5_241, ht_bucket_html5_242, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_246, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_249, ht_bucket_html5_24A, ht_bucket_html5_24B,
+ ht_bucket_empty, ht_bucket_html5_24D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_251, ht_bucket_html5_252, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_257,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_25A, ht_bucket_html5_25B,
+ ht_bucket_html5_25C, ht_bucket_html5_25D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_263,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_26A, ht_bucket_html5_26B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_26E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_274, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_277,
+ ht_bucket_html5_278, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_27C, ht_bucket_empty, ht_bucket_html5_27E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_283,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_28A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_294, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_297,
+ ht_bucket_html5_298, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_29D, ht_bucket_empty, ht_bucket_html5_29F,
+ ht_bucket_html5_2A0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_2A9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2AE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_2B1, ht_bucket_html5_2B2, ht_bucket_html5_2B3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_2B9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2BF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_2C4, ht_bucket_html5_2C5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2CE, ht_bucket_html5_2CF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2D3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2DA, ht_bucket_html5_2DB,
+ ht_bucket_html5_2DC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2E3,
+ ht_bucket_html5_2E4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_2EB,
+ ht_bucket_html5_2EC, ht_bucket_empty, ht_bucket_html5_2EE, ht_bucket_empty,
+ ht_bucket_html5_2F0, ht_bucket_empty, ht_bucket_html5_2F2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_2F8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_300, ht_bucket_html5_301, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_304, ht_bucket_html5_305, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_308, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_30B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_30F,
+ ht_bucket_empty, ht_bucket_html5_311, ht_bucket_empty, ht_bucket_html5_313,
+ ht_bucket_empty, ht_bucket_html5_315, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_319, ht_bucket_html5_31A, ht_bucket_html5_31B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_326, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_329, ht_bucket_html5_32A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_32D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_330, ht_bucket_html5_331, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_336, ht_bucket_empty,
+ ht_bucket_html5_338, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_33B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_33F,
+ ht_bucket_html5_340, ht_bucket_html5_341, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_347,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_34D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_350, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_356, ht_bucket_empty,
+ ht_bucket_html5_358, ht_bucket_html5_359, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_35D, ht_bucket_empty, ht_bucket_html5_35F,
+ ht_bucket_empty, ht_bucket_html5_361, ht_bucket_empty, ht_bucket_html5_363,
+ ht_bucket_empty, ht_bucket_html5_365, ht_bucket_empty, ht_bucket_html5_367,
+ ht_bucket_empty, ht_bucket_html5_369, ht_bucket_html5_36A, ht_bucket_html5_36B,
+ ht_bucket_empty, ht_bucket_html5_36D, ht_bucket_html5_36E, ht_bucket_html5_36F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_372, ht_bucket_empty,
+ ht_bucket_html5_374, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_378, ht_bucket_empty, ht_bucket_html5_37A, ht_bucket_empty,
+ ht_bucket_html5_37C, ht_bucket_html5_37D, ht_bucket_html5_37E, ht_bucket_html5_37F,
+ ht_bucket_html5_380, ht_bucket_empty, ht_bucket_html5_382, ht_bucket_html5_383,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_386, ht_bucket_html5_387,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_38A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_38D, ht_bucket_html5_38E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_391, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_394, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_397,
+ ht_bucket_html5_398, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_39C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_39F,
+ ht_bucket_html5_3A0, ht_bucket_html5_3A1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_3A4, ht_bucket_html5_3A5, ht_bucket_html5_3A6, ht_bucket_html5_3A7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_3AC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_3B2, ht_bucket_empty,
+ ht_bucket_html5_3B4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_3BF,
+ ht_bucket_html5_3C0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_3C4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_3C9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_3CD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_3D0, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_3D3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_3D9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_3DE, ht_bucket_empty,
+ ht_bucket_html5_3E0, ht_bucket_html5_3E1, ht_bucket_empty, ht_bucket_html5_3E3,
+ ht_bucket_html5_3E4, ht_bucket_empty, ht_bucket_html5_3E6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_3E9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_3ED, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_3F1, ht_bucket_html5_3F2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_3F7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_3FC, ht_bucket_empty, ht_bucket_html5_3FE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_402, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_405, ht_bucket_empty, ht_bucket_html5_407,
+ ht_bucket_empty, ht_bucket_html5_409, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_40E, ht_bucket_html5_40F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_413,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_41A, ht_bucket_html5_41B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_421, ht_bucket_empty, ht_bucket_html5_423,
+ ht_bucket_html5_424, ht_bucket_html5_425, ht_bucket_html5_426, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_429, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_42C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_42F,
+ ht_bucket_html5_430, ht_bucket_empty, ht_bucket_html5_432, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_436, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_439, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_43C, ht_bucket_html5_43D, ht_bucket_html5_43E, ht_bucket_html5_43F,
+ ht_bucket_html5_440, ht_bucket_html5_441, ht_bucket_empty, ht_bucket_html5_443,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_446, ht_bucket_html5_447,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_44A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_44F,
+ ht_bucket_html5_450, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_454, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_457,
+ ht_bucket_html5_458, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_45D, ht_bucket_empty, ht_bucket_html5_45F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_465, ht_bucket_html5_466, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_469, ht_bucket_html5_46A, ht_bucket_html5_46B,
+ ht_bucket_empty, ht_bucket_html5_46D, ht_bucket_empty, ht_bucket_html5_46F,
+ ht_bucket_html5_470, ht_bucket_html5_471, ht_bucket_html5_472, ht_bucket_html5_473,
+ ht_bucket_empty, ht_bucket_html5_475, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_479, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_47C, ht_bucket_html5_47D, ht_bucket_empty, ht_bucket_html5_47F,
+ ht_bucket_html5_480, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_485, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_488, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_48C, ht_bucket_empty, ht_bucket_html5_48E, ht_bucket_html5_48F,
+ ht_bucket_html5_490, ht_bucket_html5_491, ht_bucket_empty, ht_bucket_html5_493,
+ ht_bucket_empty, ht_bucket_html5_495, ht_bucket_html5_496, ht_bucket_empty,
+ ht_bucket_html5_498, ht_bucket_html5_499, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_49F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4A2, ht_bucket_empty,
+ ht_bucket_html5_4A4, ht_bucket_empty, ht_bucket_html5_4A6, ht_bucket_html5_4A7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4AA, ht_bucket_html5_4AB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4AE, ht_bucket_html5_4AF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4B2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4B6, ht_bucket_empty,
+ ht_bucket_html5_4B8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_4BC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_4C0, ht_bucket_empty, ht_bucket_html5_4C2, ht_bucket_html5_4C3,
+ ht_bucket_html5_4C4, ht_bucket_html5_4C5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_4C8, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4CB,
+ ht_bucket_empty, ht_bucket_html5_4CD, ht_bucket_empty, ht_bucket_html5_4CF,
+ ht_bucket_html5_4D0, ht_bucket_empty, ht_bucket_html5_4D2, ht_bucket_html5_4D3,
+ ht_bucket_html5_4D4, ht_bucket_html5_4D5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_4D8, ht_bucket_empty, ht_bucket_html5_4DA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4DE, ht_bucket_html5_4DF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4E3,
+ ht_bucket_html5_4E4, ht_bucket_empty, ht_bucket_html5_4E6, ht_bucket_html5_4E7,
+ ht_bucket_html5_4E8, ht_bucket_html5_4E9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_4ED, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_4F1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4F7,
+ ht_bucket_empty, ht_bucket_html5_4F9, ht_bucket_empty, ht_bucket_html5_4FB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_4FE, ht_bucket_empty,
+ ht_bucket_html5_500, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_504, ht_bucket_empty, ht_bucket_html5_506, ht_bucket_html5_507,
+ ht_bucket_empty, ht_bucket_html5_509, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_50E, ht_bucket_html5_50F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_513,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_516, ht_bucket_empty,
+ ht_bucket_html5_518, ht_bucket_html5_519, ht_bucket_empty, ht_bucket_html5_51B,
+ ht_bucket_html5_51C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_524, ht_bucket_html5_525, ht_bucket_html5_526, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_52F,
+ ht_bucket_html5_530, ht_bucket_empty, ht_bucket_html5_532, ht_bucket_html5_533,
+ ht_bucket_html5_534, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_53B,
+ ht_bucket_html5_53C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_53F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_542, ht_bucket_html5_543,
+ ht_bucket_empty, ht_bucket_html5_545, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_548, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_54F,
+ ht_bucket_html5_550, ht_bucket_html5_551, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_557,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_55B,
+ ht_bucket_empty, ht_bucket_html5_55D, ht_bucket_empty, ht_bucket_html5_55F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_564, ht_bucket_html5_565, ht_bucket_html5_566, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_56C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_56F,
+ ht_bucket_html5_570, ht_bucket_html5_571, ht_bucket_html5_572, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_575, ht_bucket_html5_576, ht_bucket_html5_577,
+ ht_bucket_html5_578, ht_bucket_empty, ht_bucket_html5_57A, ht_bucket_html5_57B,
+ ht_bucket_html5_57C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_580, ht_bucket_empty, ht_bucket_html5_582, ht_bucket_html5_583,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_586, ht_bucket_empty,
+ ht_bucket_html5_588, ht_bucket_html5_589, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_58D, ht_bucket_html5_58E, ht_bucket_html5_58F,
+ ht_bucket_html5_590, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_595, ht_bucket_html5_596, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_59A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_59D, ht_bucket_empty, ht_bucket_html5_59F,
+ ht_bucket_html5_5A0, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5A3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5A6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_5A9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_5AC, ht_bucket_html5_5AD, ht_bucket_html5_5AE, ht_bucket_empty,
+ ht_bucket_html5_5B0, ht_bucket_html5_5B1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_5B5, ht_bucket_html5_5B6, ht_bucket_html5_5B7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5BB,
+ ht_bucket_html5_5BC, ht_bucket_html5_5BD, ht_bucket_empty, ht_bucket_html5_5BF,
+ ht_bucket_html5_5C0, ht_bucket_html5_5C1, ht_bucket_html5_5C2, ht_bucket_empty,
+ ht_bucket_html5_5C4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_5D0, ht_bucket_html5_5D1, ht_bucket_empty, ht_bucket_html5_5D3,
+ ht_bucket_empty, ht_bucket_html5_5D5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_5D8, ht_bucket_html5_5D9, ht_bucket_empty, ht_bucket_html5_5DB,
+ ht_bucket_empty, ht_bucket_html5_5DD, ht_bucket_empty, ht_bucket_html5_5DF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5E2, ht_bucket_empty,
+ ht_bucket_html5_5E4, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5E7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5EA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_5ED, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_5F0, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5F3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_5F6, ht_bucket_empty,
+ ht_bucket_html5_5F8, ht_bucket_empty, ht_bucket_html5_5FA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_5FD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_601, ht_bucket_html5_602, ht_bucket_html5_603,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_606, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_609, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_60D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_613,
+ ht_bucket_empty, ht_bucket_html5_615, ht_bucket_empty, ht_bucket_html5_617,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_61A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_61D, ht_bucket_empty, ht_bucket_html5_61F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_622, ht_bucket_empty,
+ ht_bucket_html5_624, ht_bucket_empty, ht_bucket_html5_626, ht_bucket_empty,
+ ht_bucket_html5_628, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_62C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_630, ht_bucket_empty, ht_bucket_html5_632, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_636, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_63A, ht_bucket_empty,
+ ht_bucket_html5_63C, ht_bucket_html5_63D, ht_bucket_html5_63E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_641, ht_bucket_html5_642, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_645, ht_bucket_html5_646, ht_bucket_html5_647,
+ ht_bucket_html5_648, ht_bucket_html5_649, ht_bucket_html5_64A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_651, ht_bucket_html5_652, ht_bucket_html5_653,
+ ht_bucket_empty, ht_bucket_html5_655, ht_bucket_empty, ht_bucket_html5_657,
+ ht_bucket_html5_658, ht_bucket_html5_659, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_65C, ht_bucket_empty, ht_bucket_html5_65E, ht_bucket_empty,
+ ht_bucket_html5_660, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_669, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_670, ht_bucket_html5_671, ht_bucket_html5_672, ht_bucket_html5_673,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_676, ht_bucket_empty,
+ ht_bucket_html5_678, ht_bucket_html5_679, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_67D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_680, ht_bucket_empty, ht_bucket_html5_682, ht_bucket_empty,
+ ht_bucket_html5_684, ht_bucket_html5_685, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_68A, ht_bucket_empty,
+ ht_bucket_html5_68C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_691, ht_bucket_empty, ht_bucket_html5_693,
+ ht_bucket_html5_694, ht_bucket_empty, ht_bucket_html5_696, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_699, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6A3,
+ ht_bucket_html5_6A4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_6A8, ht_bucket_html5_6A9, ht_bucket_html5_6AA, ht_bucket_html5_6AB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6AE, ht_bucket_empty,
+ ht_bucket_html5_6B0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_6B4, ht_bucket_empty, ht_bucket_html5_6B6, ht_bucket_empty,
+ ht_bucket_html5_6B8, ht_bucket_html5_6B9, ht_bucket_html5_6BA, ht_bucket_empty,
+ ht_bucket_html5_6BC, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6BF,
+ ht_bucket_html5_6C0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_6C4, ht_bucket_html5_6C5, ht_bucket_html5_6C6, ht_bucket_html5_6C7,
+ ht_bucket_html5_6C8, ht_bucket_html5_6C9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_6CC, ht_bucket_empty, ht_bucket_html5_6CE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_6D1, ht_bucket_html5_6D2, ht_bucket_empty,
+ ht_bucket_html5_6D4, ht_bucket_html5_6D5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_6D9, ht_bucket_html5_6DA, ht_bucket_html5_6DB,
+ ht_bucket_html5_6DC, ht_bucket_empty, ht_bucket_html5_6DE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6E7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6EB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6EE, ht_bucket_html5_6EF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_6F5, ht_bucket_empty, ht_bucket_html5_6F7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_6FB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_704, ht_bucket_html5_705, ht_bucket_html5_706, ht_bucket_html5_707,
+ ht_bucket_empty, ht_bucket_html5_709, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_70C, ht_bucket_empty, ht_bucket_html5_70E, ht_bucket_html5_70F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_712, ht_bucket_empty,
+ ht_bucket_html5_714, ht_bucket_html5_715, ht_bucket_empty, ht_bucket_html5_717,
+ ht_bucket_empty, ht_bucket_html5_719, ht_bucket_empty, ht_bucket_html5_71B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_71E, ht_bucket_html5_71F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_723,
+ ht_bucket_html5_724, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_727,
+ ht_bucket_empty, ht_bucket_html5_729, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_72C, ht_bucket_html5_72D, ht_bucket_html5_72E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_733,
+ ht_bucket_html5_734, ht_bucket_html5_735, ht_bucket_html5_736, ht_bucket_empty,
+ ht_bucket_html5_738, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_73B,
+ ht_bucket_empty, ht_bucket_html5_73D, ht_bucket_html5_73E, ht_bucket_html5_73F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_744, ht_bucket_html5_745, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_749, ht_bucket_empty, ht_bucket_html5_74B,
+ ht_bucket_html5_74C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_74F,
+ ht_bucket_empty, ht_bucket_html5_751, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_754, ht_bucket_html5_755, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_759, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_75C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_75F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_762, ht_bucket_html5_763,
+ ht_bucket_empty, ht_bucket_html5_765, ht_bucket_html5_766, ht_bucket_empty,
+ ht_bucket_html5_768, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_76E, ht_bucket_empty,
+ ht_bucket_html5_770, ht_bucket_empty, ht_bucket_html5_772, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_776, ht_bucket_html5_777,
+ ht_bucket_empty, ht_bucket_html5_779, ht_bucket_html5_77A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_77F,
+ ht_bucket_empty, ht_bucket_html5_781, ht_bucket_empty, ht_bucket_html5_783,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_787,
+ ht_bucket_empty, ht_bucket_html5_789, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_78C, ht_bucket_html5_78D, ht_bucket_html5_78E, ht_bucket_empty,
+ ht_bucket_html5_790, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_794, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_797,
+ ht_bucket_html5_798, ht_bucket_empty, ht_bucket_html5_79A, ht_bucket_html5_79B,
+ ht_bucket_empty, ht_bucket_html5_79D, ht_bucket_empty, ht_bucket_html5_79F,
+ ht_bucket_html5_7A0, ht_bucket_html5_7A1, ht_bucket_html5_7A2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_7A5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_7A8, ht_bucket_empty, ht_bucket_html5_7AA, ht_bucket_html5_7AB,
+ ht_bucket_html5_7AC, ht_bucket_empty, ht_bucket_html5_7AE, ht_bucket_html5_7AF,
+ ht_bucket_html5_7B0, ht_bucket_html5_7B1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_7B5, ht_bucket_html5_7B6, ht_bucket_html5_7B7,
+ ht_bucket_html5_7B8, ht_bucket_empty, ht_bucket_html5_7BA, ht_bucket_html5_7BB,
+ ht_bucket_empty, ht_bucket_html5_7BD, ht_bucket_html5_7BE, ht_bucket_html5_7BF,
+ ht_bucket_html5_7C0, ht_bucket_html5_7C1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_7C9, ht_bucket_empty, ht_bucket_html5_7CB,
+ ht_bucket_empty, ht_bucket_html5_7CD, ht_bucket_html5_7CE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_7D1, ht_bucket_html5_7D2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_7D5, ht_bucket_html5_7D6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_7D9, ht_bucket_html5_7DA, ht_bucket_empty,
+ ht_bucket_html5_7DC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_7E0, ht_bucket_empty, ht_bucket_html5_7E2, ht_bucket_empty,
+ ht_bucket_html5_7E4, ht_bucket_html5_7E5, ht_bucket_html5_7E6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_7EC, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_7EF,
+ ht_bucket_empty, ht_bucket_html5_7F1, ht_bucket_empty, ht_bucket_html5_7F3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_7F6, ht_bucket_empty,
+ ht_bucket_html5_7F8, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_7FB,
+ ht_bucket_html5_7FC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_800, ht_bucket_empty, ht_bucket_html5_802, ht_bucket_html5_803,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_808, ht_bucket_html5_809, ht_bucket_html5_80A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_810, ht_bucket_html5_811, ht_bucket_html5_812, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_816, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_819, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_81C, ht_bucket_html5_81D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_821, ht_bucket_html5_822, ht_bucket_html5_823,
+ ht_bucket_html5_824, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_828, ht_bucket_html5_829, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_82D, ht_bucket_html5_82E, ht_bucket_empty,
+ ht_bucket_html5_830, ht_bucket_html5_831, ht_bucket_html5_832, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_837,
+ ht_bucket_html5_838, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_83C, ht_bucket_empty, ht_bucket_html5_83E, ht_bucket_html5_83F,
+ ht_bucket_empty, ht_bucket_html5_841, ht_bucket_html5_842, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_846, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_84A, ht_bucket_empty,
+ ht_bucket_html5_84C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_84F,
+ ht_bucket_html5_850, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_855, ht_bucket_empty, ht_bucket_html5_857,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_85B,
+ ht_bucket_html5_85C, ht_bucket_empty, ht_bucket_html5_85E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_861, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_865, ht_bucket_html5_866, ht_bucket_html5_867,
+ ht_bucket_html5_868, ht_bucket_empty, ht_bucket_html5_86A, ht_bucket_html5_86B,
+ ht_bucket_html5_86C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_873,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_876, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_879, ht_bucket_empty, ht_bucket_html5_87B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_87E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_88A, ht_bucket_empty,
+ ht_bucket_html5_88C, ht_bucket_empty, ht_bucket_html5_88E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_892, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_895, ht_bucket_html5_896, ht_bucket_html5_897,
+ ht_bucket_html5_898, ht_bucket_html5_899, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_89D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_8A5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_8AC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8B3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8B6, ht_bucket_html5_8B7,
+ ht_bucket_html5_8B8, ht_bucket_html5_8B9, ht_bucket_html5_8BA, ht_bucket_empty,
+ ht_bucket_html5_8BC, ht_bucket_html5_8BD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_8C0, ht_bucket_html5_8C1, ht_bucket_html5_8C2, ht_bucket_empty,
+ ht_bucket_html5_8C4, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8C7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8CF,
+ ht_bucket_html5_8D0, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8D3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8D6, ht_bucket_empty,
+ ht_bucket_html5_8D8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_8DC, ht_bucket_html5_8DD, ht_bucket_html5_8DE, ht_bucket_html5_8DF,
+ ht_bucket_html5_8E0, ht_bucket_empty, ht_bucket_html5_8E2, ht_bucket_html5_8E3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8E7,
+ ht_bucket_html5_8E8, ht_bucket_html5_8E9, ht_bucket_empty, ht_bucket_html5_8EB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8F3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8FB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_8FE, ht_bucket_html5_8FF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_904, ht_bucket_empty, ht_bucket_html5_906, ht_bucket_html5_907,
+ ht_bucket_empty, ht_bucket_html5_909, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_90C, ht_bucket_empty, ht_bucket_html5_90E, ht_bucket_empty,
+ ht_bucket_html5_910, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_913,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_916, ht_bucket_empty,
+ ht_bucket_html5_918, ht_bucket_html5_919, ht_bucket_empty, ht_bucket_html5_91B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_91E, ht_bucket_html5_91F,
+ ht_bucket_html5_920, ht_bucket_empty, ht_bucket_html5_922, ht_bucket_html5_923,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_927,
+ ht_bucket_empty, ht_bucket_html5_929, ht_bucket_html5_92A, ht_bucket_empty,
+ ht_bucket_html5_92C, ht_bucket_empty, ht_bucket_html5_92E, ht_bucket_empty,
+ ht_bucket_html5_930, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_936, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_939, ht_bucket_empty, ht_bucket_html5_93B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_93F,
+ ht_bucket_html5_940, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_945, ht_bucket_empty, ht_bucket_html5_947,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_94D, ht_bucket_empty, ht_bucket_html5_94F,
+ ht_bucket_html5_950, ht_bucket_empty, ht_bucket_html5_952, ht_bucket_html5_953,
+ ht_bucket_html5_954, ht_bucket_html5_955, ht_bucket_html5_956, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_959, ht_bucket_empty, ht_bucket_html5_95B,
+ ht_bucket_empty, ht_bucket_html5_95D, ht_bucket_empty, ht_bucket_html5_95F,
+ ht_bucket_html5_960, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_963,
+ ht_bucket_html5_964, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_969, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_96C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_96F,
+ ht_bucket_html5_970, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_974, ht_bucket_html5_975, ht_bucket_html5_976, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_97B,
+ ht_bucket_html5_97C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_97F,
+ ht_bucket_empty, ht_bucket_html5_981, ht_bucket_empty, ht_bucket_html5_983,
+ ht_bucket_empty, ht_bucket_html5_985, ht_bucket_html5_986, ht_bucket_empty,
+ ht_bucket_html5_988, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_98C, ht_bucket_html5_98D, ht_bucket_empty, ht_bucket_html5_98F,
+ ht_bucket_html5_990, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_996, ht_bucket_html5_997,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_99B,
+ ht_bucket_html5_99C, ht_bucket_empty, ht_bucket_html5_99E, ht_bucket_html5_99F,
+ ht_bucket_html5_9A0, ht_bucket_html5_9A1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_9A6, ht_bucket_empty,
+ ht_bucket_html5_9A8, ht_bucket_empty, ht_bucket_html5_9AA, ht_bucket_empty,
+ ht_bucket_html5_9AC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_9B0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_9B4, ht_bucket_html5_9B5, ht_bucket_html5_9B6, ht_bucket_html5_9B7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_9BB,
+ ht_bucket_html5_9BC, ht_bucket_html5_9BD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_9C1, ht_bucket_html5_9C2, ht_bucket_html5_9C3,
+ ht_bucket_empty, ht_bucket_html5_9C5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_9C9, ht_bucket_html5_9CA, ht_bucket_empty,
+ ht_bucket_html5_9CC, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_9CF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_9D5, ht_bucket_html5_9D6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_9DA, ht_bucket_html5_9DB,
+ ht_bucket_empty, ht_bucket_html5_9DD, ht_bucket_html5_9DE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_9E1, ht_bucket_html5_9E2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_9E5, ht_bucket_empty, ht_bucket_html5_9E7,
+ ht_bucket_empty, ht_bucket_html5_9E9, ht_bucket_empty, ht_bucket_html5_9EB,
+ ht_bucket_empty, ht_bucket_html5_9ED, ht_bucket_html5_9EE, ht_bucket_html5_9EF,
+ ht_bucket_html5_9F0, ht_bucket_html5_9F1, ht_bucket_html5_9F2, ht_bucket_html5_9F3,
+ ht_bucket_html5_9F4, ht_bucket_html5_9F5, ht_bucket_empty, ht_bucket_html5_9F7,
+ ht_bucket_empty, ht_bucket_html5_9F9, ht_bucket_html5_9FA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_9FD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A01, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_A04, ht_bucket_html5_A05, ht_bucket_html5_A06, ht_bucket_empty,
+ ht_bucket_html5_A08, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_A0C, ht_bucket_html5_A0D, ht_bucket_html5_A0E, ht_bucket_empty,
+ ht_bucket_html5_A10, ht_bucket_empty, ht_bucket_html5_A12, ht_bucket_empty,
+ ht_bucket_html5_A14, ht_bucket_html5_A15, ht_bucket_html5_A16, ht_bucket_html5_A17,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A21, ht_bucket_empty, ht_bucket_html5_A23,
+ ht_bucket_html5_A24, ht_bucket_html5_A25, ht_bucket_html5_A26, ht_bucket_empty,
+ ht_bucket_html5_A28, ht_bucket_empty, ht_bucket_html5_A2A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A2D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_A30, ht_bucket_empty, ht_bucket_html5_A32, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A36, ht_bucket_html5_A37,
+ ht_bucket_empty, ht_bucket_html5_A39, ht_bucket_empty, ht_bucket_html5_A3B,
+ ht_bucket_html5_A3C, ht_bucket_html5_A3D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A41, ht_bucket_empty, ht_bucket_html5_A43,
+ ht_bucket_html5_A44, ht_bucket_html5_A45, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_A48, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A4F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A53,
+ ht_bucket_html5_A54, ht_bucket_empty, ht_bucket_html5_A56, ht_bucket_html5_A57,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A5A, ht_bucket_html5_A5B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A61, ht_bucket_html5_A62, ht_bucket_html5_A63,
+ ht_bucket_html5_A64, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A69, ht_bucket_html5_A6A, ht_bucket_html5_A6B,
+ ht_bucket_empty, ht_bucket_html5_A6D, ht_bucket_empty, ht_bucket_html5_A6F,
+ ht_bucket_html5_A70, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A76, ht_bucket_empty,
+ ht_bucket_html5_A78, ht_bucket_empty, ht_bucket_html5_A7A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A7E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A81, ht_bucket_html5_A82, ht_bucket_empty,
+ ht_bucket_html5_A84, ht_bucket_html5_A85, ht_bucket_html5_A86, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A89, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A8D, ht_bucket_html5_A8E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_A92, ht_bucket_empty,
+ ht_bucket_html5_A94, ht_bucket_empty, ht_bucket_html5_A96, ht_bucket_empty,
+ ht_bucket_html5_A98, ht_bucket_html5_A99, ht_bucket_html5_A9A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_A9D, ht_bucket_empty, ht_bucket_html5_A9F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_AA3,
+ ht_bucket_html5_AA4, ht_bucket_html5_AA5, ht_bucket_empty, ht_bucket_html5_AA7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_AAC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_AB2, ht_bucket_empty,
+ ht_bucket_html5_AB4, ht_bucket_html5_AB5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_ABA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_AC0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_AC4, ht_bucket_html5_AC5, ht_bucket_html5_AC6, ht_bucket_html5_AC7,
+ ht_bucket_html5_AC8, ht_bucket_empty, ht_bucket_html5_ACA, ht_bucket_empty,
+ ht_bucket_html5_ACC, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_ACF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_AD2, ht_bucket_html5_AD3,
+ ht_bucket_html5_AD4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_ADA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_ADD, ht_bucket_empty, ht_bucket_html5_ADF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_AE4, ht_bucket_html5_AE5, ht_bucket_html5_AE6, ht_bucket_html5_AE7,
+ ht_bucket_html5_AE8, ht_bucket_html5_AE9, ht_bucket_empty, ht_bucket_html5_AEB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_AF5, ht_bucket_html5_AF6, ht_bucket_html5_AF7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_AFA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_AFD, ht_bucket_html5_AFE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_B08, ht_bucket_html5_B09, ht_bucket_html5_B0A, ht_bucket_empty,
+ ht_bucket_html5_B0C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_B10, ht_bucket_html5_B11, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_B15, ht_bucket_html5_B16, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B1E, ht_bucket_html5_B1F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B23,
+ ht_bucket_html5_B24, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B27,
+ ht_bucket_empty, ht_bucket_html5_B29, ht_bucket_html5_B2A, ht_bucket_html5_B2B,
+ ht_bucket_html5_B2C, ht_bucket_html5_B2D, ht_bucket_html5_B2E, ht_bucket_html5_B2F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B33,
+ ht_bucket_empty, ht_bucket_html5_B35, ht_bucket_html5_B36, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B3A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_B3D, ht_bucket_html5_B3E, ht_bucket_empty,
+ ht_bucket_html5_B40, ht_bucket_empty, ht_bucket_html5_B42, ht_bucket_empty,
+ ht_bucket_html5_B44, ht_bucket_empty, ht_bucket_html5_B46, ht_bucket_html5_B47,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_B4C, ht_bucket_empty, ht_bucket_html5_B4E, ht_bucket_html5_B4F,
+ ht_bucket_html5_B50, ht_bucket_html5_B51, ht_bucket_html5_B52, ht_bucket_html5_B53,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B56, ht_bucket_empty,
+ ht_bucket_html5_B58, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_B5C, ht_bucket_html5_B5D, ht_bucket_html5_B5E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B63,
+ ht_bucket_html5_B64, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B67,
+ ht_bucket_empty, ht_bucket_html5_B69, ht_bucket_empty, ht_bucket_html5_B6B,
+ ht_bucket_empty, ht_bucket_html5_B6D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B72, ht_bucket_html5_B73,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B77,
+ ht_bucket_html5_B78, ht_bucket_empty, ht_bucket_html5_B7A, ht_bucket_html5_B7B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B7E, ht_bucket_html5_B7F,
+ ht_bucket_empty, ht_bucket_html5_B81, ht_bucket_html5_B82, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_B87,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_B8D, ht_bucket_empty, ht_bucket_html5_B8F,
+ ht_bucket_html5_B90, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_B94, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_B98, ht_bucket_html5_B99, ht_bucket_html5_B9A, ht_bucket_empty,
+ ht_bucket_html5_B9C, ht_bucket_html5_B9D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_BA5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_BA9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BAE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BB2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_BB5, ht_bucket_html5_BB6, ht_bucket_html5_BB7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BBA, ht_bucket_empty,
+ ht_bucket_html5_BBC, ht_bucket_html5_BBD, ht_bucket_empty, ht_bucket_html5_BBF,
+ ht_bucket_empty, ht_bucket_html5_BC1, ht_bucket_html5_BC2, ht_bucket_html5_BC3,
+ ht_bucket_html5_BC4, ht_bucket_html5_BC5, ht_bucket_html5_BC6, ht_bucket_html5_BC7,
+ ht_bucket_html5_BC8, ht_bucket_html5_BC9, ht_bucket_empty, ht_bucket_html5_BCB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BCE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_BD1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BD7,
+ ht_bucket_html5_BD8, ht_bucket_html5_BD9, ht_bucket_html5_BDA, ht_bucket_html5_BDB,
+ ht_bucket_empty, ht_bucket_html5_BDD, ht_bucket_empty, ht_bucket_html5_BDF,
+ ht_bucket_empty, ht_bucket_html5_BE1, ht_bucket_html5_BE2, ht_bucket_empty,
+ ht_bucket_html5_BE4, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BE7,
+ ht_bucket_html5_BE8, ht_bucket_html5_BE9, ht_bucket_html5_BEA, ht_bucket_html5_BEB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BEF,
+ ht_bucket_html5_BF0, ht_bucket_html5_BF1, ht_bucket_html5_BF2, ht_bucket_html5_BF3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_BF7,
+ ht_bucket_empty, ht_bucket_html5_BF9, ht_bucket_html5_BFA, ht_bucket_empty,
+ ht_bucket_html5_BFC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C02, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C0B,
+ ht_bucket_html5_C0C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_C11, ht_bucket_html5_C12, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C16, ht_bucket_empty,
+ ht_bucket_html5_C18, ht_bucket_empty, ht_bucket_html5_C1A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_C1D, ht_bucket_html5_C1E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C23,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C27,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C2B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_C31, ht_bucket_html5_C32, ht_bucket_html5_C33,
+ ht_bucket_html5_C34, ht_bucket_html5_C35, ht_bucket_html5_C36, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C3A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C3E, ht_bucket_html5_C3F,
+ ht_bucket_html5_C40, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C43,
+ ht_bucket_html5_C44, ht_bucket_empty, ht_bucket_html5_C46, ht_bucket_empty,
+ ht_bucket_html5_C48, ht_bucket_empty, ht_bucket_html5_C4A, ht_bucket_html5_C4B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C4F,
+ ht_bucket_html5_C50, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_C54, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_C58, ht_bucket_empty, ht_bucket_html5_C5A, ht_bucket_html5_C5B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C5F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_C69, ht_bucket_empty, ht_bucket_html5_C6B,
+ ht_bucket_html5_C6C, ht_bucket_empty, ht_bucket_html5_C6E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C72, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C76, ht_bucket_html5_C77,
+ ht_bucket_html5_C78, ht_bucket_empty, ht_bucket_html5_C7A, ht_bucket_html5_C7B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_C80, ht_bucket_empty, ht_bucket_html5_C82, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_C89, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_C8E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_C91, ht_bucket_empty, ht_bucket_html5_C93,
+ ht_bucket_html5_C94, ht_bucket_html5_C95, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_C98, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_CA6, ht_bucket_empty,
+ ht_bucket_html5_CA8, ht_bucket_html5_CA9, ht_bucket_html5_CAA, ht_bucket_empty,
+ ht_bucket_html5_CAC, ht_bucket_html5_CAD, ht_bucket_empty, ht_bucket_html5_CAF,
+ ht_bucket_html5_CB0, ht_bucket_empty, ht_bucket_html5_CB2, ht_bucket_empty,
+ ht_bucket_html5_CB4, ht_bucket_empty, ht_bucket_html5_CB6, ht_bucket_html5_CB7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_CBA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_CBE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_CC2, ht_bucket_empty,
+ ht_bucket_html5_CC4, ht_bucket_html5_CC5, ht_bucket_empty, ht_bucket_html5_CC7,
+ ht_bucket_html5_CC8, ht_bucket_html5_CC9, ht_bucket_empty, ht_bucket_html5_CCB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_CD0, ht_bucket_empty, ht_bucket_html5_CD2, ht_bucket_html5_CD3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_CD9, ht_bucket_html5_CDA, ht_bucket_empty,
+ ht_bucket_html5_CDC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_CE4, ht_bucket_empty, ht_bucket_html5_CE6, ht_bucket_empty,
+ ht_bucket_html5_CE8, ht_bucket_html5_CE9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_CED, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_CF1, ht_bucket_html5_CF2, ht_bucket_html5_CF3,
+ ht_bucket_html5_CF4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_CFA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_CFF,
+ ht_bucket_html5_D00, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D06, ht_bucket_html5_D07,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D0B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D0E, ht_bucket_empty,
+ ht_bucket_html5_D10, ht_bucket_html5_D11, ht_bucket_html5_D12, ht_bucket_html5_D13,
+ ht_bucket_empty, ht_bucket_html5_D15, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_D18, ht_bucket_html5_D19, ht_bucket_html5_D1A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D1E, ht_bucket_html5_D1F,
+ ht_bucket_html5_D20, ht_bucket_empty, ht_bucket_html5_D22, ht_bucket_empty,
+ ht_bucket_html5_D24, ht_bucket_empty, ht_bucket_html5_D26, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D2A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D32, ht_bucket_empty,
+ ht_bucket_html5_D34, ht_bucket_html5_D35, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_D38, ht_bucket_html5_D39, ht_bucket_html5_D3A, ht_bucket_html5_D3B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D3E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D42, ht_bucket_empty,
+ ht_bucket_html5_D44, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_D49, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_D4C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D4F,
+ ht_bucket_empty, ht_bucket_html5_D51, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_D54, ht_bucket_html5_D55, ht_bucket_html5_D56, ht_bucket_html5_D57,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D5A, ht_bucket_html5_D5B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D5F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D63,
+ ht_bucket_empty, ht_bucket_html5_D65, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_D69, ht_bucket_html5_D6A, ht_bucket_empty,
+ ht_bucket_html5_D6C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_D6F,
+ ht_bucket_html5_D70, ht_bucket_html5_D71, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_D74, ht_bucket_html5_D75, ht_bucket_html5_D76, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_D7C, ht_bucket_html5_D7D, ht_bucket_html5_D7E, ht_bucket_empty,
+ ht_bucket_html5_D80, ht_bucket_html5_D81, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_D85, ht_bucket_empty, ht_bucket_html5_D87,
+ ht_bucket_empty, ht_bucket_html5_D89, ht_bucket_html5_D8A, ht_bucket_empty,
+ ht_bucket_html5_D8C, ht_bucket_html5_D8D, ht_bucket_html5_D8E, ht_bucket_html5_D8F,
+ ht_bucket_html5_D90, ht_bucket_html5_D91, ht_bucket_empty, ht_bucket_html5_D93,
+ ht_bucket_html5_D94, ht_bucket_html5_D95, ht_bucket_html5_D96, ht_bucket_empty,
+ ht_bucket_html5_D98, ht_bucket_empty, ht_bucket_html5_D9A, ht_bucket_empty,
+ ht_bucket_html5_D9C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_DA0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_DA5, ht_bucket_html5_DA6, ht_bucket_empty,
+ ht_bucket_html5_DA8, ht_bucket_html5_DA9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_DAC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_DB0, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_DB3,
+ ht_bucket_html5_DB4, ht_bucket_empty, ht_bucket_html5_DB6, ht_bucket_html5_DB7,
+ ht_bucket_empty, ht_bucket_html5_DB9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_DBC, ht_bucket_empty, ht_bucket_html5_DBE, ht_bucket_html5_DBF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_DC2, ht_bucket_html5_DC3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_DC6, ht_bucket_empty,
+ ht_bucket_html5_DC8, ht_bucket_empty, ht_bucket_html5_DCA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_DCF,
+ ht_bucket_empty, ht_bucket_html5_DD1, ht_bucket_empty, ht_bucket_html5_DD3,
+ ht_bucket_html5_DD4, ht_bucket_html5_DD5, ht_bucket_empty, ht_bucket_html5_DD7,
+ ht_bucket_empty, ht_bucket_html5_DD9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_DDC, ht_bucket_html5_DDD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_DE4, ht_bucket_empty, ht_bucket_html5_DE6, ht_bucket_html5_DE7,
+ ht_bucket_empty, ht_bucket_html5_DE9, ht_bucket_empty, ht_bucket_html5_DEB,
+ ht_bucket_empty, ht_bucket_html5_DED, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_DF1, ht_bucket_html5_DF2, ht_bucket_html5_DF3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_DF6, ht_bucket_html5_DF7,
+ ht_bucket_empty, ht_bucket_html5_DF9, ht_bucket_empty, ht_bucket_html5_DFB,
+ ht_bucket_empty, ht_bucket_html5_DFD, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E03,
+ ht_bucket_html5_E04, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E08, ht_bucket_html5_E09, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E0C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_E11, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E18, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E1B,
+ ht_bucket_html5_E1C, ht_bucket_html5_E1D, ht_bucket_html5_E1E, ht_bucket_empty,
+ ht_bucket_html5_E20, ht_bucket_empty, ht_bucket_html5_E22, ht_bucket_html5_E23,
+ ht_bucket_html5_E24, ht_bucket_html5_E25, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E28, ht_bucket_empty, ht_bucket_html5_E2A, ht_bucket_empty,
+ ht_bucket_html5_E2C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E2F,
+ ht_bucket_html5_E30, ht_bucket_empty, ht_bucket_html5_E32, ht_bucket_html5_E33,
+ ht_bucket_empty, ht_bucket_html5_E35, ht_bucket_html5_E36, ht_bucket_html5_E37,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E3B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_E41, ht_bucket_html5_E42, ht_bucket_html5_E43,
+ ht_bucket_html5_E44, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E48, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E4C, ht_bucket_empty, ht_bucket_html5_E4E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E53,
+ ht_bucket_empty, ht_bucket_html5_E55, ht_bucket_empty, ht_bucket_html5_E57,
+ ht_bucket_html5_E58, ht_bucket_html5_E59, ht_bucket_empty, ht_bucket_html5_E5B,
+ ht_bucket_empty, ht_bucket_html5_E5D, ht_bucket_html5_E5E, ht_bucket_html5_E5F,
+ ht_bucket_html5_E60, ht_bucket_html5_E61, ht_bucket_empty, ht_bucket_html5_E63,
+ ht_bucket_html5_E64, ht_bucket_html5_E65, ht_bucket_html5_E66, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E6A, ht_bucket_empty,
+ ht_bucket_html5_E6C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E6F,
+ ht_bucket_html5_E70, ht_bucket_html5_E71, ht_bucket_empty, ht_bucket_html5_E73,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E78, ht_bucket_empty, ht_bucket_html5_E7A, ht_bucket_empty,
+ ht_bucket_html5_E7C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E80, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E83,
+ ht_bucket_html5_E84, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_E89, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_E8E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_E91, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_E99, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_E9C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_EA1, ht_bucket_html5_EA2, ht_bucket_empty,
+ ht_bucket_html5_EA4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_EA8, ht_bucket_html5_EA9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_EB1, ht_bucket_html5_EB2, ht_bucket_empty,
+ ht_bucket_html5_EB4, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_EB7,
+ ht_bucket_html5_EB8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_ECA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_ECD, ht_bucket_empty, ht_bucket_html5_ECF,
+ ht_bucket_empty, ht_bucket_html5_ED1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_ED7,
+ ht_bucket_html5_ED8, ht_bucket_html5_ED9, ht_bucket_html5_EDA, ht_bucket_html5_EDB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_EDF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_EE2, ht_bucket_empty,
+ ht_bucket_html5_EE4, ht_bucket_html5_EE5, ht_bucket_empty, ht_bucket_html5_EE7,
+ ht_bucket_empty, ht_bucket_html5_EE9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_EEF,
+ ht_bucket_empty, ht_bucket_html5_EF1, ht_bucket_html5_EF2, ht_bucket_empty,
+ ht_bucket_html5_EF4, ht_bucket_html5_EF5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_EF9, ht_bucket_empty, ht_bucket_html5_EFB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_EFE, ht_bucket_html5_EFF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F03,
+ ht_bucket_empty, ht_bucket_html5_F05, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_F08, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F0B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F0F,
+ ht_bucket_html5_F10, ht_bucket_html5_F11, ht_bucket_empty, ht_bucket_html5_F13,
+ ht_bucket_html5_F14, ht_bucket_html5_F15, ht_bucket_empty, ht_bucket_html5_F17,
+ ht_bucket_html5_F18, ht_bucket_html5_F19, ht_bucket_html5_F1A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F1F,
+ ht_bucket_html5_F20, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F26, ht_bucket_empty,
+ ht_bucket_html5_F28, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_F2C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F2F,
+ ht_bucket_html5_F30, ht_bucket_html5_F31, ht_bucket_empty, ht_bucket_html5_F33,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F37,
+ ht_bucket_html5_F38, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_F40, ht_bucket_html5_F41, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_F44, ht_bucket_empty, ht_bucket_html5_F46, ht_bucket_html5_F47,
+ ht_bucket_html5_F48, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F4B,
+ ht_bucket_html5_F4C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_F50, ht_bucket_html5_F51, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_F55, ht_bucket_empty, ht_bucket_html5_F57,
+ ht_bucket_html5_F58, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F5B,
+ ht_bucket_empty, ht_bucket_html5_F5D, ht_bucket_empty, ht_bucket_html5_F5F,
+ ht_bucket_html5_F60, ht_bucket_empty, ht_bucket_html5_F62, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F67,
+ ht_bucket_html5_F68, ht_bucket_html5_F69, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_F6D, ht_bucket_html5_F6E, ht_bucket_html5_F6F,
+ ht_bucket_html5_F70, ht_bucket_html5_F71, ht_bucket_html5_F72, ht_bucket_empty,
+ ht_bucket_html5_F74, ht_bucket_html5_F75, ht_bucket_html5_F76, ht_bucket_html5_F77,
+ ht_bucket_html5_F78, ht_bucket_html5_F79, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_F81, ht_bucket_html5_F82, ht_bucket_html5_F83,
+ ht_bucket_html5_F84, ht_bucket_empty, ht_bucket_html5_F86, ht_bucket_empty,
+ ht_bucket_html5_F88, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F8B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F8F,
+ ht_bucket_empty, ht_bucket_html5_F91, ht_bucket_empty, ht_bucket_html5_F93,
+ ht_bucket_empty, ht_bucket_html5_F95, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F9A, ht_bucket_empty,
+ ht_bucket_html5_F9C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_F9F,
+ ht_bucket_html5_FA0, ht_bucket_html5_FA1, ht_bucket_html5_FA2, ht_bucket_html5_FA3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_FA9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_FB0, ht_bucket_html5_FB1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_FB4, ht_bucket_html5_FB5, ht_bucket_html5_FB6, ht_bucket_html5_FB7,
+ ht_bucket_empty, ht_bucket_html5_FB9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_FBC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_FC2, ht_bucket_empty,
+ ht_bucket_html5_FC4, ht_bucket_empty, ht_bucket_html5_FC6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_FCA, ht_bucket_empty,
+ ht_bucket_html5_FCC, ht_bucket_empty, ht_bucket_html5_FCE, ht_bucket_html5_FCF,
+ ht_bucket_html5_FD0, ht_bucket_empty, ht_bucket_html5_FD2, ht_bucket_html5_FD3,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_FD6, ht_bucket_html5_FD7,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_FDD, ht_bucket_empty, ht_bucket_html5_FDF,
+ ht_bucket_empty, ht_bucket_html5_FE1, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html5_FE6, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_FE9, ht_bucket_html5_FEA, ht_bucket_html5_FEB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html5_FF5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_FF8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html5_FFC, ht_bucket_empty, ht_bucket_html5_FFE, ht_bucket_empty,
+};
+
+static const entity_ht ent_ht_html5 = {
+ 0x1000,
+ ht_buckets_html5
+};
+
+/* end of HTML5 hash table for entity -> codepoint }}} */
+
+/* {{{ Start of HTML 4.01 multi-stage table for codepoint -> entity */
+
+/* {{{ Stage 3 Tables for HTML 4.01 */
+
+static const entity_stage3_row stage3_table_html4_00000[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"quot", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"amp", 3} } }, {0, { {"#039", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lt", 2} } }, {0, { {NULL, 0} } }, {0, { {"gt", 2} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_00080[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"nbsp", 4} } }, {0, { {"iexcl", 5} } }, {0, { {"cent", 4} } }, {0, { {"pound", 5} } },
+ {0, { {"curren", 6} } }, {0, { {"yen", 3} } }, {0, { {"brvbar", 6} } }, {0, { {"sect", 4} } },
+ {0, { {"uml", 3} } }, {0, { {"copy", 4} } }, {0, { {"ordf", 4} } }, {0, { {"laquo", 5} } },
+ {0, { {"not", 3} } }, {0, { {"shy", 3} } }, {0, { {"reg", 3} } }, {0, { {"macr", 4} } },
+ {0, { {"deg", 3} } }, {0, { {"plusmn", 6} } }, {0, { {"sup2", 4} } }, {0, { {"sup3", 4} } },
+ {0, { {"acute", 5} } }, {0, { {"micro", 5} } }, {0, { {"para", 4} } }, {0, { {"middot", 6} } },
+ {0, { {"cedil", 5} } }, {0, { {"sup1", 4} } }, {0, { {"ordm", 4} } }, {0, { {"raquo", 5} } },
+ {0, { {"frac14", 6} } }, {0, { {"frac12", 6} } }, {0, { {"frac34", 6} } }, {0, { {"iquest", 6} } },
+};
+
+static const entity_stage3_row stage3_table_html4_000C0[] = {
+ {0, { {"Agrave", 6} } }, {0, { {"Aacute", 6} } }, {0, { {"Acirc", 5} } }, {0, { {"Atilde", 6} } },
+ {0, { {"Auml", 4} } }, {0, { {"Aring", 5} } }, {0, { {"AElig", 5} } }, {0, { {"Ccedil", 6} } },
+ {0, { {"Egrave", 6} } }, {0, { {"Eacute", 6} } }, {0, { {"Ecirc", 5} } }, {0, { {"Euml", 4} } },
+ {0, { {"Igrave", 6} } }, {0, { {"Iacute", 6} } }, {0, { {"Icirc", 5} } }, {0, { {"Iuml", 4} } },
+ {0, { {"ETH", 3} } }, {0, { {"Ntilde", 6} } }, {0, { {"Ograve", 6} } }, {0, { {"Oacute", 6} } },
+ {0, { {"Ocirc", 5} } }, {0, { {"Otilde", 6} } }, {0, { {"Ouml", 4} } }, {0, { {"times", 5} } },
+ {0, { {"Oslash", 6} } }, {0, { {"Ugrave", 6} } }, {0, { {"Uacute", 6} } }, {0, { {"Ucirc", 5} } },
+ {0, { {"Uuml", 4} } }, {0, { {"Yacute", 6} } }, {0, { {"THORN", 5} } }, {0, { {"szlig", 5} } },
+ {0, { {"agrave", 6} } }, {0, { {"aacute", 6} } }, {0, { {"acirc", 5} } }, {0, { {"atilde", 6} } },
+ {0, { {"auml", 4} } }, {0, { {"aring", 5} } }, {0, { {"aelig", 5} } }, {0, { {"ccedil", 6} } },
+ {0, { {"egrave", 6} } }, {0, { {"eacute", 6} } }, {0, { {"ecirc", 5} } }, {0, { {"euml", 4} } },
+ {0, { {"igrave", 6} } }, {0, { {"iacute", 6} } }, {0, { {"icirc", 5} } }, {0, { {"iuml", 4} } },
+ {0, { {"eth", 3} } }, {0, { {"ntilde", 6} } }, {0, { {"ograve", 6} } }, {0, { {"oacute", 6} } },
+ {0, { {"ocirc", 5} } }, {0, { {"otilde", 6} } }, {0, { {"ouml", 4} } }, {0, { {"divide", 6} } },
+ {0, { {"oslash", 6} } }, {0, { {"ugrave", 6} } }, {0, { {"uacute", 6} } }, {0, { {"ucirc", 5} } },
+ {0, { {"uuml", 4} } }, {0, { {"yacute", 6} } }, {0, { {"thorn", 5} } }, {0, { {"yuml", 4} } },
+};
+
+static const entity_stage3_row stage3_table_html4_00140[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"OElig", 5} } }, {0, { {"oelig", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Scaron", 6} } }, {0, { {"scaron", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"Yuml", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_00180[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"fnof", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_002C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"circ", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"tilde", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_00380[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"Alpha", 5} } }, {0, { {"Beta", 4} } }, {0, { {"Gamma", 5} } },
+ {0, { {"Delta", 5} } }, {0, { {"Epsilon", 7} } }, {0, { {"Zeta", 4} } }, {0, { {"Eta", 3} } },
+ {0, { {"Theta", 5} } }, {0, { {"Iota", 4} } }, {0, { {"Kappa", 5} } }, {0, { {"Lambda", 6} } },
+ {0, { {"Mu", 2} } }, {0, { {"Nu", 2} } }, {0, { {"Xi", 2} } }, {0, { {"Omicron", 7} } },
+ {0, { {"Pi", 2} } }, {0, { {"Rho", 3} } }, {0, { {NULL, 0} } }, {0, { {"Sigma", 5} } },
+ {0, { {"Tau", 3} } }, {0, { {"Upsilon", 7} } }, {0, { {"Phi", 3} } }, {0, { {"Chi", 3} } },
+ {0, { {"Psi", 3} } }, {0, { {"Omega", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"alpha", 5} } }, {0, { {"beta", 4} } }, {0, { {"gamma", 5} } },
+ {0, { {"delta", 5} } }, {0, { {"epsilon", 7} } }, {0, { {"zeta", 4} } }, {0, { {"eta", 3} } },
+ {0, { {"theta", 5} } }, {0, { {"iota", 4} } }, {0, { {"kappa", 5} } }, {0, { {"lambda", 6} } },
+ {0, { {"mu", 2} } }, {0, { {"nu", 2} } }, {0, { {"xi", 2} } }, {0, { {"omicron", 7} } },
+};
+
+static const entity_stage3_row stage3_table_html4_003C0[] = {
+ {0, { {"pi", 2} } }, {0, { {"rho", 3} } }, {0, { {"sigmaf", 6} } }, {0, { {"sigma", 5} } },
+ {0, { {"tau", 3} } }, {0, { {"upsilon", 7} } }, {0, { {"phi", 3} } }, {0, { {"chi", 3} } },
+ {0, { {"psi", 3} } }, {0, { {"omega", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"thetasym", 8} } }, {0, { {"upsih", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"piv", 3} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02000[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"ensp", 4} } }, {0, { {"emsp", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"thinsp", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"zwnj", 4} } }, {0, { {"zwj", 3} } }, {0, { {"lrm", 3} } }, {0, { {"rlm", 3} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"ndash", 5} } },
+ {0, { {"mdash", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lsquo", 5} } }, {0, { {"rsquo", 5} } }, {0, { {"sbquo", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"ldquo", 5} } }, {0, { {"rdquo", 5} } }, {0, { {"bdquo", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"dagger", 6} } }, {0, { {"Dagger", 6} } }, {0, { {"bull", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"hellip", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"permil", 6} } }, {0, { {NULL, 0} } }, {0, { {"prime", 5} } }, {0, { {"Prime", 5} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"lsaquo", 6} } }, {0, { {"rsaquo", 6} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"oline", 5} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02040[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"frasl", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02080[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"euro", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02100[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"image", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"weierp", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"real", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"trade", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"alefsym", 7} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02180[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"larr", 4} } }, {0, { {"uarr", 4} } }, {0, { {"rarr", 4} } }, {0, { {"darr", 4} } },
+ {0, { {"harr", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"crarr", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_021C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lArr", 4} } }, {0, { {"uArr", 4} } }, {0, { {"rArr", 4} } }, {0, { {"dArr", 4} } },
+ {0, { {"hArr", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02200[] = {
+ {0, { {"forall", 6} } }, {0, { {NULL, 0} } }, {0, { {"part", 4} } }, {0, { {"exist", 5} } },
+ {0, { {NULL, 0} } }, {0, { {"empty", 5} } }, {0, { {NULL, 0} } }, {0, { {"nabla", 5} } },
+ {0, { {"isin", 4} } }, {0, { {"notin", 5} } }, {0, { {NULL, 0} } }, {0, { {"ni", 2} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"prod", 4} } },
+ {0, { {NULL, 0} } }, {0, { {"sum", 3} } }, {0, { {"minus", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"lowast", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"radic", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"prop", 4} } }, {0, { {"infin", 5} } }, {0, { {NULL, 0} } },
+ {0, { {"ang", 3} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"and", 3} } },
+ {0, { {"or", 2} } }, {0, { {"cap", 3} } }, {0, { {"cup", 3} } }, {0, { {"int", 3} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"there4", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"sim", 3} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02240[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"cong", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"asymp", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"ne", 2} } }, {0, { {"equiv", 5} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"le", 2} } }, {0, { {"ge", 2} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02280[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"sub", 3} } }, {0, { {"sup", 3} } },
+ {0, { {"nsub", 4} } }, {0, { {NULL, 0} } }, {0, { {"sube", 4} } }, {0, { {"supe", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"oplus", 5} } }, {0, { {NULL, 0} } }, {0, { {"otimes", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"perp", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_022C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"sdot", 4} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02300[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lceil", 5} } }, {0, { {"rceil", 5} } }, {0, { {"lfloor", 6} } }, {0, { {"rfloor", 6} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {"lang", 4} } }, {0, { {"rang", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_025C0[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"loz", 3} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+static const entity_stage3_row stage3_table_html4_02640[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"spades", 6} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"clubs", 5} } },
+ {0, { {NULL, 0} } }, {0, { {"hearts", 6} } }, {0, { {"diams", 5} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+/* end of stage 3 Tables for HTML 4.01 }}} */
+
+/* {{{ Stage 2 Tables for HTML 4.01 */
+
+static const entity_stage2_row stage2_table_html4_00000[] = {
+ stage3_table_html4_00000, empty_stage3_table, stage3_table_html4_00080, stage3_table_html4_000C0,
+ empty_stage3_table, stage3_table_html4_00140, stage3_table_html4_00180, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, stage3_table_html4_002C0,
+ empty_stage3_table, empty_stage3_table, stage3_table_html4_00380, stage3_table_html4_003C0,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+static const entity_stage2_row stage2_table_html4_02000[] = {
+ stage3_table_html4_02000, stage3_table_html4_02040, stage3_table_html4_02080, empty_stage3_table,
+ stage3_table_html4_02100, empty_stage3_table, stage3_table_html4_02180, stage3_table_html4_021C0,
+ stage3_table_html4_02200, stage3_table_html4_02240, stage3_table_html4_02280, stage3_table_html4_022C0,
+ stage3_table_html4_02300, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, stage3_table_html4_025C0,
+ empty_stage3_table, stage3_table_html4_02640, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+/* end of stage 2 tables for HTML 4.01 }}} */
+
+static const entity_stage1_row entity_ms_table_html4[] = {
+ stage2_table_html4_00000,
+ empty_stage2_table,
+ stage2_table_html4_02000,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+ empty_stage2_table,
+};
+
+/* end of HTML 4.01 multi-stage table for codepoint -> entity }}} */
+
+/* {{{ HTML 4.01 hash table for entity -> codepoint */
+
+static const entity_cp_map ht_bucket_html4_000[] = { {"gt", 2, 0x0003E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_003[] = { {"Igrave", 6, 0x000CC, 0}, {"amp", 3, 0x00026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_006[] = { {"oacute", 6, 0x000F3, 0}, {"Xi", 2, 0x0039E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_008[] = { {"uuml", 4, 0x000FC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_00B[] = { {"Alpha", 5, 0x00391, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_00E[] = { {"sim", 3, 0x0223C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_012[] = { {"kappa", 5, 0x003BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_016[] = { {"lArr", 4, 0x021D0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_018[] = { {"and", 3, 0x02227, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_01B[] = { {"ang", 3, 0x02220, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_020[] = { {"copy", 4, 0x000A9, 0}, {"Iacute", 6, 0x000CD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_023[] = { {"igrave", 6, 0x000EC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_026[] = { {"xi", 2, 0x003BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_027[] = { {"Acirc", 5, 0x000C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_02B[] = { {"Ecirc", 5, 0x000CA, 0}, {"alpha", 5, 0x003B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_02C[] = { {"hearts", 6, 0x02665, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_02F[] = { {"Icirc", 5, 0x000CE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_030[] = { {"Yacute", 6, 0x000DD, 0}, {"int", 3, 0x0222B, 0}, {"rlm", 3, 0x0200F, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_034[] = { {"empty", 5, 0x02205, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_036[] = { {"larr", 4, 0x02190, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_03B[] = { {"Ucirc", 5, 0x000DB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_03C[] = { {"oline", 5, 0x0203E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_040[] = { {"iacute", 6, 0x000ED, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_046[] = { {"middot", 6, 0x000B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_047[] = { {"acirc", 5, 0x000E2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_04B[] = { {"ecirc", 5, 0x000EA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_04F[] = { {"icirc", 5, 0x000EE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_050[] = { {"yacute", 6, 0x000FD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_051[] = { {"minus", 5, 0x02212, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_054[] = { {"Auml", 4, 0x000C4, 0}, {"thetasym", 8, 0x003D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_056[] = { {"Sigma", 5, 0x003A3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_059[] = { {"lsquo", 5, 0x02018, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_05B[] = { {"ucirc", 5, 0x000FB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_05C[] = { {"rArr", 4, 0x021D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_064[] = { {"brvbar", 6, 0x000A6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_067[] = { {"AElig", 5, 0x000C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_069[] = { {"Ccedil", 6, 0x000C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_071[] = { {"Psi", 3, 0x003A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_072[] = { {"exist", 5, 0x02203, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_074[] = { {"auml", 4, 0x000E4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_076[] = { {"sigma", 5, 0x003C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_078[] = { {"isin", 4, 0x02208, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_07C[] = { {"rarr", 4, 0x02192, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_089[] = { {"ccedil", 6, 0x000E7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_08D[] = { {"raquo", 5, 0x000BB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_08E[] = { {"Omega", 5, 0x003A9, 0}, {"zwnj", 4, 0x0200C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_091[] = { {"psi", 3, 0x003C8, 0}, {"there4", 6, 0x02234, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_092[] = { {"hArr", 4, 0x021D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_096[] = { {"le", 2, 0x02264, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_098[] = { {"Atilde", 6, 0x000C3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_099[] = { {"Zeta", 4, 0x00396, 0}, {"infin", 5, 0x0221E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_09D[] = { {"frasl", 5, 0x02044, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0A0[] = { {"euro", 4, 0x020AC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0A5[] = { {"lt", 2, 0x0003C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0A7[] = { {"aelig", 5, 0x000E6, 0}, {"Mu", 2, 0x0039C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0A8[] = { {"macr", 4, 0x000AF, 0}, {"image", 5, 0x02111, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0AA[] = { {"ldquo", 5, 0x0201C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0AE[] = { {"omega", 5, 0x003C9, 0}, {"upsih", 5, 0x003D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0B0[] = { {"THORN", 5, 0x000DE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0B2[] = { {"Iota", 4, 0x00399, 0}, {"harr", 4, 0x02194, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0B4[] = { {"bull", 4, 0x02022, 0}, {"rceil", 5, 0x02309, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0B8[] = { {"atilde", 6, 0x000E3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0B9[] = { {"zeta", 4, 0x003B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0BA[] = { {"emsp", 4, 0x02003, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0BC[] = { {"perp", 4, 0x022A5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0C2[] = { {"Prime", 5, 0x02033, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0C4[] = { {"frac12", 6, 0x000BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0C5[] = { {"Ntilde", 6, 0x000D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0C6[] = { {"frac14", 6, 0x000BC, 0}, {"circ", 4, 0x002C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0C7[] = { {"mu", 2, 0x003BC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0C8[] = { {"Gamma", 5, 0x00393, 0}, {"Nu", 2, 0x0039D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0CE[] = { {"fnof", 4, 0x00192, 0}, {"quot", 4, 0x00022, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0D2[] = { {"iota", 4, 0x003B9, 0}, {"mdash", 5, 0x02014, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0D8[] = { {"ne", 2, 0x02260, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0DB[] = { {"Theta", 5, 0x00398, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0DC[] = { {"ni", 2, 0x0220B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0E2[] = { {"prime", 5, 0x02032, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0E5[] = { {"ntilde", 6, 0x000F1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0E6[] = { {"Lambda", 6, 0x0039B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0E8[] = { {"gamma", 5, 0x003B3, 0}, {"nu", 2, 0x003BD, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0EB[] = { {"pound", 5, 0x000A3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0EE[] = { {"permil", 6, 0x02030, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0F9[] = { {"cap", 3, 0x02229, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0FA[] = { {"iexcl", 5, 0x000A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0FB[] = { {"Agrave", 6, 0x000C0, 0}, {"theta", 5, 0x003B8, 0}, {"ensp", 4, 0x02002, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0FE[] = { {"Pi", 2, 0x003A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_0FF[] = { {"crarr", 5, 0x021B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_100[] = { {"iquest", 6, 0x000BF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_105[] = { {"forall", 6, 0x02200, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_106[] = { {"Phi", 3, 0x003A6, 0}, {"lambda", 6, 0x003BB, 0}, {"or", 2, 0x02228, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_108[] = { {"frac34", 6, 0x000BE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_10D[] = { {"notin", 5, 0x02209, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_10E[] = { {"dArr", 4, 0x021D3, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_10F[] = { {"Dagger", 6, 0x02021, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_111[] = { {"yen", 3, 0x000A5, 0}, {"weierp", 6, 0x02118, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_113[] = { {"uml", 3, 0x000A8, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_117[] = { {"tilde", 5, 0x002DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_118[] = { {"Aacute", 6, 0x000C1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_11A[] = { {"loz", 3, 0x025CA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_11B[] = { {"agrave", 6, 0x000E0, 0}, {"thinsp", 6, 0x02009, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_11E[] = { {"pi", 2, 0x003C0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_11F[] = { {"micro", 5, 0x000B5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_125[] = { {"spades", 6, 0x02660, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_126[] = { {"phi", 3, 0x003C6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_12E[] = { {"darr", 4, 0x02193, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_12F[] = { {"Oslash", 6, 0x000D8, 0}, {"Tau", 3, 0x003A4, 0}, {"dagger", 6, 0x02020, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_135[] = { {"Ocirc", 5, 0x000D4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_136[] = { {"alefsym", 7, 0x02135, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_138[] = { {"aacute", 6, 0x000E1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_13A[] = { {"divide", 6, 0x000F7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_13F[] = { {"sdot", 4, 0x022C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_143[] = { {"reg", 3, 0x000AE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_149[] = { {"real", 4, 0x0211C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_14B[] = { {"Scaron", 6, 0x00160, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_14F[] = { {"cent", 4, 0x000A2, 0}, {"oslash", 6, 0x000F8, 0}, {"tau", 3, 0x003C4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_150[] = { {"thorn", 5, 0x000FE, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_153[] = { {"ndash", 5, 0x02013, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_154[] = { {"piv", 3, 0x003D6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_155[] = { {"ocirc", 5, 0x000F4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_156[] = { {"Aring", 5, 0x000C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_158[] = { {"nbsp", 4, 0x000A0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_15C[] = { {"Iuml", 4, 0x000CF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_15F[] = { {"rsquo", 5, 0x02019, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_160[] = { {"rsaquo", 6, 0x0203A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_163[] = { {"hellip", 6, 0x02026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_166[] = { {"Otilde", 6, 0x000D5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_16B[] = { {"scaron", 6, 0x00161, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_16C[] = { {"Yuml", 4, 0x00178, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_16E[] = { {"sup1", 4, 0x000B9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_16F[] = { {"sup2", 4, 0x000B2, 0}, {"Delta", 5, 0x00394, 0}, {"sbquo", 5, 0x0201A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_170[] = { {"sup3", 4, 0x000B3, 0}, {"lrm", 3, 0x0200E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_173[] = { {"diams", 5, 0x02666, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_175[] = { {"OElig", 5, 0x00152, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_176[] = { {"aring", 5, 0x000E5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_178[] = { {"oplus", 5, 0x02295, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_17C[] = { {"iuml", 4, 0x000EF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_17F[] = { {"Egrave", 6, 0x000C8, 0}, {"uArr", 4, 0x021D1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_181[] = { {"Beta", 4, 0x00392, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_183[] = { {"nabla", 5, 0x02207, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_186[] = { {"ETH", 3, 0x000D0, 0}, {"otilde", 6, 0x000F5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_187[] = { {"laquo", 5, 0x000AB, 0}, {"times", 5, 0x000D7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_18C[] = { {"yuml", 4, 0x000FF, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_18D[] = { {"cup", 3, 0x0222A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_18E[] = { {"Rho", 3, 0x003A1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_18F[] = { {"Ugrave", 6, 0x000D9, 0}, {"delta", 5, 0x003B4, 0}, {"equiv", 5, 0x02261, 0}, {"sub", 3, 0x02282, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_194[] = { {"curren", 6, 0x000A4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_196[] = { {"not", 3, 0x000AC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_197[] = { {"acute", 5, 0x000B4, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_19A[] = { {"prod", 4, 0x0220F, 0}, {"sum", 3, 0x02211, 0}, {"lsaquo", 6, 0x02039, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_19C[] = { {"Eacute", 6, 0x000C9, 0}, {"Omicron", 7, 0x0039F, 0}, {"sigmaf", 6, 0x003C2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_19D[] = { {"sup", 3, 0x02283, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_19F[] = { {"egrave", 6, 0x000E8, 0}, {"uarr", 4, 0x02191, 0}, {"lowast", 6, 0x02217, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A0[] = { {"zwj", 3, 0x0200D, 0}, {"bdquo", 5, 0x0201E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A1[] = { {"beta", 4, 0x003B2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A2[] = { {"Ouml", 4, 0x000D6, 0}, {"supe", 4, 0x02287, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A4[] = { {"plusmn", 6, 0x000B1, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A6[] = { {"cedil", 5, 0x000B8, 0}, {"prop", 4, 0x0221D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A7[] = { {"lang", 4, 0x02329, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A8[] = { {"radic", 5, 0x0221A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1A9[] = { {"para", 4, 0x000B6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1AC[] = { {"Uacute", 6, 0x000DA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1AE[] = { {"szlig", 5, 0x000DF, 0}, {"rho", 3, 0x003C1, 0}, {"lceil", 5, 0x02308, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1AF[] = { {"ugrave", 6, 0x000F9, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1B0[] = { {"rdquo", 5, 0x0201D, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1B5[] = { {"deg", 3, 0x000B0, 0}, {"trade", 5, 0x02122, 0}, {"oelig", 5, 0x00153, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1B9[] = { {"Chi", 3, 0x003A7, 0}, {"rfloor", 6, 0x0230B, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1BC[] = { {"eacute", 6, 0x000E9, 0}, {"omicron", 7, 0x003BF, 0}, {"part", 4, 0x02202, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1BE[] = { {"clubs", 5, 0x02663, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1BF[] = { {"Epsilon", 7, 0x00395, 0}, {"Eta", 3, 0x00397, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1C2[] = { {"ouml", 4, 0x000F6, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1C4[] = { {"#039", 4, 0x00027, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1C9[] = { {"Ograve", 6, 0x000D2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1CC[] = { {"uacute", 6, 0x000FA, 0}, {"cong", 4, 0x02245, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1CF[] = { {"Upsilon", 7, 0x003A5, 0}, {"asymp", 5, 0x02248, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1D0[] = { {"ordf", 4, 0x000AA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1D4[] = { {"sube", 4, 0x02286, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1D7[] = { {"ordm", 4, 0x000BA, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1D8[] = { {"Euml", 4, 0x000CB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1D9[] = { {"chi", 3, 0x003C7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1DD[] = { {"nsub", 4, 0x02284, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1DF[] = { {"epsilon", 7, 0x003B5, 0}, {"eta", 3, 0x003B7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1E6[] = { {"Oacute", 6, 0x000D3, 0}, {"eth", 3, 0x000F0, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1E8[] = { {"Uuml", 4, 0x000DC, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1E9[] = { {"ograve", 6, 0x000F2, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1ED[] = { {"rang", 4, 0x0232A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1EF[] = { {"upsilon", 7, 0x003C5, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F1[] = { {"ge", 2, 0x02265, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F2[] = { {"Kappa", 5, 0x0039A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F3[] = { {"lfloor", 6, 0x0230A, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F4[] = { {"sect", 4, 0x000A7, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F6[] = { {"otimes", 6, 0x02297, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F8[] = { {"euml", 4, 0x000EB, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_html4_1F9[] = { {"shy", 3, 0x000AD, 0}, {NULL, 0, 0, 0} };
+
+static const entity_cp_map *const ht_buckets_html4[] = {
+ ht_bucket_html4_000, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_003,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_006, ht_bucket_empty,
+ ht_bucket_html4_008, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_00B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_00E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_012, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_016, ht_bucket_empty,
+ ht_bucket_html4_018, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_01B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_020, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_023,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_026, ht_bucket_html4_027,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_02B,
+ ht_bucket_html4_02C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_02F,
+ ht_bucket_html4_030, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_034, ht_bucket_empty, ht_bucket_html4_036, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_03B,
+ ht_bucket_html4_03C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_040, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_046, ht_bucket_html4_047,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_04B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_04F,
+ ht_bucket_html4_050, ht_bucket_html4_051, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_054, ht_bucket_empty, ht_bucket_html4_056, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_059, ht_bucket_empty, ht_bucket_html4_05B,
+ ht_bucket_html4_05C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_064, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_067,
+ ht_bucket_empty, ht_bucket_html4_069, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_071, ht_bucket_html4_072, ht_bucket_empty,
+ ht_bucket_html4_074, ht_bucket_empty, ht_bucket_html4_076, ht_bucket_empty,
+ ht_bucket_html4_078, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_07C, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_089, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_08D, ht_bucket_html4_08E, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_091, ht_bucket_html4_092, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_096, ht_bucket_empty,
+ ht_bucket_html4_098, ht_bucket_html4_099, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_09D, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_0A0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_0A5, ht_bucket_empty, ht_bucket_html4_0A7,
+ ht_bucket_html4_0A8, ht_bucket_empty, ht_bucket_html4_0AA, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0AE, ht_bucket_empty,
+ ht_bucket_html4_0B0, ht_bucket_empty, ht_bucket_html4_0B2, ht_bucket_empty,
+ ht_bucket_html4_0B4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_0B8, ht_bucket_html4_0B9, ht_bucket_html4_0BA, ht_bucket_empty,
+ ht_bucket_html4_0BC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0C2, ht_bucket_empty,
+ ht_bucket_html4_0C4, ht_bucket_html4_0C5, ht_bucket_html4_0C6, ht_bucket_html4_0C7,
+ ht_bucket_html4_0C8, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0CE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0D2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_0D8, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0DB,
+ ht_bucket_html4_0DC, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0E2, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_0E5, ht_bucket_html4_0E6, ht_bucket_empty,
+ ht_bucket_html4_0E8, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0EB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0EE, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_0F9, ht_bucket_html4_0FA, ht_bucket_html4_0FB,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_0FE, ht_bucket_html4_0FF,
+ ht_bucket_html4_100, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_105, ht_bucket_html4_106, ht_bucket_empty,
+ ht_bucket_html4_108, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_10D, ht_bucket_html4_10E, ht_bucket_html4_10F,
+ ht_bucket_empty, ht_bucket_html4_111, ht_bucket_empty, ht_bucket_html4_113,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_117,
+ ht_bucket_html4_118, ht_bucket_empty, ht_bucket_html4_11A, ht_bucket_html4_11B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_11E, ht_bucket_html4_11F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_125, ht_bucket_html4_126, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_12E, ht_bucket_html4_12F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_135, ht_bucket_html4_136, ht_bucket_empty,
+ ht_bucket_html4_138, ht_bucket_empty, ht_bucket_html4_13A, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_13F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_143,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_149, ht_bucket_empty, ht_bucket_html4_14B,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_14F,
+ ht_bucket_html4_150, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_153,
+ ht_bucket_html4_154, ht_bucket_html4_155, ht_bucket_html4_156, ht_bucket_empty,
+ ht_bucket_html4_158, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_15C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_15F,
+ ht_bucket_html4_160, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_163,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_166, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_16B,
+ ht_bucket_html4_16C, ht_bucket_empty, ht_bucket_html4_16E, ht_bucket_html4_16F,
+ ht_bucket_html4_170, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_173,
+ ht_bucket_empty, ht_bucket_html4_175, ht_bucket_html4_176, ht_bucket_empty,
+ ht_bucket_html4_178, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_17C, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_17F,
+ ht_bucket_empty, ht_bucket_html4_181, ht_bucket_empty, ht_bucket_html4_183,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_186, ht_bucket_html4_187,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_18C, ht_bucket_html4_18D, ht_bucket_html4_18E, ht_bucket_html4_18F,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_194, ht_bucket_empty, ht_bucket_html4_196, ht_bucket_html4_197,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_19A, ht_bucket_empty,
+ ht_bucket_html4_19C, ht_bucket_html4_19D, ht_bucket_empty, ht_bucket_html4_19F,
+ ht_bucket_html4_1A0, ht_bucket_html4_1A1, ht_bucket_html4_1A2, ht_bucket_empty,
+ ht_bucket_html4_1A4, ht_bucket_empty, ht_bucket_html4_1A6, ht_bucket_html4_1A7,
+ ht_bucket_html4_1A8, ht_bucket_html4_1A9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_1AC, ht_bucket_empty, ht_bucket_html4_1AE, ht_bucket_html4_1AF,
+ ht_bucket_html4_1B0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_1B5, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_1B9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_1BC, ht_bucket_empty, ht_bucket_html4_1BE, ht_bucket_html4_1BF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_1C2, ht_bucket_empty,
+ ht_bucket_html4_1C4, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_1C9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_1CC, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_1CF,
+ ht_bucket_html4_1D0, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_html4_1D4, ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_1D7,
+ ht_bucket_html4_1D8, ht_bucket_html4_1D9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_1DD, ht_bucket_empty, ht_bucket_html4_1DF,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_html4_1E6, ht_bucket_empty,
+ ht_bucket_html4_1E8, ht_bucket_html4_1E9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_html4_1ED, ht_bucket_empty, ht_bucket_html4_1EF,
+ ht_bucket_empty, ht_bucket_html4_1F1, ht_bucket_html4_1F2, ht_bucket_html4_1F3,
+ ht_bucket_html4_1F4, ht_bucket_empty, ht_bucket_html4_1F6, ht_bucket_empty,
+ ht_bucket_html4_1F8, ht_bucket_html4_1F9, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+};
+
+static const entity_ht ent_ht_html4 = {
+ 0x200,
+ ht_buckets_html4
+};
+
+/* end of HTML 4.01 hash table for entity -> codepoint }}} */
+
+/* {{{ Start of Basic entities (no apos) table for codepoint -> entity */
+
+static const entity_stage3_row stage3_table_be_noapos_00000[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"quot", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"amp", 3} } }, {0, { {"#039", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lt", 2} } }, {0, { {NULL, 0} } }, {0, { {"gt", 2} } }, {0, { {NULL, 0} } },
+};
+
+/* {{{ Basic entities (no apos) hash table for entity -> codepoint */
+
+static const entity_cp_map ht_bucket_be_noapos_000[] = { {"gt", 2, 0x0003E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_noapos_003[] = { {"amp", 3, 0x00026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_noapos_004[] = { {"#039", 4, 0x00027, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_noapos_005[] = { {"lt", 2, 0x0003C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_noapos_00E[] = { {"quot", 4, 0x00022, 0}, {NULL, 0, 0, 0} };
+
+static const entity_cp_map *const ht_buckets_be_noapos[] = {
+ ht_bucket_be_noapos_000, ht_bucket_empty, ht_bucket_empty, ht_bucket_be_noapos_003,
+ ht_bucket_be_noapos_004, ht_bucket_be_noapos_005, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_be_noapos_00E, ht_bucket_empty,
+};
+
+static const entity_ht ent_ht_be_noapos = {
+ 0x10,
+ ht_buckets_be_noapos
+};
+
+/* end of Basic entities (no apos) hash table for entity -> codepoint }}} */
+
+/* {{{ Start of Basic entities (with apos) table for codepoint -> entity */
+
+static const entity_stage3_row stage3_table_be_apos_00000[] = {
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"quot", 4} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {"amp", 3} } }, {0, { {"apos", 4} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {"lt", 2} } }, {0, { {NULL, 0} } }, {0, { {"gt", 2} } }, {0, { {NULL, 0} } },
+};
+
+/* {{{ Basic entities (with apos) hash table for entity -> codepoint */
+
+static const entity_cp_map ht_bucket_be_apos_000[] = { {"gt", 2, 0x0003E, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_apos_003[] = { {"amp", 3, 0x00026, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_apos_005[] = { {"lt", 2, 0x0003C, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_apos_008[] = { {"apos", 4, 0x00027, 0}, {NULL, 0, 0, 0} };
+static const entity_cp_map ht_bucket_be_apos_00E[] = { {"quot", 4, 0x00022, 0}, {NULL, 0, 0, 0} };
+
+static const entity_cp_map *const ht_buckets_be_apos[] = {
+ ht_bucket_be_apos_000, ht_bucket_empty, ht_bucket_empty, ht_bucket_be_apos_003,
+ ht_bucket_empty, ht_bucket_be_apos_005, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_be_apos_008, ht_bucket_empty, ht_bucket_empty, ht_bucket_empty,
+ ht_bucket_empty, ht_bucket_empty, ht_bucket_be_apos_00E, ht_bucket_empty,
+};
+
+static const entity_ht ent_ht_be_apos = {
+ 0x10,
+ ht_buckets_be_apos
+};
+
+/* end of Basic entities (with apos) hash table for entity -> codepoint }}} */
+
+#endif /* HTML_TABLES_H */
diff --git a/ext/standard/html_tables/ents_basic.txt b/ext/standard/html_tables/ents_basic.txt
new file mode 100644
index 0000000000..3a2ec93f4c
--- /dev/null
+++ b/ext/standard/html_tables/ents_basic.txt
@@ -0,0 +1,5 @@
+quot 22
+amp 26
+#039 27
+lt 3C
+gt 3E
diff --git a/ext/standard/html_tables/ents_basic_apos.txt b/ext/standard/html_tables/ents_basic_apos.txt
new file mode 100644
index 0000000000..6a0f307a0c
--- /dev/null
+++ b/ext/standard/html_tables/ents_basic_apos.txt
@@ -0,0 +1,5 @@
+quot 22
+amp 26
+apos 27
+lt 3C
+gt 3E
diff --git a/ext/standard/html_tables/ents_html401.txt b/ext/standard/html_tables/ents_html401.txt
new file mode 100644
index 0000000000..7e1564b229
--- /dev/null
+++ b/ext/standard/html_tables/ents_html401.txt
@@ -0,0 +1,253 @@
+#039 0027 //artifical; there's no &apos; in HTML 4.01
+nbsp 00A0
+iexcl 00A1
+cent 00A2
+pound 00A3
+curren 00A4
+yen 00A5
+brvbar 00A6
+sect 00A7
+uml 00A8
+copy 00A9
+ordf 00AA
+laquo 00AB
+not 00AC
+shy 00AD
+reg 00AE
+macr 00AF
+deg 00B0
+plusmn 00B1
+sup2 00B2
+sup3 00B3
+acute 00B4
+micro 00B5
+para 00B6
+middot 00B7
+cedil 00B8
+sup1 00B9
+ordm 00BA
+raquo 00BB
+frac14 00BC
+frac12 00BD
+frac34 00BE
+iquest 00BF
+Agrave 00C0
+Aacute 00C1
+Acirc 00C2
+Atilde 00C3
+Auml 00C4
+Aring 00C5
+AElig 00C6
+Ccedil 00C7
+Egrave 00C8
+Eacute 00C9
+Ecirc 00CA
+Euml 00CB
+Igrave 00CC
+Iacute 00CD
+Icirc 00CE
+Iuml 00CF
+ETH 00D0
+Ntilde 00D1
+Ograve 00D2
+Oacute 00D3
+Ocirc 00D4
+Otilde 00D5
+Ouml 00D6
+times 00D7
+Oslash 00D8
+Ugrave 00D9
+Uacute 00DA
+Ucirc 00DB
+Uuml 00DC
+Yacute 00DD
+THORN 00DE
+szlig 00DF
+agrave 00E0
+aacute 00E1
+acirc 00E2
+atilde 00E3
+auml 00E4
+aring 00E5
+aelig 00E6
+ccedil 00E7
+egrave 00E8
+eacute 00E9
+ecirc 00EA
+euml 00EB
+igrave 00EC
+iacute 00ED
+icirc 00EE
+iuml 00EF
+eth 00F0
+ntilde 00F1
+ograve 00F2
+oacute 00F3
+ocirc 00F4
+otilde 00F5
+ouml 00F6
+divide 00F7
+oslash 00F8
+ugrave 00F9
+uacute 00FA
+ucirc 00FB
+uuml 00FC
+yacute 00FD
+thorn 00FE
+yuml 00FF
+fnof 0192
+Alpha 0391
+Beta 0392
+Gamma 0393
+Delta 0394
+Epsilon 0395
+Zeta 0396
+Eta 0397
+Theta 0398
+Iota 0399
+Kappa 039A
+Lambda 039B
+Mu 039C
+Nu 039D
+Xi 039E
+Omicron 039F
+Pi 03A0
+Rho 03A1
+Sigma 03A3
+Tau 03A4
+Upsilon 03A5
+Phi 03A6
+Chi 03A7
+Psi 03A8
+Omega 03A9
+alpha 03B1
+beta 03B2
+gamma 03B3
+delta 03B4
+epsilon 03B5
+zeta 03B6
+eta 03B7
+theta 03B8
+iota 03B9
+kappa 03BA
+lambda 03BB
+mu 03BC
+nu 03BD
+xi 03BE
+omicron 03BF
+pi 03C0
+rho 03C1
+sigmaf 03C2
+sigma 03C3
+tau 03C4
+upsilon 03C5
+phi 03C6
+chi 03C7
+psi 03C8
+omega 03C9
+thetasym 03D1
+upsih 03D2
+piv 03D6
+bull 2022
+hellip 2026
+prime 2032
+Prime 2033
+oline 203E
+frasl 2044
+weierp 2118
+image 2111
+real 211C
+trade 2122
+alefsym 2135
+larr 2190
+uarr 2191
+rarr 2192
+darr 2193
+harr 2194
+crarr 21B5
+lArr 21D0
+uArr 21D1
+rArr 21D2
+dArr 21D3
+hArr 21D4
+forall 2200
+part 2202
+exist 2203
+empty 2205
+nabla 2207
+isin 2208
+notin 2209
+ni 220B
+prod 220F
+sum 2211
+minus 2212
+lowast 2217
+radic 221A
+prop 221D
+infin 221E
+ang 2220
+and 2227
+or 2228
+cap 2229
+cup 222A
+int 222B
+there4 2234
+sim 223C
+cong 2245
+asymp 2248
+ne 2260
+equiv 2261
+le 2264
+ge 2265
+sub 2282
+sup 2283
+nsub 2284
+sube 2286
+supe 2287
+oplus 2295
+otimes 2297
+perp 22A5
+sdot 22C5
+lceil 2308
+rceil 2309
+lfloor 230A
+rfloor 230B
+lang 2329
+rang 232A
+loz 25CA
+spades 2660
+clubs 2663
+hearts 2665
+diams 2666
+quot 0022
+amp 0026
+lt 003C
+gt 003E
+OElig 0152
+oelig 0153
+Scaron 0160
+scaron 0161
+Yuml 0178
+circ 02C6
+tilde 02DC
+ensp 2002
+emsp 2003
+thinsp 2009
+zwnj 200C
+zwj 200D
+lrm 200E
+rlm 200F
+ndash 2013
+mdash 2014
+lsquo 2018
+rsquo 2019
+sbquo 201A
+ldquo 201C
+rdquo 201D
+bdquo 201E
+dagger 2020
+Dagger 2021
+permil 2030
+lsaquo 2039
+rsaquo 203A
+euro 20AC \ No newline at end of file
diff --git a/ext/standard/html_tables/ents_html5.txt b/ext/standard/html_tables/ents_html5.txt
new file mode 100644
index 0000000000..18defb29b4
--- /dev/null
+++ b/ext/standard/html_tables/ents_html5.txt
@@ -0,0 +1,2125 @@
+AElig 000C6
+AMP 00026
+Aacute 000C1
+Abreve 00102
+Acirc 000C2
+Acy 00410
+Afr 1D504
+Agrave 000C0
+Alpha 00391
+Amacr 00100
+And 02A53
+Aogon 00104
+Aopf 1D538
+ApplyFunction 02061
+Aring 000C5
+Ascr 1D49C
+Assign 02254
+Atilde 000C3
+Auml 000C4
+Backslash 02216
+Barv 02AE7
+Barwed 02306
+Bcy 00411
+Because 02235
+Bernoullis 0212C
+Beta 00392
+Bfr 1D505
+Bopf 1D539
+Breve 002D8
+Bscr 0212C
+Bumpeq 0224E
+CHcy 00427
+COPY 000A9
+Cacute 00106
+Cap 022D2
+CapitalDifferentialD 02145
+Cayleys 0212D
+Ccaron 0010C
+Ccedil 000C7
+Ccirc 00108
+Cconint 02230
+Cdot 0010A
+Cedilla 000B8
+CenterDot 000B7
+Cfr 0212D
+Chi 003A7
+CircleDot 02299
+CircleMinus 02296
+CirclePlus 02295
+CircleTimes 02297
+ClockwiseContourIntegral 02232
+CloseCurlyDoubleQuote 0201D
+CloseCurlyQuote 02019
+Colon 02237
+Colone 02A74
+Congruent 02261
+Conint 0222F
+ContourIntegral 0222E
+Copf 02102
+Coproduct 02210
+CounterClockwiseContourIntegral 02233
+Cross 02A2F
+Cscr 1D49E
+Cup 022D3
+CupCap 0224D
+DD 02145
+DDotrahd 02911
+DJcy 00402
+DScy 00405
+DZcy 0040F
+Dagger 02021
+Darr 021A1
+Dashv 02AE4
+Dcaron 0010E
+Dcy 00414
+Del 02207
+Delta 00394
+Dfr 1D507
+DiacriticalAcute 000B4
+DiacriticalDot 002D9
+DiacriticalDoubleAcute 002DD
+DiacriticalGrave 00060
+DiacriticalTilde 002DC
+Diamond 022C4
+DifferentialD 02146
+Dopf 1D53B
+Dot 000A8
+DotDot 020DC
+DotEqual 02250
+DoubleContourIntegral 0222F
+DoubleDot 000A8
+DoubleDownArrow 021D3
+DoubleLeftArrow 021D0
+DoubleLeftRightArrow 021D4
+DoubleLeftTee 02AE4
+DoubleLongLeftArrow 027F8
+DoubleLongLeftRightArrow 027FA
+DoubleLongRightArrow 027F9
+DoubleRightArrow 021D2
+DoubleRightTee 022A8
+DoubleUpArrow 021D1
+DoubleUpDownArrow 021D5
+DoubleVerticalBar 02225
+DownArrow 02193
+DownArrowBar 02913
+DownArrowUpArrow 021F5
+DownBreve 00311
+DownLeftRightVector 02950
+DownLeftTeeVector 0295E
+DownLeftVector 021BD
+DownLeftVectorBar 02956
+DownRightTeeVector 0295F
+DownRightVector 021C1
+DownRightVectorBar 02957
+DownTee 022A4
+DownTeeArrow 021A7
+Downarrow 021D3
+Dscr 1D49F
+Dstrok 00110
+ENG 0014A
+ETH 000D0
+Eacute 000C9
+Ecaron 0011A
+Ecirc 000CA
+Ecy 0042D
+Edot 00116
+Efr 1D508
+Egrave 000C8
+Element 02208
+Emacr 00112
+EmptySmallSquare 025FB
+EmptyVerySmallSquare 025AB
+Eogon 00118
+Eopf 1D53C
+Epsilon 00395
+Equal 02A75
+EqualTilde 02242
+Equilibrium 021CC
+Escr 02130
+Esim 02A73
+Eta 00397
+Euml 000CB
+Exists 02203
+ExponentialE 02147
+Fcy 00424
+Ffr 1D509
+FilledSmallSquare 025FC
+FilledVerySmallSquare 025AA
+Fopf 1D53D
+ForAll 02200
+Fouriertrf 02131
+Fscr 02131
+GJcy 00403
+GT 0003E
+Gamma 00393
+Gammad 003DC
+Gbreve 0011E
+Gcedil 00122
+Gcirc 0011C
+Gcy 00413
+Gdot 00120
+Gfr 1D50A
+Gg 022D9
+Gopf 1D53E
+GreaterEqual 02265
+GreaterEqualLess 022DB
+GreaterFullEqual 02267
+GreaterGreater 02AA2
+GreaterLess 02277
+GreaterSlantEqual 02A7E
+GreaterTilde 02273
+Gscr 1D4A2
+Gt 0226B
+HARDcy 0042A
+Hacek 002C7
+Hat 0005E
+Hcirc 00124
+Hfr 0210C
+HilbertSpace 0210B
+Hopf 0210D
+HorizontalLine 02500
+Hscr 0210B
+Hstrok 00126
+HumpDownHump 0224E
+HumpEqual 0224F
+IEcy 00415
+IJlig 00132
+IOcy 00401
+Iacute 000CD
+Icirc 000CE
+Icy 00418
+Idot 00130
+Ifr 02111
+Igrave 000CC
+Im 02111
+Imacr 0012A
+ImaginaryI 02148
+Implies 021D2
+Int 0222C
+Integral 0222B
+Intersection 022C2
+InvisibleComma 02063
+InvisibleTimes 02062
+Iogon 0012E
+Iopf 1D540
+Iota 00399
+Iscr 02110
+Itilde 00128
+Iukcy 00406
+Iuml 000CF
+Jcirc 00134
+Jcy 00419
+Jfr 1D50D
+Jopf 1D541
+Jscr 1D4A5
+Jsercy 00408
+Jukcy 00404
+KHcy 00425
+KJcy 0040C
+Kappa 0039A
+Kcedil 00136
+Kcy 0041A
+Kfr 1D50E
+Kopf 1D542
+Kscr 1D4A6
+LJcy 00409
+LT 0003C
+Lacute 00139
+Lambda 0039B
+Lang 027EA
+Laplacetrf 02112
+Larr 0219E
+Lcaron 0013D
+Lcedil 0013B
+Lcy 0041B
+LeftAngleBracket 027E8
+LeftArrow 02190
+LeftArrowBar 021E4
+LeftArrowRightArrow 021C6
+LeftCeiling 02308
+LeftDoubleBracket 027E6
+LeftDownTeeVector 02961
+LeftDownVector 021C3
+LeftDownVectorBar 02959
+LeftFloor 0230A
+LeftRightArrow 02194
+LeftRightVector 0294E
+LeftTee 022A3
+LeftTeeArrow 021A4
+LeftTeeVector 0295A
+LeftTriangle 022B2
+LeftTriangleBar 029CF
+LeftTriangleEqual 022B4
+LeftUpDownVector 02951
+LeftUpTeeVector 02960
+LeftUpVector 021BF
+LeftUpVectorBar 02958
+LeftVector 021BC
+LeftVectorBar 02952
+Leftarrow 021D0
+Leftrightarrow 021D4
+LessEqualGreater 022DA
+LessFullEqual 02266
+LessGreater 02276
+LessLess 02AA1
+LessSlantEqual 02A7D
+LessTilde 02272
+Lfr 1D50F
+Ll 022D8
+Lleftarrow 021DA
+Lmidot 0013F
+LongLeftArrow 027F5
+LongLeftRightArrow 027F7
+LongRightArrow 027F6
+Longleftarrow 027F8
+Longleftrightarrow 027FA
+Longrightarrow 027F9
+Lopf 1D543
+LowerLeftArrow 02199
+LowerRightArrow 02198
+Lscr 02112
+Lsh 021B0
+Lstrok 00141
+Lt 0226A
+Map 02905
+Mcy 0041C
+MediumSpace 0205F
+Mellintrf 02133
+Mfr 1D510
+MinusPlus 02213
+Mopf 1D544
+Mscr 02133
+Mu 0039C
+NJcy 0040A
+Nacute 00143
+Ncaron 00147
+Ncedil 00145
+Ncy 0041D
+NegativeMediumSpace 0200B
+NegativeThickSpace 0200B
+NegativeThinSpace 0200B
+NegativeVeryThinSpace 0200B
+NestedGreaterGreater 0226B
+NestedLessLess 0226A
+NewLine 0000A
+Nfr 1D511
+NoBreak 02060
+NonBreakingSpace 000A0
+Nopf 02115
+Not 02AEC
+NotCongruent 02262
+NotCupCap 0226D
+NotDoubleVerticalBar 02226
+NotElement 02209
+NotEqual 02260
+NotEqualTilde 02242 00338
+NotExists 02204
+NotGreater 0226F
+NotGreaterEqual 02271
+NotGreaterFullEqual 02267 00338
+NotGreaterGreater 0226B 00338
+NotGreaterLess 02279
+NotGreaterSlantEqual 02A7E 00338
+NotGreaterTilde 02275
+NotHumpDownHump 0224E 00338
+NotHumpEqual 0224F 00338
+NotLeftTriangle 022EA
+NotLeftTriangleBar 029CF 00338
+NotLeftTriangleEqual 022EC
+NotLess 0226E
+NotLessEqual 02270
+NotLessGreater 02278
+NotLessLess 0226A 00338
+NotLessSlantEqual 02A7D 00338
+NotLessTilde 02274
+NotNestedGreaterGreater 02AA2 00338
+NotNestedLessLess 02AA1 00338
+NotPrecedes 02280
+NotPrecedesEqual 02AAF 00338
+NotPrecedesSlantEqual 022E0
+NotReverseElement 0220C
+NotRightTriangle 022EB
+NotRightTriangleBar 029D0 00338
+NotRightTriangleEqual 022ED
+NotSquareSubset 0228F 00338
+NotSquareSubsetEqual 022E2
+NotSquareSuperset 02290 00338
+NotSquareSupersetEqual 022E3
+NotSubset 02282 020D2
+NotSubsetEqual 02288
+NotSucceeds 02281
+NotSucceedsEqual 02AB0 00338
+NotSucceedsSlantEqual 022E1
+NotSucceedsTilde 0227F 00338
+NotSuperset 02283 020D2
+NotSupersetEqual 02289
+NotTilde 02241
+NotTildeEqual 02244
+NotTildeFullEqual 02247
+NotTildeTilde 02249
+NotVerticalBar 02224
+Nscr 1D4A9
+Ntilde 000D1
+Nu 0039D
+OElig 00152
+Oacute 000D3
+Ocirc 000D4
+Ocy 0041E
+Odblac 00150
+Ofr 1D512
+Ograve 000D2
+Omacr 0014C
+Omega 003A9
+Omicron 0039F
+Oopf 1D546
+OpenCurlyDoubleQuote 0201C
+OpenCurlyQuote 02018
+Or 02A54
+Oscr 1D4AA
+Oslash 000D8
+Otilde 000D5
+Otimes 02A37
+Ouml 000D6
+OverBar 0203E
+OverBrace 023DE
+OverBracket 023B4
+OverParenthesis 023DC
+PartialD 02202
+Pcy 0041F
+Pfr 1D513
+Phi 003A6
+Pi 003A0
+PlusMinus 000B1
+Poincareplane 0210C
+Popf 02119
+Pr 02ABB
+Precedes 0227A
+PrecedesEqual 02AAF
+PrecedesSlantEqual 0227C
+PrecedesTilde 0227E
+Prime 02033
+Product 0220F
+Proportion 02237
+Proportional 0221D
+Pscr 1D4AB
+Psi 003A8
+QUOT 00022
+Qfr 1D514
+Qopf 0211A
+Qscr 1D4AC
+RBarr 02910
+REG 000AE
+Racute 00154
+Rang 027EB
+Rarr 021A0
+Rarrtl 02916
+Rcaron 00158
+Rcedil 00156
+Rcy 00420
+Re 0211C
+ReverseElement 0220B
+ReverseEquilibrium 021CB
+ReverseUpEquilibrium 0296F
+Rfr 0211C
+Rho 003A1
+RightAngleBracket 027E9
+RightArrow 02192
+RightArrowBar 021E5
+RightArrowLeftArrow 021C4
+RightCeiling 02309
+RightDoubleBracket 027E7
+RightDownTeeVector 0295D
+RightDownVector 021C2
+RightDownVectorBar 02955
+RightFloor 0230B
+RightTee 022A2
+RightTeeArrow 021A6
+RightTeeVector 0295B
+RightTriangle 022B3
+RightTriangleBar 029D0
+RightTriangleEqual 022B5
+RightUpDownVector 0294F
+RightUpTeeVector 0295C
+RightUpVector 021BE
+RightUpVectorBar 02954
+RightVector 021C0
+RightVectorBar 02953
+Rightarrow 021D2
+Ropf 0211D
+RoundImplies 02970
+Rrightarrow 021DB
+Rscr 0211B
+Rsh 021B1
+RuleDelayed 029F4
+SHCHcy 00429
+SHcy 00428
+SOFTcy 0042C
+Sacute 0015A
+Sc 02ABC
+Scaron 00160
+Scedil 0015E
+Scirc 0015C
+Scy 00421
+Sfr 1D516
+ShortDownArrow 02193
+ShortLeftArrow 02190
+ShortRightArrow 02192
+ShortUpArrow 02191
+Sigma 003A3
+SmallCircle 02218
+Sopf 1D54A
+Sqrt 0221A
+Square 025A1
+SquareIntersection 02293
+SquareSubset 0228F
+SquareSubsetEqual 02291
+SquareSuperset 02290
+SquareSupersetEqual 02292
+SquareUnion 02294
+Sscr 1D4AE
+Star 022C6
+Sub 022D0
+Subset 022D0
+SubsetEqual 02286
+Succeeds 0227B
+SucceedsEqual 02AB0
+SucceedsSlantEqual 0227D
+SucceedsTilde 0227F
+SuchThat 0220B
+Sum 02211
+Sup 022D1
+Superset 02283
+SupersetEqual 02287
+Supset 022D1
+THORN 000DE
+TRADE 02122
+TSHcy 0040B
+TScy 00426
+Tab 00009
+Tau 003A4
+Tcaron 00164
+Tcedil 00162
+Tcy 00422
+Tfr 1D517
+Therefore 02234
+Theta 00398
+ThickSpace 0205F 0200A
+ThinSpace 02009
+Tilde 0223C
+TildeEqual 02243
+TildeFullEqual 02245
+TildeTilde 02248
+Topf 1D54B
+TripleDot 020DB
+Tscr 1D4AF
+Tstrok 00166
+Uacute 000DA
+Uarr 0219F
+Uarrocir 02949
+Ubrcy 0040E
+Ubreve 0016C
+Ucirc 000DB
+Ucy 00423
+Udblac 00170
+Ufr 1D518
+Ugrave 000D9
+Umacr 0016A
+UnderBar 0005F
+UnderBrace 023DF
+UnderBracket 023B5
+UnderParenthesis 023DD
+Union 022C3
+UnionPlus 0228E
+Uogon 00172
+Uopf 1D54C
+UpArrow 02191
+UpArrowBar 02912
+UpArrowDownArrow 021C5
+UpDownArrow 02195
+UpEquilibrium 0296E
+UpTee 022A5
+UpTeeArrow 021A5
+Uparrow 021D1
+Updownarrow 021D5
+UpperLeftArrow 02196
+UpperRightArrow 02197
+Upsi 003D2
+Upsilon 003A5
+Uring 0016E
+Uscr 1D4B0
+Utilde 00168
+Uuml 000DC
+VDash 022AB
+Vbar 02AEB
+Vcy 00412
+Vdash 022A9
+Vdashl 02AE6
+Vee 022C1
+Verbar 02016
+Vert 02016
+VerticalBar 02223
+VerticalLine 0007C
+VerticalSeparator 02758
+VerticalTilde 02240
+VeryThinSpace 0200A
+Vfr 1D519
+Vopf 1D54D
+Vscr 1D4B1
+Vvdash 022AA
+Wcirc 00174
+Wedge 022C0
+Wfr 1D51A
+Wopf 1D54E
+Wscr 1D4B2
+Xfr 1D51B
+Xi 0039E
+Xopf 1D54F
+Xscr 1D4B3
+YAcy 0042F
+YIcy 00407
+YUcy 0042E
+Yacute 000DD
+Ycirc 00176
+Ycy 0042B
+Yfr 1D51C
+Yopf 1D550
+Yscr 1D4B4
+Yuml 00178
+ZHcy 00416
+Zacute 00179
+Zcaron 0017D
+Zcy 00417
+Zdot 0017B
+ZeroWidthSpace 0200B
+Zeta 00396
+Zfr 02128
+Zopf 02124
+Zscr 1D4B5
+aacute 000E1
+abreve 00103
+ac 0223E
+acE 0223E 00333
+acd 0223F
+acirc 000E2
+acute 000B4
+acy 00430
+aelig 000E6
+af 02061
+afr 1D51E
+agrave 000E0
+alefsym 02135
+aleph 02135
+alpha 003B1
+amacr 00101
+amalg 02A3F
+amp 00026
+and 02227
+andand 02A55
+andd 02A5C
+andslope 02A58
+andv 02A5A
+ang 02220
+ange 029A4
+angle 02220
+angmsd 02221
+angmsdaa 029A8
+angmsdab 029A9
+angmsdac 029AA
+angmsdad 029AB
+angmsdae 029AC
+angmsdaf 029AD
+angmsdag 029AE
+angmsdah 029AF
+angrt 0221F
+angrtvb 022BE
+angrtvbd 0299D
+angsph 02222
+angst 000C5
+angzarr 0237C
+aogon 00105
+aopf 1D552
+ap 02248
+apE 02A70
+apacir 02A6F
+ape 0224A
+apid 0224B
+apos 00027
+approx 02248
+approxeq 0224A
+aring 000E5
+ascr 1D4B6
+ast 0002A
+asymp 02248
+asympeq 0224D
+atilde 000E3
+auml 000E4
+awconint 02233
+awint 02A11
+bNot 02AED
+backcong 0224C
+backepsilon 003F6
+backprime 02035
+backsim 0223D
+backsimeq 022CD
+barvee 022BD
+barwed 02305
+barwedge 02305
+bbrk 023B5
+bbrktbrk 023B6
+bcong 0224C
+bcy 00431
+bdquo 0201E
+becaus 02235
+because 02235
+bemptyv 029B0
+bepsi 003F6
+bernou 0212C
+beta 003B2
+beth 02136
+between 0226C
+bfr 1D51F
+bigcap 022C2
+bigcirc 025EF
+bigcup 022C3
+bigodot 02A00
+bigoplus 02A01
+bigotimes 02A02
+bigsqcup 02A06
+bigstar 02605
+bigtriangledown 025BD
+bigtriangleup 025B3
+biguplus 02A04
+bigvee 022C1
+bigwedge 022C0
+bkarow 0290D
+blacklozenge 029EB
+blacksquare 025AA
+blacktriangle 025B4
+blacktriangledown 025BE
+blacktriangleleft 025C2
+blacktriangleright 025B8
+blank 02423
+blk12 02592
+blk14 02591
+blk34 02593
+block 02588
+bne 0003D 020E5
+bnequiv 02261 020E5
+bnot 02310
+bopf 1D553
+bot 022A5
+bottom 022A5
+bowtie 022C8
+boxDL 02557
+boxDR 02554
+boxDl 02556
+boxDr 02553
+boxH 02550
+boxHD 02566
+boxHU 02569
+boxHd 02564
+boxHu 02567
+boxUL 0255D
+boxUR 0255A
+boxUl 0255C
+boxUr 02559
+boxV 02551
+boxVH 0256C
+boxVL 02563
+boxVR 02560
+boxVh 0256B
+boxVl 02562
+boxVr 0255F
+boxbox 029C9
+boxdL 02555
+boxdR 02552
+boxdl 02510
+boxdr 0250C
+boxh 02500
+boxhD 02565
+boxhU 02568
+boxhd 0252C
+boxhu 02534
+boxminus 0229F
+boxplus 0229E
+boxtimes 022A0
+boxuL 0255B
+boxuR 02558
+boxul 02518
+boxur 02514
+boxv 02502
+boxvH 0256A
+boxvL 02561
+boxvR 0255E
+boxvh 0253C
+boxvl 02524
+boxvr 0251C
+bprime 02035
+breve 002D8
+brvbar 000A6
+bscr 1D4B7
+bsemi 0204F
+bsim 0223D
+bsime 022CD
+bsol 0005C
+bsolb 029C5
+bsolhsub 027C8
+bull 02022
+bullet 02022
+bump 0224E
+bumpE 02AAE
+bumpe 0224F
+bumpeq 0224F
+cacute 00107
+cap 02229
+capand 02A44
+capbrcup 02A49
+capcap 02A4B
+capcup 02A47
+capdot 02A40
+caps 02229 0FE00
+caret 02041
+caron 002C7
+ccaps 02A4D
+ccaron 0010D
+ccedil 000E7
+ccirc 00109
+ccups 02A4C
+ccupssm 02A50
+cdot 0010B
+cedil 000B8
+cemptyv 029B2
+cent 000A2
+centerdot 000B7
+cfr 1D520
+chcy 00447
+check 02713
+checkmark 02713
+chi 003C7
+cir 025CB
+cirE 029C3
+circ 002C6
+circeq 02257
+circlearrowleft 021BA
+circlearrowright 021BB
+circledR 000AE
+circledS 024C8
+circledast 0229B
+circledcirc 0229A
+circleddash 0229D
+cire 02257
+cirfnint 02A10
+cirmid 02AEF
+cirscir 029C2
+clubs 02663
+clubsuit 02663
+colon 0003A
+colone 02254
+coloneq 02254
+comma 0002C
+commat 00040
+comp 02201
+compfn 02218
+complement 02201
+complexes 02102
+cong 02245
+congdot 02A6D
+conint 0222E
+copf 1D554
+coprod 02210
+copy 000A9
+copysr 02117
+crarr 021B5
+cross 02717
+cscr 1D4B8
+csub 02ACF
+csube 02AD1
+csup 02AD0
+csupe 02AD2
+ctdot 022EF
+cudarrl 02938
+cudarrr 02935
+cuepr 022DE
+cuesc 022DF
+cularr 021B6
+cularrp 0293D
+cup 0222A
+cupbrcap 02A48
+cupcap 02A46
+cupcup 02A4A
+cupdot 0228D
+cupor 02A45
+cups 0222A 0FE00
+curarr 021B7
+curarrm 0293C
+curlyeqprec 022DE
+curlyeqsucc 022DF
+curlyvee 022CE
+curlywedge 022CF
+curren 000A4
+curvearrowleft 021B6
+curvearrowright 021B7
+cuvee 022CE
+cuwed 022CF
+cwconint 02232
+cwint 02231
+cylcty 0232D
+dArr 021D3
+dHar 02965
+dagger 02020
+daleth 02138
+darr 02193
+dash 02010
+dashv 022A3
+dbkarow 0290F
+dblac 002DD
+dcaron 0010F
+dcy 00434
+dd 02146
+ddagger 02021
+ddarr 021CA
+ddotseq 02A77
+deg 000B0
+delta 003B4
+demptyv 029B1
+dfisht 0297F
+dfr 1D521
+dharl 021C3
+dharr 021C2
+diam 022C4
+diamond 022C4
+diamondsuit 02666
+diams 02666
+die 000A8
+digamma 003DD
+disin 022F2
+div 000F7
+divide 000F7
+divideontimes 022C7
+divonx 022C7
+djcy 00452
+dlcorn 0231E
+dlcrop 0230D
+dollar 00024
+dopf 1D555
+dot 002D9
+doteq 02250
+doteqdot 02251
+dotminus 02238
+dotplus 02214
+dotsquare 022A1
+doublebarwedge 02306
+downarrow 02193
+downdownarrows 021CA
+downharpoonleft 021C3
+downharpoonright 021C2
+drbkarow 02910
+drcorn 0231F
+drcrop 0230C
+dscr 1D4B9
+dscy 00455
+dsol 029F6
+dstrok 00111
+dtdot 022F1
+dtri 025BF
+dtrif 025BE
+duarr 021F5
+duhar 0296F
+dwangle 029A6
+dzcy 0045F
+dzigrarr 027FF
+eDDot 02A77
+eDot 02251
+eacute 000E9
+easter 02A6E
+ecaron 0011B
+ecir 02256
+ecirc 000EA
+ecolon 02255
+ecy 0044D
+edot 00117
+ee 02147
+efDot 02252
+efr 1D522
+eg 02A9A
+egrave 000E8
+egs 02A96
+egsdot 02A98
+el 02A99
+elinters 023E7
+ell 02113
+els 02A95
+elsdot 02A97
+emacr 00113
+empty 02205
+emptyset 02205
+emptyv 02205
+emsp 02003
+emsp13 02004
+emsp14 02005
+eng 0014B
+ensp 02002
+eogon 00119
+eopf 1D556
+epar 022D5
+eparsl 029E3
+eplus 02A71
+epsi 003B5
+epsilon 003B5
+epsiv 003F5
+eqcirc 02256
+eqcolon 02255
+eqsim 02242
+eqslantgtr 02A96
+eqslantless 02A95
+equals 0003D
+equest 0225F
+equiv 02261
+equivDD 02A78
+eqvparsl 029E5
+erDot 02253
+erarr 02971
+escr 0212F
+esdot 02250
+esim 02242
+eta 003B7
+eth 000F0
+euml 000EB
+euro 020AC
+excl 00021
+exist 02203
+expectation 02130
+exponentiale 02147
+fallingdotseq 02252
+fcy 00444
+female 02640
+ffilig 0FB03
+fflig 0FB00
+ffllig 0FB04
+ffr 1D523
+filig 0FB01
+fjlig 00066 0006A
+flat 0266D
+fllig 0FB02
+fltns 025B1
+fnof 00192
+fopf 1D557
+forall 02200
+fork 022D4
+forkv 02AD9
+fpartint 02A0D
+frac12 000BD
+frac13 02153
+frac14 000BC
+frac15 02155
+frac16 02159
+frac18 0215B
+frac23 02154
+frac25 02156
+frac34 000BE
+frac35 02157
+frac38 0215C
+frac45 02158
+frac56 0215A
+frac58 0215D
+frac78 0215E
+frasl 02044
+frown 02322
+fscr 1D4BB
+gE 02267
+gEl 02A8C
+gacute 001F5
+gamma 003B3
+gammad 003DD
+gap 02A86
+gbreve 0011F
+gcirc 0011D
+gcy 00433
+gdot 00121
+ge 02265
+gel 022DB
+geq 02265
+geqq 02267
+geqslant 02A7E
+ges 02A7E
+gescc 02AA9
+gesdot 02A80
+gesdoto 02A82
+gesdotol 02A84
+gesl 022DB 0FE00
+gesles 02A94
+gfr 1D524
+gg 0226B
+ggg 022D9
+gimel 02137
+gjcy 00453
+gl 02277
+glE 02A92
+gla 02AA5
+glj 02AA4
+gnE 02269
+gnap 02A8A
+gnapprox 02A8A
+gne 02A88
+gneq 02A88
+gneqq 02269
+gnsim 022E7
+gopf 1D558
+grave 00060
+gscr 0210A
+gsim 02273
+gsime 02A8E
+gsiml 02A90
+gt 0003E
+gtcc 02AA7
+gtcir 02A7A
+gtdot 022D7
+gtlPar 02995
+gtquest 02A7C
+gtrapprox 02A86
+gtrarr 02978
+gtrdot 022D7
+gtreqless 022DB
+gtreqqless 02A8C
+gtrless 02277
+gtrsim 02273
+gvertneqq 02269 0FE00
+gvnE 02269 0FE00
+hArr 021D4
+hairsp 0200A
+half 000BD
+hamilt 0210B
+hardcy 0044A
+harr 02194
+harrcir 02948
+harrw 021AD
+hbar 0210F
+hcirc 00125
+hearts 02665
+heartsuit 02665
+hellip 02026
+hercon 022B9
+hfr 1D525
+hksearow 02925
+hkswarow 02926
+hoarr 021FF
+homtht 0223B
+hookleftarrow 021A9
+hookrightarrow 021AA
+hopf 1D559
+horbar 02015
+hscr 1D4BD
+hslash 0210F
+hstrok 00127
+hybull 02043
+hyphen 02010
+iacute 000ED
+ic 02063
+icirc 000EE
+icy 00438
+iecy 00435
+iexcl 000A1
+iff 021D4
+ifr 1D526
+igrave 000EC
+ii 02148
+iiiint 02A0C
+iiint 0222D
+iinfin 029DC
+iiota 02129
+ijlig 00133
+imacr 0012B
+image 02111
+imagline 02110
+imagpart 02111
+imath 00131
+imof 022B7
+imped 001B5
+in 02208
+incare 02105
+infin 0221E
+infintie 029DD
+inodot 00131
+int 0222B
+intcal 022BA
+integers 02124
+intercal 022BA
+intlarhk 02A17
+intprod 02A3C
+iocy 00451
+iogon 0012F
+iopf 1D55A
+iota 003B9
+iprod 02A3C
+iquest 000BF
+iscr 1D4BE
+isin 02208
+isinE 022F9
+isindot 022F5
+isins 022F4
+isinsv 022F3
+isinv 02208
+it 02062
+itilde 00129
+iukcy 00456
+iuml 000EF
+jcirc 00135
+jcy 00439
+jfr 1D527
+jmath 00237
+jopf 1D55B
+jscr 1D4BF
+jsercy 00458
+jukcy 00454
+kappa 003BA
+kappav 003F0
+kcedil 00137
+kcy 0043A
+kfr 1D528
+kgreen 00138
+khcy 00445
+kjcy 0045C
+kopf 1D55C
+kscr 1D4C0
+lAarr 021DA
+lArr 021D0
+lAtail 0291B
+lBarr 0290E
+lE 02266
+lEg 02A8B
+lHar 02962
+lacute 0013A
+laemptyv 029B4
+lagran 02112
+lambda 003BB
+lang 027E8
+langd 02991
+langle 027E8
+lap 02A85
+laquo 000AB
+larr 02190
+larrb 021E4
+larrbfs 0291F
+larrfs 0291D
+larrhk 021A9
+larrlp 021AB
+larrpl 02939
+larrsim 02973
+larrtl 021A2
+lat 02AAB
+latail 02919
+late 02AAD
+lates 02AAD 0FE00
+lbarr 0290C
+lbbrk 02772
+lbrace 0007B
+lbrack 0005B
+lbrke 0298B
+lbrksld 0298F
+lbrkslu 0298D
+lcaron 0013E
+lcedil 0013C
+lceil 02308
+lcub 0007B
+lcy 0043B
+ldca 02936
+ldquo 0201C
+ldquor 0201E
+ldrdhar 02967
+ldrushar 0294B
+ldsh 021B2
+le 02264
+leftarrow 02190
+leftarrowtail 021A2
+leftharpoondown 021BD
+leftharpoonup 021BC
+leftleftarrows 021C7
+leftrightarrow 02194
+leftrightarrows 021C6
+leftrightharpoons 021CB
+leftrightsquigarrow 021AD
+leftthreetimes 022CB
+leg 022DA
+leq 02264
+leqq 02266
+leqslant 02A7D
+les 02A7D
+lescc 02AA8
+lesdot 02A7F
+lesdoto 02A81
+lesdotor 02A83
+lesg 022DA 0FE00
+lesges 02A93
+lessapprox 02A85
+lessdot 022D6
+lesseqgtr 022DA
+lesseqqgtr 02A8B
+lessgtr 02276
+lesssim 02272
+lfisht 0297C
+lfloor 0230A
+lfr 1D529
+lg 02276
+lgE 02A91
+lhard 021BD
+lharu 021BC
+lharul 0296A
+lhblk 02584
+ljcy 00459
+ll 0226A
+llarr 021C7
+llcorner 0231E
+llhard 0296B
+lltri 025FA
+lmidot 00140
+lmoust 023B0
+lmoustache 023B0
+lnE 02268
+lnap 02A89
+lnapprox 02A89
+lne 02A87
+lneq 02A87
+lneqq 02268
+lnsim 022E6
+loang 027EC
+loarr 021FD
+lobrk 027E6
+longleftarrow 027F5
+longleftrightarrow 027F7
+longmapsto 027FC
+longrightarrow 027F6
+looparrowleft 021AB
+looparrowright 021AC
+lopar 02985
+lopf 1D55D
+loplus 02A2D
+lotimes 02A34
+lowast 02217
+lowbar 0005F
+loz 025CA
+lozenge 025CA
+lozf 029EB
+lpar 00028
+lparlt 02993
+lrarr 021C6
+lrcorner 0231F
+lrhar 021CB
+lrhard 0296D
+lrm 0200E
+lrtri 022BF
+lsaquo 02039
+lscr 1D4C1
+lsh 021B0
+lsim 02272
+lsime 02A8D
+lsimg 02A8F
+lsqb 0005B
+lsquo 02018
+lsquor 0201A
+lstrok 00142
+lt 0003C
+ltcc 02AA6
+ltcir 02A79
+ltdot 022D6
+lthree 022CB
+ltimes 022C9
+ltlarr 02976
+ltquest 02A7B
+ltrPar 02996
+ltri 025C3
+ltrie 022B4
+ltrif 025C2
+lurdshar 0294A
+luruhar 02966
+lvertneqq 02268 0FE00
+lvnE 02268 0FE00
+mDDot 0223A
+macr 000AF
+male 02642
+malt 02720
+maltese 02720
+map 021A6
+mapsto 021A6
+mapstodown 021A7
+mapstoleft 021A4
+mapstoup 021A5
+marker 025AE
+mcomma 02A29
+mcy 0043C
+mdash 02014
+measuredangle 02221
+mfr 1D52A
+mho 02127
+micro 000B5
+mid 02223
+midast 0002A
+midcir 02AF0
+middot 000B7
+minus 02212
+minusb 0229F
+minusd 02238
+minusdu 02A2A
+mlcp 02ADB
+mldr 02026
+mnplus 02213
+models 022A7
+mopf 1D55E
+mp 02213
+mscr 1D4C2
+mstpos 0223E
+mu 003BC
+multimap 022B8
+mumap 022B8
+nGg 022D9 00338
+nGt 0226B 020D2
+nGtv 0226B 00338
+nLeftarrow 021CD
+nLeftrightarrow 021CE
+nLl 022D8 00338
+nLt 0226A 020D2
+nLtv 0226A 00338
+nRightarrow 021CF
+nVDash 022AF
+nVdash 022AE
+nabla 02207
+nacute 00144
+nang 02220 020D2
+nap 02249
+napE 02A70 00338
+napid 0224B 00338
+napos 00149
+napprox 02249
+natur 0266E
+natural 0266E
+naturals 02115
+nbsp 000A0
+nbump 0224E 00338
+nbumpe 0224F 00338
+ncap 02A43
+ncaron 00148
+ncedil 00146
+ncong 02247
+ncongdot 02A6D 00338
+ncup 02A42
+ncy 0043D
+ndash 02013
+ne 02260
+neArr 021D7
+nearhk 02924
+nearr 02197
+nearrow 02197
+nedot 02250 00338
+nequiv 02262
+nesear 02928
+nesim 02242 00338
+nexist 02204
+nexists 02204
+nfr 1D52B
+ngE 02267 00338
+nge 02271
+ngeq 02271
+ngeqq 02267 00338
+ngeqslant 02A7E 00338
+nges 02A7E 00338
+ngsim 02275
+ngt 0226F
+ngtr 0226F
+nhArr 021CE
+nharr 021AE
+nhpar 02AF2
+ni 0220B
+nis 022FC
+nisd 022FA
+niv 0220B
+njcy 0045A
+nlArr 021CD
+nlE 02266 00338
+nlarr 0219A
+nldr 02025
+nle 02270
+nleftarrow 0219A
+nleftrightarrow 021AE
+nleq 02270
+nleqq 02266 00338
+nleqslant 02A7D 00338
+nles 02A7D 00338
+nless 0226E
+nlsim 02274
+nlt 0226E
+nltri 022EA
+nltrie 022EC
+nmid 02224
+nopf 1D55F
+not 000AC
+notin 02209
+notinE 022F9 00338
+notindot 022F5 00338
+notinva 02209
+notinvb 022F7
+notinvc 022F6
+notni 0220C
+notniva 0220C
+notnivb 022FE
+notnivc 022FD
+npar 02226
+nparallel 02226
+nparsl 02AFD 020E5
+npart 02202 00338
+npolint 02A14
+npr 02280
+nprcue 022E0
+npre 02AAF 00338
+nprec 02280
+npreceq 02AAF 00338
+nrArr 021CF
+nrarr 0219B
+nrarrc 02933 00338
+nrarrw 0219D 00338
+nrightarrow 0219B
+nrtri 022EB
+nrtrie 022ED
+nsc 02281
+nsccue 022E1
+nsce 02AB0 00338
+nscr 1D4C3
+nshortmid 02224
+nshortparallel 02226
+nsim 02241
+nsime 02244
+nsimeq 02244
+nsmid 02224
+nspar 02226
+nsqsube 022E2
+nsqsupe 022E3
+nsub 02284
+nsubE 02AC5 00338
+nsube 02288
+nsubset 02282 020D2
+nsubseteq 02288
+nsubseteqq 02AC5 00338
+nsucc 02281
+nsucceq 02AB0 00338
+nsup 02285
+nsupE 02AC6 00338
+nsupe 02289
+nsupset 02283 020D2
+nsupseteq 02289
+nsupseteqq 02AC6 00338
+ntgl 02279
+ntilde 000F1
+ntlg 02278
+ntriangleleft 022EA
+ntrianglelefteq 022EC
+ntriangleright 022EB
+ntrianglerighteq 022ED
+nu 003BD
+num 00023
+numero 02116
+numsp 02007
+nvDash 022AD
+nvHarr 02904
+nvap 0224D 020D2
+nvdash 022AC
+nvge 02265 020D2
+nvgt 0003E 020D2
+nvinfin 029DE
+nvlArr 02902
+nvle 02264 020D2
+nvlt 0003C 020D2
+nvltrie 022B4 020D2
+nvrArr 02903
+nvrtrie 022B5 020D2
+nvsim 0223C 020D2
+nwArr 021D6
+nwarhk 02923
+nwarr 02196
+nwarrow 02196
+nwnear 02927
+oS 024C8
+oacute 000F3
+oast 0229B
+ocir 0229A
+ocirc 000F4
+ocy 0043E
+odash 0229D
+odblac 00151
+odiv 02A38
+odot 02299
+odsold 029BC
+oelig 00153
+ofcir 029BF
+ofr 1D52C
+ogon 002DB
+ograve 000F2
+ogt 029C1
+ohbar 029B5
+ohm 003A9
+oint 0222E
+olarr 021BA
+olcir 029BE
+olcross 029BB
+oline 0203E
+olt 029C0
+omacr 0014D
+omega 003C9
+omicron 003BF
+omid 029B6
+ominus 02296
+oopf 1D560
+opar 029B7
+operp 029B9
+oplus 02295
+or 02228
+orarr 021BB
+ord 02A5D
+order 02134
+orderof 02134
+ordf 000AA
+ordm 000BA
+origof 022B6
+oror 02A56
+orslope 02A57
+orv 02A5B
+oscr 02134
+oslash 000F8
+osol 02298
+otilde 000F5
+otimes 02297
+otimesas 02A36
+ouml 000F6
+ovbar 0233D
+par 02225
+para 000B6
+parallel 02225
+parsim 02AF3
+parsl 02AFD
+part 02202
+pcy 0043F
+percnt 00025
+period 0002E
+permil 02030
+perp 022A5
+pertenk 02031
+pfr 1D52D
+phi 003C6
+phiv 003D5
+phmmat 02133
+phone 0260E
+pi 003C0
+pitchfork 022D4
+piv 003D6
+planck 0210F
+planckh 0210E
+plankv 0210F
+plus 0002B
+plusacir 02A23
+plusb 0229E
+pluscir 02A22
+plusdo 02214
+plusdu 02A25
+pluse 02A72
+plusmn 000B1
+plussim 02A26
+plustwo 02A27
+pm 000B1
+pointint 02A15
+popf 1D561
+pound 000A3
+pr 0227A
+prE 02AB3
+prap 02AB7
+prcue 0227C
+pre 02AAF
+prec 0227A
+precapprox 02AB7
+preccurlyeq 0227C
+preceq 02AAF
+precnapprox 02AB9
+precneqq 02AB5
+precnsim 022E8
+precsim 0227E
+prime 02032
+primes 02119
+prnE 02AB5
+prnap 02AB9
+prnsim 022E8
+prod 0220F
+profalar 0232E
+profline 02312
+profsurf 02313
+prop 0221D
+propto 0221D
+prsim 0227E
+prurel 022B0
+pscr 1D4C5
+psi 003C8
+puncsp 02008
+qfr 1D52E
+qint 02A0C
+qopf 1D562
+qprime 02057
+qscr 1D4C6
+quaternions 0210D
+quatint 02A16
+quest 0003F
+questeq 0225F
+quot 00022
+rAarr 021DB
+rArr 021D2
+rAtail 0291C
+rBarr 0290F
+rHar 02964
+race 0223D 00331
+racute 00155
+radic 0221A
+raemptyv 029B3
+rang 027E9
+rangd 02992
+range 029A5
+rangle 027E9
+raquo 000BB
+rarr 02192
+rarrap 02975
+rarrb 021E5
+rarrbfs 02920
+rarrc 02933
+rarrfs 0291E
+rarrhk 021AA
+rarrlp 021AC
+rarrpl 02945
+rarrsim 02974
+rarrtl 021A3
+rarrw 0219D
+ratail 0291A
+ratio 02236
+rationals 0211A
+rbarr 0290D
+rbbrk 02773
+rbrace 0007D
+rbrack 0005D
+rbrke 0298C
+rbrksld 0298E
+rbrkslu 02990
+rcaron 00159
+rcedil 00157
+rceil 02309
+rcub 0007D
+rcy 00440
+rdca 02937
+rdldhar 02969
+rdquo 0201D
+rdquor 0201D
+rdsh 021B3
+real 0211C
+realine 0211B
+realpart 0211C
+reals 0211D
+rect 025AD
+reg 000AE
+rfisht 0297D
+rfloor 0230B
+rfr 1D52F
+rhard 021C1
+rharu 021C0
+rharul 0296C
+rho 003C1
+rhov 003F1
+rightarrow 02192
+rightarrowtail 021A3
+rightharpoondown 021C1
+rightharpoonup 021C0
+rightleftarrows 021C4
+rightleftharpoons 021CC
+rightrightarrows 021C9
+rightsquigarrow 0219D
+rightthreetimes 022CC
+ring 002DA
+risingdotseq 02253
+rlarr 021C4
+rlhar 021CC
+rlm 0200F
+rmoust 023B1
+rmoustache 023B1
+rnmid 02AEE
+roang 027ED
+roarr 021FE
+robrk 027E7
+ropar 02986
+ropf 1D563
+roplus 02A2E
+rotimes 02A35
+rpar 00029
+rpargt 02994
+rppolint 02A12
+rrarr 021C9
+rsaquo 0203A
+rscr 1D4C7
+rsh 021B1
+rsqb 0005D
+rsquo 02019
+rsquor 02019
+rthree 022CC
+rtimes 022CA
+rtri 025B9
+rtrie 022B5
+rtrif 025B8
+rtriltri 029CE
+ruluhar 02968
+rx 0211E
+sacute 0015B
+sbquo 0201A
+sc 0227B
+scE 02AB4
+scap 02AB8
+scaron 00161
+sccue 0227D
+sce 02AB0
+scedil 0015F
+scirc 0015D
+scnE 02AB6
+scnap 02ABA
+scnsim 022E9
+scpolint 02A13
+scsim 0227F
+scy 00441
+sdot 022C5
+sdotb 022A1
+sdote 02A66
+seArr 021D8
+searhk 02925
+searr 02198
+searrow 02198
+sect 000A7
+semi 0003B
+seswar 02929
+setminus 02216
+setmn 02216
+sext 02736
+sfr 1D530
+sfrown 02322
+sharp 0266F
+shchcy 00449
+shcy 00448
+shortmid 02223
+shortparallel 02225
+shy 000AD
+sigma 003C3
+sigmaf 003C2
+sigmav 003C2
+sim 0223C
+simdot 02A6A
+sime 02243
+simeq 02243
+simg 02A9E
+simgE 02AA0
+siml 02A9D
+simlE 02A9F
+simne 02246
+simplus 02A24
+simrarr 02972
+slarr 02190
+smallsetminus 02216
+smashp 02A33
+smeparsl 029E4
+smid 02223
+smile 02323
+smt 02AAA
+smte 02AAC
+smtes 02AAC 0FE00
+softcy 0044C
+sol 0002F
+solb 029C4
+solbar 0233F
+sopf 1D564
+spades 02660
+spadesuit 02660
+spar 02225
+sqcap 02293
+sqcaps 02293 0FE00
+sqcup 02294
+sqcups 02294 0FE00
+sqsub 0228F
+sqsube 02291
+sqsubset 0228F
+sqsubseteq 02291
+sqsup 02290
+sqsupe 02292
+sqsupset 02290
+sqsupseteq 02292
+squ 025A1
+square 025A1
+squarf 025AA
+squf 025AA
+srarr 02192
+sscr 1D4C8
+ssetmn 02216
+ssmile 02323
+sstarf 022C6
+star 02606
+starf 02605
+straightepsilon 003F5
+straightphi 003D5
+strns 000AF
+sub 02282
+subE 02AC5
+subdot 02ABD
+sube 02286
+subedot 02AC3
+submult 02AC1
+subnE 02ACB
+subne 0228A
+subplus 02ABF
+subrarr 02979
+subset 02282
+subseteq 02286
+subseteqq 02AC5
+subsetneq 0228A
+subsetneqq 02ACB
+subsim 02AC7
+subsub 02AD5
+subsup 02AD3
+succ 0227B
+succapprox 02AB8
+succcurlyeq 0227D
+succeq 02AB0
+succnapprox 02ABA
+succneqq 02AB6
+succnsim 022E9
+succsim 0227F
+sum 02211
+sung 0266A
+sup 02283
+sup1 000B9
+sup2 000B2
+sup3 000B3
+supE 02AC6
+supdot 02ABE
+supdsub 02AD8
+supe 02287
+supedot 02AC4
+suphsol 027C9
+suphsub 02AD7
+suplarr 0297B
+supmult 02AC2
+supnE 02ACC
+supne 0228B
+supplus 02AC0
+supset 02283
+supseteq 02287
+supseteqq 02AC6
+supsetneq 0228B
+supsetneqq 02ACC
+supsim 02AC8
+supsub 02AD4
+supsup 02AD6
+swArr 021D9
+swarhk 02926
+swarr 02199
+swarrow 02199
+swnwar 0292A
+szlig 000DF
+target 02316
+tau 003C4
+tbrk 023B4
+tcaron 00165
+tcedil 00163
+tcy 00442
+tdot 020DB
+telrec 02315
+tfr 1D531
+there4 02234
+therefore 02234
+theta 003B8
+thetasym 003D1
+thetav 003D1
+thickapprox 02248
+thicksim 0223C
+thinsp 02009
+thkap 02248
+thksim 0223C
+thorn 000FE
+tilde 002DC
+times 000D7
+timesb 022A0
+timesbar 02A31
+timesd 02A30
+tint 0222D
+toea 02928
+top 022A4
+topbot 02336
+topcir 02AF1
+topf 1D565
+topfork 02ADA
+tosa 02929
+tprime 02034
+trade 02122
+triangle 025B5
+triangledown 025BF
+triangleleft 025C3
+trianglelefteq 022B4
+triangleq 0225C
+triangleright 025B9
+trianglerighteq 022B5
+tridot 025EC
+trie 0225C
+triminus 02A3A
+triplus 02A39
+trisb 029CD
+tritime 02A3B
+trpezium 023E2
+tscr 1D4C9
+tscy 00446
+tshcy 0045B
+tstrok 00167
+twixt 0226C
+twoheadleftarrow 0219E
+twoheadrightarrow 021A0
+uArr 021D1
+uHar 02963
+uacute 000FA
+uarr 02191
+ubrcy 0045E
+ubreve 0016D
+ucirc 000FB
+ucy 00443
+udarr 021C5
+udblac 00171
+udhar 0296E
+ufisht 0297E
+ufr 1D532
+ugrave 000F9
+uharl 021BF
+uharr 021BE
+uhblk 02580
+ulcorn 0231C
+ulcorner 0231C
+ulcrop 0230F
+ultri 025F8
+umacr 0016B
+uml 000A8
+uogon 00173
+uopf 1D566
+uparrow 02191
+updownarrow 02195
+upharpoonleft 021BF
+upharpoonright 021BE
+uplus 0228E
+upsi 003C5
+upsih 003D2
+upsilon 003C5
+upuparrows 021C8
+urcorn 0231D
+urcorner 0231D
+urcrop 0230E
+uring 0016F
+urtri 025F9
+uscr 1D4CA
+utdot 022F0
+utilde 00169
+utri 025B5
+utrif 025B4
+uuarr 021C8
+uuml 000FC
+uwangle 029A7
+vArr 021D5
+vBar 02AE8
+vBarv 02AE9
+vDash 022A8
+vangrt 0299C
+varepsilon 003F5
+varkappa 003F0
+varnothing 02205
+varphi 003D5
+varpi 003D6
+varpropto 0221D
+varr 02195
+varrho 003F1
+varsigma 003C2
+varsubsetneq 0228A 0FE00
+varsubsetneqq 02ACB 0FE00
+varsupsetneq 0228B 0FE00
+varsupsetneqq 02ACC 0FE00
+vartheta 003D1
+vartriangleleft 022B2
+vartriangleright 022B3
+vcy 00432
+vdash 022A2
+vee 02228
+veebar 022BB
+veeeq 0225A
+vellip 022EE
+verbar 0007C
+vert 0007C
+vfr 1D533
+vltri 022B2
+vnsub 02282 020D2
+vnsup 02283 020D2
+vopf 1D567
+vprop 0221D
+vrtri 022B3
+vscr 1D4CB
+vsubnE 02ACB 0FE00
+vsubne 0228A 0FE00
+vsupnE 02ACC 0FE00
+vsupne 0228B 0FE00
+vzigzag 0299A
+wcirc 00175
+wedbar 02A5F
+wedge 02227
+wedgeq 02259
+weierp 02118
+wfr 1D534
+wopf 1D568
+wp 02118
+wr 02240
+wreath 02240
+wscr 1D4CC
+xcap 022C2
+xcirc 025EF
+xcup 022C3
+xdtri 025BD
+xfr 1D535
+xhArr 027FA
+xharr 027F7
+xi 003BE
+xlArr 027F8
+xlarr 027F5
+xmap 027FC
+xnis 022FB
+xodot 02A00
+xopf 1D569
+xoplus 02A01
+xotime 02A02
+xrArr 027F9
+xrarr 027F6
+xscr 1D4CD
+xsqcup 02A06
+xuplus 02A04
+xutri 025B3
+xvee 022C1
+xwedge 022C0
+yacute 000FD
+yacy 0044F
+ycirc 00177
+ycy 0044B
+yen 000A5
+yfr 1D536
+yicy 00457
+yopf 1D56A
+yscr 1D4CE
+yucy 0044E
+yuml 000FF
+zacute 0017A
+zcaron 0017E
+zcy 00437
+zdot 0017C
+zeetrf 02128
+zeta 003B6
+zfr 1D537
+zhcy 00436
+zigrarr 021DD
+zopf 1D56B
+zscr 1D4CF
+zwj 0200D
+zwnj 0200C \ No newline at end of file
diff --git a/ext/standard/html_tables/ents_xhtml.txt b/ext/standard/html_tables/ents_xhtml.txt
new file mode 100644
index 0000000000..81800bcd2d
--- /dev/null
+++ b/ext/standard/html_tables/ents_xhtml.txt
@@ -0,0 +1,253 @@
+nbsp 00A0
+iexcl 00A1
+cent 00A2
+pound 00A3
+curren 00A4
+yen 00A5
+brvbar 00A6
+sect 00A7
+uml 00A8
+copy 00A9
+ordf 00AA
+laquo 00AB
+not 00AC
+shy 00AD
+reg 00AE
+macr 00AF
+deg 00B0
+plusmn 00B1
+sup2 00B2
+sup3 00B3
+acute 00B4
+micro 00B5
+para 00B6
+middot 00B7
+cedil 00B8
+sup1 00B9
+ordm 00BA
+raquo 00BB
+frac14 00BC
+frac12 00BD
+frac34 00BE
+iquest 00BF
+Agrave 00C0
+Aacute 00C1
+Acirc 00C2
+Atilde 00C3
+Auml 00C4
+Aring 00C5
+AElig 00C6
+Ccedil 00C7
+Egrave 00C8
+Eacute 00C9
+Ecirc 00CA
+Euml 00CB
+Igrave 00CC
+Iacute 00CD
+Icirc 00CE
+Iuml 00CF
+ETH 00D0
+Ntilde 00D1
+Ograve 00D2
+Oacute 00D3
+Ocirc 00D4
+Otilde 00D5
+Ouml 00D6
+times 00D7
+Oslash 00D8
+Ugrave 00D9
+Uacute 00DA
+Ucirc 00DB
+Uuml 00DC
+Yacute 00DD
+THORN 00DE
+szlig 00DF
+agrave 00E0
+aacute 00E1
+acirc 00E2
+atilde 00E3
+auml 00E4
+aring 00E5
+aelig 00E6
+ccedil 00E7
+egrave 00E8
+eacute 00E9
+ecirc 00EA
+euml 00EB
+igrave 00EC
+iacute 00ED
+icirc 00EE
+iuml 00EF
+eth 00F0
+ntilde 00F1
+ograve 00F2
+oacute 00F3
+ocirc 00F4
+otilde 00F5
+ouml 00F6
+divide 00F7
+oslash 00F8
+ugrave 00F9
+uacute 00FA
+ucirc 00FB
+uuml 00FC
+yacute 00FD
+thorn 00FE
+yuml 00FF
+quot 0022
+amp 0026
+lt 003C
+gt 003E
+apos 0027
+OElig 0152
+oelig 0153
+Scaron 0160
+scaron 0161
+Yuml 0178
+circ 02C6
+tilde 02DC
+ensp 2002
+emsp 2003
+thinsp 2009
+zwnj 200C
+zwj 200D
+lrm 200E
+rlm 200F
+ndash 2013
+mdash 2014
+lsquo 2018
+rsquo 2019
+sbquo 201A
+ldquo 201C
+rdquo 201D
+bdquo 201E
+dagger 2020
+Dagger 2021
+permil 2030
+lsaquo 2039
+rsaquo 203A
+euro 20AC
+fnof 0192
+Alpha 0391
+Beta 0392
+Gamma 0393
+Delta 0394
+Epsilon 0395
+Zeta 0396
+Eta 0397
+Theta 0398
+Iota 0399
+Kappa 039A
+Lambda 039B
+Mu 039C
+Nu 039D
+Xi 039E
+Omicron 039F
+Pi 03A0
+Rho 03A1
+Sigma 03A3
+Tau 03A4
+Upsilon 03A5
+Phi 03A6
+Chi 03A7
+Psi 03A8
+Omega 03A9
+alpha 03B1
+beta 03B2
+gamma 03B3
+delta 03B4
+epsilon 03B5
+zeta 03B6
+eta 03B7
+theta 03B8
+iota 03B9
+kappa 03BA
+lambda 03BB
+mu 03BC
+nu 03BD
+xi 03BE
+omicron 03BF
+pi 03C0
+rho 03C1
+sigmaf 03C2
+sigma 03C3
+tau 03C4
+upsilon 03C5
+phi 03C6
+chi 03C7
+psi 03C8
+omega 03C9
+thetasym 03D1
+upsih 03D2
+piv 03D6
+bull 2022
+hellip 2026
+prime 2032
+Prime 2033
+oline 203E
+frasl 2044
+weierp 2118
+image 2111
+real 211C
+trade 2122
+alefsym 2135
+larr 2190
+uarr 2191
+rarr 2192
+darr 2193
+harr 2194
+crarr 21B5
+lArr 21D0
+uArr 21D1
+rArr 21D2
+dArr 21D3
+hArr 21D4
+forall 2200
+part 2202
+exist 2203
+empty 2205
+nabla 2207
+isin 2208
+notin 2209
+ni 220B
+prod 220F
+sum 2211
+minus 2212
+lowast 2217
+radic 221A
+prop 221D
+infin 221E
+ang 2220
+and 2227
+or 2228
+cap 2229
+cup 222A
+int 222B
+there4 2234
+sim 223C
+cong 2245
+asymp 2248
+ne 2260
+equiv 2261
+le 2264
+ge 2265
+sub 2282
+sup 2283
+nsub 2284
+sube 2286
+supe 2287
+oplus 2295
+otimes 2297
+perp 22A5
+sdot 22C5
+lceil 2308
+rceil 2309
+lfloor 230A
+rfloor 230B
+lang 2329
+rang 232A
+loz 25CA
+spades 2660
+clubs 2663
+hearts 2665
+diams 2666 \ No newline at end of file
diff --git a/ext/standard/html_tables/html_table_gen.php b/ext/standard/html_tables/html_table_gen.php
new file mode 100644
index 0000000000..7e7314fa35
--- /dev/null
+++ b/ext/standard/html_tables/html_table_gen.php
@@ -0,0 +1,812 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* This file prints to stdout the contents of ext/standard/html_tables.h */
+/* put together with glue; have patience */
+
+$t = <<<CODE
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-%s The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+*/
+
+/* \$Id$ */
+
+#ifndef HTML_TABLES_H
+#define HTML_TABLES_H
+
+/**************************************************************************
+***************************************************************************
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY IT. **
+***************************************************************************
+** Please change html_tables/html_table_gen.php instead and then **
+** run it in order to generate this file **
+***************************************************************************
+**************************************************************************/
+
+enum entity_charset { cs_utf_8, cs_8859_1, cs_cp1252, cs_8859_15, cs_cp1251,
+ cs_8859_5, cs_cp866, cs_macroman, cs_koi8r, cs_big5,
+ cs_gb2312, cs_big5hkscs, cs_sjis, cs_eucjp,
+ cs_numelems /* used to count the number of charsets */
+ };
+#define CHARSET_UNICODE_COMPAT(cs) ((cs) <= cs_8859_1)
+#define CHARSET_SINGLE_BYTE(cs) ((cs) > cs_utf_8 && (cs) < cs_big5)
+#define CHARSET_PARTIAL_SUPPORT(cs) ((cs) >= cs_big5)
+
+static const struct {
+ const char *codeset;
+ enum entity_charset charset;
+} charset_map[] = {
+ { "ISO-8859-1", cs_8859_1 },
+ { "ISO8859-1", cs_8859_1 },
+ { "ISO-8859-15", cs_8859_15 },
+ { "ISO8859-15", cs_8859_15 },
+ { "utf-8", cs_utf_8 },
+ { "cp1252", cs_cp1252 },
+ { "Windows-1252", cs_cp1252 },
+ { "1252", cs_cp1252 },
+ { "BIG5", cs_big5 },
+ { "950", cs_big5 },
+ { "GB2312", cs_gb2312 },
+ { "936", cs_gb2312 },
+ { "BIG5-HKSCS", cs_big5hkscs },
+ { "Shift_JIS", cs_sjis },
+ { "SJIS", cs_sjis },
+ { "932", cs_sjis },
+ { "EUCJP", cs_eucjp },
+ { "EUC-JP", cs_eucjp },
+ { "KOI8-R", cs_koi8r },
+ { "koi8-ru", cs_koi8r },
+ { "koi8r", cs_koi8r },
+ { "cp1251", cs_cp1251 },
+ { "Windows-1251", cs_cp1251 },
+ { "win-1251", cs_cp1251 },
+ { "iso8859-5", cs_8859_5 },
+ { "iso-8859-5", cs_8859_5 },
+ { "cp866", cs_cp866 },
+ { "866", cs_cp866 },
+ { "ibm866", cs_cp866 },
+ { "MacRoman", cs_macroman },
+ { NULL }
+};
+
+/* longest entity name length excluding & and ; */
+#define LONGEST_ENTITY_LENGTH 31
+
+/* Definitions for mappings *to* Unicode.
+ * The origin charset must have at most 256 code points.
+ * The multi-byte encodings are not supported */
+typedef struct {
+ unsigned short uni_cp[64];
+} enc_to_uni_stage2;
+
+typedef struct {
+ const enc_to_uni_stage2 *inner[4];
+} enc_to_uni;
+
+/* bits 7-8 bits (only single bytes encodings supported )*/
+#define ENT_ENC_TO_UNI_STAGE1(k) ((k & 0xC0) >> 6)
+/* bits 1-6 */
+#define ENT_ENC_TO_UNI_STAGE2(k) ((k) & 0x3F)
+
+
+CODE;
+
+echo sprintf($t, date("Y"));
+
+$encodings = array(
+ array(
+ "ident" => "iso88591",
+ "enumid" => 1,
+ "name" => "ISO-8859-1",
+ "file" => "mappings/8859-1.TXT",
+ ),
+ array(
+ "ident" => "iso88595",
+ "enumid" => 5,
+ "name" => "ISO-8859-5",
+ "file" => "mappings/8859-5.TXT",
+ ),
+ array(
+ "ident" => "iso885915",
+ "enumid" => 3,
+ "name" => "ISO-8859-15",
+ "file" => "mappings/8859-15.TXT",
+ ),
+ array(
+ "ident" => "win1252",
+ "enumid" => 2,
+ "enumident" => "cp1252",
+ "name" => "Windows-1252",
+ "file" => "mappings/CP1252.TXT",
+ ),
+ array(
+ "ident" => "win1251",
+ "enumid" => 4,
+ "enumident" => "cp1252",
+ "name" => "Windows-1251",
+ "file" => "mappings/CP1251.TXT",
+ ),
+ array(
+ "ident" => "koi8r",
+ "enumid" => 8,
+ "name" => "KOI8-R",
+ "file" => "mappings/KOI8-R.TXT",
+ ),
+ array(
+ "ident" => "cp866",
+ "enumid" => 6,
+ "name" => "CP-866",
+ "file" => "mappings/CP866.TXT",
+ ),
+ array(
+ "ident" => "macroman",
+ "enumid" => 7,
+ "name" => "MacRoman",
+ "file" => "mappings/ROMAN.TXT",
+ ),
+);
+
+$prevStage2 = array();
+
+foreach ($encodings as $e) {
+ echo
+"/* {{{ Mappings *to* Unicode for {$e['name']} */\n\n";
+
+ /* process file */
+ $map = array();
+ $lines = explode("\n", file_get_contents($e{'file'}));
+ foreach ($lines as $l) {
+ if (preg_match("/^0x([0-9A-Z]{2})\t0x([0-9A-Z]{2,})/i", $l, $matches))
+ $map[] = array($matches[1], $matches[2]);
+ }
+
+ $mappy = array();
+ foreach ($map as $v) { $mappy[hexdec($v[0])] = hexdec($v[1]); }
+
+ $mstable = array("ident" => $e['ident']);
+ /* calculate two-stage tables */
+ for ($i = 0; $i < 4; $i++) {
+ for ($j = 0; $j < 64; $j++) {
+ $cp = $i << 6 | $j;
+ $mstable[$i][$j] = isset($mappy[$cp]) ? $mappy[$cp] : NULL;
+ }
+ }
+
+ echo
+"/* {{{ Stage 2 tables for {$e['name']} */\n\n";
+
+ $s2tables_idents = array();
+ for ($i = 0; $i < 4; $i++) {
+ if (($t = array_keys($prevStage2, $mstable[$i])) !== array()) {
+ $s2tables_idents[$i] = $encodings[$t[0]/5]["ident"];
+ continue;
+ }
+
+ $s2tables_idents[$i] = $e["ident"];
+
+ echo "static const enc_to_uni_stage2 enc_to_uni_s2_{$e['ident']}_".
+ sprintf("%02X", $i << 6)." = { {\n";
+ for ($j = 0; $j < 64; $j++) {
+ if ($j == 0) echo "\t";
+ elseif ($j % 6 == 0) echo "\n\t";
+ else echo " ";
+ if ($mstable[$i][$j] !== NULL)
+ echo sprintf("0x%04X,", $mstable[$i][$j]);
+ else
+ echo "0xFFFF,"; /* special value; indicates no mapping */
+ }
+ echo "\n} };\n\n";
+
+ $prevStage2[] = $mstable[$i];
+ }
+
+ echo
+"/* end of stage 2 tables for {$e['name']} }}} */\n\n";
+
+ echo
+"/* {{{ Stage 1 table for {$e['name']} */\n";
+
+ echo
+"static const enc_to_uni enc_to_uni_{$e['ident']} = { {
+\t&enc_to_uni_s2_{$s2tables_idents[0]}_00,
+\t&enc_to_uni_s2_{$s2tables_idents[1]}_40,
+\t&enc_to_uni_s2_{$s2tables_idents[2]}_80,
+\t&enc_to_uni_s2_{$s2tables_idents[3]}_C0 }
+};
+";
+
+ echo
+"/* end of stage 1 table for {$e['name']} }}} */\n\n";
+}
+
+$maxencnum = max(array_map(function($e) { return $e['enumid']; }, $encodings));
+$a = range(0, $maxencnum);
+foreach ($encodings as $e) { $a[$e['enumid']] = $e['ident']; }
+
+ echo
+"/* {{{ Index of tables for encoding conversion */
+static const enc_to_uni *const enc_to_uni_index[cs_numelems] = {\n";
+
+foreach ($a as $k => $v) {
+ if (is_numeric($v))
+ echo "\tNULL,\n";
+ else
+ echo "\t&enc_to_uni_$v,\n";
+}
+
+ echo
+"};
+/* }}} */\n";
+
+$t = <<<CODE
+
+/* Definitions for mappings *from* Unicode */
+
+typedef struct {
+ unsigned short un_code_point; /* we don't need bigger */
+ unsigned char cs_code; /* currently, we only have maps to single-byte encodings */
+} uni_to_enc;
+
+
+CODE;
+
+echo $t;
+
+$encodings = array(
+ array(
+ "ident" => "iso885915",
+ "name" => "ISO-8859-15",
+ "file" => "mappings/8859-15.TXT",
+ "range" => array(0xA4, 0xBE),
+ ),
+ array(
+ "ident" => "win1252",
+ "name" => "Windows-1252",
+ "file" => "mappings/CP1252.TXT",
+ "range" => array(0x80, 0x9F),
+ ),
+ array(
+ "ident" => "win1251",
+ "name" => "Windows-1251",
+ "file" => "mappings/CP1251.TXT",
+ "range" => array(0x80, 0xFF),
+ ),
+ array(
+ "ident" => "koi8r",
+ "name" => "KOI8-R",
+ "file" => "mappings/KOI8-R.TXT",
+ "range" => array(0x80, 0xFF),
+ ),
+ array(
+ "ident" => "cp866",
+ "name" => "CP-866",
+ "file" => "mappings/CP866.TXT",
+ "range" => array(0x80, 0xFF),
+ ),
+ array(
+ "ident" => "macroman",
+ "name" => "MacRoman",
+ "file" => "mappings/ROMAN.TXT",
+ "range" => array(0x80, 0xFF),
+ ),
+);
+
+foreach ($encodings as $e) {
+ echo
+"/* {{{ Mappings *from* Unicode for {$e['name']} */\n";
+
+ /* process file */
+ $map = array();
+ $lines = explode("\n", file_get_contents($e{'file'}));
+ foreach ($lines as $l) {
+ if (preg_match("/^0x([0-9A-Z]{2})\t0x([0-9A-Z]{2,})\s+#\s*(.*)$/i", $l, $matches))
+ $map[] = array($matches[1], $matches[2], rtrim($matches[3]));
+ }
+
+ $mappy = array();
+ foreach ($map as $v) {
+ if (hexdec($v[0]) >= $e['range'][0] && hexdec($v[0]) <= $e['range'][1])
+ $mappy[hexdec($v[1])] = array(hexdec($v[0]), strtolower($v[2]));
+ }
+ ksort($mappy);
+
+ echo
+"static const uni_to_enc unimap_{$e['ident']}[] = {\n";
+
+ foreach ($mappy as $k => $v) {
+ echo "\t{ ", sprintf("0x%04X", $k), ", ", sprintf("0x%02X", $v[0]), " },\t/* ",
+ $v[1], " */\n";
+ }
+ echo "};\n";
+
+ echo
+"/* {{{ end of mappings *from* Unicode for {$e['name']} */\n\n";
+}
+
+$data = file_get_contents("ents_html5.txt");
+$pass2 = false;
+$name = "HTML5";
+$ident = "html5";
+again:
+
+$t = <<<'CODE'
+/* HTML 5 has many more named entities.
+ * Some of them map to two unicode code points, not one.
+ * We're going to use a three-stage table (with an extra one for the entities
+ * with two code points). */
+
+#define ENT_STAGE1_INDEX(k) (((k) & 0xFFF000) >> 12) /* > 1D, we have no mapping */
+#define ENT_STAGE2_INDEX(k) (((k) & 0xFC0) >> 6)
+#define ENT_STAGE3_INDEX(k) ((k) & 0x3F)
+#define ENT_CODE_POINT_FROM_STAGES(i,j,k) (((i) << 12) | ((j) << 6) | (k))
+
+/* Table should be organized with a leading row telling the size of
+ * the table and the default entity (maybe NULL) and the rest being
+ * normal rows ordered by code point so that we can do a binary search */
+typedef union {
+ struct {
+ unsigned size; /* number of remaining entries in the table */
+ const char *default_entity;
+ unsigned short default_entity_len;
+ } leading_entry;
+ struct {
+ unsigned second_cp; /* second code point */
+ const char *entity;
+ unsigned short entity_len;
+ } normal_entry;
+} entity_multicodepoint_row;
+
+/* blocks of these should start at code points k where k % 0xFC0 == 0 */
+typedef struct {
+ char ambiguous; /* if 0 look into entity */
+ union {
+ struct {
+ const char *entity; /* may be NULL */
+ unsigned short entity_len;
+ } ent;
+ const entity_multicodepoint_row *multicodepoint_table;
+ } data;
+} entity_stage3_row;
+
+/* Calculate k & 0x3F Use as offset */
+typedef const entity_stage3_row *entity_stage2_row; /* 64 elements */
+
+/* Calculate k & 0xFC0 >> 6. Use as offset */
+typedef const entity_stage3_row *const *entity_stage1_row; /* 64 elements */
+
+/* For stage 1, Calculate k & 0xFFF000 >> 3*4.
+ * If larger than 1D, we have no mapping. Otherwise lookup that index */
+
+typedef struct {
+ const entity_stage1_row *ms_table;
+ /* for tables with only basic entities, this member is to be accessed
+ * directly for better performance: */
+ const entity_stage3_row *table;
+} entity_table_opt;
+
+/* Replaced "GT" > "gt" and "QUOT" > "quot" for consistency's sake. */
+
+
+CODE;
+
+if (!$pass2)
+ echo $t;
+
+$dp = array();
+
+foreach (explode("\n", $data) as $l) {
+ if (preg_match('/^(#?[a-z0-9]+)\s+([a-f0-9]+) ([a-f0-9]+)/i', $l, $matches)) {
+ //echo sprintf("\t{\"%-21s 1, 0x%05d},\n", $matches[1].",", $matches[2]);
+ $dp[] = array($matches[1], $matches[2], $matches[3]);
+ } else if (preg_match('/^(#?[a-z0-9]+)\s+([a-f0-9]+)/i', $l, $matches)) {
+ $dp[] = array($matches[1], $matches[2]);
+ }
+}
+
+$origdp = $dp;
+
+usort($dp, function($a, $b) { return hexdec($a[1])-hexdec($b[1]); });
+
+$multicp_rows = array();
+foreach ($dp as $el) {
+ if (count($el) == 3) {
+ $multicp_rows[$el[1]] = array();
+ }
+}
+
+foreach ($dp as $el) {
+ if (key_exists($el[1], $multicp_rows)) {
+ if (count($el) == 3)
+ $multicp_rows[$el[1]][$el[2]] = $el[0];
+ else
+ $multicp_rows[$el[1]]["default"] = $el[0];
+ }
+}
+
+if ($pass2 < 2)
+ echo "/* {{{ Start of $name multi-stage table for codepoint -> entity */", "\n\n";
+else
+ echo "/* {{{ Start of $name table for codepoint -> entity */", "\n\n";
+
+if (empty($multicp_rows))
+ goto skip_multicp;
+
+ksort($multicp_rows);
+foreach ($multicp_rows as &$v) { ksort($v); }
+
+echo
+"/* {{{ Start of double code point tables for $name */", "\n\n";
+
+foreach ($multicp_rows as $k => $v) {
+ echo "static const entity_multicodepoint_row multi_cp_{$ident}_",
+ sprintf("%05s", $k), "[] = {", "\n";
+ if (key_exists("default", $v)) {
+ if ($v['default'] == 'GT') /* hack to make > translate to &gt; not GT; */
+ $v['default'] = "gt";
+ echo "\t{ {", sprintf("%02d", count($v) - 1),
+ ",\t\t", sprintf("\"%-21s", $v["default"].'",'), "\t",
+ sprintf("% 2d", strlen($v["default"])), '} },', "\n";
+ } else {
+ echo "\t{ {", sprintf("%02d", count($v)),
+ ",\t\t", sprintf("%-22s", 'NULL'), ",\t0} },\n";
+ }
+ unset($v["default"]);
+ foreach ($v as $l => $w) {
+ echo "\t{ {", sprintf("0x%05s", $l), ",\t", sprintf("\"%-21s", $w.'",'), "\t",
+ sprintf("% 2d", strlen($w)), '} },', "\n";
+ }
+ echo "};\n";
+}
+echo "\n/* End of double code point tables }}} */", "\n\n";
+
+skip_multicp:
+
+if ($pass2 < 2)
+ echo "/* {{{ Stage 3 Tables for $name */", "\n\n";
+
+$t = <<<CODE
+static const entity_stage3_row empty_stage3_table[] = {
+ /* 64 elements */
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+ {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } }, {0, { {NULL, 0} } },
+};
+
+CODE;
+
+if (!$pass2)
+ echo $t;
+
+$mstable = array();
+foreach ($dp as $el) {
+ $s1 = (hexdec($el[1]) & 0xFFF000) >> 12;
+ $s2 = (hexdec($el[1]) & 0xFC0) >> 6;
+ $s3 = hexdec($el[1]) & 0x3F;
+ if (key_exists($el[1], $multicp_rows)) {
+ $mstable[$s1][$s2][$s3] = "";
+ } else {
+ $mstable[$s1][$s2][$s3] = $el[0];
+ }
+}
+
+for ($i = 0; $i < 0x1E; $i++) {
+ for ($k = 0; $k < 64; $k++) {
+ $any3 = false;
+ $col3 = array();
+ for ($l = 0; $l < 64; $l++) {
+ if (isset($mstable[$i][$k][$l])) {
+ $any3 = true;
+ $col3[$l] = $mstable[$i][$k][$l];
+ } else {
+ $col3[$l] = null;
+ }
+ }
+ if ($any3) {
+ echo "static const entity_stage3_row stage3_table_{$ident}_",
+ sprintf("%02X%03X", $i, $k << 6), "[] = {\n";
+ foreach ($col3 as $y => $z) {
+ if ($y == 0) echo "\t";
+ elseif ($y % 4 == 0) echo "\n\t";
+ else echo " ";
+ if ($z === NULL)
+ echo "{0, { {NULL, 0} } },";
+ elseif ($z === "QUOT") /* hack to translate " into &quote;, not &QUOT; */
+ echo "{0, { {\"quot\", 4} } },";
+ elseif ($z !== "")
+ echo "{0, { {\"$z\", ", strlen($z), "} } },";
+ else
+ echo "{1, { {(void *)", sprintf("multi_cp_{$ident}_%05X",
+ ($i << 12) | ($k << 6) | $y ), "} } },";
+
+ }
+ echo "\n};\n\n";
+ }
+ }
+}
+
+if ($pass2 < 2)
+ echo "/* end of stage 3 Tables for $name }}} */", "\n\n";
+
+if ($pass2 > 1)
+ goto hashtables;
+
+echo
+"/* {{{ Stage 2 Tables for $name */", "\n\n";
+
+$t = <<<CODE
+static const entity_stage2_row empty_stage2_table[] = {
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+ empty_stage3_table, empty_stage3_table, empty_stage3_table, empty_stage3_table,
+};
+
+CODE;
+
+if (!$pass2)
+ echo $t;
+
+for ($i = 0; $i < 0x1E; $i++) {
+ $any = false;
+ for ($k = 0; $k < 64; $k++) {
+ if (isset($mstable[$i][$k]))
+ $any = true;
+ }
+ if ($any) {
+ echo "static const entity_stage2_row stage2_table_{$ident}_",
+ sprintf("%02X000", $i), "[] = {\n";
+ for ($k = 0; $k < 64; $k++) {
+ if ($k == 0) echo "\t";
+ elseif ($k % 4 == 0) echo "\n\t";
+ else echo " ";
+ if (isset($mstable[$i][$k])) {
+ echo sprintf("stage3_table_{$ident}_%05X", ($i << 12) | ($k << 6)), ",";
+ } else {
+ echo "empty_stage3_table", ",";
+ }
+ }
+ echo "\n};\n\n";
+ }
+}
+
+echo
+"/* end of stage 2 tables for $name }}} */", "\n\n";
+
+echo "static const entity_stage1_row entity_ms_table_{$ident}[] = {\n";
+for ($i = 0; $i < 0x1E; $i++) {
+ if (isset($mstable[$i]))
+ echo "\t", sprintf("stage2_table_{$ident}_%02X000", $i), ",\n";
+ else
+ echo "\tempty_stage2_table,\n";
+}
+echo "};\n\n";
+
+echo
+"/* end of $name multi-stage table for codepoint -> entity }}} */\n\n";
+
+/* commented-out; this enabled binary search, which turned out to be
+ * significantly slower than the hash tables for html 5 entities */
+//echo
+//"/* {{{ HTML 5 tables for entity -> codepoint */", "\n\n";
+
+//$t = <<<CODE
+//typedef struct {
+// const char *entity;
+// unsigned short entity_len;
+// unsigned int codepoint1;
+// unsigned int codepoint2;
+//} entity_cp_map;
+//
+//#define ENTITY_CP_MAP_CMP(l, lsize, r, rsize) \
+// ( ((lsize)==(rsize)) ? (memcmp((l), (r), (lsize))) : ((lsize)-(rsize)) )
+//
+//static const entity_cp_map html5_ent_cp_map[] = {
+//
+//CODE;
+//echo $t;
+//
+//$dp = $origdp;
+//usort($dp, function($a, $b) { $d = strlen($a[0])-strlen($b[0]);
+// return $d==0?strcmp($a[0], $b[0]):$d; });
+//
+//$k = 0;
+//foreach ($dp as $o) {
+// if ($k == 0) echo "\t";
+// elseif ($k % 3 == 0) echo "\n\t";
+// else echo " ";
+// if (isset($o[2]))
+// echo sprintf('{"%s", %d, 0x%X, 0x%X},', $o[0], strlen($o[0]),
+// hexdec($o[1]), hexdec($o[2]));
+// else
+// echo sprintf('{"%s", %d, 0x%X, 0},', $o[0], strlen($o[0]),
+// hexdec($o[1]));
+//
+// if (isset($o[2])) {
+// $entlen = strlen($o[0]) + 2;
+// $utf8len = strlen(
+// mb_convert_encoding("&#x{$o[1]};&#x{$o[2]};", "UTF-8", "HTML-ENTITIES"));
+// if ($utf8len > $entlen*1.2) {
+// die("violated assumption for traverse_for_entities");
+// }
+// }
+//
+// $k++;
+//}
+//echo "\n};\n\n";
+//
+//echo "static const size_t html5_ent_cp_map_size = $k;\n\n";
+//
+//echo
+//"/* end of HTML 5 tables for entity -> codepoint }}} */\n\n";
+
+hashtables:
+
+echo
+"/* {{{ $name hash table for entity -> codepoint */", "\n\n";
+
+$t = <<<CODE
+typedef struct {
+ const char *entity;
+ unsigned short entity_len;
+ unsigned int codepoint1;
+ unsigned int codepoint2;
+} entity_cp_map;
+
+typedef const entity_cp_map *entity_ht_bucket;
+
+typedef struct {
+ unsigned num_elems; /* power of 2 */
+ const entity_ht_bucket *buckets; /* .num_elems elements */
+} entity_ht;
+
+static const entity_cp_map ht_bucket_empty[] = { {NULL, 0, 0, 0} };
+
+CODE;
+
+if (!$pass2)
+ echo $t;
+
+function hashfun($str)
+{
+
+ $hash = 5381;
+ $nKeyLength = strlen($str);
+ $pos = 0;
+
+ for (; $nKeyLength > 0; $nKeyLength--) {
+ $hash = (int)(((int)(((int)($hash << 5)) + $hash)) + ord($str[$pos++]))
+ & 0xFFFFFFFF;
+ }
+ return $hash;
+
+}
+
+$numelems = max(pow(2, ceil(log(1.5*count($origdp))/log(2))),16);
+$mask = $numelems - 1;
+$hashes = array();
+foreach ($origdp as $e) {
+ $hashes[hashfun($e[0]) & $mask][] = $e;
+ if (isset($e[2])) {
+ $entlen = strlen($e[0]) + 2;
+ $utf8len = strlen(
+ mb_convert_encoding("&#x{$e[1]};&#x{$e[2]};", "UTF-8", "HTML-ENTITIES"));
+ if ($utf8len > $entlen*1.2) {
+ die("violated assumption for traverse_for_entities");
+ }
+ }
+}
+
+for ($i = 0; $i < $numelems; $i++) {
+ if (empty($hashes[$i]))
+ continue;
+ echo "static const entity_cp_map ht_bucket_{$ident}_", sprintf("%03X", $i) ,"[] = {";
+ foreach ($hashes[$i] as $h) {
+ if (isset($h[2])) {
+ echo sprintf(' {"%s", %d, 0x%05X, 0x%05X},',
+ $h[0], strlen($h[0]), hexdec($h[1]), hexdec($h[2]));
+ } else {
+ echo sprintf(' {"%s", %d, 0x%05X, 0},',
+ $h[0], strlen($h[0]), hexdec($h[1]));
+ }
+ }
+ echo " {NULL, 0, 0, 0} };\n";
+}
+echo "\n";
+
+echo
+"static const entity_cp_map *const ht_buckets_{$ident}[] = {\n";
+
+for ($i = 0; $i < $numelems; $i++) {
+ if ($i == 0) echo "\t";
+ elseif ($i % 4 == 0) echo "\n\t";
+ else echo " ";
+ if (empty($hashes[$i]))
+ echo "ht_bucket_empty,";
+ else
+ echo "ht_bucket_{$ident}_", sprintf("%03X", $i), ",";
+}
+echo "\n};\n\n";
+
+echo
+"static const entity_ht ent_ht_{$ident} = {
+ ", sprintf("0x%X", $numelems), ",
+ ht_buckets_{$ident}
+};\n\n";
+
+echo
+"/* end of $name hash table for entity -> codepoint }}} */\n\n";
+
+if (!$pass2) {
+ $data = file_get_contents("ents_html401.txt");
+ $pass2 = 1;
+ $name = "HTML 4.01";
+ $ident = "html4";
+ goto again;
+} elseif ($pass2 == 1) {
+ $data = file_get_contents("ents_basic.txt");
+ $pass2 = 2;
+ $name = "Basic entities (no apos)";
+ $ident = "be_noapos";
+ goto again;
+} elseif ($pass2 == 2) {
+ $data = file_get_contents("ents_basic_apos.txt");
+ $pass2 = 3;
+ $name = "Basic entities (with apos)";
+ $ident = "be_apos";
+ goto again;
+}
+
+echo "#endif /* HTML_TABLES_H */\n";
diff --git a/ext/standard/html_tables/mappings/8859-1.TXT b/ext/standard/html_tables/mappings/8859-1.TXT
new file mode 100644
index 0000000000..473ecabc17
--- /dev/null
+++ b/ext/standard/html_tables/mappings/8859-1.TXT
@@ -0,0 +1,303 @@
+#
+# Name: ISO/IEC 8859-1:1998 to Unicode
+# Unicode version: 3.0
+# Table version: 1.0
+# Table format: Format A
+# Date: 1999 July 27
+# Authors: Ken Whistler <kenw@sybase.com>
+#
+# Copyright (c) 1991-1999 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on optical media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Unicode, Inc. hereby grants the right to freely use the information
+# supplied in this file in the creation of products supporting the
+# Unicode Standard, and to make copies of this file in any form for
+# internal or external distribution as long as this notice remains
+# attached.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-1:1998 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-1 order.
+#
+# Version history
+# 1.0 version updates 0.1 version by adding mappings for all
+# control characters.
+#
+# Updated versions of this file may be found in:
+# <ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+# Any comments or problems, contact <errata@unicode.org>
+# Please note that <errata@unicode.org> is an archival address;
+# notices will be checked, but do not expect an immediate response.
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x00A1 # INVERTED EXCLAMATION MARK
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x00A5 # YEN SIGN
+0xA6 0x00A6 # BROKEN BAR
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x00AA # FEMININE ORDINAL INDICATOR
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x00B8 # CEDILLA
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x00BA # MASCULINE ORDINAL INDICATOR
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x00BC # VULGAR FRACTION ONE QUARTER
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS
+0xBF 0x00BF # INVERTED QUESTION MARK
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic)
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic)
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German)
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic)
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic)
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/standard/html_tables/mappings/8859-15.TXT b/ext/standard/html_tables/mappings/8859-15.TXT
new file mode 100644
index 0000000000..ab2f32fcea
--- /dev/null
+++ b/ext/standard/html_tables/mappings/8859-15.TXT
@@ -0,0 +1,303 @@
+#
+# Name: ISO/IEC 8859-15:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 1.0
+# Table format: Format A
+# Date: 1999 July 27
+# Authors: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+# Ken Whistler <kenw@sybase.com>
+#
+# Copyright (c) 1998 - 1999 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on optical media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Unicode, Inc. hereby grants the right to freely use the information
+# supplied in this file in the creation of products supporting the
+# Unicode Standard, and to make copies of this file in any form for
+# internal or external distribution as long as this notice remains
+# attached.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-15:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-15 order.
+#
+# Version history
+#
+# Updated versions of this file may be found in:
+# <ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+# Any comments or problems, contact <errata@unicode.org>
+# Please note that <errata@unicode.org> is an archival address;
+# notices will be checked, but do not expect an immediate response.
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x00A1 # INVERTED EXCLAMATION MARK
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x20AC # EURO SIGN
+0xA5 0x00A5 # YEN SIGN
+0xA6 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x00AA # FEMININE ORDINAL INDICATOR
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x00BA # MASCULINE ORDINAL INDICATOR
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x0152 # LATIN CAPITAL LIGATURE OE
+0xBD 0x0153 # LATIN SMALL LIGATURE OE
+0xBE 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xBF 0x00BF # INVERTED QUESTION MARK
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x00D0 # LATIN CAPITAL LETTER ETH
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x00DE # LATIN CAPITAL LETTER THORN
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x00F0 # LATIN SMALL LETTER ETH
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x00FE # LATIN SMALL LETTER THORN
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
+
diff --git a/ext/standard/html_tables/mappings/8859-5.TXT b/ext/standard/html_tables/mappings/8859-5.TXT
new file mode 100644
index 0000000000..a7ed1ce2ab
--- /dev/null
+++ b/ext/standard/html_tables/mappings/8859-5.TXT
@@ -0,0 +1,303 @@
+#
+# Name: ISO 8859-5:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 1.0
+# Table format: Format A
+# Date: 1999 July 27
+# Authors: Ken Whistler <kenw@sybase.com>
+#
+# Copyright (c) 1991-1999 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on optical media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Unicode, Inc. hereby grants the right to freely use the information
+# supplied in this file in the creation of products supporting the
+# Unicode Standard, and to make copies of this file in any form for
+# internal or external distribution as long as this notice remains
+# attached.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-5:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-5 order.
+#
+# Version history
+# 1.0 version updates 0.1 version by adding mappings for all
+# control characters.
+#
+# Updated versions of this file may be found in:
+# <ftp://ftp.unicode.org/Public/MAPPINGS/>
+#
+# Any comments or problems, contact <errata@unicode.org>
+# Please note that <errata@unicode.org> is an archival address;
+# notices will be checked, but do not expect an immediate response.
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0401 # CYRILLIC CAPITAL LETTER IO
+0xA2 0x0402 # CYRILLIC CAPITAL LETTER DJE
+0xA3 0x0403 # CYRILLIC CAPITAL LETTER GJE
+0xA4 0x0404 # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xA5 0x0405 # CYRILLIC CAPITAL LETTER DZE
+0xA6 0x0406 # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xA7 0x0407 # CYRILLIC CAPITAL LETTER YI
+0xA8 0x0408 # CYRILLIC CAPITAL LETTER JE
+0xA9 0x0409 # CYRILLIC CAPITAL LETTER LJE
+0xAA 0x040A # CYRILLIC CAPITAL LETTER NJE
+0xAB 0x040B # CYRILLIC CAPITAL LETTER TSHE
+0xAC 0x040C # CYRILLIC CAPITAL LETTER KJE
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x040E # CYRILLIC CAPITAL LETTER SHORT U
+0xAF 0x040F # CYRILLIC CAPITAL LETTER DZHE
+0xB0 0x0410 # CYRILLIC CAPITAL LETTER A
+0xB1 0x0411 # CYRILLIC CAPITAL LETTER BE
+0xB2 0x0412 # CYRILLIC CAPITAL LETTER VE
+0xB3 0x0413 # CYRILLIC CAPITAL LETTER GHE
+0xB4 0x0414 # CYRILLIC CAPITAL LETTER DE
+0xB5 0x0415 # CYRILLIC CAPITAL LETTER IE
+0xB6 0x0416 # CYRILLIC CAPITAL LETTER ZHE
+0xB7 0x0417 # CYRILLIC CAPITAL LETTER ZE
+0xB8 0x0418 # CYRILLIC CAPITAL LETTER I
+0xB9 0x0419 # CYRILLIC CAPITAL LETTER SHORT I
+0xBA 0x041A # CYRILLIC CAPITAL LETTER KA
+0xBB 0x041B # CYRILLIC CAPITAL LETTER EL
+0xBC 0x041C # CYRILLIC CAPITAL LETTER EM
+0xBD 0x041D # CYRILLIC CAPITAL LETTER EN
+0xBE 0x041E # CYRILLIC CAPITAL LETTER O
+0xBF 0x041F # CYRILLIC CAPITAL LETTER PE
+0xC0 0x0420 # CYRILLIC CAPITAL LETTER ER
+0xC1 0x0421 # CYRILLIC CAPITAL LETTER ES
+0xC2 0x0422 # CYRILLIC CAPITAL LETTER TE
+0xC3 0x0423 # CYRILLIC CAPITAL LETTER U
+0xC4 0x0424 # CYRILLIC CAPITAL LETTER EF
+0xC5 0x0425 # CYRILLIC CAPITAL LETTER HA
+0xC6 0x0426 # CYRILLIC CAPITAL LETTER TSE
+0xC7 0x0427 # CYRILLIC CAPITAL LETTER CHE
+0xC8 0x0428 # CYRILLIC CAPITAL LETTER SHA
+0xC9 0x0429 # CYRILLIC CAPITAL LETTER SHCHA
+0xCA 0x042A # CYRILLIC CAPITAL LETTER HARD SIGN
+0xCB 0x042B # CYRILLIC CAPITAL LETTER YERU
+0xCC 0x042C # CYRILLIC CAPITAL LETTER SOFT SIGN
+0xCD 0x042D # CYRILLIC CAPITAL LETTER E
+0xCE 0x042E # CYRILLIC CAPITAL LETTER YU
+0xCF 0x042F # CYRILLIC CAPITAL LETTER YA
+0xD0 0x0430 # CYRILLIC SMALL LETTER A
+0xD1 0x0431 # CYRILLIC SMALL LETTER BE
+0xD2 0x0432 # CYRILLIC SMALL LETTER VE
+0xD3 0x0433 # CYRILLIC SMALL LETTER GHE
+0xD4 0x0434 # CYRILLIC SMALL LETTER DE
+0xD5 0x0435 # CYRILLIC SMALL LETTER IE
+0xD6 0x0436 # CYRILLIC SMALL LETTER ZHE
+0xD7 0x0437 # CYRILLIC SMALL LETTER ZE
+0xD8 0x0438 # CYRILLIC SMALL LETTER I
+0xD9 0x0439 # CYRILLIC SMALL LETTER SHORT I
+0xDA 0x043A # CYRILLIC SMALL LETTER KA
+0xDB 0x043B # CYRILLIC SMALL LETTER EL
+0xDC 0x043C # CYRILLIC SMALL LETTER EM
+0xDD 0x043D # CYRILLIC SMALL LETTER EN
+0xDE 0x043E # CYRILLIC SMALL LETTER O
+0xDF 0x043F # CYRILLIC SMALL LETTER PE
+0xE0 0x0440 # CYRILLIC SMALL LETTER ER
+0xE1 0x0441 # CYRILLIC SMALL LETTER ES
+0xE2 0x0442 # CYRILLIC SMALL LETTER TE
+0xE3 0x0443 # CYRILLIC SMALL LETTER U
+0xE4 0x0444 # CYRILLIC SMALL LETTER EF
+0xE5 0x0445 # CYRILLIC SMALL LETTER HA
+0xE6 0x0446 # CYRILLIC SMALL LETTER TSE
+0xE7 0x0447 # CYRILLIC SMALL LETTER CHE
+0xE8 0x0448 # CYRILLIC SMALL LETTER SHA
+0xE9 0x0449 # CYRILLIC SMALL LETTER SHCHA
+0xEA 0x044A # CYRILLIC SMALL LETTER HARD SIGN
+0xEB 0x044B # CYRILLIC SMALL LETTER YERU
+0xEC 0x044C # CYRILLIC SMALL LETTER SOFT SIGN
+0xED 0x044D # CYRILLIC SMALL LETTER E
+0xEE 0x044E # CYRILLIC SMALL LETTER YU
+0xEF 0x044F # CYRILLIC SMALL LETTER YA
+0xF0 0x2116 # NUMERO SIGN
+0xF1 0x0451 # CYRILLIC SMALL LETTER IO
+0xF2 0x0452 # CYRILLIC SMALL LETTER DJE
+0xF3 0x0453 # CYRILLIC SMALL LETTER GJE
+0xF4 0x0454 # CYRILLIC SMALL LETTER UKRAINIAN IE
+0xF5 0x0455 # CYRILLIC SMALL LETTER DZE
+0xF6 0x0456 # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xF7 0x0457 # CYRILLIC SMALL LETTER YI
+0xF8 0x0458 # CYRILLIC SMALL LETTER JE
+0xF9 0x0459 # CYRILLIC SMALL LETTER LJE
+0xFA 0x045A # CYRILLIC SMALL LETTER NJE
+0xFB 0x045B # CYRILLIC SMALL LETTER TSHE
+0xFC 0x045C # CYRILLIC SMALL LETTER KJE
+0xFD 0x00A7 # SECTION SIGN
+0xFE 0x045E # CYRILLIC SMALL LETTER SHORT U
+0xFF 0x045F # CYRILLIC SMALL LETTER DZHE
diff --git a/ext/standard/html_tables/mappings/CP1251.TXT b/ext/standard/html_tables/mappings/CP1251.TXT
new file mode 100644
index 0000000000..4d9b3558ac
--- /dev/null
+++ b/ext/standard/html_tables/mappings/CP1251.TXT
@@ -0,0 +1,274 @@
+#
+# Name: cp1251 to Unicode table
+# Unicode version: 2.0
+# Table version: 2.01
+# Table format: Format A
+# Date: 04/15/98
+#
+# Contact: Shawn.Steele@microsoft.com
+#
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1251 code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1251 order
+#
+0x00 0x0000 #NULL
+0x01 0x0001 #START OF HEADING
+0x02 0x0002 #START OF TEXT
+0x03 0x0003 #END OF TEXT
+0x04 0x0004 #END OF TRANSMISSION
+0x05 0x0005 #ENQUIRY
+0x06 0x0006 #ACKNOWLEDGE
+0x07 0x0007 #BELL
+0x08 0x0008 #BACKSPACE
+0x09 0x0009 #HORIZONTAL TABULATION
+0x0A 0x000A #LINE FEED
+0x0B 0x000B #VERTICAL TABULATION
+0x0C 0x000C #FORM FEED
+0x0D 0x000D #CARRIAGE RETURN
+0x0E 0x000E #SHIFT OUT
+0x0F 0x000F #SHIFT IN
+0x10 0x0010 #DATA LINK ESCAPE
+0x11 0x0011 #DEVICE CONTROL ONE
+0x12 0x0012 #DEVICE CONTROL TWO
+0x13 0x0013 #DEVICE CONTROL THREE
+0x14 0x0014 #DEVICE CONTROL FOUR
+0x15 0x0015 #NEGATIVE ACKNOWLEDGE
+0x16 0x0016 #SYNCHRONOUS IDLE
+0x17 0x0017 #END OF TRANSMISSION BLOCK
+0x18 0x0018 #CANCEL
+0x19 0x0019 #END OF MEDIUM
+0x1A 0x001A #SUBSTITUTE
+0x1B 0x001B #ESCAPE
+0x1C 0x001C #FILE SEPARATOR
+0x1D 0x001D #GROUP SEPARATOR
+0x1E 0x001E #RECORD SEPARATOR
+0x1F 0x001F #UNIT SEPARATOR
+0x20 0x0020 #SPACE
+0x21 0x0021 #EXCLAMATION MARK
+0x22 0x0022 #QUOTATION MARK
+0x23 0x0023 #NUMBER SIGN
+0x24 0x0024 #DOLLAR SIGN
+0x25 0x0025 #PERCENT SIGN
+0x26 0x0026 #AMPERSAND
+0x27 0x0027 #APOSTROPHE
+0x28 0x0028 #LEFT PARENTHESIS
+0x29 0x0029 #RIGHT PARENTHESIS
+0x2A 0x002A #ASTERISK
+0x2B 0x002B #PLUS SIGN
+0x2C 0x002C #COMMA
+0x2D 0x002D #HYPHEN-MINUS
+0x2E 0x002E #FULL STOP
+0x2F 0x002F #SOLIDUS
+0x30 0x0030 #DIGIT ZERO
+0x31 0x0031 #DIGIT ONE
+0x32 0x0032 #DIGIT TWO
+0x33 0x0033 #DIGIT THREE
+0x34 0x0034 #DIGIT FOUR
+0x35 0x0035 #DIGIT FIVE
+0x36 0x0036 #DIGIT SIX
+0x37 0x0037 #DIGIT SEVEN
+0x38 0x0038 #DIGIT EIGHT
+0x39 0x0039 #DIGIT NINE
+0x3A 0x003A #COLON
+0x3B 0x003B #SEMICOLON
+0x3C 0x003C #LESS-THAN SIGN
+0x3D 0x003D #EQUALS SIGN
+0x3E 0x003E #GREATER-THAN SIGN
+0x3F 0x003F #QUESTION MARK
+0x40 0x0040 #COMMERCIAL AT
+0x41 0x0041 #LATIN CAPITAL LETTER A
+0x42 0x0042 #LATIN CAPITAL LETTER B
+0x43 0x0043 #LATIN CAPITAL LETTER C
+0x44 0x0044 #LATIN CAPITAL LETTER D
+0x45 0x0045 #LATIN CAPITAL LETTER E
+0x46 0x0046 #LATIN CAPITAL LETTER F
+0x47 0x0047 #LATIN CAPITAL LETTER G
+0x48 0x0048 #LATIN CAPITAL LETTER H
+0x49 0x0049 #LATIN CAPITAL LETTER I
+0x4A 0x004A #LATIN CAPITAL LETTER J
+0x4B 0x004B #LATIN CAPITAL LETTER K
+0x4C 0x004C #LATIN CAPITAL LETTER L
+0x4D 0x004D #LATIN CAPITAL LETTER M
+0x4E 0x004E #LATIN CAPITAL LETTER N
+0x4F 0x004F #LATIN CAPITAL LETTER O
+0x50 0x0050 #LATIN CAPITAL LETTER P
+0x51 0x0051 #LATIN CAPITAL LETTER Q
+0x52 0x0052 #LATIN CAPITAL LETTER R
+0x53 0x0053 #LATIN CAPITAL LETTER S
+0x54 0x0054 #LATIN CAPITAL LETTER T
+0x55 0x0055 #LATIN CAPITAL LETTER U
+0x56 0x0056 #LATIN CAPITAL LETTER V
+0x57 0x0057 #LATIN CAPITAL LETTER W
+0x58 0x0058 #LATIN CAPITAL LETTER X
+0x59 0x0059 #LATIN CAPITAL LETTER Y
+0x5A 0x005A #LATIN CAPITAL LETTER Z
+0x5B 0x005B #LEFT SQUARE BRACKET
+0x5C 0x005C #REVERSE SOLIDUS
+0x5D 0x005D #RIGHT SQUARE BRACKET
+0x5E 0x005E #CIRCUMFLEX ACCENT
+0x5F 0x005F #LOW LINE
+0x60 0x0060 #GRAVE ACCENT
+0x61 0x0061 #LATIN SMALL LETTER A
+0x62 0x0062 #LATIN SMALL LETTER B
+0x63 0x0063 #LATIN SMALL LETTER C
+0x64 0x0064 #LATIN SMALL LETTER D
+0x65 0x0065 #LATIN SMALL LETTER E
+0x66 0x0066 #LATIN SMALL LETTER F
+0x67 0x0067 #LATIN SMALL LETTER G
+0x68 0x0068 #LATIN SMALL LETTER H
+0x69 0x0069 #LATIN SMALL LETTER I
+0x6A 0x006A #LATIN SMALL LETTER J
+0x6B 0x006B #LATIN SMALL LETTER K
+0x6C 0x006C #LATIN SMALL LETTER L
+0x6D 0x006D #LATIN SMALL LETTER M
+0x6E 0x006E #LATIN SMALL LETTER N
+0x6F 0x006F #LATIN SMALL LETTER O
+0x70 0x0070 #LATIN SMALL LETTER P
+0x71 0x0071 #LATIN SMALL LETTER Q
+0x72 0x0072 #LATIN SMALL LETTER R
+0x73 0x0073 #LATIN SMALL LETTER S
+0x74 0x0074 #LATIN SMALL LETTER T
+0x75 0x0075 #LATIN SMALL LETTER U
+0x76 0x0076 #LATIN SMALL LETTER V
+0x77 0x0077 #LATIN SMALL LETTER W
+0x78 0x0078 #LATIN SMALL LETTER X
+0x79 0x0079 #LATIN SMALL LETTER Y
+0x7A 0x007A #LATIN SMALL LETTER Z
+0x7B 0x007B #LEFT CURLY BRACKET
+0x7C 0x007C #VERTICAL LINE
+0x7D 0x007D #RIGHT CURLY BRACKET
+0x7E 0x007E #TILDE
+0x7F 0x007F #DELETE
+0x80 0x0402 #CYRILLIC CAPITAL LETTER DJE
+0x81 0x0403 #CYRILLIC CAPITAL LETTER GJE
+0x82 0x201A #SINGLE LOW-9 QUOTATION MARK
+0x83 0x0453 #CYRILLIC SMALL LETTER GJE
+0x84 0x201E #DOUBLE LOW-9 QUOTATION MARK
+0x85 0x2026 #HORIZONTAL ELLIPSIS
+0x86 0x2020 #DAGGER
+0x87 0x2021 #DOUBLE DAGGER
+0x88 0x20AC #EURO SIGN
+0x89 0x2030 #PER MILLE SIGN
+0x8A 0x0409 #CYRILLIC CAPITAL LETTER LJE
+0x8B 0x2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C 0x040A #CYRILLIC CAPITAL LETTER NJE
+0x8D 0x040C #CYRILLIC CAPITAL LETTER KJE
+0x8E 0x040B #CYRILLIC CAPITAL LETTER TSHE
+0x8F 0x040F #CYRILLIC CAPITAL LETTER DZHE
+0x90 0x0452 #CYRILLIC SMALL LETTER DJE
+0x91 0x2018 #LEFT SINGLE QUOTATION MARK
+0x92 0x2019 #RIGHT SINGLE QUOTATION MARK
+0x93 0x201C #LEFT DOUBLE QUOTATION MARK
+0x94 0x201D #RIGHT DOUBLE QUOTATION MARK
+0x95 0x2022 #BULLET
+0x96 0x2013 #EN DASH
+0x97 0x2014 #EM DASH
+0x98 #UNDEFINED
+0x99 0x2122 #TRADE MARK SIGN
+0x9A 0x0459 #CYRILLIC SMALL LETTER LJE
+0x9B 0x203A #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C 0x045A #CYRILLIC SMALL LETTER NJE
+0x9D 0x045C #CYRILLIC SMALL LETTER KJE
+0x9E 0x045B #CYRILLIC SMALL LETTER TSHE
+0x9F 0x045F #CYRILLIC SMALL LETTER DZHE
+0xA0 0x00A0 #NO-BREAK SPACE
+0xA1 0x040E #CYRILLIC CAPITAL LETTER SHORT U
+0xA2 0x045E #CYRILLIC SMALL LETTER SHORT U
+0xA3 0x0408 #CYRILLIC CAPITAL LETTER JE
+0xA4 0x00A4 #CURRENCY SIGN
+0xA5 0x0490 #CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0xA6 0x00A6 #BROKEN BAR
+0xA7 0x00A7 #SECTION SIGN
+0xA8 0x0401 #CYRILLIC CAPITAL LETTER IO
+0xA9 0x00A9 #COPYRIGHT SIGN
+0xAA 0x0404 #CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xAB 0x00AB #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC #NOT SIGN
+0xAD 0x00AD #SOFT HYPHEN
+0xAE 0x00AE #REGISTERED SIGN
+0xAF 0x0407 #CYRILLIC CAPITAL LETTER YI
+0xB0 0x00B0 #DEGREE SIGN
+0xB1 0x00B1 #PLUS-MINUS SIGN
+0xB2 0x0406 #CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB3 0x0456 #CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB4 0x0491 #CYRILLIC SMALL LETTER GHE WITH UPTURN
+0xB5 0x00B5 #MICRO SIGN
+0xB6 0x00B6 #PILCROW SIGN
+0xB7 0x00B7 #MIDDLE DOT
+0xB8 0x0451 #CYRILLIC SMALL LETTER IO
+0xB9 0x2116 #NUMERO SIGN
+0xBA 0x0454 #CYRILLIC SMALL LETTER UKRAINIAN IE
+0xBB 0x00BB #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x0458 #CYRILLIC SMALL LETTER JE
+0xBD 0x0405 #CYRILLIC CAPITAL LETTER DZE
+0xBE 0x0455 #CYRILLIC SMALL LETTER DZE
+0xBF 0x0457 #CYRILLIC SMALL LETTER YI
+0xC0 0x0410 #CYRILLIC CAPITAL LETTER A
+0xC1 0x0411 #CYRILLIC CAPITAL LETTER BE
+0xC2 0x0412 #CYRILLIC CAPITAL LETTER VE
+0xC3 0x0413 #CYRILLIC CAPITAL LETTER GHE
+0xC4 0x0414 #CYRILLIC CAPITAL LETTER DE
+0xC5 0x0415 #CYRILLIC CAPITAL LETTER IE
+0xC6 0x0416 #CYRILLIC CAPITAL LETTER ZHE
+0xC7 0x0417 #CYRILLIC CAPITAL LETTER ZE
+0xC8 0x0418 #CYRILLIC CAPITAL LETTER I
+0xC9 0x0419 #CYRILLIC CAPITAL LETTER SHORT I
+0xCA 0x041A #CYRILLIC CAPITAL LETTER KA
+0xCB 0x041B #CYRILLIC CAPITAL LETTER EL
+0xCC 0x041C #CYRILLIC CAPITAL LETTER EM
+0xCD 0x041D #CYRILLIC CAPITAL LETTER EN
+0xCE 0x041E #CYRILLIC CAPITAL LETTER O
+0xCF 0x041F #CYRILLIC CAPITAL LETTER PE
+0xD0 0x0420 #CYRILLIC CAPITAL LETTER ER
+0xD1 0x0421 #CYRILLIC CAPITAL LETTER ES
+0xD2 0x0422 #CYRILLIC CAPITAL LETTER TE
+0xD3 0x0423 #CYRILLIC CAPITAL LETTER U
+0xD4 0x0424 #CYRILLIC CAPITAL LETTER EF
+0xD5 0x0425 #CYRILLIC CAPITAL LETTER HA
+0xD6 0x0426 #CYRILLIC CAPITAL LETTER TSE
+0xD7 0x0427 #CYRILLIC CAPITAL LETTER CHE
+0xD8 0x0428 #CYRILLIC CAPITAL LETTER SHA
+0xD9 0x0429 #CYRILLIC CAPITAL LETTER SHCHA
+0xDA 0x042A #CYRILLIC CAPITAL LETTER HARD SIGN
+0xDB 0x042B #CYRILLIC CAPITAL LETTER YERU
+0xDC 0x042C #CYRILLIC CAPITAL LETTER SOFT SIGN
+0xDD 0x042D #CYRILLIC CAPITAL LETTER E
+0xDE 0x042E #CYRILLIC CAPITAL LETTER YU
+0xDF 0x042F #CYRILLIC CAPITAL LETTER YA
+0xE0 0x0430 #CYRILLIC SMALL LETTER A
+0xE1 0x0431 #CYRILLIC SMALL LETTER BE
+0xE2 0x0432 #CYRILLIC SMALL LETTER VE
+0xE3 0x0433 #CYRILLIC SMALL LETTER GHE
+0xE4 0x0434 #CYRILLIC SMALL LETTER DE
+0xE5 0x0435 #CYRILLIC SMALL LETTER IE
+0xE6 0x0436 #CYRILLIC SMALL LETTER ZHE
+0xE7 0x0437 #CYRILLIC SMALL LETTER ZE
+0xE8 0x0438 #CYRILLIC SMALL LETTER I
+0xE9 0x0439 #CYRILLIC SMALL LETTER SHORT I
+0xEA 0x043A #CYRILLIC SMALL LETTER KA
+0xEB 0x043B #CYRILLIC SMALL LETTER EL
+0xEC 0x043C #CYRILLIC SMALL LETTER EM
+0xED 0x043D #CYRILLIC SMALL LETTER EN
+0xEE 0x043E #CYRILLIC SMALL LETTER O
+0xEF 0x043F #CYRILLIC SMALL LETTER PE
+0xF0 0x0440 #CYRILLIC SMALL LETTER ER
+0xF1 0x0441 #CYRILLIC SMALL LETTER ES
+0xF2 0x0442 #CYRILLIC SMALL LETTER TE
+0xF3 0x0443 #CYRILLIC SMALL LETTER U
+0xF4 0x0444 #CYRILLIC SMALL LETTER EF
+0xF5 0x0445 #CYRILLIC SMALL LETTER HA
+0xF6 0x0446 #CYRILLIC SMALL LETTER TSE
+0xF7 0x0447 #CYRILLIC SMALL LETTER CHE
+0xF8 0x0448 #CYRILLIC SMALL LETTER SHA
+0xF9 0x0449 #CYRILLIC SMALL LETTER SHCHA
+0xFA 0x044A #CYRILLIC SMALL LETTER HARD SIGN
+0xFB 0x044B #CYRILLIC SMALL LETTER YERU
+0xFC 0x044C #CYRILLIC SMALL LETTER SOFT SIGN
+0xFD 0x044D #CYRILLIC SMALL LETTER E
+0xFE 0x044E #CYRILLIC SMALL LETTER YU
+0xFF 0x044F #CYRILLIC SMALL LETTER YA
diff --git a/ext/standard/html_tables/mappings/CP1252.TXT b/ext/standard/html_tables/mappings/CP1252.TXT
new file mode 100644
index 0000000000..8ff4b204b7
--- /dev/null
+++ b/ext/standard/html_tables/mappings/CP1252.TXT
@@ -0,0 +1,274 @@
+#
+# Name: cp1252 to Unicode table
+# Unicode version: 2.0
+# Table version: 2.01
+# Table format: Format A
+# Date: 04/15/98
+#
+# Contact: Shawn.Steele@microsoft.com
+#
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1252 code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1252 order
+#
+0x00 0x0000 #NULL
+0x01 0x0001 #START OF HEADING
+0x02 0x0002 #START OF TEXT
+0x03 0x0003 #END OF TEXT
+0x04 0x0004 #END OF TRANSMISSION
+0x05 0x0005 #ENQUIRY
+0x06 0x0006 #ACKNOWLEDGE
+0x07 0x0007 #BELL
+0x08 0x0008 #BACKSPACE
+0x09 0x0009 #HORIZONTAL TABULATION
+0x0A 0x000A #LINE FEED
+0x0B 0x000B #VERTICAL TABULATION
+0x0C 0x000C #FORM FEED
+0x0D 0x000D #CARRIAGE RETURN
+0x0E 0x000E #SHIFT OUT
+0x0F 0x000F #SHIFT IN
+0x10 0x0010 #DATA LINK ESCAPE
+0x11 0x0011 #DEVICE CONTROL ONE
+0x12 0x0012 #DEVICE CONTROL TWO
+0x13 0x0013 #DEVICE CONTROL THREE
+0x14 0x0014 #DEVICE CONTROL FOUR
+0x15 0x0015 #NEGATIVE ACKNOWLEDGE
+0x16 0x0016 #SYNCHRONOUS IDLE
+0x17 0x0017 #END OF TRANSMISSION BLOCK
+0x18 0x0018 #CANCEL
+0x19 0x0019 #END OF MEDIUM
+0x1A 0x001A #SUBSTITUTE
+0x1B 0x001B #ESCAPE
+0x1C 0x001C #FILE SEPARATOR
+0x1D 0x001D #GROUP SEPARATOR
+0x1E 0x001E #RECORD SEPARATOR
+0x1F 0x001F #UNIT SEPARATOR
+0x20 0x0020 #SPACE
+0x21 0x0021 #EXCLAMATION MARK
+0x22 0x0022 #QUOTATION MARK
+0x23 0x0023 #NUMBER SIGN
+0x24 0x0024 #DOLLAR SIGN
+0x25 0x0025 #PERCENT SIGN
+0x26 0x0026 #AMPERSAND
+0x27 0x0027 #APOSTROPHE
+0x28 0x0028 #LEFT PARENTHESIS
+0x29 0x0029 #RIGHT PARENTHESIS
+0x2A 0x002A #ASTERISK
+0x2B 0x002B #PLUS SIGN
+0x2C 0x002C #COMMA
+0x2D 0x002D #HYPHEN-MINUS
+0x2E 0x002E #FULL STOP
+0x2F 0x002F #SOLIDUS
+0x30 0x0030 #DIGIT ZERO
+0x31 0x0031 #DIGIT ONE
+0x32 0x0032 #DIGIT TWO
+0x33 0x0033 #DIGIT THREE
+0x34 0x0034 #DIGIT FOUR
+0x35 0x0035 #DIGIT FIVE
+0x36 0x0036 #DIGIT SIX
+0x37 0x0037 #DIGIT SEVEN
+0x38 0x0038 #DIGIT EIGHT
+0x39 0x0039 #DIGIT NINE
+0x3A 0x003A #COLON
+0x3B 0x003B #SEMICOLON
+0x3C 0x003C #LESS-THAN SIGN
+0x3D 0x003D #EQUALS SIGN
+0x3E 0x003E #GREATER-THAN SIGN
+0x3F 0x003F #QUESTION MARK
+0x40 0x0040 #COMMERCIAL AT
+0x41 0x0041 #LATIN CAPITAL LETTER A
+0x42 0x0042 #LATIN CAPITAL LETTER B
+0x43 0x0043 #LATIN CAPITAL LETTER C
+0x44 0x0044 #LATIN CAPITAL LETTER D
+0x45 0x0045 #LATIN CAPITAL LETTER E
+0x46 0x0046 #LATIN CAPITAL LETTER F
+0x47 0x0047 #LATIN CAPITAL LETTER G
+0x48 0x0048 #LATIN CAPITAL LETTER H
+0x49 0x0049 #LATIN CAPITAL LETTER I
+0x4A 0x004A #LATIN CAPITAL LETTER J
+0x4B 0x004B #LATIN CAPITAL LETTER K
+0x4C 0x004C #LATIN CAPITAL LETTER L
+0x4D 0x004D #LATIN CAPITAL LETTER M
+0x4E 0x004E #LATIN CAPITAL LETTER N
+0x4F 0x004F #LATIN CAPITAL LETTER O
+0x50 0x0050 #LATIN CAPITAL LETTER P
+0x51 0x0051 #LATIN CAPITAL LETTER Q
+0x52 0x0052 #LATIN CAPITAL LETTER R
+0x53 0x0053 #LATIN CAPITAL LETTER S
+0x54 0x0054 #LATIN CAPITAL LETTER T
+0x55 0x0055 #LATIN CAPITAL LETTER U
+0x56 0x0056 #LATIN CAPITAL LETTER V
+0x57 0x0057 #LATIN CAPITAL LETTER W
+0x58 0x0058 #LATIN CAPITAL LETTER X
+0x59 0x0059 #LATIN CAPITAL LETTER Y
+0x5A 0x005A #LATIN CAPITAL LETTER Z
+0x5B 0x005B #LEFT SQUARE BRACKET
+0x5C 0x005C #REVERSE SOLIDUS
+0x5D 0x005D #RIGHT SQUARE BRACKET
+0x5E 0x005E #CIRCUMFLEX ACCENT
+0x5F 0x005F #LOW LINE
+0x60 0x0060 #GRAVE ACCENT
+0x61 0x0061 #LATIN SMALL LETTER A
+0x62 0x0062 #LATIN SMALL LETTER B
+0x63 0x0063 #LATIN SMALL LETTER C
+0x64 0x0064 #LATIN SMALL LETTER D
+0x65 0x0065 #LATIN SMALL LETTER E
+0x66 0x0066 #LATIN SMALL LETTER F
+0x67 0x0067 #LATIN SMALL LETTER G
+0x68 0x0068 #LATIN SMALL LETTER H
+0x69 0x0069 #LATIN SMALL LETTER I
+0x6A 0x006A #LATIN SMALL LETTER J
+0x6B 0x006B #LATIN SMALL LETTER K
+0x6C 0x006C #LATIN SMALL LETTER L
+0x6D 0x006D #LATIN SMALL LETTER M
+0x6E 0x006E #LATIN SMALL LETTER N
+0x6F 0x006F #LATIN SMALL LETTER O
+0x70 0x0070 #LATIN SMALL LETTER P
+0x71 0x0071 #LATIN SMALL LETTER Q
+0x72 0x0072 #LATIN SMALL LETTER R
+0x73 0x0073 #LATIN SMALL LETTER S
+0x74 0x0074 #LATIN SMALL LETTER T
+0x75 0x0075 #LATIN SMALL LETTER U
+0x76 0x0076 #LATIN SMALL LETTER V
+0x77 0x0077 #LATIN SMALL LETTER W
+0x78 0x0078 #LATIN SMALL LETTER X
+0x79 0x0079 #LATIN SMALL LETTER Y
+0x7A 0x007A #LATIN SMALL LETTER Z
+0x7B 0x007B #LEFT CURLY BRACKET
+0x7C 0x007C #VERTICAL LINE
+0x7D 0x007D #RIGHT CURLY BRACKET
+0x7E 0x007E #TILDE
+0x7F 0x007F #DELETE
+0x80 0x20AC #EURO SIGN
+0x81 #UNDEFINED
+0x82 0x201A #SINGLE LOW-9 QUOTATION MARK
+0x83 0x0192 #LATIN SMALL LETTER F WITH HOOK
+0x84 0x201E #DOUBLE LOW-9 QUOTATION MARK
+0x85 0x2026 #HORIZONTAL ELLIPSIS
+0x86 0x2020 #DAGGER
+0x87 0x2021 #DOUBLE DAGGER
+0x88 0x02C6 #MODIFIER LETTER CIRCUMFLEX ACCENT
+0x89 0x2030 #PER MILLE SIGN
+0x8A 0x0160 #LATIN CAPITAL LETTER S WITH CARON
+0x8B 0x2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C 0x0152 #LATIN CAPITAL LIGATURE OE
+0x8D #UNDEFINED
+0x8E 0x017D #LATIN CAPITAL LETTER Z WITH CARON
+0x8F #UNDEFINED
+0x90 #UNDEFINED
+0x91 0x2018 #LEFT SINGLE QUOTATION MARK
+0x92 0x2019 #RIGHT SINGLE QUOTATION MARK
+0x93 0x201C #LEFT DOUBLE QUOTATION MARK
+0x94 0x201D #RIGHT DOUBLE QUOTATION MARK
+0x95 0x2022 #BULLET
+0x96 0x2013 #EN DASH
+0x97 0x2014 #EM DASH
+0x98 0x02DC #SMALL TILDE
+0x99 0x2122 #TRADE MARK SIGN
+0x9A 0x0161 #LATIN SMALL LETTER S WITH CARON
+0x9B 0x203A #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C 0x0153 #LATIN SMALL LIGATURE OE
+0x9D #UNDEFINED
+0x9E 0x017E #LATIN SMALL LETTER Z WITH CARON
+0x9F 0x0178 #LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xA0 0x00A0 #NO-BREAK SPACE
+0xA1 0x00A1 #INVERTED EXCLAMATION MARK
+0xA2 0x00A2 #CENT SIGN
+0xA3 0x00A3 #POUND SIGN
+0xA4 0x00A4 #CURRENCY SIGN
+0xA5 0x00A5 #YEN SIGN
+0xA6 0x00A6 #BROKEN BAR
+0xA7 0x00A7 #SECTION SIGN
+0xA8 0x00A8 #DIAERESIS
+0xA9 0x00A9 #COPYRIGHT SIGN
+0xAA 0x00AA #FEMININE ORDINAL INDICATOR
+0xAB 0x00AB #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC #NOT SIGN
+0xAD 0x00AD #SOFT HYPHEN
+0xAE 0x00AE #REGISTERED SIGN
+0xAF 0x00AF #MACRON
+0xB0 0x00B0 #DEGREE SIGN
+0xB1 0x00B1 #PLUS-MINUS SIGN
+0xB2 0x00B2 #SUPERSCRIPT TWO
+0xB3 0x00B3 #SUPERSCRIPT THREE
+0xB4 0x00B4 #ACUTE ACCENT
+0xB5 0x00B5 #MICRO SIGN
+0xB6 0x00B6 #PILCROW SIGN
+0xB7 0x00B7 #MIDDLE DOT
+0xB8 0x00B8 #CEDILLA
+0xB9 0x00B9 #SUPERSCRIPT ONE
+0xBA 0x00BA #MASCULINE ORDINAL INDICATOR
+0xBB 0x00BB #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x00BC #VULGAR FRACTION ONE QUARTER
+0xBD 0x00BD #VULGAR FRACTION ONE HALF
+0xBE 0x00BE #VULGAR FRACTION THREE QUARTERS
+0xBF 0x00BF #INVERTED QUESTION MARK
+0xC0 0x00C0 #LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 #LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 #LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 #LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 #LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 #LATIN CAPITAL LETTER AE
+0xC7 0x00C7 #LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 #LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 #LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA #LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB #LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC #LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD #LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE #LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF #LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x00D0 #LATIN CAPITAL LETTER ETH
+0xD1 0x00D1 #LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 #LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 #LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 #LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 #LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 #MULTIPLICATION SIGN
+0xD8 0x00D8 #LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 #LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA #LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB #LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC #LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD #LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x00DE #LATIN CAPITAL LETTER THORN
+0xDF 0x00DF #LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 #LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 #LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 #LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 #LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 #LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 #LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 #LATIN SMALL LETTER AE
+0xE7 0x00E7 #LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 #LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 #LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA #LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB #LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC #LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED #LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE #LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF #LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x00F0 #LATIN SMALL LETTER ETH
+0xF1 0x00F1 #LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 #LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 #LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 #LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 #LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 #LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 #DIVISION SIGN
+0xF8 0x00F8 #LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 #LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA #LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB #LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC #LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD #LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x00FE #LATIN SMALL LETTER THORN
+0xFF 0x00FF #LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/standard/html_tables/mappings/CP866.TXT b/ext/standard/html_tables/mappings/CP866.TXT
new file mode 100644
index 0000000000..b0213a1e81
--- /dev/null
+++ b/ext/standard/html_tables/mappings/CP866.TXT
@@ -0,0 +1,275 @@
+#
+# Name: cp866_DOSCyrillicRussian to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Contact: Shawn.Steele@microsoft.com
+#
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp866_DOSCyrillicRussian code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp866_DOSCyrillicRussian order
+#
+0x00 0x0000 #NULL
+0x01 0x0001 #START OF HEADING
+0x02 0x0002 #START OF TEXT
+0x03 0x0003 #END OF TEXT
+0x04 0x0004 #END OF TRANSMISSION
+0x05 0x0005 #ENQUIRY
+0x06 0x0006 #ACKNOWLEDGE
+0x07 0x0007 #BELL
+0x08 0x0008 #BACKSPACE
+0x09 0x0009 #HORIZONTAL TABULATION
+0x0a 0x000a #LINE FEED
+0x0b 0x000b #VERTICAL TABULATION
+0x0c 0x000c #FORM FEED
+0x0d 0x000d #CARRIAGE RETURN
+0x0e 0x000e #SHIFT OUT
+0x0f 0x000f #SHIFT IN
+0x10 0x0010 #DATA LINK ESCAPE
+0x11 0x0011 #DEVICE CONTROL ONE
+0x12 0x0012 #DEVICE CONTROL TWO
+0x13 0x0013 #DEVICE CONTROL THREE
+0x14 0x0014 #DEVICE CONTROL FOUR
+0x15 0x0015 #NEGATIVE ACKNOWLEDGE
+0x16 0x0016 #SYNCHRONOUS IDLE
+0x17 0x0017 #END OF TRANSMISSION BLOCK
+0x18 0x0018 #CANCEL
+0x19 0x0019 #END OF MEDIUM
+0x1a 0x001a #SUBSTITUTE
+0x1b 0x001b #ESCAPE
+0x1c 0x001c #FILE SEPARATOR
+0x1d 0x001d #GROUP SEPARATOR
+0x1e 0x001e #RECORD SEPARATOR
+0x1f 0x001f #UNIT SEPARATOR
+0x20 0x0020 #SPACE
+0x21 0x0021 #EXCLAMATION MARK
+0x22 0x0022 #QUOTATION MARK
+0x23 0x0023 #NUMBER SIGN
+0x24 0x0024 #DOLLAR SIGN
+0x25 0x0025 #PERCENT SIGN
+0x26 0x0026 #AMPERSAND
+0x27 0x0027 #APOSTROPHE
+0x28 0x0028 #LEFT PARENTHESIS
+0x29 0x0029 #RIGHT PARENTHESIS
+0x2a 0x002a #ASTERISK
+0x2b 0x002b #PLUS SIGN
+0x2c 0x002c #COMMA
+0x2d 0x002d #HYPHEN-MINUS
+0x2e 0x002e #FULL STOP
+0x2f 0x002f #SOLIDUS
+0x30 0x0030 #DIGIT ZERO
+0x31 0x0031 #DIGIT ONE
+0x32 0x0032 #DIGIT TWO
+0x33 0x0033 #DIGIT THREE
+0x34 0x0034 #DIGIT FOUR
+0x35 0x0035 #DIGIT FIVE
+0x36 0x0036 #DIGIT SIX
+0x37 0x0037 #DIGIT SEVEN
+0x38 0x0038 #DIGIT EIGHT
+0x39 0x0039 #DIGIT NINE
+0x3a 0x003a #COLON
+0x3b 0x003b #SEMICOLON
+0x3c 0x003c #LESS-THAN SIGN
+0x3d 0x003d #EQUALS SIGN
+0x3e 0x003e #GREATER-THAN SIGN
+0x3f 0x003f #QUESTION MARK
+0x40 0x0040 #COMMERCIAL AT
+0x41 0x0041 #LATIN CAPITAL LETTER A
+0x42 0x0042 #LATIN CAPITAL LETTER B
+0x43 0x0043 #LATIN CAPITAL LETTER C
+0x44 0x0044 #LATIN CAPITAL LETTER D
+0x45 0x0045 #LATIN CAPITAL LETTER E
+0x46 0x0046 #LATIN CAPITAL LETTER F
+0x47 0x0047 #LATIN CAPITAL LETTER G
+0x48 0x0048 #LATIN CAPITAL LETTER H
+0x49 0x0049 #LATIN CAPITAL LETTER I
+0x4a 0x004a #LATIN CAPITAL LETTER J
+0x4b 0x004b #LATIN CAPITAL LETTER K
+0x4c 0x004c #LATIN CAPITAL LETTER L
+0x4d 0x004d #LATIN CAPITAL LETTER M
+0x4e 0x004e #LATIN CAPITAL LETTER N
+0x4f 0x004f #LATIN CAPITAL LETTER O
+0x50 0x0050 #LATIN CAPITAL LETTER P
+0x51 0x0051 #LATIN CAPITAL LETTER Q
+0x52 0x0052 #LATIN CAPITAL LETTER R
+0x53 0x0053 #LATIN CAPITAL LETTER S
+0x54 0x0054 #LATIN CAPITAL LETTER T
+0x55 0x0055 #LATIN CAPITAL LETTER U
+0x56 0x0056 #LATIN CAPITAL LETTER V
+0x57 0x0057 #LATIN CAPITAL LETTER W
+0x58 0x0058 #LATIN CAPITAL LETTER X
+0x59 0x0059 #LATIN CAPITAL LETTER Y
+0x5a 0x005a #LATIN CAPITAL LETTER Z
+0x5b 0x005b #LEFT SQUARE BRACKET
+0x5c 0x005c #REVERSE SOLIDUS
+0x5d 0x005d #RIGHT SQUARE BRACKET
+0x5e 0x005e #CIRCUMFLEX ACCENT
+0x5f 0x005f #LOW LINE
+0x60 0x0060 #GRAVE ACCENT
+0x61 0x0061 #LATIN SMALL LETTER A
+0x62 0x0062 #LATIN SMALL LETTER B
+0x63 0x0063 #LATIN SMALL LETTER C
+0x64 0x0064 #LATIN SMALL LETTER D
+0x65 0x0065 #LATIN SMALL LETTER E
+0x66 0x0066 #LATIN SMALL LETTER F
+0x67 0x0067 #LATIN SMALL LETTER G
+0x68 0x0068 #LATIN SMALL LETTER H
+0x69 0x0069 #LATIN SMALL LETTER I
+0x6a 0x006a #LATIN SMALL LETTER J
+0x6b 0x006b #LATIN SMALL LETTER K
+0x6c 0x006c #LATIN SMALL LETTER L
+0x6d 0x006d #LATIN SMALL LETTER M
+0x6e 0x006e #LATIN SMALL LETTER N
+0x6f 0x006f #LATIN SMALL LETTER O
+0x70 0x0070 #LATIN SMALL LETTER P
+0x71 0x0071 #LATIN SMALL LETTER Q
+0x72 0x0072 #LATIN SMALL LETTER R
+0x73 0x0073 #LATIN SMALL LETTER S
+0x74 0x0074 #LATIN SMALL LETTER T
+0x75 0x0075 #LATIN SMALL LETTER U
+0x76 0x0076 #LATIN SMALL LETTER V
+0x77 0x0077 #LATIN SMALL LETTER W
+0x78 0x0078 #LATIN SMALL LETTER X
+0x79 0x0079 #LATIN SMALL LETTER Y
+0x7a 0x007a #LATIN SMALL LETTER Z
+0x7b 0x007b #LEFT CURLY BRACKET
+0x7c 0x007c #VERTICAL LINE
+0x7d 0x007d #RIGHT CURLY BRACKET
+0x7e 0x007e #TILDE
+0x7f 0x007f #DELETE
+0x80 0x0410 #CYRILLIC CAPITAL LETTER A
+0x81 0x0411 #CYRILLIC CAPITAL LETTER BE
+0x82 0x0412 #CYRILLIC CAPITAL LETTER VE
+0x83 0x0413 #CYRILLIC CAPITAL LETTER GHE
+0x84 0x0414 #CYRILLIC CAPITAL LETTER DE
+0x85 0x0415 #CYRILLIC CAPITAL LETTER IE
+0x86 0x0416 #CYRILLIC CAPITAL LETTER ZHE
+0x87 0x0417 #CYRILLIC CAPITAL LETTER ZE
+0x88 0x0418 #CYRILLIC CAPITAL LETTER I
+0x89 0x0419 #CYRILLIC CAPITAL LETTER SHORT I
+0x8a 0x041a #CYRILLIC CAPITAL LETTER KA
+0x8b 0x041b #CYRILLIC CAPITAL LETTER EL
+0x8c 0x041c #CYRILLIC CAPITAL LETTER EM
+0x8d 0x041d #CYRILLIC CAPITAL LETTER EN
+0x8e 0x041e #CYRILLIC CAPITAL LETTER O
+0x8f 0x041f #CYRILLIC CAPITAL LETTER PE
+0x90 0x0420 #CYRILLIC CAPITAL LETTER ER
+0x91 0x0421 #CYRILLIC CAPITAL LETTER ES
+0x92 0x0422 #CYRILLIC CAPITAL LETTER TE
+0x93 0x0423 #CYRILLIC CAPITAL LETTER U
+0x94 0x0424 #CYRILLIC CAPITAL LETTER EF
+0x95 0x0425 #CYRILLIC CAPITAL LETTER HA
+0x96 0x0426 #CYRILLIC CAPITAL LETTER TSE
+0x97 0x0427 #CYRILLIC CAPITAL LETTER CHE
+0x98 0x0428 #CYRILLIC CAPITAL LETTER SHA
+0x99 0x0429 #CYRILLIC CAPITAL LETTER SHCHA
+0x9a 0x042a #CYRILLIC CAPITAL LETTER HARD SIGN
+0x9b 0x042b #CYRILLIC CAPITAL LETTER YERU
+0x9c 0x042c #CYRILLIC CAPITAL LETTER SOFT SIGN
+0x9d 0x042d #CYRILLIC CAPITAL LETTER E
+0x9e 0x042e #CYRILLIC CAPITAL LETTER YU
+0x9f 0x042f #CYRILLIC CAPITAL LETTER YA
+0xa0 0x0430 #CYRILLIC SMALL LETTER A
+0xa1 0x0431 #CYRILLIC SMALL LETTER BE
+0xa2 0x0432 #CYRILLIC SMALL LETTER VE
+0xa3 0x0433 #CYRILLIC SMALL LETTER GHE
+0xa4 0x0434 #CYRILLIC SMALL LETTER DE
+0xa5 0x0435 #CYRILLIC SMALL LETTER IE
+0xa6 0x0436 #CYRILLIC SMALL LETTER ZHE
+0xa7 0x0437 #CYRILLIC SMALL LETTER ZE
+0xa8 0x0438 #CYRILLIC SMALL LETTER I
+0xa9 0x0439 #CYRILLIC SMALL LETTER SHORT I
+0xaa 0x043a #CYRILLIC SMALL LETTER KA
+0xab 0x043b #CYRILLIC SMALL LETTER EL
+0xac 0x043c #CYRILLIC SMALL LETTER EM
+0xad 0x043d #CYRILLIC SMALL LETTER EN
+0xae 0x043e #CYRILLIC SMALL LETTER O
+0xaf 0x043f #CYRILLIC SMALL LETTER PE
+0xb0 0x2591 #LIGHT SHADE
+0xb1 0x2592 #MEDIUM SHADE
+0xb2 0x2593 #DARK SHADE
+0xb3 0x2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 0x2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 0x2561 #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6 0x2562 #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7 0x2556 #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8 0x2555 #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9 0x2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba 0x2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb 0x2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc 0x255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd 0x255c #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe 0x255b #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf 0x2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 0x2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 0x2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 0x252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 0x251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 0x2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 0x253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 0x255e #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7 0x255f #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8 0x255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 0x2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca 0x2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb 0x2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc 0x2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd 0x2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce 0x256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf 0x2567 #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0 0x2568 #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1 0x2564 #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2 0x2565 #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3 0x2559 #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4 0x2558 #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5 0x2552 #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6 0x2553 #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7 0x256b #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8 0x256a #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9 0x2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda 0x250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb 0x2588 #FULL BLOCK
+0xdc 0x2584 #LOWER HALF BLOCK
+0xdd 0x258c #LEFT HALF BLOCK
+0xde 0x2590 #RIGHT HALF BLOCK
+0xdf 0x2580 #UPPER HALF BLOCK
+0xe0 0x0440 #CYRILLIC SMALL LETTER ER
+0xe1 0x0441 #CYRILLIC SMALL LETTER ES
+0xe2 0x0442 #CYRILLIC SMALL LETTER TE
+0xe3 0x0443 #CYRILLIC SMALL LETTER U
+0xe4 0x0444 #CYRILLIC SMALL LETTER EF
+0xe5 0x0445 #CYRILLIC SMALL LETTER HA
+0xe6 0x0446 #CYRILLIC SMALL LETTER TSE
+0xe7 0x0447 #CYRILLIC SMALL LETTER CHE
+0xe8 0x0448 #CYRILLIC SMALL LETTER SHA
+0xe9 0x0449 #CYRILLIC SMALL LETTER SHCHA
+0xea 0x044a #CYRILLIC SMALL LETTER HARD SIGN
+0xeb 0x044b #CYRILLIC SMALL LETTER YERU
+0xec 0x044c #CYRILLIC SMALL LETTER SOFT SIGN
+0xed 0x044d #CYRILLIC SMALL LETTER E
+0xee 0x044e #CYRILLIC SMALL LETTER YU
+0xef 0x044f #CYRILLIC SMALL LETTER YA
+0xf0 0x0401 #CYRILLIC CAPITAL LETTER IO
+0xf1 0x0451 #CYRILLIC SMALL LETTER IO
+0xf2 0x0404 #CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xf3 0x0454 #CYRILLIC SMALL LETTER UKRAINIAN IE
+0xf4 0x0407 #CYRILLIC CAPITAL LETTER YI
+0xf5 0x0457 #CYRILLIC SMALL LETTER YI
+0xf6 0x040e #CYRILLIC CAPITAL LETTER SHORT U
+0xf7 0x045e #CYRILLIC SMALL LETTER SHORT U
+0xf8 0x00b0 #DEGREE SIGN
+0xf9 0x2219 #BULLET OPERATOR
+0xfa 0x00b7 #MIDDLE DOT
+0xfb 0x221a #SQUARE ROOT
+0xfc 0x2116 #NUMERO SIGN
+0xfd 0x00a4 #CURRENCY SIGN
+0xfe 0x25a0 #BLACK SQUARE
+0xff 0x00a0 #NO-BREAK SPACE
+
+ \ No newline at end of file
diff --git a/ext/standard/html_tables/mappings/KOI8-R.TXT b/ext/standard/html_tables/mappings/KOI8-R.TXT
new file mode 100644
index 0000000000..510561005c
--- /dev/null
+++ b/ext/standard/html_tables/mappings/KOI8-R.TXT
@@ -0,0 +1,302 @@
+#
+# Name: KOI8-R (RFC1489) to Unicode
+# Unicode version: 3.0
+# Table version: 1.0
+# Table format: Format A
+# Date: 18 August 1999
+# Authors: Helmut Richter <richter@lrz.de>
+#
+# Copyright (c) 1991-1999 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on optical media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Unicode, Inc. hereby grants the right to freely use the information
+# supplied in this file in the creation of products supporting the
+# Unicode Standard, and to make copies of this file in any form for
+# internal or external distribution as long as this notice remains
+# attached.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# KOI8-R characters map into Unicode. The underlying document is the
+# mapping described in RFC 1489. No statements are made as to whether
+# this mapping is the same as the mapping defined as "Code Page 878"
+# with some vendors.
+#
+# Format: Three tab-separated columns
+# Column #1 is the KOI8-R code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in KOI8-R order.
+#
+# Version history
+# 1.0 version: created.
+#
+# Any comments or problems, contact <errata@unicode.org>
+# Please note that <errata@unicode.org> is an archival address;
+# notices will be checked, but do not expect an immediate response.
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x2500 # BOX DRAWINGS LIGHT HORIZONTAL
+0x81 0x2502 # BOX DRAWINGS LIGHT VERTICAL
+0x82 0x250C # BOX DRAWINGS LIGHT DOWN AND RIGHT
+0x83 0x2510 # BOX DRAWINGS LIGHT DOWN AND LEFT
+0x84 0x2514 # BOX DRAWINGS LIGHT UP AND RIGHT
+0x85 0x2518 # BOX DRAWINGS LIGHT UP AND LEFT
+0x86 0x251C # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0x87 0x2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0x88 0x252C # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0x89 0x2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0x8A 0x253C # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0x8B 0x2580 # UPPER HALF BLOCK
+0x8C 0x2584 # LOWER HALF BLOCK
+0x8D 0x2588 # FULL BLOCK
+0x8E 0x258C # LEFT HALF BLOCK
+0x8F 0x2590 # RIGHT HALF BLOCK
+0x90 0x2591 # LIGHT SHADE
+0x91 0x2592 # MEDIUM SHADE
+0x92 0x2593 # DARK SHADE
+0x93 0x2320 # TOP HALF INTEGRAL
+0x94 0x25A0 # BLACK SQUARE
+0x95 0x2219 # BULLET OPERATOR
+0x96 0x221A # SQUARE ROOT
+0x97 0x2248 # ALMOST EQUAL TO
+0x98 0x2264 # LESS-THAN OR EQUAL TO
+0x99 0x2265 # GREATER-THAN OR EQUAL TO
+0x9A 0x00A0 # NO-BREAK SPACE
+0x9B 0x2321 # BOTTOM HALF INTEGRAL
+0x9C 0x00B0 # DEGREE SIGN
+0x9D 0x00B2 # SUPERSCRIPT TWO
+0x9E 0x00B7 # MIDDLE DOT
+0x9F 0x00F7 # DIVISION SIGN
+0xA0 0x2550 # BOX DRAWINGS DOUBLE HORIZONTAL
+0xA1 0x2551 # BOX DRAWINGS DOUBLE VERTICAL
+0xA2 0x2552 # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xA3 0x0451 # CYRILLIC SMALL LETTER IO
+0xA4 0x2553 # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xA5 0x2554 # BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xA6 0x2555 # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xA7 0x2556 # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xA8 0x2557 # BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xA9 0x2558 # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xAA 0x2559 # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xAB 0x255A # BOX DRAWINGS DOUBLE UP AND RIGHT
+0xAC 0x255B # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xAD 0x255C # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xAE 0x255D # BOX DRAWINGS DOUBLE UP AND LEFT
+0xAF 0x255E # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xB0 0x255F # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xB1 0x2560 # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xB2 0x2561 # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xB3 0x0401 # CYRILLIC CAPITAL LETTER IO
+0xB4 0x2562 # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xB5 0x2563 # BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xB6 0x2564 # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xB7 0x2565 # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xB8 0x2566 # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xB9 0x2567 # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xBA 0x2568 # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xBB 0x2569 # BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xBC 0x256A # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xBD 0x256B # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xBE 0x256C # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xBF 0x00A9 # COPYRIGHT SIGN
+0xC0 0x044E # CYRILLIC SMALL LETTER YU
+0xC1 0x0430 # CYRILLIC SMALL LETTER A
+0xC2 0x0431 # CYRILLIC SMALL LETTER BE
+0xC3 0x0446 # CYRILLIC SMALL LETTER TSE
+0xC4 0x0434 # CYRILLIC SMALL LETTER DE
+0xC5 0x0435 # CYRILLIC SMALL LETTER IE
+0xC6 0x0444 # CYRILLIC SMALL LETTER EF
+0xC7 0x0433 # CYRILLIC SMALL LETTER GHE
+0xC8 0x0445 # CYRILLIC SMALL LETTER HA
+0xC9 0x0438 # CYRILLIC SMALL LETTER I
+0xCA 0x0439 # CYRILLIC SMALL LETTER SHORT I
+0xCB 0x043A # CYRILLIC SMALL LETTER KA
+0xCC 0x043B # CYRILLIC SMALL LETTER EL
+0xCD 0x043C # CYRILLIC SMALL LETTER EM
+0xCE 0x043D # CYRILLIC SMALL LETTER EN
+0xCF 0x043E # CYRILLIC SMALL LETTER O
+0xD0 0x043F # CYRILLIC SMALL LETTER PE
+0xD1 0x044F # CYRILLIC SMALL LETTER YA
+0xD2 0x0440 # CYRILLIC SMALL LETTER ER
+0xD3 0x0441 # CYRILLIC SMALL LETTER ES
+0xD4 0x0442 # CYRILLIC SMALL LETTER TE
+0xD5 0x0443 # CYRILLIC SMALL LETTER U
+0xD6 0x0436 # CYRILLIC SMALL LETTER ZHE
+0xD7 0x0432 # CYRILLIC SMALL LETTER VE
+0xD8 0x044C # CYRILLIC SMALL LETTER SOFT SIGN
+0xD9 0x044B # CYRILLIC SMALL LETTER YERU
+0xDA 0x0437 # CYRILLIC SMALL LETTER ZE
+0xDB 0x0448 # CYRILLIC SMALL LETTER SHA
+0xDC 0x044D # CYRILLIC SMALL LETTER E
+0xDD 0x0449 # CYRILLIC SMALL LETTER SHCHA
+0xDE 0x0447 # CYRILLIC SMALL LETTER CHE
+0xDF 0x044A # CYRILLIC SMALL LETTER HARD SIGN
+0xE0 0x042E # CYRILLIC CAPITAL LETTER YU
+0xE1 0x0410 # CYRILLIC CAPITAL LETTER A
+0xE2 0x0411 # CYRILLIC CAPITAL LETTER BE
+0xE3 0x0426 # CYRILLIC CAPITAL LETTER TSE
+0xE4 0x0414 # CYRILLIC CAPITAL LETTER DE
+0xE5 0x0415 # CYRILLIC CAPITAL LETTER IE
+0xE6 0x0424 # CYRILLIC CAPITAL LETTER EF
+0xE7 0x0413 # CYRILLIC CAPITAL LETTER GHE
+0xE8 0x0425 # CYRILLIC CAPITAL LETTER HA
+0xE9 0x0418 # CYRILLIC CAPITAL LETTER I
+0xEA 0x0419 # CYRILLIC CAPITAL LETTER SHORT I
+0xEB 0x041A # CYRILLIC CAPITAL LETTER KA
+0xEC 0x041B # CYRILLIC CAPITAL LETTER EL
+0xED 0x041C # CYRILLIC CAPITAL LETTER EM
+0xEE 0x041D # CYRILLIC CAPITAL LETTER EN
+0xEF 0x041E # CYRILLIC CAPITAL LETTER O
+0xF0 0x041F # CYRILLIC CAPITAL LETTER PE
+0xF1 0x042F # CYRILLIC CAPITAL LETTER YA
+0xF2 0x0420 # CYRILLIC CAPITAL LETTER ER
+0xF3 0x0421 # CYRILLIC CAPITAL LETTER ES
+0xF4 0x0422 # CYRILLIC CAPITAL LETTER TE
+0xF5 0x0423 # CYRILLIC CAPITAL LETTER U
+0xF6 0x0416 # CYRILLIC CAPITAL LETTER ZHE
+0xF7 0x0412 # CYRILLIC CAPITAL LETTER VE
+0xF8 0x042C # CYRILLIC CAPITAL LETTER SOFT SIGN
+0xF9 0x042B # CYRILLIC CAPITAL LETTER YERU
+0xFA 0x0417 # CYRILLIC CAPITAL LETTER ZE
+0xFB 0x0428 # CYRILLIC CAPITAL LETTER SHA
+0xFC 0x042D # CYRILLIC CAPITAL LETTER E
+0xFD 0x0429 # CYRILLIC CAPITAL LETTER SHCHA
+0xFE 0x0427 # CYRILLIC CAPITAL LETTER CHE
+0xFF 0x042A # CYRILLIC CAPITAL LETTER HARD SIGN
diff --git a/ext/standard/html_tables/mappings/ROMAN.TXT b/ext/standard/html_tables/mappings/ROMAN.TXT
new file mode 100644
index 0000000000..5b3b8b4005
--- /dev/null
+++ b/ext/standard/html_tables/mappings/ROMAN.TXT
@@ -0,0 +1,370 @@
+#=======================================================================
+# File name: ROMAN.TXT
+#
+# Contents: Map (external version) from Mac OS Roman
+# character set to Unicode 2.1 and later.
+#
+# Copyright: (c) 1994-2002, 2005 by Apple Computer, Inc., all rights
+# reserved.
+#
+# Contact: charsets@apple.com
+#
+# Changes:
+#
+# c02 2005-Apr-05 Update header comments. Matches internal xml
+# <c1.1> and Text Encoding Converter 2.0.
+# b4,c1 2002-Dec-19 Update URLs, notes. Matches internal
+# utom<b5>.
+# b03 1999-Sep-22 Update contact e-mail address. Matches
+# internal utom<b4>, ufrm<b3>, and Text
+# Encoding Converter version 1.5.
+# b02 1998-Aug-18 Encoding changed for Mac OS 8.5; change
+# mapping of 0xDB from CURRENCY SIGN to
+# EURO SIGN. Matches internal utom<b3>,
+# ufrm<b3>.
+# n08 1998-Feb-05 Minor update to header comments
+# n06 1997-Dec-14 Add warning about future changes to 0xDB
+# from CURRENCY SIGN to EURO SIGN. Clarify
+# some header information
+# n04 1997-Dec-01 Update to match internal utom<n3>, ufrm<n22>:
+# Change standard mapping for 0xBD from U+2126
+# to its canonical decomposition, U+03A9.
+# n03 1995-Apr-15 First version (after fixing some typos).
+# Matches internal ufrm<n9>.
+#
+# Standard header:
+# ----------------
+#
+# Apple, the Apple logo, and Macintosh are trademarks of Apple
+# Computer, Inc., registered in the United States and other countries.
+# Unicode is a trademark of Unicode Inc. For the sake of brevity,
+# throughout this document, "Macintosh" can be used to refer to
+# Macintosh computers and "Unicode" can be used to refer to the
+# Unicode standard.
+#
+# Apple Computer, Inc. ("Apple") makes no warranty or representation,
+# either express or implied, with respect to this document and the
+# included data, its quality, accuracy, or fitness for a particular
+# purpose. In no event will Apple be liable for direct, indirect,
+# special, incidental, or consequential damages resulting from any
+# defect or inaccuracy in this document or the included data.
+#
+# These mapping tables and character lists are subject to change.
+# The latest tables should be available from the following:
+#
+# <http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/>
+#
+# For general information about Mac OS encodings and these mapping
+# tables, see the file "README.TXT".
+#
+# Format:
+# -------
+#
+# Three tab-separated columns;
+# '#' begins a comment which continues to the end of the line.
+# Column #1 is the Mac OS Roman code (in hex as 0xNN)
+# Column #2 is the corresponding Unicode (in hex as 0xNNNN)
+# Column #3 is a comment containing the Unicode name
+#
+# The entries are in Mac OS Roman code order.
+#
+# One of these mappings requires the use of a corporate character.
+# See the file "CORPCHAR.TXT" and notes below.
+#
+# Control character mappings are not shown in this table, following
+# the conventions of the standard UTC mapping tables. However, the
+# Mac OS Roman character set uses the standard control characters at
+# 0x00-0x1F and 0x7F.
+#
+# Notes on Mac OS Roman:
+# ----------------------
+#
+# This is a legacy Mac OS encoding; in the Mac OS X Carbon and Cocoa
+# environments, it is only supported directly in programming
+# interfaces for QuickDraw Text, the Script Manager, and related
+# Text Utilities. For other purposes it is supported via transcoding
+# to and from Unicode.
+#
+# This character set is used for at least the following Mac OS
+# localizations: U.S., British, Canadian French, French, Swiss
+# French, German, Swiss German, Italian, Swiss Italian, Dutch,
+# Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
+# Portuguese, Brazilian, and the default International system.
+#
+# Variants of Mac OS Roman are used for Croatian, Icelandic,
+# Turkish, Romanian, and other encodings. Separate mapping tables
+# are available for these encodings.
+#
+# Before Mac OS 8.5, code point 0xDB was CURRENCY SIGN, and was
+# mapped to U+00A4. In Mac OS 8.5 and later versions, code point
+# 0xDB is changed to EURO SIGN and maps to U+20AC; the standard
+# Apple fonts are updated for Mac OS 8.5 to reflect this. There is
+# a "currency sign" variant of the Mac OS Roman encoding that still
+# maps 0xDB to U+00A4; this can be used for older fonts.
+#
+# Before Mac OS 8.5, the ROM bitmap versions of the fonts Chicago,
+# New York, Geneva, and Monaco did not implement the full Mac OS
+# Roman character set; they only supported character codes up to
+# 0xD8. The TrueType versions of these fonts have always implemented
+# the full character set, as with the bitmap and TrueType versions
+# of the other standard Roman fonts.
+#
+# In all Mac OS encodings, fonts such as Chicago which are used
+# as "system" fonts (for menus, dialogs, etc.) have four glyphs
+# at code points 0x11-0x14 for transient use by the Menu Manager.
+# These glyphs are not intended as characters for use in normal
+# text, and the associated code points are not generally
+# interpreted as associated with these glyphs; they are usually
+# interpreted (if at all) as the control codes DC1-DC4.
+#
+# Unicode mapping issues and notes:
+# ---------------------------------
+#
+# The following corporate zone Unicode character is used in this
+# mapping:
+#
+# 0xF8FF Apple logo
+#
+# NOTE: The graphic image associated with the Apple logo character
+# is not authorized for use without permission of Apple, and
+# unauthorized use might constitute trademark infringement.
+#
+# Details of mapping changes in each version:
+# -------------------------------------------
+#
+# Changes from version n08 to version b02:
+#
+# - Encoding changed for Mac OS 8.5; change mapping of 0xDB from
+# CURRENCY SIGN (U+00A4) to EURO SIGN (U+20AC).
+#
+# Changes from version n03 to version n04:
+#
+# - Change mapping of 0xBD from U+2126 to its canonical
+# decomposition, U+03A9.
+#
+##################
+
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+#
+0x80 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0x81 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0x82 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0x83 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0x84 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0x85 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0x86 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0x87 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0x88 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0x89 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x8A 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0x8B 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0x8C 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0x8D 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0x8E 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0x8F 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0x90 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x91 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0x92 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0x93 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0x94 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x95 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0x96 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0x97 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0x98 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0x99 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x9A 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0x9B 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0x9C 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0x9D 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0x9E 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x9F 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xA0 0x2020 # DAGGER
+0xA1 0x00B0 # DEGREE SIGN
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A7 # SECTION SIGN
+0xA5 0x2022 # BULLET
+0xA6 0x00B6 # PILCROW SIGN
+0xA7 0x00DF # LATIN SMALL LETTER SHARP S
+0xA8 0x00AE # REGISTERED SIGN
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x2122 # TRADE MARK SIGN
+0xAB 0x00B4 # ACUTE ACCENT
+0xAC 0x00A8 # DIAERESIS
+0xAD 0x2260 # NOT EQUAL TO
+0xAE 0x00C6 # LATIN CAPITAL LETTER AE
+0xAF 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xB0 0x221E # INFINITY
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x2264 # LESS-THAN OR EQUAL TO
+0xB3 0x2265 # GREATER-THAN OR EQUAL TO
+0xB4 0x00A5 # YEN SIGN
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x2202 # PARTIAL DIFFERENTIAL
+0xB7 0x2211 # N-ARY SUMMATION
+0xB8 0x220F # N-ARY PRODUCT
+0xB9 0x03C0 # GREEK SMALL LETTER PI
+0xBA 0x222B # INTEGRAL
+0xBB 0x00AA # FEMININE ORDINAL INDICATOR
+0xBC 0x00BA # MASCULINE ORDINAL INDICATOR
+0xBD 0x03A9 # GREEK CAPITAL LETTER OMEGA
+0xBE 0x00E6 # LATIN SMALL LETTER AE
+0xBF 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xC0 0x00BF # INVERTED QUESTION MARK
+0xC1 0x00A1 # INVERTED EXCLAMATION MARK
+0xC2 0x00AC # NOT SIGN
+0xC3 0x221A # SQUARE ROOT
+0xC4 0x0192 # LATIN SMALL LETTER F WITH HOOK
+0xC5 0x2248 # ALMOST EQUAL TO
+0xC6 0x2206 # INCREMENT
+0xC7 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC8 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC9 0x2026 # HORIZONTAL ELLIPSIS
+0xCA 0x00A0 # NO-BREAK SPACE
+0xCB 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xCC 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xCD 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xCE 0x0152 # LATIN CAPITAL LIGATURE OE
+0xCF 0x0153 # LATIN SMALL LIGATURE OE
+0xD0 0x2013 # EN DASH
+0xD1 0x2014 # EM DASH
+0xD2 0x201C # LEFT DOUBLE QUOTATION MARK
+0xD3 0x201D # RIGHT DOUBLE QUOTATION MARK
+0xD4 0x2018 # LEFT SINGLE QUOTATION MARK
+0xD5 0x2019 # RIGHT SINGLE QUOTATION MARK
+0xD6 0x00F7 # DIVISION SIGN
+0xD7 0x25CA # LOZENGE
+0xD8 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
+0xD9 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xDA 0x2044 # FRACTION SLASH
+0xDB 0x20AC # EURO SIGN
+0xDC 0x2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0xDD 0x203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0xDE 0xFB01 # LATIN SMALL LIGATURE FI
+0xDF 0xFB02 # LATIN SMALL LIGATURE FL
+0xE0 0x2021 # DOUBLE DAGGER
+0xE1 0x00B7 # MIDDLE DOT
+0xE2 0x201A # SINGLE LOW-9 QUOTATION MARK
+0xE3 0x201E # DOUBLE LOW-9 QUOTATION MARK
+0xE4 0x2030 # PER MILLE SIGN
+0xE5 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xE6 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xE7 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xE8 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xE9 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xEA 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xEB 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xEC 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xED 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xEE 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xEF 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xF0 0xF8FF # Apple logo
+0xF1 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xF2 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xF3 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xF4 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xF5 0x0131 # LATIN SMALL LETTER DOTLESS I
+0xF6 0x02C6 # MODIFIER LETTER CIRCUMFLEX ACCENT
+0xF7 0x02DC # SMALL TILDE
+0xF8 0x00AF # MACRON
+0xF9 0x02D8 # BREVE
+0xFA 0x02D9 # DOT ABOVE
+0xFB 0x02DA # RING ABOVE
+0xFC 0x00B8 # CEDILLA
+0xFD 0x02DD # DOUBLE ACUTE ACCENT
+0xFE 0x02DB # OGONEK
+0xFF 0x02C7 # CARON
diff --git a/ext/standard/http.c b/ext/standard/http.c
index e7de97735c..8f5625e244 100644
--- a/ext/standard/http.c
+++ b/ext/standard/http.c
@@ -29,10 +29,12 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
const char *num_prefix, int num_prefix_len,
const char *key_prefix, int key_prefix_len,
const char *key_suffix, int key_suffix_len,
- zval *type, char *arg_sep TSRMLS_DC)
+ zval *type, char *arg_sep, int enc_type TSRMLS_DC)
{
- char *key = NULL, *ekey, *newprefix, *p;
- int arg_sep_len, key_len, ekey_len, key_type, newprefix_len;
+ char *key = NULL;
+ char *ekey, *newprefix, *p;
+ int arg_sep_len, ekey_len, key_type, newprefix_len;
+ uint key_len;
ulong idx;
zval **zdata = NULL, *copyzval;
@@ -64,14 +66,14 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
/* handling for private & protected object properties */
if (key && *key == '\0' && type != NULL) {
- char *tmp;
+ const char *tmp;
zend_object *zobj = zend_objects_get_address(type TSRMLS_CC);
if (zend_check_property_access(zobj, key, key_len-1 TSRMLS_CC) != SUCCESS) {
/* private or protected property access outside of the class */
continue;
}
- zend_unmangle_property_name(key, key_len-1, &tmp, &key);
+ zend_unmangle_property_name(key, key_len-1, &tmp, (const char**)&key);
key_len = strlen(key);
}
@@ -81,7 +83,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
}
if (Z_TYPE_PP(zdata) == IS_ARRAY || Z_TYPE_PP(zdata) == IS_OBJECT) {
if (key_type == HASH_KEY_IS_STRING) {
- ekey = php_url_encode(key, key_len, &ekey_len);
+ if (enc_type == PHP_QUERY_RFC3986) {
+ ekey = php_raw_url_encode(key, key_len, &ekey_len);
+ } else {
+ ekey = php_url_encode(key, key_len, &ekey_len);
+ }
newprefix_len = key_suffix_len + ekey_len + key_prefix_len + 3 /* %5B */;
newprefix = emalloc(newprefix_len + 1);
p = newprefix;
@@ -132,7 +138,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
*p = '\0';
}
ht->nApplyCount++;
- php_url_encode_hash_ex(HASH_OF(*zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL), arg_sep TSRMLS_CC);
+ php_url_encode_hash_ex(HASH_OF(*zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL), arg_sep, enc_type TSRMLS_CC);
ht->nApplyCount--;
efree(newprefix);
} else if (Z_TYPE_PP(zdata) == IS_NULL || Z_TYPE_PP(zdata) == IS_RESOURCE) {
@@ -145,7 +151,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
/* Simple key=value */
smart_str_appendl(formstr, key_prefix, key_prefix_len);
if (key_type == HASH_KEY_IS_STRING) {
- ekey = php_url_encode(key, key_len, &ekey_len);
+ if (enc_type == PHP_QUERY_RFC3986) {
+ ekey = php_raw_url_encode(key, key_len, &ekey_len);
+ } else {
+ ekey = php_url_encode(key, key_len, &ekey_len);
+ }
smart_str_appendl(formstr, ekey, ekey_len);
efree(ekey);
} else {
@@ -161,7 +171,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
smart_str_appendl(formstr, "=", 1);
switch (Z_TYPE_PP(zdata)) {
case IS_STRING:
- ekey = php_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len);
+ if (enc_type == PHP_QUERY_RFC3986) {
+ ekey = php_raw_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len);
+ } else {
+ ekey = php_url_encode(Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata), &ekey_len);
+ }
break;
case IS_LONG:
case IS_BOOL:
@@ -176,7 +190,11 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
*copyzval = **zdata;
zval_copy_ctor(copyzval);
convert_to_string_ex(&copyzval);
- ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len);
+ if (enc_type == PHP_QUERY_RFC3986) {
+ ekey = php_raw_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len);
+ } else {
+ ekey = php_url_encode(Z_STRVAL_P(copyzval), Z_STRLEN_P(copyzval), &ekey_len);
+ }
zval_ptr_dtor(&copyzval);
}
smart_str_appendl(formstr, ekey, ekey_len);
@@ -188,7 +206,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
}
/* }}} */
-/* {{{ proto string http_build_query(mixed formdata [, string prefix [, string arg_separator]])
+/* {{{ proto string http_build_query(mixed formdata [, string prefix [, string arg_separator [, int enc_type]]])
Generates a form-encoded query string from an associative array or object. */
PHP_FUNCTION(http_build_query)
{
@@ -196,9 +214,9 @@ PHP_FUNCTION(http_build_query)
char *prefix = NULL, *arg_sep=NULL;
int arg_sep_len = 0, prefix_len = 0;
smart_str formstr = {0};
-
+ long enc_type = PHP_QUERY_RFC1738;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ssl", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len, &enc_type) != SUCCESS) {
RETURN_FALSE;
}
@@ -207,7 +225,7 @@ PHP_FUNCTION(http_build_query)
RETURN_FALSE;
}
- if (php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, NULL, 0, NULL, 0, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL), arg_sep TSRMLS_CC) == FAILURE) {
+ if (php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, NULL, 0, NULL, 0, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL), arg_sep, enc_type TSRMLS_CC) == FAILURE) {
if (formstr.c) {
efree(formstr.c);
}
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index fff7c8bcae..4939a742ac 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -132,7 +132,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
Z_TYPE_PP(tmpzval) != IS_STRING ||
Z_STRLEN_PP(tmpzval) <= 0) {
php_url_free(resource);
- return php_stream_open_wrapper_ex(path, mode, ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
+ return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context);
}
/* Called from a non-http wrapper with http proxying requested (i.e. ftp) */
request_fulluri = 1;
@@ -543,12 +543,9 @@ finish:
}
/* if the user has configured who they are, send a From: line */
- {
- char *from_address = php_ini_string("from", sizeof("from"), 0);
- if (((have_header & HTTP_HEADER_FROM) == 0) && from_address && from_address[0] != '\0') {
- if (snprintf(scratch, scratch_len, "From: %s\r\n", from_address) > 0)
- php_stream_write(stream, scratch, strlen(scratch));
- }
+ if (((have_header & HTTP_HEADER_FROM) == 0) && FG(from_address)) {
+ if (snprintf(scratch, scratch_len, "From: %s\r\n", FG(from_address)) > 0)
+ php_stream_write(stream, scratch, strlen(scratch));
}
/* Send Host: header so name-based virtual hosts work */
diff --git a/ext/standard/image.c b/ext/standard/image.c
index d9ca19cbc0..de49fb38e2 100644
--- a/ext/standard/image.c
+++ b/ext/standard/image.c
@@ -1289,26 +1289,11 @@ PHPAPI int php_getimagetype(php_stream * stream, char *filetype TSRMLS_DC)
}
/* }}} */
-/* {{{ proto array getimagesize(string imagefile [, array info])
- Get the size of an image as 4-element array */
-PHP_FUNCTION(getimagesize)
+static void php_getimagesize_from_stream(php_stream *stream, zval **info, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
- zval **info = NULL;
- char *arg1, *temp;
- int arg1_len, itype = 0, argc = ZEND_NUM_ARGS();
+ char *temp;
+ int itype = 0;
struct gfxinfo *result = NULL;
- php_stream * stream = NULL;
-
- if (zend_parse_parameters(argc TSRMLS_CC, "s|Z", &arg1, &arg1_len, &info) == FAILURE) {
- return;
- }
-
- if (argc == 2) {
- zval_dtor(*info);
- array_init(*info);
- }
-
- stream = php_stream_open_wrapper(arg1, "rb", STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
if (!stream) {
RETURN_FALSE;
@@ -1374,8 +1359,6 @@ PHP_FUNCTION(getimagesize)
break;
}
- php_stream_close(stream);
-
if (result) {
array_init(return_value);
add_index_long(return_value, 0, result->width);
@@ -1398,6 +1381,56 @@ PHP_FUNCTION(getimagesize)
}
/* }}} */
+#define FROM_DATA 0
+#define FROM_PATH 1
+
+static void php_getimagesize_from_any(INTERNAL_FUNCTION_PARAMETERS, int mode) { /* {{{ */
+ zval **info = NULL;
+ php_stream *stream = NULL;
+ char *input;
+ int input_len;
+ const int argc = ZEND_NUM_ARGS();
+
+ if (zend_parse_parameters(argc TSRMLS_CC, "s|Z", &input, &input_len, &info) == FAILURE) {
+ return;
+ }
+
+ if (argc == 2) {
+ zval_dtor(*info);
+ array_init(*info);
+ }
+
+
+ if (mode == FROM_PATH) {
+ stream = php_stream_open_wrapper(input, "rb", STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH, NULL);
+ } else {
+ stream = php_stream_memory_open(TEMP_STREAM_READONLY, input, input_len);
+ }
+
+ if (!stream) {
+ RETURN_FALSE;
+ }
+
+ php_getimagesize_from_stream(stream, info, INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ php_stream_close(stream);
+}
+/* }}} */
+
+/* {{{ proto array getimagesize(string imagefile [, array info])
+ Get the size of an image as 4-element array */
+PHP_FUNCTION(getimagesize)
+{
+ php_getimagesize_from_any(INTERNAL_FUNCTION_PARAM_PASSTHRU, FROM_PATH);
+}
+/* }}} */
+
+/* {{{ proto array getimagesizefromstring(string data [, array info])
+ Get the size of an image as 4-element array */
+PHP_FUNCTION(getimagesizefromstring)
+{
+ php_getimagesize_from_any(INTERNAL_FUNCTION_PARAM_PASSTHRU, FROM_DATA);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/incomplete_class.c b/ext/standard/incomplete_class.c
index 5a0c38daaf..f6d3750e2b 100644
--- a/ext/standard/incomplete_class.c
+++ b/ext/standard/incomplete_class.c
@@ -54,7 +54,7 @@ static void incomplete_class_message(zval *object, int error_type TSRMLS_DC)
}
/* }}} */
-static zval *incomplete_class_get_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
+static zval *incomplete_class_get_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
{
incomplete_class_message(object, E_NOTICE TSRMLS_CC);
@@ -66,33 +66,33 @@ static zval *incomplete_class_get_property(zval *object, zval *member, int type
}
/* }}} */
-static void incomplete_class_write_property(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */
+static void incomplete_class_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
{
incomplete_class_message(object, E_NOTICE TSRMLS_CC);
}
/* }}} */
-static zval **incomplete_class_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval **incomplete_class_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
incomplete_class_message(object, E_NOTICE TSRMLS_CC);
return &EG(error_zval_ptr);
}
/* }}} */
-static void incomplete_class_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static void incomplete_class_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
incomplete_class_message(object, E_NOTICE TSRMLS_CC);
}
/* }}} */
-static int incomplete_class_has_property(zval *object, zval *member, int check_empty TSRMLS_DC) /* {{{ */
+static int incomplete_class_has_property(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC) /* {{{ */
{
incomplete_class_message(object, E_NOTICE TSRMLS_CC);
return 0;
}
/* }}} */
-static union _zend_function *incomplete_class_get_method(zval **object, char *method, int method_len TSRMLS_DC) /* {{{ */
+static union _zend_function *incomplete_class_get_method(zval **object, char *method, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */
{
incomplete_class_message(*object, E_ERROR TSRMLS_CC);
return NULL;
@@ -109,8 +109,8 @@ static zend_object_value php_create_incomplete_object(zend_class_entry *class_ty
value = zend_objects_new(&object, class_type TSRMLS_CC);
value.handlers = &php_incomplete_object_handlers;
- ALLOC_HASHTABLE(object->properties);
- zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ object_properties_init(object, class_type);
+
return value;
}
diff --git a/ext/standard/info.c b/ext/standard/info.c
index 08e4a45e08..07e152874a 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -38,30 +38,19 @@
#include <sys/utsname.h>
#endif
+
#ifdef PHP_WIN32
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
-
# include "winver.h"
-#if _MSC_VER < 1300
-# define OSVERSIONINFOEX php_win_OSVERSIONINFOEX
-#endif
-
-#endif
-
-#if HAVE_MBSTRING
-#include "ext/mbstring/mbstring.h"
-ZEND_EXTERN_MODULE_GLOBALS(mbstring)
-#endif
-
-#if HAVE_ICONV
-#include "ext/iconv/php_iconv.h"
-ZEND_EXTERN_MODULE_GLOBALS(iconv)
+# if _MSC_VER < 1300
+# define OSVERSIONINFOEX php_win_OSVERSIONINFOEX
+# endif
#endif
#define SECTION(name) if (!sapi_module.phpinfo_as_text) { \
- PUTS("<h2>" name "</h2>\n"); \
+ php_info_print("<h2>" name "</h2>\n"); \
} else { \
php_info_print_table_start(); \
php_info_print_table_header(1, name); \
@@ -71,29 +60,99 @@ ZEND_EXTERN_MODULE_GLOBALS(iconv)
PHPAPI extern char *php_ini_opened_path;
PHPAPI extern char *php_ini_scanned_path;
PHPAPI extern char *php_ini_scanned_files;
-
-static int php_info_write_wrapper(const char *str, uint str_length)
+
+static int php_info_print_html_esc(const char *str, int len) /* {{{ */
{
- int new_len, written;
- char *elem_esc;
+ size_t new_len;
+ int written;
+ char *new_str;
+ TSRMLS_FETCH();
+
+ new_str = php_escape_html_entities((unsigned char *) str, len, &new_len, 0, ENT_QUOTES, "utf-8" TSRMLS_CC);
+ written = php_output_write(new_str, new_len TSRMLS_CC);
+ efree(new_str);
+ return written;
+}
+/* }}} */
+static int php_info_printf(const char *fmt, ...) /* {{{ */
+{
+ char *buf;
+ int len, written;
+ va_list argv;
TSRMLS_FETCH();
+
+ va_start(argv, fmt);
+ len = vspprintf(&buf, 0, fmt, argv);
+ va_end(argv);
+
+ written = php_output_write(buf, len TSRMLS_CC);
+ efree(buf);
+ return written;
+}
+/* }}} */
- elem_esc = php_escape_html_entities((unsigned char *)str, str_length, &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
+static void php_info_print_request_uri(TSRMLS_D) /* {{{ */
+{
+ if (SG(request_info).request_uri) {
+ php_info_print_html_esc(SG(request_info).request_uri, strlen(SG(request_info).request_uri));
+ }
+}
+/* }}} */
- written = php_body_write(elem_esc, new_len TSRMLS_CC);
+static int php_info_print(const char *str) /* {{{ */
+{
+ TSRMLS_FETCH();
+ return php_output_write(str, strlen(str) TSRMLS_CC);
+}
+/* }}} */
- efree(elem_esc);
+static void php_info_print_stream_hash(const char *name, HashTable *ht TSRMLS_DC) /* {{{ */
+{
+ char *key;
+ uint len;
+
+ if (ht) {
+ if (zend_hash_num_elements(ht)) {
+ HashPosition pos;
- return written;
+ if (!sapi_module.phpinfo_as_text) {
+ php_info_printf("<tr><td class=\"e\">Registered %s</td><td class=\"v\">", name);
+ } else {
+ php_info_printf("\nRegistered %s => ", name);
+ }
+
+ zend_hash_internal_pointer_reset_ex(ht, &pos);
+ while (zend_hash_get_current_key_ex(ht, &key, &len, NULL, 0, &pos) == HASH_KEY_IS_STRING)
+ {
+ php_info_print(key);
+ zend_hash_move_forward_ex(ht, &pos);
+ if (zend_hash_get_current_key_ex(ht, &key, &len, NULL, 0, &pos) == HASH_KEY_IS_STRING) {
+ php_info_print(", ");
+ } else {
+ break;
+ }
+ }
+
+ if (!sapi_module.phpinfo_as_text) {
+ php_info_print("</td></tr>\n");
+ }
+ } else {
+ char reg_name[128];
+ snprintf(reg_name, sizeof(reg_name), "Registered %s", name);
+ php_info_print_table_row(2, reg_name, "none registered");
+ }
+ } else {
+ php_info_print_table_row(2, name, "disabled");
+ }
}
-
+/* }}} */
PHPAPI void php_info_print_module(zend_module_entry *zend_module TSRMLS_DC) /* {{{ */
{
if (zend_module->info_func || zend_module->version) {
if (!sapi_module.phpinfo_as_text) {
- php_printf("<h2><a name=\"module_%s\">%s</a></h2>\n", zend_module->name, zend_module->name);
+ php_info_printf("<h2><a name=\"module_%s\">%s</a></h2>\n", zend_module->name, zend_module->name);
} else {
php_info_print_table_start();
php_info_print_table_header(1, zend_module->name);
@@ -109,9 +168,9 @@ PHPAPI void php_info_print_module(zend_module_entry *zend_module TSRMLS_DC) /* {
}
} else {
if (!sapi_module.phpinfo_as_text) {
- php_printf("<tr><td>%s</td></tr>\n", zend_module->name);
+ php_info_printf("<tr><td>%s</td></tr>\n", zend_module->name);
} else {
- php_printf("%s\n", zend_module->name);
+ php_info_printf("%s\n", zend_module->name);
}
}
}
@@ -151,70 +210,66 @@ static void php_print_gpcse_array(char *name, uint name_length TSRMLS_DC)
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(data));
while (zend_hash_get_current_data(Z_ARRVAL_PP(data), (void **) &tmp) == SUCCESS) {
if (!sapi_module.phpinfo_as_text) {
- PUTS("<tr>");
- PUTS("<td class=\"e\">");
-
+ php_info_print("<tr>");
+ php_info_print("<td class=\"e\">");
}
- PUTS(name);
- PUTS("[\"");
+ php_info_print(name);
+ php_info_print("[\"");
switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(data), &string_key, &string_len, &num_key, 0, NULL)) {
case HASH_KEY_IS_STRING:
if (!sapi_module.phpinfo_as_text) {
- php_info_html_esc_write(string_key, string_len - 1 TSRMLS_CC);
+ php_info_print_html_esc(string_key, string_len-1);
} else {
- PHPWRITE(string_key, string_len - 1);
- }
+ php_info_print(string_key);
+ }
break;
case HASH_KEY_IS_LONG:
- php_printf("%ld", num_key);
+ php_info_printf("%ld", num_key);
break;
}
- PUTS("\"]");
+ php_info_print("\"]");
if (!sapi_module.phpinfo_as_text) {
- PUTS("</td><td class=\"v\">");
+ php_info_print("</td><td class=\"v\">");
} else {
- PUTS(" => ");
+ php_info_print(" => ");
}
if (Z_TYPE_PP(tmp) == IS_ARRAY) {
if (!sapi_module.phpinfo_as_text) {
- PUTS("<pre>");
- zend_print_zval_r_ex((zend_write_func_t) php_info_write_wrapper, *tmp, 0 TSRMLS_CC);
- PUTS("</pre>");
+ php_info_print("<pre>");
+ zend_print_zval_r_ex((zend_write_func_t) php_info_print_html_esc, *tmp, 0 TSRMLS_CC);
+ php_info_print("</pre>");
} else {
zend_print_zval_r(*tmp, 0 TSRMLS_CC);
}
- } else if (Z_TYPE_PP(tmp) != IS_STRING) {
+ } else {
tmp2 = **tmp;
- zval_copy_ctor(&tmp2);
- convert_to_string(&tmp2);
+ if (Z_TYPE_PP(tmp) != IS_STRING) {
+ tmp = NULL;
+ zval_copy_ctor(&tmp2);
+ convert_to_string(&tmp2);
+ }
+
if (!sapi_module.phpinfo_as_text) {
if (Z_STRLEN(tmp2) == 0) {
- PUTS("<i>no value</i>");
- } else {
- php_info_html_esc_write(Z_STRVAL(tmp2), Z_STRLEN(tmp2) TSRMLS_CC);
- }
- } else {
- PHPWRITE(Z_STRVAL(tmp2), Z_STRLEN(tmp2));
- }
- zval_dtor(&tmp2);
- } else {
- if (!sapi_module.phpinfo_as_text) {
- if (Z_STRLEN_PP(tmp) == 0) {
- PUTS("<i>no value</i>");
+ php_info_print("<i>no value</i>");
} else {
- php_info_html_esc_write(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) TSRMLS_CC);
+ php_info_print_html_esc(Z_STRVAL(tmp2), Z_STRLEN(tmp2));
}
} else {
- PHPWRITE(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
- }
+ php_info_print(Z_STRVAL(tmp2));
+ }
+
+ if (!tmp) {
+ zval_dtor(&tmp2);
+ }
}
if (!sapi_module.phpinfo_as_text) {
- PUTS("</td></tr>\n");
+ php_info_print("</td></tr>\n");
} else {
- PUTS("\n");
- }
+ php_info_print("\n");
+ }
zend_hash_move_forward(Z_ARRVAL_PP(data));
}
}
@@ -225,21 +280,9 @@ static void php_print_gpcse_array(char *name, uint name_length TSRMLS_DC)
*/
void php_info_print_style(TSRMLS_D)
{
- php_printf("<style type=\"text/css\">\n");
+ php_info_printf("<style type=\"text/css\">\n");
php_info_print_css(TSRMLS_C);
- php_printf("</style>\n");
-}
-/* }}} */
-
-/* {{{ php_info_html_esc_write
- */
-PHPAPI void php_info_html_esc_write(char *string, int str_len TSRMLS_DC)
-{
- int new_len;
- char *ret = php_escape_html_entities((unsigned char *)string, str_len, &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
-
- PHPWRITE(ret, new_len);
- efree(ret);
+ php_info_printf("</style>\n");
}
/* }}} */
@@ -247,14 +290,14 @@ PHPAPI void php_info_html_esc_write(char *string, int str_len TSRMLS_DC)
*/
PHPAPI char *php_info_html_esc(char *string TSRMLS_DC)
{
- int new_len;
- return php_escape_html_entities((unsigned char *)string, strlen(string), &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
+ size_t new_len;
+ return php_escape_html_entities(string, strlen(string), &new_len, 0, ENT_QUOTES, NULL TSRMLS_CC);
}
/* }}} */
-
#ifdef PHP_WIN32
/* {{{ */
+
char* php_get_windows_name()
{
OSVERSIONINFOEX osvi;
@@ -281,7 +324,7 @@ char* php_get_windows_name()
}
if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion > 4 ) {
- if (osvi.dwMajorVersion == 6) {
+ if (osvi.dwMajorVersion == 6) {
if( osvi.dwMinorVersion == 0 ) {
if( osvi.wProductType == VER_NT_WORKSTATION ) {
major = "Windows Vista";
@@ -296,7 +339,7 @@ char* php_get_windows_name()
major = "Windows Server 2008 R2";
}
} else {
- major = "Unknow Windows version";
+ major = "Unknown Windows version";
}
pGPI = (PGPI) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetProductInfo");
@@ -357,12 +400,12 @@ char* php_get_windows_name()
}
}
- if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) {
+ if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) {
if (GetSystemMetrics(SM_SERVERR2))
major = "Windows Server 2003 R2";
- else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
+ else if (osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER)
major = "Windows Storage Server 2003";
- else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
+ else if (osvi.wSuiteMask==VER_SUITE_WH_SERVER)
major = "Windows Home Server";
else if (osvi.wProductType == VER_NT_WORKSTATION &&
si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) {
@@ -402,9 +445,17 @@ char* php_get_windows_name()
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) {
major = "Windows XP";
- if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
+ if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) {
sub = "Home Edition";
- else sub = "Professional";
+ } else if (GetSystemMetrics(SM_MEDIACENTER)) {
+ sub = "Media Center Edition";
+ } else if (GetSystemMetrics(SM_STARTER)) {
+ sub = "Starter Edition";
+ } else if (GetSystemMetrics(SM_TABLETPC)) {
+ sub = "Tablet PC Edition";
+ } else {
+ sub = "Professional";
+ }
}
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) {
@@ -486,11 +537,7 @@ PHPAPI char *php_get_uname(char mode)
GetComputerName(ComputerName, &dwSize);
if (mode == 's') {
- if (dwVersion < 0x80000000) {
- php_uname = "Windows NT";
- } else {
- php_uname = "Windows 9x";
- }
+ php_uname = "Windows NT";
} else if (mode == 'r') {
snprintf(tmp_uname, sizeof(tmp_uname), "%d.%d", dwWindowsMajorVersion, dwWindowsMinorVersion);
php_uname = tmp_uname;
@@ -512,23 +559,16 @@ PHPAPI char *php_get_uname(char mode)
php_get_windows_cpu(tmp_uname, sizeof(tmp_uname));
php_uname = tmp_uname;
} else { /* assume mode == 'a' */
- /* Get build numbers for Windows NT or Win95 */
- if (dwVersion < 0x80000000){
- char *winver = php_get_windows_name();
- char wincpu[20];
-
- php_get_windows_cpu(wincpu, sizeof(wincpu));
- dwBuild = (DWORD)(HIWORD(dwVersion));
- snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d build %d (%s) %s",
- "Windows NT", ComputerName,
- dwWindowsMajorVersion, dwWindowsMinorVersion, dwBuild, winver?winver:"unknown", wincpu);
- if(winver) {
- efree(winver);
- }
- } else {
- snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d",
- "Windows 9x", ComputerName,
- dwWindowsMajorVersion, dwWindowsMinorVersion);
+ char *winver = php_get_windows_name();
+ char wincpu[20];
+
+ php_get_windows_cpu(wincpu, sizeof(wincpu));
+ dwBuild = (DWORD)(HIWORD(dwVersion));
+ snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d build %d (%s) %s",
+ "Windows NT", ComputerName,
+ dwWindowsMajorVersion, dwWindowsMinorVersion, dwBuild, winver?winver:"unknown", wincpu);
+ if(winver) {
+ efree(winver);
}
php_uname = tmp_uname;
}
@@ -588,54 +628,18 @@ PHPAPI char *php_get_uname(char mode)
}
/* }}} */
-
/* {{{ php_print_info_htmlhead
*/
PHPAPI void php_print_info_htmlhead(TSRMLS_D)
{
-
-/*** none of this is needed now ***
-
- const char *charset = NULL;
-
- if (SG(default_charset)) {
- charset = SG(default_charset);
- }
-
-#if HAVE_MBSTRING
- if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) {
- if (MBSTRG(current_http_output_encoding) == mbfl_no_encoding_pass) {
- charset = "US-ASCII";
- } else {
- charset = mbfl_no2preferred_mime_name(MBSTRG(current_http_output_encoding));
- }
- }
-#endif
-
-#if HAVE_ICONV
- if (php_ob_handler_used("ob_iconv_handler" TSRMLS_CC)) {
- charset = ICONVG(output_encoding);
- }
-#endif
-
- if (!charset || !charset[0]) {
- charset = "US-ASCII";
- }
-
-*** none of that is needed now ***/
-
-
- PUTS("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n");
- PUTS("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
- PUTS("<head>\n");
+ php_info_print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n");
+ php_info_print("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
+ php_info_print("<head>\n");
php_info_print_style(TSRMLS_C);
- PUTS("<title>phpinfo()</title>");
- PUTS("<meta name=\"ROBOTS\" content=\"NOINDEX,NOFOLLOW,NOARCHIVE\" />");
-/*
- php_printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\" />\n", charset);
-*/
- PUTS("</head>\n");
- PUTS("<body><div class=\"center\">\n");
+ php_info_print("<title>phpinfo()</title>");
+ php_info_print("<meta name=\"ROBOTS\" content=\"NOINDEX,NOFOLLOW,NOARCHIVE\" />");
+ php_info_print("</head>\n");
+ php_info_print("<body><div class=\"center\">\n");
}
/* }}} */
@@ -661,8 +665,8 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
if (!sapi_module.phpinfo_as_text) {
php_print_info_htmlhead(TSRMLS_C);
} else {
- PUTS("phpinfo()\n");
- }
+ php_info_print("phpinfo()\n");
+ }
if (flag & PHP_INFO_GENERAL) {
char *zend_version = get_zend_version();
@@ -676,21 +680,17 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
}
if (expose_php && !sapi_module.phpinfo_as_text) {
- PUTS("<a href=\"http://www.php.net/\"><img border=\"0\" src=\"");
- if (SG(request_info).request_uri) {
- char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC);
- PUTS(elem_esc);
- efree(elem_esc);
- }
- PUTS("?=");
+ php_info_print("<a href=\"http://www.php.net/\"><img border=\"0\" src=\"");
+ php_info_print_request_uri(TSRMLS_C);
+ php_info_print("?=");
logo_guid = php_logo_guid();
- PUTS(logo_guid);
+ php_info_print(logo_guid);
efree(logo_guid);
- PUTS("\" alt=\"PHP Logo\" /></a>");
+ php_info_print("\" alt=\"PHP Logo\" /></a>");
}
if (!sapi_module.phpinfo_as_text) {
- php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
+ php_info_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
} else {
php_info_print_table_row(2, "PHP Version", PHP_VERSION);
}
@@ -747,152 +747,55 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
php_info_print_table_row(2, "Thread Safety", "disabled" );
#endif
- php_info_print_table_row(2, "Zend Memory Manager", is_zend_mm(TSRMLS_C) ? "enabled" : "disabled" );
-
-#ifdef ZEND_MULTIBYTE
- php_info_print_table_row(2, "Zend Multibyte Support", "enabled");
+#ifdef ZEND_SIGNALS
+ php_info_print_table_row(2, "Zend Signal Handling", "enabled" );
#else
- php_info_print_table_row(2, "Zend Multibyte Support", "disabled");
+ php_info_print_table_row(2, "Zend Signal Handling", "disabled" );
#endif
-#if HAVE_IPV6
- php_info_print_table_row(2, "IPv6 Support", "enabled" );
-#else
- php_info_print_table_row(2, "IPv6 Support", "disabled" );
-#endif
- {
- HashTable *url_stream_wrappers_hash;
- char *stream_protocol, *stream_protocols_buf = NULL;
- int stream_protocol_len, stream_protocols_buf_len = 0;
- ulong num_key;
-
- if ((url_stream_wrappers_hash = php_stream_get_url_stream_wrappers_hash())) {
- HashPosition pos;
- for (zend_hash_internal_pointer_reset_ex(url_stream_wrappers_hash, &pos);
- zend_hash_get_current_key_ex(url_stream_wrappers_hash, &stream_protocol, (uint *)&stream_protocol_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
- zend_hash_move_forward_ex(url_stream_wrappers_hash, &pos)) {
- stream_protocols_buf = erealloc(stream_protocols_buf, stream_protocols_buf_len + stream_protocol_len + 2 + 1);
- memcpy(stream_protocols_buf + stream_protocols_buf_len, stream_protocol, stream_protocol_len - 1);
- stream_protocols_buf[stream_protocols_buf_len + stream_protocol_len - 1] = ',';
- stream_protocols_buf[stream_protocols_buf_len + stream_protocol_len] = ' ';
- stream_protocols_buf_len += stream_protocol_len + 1;
- }
- if (stream_protocols_buf) {
- stream_protocols_buf[stream_protocols_buf_len - 2] = ' ';
- stream_protocols_buf[stream_protocols_buf_len] = 0;
- php_info_print_table_row(2, "Registered PHP Streams", stream_protocols_buf);
- efree(stream_protocols_buf);
- } else {
- /* Any chances we will ever hit this? */
- php_info_print_table_row(2, "Registered PHP Streams", "no streams registered");
- }
- } else {
- /* Any chances we will ever hit this? */
- php_info_print_table_row(2, "PHP Streams", "disabled"); /* ?? */
- }
- }
+ php_info_print_table_row(2, "Zend Memory Manager", is_zend_mm(TSRMLS_C) ? "enabled" : "disabled" );
{
- HashTable *stream_xport_hash;
- char *xport_name, *xport_buf = NULL;
- int xport_name_len, xport_buf_len = 0, xport_buf_size = 0;
- ulong num_key;
-
- if ((stream_xport_hash = php_stream_xport_get_hash())) {
- HashPosition pos;
- for(zend_hash_internal_pointer_reset_ex(stream_xport_hash, &pos);
- zend_hash_get_current_key_ex(stream_xport_hash, &xport_name, (uint *)&xport_name_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
- zend_hash_move_forward_ex(stream_xport_hash, &pos)) {
- if (xport_buf_len + xport_name_len + 2 > xport_buf_size) {
- while (xport_buf_len + xport_name_len + 2 > xport_buf_size) {
- xport_buf_size += 256;
- }
- if (xport_buf) {
- xport_buf = erealloc(xport_buf, xport_buf_size);
- } else {
- xport_buf = emalloc(xport_buf_size);
- }
- }
- if (xport_buf_len > 0) {
- xport_buf[xport_buf_len++] = ',';
- xport_buf[xport_buf_len++] = ' ';
- }
- memcpy(xport_buf + xport_buf_len, xport_name, xport_name_len - 1);
- xport_buf_len += xport_name_len - 1;
- xport_buf[xport_buf_len] = '\0';
- }
- if (xport_buf) {
- php_info_print_table_row(2, "Registered Stream Socket Transports", xport_buf);
- efree(xport_buf);
- } else {
- /* Any chances we will ever hit this? */
- php_info_print_table_row(2, "Registered Stream Socket Transports", "no transports registered");
- }
+ const zend_multibyte_functions *functions = zend_multibyte_get_functions(TSRMLS_C);
+ char *descr;
+ if (functions) {
+ spprintf(&descr, 0, "provided by %s", functions->provider_name);
} else {
- /* Any chances we will ever hit this? */
- php_info_print_table_row(2, "Stream Socket Transports", "disabled"); /* ?? */
+ descr = estrdup("disabled");
}
+ php_info_print_table_row(2, "Zend Multibyte Support", descr);
+ efree(descr);
}
- {
- HashTable *stream_filter_hash;
- char *filter_name, *filter_buf = NULL;
- int filter_name_len, filter_buf_len = 0, filter_buf_size = 0;
- ulong num_key;
-
- if ((stream_filter_hash = php_get_stream_filters_hash())) {
- HashPosition pos;
- for(zend_hash_internal_pointer_reset_ex(stream_filter_hash, &pos);
- zend_hash_get_current_key_ex(stream_filter_hash, &filter_name, (uint *)&filter_name_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
- zend_hash_move_forward_ex(stream_filter_hash, &pos)) {
- if (filter_buf_len + filter_name_len + 2 > filter_buf_size) {
- while (filter_buf_len + filter_name_len + 2 > filter_buf_size) {
- filter_buf_size += 256;
- }
- if (filter_buf) {
- filter_buf = erealloc(filter_buf, filter_buf_size);
- } else {
- filter_buf = emalloc(filter_buf_size);
- }
- }
- if (filter_buf_len > 0) {
- filter_buf[filter_buf_len++] = ',';
- filter_buf[filter_buf_len++] = ' ';
- }
- memcpy(filter_buf + filter_buf_len, filter_name, filter_name_len - 1);
- filter_buf_len += filter_name_len - 1;
- filter_buf[filter_buf_len] = '\0';
- }
- if (filter_buf) {
- php_info_print_table_row(2, "Registered Stream Filters", filter_buf);
- efree(filter_buf);
- } else {
- /* Any chances we will ever hit this? */
- php_info_print_table_row(2, "Registered Stream Filters", "no filters registered");
- }
- } else {
- /* Any chances we will ever hit this? */
- php_info_print_table_row(2, "Stream Filters", "disabled"); /* ?? */
- }
- }
+#if HAVE_IPV6
+ php_info_print_table_row(2, "IPv6 Support", "enabled" );
+#else
+ php_info_print_table_row(2, "IPv6 Support", "disabled" );
+#endif
+
+#if HAVE_DTRACE
+ php_info_print_table_row(2, "DTrace Support", "enabled" );
+#else
+ php_info_print_table_row(2, "DTrace Support", "disabled" );
+#endif
+ php_info_print_stream_hash("PHP Streams", php_stream_get_url_stream_wrappers_hash() TSRMLS_CC);
+ php_info_print_stream_hash("Stream Socket Transports", php_stream_xport_get_hash() TSRMLS_CC);
+ php_info_print_stream_hash("Stream Filters", php_get_stream_filters_hash() TSRMLS_CC);
+
php_info_print_table_end();
/* Zend Engine */
php_info_print_box_start(0);
if (expose_php && !sapi_module.phpinfo_as_text) {
- PUTS("<a href=\"http://www.zend.com/\"><img border=\"0\" src=\"");
- if (SG(request_info).request_uri) {
- char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC);
- PUTS(elem_esc);
- efree(elem_esc);
- }
- PUTS("?="ZEND_LOGO_GUID"\" alt=\"Zend logo\" /></a>\n");
+ php_info_print("<a href=\"http://www.zend.com/\"><img border=\"0\" src=\"");
+ php_info_print_request_uri(TSRMLS_C);
+ php_info_print("?="ZEND_LOGO_GUID"\" alt=\"Zend logo\" /></a>\n");
}
- PUTS("This program makes use of the Zend Scripting Language Engine:");
- PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
+ php_info_print("This program makes use of the Zend Scripting Language Engine:");
+ php_info_print(!sapi_module.phpinfo_as_text?"<br />":"\n");
if (sapi_module.phpinfo_as_text) {
- PUTS(zend_version);
+ php_info_print(zend_version);
} else {
zend_html_puts(zend_version, strlen(zend_version) TSRMLS_CC);
}
@@ -902,15 +805,11 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
if ((flag & PHP_INFO_CREDITS) && expose_php && !sapi_module.phpinfo_as_text) {
php_info_print_hr();
- PUTS("<h1><a href=\"");
- if (SG(request_info).request_uri) {
- char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC);
- PUTS(elem_esc);
- efree(elem_esc);
- }
- PUTS("?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000\">");
- PUTS("PHP Credits");
- PUTS("</a></h1>\n");
+ php_info_print("<h1><a href=\"");
+ php_info_print_request_uri(TSRMLS_C);
+ php_info_print("?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000\">");
+ php_info_print("PHP Credits");
+ php_info_print("</a></h1>\n");
}
zend_ini_sort_entries(TSRMLS_C);
@@ -918,7 +817,7 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
if (flag & PHP_INFO_CONFIGURATION) {
php_info_print_hr();
if (!sapi_module.phpinfo_as_text) {
- PUTS("<h1>Configuration</h1>\n");
+ php_info_print("<h1>Configuration</h1>\n");
} else {
SECTION("Configuration");
}
@@ -984,13 +883,13 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
if (zend_hash_find(&EG(symbol_table), "PHP_AUTH_PW", sizeof("PHP_AUTH_PW"), (void **) &data) != FAILURE) {
php_info_print_table_row(2, "PHP_AUTH_PW", Z_STRVAL_PP(data));
}
- php_print_gpcse_array("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
- php_print_gpcse_array("_GET", sizeof("_GET")-1 TSRMLS_CC);
- php_print_gpcse_array("_POST", sizeof("_POST")-1 TSRMLS_CC);
- php_print_gpcse_array("_FILES", sizeof("_FILES")-1 TSRMLS_CC);
- php_print_gpcse_array("_COOKIE", sizeof("_COOKIE")-1 TSRMLS_CC);
- php_print_gpcse_array("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
- php_print_gpcse_array("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_REQUEST") TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_GET") TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_POST") TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_FILES") TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_COOKIE") TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_SERVER") TSRMLS_CC);
+ php_print_gpcse_array(ZEND_STRL("_ENV") TSRMLS_CC);
php_info_print_table_end();
}
@@ -998,103 +897,108 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
if (!sapi_module.phpinfo_as_text) {
SECTION("PHP License");
php_info_print_box_start(0);
- PUTS("<p>\n");
- PUTS("This program is free software; you can redistribute it and/or modify ");
- PUTS("it under the terms of the PHP License as published by the PHP Group ");
- PUTS("and included in the distribution in the file: LICENSE\n");
- PUTS("</p>\n");
- PUTS("<p>");
- PUTS("This program is distributed in the hope that it will be useful, ");
- PUTS("but WITHOUT ANY WARRANTY; without even the implied warranty of ");
- PUTS("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
- PUTS("</p>\n");
- PUTS("<p>");
- PUTS("If you did not receive a copy of the PHP license, or have any questions about ");
- PUTS("PHP licensing, please contact license@php.net.\n");
- PUTS("</p>\n");
+ php_info_print("<p>\n");
+ php_info_print("This program is free software; you can redistribute it and/or modify ");
+ php_info_print("it under the terms of the PHP License as published by the PHP Group ");
+ php_info_print("and included in the distribution in the file: LICENSE\n");
+ php_info_print("</p>\n");
+ php_info_print("<p>");
+ php_info_print("This program is distributed in the hope that it will be useful, ");
+ php_info_print("but WITHOUT ANY WARRANTY; without even the implied warranty of ");
+ php_info_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+ php_info_print("</p>\n");
+ php_info_print("<p>");
+ php_info_print("If you did not receive a copy of the PHP license, or have any questions about ");
+ php_info_print("PHP licensing, please contact license@php.net.\n");
+ php_info_print("</p>\n");
php_info_print_box_end();
} else {
- PUTS("\nPHP License\n");
- PUTS("This program is free software; you can redistribute it and/or modify\n");
- PUTS("it under the terms of the PHP License as published by the PHP Group\n");
- PUTS("and included in the distribution in the file: LICENSE\n");
- PUTS("\n");
- PUTS("This program is distributed in the hope that it will be useful,\n");
- PUTS("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
- PUTS("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
- PUTS("\n");
- PUTS("If you did not receive a copy of the PHP license, or have any\n");
- PUTS("questions about PHP licensing, please contact license@php.net.\n");
+ php_info_print("\nPHP License\n");
+ php_info_print("This program is free software; you can redistribute it and/or modify\n");
+ php_info_print("it under the terms of the PHP License as published by the PHP Group\n");
+ php_info_print("and included in the distribution in the file: LICENSE\n");
+ php_info_print("\n");
+ php_info_print("This program is distributed in the hope that it will be useful,\n");
+ php_info_print("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
+ php_info_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
+ php_info_print("\n");
+ php_info_print("If you did not receive a copy of the PHP license, or have any\n");
+ php_info_print("questions about PHP licensing, please contact license@php.net.\n");
}
}
if (!sapi_module.phpinfo_as_text) {
- PUTS("</div></body></html>");
+ php_info_print("</div></body></html>");
}
}
/* }}} */
-
-PHPAPI void php_info_print_table_start(void)
+PHPAPI void php_info_print_table_start(void) /* {{{ */
{
if (!sapi_module.phpinfo_as_text) {
- php_printf("<table border=\"0\" cellpadding=\"3\" width=\"600\">\n");
+ php_info_print("<table border=\"0\" cellpadding=\"3\" width=\"600\">\n");
} else {
- php_printf("\n");
+ php_info_print("\n");
}
}
+/* }}} */
-PHPAPI void php_info_print_table_end(void)
+PHPAPI void php_info_print_table_end(void) /* {{{ */
{
if (!sapi_module.phpinfo_as_text) {
- php_printf("</table><br />\n");
+ php_info_print("</table><br />\n");
}
}
+/* }}} */
-PHPAPI void php_info_print_box_start(int flag)
+PHPAPI void php_info_print_box_start(int flag) /* {{{ */
{
php_info_print_table_start();
if (flag) {
if (!sapi_module.phpinfo_as_text) {
- php_printf("<tr class=\"h\"><td>\n");
+ php_info_print("<tr class=\"h\"><td>\n");
}
} else {
if (!sapi_module.phpinfo_as_text) {
- php_printf("<tr class=\"v\"><td>\n");
+ php_info_print("<tr class=\"v\"><td>\n");
} else {
- php_printf("\n");
+ php_info_print("\n");
}
}
}
+/* }}} */
-PHPAPI void php_info_print_box_end(void)
+PHPAPI void php_info_print_box_end(void) /* {{{ */
{
if (!sapi_module.phpinfo_as_text) {
- php_printf("</td></tr>\n");
+ php_info_print("</td></tr>\n");
}
php_info_print_table_end();
}
+/* }}} */
-PHPAPI void php_info_print_hr(void)
+PHPAPI void php_info_print_hr(void) /* {{{ */
{
if (!sapi_module.phpinfo_as_text) {
- php_printf("<hr />\n");
+ php_info_print("<hr />\n");
} else {
- php_printf("\n\n _______________________________________________________________________\n\n");
+ php_info_print("\n\n _______________________________________________________________________\n\n");
}
}
+/* }}} */
-PHPAPI void php_info_print_table_colspan_header(int num_cols, char *header)
+PHPAPI void php_info_print_table_colspan_header(int num_cols, char *header) /* {{{ */
{
int spaces;
if (!sapi_module.phpinfo_as_text) {
- php_printf("<tr class=\"h\"><th colspan=\"%d\">%s</th></tr>\n", num_cols, header );
+ php_info_printf("<tr class=\"h\"><th colspan=\"%d\">%s</th></tr>\n", num_cols, header );
} else {
spaces = (74 - strlen(header));
- php_printf("%*s%s%*s\n", (int)(spaces/2), " ", header, (int)(spaces/2), " ");
+ php_info_printf("%*s%s%*s\n", (int)(spaces/2), " ", header, (int)(spaces/2), " ");
}
}
+/* }}} */
/* {{{ php_info_print_table_header
*/
@@ -1104,11 +1008,9 @@ PHPAPI void php_info_print_table_header(int num_cols, ...)
va_list row_elements;
char *row_element;
- TSRMLS_FETCH();
-
va_start(row_elements, num_cols);
if (!sapi_module.phpinfo_as_text) {
- php_printf("<tr class=\"h\">");
+ php_info_print("<tr class=\"h\">");
}
for (i=0; i<num_cols; i++) {
row_element = va_arg(row_elements, char *);
@@ -1116,21 +1018,21 @@ PHPAPI void php_info_print_table_header(int num_cols, ...)
row_element = " ";
}
if (!sapi_module.phpinfo_as_text) {
- PUTS("<th>");
- PUTS(row_element);
- PUTS("</th>");
+ php_info_print("<th>");
+ php_info_print(row_element);
+ php_info_print("</th>");
} else {
- PUTS(row_element);
+ php_info_print(row_element);
if (i < num_cols-1) {
- PUTS(" => ");
+ php_info_print(" => ");
} else {
- PUTS("\n");
- }
- }
+ php_info_print("\n");
+ }
+ }
}
if (!sapi_module.phpinfo_as_text) {
- php_printf("</tr>\n");
- }
+ php_info_print("</tr>\n");
+ }
va_end(row_elements);
}
@@ -1143,49 +1045,41 @@ static void php_info_print_table_row_internal(int num_cols,
{
int i;
char *row_element;
- char *elem_esc = NULL;
-/*
- int elem_esc_len;
-*/
-
- TSRMLS_FETCH();
if (!sapi_module.phpinfo_as_text) {
- php_printf("<tr>");
+ php_info_print("<tr>");
}
for (i=0; i<num_cols; i++) {
if (!sapi_module.phpinfo_as_text) {
- php_printf("<td class=\"%s\">",
+ php_info_printf("<td class=\"%s\">",
(i==0 ? "e" : value_class )
);
}
row_element = va_arg(row_elements, char *);
if (!row_element || !*row_element) {
if (!sapi_module.phpinfo_as_text) {
- PUTS( "<i>no value</i>" );
+ php_info_print( "<i>no value</i>" );
} else {
- PUTS( " " );
+ php_info_print( " " );
}
} else {
if (!sapi_module.phpinfo_as_text) {
- elem_esc = php_info_html_esc(row_element TSRMLS_CC);
- PUTS(elem_esc);
- efree(elem_esc);
+ php_info_print_html_esc(row_element, strlen(row_element));
} else {
- PUTS(row_element);
+ php_info_print(row_element);
if (i < num_cols-1) {
- PUTS(" => ");
+ php_info_print(" => ");
}
}
}
if (!sapi_module.phpinfo_as_text) {
- php_printf(" </td>");
+ php_info_print(" </td>");
} else if (i == (num_cols - 1)) {
- PUTS("\n");
+ php_info_print("\n");
}
}
if (!sapi_module.phpinfo_as_text) {
- php_printf("</tr>\n");
+ php_info_print("</tr>\n");
}
}
/* }}} */
@@ -1249,9 +1143,9 @@ PHP_FUNCTION(phpinfo)
}
/* Andale! Andale! Yee-Hah! */
- php_start_ob_buffer(NULL, 4096, 0 TSRMLS_CC);
+ php_output_start_default(TSRMLS_C);
php_print_info(flag TSRMLS_CC);
- php_end_ob_buffer(1, 0 TSRMLS_CC);
+ php_output_end(TSRMLS_C);
RETURN_TRUE;
}
@@ -1262,20 +1156,18 @@ PHP_FUNCTION(phpinfo)
Return the current PHP version */
PHP_FUNCTION(phpversion)
{
- zval **arg;
- const char *version;
- int argc = ZEND_NUM_ARGS();
+ char *ext_name = NULL;
+ int ext_name_len = 0;
- if (argc == 0) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ext_name, &ext_name_len) == FAILURE) {
+ return;
+ }
+
+ if (!ext_name) {
RETURN_STRING(PHP_VERSION, 1);
} else {
- if (zend_parse_parameters(argc TSRMLS_CC, "Z", &arg) == FAILURE) {
- return;
- }
-
- convert_to_string_ex(arg);
- version = zend_get_module_version(Z_STRVAL_PP(arg));
-
+ const char *version;
+ version = zend_get_module_version(ext_name);
if (version == NULL) {
RETURN_FALSE;
}
@@ -1299,7 +1191,6 @@ PHP_FUNCTION(phpcredits)
}
/* }}} */
-
/* {{{ php_logo_guid
*/
PHPAPI char *php_logo_guid(void)
@@ -1327,7 +1218,6 @@ PHPAPI char *php_logo_guid(void)
Return the special ID used to request the PHP logo in phpinfo screens*/
PHP_FUNCTION(php_logo_guid)
{
-
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -1340,7 +1230,6 @@ PHP_FUNCTION(php_logo_guid)
Return the special ID used to request the PHP logo in phpinfo screens*/
PHP_FUNCTION(php_real_logo_guid)
{
-
if (zend_parse_parameters_none() == FAILURE) {
return;
}
@@ -1396,6 +1285,7 @@ PHP_FUNCTION(php_uname)
{
char *mode = "a";
int modelen = sizeof("a")-1;
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &mode, &modelen) == FAILURE) {
return;
}
diff --git a/ext/standard/iptc.c b/ext/standard/iptc.c
index d1cf42f2d2..43dc372bcf 100644
--- a/ext/standard/iptc.c
+++ b/ext/standard/iptc.c
@@ -181,23 +181,16 @@ PHP_FUNCTION(iptcembed)
int iptcdata_len, jpeg_file_len;
long spool = 0;
FILE *fp;
- unsigned int marker, done = 0, inx;
+ unsigned int marker, done = 0;
+ int inx;
unsigned char *spoolbuf = NULL, *poi = NULL;
struct stat sb;
zend_bool written = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &iptcdata, &iptcdata_len, &jpeg_file, &jpeg_file_len, &spool) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sp|l", &iptcdata, &iptcdata_len, &jpeg_file, &jpeg_file_len, &spool) != SUCCESS) {
return;
}
- if (strlen(jpeg_file) != jpeg_file_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && (!php_checkuid(jpeg_file, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(jpeg_file TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -303,7 +296,8 @@ PHP_FUNCTION(iptcembed)
Parse binary IPTC-data into associative array */
PHP_FUNCTION(iptcparse)
{
- unsigned int inx = 0, len, tagsfound = 0;
+ int inx = 0, len;
+ unsigned int tagsfound = 0;
unsigned char *buffer, recnum, dataset, key[ 16 ];
char *str;
int str_len;
diff --git a/ext/standard/link.c b/ext/standard/link.c
index cb42408f6d..3832e703bb 100644
--- a/ext/standard/link.c
+++ b/ext/standard/link.c
@@ -47,7 +47,6 @@
#include <errno.h>
#include <ctype.h>
-#include "safe_mode.h"
#include "php_link.h"
#include "php_string.h"
@@ -64,14 +63,6 @@ PHP_FUNCTION(readlink)
return;
}
- if (strlen(link) != link_len) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && !php_checkuid(link, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(link TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -99,7 +90,7 @@ PHP_FUNCTION(linkinfo)
struct stat sb;
int ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &link, &link_len) == FAILURE) {
return;
}
@@ -135,17 +126,9 @@ PHP_FUNCTION(symlink)
char dirname[MAXPATHLEN];
size_t len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
return;
}
-
- if (strlen(topath) != topath_len) {
- RETURN_FALSE;
- }
-
- if (strlen(frompath) != frompath_len) {
- RETURN_FALSE;
- }
if (!expand_filepath(frompath, source_p TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
@@ -167,14 +150,6 @@ PHP_FUNCTION(symlink)
RETURN_FALSE;
}
- if (PG(safe_mode) && !php_checkuid(dest_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && !php_checkuid(source_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(dest_p TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -207,18 +182,10 @@ PHP_FUNCTION(link)
char source_p[MAXPATHLEN];
char dest_p[MAXPATHLEN];
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
return;
}
- if (strlen(topath) != topath_len) {
- RETURN_FALSE;
- }
-
- if (strlen(frompath) != frompath_len) {
- RETURN_FALSE;
- }
-
if (!expand_filepath(frompath, source_p TSRMLS_CC) || !expand_filepath(topath, dest_p TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
RETURN_FALSE;
@@ -231,14 +198,6 @@ PHP_FUNCTION(link)
RETURN_FALSE;
}
- if (PG(safe_mode) && !php_checkuid(dest_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
- if (PG(safe_mode) && !php_checkuid(source_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- RETURN_FALSE;
- }
-
if (php_check_open_basedir(dest_p TSRMLS_CC)) {
RETURN_FALSE;
}
diff --git a/ext/standard/link_win32.c b/ext/standard/link_win32.c
index 7e2606c513..effe67bd78 100644
--- a/ext/standard/link_win32.c
+++ b/ext/standard/link_win32.c
@@ -39,7 +39,6 @@
#include <errno.h>
#include <ctype.h>
-#include "safe_mode.h"
#include "php_link.h"
#include "php_string.h"
@@ -51,6 +50,14 @@ TODO:
- this file is then useless and we have a portable link API
*/
+#ifndef VOLUME_NAME_NT
+#define VOLUME_NAME_NT 0x2
+#endif
+
+#ifndef VOLUME_NAME_DOS
+#define VOLUME_NAME_DOS 0x0
+#endif
+
/* {{{ proto string readlink(string filename)
Return the target of a symbolic link */
PHP_FUNCTION(readlink)
@@ -59,7 +66,7 @@ PHP_FUNCTION(readlink)
int link_len;
char target[MAXPATHLEN];
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &link, &link_len) == FAILURE) {
return;
}
@@ -84,7 +91,7 @@ PHP_FUNCTION(linkinfo)
struct stat sb;
int ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &link, &link_len) == FAILURE) {
return;
}
@@ -127,7 +134,7 @@ PHP_FUNCTION(symlink)
RETURN_FALSE;
}
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
return;
}
diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index 13f57781af..364f7fc399 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -39,10 +39,10 @@
#endif
#endif
+#include "php_syslog.h"
#include "php_mail.h"
#include "php_ini.h"
#include "php_string.h"
-#include "safe_mode.h"
#include "exec.h"
#ifdef PHP_WIN32
@@ -70,7 +70,7 @@
*p = ' '; \
} \
-extern long php_getuid(void);
+extern long php_getuid(TSRMLS_D);
/* {{{ proto int ezmlm_hash(string addr)
Calculate EZMLM list hash value. */
@@ -106,14 +106,7 @@ PHP_FUNCTION(mail)
char *to_r, *subject_r;
char *p, *e;
- if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The fifth parameter is disabled in SAFE MODE");
- RETURN_FALSE;
- }
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss", &to, &to_len, &subject, &subject_len, &message, &message_len,
- &headers, &headers_len, &extra_cmd, &extra_cmd_len) == FAILURE
- ) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &headers_len, &extra_cmd, &extra_cmd_len) == FAILURE) {
return;
}
@@ -197,6 +190,37 @@ PHP_FUNCTION(mail)
}
/* }}} */
+
+void php_mail_log_crlf_to_spaces(char *message) {
+ /* Find all instances of carriage returns or line feeds and
+ * replace them with spaces. Thus, a log line is always one line
+ * long
+ */
+ char *p = message;
+ while ((p = strpbrk(p, "\r\n"))) {
+ *p = ' ';
+ }
+}
+
+void php_mail_log_to_syslog(char *message) {
+ /* Write 'message' to syslog. */
+#ifdef HAVE_SYSLOG_H
+ php_syslog(LOG_NOTICE, "%s", message);
+#endif
+}
+
+
+void php_mail_log_to_file(char *filename, char *message, size_t message_size TSRMLS_DC) {
+ /* Write 'message' to the given file. */
+ uint flags = IGNORE_URL_WIN | REPORT_ERRORS | STREAM_DISABLE_OPEN_BASEDIR;
+ php_stream *stream = php_stream_open_wrapper(filename, "a", flags, NULL);
+ if (stream) {
+ php_stream_write(stream, message, message_size);
+ php_stream_close(stream);
+ }
+}
+
+
/* {{{ php_mail
*/
PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd TSRMLS_DC)
@@ -224,32 +248,35 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
if (mail_log && *mail_log) {
char *tmp;
int l = spprintf(&tmp, 0, "mail() on [%s:%d]: To: %s -- Headers: %s\n", zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C), to, hdr ? hdr : "");
- php_stream *stream = php_stream_open_wrapper(mail_log, "a", IGNORE_URL_WIN | REPORT_ERRORS | STREAM_DISABLE_OPEN_BASEDIR, NULL);
- if (hdr) { /* find all \r\n instances and replace them with spaces, so a log line is always one line long */
- char *p = tmp;
- while ((p = strpbrk(p, "\r\n"))) {
- *p = ' ';
- }
- tmp[l - 1] = '\n';
+ if (hdr) {
+ php_mail_log_crlf_to_spaces(tmp);
}
- if (stream) {
- php_stream_write(stream, tmp, l);
- php_stream_close(stream);
+
+ if (!strcmp(mail_log, "syslog")) {
+ /* Drop the final space when logging to syslog. */
+ tmp[l - 1] = 0;
+ php_mail_log_to_syslog(tmp);
}
+ else {
+ /* Convert the final space to a newline when logging to file. */
+ tmp[l - 1] = '\n';
+ php_mail_log_to_file(mail_log, tmp, l TSRMLS_CC);
+ }
+
efree(tmp);
}
if (PG(mail_x_header)) {
- char *tmp = zend_get_executed_filename(TSRMLS_C);
+ const char *tmp = zend_get_executed_filename(TSRMLS_C);
char *f;
size_t f_len;
php_basename(tmp, strlen(tmp), NULL, 0,&f, &f_len TSRMLS_CC);
if (headers != NULL) {
- spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n%s", php_getuid(), f, headers);
+ spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n%s", php_getuid(TSRMLS_C), f, headers);
} else {
- spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n", php_getuid(), f);
+ spprintf(&hdr, 0, "X-PHP-Originating-Script: %ld:%s\n", php_getuid(TSRMLS_C), f);
}
efree(f);
}
@@ -288,7 +315,7 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
#endif
#ifdef PHP_WIN32
- sendmail = popen(sendmail_cmd, "wb");
+ sendmail = popen_ex(sendmail_cmd, "wb", NULL, NULL TSRMLS_CC);
#else
/* Since popen() doesn't indicate if the internal fork() doesn't work
* (e.g. the shell can't be executed) we explicitely set it to 0 to be
diff --git a/ext/standard/math.c b/ext/standard/math.c
index 749c77c75c..6e934a3857 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -620,7 +620,7 @@ PHP_FUNCTION(pow)
/* calculate pow(long,long) in O(log exp) operations, bail if overflow */
while (i >= 1) {
- int overflow;
+ long overflow;
double dval = 0.0;
if (i % 2) {
@@ -1094,6 +1094,13 @@ PHP_FUNCTION(base_convert)
*/
PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
{
+ return _php_math_number_format_ex(d, dec, &dec_point, 1, &thousand_sep, 1);
+}
+
+static char *_php_math_number_format_ex_len(double d, int dec, char *dec_point,
+ size_t dec_point_len, char *thousand_sep, size_t thousand_sep_len,
+ int *result_len)
+{
char *tmpbuf = NULL, *resbuf;
char *s, *t; /* source, target */
char *dp;
@@ -1113,6 +1120,10 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho
tmplen = spprintf(&tmpbuf, 0, "%.*F", dec, d);
if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
+ if (result_len) {
+ *result_len = tmplen;
+ }
+
return tmpbuf;
}
@@ -1133,7 +1144,7 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho
/* allow for thousand separators */
if (thousand_sep) {
- integral += (integral-1) / 3;
+ integral += thousand_sep_len * ((integral-1) / 3);
}
reslen = integral;
@@ -1142,7 +1153,7 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho
reslen += dec;
if (dec_point) {
- reslen++;
+ reslen += dec_point_len;
}
}
@@ -1178,7 +1189,8 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho
/* add decimal point */
if (dec_point) {
- *t-- = dec_point;
+ t -= dec_point_len;
+ memcpy(t + 1, dec_point, dec_point_len);
}
}
@@ -1187,7 +1199,8 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho
while(s >= tmpbuf) {
*t-- = *s--;
if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
- *t-- = thousand_sep;
+ t -= thousand_sep_len;
+ memcpy(t + 1, thousand_sep, thousand_sep_len);
}
}
@@ -1198,8 +1211,19 @@ PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char tho
efree(tmpbuf);
+ if (result_len) {
+ *result_len = reslen;
+ }
+
return resbuf;
}
+
+PHPAPI char *_php_math_number_format_ex(double d, int dec, char *dec_point,
+ size_t dec_point_len, char *thousand_sep, size_t thousand_sep_len)
+{
+ return _php_math_number_format_ex_len(d, dec, dec_point, dec_point_len,
+ thousand_sep, thousand_sep_len, NULL);
+}
/* }}} */
/* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_seperator, string thousands_seperator]])
@@ -1224,21 +1248,20 @@ PHP_FUNCTION(number_format)
RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
break;
case 4:
- if (dec_point != NULL) {
- if (dec_point_len) {
- dec_point_chr = dec_point[0];
- } else {
- dec_point_chr = 0;
- }
+ if (dec_point == NULL) {
+ dec_point = &dec_point_chr;
+ dec_point_len = 1;
}
- if (thousand_sep != NULL) {
- if (thousand_sep_len) {
- thousand_sep_chr = thousand_sep[0];
- } else {
- thousand_sep_chr = 0;
- }
+
+ if (thousand_sep == NULL) {
+ thousand_sep = &thousand_sep_chr;
+ thousand_sep_len = 1;
}
- RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
+
+ Z_TYPE_P(return_value) = IS_STRING;
+ Z_STRVAL_P(return_value) = _php_math_number_format_ex_len(num, dec,
+ dec_point, dec_point_len, thousand_sep, thousand_sep_len,
+ &Z_STRLEN_P(return_value));
break;
default:
WRONG_PARAM_COUNT;
diff --git a/ext/standard/md5.c b/ext/standard/md5.c
index c5e315742a..91a5e8ceef 100644
--- a/ext/standard/md5.c
+++ b/ext/standard/md5.c
@@ -85,11 +85,11 @@ PHP_NAMED_FUNCTION(php_if_md5_file)
int n;
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
return;
}
- stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
+ stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
if (!stream) {
RETURN_FALSE;
}
diff --git a/ext/standard/pack.c b/ext/standard/pack.c
index 5d3c8a8246..65a5c00cc4 100644
--- a/ext/standard/pack.c
+++ b/ext/standard/pack.c
@@ -39,7 +39,6 @@
#include <sys/param.h>
#endif
#include "ext/standard/head.h"
-#include "safe_mode.h"
#include "php_string.h"
#include "pack.h"
#if HAVE_PWD_H
diff --git a/ext/standard/pageinfo.c b/ext/standard/pageinfo.c
index 16b7a74825..c9bb34d0b6 100644
--- a/ext/standard/pageinfo.c
+++ b/ext/standard/pageinfo.c
@@ -79,19 +79,15 @@ PHPAPI void php_statpage(TSRMLS_D)
/* {{{ php_getuid
*/
-long php_getuid(void)
+long php_getuid(TSRMLS_D)
{
- TSRMLS_FETCH();
-
php_statpage(TSRMLS_C);
return (BG(page_uid));
}
/* }}} */
-long php_getgid(void)
+long php_getgid(TSRMLS_D)
{
- TSRMLS_FETCH();
-
php_statpage(TSRMLS_C);
return (BG(page_gid));
}
@@ -101,8 +97,12 @@ long php_getgid(void)
PHP_FUNCTION(getmyuid)
{
long uid;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
- uid = php_getuid();
+ uid = php_getuid(TSRMLS_C);
if (uid < 0) {
RETURN_FALSE;
} else {
@@ -116,8 +116,12 @@ PHP_FUNCTION(getmyuid)
PHP_FUNCTION(getmygid)
{
long gid;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
- gid = php_getgid();
+ gid = php_getgid(TSRMLS_C);
if (gid < 0) {
RETURN_FALSE;
} else {
@@ -131,6 +135,10 @@ PHP_FUNCTION(getmygid)
PHP_FUNCTION(getmypid)
{
int pid;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
pid = getpid();
if (pid < 0) {
@@ -145,6 +153,10 @@ PHP_FUNCTION(getmypid)
Get the inode of the current script being parsed */
PHP_FUNCTION(getmyinode)
{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
php_statpage(TSRMLS_C);
if (BG(page_inode) < 0) {
RETURN_FALSE;
@@ -164,7 +176,13 @@ PHPAPI long php_getlastmod(TSRMLS_D)
Get time of last page modification */
PHP_FUNCTION(getlastmod)
{
- long lm = php_getlastmod(TSRMLS_C);
+ long lm;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ lm = php_getlastmod(TSRMLS_C);
if (lm < 0) {
RETURN_FALSE;
} else {
@@ -173,7 +191,7 @@ PHP_FUNCTION(getlastmod)
}
/* }}} */
-/*
+/*nma
* Local variables:
* tab-width: 4
* c-basic-offset: 4
diff --git a/ext/standard/pageinfo.h b/ext/standard/pageinfo.h
index 9bbf8e98a6..6fab2e0007 100644
--- a/ext/standard/pageinfo.h
+++ b/ext/standard/pageinfo.h
@@ -29,7 +29,7 @@ PHP_FUNCTION(getlastmod);
PHPAPI void php_statpage(TSRMLS_D);
PHPAPI long php_getlastmod(TSRMLS_D);
-extern long php_getuid(void);
-extern long php_getgid(void);
+extern long php_getuid(TSRMLS_D);
+extern long php_getgid(TSRMLS_D);
#endif
diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h
index 991790c31c..e63e01c61e 100644
--- a/ext/standard/php_array.h
+++ b/ext/standard/php_array.h
@@ -113,6 +113,8 @@ PHPAPI int php_multisort_compare(const void *a, const void *b TSRMLS_DC);
#define PHP_SORT_DESC 3
#define PHP_SORT_ASC 4
#define PHP_SORT_LOCALE_STRING 5
+#define PHP_SORT_NATURAL 6
+#define PHP_SORT_FLAG_CASE 8
ZEND_BEGIN_MODULE_GLOBALS(array)
int *multisort_flags[2];
diff --git a/ext/standard/php_crypt_r.c b/ext/standard/php_crypt_r.c
index 31e97df320..f2c754e2f2 100644
--- a/ext/standard/php_crypt_r.c
+++ b/ext/standard/php_crypt_r.c
@@ -219,17 +219,12 @@ char * php_md5_crypt_r(const char *pw, const char *salt, char *out) {
memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
-#if _MSC_VER >= 1500
if (strncpy_s(passwd + MD5_MAGIC_LEN, MD5_HASH_MAX_LEN - MD5_MAGIC_LEN, sp, sl + 1) != 0) {
goto _destroyCtx1;
}
passwd[MD5_MAGIC_LEN + sl] = '\0';
strcat_s(passwd, MD5_HASH_MAX_LEN, "$");
-#else
- /* VC6 version doesn't have strcat_s or strncpy_s */
- strncpy(passwd + MD5_MAGIC_LEN, sp, sl + 1);
- strcat(passwd, "$");
-#endif
+
dwHashLen = 16;
/* Fetch the ctx hash value */
diff --git a/ext/standard/php_dir.h b/ext/standard/php_dir.h
index e3f9c460d9..15c9690eaa 100644
--- a/ext/standard/php_dir.h
+++ b/ext/standard/php_dir.h
@@ -37,4 +37,8 @@ PHP_FUNCTION(getdir);
PHP_FUNCTION(glob);
PHP_FUNCTION(scandir);
+#define PHP_SCANDIR_SORT_ASCENDING 0
+#define PHP_SCANDIR_SORT_DESCENDING 1
+#define PHP_SCANDIR_SORT_NONE 2
+
#endif /* PHP_DIR_H */
diff --git a/ext/standard/php_ext_syslog.h b/ext/standard/php_ext_syslog.h
index 5f76a686fa..cc72d6634b 100644
--- a/ext/standard/php_ext_syslog.h
+++ b/ext/standard/php_ext_syslog.h
@@ -35,7 +35,6 @@ PHP_MSHUTDOWN_FUNCTION(syslog);
PHP_FUNCTION(openlog);
PHP_FUNCTION(syslog);
PHP_FUNCTION(closelog);
-PHP_FUNCTION(define_syslog_variables);
#endif
diff --git a/ext/standard/php_http.h b/ext/standard/php_http.h
index 784400e10f..e0fdeded26 100644
--- a/ext/standard/php_http.h
+++ b/ext/standard/php_http.h
@@ -28,7 +28,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
const char *num_prefix, int num_prefix_len,
const char *key_prefix, int key_prefix_len,
const char *key_suffix, int key_suffix_len,
- zval *type, char *arg_sep TSRMLS_DC);
+ zval *type, char *arg_sep, int enc_type TSRMLS_DC);
#define php_url_encode_hash(ht, formstr) php_url_encode_hash_ex((ht), (formstr), NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)
PHP_FUNCTION(http_build_query);
diff --git a/ext/standard/php_image.h b/ext/standard/php_image.h
index bd94778f69..5562f997e5 100644
--- a/ext/standard/php_image.h
+++ b/ext/standard/php_image.h
@@ -23,6 +23,7 @@
#define PHP_IMAGE_H
PHP_FUNCTION(getimagesize);
+PHP_FUNCTION(getimagesizefromstring);
PHP_FUNCTION(image_type_to_mime_type);
PHP_FUNCTION(image_type_to_extension);
diff --git a/ext/standard/php_incomplete_class.h b/ext/standard/php_incomplete_class.h
index 661991dd36..027ff211d5 100644
--- a/ext/standard/php_incomplete_class.h
+++ b/ext/standard/php_incomplete_class.h
@@ -38,7 +38,7 @@
free_class_name = 1; \
incomplete_class = 1; \
} else { \
- free_class_name = !zend_get_object_classname(struc, &class_name, &name_len TSRMLS_CC);\
+ free_class_name = !zend_get_object_classname(struc, (const char **)&class_name, &name_len TSRMLS_CC);\
}
#define PHP_CLEANUP_CLASS_ATTRIBUTES() \
diff --git a/ext/standard/php_math.h b/ext/standard/php_math.h
index d15e75fd7a..3da3cf0089 100644
--- a/ext/standard/php_math.h
+++ b/ext/standard/php_math.h
@@ -22,7 +22,8 @@
#ifndef PHP_MATH_H
#define PHP_MATH_H
-PHPAPI char *_php_math_number_format(double, int, char , char);
+PHPAPI char *_php_math_number_format(double, int, char, char);
+PHPAPI char *_php_math_number_format_ex(double, int, char *, size_t, char *, size_t);
PHPAPI char * _php_math_longtobase(zval *arg, int base);
PHPAPI long _php_math_basetolong(zval *arg, int base);
PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret);
diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h
index e4db6beefe..44ec0c7647 100644
--- a/ext/standard/php_string.h
+++ b/ext/standard/php_string.h
@@ -78,6 +78,7 @@ PHP_FUNCTION(chunk_split);
PHP_FUNCTION(parse_str);
PHP_FUNCTION(str_getcsv);
PHP_FUNCTION(bin2hex);
+PHP_FUNCTION(hex2bin);
PHP_FUNCTION(similar_text);
PHP_FUNCTION(strip_tags);
PHP_FUNCTION(str_repeat);
@@ -121,11 +122,10 @@ PHPAPI char *php_strtoupper(char *s, size_t len);
PHPAPI char *php_strtolower(char *s, size_t len);
PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen);
PHPAPI char *php_addslashes(char *str, int length, int *new_length, int freeit TSRMLS_DC);
-PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int freeit, int ignore_sybase TSRMLS_DC);
-PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int freeit, char *what, int wlength TSRMLS_DC);
+PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int freeit, char *what, int wlength TSRMLS_DC);
PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC);
PHPAPI void php_stripcslashes(char *str, int *len);
-PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC);
+PHPAPI void php_basename(const char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC);
PHPAPI size_t php_dirname(char *str, size_t len);
PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len);
PHPAPI char *php_str_to_str_ex(char *haystack, int length, char *needle,
@@ -143,6 +143,10 @@ PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit);
PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end);
PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end);
+PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC);
+PHPAPI int string_natural_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+PHPAPI int string_natural_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+
#ifndef HAVE_STRERROR
PHPAPI char *php_strerror(int errnum);
#define strerror php_strerror
diff --git a/ext/standard/php_var.h b/ext/standard/php_var.h
index 6396283566..479f1a354e 100644
--- a/ext/standard/php_var.h
+++ b/ext/standard/php_var.h
@@ -12,7 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Jani Lehtimäki <jkl@njet.net> |
+ | Author: Jani Lehtimäki <jkl@njet.net> |
+----------------------------------------------------------------------+
*/
@@ -21,6 +21,7 @@
#ifndef PHP_VAR_H
#define PHP_VAR_H
+#include "ext/standard/basic_functions.h"
#include "ext/standard/php_smart_str_public.h"
PHP_FUNCTION(var_dump);
@@ -37,29 +38,80 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC);
-/* typdef HashTable php_serialize_data_t; */
-#define php_serialize_data_t HashTable
+typedef HashTable* php_serialize_data_t;
struct php_unserialize_data {
void *first;
+ void *last;
void *first_dtor;
+ void *last_dtor;
};
-typedef struct php_unserialize_data php_unserialize_data_t;
+typedef struct php_unserialize_data* php_unserialize_data_t;
PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC);
PHPAPI int php_var_unserialize(zval **rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash TSRMLS_DC);
-#define PHP_VAR_SERIALIZE_INIT(var_hash) \
- zend_hash_init(&(var_hash), 10, NULL, NULL, 0)
-#define PHP_VAR_SERIALIZE_DESTROY(var_hash) \
- zend_hash_destroy(&(var_hash))
-
-#define PHP_VAR_UNSERIALIZE_INIT(var_hash) \
- (var_hash).first = 0; \
- (var_hash).first_dtor = 0
-#define PHP_VAR_UNSERIALIZE_DESTROY(var_hash) \
- var_destroy(&(var_hash))
+#define PHP_VAR_SERIALIZE_INIT(var_hash_ptr) \
+do { \
+ /* fprintf(stderr, "SERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
+ if (BG(serialize_lock) || !BG(serialize).level) { \
+ ALLOC_HASHTABLE(var_hash_ptr); \
+ zend_hash_init((var_hash_ptr), 10, NULL, NULL, 0); \
+ if (!BG(serialize_lock)) { \
+ BG(serialize).var_hash = (void *)(var_hash_ptr); \
+ BG(serialize).level = 1; \
+ } \
+ } else { \
+ (var_hash_ptr) = (php_serialize_data_t)BG(serialize).var_hash; \
+ ++BG(serialize).level; \
+ } \
+} while(0)
+
+#define PHP_VAR_SERIALIZE_DESTROY(var_hash_ptr) \
+do { \
+ /* fprintf(stderr, "SERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ \
+ if (BG(serialize_lock) || !BG(serialize).level) { \
+ zend_hash_destroy((var_hash_ptr)); \
+ FREE_HASHTABLE(var_hash_ptr); \
+ } else { \
+ if (!--BG(serialize).level) { \
+ zend_hash_destroy((php_serialize_data_t)BG(serialize).var_hash); \
+ FREE_HASHTABLE((php_serialize_data_t)BG(serialize).var_hash); \
+ BG(serialize).var_hash = NULL; \
+ } \
+ } \
+} while (0)
+
+#define PHP_VAR_UNSERIALIZE_INIT(var_hash_ptr) \
+do { \
+ /* fprintf(stderr, "UNSERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
+ if (BG(serialize_lock) || !BG(unserialize).level) { \
+ (var_hash_ptr) = (php_unserialize_data_t)ecalloc(1, sizeof(struct php_unserialize_data)); \
+ if (!BG(serialize_lock)) { \
+ BG(unserialize).var_hash = (void *)(var_hash_ptr); \
+ BG(unserialize).level = 1; \
+ } \
+ } else { \
+ (var_hash_ptr) = (php_unserialize_data_t)BG(unserialize).var_hash; \
+ ++BG(unserialize).level; \
+ } \
+} while (0)
+
+#define PHP_VAR_UNSERIALIZE_DESTROY(var_hash_ptr) \
+do { \
+ /* fprintf(stderr, "UNSERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(unserialize).level); */ \
+ if (BG(serialize_lock) || !BG(unserialize).level) { \
+ var_destroy(&(var_hash_ptr)); \
+ efree(var_hash_ptr); \
+ } else { \
+ if (!--BG(unserialize).level) { \
+ var_destroy(&(var_hash_ptr)); \
+ efree((var_hash_ptr)); \
+ BG(unserialize).var_hash = NULL; \
+ } \
+ } \
+} while (0)
PHPAPI void var_replace(php_unserialize_data_t *var_hash, zval *ozval, zval **nzval);
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hash, zval **val);
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index db63a67b77..5ff91994a7 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -28,7 +28,6 @@
#include <stdio.h>
#include <ctype.h>
#include "php_string.h"
-#include "safe_mode.h"
#include "ext/standard/head.h"
#include "ext/standard/basic_functions.h"
#include "ext/standard/file.h"
@@ -153,33 +152,6 @@ static php_process_env_t _php_array_to_envp(zval *environment, int is_persistent
if (string_length == 0) {
continue;
}
- if (PG(safe_mode)) {
- /* Check the protected list */
- if (zend_hash_exists(&BG(sm_protected_env_vars), string_key, string_length - 1)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Safe Mode warning: Cannot override protected environment variable '%s'", string_key);
- return env;
- }
- /* Check the allowed list */
- if (BG(sm_allowed_env_vars) && *BG(sm_allowed_env_vars)) {
- char *allowed_env_vars = estrdup(BG(sm_allowed_env_vars));
- char *strtok_buf = NULL;
- char *allowed_prefix = php_strtok_r(allowed_env_vars, ", ", &strtok_buf);
- zend_bool allowed = 0;
-
- while (allowed_prefix) {
- if (!strncmp(allowed_prefix, string_key, strlen(allowed_prefix))) {
- allowed = 1;
- break;
- }
- allowed_prefix = php_strtok_r(NULL, ", ", &strtok_buf);
- }
- efree(allowed_env_vars);
- if (!allowed) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Safe Mode warning: Cannot set environment variable '%s' - it's not in the allowed list", string_key);
- return env;
- }
- }
- }
l = string_length + el_len + 1;
memcpy(p, string_key, string_length);
@@ -273,53 +245,7 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
_php_free_envp(proc->env, proc->is_persistent);
pefree(proc->command, proc->is_persistent);
pefree(proc, proc->is_persistent);
-}
-/* }}} */
-
-/* {{{ php_make_safe_mode_command */
-static int php_make_safe_mode_command(char *cmd, char **safecmd, int is_persistent TSRMLS_DC)
-{
- int lcmd, larg0;
- char *space, *sep, *arg0;
-
- if (!PG(safe_mode)) {
- *safecmd = pestrdup(cmd, is_persistent);
- return SUCCESS;
- }
-
- lcmd = strlen(cmd);
-
- arg0 = estrndup(cmd, lcmd);
-
- space = memchr(arg0, ' ', lcmd);
- if (space) {
- *space = '\0';
- larg0 = space - arg0;
- } else {
- larg0 = lcmd;
- }
-
- if (php_memnstr(arg0, "..", sizeof("..")-1, arg0 + larg0)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No '..' components allowed in path");
- efree(arg0);
- return FAILURE;
- }
-
- sep = zend_memrchr(arg0, PHP_DIR_SEPARATOR, larg0);
-
- spprintf(safecmd, 0, "%s%s%s%s", PG(safe_mode_exec_dir), (sep ? sep : "/"), (sep ? "" : arg0), (space ? cmd + larg0 : ""));
- efree(arg0);
- arg0 = php_escape_shell_cmd(*safecmd);
- efree(*safecmd);
- if (is_persistent) {
- *safecmd = pestrdup(arg0, 1);
- efree(arg0);
- } else {
- *safecmd = arg0;
- }
-
- return SUCCESS;
}
/* }}} */
@@ -538,9 +464,7 @@ PHP_FUNCTION(proc_open)
RETURN_FALSE;
}
- if (FAILURE == php_make_safe_mode_command(command, &command, is_persistent TSRMLS_CC)) {
- RETURN_FALSE;
- }
+ command = pestrdup(command, is_persistent);
#ifdef PHP_WIN32
if (other_options) {
@@ -692,7 +616,7 @@ PHP_FUNCTION(proc_open)
/* try a wrapper */
stream = php_stream_open_wrapper(Z_STRVAL_PP(zfile), Z_STRVAL_PP(zmode),
- ENFORCE_SAFE_MODE|REPORT_ERRORS|STREAM_WILL_CAST, NULL);
+ REPORT_ERRORS|STREAM_WILL_CAST, NULL);
/* force into an fd */
if (stream == NULL || FAILURE == php_stream_cast(stream,
@@ -918,7 +842,7 @@ PHP_FUNCTION(proc_open)
#endif
if (cwd) {
- chdir(cwd);
+ php_ignore_value(chdir(cwd));
}
if (env.envarray) {
diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c
index 1ce7eff052..4eb69d7ef2 100644
--- a/ext/standard/quot_print.c
+++ b/ext/standard/quot_print.c
@@ -162,7 +162,10 @@ PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t len
lp = 0;
} else {
if (iscntrl (c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*str == '\015'))) {
- if ((lp += 3) > PHP_QPRINT_MAXL) {
+ if ((((lp+= 3) > PHP_QPRINT_MAXL) && (c <= 0x7f))
+ || ((c > 0x7f) && (c <= 0xdf) && ((lp + 3) > PHP_QPRINT_MAXL))
+ || ((c > 0xdf) && (c <= 0xef) && ((lp + 6) > PHP_QPRINT_MAXL))
+ || ((c > 0xef) && (c <= 0xf4) && ((lp + 9) > PHP_QPRINT_MAXL))) {
*d++ = '=';
*d++ = '\015';
*d++ = '\012';
@@ -283,4 +286,4 @@ PHP_FUNCTION(quoted_printable_encode)
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
- */
+ */ \ No newline at end of file
diff --git a/ext/standard/sha1.c b/ext/standard/sha1.c
index 92a6cff61f..6e6a979802 100644
--- a/ext/standard/sha1.c
+++ b/ext/standard/sha1.c
@@ -75,11 +75,11 @@ PHP_FUNCTION(sha1_file)
int n;
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
return;
}
- stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
+ stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
if (!stream) {
RETURN_FALSE;
}
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index 83bc26aca5..86e0bc6e60 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -128,7 +128,7 @@ PHP_FUNCTION(stream_socket_client)
ZVAL_STRING(zerrstr, "", 1);
}
- stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ stream = php_stream_xport_create(host, host_len, REPORT_ERRORS,
STREAM_XPORT_CLIENT | (flags & PHP_STREAM_CLIENT_CONNECT ? STREAM_XPORT_CONNECT : 0) |
(flags & PHP_STREAM_CLIENT_ASYNC_CONNECT ? STREAM_XPORT_CONNECT_ASYNC : 0),
hashkey, &tv, context, &errstr, &err);
@@ -204,7 +204,7 @@ PHP_FUNCTION(stream_socket_server)
ZVAL_STRING(zerrstr, "", 1);
}
- stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ stream = php_stream_xport_create(host, host_len, REPORT_ERRORS,
STREAM_XPORT_SERVER | flags,
NULL, NULL, context, &errstr, &err);
@@ -391,13 +391,7 @@ PHP_FUNCTION(stream_socket_recvfrom)
}
read_buf[recvd] = '\0';
- if (PG(magic_quotes_runtime)) {
- Z_TYPE_P(return_value) = IS_STRING;
- Z_STRVAL_P(return_value) = php_addslashes(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), &Z_STRLEN_P(return_value), 1 TSRMLS_CC);
- return;
- } else {
- RETURN_STRINGL(read_buf, recvd, 0);
- }
+ RETURN_STRINGL(read_buf, recvd, 0);
}
efree(read_buf);
@@ -413,8 +407,7 @@ PHP_FUNCTION(stream_get_contents)
zval *zsrc;
long maxlen = PHP_STREAM_COPY_ALL,
desiredpos = -1L;
- int len,
- newlen;
+ int len;
char *contents = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ll", &zsrc, &maxlen, &desiredpos) == FAILURE) {
@@ -446,10 +439,6 @@ PHP_FUNCTION(stream_get_contents)
len = php_stream_copy_to_mem(stream, &contents, maxlen, 0);
if (contents) {
- if (len && PG(magic_quotes_runtime)) {
- contents = php_addslashes(contents, len, &newlen, 1 TSRMLS_CC); /* 1 = free source string */
- len = newlen;
- }
RETVAL_STRINGL(contents, len, 0);
} else {
RETVAL_EMPTY_STRING();
@@ -553,7 +542,7 @@ PHP_FUNCTION(stream_get_transports)
{
HashTable *stream_xport_hash;
char *stream_xport;
- int stream_xport_len;
+ uint stream_xport_len;
ulong num_key;
if (zend_parse_parameters_none() == FAILURE) {
@@ -582,7 +571,8 @@ PHP_FUNCTION(stream_get_wrappers)
{
HashTable *url_stream_wrappers_hash;
char *stream_protocol;
- int key_flags, stream_protocol_len = 0;
+ int key_flags;
+ uint stream_protocol_len = 0;
ulong num_key;
if (zend_parse_parameters_none() == FAILURE) {
@@ -658,9 +648,21 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC)
zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(stream_array)), NULL, ZVAL_PTR_DTOR, 0);
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
- zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
+ zend_hash_has_more_elements(Z_ARRVAL_P(stream_array)) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
+ int type;
+ char *key;
+ uint key_len;
+ ulong num_ind;
+
+ type = zend_hash_get_current_key_ex(Z_ARRVAL_P(stream_array),
+ &key, &key_len, &num_ind, 0, NULL);
+ if (type == HASH_KEY_NON_EXISTANT ||
+ zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == FAILURE) {
+ continue; /* should not happen */
+ }
+
php_stream_from_zval_no_verify(stream, elem);
if (stream == NULL) {
continue;
@@ -672,7 +674,12 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC)
*/
if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != -1) {
if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
- zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
+ if (type == HASH_KEY_IS_LONG) {
+ zend_hash_index_update(new_hash, num_ind, (void *)elem, sizeof(zval *), (void **)&dest_elem);
+ } else { /* HASH_KEY_IS_STRING */
+ zend_hash_update(new_hash, key, key_len, (void *)elem, sizeof(zval *), (void **)&dest_elem);
+ }
+
if (dest_elem) {
zval_add_ref(dest_elem);
}
@@ -903,7 +910,7 @@ static int parse_context_options(php_stream_context *context, zval *options TSRM
HashPosition pos, opos;
zval **wval, **oval;
char *wkey, *okey;
- int wkey_len, okey_len;
+ uint wkey_len, okey_len;
int ret = SUCCESS;
ulong num_key;
@@ -966,7 +973,7 @@ static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC)
{
php_stream_context *context = NULL;
- context = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 1, php_le_stream_context());
+ context = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 1, php_le_stream_context(TSRMLS_C));
if (context == NULL) {
php_stream *stream;
@@ -979,7 +986,7 @@ static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC)
param, but then something is called which requires a context.
Don't give them the default one though since they already said they
didn't want it. */
- context = stream->context = php_stream_context_alloc();
+ context = stream->context = php_stream_context_alloc(TSRMLS_C);
}
}
}
@@ -1105,7 +1112,7 @@ PHP_FUNCTION(stream_context_get_default)
}
if (FG(default_context) == NULL) {
- FG(default_context) = php_stream_context_alloc();
+ FG(default_context) = php_stream_context_alloc(TSRMLS_C);
}
context = FG(default_context);
@@ -1129,7 +1136,7 @@ PHP_FUNCTION(stream_context_set_default)
}
if (FG(default_context) == NULL) {
- FG(default_context) = php_stream_context_alloc();
+ FG(default_context) = php_stream_context_alloc(TSRMLS_C);
}
context = FG(default_context);
@@ -1150,7 +1157,7 @@ PHP_FUNCTION(stream_context_create)
RETURN_FALSE;
}
- context = php_stream_context_alloc();
+ context = php_stream_context_alloc(TSRMLS_C);
if (options) {
parse_context_options(context, options TSRMLS_CC);
@@ -1412,6 +1419,40 @@ PHP_FUNCTION(stream_set_write_buffer)
}
/* }}} */
+/* {{{ proto int stream_set_chunk_size(resource fp, int chunk_size)
+ Set the stream chunk size */
+PHP_FUNCTION(stream_set_chunk_size)
+{
+ int ret;
+ long csize;
+ zval *zstream;
+ php_stream *stream;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zstream, &csize) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (csize <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The chunk size must be a positive integer, given %ld", csize);
+ RETURN_FALSE;
+ }
+ /* stream.chunk_size is actually a size_t, but php_stream_set_option
+ * can only use an int to accept the new value and return the old one.
+ * In any case, values larger than INT_MAX for a chunk size make no sense.
+ */
+ if (csize > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The chunk size cannot be larger than %d", INT_MAX);
+ RETURN_FALSE;
+ }
+
+ php_stream_from_zval(stream, &zstream);
+
+ ret = php_stream_set_option(stream, PHP_STREAM_OPTION_SET_CHUNK_SIZE, (int)csize, NULL);
+
+ RETURN_LONG(ret > 0 ? (long)ret : (long)EOF);
+}
+/* }}} */
+
/* {{{ proto int stream_set_read_buffer(resource fp, int buffer)
Set file read buffer */
PHP_FUNCTION(stream_set_read_buffer)
diff --git a/ext/standard/streamsfuncs.h b/ext/standard/streamsfuncs.h
index c14b117c4a..46357a21f1 100644
--- a/ext/standard/streamsfuncs.h
+++ b/ext/standard/streamsfuncs.h
@@ -38,6 +38,7 @@ PHP_FUNCTION(stream_select);
PHP_FUNCTION(stream_set_timeout);
PHP_FUNCTION(stream_set_read_buffer);
PHP_FUNCTION(stream_set_write_buffer);
+PHP_FUNCTION(stream_set_chunk_size);
PHP_FUNCTION(stream_get_transports);
PHP_FUNCTION(stream_get_wrappers);
PHP_FUNCTION(stream_get_line);
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 68bf3fecfc..9154b3296c 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -36,7 +36,7 @@
#ifdef HAVE_MONETARY_H
# include <monetary.h>
#endif
-/*
+/*
* This define is here because some versions of libintl redefine setlocale
* to point to libintl_setlocale. That's a ridiculous thing to do as far
* as I am concerned, but with this define and the subsequent undef we
@@ -89,7 +89,7 @@ void register_string_constants(INIT_FUNC_ARGS)
REGISTER_LONG_CONSTANT("PATHINFO_FILENAME", PHP_PATHINFO_FILENAME, CONST_CS | CONST_PERSISTENT);
#ifdef HAVE_LOCALECONV
- /* If last members of struct lconv equal CHAR_MAX, no grouping is done */
+ /* If last members of struct lconv equal CHAR_MAX, no grouping is done */
/* This is bad, but since we are going to be hardcoding in the POSIX stuff anyway... */
# ifndef HAVE_LIMITS_H
@@ -110,7 +110,7 @@ void register_string_constants(INIT_FUNC_ARGS)
REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);
# endif
#endif
-
+
}
/* }}} */
@@ -139,13 +139,53 @@ static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t *
}
result[j] = '\0';
- if (newlen)
+ if (newlen)
*newlen = oldlen * 2 * sizeof(char);
return (char *)result;
}
/* }}} */
+/* {{{ php_hex2bin
+ */
+static char *php_hex2bin(const unsigned char *old, const size_t oldlen, size_t *newlen)
+{
+ size_t target_length = oldlen >> 1;
+ register unsigned char *str = (unsigned char *)safe_emalloc(target_length, sizeof(char), 1);
+ size_t i, j;
+ for (i = j = 0; i < target_length; i++) {
+ char c = old[j++];
+ if (c >= '0' && c <= '9') {
+ str[i] = (c - '0') << 4;
+ } else if (c >= 'a' && c <= 'f') {
+ str[i] = (c - 'a' + 10) << 4;
+ } else if (c >= 'A' && c <= 'F') {
+ str[i] = (c - 'A' + 10) << 4;
+ } else {
+ efree(str);
+ return NULL;
+ }
+ c = old[j++];
+ if (c >= '0' && c <= '9') {
+ str[i] |= c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ str[i] |= c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ str[i] |= c - 'A' + 10;
+ } else {
+ efree(str);
+ return NULL;
+ }
+ }
+ str[target_length] = '\0';
+
+ if (newlen)
+ *newlen = target_length;
+
+ return (char *)str;
+}
+/* }}} */
+
#ifdef HAVE_LOCALECONV
/* {{{ localeconv_r
* glibc's localeconv is not reentrant, so lets make it so ... sorta */
@@ -205,7 +245,34 @@ PHP_FUNCTION(bin2hex)
}
result = php_bin2hex((unsigned char *)data, datalen, &newlen);
-
+
+ if (!result) {
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(result, newlen, 0);
+}
+/* }}} */
+
+/* {{{ proto string hex2bin(string data)
+ Converts the hex representation of data to binary */
+PHP_FUNCTION(hex2bin)
+{
+ char *result, *data;
+ size_t newlen;
+ int datalen;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &datalen) == FAILURE) {
+ return;
+ }
+
+ if (datalen % 2 != 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Hexadecimal input string must have an even length");
+ RETURN_FALSE;
+ }
+
+ result = php_hex2bin((unsigned char *)data, datalen, &newlen);
+
if (!result) {
RETURN_FALSE;
}
@@ -219,18 +286,18 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
char *s11, *s22;
int len1, len2;
long start = 0, len = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &s11, &len1,
&s22, &len2, &start, &len) == FAILURE) {
return;
}
-
+
if (ZEND_NUM_ARGS() < 4) {
len = len1;
}
-
+
/* look at substr() function for more information */
-
+
if (start < 0) {
start += len1;
if (start < 0) {
@@ -239,14 +306,14 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
} else if (start > len1) {
RETURN_FALSE;
}
-
+
if (len < 0) {
len += (len1 - start);
if (len < 0) {
len = 0;
}
}
-
+
if (len > len1 - start) {
len = len1 - start;
}
@@ -266,7 +333,7 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
s11 + start + len /*str1_end*/,
s22 + len2 /*str2_end*/));
}
-
+
}
/* }}} */
@@ -462,7 +529,7 @@ PHP_FUNCTION(nl_langinfo)
{
long item;
char *value;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &item) == FAILURE) {
return;
}
@@ -650,12 +717,12 @@ PHP_FUNCTION(strcoll)
{
char *s1, *s2;
int s1len, s2len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &s1, &s1len, &s2, &s2len) == FAILURE) {
return;
}
- RETURN_LONG(strcoll((const char *) s1,
+ RETURN_LONG(strcoll((const char *) s1,
(const char *) s2));
}
/* }}} */
@@ -663,7 +730,7 @@ PHP_FUNCTION(strcoll)
/* {{{ php_charmask
* Fills a 256-byte bytemask with input. You can specify a range like 'a..z',
- * it needs to be incrementing.
+ * it needs to be incrementing.
* Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
*/
static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_DC)
@@ -674,8 +741,8 @@ static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_
memset(mask, 0, 256);
for (end = input+len; input < end; input++) {
- c=*input;
- if ((input+3 < end) && input[1] == '.' && input[2] == '.'
+ c=*input;
+ if ((input+3 < end) && input[1] == '.' && input[2] == '.'
&& input[3] >= c) {
memset(mask+c, 1, input[3] - c + 1);
input+=3;
@@ -696,7 +763,7 @@ static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing");
result = FAILURE;
continue;
- }
+ }
/* FIXME: better error (a..b..c is the only left possibility?) */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid '..'-range");
result = FAILURE;
@@ -765,11 +832,11 @@ static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
char *str;
char *what = NULL;
int str_len, what_len = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &what, &what_len) == FAILURE) {
return;
}
-
+
php_trim(str, str_len, what, what_len, return_value, mode TSRMLS_CC);
}
/* }}} */
@@ -939,7 +1006,7 @@ PHP_FUNCTION(wordwrap)
/* {{{ php_explode
*/
-PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
+PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
{
char *p1, *p2, *endp;
@@ -965,11 +1032,11 @@ PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
/* {{{ php_explode_negative_limit
*/
-PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, long limit)
+PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, long limit)
{
#define EXPLODE_ALLOC_STEP 64
char *p1, *p2, *endp;
-
+
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
p1 = Z_STRVAL_P(str);
@@ -993,11 +1060,11 @@ PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_valu
}
positions[found++] = p1 = p2 + Z_STRLEN_P(delim);
} while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL);
-
+
to_return = limit + found;
/* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
for (i = 0;i < to_return;i++) { /* this checks also for to_return > 0 */
- add_next_index_stringl(return_value, positions[i],
+ add_next_index_stringl(return_value, positions[i],
(positions[i+1] - Z_STRLEN_P(delim)) - positions[i],
1
);
@@ -1016,11 +1083,11 @@ PHP_FUNCTION(explode)
int str_len = 0, delim_len = 0;
long limit = LONG_MAX; /* No limit */
zval zdelim, zstr;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &delim, &delim_len, &str, &str_len, &limit) == FAILURE) {
return;
}
-
+
if (delim_len == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
RETURN_FALSE;
@@ -1031,7 +1098,7 @@ PHP_FUNCTION(explode)
if (str_len == 0) {
if (limit >= 0) {
add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
- }
+ }
return;
}
@@ -1053,7 +1120,7 @@ PHP_FUNCTION(explode)
/* {{{ php_implode
*/
-PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
+PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
{
zval **tmp;
HashPosition pos;
@@ -1088,7 +1155,7 @@ PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
smart_str_appendl(&implstr, "1", sizeof("1")-1);
}
break;
-
+
case IS_NULL:
break;
@@ -1118,7 +1185,7 @@ PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC)
smart_str_appendl(&implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
zval_dtor(&tmp_val);
break;
-
+
}
if (++i != numelems) {
@@ -1146,7 +1213,7 @@ PHP_FUNCTION(implode)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z", &arg1, &arg2) == FAILURE) {
return;
}
-
+
if (arg2 == NULL) {
if (Z_TYPE_PP(arg1) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument must be an array");
@@ -1173,7 +1240,7 @@ PHP_FUNCTION(implode)
return;
}
}
-
+
php_implode(delim, arr, return_value TSRMLS_CC);
if (arg2 == NULL) {
@@ -1182,22 +1249,22 @@ PHP_FUNCTION(implode)
}
/* }}} */
-#define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]
+#define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]
/* {{{ proto string strtok([string str,] string token)
Tokenize a string */
PHP_FUNCTION(strtok)
-{
+{
char *str, *tok = NULL;
int str_len, tok_len = 0;
zval *zv;
-
+
char *token;
char *token_end;
char *p;
char *pe;
int skipped = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &tok, &tok_len) == FAILURE) {
return;
}
@@ -1216,21 +1283,21 @@ PHP_FUNCTION(strtok)
BG(strtok_last) = BG(strtok_string) = Z_STRVAL_P(zv);
BG(strtok_len) = str_len;
}
-
+
p = BG(strtok_last); /* Where we start to search */
pe = BG(strtok_string) + BG(strtok_len);
if (!p || p >= pe) {
RETURN_FALSE;
}
-
+
token = tok;
token_end = token + tok_len;
while (token < token_end) {
STRTOK_TABLE(token++) = 1;
}
-
+
/* Skip leading delimiters */
while (STRTOK_TABLE(p)) {
if (++p >= pe) {
@@ -1241,14 +1308,14 @@ PHP_FUNCTION(strtok)
}
skipped++;
}
-
- /* We know at this place that *p is no delimiter, so skip it */
+
+ /* We know at this place that *p is no delimiter, so skip it */
while (++p < pe) {
if (STRTOK_TABLE(p)) {
- goto return_token;
+ goto return_token;
}
}
-
+
if (p - BG(strtok_last)) {
return_token:
RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped, 1);
@@ -1261,7 +1328,7 @@ return_token:
/* Restore table -- usually faster then memset'ing the table on every invocation */
restore:
token = tok;
-
+
while (token < token_end) {
STRTOK_TABLE(token++) = 0;
}
@@ -1273,7 +1340,7 @@ restore:
PHPAPI char *php_strtoupper(char *s, size_t len)
{
unsigned char *c, *e;
-
+
c = (unsigned char *)s;
e = (unsigned char *)c+len;
@@ -1291,13 +1358,13 @@ PHP_FUNCTION(strtoupper)
{
char *arg;
int arglen;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arglen) == FAILURE) {
return;
}
arg = estrndup(arg, arglen);
- php_strtoupper(arg, arglen);
+ php_strtoupper(arg, arglen);
RETURN_STRINGL(arg, arglen, 0);
}
/* }}} */
@@ -1307,7 +1374,7 @@ PHP_FUNCTION(strtoupper)
PHPAPI char *php_strtolower(char *s, size_t len)
{
unsigned char *c, *e;
-
+
c = (unsigned char *)s;
e = c+len;
@@ -1325,7 +1392,7 @@ PHP_FUNCTION(strtolower)
{
char *str;
int arglen;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &arglen) == FAILURE) {
return;
}
@@ -1338,13 +1405,13 @@ PHP_FUNCTION(strtolower)
/* {{{ php_basename
*/
-PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC)
+PHPAPI void php_basename(const char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC)
{
char *ret = NULL, *c, *comp, *cend;
size_t inc_len, cnt;
int state;
- c = comp = cend = s;
+ c = comp = cend = (char*)s;
cnt = len;
state = 0;
while (cnt > 0) {
@@ -1354,7 +1421,7 @@ PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char
case -2:
case -1:
inc_len = 1;
- php_mblen(NULL, 0);
+ php_ignore_value(php_mblen(NULL, 0));
break;
case 0:
goto quit_loop;
@@ -1446,7 +1513,7 @@ PHP_FUNCTION(dirname)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
-
+
ret = estrndup(str, str_len);
ret_len = php_dirname(ret, str_len);
@@ -1469,10 +1536,10 @@ PHP_FUNCTION(pathinfo)
}
have_basename = ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);
-
+
MAKE_STD_ZVAL(tmp);
array_init(tmp);
-
+
if ((opt & PHP_PATHINFO_DIRNAME) == PHP_PATHINFO_DIRNAME) {
ret = estrndup(path, path_len);
php_dirname(ret, path_len);
@@ -1482,14 +1549,14 @@ PHP_FUNCTION(pathinfo)
efree(ret);
ret = NULL;
}
-
+
if (have_basename) {
php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
add_assoc_stringl(tmp, "basename", ret, ret_len, 0);
}
-
+
if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
- char *p;
+ const char *p;
int idx;
if (!have_basename) {
@@ -1503,9 +1570,9 @@ PHP_FUNCTION(pathinfo)
add_assoc_stringl(tmp, "extension", ret + idx + 1, ret_len - idx - 1, 1);
}
}
-
+
if ((opt & PHP_PATHINFO_FILENAME) == PHP_PATHINFO_FILENAME) {
- char *p;
+ const char *p;
int idx;
/* Have we alrady looked up the basename? */
@@ -1632,7 +1699,7 @@ PHP_FUNCTION(stristr)
char *haystack_dup;
char needle_char[2];
zend_bool part = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &haystack, &haystack_len, &needle, &part) == FAILURE) {
return;
}
@@ -1665,7 +1732,7 @@ PHP_FUNCTION(stristr)
RETVAL_STRINGL(haystack, found_offset, 1);
} else {
RETVAL_STRINGL(haystack + found_offset, haystack_len - found_offset, 1);
- }
+ }
} else {
RETVAL_FALSE;
}
@@ -1685,7 +1752,7 @@ PHP_FUNCTION(strstr)
char needle_char[2];
long found_offset;
zend_bool part = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|b", &haystack, &haystack_len, &needle, &part) == FAILURE) {
return;
}
@@ -1732,7 +1799,7 @@ PHP_FUNCTION(strpos)
char needle_char[2];
long offset = 0;
int haystack_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &haystack, &haystack_len, &needle, &offset) == FAILURE) {
return;
}
@@ -1816,9 +1883,9 @@ PHP_FUNCTION(stripos)
}
needle_char[0] = tolower(needle_char[0]);
needle_char[1] = '\0';
- found = php_memnstr(haystack_dup + offset,
- needle_char,
- sizeof(needle_char) - 1,
+ found = php_memnstr(haystack_dup + offset,
+ needle_char,
+ sizeof(needle_char) - 1,
haystack_dup + haystack_len);
}
@@ -1940,7 +2007,7 @@ PHP_FUNCTION(strripos)
}
if (needle_len == 1) {
- /* Single character search can shortcut memcmps
+ /* Single character search can shortcut memcmps
Can also avoid tolower emallocs */
if (offset >= 0) {
if (offset > haystack_len) {
@@ -2018,10 +2085,10 @@ PHP_FUNCTION(strrchr)
{
zval *needle;
char *haystack;
- char *found = NULL;
+ const char *found = NULL;
long found_offset;
int haystack_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &haystack, &haystack_len, &needle) == FAILURE) {
return;
}
@@ -2054,7 +2121,7 @@ static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int c
char *p, *q;
int chunks; /* complete chunks! */
int restlen;
- int out_len;
+ int out_len;
chunks = srclen / chunklen;
restlen = srclen - chunks * chunklen; /* srclen % chunklen */
@@ -2100,7 +2167,7 @@ static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int c
/* {{{ proto string chunk_split(string str [, int chunklen [, string ending]])
Returns split line */
-PHP_FUNCTION(chunk_split)
+PHP_FUNCTION(chunk_split)
{
char *str;
char *result;
@@ -2109,7 +2176,7 @@ PHP_FUNCTION(chunk_split)
long chunklen = 76;
int result_len;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &str, &str_len, &chunklen, &end, &endlen) == FAILURE) {
return;
}
@@ -2125,8 +2192,8 @@ PHP_FUNCTION(chunk_split)
result = emalloc(result_len + 1);
memcpy(result, str, str_len);
memcpy(result + str_len, end, endlen);
- result[result_len] = '\0';
- RETURN_STRINGL(result, result_len, 0);
+ result[result_len] = '\0';
+ RETURN_STRINGL(result, result_len, 0);
}
if (!str_len) {
@@ -2151,7 +2218,7 @@ PHP_FUNCTION(substr)
long l = 0, f;
int str_len;
int argc = ZEND_NUM_ARGS();
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &str, &str_len, &f, &l) == FAILURE) {
return;
}
@@ -2165,7 +2232,7 @@ PHP_FUNCTION(substr)
} else {
l = str_len;
}
-
+
if (f > str_len) {
RETURN_FALSE;
} else if (f < 0 && -f > str_len) {
@@ -2228,7 +2295,7 @@ PHP_FUNCTION(substr_replace)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|Z", &str, &repl, &from, &len) == FAILURE) {
return;
}
-
+
if (Z_TYPE_PP(str) != IS_ARRAY) {
if (Z_ISREF_PP(str)) {
SEPARATE_ZVAL(str);
@@ -2262,20 +2329,20 @@ PHP_FUNCTION(substr_replace)
if (Z_TYPE_PP(str) == IS_STRING) {
if (
- (argc == 3 && Z_TYPE_PP(from) == IS_ARRAY) ||
+ (argc == 3 && Z_TYPE_PP(from) == IS_ARRAY) ||
(argc == 4 && Z_TYPE_PP(from) != Z_TYPE_PP(len))
) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should be of same type - numerical or array ");
- RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
+ RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
}
if (argc == 4 && Z_TYPE_PP(from) == IS_ARRAY) {
if (zend_hash_num_elements(Z_ARRVAL_PP(from)) != zend_hash_num_elements(Z_ARRVAL_PP(len))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should have the same number of elements");
- RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
+ RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
}
}
}
-
+
if (Z_TYPE_PP(str) != IS_ARRAY) {
if (Z_TYPE_PP(from) != IS_ARRAY) {
int repl_len = 0;
@@ -2333,7 +2400,7 @@ PHP_FUNCTION(substr_replace)
RETURN_STRINGL(result, result_len, 0);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Functionality of 'from' and 'len' as arrays is not implemented");
- RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
+ RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
}
} else { /* str is array of strings */
char *str_index = NULL;
@@ -2358,6 +2425,9 @@ PHP_FUNCTION(substr_replace)
while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(str), (void **) &tmp_str, &pos_str) == SUCCESS) {
zval *orig_str;
zval dummy;
+ ulong refcount;
+ int was_ref;
+
if(Z_TYPE_PP(tmp_str) != IS_STRING) {
dummy = **tmp_str;
orig_str = &dummy;
@@ -2366,6 +2436,9 @@ PHP_FUNCTION(substr_replace)
} else {
orig_str = *tmp_str;
}
+ was_ref = Z_ISREF_P(orig_str);
+ Z_UNSET_ISREF_P(orig_str);
+ refcount = Z_REFCOUNT_P(orig_str);
if (Z_TYPE_PP(from) == IS_ARRAY) {
if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(from), (void **) &tmp_from, &pos_from)) {
@@ -2416,7 +2489,7 @@ PHP_FUNCTION(substr_replace)
} else {
l = Z_STRLEN_P(orig_str);
}
- } else if (argc > 3) {
+ } else if (argc > 3) {
l = Z_LVAL_PP(len);
} else {
l = Z_STRLEN_P(orig_str);
@@ -2448,8 +2521,16 @@ PHP_FUNCTION(substr_replace)
repl_str = *tmp_repl;
}
+ if(Z_REFCOUNT_P(orig_str) != refcount) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument was modified while replacing");
+ if(Z_TYPE_PP(tmp_repl) != IS_STRING) {
+ zval_dtor(repl_str);
+ }
+ break;
+ }
+
result_len += Z_STRLEN_P(repl_str);
- zend_hash_move_forward_ex(Z_ARRVAL_PP(repl), &pos_repl);
+ zend_hash_move_forward_ex(Z_ARRVAL_PP(repl), &pos_repl);
result = emalloc(result_len + 1);
memcpy(result, Z_STRVAL_P(orig_str), f);
@@ -2460,7 +2541,7 @@ PHP_FUNCTION(substr_replace)
}
} else {
result = emalloc(result_len + 1);
-
+
memcpy(result, Z_STRVAL_P(orig_str), f);
memcpy((result + f), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
}
@@ -2484,6 +2565,8 @@ PHP_FUNCTION(substr_replace)
if(Z_TYPE_PP(tmp_str) != IS_STRING) {
zval_dtor(orig_str);
+ } else {
+ Z_SET_ISREF_TO_P(orig_str, was_ref);
}
zend_hash_move_forward_ex(Z_ARRVAL_PP(str), &pos_str);
} /*while*/
@@ -2504,15 +2587,15 @@ PHP_FUNCTION(quotemeta)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &old, &old_len) == FAILURE) {
return;
}
-
+
old_end = old + old_len;
-
+
if (old == old_end) {
RETURN_FALSE;
}
-
+
str = safe_emalloc(2, old_len, 1);
-
+
for (p = old, q = str; p != old_end; p++) {
c = *p;
switch (c) {
@@ -2545,11 +2628,11 @@ PHP_FUNCTION(ord)
{
char *str;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
-
+
RETURN_LONG((unsigned char) str[0]);
}
/* }}} */
@@ -2578,7 +2661,7 @@ PHP_FUNCTION(chr)
/* {{{ php_ucfirst
Uppercase the first character of the word in a native string */
-static void php_ucfirst(char *str)
+static void php_ucfirst(char *str)
{
register char *r;
r = str;
@@ -2592,7 +2675,7 @@ PHP_FUNCTION(ucfirst)
{
char *str;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
@@ -2643,7 +2726,7 @@ PHP_FUNCTION(ucwords)
char *str;
register char *r, *r_end;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
@@ -2705,7 +2788,7 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
HashPosition hpos;
smart_str result = {0};
HashTable tmp_hash;
-
+
zend_hash_init(&tmp_hash, zend_hash_num_elements(hash), NULL, NULL, 0);
zend_hash_internal_pointer_reset_ex(hash, &hpos);
while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) {
@@ -2723,12 +2806,12 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
if (len < minlen) {
minlen = len;
}
- break;
-
+ break;
+
case HASH_KEY_IS_LONG:
Z_TYPE(ctmp) = IS_LONG;
Z_LVAL(ctmp) = num_key;
-
+
convert_to_string(&ctmp);
len = Z_STRLEN(ctmp);
zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL);
@@ -2758,7 +2841,7 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
for (len = maxlen; len >= minlen; len--) {
key[len] = 0;
-
+
if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) {
char *tval;
int tlen;
@@ -2783,7 +2866,7 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
zval_dtor(&tmp);
}
break;
- }
+ }
}
if (! found) {
@@ -2801,16 +2884,16 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
/* {{{ proto string strtr(string str, string from[, string to])
Translates characters in str using given translation tables */
PHP_FUNCTION(strtr)
-{
+{
zval **from;
char *str, *to = NULL;
int str_len, to_len = 0;
int ac = ZEND_NUM_ARGS();
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ|s", &str, &str_len, &from, &to, &to_len) == FAILURE) {
return;
}
-
+
if (ac == 2 && Z_TYPE_PP(from) != IS_ARRAY) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array");
RETURN_FALSE;
@@ -2827,12 +2910,12 @@ PHP_FUNCTION(strtr)
convert_to_string_ex(from);
ZVAL_STRINGL(return_value, str, str_len, 1);
-
+
php_strtr(Z_STRVAL_P(return_value),
Z_STRLEN_P(return_value),
Z_STRVAL_PP(from),
to,
- MIN(Z_STRLEN_PP(from),
+ MIN(Z_STRLEN_PP(from),
to_len));
}
}
@@ -2845,22 +2928,22 @@ PHP_FUNCTION(strrev)
char *str;
char *e, *n, *p;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
-
+
n = emalloc(str_len+1);
p = n;
-
+
e = str + str_len;
-
+
while (--e>=str) {
*p++ = *e;
}
-
+
*p = '\0';
-
+
RETVAL_STRINGL(n, str_len, 0);
}
/* }}} */
@@ -2873,7 +2956,7 @@ static void php_similar_str(const char *txt1, int len1, const char *txt2, int le
char *end1 = (char *) txt1 + len1;
char *end2 = (char *) txt2 + len2;
int l;
-
+
*max = 0;
for (p = (char *) txt1; p < end1; p++) {
for (q = (char *) txt2; q < end2; q++) {
@@ -2898,11 +2981,11 @@ static int php_similar_char(const char *txt1, int len1, const char *txt2, int le
php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max);
if ((sum = max)) {
if (pos1 && pos2) {
- sum += php_similar_char(txt1, pos1,
+ sum += php_similar_char(txt1, pos1,
txt2, pos2);
}
if ((pos1 + max < len1) && (pos2 + max < len2)) {
- sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
+ sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
txt2 + pos2 + max, len2 - pos2 - max);
}
}
@@ -2920,15 +3003,15 @@ PHP_FUNCTION(similar_text)
int ac = ZEND_NUM_ARGS();
int sim;
int t1_len, t2_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Z", &t1, &t1_len, &t2, &t2_len, &percent) == FAILURE) {
return;
}
-
+
if (ac > 2) {
convert_to_double_ex(percent);
}
-
+
if (t1_len + t2_len == 0) {
if (ac > 2) {
Z_DVAL_PP(percent) = 0;
@@ -2936,8 +3019,8 @@ PHP_FUNCTION(similar_text)
RETURN_LONG(0);
}
-
- sim = php_similar_char(t1, t1_len, t2, t2_len);
+
+ sim = php_similar_char(t1, t1_len, t2, t2_len);
if (ac > 2) {
Z_DVAL_PP(percent) = sim * 200.0 / (t1_len + t2_len);
@@ -2963,34 +3046,6 @@ PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC)
s = str;
t = str;
- if (PG(magic_quotes_sybase)) {
- while (l > 0) {
- if (*t == '\'') {
- if ((l > 0) && (t[1] == '\'')) {
- t++;
- if (len != NULL) {
- (*len)--;
- }
- l--;
- }
- *s++ = *t++;
- } else if (*t == '\\' && t[1] == '0' && l > 0) {
- *s++='\0';
- t+=2;
- if (len != NULL) {
- (*len)--;
- }
- l--;
- } else {
- *s++ = *t++;
- }
- l--;
- }
- *s = '\0';
-
- return;
- }
-
while (l > 0) {
if (*t == '\\') {
t++; /* skip the slash */
@@ -3048,7 +3103,7 @@ PHP_FUNCTION(addslashes)
{
char *str;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
@@ -3058,8 +3113,8 @@ PHP_FUNCTION(addslashes)
}
RETURN_STRING(php_addslashes(str,
- str_len,
- &Z_STRLEN_P(return_value), 0
+ str_len,
+ &Z_STRLEN_P(return_value), 0
TSRMLS_CC), 0);
}
/* }}} */
@@ -3070,7 +3125,7 @@ PHP_FUNCTION(stripcslashes)
{
char *str;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
@@ -3086,7 +3141,7 @@ PHP_FUNCTION(stripslashes)
{
char *str;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
@@ -3099,7 +3154,7 @@ PHP_FUNCTION(stripslashes)
#ifndef HAVE_STRERROR
/* {{{ php_strerror
*/
-char *php_strerror(int errnum)
+char *php_strerror(int errnum)
{
extern int sys_nerr;
extern char *sys_errlist[];
@@ -3150,8 +3205,8 @@ PHPAPI void php_stripcslashes(char *str, int *len)
break;
}
/* break is left intentionally */
- default:
- i=0;
+ default:
+ i=0;
while (source < end && *source >= '0' && *source <= '7' && i<3) {
numtmp[i++] = *source++;
}
@@ -3177,10 +3232,10 @@ PHPAPI void php_stripcslashes(char *str, int *len)
*len = nlen;
}
/* }}} */
-
+
/* {{{ php_addcslashes
*/
-PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_free, char *what, int wlength TSRMLS_DC)
+PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int should_free, char *what, int wlength TSRMLS_DC)
{
char flags[256];
char *new_str = safe_emalloc(4, (length?length:(length=strlen(str))), 1);
@@ -3195,8 +3250,8 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_
php_charmask((unsigned char *)what, wlength, flags TSRMLS_CC);
- for (source = str, end = source + length, target = new_str; source < end; source++) {
- c = *source;
+ for (source = (char*)str, end = source + length, target = new_str; source < end; source++) {
+ c = *source;
if (flags[(unsigned char)c]) {
if ((unsigned char) c < 32 || (unsigned char) c > 126) {
*target++ = '\\';
@@ -3211,7 +3266,7 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_
default: target += sprintf(target, "%03o", (unsigned char) c);
}
continue;
- }
+ }
*target++ = '\\';
}
*target++ = c;
@@ -3225,7 +3280,7 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_
*new_length = newlen;
}
if (should_free) {
- STR_FREE(str);
+ STR_FREE((char*)str);
}
return new_str;
}
@@ -3235,20 +3290,12 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_
*/
PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC)
{
- return php_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC);
-}
-/* }}} */
-
-/* {{{ php_addslashes_ex
- */
-PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC)
-{
/* maximum string length, worst case situation */
char *new_str;
char *source, *target;
char *end;
int local_new_length;
-
+
if (!new_length) {
new_length = &local_new_length;
}
@@ -3260,45 +3307,26 @@ PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int shoul
source = str;
end = source + length;
target = new_str;
-
- if (!ignore_sybase && PG(magic_quotes_sybase)) {
- while (source < end) {
- switch (*source) {
- case '\0':
- *target++ = '\\';
- *target++ = '0';
- break;
- case '\'':
- *target++ = '\'';
- *target++ = '\'';
- break;
- default:
- *target++ = *source;
- break;
- }
- source++;
- }
- } else {
- while (source < end) {
- switch (*source) {
- case '\0':
- *target++ = '\\';
- *target++ = '0';
- break;
- case '\'':
- case '\"':
- case '\\':
- *target++ = '\\';
- /* break is missing *intentionally* */
- default:
- *target++ = *source;
- break;
- }
-
- source++;
+
+ while (source < end) {
+ switch (*source) {
+ case '\0':
+ *target++ = '\\';
+ *target++ = '0';
+ break;
+ case '\'':
+ case '\"':
+ case '\\':
+ *target++ = '\\';
+ /* break is missing *intentionally* */
+ default:
+ *target++ = *source;
+ break;
}
+
+ source++;
}
-
+
*target = 0;
*new_length = target - new_str;
if (should_free) {
@@ -3322,7 +3350,7 @@ PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_l
int char_count = 0;
int replaced = 0;
char *source, *target, *tmp, *source_end=str+len, *tmp_end = NULL;
-
+
if (case_sensitivity) {
char *p = str, *e = p + len;
while ((p = memchr(p, from, (e - p)))) {
@@ -3341,7 +3369,7 @@ PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_l
ZVAL_STRINGL(result, str, len, 1);
return 0;
}
-
+
Z_STRLEN_P(result) = len + (char_count * (to_len - 1));
Z_STRVAL_P(result) = target = safe_emalloc(char_count, to_len, len + 1);
Z_TYPE_P(result) = IS_STRING;
@@ -3395,7 +3423,7 @@ PHPAPI int php_char_to_str(char *str, uint len, char from, char *to, int to_len,
/* {{{ php_str_to_str_ex
*/
-PHPAPI char *php_str_to_str_ex(char *haystack, int length,
+PHPAPI char *php_str_to_str_ex(char *haystack, int length,
char *needle, int needle_len, char *str, int str_len, int *_new_length, int case_sensitivity, int *replace_count)
{
char *new_str;
@@ -3567,11 +3595,11 @@ nothing_todo:
/* {{{ php_str_to_str
*/
-PHPAPI char *php_str_to_str(char *haystack, int length,
+PHPAPI char *php_str_to_str(char *haystack, int length,
char *needle, int needle_len, char *str, int str_len, int *_new_length)
{
return php_str_to_str_ex(haystack, length, needle, needle_len, str, str_len, _new_length, 1, NULL);
-}
+}
/* }}} */
/* {{{ php_str_replace_in_subject
@@ -3584,19 +3612,19 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
char *replace_value = NULL;
int replace_len = 0;
- /* Make sure we're dealing with strings. */
+ /* Make sure we're dealing with strings. */
convert_to_string_ex(subject);
Z_TYPE_P(result) = IS_STRING;
if (Z_STRLEN_PP(subject) == 0) {
ZVAL_STRINGL(result, "", 0, 1);
return;
}
-
+
/* If search is an array */
if (Z_TYPE_P(search) == IS_ARRAY) {
/* Duplicate subject string for repeated replacement */
MAKE_COPY_ZVAL(subject, result);
-
+
zend_hash_internal_pointer_reset(Z_ARRVAL_P(search));
if (Z_TYPE_P(replace) == IS_ARRAY) {
@@ -3609,7 +3637,7 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
/* For each entry in the search array, get the entry */
while (zend_hash_get_current_data(Z_ARRVAL_P(search), (void **) &search_entry) == SUCCESS) {
- /* Make sure we're dealing with strings. */
+ /* Make sure we're dealing with strings. */
SEPARATE_ZVAL(search_entry);
convert_to_string(*search_entry);
if (Z_STRLEN_PP(search_entry) == 0) {
@@ -3624,9 +3652,9 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
if (Z_TYPE_P(replace) == IS_ARRAY) {
/* Get current entry */
if (zend_hash_get_current_data(Z_ARRVAL_P(replace), (void **)&replace_entry) == SUCCESS) {
- /* Make sure we're dealing with strings. */
+ /* Make sure we're dealing with strings. */
convert_to_string_ex(replace_entry);
-
+
/* Set replacement value to the one we got from array */
replace_value = Z_STRVAL_PP(replace_entry);
replace_len = Z_STRLEN_PP(replace_entry);
@@ -3638,7 +3666,7 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
replace_len = 0;
}
}
-
+
if (Z_STRLEN_PP(search_entry) == 1) {
php_char_to_str_ex(Z_STRVAL_P(result),
Z_STRLEN_P(result),
@@ -3654,7 +3682,7 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje
replace_value, replace_len, &Z_STRLEN(temp_result), case_sensitivity, replace_count);
}
- efree(Z_STRVAL_P(result));
+ str_efree(Z_STRVAL_P(result));
Z_STRVAL_P(result) = Z_STRVAL(temp_result);
Z_STRLEN_P(result) = Z_STRLEN(temp_result);
@@ -3741,12 +3769,12 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
add_index_zval(return_value, num_key, result);
break;
}
-
+
zend_hash_move_forward(Z_ARRVAL_PP(subject));
}
} else { /* if subject is not an array */
php_str_replace_in_subject(*search, *replace, subject, return_value, case_sensitivity, (argc > 3) ? &count : NULL);
- }
+ }
if (argc > 3) {
zval_dtor(*zcount);
ZVAL_LONG(*zcount, count);
@@ -3783,11 +3811,11 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
long max_chars=0;
int begin, end, char_count, orig_begin;
int str_len;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &max_chars) == FAILURE) {
return;
}
-
+
if (str_len == 0) {
RETURN_FALSE;
}
@@ -3807,7 +3835,7 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
} else {
block_type = _HEB_BLOCK_TYPE_ENG;
}
-
+
do {
if (block_type == _HEB_BLOCK_TYPE_HEB) {
while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) {
@@ -3877,7 +3905,7 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
broken_str = (char *) emalloc(str_len+1);
begin=end=str_len-1;
target = broken_str;
-
+
while (1) {
char_count=0;
while ((!max_chars || char_count < max_chars) && begin > 0) {
@@ -3893,7 +3921,7 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
}
if (char_count == max_chars) { /* try to avoid breaking words */
int new_char_count=char_count, new_begin=begin;
-
+
while (new_char_count > 0) {
if (_isblank(heb_str[new_begin]) || _isnewline(heb_str[new_begin])) {
break;
@@ -3906,7 +3934,7 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
}
}
orig_begin=begin;
-
+
if (_isblank(heb_str[begin])) {
heb_str[begin]='\n';
}
@@ -3970,14 +3998,14 @@ PHP_FUNCTION(nl2br)
int repl_cnt = 0;
int str_len;
zend_bool is_xhtml = 1;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &str, &str_len, &is_xhtml) == FAILURE) {
return;
}
-
+
tmp = str;
end = str + str_len;
-
+
/* it is really faster to scan twice and allocate mem once instead of scanning once
and constantly reallocing */
while (tmp < end) {
@@ -3992,10 +4020,10 @@ PHP_FUNCTION(nl2br)
}
repl_cnt++;
}
-
+
tmp++;
}
-
+
if (repl_cnt == 0) {
RETURN_STRINGL(str, str_len, 1);
}
@@ -4021,7 +4049,7 @@ PHP_FUNCTION(nl2br)
}
*target++ = '>';
-
+
if ((*str == '\r' && *(str+1) == '\n') || (*str == '\n' && *(str+1) == '\r')) {
*target++ = *str++;
}
@@ -4029,10 +4057,10 @@ PHP_FUNCTION(nl2br)
default:
*target++ = *str;
}
-
+
str++;
}
-
+
*target = '\0';
RETURN_STRINGL(tmp, new_length, 0);
@@ -4054,7 +4082,7 @@ PHP_FUNCTION(strip_tags)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Z", &str, &str_len, &allow) == FAILURE) {
return;
}
-
+
/* To maintain a certain BC, we allow anything for the second parameter and return original string */
if (allow != NULL) {
convert_to_string_ex(allow);
@@ -4083,14 +4111,14 @@ PHP_FUNCTION(setlocale)
#ifdef HAVE_SETLOCALE
if (Z_TYPE_PP(pcategory) == IS_LONG) {
- convert_to_long_ex(pcategory);
+ convert_to_long_ex(pcategory);
cat = Z_LVAL_PP(pcategory);
} else {
/* FIXME: The following behaviour should be removed. */
char *category;
-
+
php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "Passing locale category name as string is deprecated. Use the LC_* -constants instead");
-
+
convert_to_string_ex(pcategory);
category = Z_STRVAL_PP(pcategory);
@@ -4112,10 +4140,10 @@ PHP_FUNCTION(setlocale)
cat = LC_TIME;
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid locale category name %s, must be one of LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, or LC_TIME", category);
-
+
if (args) {
efree(args);
- }
+ }
RETURN_FALSE;
}
}
@@ -4123,7 +4151,7 @@ PHP_FUNCTION(setlocale)
if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(args[0]));
}
-
+
while (1) {
if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
if (!zend_hash_num_elements(Z_ARRVAL_PP(args[0]))) {
@@ -4135,7 +4163,7 @@ PHP_FUNCTION(setlocale)
}
convert_to_string_ex(plocale);
-
+
if (!strcmp ("0", Z_STRVAL_PP(plocale))) {
loc = NULL;
} else {
@@ -4160,7 +4188,7 @@ PHP_FUNCTION(setlocale)
}
RETURN_STRING(retval, 1);
}
-
+
if (Z_TYPE_PP(args[0]) == IS_ARRAY) {
if (zend_hash_move_forward(Z_ARRVAL_PP(args[0])) == FAILURE) break;
} else {
@@ -4201,13 +4229,12 @@ PHP_FUNCTION(parse_str)
sapi_module.treat_data(PARSE_STRING, res, &tmp TSRMLS_CC);
} else {
zval ret;
-
+
array_init(&ret);
sapi_module.treat_data(PARSE_STRING, res, &ret TSRMLS_CC);
/* Clear out the array that was passed in. */
zval_dtor(arrayArg);
- arrayArg->type = ret.type;
- arrayArg->value = ret.value;
+ ZVAL_COPY_VALUE(arrayArg, &ret);
}
}
/* }}} */
@@ -4216,10 +4243,10 @@ PHP_FUNCTION(parse_str)
/* {{{ php_tag_find
*
- * Check if tag is in a set of tags
+ * Check if tag is in a set of tags
*
* states:
- *
+ *
* 0 start tag
* 1 first non-whitespace char seen
*/
@@ -4231,13 +4258,13 @@ int php_tag_find(char *tag, int len, char *set) {
if (len <= 0) {
return 0;
}
-
+
norm = emalloc(len+1);
n = norm;
t = tag;
c = tolower(*t);
- /*
+ /*
normalize the tag removing leading and trailing whitespace
and turn any <a whatever...> into just <a> and any </tag>
into <tag>
@@ -4265,9 +4292,9 @@ int php_tag_find(char *tag, int len, char *set) {
break;
}
c = tolower(*(++t));
- }
+ }
*(n++) = '>';
- *n = '\0';
+ *n = '\0';
if (strstr(set, norm)) {
done=1;
} else {
@@ -4285,9 +4312,9 @@ PHPAPI size_t php_strip_tags(char *rbuf, int len, int *stateptr, char *allow, in
/* }}} */
/* {{{ php_strip_tags
-
- A simple little state-machine to strip out html and php tags
-
+
+ A simple little state-machine to strip out html and php tags
+
State 0 is the output state, State 1 means we are inside a
normal html tag and state 2 means we are inside a php tag.
@@ -4309,6 +4336,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
char *tbuf, *buf, *p, *tp, *rp, c, lc;
int br, i=0, depth=0, in_q = 0;
int state = 0, pos;
+ char *allow_free;
if (stateptr)
state = *stateptr;
@@ -4320,7 +4348,12 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
rp = rbuf;
br = 0;
if (allow) {
- php_strtolower(allow, allow_len);
+ if (IS_INTERNED(allow)) {
+ allow_free = allow = zend_str_tolower_dup(allow, allow_len);
+ } else {
+ allow_free = NULL;
+ php_strtolower(allow, allow_len);
+ }
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
tp = tbuf;
} else {
@@ -4370,7 +4403,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
} else if (state == 0) {
*(rp++) = c;
}
- break;
+ break;
case ')':
if (state == 2) {
@@ -4388,7 +4421,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
} else if (state == 0) {
*(rp++) = c;
}
- break;
+ break;
case '>':
if (depth) {
@@ -4419,14 +4452,14 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
tp = tbuf;
}
break;
-
+
case 2: /* PHP */
if (!br && lc != '\"' && *(p-1) == '?') {
in_q = state = 0;
tp = tbuf;
}
break;
-
+
case 3:
in_q = state = 0;
tp = tbuf;
@@ -4474,10 +4507,10 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
}
}
break;
-
- case '!':
+
+ case '!':
/* JavaScript & Other HTML scripting languages */
- if (state == 1 && *(p-1) == '<') {
+ if (state == 1 && *(p-1) == '<') {
state = 3;
lc = c;
} else {
@@ -4504,7 +4537,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow,
case '?':
- if (state == 1 && *(p-1) == '<') {
+ if (state == 1 && *(p-1) == '<') {
br=0;
state=2;
break;
@@ -4549,18 +4582,22 @@ reg_char:
tp = tbuf + pos;
}
*(tp++) = c;
- }
+ }
break;
}
c = *(++p);
i++;
- }
+ }
if (rp < rbuf + len) {
*rp = '\0';
}
efree(buf);
- if (allow)
+ if (allow) {
efree(tbuf);
+ if (allow_free) {
+ efree(allow_free);
+ }
+ }
if (stateptr)
*stateptr = state;
@@ -4576,11 +4613,11 @@ PHP_FUNCTION(str_getcsv)
char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
int str_len = 0, delim_len = 0, enc_len = 0, esc_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss", &str, &str_len, &delim_str, &delim_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss", &str, &str_len, &delim_str, &delim_len,
&enc_str, &enc_len, &esc_str, &esc_len) == FAILURE) {
return;
}
-
+
delim = delim_len ? delim_str[0] : delim;
enc = enc_len ? enc_str[0] : enc;
esc = esc_len ? esc_str[0] : esc;
@@ -4598,7 +4635,7 @@ PHP_FUNCTION(str_repeat)
long mult; /* Multiplier */
char *result; /* Resulting string */
size_t result_len; /* Length of the resulting string */
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &input_str, &input_len, &mult) == FAILURE) {
return;
}
@@ -4613,13 +4650,13 @@ PHP_FUNCTION(str_repeat)
if (input_len == 0 || mult == 0)
RETURN_EMPTY_STRING();
- /* Initialize the result string */
+ /* Initialize the result string */
result_len = input_len * mult;
result = (char *)safe_emalloc(input_len, mult, 1);
-
+
/* Heavy optimization for situations where input string is 1 byte long */
if (input_len == 1) {
- memset(result, *(input_str), mult);
+ memset(result, *(input_str), mult);
} else {
char *s, *e, *ee;
int l=0;
@@ -4627,7 +4664,7 @@ PHP_FUNCTION(str_repeat)
s = result;
e = result + input_len;
ee = result + result_len;
-
+
while (e<ee) {
l = (e-s) < (ee-e) ? (e-s) : (ee-e);
memmove(e, s, l);
@@ -4636,7 +4673,7 @@ PHP_FUNCTION(str_repeat)
}
result[result_len] = '\0';
-
+
RETURN_STRINGL(result, result_len, 0);
}
/* }}} */
@@ -4702,7 +4739,7 @@ PHP_FUNCTION(count_chars)
break;
}
}
-
+
if (mymode >= 3 && mymode <= 4) {
RETURN_STRINGL(retstr, retlen, 1);
}
@@ -4726,6 +4763,49 @@ static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
}
/* }}} */
+PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */
+{
+ zval op1_copy, op2_copy;
+ int use_copy1 = 0, use_copy2 = 0;
+
+ if (Z_TYPE_P(op1) != IS_STRING) {
+ zend_make_printable_zval(op1, &op1_copy, &use_copy1);
+ }
+ if (Z_TYPE_P(op2) != IS_STRING) {
+ zend_make_printable_zval(op2, &op2_copy, &use_copy2);
+ }
+
+ if (use_copy1) {
+ op1 = &op1_copy;
+ }
+ if (use_copy2) {
+ op2 = &op2_copy;
+ }
+
+ ZVAL_LONG(result, strnatcmp_ex(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2), case_insensitive));
+
+ if (use_copy1) {
+ zval_dtor(op1);
+ }
+ if (use_copy2) {
+ zval_dtor(op2);
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+PHPAPI int string_natural_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ return string_natural_compare_function_ex(result, op1, op2, 1 TSRMLS_CC);
+}
+/* }}} */
+
+PHPAPI int string_natural_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
+{
+ return string_natural_compare_function_ex(result, op1, op2, 0 TSRMLS_CC);
+}
+/* }}} */
+
/* {{{ proto int strnatcmp(string s1, string s2)
Returns the result of string comparison using 'natural' algorithm */
PHP_FUNCTION(strnatcmp)
@@ -4758,7 +4838,7 @@ PHP_FUNCTION(localeconv)
struct lconv currlocdata;
localeconv_r( &currlocdata );
-
+
/* Grab the grouping data out of the array */
len = strlen(currlocdata.grouping);
@@ -4847,18 +4927,18 @@ PHP_FUNCTION(substr_count)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring");
RETURN_FALSE;
}
-
+
p = haystack;
endp = p + haystack_len;
if (offset < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset should be greater than or equal to 0");
- RETURN_FALSE;
+ RETURN_FALSE;
}
if (offset > haystack_len) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset value %ld exceeds string length", offset);
- RETURN_FALSE;
+ RETURN_FALSE;
}
p += offset;
@@ -4866,7 +4946,7 @@ PHP_FUNCTION(substr_count)
if (length <= 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length should be greater than 0");
- RETURN_FALSE;
+ RETURN_FALSE;
}
if (length > (haystack_len - offset)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length value %ld exceeds string length", length);
@@ -4874,7 +4954,7 @@ PHP_FUNCTION(substr_count)
}
endp = p + length;
}
-
+
if (needle_len == 1) {
cmp = needle[0];
@@ -4891,7 +4971,7 @@ PHP_FUNCTION(substr_count)
RETURN_LONG(count);
}
-/* }}} */
+/* }}} */
/* {{{ proto string str_pad(string input, int pad_length [, string pad_string [, int pad_type]])
Returns input string padded on the left or right to specified length with pad_string */
@@ -4901,7 +4981,7 @@ PHP_FUNCTION(str_pad)
char *input; /* Input string */
int input_len;
long pad_length; /* Length to pad to */
-
+
/* Helper variables */
size_t num_pad_chars; /* Number of padding characters (total - input size) */
char *result = NULL; /* Resulting string */
@@ -4926,7 +5006,7 @@ PHP_FUNCTION(str_pad)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding string cannot be empty");
return;
}
-
+
if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
return;
@@ -4935,7 +5015,7 @@ PHP_FUNCTION(str_pad)
num_pad_chars = pad_length - input_len;
if (num_pad_chars >= INT_MAX) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding length is too long");
- return;
+ return;
}
result = (char *)emalloc(input_len + num_pad_chars + 1);
@@ -4974,7 +5054,7 @@ PHP_FUNCTION(str_pad)
RETURN_STRINGL(result, result_len, 0);
}
/* }}} */
-
+
/* {{{ proto mixed sscanf(string str, string format [, string ...])
Implements an ANSI C compatible sscanf */
PHP_FUNCTION(sscanf)
@@ -4983,13 +5063,13 @@ PHP_FUNCTION(sscanf)
char *str, *format;
int str_len, format_len, result, num_args = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss*", &str, &str_len, &format, &format_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss*", &str, &str_len, &format, &format_len,
&args, &num_args) == FAILURE) {
return;
}
-
+
result = php_sscanf_internal(str, format, num_args, args, 0, &return_value TSRMLS_CC);
-
+
if (args) {
efree(args);
}
@@ -5027,13 +5107,13 @@ static void php_string_shuffle(char *str, long len TSRMLS_DC) /* {{{ */
/* The implementation is stolen from array_data_shuffle */
/* Thus the characteristics of the randomization are the same */
n_elems = len;
-
+
if (n_elems <= 1) {
return;
}
n_left = n_elems;
-
+
while (--n_left) {
rnd_idx = php_rand(TSRMLS_C);
RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
@@ -5058,7 +5138,7 @@ PHP_FUNCTION(str_shuffle)
}
RETVAL_STRINGL(arg, arglen, 1);
- if (Z_STRLEN_P(return_value) > 1) {
+ if (Z_STRLEN_P(return_value) > 1) {
php_string_shuffle(Z_STRVAL_P(return_value), (long) Z_STRLEN_P(return_value) TSRMLS_CC);
}
}
@@ -5070,7 +5150,7 @@ PHP_FUNCTION(str_shuffle)
found inside the string. If format of 2 is specified, then the function
will return an associated array where the position of the word is the key
and the word itself is the value.
-
+
For the purpose of this function, 'word' is defined as a locale dependent
string containing alphabetic characters, which also may contain, but not start
with "'" and "-" characters.
@@ -5107,7 +5187,7 @@ PHP_FUNCTION(str_word_count)
if (char_list) {
php_charmask((unsigned char *)char_list, char_list_len, ch TSRMLS_CC);
}
-
+
p = str;
e = str + str_len;
@@ -5138,14 +5218,14 @@ PHP_FUNCTION(str_word_count)
break;
default:
word_count++;
- break;
+ break;
}
}
p++;
}
-
+
if (!type) {
- RETURN_LONG(word_count);
+ RETURN_LONG(word_count);
}
}
@@ -5169,7 +5249,7 @@ PHP_FUNCTION(money_format)
e = p + format_len;
while ((p = memchr(p, '%', (e - p)))) {
if (*(p + 1) == '%') {
- p += 2;
+ p += 2;
} else if (!check) {
check = 1;
p++;
@@ -5201,7 +5281,7 @@ PHP_FUNCTION(str_split)
long split_length = 1;
char *p;
int n_reg_segments;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &split_length) == FAILURE) {
return;
}
@@ -5239,14 +5319,14 @@ PHP_FUNCTION(strpbrk)
char *haystack, *char_list;
int haystack_len, char_list_len;
char *haystack_ptr, *cl_ptr;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &haystack, &haystack_len, &char_list, &char_list_len) == FAILURE) {
RETURN_FALSE;
}
if (!char_list_len) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The character list cannot be empty");
- RETURN_FALSE;
+ RETURN_FALSE;
}
for (haystack_ptr = haystack; haystack_ptr < (haystack + haystack_len); ++haystack_ptr) {
@@ -5290,10 +5370,6 @@ PHP_FUNCTION(substr_compare)
RETURN_FALSE;
}
- if (len > s1_len - offset) {
- len = s1_len - offset;
- }
-
cmp_len = (uint) (len ? len : MAX(s2_len, (s1_len - offset)));
if (!cs) {
diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c
index 582074532b..7a83320e27 100644
--- a/ext/standard/syslog.c
+++ b/ext/standard/syslog.c
@@ -36,8 +36,6 @@
#include "basic_functions.h"
#include "php_ext_syslog.h"
-static void start_syslog(TSRMLS_D);
-
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(syslog)
@@ -105,11 +103,6 @@ PHP_MINIT_FUNCTION(syslog)
PHP_RINIT_FUNCTION(syslog)
{
- if (INI_INT("define_syslog_variables")) {
- start_syslog(TSRMLS_C);
- } else {
- BG(syslog_started)=0;
- }
BG(syslog_device) = NULL;
return SUCCESS;
}
@@ -132,87 +125,6 @@ PHP_MSHUTDOWN_FUNCTION(syslog)
return SUCCESS;
}
-/* {{{ start_syslog
- */
-static void start_syslog(TSRMLS_D)
-{
- /* error levels */
- SET_VAR_LONG("LOG_EMERG", LOG_EMERG); /* system unusable */
- SET_VAR_LONG("LOG_ALERT", LOG_ALERT); /* immediate action required */
- SET_VAR_LONG("LOG_CRIT", LOG_CRIT); /* critical conditions */
- SET_VAR_LONG("LOG_ERR", LOG_ERR);
- SET_VAR_LONG("LOG_WARNING", LOG_WARNING);
- SET_VAR_LONG("LOG_NOTICE", LOG_NOTICE);
- SET_VAR_LONG("LOG_INFO", LOG_INFO);
- SET_VAR_LONG("LOG_DEBUG", LOG_DEBUG);
- /* facility: type of program logging the message */
- SET_VAR_LONG("LOG_KERN", LOG_KERN);
- SET_VAR_LONG("LOG_USER", LOG_USER); /* generic user level */
- SET_VAR_LONG("LOG_MAIL", LOG_MAIL); /* log to email */
- SET_VAR_LONG("LOG_DAEMON", LOG_DAEMON); /* other system daemons */
- SET_VAR_LONG("LOG_AUTH", LOG_AUTH);
-#ifndef NETWARE
- SET_VAR_LONG("LOG_SYSLOG", LOG_SYSLOG);
-#endif
- SET_VAR_LONG("LOG_LPR", LOG_LPR);
-#ifdef LOG_NEWS
- /* No LOG_NEWS on HP-UX */
- SET_VAR_LONG("LOG_NEWS", LOG_NEWS); /* usenet new */
-#endif
-#ifdef LOG_UUCP
- /* No LOG_UUCP on HP-UX */
- SET_VAR_LONG("LOG_UUCP", LOG_UUCP);
-#endif
-#ifdef LOG_CRON
- /* apparently some systems don't have this one */
- SET_VAR_LONG("LOG_CRON", LOG_CRON);
-#endif
-#ifdef LOG_AUTHPRIV
- /* AIX doesn't have LOG_AUTHPRIV */
- SET_VAR_LONG("LOG_AUTHPRIV", LOG_AUTHPRIV);
-#endif
-#if !defined(PHP_WIN32) && !defined(NETWARE)
- SET_VAR_LONG("LOG_LOCAL0", LOG_LOCAL0);
- SET_VAR_LONG("LOG_LOCAL1", LOG_LOCAL1);
- SET_VAR_LONG("LOG_LOCAL2", LOG_LOCAL2);
- SET_VAR_LONG("LOG_LOCAL3", LOG_LOCAL3);
- SET_VAR_LONG("LOG_LOCAL4", LOG_LOCAL4);
- SET_VAR_LONG("LOG_LOCAL5", LOG_LOCAL5);
- SET_VAR_LONG("LOG_LOCAL6", LOG_LOCAL6);
- SET_VAR_LONG("LOG_LOCAL7", LOG_LOCAL7);
-#endif
- /* options */
- SET_VAR_LONG("LOG_PID", LOG_PID);
- SET_VAR_LONG("LOG_CONS", LOG_CONS);
- SET_VAR_LONG("LOG_ODELAY", LOG_ODELAY);
- SET_VAR_LONG("LOG_NDELAY", LOG_NDELAY);
-#ifdef LOG_NOWAIT
- /* BeOS doesn't have LOG_NOWAIT */
- SET_VAR_LONG("LOG_NOWAIT", LOG_NOWAIT);
-#endif
-#ifdef LOG_PERROR
- /* AIX doesn't have LOG_PERROR */
- SET_VAR_LONG("LOG_PERROR", LOG_PERROR); /*log to stderr*/
-#endif
-
- BG(syslog_started)=1;
-}
-/* }}} */
-
-/* {{{ proto void define_syslog_variables(void)
- Initializes all syslog-related variables */
-PHP_FUNCTION(define_syslog_variables)
-{
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- if (!BG(syslog_started)) {
- start_syslog(TSRMLS_C);
- }
-}
-/* }}} */
-
/* {{{ proto bool openlog(string ident, int option, int facility)
Open connection to system logger */
/*
@@ -234,6 +146,9 @@ PHP_FUNCTION(openlog)
free(BG(syslog_device));
}
BG(syslog_device) = zend_strndup(ident, ident_len);
+ if(BG(syslog_device) == NULL) {
+ RETURN_FALSE;
+ }
openlog(BG(syslog_device), option, facility);
RETURN_TRUE;
}
diff --git a/ext/standard/tests/array/002.phpt b/ext/standard/tests/array/002.phpt
index b865dc100c..469e862675 100644
--- a/ext/standard/tests/array/002.phpt
+++ b/ext/standard/tests/array/002.phpt
@@ -129,6 +129,16 @@ array(8) {
float(-0.33333333333333)
}
Using SORT_STRING
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
array(8) {
[1000]=>
string(4) "test"
@@ -227,6 +237,16 @@ array(8) {
int(27)
}
Using SORT_STRING
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
array(8) {
[16777216]=>
float(-0.33333333333333)
@@ -521,6 +541,16 @@ array(8) {
float(-0.33333333333333)
}
Using SORT_STRING
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
array(8) {
[0]=>
string(4) "test"
@@ -619,6 +649,16 @@ array(8) {
int(27)
}
Using SORT_STRING
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
+
+Notice: Array to string conversion in %s002.php on line %d
array(8) {
[0]=>
float(-0.33333333333333)
diff --git a/ext/standard/tests/array/array_change_key_case_variation7.phpt b/ext/standard/tests/array/array_change_key_case_variation7.phpt
index cdae8c7e05..8cbc23a12f 100644
--- a/ext/standard/tests/array/array_change_key_case_variation7.phpt
+++ b/ext/standard/tests/array/array_change_key_case_variation7.phpt
@@ -1,7 +1,5 @@
--TEST--
Test array_change_key_case() function : usage variations - referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : array array_change_key_case(array $input [, int $case])
@@ -28,12 +26,6 @@ var_dump($input);
echo "Referenced:\n";
var_dump($new_input);
-echo "\n-- \$input is an array passed by reference --\n";
-echo "Result:\n";
-var_dump(array_change_key_case(&$input, CASE_UPPER));
-echo "Original:\n";
-var_dump($input);
-
echo "Done";
?>
@@ -68,25 +60,5 @@ array(3) {
["ABC"]=>
string(3) "xyz"
}
-
--- $input is an array passed by reference --
-Result:
-array(3) {
- ["ONE"]=>
- int(1)
- ["TWO"]=>
- int(2)
- ["ABC"]=>
- string(3) "xyz"
-}
-Original:
-array(3) {
- ["one"]=>
- int(1)
- ["two"]=>
- int(2)
- ["ABC"]=>
- string(3) "xyz"
-}
Done
diff --git a/ext/standard/tests/array/array_change_key_case_variation8.phpt b/ext/standard/tests/array/array_change_key_case_variation8.phpt
index 3dc22ce0e0..361480008a 100644
--- a/ext/standard/tests/array/array_change_key_case_variation8.phpt
+++ b/ext/standard/tests/array/array_change_key_case_variation8.phpt
@@ -47,7 +47,7 @@ array(10) {
int(3)
["\cx"]=>
int(4)
- ["\e"]=>
+ [""]=>
int(5)
[" "]=>
int(6)
@@ -71,7 +71,7 @@ array(10) {
int(3)
["\CX"]=>
int(4)
- ["\E"]=>
+ [""]=>
int(5)
[" "]=>
int(6)
@@ -130,4 +130,4 @@ array(9) {
["X"]=>
int(10)
}
-Done \ No newline at end of file
+Done
diff --git a/ext/standard/tests/array/array_combine_error2.phpt b/ext/standard/tests/array/array_combine_error2.phpt
index c06fdb490a..4224f1c8eb 100644
--- a/ext/standard/tests/array/array_combine_error2.phpt
+++ b/ext/standard/tests/array/array_combine_error2.phpt
@@ -32,9 +32,8 @@ echo "Done";
*** Testing array_combine() : error conditions specific to array_combine() ***
-- Testing array_combine() function with empty arrays --
-
-Warning: array_combine(): Both parameters should have at least 1 element in %s on line %d
-bool(false)
+array(0) {
+}
-- Testing array_combine() function with empty array for $keys argument --
diff --git a/ext/standard/tests/array/array_combine_variation3.phpt b/ext/standard/tests/array/array_combine_variation3.phpt
index 51d8462d51..03de632905 100644
--- a/ext/standard/tests/array/array_combine_variation3.phpt
+++ b/ext/standard/tests/array/array_combine_variation3.phpt
@@ -108,9 +108,8 @@ array(2) {
bool(true)
}
-- Iteration 4 --
-
-Warning: array_combine(): Both parameters should have at least 1 element in %s on line %d
-bool(false)
+array(0) {
+}
-- Iteration 5 --
array(1) {
[""]=>
diff --git a/ext/standard/tests/array/array_combine_variation4.phpt b/ext/standard/tests/array/array_combine_variation4.phpt
index 02ec6efd22..bcd8428cee 100644
--- a/ext/standard/tests/array/array_combine_variation4.phpt
+++ b/ext/standard/tests/array/array_combine_variation4.phpt
@@ -100,9 +100,8 @@ Warning: Illegal offset type in %s on line %d
Warning: Illegal offset type in %s on line %d
-- Iteration 1 --
-
-Warning: array_combine(): Both parameters should have at least 1 element in %s on line %d
-bool(false)
+array(0) {
+}
-- Iteration 2 --
array(1) {
[0]=>
diff --git a/ext/standard/tests/array/array_combine_variation5.phpt b/ext/standard/tests/array/array_combine_variation5.phpt
index c3d1d57aac..4d9f185786 100644
--- a/ext/standard/tests/array/array_combine_variation5.phpt
+++ b/ext/standard/tests/array/array_combine_variation5.phpt
@@ -82,9 +82,8 @@ echo "Done";
--EXPECTF--
*** Testing array_combine() : assoc array with diff values to both $keys and $values argument ***
-- Iteration 1 --
-
-Warning: array_combine(): Both parameters should have at least 1 element in %s on line %d
-bool(false)
+array(0) {
+}
-- Iteration 2 --
array(1) {
[0]=>
diff --git a/ext/standard/tests/array/array_diff_variation9.phpt b/ext/standard/tests/array/array_diff_variation9.phpt
index 58d9c201ba..1bf1f1c2ac 100644
--- a/ext/standard/tests/array/array_diff_variation9.phpt
+++ b/ext/standard/tests/array/array_diff_variation9.phpt
@@ -39,8 +39,40 @@ echo "Done";
--EXPECTF--
*** Testing array_diff() : usage variations ***
-- Compare two 2-D arrays --
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
array(0) {
}
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
array(0) {
}
@@ -69,6 +101,16 @@ array(3) {
}
-- Compare a subarray from one 2-D array and one 2-D array --
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
array(3) {
[0]=>
int(1)
@@ -77,6 +119,20 @@ array(3) {
[2]=>
int(3)
}
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_diff_variation9.php on line %d
array(2) {
["sub_array1"]=>
array(3) {
diff --git a/ext/standard/tests/array/array_fill_object.phpt b/ext/standard/tests/array/array_fill_object.phpt
index 48aac60b55..86773b17f8 100644
--- a/ext/standard/tests/array/array_fill_object.phpt
+++ b/ext/standard/tests/array/array_fill_object.phpt
@@ -1,5 +1,7 @@
--TEST--
Test array_fill() function : usage variations - various object values for 'val' argument
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
--FILE--
<?php
/* Prototype : array array_fill(int $start_key, int $num, mixed $val)
diff --git a/ext/standard/tests/array/array_fill_object_2_4.phpt b/ext/standard/tests/array/array_fill_object_2_4.phpt
new file mode 100644
index 0000000000..fb8179766c
--- /dev/null
+++ b/ext/standard/tests/array/array_fill_object_2_4.phpt
@@ -0,0 +1,434 @@
+--TEST--
+Test array_fill() function : usage variations - various object values for 'val' argument
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+/* Prototype : array array_fill(int $start_key, int $num, mixed $val)
+ * Description: Create an array containing num elements starting with index start_key each initialized to val
+ * Source code: ext/standard/array.c
+ */
+
+/*
+ * testing array_fill() by passing various object values for 'val' argument
+ */
+
+echo "*** Testing array_fill() : usage variations ***\n";
+
+// Initialise function arguments not being substituted
+$start_key = 0;
+$num = 2;
+
+// class without a member
+class Test
+{
+}
+
+//class with public member, static member , constant and consturctor to initialize the public member
+class Test1
+{
+ const test1_constant = "test1";
+ public static $test1_static = 0;
+ public $member1;
+ var $var1 = 30;
+ var $var2;
+
+ function __construct($value1 , $value2)
+ {
+ $this->member1 = $value1;
+ $this->var2 = $value2;
+ }
+}
+
+// child class which inherits parent class test1
+class Child_test1 extends Test1
+{
+ public $member2;
+
+ function __construct($value1 , $value2 , $value3)
+ {
+ parent::__construct($value1 , $value2);
+ $this->member2 = $value3;
+ }
+}
+
+//class with private member, static member, constant and constructor to initialize the private member
+class Test2
+{
+ const test2_constant = "test2";
+ public static $test2_static = 0;
+ private $member1;
+ var $var1 = 30;
+ var $var2;
+
+ function __construct($value1 , $value2)
+ {
+ $this->member1 = $value1;
+ $this->var2 = $value2;
+ }
+}
+
+// child class which inherits parent class test2
+class Child_test2 extends Test2
+{
+ private $member1;
+
+ function __construct($value1 , $value2 , $value3)
+ {
+ parent::__construct($value1 , $value2);
+ $this->member1 = $value3;
+ }
+}
+
+// class with protected member, static member, constant and consturctor to initialize the protected member
+class Test3
+{
+ const test3_constant = "test3";
+ public static $test3_static = 0;
+ protected $member1;
+ var $var1 = 30;
+ var $var2;
+
+ function __construct($value1 , $value2)
+ {
+ $this->member1 = $value1;
+ $this->var2 = $value2;
+ }
+}
+
+// child class which inherits parent class test3
+class Child_test3 extends Test3
+{
+ protected $member1;
+
+ function __construct($value1 , $value2 , $value3)
+ {
+ parent::__construct($value1 , $value2);
+ $this->member1 = $value3;
+ }
+}
+
+// class with public, private, protected members, static, constant members and constructor to initialize all the members
+class Test4
+{
+ const test4_constant = "test4";
+ public static $test4_static = 0;
+ public $member1;
+ private $member2;
+ protected $member3;
+
+ function __construct($value1 , $value2 , $value3)
+ {
+ $this->member1 = $value1;
+ $this->member2 = $value2;
+ $this->member3 = $value3;
+ }
+}
+
+// child class which inherits parent class test4
+class Child_test4 extends Test4
+{
+ var $var1;
+
+ function __construct($value1 , $value2 , $value3 , $value4)
+ {
+ parent::__construct($value1 , $value2 , $value3);
+ $this->var1 = $value4;
+ }
+}
+
+// abstract class with public, private, protected members
+abstract class AbstractClass
+{
+ public $member1;
+ private $member2;
+ protected $member3;
+ var $var1 = 30;
+
+ abstract protected function display();
+}
+
+// implement abstract 'AbstractClass' class
+class ConcreteClass1 extends AbstractClass
+{
+ protected function display()
+ {
+ echo "class name is ConcreteClass1 \n";
+ }
+}
+
+
+// declarationn of the interface 'iTemplate'
+interface iTemplate
+{
+ public function display();
+}
+
+// implement the interface 'iTemplate'
+class Template1 implements iTemplate
+{
+ public function display()
+ {
+ echo "class name is Template1\n";
+ }
+}
+
+//array of object values for 'val' argument
+$objects = array(
+
+ /* 1 */ new Test(),
+ new Test1(100 , 101),
+ new Child_test1(100 , 101 , 102),
+ new Test2(100 , 101),
+ /* 5 */ new Child_test2(100 , 101 , 102),
+ new Test3(100 , 101),
+ new Child_test3(100 , 101 , 102),
+ new Test4( 100 , 101 , 102),
+ new Child_test4(100 , 101 , 102 , 103),
+ new ConcreteClass1(),
+ /* 11 */ new Template1()
+);
+
+// loop through each element of the array for 'val' argument
+// check the working of array_fill()
+echo "--- Testing array_fill() with different object values for 'val' argument ---\n";
+$counter = 1;
+for($index = 0; $index < count($objects); $index ++)
+{
+ echo "-- Iteration $counter --\n";
+ $val = $objects[$index];
+
+ var_dump( array_fill($start_key,$num,$val) );
+
+ $counter++;
+}
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing array_fill() : usage variations ***
+--- Testing array_fill() with different object values for 'val' argument ---
+-- Iteration 1 --
+array(2) {
+ [0]=>
+ object(Test)#%d (0) {
+ }
+ [1]=>
+ object(Test)#%d (0) {
+ }
+}
+-- Iteration 2 --
+array(2) {
+ [0]=>
+ object(Test1)#%d (3) {
+ ["member1"]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+ [1]=>
+ object(Test1)#%d (3) {
+ ["member1"]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+}
+-- Iteration 3 --
+array(2) {
+ [0]=>
+ object(Child_test1)#%d (4) {
+ ["member2"]=>
+ int(102)
+ ["member1"]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+ [1]=>
+ object(Child_test1)#%d (4) {
+ ["member2"]=>
+ int(102)
+ ["member1"]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+}
+-- Iteration 4 --
+array(2) {
+ [0]=>
+ object(Test2)#%d (3) {
+ ["member1":"Test2":private]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+ [1]=>
+ object(Test2)#%d (3) {
+ ["member1":"Test2":private]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+}
+-- Iteration 5 --
+array(2) {
+ [0]=>
+ object(Child_test2)#%d (4) {
+ ["member1":"Child_test2":private]=>
+ int(102)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ ["member1":"Test2":private]=>
+ int(100)
+ }
+ [1]=>
+ object(Child_test2)#%d (4) {
+ ["member1":"Child_test2":private]=>
+ int(102)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ ["member1":"Test2":private]=>
+ int(100)
+ }
+}
+-- Iteration 6 --
+array(2) {
+ [0]=>
+ object(Test3)#%d (3) {
+ ["member1":protected]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+ [1]=>
+ object(Test3)#%d (3) {
+ ["member1":protected]=>
+ int(100)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+}
+-- Iteration 7 --
+array(2) {
+ [0]=>
+ object(Child_test3)#%d (3) {
+ ["member1":protected]=>
+ int(102)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+ [1]=>
+ object(Child_test3)#%d (3) {
+ ["member1":protected]=>
+ int(102)
+ ["var1"]=>
+ int(30)
+ ["var2"]=>
+ int(101)
+ }
+}
+-- Iteration 8 --
+array(2) {
+ [0]=>
+ object(Test4)#%d (3) {
+ ["member1"]=>
+ int(100)
+ ["member2":"Test4":private]=>
+ int(101)
+ ["member3":protected]=>
+ int(102)
+ }
+ [1]=>
+ object(Test4)#%d (3) {
+ ["member1"]=>
+ int(100)
+ ["member2":"Test4":private]=>
+ int(101)
+ ["member3":protected]=>
+ int(102)
+ }
+}
+-- Iteration 9 --
+array(2) {
+ [0]=>
+ object(Child_test4)#%d (4) {
+ ["var1"]=>
+ int(103)
+ ["member1"]=>
+ int(100)
+ ["member2":"Test4":private]=>
+ int(101)
+ ["member3":protected]=>
+ int(102)
+ }
+ [1]=>
+ object(Child_test4)#%d (4) {
+ ["var1"]=>
+ int(103)
+ ["member1"]=>
+ int(100)
+ ["member2":"Test4":private]=>
+ int(101)
+ ["member3":protected]=>
+ int(102)
+ }
+}
+-- Iteration 10 --
+array(2) {
+ [0]=>
+ object(ConcreteClass1)#%d (4) {
+ ["member1"]=>
+ NULL
+ ["member2":"AbstractClass":private]=>
+ NULL
+ ["member3":protected]=>
+ NULL
+ ["var1"]=>
+ int(30)
+ }
+ [1]=>
+ object(ConcreteClass1)#%d (4) {
+ ["member1"]=>
+ NULL
+ ["member2":"AbstractClass":private]=>
+ NULL
+ ["member3":protected]=>
+ NULL
+ ["var1"]=>
+ int(30)
+ }
+}
+-- Iteration 11 --
+array(2) {
+ [0]=>
+ object(Template1)#%d (0) {
+ }
+ [1]=>
+ object(Template1)#%d (0) {
+ }
+}
+Done
diff --git a/ext/standard/tests/array/array_intersect_assoc_variation9.phpt b/ext/standard/tests/array/array_intersect_assoc_variation9.phpt
index 456109b1c2..338d40936e 100644
--- a/ext/standard/tests/array/array_intersect_assoc_variation9.phpt
+++ b/ext/standard/tests/array/array_intersect_assoc_variation9.phpt
@@ -61,6 +61,14 @@ echo "Done";
*** Testing array_intersect_assoc() : passing two dimensional array to both $arr1 and $arr2 arguments ***
-- Passing the entire 2-D array to $arr1 and $arr2 --
- With default arguments -
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
array(2) {
[0]=>
array(4) {
@@ -86,6 +94,22 @@ array(2) {
}
}
- With more arguments -
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_assoc_variation9.php on line %d
array(2) {
[0]=>
array(4) {
diff --git a/ext/standard/tests/array/array_intersect_variation9.phpt b/ext/standard/tests/array/array_intersect_variation9.phpt
index d3525dcd06..fda63dd628 100644
--- a/ext/standard/tests/array/array_intersect_variation9.phpt
+++ b/ext/standard/tests/array/array_intersect_variation9.phpt
@@ -60,6 +60,42 @@ echo "Done";
*** Testing array_intersect() : passing two dimensional array to both $arr1 and $arr2 arguments ***
-- Passing the entire 2-D array to $arr1 and $arr2 --
- With default arguments -
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
array(4) {
[0]=>
array(4) {
@@ -103,6 +139,62 @@ array(4) {
}
}
- With more arguments -
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
+
+Notice: Array to string conversion in %sarray_intersect_variation9.php on line %d
array(4) {
[0]=>
array(4) {
diff --git a/ext/standard/tests/array/array_key_exists_variation4.phpt b/ext/standard/tests/array/array_key_exists_variation4.phpt
index edc39269a5..84dfeb9373 100644
--- a/ext/standard/tests/array/array_key_exists_variation4.phpt
+++ b/ext/standard/tests/array/array_key_exists_variation4.phpt
@@ -1,7 +1,5 @@
--TEST--
Test array_key_exists() function : usage variations - referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : bool array_key_exists(mixed $key, array $search)
@@ -22,13 +20,6 @@ echo "\n-- \$search is a reference to \$array --\n";
$search = &$array;
var_dump(array_key_exists('one', $search));
-echo "\n-- \$key is a referenced variable --\n";
-$key = 'two';
-var_dump(array_key_exists(&$key, $array));
-
-echo "\n-- Both arguments are referenced variables --\n";
-var_dump(array_key_exists(&$key, &$array));
-
echo "Done";
?>
@@ -37,10 +28,4 @@ echo "Done";
-- $search is a reference to $array --
bool(true)
-
--- $key is a referenced variable --
-bool(true)
-
--- Both arguments are referenced variables --
-bool(true)
Done
diff --git a/ext/standard/tests/array/array_map_variation19.phpt b/ext/standard/tests/array/array_map_variation19.phpt
index 9478f70eff..0e56428a03 100644
--- a/ext/standard/tests/array/array_map_variation19.phpt
+++ b/ext/standard/tests/array/array_map_variation19.phpt
@@ -34,7 +34,7 @@ array(2) {
}
array(2) {
[0]=>
- &string(7) "changed"
+ &string(10) "original.0"
[1]=>
string(10) "original.1"
} \ No newline at end of file
diff --git a/ext/standard/tests/array/array_merge_variation9.phpt b/ext/standard/tests/array/array_merge_variation9.phpt
index e42e292827..69e0401a0e 100644
--- a/ext/standard/tests/array/array_merge_variation9.phpt
+++ b/ext/standard/tests/array/array_merge_variation9.phpt
@@ -1,7 +1,5 @@
--TEST--
Test array_merge() function : usage variations - referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : array array_merge(array $arr1, array $arr2 [, array $...])
@@ -33,9 +31,6 @@ echo "\n-- Change \$val2 --\n";
var_dump(array_merge($arr1, $arr2));
var_dump(array_merge($arr2, $arr1));
-echo "\n-- Merge an array and a reference to the first array --\n";
-var_dump(array_merge($arr2, &$arr2));
-
echo "Done";
?>
@@ -101,14 +96,4 @@ array(6) {
[2]=>
&string(3) "baz"
}
-
--- Merge an array and a reference to the first array --
-array(3) {
- ["key1"]=>
- string(4) "val1"
- ["key2"]=>
- string(4) "val2"
- ["key3"]=>
- string(4) "val3"
-}
Done
diff --git a/ext/standard/tests/array/array_multisort_basic1.phpt b/ext/standard/tests/array/array_multisort_basic1.phpt
index af5f8df4f3..ab7db94463 100644
--- a/ext/standard/tests/array/array_multisort_basic1.phpt
+++ b/ext/standard/tests/array/array_multisort_basic1.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : basic functionality
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_basic2.phpt b/ext/standard/tests/array/array_multisort_basic2.phpt
index d2c7ac20b7..4a46072e65 100644
--- a/ext/standard/tests/array/array_multisort_basic2.phpt
+++ b/ext/standard/tests/array/array_multisort_basic2.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : basic functionality
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_case.phpt b/ext/standard/tests/array/array_multisort_case.phpt
new file mode 100644
index 0000000000..6be42edf57
--- /dev/null
+++ b/ext/standard/tests/array/array_multisort_case.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Test array_multisort() function : case-sensitive
+--FILE--
+<?php
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE], ...])
+ * Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
+ * Source code: ext/standard/array.c
+ * Alias to functions:
+ */
+
+echo "*** Testing array_multisort() : case-sensitive\n";
+
+$a = array(
+ 'Second',
+ 'First.1',
+ 'First.2',
+ 'First.3',
+ 'Twentieth',
+ 'Tenth',
+ 'Third',
+);
+
+$b = array(
+ '2 a',
+ '1 bb 1',
+ '1 bB 2',
+ '1 BB 3',
+ '20 c',
+ '10 d',
+ '3 e',
+);
+
+array_multisort($b, SORT_STRING, $a);
+
+var_dump($a, $b);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing array_multisort() : case-sensitive
+array(7) {
+ [0]=>
+ string(7) "First.3"
+ [1]=>
+ string(7) "First.2"
+ [2]=>
+ string(7) "First.1"
+ [3]=>
+ string(5) "Tenth"
+ [4]=>
+ string(6) "Second"
+ [5]=>
+ string(9) "Twentieth"
+ [6]=>
+ string(5) "Third"
+}
+array(7) {
+ [0]=>
+ string(6) "1 BB 3"
+ [1]=>
+ string(6) "1 bB 2"
+ [2]=>
+ string(6) "1 bb 1"
+ [3]=>
+ string(4) "10 d"
+ [4]=>
+ string(3) "2 a"
+ [5]=>
+ string(4) "20 c"
+ [6]=>
+ string(3) "3 e"
+}
+===DONE===
diff --git a/ext/standard/tests/array/array_multisort_error.phpt b/ext/standard/tests/array/array_multisort_error.phpt
index 7cd95ec169..5956630f84 100644
--- a/ext/standard/tests/array/array_multisort_error.phpt
+++ b/ext/standard/tests/array/array_multisort_error.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : error conditions
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_incase.phpt b/ext/standard/tests/array/array_multisort_incase.phpt
new file mode 100644
index 0000000000..951cce4927
--- /dev/null
+++ b/ext/standard/tests/array/array_multisort_incase.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Test array_multisort() function : case-insensitive
+--FILE--
+<?php
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE], ...])
+ * Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
+ * Source code: ext/standard/array.c
+ * Alias to functions:
+ */
+
+echo "*** Testing array_multisort() : case-insensitive\n";
+
+$a = array(
+ 'Second',
+ 'First.1',
+ 'First.2',
+ 'First.3',
+ 'Twentieth',
+ 'Tenth',
+ 'Third',
+);
+
+$b = array(
+ '2 a',
+ '1 bb 1',
+ '1 bB 2',
+ '1 BB 3',
+ '20 c',
+ '10 d',
+ '3 e',
+);
+
+array_multisort($b, SORT_STRING | SORT_FLAG_CASE, $a);
+
+var_dump($a, $b);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing array_multisort() : case-insensitive
+array(7) {
+ [0]=>
+ string(7) "First.1"
+ [1]=>
+ string(7) "First.2"
+ [2]=>
+ string(7) "First.3"
+ [3]=>
+ string(5) "Tenth"
+ [4]=>
+ string(6) "Second"
+ [5]=>
+ string(9) "Twentieth"
+ [6]=>
+ string(5) "Third"
+}
+array(7) {
+ [0]=>
+ string(6) "1 bb 1"
+ [1]=>
+ string(6) "1 bB 2"
+ [2]=>
+ string(6) "1 BB 3"
+ [3]=>
+ string(4) "10 d"
+ [4]=>
+ string(3) "2 a"
+ [5]=>
+ string(4) "20 c"
+ [6]=>
+ string(3) "3 e"
+}
+===DONE===
diff --git a/ext/standard/tests/array/array_multisort_natural.phpt b/ext/standard/tests/array/array_multisort_natural.phpt
new file mode 100644
index 0000000000..e7910882e4
--- /dev/null
+++ b/ext/standard/tests/array/array_multisort_natural.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Test array_multisort() function : natural sorting
+--FILE--
+<?php
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE], ...])
+ * Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
+ * Source code: ext/standard/array.c
+ * Alias to functions:
+ */
+
+echo "*** Testing array_multisort() : natural sorting\n";
+
+$a = array(
+ 'Second',
+ 'First',
+ 'Twentieth',
+ 'Tenth',
+ 'Third',
+);
+
+$b = array(
+ '2 a',
+ '1 b',
+ '20 c',
+ '10 d',
+ '3 e',
+);
+
+array_multisort($b, SORT_NATURAL, $a);
+
+var_dump($a, $b);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing array_multisort() : natural sorting
+array(5) {
+ [0]=>
+ string(5) "First"
+ [1]=>
+ string(6) "Second"
+ [2]=>
+ string(5) "Third"
+ [3]=>
+ string(5) "Tenth"
+ [4]=>
+ string(9) "Twentieth"
+}
+array(5) {
+ [0]=>
+ string(3) "1 b"
+ [1]=>
+ string(3) "2 a"
+ [2]=>
+ string(3) "3 e"
+ [3]=>
+ string(4) "10 d"
+ [4]=>
+ string(4) "20 c"
+}
+===DONE===
diff --git a/ext/standard/tests/array/array_multisort_natural_case.phpt b/ext/standard/tests/array/array_multisort_natural_case.phpt
new file mode 100644
index 0000000000..d59e4931b6
--- /dev/null
+++ b/ext/standard/tests/array/array_multisort_natural_case.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Test array_multisort() function : natural sorting case-sensitive
+--FILE--
+<?php
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE], ...])
+ * Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
+ * Source code: ext/standard/array.c
+ * Alias to functions:
+ */
+
+echo "*** Testing array_multisort() : natural sorting case-sensitive\n";
+
+$a = array(
+ 'Second',
+ 'First.1',
+ 'First.2',
+ 'First.3',
+ 'Twentieth',
+ 'Tenth',
+ 'Third',
+);
+
+$b = array(
+ '2 a',
+ '1 bb 1',
+ '1 bB 2',
+ '1 BB 3',
+ '20 c',
+ '10 d',
+ '3 e',
+);
+
+array_multisort($b, SORT_NATURAL, $a);
+
+var_dump($a, $b);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing array_multisort() : natural sorting case-sensitive
+array(7) {
+ [0]=>
+ string(7) "First.3"
+ [1]=>
+ string(7) "First.2"
+ [2]=>
+ string(7) "First.1"
+ [3]=>
+ string(6) "Second"
+ [4]=>
+ string(5) "Third"
+ [5]=>
+ string(5) "Tenth"
+ [6]=>
+ string(9) "Twentieth"
+}
+array(7) {
+ [0]=>
+ string(6) "1 BB 3"
+ [1]=>
+ string(6) "1 bB 2"
+ [2]=>
+ string(6) "1 bb 1"
+ [3]=>
+ string(3) "2 a"
+ [4]=>
+ string(3) "3 e"
+ [5]=>
+ string(4) "10 d"
+ [6]=>
+ string(4) "20 c"
+}
+===DONE===
diff --git a/ext/standard/tests/array/array_multisort_natural_incase.phpt b/ext/standard/tests/array/array_multisort_natural_incase.phpt
new file mode 100644
index 0000000000..87514058a9
--- /dev/null
+++ b/ext/standard/tests/array/array_multisort_natural_incase.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Test array_multisort() function : natural sorting case-insensitive
+--FILE--
+<?php
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE], ...])
+ * Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
+ * Source code: ext/standard/array.c
+ * Alias to functions:
+ */
+
+echo "*** Testing array_multisort() : natural sorting case-insensitive\n";
+
+$a = array(
+ 'Second',
+ 'First.1',
+ 'First.2',
+ 'First.3',
+ 'Twentieth',
+ 'Tenth',
+ 'Third',
+);
+
+$b = array(
+ '2 a',
+ '1 bb 1',
+ '1 bB 2',
+ '1 BB 3',
+ '20 c',
+ '10 d',
+ '3 e',
+);
+
+array_multisort($b, SORT_NATURAL | SORT_FLAG_CASE, $a);
+
+var_dump($a, $b);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing array_multisort() : natural sorting case-insensitive
+array(7) {
+ [0]=>
+ string(7) "First.1"
+ [1]=>
+ string(7) "First.2"
+ [2]=>
+ string(7) "First.3"
+ [3]=>
+ string(6) "Second"
+ [4]=>
+ string(5) "Third"
+ [5]=>
+ string(5) "Tenth"
+ [6]=>
+ string(9) "Twentieth"
+}
+array(7) {
+ [0]=>
+ string(6) "1 bb 1"
+ [1]=>
+ string(6) "1 bB 2"
+ [2]=>
+ string(6) "1 BB 3"
+ [3]=>
+ string(3) "2 a"
+ [4]=>
+ string(3) "3 e"
+ [5]=>
+ string(4) "10 d"
+ [6]=>
+ string(4) "20 c"
+}
+===DONE===
diff --git a/ext/standard/tests/array/array_multisort_variation1.phpt b/ext/standard/tests/array/array_multisort_variation1.phpt
index 084addef40..93c265922e 100644
--- a/ext/standard/tests/array/array_multisort_variation1.phpt
+++ b/ext/standard/tests/array/array_multisort_variation1.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation10.phpt b/ext/standard/tests/array/array_multisort_variation10.phpt
index 4e9f4890ca..71c4494270 100644
--- a/ext/standard/tests/array/array_multisort_variation10.phpt
+++ b/ext/standard/tests/array/array_multisort_variation10.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - testing with anonymous arrary arguments
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation11.phpt b/ext/standard/tests/array/array_multisort_variation11.phpt
index 520dd3d51a..046b45f020 100644
--- a/ext/standard/tests/array/array_multisort_variation11.phpt
+++ b/ext/standard/tests/array/array_multisort_variation11.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - testing with empty array
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation2.phpt b/ext/standard/tests/array/array_multisort_variation2.phpt
index bad20188ed..86210eeb49 100644
--- a/ext/standard/tests/array/array_multisort_variation2.phpt
+++ b/ext/standard/tests/array/array_multisort_variation2.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
@@ -101,7 +101,7 @@ $inputs = array(
'unset var' => @$unset_var,
);
-// loop through each element of the array for SORT_REGULAR|SORT_NUMERIC|SORT_STRING]]
+// loop through each element of the array for SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]]
foreach($inputs as $key =>$value) {
echo "\n--$key--\n";
diff --git a/ext/standard/tests/array/array_multisort_variation3.phpt b/ext/standard/tests/array/array_multisort_variation3.phpt
index 534374c431..b2cdb05ece 100644
--- a/ext/standard/tests/array/array_multisort_variation3.phpt
+++ b/ext/standard/tests/array/array_multisort_variation3.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation4.phpt b/ext/standard/tests/array/array_multisort_variation4.phpt
index ce2ae23564..5d11fb3ac0 100644
--- a/ext/standard/tests/array/array_multisort_variation4.phpt
+++ b/ext/standard/tests/array/array_multisort_variation4.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - testing with multiple array arguments
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation5.phpt b/ext/standard/tests/array/array_multisort_variation5.phpt
index 87e60f22b1..76d7092c21 100644
--- a/ext/standard/tests/array/array_multisort_variation5.phpt
+++ b/ext/standard/tests/array/array_multisort_variation5.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - testing with multiple array arguments
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation6.phpt b/ext/standard/tests/array/array_multisort_variation6.phpt
index 9774d49bad..4e2a62227d 100644
--- a/ext/standard/tests/array/array_multisort_variation6.phpt
+++ b/ext/standard/tests/array/array_multisort_variation6.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - testing with multiple array arguments
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation7.phpt b/ext/standard/tests/array/array_multisort_variation7.phpt
index c8ca24013a..4e9feb5126 100644
--- a/ext/standard/tests/array/array_multisort_variation7.phpt
+++ b/ext/standard/tests/array/array_multisort_variation7.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - test sort order of all types
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation8.phpt b/ext/standard/tests/array/array_multisort_variation8.phpt
index 60f7a97e32..1995ee8d2b 100644
--- a/ext/standard/tests/array/array_multisort_variation8.phpt
+++ b/ext/standard/tests/array/array_multisort_variation8.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - test sort order of all types
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_multisort_variation9.phpt b/ext/standard/tests/array/array_multisort_variation9.phpt
index 98ccd06ed0..b56357a4a3 100644
--- a/ext/standard/tests/array/array_multisort_variation9.phpt
+++ b/ext/standard/tests/array/array_multisort_variation9.phpt
@@ -2,7 +2,7 @@
Test array_multisort() function : usage variation - test sort order of all types
--FILE--
<?php
-/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING]], ...])
+/* Prototype : bool array_multisort(array ar1 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]] [, array ar2 [, SORT_ASC|SORT_DESC [, SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_NATURAL|SORT_FLAG_CASE]], ...])
* Description: Sort multiple arrays at once similar to how ORDER BY clause works in SQL
* Source code: ext/standard/array.c
* Alias to functions:
diff --git a/ext/standard/tests/array/array_push_variation4.phpt b/ext/standard/tests/array/array_push_variation4.phpt
deleted file mode 100644
index f8f89042aa..0000000000
--- a/ext/standard/tests/array/array_push_variation4.phpt
+++ /dev/null
@@ -1,110 +0,0 @@
---TEST--
-Test array_push() function : usage variations - referenced variables
---INI--
-allow_call_time_pass_reference=on
---FILE--
-<?php
-/* Prototype : int array_push(array $stack, mixed $var [, mixed $...])
- * Description: Pushes elements onto the end of the array
- * Source code: ext/standard/array.c
- */
-
-/*
- * Test array_push when:
- * 1. passed referenced variables as $var arguments
- * 2. $var argument is a reference to $stack argument
- */
-
-echo "*** Testing array_push() : usage variations ***\n";
-
-$var1 = 'a';
-$var2 = 'b';
-$var3 = 'c';
-$var4 = 'x';
-$var5 = 'y';
-$var6 = 'z';
-
-$array = array(1, 2, 3);
-
-echo "\n-- Pass array_push referenced varialbes as \$var arguments --\n";
-var_dump(array_push($array, &$var1, &$var2, &$var3, &$var4, &$var5, &$var6));
-var_dump($array);
-
-echo "\n-- Pass \$var argument which is a reference to \$stack argument --\n";
-var_dump(array_push($array, &$array));
-var_dump($array);
-
-echo "Done";
-?>
---EXPECTF--
-*** Testing array_push() : usage variations ***
-
--- Pass array_push referenced varialbes as $var arguments --
-int(9)
-array(9) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- [3]=>
- &string(1) "a"
- [4]=>
- &string(1) "b"
- [5]=>
- &string(1) "c"
- [6]=>
- &string(1) "x"
- [7]=>
- &string(1) "y"
- [8]=>
- &string(1) "z"
-}
-
--- Pass $var argument which is a reference to $stack argument --
-int(10)
-array(10) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- [3]=>
- &string(1) "a"
- [4]=>
- &string(1) "b"
- [5]=>
- &string(1) "c"
- [6]=>
- &string(1) "x"
- [7]=>
- &string(1) "y"
- [8]=>
- &string(1) "z"
- [9]=>
- &array(10) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
- [3]=>
- &string(1) "a"
- [4]=>
- &string(1) "b"
- [5]=>
- &string(1) "c"
- [6]=>
- &string(1) "x"
- [7]=>
- &string(1) "y"
- [8]=>
- &string(1) "z"
- [9]=>
- *RECURSION*
- }
-}
-Done
diff --git a/ext/standard/tests/array/array_slice_variation9.phpt b/ext/standard/tests/array/array_slice_variation9.phpt
index 030d4bd73a..7ae9238d47 100644
--- a/ext/standard/tests/array/array_slice_variation9.phpt
+++ b/ext/standard/tests/array/array_slice_variation9.phpt
@@ -1,7 +1,5 @@
--TEST--
Test array_slice() function : usage variations - referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : array array_slice(array $input, int $offset [, int $length [, bool $preserve_keys]])
@@ -29,12 +27,6 @@ echo "-- Change \$val2 (\$preserve_keys = TRUE) --\n";
$val2 = 'hello, world';
var_dump(array_slice($input, 1, 2, true));
-echo "\n-- Pass array by reference --\n";
-$new_input = array (1, 2, 3);
-var_dump(array_slice(&$new_input, 1));
-echo "-- Check passed array: --\n";
-var_dump($new_input);
-
echo "Done";
?>
@@ -55,21 +47,4 @@ array(2) {
[1]=>
&string(5) "three"
}
-
--- Pass array by reference --
-array(2) {
- [0]=>
- int(2)
- [1]=>
- int(3)
-}
--- Check passed array: --
-array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
-}
Done
diff --git a/ext/standard/tests/array/array_unique_variation8.phpt b/ext/standard/tests/array/array_unique_variation8.phpt
index 6cf343221f..ee34deeecc 100644
--- a/ext/standard/tests/array/array_unique_variation8.phpt
+++ b/ext/standard/tests/array/array_unique_variation8.phpt
@@ -28,6 +28,34 @@ echo "Done";
?>
--EXPECTF--
*** Testing array_unique() : two dimensional array for $input argument ***
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
+
+Notice: Array to string conversion in %sarray_unique_variation8.php on line %d
array(1) {
[0]=>
array(4) {
diff --git a/ext/standard/tests/array/array_values_variation6.phpt b/ext/standard/tests/array/array_values_variation6.phpt
index e565150760..8c4479ca6f 100644
--- a/ext/standard/tests/array/array_values_variation6.phpt
+++ b/ext/standard/tests/array/array_values_variation6.phpt
@@ -1,7 +1,5 @@
--TEST--
Test array_values() function : usage variations - Referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : array array_values(array $input)
@@ -29,10 +27,6 @@ echo "Change \$val2 and check result of array_values():\n";
$val2 = 'deux';
var_dump($result1);
-echo "\n-- Pass \$input argument by reference --\n";
-$array = array(1, 2, 3);
-var_dump($result2 = array_values(&$array));
-
echo "Done";
?>
@@ -57,14 +51,4 @@ array(3) {
[2]=>
&string(5) "three"
}
-
--- Pass $input argument by reference --
-array(3) {
- [0]=>
- int(1)
- [1]=>
- int(2)
- [2]=>
- int(3)
-}
Done
diff --git a/ext/standard/tests/array/arsort_basic.phpt b/ext/standard/tests/array/arsort_basic.phpt
index 481a590701..24799ab771 100644
--- a/ext/standard/tests/array/arsort_basic.phpt
+++ b/ext/standard/tests/array/arsort_basic.phpt
@@ -20,7 +20,11 @@ Test arsort() function : basic functionality
echo "*** Testing arsort() : basic functionality ***\n";
// an array containing unsorted string values with indices
-$unsorted_strings = array( "l" => "lemon", "o" => "orange", "b" => "banana" );
+$unsorted_strings = array(
+ "l" => "lemon", "o" => "orange",
+ "O" => "Orange", "O1" => "Orange1", "o2" => "orange2", "O3" => "Orange3", "o20" => "orange20",
+ "b" => "banana",
+);
// an array containing unsorted numeric values with indices
$unsorted_numerics = array( 1 => 100, 2 => 33, 3 => 555, 4 => 22 );
@@ -49,6 +53,21 @@ $temp_array = $unsorted_strings;
var_dump( arsort($temp_array, SORT_STRING) ); // expecting : bool(true)
var_dump( $temp_array);
+echo "\n-- Testing arsort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( arsort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing arsort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
+$temp_array = $unsorted_strings;
+var_dump( arsort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing arsort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( arsort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
echo "\n-- Testing arsort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
$temp_array = $unsorted_numerics;
var_dump( arsort($temp_array, SORT_NUMERIC) ); // expecting : bool(true)
@@ -61,13 +80,23 @@ echo "Done\n";
-- Testing arsort() by supplying string array, 'flag' value is default --
bool(true)
-array(3) {
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
["o"]=>
string(6) "orange"
["l"]=>
string(5) "lemon"
["b"]=>
string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
}
-- Testing arsort() by supplying numeric array, 'flag' value is default --
@@ -85,13 +114,23 @@ array(4) {
-- Testing arsort() by supplying string array, 'flag' = SORT_REGULAR --
bool(true)
-array(3) {
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
["o"]=>
string(6) "orange"
["l"]=>
string(5) "lemon"
["b"]=>
string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
}
-- Testing arsort() by supplying numeric array, 'flag' = SORT_REGULAR --
@@ -109,9 +148,82 @@ array(4) {
-- Testing arsort() by supplying string array, 'flag' = SORT_STRING --
bool(true)
-array(3) {
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o"]=>
+ string(6) "orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
+}
+
+-- Testing arsort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ ["O3"]=>
+ string(7) "Orange3"
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["o"]=>
+ string(6) "orange"
+ ["O"]=>
+ string(6) "Orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+}
+
+-- Testing arsort() by supplying string array (natural), 'flag' = SORT_NATURAL --
+bool(true)
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o"]=>
+ string(6) "orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
+}
+
+-- Testing arsort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["o2"]=>
+ string(7) "orange2"
+ ["O1"]=>
+ string(7) "Orange1"
["o"]=>
string(6) "orange"
+ ["O"]=>
+ string(6) "Orange"
["l"]=>
string(5) "lemon"
["b"]=>
diff --git a/ext/standard/tests/array/arsort_variation2.phpt b/ext/standard/tests/array/arsort_variation2.phpt
index ab04b44099..b85653052f 100644
--- a/ext/standard/tests/array/arsort_variation2.phpt
+++ b/ext/standard/tests/array/arsort_variation2.phpt
@@ -104,10 +104,10 @@ bool(true)
array(3) {
[3]=>
int(45)
- [1]=>
- int(10)
[2]=>
int(2)
+ [1]=>
+ int(10)
}
-- Iteration 3 --
bool(true)
@@ -305,4 +305,4 @@ array(3) {
[3]=>
int(45)
}
-Done \ No newline at end of file
+Done
diff --git a/ext/standard/tests/array/arsort_variation5.phpt b/ext/standard/tests/array/arsort_variation5.phpt
index f671da6508..187d43c482 100644
--- a/ext/standard/tests/array/arsort_variation5.phpt
+++ b/ext/standard/tests/array/arsort_variation5.phpt
@@ -73,14 +73,14 @@ bool(true)
array(12) {
["\xhh"]=>
string(4) "\xhh"
- ["\e"]=>
- string(2) "\e"
["\ddd"]=>
string(4) "\ddd"
["\cx"]=>
string(3) "\cx"
["\a"]=>
string(2) "\a"
+ [""]=>
+ string(1) ""
[" "]=>
string(1) " "
[" "]=>
@@ -103,14 +103,14 @@ bool(true)
array(12) {
["\xhh"]=>
string(4) "\xhh"
- ["\e"]=>
- string(2) "\e"
["\ddd"]=>
string(4) "\ddd"
["\cx"]=>
string(3) "\cx"
["\a"]=>
string(2) "\a"
+ [""]=>
+ string(1) ""
[" "]=>
string(1) " "
[" "]=>
@@ -133,14 +133,14 @@ bool(true)
array(12) {
["\xhh"]=>
string(4) "\xhh"
- ["\e"]=>
- string(2) "\e"
["\ddd"]=>
string(4) "\ddd"
["\cx"]=>
string(3) "\cx"
["\a"]=>
string(2) "\a"
+ [""]=>
+ string(1) ""
[" "]=>
string(1) " "
[" "]=>
diff --git a/ext/standard/tests/array/asort_basic.phpt b/ext/standard/tests/array/asort_basic.phpt
index 13fa4f794e..b80d31d37f 100644
--- a/ext/standard/tests/array/asort_basic.phpt
+++ b/ext/standard/tests/array/asort_basic.phpt
@@ -20,7 +20,11 @@ Test asort() function : basic functionality
echo "*** Testing asort() : basic functionality ***\n";
// an array containing unsorted string values with indices
-$unsorted_strings = array( "l" => "lemon", "o" => "orange", "b" => "banana" );
+$unsorted_strings = array(
+ "l" => "lemon", "o" => "orange",
+ "O" => "Orange", "O1" => "Orange1", "o2" => "orange2", "O3" => "Orange3", "o20" => "orange20",
+ "b" => "banana",
+);
// an array containing unsorted numeric values with indices
$unsorted_numerics = array( 1 => 100, 2 => 33, 3 => 555, 4 => 22 );
@@ -49,6 +53,21 @@ $temp_array = $unsorted_strings;
var_dump( asort($temp_array, SORT_STRING) ); // expecting : bool(true)
var_dump( $temp_array);
+echo "\n-- Testing asort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( asort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing asort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
+$temp_array = $unsorted_strings;
+var_dump( asort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing asort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( asort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
echo "\n-- Testing asort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
$temp_array = $unsorted_numerics;
var_dump( asort($temp_array, SORT_NUMERIC) ); // expecting : bool(true)
@@ -61,13 +80,23 @@ echo "Done\n";
-- Testing asort() by supplying string array, 'flag' value is default --
bool(true)
-array(3) {
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
["b"]=>
string(6) "banana"
["l"]=>
string(5) "lemon"
["o"]=>
string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
}
-- Testing asort() by supplying numeric array, 'flag' value is default --
@@ -85,13 +114,23 @@ array(4) {
-- Testing asort() by supplying string array, 'flag' = SORT_REGULAR --
bool(true)
-array(3) {
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
["b"]=>
string(6) "banana"
["l"]=>
string(5) "lemon"
["o"]=>
string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
}
-- Testing asort() by supplying numeric array, 'flag' = SORT_REGULAR --
@@ -109,13 +148,86 @@ array(4) {
-- Testing asort() by supplying string array, 'flag' = SORT_STRING --
bool(true)
-array(3) {
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["b"]=>
+ string(6) "banana"
+ ["l"]=>
+ string(5) "lemon"
+ ["o"]=>
+ string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
+}
+
+-- Testing asort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ ["b"]=>
+ string(6) "banana"
+ ["l"]=>
+ string(5) "lemon"
+ ["o"]=>
+ string(6) "orange"
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
+ ["O3"]=>
+ string(7) "Orange3"
+}
+
+-- Testing asort() by supplying string array (natural), 'flag' = SORT_NATURAL --
+bool(true)
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["b"]=>
+ string(6) "banana"
+ ["l"]=>
+ string(5) "lemon"
+ ["o"]=>
+ string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
+}
+
+-- Testing asort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
+bool(true)
+array(8) {
["b"]=>
string(6) "banana"
["l"]=>
string(5) "lemon"
["o"]=>
string(6) "orange"
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["o2"]=>
+ string(7) "orange2"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["o20"]=>
+ string(8) "orange20"
}
-- Testing asort() by supplying numeric array, 'flag' = SORT_NUMERIC --
@@ -130,4 +242,4 @@ array(4) {
[3]=>
int(555)
}
-Done
+Done \ No newline at end of file
diff --git a/ext/standard/tests/array/asort_variation2.phpt b/ext/standard/tests/array/asort_variation2.phpt
index 07dfe9b815..6cce644331 100644
--- a/ext/standard/tests/array/asort_variation2.phpt
+++ b/ext/standard/tests/array/asort_variation2.phpt
@@ -102,10 +102,10 @@ array(3) {
-- Iteration 2 --
bool(true)
array(3) {
- [2]=>
- int(2)
[1]=>
int(10)
+ [2]=>
+ int(2)
[3]=>
int(45)
}
diff --git a/ext/standard/tests/array/asort_variation5.phpt b/ext/standard/tests/array/asort_variation5.phpt
index bb27dd6927..3d6a12ef27 100644
--- a/ext/standard/tests/array/asort_variation5.phpt
+++ b/ext/standard/tests/array/asort_variation5.phpt
@@ -87,14 +87,14 @@ array(12) {
string(1) " "
[" "]=>
string(1) " "
+ [""]=>
+ string(1) ""
["\a"]=>
string(2) "\a"
["\cx"]=>
string(3) "\cx"
["\ddd"]=>
string(4) "\ddd"
- ["\e"]=>
- string(2) "\e"
["\xhh"]=>
string(4) "\xhh"
}
@@ -117,14 +117,14 @@ array(12) {
string(1) " "
[" "]=>
string(1) " "
+ [""]=>
+ string(1) ""
["\a"]=>
string(2) "\a"
["\cx"]=>
string(3) "\cx"
["\ddd"]=>
string(4) "\ddd"
- ["\e"]=>
- string(2) "\e"
["\xhh"]=>
string(4) "\xhh"
}
@@ -147,14 +147,14 @@ array(12) {
string(1) " "
[" "]=>
string(1) " "
+ [""]=>
+ string(1) ""
["\a"]=>
string(2) "\a"
["\cx"]=>
string(3) "\cx"
["\ddd"]=>
string(4) "\ddd"
- ["\e"]=>
- string(2) "\e"
["\xhh"]=>
string(4) "\xhh"
}
diff --git a/ext/standard/tests/array/bug29253.phpt b/ext/standard/tests/array/bug29253.phpt
index 378489f926..4be9839221 100644
--- a/ext/standard/tests/array/bug29253.phpt
+++ b/ext/standard/tests/array/bug29253.phpt
@@ -4,7 +4,7 @@ Bug #29253 (array_diff with $GLOBALS argument fails)
<?php
$zz = $GLOBALS;
$gg = 'afad';
-var_dump(array_diff_assoc($GLOBALS, $zz));
+var_dump(@array_diff_assoc($GLOBALS, $zz));
var_dump($gg);
?>
--EXPECTF--
diff --git a/ext/standard/tests/array/bug33940.phpt b/ext/standard/tests/array/bug33940.phpt
deleted file mode 100644
index a6d1ff8358..0000000000
--- a/ext/standard/tests/array/bug33940.phpt
+++ /dev/null
@@ -1,63 +0,0 @@
---TEST--
-Bug #33940 (array_map() fails to pass by reference when called recursively)
---INI--
-allow_call_time_pass_reference=1
-error_reporting=4095
---FILE--
-<?php
-function ref_map(&$item) {
- if(!is_array($item)) {
- $item = 1;
- return 2;
- } else {
- $ret = array_map('ref_map', &$item);
- return $ret;
- }
-}
-
-$a = array(array(0), 0);
-$ret = array_map('ref_map', $a);
-echo 'Array: '; print_r($a);
-echo 'Return: '; print_r($ret);
-$a = array(array(0), 0);
-$ret = array_map('ref_map', &$a);
-echo 'Array: '; print_r($a);
-echo 'Return: '; print_r($ret);
-?>
---EXPECTF--
-Array: Array
-(
- [0] => Array
- (
- [0] => 0
- )
-
- [1] => 0
-)
-Return: Array
-(
- [0] => Array
- (
- [0] => 2
- )
-
- [1] => 2
-)
-Array: Array
-(
- [0] => Array
- (
- [0] => 1
- )
-
- [1] => 1
-)
-Return: Array
-(
- [0] => Array
- (
- [0] => 2
- )
-
- [1] => 2
-)
diff --git a/ext/standard/tests/array/current_variation5.phpt b/ext/standard/tests/array/current_variation5.phpt
index b9bf4a9955..9e7c9e8d9d 100644
--- a/ext/standard/tests/array/current_variation5.phpt
+++ b/ext/standard/tests/array/current_variation5.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test current() function : usage variations - reference
+Test current() function : usage variations - reference & normal parameters
--FILE--
<?php
/* Prototype : mixed current(array $array_arg)
diff --git a/ext/standard/tests/array/each_variation4.phpt b/ext/standard/tests/array/each_variation4.phpt
index 6ac57a736e..535ae297d1 100644
--- a/ext/standard/tests/array/each_variation4.phpt
+++ b/ext/standard/tests/array/each_variation4.phpt
@@ -1,7 +1,5 @@
--TEST--
Test each() function : usage variations - Referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : array each(array $arr)
@@ -29,14 +27,6 @@ var_dump( each($arr1) );
var_dump( each($arr1) );
var_dump( each($arr1) );
-
-echo "\n-- Pass an array by reference to each(): --\n";
-$arr2 = array('zero', 'one', 'two');
-
-var_dump( each(&$arr2) );
-echo "-- Check original array: --\n";
-var_dump($arr2);
-
echo "Done";
?>
@@ -66,25 +56,4 @@ array(4) {
int(0)
}
bool(false)
-
--- Pass an array by reference to each(): --
-array(4) {
- [1]=>
- string(4) "zero"
- ["value"]=>
- string(4) "zero"
- [0]=>
- int(0)
- ["key"]=>
- int(0)
-}
--- Check original array: --
-array(3) {
- [0]=>
- string(4) "zero"
- [1]=>
- string(3) "one"
- [2]=>
- string(3) "two"
-}
Done
diff --git a/ext/standard/tests/array/krsort_basic.phpt b/ext/standard/tests/array/krsort_basic.phpt
index 913256897b..27361eb96d 100644
--- a/ext/standard/tests/array/krsort_basic.phpt
+++ b/ext/standard/tests/array/krsort_basic.phpt
@@ -20,6 +20,11 @@ echo "*** Testing krsort() : basic functionality ***\n";
// an array containing unsorted string values with indices
$unsorted_strings = array( "lemon" => "l", "orange" => "o", "banana" => "b" );
+$unsorted_strings = array(
+ "l" => "lemon", "o" => "orange",
+ "O" => "Orange", "O1" => "Orange1", "o2" => "orange2", "O3" => "Orange3", "o20" => "orange20",
+ "b" => "banana",
+);
// an array containing unsorted numeric values with indices
$unsorted_numerics = array( 100 => 4, 33 => 3, 555 => 2, 22 => 1 );
@@ -48,6 +53,21 @@ $temp_array = $unsorted_strings;
var_dump( krsort($temp_array, SORT_STRING) ); // expecting : bool(true)
var_dump( $temp_array);
+echo "\n-- Testing krsort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( krsort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing krsort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
+$temp_array = $unsorted_strings;
+var_dump( krsort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing krsort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( krsort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
echo "\n-- Testing krsort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
$temp_array = $unsorted_numerics;
var_dump( krsort($temp_array, SORT_NUMERIC) ); // expecting : bool(true)
@@ -60,13 +80,23 @@ echo "Done\n";
-- Testing krsort() by supplying string array, 'flag' value is defualt --
bool(true)
-array(3) {
- ["orange"]=>
- string(1) "o"
- ["lemon"]=>
- string(1) "l"
- ["banana"]=>
- string(1) "b"
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o"]=>
+ string(6) "orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
}
-- Testing krsort() by supplying numeric array, 'flag' value is defualt --
@@ -84,13 +114,23 @@ array(4) {
-- Testing krsort() by supplying string array, 'flag' = SORT_REGULAR --
bool(true)
-array(3) {
- ["orange"]=>
- string(1) "o"
- ["lemon"]=>
- string(1) "l"
- ["banana"]=>
- string(1) "b"
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o"]=>
+ string(6) "orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
}
-- Testing krsort() by supplying numeric array, 'flag' = SORT_REGULAR --
@@ -108,13 +148,86 @@ array(4) {
-- Testing krsort() by supplying string array, 'flag' = SORT_STRING --
bool(true)
-array(3) {
- ["orange"]=>
- string(1) "o"
- ["lemon"]=>
- string(1) "l"
- ["banana"]=>
- string(1) "b"
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o"]=>
+ string(6) "orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
+}
+
+-- Testing krsort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ ["O3"]=>
+ string(7) "Orange3"
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["o"]=>
+ string(6) "orange"
+ ["O"]=>
+ string(6) "Orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+}
+
+-- Testing krsort() by supplying string array (natural), 'flag' = SORT_NATURAL --
+bool(true)
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o"]=>
+ string(6) "orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O"]=>
+ string(6) "Orange"
+}
+
+-- Testing krsort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ ["o20"]=>
+ string(8) "orange20"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["o2"]=>
+ string(7) "orange2"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["o"]=>
+ string(6) "orange"
+ ["O"]=>
+ string(6) "Orange"
+ ["l"]=>
+ string(5) "lemon"
+ ["b"]=>
+ string(6) "banana"
}
-- Testing krsort() by supplying numeric array, 'flag' = SORT_NUMERIC --
@@ -129,4 +242,4 @@ array(4) {
[22]=>
int(1)
}
-Done
+Done \ No newline at end of file
diff --git a/ext/standard/tests/array/krsort_variation2.phpt b/ext/standard/tests/array/krsort_variation2.phpt
index c567f766cb..1376202470 100644
--- a/ext/standard/tests/array/krsort_variation2.phpt
+++ b/ext/standard/tests/array/krsort_variation2.phpt
@@ -103,10 +103,10 @@ bool(true)
array(3) {
[45]=>
int(45)
- [10]=>
- int(10)
[2]=>
int(2)
+ [10]=>
+ int(10)
}
-- Iteration 3 --
bool(true)
diff --git a/ext/standard/tests/array/krsort_variation5.phpt b/ext/standard/tests/array/krsort_variation5.phpt
index ac22bdddab..0fa1e9c68f 100644
--- a/ext/standard/tests/array/krsort_variation5.phpt
+++ b/ext/standard/tests/array/krsort_variation5.phpt
@@ -73,14 +73,14 @@ bool(true)
array(11) {
["\xhh"]=>
string(4) "\xhh"
- ["\e"]=>
- string(2) "\e"
["\ddd"]=>
string(4) "\ddd"
["\cx"]=>
string(3) "\cx"
["\a"]=>
string(2) "\a"
+ [""]=>
+ string(1) ""
[" "]=>
string(1) " "
[" "]=>
@@ -101,14 +101,14 @@ bool(true)
array(11) {
["\xhh"]=>
string(4) "\xhh"
- ["\e"]=>
- string(2) "\e"
["\ddd"]=>
string(4) "\ddd"
["\cx"]=>
string(3) "\cx"
["\a"]=>
string(2) "\a"
+ [""]=>
+ string(1) ""
[" "]=>
string(1) " "
[" "]=>
@@ -129,14 +129,14 @@ bool(true)
array(11) {
["\xhh"]=>
string(4) "\xhh"
- ["\e"]=>
- string(2) "\e"
["\ddd"]=>
string(4) "\ddd"
["\cx"]=>
string(3) "\cx"
["\a"]=>
string(2) "\a"
+ [""]=>
+ string(1) ""
[" "]=>
string(1) " "
[" "]=>
diff --git a/ext/standard/tests/array/ksort_basic.phpt b/ext/standard/tests/array/ksort_basic.phpt
index fdc8bd8dc6..dd9f7a2158 100644
--- a/ext/standard/tests/array/ksort_basic.phpt
+++ b/ext/standard/tests/array/ksort_basic.phpt
@@ -18,7 +18,11 @@ Test ksort() function : basic functionality
echo "*** Testing ksort() : basic functionality ***\n";
// an array containing unsorted string values with indices
-$unsorted_strings = array( "lemon" => "l", "orange" => "o", "banana" => "b" );
+$unsorted_strings = array(
+ "l" => "lemon", "o" => "orange",
+ "O" => "Orange", "O1" => "Orange1", "o2" => "orange2", "O3" => "Orange3", "o20" => "orange20",
+ "b" => "banana",
+);
// an array containing unsorted numeric values with indices
$unsorted_numerics = array( 100 => 4, 33 => 3, 555 => 2, 22 => 1 );
@@ -47,6 +51,21 @@ $temp_array = $unsorted_strings;
var_dump( ksort($temp_array, SORT_STRING) ); // expecting : bool(true)
var_dump( $temp_array);
+echo "\n-- Testing ksort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( sort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing ksort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
+$temp_array = $unsorted_strings;
+var_dump( sort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing ksort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( sort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
echo "\n-- Testing ksort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
$temp_array = $unsorted_numerics;
var_dump( ksort($temp_array, SORT_NUMERIC) ); // expecting : bool(true)
@@ -59,13 +78,23 @@ echo "Done\n";
-- Testing ksort() by supplying string array, 'flag' value is defualt --
bool(true)
-array(3) {
- ["banana"]=>
- string(1) "b"
- ["lemon"]=>
- string(1) "l"
- ["orange"]=>
- string(1) "o"
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["b"]=>
+ string(6) "banana"
+ ["l"]=>
+ string(5) "lemon"
+ ["o"]=>
+ string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
}
-- Testing ksort() by supplying numeric array, 'flag' value is defualt --
@@ -83,13 +112,23 @@ array(4) {
-- Testing ksort() by supplying string array, 'flag' = SORT_REGULAR --
bool(true)
-array(3) {
- ["banana"]=>
- string(1) "b"
- ["lemon"]=>
- string(1) "l"
- ["orange"]=>
- string(1) "o"
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["b"]=>
+ string(6) "banana"
+ ["l"]=>
+ string(5) "lemon"
+ ["o"]=>
+ string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
}
-- Testing ksort() by supplying numeric array, 'flag' = SORT_REGULAR --
@@ -107,13 +146,86 @@ array(4) {
-- Testing ksort() by supplying string array, 'flag' = SORT_STRING --
bool(true)
-array(3) {
- ["banana"]=>
- string(1) "b"
- ["lemon"]=>
- string(1) "l"
- ["orange"]=>
- string(1) "o"
+array(8) {
+ ["O"]=>
+ string(6) "Orange"
+ ["O1"]=>
+ string(7) "Orange1"
+ ["O3"]=>
+ string(7) "Orange3"
+ ["b"]=>
+ string(6) "banana"
+ ["l"]=>
+ string(5) "lemon"
+ ["o"]=>
+ string(6) "orange"
+ ["o2"]=>
+ string(7) "orange2"
+ ["o20"]=>
+ string(8) "orange20"
+}
+
+-- Testing ksort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ [0]=>
+ string(6) "banana"
+ [1]=>
+ string(5) "lemon"
+ [2]=>
+ string(6) "orange"
+ [3]=>
+ string(6) "Orange"
+ [4]=>
+ string(7) "Orange1"
+ [5]=>
+ string(7) "orange2"
+ [6]=>
+ string(8) "orange20"
+ [7]=>
+ string(7) "Orange3"
+}
+
+-- Testing ksort() by supplying string array (natural), 'flag' = SORT_NATURAL --
+bool(true)
+array(8) {
+ [0]=>
+ string(6) "Orange"
+ [1]=>
+ string(7) "Orange1"
+ [2]=>
+ string(7) "Orange3"
+ [3]=>
+ string(6) "banana"
+ [4]=>
+ string(5) "lemon"
+ [5]=>
+ string(6) "orange"
+ [6]=>
+ string(7) "orange2"
+ [7]=>
+ string(8) "orange20"
+}
+
+-- Testing ksort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ [0]=>
+ string(6) "banana"
+ [1]=>
+ string(5) "lemon"
+ [2]=>
+ string(6) "orange"
+ [3]=>
+ string(6) "Orange"
+ [4]=>
+ string(7) "Orange1"
+ [5]=>
+ string(7) "orange2"
+ [6]=>
+ string(7) "Orange3"
+ [7]=>
+ string(8) "orange20"
}
-- Testing ksort() by supplying numeric array, 'flag' = SORT_NUMERIC --
@@ -128,4 +240,4 @@ array(4) {
[555]=>
int(2)
}
-Done
+Done \ No newline at end of file
diff --git a/ext/standard/tests/array/ksort_variation2.phpt b/ext/standard/tests/array/ksort_variation2.phpt
index f765977d21..4969844e75 100644
--- a/ext/standard/tests/array/ksort_variation2.phpt
+++ b/ext/standard/tests/array/ksort_variation2.phpt
@@ -101,10 +101,10 @@ array(3) {
-- Iteration 2 --
bool(true)
array(3) {
- [2]=>
- int(2)
[10]=>
int(10)
+ [2]=>
+ int(2)
[45]=>
int(45)
}
diff --git a/ext/standard/tests/array/ksort_variation5.phpt b/ext/standard/tests/array/ksort_variation5.phpt
index 706474b485..6e6a38b0a5 100644
--- a/ext/standard/tests/array/ksort_variation5.phpt
+++ b/ext/standard/tests/array/ksort_variation5.phpt
@@ -85,14 +85,14 @@ array(11) {
string(1) " "
[" "]=>
string(1) " "
+ [""]=>
+ string(1) ""
["\a"]=>
string(2) "\a"
["\cx"]=>
string(3) "\cx"
["\ddd"]=>
string(4) "\ddd"
- ["\e"]=>
- string(2) "\e"
["\xhh"]=>
string(4) "\xhh"
}
@@ -113,14 +113,14 @@ array(11) {
string(1) " "
[" "]=>
string(1) " "
+ [""]=>
+ string(1) ""
["\a"]=>
string(2) "\a"
["\cx"]=>
string(3) "\cx"
["\ddd"]=>
string(4) "\ddd"
- ["\e"]=>
- string(2) "\e"
["\xhh"]=>
string(4) "\xhh"
}
@@ -141,14 +141,14 @@ array(11) {
string(1) " "
[" "]=>
string(1) " "
+ [""]=>
+ string(1) ""
["\a"]=>
string(2) "\a"
["\cx"]=>
string(3) "\cx"
["\ddd"]=>
string(4) "\ddd"
- ["\e"]=>
- string(2) "\e"
["\xhh"]=>
string(4) "\xhh"
}
diff --git a/ext/standard/tests/array/natcasesort_variation4.phpt b/ext/standard/tests/array/natcasesort_variation4.phpt
index 2a189f337c..c7f99e1f6d 100644
--- a/ext/standard/tests/array/natcasesort_variation4.phpt
+++ b/ext/standard/tests/array/natcasesort_variation4.phpt
@@ -50,14 +50,14 @@ array(11) {
string(1) " "
[5]=>
string(1) " "
+ [4]=>
+ string(1) ""
[2]=>
string(2) "\a"
[3]=>
string(3) "\cx"
[9]=>
string(4) "\ddd"
- [4]=>
- string(2) "\e"
[8]=>
string(4) "\xhh"
}
@@ -88,4 +88,4 @@ array(12) {
[9]=>
string(1) "X"
}
-Done \ No newline at end of file
+Done
diff --git a/ext/standard/tests/array/range_variation.phpt b/ext/standard/tests/array/range_variation.phpt
index 0ac8c55e65..e97d918d9b 100644
--- a/ext/standard/tests/array/range_variation.phpt
+++ b/ext/standard/tests/array/range_variation.phpt
@@ -11,7 +11,7 @@ $high_arr = array( "ABCD", -10.5555, TRUE, NULL, FALSE, "", array(1,2));
for( $i = 0; $i < count($low_arr); $i++) {
for( $j = 0; $j < count($high_arr); $j++) {
- echo "\n-- creating an array with low = '$low_arr[$i]' and high = '$high_arr[$j]' --\n";
+ echo @"\n-- creating an array with low = '$low_arr[$i]' and high = '$high_arr[$j]' --\n";
var_dump( range( $low_arr[$i], $high_arr[$j] ) );
}
}
diff --git a/ext/standard/tests/array/rsort_basic.phpt b/ext/standard/tests/array/rsort_basic.phpt
index 5495be9257..34fcbb7034 100644
--- a/ext/standard/tests/array/rsort_basic.phpt
+++ b/ext/standard/tests/array/rsort_basic.phpt
@@ -14,7 +14,11 @@ Test rsort() function : basic functionality
echo "*** Testing rsort() : basic functionality ***\n";
// associative array containing unsorted string values
-$unsorted_strings = array( "l" => "lemon", "o" => "orange", "b" => "banana" );
+$unsorted_strings = array(
+ "l" => "lemon", "o" => "orange",
+ "O" => "Orange", "O1" => "Orange1", "o2" => "orange2", "O3" => "Orange3", "o20" => "orange20",
+ "b" => "banana",
+);
// array with default keys containing unsorted numeric values
$unsorted_numerics = array( 100, 33, 555, 22 );
@@ -44,6 +48,21 @@ $temp_array = $unsorted_strings;
var_dump( rsort($temp_array, SORT_STRING) );
var_dump( $temp_array);
+echo "\n-- Testing rsort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( rsort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing rsort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
+$temp_array = $unsorted_strings;
+var_dump( rsort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing rsort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( rsort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
echo "\n-- Testing rsort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
$temp_array = $unsorted_numerics;
var_dump( rsort($temp_array, SORT_NUMERIC) );
@@ -57,13 +76,23 @@ echo "Done";
-- Testing rsort() by supplying string array, 'flag' value is defualt --
bool(true)
-array(3) {
+array(8) {
[0]=>
- string(6) "orange"
+ string(8) "orange20"
[1]=>
- string(5) "lemon"
+ string(7) "orange2"
[2]=>
+ string(6) "orange"
+ [3]=>
+ string(5) "lemon"
+ [4]=>
string(6) "banana"
+ [5]=>
+ string(7) "Orange3"
+ [6]=>
+ string(7) "Orange1"
+ [7]=>
+ string(6) "Orange"
}
-- Testing rsort() by supplying numeric array, 'flag' value is defualt --
@@ -81,13 +110,23 @@ array(4) {
-- Testing rsort() by supplying string array, 'flag' = SORT_REGULAR --
bool(true)
-array(3) {
+array(8) {
[0]=>
- string(6) "orange"
+ string(8) "orange20"
[1]=>
- string(5) "lemon"
+ string(7) "orange2"
[2]=>
+ string(6) "orange"
+ [3]=>
+ string(5) "lemon"
+ [4]=>
string(6) "banana"
+ [5]=>
+ string(7) "Orange3"
+ [6]=>
+ string(7) "Orange1"
+ [7]=>
+ string(6) "Orange"
}
-- Testing rsort() by supplying numeric array, 'flag' = SORT_REGULAR --
@@ -105,12 +144,85 @@ array(4) {
-- Testing rsort() by supplying string array, 'flag' = SORT_STRING --
bool(true)
-array(3) {
+array(8) {
+ [0]=>
+ string(8) "orange20"
+ [1]=>
+ string(7) "orange2"
+ [2]=>
+ string(6) "orange"
+ [3]=>
+ string(5) "lemon"
+ [4]=>
+ string(6) "banana"
+ [5]=>
+ string(7) "Orange3"
+ [6]=>
+ string(7) "Orange1"
+ [7]=>
+ string(6) "Orange"
+}
+
+-- Testing rsort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
+bool(true)
+array(8) {
[0]=>
+ string(7) "Orange3"
+ [1]=>
+ string(8) "orange20"
+ [2]=>
+ string(7) "orange2"
+ [3]=>
+ string(7) "Orange1"
+ [4]=>
string(6) "orange"
+ [5]=>
+ string(6) "Orange"
+ [6]=>
+ string(5) "lemon"
+ [7]=>
+ string(6) "banana"
+}
+
+-- Testing rsort() by supplying string array (natural), 'flag' = SORT_NATURAL --
+bool(true)
+array(8) {
+ [0]=>
+ string(8) "orange20"
[1]=>
+ string(7) "orange2"
+ [2]=>
+ string(6) "orange"
+ [3]=>
string(5) "lemon"
+ [4]=>
+ string(6) "banana"
+ [5]=>
+ string(7) "Orange3"
+ [6]=>
+ string(7) "Orange1"
+ [7]=>
+ string(6) "Orange"
+}
+
+-- Testing rsort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ [0]=>
+ string(8) "orange20"
+ [1]=>
+ string(7) "Orange3"
[2]=>
+ string(7) "orange2"
+ [3]=>
+ string(7) "Orange1"
+ [4]=>
+ string(6) "orange"
+ [5]=>
+ string(6) "Orange"
+ [6]=>
+ string(5) "lemon"
+ [7]=>
string(6) "banana"
}
diff --git a/ext/standard/tests/array/rsort_variation4.phpt b/ext/standard/tests/array/rsort_variation4.phpt
index 4cab1a9334..226284d329 100644
--- a/ext/standard/tests/array/rsort_variation4.phpt
+++ b/ext/standard/tests/array/rsort_variation4.phpt
@@ -1,7 +1,5 @@
--TEST--
Test rsort() function : usage variations - referenced variables
---INI--
-allow_call_time_pass_reference=on
--FILE--
<?php
/* Prototype : bool rsort(array &$array_arg [, int $sort_flags])
@@ -35,11 +33,6 @@ $temp_array = &$unsorted_numerics;
var_dump( rsort($temp_array, SORT_REGULAR) );
var_dump( $temp_array);
-echo "\n-- 'flag' = SORT_NUMERIC --\n";
-$temp_array = $unsorted_numerics;
-var_dump( rsort(&$temp_array, SORT_NUMERIC) );
-var_dump( $temp_array);
-
echo "Done";
?>
--EXPECTF--
@@ -66,15 +59,4 @@ array(3) {
[2]=>
&int(33)
}
-
--- 'flag' = SORT_NUMERIC --
-bool(true)
-array(3) {
- [0]=>
- &int(555)
- [1]=>
- &int(100)
- [2]=>
- &int(33)
-}
Done
diff --git a/ext/standard/tests/array/rsort_variation5.phpt b/ext/standard/tests/array/rsort_variation5.phpt
index e955cb34fd..c0184e83b9 100644
--- a/ext/standard/tests/array/rsort_variation5.phpt
+++ b/ext/standard/tests/array/rsort_variation5.phpt
@@ -62,13 +62,13 @@ array(11) {
[0]=>
string(4) "\xhh"
[1]=>
- string(2) "\e"
- [2]=>
string(4) "\ddd"
- [3]=>
+ [2]=>
string(3) "\cx"
- [4]=>
+ [3]=>
string(2) "\a"
+ [4]=>
+ string(1) ""
[5]=>
string(1) " "
[6]=>
@@ -89,13 +89,13 @@ array(11) {
[0]=>
string(4) "\xhh"
[1]=>
- string(2) "\e"
- [2]=>
string(4) "\ddd"
- [3]=>
+ [2]=>
string(3) "\cx"
- [4]=>
+ [3]=>
string(2) "\a"
+ [4]=>
+ string(1) ""
[5]=>
string(1) " "
[6]=>
@@ -116,13 +116,13 @@ array(11) {
[0]=>
string(4) "\xhh"
[1]=>
- string(2) "\e"
- [2]=>
string(4) "\ddd"
- [3]=>
+ [2]=>
string(3) "\cx"
- [4]=>
+ [3]=>
string(2) "\a"
+ [4]=>
+ string(1) ""
[5]=>
string(1) " "
[6]=>
@@ -223,4 +223,4 @@ array(12) {
[11]=>
string(6) "BANANA"
}
-Done \ No newline at end of file
+Done
diff --git a/ext/standard/tests/array/sort_basic.phpt b/ext/standard/tests/array/sort_basic.phpt
index 3cf653f208..460b572fc1 100644
--- a/ext/standard/tests/array/sort_basic.phpt
+++ b/ext/standard/tests/array/sort_basic.phpt
@@ -20,7 +20,11 @@ Test sort() function : basic functionality
echo "*** Testing sort() : basic functionality ***\n";
// associative array containing unsorted string values
-$unsorted_strings = array( "l" => "lemon", "o" => "orange", "b" => "banana" );
+$unsorted_strings = array(
+ "l" => "lemon", "o" => "orange",
+ "O" => "Orange", "O1" => "Orange1", "o2" => "orange2", "O3" => "Orange3", "o20" => "orange20",
+ "b" => "banana",
+);
// array with default keys containing unsorted numeric values
$unsorted_numerics = array( 100, 33, 555, 22 );
@@ -50,6 +54,21 @@ $temp_array = $unsorted_strings;
var_dump( sort($temp_array, SORT_STRING) ); // expecting : bool(true)
var_dump( $temp_array);
+echo "\n-- Testing sort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( sort($temp_array, SORT_STRING|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing sort() by supplying string array (natural), 'flag' = SORT_NATURAL --\n";
+$temp_array = $unsorted_strings;
+var_dump( sort($temp_array, SORT_NATURAL) ); // expecting : bool(true)
+var_dump( $temp_array);
+
+echo "\n-- Testing sort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --\n";
+$temp_array = $unsorted_strings;
+var_dump( sort($temp_array, SORT_NATURAL|SORT_FLAG_CASE) ); // expecting : bool(true)
+var_dump( $temp_array);
+
echo "\n-- Testing sort() by supplying numeric array, 'flag' = SORT_NUMERIC --\n";
$temp_array = $unsorted_numerics;
var_dump( sort($temp_array, SORT_NUMERIC) ); // expecting : bool(true)
@@ -62,13 +81,23 @@ echo "Done\n";
-- Testing sort() by supplying string array, 'flag' value is defualt --
bool(true)
-array(3) {
+array(8) {
[0]=>
- string(6) "banana"
+ string(6) "Orange"
[1]=>
- string(5) "lemon"
+ string(7) "Orange1"
[2]=>
+ string(7) "Orange3"
+ [3]=>
+ string(6) "banana"
+ [4]=>
+ string(5) "lemon"
+ [5]=>
string(6) "orange"
+ [6]=>
+ string(7) "orange2"
+ [7]=>
+ string(8) "orange20"
}
-- Testing sort() by supplying numeric array, 'flag' value is defualt --
@@ -86,13 +115,23 @@ array(4) {
-- Testing sort() by supplying string array, 'flag' = SORT_REGULAR --
bool(true)
-array(3) {
+array(8) {
[0]=>
- string(6) "banana"
+ string(6) "Orange"
[1]=>
- string(5) "lemon"
+ string(7) "Orange1"
[2]=>
+ string(7) "Orange3"
+ [3]=>
+ string(6) "banana"
+ [4]=>
+ string(5) "lemon"
+ [5]=>
string(6) "orange"
+ [6]=>
+ string(7) "orange2"
+ [7]=>
+ string(8) "orange20"
}
-- Testing sort() by supplying numeric array, 'flag' = SORT_REGULAR --
@@ -110,13 +149,86 @@ array(4) {
-- Testing sort() by supplying string array, 'flag' = SORT_STRING --
bool(true)
-array(3) {
+array(8) {
+ [0]=>
+ string(6) "Orange"
+ [1]=>
+ string(7) "Orange1"
+ [2]=>
+ string(7) "Orange3"
+ [3]=>
+ string(6) "banana"
+ [4]=>
+ string(5) "lemon"
+ [5]=>
+ string(6) "orange"
+ [6]=>
+ string(7) "orange2"
+ [7]=>
+ string(8) "orange20"
+}
+
+-- Testing sort() by supplying string array (case insensitive), 'flag' = SORT_STRING|SORT_FLAG_CASE --
+bool(true)
+array(8) {
[0]=>
string(6) "banana"
[1]=>
string(5) "lemon"
[2]=>
string(6) "orange"
+ [3]=>
+ string(6) "Orange"
+ [4]=>
+ string(7) "Orange1"
+ [5]=>
+ string(7) "orange2"
+ [6]=>
+ string(8) "orange20"
+ [7]=>
+ string(7) "Orange3"
+}
+
+-- Testing sort() by supplying string array (natural), 'flag' = SORT_NATURAL --
+bool(true)
+array(8) {
+ [0]=>
+ string(6) "Orange"
+ [1]=>
+ string(7) "Orange1"
+ [2]=>
+ string(7) "Orange3"
+ [3]=>
+ string(6) "banana"
+ [4]=>
+ string(5) "lemon"
+ [5]=>
+ string(6) "orange"
+ [6]=>
+ string(7) "orange2"
+ [7]=>
+ string(8) "orange20"
+}
+
+-- Testing sort() by supplying string array (natural, case insensitive), 'flag' = SORT_NATURAL|SORT_FLAG_CASE --
+bool(true)
+array(8) {
+ [0]=>
+ string(6) "banana"
+ [1]=>
+ string(5) "lemon"
+ [2]=>
+ string(6) "orange"
+ [3]=>
+ string(6) "Orange"
+ [4]=>
+ string(7) "Orange1"
+ [5]=>
+ string(7) "orange2"
+ [6]=>
+ string(7) "Orange3"
+ [7]=>
+ string(8) "orange20"
}
-- Testing sort() by supplying numeric array, 'flag' = SORT_NUMERIC --
@@ -131,4 +243,4 @@ array(4) {
[3]=>
int(555)
}
-Done
+Done \ No newline at end of file
diff --git a/ext/standard/tests/array/sort_variation2.phpt b/ext/standard/tests/array/sort_variation2.phpt
index 4304ecb767..7cb8ed642a 100644
--- a/ext/standard/tests/array/sort_variation2.phpt
+++ b/ext/standard/tests/array/sort_variation2.phpt
@@ -106,9 +106,9 @@ array(3) {
bool(true)
array(3) {
[0]=>
- int(2)
- [1]=>
int(10)
+ [1]=>
+ int(2)
[2]=>
int(45)
}
diff --git a/ext/standard/tests/array/sort_variation5.phpt b/ext/standard/tests/array/sort_variation5.phpt
index 1e216943a9..a06c22c751 100644
--- a/ext/standard/tests/array/sort_variation5.phpt
+++ b/ext/standard/tests/array/sort_variation5.phpt
@@ -81,13 +81,13 @@ array(12) {
[6]=>
string(1) " "
[7]=>
- string(2) "\a"
+ string(1) ""
[8]=>
- string(3) "\cx"
+ string(2) "\a"
[9]=>
- string(4) "\ddd"
+ string(3) "\cx"
[10]=>
- string(2) "\e"
+ string(4) "\ddd"
[11]=>
string(4) "\xhh"
}
@@ -110,13 +110,13 @@ array(12) {
[6]=>
string(1) " "
[7]=>
- string(2) "\a"
+ string(1) ""
[8]=>
- string(3) "\cx"
+ string(2) "\a"
[9]=>
- string(4) "\ddd"
+ string(3) "\cx"
[10]=>
- string(2) "\e"
+ string(4) "\ddd"
[11]=>
string(4) "\xhh"
}
@@ -139,13 +139,13 @@ array(12) {
[6]=>
string(1) " "
[7]=>
- string(2) "\a"
+ string(1) ""
[8]=>
- string(3) "\cx"
+ string(2) "\a"
[9]=>
- string(4) "\ddd"
+ string(3) "\cx"
[10]=>
- string(2) "\e"
+ string(4) "\ddd"
[11]=>
string(4) "\xhh"
}
diff --git a/ext/standard/tests/assert/assert04.phpt b/ext/standard/tests/assert/assert04.phpt
index 0da23186e6..bffadcb97c 100644
--- a/ext/standard/tests/assert/assert04.phpt
+++ b/ext/standard/tests/assert/assert04.phpt
@@ -15,7 +15,7 @@ assert(1);
/* Wrong parameter count in assert */
assert_options(ASSERT_ACTIVE, 1);
-assert(2,3);
+assert(2, "failure", 3);
/* Wrong parameter count in assert_options */
assert_options(ASSERT_ACTIVE, 0, 2);
@@ -36,7 +36,7 @@ echo "not reached\n";
?>
--EXPECTF--
-Warning: assert() expects exactly 1 parameter, 2 given in %s on line %d
+Warning: assert() expects at most 2 parameters, 3 given in %s on line %d
Warning: assert_options() expects at most 2 parameters, 3 given in %s on line %d
@@ -45,3 +45,4 @@ Warning: assert_options() expects parameter 1 to be long, %unicode_string_option
Warning: assert(): Assertion failed in %s on line %d
Warning: assert(): Assertion failed in %s on line %d
+
diff --git a/ext/standard/tests/assert/assert_basic6.phpt b/ext/standard/tests/assert/assert_basic6.phpt
new file mode 100644
index 0000000000..2a73713437
--- /dev/null
+++ b/ext/standard/tests/assert/assert_basic6.phpt
@@ -0,0 +1,26 @@
+--TEST--
+assert() - basic - Test that bailout works
+--INI--
+assert.active = 1
+assert.warning = 1
+assert.callback = f1
+assert.quiet_eval = 1
+assert.bail = 0
+--FILE--
+<?php
+function f1($message)
+{
+ echo "f1 called\n";
+}
+
+//bail out on error
+var_dump($rao = assert_options(ASSERT_BAIL, 1));
+$sa = "0 != 0";
+var_dump($r2 = assert($sa, "0 is 0"));
+echo "If this is printed BAIL hasn't worked";
+--EXPECTF--
+int(0)
+f1 called
+
+Warning: assert(): 0 is 0: "0 != 0" failed in %s on line 10
+
diff --git a/ext/standard/tests/assert/assert_error1.phpt b/ext/standard/tests/assert/assert_error1.phpt
index 6211f1c918..657b411f67 100644
--- a/ext/standard/tests/assert/assert_error1.phpt
+++ b/ext/standard/tests/assert/assert_error1.phpt
@@ -20,19 +20,19 @@ function handler($errno, $errstr) {
//Wrong number of parameters for assert_options()
assert_options(ASSERT_WARNING, 1);
-var_dump($rao=assert_options(ASSERT_CALLBACK,"f1",1));
+var_dump($rao = assert_options(ASSERT_CALLBACK, "f1", 1));
//Unknown option for assert_options()
-var_dump($rao=assert_options("F1","f1"));
+var_dump($rao=assert_options("F1", "f1"));
//Wrong number of parameters for assert()
$sa="0 != 0";
-var_dump($r2=assert($sa,1));
+var_dump($r2 = assert($sa, "message", 1));
//Catch recoverable error with handler
-var_dump($rc=assert('aa=sd+as+safsafasfaçsafçsafç'));
+var_dump($rc = assert('aa=sd+as+safsafasfaçsafçsafç'));
--EXPECTF--
Warning: assert_options() expects at most 2 parameters, 3 given in %s on line %d
NULL
@@ -40,5 +40,6 @@ NULL
Warning: assert_options() expects parameter 1 to be long, string given in %s on line %d
NULL
-Warning: assert() expects exactly 1 parameter, 2 given in %s on line %d
+Warning: assert() expects at most 2 parameters, 3 given in %s on line %d
NULL
+
diff --git a/ext/standard/tests/assert/assert_error2.phpt b/ext/standard/tests/assert/assert_error2.phpt
new file mode 100644
index 0000000000..da7c3d9e0b
--- /dev/null
+++ b/ext/standard/tests/assert/assert_error2.phpt
@@ -0,0 +1,30 @@
+--TEST--
+assert() - basic - Test that bailout works
+--INI--
+assert.active = 1
+assert.warning = 1
+assert.callback = f1
+assert.quiet_eval = 1
+assert.bail = 0
+error_reporting = -1
+display_errors = 1
+--FILE--
+<?php
+function f1($script, $line, $message, $user_message)
+{
+ echo "f1 called\n";
+}
+
+//bail out on error
+var_dump($rao = assert_options(ASSERT_BAIL, 1));
+$sa = "0 != 0";
+var_dump($r2 = assert($sa));
+echo "If this is printed BAIL hasn't worked";
+--EXPECTF--
+int(0)
+
+Warning: Missing argument 4 for f1() in %s on line 2
+f1 called
+
+Warning: assert(): Assertion "0 != 0" failed in %s on line 10
+
diff --git a/ext/standard/tests/assert/assert_error3.phpt b/ext/standard/tests/assert/assert_error3.phpt
new file mode 100644
index 0000000000..54b91edd3d
--- /dev/null
+++ b/ext/standard/tests/assert/assert_error3.phpt
@@ -0,0 +1,21 @@
+--TEST--
+assert() - basic - Test recoverable error
+--INI--
+assert.active = 1
+assert.warning = 1
+assert.callback = f1
+assert.quiet_eval = 0
+assert.bail = 0
+error_reporting = -1
+display_errors = 1
+--FILE--
+<?php
+$sa = "0 $ 0";
+var_dump($r2 = assert($sa));
+--EXPECTF--
+
+Parse error: syntax error, unexpected '$' in %s(3) : assert code on line 1
+
+Catchable fatal error: assert(): Failure evaluating code:
+0 $ 0 in %s on line 3
+
diff --git a/ext/standard/tests/assert/assert_error4.phpt b/ext/standard/tests/assert/assert_error4.phpt
new file mode 100644
index 0000000000..264cc8fecf
--- /dev/null
+++ b/ext/standard/tests/assert/assert_error4.phpt
@@ -0,0 +1,21 @@
+--TEST--
+assert() - basic - Test recoverable error
+--INI--
+assert.active = 1
+assert.warning = 1
+assert.callback = f1
+assert.quiet_eval = 0
+assert.bail = 0
+error_reporting = -1
+display_errors = 1
+--FILE--
+<?php
+$sa = "0 $ 0";
+var_dump($r2 = assert($sa, "Describing what was asserted"));
+--EXPECTF--
+
+Parse error: syntax error, unexpected '$' in %s(3) : assert code on line 1
+
+Catchable fatal error: assert(): Failure evaluating code:
+Describing what was asserted:"0 $ 0" in %s on line 3
+
diff --git a/ext/standard/tests/class_object/AutoTrait.inc b/ext/standard/tests/class_object/AutoTrait.inc
new file mode 100644
index 0000000000..698e975ef7
--- /dev/null
+++ b/ext/standard/tests/class_object/AutoTrait.inc
@@ -0,0 +1,5 @@
+<?php
+
+trait AutoTrait {}
+
+?> \ No newline at end of file
diff --git a/ext/standard/tests/class_object/class_exists_variation_001.phpt b/ext/standard/tests/class_object/class_exists_variation_001.phpt
index 2141d65eb8..c9146ba9f7 100644
--- a/ext/standard/tests/class_object/class_exists_variation_001.phpt
+++ b/ext/standard/tests/class_object/class_exists_variation_001.phpt
@@ -122,22 +122,27 @@ bool(false)
Arg value 0.5
In __autoload(0.5)
bool(false)
+Error: 8 - Array to string conversion, %sclass_exists_variation_001.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 1 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_001.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 1 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_001.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 1 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_001.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 1 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_001.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 1 to be string, array given, %s(77)
diff --git a/ext/standard/tests/class_object/class_exists_variation_002.phpt b/ext/standard/tests/class_object/class_exists_variation_002.phpt
index da10cac908..ae9de157f6 100644
--- a/ext/standard/tests/class_object/class_exists_variation_002.phpt
+++ b/ext/standard/tests/class_object/class_exists_variation_002.phpt
@@ -125,22 +125,27 @@ bool(false)
Arg value 0.5
In __autoload(string_val)
bool(false)
+Error: 8 - Array to string conversion, %sclass_exists_variation_002.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 2 to be boolean, array given, %s(81)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_002.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 2 to be boolean, array given, %s(81)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_002.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 2 to be boolean, array given, %s(81)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_002.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 2 to be boolean, array given, %s(81)
NULL
+Error: 8 - Array to string conversion, %sclass_exists_variation_002.php(%d)
Arg value Array
Error: 2 - class_exists() expects parameter 2 to be boolean, array given, %s(81)
diff --git a/ext/standard/tests/class_object/get_class_methods_variation_001.phpt b/ext/standard/tests/class_object/get_class_methods_variation_001.phpt
index b881452b4c..8cdef12a7b 100644
--- a/ext/standard/tests/class_object/get_class_methods_variation_001.phpt
+++ b/ext/standard/tests/class_object/get_class_methods_variation_001.phpt
@@ -113,18 +113,23 @@ NULL
Arg value 0.5
NULL
+Error: 8 - Array to string conversion, %sget_class_methods_variation_001.php(%d)
Arg value Array
NULL
+Error: 8 - Array to string conversion, %sget_class_methods_variation_001.php(%d)
Arg value Array
NULL
+Error: 8 - Array to string conversion, %sget_class_methods_variation_001.php(%d)
Arg value Array
NULL
+Error: 8 - Array to string conversion, %sget_class_methods_variation_001.php(%d)
Arg value Array
NULL
+Error: 8 - Array to string conversion, %sget_class_methods_variation_001.php(%d)
Arg value Array
NULL
diff --git a/ext/standard/tests/class_object/get_class_variation_001.phpt b/ext/standard/tests/class_object/get_class_variation_001.phpt
index e2bf986c21..2baef2e14c 100644
--- a/ext/standard/tests/class_object/get_class_variation_001.phpt
+++ b/ext/standard/tests/class_object/get_class_variation_001.phpt
@@ -67,7 +67,7 @@ $values = array(
// loop through each element of the array for object
foreach($values as $value) {
- echo "\nArg value: $value (type: " . gettype($value) . ")\n";
+ echo @"\nArg value: $value (type: " . gettype($value) . ")\n";
var_dump( get_class($value) );
};
diff --git a/ext/standard/tests/class_object/get_declared_traits_basic_001.phpt b/ext/standard/tests/class_object/get_declared_traits_basic_001.phpt
new file mode 100644
index 0000000000..69d8de9c31
--- /dev/null
+++ b/ext/standard/tests/class_object/get_declared_traits_basic_001.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Test get_declared_traits() function : basic functionality
+--FILE--
+<?php
+/* Prototype : proto array get_declared_traits()
+ * Description: Returns an array of all declared traits.
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+
+echo "*** Testing get_declared_traits() : basic functionality ***\n";
+
+trait MyTrait {}
+
+// Zero arguments
+echo "\n-- Testing get_declared_traits() function with Zero arguments --\n";
+var_dump(get_declared_traits());
+
+foreach (get_declared_traits() as $trait) {
+ if (!trait_exists($trait)) {
+ echo "Error: $trait is not a valid trait.\n";
+ }
+}
+
+echo "\n-- Ensure trait is listed --\n";
+var_dump(in_array('MyTrait', get_declared_traits()));
+
+echo "\n-- Ensure userspace interfaces are not listed --\n";
+interface I {}
+var_dump(in_array( 'I', get_declared_traits()));
+
+echo "\n-- Ensure userspace classes are not listed --\n";
+class MyClass {}
+var_dump(in_array( 'MyClass', get_declared_traits()));
+
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing get_declared_traits() : basic functionality ***
+
+-- Testing get_declared_traits() function with Zero arguments --
+array(%d) {
+%a
+}
+
+-- Ensure trait is listed --
+bool(true)
+
+-- Ensure userspace interfaces are not listed --
+bool(false)
+
+-- Ensure userspace classes are not listed --
+bool(false)
+Done \ No newline at end of file
diff --git a/ext/standard/tests/class_object/get_declared_traits_error_001.phpt b/ext/standard/tests/class_object/get_declared_traits_error_001.phpt
new file mode 100644
index 0000000000..f7a00da0dd
--- /dev/null
+++ b/ext/standard/tests/class_object/get_declared_traits_error_001.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test get_declared_traits() function : error conditions
+--FILE--
+<?php
+/* Prototype : proto array get_declared_traits()
+ * Description: Returns an array of all declared traits.
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+echo "*** Testing get_declared_traits() : error conditions ***\n";
+
+// One argument
+echo "\n-- Testing get_declared_traits() function with one argument --\n";
+$extra_arg = 10;;
+var_dump( get_declared_traits($extra_arg) );
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing get_declared_traits() : error conditions ***
+
+-- Testing get_declared_traits() function with one argument --
+
+Warning: get_declared_traits() expects exactly 0 parameters, 1 given in %s on line 13
+NULL
+Done
diff --git a/ext/standard/tests/class_object/get_declared_traits_variation1.phpt b/ext/standard/tests/class_object/get_declared_traits_variation1.phpt
new file mode 100644
index 0000000000..bedd37a3db
--- /dev/null
+++ b/ext/standard/tests/class_object/get_declared_traits_variation1.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Test get_declared_traits() function : testing autoloaded traits
+--FILE--
+<?php
+/* Prototype : proto array get_declared_traits()
+ * Description: Returns an array of all declared traits.
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+
+echo "*** Testing get_declared_traits() : testing autoloaded traits ***\n";
+
+function __autoload($trait_name) {
+ require_once $trait_name . '.inc';
+}
+
+echo "\n-- before instance is declared --\n";
+var_dump(in_array('AutoTrait', get_declared_traits()));
+
+echo "\n-- after use is declared --\n";
+
+class MyClass {
+ use AutoTrait;
+}
+
+var_dump(in_array('AutoTrait', get_declared_traits()));
+
+echo "\nDONE\n";
+
+?>
+--EXPECTF--
+*** Testing get_declared_traits() : testing autoloaded traits ***
+
+-- before instance is declared --
+bool(false)
+
+-- after use is declared --
+bool(true)
+
+DONE
diff --git a/ext/standard/tests/class_object/get_object_vars_variation_003.phpt b/ext/standard/tests/class_object/get_object_vars_variation_003.phpt
index adefa793ad..1e68d08ee3 100644
--- a/ext/standard/tests/class_object/get_object_vars_variation_003.phpt
+++ b/ext/standard/tests/class_object/get_object_vars_variation_003.phpt
@@ -65,7 +65,7 @@ $values = array(
// loop through each element of the array for obj
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( get_object_vars($value) );
};
diff --git a/ext/standard/tests/class_object/get_parent_class_variation_002.phpt b/ext/standard/tests/class_object/get_parent_class_variation_002.phpt
index f7e5b9df3f..0d19e22364 100644
--- a/ext/standard/tests/class_object/get_parent_class_variation_002.phpt
+++ b/ext/standard/tests/class_object/get_parent_class_variation_002.phpt
@@ -114,18 +114,23 @@ bool(false)
Arg value 0.5
bool(false)
+Error: 8 - Array to string conversion, %sget_parent_class_variation_002.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sget_parent_class_variation_002.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sget_parent_class_variation_002.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sget_parent_class_variation_002.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sget_parent_class_variation_002.php(%d)
Arg value Array
bool(false)
diff --git a/ext/standard/tests/class_object/is_a_variation_001.phpt b/ext/standard/tests/class_object/is_a_variation_001.phpt
index d2d6ce2407..d449fd3797 100644
--- a/ext/standard/tests/class_object/is_a_variation_001.phpt
+++ b/ext/standard/tests/class_object/is_a_variation_001.phpt
@@ -70,7 +70,7 @@ $values = array(
// loop through each element of the array for object
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( is_a($value, $class_name) );
};
diff --git a/ext/standard/tests/class_object/is_a_variation_002.phpt b/ext/standard/tests/class_object/is_a_variation_002.phpt
index 970da72f1c..a34c325d87 100644
--- a/ext/standard/tests/class_object/is_a_variation_002.phpt
+++ b/ext/standard/tests/class_object/is_a_variation_002.phpt
@@ -75,7 +75,7 @@ $values = array(
// loop through each element of the array for class_name
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( is_a($object, $value) );
};
diff --git a/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt b/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt
index 14aaa3347b..201d8789ea 100644
--- a/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt
+++ b/ext/standard/tests/class_object/is_subclass_of_variation_001.phpt
@@ -115,18 +115,23 @@ bool(false)
Arg value 0.5
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_001.php(%d)
Arg value Array
bool(false)
diff --git a/ext/standard/tests/class_object/is_subclass_of_variation_002.phpt b/ext/standard/tests/class_object/is_subclass_of_variation_002.phpt
index c550d8090c..9bb712b757 100644
--- a/ext/standard/tests/class_object/is_subclass_of_variation_002.phpt
+++ b/ext/standard/tests/class_object/is_subclass_of_variation_002.phpt
@@ -113,22 +113,27 @@ bool(false)
Arg value 0.5
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_002.php(%d)
Arg value Array
Error: 2 - is_subclass_of() expects parameter 2 to be string, array given, %s(%d)
NULL
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_002.php(%d)
Arg value Array
Error: 2 - is_subclass_of() expects parameter 2 to be string, array given, %s(%d)
NULL
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_002.php(%d)
Arg value Array
Error: 2 - is_subclass_of() expects parameter 2 to be string, array given, %s(%d)
NULL
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_002.php(%d)
Arg value Array
Error: 2 - is_subclass_of() expects parameter 2 to be string, array given, %s(%d)
NULL
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_002.php(%d)
Arg value Array
Error: 2 - is_subclass_of() expects parameter 2 to be string, array given, %s(%d)
diff --git a/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt b/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt
index 2f46c4a8df..65ae8a4e23 100644
--- a/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt
+++ b/ext/standard/tests/class_object/is_subclass_of_variation_004.phpt
@@ -115,18 +115,23 @@ bool(false)
Arg value 0.5
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_004.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_004.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_004.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_004.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %sis_subclass_of_variation_004.php(%d)
Arg value Array
bool(false)
diff --git a/ext/standard/tests/class_object/method_exists_variation_001.phpt b/ext/standard/tests/class_object/method_exists_variation_001.phpt
index 117c211d0d..1947c76ac5 100644
--- a/ext/standard/tests/class_object/method_exists_variation_001.phpt
+++ b/ext/standard/tests/class_object/method_exists_variation_001.phpt
@@ -114,18 +114,23 @@ bool(false)
Arg value 0.5
bool(false)
+Error: 8 - Array to string conversion, %smethod_exists_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %smethod_exists_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %smethod_exists_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %smethod_exists_variation_001.php(%d)
Arg value Array
bool(false)
+Error: 8 - Array to string conversion, %smethod_exists_variation_001.php(%d)
Arg value Array
bool(false)
diff --git a/ext/standard/tests/class_object/method_exists_variation_002.phpt b/ext/standard/tests/class_object/method_exists_variation_002.phpt
index ba38894b53..b1204e833d 100644
--- a/ext/standard/tests/class_object/method_exists_variation_002.phpt
+++ b/ext/standard/tests/class_object/method_exists_variation_002.phpt
@@ -113,22 +113,27 @@ bool(false)
Arg value 0.5
bool(false)
+Error: 8 - Array to string conversion, %smethod_exists_variation_002.php(%d)
Arg value Array
Error: 2 - method_exists() expects parameter 2 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %smethod_exists_variation_002.php(%d)
Arg value Array
Error: 2 - method_exists() expects parameter 2 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %smethod_exists_variation_002.php(%d)
Arg value Array
Error: 2 - method_exists() expects parameter 2 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %smethod_exists_variation_002.php(%d)
Arg value Array
Error: 2 - method_exists() expects parameter 2 to be string, array given, %s(77)
NULL
+Error: 8 - Array to string conversion, %smethod_exists_variation_002.php(%d)
Arg value Array
Error: 2 - method_exists() expects parameter 2 to be string, array given, %s(77)
diff --git a/ext/standard/tests/class_object/trait_class_exists_variation_003.phpt b/ext/standard/tests/class_object/trait_class_exists_variation_003.phpt
new file mode 100644
index 0000000000..6a8e55bda0
--- /dev/null
+++ b/ext/standard/tests/class_object/trait_class_exists_variation_003.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test trait_exists() function : usage variations - case sensitivity
+--FILE--
+<?php
+/* Prototype : proto bool trait_exists(string traitname [, bool autoload])
+ * Description: Checks if the trait exists
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+trait caseSensitivityTest {}
+var_dump(trait_exists('casesensitivitytest'));
+
+echo "Done"
+?>
+--EXPECTF--
+bool(true)
+Done \ No newline at end of file
diff --git a/ext/standard/tests/class_object/trait_exists_basic_001.phpt b/ext/standard/tests/class_object/trait_exists_basic_001.phpt
new file mode 100644
index 0000000000..19616ab5c5
--- /dev/null
+++ b/ext/standard/tests/class_object/trait_exists_basic_001.phpt
@@ -0,0 +1,57 @@
+--TEST--
+Test trait_exists() function : basic functionality
+--FILE--
+<?php
+/* Prototype : proto bool trait_exists(string traitname [, bool autoload])
+ * Description: Checks if the trait exists
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+echo "*** Testing trait_exists() : basic functionality ***\n";
+
+function __autoload($traitName) {
+ echo "In __autoload($traitName)\n";
+}
+
+trait MyTrait {}
+
+echo "Calling trait_exists() on non-existent trait with autoload explicitly enabled:\n";
+var_dump( trait_exists('C', true) );
+echo "\nCalling trait_exists() on existing trait with autoload explicitly enabled:\n";
+var_dump( trait_exists('MyTrait', true) );
+
+echo "\nCalling trait_exists() on non-existent trait with autoload explicitly enabled:\n";
+var_dump( trait_exists('D', false) );
+echo "\nCalling trait_exists() on existing trait with autoload explicitly disabled:\n";
+var_dump( trait_exists('MyTrait', false) );
+
+echo "\nCalling trait_exists() on non-existent trait with autoload unspecified:\n";
+var_dump( trait_exists('E') );
+echo "\nCalling trait_exists() on existing trait with autoload unspecified:\n";
+var_dump( trait_exists('MyTrait') );
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing trait_exists() : basic functionality ***
+Calling trait_exists() on non-existent trait with autoload explicitly enabled:
+In __autoload(C)
+bool(false)
+
+Calling trait_exists() on existing trait with autoload explicitly enabled:
+bool(true)
+
+Calling trait_exists() on non-existent trait with autoload explicitly enabled:
+bool(false)
+
+Calling trait_exists() on existing trait with autoload explicitly disabled:
+bool(true)
+
+Calling trait_exists() on non-existent trait with autoload unspecified:
+In __autoload(E)
+bool(false)
+
+Calling trait_exists() on existing trait with autoload unspecified:
+bool(true)
+Done \ No newline at end of file
diff --git a/ext/standard/tests/class_object/trait_exists_error_001.phpt b/ext/standard/tests/class_object/trait_exists_error_001.phpt
new file mode 100644
index 0000000000..b80f06ed2a
--- /dev/null
+++ b/ext/standard/tests/class_object/trait_exists_error_001.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Test trait_exists() function : error conditions (wrong number of arguments)
+--FILE--
+<?php
+/* Prototype : proto bool trait_exists(string traitname [, bool autoload])
+ * Description: Checks if the trait exists
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+/**
+ * Test wrong number of arguments
+ */
+
+echo "*** Testing trait_exists() : error conditions ***\n";
+
+// Zero arguments
+echo "\n-- Testing trait_exists() function with Zero arguments --\n";
+var_dump( trait_exists() );
+
+//Test trait_exists with one more than the expected number of arguments
+echo "\n-- Testing trait_exists() function with more than expected no. of arguments --\n";
+$traitname = 'string_val';
+$autoload = true;
+$extra_arg = 10;
+var_dump( trait_exists($traitname, $autoload, $extra_arg) );
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing trait_exists() : error conditions ***
+
+-- Testing trait_exists() function with Zero arguments --
+
+Warning: trait_exists() expects at least 1 parameter, 0 given in %s on line 16
+NULL
+
+-- Testing trait_exists() function with more than expected no. of arguments --
+
+Warning: trait_exists() expects at most 2 parameters, 3 given in %s on line 23
+NULL
+Done
diff --git a/ext/standard/tests/class_object/trait_exists_variation_001.phpt b/ext/standard/tests/class_object/trait_exists_variation_001.phpt
new file mode 100644
index 0000000000..65ef1993cf
--- /dev/null
+++ b/ext/standard/tests/class_object/trait_exists_variation_001.phpt
@@ -0,0 +1,187 @@
+--TEST--
+Test trait_exists() function : usage variations - unexpected types for agument 1
+--FILE--
+<?php
+/* Prototype : proto bool trait_exists(string traitname [, bool autoload])
+ * Description: Checks if the trait exists
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+function __autoload($traitName) {
+ echo "In __autoload($traitName)\n";
+}
+
+function test_error_handler($err_no, $err_msg, $filename, $linenum, $vars) {
+ echo "Error: $err_no - $err_msg, $filename($linenum)\n";
+}
+set_error_handler('test_error_handler');
+
+echo "*** Testing trait_exists() : usage variations ***\n";
+
+// Initialise function arguments not being substituted (if any)
+$autoload = true;
+
+//get an unset variable
+$unset_var = 10;
+unset ($unset_var);
+
+//array of values to iterate over
+$values = array(
+
+ // int data
+ 0,
+ 1,
+ 12345,
+ -2345,
+
+ // float data
+ 10.5,
+ -10.5,
+ 10.1234567e10,
+ 10.7654321E-10,
+ .5,
+
+ // array data
+ array(),
+ array(0),
+ array(1),
+ array(1, 2),
+ array('color' => 'red', 'item' => 'pen'),
+
+ // null data
+ NULL,
+ null,
+
+ // boolean data
+ true,
+ false,
+ TRUE,
+ FALSE,
+
+ // empty data
+ "",
+ '',
+
+ // object data
+ new stdclass(),
+
+ // undefined data
+ $undefined_var,
+
+ // unset data
+ $unset_var,
+);
+
+// loop through each element of the array for traitname
+
+foreach($values as $value) {
+ echo "\nArg value $value \n";
+ var_dump( trait_exists($value, $autoload) );
+};
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing trait_exists() : usage variations ***
+Error: 8 - Undefined variable: undefined_var, %s(67)
+Error: 8 - Undefined variable: unset_var, %s(70)
+
+Arg value 0
+In __autoload(0)
+bool(false)
+
+Arg value 1
+In __autoload(1)
+bool(false)
+
+Arg value 12345
+In __autoload(12345)
+bool(false)
+
+Arg value -2345
+In __autoload(-2345)
+bool(false)
+
+Arg value 10.5
+In __autoload(10.5)
+bool(false)
+
+Arg value -10.5
+In __autoload(-10.5)
+bool(false)
+
+Arg value 101234567000
+In __autoload(101234567000)
+bool(false)
+
+Arg value 1.07654321E-9
+In __autoload(1.07654321E-9)
+bool(false)
+
+Arg value 0.5
+In __autoload(0.5)
+bool(false)
+Error: 8 - Array to string conversion, %strait_exists_variation_001.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 1 to be string, array given, %s(77)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_001.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 1 to be string, array given, %s(77)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_001.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 1 to be string, array given, %s(77)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_001.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 1 to be string, array given, %s(77)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_001.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 1 to be string, array given, %s(77)
+NULL
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value 1
+In __autoload(1)
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value 1
+In __autoload(1)
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+Error: 4096 - Object of class stdClass could not be converted to string, %s(76)
+
+Arg value
+Error: 2 - trait_exists() expects parameter 1 to be string, object given, %s(77)
+NULL
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+Done \ No newline at end of file
diff --git a/ext/standard/tests/class_object/trait_exists_variation_002.phpt b/ext/standard/tests/class_object/trait_exists_variation_002.phpt
new file mode 100644
index 0000000000..a2fcbbf018
--- /dev/null
+++ b/ext/standard/tests/class_object/trait_exists_variation_002.phpt
@@ -0,0 +1,198 @@
+--TEST--
+Test trait_exists() function : usage variations - unexpected types for agument 2
+--FILE--
+<?php
+/* Prototype : proto bool trait_exists(string traitname [, bool autoload])
+ * Description: Checks if the trait exists
+ * Source code: Zend/zend_builtin_functions.c
+ * Alias to functions:
+ */
+
+function __autoload($traitName) {
+ echo "In __autoload($traitName)\n";
+}
+
+function test_error_handler($err_no, $err_msg, $filename, $linenum, $vars) {
+ echo "Error: $err_no - $err_msg, $filename($linenum)\n";
+}
+set_error_handler('test_error_handler');
+
+echo "*** Testing trait_exists() : usage variations ***\n";
+
+// Initialise function arguments not being substituted (if any)
+$traitname = 'string_val';
+
+//get an unset variable
+$unset_var = 10;
+unset ($unset_var);
+
+//array of values to iterate over
+$values = array(
+
+ // int data
+ 0,
+ 1,
+ 12345,
+ -2345,
+
+ // float data
+ 10.5,
+ -10.5,
+ 10.1234567e10,
+ 10.7654321E-10,
+ .5,
+
+ // array data
+ array(),
+ array(0),
+ array(1),
+ array(1, 2),
+ array('color' => 'red', 'item' => 'pen'),
+
+ // null data
+ NULL,
+ null,
+
+ // boolean data
+ true,
+ false,
+ TRUE,
+ FALSE,
+
+ // empty data
+ "",
+ '',
+
+ // string data
+ "string",
+ 'string',
+
+ // object data
+ new stdclass(),
+
+ // undefined data
+ $undefined_var,
+
+ // unset data
+ $unset_var,
+);
+
+// loop through each element of the array for autoload
+
+foreach($values as $value) {
+ echo "\nArg value $value \n";
+ var_dump( trait_exists($traitname, $value) );
+};
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing trait_exists() : usage variations ***
+Error: 8 - Undefined variable: undefined_var, %s(71)
+Error: 8 - Undefined variable: unset_var, %s(74)
+
+Arg value 0
+bool(false)
+
+Arg value 1
+In __autoload(string_val)
+bool(false)
+
+Arg value 12345
+In __autoload(string_val)
+bool(false)
+
+Arg value -2345
+In __autoload(string_val)
+bool(false)
+
+Arg value 10.5
+In __autoload(string_val)
+bool(false)
+
+Arg value -10.5
+In __autoload(string_val)
+bool(false)
+
+Arg value 101234567000
+In __autoload(string_val)
+bool(false)
+
+Arg value 1.07654321E-9
+In __autoload(string_val)
+bool(false)
+
+Arg value 0.5
+In __autoload(string_val)
+bool(false)
+Error: 8 - Array to string conversion, %strait_exists_variation_002.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 2 to be boolean, array given, %s(81)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_002.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 2 to be boolean, array given, %s(81)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_002.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 2 to be boolean, array given, %s(81)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_002.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 2 to be boolean, array given, %s(81)
+NULL
+Error: 8 - Array to string conversion, %strait_exists_variation_002.php(%d)
+
+Arg value Array
+Error: 2 - trait_exists() expects parameter 2 to be boolean, array given, %s(81)
+NULL
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value 1
+In __autoload(string_val)
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value 1
+In __autoload(string_val)
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+
+Arg value string
+In __autoload(string_val)
+bool(false)
+
+Arg value string
+In __autoload(string_val)
+bool(false)
+Error: 4096 - Object of class stdClass could not be converted to string, %s(80)
+
+Arg value
+Error: 2 - trait_exists() expects parameter 2 to be boolean, object given, %s(81)
+NULL
+
+Arg value
+bool(false)
+
+Arg value
+bool(false)
+Done \ No newline at end of file
diff --git a/ext/standard/tests/dir/chdir_variation1.phpt b/ext/standard/tests/dir/chdir_variation1.phpt
index a7cf857f7f..c4c0431ccc 100644
--- a/ext/standard/tests/dir/chdir_variation1.phpt
+++ b/ext/standard/tests/dir/chdir_variation1.phpt
@@ -201,7 +201,7 @@ bool(false)
-- Iteration 18 --
-Warning: chdir() expects parameter 1 to be string, array given in %s on line %d
+Warning: chdir() expects parameter 1 to be a valid path, array given in %s on line %d
bool(false)
-- Iteration 19 --
@@ -230,6 +230,6 @@ bool(false)
-- Iteration 25 --
-Warning: chdir() expects parameter 1 to be string, resource given in %s on line %d
+Warning: chdir() expects parameter 1 to be a valid path, resource given in %s on line %d
bool(false)
===DONE===
diff --git a/ext/standard/tests/dir/dir_variation1-win32.phpt b/ext/standard/tests/dir/dir_variation1-win32.phpt
new file mode 100644
index 0000000000..1f7f4a2cf3
--- /dev/null
+++ b/ext/standard/tests/dir/dir_variation1-win32.phpt
@@ -0,0 +1,170 @@
+--TEST--
+Test dir() function : usage variations - unexpected value for 'dir' argument
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/*
+ * Prototype : object dir(string $directory[, resource $context])
+ * Description: Directory class with properties, handle and class and methods read, rewind and close
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Passing non string values to 'directory' argument of dir() and see
+ * that the function outputs proper warning messages wherever expected.
+ */
+
+echo "*** Testing dir() : unexpected values for \$directory argument ***\n";
+
+// get an unset variable
+$unset_var = 10;
+unset($unset_var);
+
+class A
+{
+ public $var;
+ public function init() {
+ $this->var = 10;
+ }
+}
+
+// get a resource variable
+$fp = fopen(__FILE__, "r"); // get a file handle
+$dfp = opendir( dirname(__FILE__) ); // get a dir handle
+
+// unexpected values to be passed to $directory argument
+$unexpected_values = array (
+
+ // array data
+/*1*/ array(),
+ array(0),
+ array(1),
+ array(1, 2),
+ array('color' => 'red', 'item' => 'pen'),
+
+ // null data
+/*6*/ NULL,
+ null,
+
+ // boolean data
+/*8*/ true,
+ false,
+ TRUE,
+ FALSE,
+
+ // empty data
+/*12*/ "",
+ '',
+
+ // undefined data
+/*14*/ @$undefined_var,
+
+ // unset data
+/*15*/ @$unset_var,
+
+ // resource variable(dir and file handle)
+/*16*/ $fp,
+ $dfp,
+
+ // object data
+/*18*/ new A()
+);
+
+// loop through various elements of $unexpected_values to check the behavior of dir()
+$iterator = 1;
+foreach( $unexpected_values as $unexpected_value ) {
+ echo "\n-- Iteration $iterator --\n";
+ var_dump( dir($unexpected_value) );
+ $iterator++;
+}
+
+fclose($fp);
+closedir($dfp);
+echo "Done";
+?>
+--EXPECTF--
+*** Testing dir() : unexpected values for $directory argument ***
+
+-- Iteration 1 --
+
+Warning: dir() expects parameter 1 to be string, array given in %s on line %d
+NULL
+
+-- Iteration 2 --
+
+Warning: dir() expects parameter 1 to be string, array given in %s on line %d
+NULL
+
+-- Iteration 3 --
+
+Warning: dir() expects parameter 1 to be string, array given in %s on line %d
+NULL
+
+-- Iteration 4 --
+
+Warning: dir() expects parameter 1 to be string, array given in %s on line %d
+NULL
+
+-- Iteration 5 --
+
+Warning: dir() expects parameter 1 to be string, array given in %s on line %d
+NULL
+
+-- Iteration 6 --
+bool(false)
+
+-- Iteration 7 --
+bool(false)
+
+-- Iteration 8 --
+
+Warning: dir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: dir(1): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 9 --
+bool(false)
+
+-- Iteration 10 --
+
+Warning: dir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: dir(1): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 11 --
+bool(false)
+
+-- Iteration 12 --
+bool(false)
+
+-- Iteration 13 --
+bool(false)
+
+-- Iteration 14 --
+bool(false)
+
+-- Iteration 15 --
+bool(false)
+
+-- Iteration 16 --
+
+Warning: dir() expects parameter 1 to be string, resource given in %s on line %d
+NULL
+
+-- Iteration 17 --
+
+Warning: dir() expects parameter 1 to be string, resource given in %s on line %d
+NULL
+
+-- Iteration 18 --
+
+Warning: dir() expects parameter 1 to be string, object given in %s on line %d
+NULL
+Done \ No newline at end of file
diff --git a/ext/standard/tests/dir/dir_variation5-win32.phpt b/ext/standard/tests/dir/dir_variation5-win32.phpt
new file mode 100644
index 0000000000..e70b9d3533
--- /dev/null
+++ b/ext/standard/tests/dir/dir_variation5-win32.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Test dir() function : usage variations - open a file instead of directory
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/*
+ * Prototype : object dir(string $directory[, resource $context])
+ * Description: Directory class with properties, handle and class and methods read, rewind and close
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Passing a file as argument to dir() function instead of a directory
+ * and checking if proper warning message is generated.
+ */
+
+echo "*** Testing dir() : open a file instead of a directory ***\n";
+
+// open the file instead of directory
+$d = dir(__FILE__);
+var_dump( $d );
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing dir() : open a file instead of a directory ***
+
+Warning: dir(%s): The directory name is invalid. (code: %d) in %s on line %d
+
+Warning: dir(%s): failed to open dir: %s in %s on line %d
+bool(false)
+Done
diff --git a/ext/standard/tests/dir/dir_variation6-win32.phpt b/ext/standard/tests/dir/dir_variation6-win32.phpt
new file mode 100644
index 0000000000..e0e4749809
--- /dev/null
+++ b/ext/standard/tests/dir/dir_variation6-win32.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Test dir() function : usage variations - non-existent directory
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/*
+ * Prototype : object dir(string $directory[, resource $context])
+ * Description: Directory class with properties, handle and class and methods read, rewind and close
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Passing a non-existent directory as argument to dir() function
+ * and checking to see if proper warning message is output.
+ */
+echo "*** Testing dir() : open a non-existent directory ***\n";
+
+// create the temporary directory
+$file_path = dirname(__FILE__);
+$dir_path = $file_path."/dir_variation6";
+@mkdir($dir_path);
+
+// open existent directory
+$d = dir($dir_path);
+$d->close(); //close the dir
+
+// remove directory and try to open the same(non-existent) directory again
+rmdir($dir_path);
+clearstatcache();
+
+echo "-- opening previously removed directory --\n";
+var_dump( dir($dir_path) );
+
+// point to a non-existent directory
+$non_existent_dir = $file_path."/non_existent_dir";
+echo "-- opening non-existent directory --\n";
+$d = dir($non_existent_dir);
+var_dump( $d );
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing dir() : open a non-existent directory ***
+-- opening previously removed directory --
+
+Warning: dir(%s): The system cannot find the file specified. (code: %d) in %s on line %d
+
+Warning: dir(%s): failed to open dir: %s in %s on line %d
+bool(false)
+-- opening non-existent directory --
+
+Warning: dir(%s): The system cannot find the file specified. (code: %d) in %s on line %d
+
+Warning: dir(%s): failed to open dir: %s in %s on line %d
+bool(false)
+Done
diff --git a/ext/standard/tests/dir/dir_variation8-win32.phpt b/ext/standard/tests/dir/dir_variation8-win32.phpt
new file mode 100644
index 0000000000..a56c98b880
--- /dev/null
+++ b/ext/standard/tests/dir/dir_variation8-win32.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Test dir() function : usage variations - checking with wildcard characters
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/*
+ * Prototype : object dir(string $directory[, resource $context])
+ * Description: Directory class with properties, handle and class and methods read, rewind and close
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Create more than one temporary directory & subdirectory and check if dir() function can open
+ * those directories when wildcard characters are used to refer to them.
+ */
+
+echo "*** Testing dir() : checking with wildcard characters ***\n";
+
+// create the temporary directories
+$file_path = dirname(__FILE__);
+$dir_path = $file_path."/dir_variation81";
+$sub_dir_path = $dir_path."/sub_dir1";
+
+@mkdir($dir_path1);
+@mkdir($sub_dir_path);
+
+/* with different wildcard characters */
+
+echo "-- wildcard = '*' --\n";
+var_dump( dir($file_path."/dir_var*") );
+var_dump( dir($file_path."/*") );
+
+echo "-- wildcard = '?' --\n";
+var_dump( dir($dir_path."/sub_dir?") );
+var_dump( dir($dir_path."/sub?dir1") );
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing dir() : checking with wildcard characters ***
+-- wildcard = '*' --
+
+Warning: dir(%s/dir_var*,%s/dir_var*): %r(No such file or directory|The system cannot find the path specified. \(code: 3\))%r in %s on line %d
+
+Warning: dir(%s/dir_var*): failed to open dir: %s in %s on line %d
+bool(false)
+
+Warning: dir(%s/*,%s/*): %r(No such file or directory|The system cannot find the path specified. \(code: 3\))%r in %s on line %d
+
+Warning: dir(%s/*): failed to open dir: %s in %s on line %d
+bool(false)
+-- wildcard = '?' --
+
+Warning: dir(%s/dir_variation81/sub_dir?,%s/dir_variation81/sub_dir?): %r(No such file or directory|The system cannot find the path specified. \(code: 3\))%r in %s on line %d
+
+Warning: dir(%s/dir_variation81/sub_dir?): failed to open dir: %s in %s on line %d
+bool(false)
+
+Warning: dir(%s/dir_variation81/sub?dir1,%s/dir_variation81/sub?dir1): %r(No such file or directory|The system cannot find the path specified. \(code: 3\))%r in %s on line %d
+
+Warning: dir(%s/dir_variation81/sub?dir1): failed to open dir: %s in %s on line %d
+bool(false)
+Done
diff --git a/ext/standard/tests/dir/dir_variation9-win32.phpt b/ext/standard/tests/dir/dir_variation9-win32.phpt
new file mode 100644
index 0000000000..32b0bd946b
--- /dev/null
+++ b/ext/standard/tests/dir/dir_variation9-win32.phpt
@@ -0,0 +1,125 @@
+--TEST--
+Test dir() function : usage variations - relative valid and invalid paths
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/*
+ * Prototype : object dir(string $directory[, resource $context])
+ * Description: Directory class with properties, handle and class and methods read, rewind and close
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Checking the behavior of dir() function by passing directories which
+ * have valid and invalid relative path.
+ */
+
+echo "*** Testing dir() : checking with valid and invalid paths ***\n";
+
+/* create the temporary directories */
+
+$file_path = dirname(__FILE__);
+
+// directory dir_variation91 with one sub-directory sub_dir11 and sub-sub-directory sub_dir111
+$dir_path1 = $file_path."/dir_variation91";
+$sub_dir11 = $dir_path1."/sub_dir11";
+$sub_dir111 = $sub_dir11."/sub_dir111";
+
+// directory dir_variation92 with one sub-directory sub_dir21
+$dir_path2 = $file_path."/dir_variation92";
+$sub_dir21 = $dir_path2."/sub_dir21";
+
+@mkdir($dir_path1);
+@mkdir($dir_path2);
+@mkdir($sub_dir11);
+@mkdir($sub_dir111);
+@mkdir($sub_dir21);
+
+// open the directory with valid paths
+echo "\n-- With valid paths --\n";
+var_dump( dir("$dir_path1/sub_dir11/sub_dir111/..") );
+var_dump( dir("$dir_path2/sub_dir21/../../dir_variation91") );
+var_dump( dir("$dir_path2/sub_dir21/../../dir_variation91/sub_dir11/..") );
+var_dump( dir("$dir_path1/sub_dir11/sub_dir111/../../../dir_variation92/sub_dir21/..") );
+
+// open the directory with invalid path
+echo "\n-- With invalid paths --\n";
+var_dump( dir("$dir_path1/sub_dir12/sub_dir111/..") );
+var_dump( dir("$dir_path2/sub_dir21/../dir_variation91") );
+var_dump( dir("$dir_path2/sub_dir21/../../dir_variation91/sub_dir12/..") );
+var_dump( dir("$dir_path1/sub_dir11/sub_dir111/../../dir_variation92/sub_dir21/..") );
+
+echo "Done";
+?>
+--CLEAN--
+<?php
+$file_path = dirname(__FILE__);
+
+$dir_path1 = $file_path."/dir_variation91";
+$sub_dir11 = $dir_path1."/sub_dir11";
+$sub_dir111 = $sub_dir11."/sub_dir111";
+$dir_path2 = $file_path."/dir_variation92";
+$sub_dir21 = $dir_path2."/sub_dir21";
+
+rmdir($sub_dir21);
+rmdir($sub_dir111);
+rmdir($sub_dir11);
+rmdir($dir_path1);
+rmdir($dir_path2);
+?>
+--EXPECTF--
+*** Testing dir() : checking with valid and invalid paths ***
+
+-- With valid paths --
+object(Directory)#%d (2) {
+ ["path"]=>
+ string(%d) "%s/dir_variation91/sub_dir11/sub_dir111/.."
+ ["handle"]=>
+ resource(%d) of type (stream)
+}
+object(Directory)#%d (2) {
+ ["path"]=>
+ string(%d) "%s/dir_variation92/sub_dir21/../../dir_variation91"
+ ["handle"]=>
+ resource(%d) of type (stream)
+}
+object(Directory)#%d (2) {
+ ["path"]=>
+ string(%d) "%s/dir_variation92/sub_dir21/../../dir_variation91/sub_dir11/.."
+ ["handle"]=>
+ resource(%d) of type (stream)
+}
+object(Directory)#%d (2) {
+ ["path"]=>
+ string(%d) "%s/dir_variation91/sub_dir11/sub_dir111/../../../dir_variation92/sub_dir21/.."
+ ["handle"]=>
+ resource(%d) of type (stream)
+}
+
+-- With invalid paths --
+
+Warning: dir(%sdir_variation91/sub_dir12/sub_dir111/..,%sdir_variation91/sub_dir12/sub_dir111/..): The system cannot find the path specified. (code: 3) in %sdir_variation9-win32.php on line %d
+
+Warning: dir(%s/dir_variation91/sub_dir12/sub_dir111/..): failed to open dir: %s in %s on line %d
+bool(false)
+
+Warning: dir(%sdir_variation92/sub_dir21/../dir_variation91,%sdir_variation92/sub_dir21/../dir_variation91): The system cannot find the file specified. (code: 2) in %sdir_variation9-win32.php on line %d
+
+Warning: dir(%s/dir_variation92/sub_dir21/../dir_variation91): failed to open dir: %s in %s on line %d
+bool(false)
+
+Warning: dir(%sdir_variation92/sub_dir21/../../dir_variation91/sub_dir12/..,%sdir_variation92/sub_dir21/../../dir_variation91/sub_dir12/..): The system cannot find the file specified. (code: 2) in %sdir_variation9-win32.php on line %d
+
+Warning: dir(%s/dir_variation92/sub_dir21/../../dir_variation91/sub_dir12/..): failed to open dir: %s in %s on line %d
+bool(false)
+
+Warning: dir(%sdir_variation91/sub_dir11/sub_dir111/../../dir_variation92/sub_dir21/..,%sdir_variation91/sub_dir11/sub_dir111/../../dir_variation92/sub_dir21/..): The system cannot find the path specified. (code: 3) in %sdir_variation9-win32.php on line %d
+
+Warning: dir(%s/dir_variation91/sub_dir11/sub_dir111/../../dir_variation92/sub_dir21/..): failed to open dir: %s in %s on line %d
+bool(false)
+Done
diff --git a/ext/standard/tests/dir/opendir_error2-win32.phpt b/ext/standard/tests/dir/opendir_error2-win32.phpt
new file mode 100644
index 0000000000..c3ecd35349
--- /dev/null
+++ b/ext/standard/tests/dir/opendir_error2-win32.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Test opendir() function : error conditions - Non-existent directory
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/* Prototype : mixed opendir(string $path[, resource $context])
+ * Description: Open a directory and return a dir_handle
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Pass a non-existent directory as $path argument to opendir() to test behaviour
+ */
+
+echo "*** Testing opendir() : error conditions ***\n";
+
+echo "\n-- Pass a non-existent absolute path: --\n";
+$path = dirname(__FILE__) . "/idonotexist";
+var_dump(opendir($path));
+
+echo "\n-- Pass a non-existent relative path: --\n";
+chdir(dirname(__FILE__));
+var_dump(opendir('idonotexist'));
+?>
+===DONE===
+--EXPECTF--
+*** Testing opendir() : error conditions ***
+
+-- Pass a non-existent absolute path: --
+
+Warning: opendir(%s/idonotexist,%s/idonotexist): The system cannot find the file specified. (code: %d) in %s on line %d
+
+Warning: opendir(%s/idonotexist): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Pass a non-existent relative path: --
+
+Warning: opendir(idonotexist,idonotexist): The system cannot find the file specified. (code: %d) in %s on line %d
+
+Warning: opendir(idonotexist): failed to open dir: %s in %s on line %d
+bool(false)
+===DONE===
diff --git a/ext/standard/tests/dir/opendir_variation1-win32.phpt b/ext/standard/tests/dir/opendir_variation1-win32.phpt
new file mode 100644
index 0000000000..9a75a5b6a7
--- /dev/null
+++ b/ext/standard/tests/dir/opendir_variation1-win32.phpt
@@ -0,0 +1,248 @@
+--TEST--
+Test opendir() function : usage variations - different data types as $path arg
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/* Prototype : mixed opendir(string $path[, resource $context])
+ * Description: Open a directory and return a dir_handle
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Pass different data types as $path argument to opendir() to test behaviour
+ * Where possible, an existing directory has been entered as a string value
+ */
+
+echo "*** Testing opendir() : usage variations ***\n";
+
+// create directory to be passed as string value where possible
+$path = dirname(__FILE__) . "/opendir_variation1";
+mkdir($path);
+
+//get an unset variable
+$unset_var = 10;
+unset ($unset_var);
+
+// get a class
+class classA {
+
+ var $path;
+ function __construct($path) {
+ $this->path = $path;
+ }
+ public function __toString() {
+ return $this->path;
+ }
+}
+
+// heredoc string
+$heredoc = <<<EOT
+$path
+EOT;
+
+// get a resource variable
+$fp = fopen(__FILE__, "r");
+
+// unexpected values to be passed to $path argument
+$inputs = array(
+
+ // int data
+/*1*/ 0,
+ 1,
+ 12345,
+ -2345,
+
+ // float data
+/*5*/ 10.5,
+ -10.5,
+ 12.3456789000e10,
+ 12.3456789000E-10,
+ .5,
+
+ // null data
+/*10*/ NULL,
+ null,
+
+ // boolean data
+/*12*/ true,
+ false,
+ TRUE,
+ FALSE,
+
+ // empty data
+/*16*/ "",
+ '',
+ array(),
+
+ // string data
+/*19*/ "$path",
+ 'string',
+ $heredoc,
+
+ // object data
+/*22*/ new classA($path),
+
+ // undefined data
+/*23*/ @$undefined_var,
+
+ // unset data
+/*24*/ @$unset_var,
+
+ // resource variable
+/*25*/ $fp
+);
+
+// loop through each element of $inputs to check the behavior of opendir()
+$iterator = 1;
+foreach($inputs as $input) {
+ echo "\n-- Iteration $iterator --\n";
+ var_dump( $dh = opendir($input) );
+ if ($dh) {
+ closedir($dh);
+ }
+ $iterator++;
+};
+
+fclose($fp);
+?>
+===DONE===
+--CLEAN--
+<?php
+$path = dirname(__FILE__) . "/opendir_variation1";
+rmdir($path);
+?>
+--EXPECTF--
+*** Testing opendir() : usage variations ***
+
+-- Iteration 1 --
+
+Warning: opendir(0,0): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(0): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 2 --
+
+Warning: opendir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(1): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 3 --
+
+Warning: opendir(12345,12345): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(12345): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 4 --
+
+Warning: opendir(-2345,-2345): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(-2345): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 5 --
+
+Warning: opendir(10.5,10.5): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(10.5): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 6 --
+
+Warning: opendir(-10.5,-10.5): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(-10.5): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 7 --
+
+Warning: opendir(123456789000,123456789000): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(123456789000): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 8 --
+
+Warning: opendir(1.23456789E-9,1.23456789E-9): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(1.23456789E-9): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 9 --
+
+Warning: opendir(0.5,0.5): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(0.5): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 10 --
+bool(false)
+
+-- Iteration 11 --
+bool(false)
+
+-- Iteration 12 --
+
+Warning: opendir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(1): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 13 --
+bool(false)
+
+-- Iteration 14 --
+
+Warning: opendir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(1): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 15 --
+bool(false)
+
+-- Iteration 16 --
+bool(false)
+
+-- Iteration 17 --
+bool(false)
+
+-- Iteration 18 --
+
+Warning: opendir() expects parameter 1 to be string, array given in %s on line %d
+NULL
+
+-- Iteration 19 --
+resource(%d) of type (stream)
+
+-- Iteration 20 --
+
+Warning: opendir(string,string): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: opendir(string): failed to open dir: %s in %s on line %d
+bool(false)
+
+-- Iteration 21 --
+resource(%d) of type (stream)
+
+-- Iteration 22 --
+resource(%d) of type (stream)
+
+-- Iteration 23 --
+bool(false)
+
+-- Iteration 24 --
+bool(false)
+
+-- Iteration 25 --
+
+Warning: opendir() expects parameter 1 to be string, resource given in %s on line %d
+NULL
+===DONE===
diff --git a/ext/standard/tests/dir/readdir_variation4.phpt b/ext/standard/tests/dir/readdir_variation4.phpt
index 4c22de8697..9b04a986a6 100644
--- a/ext/standard/tests/dir/readdir_variation4.phpt
+++ b/ext/standard/tests/dir/readdir_variation4.phpt
@@ -51,7 +51,7 @@ $iterator = 1;
foreach($inputs as $key => $input) {
echo "\n-- Iteration $iterator --\n";
$handle = "fp{$iterator}";
- var_dump( $$handle = fopen($dir_path . $input . '.tmp', 'w') );
+ var_dump( $$handle = fopen(@"$dir_path$input.tmp", 'w') );
var_dump( fwrite($$handle, $key));
fclose($$handle);
$iterator++;
diff --git a/ext/standard/tests/dir/scandir_basic.phpt b/ext/standard/tests/dir/scandir_basic.phpt
index 25700a7a4f..7a044da529 100644
--- a/ext/standard/tests/dir/scandir_basic.phpt
+++ b/ext/standard/tests/dir/scandir_basic.phpt
@@ -25,7 +25,7 @@ echo "\n-- scandir() with mandatory arguments --\n";
var_dump(scandir($directory));
echo "\n-- scandir() with all arguments --\n";
-$sorting_order = 1;
+$sorting_order = SCANDIR_SORT_DESCENDING;
$context = stream_context_create();
var_dump(scandir($directory, $sorting_order, $context));
diff --git a/ext/standard/tests/dir/scandir_error2-win32.phpt b/ext/standard/tests/dir/scandir_error2-win32.phpt
new file mode 100644
index 0000000000..9920be747d
--- /dev/null
+++ b/ext/standard/tests/dir/scandir_error2-win32.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Test scandir() function : error conditions - Non-existent directory
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/* Prototype : array scandir(string $dir [, int $sorting_order [, resource $context]])
+ * Description: List files & directories inside the specified path
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Pass a directory that does not exist to scandir() to test error messages
+ */
+
+echo "*** Testing scandir() : error conditions ***\n";
+
+$directory = dirname(__FILE__) . '/idonotexist';
+
+echo "\n-- Pass scandir() an absolute path that does not exist --\n";
+var_dump(scandir($directory));
+
+echo "\n-- Pass scandir() a relative path that does not exist --\n";
+var_dump(scandir('/idonotexist'));
+?>
+===DONE===
+--EXPECTF--
+*** Testing scandir() : error conditions ***
+
+-- Pass scandir() an absolute path that does not exist --
+
+Warning: scandir(%s/idonotexist,%s/idonotexist): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(%s/idonotexist): failed to open dir: %s in %s on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Pass scandir() a relative path that does not exist --
+
+Warning: scandir(/idonotexist,/idonotexist): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(/idonotexist): failed to open dir: %s in %s on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+===DONE===
diff --git a/ext/standard/tests/dir/scandir_variation1-win32.phpt b/ext/standard/tests/dir/scandir_variation1-win32.phpt
new file mode 100644
index 0000000000..a2b5bd4672
--- /dev/null
+++ b/ext/standard/tests/dir/scandir_variation1-win32.phpt
@@ -0,0 +1,289 @@
+--TEST--
+Test scandir() function : usage variations - different data types as $dir arg
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/* Prototype : array scandir(string $dir [, int $sorting_order [, resource $context]])
+ * Description: List files & directories inside the specified path
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Pass different data types as $dir argument to test behaviour of scandir()
+ */
+
+echo "*** Testing scandir() : usage variations ***\n";
+
+//get an unset variable
+$unset_var = 10;
+unset ($unset_var);
+
+// get a class
+class classA
+{
+ public function __toString() {
+ return "Class A object";
+ }
+}
+
+// heredoc string
+$heredoc = <<<EOT
+hello world
+EOT;
+
+// get a resource variable
+$fp = fopen(__FILE__, "r");
+
+// unexpected values to be passed to $dir argument
+$inputs = array(
+
+ // int data
+/*1*/ 0,
+ 1,
+ 12345,
+ -2345,
+
+ // float data
+/*5*/ 10.5,
+ -10.5,
+ 12.3456789000e10,
+ 12.3456789000E-10,
+ .5,
+
+ // null data
+/*10*/ NULL,
+ null,
+
+ // boolean data
+/*12*/ true,
+ false,
+ TRUE,
+ FALSE,
+
+ // empty data
+/*16*/ "",
+ '',
+ array(),
+
+ // string data
+/*19*/ "string",
+ 'string',
+ $heredoc,
+
+ // object data
+/*22*/ new classA(),
+
+ // undefined data
+/*23*/ @$undefined_var,
+
+ // unset data
+/*24*/ @$unset_var,
+
+ // resource variable
+/*25*/ $fp
+);
+
+// loop through each element of $inputs to check the behavior of scandir()
+$iterator = 1;
+foreach($inputs as $input) {
+ echo "\n-- Iteration $iterator --\n";
+ var_dump( scandir($input) );
+ $iterator++;
+};
+
+fclose($fp);
+?>
+===DONE===
+--EXPECTF--
+*** Testing scandir() : usage variations ***
+
+-- Iteration 1 --
+
+Warning: scandir(0,0): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(0): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 2 --
+
+Warning: scandir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(1): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 3 --
+
+Warning: scandir(12345,12345): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(12345): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 4 --
+
+Warning: scandir(-2345,-2345): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(-2345): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 5 --
+
+Warning: scandir(10.5,10.5): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(10.5): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 6 --
+
+Warning: scandir(-10.5,-10.5): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(-10.5): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 7 --
+
+Warning: scandir(123456789000,123456789000): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(123456789000): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 8 --
+
+Warning: scandir(1.23456789E-9,1.23456789E-9): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(1.23456789E-9): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 9 --
+
+Warning: scandir(0.5,0.5): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(0.5): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 10 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 11 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 12 --
+
+Warning: scandir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(1): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 13 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 14 --
+
+Warning: scandir(1,1): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(1): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 15 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 16 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 17 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 18 --
+
+Warning: scandir() expects parameter 1 to be a valid path, array given in %s on line %d
+NULL
+
+-- Iteration 19 --
+
+Warning: scandir(string,string): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(string): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 20 --
+
+Warning: scandir(string,string): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(string): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 21 --
+
+Warning: scandir(hello world,hello world): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(hello world): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 22 --
+
+Warning: scandir(Class A object,Class A object): The system cannot find the file specified. (code: 2) in %s on line %d
+
+Warning: scandir(Class A object): failed to open dir: No such file or directory in %sscandir_variation1-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Iteration 23 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 24 --
+
+Warning: scandir(): Directory name cannot be empty in %s on line %d
+bool(false)
+
+-- Iteration 25 --
+
+Warning: scandir() expects parameter 1 to be a valid path, resource given in %s on line %d
+NULL
+===DONE===
diff --git a/ext/standard/tests/dir/scandir_variation1.phpt b/ext/standard/tests/dir/scandir_variation1.phpt
index 9988ca368a..ccd5bb967a 100644
--- a/ext/standard/tests/dir/scandir_variation1.phpt
+++ b/ext/standard/tests/dir/scandir_variation1.phpt
@@ -211,7 +211,7 @@ bool(false)
-- Iteration 18 --
-Warning: scandir() expects parameter 1 to be string, array given in %s on line %d
+Warning: scandir() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 19 --
@@ -254,6 +254,6 @@ bool(false)
-- Iteration 25 --
-Warning: scandir() expects parameter 1 to be string, resource given in %s on line %d
+Warning: scandir() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
===DONE===
diff --git a/ext/standard/tests/dir/scandir_variation10.phpt b/ext/standard/tests/dir/scandir_variation10.phpt
new file mode 100644
index 0000000000..412836b2ba
--- /dev/null
+++ b/ext/standard/tests/dir/scandir_variation10.phpt
@@ -0,0 +1,79 @@
+--TEST--
+Test scandir() function : usage variations - different sorting constants
+--FILE--
+<?php
+/* Prototype : array scandir(string $dir [, int $sorting_order [, resource $context]])
+ * Description: List files & directories inside the specified path
+ * Source code: ext/standard/dir.c
+ */
+
+printf("SCANDIR_SORT_ASCENDING: %d\n", SCANDIR_SORT_ASCENDING);
+printf("SCANDIR_SORT_DESCENDING: %d\n", SCANDIR_SORT_DESCENDING);
+printf("SCANDIR_SORT_NONE: %d\n", SCANDIR_SORT_NONE);
+
+/*
+ * Pass different integers as $sorting_order argument to test how scandir()
+ * re-orders the array
+ */
+
+echo "*** Testing scandir() : usage variations ***\n";
+
+// include for create_files/delete_files functions
+include(dirname(__FILE__) . '/../file/file.inc');
+
+// create directory and files
+$dir = dirname(__FILE__) . '/scandir_variation10';
+mkdir($dir);
+@create_files($dir, 2);
+
+// Deterministic tests.
+var_dump(scandir($dir, SCANDIR_SORT_ASCENDING));
+var_dump(scandir($dir, SCANDIR_SORT_DESCENDING));
+
+// Non-deterministic tests.
+$files = scandir($dir, SCANDIR_SORT_NONE);
+var_dump(count($files));
+var_dump(in_array('.', $files));
+var_dump(in_array('..', $files));
+var_dump(in_array('file1.tmp', $files));
+var_dump(in_array('file2.tmp', $files));
+
+delete_files($dir, 2);
+?>
+===DONE===
+--CLEAN--
+<?php
+$dir = dirname(__FILE__) . '/scandir_variation10';
+rmdir($dir);
+?>
+--EXPECTF--
+SCANDIR_SORT_ASCENDING: 0
+SCANDIR_SORT_DESCENDING: 1
+SCANDIR_SORT_NONE: 2
+*** Testing scandir() : usage variations ***
+array(4) {
+ [0]=>
+ string(1) "."
+ [1]=>
+ string(2) ".."
+ [2]=>
+ string(9) "file1.tmp"
+ [3]=>
+ string(9) "file2.tmp"
+}
+array(4) {
+ [0]=>
+ string(9) "file2.tmp"
+ [1]=>
+ string(9) "file1.tmp"
+ [2]=>
+ string(2) ".."
+ [3]=>
+ string(1) "."
+}
+int(4)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+===DONE===
diff --git a/ext/standard/tests/dir/scandir_variation3.phpt b/ext/standard/tests/dir/scandir_variation3.phpt
index 8e23faf2d4..58da5e2c53 100644
--- a/ext/standard/tests/dir/scandir_variation3.phpt
+++ b/ext/standard/tests/dir/scandir_variation3.phpt
@@ -16,7 +16,7 @@ echo "*** Testing scandir() : usage variations ***\n";
// Initialise function arguments not being substituted
$dir = dirname(__FILE__) . '/scandir_variation3';
mkdir($dir);
-$sorting_order = 0;
+$sorting_order = SCANDIR_SORT_ASCENDING;
//get an unset variable
$unset_var = 10;
diff --git a/ext/standard/tests/dir/scandir_variation6-win32.phpt b/ext/standard/tests/dir/scandir_variation6-win32.phpt
new file mode 100644
index 0000000000..040dc787cc
--- /dev/null
+++ b/ext/standard/tests/dir/scandir_variation6-win32.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Test scandir() function : usage variations - Wildcards in directory path
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
+?>
+--FILE--
+<?php
+/* Prototype : array scandir(string $dir [, int $sorting_order [, resource $context]])
+ * Description: List files & directories inside the specified path
+ * Source code: ext/standard/dir.c
+ */
+
+/*
+ * Pass a directory path using wildcards as $dir argument to test how scandir() behaves
+ */
+
+echo "*** Testing scandir() : usage variations ***\n";
+
+// create the temporary directories
+$file_path = dirname(__FILE__);
+$dir_path = $file_path . "/scandir_variation6";
+$sub_dir_path = $dir_path . "/sub_dir1";
+
+mkdir($dir_path);
+mkdir($sub_dir_path);
+
+// with different wildcard characters
+
+echo "\n-- Wildcard = '*' --\n";
+var_dump( scandir($file_path . "/scandir_var*") );
+var_dump( scandir($file_path . "/*") );
+
+echo "\n-- Wildcard = '?' --\n";
+var_dump( scandir($dir_path . "/sub_dir?") );
+var_dump( scandir($dir_path . "/sub?dir1") );
+
+?>
+===DONE===
+--CLEAN--
+<?php
+$dir_path = dirname(__FILE__) . "/scandir_variation6";
+$sub_dir_path = $dir_path . "/sub_dir1";
+
+rmdir($sub_dir_path);
+rmdir($dir_path);
+?>
+--EXPECTF--
+*** Testing scandir() : usage variations ***
+
+-- Wildcard = '*' --
+
+Warning: scandir(%s/scandir_var*,%s/scandir_var*): No such file or directory in %s on line %d
+
+Warning: scandir(%s/scandir_var*): failed to open dir: No such file or directory in %sscandir_variation6-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+Warning: scandir(%s/*,%s/*): No such file or directory in %s on line %d
+
+Warning: scandir(%s/*): failed to open dir: No such file or directory in %sscandir_variation6-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+-- Wildcard = '?' --
+
+Warning: scandir(%s/scandir_variation6/sub_dir?,%s/scandir_variation6/sub_dir?): No such file or directory in %s on line %d
+
+Warning: scandir(%s/scandir_variation6/sub_dir?): failed to open dir: No such file or directory in %sscandir_variation6-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+
+Warning: scandir(%s/scandir_variation6/sub?dir1,%s/scandir_variation6/sub?dir1): No such file or directory in %s on line %d
+
+Warning: scandir(%s/scandir_variation6/sub?dir1): failed to open dir: No such file or directory in %sscandir_variation6-win32.php on line %d
+
+Warning: scandir(): (errno %d): %s in %s on line %d
+bool(false)
+===DONE===
diff --git a/ext/standard/tests/dir/scandir_variation8.phpt b/ext/standard/tests/dir/scandir_variation8.phpt
index 36ae88c8f5..4e96e04a4e 100644
--- a/ext/standard/tests/dir/scandir_variation8.phpt
+++ b/ext/standard/tests/dir/scandir_variation8.phpt
@@ -51,7 +51,7 @@ $iterator = 1;
foreach($inputs as $key => $input) {
echo "\n-- Iteration $iterator --\n";
$handle = "fp{$iterator}";
- var_dump( $$handle = fopen($dir_path . $input . '.tmp', 'w') );
+ var_dump( $$handle = fopen(@"$dir_path$input.tmp", 'w') );
fclose($$handle);
$iterator++;
};
diff --git a/ext/standard/tests/file/005_variation2-win32.phpt b/ext/standard/tests/file/005_variation2-win32.phpt
index 45dcbc5f07..8508ecf7fb 100644
--- a/ext/standard/tests/file/005_variation2-win32.phpt
+++ b/ext/standard/tests/file/005_variation2-win32.phpt
@@ -107,14 +107,8 @@ Warning: filemtime(): stat failed for | in %s on line %d
Warning: filectime(): stat failed for | in %s on line %d
-*** testing touch ***
-Warning: touch(): %s in %s on line %d
-bool(false)
-
-Warning: touch(): %s in %s on line %d
+*** testing touch ***bool(false)
bool(false)
-
-Warning: touch(): %s in %s on line %d
bool(false)
Warning: touch(): %s in %s on line %d
diff --git a/ext/standard/tests/file/005_variation2.phpt b/ext/standard/tests/file/005_variation2.phpt
index d14a9bddd7..6d4ca5e83d 100644
--- a/ext/standard/tests/file/005_variation2.phpt
+++ b/ext/standard/tests/file/005_variation2.phpt
@@ -77,12 +77,6 @@ echo "Done";
*** Testing fileattime(), filemtime(), filectime() & touch() : usage variations ***
*** testing touch ***
-
-Warning: touch(): Unable to create file because No such file or directory in %s on line %d
-
-Warning: touch(): Unable to create file because No such file or directory in %s on line %d
-
-Warning: touch(): Unable to create file because No such file or directory in %s on line %d
bool(false)
bool(false)
bool(false)
diff --git a/ext/standard/tests/file/007_error.phpt b/ext/standard/tests/file/007_error.phpt
index 78a9d4ac33..a369c9d977 100644
--- a/ext/standard/tests/file/007_error.phpt
+++ b/ext/standard/tests/file/007_error.phpt
@@ -145,7 +145,7 @@ Warning: feof() expects parameter 1 to be resource, boolean given in %s on line
bool(false)
-- Iteration 5 --
-Warning: fopen() expects parameter 1 to be string, array given in %s on line %d
+Warning: fopen() expects parameter 1 to be a valid path, array given in %s on line %d
bool(false)
Warning: fclose() expects parameter 1 to be resource, array given in %s on line %d
@@ -155,7 +155,7 @@ Warning: feof() expects parameter 1 to be resource, array given in %s on line %d
bool(false)
-- Iteration 6 --
-Warning: fopen() expects parameter 1 to be string, object given in %s on line %d
+Warning: fopen() expects parameter 1 to be a valid path, object given in %s on line %d
bool(false)
Warning: fclose() expects parameter 1 to be resource, object given in %s on line %d
diff --git a/ext/standard/tests/file/bug22414.phpt b/ext/standard/tests/file/bug22414.phpt
index 90e4c58bd9..9538c8ede8 100644
--- a/ext/standard/tests/file/bug22414.phpt
+++ b/ext/standard/tests/file/bug22414.phpt
@@ -1,14 +1,13 @@
--TEST--
Bug #22414 (passthru() does not read data correctly)
--INI--
-safe_mode=
output_handler=
--FILE--
<?php
$php = getenv('TEST_PHP_EXECUTABLE');
$tmpfile = tempnam(__DIR__, 'phpt');
- $args = ' -n -dsafe_mode=off ';
+ $args = ' -n ';
/* Regular Data Test */
passthru($php . $args . ' -r " echo \"HELLO\"; "');
diff --git a/ext/standard/tests/file/bug38450_3.phpt b/ext/standard/tests/file/bug38450_3.phpt
index d11ebd91e3..389de87b4c 100644
--- a/ext/standard/tests/file/bug38450_3.phpt
+++ b/ext/standard/tests/file/bug38450_3.phpt
@@ -102,4 +102,4 @@ var_dump($myvar);
echo "Done\n";
?>
--EXPECTF--
-Catchable fatal error: Argument 1 passed to VariableStream::__construct() must be an array, none given in %s on line %d
+Catchable fatal error: Argument 1 passed to VariableStream::__construct() must be of the type array, none given in %s on line %d
diff --git a/ext/standard/tests/file/bug39863.phpt b/ext/standard/tests/file/bug39863.phpt
index 6913655ee4..5e26b5a636 100644
--- a/ext/standard/tests/file/bug39863.phpt
+++ b/ext/standard/tests/file/bug39863.phpt
@@ -16,7 +16,8 @@ else {
?>
===DONE===
<?php exit(0); ?>
---EXPECT--
+--EXPECTF--
+Warning: file_exists() expects parameter 1 to be a valid path, string given in %s on line %d
PASS
===DONE===
diff --git a/ext/standard/tests/file/bug52820.phpt b/ext/standard/tests/file/bug52820.phpt
index 9ddff654c2..8a1e7cc981 100644
--- a/ext/standard/tests/file/bug52820.phpt
+++ b/ext/standard/tests/file/bug52820.phpt
@@ -2,6 +2,8 @@
Bug #52820 (writes to fopencookie FILE* not commited when seeking the stream)
--SKIPIF--
<?php
+if (!function_exists('leak_variable'))
+ die("skip only for debug builds");
/* unfortunately no standard function does a cast to FILE*, so we need
* curl to test this */
if (!extension_loaded("curl")) exit("skip curl extension not loaded");
@@ -30,6 +32,12 @@ fclose(do_stuff("php://temp"));
echo "\nmemory stream (close after):\n";
fclose(do_stuff("php://memory"));
+echo "\ntemp stream (leak):\n";
+leak_variable(do_stuff("php://temp"), true);
+
+echo "\nmemory stream (leak):\n";
+leak_variable(do_stuff("php://memory"), true);
+
echo "\nDone.\n";
--EXPECTF--
temp stream (close after):
@@ -46,4 +54,18 @@ About to rewind!
* couldn't connect to host
* Closing connection #0
+temp stream (leak):
+About to rewind!
+* About to connect() to 127.0.0.1 port 37349%r.*%r
+* Trying 127.0.0.1... * Connection refused
+* couldn't connect to host
+* Closing connection #0
+
+memory stream (leak):
+About to rewind!
+* About to connect() to 127.0.0.1 port 37349%r.*%r
+* Trying 127.0.0.1... * Connection refused
+* couldn't connect to host
+* Closing connection #0
+
Done.
diff --git a/ext/standard/tests/file/bug55124.phpt b/ext/standard/tests/file/bug55124.phpt
new file mode 100644
index 0000000000..1915b7f209
--- /dev/null
+++ b/ext/standard/tests/file/bug55124.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #55124 (recursive mkdir fails with current (dot) directory in path)
+--FILE--
+<?php
+$old_dir_path = getcwd();
+chdir(__DIR__);
+mkdir('a/./b', 0755, true);
+if (is_dir('a/b')) {
+ rmdir('a/b');
+}
+if (is_dir('./a')) {
+ rmdir('a');
+}
+chdir($old_dir_path);
+echo "OK";
+?>
+--EXPECT--
+OK
diff --git a/ext/standard/tests/file/chmod_variation3.phpt b/ext/standard/tests/file/chmod_variation3.phpt
index df18ccf986..7c637b8560 100644
--- a/ext/standard/tests/file/chmod_variation3.phpt
+++ b/ext/standard/tests/file/chmod_variation3.phpt
@@ -143,19 +143,19 @@ Error: 2 - chmod(): No such file or directory, %s(%d)
bool(false)
--empty array--
-Error: 2 - chmod() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - chmod() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--int indexed array--
-Error: 2 - chmod() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - chmod() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--associative array--
-Error: 2 - chmod() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - chmod() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--nested arrays--
-Error: 2 - chmod() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - chmod() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--uppercase NULL--
@@ -195,7 +195,7 @@ Error: 2 - chmod(): No such file or directory, %s(%d)
bool(false)
--instance of classWithoutToString--
-Error: 2 - chmod() expects parameter 1 to be string, object given, %s(%d)
+Error: 2 - chmod() expects parameter 1 to be a valid path, object given, %s(%d)
NULL
--undefined var--
diff --git a/ext/standard/tests/file/copy_variation4.phpt b/ext/standard/tests/file/copy_variation4.phpt
index 0a965fd54f..3c8224da0a 100644
--- a/ext/standard/tests/file/copy_variation4.phpt
+++ b/ext/standard/tests/file/copy_variation4.phpt
Binary files differ
diff --git a/ext/standard/tests/file/disk_free_space_variation.phpt b/ext/standard/tests/file/disk_free_space_variation.phpt
index 178f857aba..adb1acaf82 100644
--- a/ext/standard/tests/file/disk_free_space_variation.phpt
+++ b/ext/standard/tests/file/disk_free_space_variation.phpt
@@ -105,19 +105,35 @@ float(%d)
float(%d)
-- Iteration 9 --
-bool(false)
-bool(false)
+
+Warning: disk_free_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: diskfreespace() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 10 --
-bool(false)
-bool(false)
+
+Warning: disk_free_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: diskfreespace() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 11 --
-bool(false)
-bool(false)
+
+Warning: disk_free_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: diskfreespace() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 12 --
-bool(false)
-bool(false)
+
+Warning: disk_free_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: diskfreespace() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
--- Done ---
diff --git a/ext/standard/tests/file/disk_total_space_variation.phpt b/ext/standard/tests/file/disk_total_space_variation.phpt
index c03ba594bd..ba2ceb2d1b 100644
--- a/ext/standard/tests/file/disk_total_space_variation.phpt
+++ b/ext/standard/tests/file/disk_total_space_variation.phpt
@@ -99,16 +99,24 @@ float(%d)
float(%d)
-- Iteration 9 --
-float(%d)
+
+Warning: disk_total_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 10 --
-float(%d)
+
+Warning: disk_total_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 11 --
-float(%d)
+
+Warning: disk_total_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 12 --
-float(%d)
+
+Warning: disk_total_space() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Testing with Binary Input ***
float(%d)
diff --git a/ext/standard/tests/file/fclose_variation1.phpt b/ext/standard/tests/file/fclose_variation1.phpt
new file mode 100644
index 0000000000..43a6c343d0
--- /dev/null
+++ b/ext/standard/tests/file/fclose_variation1.phpt
@@ -0,0 +1,15 @@
+--TEST--
+fclose() actually closes streams with refcount > 1
+--FILE--
+<?php
+$s = fopen(__FILE__, "rb");
+function separate_zval(&$var) { }
+$s2 = $s;
+separate_zval($s2);
+fclose($s);
+echo fread($s2, strlen("<?php"));
+echo "\nDone.\n";
+--EXPECTF--
+Warning: fread(): %d is not a valid stream resource in %s on line %d
+
+Done.
diff --git a/ext/standard/tests/file/file_get_contents_variation8-win32.phpt b/ext/standard/tests/file/file_get_contents_variation8-win32.phpt
index c0074ff38a..bb62eb47fb 100644
--- a/ext/standard/tests/file/file_get_contents_variation8-win32.phpt
+++ b/ext/standard/tests/file/file_get_contents_variation8-win32.phpt
@@ -4,8 +4,9 @@ Test file_get_contents() function : variation - obscure filenames
Dave Kelsey <d_kelsey@uk.ibm.com>
--SKIPIF--
<?php
-if(substr(PHP_OS, 0, 3) != "WIN")
- die("skip Only run on Windows");
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die("skip Valid only on Windows");
+}
?>
--FILE--
<?php
@@ -62,7 +63,7 @@ bool(false)
-- Filename: NULL --
-Warning: file_get_contents(): Filename cannot be empty in %s on line %d
+Warning: file_get_contents(): Filename cannot be empty in %sfile_get_contents_variation8-win32.php on line %d
bool(false)
-- Filename: "" --
@@ -76,11 +77,13 @@ Warning: file_get_contents( ): failed to open stream: Permission denied in %s on
bool(false)
-- Filename: \0 --
-bool(false)
+
+Warning: file_get_contents() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Filename: array() --
-Warning: file_get_contents() expects parameter 1 to be string, array given in %s on line %d
+Warning: file_get_contents() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Filename: /no/such/file/dir --
@@ -92,4 +95,4 @@ bool(false)
Warning: file_get_contents(php/php): failed to open stream: No such file or directory in %s on line %d
bool(false)
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/standard/tests/file/file_get_contents_variation8.phpt b/ext/standard/tests/file/file_get_contents_variation8.phpt
index 84621e1bd8..5b325b0e98 100644
--- a/ext/standard/tests/file/file_get_contents_variation8.phpt
+++ b/ext/standard/tests/file/file_get_contents_variation8.phpt
@@ -4,8 +4,9 @@ Test file_get_contents() function : variation - obscure filenames
Dave Kelsey <d_kelsey@uk.ibm.com>
--SKIPIF--
<?php
-if(substr(PHP_OS, 0, 3) == "WIN")
- die("skip Do not run on Windows");
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ die('skip.. Not valid for Windows');
+}
?>
--FILE--
<?php
@@ -68,14 +69,16 @@ bool(false)
Warning: file_get_contents( ): failed to open stream: No such file or directory in %s on line %d
bool(false)
-- Iteration 6 --
-bool(false)
+
+Warning: file_get_contents() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 7 --
-Warning: file_get_contents() expects parameter 1 to be string, array given in %s on line %d
+Warning: file_get_contents() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-- Iteration 8 --
-Warning: file_get_contents(/no/such/file/dir): failed to open stream: %s in %s on line %d
+Warning: file_get_contents(/no/such/file/dir): failed to open stream: No such file or directory in %s on line %d
bool(false)
-- Iteration 9 --
diff --git a/ext/standard/tests/file/file_put_contents_variation8-win32.phpt b/ext/standard/tests/file/file_put_contents_variation8-win32.phpt
index 5f2a4c7310..92fe7b3d6a 100644
--- a/ext/standard/tests/file/file_put_contents_variation8-win32.phpt
+++ b/ext/standard/tests/file/file_put_contents_variation8-win32.phpt
@@ -77,11 +77,13 @@ Warning: file_put_contents( ): failed to open stream: Permission denied in %s on
Failed to write data to: " "
-- Filename: \0 --
+
+Warning: file_put_contents() expects parameter 1 to be a valid path, string given in %s on line %d
Failed to write data to: \0
-- Filename: array() --
-Warning: file_put_contents() expects parameter 1 to be string, array given in %s on line %d
+Warning: file_put_contents() expects parameter 1 to be a valid path, array given in %s on line %d
Failed to write data to: array()
-- Filename: /no/such/file/dir --
diff --git a/ext/standard/tests/file/file_put_contents_variation8.phpt b/ext/standard/tests/file/file_put_contents_variation8.phpt
index 79586ada25..3cd92c5ec8 100644
--- a/ext/standard/tests/file/file_put_contents_variation8.phpt
+++ b/ext/standard/tests/file/file_put_contents_variation8.phpt
Binary files differ
diff --git a/ext/standard/tests/file/file_variation2.phpt b/ext/standard/tests/file/file_variation2.phpt
index a9618b62c6..ab37ea5c45 100644
--- a/ext/standard/tests/file/file_variation2.phpt
+++ b/ext/standard/tests/file/file_variation2.phpt
@@ -145,19 +145,19 @@ Error: 2 - file(0.5): failed to open stream: No such file or directory, %s(%d)
bool(false)
--empty array--
-Error: 2 - file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - file() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--int indexed array--
-Error: 2 - file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - file() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--associative array--
-Error: 2 - file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - file() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--nested arrays--
-Error: 2 - file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - file() expects parameter 1 to be a valid path, array given, %s(%d)
NULL
--uppercase NULL--
@@ -197,7 +197,7 @@ Error: 2 - file(Class A object): failed to open stream: %s, %s(%d)
bool(false)
--instance of classWithoutToString--
-Error: 2 - file() expects parameter 1 to be string, object given, %s(%d)
+Error: 2 - file() expects parameter 1 to be a valid path, object given, %s(%d)
NULL
--undefined var--
diff --git a/ext/standard/tests/file/filegroup_variation2.phpt b/ext/standard/tests/file/filegroup_variation2.phpt
index d5b7b1bac8..afac40c9ab 100644
--- a/ext/standard/tests/file/filegroup_variation2.phpt
+++ b/ext/standard/tests/file/filegroup_variation2.phpt
@@ -58,7 +58,7 @@ bool(false)
bool(false)
bool(false)
-Warning: filegroup() expects parameter 1 to be string, resource given in %s on line %d
+Warning: filegroup() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
Warning: filegroup(): stat failed for 1234 in %s on line %d
diff --git a/ext/standard/tests/file/filegroup_variation3.phpt b/ext/standard/tests/file/filegroup_variation3.phpt
index c41f383632..b275944f78 100644
--- a/ext/standard/tests/file/filegroup_variation3.phpt
+++ b/ext/standard/tests/file/filegroup_variation3.phpt
@@ -74,8 +74,12 @@ bool(false)
Warning: filegroup(): stat failed for %s/filegroup_variation3/filegroup*.tmp in %s on line %d
bool(false)
- Iteration 7 -
-bool(false)
+
+Warning: filegroup() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
- Iteration 8 -
-bool(false)
+
+Warning: filegroup() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Done ***
diff --git a/ext/standard/tests/file/fileinode_variation2.phpt b/ext/standard/tests/file/fileinode_variation2.phpt
index 7d71ef4ab2..e8e7af6a6e 100644
--- a/ext/standard/tests/file/fileinode_variation2.phpt
+++ b/ext/standard/tests/file/fileinode_variation2.phpt
@@ -59,7 +59,7 @@ bool(false)
bool(false)
bool(false)
-Warning: fileinode() expects parameter 1 to be string, resource given in %s on line %d
+Warning: fileinode() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
Warning: fileinode(): stat failed for 1234 in %s on line %d
diff --git a/ext/standard/tests/file/fileinode_variation3.phpt b/ext/standard/tests/file/fileinode_variation3.phpt
index 3595dbcf9d..ca84864b59 100644
--- a/ext/standard/tests/file/fileinode_variation3.phpt
+++ b/ext/standard/tests/file/fileinode_variation3.phpt
@@ -75,8 +75,12 @@ bool(false)
Warning: fileinode(): stat failed for %s/fileinode_variation3/fileinode*.tmp in %s on line %d
bool(false)
- Iteration 7 -
-bool(false)
+
+Warning: fileinode() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
- Iteration 8 -
-bool(false)
+
+Warning: fileinode() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Done ***
diff --git a/ext/standard/tests/file/fileowner_variation2.phpt b/ext/standard/tests/file/fileowner_variation2.phpt
index 07eb6ec8b6..feff767879 100644
--- a/ext/standard/tests/file/fileowner_variation2.phpt
+++ b/ext/standard/tests/file/fileowner_variation2.phpt
@@ -59,7 +59,7 @@ bool(false)
bool(false)
bool(false)
-Warning: fileowner() expects parameter 1 to be string, resource given in %s on line %d
+Warning: fileowner() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
Warning: fileowner(): stat failed for 1234 in %s on line %d
diff --git a/ext/standard/tests/file/fileowner_variation3.phpt b/ext/standard/tests/file/fileowner_variation3.phpt
index b2691e923d..6f91c31d11 100644
--- a/ext/standard/tests/file/fileowner_variation3.phpt
+++ b/ext/standard/tests/file/fileowner_variation3.phpt
@@ -75,8 +75,12 @@ bool(false)
Warning: fileowner(): stat failed for %s/fileowner_variation3/fileowner*.tmp in %s on line %d
bool(false)
- Iteration 7 -
-bool(false)
+
+Warning: fileowner() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
- Iteration 8 -
-bool(false)
+
+Warning: fileowner() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Done ***
diff --git a/ext/standard/tests/file/fileperms_variation2.phpt b/ext/standard/tests/file/fileperms_variation2.phpt
index ad809a1559..47c0c6593a 100644
--- a/ext/standard/tests/file/fileperms_variation2.phpt
+++ b/ext/standard/tests/file/fileperms_variation2.phpt
@@ -58,7 +58,7 @@ bool(false)
bool(false)
bool(false)
-Warning: fileperms() expects parameter 1 to be string, resource given in %s on line %d
+Warning: fileperms() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
Warning: fileperms(): stat failed for 1234 in %s on line %d
diff --git a/ext/standard/tests/file/fileperms_variation3.phpt b/ext/standard/tests/file/fileperms_variation3.phpt
index 1e7396a503..575fe11a2f 100644
--- a/ext/standard/tests/file/fileperms_variation3.phpt
+++ b/ext/standard/tests/file/fileperms_variation3.phpt
@@ -74,8 +74,12 @@ bool(false)
Warning: fileperms(): stat failed for %s/fileperms_variation3/fileperms*.tmp in %s on line %d
bool(false)
- Iteration 7 -
-bool(false)
+
+Warning: fileperms() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
- Iteration 8 -
-bool(false)
+
+Warning: fileperms() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Done ***
diff --git a/ext/standard/tests/file/fnmatch_error.phpt b/ext/standard/tests/file/fnmatch_error.phpt
index 6afbe05dcc..5277874ba6 100644
--- a/ext/standard/tests/file/fnmatch_error.phpt
+++ b/ext/standard/tests/file/fnmatch_error.phpt
@@ -36,13 +36,13 @@ echo "\n*** Done ***\n";
?>
--EXPECTF--
*** Testing error conditions for fnmatch() ***
-Warning: fnmatch() expects parameter 1 to be string, array given in %s on line %d%d
+Warning: fnmatch() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-Warning: fnmatch() expects parameter 1 to be string, resource given in %s on line %d%d
+Warning: fnmatch() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
-Warning: fnmatch() expects parameter 1 to be string, object given in %s on line %d%d
+Warning: fnmatch() expects parameter 1 to be a valid path, object given in %s on line %d
NULL
Warning: fnmatch() expects at least 2 parameters, 1 given in %s on line %d%d
diff --git a/ext/standard/tests/file/fnmatch_variation.phpt b/ext/standard/tests/file/fnmatch_variation.phpt
index 13afebb6f0..6d28528c1c 100644
--- a/ext/standard/tests/file/fnmatch_variation.phpt
+++ b/ext/standard/tests/file/fnmatch_variation.phpt
@@ -134,7 +134,7 @@ match($null_arr, $null_arr);
echo "\n*** Done ***\n";
?>
---EXPECT--
+--EXPECTF--
*** Testing fnmatch() with file and various patterns ***
-- Iteration 0 --
bool(true)
@@ -183,9 +183,13 @@ bool(false)
-- Iteration 22 --
bool(false)
-- Iteration 23 --
-bool(false)
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 24 --
-bool(false)
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 25 --
bool(false)
-- Iteration 26 --
@@ -259,44 +263,84 @@ bool(true)
--- With Strings ---
-- Iteration 0 --
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(true)
-- Iteration 1 --
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 2 --
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(true)
-- Iteration 3 --
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 4 --
bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
-bool(false)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(true)
bool(false)
-- Iteration 5 --
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(true)
@@ -397,42 +441,64 @@ bool(true)
bool(true)
bool(true)
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(false)
-- Iteration 1 --
bool(true)
bool(true)
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(false)
-- Iteration 2 --
bool(true)
bool(true)
bool(true)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(false)
-- Iteration 3 --
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: fnmatch() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 4 --
bool(false)
bool(false)
bool(false)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(true)
bool(false)
-- Iteration 5 --
bool(false)
bool(false)
bool(false)
-bool(false)
+
+Warning: fnmatch() expects parameter 2 to be a valid path, string given in %s on line %d
+NULL
bool(false)
bool(true)
diff --git a/ext/standard/tests/file/fpassthru_variation1.phpt b/ext/standard/tests/file/fpassthru_variation1.phpt
index 0d74d2ed79..f6868e3ece 100644
--- a/ext/standard/tests/file/fpassthru_variation1.phpt
+++ b/ext/standard/tests/file/fpassthru_variation1.phpt
@@ -77,7 +77,7 @@ $values = array(
// loop through each element of the array for fp
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( fpassthru($value) );
};
diff --git a/ext/standard/tests/file/fseek_variation1.phpt b/ext/standard/tests/file/fseek_variation1.phpt
index ebf3cf698d..fbe4673a3f 100644
--- a/ext/standard/tests/file/fseek_variation1.phpt
+++ b/ext/standard/tests/file/fseek_variation1.phpt
@@ -76,7 +76,7 @@ $values = array(
// loop through each element of the array for offset
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( fseek($fp, $value, $whence) );
var_dump( ftell($fp));
};
diff --git a/ext/standard/tests/file/glob_variation-win32.phpt b/ext/standard/tests/file/glob_variation-win32.phpt
index 6552fe41da..5027ac03e6 100644
--- a/ext/standard/tests/file/glob_variation-win32.phpt
+++ b/ext/standard/tests/file/glob_variation-win32.phpt
@@ -325,12 +325,24 @@ array(0) {
}
-- Iteration 8 --
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
+
+Warning: glob() expects parameter 1 to be a valid path, string given %sglob_variation-win32.php on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given %sglob_variation-win32.php on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given %sglob_variation-win32.php on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given %sglob_variation-win32.php on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given %sglob_variation-win32.php on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given %sglob_variation-win32.php on line %d
+NULL
-- Iteration 9 --
array(0) {
@@ -433,7 +445,9 @@ array(1) {
array(0) {
}
-- Iteration 8 --
-bool(false)
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %sglob_variation-win32.php on line %d
+NULL
-- Iteration 9 --
array(0) {
}
diff --git a/ext/standard/tests/file/glob_variation.phpt b/ext/standard/tests/file/glob_variation.phpt
index 64d3d8a2db..00fd6ff3ed 100644
--- a/ext/standard/tests/file/glob_variation.phpt
+++ b/ext/standard/tests/file/glob_variation.phpt
@@ -325,12 +325,24 @@ array(0) {
}
-- Iteration 8 --
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
-bool(false)
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 9 --
array(0) {
@@ -433,7 +445,9 @@ array(1) {
array(0) {
}
-- Iteration 8 --
-bool(false)
+
+Warning: glob() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 9 --
array(0) {
}
diff --git a/ext/standard/tests/file/is_dir_variation3.phpt b/ext/standard/tests/file/is_dir_variation3.phpt
index 2df297843b..41826ad7ec 100644
--- a/ext/standard/tests/file/is_dir_variation3.phpt
+++ b/ext/standard/tests/file/is_dir_variation3.phpt
@@ -42,7 +42,7 @@ bool(false)
bool(false)
bool(false)
-Warning: is_dir() expects parameter 1 to be string, resource given in %s on line %d
+Warning: is_dir() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
bool(false)
bool(false)
diff --git a/ext/standard/tests/file/is_dir_variation4.phpt b/ext/standard/tests/file/is_dir_variation4.phpt
index b83d185b65..5c0be485c5 100644
--- a/ext/standard/tests/file/is_dir_variation4.phpt
+++ b/ext/standard/tests/file/is_dir_variation4.phpt
@@ -77,9 +77,13 @@ bool(true)
bool(false)
-- Iteration 9 --
-bool(false)
+
+Warning: is_dir() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 10 --
-bool(false)
+
+Warning: is_dir() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Done ***
diff --git a/ext/standard/tests/file/is_executable_variation1.phpt b/ext/standard/tests/file/is_executable_variation1.phpt
index bc826b9493..231f1bff3f 100644
--- a/ext/standard/tests/file/is_executable_variation1.phpt
+++ b/ext/standard/tests/file/is_executable_variation1.phpt
@@ -76,9 +76,13 @@ bool(false)
-- Iteration 5 --
bool(false)
-- Iteration 6 --
-bool(false)
+
+Warning: is_executable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 7 --
-bool(false)
+
+Warning: is_executable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 8 --
bool(false)
-- Iteration 9 --
diff --git a/ext/standard/tests/file/is_executable_variation3.phpt b/ext/standard/tests/file/is_executable_variation3.phpt
index 634ce1f40c..925f9963c0 100644
--- a/ext/standard/tests/file/is_executable_variation3.phpt
+++ b/ext/standard/tests/file/is_executable_variation3.phpt
@@ -62,7 +62,7 @@ bool(false)
bool(false)
bool(false)
-Warning: is_executable() expects parameter 1 to be string, array given in %s on line %d
+Warning: is_executable() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
bool(false)
Done
diff --git a/ext/standard/tests/file/is_file_error.phpt b/ext/standard/tests/file/is_file_error.phpt
index 711d761763..abccb721a1 100644
--- a/ext/standard/tests/file/is_file_error.phpt
+++ b/ext/standard/tests/file/is_file_error.phpt
@@ -45,7 +45,7 @@ Warning: is_file() expects exactly 1 parameter, 2 given in %s on line %d
NULL
bool(false)
-Warning: is_file() expects parameter 1 to be string, resource given in %s on line %d
+Warning: is_file() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
*** Done ***
diff --git a/ext/standard/tests/file/is_file_variation3.phpt b/ext/standard/tests/file/is_file_variation3.phpt
index 917fa5acc8..2a13e46779 100644
--- a/ext/standard/tests/file/is_file_variation3.phpt
+++ b/ext/standard/tests/file/is_file_variation3.phpt
@@ -51,7 +51,7 @@ bool(false)
bool(false)
bool(false)
-Warning: is_file() expects parameter 1 to be string, resource given in %s on line %d
+Warning: is_file() expects parameter 1 to be a valid path, resource given in %s on line %d
NULL
bool(false)
bool(false)
diff --git a/ext/standard/tests/file/is_file_variation4.phpt b/ext/standard/tests/file/is_file_variation4.phpt
index fbdf438945..b927446b7c 100644
--- a/ext/standard/tests/file/is_file_variation4.phpt
+++ b/ext/standard/tests/file/is_file_variation4.phpt
@@ -67,8 +67,12 @@ bool(false)
- Iteration 6 -
bool(false)
- Iteration 7 -
-bool(false)
+
+Warning: is_file() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
- Iteration 8 -
-bool(false)
+
+Warning: is_file() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
*** Done ***
diff --git a/ext/standard/tests/file/is_readable_variation1.phpt b/ext/standard/tests/file/is_readable_variation1.phpt
index 74935743ce..5becac00a2 100644
--- a/ext/standard/tests/file/is_readable_variation1.phpt
+++ b/ext/standard/tests/file/is_readable_variation1.phpt
@@ -87,11 +87,17 @@ bool(false)
-- Iteration 6 --
bool(false)
-- Iteration 7 --
-bool(false)
+
+Warning: is_readable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 8 --
-bool(false)
+
+Warning: is_readable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 9 --
-bool(false)
+
+Warning: is_readable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 10 --
bool(true)
-- Iteration 11 --
diff --git a/ext/standard/tests/file/is_readable_variation3.phpt b/ext/standard/tests/file/is_readable_variation3.phpt
index dde47cc3b5..dc4d3b16f3 100644
--- a/ext/standard/tests/file/is_readable_variation3.phpt
+++ b/ext/standard/tests/file/is_readable_variation3.phpt
@@ -61,7 +61,7 @@ bool(false)
bool(false)
bool(false)
-Warning: is_readable() expects parameter 1 to be string, array given in %s on line %d
+Warning: is_readable() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
bool(false)
Done
diff --git a/ext/standard/tests/file/is_writable_variation1.phpt b/ext/standard/tests/file/is_writable_variation1.phpt
index 1f3cbf599e..718c7fb8e9 100644
--- a/ext/standard/tests/file/is_writable_variation1.phpt
+++ b/ext/standard/tests/file/is_writable_variation1.phpt
@@ -96,18 +96,30 @@ bool(false)
bool(false)
bool(false)
-- Iteration 7 --
-bool(false)
-bool(false)
+
+Warning: is_writable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: is_writeable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 8 --
-bool(false)
-bool(false)
+
+Warning: is_writable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: is_writeable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 9 --
-bool(false)
-bool(false)
+
+Warning: is_writable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
+
+Warning: is_writeable() expects parameter 1 to be a valid path, string given in %s on line %d
+NULL
-- Iteration 10 --
bool(true)
bool(true)
-- Iteration 11 --
bool(true)
bool(true)
-Done \ No newline at end of file
+Done
diff --git a/ext/standard/tests/file/is_writable_variation3.phpt b/ext/standard/tests/file/is_writable_variation3.phpt
index 4c5bfa9082..66a80abf1e 100644
--- a/ext/standard/tests/file/is_writable_variation3.phpt
+++ b/ext/standard/tests/file/is_writable_variation3.phpt
@@ -67,10 +67,10 @@ bool(false)
bool(false)
bool(false)
-Warning: is_writable() expects parameter 1 to be string, array given in %s on line %d
+Warning: is_writable() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-Warning: is_writeable() expects parameter 1 to be string, array given in %s on line %d
+Warning: is_writeable() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
bool(false)
bool(false)
diff --git a/ext/standard/tests/file/lchown_error.phpt b/ext/standard/tests/file/lchown_error.phpt
index 1e0356569c..979959e280 100644
--- a/ext/standard/tests/file/lchown_error.phpt
+++ b/ext/standard/tests/file/lchown_error.phpt
@@ -67,10 +67,10 @@ bool(true)
Warning: lchown(): No such file or directory in %s on line %d
bool(false)
-Warning: lchown() expects parameter 1 to be string, object given in %s on line %d
+Warning: lchown() expects parameter 1 to be a valid path, object given in %s on line %d
bool(true)
-Warning: lchown() expects parameter 1 to be string, array given in %s on line %d
+Warning: lchown() expects parameter 1 to be a valid path, array given in %s on line %d
bool(true)
Warning: lchown(): Operation not permitted in %s on line %d
diff --git a/ext/standard/tests/file/lstat_stat_error.phpt b/ext/standard/tests/file/lstat_stat_error.phpt
index 2a220084a4..385167fe32 100644
--- a/ext/standard/tests/file/lstat_stat_error.phpt
+++ b/ext/standard/tests/file/lstat_stat_error.phpt
@@ -51,7 +51,7 @@ bool(false)
Warning: lstat(): Lstat failed for 22 in %s on line %d
bool(false)
-Warning: lstat() expects parameter 1 to be string, array given in %s on line %d
+Warning: lstat() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
*** Testing stat() for error conditions ***
@@ -74,6 +74,6 @@ bool(false)
Warning: stat(): stat failed for 22 in %s on line %d
bool(false)
-Warning: stat() expects parameter 1 to be string, array given in %s on line %d
+Warning: stat() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
Done
diff --git a/ext/standard/tests/file/lstat_stat_variation7.phpt b/ext/standard/tests/file/lstat_stat_variation7.phpt
index f950c8fe6b..2296193c91 100644
--- a/ext/standard/tests/file/lstat_stat_variation7.phpt
+++ b/ext/standard/tests/file/lstat_stat_variation7.phpt
@@ -29,7 +29,7 @@ echo "*** Testing stat() on file after data is written in it ***\n";
$fh = fopen($file_name,"w");
$old_stat = stat($file_name);
clearstatcache();
-fwrite($fh, (binary)"Hello World");
+fwrite($fh, str_repeat((binary)"Hello World", $old_stat['blksize']));
$new_stat = stat($file_name);
// compare self stats
diff --git a/ext/standard/tests/file/magic_quotes.phpt b/ext/standard/tests/file/magic_quotes.phpt
deleted file mode 100644
index 0f42cd7c87..0000000000
--- a/ext/standard/tests/file/magic_quotes.phpt
+++ /dev/null
@@ -1,77 +0,0 @@
---TEST--
-various magic quotes tests
---INI--
-error_reporting=14335
---FILE--
-<?php
-
-$filename = dirname(__FILE__)."/magic_quotes.dat";
-
-var_dump(get_magic_quotes_runtime());
-var_dump(get_magic_quotes_runtime("blah"));
-
-file_put_contents($filename, "some'content'here\"and}there");
-
-var_dump(set_magic_quotes_runtime(true));
-var_dump(get_magic_quotes_runtime());
-var_dump(set_magic_quotes_runtime(-1));
-var_dump(get_magic_quotes_runtime());
-
-var_dump(file_get_contents($filename));
-
-var_dump(set_magic_quotes_runtime(0));
-var_dump(get_magic_quotes_runtime());
-
-var_dump(file_get_contents($filename));
-
-var_dump(set_magic_quotes_runtime(1));
-var_dump(get_magic_quotes_runtime());
-
-file_put_contents($filename, "some'content'here\"and}there");
-
-var_dump(file_get_contents($filename));
-
-var_dump(set_magic_quotes_runtime(0));
-var_dump(set_magic_quotes_runtime());
-var_dump(get_magic_quotes_runtime());
-
-var_dump(file_get_contents($filename));
-
-
-@unlink($filename);
-
-echo "Done\n";
-?>
---EXPECTF--
-int(0)
-int(0)
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-int(1)
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-int(1)
-string(30) "some\'content\'here\"and}there"
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-int(0)
-string(27) "some'content'here"and}there"
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-int(1)
-string(30) "some\'content\'here\"and}there"
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-
-Warning: set_magic_quotes_runtime() expects exactly 1 parameter, 0 given in %s on line %d
-NULL
-int(0)
-string(27) "some'content'here"and}there"
-Done
diff --git a/ext/standard/tests/file/mkdir_rmdir_variation2.phpt b/ext/standard/tests/file/mkdir_rmdir_variation2.phpt
index 101e890419..14dd361e07 100644
--- a/ext/standard/tests/file/mkdir_rmdir_variation2.phpt
+++ b/ext/standard/tests/file/mkdir_rmdir_variation2.phpt
@@ -64,13 +64,17 @@ Warning: rmdir(%s/mkdir_variation2/): %s on line %d
bool(false)
*** Testing mkdir() and rmdir() for binary safe functionality ***
+
+Warning: mkdir() expects parameter 1 to be a valid path, string given in %s on line %d
bool(false)
+
+Warning: rmdir(%s): No such file or directory in %s on line %d
bool(false)
*** Testing mkdir() with miscelleneous input ***
bool(true)
-Warning: mkdir(): Permission denied in %sfile/mkdir_rmdir_variation2.php on line %d
+Warning: mkdir(): Permission denied in %s on line %d
bool(false)
bool(true)
Done
diff --git a/ext/standard/tests/file/parse_ini_file_variation3.phpt b/ext/standard/tests/file/parse_ini_file_variation3.phpt
index 77ffa07415..43b0274ea9 100644
--- a/ext/standard/tests/file/parse_ini_file_variation3.phpt
+++ b/ext/standard/tests/file/parse_ini_file_variation3.phpt
@@ -79,7 +79,7 @@ foreach($newdirs as $newdir) {
New include path is : %sparse_ini_file_variation3.dir1%sparse_ini_file_variation3.dir2%sparse_ini_file_variation3.dir3%S
array(11) {
["error_reporting"]=>
- string(5) "30719"
+ string(5) "32767"
["display_errors"]=>
string(1) "1"
["display_startup_errors"]=>
@@ -101,4 +101,4 @@ array(11) {
["docref_ext"]=>
string(5) ".html"
}
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/standard/tests/file/parse_ini_file_variation4.phpt b/ext/standard/tests/file/parse_ini_file_variation4.phpt
index 46d45af48e..66cab3bedc 100644
--- a/ext/standard/tests/file/parse_ini_file_variation4.phpt
+++ b/ext/standard/tests/file/parse_ini_file_variation4.phpt
@@ -145,19 +145,19 @@ Error: 2 - parse_ini_file(0.5): failed to open stream: No such file or directory
bool(false)
--empty array--
-Error: 2 - parse_ini_file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - parse_ini_file() expects parameter 1 to be a valid path, array given, %s(%d)
bool(false)
--int indexed array--
-Error: 2 - parse_ini_file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - parse_ini_file() expects parameter 1 to be a valid path, array given, %s(%d)
bool(false)
--associative array--
-Error: 2 - parse_ini_file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - parse_ini_file() expects parameter 1 to be a valid path, array given, %s(%d)
bool(false)
--nested arrays--
-Error: 2 - parse_ini_file() expects parameter 1 to be string, array given, %s(%d)
+Error: 2 - parse_ini_file() expects parameter 1 to be a valid path, array given, %s(%d)
bool(false)
--uppercase NULL--
@@ -197,7 +197,7 @@ Error: 2 - parse_ini_file(Class A object): failed to open stream: No such file o
bool(false)
--instance of classWithoutToString--
-Error: 2 - parse_ini_file() expects parameter 1 to be string, object given, %s(%d)
+Error: 2 - parse_ini_file() expects parameter 1 to be a valid path, object given, %s(%d)
bool(false)
--undefined var--
diff --git a/ext/standard/tests/file/readfile_variation10-win32.phpt b/ext/standard/tests/file/readfile_variation10-win32.phpt
index 1624194897..61f6aba7a5 100644
--- a/ext/standard/tests/file/readfile_variation10-win32.phpt
+++ b/ext/standard/tests/file/readfile_variation10-win32.phpt
@@ -37,7 +37,7 @@ $names_arr = array(
foreach($names_arr as $key => $value) {
echo "\n-- Filename: $key --\n";
- var_dump(readfile($value));
+ readfile($value);
};
?>
@@ -48,48 +48,40 @@ foreach($names_arr as $key => $value) {
-- Filename: -1 --
Warning: readfile(-1): failed to open stream: No such file or directory in %s on line %d
-bool(false)
-- Filename: TRUE --
Warning: readfile(1): failed to open stream: No such file or directory in %s on line %d
-bool(false)
-- Filename: FALSE --
Warning: readfile(): Filename cannot be empty in %s on line %d
-bool(false)
-- Filename: NULL --
Warning: readfile(): Filename cannot be empty in %s on line %d
-bool(false)
-- Filename: "" --
Warning: readfile(): Filename cannot be empty in %s on line %d
-bool(false)
-- Filename: " " --
Warning: readfile( ): failed to open stream: Permission denied in %s on line %d
-bool(false)
-- Filename: \0 --
-bool(false)
+
+Warning: readfile() expects parameter 1 to be a valid path, string given in %s on line %d
-- Filename: array() --
-Warning: readfile() expects parameter 1 to be string, array given in %s on line %d
-bool(false)
+Warning: readfile() expects parameter 1 to be a valid path, array given in %s on line %d
-- Filename: /no/such/file/dir --
Warning: readfile(/no/such/file/dir): failed to open stream: No such file or directory in %s on line %d
-bool(false)
-- Filename: php/php --
Warning: readfile(php/php): failed to open stream: No such file or directory in %s on line %d
-bool(false)
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/standard/tests/file/readfile_variation10.phpt b/ext/standard/tests/file/readfile_variation10.phpt
index 76f1d2dbfb..3bbc329f31 100644
--- a/ext/standard/tests/file/readfile_variation10.phpt
+++ b/ext/standard/tests/file/readfile_variation10.phpt
Binary files differ
diff --git a/ext/standard/tests/file/rename_variation13-win32.phpt b/ext/standard/tests/file/rename_variation13-win32.phpt
index 146faa1893..a5030761a5 100644
--- a/ext/standard/tests/file/rename_variation13-win32.phpt
+++ b/ext/standard/tests/file/rename_variation13-win32.phpt
Binary files differ
diff --git a/ext/standard/tests/file/rename_variation13.phpt b/ext/standard/tests/file/rename_variation13.phpt
index 2c35198a10..ec1ee7c78d 100644
--- a/ext/standard/tests/file/rename_variation13.phpt
+++ b/ext/standard/tests/file/rename_variation13.phpt
@@ -41,7 +41,7 @@ $names_arr = array(
for( $i=0; $i<count($names_arr); $i++ ) {
$name = $names_arr[$i];
- echo "-- testing '$name' --\n";
+ echo @"-- testing '$name' --\n";
touch($aFile);
var_dump(rename($aFile, $name));
if (file_exists($name)) {
@@ -98,16 +98,22 @@ bool(true)
Warning: rename( ,%s/renameVar13/afile.tmp): No such file or directory in %s on line %d
bool(false)
-- testing '%s' --
+
+Warning: rename() %s in %s on line %d
bool(false)
+
+Warning: file_exists() expects parameter 1 to be a valid path, string given in %s on line %d
+
+Warning: rename() expects parameter 1 to be a valid path, string given in %s on line %d
bool(false)
-- testing 'Array' --
-Warning: rename() expects parameter 2 to be string, array given in %s on line %d
+Warning: rename() expects parameter 2 to be a valid path, array given in %s on line %d
bool(false)
-Warning: file_exists() expects parameter 1 to be string, array given in %s on line %d
+Warning: file_exists() expects parameter 1 to be a valid path, array given in %s on line %d
-Warning: rename() expects parameter 1 to be string, array given in %s on line %d
+Warning: rename() expects parameter 1 to be a valid path, array given in %s on line %d
bool(false)
-- testing '/no/such/file/dir' --
diff --git a/ext/standard/tests/file/rename_variation7-win32.phpt b/ext/standard/tests/file/rename_variation7-win32.phpt
index 6df0d9db99..369e8c2d43 100644
--- a/ext/standard/tests/file/rename_variation7-win32.phpt
+++ b/ext/standard/tests/file/rename_variation7-win32.phpt
@@ -26,11 +26,11 @@ var_dump(readlink($tmp_link2));
echo "Done\n";
?>
--EXPECTF--
-Warning: symlink(): Could not fetch file information(error 2) in %s on line %d
+Warning: symlink(): Could not fetch file information(error 2) in %srename_variation7-win32.php on line %d
-Warning: readlink(): readlink failed to read the symbolic link (%s), error 2) in %s on line %d
+Warning: readlink(): readlink failed to read the symbolic link (%srename_variation7-win32.php.tmp.link), error 2) in %srename_variation7-win32.php on line %d
bool(false)
-Warning: readlink(): readlink failed to read the symbolic link (%s), error 2) in %s on line %d
+Warning: readlink(): readlink failed to read the symbolic link (%srename_variation7-win32.php.tmp.link2), error 2) in %srename_variation7-win32.php on line %d
bool(false)
Done
diff --git a/ext/standard/tests/file/stat_error-win32.phpt b/ext/standard/tests/file/stat_error-win32.phpt
index c15ef58dd8..1b69da8bf5 100644
--- a/ext/standard/tests/file/stat_error-win32.phpt
+++ b/ext/standard/tests/file/stat_error-win32.phpt
@@ -49,7 +49,7 @@ bool(false)
Warning: stat(): stat failed for 22 in %s on line %d
bool(false)
-Warning: stat() expects parameter 1 to be string, array given in %s on line %d
+Warning: stat() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
Done
diff --git a/ext/standard/tests/file/stream_enclosed.phpt b/ext/standard/tests/file/stream_enclosed.phpt
new file mode 100644
index 0000000000..9520ecce74
--- /dev/null
+++ b/ext/standard/tests/file/stream_enclosed.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Unexposed/leaked stream encloses another stream
+--SKIPIF--
+<?php
+if (!function_exists('leak_variable')) die("skip only debug builds");
+--FILE--
+<?php
+$s = fopen('php://temp/maxmemory=1024','wb+');
+
+$t = fopen('php://temp/maxmemory=1024','wb+');
+
+/* force conversion of inner stream to STDIO. */
+$i = 0;
+while ($i++ < 5000) {
+ fwrite($t, str_repeat('a',1024));
+}
+
+leak_variable($s, true);
+leak_variable($t, true);
+--EXPECT--
diff --git a/ext/standard/tests/file/stream_rfc2397_006.phpt b/ext/standard/tests/file/stream_rfc2397_006.phpt
index b1b3111cf0..e6694a2861 100644
--- a/ext/standard/tests/file/stream_rfc2397_006.phpt
+++ b/ext/standard/tests/file/stream_rfc2397_006.phpt
@@ -21,8 +21,11 @@ foreach($streams as $stream)
===DONE===
<?php exit(0); ?>
--EXPECTF--
-bool(false)
-bool(false)
+Warning: file_get_contents() expects parameter 1 to be a valid path, string given in %s line %d
+NULL
+
+Warning: file_get_contents() expects parameter 1 to be a valid path, string given in %s line %d
+NULL
string(13) "foobar foobar"
Warning: file_get_contents(data:;base64,#Zm9vYmFyIGZvb2Jhc=): failed to open stream: rfc2397: unable to decode in %sstream_rfc2397_006.php on line %d
diff --git a/ext/standard/tests/file/tempnam_variation3-win32.phpt b/ext/standard/tests/file/tempnam_variation3-win32.phpt
index a51a10ab2b..fb457cb6ab 100644
--- a/ext/standard/tests/file/tempnam_variation3-win32.phpt
+++ b/ext/standard/tests/file/tempnam_variation3-win32.phpt
@@ -31,8 +31,8 @@ $names_arr = array(
NULL,
"",
" ",
- /* Invalid args */
"\0",
+ /* Invalid args */
array(),
/* Valid args*/
@@ -102,8 +102,7 @@ OK
Failed, not created in the correct directory %s vs %s
0
-- Iteration 6 --
-Failed, not created in the correct directory %s vs %s
-0
+OK
-- Iteration 7 --
Warning: tempnam() expects parameter 2 to be string, array given in %s\ext\standard\tests\file\tempnam_variation3-win32.php on line %d
diff --git a/ext/standard/tests/file/tempnam_variation3.phpt b/ext/standard/tests/file/tempnam_variation3.phpt
index 4a0e86173a..69ab16c896 100644
--- a/ext/standard/tests/file/tempnam_variation3.phpt
+++ b/ext/standard/tests/file/tempnam_variation3.phpt
@@ -100,9 +100,9 @@ File name is => %s/%s
File permissions are => 100600
File created in => directory specified
-- Iteration 6 --
--- File is not created --
-
-Warning: unlink(): %s in %s on line %d
+File name is => %s/%s
+File permissions are => 100600
+File created in => directory specified
-- Iteration 7 --
Warning: tempnam() expects parameter 2 to be string, array given in %s on line %d
diff --git a/ext/standard/tests/file/tempnam_variation7-win32.phpt b/ext/standard/tests/file/tempnam_variation7-win32.phpt
index 8ea839e2a7..0c8caca95c 100644
--- a/ext/standard/tests/file/tempnam_variation7-win32.phpt
+++ b/ext/standard/tests/file/tempnam_variation7-win32.phpt
@@ -13,7 +13,7 @@ if(substr(PHP_OS, 0, 3) != "WIN")
/* Passing invalid/non-existing args for $dir,
hence the unique files will be created in temporary dir */
-
+
echo "*** Testing tempnam() with invalid/non-existing directory names ***\n";
/* An array of names, which will be passed as a dir name */
$names_arr = array(
@@ -89,15 +89,17 @@ File name is => %s%et%s
File permissions are => 100666
File created in => temp dir
-- Iteration 6 --
+
+Warning: tempnam() expects parameter 1 to be a valid path, string given in %stempnam_variation7-win32.php on line %d
-- File is not created --
-Warning: unlink(): %s in %s on line %d
+Warning: unlink(): %r(Invalid argument|No such file or directory)%r in %s on line %d
-- Iteration 7 --
-Warning: tempnam() expects parameter 1 to be string, array given in %s on line %d
+Warning: tempnam() expects parameter 1 to be a valid path, array given in %s on line %d
-- File is not created --
-Warning: unlink(): %s in %s on line %d
+Warning: unlink(): %r(Invalid argument|No such file or directory)%r in %s on line %d
-- Iteration 8 --
File name is => %s%et%s
File permissions are => 100666
diff --git a/ext/standard/tests/file/tempnam_variation7.phpt b/ext/standard/tests/file/tempnam_variation7.phpt
index 16f94f0a1b..b6f81caabc 100644
--- a/ext/standard/tests/file/tempnam_variation7.phpt
+++ b/ext/standard/tests/file/tempnam_variation7.phpt
@@ -94,21 +94,23 @@ File name is => %s%etempnam_variation3.tmp%s
File permissions are => 100600
File created in => temp dir
-- Iteration 6 --
+
+Warning: tempnam() expects parameter 1 to be a valid path, string given in %s on line %d
-- File is not created --
Warning: unlink(): %s in %s on line %d
-- Iteration 7 --
-Warning: tempnam() expects parameter 1 to be string, array given in %s on line %d
+Warning: tempnam() expects parameter 1 to be a valid path, array given in %s on line %d
-- File is not created --
Warning: unlink(): %s in %s on line %d
-- Iteration 8 --
-File name is => %s%etempnam_variation3.tmp%s
+File name is => %s/tempnam_variation3.tmp%s
File permissions are => 100600
File created in => temp dir
-- Iteration 9 --
-File name is => %s%etempnam_variation3.tmp%s
+File name is => %s/tempnam_variation3.tmp%s
File permissions are => 100600
File created in => temp dir
diff --git a/ext/standard/tests/file/umask_basic.phpt b/ext/standard/tests/file/umask_basic.phpt
index 7a2eb762db..761df97253 100644
--- a/ext/standard/tests/file/umask_basic.phpt
+++ b/ext/standard/tests/file/umask_basic.phpt
@@ -20,7 +20,7 @@ for($mask = 0000; $mask <= 0777; $mask++) {
var_dump( umask() );
echo "\n";
if ($mask != umask()) {
- die('An error occured while changing back the umask');
+ die('An error occurred while changing back the umask');
}
}
diff --git a/ext/standard/tests/file/umask_variation3.phpt b/ext/standard/tests/file/umask_variation3.phpt
index cb34294fea..c666c328df 100644
--- a/ext/standard/tests/file/umask_variation3.phpt
+++ b/ext/standard/tests/file/umask_variation3.phpt
@@ -11,9 +11,9 @@ if (substr(PHP_OS, 0, 3) == 'WIN') {
--FILE--
<?php
/* Prototype : int umask([int mask])
- * Description: Return or change the umask
+ * Description: Return or change the umask
* Source code: ext/standard/file.c
- * Alias to functions:
+ * Alias to functions:
*/
echo "*** Testing umask() : usage variation ***\n";
@@ -110,7 +110,7 @@ foreach($inputs as $key =>$value) {
echo "\n--$key--\n";
umask(0);
var_dump(umask($value));
- var_dump(umask() & 0777);
+ var_dump( umask() & 0777);
};
?>
diff --git a/ext/standard/tests/file/userstreams_005.phpt b/ext/standard/tests/file/userstreams_005.phpt
new file mode 100644
index 0000000000..2d39be25d6
--- /dev/null
+++ b/ext/standard/tests/file/userstreams_005.phpt
@@ -0,0 +1,63 @@
+--TEST--
+User-space streams: stream_truncate()
+--FILE--
+<?php
+class test_wrapper_base {
+ public $mode;
+ function stream_open($path, $mode, $openedpath) {
+ return true;
+ }
+ function stream_eof() {
+ return false;
+ }
+}
+class test_wrapper extends test_wrapper_base {
+ function stream_truncate($new_size) {
+ echo "truncation with new_size=$new_size\n";
+ return true;
+ }
+}
+class test_wrapper_bad extends test_wrapper_base {
+ function stream_truncate($new_size) {
+ echo "truncation with new_size=$new_size\n";
+ return "kkk";
+ }
+}
+function test($name, $fd, $dest_size) {
+ echo "------ $name: -------\n";
+ var_dump(ftruncate($fd, $dest_size));
+}
+var_dump(stream_wrapper_register('test', 'test_wrapper'));
+var_dump(stream_wrapper_register('test2', 'test_wrapper_base'));
+var_dump(stream_wrapper_register('test3', 'test_wrapper_bad'));
+
+$fd = fopen("test://foo","r");
+$fd2 = fopen("test2://foo","r");
+$fd3 = fopen("test3://foo","r");
+
+test("stream_truncate not implemented", $fd2, 0);
+test("stream_truncate size 0", $fd, 0);
+test("stream_truncate size 10", $fd, 10);
+test("stream_truncate negative size", $fd, -1);
+test("stream_truncate bad return", $fd3, 0);
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+------ stream_truncate not implemented: -------
+
+Warning: ftruncate(): Can't truncate this stream! in %s on line %d
+bool(false)
+------ stream_truncate size 0: -------
+truncation with new_size=0
+bool(true)
+------ stream_truncate size 10: -------
+truncation with new_size=10
+bool(true)
+------ stream_truncate negative size: -------
+bool(false)
+------ stream_truncate bad return: -------
+truncation with new_size=0
+
+Warning: ftruncate(): test_wrapper_bad::stream_truncate did not return a boolean! in %s on line %d
+bool(false)
diff --git a/ext/standard/tests/file/userstreams_006.phpt b/ext/standard/tests/file/userstreams_006.phpt
new file mode 100644
index 0000000000..69ebd8d0a9
--- /dev/null
+++ b/ext/standard/tests/file/userstreams_006.phpt
@@ -0,0 +1,38 @@
+--TEST--
+User-space streams: set_options returns "not implemented" for unhandled option types
+--FILE--
+<?php
+class test_wrapper {
+ function stream_open($path, $mode, $openedpath) {
+ return true;
+ }
+ function stream_eof() {
+ return false;
+ }
+ function stream_write($data) {
+ echo "size: ", strlen($data), "\n";
+ return strlen($data);
+ }
+ function stream_set_option($option, $arg1, $arg2) {
+ echo "option: ", $option, ", ", $arg1, ", ", $arg2, "\n";
+ return false;
+ }
+}
+
+var_dump(stream_wrapper_register('test', 'test_wrapper'));
+
+$fd = fopen("test://foo","r");
+
+var_dump(stream_set_write_buffer($fd, 50));
+var_dump(stream_set_chunk_size($fd, 42));
+
+var_dump(fwrite($fd, str_repeat('0', 70)));
+
+--EXPECT--
+bool(true)
+option: 3, 2, 50
+int(-1)
+int(8192)
+size: 42
+size: 28
+int(70)
diff --git a/ext/standard/tests/file/userstreams_007.phpt b/ext/standard/tests/file/userstreams_007.phpt
new file mode 100644
index 0000000000..3f66f1802b
--- /dev/null
+++ b/ext/standard/tests/file/userstreams_007.phpt
@@ -0,0 +1,49 @@
+--TEST--
+User-space streams: test metadata option
+--FILE--
+<?php
+class test_wrapper {
+ function stream_open($path, $mode, $openedpath) {
+ return true;
+ }
+ public function stream_metadata($path, $option, $var) {
+ echo "metadata: $path, $option\n";
+ if(is_array($var)) {
+ echo join(",", $var);
+ } else {
+ echo $var;
+ }
+ echo "\n";
+ return false;
+ }
+}
+
+var_dump(stream_wrapper_register('test', 'test_wrapper'));
+
+$fd = fopen("test://foo","r");
+touch("test://testdir/touch");
+touch("test://testdir/touch", 1);
+touch("test://testdir/touch", 1, 2);
+chown("test://testdir/chown", "test");
+chown("test://testdir/chown", 42);
+chgrp("test://testdir/chgrp", "test");
+chgrp("test://testdir/chgrp", 42);
+chmod("test://testdir/chmod", 0755);
+--EXPECT--
+bool(true)
+metadata: test://testdir/touch, 1
+
+metadata: test://testdir/touch, 1
+1,1
+metadata: test://testdir/touch, 1
+1,2
+metadata: test://testdir/chown, 2
+test
+metadata: test://testdir/chown, 3
+42
+metadata: test://testdir/chgrp, 4
+test
+metadata: test://testdir/chgrp, 5
+42
+metadata: test://testdir/chmod, 6
+493 \ No newline at end of file
diff --git a/ext/standard/tests/file/windows_links/bug48746.phpt b/ext/standard/tests/file/windows_links/bug48746.phpt
index 55465aea86..5978e7f7f1 100644
--- a/ext/standard/tests/file/windows_links/bug48746.phpt
+++ b/ext/standard/tests/file/windows_links/bug48746.phpt
@@ -1,7 +1,7 @@
--TEST--
Bug#48746 - Junction not working properly
---CREDIT--
+--CREDITS--
Venkat Raman Don (don.raman@microsoft.com)
--SKIPIF--
diff --git a/ext/standard/tests/file/windows_links/bug48746_1.phpt b/ext/standard/tests/file/windows_links/bug48746_1.phpt
index 5d8e685e1b..a4277a47a1 100644
--- a/ext/standard/tests/file/windows_links/bug48746_1.phpt
+++ b/ext/standard/tests/file/windows_links/bug48746_1.phpt
@@ -1,7 +1,7 @@
--TEST--
Bug#48746 - Junction not working properly
---CREDIT--
+--CREDITS--
Venkat Raman Don (don.raman@microsoft.com)
--SKIPIF--
diff --git a/ext/standard/tests/file/windows_links/bug48746_2.phpt b/ext/standard/tests/file/windows_links/bug48746_2.phpt
index 56924a59bc..509610f8a4 100644
--- a/ext/standard/tests/file/windows_links/bug48746_2.phpt
+++ b/ext/standard/tests/file/windows_links/bug48746_2.phpt
@@ -1,7 +1,7 @@
--TEST--
Bug#48746 - Junction not working properly
---CREDIT--
+--CREDITS--
Venkat Raman Don (don.raman@microsoft.com)
--SKIPIF--
diff --git a/ext/standard/tests/file/windows_links/bug48746_3.phpt b/ext/standard/tests/file/windows_links/bug48746_3.phpt
index b88ab76ef3..98e81787b8 100644
--- a/ext/standard/tests/file/windows_links/bug48746_3.phpt
+++ b/ext/standard/tests/file/windows_links/bug48746_3.phpt
@@ -1,7 +1,7 @@
--TEST--
Bug#48746 - Junction not working properly
---CREDIT--
+--CREDITS--
Venkat Raman Don (don.raman@microsoft.com)
--SKIPIF--
diff --git a/ext/standard/tests/filters/php_user_filter_01.phpt b/ext/standard/tests/filters/php_user_filter_01.phpt
index 534b9abf32..e4a9c6853c 100644
--- a/ext/standard/tests/filters/php_user_filter_01.phpt
+++ b/ext/standard/tests/filters/php_user_filter_01.phpt
@@ -14,4 +14,4 @@ class bar extends php_user_filter {
}
?>
--EXPECTF--
-Strict Standards: Declaration of bar::filter() should be compatible with that of php_user_filter::filter() in %s on line %d
+Strict Standards: Declaration of bar::filter() should be compatible with php_user_filter::filter($in, $out, &$consumed, $closing) in %s on line %d
diff --git a/ext/standard/tests/filters/php_user_filter_02.phpt b/ext/standard/tests/filters/php_user_filter_02.phpt
index 73a1f02672..2a1dbfdadf 100644
--- a/ext/standard/tests/filters/php_user_filter_02.phpt
+++ b/ext/standard/tests/filters/php_user_filter_02.phpt
@@ -9,4 +9,4 @@ class foo extends php_user_filter {
}
?>
--EXPECTF--
-Strict Standards: Declaration of foo::filter() should be compatible with that of php_user_filter::filter() in %s on line %d
+Strict Standards: Declaration of foo::filter() should be compatible with php_user_filter::filter($in, $out, &$consumed, $closing) in %s on line %d
diff --git a/ext/standard/tests/filters/php_user_filter_03.phpt b/ext/standard/tests/filters/php_user_filter_03.phpt
index 5962951eee..e9e0266381 100644
--- a/ext/standard/tests/filters/php_user_filter_03.phpt
+++ b/ext/standard/tests/filters/php_user_filter_03.phpt
@@ -9,4 +9,4 @@ class foo extends php_user_filter {
}
?>
--EXPECTF--
-Strict Standards: Declaration of foo::onCreate() should be compatible with that of php_user_filter::onCreate() in %s on line %d
+Strict Standards: Declaration of foo::onCreate() should be compatible with php_user_filter::onCreate() in %s on line %d
diff --git a/ext/standard/tests/general_functions/bug27678.phpt b/ext/standard/tests/general_functions/bug27678.phpt
index 5db5890a1c..6f95509e14 100644
--- a/ext/standard/tests/general_functions/bug27678.phpt
+++ b/ext/standard/tests/general_functions/bug27678.phpt
@@ -6,9 +6,11 @@ Bug #27678 (number_format() crashes with large numbers)
number_format(1e80, 0, '', ' ');
number_format(1e300, 0, '', ' ');
number_format(1e320, 0, '', ' ');
-number_format(1e1000, 0, '', ' ');
+$num = number_format(1e1000, 0, '', ' ');
+var_dump(strlen($num) == 3); // $num == 'inf'
echo "Done\n";
?>
--EXPECT--
+bool(true)
Done
diff --git a/ext/standard/tests/general_functions/bug41518.phpt b/ext/standard/tests/general_functions/bug41518.phpt
index 4a3858b4ea..26e2413ce9 100644
--- a/ext/standard/tests/general_functions/bug41518.phpt
+++ b/ext/standard/tests/general_functions/bug41518.phpt
@@ -7,6 +7,7 @@ mkdir($tmp_dir);
if (!is_dir($tmp_dir)) {
die("skip");
}
+@unlink($tmp_dir);
?>
--INI--
open_basedir=.
@@ -14,6 +15,7 @@ open_basedir=.
<?php
$tmp_dir = __DIR__ . "/bug41518/";
+@mkdir($tmp_dir);
$tmp_file = $tmp_dir."/bug41418.tmp";
touch($tmp_file);
@@ -24,6 +26,11 @@ var_dump(file_exists($tmp_file."nosuchfile")); //doesn't exist
@rmdir($tmp_dir);
echo "Done\n";
?>
+--CLEAN--
+<?php
+$tmp_dir = __DIR__ . "/bug41518/";
+@unlink($tmp_dir);
+?>
--EXPECT--
bool(true)
bool(false)
diff --git a/ext/standard/tests/general_functions/bug55371.phpt b/ext/standard/tests/general_functions/bug55371.phpt
new file mode 100644
index 0000000000..179da01f39
--- /dev/null
+++ b/ext/standard/tests/general_functions/bug55371.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #55371 (get_magic_quotes_gpc() and get_magic_quotes_runtime() throw deprecated warning)
+--FILE--
+<?php
+
+get_magic_quotes_gpc();
+get_magic_quotes_runtime();
+
+?>
+--EXPECT--
diff --git a/ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt b/ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
index 340e4e5daf..c05a329342 100644
--- a/ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
+++ b/ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
@@ -50,7 +50,7 @@ array(1) {
------ Calling by_val() with referenced argument ------
array(1) {
[0]=>
- &string(7) "changed"
+ &string(8) "original"
}
------ Calling by_ref() with referenced argument ------
array(1) {
diff --git a/ext/standard/tests/general_functions/debug_zval_dump_b.phpt b/ext/standard/tests/general_functions/debug_zval_dump_b.phpt
index 193d7dc960..e83cdbf540 100644
--- a/ext/standard/tests/general_functions/debug_zval_dump_b.phpt
+++ b/ext/standard/tests/general_functions/debug_zval_dump_b.phpt
Binary files differ
diff --git a/ext/standard/tests/general_functions/debug_zval_dump_b_64bit.phpt b/ext/standard/tests/general_functions/debug_zval_dump_b_64bit.phpt
index b5dfa5e6be..d6d8ae24f3 100644
--- a/ext/standard/tests/general_functions/debug_zval_dump_b_64bit.phpt
+++ b/ext/standard/tests/general_functions/debug_zval_dump_b_64bit.phpt
Binary files differ
diff --git a/ext/standard/tests/general_functions/debug_zval_dump_o.phpt b/ext/standard/tests/general_functions/debug_zval_dump_o.phpt
index dd4b5142a1..78f0f03003 100644
--- a/ext/standard/tests/general_functions/debug_zval_dump_o.phpt
+++ b/ext/standard/tests/general_functions/debug_zval_dump_o.phpt
@@ -1,5 +1,7 @@
--TEST--
Test debug_zval_dump() function : working on objects
+--SKIPIF--
+<?php if (PHP_ZTS) { print "skip only for no-zts build"; }
--FILE--
<?php
/* Prototype: void debug_zval_dump ( mixed $variable );
diff --git a/ext/standard/tests/general_functions/debug_zval_dump_v.phpt b/ext/standard/tests/general_functions/debug_zval_dump_v.phpt
index a01e592628..82ee2a63d5 100644
--- a/ext/standard/tests/general_functions/debug_zval_dump_v.phpt
+++ b/ext/standard/tests/general_functions/debug_zval_dump_v.phpt
@@ -1,7 +1,5 @@
--TEST--
Test debug_zval_dump() function : usage variations
---INI--
-allow_call_time_pass_reference=1
--FILE--
<?php
/* Prototype: void debug_zval_dump ( mixed $variable );
@@ -115,7 +113,6 @@ $counter = 1;
foreach( $misc_values as $value ) {
echo "-- Iteration $counter --\n";
debug_zval_dump( $value );
- debug_zval_dump( &$value );
$counter++;
}
@@ -190,26 +187,18 @@ long(10) refcount(2)
*** Testing debug_zval_dump() on miscelleneous input arguments ***
-- Iteration 1 --
NULL refcount(3)
-&NULL refcount(2)
-- Iteration 2 --
NULL refcount(3)
-&NULL refcount(2)
-- Iteration 3 --
NULL refcount(1)
-&NULL refcount(2)
-- Iteration 4 --
NULL refcount(1)
-&NULL refcount(2)
-- Iteration 5 --
string(7) "TRUE123" refcount(3)
-&string(7) "TRUE123" refcount(2)
-- Iteration 6 --
string(9) "123string" refcount(3)
-&string(9) "123string" refcount(2)
-- Iteration 7 --
string(9) "string123" refcount(3)
-&string(9) "string123" refcount(2)
-- Iteration 8 --
string(10) "NULLstring" refcount(3)
-&string(10) "NULLstring" refcount(2)
Done
diff --git a/ext/standard/tests/general_functions/get_cfg_var_variation8.phpt b/ext/standard/tests/general_functions/get_cfg_var_variation8.phpt
index f679a41ebf..c7a72de944 100644
--- a/ext/standard/tests/general_functions/get_cfg_var_variation8.phpt
+++ b/ext/standard/tests/general_functions/get_cfg_var_variation8.phpt
@@ -1,20 +1,17 @@
---TEST--
-Test function get_cfg_var() by calling deprecated option
---CREDITS--
-Francesco Fullone ff@ideato.it
-#PHPTestFest Cesena Italia on 2009-06-20
---INI--
-register_globals=1
---SKIPIF--
-<?php if (version_compare(PHP_VERSION, "5.3", "<")) die("skip requires 5.3 or greater"); ?>
---FILE--
-<?php
-echo "*** Test by calling method or function with deprecated option ***\n";
-var_dump(get_cfg_var( 'register_globals' ) );
-
-?>
---EXPECTF--
-Deprecated: Directive 'register_globals' is deprecated in PHP 5.3 and greater in %s on line 0
-*** Test by calling method or function with deprecated option ***
-string(1) "1"
-
+--TEST--
+Test function get_cfg_var() by calling deprecated option
+--CREDITS--
+Francesco Fullone ff@ideato.it
+#PHPTestFest Cesena Italia on 2009-06-20
+--INI--
+magic_quotes_gpc=1
+--SKIPIF--
+<?php if (version_compare(PHP_VERSION, "5.3", "<")) die("skip requires 5.3 or greater"); ?>
+--FILE--
+<?php
+echo "*** Test by calling method or function with deprecated option ***\n";
+var_dump(get_cfg_var( 'magic_quotes_gpc' ) );
+
+?>
+--EXPECTF--
+Fatal error: Directive 'magic_quotes_gpc' is no longer available in PHP in Unknown on line 0
diff --git a/ext/standard/tests/general_functions/get_magic_quotes_gpc.phpt b/ext/standard/tests/general_functions/get_magic_quotes_gpc.phpt
index cfa4dcc681..75cde18b08 100644
--- a/ext/standard/tests/general_functions/get_magic_quotes_gpc.phpt
+++ b/ext/standard/tests/general_functions/get_magic_quotes_gpc.phpt
@@ -1,27 +1,13 @@
--TEST--
Test get_magic_quotes_gpc() function
---INI--
-magic_quotes_gpc = 0
--FILE--
<?php
/* Prototype: int get_magic_quotes_gpc ( void )
- * Description: Gets the current configuration setting of magic quotes gpc
-*/
+ * This function is not supported anymore and will always return false
+ */
echo "Simple testcase for get_magic_quotes_gpc() function\n";
-
-$g = get_magic_quotes_gpc();
-echo "\n-- magic quotes gpc set in INI file: " . $g . " --\n";
-
-echo "\n-- Set magic quotes gpc to 1 - not allowed so should fail! --\n";
-var_dump(ini_set("magic_quotes_gpc", 1));
-$g = get_magic_quotes_gpc();
-echo "\n-- magic quotes gpc after set: " . $g . " --\n";
-
-echo "\n-- Set magic quotes gpc to 0: --\n";
-var_dump(ini_set("magic_quotes_gpc", 0));
-$g = get_magic_quotes_gpc();
-echo "\n-- magic quotes gpc after set: " . $g . " --\n";
+var_dump(get_magic_quotes_gpc());
echo "\n-- Error cases --\n";
// no checks on number of args
@@ -29,21 +15,12 @@ var_dump(get_magic_quotes_gpc(true));
?>
===DONE===
---EXPECT--
+--EXPECTF--
Simple testcase for get_magic_quotes_gpc() function
-
--- magic quotes gpc set in INI file: 0 --
-
--- Set magic quotes gpc to 1 - not allowed so should fail! --
bool(false)
--- magic quotes gpc after set: 0 --
-
--- Set magic quotes gpc to 0: --
-bool(false)
-
--- magic quotes gpc after set: 0 --
-
-- Error cases --
-int(0)
-===DONE=== \ No newline at end of file
+
+Warning: get_magic_quotes_gpc() expects exactly 0 parameters, 1 given in %s on line %d
+NULL
+===DONE===
diff --git a/ext/standard/tests/general_functions/get_magic_quotes_runtime.phpt b/ext/standard/tests/general_functions/get_magic_quotes_runtime.phpt
index fca064d840..4106ee9eea 100644
--- a/ext/standard/tests/general_functions/get_magic_quotes_runtime.phpt
+++ b/ext/standard/tests/general_functions/get_magic_quotes_runtime.phpt
@@ -1,32 +1,14 @@
--TEST--
Test get_magic_quotes_runtime() function
---INI--
-magic_quotes_runtime = 0
--FILE--
<?php
/* Prototype: int get_magic_quotes_runtime ( void )
- * Description: Gets the current active configuration setting of magic_quotes_runtime
-*/
+ * This function is not supported anymore and will always return false
+ */
echo "Simple testcase for get_magic_quotes_runtime() function\n";
-$g = get_magic_quotes_runtime();
-echo "\n-- magic quotes runtime set in INI file: " . $g . " --\n";
-
-echo "\n-- Set magic quotes runtime to 1: --\n";
-var_dump(set_magic_quotes_runtime(1));
-$g = get_magic_quotes_runtime();
-echo "\n-- magic quotes runtime after set: " . $g . " --\n";
-
-echo "\n-- Set magic quotes runtime to 0: --\n";
-var_dump(set_magic_quotes_runtime(0));
-$g = get_magic_quotes_runtime();
-echo "\n-- magic quotes runtime after set: " . $g . " --\n";
-
-echo "\n-- Set magic quotes runtime to 1: --\n";
-var_dump(set_magic_quotes_runtime(1));
-$g = get_magic_quotes_runtime();
-echo "\n-- magic quotes runtime after set: " . $g . " --\n";
+var_dump(get_magic_quotes_runtime());
echo "\n-- Error cases --\n";
// no checks on number of args
@@ -36,30 +18,10 @@ var_dump(get_magic_quotes_runtime(true));
===DONE===
--EXPECTF--
Simple testcase for get_magic_quotes_runtime() function
-
--- magic quotes runtime set in INI file: 0 --
-
--- Set magic quotes runtime to 1: --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-
--- magic quotes runtime after set: 1 --
-
--- Set magic quotes runtime to 0: --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-
--- magic quotes runtime after set: 0 --
-
--- Set magic quotes runtime to 1: --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-
--- magic quotes runtime after set: 1 --
+bool(false)
-- Error cases --
-int(1)
+
+Warning: get_magic_quotes_runtime() expects exactly 0 parameters, 1 given in %s on line %d
+NULL
===DONE===
diff --git a/ext/standard/tests/general_functions/getservbyname_variation10.phpt b/ext/standard/tests/general_functions/getservbyname_variation10.phpt
index 70aa567646..c7ed144f10 100644
--- a/ext/standard/tests/general_functions/getservbyname_variation10.phpt
+++ b/ext/standard/tests/general_functions/getservbyname_variation10.phpt
@@ -1,5 +1,11 @@
--TEST--
Test function getservbyname() by substituting argument 2 with emptyUnsetUndefNull values.
+--SKIPIF--
+<?php
+if(PHP_OS == 'Darwin') {
+ die("skip.. Mac OS X is fine with NULLs in getservbyname");
+}
+?>
--FILE--
<?php
diff --git a/ext/standard/tests/general_functions/getservbyname_variation9.phpt b/ext/standard/tests/general_functions/getservbyname_variation9.phpt
index c1c231e148..eef2744c26 100644
--- a/ext/standard/tests/general_functions/getservbyname_variation9.phpt
+++ b/ext/standard/tests/general_functions/getservbyname_variation9.phpt
@@ -1,5 +1,11 @@
--TEST--
Test function getservbyname() by substituting argument 2 with boolean values.
+--SKIPIF--
+<?php
+if(PHP_OS == 'Darwin') {
+ die("skip.. Mac OS X is fine with NULLs in getservbyname");
+}
+?>
--FILE--
<?php
diff --git a/ext/standard/tests/general_functions/import_request.phpt b/ext/standard/tests/general_functions/import_request.phpt
index 0f9e93bf0c..4a791c736a 100644
--- a/ext/standard/tests/general_functions/import_request.phpt
+++ b/ext/standard/tests/general_functions/import_request.phpt
@@ -1,11 +1,11 @@
--TEST--
import_request_variables() tests
+--SKIPIF--
+<?php if(PHP_VERSION_ID >= 50399){ die('skip not needed anymore without register_globals'); } ?>
--GET--
a=1&b=heh&c=3&d[]=5&GLOBALS=test&1=hm
--POST--
ap=25&bp=test&cp=blah3&dp[]=ar
---INI--
-register_globals=0
--FILE--
<?php
diff --git a/ext/standard/tests/general_functions/import_request1.phpt b/ext/standard/tests/general_functions/import_request1.phpt
index cb6df69e08..f592088afc 100644
--- a/ext/standard/tests/general_functions/import_request1.phpt
+++ b/ext/standard/tests/general_functions/import_request1.phpt
@@ -1,5 +1,7 @@
--TEST--
import_request_variables() test (overwrite super-globals)
+--SKIPIF--
+<?php if(PHP_VERSION_ID >= 50399){ die('skip not needed anymore without register_globals'); } ?>
--GET--
GET=0&POST=1&COOKIE=2&FILES=3&REQUEST=4
--POST--
diff --git a/ext/standard/tests/general_functions/import_request2.phpt b/ext/standard/tests/general_functions/import_request2.phpt
index eb278217c0..c290602b23 100644
--- a/ext/standard/tests/general_functions/import_request2.phpt
+++ b/ext/standard/tests/general_functions/import_request2.phpt
@@ -1,5 +1,7 @@
--TEST--
import_request_variables() test (numeric keys)
+--SKIPIF--
+<?php if(PHP_VERSION_ID >= 50399){ die('skip not needed anymore without register_globals'); } ?>
--GET--
1=0&2=1&3=2&4=3&5=4
--POST--
diff --git a/ext/standard/tests/general_functions/import_request3.phpt b/ext/standard/tests/general_functions/import_request3.phpt
index a9fba26ddf..a8cbf565dd 100644
--- a/ext/standard/tests/general_functions/import_request3.phpt
+++ b/ext/standard/tests/general_functions/import_request3.phpt
@@ -1,5 +1,7 @@
--TEST--
import_request_variables() test (numeric keys, different order)
+--SKIPIF--
+<?php if(PHP_VERSION_ID >= 50399){ die('skip not needed anymore without register_globals'); } ?>
--GET--
1=0&2=1&3=2&4=3&5=4
--POST--
diff --git a/ext/standard/tests/general_functions/ob_get_flush_error.phpt b/ext/standard/tests/general_functions/ob_get_flush_error.phpt
index db666c5a6a..1d3538120d 100644
--- a/ext/standard/tests/general_functions/ob_get_flush_error.phpt
+++ b/ext/standard/tests/general_functions/ob_get_flush_error.phpt
@@ -26,5 +26,7 @@ var_dump( ob_get_flush() );
Warning: ob_get_flush() expects exactly 0 parameters, 1 given in %s on line %d
NULL
+
+Notice: ob_get_flush(): failed to delete and flush buffer. No buffer to delete or flush in %s on line %d
bool(false)
===DONE===
diff --git a/ext/standard/tests/general_functions/parse_ini_basic.data b/ext/standard/tests/general_functions/parse_ini_basic.data
index fdbd55cbf9..cafbb15742 100644
--- a/ext/standard/tests/general_functions/parse_ini_basic.data
+++ b/ext/standard/tests/general_functions/parse_ini_basic.data
@@ -12,7 +12,7 @@ boolno = no
string = asdadfsdjkslkj ¡@£$$ { }[ ]/%#¤
sqstring = 'adsasdadasdasd'
dqstring = "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #"
-php_constant = E_ALL
+php_constant = E_WARNING
user_constant = TEST_CONSTANT
[basic with whitespace]
@@ -28,7 +28,7 @@ boolnone = none
boolno = no
sqstring = 'adsasdadasdasd'
dqstring = "asdadfsdjkslkj ¡@£$$€¥¥{[()/)&/%#¤"
-php_constant = E_ALL
+php_constant = E_WARNING
[comments]
; some comment
diff --git a/ext/standard/tests/general_functions/parse_ini_basic.phpt b/ext/standard/tests/general_functions/parse_ini_basic.phpt
index bdd44e0a2f..0c0591e7eb 100644
--- a/ext/standard/tests/general_functions/parse_ini_basic.phpt
+++ b/ext/standard/tests/general_functions/parse_ini_basic.phpt
@@ -45,7 +45,7 @@ array(26) {
["dqstring"]=>
string(51) "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #"
["php_constant"]=>
- string(5) "30719"
+ string(1) "2"
["user_constant"]=>
string(21) "this_is_test_constant"
}
@@ -76,7 +76,7 @@ array(26) {
["dqstring"]=>
string(41) "asdadfsdjkslkj ¡@£$$€¥¥{[()/)&/%#¤"
["php_constant"]=>
- string(5) "30719"
+ string(1) "2"
}
["comments"]=>
array(1) {
diff --git a/ext/standard/tests/general_functions/parse_ini_booleans.phpt b/ext/standard/tests/general_functions/parse_ini_booleans.phpt
index 37965789e0..7b012c50f6 100644
--- a/ext/standard/tests/general_functions/parse_ini_booleans.phpt
+++ b/ext/standard/tests/general_functions/parse_ini_booleans.phpt
@@ -15,15 +15,15 @@ array(3) {
["error_reporting values"]=>
array(6) {
["foo"]=>
- string(7) "30719 8"
+ string(7) "32767 8"
["error_reporting"]=>
- string(5) "30719"
+ string(5) "32767"
["error_reporting1"]=>
string(4) "4177"
["error_reporting2"]=>
- string(5) "30711"
+ string(5) "32759"
["error_reporting3"]=>
- string(5) "30711"
+ string(5) "32759"
["error_reporting4"]=>
string(5) "32759"
}
diff --git a/ext/standard/tests/general_functions/phpinfo.phpt b/ext/standard/tests/general_functions/phpinfo.phpt
index 7da94c3596..01b0c62c3b 100644
--- a/ext/standard/tests/general_functions/phpinfo.phpt
+++ b/ext/standard/tests/general_functions/phpinfo.phpt
@@ -34,9 +34,12 @@ Zend Extension Build => API%s
PHP Extension Build => API%s
Debug Build => %s
Thread Safety => %s
+Zend Signal Handling => %s
Zend Memory Manager => %s
Zend Multibyte Support => %s
IPv6 Support => %s
+DTrace Support => %s
+
Registered PHP Streams => %s
Registered Stream Socket Transports => %s
Registered Stream Filters => %s
diff --git a/ext/standard/tests/general_functions/proc_nice_error.phpt b/ext/standard/tests/general_functions/proc_nice_error.phpt
index 09f84fa552..a05a18263e 100644
--- a/ext/standard/tests/general_functions/proc_nice_error.phpt
+++ b/ext/standard/tests/general_functions/proc_nice_error.phpt
@@ -6,20 +6,23 @@ if(!function_exists('proc_nice')) die("skip. proc_nice not available ");
?>
--FILE--
<?php
+echo "*** Test by calling method or function with incorrect numbers of arguments ***\n";
+$priority = 1;
-echo "*** Test by calling method or function with incorrect numbers of arguments ***\n"
+$extra_arg = 1;
-$priority =
-
-
-$extra_arg =
-
-var_dump(proc_nice( $priority, $extra_arg ) );
+var_dump(proc_nice( $priority, $extra_arg) );
var_dump(proc_nice( ) );
?>
--EXPECTF--
-Parse error: syntax error, unexpected T_VARIABLE, expecting ',' or ';' in %s on line %d
+*** Test by calling method or function with incorrect numbers of arguments ***
+
+Warning: proc_nice() expects exactly 1 parameter, 2 given in %s line %d
+bool(false)
+
+Warning: proc_nice() expects exactly 1 parameter, 0 given in %s line %d
+bool(false)
diff --git a/ext/standard/tests/general_functions/putenv_error1.phpt b/ext/standard/tests/general_functions/putenv_error1.phpt
deleted file mode 100644
index 0fd0640bf4..0000000000
--- a/ext/standard/tests/general_functions/putenv_error1.phpt
+++ /dev/null
@@ -1,26 +0,0 @@
---TEST--
-putenv() - usage in safe mode with safe_mode_allowed_env_vars set
---CREDITS--
-Brian DeShong <brian@deshong.net>
---INI--
-safe_mode=1
-safe_mode_allowed_env_vars=TESTING_
---FILE--
-<?php
-putenv('FOO=bar');
-putenv('BAZ=bop');
-$set = putenv('TESTING_FOO=bar');
-print ($set ? 'it worked' : 'boo') . "\n";
-$set = putenv('TESTING_BAR=baz');
-print ($set ? 'it worked' : 'boo') . "\n";
-?>
-==DONE==
---EXPECTF--
-Deprecated: Directive 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Warning: putenv(): Safe Mode warning: Cannot set environment variable 'FOO' - it's not in the allowed list in %s on line %d
-
-Warning: putenv(): Safe Mode warning: Cannot set environment variable 'BAZ' - it's not in the allowed list in %s on line %d
-it worked
-it worked
-==DONE==
diff --git a/ext/standard/tests/general_functions/putenv_error2.phpt b/ext/standard/tests/general_functions/putenv_error2.phpt
deleted file mode 100644
index b8f306c79e..0000000000
--- a/ext/standard/tests/general_functions/putenv_error2.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-putenv() - usage in safe mode with safe_mode_protected_env_vars set
---CREDITS--
-Brian DeShong <brian@deshong.net>
---INI--
-safe_mode=1
-safe_mode_protected_env_vars=FOO,BAZ
---FILE--
-<?php
-putenv('FOO=bar');
-putenv('BAZ=bop');
-?>
-==DONE==
---EXPECTF--
-Deprecated: Directive 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line 0
-
-Warning: putenv(): Safe Mode warning: Cannot override protected environment variable 'FOO' in %s on line %d
-
-Warning: putenv(): Safe Mode warning: Cannot override protected environment variable 'BAZ' in %s on line %d
-==DONE==
diff --git a/ext/standard/tests/general_functions/set_magic_quotes_runtime_basic.phpt b/ext/standard/tests/general_functions/set_magic_quotes_runtime_basic.phpt
index eb647435ac..ad786fb525 100644
--- a/ext/standard/tests/general_functions/set_magic_quotes_runtime_basic.phpt
+++ b/ext/standard/tests/general_functions/set_magic_quotes_runtime_basic.phpt
@@ -13,11 +13,6 @@ echo "Simple testcase for set_magic_quotes_runtime() function - basic test\n";
$g = get_magic_quotes_runtime();
echo "\n-- magic quotes runtime set in INI file: " . $g . "--\n";
-echo "\n-- Set magic quotes runtime to 1: --\n";
-var_dump(set_magic_quotes_runtime(1));
-$g = get_magic_quotes_runtime();
-echo "\n-- magic quotes runtime after set: " . $g . " --\n";
-
echo "\n-- Set magic quotes runtime to 0: --\n";
var_dump(set_magic_quotes_runtime(0));
$g = get_magic_quotes_runtime();
@@ -33,26 +28,19 @@ echo "\n-- magic quotes runtime after set: " . $g . " --\n";
--EXPECTF--
Simple testcase for set_magic_quotes_runtime() function - basic test
--- magic quotes runtime set in INI file: 0--
-
--- Set magic quotes runtime to 1: --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-
--- magic quotes runtime after set: 1 --
+-- magic quotes runtime set in INI file: --
-- Set magic quotes runtime to 0: --
Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
+bool(false)
--- magic quotes runtime after set: 0 --
+-- magic quotes runtime after set: --
-- Set magic quotes runtime to 1: --
Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
--- magic quotes runtime after set: 1 --
-===DONE=== \ No newline at end of file
+Fatal error: set_magic_quotes_runtime(): magic_quotes_runtime is not supported anymore in Unknown on line 0
+
+
diff --git a/ext/standard/tests/general_functions/set_magic_quotes_runtime_variation1.phpt b/ext/standard/tests/general_functions/set_magic_quotes_runtime_variation1.phpt
deleted file mode 100644
index 843dbe22f3..0000000000
--- a/ext/standard/tests/general_functions/set_magic_quotes_runtime_variation1.phpt
+++ /dev/null
@@ -1,204 +0,0 @@
---TEST--
-Test set_magic_quotes_runtime() function - usage variation
---INI--
-magic_quotes_runtime = 0
---FILE--
-<?php
-/* Prototype: bool set_magic_quotes_runtime ( int $new_setting )
- * Description: Sets the current active configuration setting of magic_quotes_runtime
-*/
-
-echo "Simple testcase for set_magic_quotes_runtime() function\n";
-
-$g = get_magic_quotes_runtime();
-echo "magic quotes runtime set in INI file: ".$g."\n";
-
-// Prevent notices about undefines variables
-error_reporting(E_ALL & ~E_NOTICE);
-
-$unset_var = 10;
-unset ($unset_var);
-
-class fooClass {
- function __toString() {
- return "true";
- }
-}
-
-$fp = fopen(__FILE__, "r");
-
-$values = array(
-
- // int data
-/*1*/ 0,
- 1,
- 12345,
- -2345,
-
- // float data
-/*5*/ 0.0,
- 10.5,
- -10.5,
- 10.1234567e10,
- 10.7654321E-10,
- .5,
-
- // null data
-/*11*/ NULL,
- null,
-
- // boolean data
-/*13*/ true,
- false,
- TRUE,
- FALSE,
-
- // empty data
-/*17*/ "",
- '',
-
- // object data
-/*19*/ new fooClass(),
-
- // resource
-/*20*/ $fp,
-
- // undefined data
-/*21*/ $undefined_var,
-
- // unset data
-/*22*/ $unset_var
-);
-
-// loop through each element of the array for data
-
-$iterator = 1;
-foreach($values as $value) {
- echo "-- Iterator $iterator --\n";
- var_dump( set_magic_quotes_runtime($value) );
- echo "New value of magic_quotes_runtime after last set is " . get_magic_quotes_runtime(). "\n";
- $iterator++;
-};
-
-fclose($fp);
-
-?>
-===DONE===
---EXPECTF--
-Simple testcase for set_magic_quotes_runtime() function
-magic quotes runtime set in INI file: 0
--- Iterator 1 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 2 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 3 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 4 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 5 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 6 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 7 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 8 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 9 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 10 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 11 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 12 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 13 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 14 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 15 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 1
--- Iterator 16 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 17 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 18 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 19 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-
-Warning: set_magic_quotes_runtime() expects parameter 1 to be boolean, object given in %s on line %d
-NULL
-New value of magic_quotes_runtime after last set is 0
--- Iterator 20 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-
-Warning: set_magic_quotes_runtime() expects parameter 1 to be boolean, resource given in %s on line %d
-NULL
-New value of magic_quotes_runtime after last set is 0
--- Iterator 21 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
--- Iterator 22 --
-
-Deprecated: Function set_magic_quotes_runtime() is deprecated in %s on line %d
-bool(true)
-New value of magic_quotes_runtime after last set is 0
-===DONE===
diff --git a/ext/standard/tests/general_functions/strval.phpt b/ext/standard/tests/general_functions/strval.phpt
index 3506785781..b92be41ef4 100644
--- a/ext/standard/tests/general_functions/strval.phpt
+++ b/ext/standard/tests/general_functions/strval.phpt
@@ -283,12 +283,20 @@ string(14) "Resource id #5"
-- Iteration 3 --
string(14) "Resource id #6"
-- Iteration 4 --
+
+Notice: Array to string conversion in %sstrval.php on line %d
string(5) "Array"
-- Iteration 5 --
+
+Notice: Array to string conversion in %sstrval.php on line %d
string(5) "Array"
-- Iteration 6 --
+
+Notice: Array to string conversion in %sstrval.php on line %d
string(5) "Array"
-- Iteration 7 --
+
+Notice: Array to string conversion in %sstrval.php on line %d
string(5) "Array"
-- Iteration 8 --
string(0) ""
diff --git a/ext/standard/tests/general_functions/sys_getloadavg.phpt b/ext/standard/tests/general_functions/sys_getloadavg.phpt
index cb3a798dbd..a788e3206b 100644
--- a/ext/standard/tests/general_functions/sys_getloadavg.phpt
+++ b/ext/standard/tests/general_functions/sys_getloadavg.phpt
@@ -12,15 +12,10 @@ var_dump(sys_getloadavg());
echo "Done\n";
?>
---EXPECTF--
-array(3) {
- [0]=>
- float(%f)
- [1]=>
- float(%f)
- [2]=>
- float(%f)
-}
+--EXPECTF--
+
+Warning: sys_getloadavg() expects exactly 0 parameters, %d given in %s
+NULL
array(3) {
[0]=>
float(%f)
diff --git a/ext/standard/tests/general_functions/var_export_error2.phpt b/ext/standard/tests/general_functions/var_export_error2.phpt
index 2b306696a6..a6403e610d 100644
--- a/ext/standard/tests/general_functions/var_export_error2.phpt
+++ b/ext/standard/tests/general_functions/var_export_error2.phpt
@@ -15,4 +15,5 @@ var_export($obj, true);
===DONE===
--EXPECTF--
-Fatal error: Nesting level too deep - recursive dependency? in %s on line 9 \ No newline at end of file
+Warning: var_export does not handle circular references in %s on line 9
+===DONE===
diff --git a/ext/standard/tests/general_functions/var_export_error3.phpt b/ext/standard/tests/general_functions/var_export_error3.phpt
index 03ed496aca..c862691e91 100644
--- a/ext/standard/tests/general_functions/var_export_error3.phpt
+++ b/ext/standard/tests/general_functions/var_export_error3.phpt
@@ -15,4 +15,5 @@ var_export($a, true);
===DONE===
--EXPECTF--
-Fatal error: Nesting level too deep - recursive dependency? in %s on line 9 \ No newline at end of file
+Warning: var_export does not handle circular references in %s on line 9
+===DONE===
diff --git a/ext/standard/tests/image/getimagesizefromstring1.phpt b/ext/standard/tests/image/getimagesizefromstring1.phpt
new file mode 100644
index 0000000000..df75be518b
--- /dev/null
+++ b/ext/standard/tests/image/getimagesizefromstring1.phpt
@@ -0,0 +1,49 @@
+--TEST--
+Compare getimagesize and getimagesizefromstring
+--FILE--
+<?PHP
+$img = __DIR__ . '/test.gif';
+
+$i1 = getimagesize($img);
+
+$data = file_get_contents($img);
+
+$i2 = getimagesizefromstring($data);
+
+var_dump($i1);
+var_dump($i2);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(120)
+ [1]=>
+ int(67)
+ [2]=>
+ int(1)
+ [3]=>
+ string(23) "width="120" height="67""
+ ["bits"]=>
+ int(7)
+ ["channels"]=>
+ int(3)
+ ["mime"]=>
+ string(9) "image/gif"
+}
+array(7) {
+ [0]=>
+ int(120)
+ [1]=>
+ int(67)
+ [2]=>
+ int(1)
+ [3]=>
+ string(23) "width="120" height="67""
+ ["bits"]=>
+ int(7)
+ ["channels"]=>
+ int(3)
+ ["mime"]=>
+ string(9) "image/gif"
+}
+
diff --git a/ext/standard/tests/image/test.gif b/ext/standard/tests/image/test.gif
new file mode 100644
index 0000000000..f352c7308f
--- /dev/null
+++ b/ext/standard/tests/image/test.gif
Binary files differ
diff --git a/ext/standard/tests/mail/mail_basic2.phpt b/ext/standard/tests/mail/mail_basic2.phpt
index 2ac4d20b1f..8967d18c4f 100644
--- a/ext/standard/tests/mail/mail_basic2.phpt
+++ b/ext/standard/tests/mail/mail_basic2.phpt
@@ -6,7 +6,7 @@ if(substr(PHP_OS, 0, 3) == "WIN")
die("skip Won't run on Windows");
?>
--INI--
-sendmail_path="sed > /tmp/php_test_mailBasic2.out"
+sendmail_path="cat > /tmp/php_test_mailBasic2.out"
mail.add_x_header = Off
--FILE--
<?php
@@ -24,7 +24,7 @@ $to = 'user@company.com';
$subject = 'Test Subject';
$message = 'A Message';
$additional_headers = 'KHeaders';
-$additional_parameters = "-e '5 a--- Extras'";
+$additional_parameters = "-n";
$outFile = "/tmp/php_test_mailBasic2.out";
@unlink($outFile);
@@ -36,14 +36,13 @@ echo file_get_contents($outFile);
unlink($outFile);
?>
===DONE===
---EXPECT--
+--EXPECTF--
*** Testing mail() : basic functionality ***
-- extra parameters --
bool(true)
-To: user@company.com
-Subject: Test Subject
-KHeaders
-
-A Message
---- Extras
+%w1%wTo: user@company.com
+%w2%wSubject: Test Subject
+%w3%wKHeaders
+%w4%w
+%w5%wA Message
===DONE===
diff --git a/ext/standard/tests/mail/mail_variation2.phpt b/ext/standard/tests/mail/mail_variation2.phpt
index d6eafd2e52..c16c2706a7 100644
--- a/ext/standard/tests/mail/mail_variation2.phpt
+++ b/ext/standard/tests/mail/mail_variation2.phpt
@@ -1,8 +1,8 @@
--TEST--
Test mail() function : variation force extra parameters
--INI--
-sendmail_path="sed > /tmp/php_test_mailVariation2.out"
-mail.force_extra_parameters="-e4a---forced-params"
+sendmail_path="cat > /tmp/php_test_mailVariation2.out"
+mail.force_extra_parameters="-n"
mail.add_x_header = Off
--SKIPIF--
<?php
@@ -33,12 +33,11 @@ unlink($outFile);
?>
===DONE===
---EXPECT--
+--EXPECTF--
*** Testing mail() : basic functionality ***
bool(true)
-To: user@company.com
-Subject: Test Subject
-
-A Message
----forced-params
+%w1%wTo: user@company.com
+%w2%wSubject: Test Subject
+%w3%w
+%w4%wA Message
===DONE===
diff --git a/ext/standard/tests/math/bug45712.phpt b/ext/standard/tests/math/bug45712.phpt
index 3ebc94c92e..e10d0e7ec3 100644
--- a/ext/standard/tests/math/bug45712.phpt
+++ b/ext/standard/tests/math/bug45712.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #45712 (NaN/INF comparison)
+--XFAIL--
+Bug 45712 not fixed yet.
--FILE--
<?php
diff --git a/ext/standard/tests/math/bug62112.phpt b/ext/standard/tests/math/bug62112.phpt
new file mode 100644
index 0000000000..01de35a9c5
--- /dev/null
+++ b/ext/standard/tests/math/bug62112.phpt
Binary files differ
diff --git a/ext/standard/tests/math/number_format_multichar.phpt b/ext/standard/tests/math/number_format_multichar.phpt
new file mode 100644
index 0000000000..ae36d12c73
--- /dev/null
+++ b/ext/standard/tests/math/number_format_multichar.phpt
@@ -0,0 +1,77 @@
+--TEST--
+Test number_format() - multiple character separator support
+--FILE--
+<?php
+$values = array(1234.5678,
+ -1234.5678,
+ 1234.6578e4,
+ -1234.56789e4,
+ 0x1234CDEF,
+ 02777777777,
+ "123456789",
+ "123.456789",
+ "12.3456789e1",
+ null,
+ true,
+ false);
+
+echo " number_format tests.....multiple character decimal point\n";
+for ($i = 0; $i < count($values); $i++) {
+ $res = number_format($values[$i], 2, '&#183;', ' ');
+ var_dump($res);
+}
+
+echo "\n number_format tests.....multiple character thousand separator\n";
+for ($i = 0; $i < count($values); $i++) {
+ $res = number_format($values[$i], 2, '.' , '&thinsp;');
+ var_dump($res);
+}
+
+echo "\n number_format tests.....multiple character decimal and thousep\n";
+for ($i = 0; $i < count($values); $i++) {
+ $res = number_format($values[$i], 2, '&#183;' , '&thinsp;');
+ var_dump($res);
+}
+?>
+--EXPECTF--
+ number_format tests.....multiple character decimal point
+string(13) "1 234&#183;57"
+string(14) "-1 234&#183;57"
+string(18) "12 346 578&#183;00"
+string(19) "-12 345 678&#183;90"
+string(19) "305 450 479&#183;00"
+string(19) "402 653 183&#183;00"
+string(19) "123 456 789&#183;00"
+string(11) "123&#183;46"
+string(11) "123&#183;46"
+string(9) "0&#183;00"
+string(9) "1&#183;00"
+string(9) "0&#183;00"
+
+ number_format tests.....multiple character thousand separator
+string(15) "1&thinsp;234.57"
+string(16) "-1&thinsp;234.57"
+string(27) "12&thinsp;346&thinsp;578.00"
+string(28) "-12&thinsp;345&thinsp;678.90"
+string(28) "305&thinsp;450&thinsp;479.00"
+string(28) "402&thinsp;653&thinsp;183.00"
+string(28) "123&thinsp;456&thinsp;789.00"
+string(6) "123.46"
+string(6) "123.46"
+string(4) "0.00"
+string(4) "1.00"
+string(4) "0.00"
+
+ number_format tests.....multiple character decimal and thousep
+string(20) "1&thinsp;234&#183;57"
+string(21) "-1&thinsp;234&#183;57"
+string(32) "12&thinsp;346&thinsp;578&#183;00"
+string(33) "-12&thinsp;345&thinsp;678&#183;90"
+string(33) "305&thinsp;450&thinsp;479&#183;00"
+string(33) "402&thinsp;653&thinsp;183&#183;00"
+string(33) "123&thinsp;456&thinsp;789&#183;00"
+string(11) "123&#183;46"
+string(11) "123&#183;46"
+string(9) "0&#183;00"
+string(9) "1&#183;00"
+string(9) "0&#183;00"
diff --git a/ext/standard/tests/misc/syslog_vars_variation1.phpt b/ext/standard/tests/misc/syslog_vars_variation1.phpt
deleted file mode 100644
index 0237830dfc..0000000000
--- a/ext/standard/tests/misc/syslog_vars_variation1.phpt
+++ /dev/null
@@ -1,11 +0,0 @@
---TEST--
-define_syslog_variables() variation 1
---INI--
-define_syslog_variables=On
---FILE--
-<?php
-var_dump(isset($LOG_ERR));
-?>
---EXPECTF--
-Deprecated: Directive 'define_syslog_variables' is deprecated in PHP 5.3 and greater in Unknown on line 0
-bool(true)
diff --git a/ext/standard/tests/misc/syslog_vars_variation2.phpt b/ext/standard/tests/misc/syslog_vars_variation2.phpt
deleted file mode 100644
index bdd445b3b3..0000000000
--- a/ext/standard/tests/misc/syslog_vars_variation2.phpt
+++ /dev/null
@@ -1,52 +0,0 @@
---TEST--
-define_syslog_variables() variation 2
---FILE--
-<?php
-define_syslog_variables();
-
-$standard_types = Array(
- 'LOG_EMERG',
- 'LOG_ALERT',
- 'LOG_CRIT',
- 'LOG_ERR',
- 'LOG_WARNING',
- 'LOG_NOTICE',
- 'LOG_INFO',
- 'LOG_DEBUG',
- 'LOG_KERN',
- 'LOG_USER',
- 'LOG_MAIL',
- 'LOG_DAEMON',
- 'LOG_AUTH',
- 'LOG_LPR',
- 'LOG_PID',
- 'LOG_CONS',
- 'LOG_ODELAY',
- 'LOG_NDELAY'
- );
-
-foreach($standard_types as $logtype)
-{
- var_dump(isset(${$logtype}));
-}
-?>
---EXPECTF--
-Deprecated: Function define_syslog_variables() is deprecated in %s on line %d
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
-bool(true)
diff --git a/ext/standard/tests/network/define_syslog_variables_basic-win32.phpt b/ext/standard/tests/network/define_syslog_variables_basic-win32.phpt
deleted file mode 100644
index 395e3afaba..0000000000
--- a/ext/standard/tests/network/define_syslog_variables_basic-win32.phpt
+++ /dev/null
@@ -1,107 +0,0 @@
---TEST--
-Test define_syslog_variables() function : basic functionality
---SKIPIF--
-<?php
-if(substr(PHP_OS, 0, 3) != "WIN")
- die("skip Only run on Windows");
-?>
---FILE--
-<?php
-/* Prototype : void define_syslog_variables(void)
- * Description: Initializes all syslog-related variables
- * Source code: ext/standard/syslog.c
- * Alias to functions:
- */
-
-echo "*** Testing define_syslog_variables() : basic functionality ***\n";
-
-$log_constants = array(
- LOG_EMERG,
- LOG_ALERT,
- LOG_CRIT,
- LOG_ERR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_INFO,
- LOG_DEBUG,
- LOG_KERN,
- LOG_USER,
- LOG_MAIL,
- LOG_DAEMON,
- LOG_AUTH,
- LOG_SYSLOG,
- LOG_LPR,
- LOG_NEWS,
- LOG_UUCP,
- LOG_CRON,
- LOG_AUTHPRIV,
- LOG_PID,
- LOG_CONS,
- LOG_ODELAY,
- LOG_NDELAY,
- LOG_NOWAIT,
- LOG_PERROR,
-);
-
-
-$log_variables = array(
- "LOG_EMERG",
- "LOG_ALERT",
- "LOG_CRIT",
- "LOG_ERR",
- "LOG_WARNING",
- "LOG_NOTICE",
- "LOG_INFO",
- "LOG_DEBUG",
- "LOG_KERN",
- "LOG_USER",
- "LOG_MAIL",
- "LOG_DAEMON",
- "LOG_AUTH",
- "LOG_SYSLOG",
- "LOG_LPR",
- "LOG_NEWS",
- "LOG_UUCP",
- "LOG_CRON",
- "LOG_AUTHPRIV",
- "LOG_PID",
- "LOG_CONS",
- "LOG_ODELAY",
- "LOG_NDELAY",
- "LOG_NOWAIT",
- "LOG_PERROR",
-);
-
-error_reporting(E_ALL);
-$failed = false;
-
-// show variables not defined
-foreach($log_variables as $log_var) {
- if (isset($$log_var)) {
- $failed = true;
- echo "FAILED: variable defined\n";
- }
-}
-
-var_dump( define_syslog_variables() );
-
-// show variables defined
-for ($t = 0; $t < count($log_variables); $t++) {
- if (isset($$log_variables[$t]) === false || $$log_variables[$t] != $log_constants[$t]) {
- $failed = true;
- echo "FAILED: $log_variables[$t] doesn't contain the correct value\n";
- }
-}
-
-if ($failed == false) {
- echo "PASSED\n";
-}
-?>
-===DONE===
---EXPECTF--
-*** Testing define_syslog_variables() : basic functionality ***
-
-Deprecated: Function define_syslog_variables() is deprecated in %s on line %d
-NULL
-PASSED
-===DONE===
diff --git a/ext/standard/tests/network/define_syslog_variables_basic.phpt b/ext/standard/tests/network/define_syslog_variables_basic.phpt
deleted file mode 100644
index 8ccb16a9e3..0000000000
--- a/ext/standard/tests/network/define_syslog_variables_basic.phpt
+++ /dev/null
@@ -1,126 +0,0 @@
---TEST--
-Test define_syslog_variables() function : basic functionality
---SKIPIF--
-<?php
-if(substr(PHP_OS, 0, 3) == "WIN")
- die("skip don't run on Windows");
-?>
---FILE--
-<?php
-/* Prototype : void define_syslog_variables(void)
- * Description: Initializes all syslog-related variables
- * Source code: ext/standard/syslog.c
- * Alias to functions:
- */
-
-echo "*** Testing define_syslog_variables() : basic functionality ***\n";
-
-$log_constants = array(
- LOG_EMERG,
- LOG_ALERT,
- LOG_CRIT,
- LOG_ERR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_INFO,
- LOG_DEBUG,
- LOG_KERN,
- LOG_USER,
- LOG_MAIL,
- LOG_DAEMON,
- LOG_AUTH,
- LOG_SYSLOG,
- LOG_LPR,
- LOG_NEWS,
- LOG_UUCP,
- LOG_CRON,
- LOG_AUTHPRIV,
- LOG_PID,
- LOG_CONS,
- LOG_ODELAY,
- LOG_NDELAY,
- LOG_NOWAIT,
- LOG_PERROR,
-
- LOG_LOCAL0,
- LOG_LOCAL1,
- LOG_LOCAL2,
- LOG_LOCAL3,
- LOG_LOCAL4,
- LOG_LOCAL5,
- LOG_LOCAL6,
- LOG_LOCAL7
-
-);
-
-
-$log_variables = array(
- "LOG_EMERG",
- "LOG_ALERT",
- "LOG_CRIT",
- "LOG_ERR",
- "LOG_WARNING",
- "LOG_NOTICE",
- "LOG_INFO",
- "LOG_DEBUG",
- "LOG_KERN",
- "LOG_USER",
- "LOG_MAIL",
- "LOG_DAEMON",
- "LOG_AUTH",
- "LOG_SYSLOG",
- "LOG_LPR",
- "LOG_NEWS",
- "LOG_UUCP",
- "LOG_CRON",
- "LOG_AUTHPRIV",
- "LOG_PID",
- "LOG_CONS",
- "LOG_ODELAY",
- "LOG_NDELAY",
- "LOG_NOWAIT",
- "LOG_PERROR",
-
- "LOG_LOCAL0",
- "LOG_LOCAL1",
- "LOG_LOCAL2",
- "LOG_LOCAL3",
- "LOG_LOCAL4",
- "LOG_LOCAL5",
- "LOG_LOCAL6",
- "LOG_LOCAL7"
-);
-
-error_reporting(E_ALL);
-$failed = false;
-
-// show variables not defined
-foreach($log_variables as $log_var) {
- if (isset($$log_var)) {
- $failed = true;
- echo "FAILED: variable defined\n";
- }
-}
-
-var_dump( define_syslog_variables() );
-
-// show variables now defined
-for ($t = 0; $t < count($log_variables); $t++) {
- if (isset($$log_variables[$t]) === false || $$log_variables[$t] != $log_constants[$t]) {
- $failed = true;
- echo "FAILED: $log_variables[$t] doesn't contain the correct value\n";
- }
-}
-
-if ($failed == false) {
- echo "PASSED\n";
-}
-?>
-===DONE===
---EXPECTF--
-*** Testing define_syslog_variables() : basic functionality ***
-
-Deprecated: Function define_syslog_variables() is deprecated in %s on line %d
-NULL
-PASSED
-===DONE===
diff --git a/ext/standard/tests/network/define_syslog_variables_error.phpt b/ext/standard/tests/network/define_syslog_variables_error.phpt
deleted file mode 100644
index 4348895567..0000000000
--- a/ext/standard/tests/network/define_syslog_variables_error.phpt
+++ /dev/null
@@ -1,29 +0,0 @@
---TEST--
-Test define_syslog_variables() function : error conditions
---FILE--
-<?php
-/* Prototype : void define_syslog_variables(void)
- * Description: Initializes all syslog-related variables
- * Source code: ext/standard/syslog.c
- * Alias to functions:
- */
-
-echo "*** Testing define_syslog_variables() : error conditions ***\n";
-
-// One argument
-echo "\n-- Testing define_syslog_variables() function with one argument --\n";
-$extra_arg = 10;
-var_dump( define_syslog_variables($extra_arg) );
-
-?>
-===DONE===
---EXPECTF--
-*** Testing define_syslog_variables() : error conditions ***
-
--- Testing define_syslog_variables() function with one argument --
-
-Deprecated: Function define_syslog_variables() is deprecated in %s on line %d
-
-Warning: define_syslog_variables() expects exactly 0 parameters, 1 given in %s on line %d
-NULL
-===DONE===
diff --git a/ext/standard/tests/network/define_syslog_variables_variation.phpt b/ext/standard/tests/network/define_syslog_variables_variation.phpt
deleted file mode 100644
index e5842b036b..0000000000
--- a/ext/standard/tests/network/define_syslog_variables_variation.phpt
+++ /dev/null
@@ -1,92 +0,0 @@
---TEST--
-Test define_syslog_variables() function : variation
---FILE--
-<?php
-/* Prototype : void define_syslog_variables(void)
- * Description: Initializes all syslog-related variables
- * Source code: ext/standard/syslog.c
- * Alias to functions:
- */
-
-define_syslog_variables();
-
-echo "*** Testing define_syslog_variables() : variation ***\n";
-
-$log_constants = array(
- LOG_EMERG,
- LOG_ALERT,
- LOG_CRIT,
- LOG_ERR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_INFO,
- LOG_DEBUG,
- LOG_KERN,
- LOG_USER,
- LOG_MAIL,
- LOG_DAEMON,
- LOG_AUTH,
- LOG_SYSLOG,
- LOG_LPR,
- LOG_NEWS,
- LOG_UUCP,
- LOG_CRON,
- LOG_AUTHPRIV,
- LOG_PID,
- LOG_CONS,
- LOG_ODELAY,
- LOG_NDELAY,
- LOG_NOWAIT,
- LOG_PERROR,
-);
-
-
-$log_variables = array(
- "LOG_EMERG",
- "LOG_ALERT",
- "LOG_CRIT",
- "LOG_ERR",
- "LOG_WARNING",
- "LOG_NOTICE",
- "LOG_INFO",
- "LOG_DEBUG",
- "LOG_KERN",
- "LOG_USER",
- "LOG_MAIL",
- "LOG_DAEMON",
- "LOG_AUTH",
- "LOG_SYSLOG",
- "LOG_LPR",
- "LOG_NEWS",
- "LOG_UUCP",
- "LOG_CRON",
- "LOG_AUTHPRIV",
- "LOG_PID",
- "LOG_CONS",
- "LOG_ODELAY",
- "LOG_NDELAY",
- "LOG_NOWAIT",
- "LOG_PERROR",
-);
-
-error_reporting(E_ALL);
-$failed = false;
-
-// show variables defined
-for ($t = 0; $t < count($log_variables); $t++) {
- if (isset($$log_variables[$t]) === false || $$log_variables[$t] != $log_constants[$t]) {
- $failed = true;
- echo "FAILED: $log_variables[$t] doesn't contain the correct value\n";
- }
-}
-
-if ($failed == false) {
- echo "PASSED\n";
-}
-?>
-===DONE===
---EXPECTF--
-Deprecated: Function define_syslog_variables() is deprecated in %s on line %d
-*** Testing define_syslog_variables() : variation ***
-PASSED
-===DONE===
diff --git a/ext/standard/tests/network/define_syslog_variables_variation2-win32.phpt b/ext/standard/tests/network/define_syslog_variables_variation2-win32.phpt
deleted file mode 100644
index a8785fe7d6..0000000000
--- a/ext/standard/tests/network/define_syslog_variables_variation2-win32.phpt
+++ /dev/null
@@ -1,96 +0,0 @@
---TEST--
-Test define_syslog_variables() function : variation
---INI--
-define_syslog_variables = false
---SKIPIF--
-<?php
-if(substr(PHP_OS, 0, 3) != "WIN")
- die("skip Only run on Windows");
-?>
---FILE--
-<?php
-/* Prototype : void define_syslog_variables(void)
- * Description: Initializes all syslog-related variables
- * Source code: ext/standard/syslog.c
- * Alias to functions:
- */
-
-echo "*** Testing define_syslog_variables() : variation ***\n";
-
-$log_constants = array(
- LOG_EMERG,
- LOG_ALERT,
- LOG_CRIT,
- LOG_ERR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_INFO,
- LOG_DEBUG,
- LOG_KERN,
- LOG_USER,
- LOG_MAIL,
- LOG_DAEMON,
- LOG_AUTH,
- LOG_SYSLOG,
- LOG_LPR,
- LOG_NEWS,
- LOG_UUCP,
- LOG_CRON,
- LOG_AUTHPRIV,
- LOG_PID,
- LOG_CONS,
- LOG_ODELAY,
- LOG_NDELAY,
- LOG_NOWAIT,
- LOG_PERROR,
-);
-
-
-$log_variables = array(
- "LOG_EMERG",
- "LOG_ALERT",
- "LOG_CRIT",
- "LOG_ERR",
- "LOG_WARNING",
- "LOG_NOTICE",
- "LOG_INFO",
- "LOG_DEBUG",
- "LOG_KERN",
- "LOG_USER",
- "LOG_MAIL",
- "LOG_DAEMON",
- "LOG_AUTH",
- "LOG_SYSLOG",
- "LOG_LPR",
- "LOG_NEWS",
- "LOG_UUCP",
- "LOG_CRON",
- "LOG_AUTHPRIV",
- "LOG_PID",
- "LOG_CONS",
- "LOG_ODELAY",
- "LOG_NDELAY",
- "LOG_NOWAIT",
- "LOG_PERROR",
-);
-
-error_reporting(E_ALL);
-$failed = false;
-
-// show variables not defined
-foreach($log_variables as $log_var) {
- if (isset($$log_var)) {
- $failed = true;
- echo "FAILED: variable defined\n";
- }
-}
-
-if ($failed == false) {
- echo "PASSED\n";
-}
-?>
-===DONE===
---EXPECT--
-*** Testing define_syslog_variables() : variation ***
-PASSED
-===DONE===
diff --git a/ext/standard/tests/network/define_syslog_variables_variation2.phpt b/ext/standard/tests/network/define_syslog_variables_variation2.phpt
deleted file mode 100644
index da68df2897..0000000000
--- a/ext/standard/tests/network/define_syslog_variables_variation2.phpt
+++ /dev/null
@@ -1,96 +0,0 @@
---TEST--
-Test define_syslog_variables() function : variation
---SKIPIF--
-<?php
-if(substr(PHP_OS, 0, 3) == "WIN")
- die("skip don't run on Windows");
-?>
---INI--
-define_syslog_variables = false
---FILE--
-<?php
-/* Prototype : void define_syslog_variables(void)
- * Description: Initializes all syslog-related variables
- * Source code: ext/standard/syslog.c
- * Alias to functions:
- */
-
-echo "*** Testing define_syslog_variables() : variation ***\n";
-
-$log_constants = array(
- LOG_EMERG,
- LOG_ALERT,
- LOG_CRIT,
- LOG_ERR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_INFO,
- LOG_DEBUG,
- LOG_KERN,
- LOG_USER,
- LOG_MAIL,
- LOG_DAEMON,
- LOG_AUTH,
- LOG_SYSLOG,
- LOG_LPR,
- LOG_NEWS,
- LOG_UUCP,
- LOG_CRON,
- LOG_AUTHPRIV,
- LOG_PID,
- LOG_CONS,
- LOG_ODELAY,
- LOG_NDELAY,
- LOG_NOWAIT,
- LOG_PERROR,
-);
-
-
-$log_variables = array(
- "LOG_EMERG",
- "LOG_ALERT",
- "LOG_CRIT",
- "LOG_ERR",
- "LOG_WARNING",
- "LOG_NOTICE",
- "LOG_INFO",
- "LOG_DEBUG",
- "LOG_KERN",
- "LOG_USER",
- "LOG_MAIL",
- "LOG_DAEMON",
- "LOG_AUTH",
- "LOG_SYSLOG",
- "LOG_LPR",
- "LOG_NEWS",
- "LOG_UUCP",
- "LOG_CRON",
- "LOG_AUTHPRIV",
- "LOG_PID",
- "LOG_CONS",
- "LOG_ODELAY",
- "LOG_NDELAY",
- "LOG_NOWAIT",
- "LOG_PERROR",
-);
-
-error_reporting(E_ALL);
-$failed = false;
-
-// show variables not defined
-foreach($log_variables as $log_var) {
- if (isset($$log_var)) {
- $failed = true;
- echo "FAILED: variable defined\n";
- }
-}
-
-if ($failed == false) {
- echo "PASSED\n";
-}
-?>
-===DONE===
---EXPECT--
-*** Testing define_syslog_variables() : variation ***
-PASSED
-===DONE===
diff --git a/ext/standard/tests/network/gethostbyname_basic001.phpt b/ext/standard/tests/network/gethostbyname_basic001.phpt
index e917b59920..9171e226aa 100644
--- a/ext/standard/tests/network/gethostbyname_basic001.phpt
+++ b/ext/standard/tests/network/gethostbyname_basic001.phpt
@@ -5,6 +5,7 @@ gethostbyname() function - basic type return test
--SKIPIF--
<?php
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+if (getenv("SKIP_ONLINE_TESTS")) die("skip test requiring internet connection");
?>
--FILE--
<?php
diff --git a/ext/standard/tests/network/gethostbyname_basic002.phpt b/ext/standard/tests/network/gethostbyname_basic002.phpt
deleted file mode 100644
index 983faa929e..0000000000
--- a/ext/standard/tests/network/gethostbyname_basic002.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-gethostbyname() function - basic invalid parameter test
---CREDITS--
-"Sylvain R." <sracine@phpquebec.org>
---SKIPIF--
-<?php
-if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
-?>
---FILE--
-<?php
- $ip = gethostbyname("www.php.net");
- var_dump((bool) ip2long($ip));
-?>
---EXPECT--
-bool(true)
diff --git a/ext/standard/tests/network/gethostbyname_error004.phpt b/ext/standard/tests/network/gethostbyname_error004.phpt
index 7aac172920..274301a236 100644
--- a/ext/standard/tests/network/gethostbyname_error004.phpt
+++ b/ext/standard/tests/network/gethostbyname_error004.phpt
@@ -5,6 +5,7 @@ gethostbyname() function - basic return valid ip address test
--SKIPIF--
<?php
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+if (getenv("SKIP_ONLINE_TESTS")) die("skip test requiring internet connection");
?>
--FILE--
<?php
diff --git a/ext/standard/tests/network/getmxrr.phpt b/ext/standard/tests/network/getmxrr.phpt
index 29cea1d71e..c4a15c52ce 100644
--- a/ext/standard/tests/network/getmxrr.phpt
+++ b/ext/standard/tests/network/getmxrr.phpt
@@ -3,6 +3,7 @@ getmxrr() test
--SKIPIF--
<?php
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+if (getenv("SKIP_ONLINE_TESTS")) die("skip test requiring internet connection");
if (substr(PHP_OS, 0, 3) == 'WIN') {
die('skip: no Windows support');
}
diff --git a/ext/standard/tests/network/ip2long_variation1.phpt b/ext/standard/tests/network/ip2long_variation1.phpt
index ca67aa41a8..f87282ae75 100644
--- a/ext/standard/tests/network/ip2long_variation1.phpt
+++ b/ext/standard/tests/network/ip2long_variation1.phpt
@@ -201,4 +201,4 @@ bool(false)
--resource--
Error: 2 - ip2long() expects parameter 1 to be string, resource given, %s(%d)
NULL
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/standard/tests/serialize/bug36424.phpt b/ext/standard/tests/serialize/bug36424.phpt
new file mode 100644
index 0000000000..c62be01758
--- /dev/null
+++ b/ext/standard/tests/serialize/bug36424.phpt
@@ -0,0 +1,72 @@
+--TEST--
+Bug #36424 - Serializable interface breaks object references
+--FILE--
+<?php
+
+echo "-TEST\n";
+
+class a implements Serializable {
+ function serialize() {
+ return serialize(get_object_vars($this));
+ }
+ function unserialize($s) {
+ foreach (unserialize($s) as $p=>$v) {
+ $this->$p=$v;
+ }
+ }
+}
+class b extends a {}
+class c extends b {}
+
+$c = new c;
+$c->a = new a;
+$c->a->b = new b;
+$c->a->b->c = $c;
+$c->a->c = $c;
+$c->a->b->a = $c->a;
+$c->a->a = $c->a;
+
+$s = serialize($c);
+printf("%s\n", $s);
+
+$d = unserialize($s);
+
+var_dump(
+ $d === $d->a->b->c,
+ $d->a->a === $d->a,
+ $d->a->b->a === $d->a,
+ $d->a->c === $d
+);
+
+print_r($d);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+%aTEST
+C:1:"c":108:{a:1:{s:1:"a";C:1:"a":81:{a:3:{s:1:"b";C:1:"b":30:{a:2:{s:1:"c";r:1;s:1:"a";r:3;}}s:1:"c";r:1;s:1:"a";r:3;}}}}
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+c Object
+(
+ [a] => a Object
+ (
+ [b] => b Object
+ (
+ [c] => c Object
+ *RECURSION*
+ [a] => a Object
+ *RECURSION*
+ )
+
+ [c] => c Object
+ *RECURSION*
+ [a] => a Object
+ *RECURSION*
+ )
+
+)
+Done
diff --git a/ext/standard/tests/serialize/bug62836_1.phpt b/ext/standard/tests/serialize/bug62836_1.phpt
new file mode 100644
index 0000000000..7291046410
--- /dev/null
+++ b/ext/standard/tests/serialize/bug62836_1.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #62836 (Seg fault or broken object references on unserialize())
+--FILE--
+<?php
+$serialized_object='O:1:"A":4:{s:1:"b";O:1:"B":0:{}s:2:"b1";r:2;s:1:"c";O:1:"B":0:{}s:2:"c1";r:4;}';
+function __autoload($name) {
+ unserialize("i:4;");
+ eval("class $name {} ");
+}
+
+print_r(unserialize($serialized_object));
+echo "okey";
+?>
+--EXPECT--
+A Object
+(
+ [b] => B Object
+ (
+ )
+
+ [b1] => B Object
+ (
+ )
+
+ [c] => B Object
+ (
+ )
+
+ [c1] => B Object
+ (
+ )
+
+)
+okey
diff --git a/ext/standard/tests/serialize/bug62836_2.phpt b/ext/standard/tests/serialize/bug62836_2.phpt
new file mode 100644
index 0000000000..0634b1dac1
--- /dev/null
+++ b/ext/standard/tests/serialize/bug62836_2.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Bug #62836 (Seg fault or broken object references on unserialize())
+--FILE--
+<?php
+$serialized_object='O:1:"A":4:{s:1:"b";O:1:"B":0:{}s:2:"b1";r:2;s:1:"c";O:1:"B":0:{}s:2:"c1";r:4;}';
+
+ini_set('unserialize_callback_func','mycallback');
+
+function mycallback($classname) {
+ unserialize("i:4;");
+ eval ("class $classname {} ");
+}
+
+print_r(unserialize($serialized_object));
+echo "okey";
+?>
+--EXPECT--
+A Object
+(
+ [b] => B Object
+ (
+ )
+
+ [b1] => B Object
+ (
+ )
+
+ [c] => B Object
+ (
+ )
+
+ [c1] => B Object
+ (
+ )
+
+)
+okey
diff --git a/ext/standard/tests/serialize/serialization_miscTypes_001.phpt b/ext/standard/tests/serialize/serialization_miscTypes_001.phpt
index 8b974d4758..548a67345f 100644
--- a/ext/standard/tests/serialize/serialization_miscTypes_001.phpt
+++ b/ext/standard/tests/serialize/serialization_miscTypes_001.phpt
Binary files differ
diff --git a/ext/standard/tests/streams/bug40459.phpt b/ext/standard/tests/streams/bug40459.phpt
new file mode 100644
index 0000000000..8ee4363ed9
--- /dev/null
+++ b/ext/standard/tests/streams/bug40459.phpt
@@ -0,0 +1,103 @@
+--TEST--
+bug 40459 - Test whether the constructor of the user-space stream wrapper is called when stream functions are called
+--FILE--
+<?php
+// Test whether the constructor of the user-space stream wrapper is called when stream functions are called
+class testwrapper {
+ private $constructorCalled = false;
+ function __construct() {
+ $this->constructorCalled = true;
+ }
+
+ function stream_open($path, $mode, $options, &$opened_path)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return true;
+ }
+
+ function url_stat($url, $flags)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return array();
+ }
+
+ function unlink($url)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function rename($from, $to)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function mkdir($dir, $mode, $options)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function rmdir($dir, $options)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ }
+
+ function dir_opendir($url, $options)
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return TRUE;
+ }
+ function stream_metadata()
+ {
+ echo $this->constructorCalled ? 'yes' : 'no';
+ return TRUE;
+ }
+}
+
+stream_wrapper_register('test', 'testwrapper', STREAM_IS_URL);
+
+echo 'stream_open: ';
+fopen('test://test', 'r');
+echo "\n";
+
+echo 'url_stat: ';
+stat('test://test');
+echo "\n";
+
+echo 'dir_opendir: ';
+opendir('test://test');
+echo "\n";
+
+echo 'rmdir: ';
+rmdir('test://test');
+echo "\n";
+
+echo 'mkdir: ';
+mkdir('test://test');
+echo "\n";
+
+echo 'rename: ';
+rename('test://test', 'test://test2');
+echo "\n";
+
+echo 'unlink: ';
+unlink('test://test');
+echo "\n";
+
+echo 'touch: ';
+touch('test://test', time());
+echo "\n";
+
+
+
+?>
+==DONE==
+--EXPECT--
+stream_open: yes
+url_stat: yes
+dir_opendir: yes
+rmdir: yes
+mkdir: yes
+rename: yes
+unlink: yes
+touch: yes
+==DONE==
diff --git a/ext/standard/tests/streams/bug49936.phpt b/ext/standard/tests/streams/bug49936.phpt
index d77e161c5f..d98db1d799 100644
--- a/ext/standard/tests/streams/bug49936.phpt
+++ b/ext/standard/tests/streams/bug49936.phpt
@@ -10,17 +10,12 @@ if( substr(PHP_OS, 0, 3) == "WIN" )
$dir = 'ftp://your:self@localhost/';
-var_dump(opendir($dir));
-var_dump(opendir($dir));
+var_dump(@opendir($dir));
+var_dump(@opendir($dir));
?>
+===DONE===
--EXPECTF--
-Warning: opendir(): connect() failed: Connection refused in %s on line %d
-
-Warning: opendir(ftp://...@localhost/): failed to open dir: operation failed in %s on line %d
bool(false)
-
-Warning: opendir(): connect() failed: Connection refused in %s on line %d
-
-Warning: opendir(ftp://...@localhost/): failed to open dir: operation failed in %s on line %d
bool(false)
+===DONE===
diff --git a/ext/standard/tests/streams/bug53427.phpt b/ext/standard/tests/streams/bug53427.phpt
new file mode 100644
index 0000000000..9e2e037959
--- /dev/null
+++ b/ext/standard/tests/streams/bug53427.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #53427 (stream_select does not preserve keys)
+--FILE--
+<?php
+$read[1] = fopen(__FILE__, "r");
+$read["myindex"] = reset($read);
+$write = NULL;
+$except = NULL;
+
+var_dump($read);
+
+stream_select($read, $write, $except, 0);
+
+var_dump($read);
+--EXPECTF--
+array(2) {
+ [1]=>
+ resource(%d) of type (stream)
+ ["myindex"]=>
+ resource(%d) of type (stream)
+}
+array(2) {
+ [1]=>
+ resource(%d) of type (stream)
+ ["myindex"]=>
+ resource(%d) of type (stream)
+}
diff --git a/ext/standard/tests/streams/bug54623.phpt b/ext/standard/tests/streams/bug54623.phpt
index cd83854f43..43bcb09a42 100644
--- a/ext/standard/tests/streams/bug54623.phpt
+++ b/ext/standard/tests/streams/bug54623.phpt
@@ -4,10 +4,10 @@ Bug #54623: Segfault when when writing to a persistent socket after closing a co
<?php
$sock = pfsockopen('udp://127.0.0.1', '63844');
var_dump((int)$sock);
-fwrite($sock, "1");
+@fwrite($sock, "1");
$sock2 = pfsockopen('udp://127.0.0.1', '63844');
var_dump((int)$sock2);
-fwrite($sock2, "2");
+@fwrite($sock2, "2");
fclose($sock2);
fwrite($sock, "3");
--EXPECTF--
diff --git a/ext/standard/tests/streams/stream_set_chunk_size.phpt b/ext/standard/tests/streams/stream_set_chunk_size.phpt
new file mode 100644
index 0000000000..193bc1ac9b
--- /dev/null
+++ b/ext/standard/tests/streams/stream_set_chunk_size.phpt
@@ -0,0 +1,93 @@
+--TEST--
+stream_set_chunk_size basic tests
+--FILE--
+<?php
+class test_wrapper {
+ function stream_open($path, $mode, $openedpath) {
+ return true;
+ }
+ function stream_eof() {
+ return false;
+ }
+ function stream_read($count) {
+ echo "read with size: ", $count, "\n";
+ return str_repeat('a', $count);
+ }
+ function stream_write($data) {
+ echo "write with size: ", strlen($data), "\n";
+ return strlen($data);
+ }
+ function stream_set_option($option, $arg1, $arg2) {
+ echo "option: ", $option, ", ", $arg1, ", ", $arg2, "\n";
+ return false;
+ }
+}
+
+var_dump(stream_wrapper_register('test', 'test_wrapper'));
+
+$f = fopen("test://foo","r");
+
+/* when the chunk size is 1, the read buffer is skipped, but the
+ * the writes are made in chunks of size 1 (business as usual)
+ * This should probably be revisited */
+echo "should return previous chunk size (8192)\n";
+var_dump(stream_set_chunk_size($f, 1));
+echo "should be read without buffer (\$count == 10000)\n";
+var_dump(strlen(fread($f, 10000)));
+echo "should elicit 3 writes of size 1 and return 3\n";
+var_dump(fwrite($f, str_repeat('b', 3)));
+
+echo "should return previous chunk size (1)\n";
+var_dump(stream_set_chunk_size($f, 100));
+echo "should elicit one read of size 100 (chunk size)\n";
+var_dump(strlen(fread($f, 250)));
+echo "should elicit one read of size 100 (chunk size)\n";
+var_dump(strlen(fread($f, 50)));
+echo "should elicit no read because there is sufficient cached data\n";
+var_dump(strlen(fread($f, 50)));
+echo "should elicit 2 writes of size 100 and one of size 50\n";
+var_dump(strlen(fwrite($f, str_repeat('b', 250))));
+
+echo "\nerror conditions\n";
+var_dump(stream_set_chunk_size($f, 0));
+var_dump(stream_set_chunk_size($f, -1));
+var_dump(stream_set_chunk_size($f, array()));
+
+--EXPECTF--
+bool(true)
+should return previous chunk size (8192)
+int(8192)
+should be read without buffer ($count == 10000)
+read with size: 10000
+int(10000)
+should elicit 3 writes of size 1 and return 3
+write with size: 1
+write with size: 1
+write with size: 1
+int(3)
+should return previous chunk size (1)
+int(1)
+should elicit one read of size 100 (chunk size)
+read with size: 100
+int(100)
+should elicit one read of size 100 (chunk size)
+read with size: 100
+int(50)
+should elicit no read because there is sufficient cached data
+int(50)
+should elicit 2 writes of size 100 and one of size 50
+write with size: 100
+write with size: 100
+write with size: 50
+int(3)
+
+error conditions
+
+Warning: stream_set_chunk_size(): The chunk size must be a positive integer, given 0 in %s on line %d
+bool(false)
+
+Warning: stream_set_chunk_size(): The chunk size must be a positive integer, given -1 in %s on line %d
+bool(false)
+
+Warning: stream_set_chunk_size() expects parameter 2 to be long, array given in %s on line %d
+bool(false)
diff --git a/ext/standard/tests/strings/add-and-stripslashes.phpt b/ext/standard/tests/strings/add-and-stripslashes.phpt
index a5eab410b9..6f01176d4e 100644
--- a/ext/standard/tests/strings/add-and-stripslashes.phpt
+++ b/ext/standard/tests/strings/add-and-stripslashes.phpt
@@ -1,5 +1,5 @@
--TEST--
-addslashes() and stripslashes() functions, normal and sybase-style
+addslashes() and stripslashes() functions
--FILE--
<?php
@@ -9,15 +9,6 @@ for($i=0; $i<512; $i++) {
}
echo "Normal: ";
-ini_set('magic_quotes_sybase', 0);
-if($input === stripslashes(addslashes($input))) {
- echo "OK\n";
-} else {
- echo "FAILED\n";
-}
-
-echo "Sybase: ";
-ini_set('magic_quotes_sybase', 1);
if($input === stripslashes(addslashes($input))) {
echo "OK\n";
} else {
@@ -27,4 +18,3 @@ if($input === stripslashes(addslashes($input))) {
?>
--EXPECT--
Normal: OK
-Sybase: OK
diff --git a/ext/standard/tests/strings/addslashes_variation3.phpt b/ext/standard/tests/strings/addslashes_variation3.phpt
deleted file mode 100644
index 8f46ebe9a4..0000000000
--- a/ext/standard/tests/strings/addslashes_variation3.phpt
+++ /dev/null
@@ -1,196 +0,0 @@
---TEST--
-Test addslashes() function : usage variations - with magic_quotes_sybase directive ON
---FILE--
-<?php
-/* Prototype : string addslashes ( string $str )
- * Description: Returns a string with backslashes before characters that need to be quoted in database queries etc.
- * Source code: ext/standard/string.c
-*/
-
-/*
- * Test addslashes() with PHP directive magic_quotes_sybase set ON
-*/
-
-echo "*** Testing addslashes() : with php directive magic_quotes_sybase set ON ***\n";
-
-// setting ON the php directive magic_quotes_sybase
-ini_set("magic_quotes_sybase", "1");
-
-// initialising a heredoc string
-$heredoc_string = <<<EOT
-This is line 1 of 'heredoc' string
-This is line 2 of "heredoc" string
-EOT;
-
-$heredoc_null_string =<<<EOT
-EOT;
-
-// initialising the string array
-$str_array = array(
- // string without any characters that can be backslashed
- 'Hello world',
-
- // string with single quotes
- "how're you doing?",
- "don't disturb u'r neighbours",
- "don't disturb u'r neighbours''",
- '',
- '\'',
- "'",
-
- // string with double quotes
- 'he said, "he will be on leave"',
- 'he said, ""he will be on leave"',
- '"""PHP"""',
- "",
- "\"",
- '"',
- "hello\"",
-
- // string with backslash characters
- 'Is your name Ram\Krishna?',
- '\\0.0.0.0',
- 'c:\php\testcase\addslashes',
- '\\',
-
- // string with nul characters
- 'hello'.chr(0).'world',
- chr(0).'hello'.chr(0),
- chr(0).chr(0).'hello',
- chr(0),
-
- // mixed strings
- "'\\0.0.0.0'",
- "'\\0.0.0.0'".chr(0),
- chr(0)."'c:\php\'",
- '"\\0.0.0.0"',
- '"c:\php\"'.chr(0)."'",
- '"hello"'."'world'".chr(0).'//',
-
- // string with hexadecimal number
- "0xABCDEF0123456789",
- "\xabcdef0123456789",
- '!@#$%&*@$%#&/;:,<>',
- "hello\x00world",
-
- // heredoc strings
- $heredoc_string,
- $heredoc_null_string
- );
-
-$count = 1;
-// looping to test for all strings in $str_array
-foreach( $str_array as $str ) {
- echo "\n-- Iteration $count --\n";
- var_dump( addslashes($str) );
- $count ++;
-}
-
-echo "Done\n";
-?>
---EXPECTF--
-*** Testing addslashes() : with php directive magic_quotes_sybase set ON ***
-
--- Iteration 1 --
-string(11) "Hello world"
-
--- Iteration 2 --
-string(18) "how''re you doing?"
-
--- Iteration 3 --
-string(30) "don''t disturb u''r neighbours"
-
--- Iteration 4 --
-string(34) "don''t disturb u''r neighbours''''"
-
--- Iteration 5 --
-string(0) ""
-
--- Iteration 6 --
-string(2) "''"
-
--- Iteration 7 --
-string(2) "''"
-
--- Iteration 8 --
-string(30) "he said, "he will be on leave""
-
--- Iteration 9 --
-string(31) "he said, ""he will be on leave""
-
--- Iteration 10 --
-string(9) """"PHP""""
-
--- Iteration 11 --
-string(0) ""
-
--- Iteration 12 --
-string(1) """
-
--- Iteration 13 --
-string(1) """
-
--- Iteration 14 --
-string(6) "hello""
-
--- Iteration 15 --
-string(25) "Is your name Ram\Krishna?"
-
--- Iteration 16 --
-string(8) "\0.0.0.0"
-
--- Iteration 17 --
-string(26) "c:\php\testcase\addslashes"
-
--- Iteration 18 --
-string(1) "\"
-
--- Iteration 19 --
-string(12) "hello\0world"
-
--- Iteration 20 --
-string(9) "\0hello\0"
-
--- Iteration 21 --
-string(9) "\0\0hello"
-
--- Iteration 22 --
-string(2) "\0"
-
--- Iteration 23 --
-string(12) "''\0.0.0.0''"
-
--- Iteration 24 --
-string(14) "''\0.0.0.0''\0"
-
--- Iteration 25 --
-string(13) "\0''c:\php\''"
-
--- Iteration 26 --
-string(10) ""\0.0.0.0""
-
--- Iteration 27 --
-string(13) ""c:\php\"\0''"
-
--- Iteration 28 --
-string(20) ""hello"''world''\0//"
-
--- Iteration 29 --
-string(18) "0xABCDEF0123456789"
-
--- Iteration 30 --
-string(15) "«cdef0123456789"
-
--- Iteration 31 --
-string(18) "!@#$%&*@$%#&/;:,<>"
-
--- Iteration 32 --
-string(12) "hello\0world"
-
--- Iteration 33 --
-string(71) "This is line 1 of ''heredoc'' string
-This is line 2 of "heredoc" string"
-
--- Iteration 34 --
-string(0) ""
-Done
diff --git a/ext/standard/tests/strings/bug22904.phpt b/ext/standard/tests/strings/bug22904.phpt
deleted file mode 100644
index 3c56e1a414..0000000000
--- a/ext/standard/tests/strings/bug22904.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-Bug #22904 (magic mode failed for cybase with '\0')
---FILE--
-not active yet
-<?php
-
-/*
-ini_set("magic_quotes_sybase","on");
-test();
-ini_set("magic_quotes_sybase","off");
-test();
-*/
-function test(){
- $buf = 'g\g"\0g'."'";
- $slashed = addslashes($buf);
- echo "$buf\n";
- echo "$slashed\n";
- echo stripslashes($slashed."\n");
-/*
-g\g"\0g'
-g\\g"\\0g''
-g\g"\0g'
-g\g"\0g'
-g\\g\"\\0g\'
-g\g"\0g'
-*/
-}
-?>
---EXPECT--
-not active yet
diff --git a/ext/standard/tests/strings/bug44703.phpt b/ext/standard/tests/strings/bug44703.phpt
index 0b019b9cb4..e20b1dd83f 100644
--- a/ext/standard/tests/strings/bug44703.phpt
+++ b/ext/standard/tests/strings/bug44703.phpt
@@ -22,25 +22,25 @@ var_dump(htmlspecialchars(b"<>", ENT_COMPAT, str_repeat('a', 100)));
?>
--EXPECTF--
-Warning: htmlspecialchars(): charset `1' not supported, assuming iso-8859-1 in %s on line %d
+Warning: htmlspecialchars(): charset `1' not supported, assuming utf-8 in %s on line %d
string(35) "&lt;a href='test'&gt;Test&lt;/a&gt;"
-Warning: htmlspecialchars(): charset `12' not supported, assuming iso-8859-1 in %s on line %d
+Warning: htmlspecialchars(): charset `12' not supported, assuming utf-8 in %s on line %d
string(35) "&lt;a href='test'&gt;Test&lt;/a&gt;"
-Warning: htmlspecialchars(): charset `125' not supported, assuming iso-8859-1 in %s on line %d
+Warning: htmlspecialchars(): charset `125' not supported, assuming utf-8 in %s on line %d
string(35) "&lt;a href='test'&gt;Test&lt;/a&gt;"
string(35) "&lt;a href='test'&gt;Test&lt;/a&gt;"
-Warning: htmlspecialchars(): charset `12526' not supported, assuming iso-8859-1 in %s on line %d
+Warning: htmlspecialchars(): charset `12526' not supported, assuming utf-8 in %s on line %d
string(35) "&lt;a href='test'&gt;Test&lt;/a&gt;"
string(8) "&lt;&gt;"
-Warning: htmlspecialchars(): charset `8666' not supported, assuming iso-8859-1 in %s on line %d
+Warning: htmlspecialchars(): charset `8666' not supported, assuming utf-8 in %s on line %d
string(8) "&lt;&gt;"
string(8) "&lt;&gt;"
string(8) "&lt;&gt;"
string(8) "&lt;&gt;"
-Warning: htmlspecialchars(): charset `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' not supported, assuming iso-8859-1 in %s on line %d
+Warning: htmlspecialchars(): charset `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' not supported, assuming utf-8 in %s on line %d
string(8) "&lt;&gt;"
diff --git a/ext/standard/tests/strings/bug49785.phpt b/ext/standard/tests/strings/bug49785.phpt
index 3c38afd8f6..78a1837280 100644
--- a/ext/standard/tests/strings/bug49785.phpt
+++ b/ext/standard/tests/strings/bug49785.phpt
@@ -6,7 +6,7 @@ function _bin2hex($val) {
return is_string($val) ? bin2hex($val): $val;
}
-// UTF-8: basic tests
+echo "UTF-8: basic tests\n";
var_dump(_bin2hex(htmlentities("\xc1\xbf", ENT_QUOTES, "UTF-8")));
var_dump(_bin2hex(htmlentities("\xc2\x80", ENT_QUOTES, "UTF-8")));
var_dump(_bin2hex(htmlentities("\xc2\x00", ENT_QUOTES, "UTF-8")));
@@ -36,13 +36,13 @@ var_dump(_bin2hex(htmlentities("\xf7\xbf\xbf\xff", ENT_QUOTES, "UTF-8")));
var_dump(_bin2hex(htmlentities("\xf8\x88\x80\x80\x80", ENT_QUOTES, "UTF-8")));
echo "--\n";
-// UTF-8: with ENT_IGNORE
+echo "UTF-8: with ENT_IGNORE\n";
var_dump(_bin2hex(htmlentities("\xc0\xa0\xc2\x80", ENT_QUOTES | ENT_IGNORE, "UTF-8")));
var_dump(_bin2hex(htmlentities("\xe0\x80\x80\xe0\xa0\x80", ENT_QUOTES | ENT_IGNORE, "UTF-8")));
var_dump(_bin2hex(htmlentities("\xf0\x80\x80\x80\xf0\x90\x80\x80", ENT_QUOTES | ENT_IGNORE, "UTF-8")));
echo "--\n";
-// UTF-8: alternative (invalid) UTF-8 sequence / surrogate pairs
+echo "UTF-8: alternative (invalid) UTF-8 sequence / surrogate pairs\n";
var_dump(_bin2hex(htmlspecialchars("\xc0\xa6", ENT_QUOTES, 'UTF-8')));
var_dump(_bin2hex(htmlspecialchars("\xe0\x80\xa6", ENT_QUOTES, 'UTF-8')));
var_dump(_bin2hex(htmlspecialchars("\xf0\x80\x80\xa6", ENT_QUOTES, 'UTF-8')));
@@ -51,7 +51,8 @@ var_dump(_bin2hex(htmlspecialchars("\xed\xa0\x80", ENT_QUOTES, 'UTF-8')));
var_dump(_bin2hex(htmlspecialchars("\xed\xbf\xbf", ENT_QUOTES, 'UTF-8')));
var_dump(_bin2hex(htmlspecialchars("\xee\x80\x80", ENT_QUOTES, 'UTF-8')));
-// Shift_JIS: non-lead byte >= 0x80
+echo "--\n";
+echo "Shift_JIS: non-lead byte >= 0x80\n";
var_dump(_bin2hex(htmlspecialchars("\x80", ENT_QUOTES, 'Shift_JIS')));
foreach (array_map('chr', range(0xa0, 0xdf)) as $c) {
var_dump(_bin2hex(htmlspecialchars($c, ENT_QUOTES, 'Shift_JIS')));
@@ -61,7 +62,7 @@ var_dump(_bin2hex(htmlspecialchars("\xfe", ENT_QUOTES, 'Shift_JIS')));
var_dump(_bin2hex(htmlspecialchars("\xff", ENT_QUOTES, 'Shift_JIS')));
echo "--\n";
-// Shift_JIS: incomplete / invalid multibyte sequences
+echo "Shift_JIS: incomplete / invalid multibyte sequences\n";
foreach (array_map('chr', array_merge(range(0x81, 0x9f), range(0xe0, 0xfc))) as $c) {
var_dump(_bin2hex(htmlspecialchars("$c", ENT_QUOTES, 'Shift_JIS')));
var_dump(_bin2hex(htmlspecialchars("$c\x3f", ENT_QUOTES, 'Shift_JIS')));
@@ -76,7 +77,7 @@ foreach (array_map('chr', array_merge(range(0x81, 0x9f), range(0xe0, 0xfc))) as
}
echo "--\n";
-// EUC-JP: non-lead byte >= 0x80
+echo "EUC-JP: non-lead byte >= 0x80\n";
foreach (array_map('chr', array_merge(range(0x80, 0x8d), range(0x90, 0x9f))) as $c) {
var_dump(_bin2hex(htmlspecialchars($c, ENT_QUOTES, 'EUC-JP')));
}
@@ -91,7 +92,7 @@ var_dump(_bin2hex(htmlspecialchars("\x8e\xa1\xa3", ENT_QUOTES, 'EUC-JP')));
var_dump(_bin2hex(htmlspecialchars("\x8f\xa1\xa3", ENT_QUOTES, 'EUC-JP')));
echo "--\n";
-// EUC-JP: incomplete / invalid multibyte sequences
+echo "EUC-JP: incomplete / invalid multibyte sequences\n";
foreach (array_map('chr', array_merge(range(0xa1, 0xfe))) as $c) {
var_dump(_bin2hex(htmlspecialchars("$c", ENT_QUOTES, 'EUC-JP')));
var_dump(_bin2hex(htmlspecialchars("$c\x26", ENT_QUOTES, 'EUC-JP')));
@@ -117,12 +118,12 @@ foreach (array_map('chr', array_merge(range(0xa1, 0xfe))) as $c) {
}
echo "--\n";
-// BIG5: non-lead byte >= 0x80
+echo "BIG5: non-lead byte >= 0x80\n";
var_dump(_bin2hex(htmlspecialchars("\x80", ENT_QUOTES, 'BIG5')));
var_dump(_bin2hex(htmlspecialchars("\xff", ENT_QUOTES, 'BIG5')));
echo "--\n";
-// BIG5: incomplete / invalid multibyte sequences
+echo "BIG5: incomplete / invalid multibyte sequences\n";
foreach (array_map('chr', range(0x81, 0xfe)) as $c) {
var_dump(_bin2hex(htmlspecialchars("$c", ENT_QUOTES, 'BIG5')));
var_dump(_bin2hex(htmlspecialchars("$c\x3f", ENT_QUOTES, 'BIG5')));
@@ -137,6 +138,7 @@ foreach (array_map('chr', range(0x81, 0xfe)) as $c) {
}
?>
--EXPECT--
+UTF-8: basic tests
string(0) ""
string(4) "c280"
string(0) ""
@@ -165,10 +167,12 @@ string(0) ""
string(0) ""
string(0) ""
--
+UTF-8: with ENT_IGNORE
string(4) "c280"
string(6) "e0a080"
string(8) "f0908080"
--
+UTF-8: alternative (invalid) UTF-8 sequence / surrogate pairs
string(0) ""
string(0) ""
string(0) ""
@@ -176,8 +180,10 @@ string(6) "ecbfbf"
string(0) ""
string(0) ""
string(6) "ee8080"
-string(2) "80"
-string(2) "a0"
+--
+Shift_JIS: non-lead byte >= 0x80
+string(0) ""
+string(0) ""
string(2) "a1"
string(2) "a2"
string(2) "a3"
@@ -241,10 +247,11 @@ string(2) "dc"
string(2) "dd"
string(2) "de"
string(2) "df"
-string(2) "fd"
-string(2) "fe"
-string(2) "ff"
+string(0) ""
+string(0) ""
+string(0) ""
--
+Shift_JIS: incomplete / invalid multibyte sequences
string(0) ""
string(0) ""
string(4) "8140"
@@ -846,6 +853,7 @@ string(0) ""
string(0) ""
string(0) ""
--
+EUC-JP: non-lead byte >= 0x80
string(2) "80"
string(2) "81"
string(2) "82"
@@ -876,7 +884,7 @@ string(2) "9c"
string(2) "9d"
string(2) "9e"
string(2) "9f"
-string(2) "ff"
+string(0) ""
string(0) ""
string(0) ""
string(4) "8ea1"
@@ -884,6 +892,7 @@ string(0) ""
string(0) ""
string(6) "8fa1a3"
--
+EUC-JP: incomplete / invalid multibyte sequences
string(0) ""
string(0) ""
string(0) ""
@@ -894,10 +903,10 @@ string(0) ""
string(4) "8ea1"
string(14) "8ea126616d703b"
string(6) "8ea180"
-string(6) "8ea1a0"
string(0) ""
string(0) ""
-string(6) "8ea1ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -915,10 +924,10 @@ string(0) ""
string(4) "8ea2"
string(14) "8ea226616d703b"
string(6) "8ea280"
-string(6) "8ea2a0"
string(0) ""
string(0) ""
-string(6) "8ea2ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -936,10 +945,10 @@ string(0) ""
string(4) "8ea3"
string(14) "8ea326616d703b"
string(6) "8ea380"
-string(6) "8ea3a0"
string(0) ""
string(0) ""
-string(6) "8ea3ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -957,10 +966,10 @@ string(0) ""
string(4) "8ea4"
string(14) "8ea426616d703b"
string(6) "8ea480"
-string(6) "8ea4a0"
string(0) ""
string(0) ""
-string(6) "8ea4ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -978,10 +987,10 @@ string(0) ""
string(4) "8ea5"
string(14) "8ea526616d703b"
string(6) "8ea580"
-string(6) "8ea5a0"
string(0) ""
string(0) ""
-string(6) "8ea5ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -999,10 +1008,10 @@ string(0) ""
string(4) "8ea6"
string(14) "8ea626616d703b"
string(6) "8ea680"
-string(6) "8ea6a0"
string(0) ""
string(0) ""
-string(6) "8ea6ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1020,10 +1029,10 @@ string(0) ""
string(4) "8ea7"
string(14) "8ea726616d703b"
string(6) "8ea780"
-string(6) "8ea7a0"
string(0) ""
string(0) ""
-string(6) "8ea7ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1041,10 +1050,10 @@ string(0) ""
string(4) "8ea8"
string(14) "8ea826616d703b"
string(6) "8ea880"
-string(6) "8ea8a0"
string(0) ""
string(0) ""
-string(6) "8ea8ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1062,10 +1071,10 @@ string(0) ""
string(4) "8ea9"
string(14) "8ea926616d703b"
string(6) "8ea980"
-string(6) "8ea9a0"
string(0) ""
string(0) ""
-string(6) "8ea9ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1083,10 +1092,10 @@ string(0) ""
string(4) "8eaa"
string(14) "8eaa26616d703b"
string(6) "8eaa80"
-string(6) "8eaaa0"
string(0) ""
string(0) ""
-string(6) "8eaaff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1104,10 +1113,10 @@ string(0) ""
string(4) "8eab"
string(14) "8eab26616d703b"
string(6) "8eab80"
-string(6) "8eaba0"
string(0) ""
string(0) ""
-string(6) "8eabff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1125,10 +1134,10 @@ string(0) ""
string(4) "8eac"
string(14) "8eac26616d703b"
string(6) "8eac80"
-string(6) "8eaca0"
string(0) ""
string(0) ""
-string(6) "8eacff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1146,10 +1155,10 @@ string(0) ""
string(4) "8ead"
string(14) "8ead26616d703b"
string(6) "8ead80"
-string(6) "8eada0"
string(0) ""
string(0) ""
-string(6) "8eadff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1167,10 +1176,10 @@ string(0) ""
string(4) "8eae"
string(14) "8eae26616d703b"
string(6) "8eae80"
-string(6) "8eaea0"
string(0) ""
string(0) ""
-string(6) "8eaeff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1188,10 +1197,10 @@ string(0) ""
string(4) "8eaf"
string(14) "8eaf26616d703b"
string(6) "8eaf80"
-string(6) "8eafa0"
string(0) ""
string(0) ""
-string(6) "8eafff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1209,10 +1218,10 @@ string(0) ""
string(4) "8eb0"
string(14) "8eb026616d703b"
string(6) "8eb080"
-string(6) "8eb0a0"
string(0) ""
string(0) ""
-string(6) "8eb0ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1230,10 +1239,10 @@ string(0) ""
string(4) "8eb1"
string(14) "8eb126616d703b"
string(6) "8eb180"
-string(6) "8eb1a0"
string(0) ""
string(0) ""
-string(6) "8eb1ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1251,10 +1260,10 @@ string(0) ""
string(4) "8eb2"
string(14) "8eb226616d703b"
string(6) "8eb280"
-string(6) "8eb2a0"
string(0) ""
string(0) ""
-string(6) "8eb2ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1272,10 +1281,10 @@ string(0) ""
string(4) "8eb3"
string(14) "8eb326616d703b"
string(6) "8eb380"
-string(6) "8eb3a0"
string(0) ""
string(0) ""
-string(6) "8eb3ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1293,10 +1302,10 @@ string(0) ""
string(4) "8eb4"
string(14) "8eb426616d703b"
string(6) "8eb480"
-string(6) "8eb4a0"
string(0) ""
string(0) ""
-string(6) "8eb4ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1314,10 +1323,10 @@ string(0) ""
string(4) "8eb5"
string(14) "8eb526616d703b"
string(6) "8eb580"
-string(6) "8eb5a0"
string(0) ""
string(0) ""
-string(6) "8eb5ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1335,10 +1344,10 @@ string(0) ""
string(4) "8eb6"
string(14) "8eb626616d703b"
string(6) "8eb680"
-string(6) "8eb6a0"
string(0) ""
string(0) ""
-string(6) "8eb6ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1356,10 +1365,10 @@ string(0) ""
string(4) "8eb7"
string(14) "8eb726616d703b"
string(6) "8eb780"
-string(6) "8eb7a0"
string(0) ""
string(0) ""
-string(6) "8eb7ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1377,10 +1386,10 @@ string(0) ""
string(4) "8eb8"
string(14) "8eb826616d703b"
string(6) "8eb880"
-string(6) "8eb8a0"
string(0) ""
string(0) ""
-string(6) "8eb8ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1398,10 +1407,10 @@ string(0) ""
string(4) "8eb9"
string(14) "8eb926616d703b"
string(6) "8eb980"
-string(6) "8eb9a0"
string(0) ""
string(0) ""
-string(6) "8eb9ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1419,10 +1428,10 @@ string(0) ""
string(4) "8eba"
string(14) "8eba26616d703b"
string(6) "8eba80"
-string(6) "8ebaa0"
string(0) ""
string(0) ""
-string(6) "8ebaff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1440,10 +1449,10 @@ string(0) ""
string(4) "8ebb"
string(14) "8ebb26616d703b"
string(6) "8ebb80"
-string(6) "8ebba0"
string(0) ""
string(0) ""
-string(6) "8ebbff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1461,10 +1470,10 @@ string(0) ""
string(4) "8ebc"
string(14) "8ebc26616d703b"
string(6) "8ebc80"
-string(6) "8ebca0"
string(0) ""
string(0) ""
-string(6) "8ebcff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1482,10 +1491,10 @@ string(0) ""
string(4) "8ebd"
string(14) "8ebd26616d703b"
string(6) "8ebd80"
-string(6) "8ebda0"
string(0) ""
string(0) ""
-string(6) "8ebdff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1503,10 +1512,10 @@ string(0) ""
string(4) "8ebe"
string(14) "8ebe26616d703b"
string(6) "8ebe80"
-string(6) "8ebea0"
string(0) ""
string(0) ""
-string(6) "8ebeff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1524,10 +1533,10 @@ string(0) ""
string(4) "8ebf"
string(14) "8ebf26616d703b"
string(6) "8ebf80"
-string(6) "8ebfa0"
string(0) ""
string(0) ""
-string(6) "8ebfff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1545,10 +1554,10 @@ string(0) ""
string(4) "8ec0"
string(14) "8ec026616d703b"
string(6) "8ec080"
-string(6) "8ec0a0"
string(0) ""
string(0) ""
-string(6) "8ec0ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1566,10 +1575,10 @@ string(0) ""
string(4) "8ec1"
string(14) "8ec126616d703b"
string(6) "8ec180"
-string(6) "8ec1a0"
string(0) ""
string(0) ""
-string(6) "8ec1ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1587,10 +1596,10 @@ string(0) ""
string(4) "8ec2"
string(14) "8ec226616d703b"
string(6) "8ec280"
-string(6) "8ec2a0"
string(0) ""
string(0) ""
-string(6) "8ec2ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1608,10 +1617,10 @@ string(0) ""
string(4) "8ec3"
string(14) "8ec326616d703b"
string(6) "8ec380"
-string(6) "8ec3a0"
string(0) ""
string(0) ""
-string(6) "8ec3ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1629,10 +1638,10 @@ string(0) ""
string(4) "8ec4"
string(14) "8ec426616d703b"
string(6) "8ec480"
-string(6) "8ec4a0"
string(0) ""
string(0) ""
-string(6) "8ec4ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1650,10 +1659,10 @@ string(0) ""
string(4) "8ec5"
string(14) "8ec526616d703b"
string(6) "8ec580"
-string(6) "8ec5a0"
string(0) ""
string(0) ""
-string(6) "8ec5ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1671,10 +1680,10 @@ string(0) ""
string(4) "8ec6"
string(14) "8ec626616d703b"
string(6) "8ec680"
-string(6) "8ec6a0"
string(0) ""
string(0) ""
-string(6) "8ec6ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1692,10 +1701,10 @@ string(0) ""
string(4) "8ec7"
string(14) "8ec726616d703b"
string(6) "8ec780"
-string(6) "8ec7a0"
string(0) ""
string(0) ""
-string(6) "8ec7ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1713,10 +1722,10 @@ string(0) ""
string(4) "8ec8"
string(14) "8ec826616d703b"
string(6) "8ec880"
-string(6) "8ec8a0"
string(0) ""
string(0) ""
-string(6) "8ec8ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1734,10 +1743,10 @@ string(0) ""
string(4) "8ec9"
string(14) "8ec926616d703b"
string(6) "8ec980"
-string(6) "8ec9a0"
string(0) ""
string(0) ""
-string(6) "8ec9ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1755,10 +1764,10 @@ string(0) ""
string(4) "8eca"
string(14) "8eca26616d703b"
string(6) "8eca80"
-string(6) "8ecaa0"
string(0) ""
string(0) ""
-string(6) "8ecaff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1776,10 +1785,10 @@ string(0) ""
string(4) "8ecb"
string(14) "8ecb26616d703b"
string(6) "8ecb80"
-string(6) "8ecba0"
string(0) ""
string(0) ""
-string(6) "8ecbff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1797,10 +1806,10 @@ string(0) ""
string(4) "8ecc"
string(14) "8ecc26616d703b"
string(6) "8ecc80"
-string(6) "8ecca0"
string(0) ""
string(0) ""
-string(6) "8eccff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1818,10 +1827,10 @@ string(0) ""
string(4) "8ecd"
string(14) "8ecd26616d703b"
string(6) "8ecd80"
-string(6) "8ecda0"
string(0) ""
string(0) ""
-string(6) "8ecdff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1839,10 +1848,10 @@ string(0) ""
string(4) "8ece"
string(14) "8ece26616d703b"
string(6) "8ece80"
-string(6) "8ecea0"
string(0) ""
string(0) ""
-string(6) "8eceff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1860,10 +1869,10 @@ string(0) ""
string(4) "8ecf"
string(14) "8ecf26616d703b"
string(6) "8ecf80"
-string(6) "8ecfa0"
string(0) ""
string(0) ""
-string(6) "8ecfff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1881,10 +1890,10 @@ string(0) ""
string(4) "8ed0"
string(14) "8ed026616d703b"
string(6) "8ed080"
-string(6) "8ed0a0"
string(0) ""
string(0) ""
-string(6) "8ed0ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1902,10 +1911,10 @@ string(0) ""
string(4) "8ed1"
string(14) "8ed126616d703b"
string(6) "8ed180"
-string(6) "8ed1a0"
string(0) ""
string(0) ""
-string(6) "8ed1ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1923,10 +1932,10 @@ string(0) ""
string(4) "8ed2"
string(14) "8ed226616d703b"
string(6) "8ed280"
-string(6) "8ed2a0"
string(0) ""
string(0) ""
-string(6) "8ed2ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1944,10 +1953,10 @@ string(0) ""
string(4) "8ed3"
string(14) "8ed326616d703b"
string(6) "8ed380"
-string(6) "8ed3a0"
string(0) ""
string(0) ""
-string(6) "8ed3ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1965,10 +1974,10 @@ string(0) ""
string(4) "8ed4"
string(14) "8ed426616d703b"
string(6) "8ed480"
-string(6) "8ed4a0"
string(0) ""
string(0) ""
-string(6) "8ed4ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -1986,10 +1995,10 @@ string(0) ""
string(4) "8ed5"
string(14) "8ed526616d703b"
string(6) "8ed580"
-string(6) "8ed5a0"
string(0) ""
string(0) ""
-string(6) "8ed5ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2007,10 +2016,10 @@ string(0) ""
string(4) "8ed6"
string(14) "8ed626616d703b"
string(6) "8ed680"
-string(6) "8ed6a0"
string(0) ""
string(0) ""
-string(6) "8ed6ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2028,10 +2037,10 @@ string(0) ""
string(4) "8ed7"
string(14) "8ed726616d703b"
string(6) "8ed780"
-string(6) "8ed7a0"
string(0) ""
string(0) ""
-string(6) "8ed7ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2049,10 +2058,10 @@ string(0) ""
string(4) "8ed8"
string(14) "8ed826616d703b"
string(6) "8ed880"
-string(6) "8ed8a0"
string(0) ""
string(0) ""
-string(6) "8ed8ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2070,10 +2079,10 @@ string(0) ""
string(4) "8ed9"
string(14) "8ed926616d703b"
string(6) "8ed980"
-string(6) "8ed9a0"
string(0) ""
string(0) ""
-string(6) "8ed9ff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2091,10 +2100,10 @@ string(0) ""
string(4) "8eda"
string(14) "8eda26616d703b"
string(6) "8eda80"
-string(6) "8edaa0"
string(0) ""
string(0) ""
-string(6) "8edaff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2112,10 +2121,10 @@ string(0) ""
string(4) "8edb"
string(14) "8edb26616d703b"
string(6) "8edb80"
-string(6) "8edba0"
string(0) ""
string(0) ""
-string(6) "8edbff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2133,10 +2142,10 @@ string(0) ""
string(4) "8edc"
string(14) "8edc26616d703b"
string(6) "8edc80"
-string(6) "8edca0"
string(0) ""
string(0) ""
-string(6) "8edcff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2154,10 +2163,10 @@ string(0) ""
string(4) "8edd"
string(14) "8edd26616d703b"
string(6) "8edd80"
-string(6) "8edda0"
string(0) ""
string(0) ""
-string(6) "8eddff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2175,10 +2184,10 @@ string(0) ""
string(4) "8ede"
string(14) "8ede26616d703b"
string(6) "8ede80"
-string(6) "8edea0"
string(0) ""
string(0) ""
-string(6) "8edeff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2196,10 +2205,10 @@ string(0) ""
string(4) "8edf"
string(14) "8edf26616d703b"
string(6) "8edf80"
-string(6) "8edfa0"
string(0) ""
string(0) ""
-string(6) "8edfff"
+string(0) ""
+string(0) ""
string(0) ""
string(0) ""
string(0) ""
@@ -2859,9 +2868,11 @@ string(6) "8ffea1"
string(6) "8ffefe"
string(0) ""
--
+BIG5: non-lead byte >= 0x80
string(2) "80"
string(2) "ff"
--
+BIG5: incomplete / invalid multibyte sequences
string(0) ""
string(0) ""
string(4) "8140"
diff --git a/ext/standard/tests/strings/bug54322.phpt b/ext/standard/tests/strings/bug54322.phpt
new file mode 100644
index 0000000000..aead172b82
--- /dev/null
+++ b/ext/standard/tests/strings/bug54322.phpt
@@ -0,0 +1,9 @@
+--TEST--
+Bug #54322: Null pointer deref in get_html_translation_table due to information loss in long-to-int conversion
+--FILE--
+<?php
+var_dump(
+get_html_translation_table(NAN, 0, "UTF-8") > 0
+);
+--EXPECT--
+bool(true)
diff --git a/ext/standard/tests/strings/bug54454.phpt b/ext/standard/tests/strings/bug54454.phpt
new file mode 100644
index 0000000000..88835c983b
--- /dev/null
+++ b/ext/standard/tests/strings/bug54454.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #54454 (substr_compare incorrectly reports equality in some cases)
+--FILE--
+<?php
+var_dump(substr_compare('/', '/asd', 0, 4));
+?>
+--EXPECT--
+int(-3)
diff --git a/ext/standard/tests/strings/bug55871.phpt b/ext/standard/tests/strings/bug55871.phpt
new file mode 100644
index 0000000000..7b743fdfc1
--- /dev/null
+++ b/ext/standard/tests/strings/bug55871.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #55871 (Interruption in substr_replace())
+--FILE--
+<?php
+class test1 {
+ public function __toString() {
+ preg_match('//', '', $GLOBALS['my_var']);
+ return '';
+ }
+}
+
+class test2 {
+ public function __toString() {
+ $GLOBALS['my_var'] += 0x08048000;
+ return '';
+ }
+}
+
+class test3 {
+ public function __toString() {
+ $GLOBALS['my_var'] .= "AAAAAAAA";
+ return '';
+ }
+}
+
+$my_var = str_repeat('A', 40);
+$out = substr_replace(array(&$my_var), array(new test1), 40, 0);
+var_dump($out);
+$my_var = str_repeat('A', 40);
+$out = substr_replace(array(&$my_var), array(new test2), 40, 0);
+var_dump($out);
+$my_var = str_repeat('A', 40);
+$out = substr_replace(array(&$my_var), array(new test3), 40, 0);
+var_dump($out);
+--EXPECTF--
+
+Warning: substr_replace(): Argument was modified while replacing in %s on line %d
+array(0) {
+}
+
+Warning: substr_replace(): Argument was modified while replacing in %s on line %d
+array(0) {
+}
+
+Warning: substr_replace(): Argument was modified while replacing in %s on line %d
+array(0) {
+}
diff --git a/ext/standard/tests/strings/bug60965.phpt b/ext/standard/tests/strings/bug60965.phpt
new file mode 100644
index 0000000000..57a3b1c947
--- /dev/null
+++ b/ext/standard/tests/strings/bug60965.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #60965: Buffer overflow on htmlspecialchars/entities with $double=false
+--FILE--
+<?php
+echo htmlspecialchars('"""""""""""""""""""""""""""""""""""""""""""""&#x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005;',
+ENT_QUOTES, 'UTF-8', false), "\n";
+echo "Done.\n";
+--EXPECT--
+&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&#x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005;
+Done.
diff --git a/ext/standard/tests/strings/bug61374.phpt b/ext/standard/tests/strings/bug61374.phpt
new file mode 100644
index 0000000000..b7fce11ee2
--- /dev/null
+++ b/ext/standard/tests/strings/bug61374.phpt
@@ -0,0 +1,7 @@
+--TEST--
+Bug #61374: html_entity_decode tries to decode code points that don't exist in ISO-8859-1
+--FILE--
+<?php
+echo html_entity_decode('&OElig;', 0, 'ISO-8859-1');
+--EXPECT--
+&OElig;
diff --git a/ext/standard/tests/strings/bug61660.phpt b/ext/standard/tests/strings/bug61660.phpt
new file mode 100644
index 0000000000..010ea47e92
--- /dev/null
+++ b/ext/standard/tests/strings/bug61660.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #61660: bin2hex(hex2bin($data)) != $data
+--FILE--
+<?php
+
+var_dump(hex2bin('123'));
+
+?>
+--EXPECTF--
+Warning: hex2bin(): Hexadecimal input string must have an even length in %s on line %d
+bool(false)
diff --git a/ext/standard/tests/strings/bug62462.phpt b/ext/standard/tests/strings/bug62462.phpt
new file mode 100644
index 0000000000..c6eb41a543
--- /dev/null
+++ b/ext/standard/tests/strings/bug62462.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Multibyte characters shouldn't be split by soft line break added by quoted_printable_encode - 4 byte character test
+--FILE--
+<?php
+echo quoted_printable_encode(str_repeat("\xc4\x85", 77));
+?>
+
+==DONE==
+--EXPECT--
+=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=
+=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=
+=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=
+=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=
+=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=
+=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=C4=85=
+=C4=85=C4=85=C4=85=C4=85=C4=85
+==DONE==
diff --git a/ext/standard/tests/strings/crypt_blowfish.phpt b/ext/standard/tests/strings/crypt_blowfish.phpt
index cce09c1518..20a6a2750a 100644
--- a/ext/standard/tests/strings/crypt_blowfish.phpt
+++ b/ext/standard/tests/strings/crypt_blowfish.phpt
@@ -15,13 +15,27 @@ $tests =array(
array('$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a', 'U*U*U'),
array('$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars after 72 are ignored'),
array('$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e', "\xa3"),
+ array('$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e', "\xff\xff\xa3"),
+ array('$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e', "\xff\xff\xa3"),
+ array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85.', "\xff\xff\xa3"),
+ array('$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq', "\xa3"),
array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq', "\xa3"),
+ array('$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi', "1\xa3345"),
+ array('$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi', "\xff\xa3345"),
+ array('$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi', "\xff\xa334\xff\xff\xff\xa3345"),
+ array('$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi', "\xff\xa334\xff\xff\xff\xa3345"),
+ array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd.', "\xff\xa334\xff\xff\xff\xa3345"),
+ array('$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e', "\xff\xa3345"),
+ array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e', "\xff\xa3345"),
+ array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab"),
+ array('$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab"),
+ array('$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab"),
array('$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS', "\xd1\x91"),
array('$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS', "\xd0\xc1\xd2\xcf\xcc\xd8"),
array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6', "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaachars after 72 are ignored as usual"),
array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy', "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"),
array('$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe', "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"),
- array('$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy', ''),
+ array('$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy', ''),
);
$i=0;
@@ -47,4 +61,18 @@ foreach($tests as $test) {
8. OK
9. OK
10. OK
-11. OK \ No newline at end of file
+11. OK
+12. OK
+13. OK
+14. OK
+15. OK
+16. OK
+17. OK
+18. OK
+19. OK
+20. OK
+21. OK
+22. OK
+23. OK
+24. OK
+25. OK
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic1.phpt b/ext/standard/tests/strings/get_html_translation_table_basic1.phpt
index 0adafa3385..87857d9cbd 100644
--- a/ext/standard/tests/strings/get_html_translation_table_basic1.phpt
+++ b/ext/standard/tests/strings/get_html_translation_table_basic1.phpt
@@ -1,545 +1,549 @@
---TEST--
-Test get_html_translation_table() function : basic functionality - with default args
---FILE--
-<?php
-/* Prototype : array get_html_translation_table ( [int $table [, int $quote_style [, string charset_hint]]] )
- * Description: Returns the internal translation table used by htmlspecialchars and htmlentities
- * Source code: ext/standard/html.c
-*/
-
-/* Test get_html_translation_table() when table is specified as HTML_ENTITIES */
-
-
-echo "*** Testing get_html_translation_table() : basic functionality ***\n";
-
-echo "-- with table = HTML_ENTITIES --\n";
-$table = HTML_ENTITIES;
-var_dump( get_html_translation_table($table, ENT_COMPAT, "UTF-8") );
-
-echo "-- with table = HTML_SPECIALCHARS --\n";
-$table = HTML_SPECIALCHARS;
-var_dump( get_html_translation_table($table, ENT_COMPAT, "UTF-8") );
-
-echo "Done\n";
-?>
---EXPECTF--
-*** Testing get_html_translation_table() : basic functionality ***
--- with table = HTML_ENTITIES --
-array(252) {
- [" "]=>
- string(6) "&nbsp;"
- ["¡"]=>
- string(7) "&iexcl;"
- ["¢"]=>
- string(6) "&cent;"
- ["£"]=>
- string(7) "&pound;"
- ["¤"]=>
- string(8) "&curren;"
- ["Â¥"]=>
- string(5) "&yen;"
- ["¦"]=>
- string(8) "&brvbar;"
- ["§"]=>
- string(6) "&sect;"
- ["¨"]=>
- string(5) "&uml;"
- ["©"]=>
- string(6) "&copy;"
- ["ª"]=>
- string(6) "&ordf;"
- ["«"]=>
- string(7) "&laquo;"
- ["¬"]=>
- string(5) "&not;"
- ["­"]=>
- string(5) "&shy;"
- ["®"]=>
- string(5) "&reg;"
- ["¯"]=>
- string(6) "&macr;"
- ["°"]=>
- string(5) "&deg;"
- ["±"]=>
- string(8) "&plusmn;"
- ["²"]=>
- string(6) "&sup2;"
- ["³"]=>
- string(6) "&sup3;"
- ["´"]=>
- string(7) "&acute;"
- ["µ"]=>
- string(7) "&micro;"
- ["¶"]=>
- string(6) "&para;"
- ["·"]=>
- string(8) "&middot;"
- ["¸"]=>
- string(7) "&cedil;"
- ["¹"]=>
- string(6) "&sup1;"
- ["º"]=>
- string(6) "&ordm;"
- ["»"]=>
- string(7) "&raquo;"
- ["¼"]=>
- string(8) "&frac14;"
- ["½"]=>
- string(8) "&frac12;"
- ["¾"]=>
- string(8) "&frac34;"
- ["¿"]=>
- string(8) "&iquest;"
- ["À"]=>
- string(8) "&Agrave;"
- ["Ã"]=>
- string(8) "&Aacute;"
- ["Â"]=>
- string(7) "&Acirc;"
- ["Ã"]=>
- string(8) "&Atilde;"
- ["Ä"]=>
- string(6) "&Auml;"
- ["Ã…"]=>
- string(7) "&Aring;"
- ["Æ"]=>
- string(7) "&AElig;"
- ["Ç"]=>
- string(8) "&Ccedil;"
- ["È"]=>
- string(8) "&Egrave;"
- ["É"]=>
- string(8) "&Eacute;"
- ["Ê"]=>
- string(7) "&Ecirc;"
- ["Ë"]=>
- string(6) "&Euml;"
- ["Ì"]=>
- string(8) "&Igrave;"
- ["Ã"]=>
- string(8) "&Iacute;"
- ["ÃŽ"]=>
- string(7) "&Icirc;"
- ["Ã"]=>
- string(6) "&Iuml;"
- ["Ã"]=>
- string(5) "&ETH;"
- ["Ñ"]=>
- string(8) "&Ntilde;"
- ["Ã’"]=>
- string(8) "&Ograve;"
- ["Ó"]=>
- string(8) "&Oacute;"
- ["Ô"]=>
- string(7) "&Ocirc;"
- ["Õ"]=>
- string(8) "&Otilde;"
- ["Ö"]=>
- string(6) "&Ouml;"
- ["×"]=>
- string(7) "&times;"
- ["Ø"]=>
- string(8) "&Oslash;"
- ["Ù"]=>
- string(8) "&Ugrave;"
- ["Ú"]=>
- string(8) "&Uacute;"
- ["Û"]=>
- string(7) "&Ucirc;"
- ["Ü"]=>
- string(6) "&Uuml;"
- ["Ã"]=>
- string(8) "&Yacute;"
- ["Þ"]=>
- string(7) "&THORN;"
- ["ß"]=>
- string(7) "&szlig;"
- ["à"]=>
- string(8) "&agrave;"
- ["á"]=>
- string(8) "&aacute;"
- ["â"]=>
- string(7) "&acirc;"
- ["ã"]=>
- string(8) "&atilde;"
- ["ä"]=>
- string(6) "&auml;"
- ["Ã¥"]=>
- string(7) "&aring;"
- ["æ"]=>
- string(7) "&aelig;"
- ["ç"]=>
- string(8) "&ccedil;"
- ["è"]=>
- string(8) "&egrave;"
- ["é"]=>
- string(8) "&eacute;"
- ["ê"]=>
- string(7) "&ecirc;"
- ["ë"]=>
- string(6) "&euml;"
- ["ì"]=>
- string(8) "&igrave;"
- ["í"]=>
- string(8) "&iacute;"
- ["î"]=>
- string(7) "&icirc;"
- ["ï"]=>
- string(6) "&iuml;"
- ["ð"]=>
- string(5) "&eth;"
- ["ñ"]=>
- string(8) "&ntilde;"
- ["ò"]=>
- string(8) "&ograve;"
- ["ó"]=>
- string(8) "&oacute;"
- ["ô"]=>
- string(7) "&ocirc;"
- ["õ"]=>
- string(8) "&otilde;"
- ["ö"]=>
- string(6) "&ouml;"
- ["÷"]=>
- string(8) "&divide;"
- ["ø"]=>
- string(8) "&oslash;"
- ["ù"]=>
- string(8) "&ugrave;"
- ["ú"]=>
- string(8) "&uacute;"
- ["û"]=>
- string(7) "&ucirc;"
- ["ü"]=>
- string(6) "&uuml;"
- ["ý"]=>
- string(8) "&yacute;"
- ["þ"]=>
- string(7) "&thorn;"
- ["ÿ"]=>
- string(6) "&yuml;"
- ["Å’"]=>
- string(7) "&OElig;"
- ["Å“"]=>
- string(7) "&oelig;"
- ["Å "]=>
- string(8) "&Scaron;"
- ["Å¡"]=>
- string(8) "&scaron;"
- ["Ÿ"]=>
- string(6) "&Yuml;"
- ["Æ’"]=>
- string(6) "&fnof;"
- ["ˆ"]=>
- string(6) "&circ;"
- ["˜"]=>
- string(7) "&tilde;"
- ["Α"]=>
- string(7) "&Alpha;"
- ["Î’"]=>
- string(6) "&Beta;"
- ["Γ"]=>
- string(7) "&Gamma;"
- ["Δ"]=>
- string(7) "&Delta;"
- ["Ε"]=>
- string(9) "&Epsilon;"
- ["Ζ"]=>
- string(6) "&Zeta;"
- ["Η"]=>
- string(5) "&Eta;"
- ["Θ"]=>
- string(7) "&Theta;"
- ["Ι"]=>
- string(6) "&Iota;"
- ["Κ"]=>
- string(7) "&Kappa;"
- ["Λ"]=>
- string(8) "&Lambda;"
- ["Μ"]=>
- string(4) "&Mu;"
- ["Î"]=>
- string(4) "&Nu;"
- ["Ξ"]=>
- string(4) "&Xi;"
- ["Ο"]=>
- string(9) "&Omicron;"
- ["Π"]=>
- string(4) "&Pi;"
- ["Ρ"]=>
- string(5) "&Rho;"
- ["Σ"]=>
- string(7) "&Sigma;"
- ["Τ"]=>
- string(5) "&Tau;"
- ["Î¥"]=>
- string(9) "&Upsilon;"
- ["Φ"]=>
- string(5) "&Phi;"
- ["Χ"]=>
- string(5) "&Chi;"
- ["Ψ"]=>
- string(5) "&Psi;"
- ["Ω"]=>
- string(7) "&Omega;"
- ["α"]=>
- string(7) "&alpha;"
- ["β"]=>
- string(6) "&beta;"
- ["γ"]=>
- string(7) "&gamma;"
- ["δ"]=>
- string(7) "&delta;"
- ["ε"]=>
- string(9) "&epsilon;"
- ["ζ"]=>
- string(6) "&zeta;"
- ["η"]=>
- string(5) "&eta;"
- ["θ"]=>
- string(7) "&theta;"
- ["ι"]=>
- string(6) "&iota;"
- ["κ"]=>
- string(7) "&kappa;"
- ["λ"]=>
- string(8) "&lambda;"
- ["μ"]=>
- string(4) "&mu;"
- ["ν"]=>
- string(4) "&nu;"
- ["ξ"]=>
- string(4) "&xi;"
- ["ο"]=>
- string(9) "&omicron;"
- ["Ï€"]=>
- string(4) "&pi;"
- ["Ï"]=>
- string(5) "&rho;"
- ["Ï‚"]=>
- string(8) "&sigmaf;"
- ["σ"]=>
- string(7) "&sigma;"
- ["Ï„"]=>
- string(5) "&tau;"
- ["Ï…"]=>
- string(9) "&upsilon;"
- ["φ"]=>
- string(5) "&phi;"
- ["χ"]=>
- string(5) "&chi;"
- ["ψ"]=>
- string(5) "&psi;"
- ["ω"]=>
- string(7) "&omega;"
- ["Ï‘"]=>
- string(10) "&thetasym;"
- ["Ï’"]=>
- string(7) "&upsih;"
- ["Ï–"]=>
- string(5) "&piv;"
- [" "]=>
- string(6) "&ensp;"
- [" "]=>
- string(6) "&emsp;"
- [" "]=>
- string(8) "&thinsp;"
- ["‌"]=>
- string(6) "&zwnj;"
- ["â€"]=>
- string(5) "&zwj;"
- ["‎"]=>
- string(5) "&lrm;"
- ["â€"]=>
- string(5) "&rlm;"
- ["–"]=>
- string(7) "&ndash;"
- ["—"]=>
- string(7) "&mdash;"
- ["‘"]=>
- string(7) "&lsquo;"
- ["’"]=>
- string(7) "&rsquo;"
- ["‚"]=>
- string(7) "&sbquo;"
- ["“"]=>
- string(7) "&ldquo;"
- ["â€"]=>
- string(7) "&rdquo;"
- ["„"]=>
- string(7) "&bdquo;"
- ["†"]=>
- string(8) "&dagger;"
- ["‡"]=>
- string(8) "&Dagger;"
- ["•"]=>
- string(6) "&bull;"
- ["…"]=>
- string(8) "&hellip;"
- ["‰"]=>
- string(8) "&permil;"
- ["′"]=>
- string(7) "&prime;"
- ["″"]=>
- string(7) "&Prime;"
- ["‹"]=>
- string(8) "&lsaquo;"
- ["›"]=>
- string(8) "&rsaquo;"
- ["‾"]=>
- string(7) "&oline;"
- ["â„"]=>
- string(7) "&frasl;"
- ["€"]=>
- string(6) "&euro;"
- ["â„‘"]=>
- string(7) "&image;"
- ["℘"]=>
- string(8) "&weierp;"
- ["ℜ"]=>
- string(6) "&real;"
- ["â„¢"]=>
- string(7) "&trade;"
- ["ℵ"]=>
- string(9) "&alefsym;"
- ["â†"]=>
- string(6) "&larr;"
- ["↑"]=>
- string(6) "&uarr;"
- ["→"]=>
- string(6) "&rarr;"
- ["↓"]=>
- string(6) "&darr;"
- ["↔"]=>
- string(6) "&harr;"
- ["↵"]=>
- string(7) "&crarr;"
- ["â‡"]=>
- string(6) "&lArr;"
- ["⇑"]=>
- string(6) "&uArr;"
- ["⇒"]=>
- string(6) "&rArr;"
- ["⇓"]=>
- string(6) "&dArr;"
- ["⇔"]=>
- string(6) "&hArr;"
- ["∀"]=>
- string(8) "&forall;"
- ["∂"]=>
- string(6) "&part;"
- ["∃"]=>
- string(7) "&exist;"
- ["∅"]=>
- string(7) "&empty;"
- ["∇"]=>
- string(7) "&nabla;"
- ["∈"]=>
- string(6) "&isin;"
- ["∉"]=>
- string(7) "&notin;"
- ["∋"]=>
- string(4) "&ni;"
- ["âˆ"]=>
- string(6) "&prod;"
- ["∑"]=>
- string(5) "&sum;"
- ["−"]=>
- string(7) "&minus;"
- ["∗"]=>
- string(8) "&lowast;"
- ["√"]=>
- string(7) "&radic;"
- ["âˆ"]=>
- string(6) "&prop;"
- ["∞"]=>
- string(7) "&infin;"
- ["∠"]=>
- string(5) "&ang;"
- ["∧"]=>
- string(5) "&and;"
- ["∨"]=>
- string(4) "&or;"
- ["∩"]=>
- string(5) "&cap;"
- ["∪"]=>
- string(5) "&cup;"
- ["∫"]=>
- string(5) "&int;"
- ["∴"]=>
- string(8) "&there4;"
- ["∼"]=>
- string(5) "&sim;"
- ["≅"]=>
- string(6) "&cong;"
- ["≈"]=>
- string(7) "&asymp;"
- ["≠"]=>
- string(4) "&ne;"
- ["≡"]=>
- string(7) "&equiv;"
- ["≤"]=>
- string(4) "&le;"
- ["≥"]=>
- string(4) "&ge;"
- ["⊂"]=>
- string(5) "&sub;"
- ["⊃"]=>
- string(5) "&sup;"
- ["⊄"]=>
- string(6) "&nsub;"
- ["⊆"]=>
- string(6) "&sube;"
- ["⊇"]=>
- string(6) "&supe;"
- ["⊕"]=>
- string(7) "&oplus;"
- ["⊗"]=>
- string(8) "&otimes;"
- ["⊥"]=>
- string(6) "&perp;"
- ["â‹…"]=>
- string(6) "&sdot;"
- ["⌈"]=>
- string(7) "&lceil;"
- ["⌉"]=>
- string(7) "&rceil;"
- ["⌊"]=>
- string(8) "&lfloor;"
- ["⌋"]=>
- string(8) "&rfloor;"
- ["〈"]=>
- string(6) "&lang;"
- ["〉"]=>
- string(6) "&rang;"
- ["â—Š"]=>
- string(5) "&loz;"
- ["â™ "]=>
- string(8) "&spades;"
- ["♣"]=>
- string(7) "&clubs;"
- ["♥"]=>
- string(8) "&hearts;"
- ["♦"]=>
- string(7) "&diams;"
- ["&"]=>
- string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
- [">"]=>
- string(4) "&gt;"
-}
--- with table = HTML_SPECIALCHARS --
-array(4) {
- ["&"]=>
- string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
- [">"]=>
- string(4) "&gt;"
-}
-Done
+--TEST--
+Test get_html_translation_table() function : basic functionality - with default args
+--FILE--
+<?php
+/* Prototype : array get_html_translation_table ( [int $table [, int $quote_style [, string charset_hint]]] )
+ * Description: Returns the internal translation table used by htmlspecialchars and htmlentities
+ * Source code: ext/standard/html.c
+*/
+
+/* Test get_html_translation_table() when table is specified as HTML_ENTITIES */
+
+
+echo "*** Testing get_html_translation_table() : basic functionality ***\n";
+
+echo "-- with table = HTML_ENTITIES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_COMPAT, "UTF-8");
+asort($tt);
+var_dump( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_COMPAT, "UTF-8");
+asort($tt);
+var_dump( $tt );
+
+echo "Done\n";
+?>
+--EXPECT--
+*** Testing get_html_translation_table() : basic functionality ***
+-- with table = HTML_ENTITIES --
+array(252) {
+ ["Æ"]=>
+ string(7) "&AElig;"
+ ["Ã"]=>
+ string(8) "&Aacute;"
+ ["Â"]=>
+ string(7) "&Acirc;"
+ ["À"]=>
+ string(8) "&Agrave;"
+ ["Α"]=>
+ string(7) "&Alpha;"
+ ["Ã…"]=>
+ string(7) "&Aring;"
+ ["Ã"]=>
+ string(8) "&Atilde;"
+ ["Ä"]=>
+ string(6) "&Auml;"
+ ["Î’"]=>
+ string(6) "&Beta;"
+ ["Ç"]=>
+ string(8) "&Ccedil;"
+ ["Χ"]=>
+ string(5) "&Chi;"
+ ["‡"]=>
+ string(8) "&Dagger;"
+ ["Δ"]=>
+ string(7) "&Delta;"
+ ["Ã"]=>
+ string(5) "&ETH;"
+ ["É"]=>
+ string(8) "&Eacute;"
+ ["Ê"]=>
+ string(7) "&Ecirc;"
+ ["È"]=>
+ string(8) "&Egrave;"
+ ["Ε"]=>
+ string(9) "&Epsilon;"
+ ["Η"]=>
+ string(5) "&Eta;"
+ ["Ë"]=>
+ string(6) "&Euml;"
+ ["Γ"]=>
+ string(7) "&Gamma;"
+ ["Ã"]=>
+ string(8) "&Iacute;"
+ ["ÃŽ"]=>
+ string(7) "&Icirc;"
+ ["Ì"]=>
+ string(8) "&Igrave;"
+ ["Ι"]=>
+ string(6) "&Iota;"
+ ["Ã"]=>
+ string(6) "&Iuml;"
+ ["Κ"]=>
+ string(7) "&Kappa;"
+ ["Λ"]=>
+ string(8) "&Lambda;"
+ ["Μ"]=>
+ string(4) "&Mu;"
+ ["Ñ"]=>
+ string(8) "&Ntilde;"
+ ["Î"]=>
+ string(4) "&Nu;"
+ ["Å’"]=>
+ string(7) "&OElig;"
+ ["Ó"]=>
+ string(8) "&Oacute;"
+ ["Ô"]=>
+ string(7) "&Ocirc;"
+ ["Ã’"]=>
+ string(8) "&Ograve;"
+ ["Ω"]=>
+ string(7) "&Omega;"
+ ["Ο"]=>
+ string(9) "&Omicron;"
+ ["Ø"]=>
+ string(8) "&Oslash;"
+ ["Õ"]=>
+ string(8) "&Otilde;"
+ ["Ö"]=>
+ string(6) "&Ouml;"
+ ["Φ"]=>
+ string(5) "&Phi;"
+ ["Π"]=>
+ string(4) "&Pi;"
+ ["″"]=>
+ string(7) "&Prime;"
+ ["Ψ"]=>
+ string(5) "&Psi;"
+ ["Ρ"]=>
+ string(5) "&Rho;"
+ ["Å "]=>
+ string(8) "&Scaron;"
+ ["Σ"]=>
+ string(7) "&Sigma;"
+ ["Þ"]=>
+ string(7) "&THORN;"
+ ["Τ"]=>
+ string(5) "&Tau;"
+ ["Θ"]=>
+ string(7) "&Theta;"
+ ["Ú"]=>
+ string(8) "&Uacute;"
+ ["Û"]=>
+ string(7) "&Ucirc;"
+ ["Ù"]=>
+ string(8) "&Ugrave;"
+ ["Î¥"]=>
+ string(9) "&Upsilon;"
+ ["Ü"]=>
+ string(6) "&Uuml;"
+ ["Ξ"]=>
+ string(4) "&Xi;"
+ ["Ã"]=>
+ string(8) "&Yacute;"
+ ["Ÿ"]=>
+ string(6) "&Yuml;"
+ ["Ζ"]=>
+ string(6) "&Zeta;"
+ ["á"]=>
+ string(8) "&aacute;"
+ ["â"]=>
+ string(7) "&acirc;"
+ ["´"]=>
+ string(7) "&acute;"
+ ["æ"]=>
+ string(7) "&aelig;"
+ ["à"]=>
+ string(8) "&agrave;"
+ ["ℵ"]=>
+ string(9) "&alefsym;"
+ ["α"]=>
+ string(7) "&alpha;"
+ ["&"]=>
+ string(5) "&amp;"
+ ["∧"]=>
+ string(5) "&and;"
+ ["∠"]=>
+ string(5) "&ang;"
+ ["Ã¥"]=>
+ string(7) "&aring;"
+ ["≈"]=>
+ string(7) "&asymp;"
+ ["ã"]=>
+ string(8) "&atilde;"
+ ["ä"]=>
+ string(6) "&auml;"
+ ["„"]=>
+ string(7) "&bdquo;"
+ ["β"]=>
+ string(6) "&beta;"
+ ["¦"]=>
+ string(8) "&brvbar;"
+ ["•"]=>
+ string(6) "&bull;"
+ ["∩"]=>
+ string(5) "&cap;"
+ ["ç"]=>
+ string(8) "&ccedil;"
+ ["¸"]=>
+ string(7) "&cedil;"
+ ["¢"]=>
+ string(6) "&cent;"
+ ["χ"]=>
+ string(5) "&chi;"
+ ["ˆ"]=>
+ string(6) "&circ;"
+ ["♣"]=>
+ string(7) "&clubs;"
+ ["≅"]=>
+ string(6) "&cong;"
+ ["©"]=>
+ string(6) "&copy;"
+ ["↵"]=>
+ string(7) "&crarr;"
+ ["∪"]=>
+ string(5) "&cup;"
+ ["¤"]=>
+ string(8) "&curren;"
+ ["⇓"]=>
+ string(6) "&dArr;"
+ ["†"]=>
+ string(8) "&dagger;"
+ ["↓"]=>
+ string(6) "&darr;"
+ ["°"]=>
+ string(5) "&deg;"
+ ["δ"]=>
+ string(7) "&delta;"
+ ["♦"]=>
+ string(7) "&diams;"
+ ["÷"]=>
+ string(8) "&divide;"
+ ["é"]=>
+ string(8) "&eacute;"
+ ["ê"]=>
+ string(7) "&ecirc;"
+ ["è"]=>
+ string(8) "&egrave;"
+ ["∅"]=>
+ string(7) "&empty;"
+ [" "]=>
+ string(6) "&emsp;"
+ [" "]=>
+ string(6) "&ensp;"
+ ["ε"]=>
+ string(9) "&epsilon;"
+ ["≡"]=>
+ string(7) "&equiv;"
+ ["η"]=>
+ string(5) "&eta;"
+ ["ð"]=>
+ string(5) "&eth;"
+ ["ë"]=>
+ string(6) "&euml;"
+ ["€"]=>
+ string(6) "&euro;"
+ ["∃"]=>
+ string(7) "&exist;"
+ ["Æ’"]=>
+ string(6) "&fnof;"
+ ["∀"]=>
+ string(8) "&forall;"
+ ["½"]=>
+ string(8) "&frac12;"
+ ["¼"]=>
+ string(8) "&frac14;"
+ ["¾"]=>
+ string(8) "&frac34;"
+ ["â„"]=>
+ string(7) "&frasl;"
+ ["γ"]=>
+ string(7) "&gamma;"
+ ["≥"]=>
+ string(4) "&ge;"
+ [">"]=>
+ string(4) "&gt;"
+ ["⇔"]=>
+ string(6) "&hArr;"
+ ["↔"]=>
+ string(6) "&harr;"
+ ["♥"]=>
+ string(8) "&hearts;"
+ ["…"]=>
+ string(8) "&hellip;"
+ ["í"]=>
+ string(8) "&iacute;"
+ ["î"]=>
+ string(7) "&icirc;"
+ ["¡"]=>
+ string(7) "&iexcl;"
+ ["ì"]=>
+ string(8) "&igrave;"
+ ["â„‘"]=>
+ string(7) "&image;"
+ ["∞"]=>
+ string(7) "&infin;"
+ ["∫"]=>
+ string(5) "&int;"
+ ["ι"]=>
+ string(6) "&iota;"
+ ["¿"]=>
+ string(8) "&iquest;"
+ ["∈"]=>
+ string(6) "&isin;"
+ ["ï"]=>
+ string(6) "&iuml;"
+ ["κ"]=>
+ string(7) "&kappa;"
+ ["â‡"]=>
+ string(6) "&lArr;"
+ ["λ"]=>
+ string(8) "&lambda;"
+ ["〈"]=>
+ string(6) "&lang;"
+ ["«"]=>
+ string(7) "&laquo;"
+ ["â†"]=>
+ string(6) "&larr;"
+ ["⌈"]=>
+ string(7) "&lceil;"
+ ["“"]=>
+ string(7) "&ldquo;"
+ ["≤"]=>
+ string(4) "&le;"
+ ["⌊"]=>
+ string(8) "&lfloor;"
+ ["∗"]=>
+ string(8) "&lowast;"
+ ["â—Š"]=>
+ string(5) "&loz;"
+ ["‎"]=>
+ string(5) "&lrm;"
+ ["‹"]=>
+ string(8) "&lsaquo;"
+ ["‘"]=>
+ string(7) "&lsquo;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["¯"]=>
+ string(6) "&macr;"
+ ["—"]=>
+ string(7) "&mdash;"
+ ["µ"]=>
+ string(7) "&micro;"
+ ["·"]=>
+ string(8) "&middot;"
+ ["−"]=>
+ string(7) "&minus;"
+ ["μ"]=>
+ string(4) "&mu;"
+ ["∇"]=>
+ string(7) "&nabla;"
+ [" "]=>
+ string(6) "&nbsp;"
+ ["–"]=>
+ string(7) "&ndash;"
+ ["≠"]=>
+ string(4) "&ne;"
+ ["∋"]=>
+ string(4) "&ni;"
+ ["¬"]=>
+ string(5) "&not;"
+ ["∉"]=>
+ string(7) "&notin;"
+ ["⊄"]=>
+ string(6) "&nsub;"
+ ["ñ"]=>
+ string(8) "&ntilde;"
+ ["ν"]=>
+ string(4) "&nu;"
+ ["ó"]=>
+ string(8) "&oacute;"
+ ["ô"]=>
+ string(7) "&ocirc;"
+ ["Å“"]=>
+ string(7) "&oelig;"
+ ["ò"]=>
+ string(8) "&ograve;"
+ ["‾"]=>
+ string(7) "&oline;"
+ ["ω"]=>
+ string(7) "&omega;"
+ ["ο"]=>
+ string(9) "&omicron;"
+ ["⊕"]=>
+ string(7) "&oplus;"
+ ["∨"]=>
+ string(4) "&or;"
+ ["ª"]=>
+ string(6) "&ordf;"
+ ["º"]=>
+ string(6) "&ordm;"
+ ["ø"]=>
+ string(8) "&oslash;"
+ ["õ"]=>
+ string(8) "&otilde;"
+ ["⊗"]=>
+ string(8) "&otimes;"
+ ["ö"]=>
+ string(6) "&ouml;"
+ ["¶"]=>
+ string(6) "&para;"
+ ["∂"]=>
+ string(6) "&part;"
+ ["‰"]=>
+ string(8) "&permil;"
+ ["⊥"]=>
+ string(6) "&perp;"
+ ["φ"]=>
+ string(5) "&phi;"
+ ["Ï€"]=>
+ string(4) "&pi;"
+ ["Ï–"]=>
+ string(5) "&piv;"
+ ["±"]=>
+ string(8) "&plusmn;"
+ ["£"]=>
+ string(7) "&pound;"
+ ["′"]=>
+ string(7) "&prime;"
+ ["âˆ"]=>
+ string(6) "&prod;"
+ ["âˆ"]=>
+ string(6) "&prop;"
+ ["ψ"]=>
+ string(5) "&psi;"
+ ["""]=>
+ string(6) "&quot;"
+ ["⇒"]=>
+ string(6) "&rArr;"
+ ["√"]=>
+ string(7) "&radic;"
+ ["〉"]=>
+ string(6) "&rang;"
+ ["»"]=>
+ string(7) "&raquo;"
+ ["→"]=>
+ string(6) "&rarr;"
+ ["⌉"]=>
+ string(7) "&rceil;"
+ ["â€"]=>
+ string(7) "&rdquo;"
+ ["ℜ"]=>
+ string(6) "&real;"
+ ["®"]=>
+ string(5) "&reg;"
+ ["⌋"]=>
+ string(8) "&rfloor;"
+ ["Ï"]=>
+ string(5) "&rho;"
+ ["â€"]=>
+ string(5) "&rlm;"
+ ["›"]=>
+ string(8) "&rsaquo;"
+ ["’"]=>
+ string(7) "&rsquo;"
+ ["‚"]=>
+ string(7) "&sbquo;"
+ ["Å¡"]=>
+ string(8) "&scaron;"
+ ["â‹…"]=>
+ string(6) "&sdot;"
+ ["§"]=>
+ string(6) "&sect;"
+ ["­"]=>
+ string(5) "&shy;"
+ ["σ"]=>
+ string(7) "&sigma;"
+ ["Ï‚"]=>
+ string(8) "&sigmaf;"
+ ["∼"]=>
+ string(5) "&sim;"
+ ["â™ "]=>
+ string(8) "&spades;"
+ ["⊂"]=>
+ string(5) "&sub;"
+ ["⊆"]=>
+ string(6) "&sube;"
+ ["∑"]=>
+ string(5) "&sum;"
+ ["¹"]=>
+ string(6) "&sup1;"
+ ["²"]=>
+ string(6) "&sup2;"
+ ["³"]=>
+ string(6) "&sup3;"
+ ["⊃"]=>
+ string(5) "&sup;"
+ ["⊇"]=>
+ string(6) "&supe;"
+ ["ß"]=>
+ string(7) "&szlig;"
+ ["Ï„"]=>
+ string(5) "&tau;"
+ ["∴"]=>
+ string(8) "&there4;"
+ ["θ"]=>
+ string(7) "&theta;"
+ ["Ï‘"]=>
+ string(10) "&thetasym;"
+ [" "]=>
+ string(8) "&thinsp;"
+ ["þ"]=>
+ string(7) "&thorn;"
+ ["˜"]=>
+ string(7) "&tilde;"
+ ["×"]=>
+ string(7) "&times;"
+ ["â„¢"]=>
+ string(7) "&trade;"
+ ["⇑"]=>
+ string(6) "&uArr;"
+ ["ú"]=>
+ string(8) "&uacute;"
+ ["↑"]=>
+ string(6) "&uarr;"
+ ["û"]=>
+ string(7) "&ucirc;"
+ ["ù"]=>
+ string(8) "&ugrave;"
+ ["¨"]=>
+ string(5) "&uml;"
+ ["Ï’"]=>
+ string(7) "&upsih;"
+ ["Ï…"]=>
+ string(9) "&upsilon;"
+ ["ü"]=>
+ string(6) "&uuml;"
+ ["℘"]=>
+ string(8) "&weierp;"
+ ["ξ"]=>
+ string(4) "&xi;"
+ ["ý"]=>
+ string(8) "&yacute;"
+ ["Â¥"]=>
+ string(5) "&yen;"
+ ["ÿ"]=>
+ string(6) "&yuml;"
+ ["ζ"]=>
+ string(6) "&zeta;"
+ ["â€"]=>
+ string(5) "&zwj;"
+ ["‌"]=>
+ string(6) "&zwnj;"
+}
+-- with table = HTML_SPECIALCHARS --
+array(4) {
+ ["&"]=>
+ string(5) "&amp;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
+}
+Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic2.phpt b/ext/standard/tests/strings/get_html_translation_table_basic2.phpt
index 8d27e15ed8..1ab2ffab25 100644
--- a/ext/standard/tests/strings/get_html_translation_table_basic2.phpt
+++ b/ext/standard/tests/strings/get_html_translation_table_basic2.phpt
@@ -20,1540 +20,1546 @@ echo "*** Testing get_html_translation_table() : basic functionality ***\n";
echo "-- with table = HTML_ENTITIES & quote_style = ENT_COMPAT --\n";
$table = HTML_ENTITIES;
$quote_style = ENT_COMPAT;
-var_dump( get_html_translation_table($table, $quote_style, "UTF-8") );
+$tt = get_html_translation_table($table, $quote_style, "UTF-8");
+asort( $tt );
+var_dump( $tt );
echo "-- with table = HTML_ENTITIES & quote_style = ENT_QUOTES --\n";
$quote_style = ENT_QUOTES;
-var_dump( get_html_translation_table($table, $quote_style, "UTF-8") );
+$tt = get_html_translation_table($table, $quote_style, "UTF-8");
+asort( $tt );
+var_dump( $tt );
echo "-- with table = HTML_ENTITIES & quote_style = ENT_NOQUOTES --\n";
$quote_style = ENT_NOQUOTES;
-var_dump( get_html_translation_table($table, $quote_style, "UTF-8") );
+$tt = get_html_translation_table($table, $quote_style, "UTF-8");
+asort( $tt );
+var_dump( $tt );
echo "Done\n";
?>
---EXPECTF--
+--EXPECT--
*** Testing get_html_translation_table() : basic functionality ***
-- with table = HTML_ENTITIES & quote_style = ENT_COMPAT --
array(252) {
- [" "]=>
- string(6) "&nbsp;"
- ["¡"]=>
- string(7) "&iexcl;"
- ["¢"]=>
- string(6) "&cent;"
- ["£"]=>
- string(7) "&pound;"
- ["¤"]=>
- string(8) "&curren;"
- ["Â¥"]=>
- string(5) "&yen;"
- ["¦"]=>
- string(8) "&brvbar;"
- ["§"]=>
- string(6) "&sect;"
- ["¨"]=>
- string(5) "&uml;"
- ["©"]=>
- string(6) "&copy;"
- ["ª"]=>
- string(6) "&ordf;"
- ["«"]=>
- string(7) "&laquo;"
- ["¬"]=>
- string(5) "&not;"
- ["­"]=>
- string(5) "&shy;"
- ["®"]=>
- string(5) "&reg;"
- ["¯"]=>
- string(6) "&macr;"
- ["°"]=>
- string(5) "&deg;"
- ["±"]=>
- string(8) "&plusmn;"
- ["²"]=>
- string(6) "&sup2;"
- ["³"]=>
- string(6) "&sup3;"
- ["´"]=>
- string(7) "&acute;"
- ["µ"]=>
- string(7) "&micro;"
- ["¶"]=>
- string(6) "&para;"
- ["·"]=>
- string(8) "&middot;"
- ["¸"]=>
- string(7) "&cedil;"
- ["¹"]=>
- string(6) "&sup1;"
- ["º"]=>
- string(6) "&ordm;"
- ["»"]=>
- string(7) "&raquo;"
- ["¼"]=>
- string(8) "&frac14;"
- ["½"]=>
- string(8) "&frac12;"
- ["¾"]=>
- string(8) "&frac34;"
- ["¿"]=>
- string(8) "&iquest;"
- ["À"]=>
- string(8) "&Agrave;"
+ ["Æ"]=>
+ string(7) "&AElig;"
["Ã"]=>
string(8) "&Aacute;"
["Â"]=>
string(7) "&Acirc;"
+ ["À"]=>
+ string(8) "&Agrave;"
+ ["Α"]=>
+ string(7) "&Alpha;"
+ ["Ã…"]=>
+ string(7) "&Aring;"
["Ã"]=>
string(8) "&Atilde;"
["Ä"]=>
string(6) "&Auml;"
- ["Ã…"]=>
- string(7) "&Aring;"
- ["Æ"]=>
- string(7) "&AElig;"
+ ["Î’"]=>
+ string(6) "&Beta;"
["Ç"]=>
string(8) "&Ccedil;"
- ["È"]=>
- string(8) "&Egrave;"
+ ["Χ"]=>
+ string(5) "&Chi;"
+ ["‡"]=>
+ string(8) "&Dagger;"
+ ["Δ"]=>
+ string(7) "&Delta;"
+ ["Ã"]=>
+ string(5) "&ETH;"
["É"]=>
string(8) "&Eacute;"
["Ê"]=>
string(7) "&Ecirc;"
+ ["È"]=>
+ string(8) "&Egrave;"
+ ["Ε"]=>
+ string(9) "&Epsilon;"
+ ["Η"]=>
+ string(5) "&Eta;"
["Ë"]=>
string(6) "&Euml;"
- ["Ì"]=>
- string(8) "&Igrave;"
+ ["Γ"]=>
+ string(7) "&Gamma;"
["Ã"]=>
string(8) "&Iacute;"
["ÃŽ"]=>
string(7) "&Icirc;"
+ ["Ì"]=>
+ string(8) "&Igrave;"
+ ["Ι"]=>
+ string(6) "&Iota;"
["Ã"]=>
string(6) "&Iuml;"
- ["Ã"]=>
- string(5) "&ETH;"
+ ["Κ"]=>
+ string(7) "&Kappa;"
+ ["Λ"]=>
+ string(8) "&Lambda;"
+ ["Μ"]=>
+ string(4) "&Mu;"
["Ñ"]=>
string(8) "&Ntilde;"
- ["Ã’"]=>
- string(8) "&Ograve;"
+ ["Î"]=>
+ string(4) "&Nu;"
+ ["Å’"]=>
+ string(7) "&OElig;"
["Ó"]=>
string(8) "&Oacute;"
["Ô"]=>
string(7) "&Ocirc;"
+ ["Ã’"]=>
+ string(8) "&Ograve;"
+ ["Ω"]=>
+ string(7) "&Omega;"
+ ["Ο"]=>
+ string(9) "&Omicron;"
+ ["Ø"]=>
+ string(8) "&Oslash;"
["Õ"]=>
string(8) "&Otilde;"
["Ö"]=>
string(6) "&Ouml;"
- ["×"]=>
- string(7) "&times;"
- ["Ø"]=>
- string(8) "&Oslash;"
- ["Ù"]=>
- string(8) "&Ugrave;"
+ ["Φ"]=>
+ string(5) "&Phi;"
+ ["Π"]=>
+ string(4) "&Pi;"
+ ["″"]=>
+ string(7) "&Prime;"
+ ["Ψ"]=>
+ string(5) "&Psi;"
+ ["Ρ"]=>
+ string(5) "&Rho;"
+ ["Å "]=>
+ string(8) "&Scaron;"
+ ["Σ"]=>
+ string(7) "&Sigma;"
+ ["Þ"]=>
+ string(7) "&THORN;"
+ ["Τ"]=>
+ string(5) "&Tau;"
+ ["Θ"]=>
+ string(7) "&Theta;"
["Ú"]=>
string(8) "&Uacute;"
["Û"]=>
string(7) "&Ucirc;"
+ ["Ù"]=>
+ string(8) "&Ugrave;"
+ ["Î¥"]=>
+ string(9) "&Upsilon;"
["Ü"]=>
string(6) "&Uuml;"
+ ["Ξ"]=>
+ string(4) "&Xi;"
["Ã"]=>
string(8) "&Yacute;"
- ["Þ"]=>
- string(7) "&THORN;"
- ["ß"]=>
- string(7) "&szlig;"
- ["à"]=>
- string(8) "&agrave;"
+ ["Ÿ"]=>
+ string(6) "&Yuml;"
+ ["Ζ"]=>
+ string(6) "&Zeta;"
["á"]=>
string(8) "&aacute;"
["â"]=>
string(7) "&acirc;"
+ ["´"]=>
+ string(7) "&acute;"
+ ["æ"]=>
+ string(7) "&aelig;"
+ ["à"]=>
+ string(8) "&agrave;"
+ ["ℵ"]=>
+ string(9) "&alefsym;"
+ ["α"]=>
+ string(7) "&alpha;"
+ ["&"]=>
+ string(5) "&amp;"
+ ["∧"]=>
+ string(5) "&and;"
+ ["∠"]=>
+ string(5) "&ang;"
+ ["Ã¥"]=>
+ string(7) "&aring;"
+ ["≈"]=>
+ string(7) "&asymp;"
["ã"]=>
string(8) "&atilde;"
["ä"]=>
string(6) "&auml;"
- ["Ã¥"]=>
- string(7) "&aring;"
- ["æ"]=>
- string(7) "&aelig;"
+ ["„"]=>
+ string(7) "&bdquo;"
+ ["β"]=>
+ string(6) "&beta;"
+ ["¦"]=>
+ string(8) "&brvbar;"
+ ["•"]=>
+ string(6) "&bull;"
+ ["∩"]=>
+ string(5) "&cap;"
["ç"]=>
string(8) "&ccedil;"
- ["è"]=>
- string(8) "&egrave;"
+ ["¸"]=>
+ string(7) "&cedil;"
+ ["¢"]=>
+ string(6) "&cent;"
+ ["χ"]=>
+ string(5) "&chi;"
+ ["ˆ"]=>
+ string(6) "&circ;"
+ ["♣"]=>
+ string(7) "&clubs;"
+ ["≅"]=>
+ string(6) "&cong;"
+ ["©"]=>
+ string(6) "&copy;"
+ ["↵"]=>
+ string(7) "&crarr;"
+ ["∪"]=>
+ string(5) "&cup;"
+ ["¤"]=>
+ string(8) "&curren;"
+ ["⇓"]=>
+ string(6) "&dArr;"
+ ["†"]=>
+ string(8) "&dagger;"
+ ["↓"]=>
+ string(6) "&darr;"
+ ["°"]=>
+ string(5) "&deg;"
+ ["δ"]=>
+ string(7) "&delta;"
+ ["♦"]=>
+ string(7) "&diams;"
+ ["÷"]=>
+ string(8) "&divide;"
["é"]=>
string(8) "&eacute;"
["ê"]=>
string(7) "&ecirc;"
- ["ë"]=>
- string(6) "&euml;"
- ["ì"]=>
- string(8) "&igrave;"
- ["í"]=>
- string(8) "&iacute;"
- ["î"]=>
- string(7) "&icirc;"
- ["ï"]=>
- string(6) "&iuml;"
+ ["è"]=>
+ string(8) "&egrave;"
+ ["∅"]=>
+ string(7) "&empty;"
+ [" "]=>
+ string(6) "&emsp;"
+ [" "]=>
+ string(6) "&ensp;"
+ ["ε"]=>
+ string(9) "&epsilon;"
+ ["≡"]=>
+ string(7) "&equiv;"
+ ["η"]=>
+ string(5) "&eta;"
["ð"]=>
string(5) "&eth;"
- ["ñ"]=>
- string(8) "&ntilde;"
- ["ò"]=>
- string(8) "&ograve;"
- ["ó"]=>
- string(8) "&oacute;"
- ["ô"]=>
- string(7) "&ocirc;"
- ["õ"]=>
- string(8) "&otilde;"
- ["ö"]=>
- string(6) "&ouml;"
- ["÷"]=>
- string(8) "&divide;"
- ["ø"]=>
- string(8) "&oslash;"
- ["ù"]=>
- string(8) "&ugrave;"
- ["ú"]=>
- string(8) "&uacute;"
- ["û"]=>
- string(7) "&ucirc;"
- ["ü"]=>
- string(6) "&uuml;"
- ["ý"]=>
- string(8) "&yacute;"
- ["þ"]=>
- string(7) "&thorn;"
- ["ÿ"]=>
- string(6) "&yuml;"
- ["Å’"]=>
- string(7) "&OElig;"
- ["Å“"]=>
- string(7) "&oelig;"
- ["Å "]=>
- string(8) "&Scaron;"
- ["Å¡"]=>
- string(8) "&scaron;"
- ["Ÿ"]=>
- string(6) "&Yuml;"
+ ["ë"]=>
+ string(6) "&euml;"
+ ["€"]=>
+ string(6) "&euro;"
+ ["∃"]=>
+ string(7) "&exist;"
["Æ’"]=>
string(6) "&fnof;"
- ["ˆ"]=>
- string(6) "&circ;"
- ["˜"]=>
- string(7) "&tilde;"
- ["Α"]=>
- string(7) "&Alpha;"
- ["Î’"]=>
- string(6) "&Beta;"
- ["Γ"]=>
- string(7) "&Gamma;"
- ["Δ"]=>
- string(7) "&Delta;"
- ["Ε"]=>
- string(9) "&Epsilon;"
- ["Ζ"]=>
- string(6) "&Zeta;"
- ["Η"]=>
- string(5) "&Eta;"
- ["Θ"]=>
- string(7) "&Theta;"
- ["Ι"]=>
- string(6) "&Iota;"
- ["Κ"]=>
- string(7) "&Kappa;"
- ["Λ"]=>
- string(8) "&Lambda;"
- ["Μ"]=>
- string(4) "&Mu;"
- ["Î"]=>
- string(4) "&Nu;"
- ["Ξ"]=>
- string(4) "&Xi;"
- ["Ο"]=>
- string(9) "&Omicron;"
- ["Π"]=>
- string(4) "&Pi;"
- ["Ρ"]=>
- string(5) "&Rho;"
- ["Σ"]=>
- string(7) "&Sigma;"
- ["Τ"]=>
- string(5) "&Tau;"
- ["Î¥"]=>
- string(9) "&Upsilon;"
- ["Φ"]=>
- string(5) "&Phi;"
- ["Χ"]=>
- string(5) "&Chi;"
- ["Ψ"]=>
- string(5) "&Psi;"
- ["Ω"]=>
- string(7) "&Omega;"
- ["α"]=>
- string(7) "&alpha;"
- ["β"]=>
- string(6) "&beta;"
+ ["∀"]=>
+ string(8) "&forall;"
+ ["½"]=>
+ string(8) "&frac12;"
+ ["¼"]=>
+ string(8) "&frac14;"
+ ["¾"]=>
+ string(8) "&frac34;"
+ ["â„"]=>
+ string(7) "&frasl;"
["γ"]=>
string(7) "&gamma;"
- ["δ"]=>
- string(7) "&delta;"
- ["ε"]=>
- string(9) "&epsilon;"
- ["ζ"]=>
- string(6) "&zeta;"
- ["η"]=>
- string(5) "&eta;"
- ["θ"]=>
- string(7) "&theta;"
+ ["≥"]=>
+ string(4) "&ge;"
+ [">"]=>
+ string(4) "&gt;"
+ ["⇔"]=>
+ string(6) "&hArr;"
+ ["↔"]=>
+ string(6) "&harr;"
+ ["♥"]=>
+ string(8) "&hearts;"
+ ["…"]=>
+ string(8) "&hellip;"
+ ["í"]=>
+ string(8) "&iacute;"
+ ["î"]=>
+ string(7) "&icirc;"
+ ["¡"]=>
+ string(7) "&iexcl;"
+ ["ì"]=>
+ string(8) "&igrave;"
+ ["â„‘"]=>
+ string(7) "&image;"
+ ["∞"]=>
+ string(7) "&infin;"
+ ["∫"]=>
+ string(5) "&int;"
["ι"]=>
string(6) "&iota;"
+ ["¿"]=>
+ string(8) "&iquest;"
+ ["∈"]=>
+ string(6) "&isin;"
+ ["ï"]=>
+ string(6) "&iuml;"
["κ"]=>
string(7) "&kappa;"
+ ["â‡"]=>
+ string(6) "&lArr;"
["λ"]=>
string(8) "&lambda;"
- ["μ"]=>
- string(4) "&mu;"
- ["ν"]=>
- string(4) "&nu;"
- ["ξ"]=>
- string(4) "&xi;"
- ["ο"]=>
- string(9) "&omicron;"
- ["Ï€"]=>
- string(4) "&pi;"
- ["Ï"]=>
- string(5) "&rho;"
- ["Ï‚"]=>
- string(8) "&sigmaf;"
- ["σ"]=>
- string(7) "&sigma;"
- ["Ï„"]=>
- string(5) "&tau;"
- ["Ï…"]=>
- string(9) "&upsilon;"
- ["φ"]=>
- string(5) "&phi;"
- ["χ"]=>
- string(5) "&chi;"
- ["ψ"]=>
- string(5) "&psi;"
- ["ω"]=>
- string(7) "&omega;"
- ["Ï‘"]=>
- string(10) "&thetasym;"
- ["Ï’"]=>
- string(7) "&upsih;"
- ["Ï–"]=>
- string(5) "&piv;"
- [" "]=>
- string(6) "&ensp;"
- [" "]=>
- string(6) "&emsp;"
- [" "]=>
- string(8) "&thinsp;"
- ["‌"]=>
- string(6) "&zwnj;"
- ["â€"]=>
- string(5) "&zwj;"
- ["‎"]=>
- string(5) "&lrm;"
- ["â€"]=>
- string(5) "&rlm;"
- ["–"]=>
- string(7) "&ndash;"
- ["—"]=>
- string(7) "&mdash;"
- ["‘"]=>
- string(7) "&lsquo;"
- ["’"]=>
- string(7) "&rsquo;"
- ["‚"]=>
- string(7) "&sbquo;"
+ ["〈"]=>
+ string(6) "&lang;"
+ ["«"]=>
+ string(7) "&laquo;"
+ ["â†"]=>
+ string(6) "&larr;"
+ ["⌈"]=>
+ string(7) "&lceil;"
["“"]=>
string(7) "&ldquo;"
- ["â€"]=>
- string(7) "&rdquo;"
- ["„"]=>
- string(7) "&bdquo;"
- ["†"]=>
- string(8) "&dagger;"
- ["‡"]=>
- string(8) "&Dagger;"
- ["•"]=>
- string(6) "&bull;"
- ["…"]=>
- string(8) "&hellip;"
- ["‰"]=>
- string(8) "&permil;"
- ["′"]=>
- string(7) "&prime;"
- ["″"]=>
- string(7) "&Prime;"
+ ["≤"]=>
+ string(4) "&le;"
+ ["⌊"]=>
+ string(8) "&lfloor;"
+ ["∗"]=>
+ string(8) "&lowast;"
+ ["â—Š"]=>
+ string(5) "&loz;"
+ ["‎"]=>
+ string(5) "&lrm;"
["‹"]=>
string(8) "&lsaquo;"
- ["›"]=>
- string(8) "&rsaquo;"
- ["‾"]=>
- string(7) "&oline;"
- ["â„"]=>
- string(7) "&frasl;"
- ["€"]=>
- string(6) "&euro;"
- ["â„‘"]=>
- string(7) "&image;"
- ["℘"]=>
- string(8) "&weierp;"
- ["ℜ"]=>
- string(6) "&real;"
- ["â„¢"]=>
- string(7) "&trade;"
- ["ℵ"]=>
- string(9) "&alefsym;"
- ["â†"]=>
- string(6) "&larr;"
- ["↑"]=>
- string(6) "&uarr;"
- ["→"]=>
- string(6) "&rarr;"
- ["↓"]=>
- string(6) "&darr;"
- ["↔"]=>
- string(6) "&harr;"
- ["↵"]=>
- string(7) "&crarr;"
- ["â‡"]=>
- string(6) "&lArr;"
- ["⇑"]=>
- string(6) "&uArr;"
- ["⇒"]=>
- string(6) "&rArr;"
- ["⇓"]=>
- string(6) "&dArr;"
- ["⇔"]=>
- string(6) "&hArr;"
- ["∀"]=>
- string(8) "&forall;"
- ["∂"]=>
- string(6) "&part;"
- ["∃"]=>
- string(7) "&exist;"
- ["∅"]=>
- string(7) "&empty;"
- ["∇"]=>
- string(7) "&nabla;"
- ["∈"]=>
- string(6) "&isin;"
- ["∉"]=>
- string(7) "&notin;"
- ["∋"]=>
- string(4) "&ni;"
- ["âˆ"]=>
- string(6) "&prod;"
- ["∑"]=>
- string(5) "&sum;"
+ ["‘"]=>
+ string(7) "&lsquo;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["¯"]=>
+ string(6) "&macr;"
+ ["—"]=>
+ string(7) "&mdash;"
+ ["µ"]=>
+ string(7) "&micro;"
+ ["·"]=>
+ string(8) "&middot;"
["−"]=>
string(7) "&minus;"
- ["∗"]=>
- string(8) "&lowast;"
- ["√"]=>
- string(7) "&radic;"
- ["âˆ"]=>
- string(6) "&prop;"
- ["∞"]=>
- string(7) "&infin;"
- ["∠"]=>
- string(5) "&ang;"
- ["∧"]=>
- string(5) "&and;"
- ["∨"]=>
- string(4) "&or;"
- ["∩"]=>
- string(5) "&cap;"
- ["∪"]=>
- string(5) "&cup;"
- ["∫"]=>
- string(5) "&int;"
- ["∴"]=>
- string(8) "&there4;"
- ["∼"]=>
- string(5) "&sim;"
- ["≅"]=>
- string(6) "&cong;"
- ["≈"]=>
- string(7) "&asymp;"
+ ["μ"]=>
+ string(4) "&mu;"
+ ["∇"]=>
+ string(7) "&nabla;"
+ [" "]=>
+ string(6) "&nbsp;"
+ ["–"]=>
+ string(7) "&ndash;"
["≠"]=>
string(4) "&ne;"
- ["≡"]=>
- string(7) "&equiv;"
- ["≤"]=>
- string(4) "&le;"
- ["≥"]=>
- string(4) "&ge;"
- ["⊂"]=>
- string(5) "&sub;"
- ["⊃"]=>
- string(5) "&sup;"
+ ["∋"]=>
+ string(4) "&ni;"
+ ["¬"]=>
+ string(5) "&not;"
+ ["∉"]=>
+ string(7) "&notin;"
["⊄"]=>
string(6) "&nsub;"
- ["⊆"]=>
- string(6) "&sube;"
- ["⊇"]=>
- string(6) "&supe;"
+ ["ñ"]=>
+ string(8) "&ntilde;"
+ ["ν"]=>
+ string(4) "&nu;"
+ ["ó"]=>
+ string(8) "&oacute;"
+ ["ô"]=>
+ string(7) "&ocirc;"
+ ["Å“"]=>
+ string(7) "&oelig;"
+ ["ò"]=>
+ string(8) "&ograve;"
+ ["‾"]=>
+ string(7) "&oline;"
+ ["ω"]=>
+ string(7) "&omega;"
+ ["ο"]=>
+ string(9) "&omicron;"
["⊕"]=>
string(7) "&oplus;"
+ ["∨"]=>
+ string(4) "&or;"
+ ["ª"]=>
+ string(6) "&ordf;"
+ ["º"]=>
+ string(6) "&ordm;"
+ ["ø"]=>
+ string(8) "&oslash;"
+ ["õ"]=>
+ string(8) "&otilde;"
["⊗"]=>
string(8) "&otimes;"
+ ["ö"]=>
+ string(6) "&ouml;"
+ ["¶"]=>
+ string(6) "&para;"
+ ["∂"]=>
+ string(6) "&part;"
+ ["‰"]=>
+ string(8) "&permil;"
["⊥"]=>
string(6) "&perp;"
- ["â‹…"]=>
- string(6) "&sdot;"
- ["⌈"]=>
- string(7) "&lceil;"
+ ["φ"]=>
+ string(5) "&phi;"
+ ["Ï€"]=>
+ string(4) "&pi;"
+ ["Ï–"]=>
+ string(5) "&piv;"
+ ["±"]=>
+ string(8) "&plusmn;"
+ ["£"]=>
+ string(7) "&pound;"
+ ["′"]=>
+ string(7) "&prime;"
+ ["âˆ"]=>
+ string(6) "&prod;"
+ ["âˆ"]=>
+ string(6) "&prop;"
+ ["ψ"]=>
+ string(5) "&psi;"
+ ["""]=>
+ string(6) "&quot;"
+ ["⇒"]=>
+ string(6) "&rArr;"
+ ["√"]=>
+ string(7) "&radic;"
+ ["〉"]=>
+ string(6) "&rang;"
+ ["»"]=>
+ string(7) "&raquo;"
+ ["→"]=>
+ string(6) "&rarr;"
["⌉"]=>
string(7) "&rceil;"
- ["⌊"]=>
- string(8) "&lfloor;"
+ ["â€"]=>
+ string(7) "&rdquo;"
+ ["ℜ"]=>
+ string(6) "&real;"
+ ["®"]=>
+ string(5) "&reg;"
["⌋"]=>
string(8) "&rfloor;"
- ["〈"]=>
- string(6) "&lang;"
- ["〉"]=>
- string(6) "&rang;"
- ["â—Š"]=>
- string(5) "&loz;"
- ["â™ "]=>
- string(8) "&spades;"
- ["♣"]=>
- string(7) "&clubs;"
- ["♥"]=>
- string(8) "&hearts;"
- ["♦"]=>
- string(7) "&diams;"
- ["&"]=>
- string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
- [">"]=>
- string(4) "&gt;"
-}
--- with table = HTML_ENTITIES & quote_style = ENT_QUOTES --
-array(253) {
- [" "]=>
- string(6) "&nbsp;"
- ["¡"]=>
- string(7) "&iexcl;"
- ["¢"]=>
- string(6) "&cent;"
- ["£"]=>
- string(7) "&pound;"
- ["¤"]=>
- string(8) "&curren;"
- ["Â¥"]=>
- string(5) "&yen;"
- ["¦"]=>
- string(8) "&brvbar;"
+ ["Ï"]=>
+ string(5) "&rho;"
+ ["â€"]=>
+ string(5) "&rlm;"
+ ["›"]=>
+ string(8) "&rsaquo;"
+ ["’"]=>
+ string(7) "&rsquo;"
+ ["‚"]=>
+ string(7) "&sbquo;"
+ ["Å¡"]=>
+ string(8) "&scaron;"
+ ["â‹…"]=>
+ string(6) "&sdot;"
["§"]=>
string(6) "&sect;"
- ["¨"]=>
- string(5) "&uml;"
- ["©"]=>
- string(6) "&copy;"
- ["ª"]=>
- string(6) "&ordf;"
- ["«"]=>
- string(7) "&laquo;"
- ["¬"]=>
- string(5) "&not;"
["­"]=>
string(5) "&shy;"
- ["®"]=>
- string(5) "&reg;"
- ["¯"]=>
- string(6) "&macr;"
- ["°"]=>
- string(5) "&deg;"
- ["±"]=>
- string(8) "&plusmn;"
+ ["σ"]=>
+ string(7) "&sigma;"
+ ["Ï‚"]=>
+ string(8) "&sigmaf;"
+ ["∼"]=>
+ string(5) "&sim;"
+ ["â™ "]=>
+ string(8) "&spades;"
+ ["⊂"]=>
+ string(5) "&sub;"
+ ["⊆"]=>
+ string(6) "&sube;"
+ ["∑"]=>
+ string(5) "&sum;"
+ ["¹"]=>
+ string(6) "&sup1;"
["²"]=>
string(6) "&sup2;"
["³"]=>
string(6) "&sup3;"
- ["´"]=>
- string(7) "&acute;"
- ["µ"]=>
- string(7) "&micro;"
- ["¶"]=>
- string(6) "&para;"
- ["·"]=>
- string(8) "&middot;"
- ["¸"]=>
- string(7) "&cedil;"
- ["¹"]=>
- string(6) "&sup1;"
- ["º"]=>
- string(6) "&ordm;"
- ["»"]=>
- string(7) "&raquo;"
- ["¼"]=>
- string(8) "&frac14;"
- ["½"]=>
- string(8) "&frac12;"
- ["¾"]=>
- string(8) "&frac34;"
- ["¿"]=>
- string(8) "&iquest;"
- ["À"]=>
- string(8) "&Agrave;"
+ ["⊃"]=>
+ string(5) "&sup;"
+ ["⊇"]=>
+ string(6) "&supe;"
+ ["ß"]=>
+ string(7) "&szlig;"
+ ["Ï„"]=>
+ string(5) "&tau;"
+ ["∴"]=>
+ string(8) "&there4;"
+ ["θ"]=>
+ string(7) "&theta;"
+ ["Ï‘"]=>
+ string(10) "&thetasym;"
+ [" "]=>
+ string(8) "&thinsp;"
+ ["þ"]=>
+ string(7) "&thorn;"
+ ["˜"]=>
+ string(7) "&tilde;"
+ ["×"]=>
+ string(7) "&times;"
+ ["â„¢"]=>
+ string(7) "&trade;"
+ ["⇑"]=>
+ string(6) "&uArr;"
+ ["ú"]=>
+ string(8) "&uacute;"
+ ["↑"]=>
+ string(6) "&uarr;"
+ ["û"]=>
+ string(7) "&ucirc;"
+ ["ù"]=>
+ string(8) "&ugrave;"
+ ["¨"]=>
+ string(5) "&uml;"
+ ["Ï’"]=>
+ string(7) "&upsih;"
+ ["Ï…"]=>
+ string(9) "&upsilon;"
+ ["ü"]=>
+ string(6) "&uuml;"
+ ["℘"]=>
+ string(8) "&weierp;"
+ ["ξ"]=>
+ string(4) "&xi;"
+ ["ý"]=>
+ string(8) "&yacute;"
+ ["Â¥"]=>
+ string(5) "&yen;"
+ ["ÿ"]=>
+ string(6) "&yuml;"
+ ["ζ"]=>
+ string(6) "&zeta;"
+ ["â€"]=>
+ string(5) "&zwj;"
+ ["‌"]=>
+ string(6) "&zwnj;"
+}
+-- with table = HTML_ENTITIES & quote_style = ENT_QUOTES --
+array(253) {
+ ["'"]=>
+ string(6) "&#039;"
+ ["Æ"]=>
+ string(7) "&AElig;"
["Ã"]=>
string(8) "&Aacute;"
["Â"]=>
string(7) "&Acirc;"
+ ["À"]=>
+ string(8) "&Agrave;"
+ ["Α"]=>
+ string(7) "&Alpha;"
+ ["Ã…"]=>
+ string(7) "&Aring;"
["Ã"]=>
string(8) "&Atilde;"
["Ä"]=>
string(6) "&Auml;"
- ["Ã…"]=>
- string(7) "&Aring;"
- ["Æ"]=>
- string(7) "&AElig;"
+ ["Î’"]=>
+ string(6) "&Beta;"
["Ç"]=>
string(8) "&Ccedil;"
- ["È"]=>
- string(8) "&Egrave;"
+ ["Χ"]=>
+ string(5) "&Chi;"
+ ["‡"]=>
+ string(8) "&Dagger;"
+ ["Δ"]=>
+ string(7) "&Delta;"
+ ["Ã"]=>
+ string(5) "&ETH;"
["É"]=>
string(8) "&Eacute;"
["Ê"]=>
string(7) "&Ecirc;"
+ ["È"]=>
+ string(8) "&Egrave;"
+ ["Ε"]=>
+ string(9) "&Epsilon;"
+ ["Η"]=>
+ string(5) "&Eta;"
["Ë"]=>
string(6) "&Euml;"
- ["Ì"]=>
- string(8) "&Igrave;"
+ ["Γ"]=>
+ string(7) "&Gamma;"
["Ã"]=>
string(8) "&Iacute;"
["ÃŽ"]=>
string(7) "&Icirc;"
+ ["Ì"]=>
+ string(8) "&Igrave;"
+ ["Ι"]=>
+ string(6) "&Iota;"
["Ã"]=>
string(6) "&Iuml;"
- ["Ã"]=>
- string(5) "&ETH;"
+ ["Κ"]=>
+ string(7) "&Kappa;"
+ ["Λ"]=>
+ string(8) "&Lambda;"
+ ["Μ"]=>
+ string(4) "&Mu;"
["Ñ"]=>
string(8) "&Ntilde;"
- ["Ã’"]=>
- string(8) "&Ograve;"
+ ["Î"]=>
+ string(4) "&Nu;"
+ ["Å’"]=>
+ string(7) "&OElig;"
["Ó"]=>
string(8) "&Oacute;"
["Ô"]=>
string(7) "&Ocirc;"
+ ["Ã’"]=>
+ string(8) "&Ograve;"
+ ["Ω"]=>
+ string(7) "&Omega;"
+ ["Ο"]=>
+ string(9) "&Omicron;"
+ ["Ø"]=>
+ string(8) "&Oslash;"
["Õ"]=>
string(8) "&Otilde;"
["Ö"]=>
string(6) "&Ouml;"
- ["×"]=>
- string(7) "&times;"
- ["Ø"]=>
- string(8) "&Oslash;"
- ["Ù"]=>
- string(8) "&Ugrave;"
+ ["Φ"]=>
+ string(5) "&Phi;"
+ ["Π"]=>
+ string(4) "&Pi;"
+ ["″"]=>
+ string(7) "&Prime;"
+ ["Ψ"]=>
+ string(5) "&Psi;"
+ ["Ρ"]=>
+ string(5) "&Rho;"
+ ["Å "]=>
+ string(8) "&Scaron;"
+ ["Σ"]=>
+ string(7) "&Sigma;"
+ ["Þ"]=>
+ string(7) "&THORN;"
+ ["Τ"]=>
+ string(5) "&Tau;"
+ ["Θ"]=>
+ string(7) "&Theta;"
["Ú"]=>
string(8) "&Uacute;"
["Û"]=>
string(7) "&Ucirc;"
+ ["Ù"]=>
+ string(8) "&Ugrave;"
+ ["Î¥"]=>
+ string(9) "&Upsilon;"
["Ü"]=>
string(6) "&Uuml;"
+ ["Ξ"]=>
+ string(4) "&Xi;"
["Ã"]=>
string(8) "&Yacute;"
- ["Þ"]=>
- string(7) "&THORN;"
- ["ß"]=>
- string(7) "&szlig;"
- ["à"]=>
- string(8) "&agrave;"
+ ["Ÿ"]=>
+ string(6) "&Yuml;"
+ ["Ζ"]=>
+ string(6) "&Zeta;"
["á"]=>
string(8) "&aacute;"
["â"]=>
string(7) "&acirc;"
+ ["´"]=>
+ string(7) "&acute;"
+ ["æ"]=>
+ string(7) "&aelig;"
+ ["à"]=>
+ string(8) "&agrave;"
+ ["ℵ"]=>
+ string(9) "&alefsym;"
+ ["α"]=>
+ string(7) "&alpha;"
+ ["&"]=>
+ string(5) "&amp;"
+ ["∧"]=>
+ string(5) "&and;"
+ ["∠"]=>
+ string(5) "&ang;"
+ ["Ã¥"]=>
+ string(7) "&aring;"
+ ["≈"]=>
+ string(7) "&asymp;"
["ã"]=>
string(8) "&atilde;"
["ä"]=>
string(6) "&auml;"
- ["Ã¥"]=>
- string(7) "&aring;"
- ["æ"]=>
- string(7) "&aelig;"
+ ["„"]=>
+ string(7) "&bdquo;"
+ ["β"]=>
+ string(6) "&beta;"
+ ["¦"]=>
+ string(8) "&brvbar;"
+ ["•"]=>
+ string(6) "&bull;"
+ ["∩"]=>
+ string(5) "&cap;"
["ç"]=>
string(8) "&ccedil;"
- ["è"]=>
- string(8) "&egrave;"
+ ["¸"]=>
+ string(7) "&cedil;"
+ ["¢"]=>
+ string(6) "&cent;"
+ ["χ"]=>
+ string(5) "&chi;"
+ ["ˆ"]=>
+ string(6) "&circ;"
+ ["♣"]=>
+ string(7) "&clubs;"
+ ["≅"]=>
+ string(6) "&cong;"
+ ["©"]=>
+ string(6) "&copy;"
+ ["↵"]=>
+ string(7) "&crarr;"
+ ["∪"]=>
+ string(5) "&cup;"
+ ["¤"]=>
+ string(8) "&curren;"
+ ["⇓"]=>
+ string(6) "&dArr;"
+ ["†"]=>
+ string(8) "&dagger;"
+ ["↓"]=>
+ string(6) "&darr;"
+ ["°"]=>
+ string(5) "&deg;"
+ ["δ"]=>
+ string(7) "&delta;"
+ ["♦"]=>
+ string(7) "&diams;"
+ ["÷"]=>
+ string(8) "&divide;"
["é"]=>
string(8) "&eacute;"
["ê"]=>
string(7) "&ecirc;"
- ["ë"]=>
- string(6) "&euml;"
- ["ì"]=>
- string(8) "&igrave;"
- ["í"]=>
- string(8) "&iacute;"
- ["î"]=>
- string(7) "&icirc;"
- ["ï"]=>
- string(6) "&iuml;"
+ ["è"]=>
+ string(8) "&egrave;"
+ ["∅"]=>
+ string(7) "&empty;"
+ [" "]=>
+ string(6) "&emsp;"
+ [" "]=>
+ string(6) "&ensp;"
+ ["ε"]=>
+ string(9) "&epsilon;"
+ ["≡"]=>
+ string(7) "&equiv;"
+ ["η"]=>
+ string(5) "&eta;"
["ð"]=>
string(5) "&eth;"
- ["ñ"]=>
- string(8) "&ntilde;"
- ["ò"]=>
- string(8) "&ograve;"
- ["ó"]=>
- string(8) "&oacute;"
- ["ô"]=>
- string(7) "&ocirc;"
- ["õ"]=>
- string(8) "&otilde;"
- ["ö"]=>
- string(6) "&ouml;"
- ["÷"]=>
- string(8) "&divide;"
- ["ø"]=>
- string(8) "&oslash;"
- ["ù"]=>
- string(8) "&ugrave;"
- ["ú"]=>
- string(8) "&uacute;"
- ["û"]=>
- string(7) "&ucirc;"
- ["ü"]=>
- string(6) "&uuml;"
- ["ý"]=>
- string(8) "&yacute;"
- ["þ"]=>
- string(7) "&thorn;"
- ["ÿ"]=>
- string(6) "&yuml;"
- ["Å’"]=>
- string(7) "&OElig;"
- ["Å“"]=>
- string(7) "&oelig;"
- ["Å "]=>
- string(8) "&Scaron;"
- ["Å¡"]=>
- string(8) "&scaron;"
- ["Ÿ"]=>
- string(6) "&Yuml;"
+ ["ë"]=>
+ string(6) "&euml;"
+ ["€"]=>
+ string(6) "&euro;"
+ ["∃"]=>
+ string(7) "&exist;"
["Æ’"]=>
string(6) "&fnof;"
- ["ˆ"]=>
- string(6) "&circ;"
- ["˜"]=>
- string(7) "&tilde;"
- ["Α"]=>
- string(7) "&Alpha;"
- ["Î’"]=>
- string(6) "&Beta;"
- ["Γ"]=>
- string(7) "&Gamma;"
- ["Δ"]=>
- string(7) "&Delta;"
- ["Ε"]=>
- string(9) "&Epsilon;"
- ["Ζ"]=>
- string(6) "&Zeta;"
- ["Η"]=>
- string(5) "&Eta;"
- ["Θ"]=>
- string(7) "&Theta;"
- ["Ι"]=>
- string(6) "&Iota;"
- ["Κ"]=>
- string(7) "&Kappa;"
- ["Λ"]=>
- string(8) "&Lambda;"
- ["Μ"]=>
- string(4) "&Mu;"
- ["Î"]=>
- string(4) "&Nu;"
- ["Ξ"]=>
- string(4) "&Xi;"
- ["Ο"]=>
- string(9) "&Omicron;"
- ["Π"]=>
- string(4) "&Pi;"
- ["Ρ"]=>
- string(5) "&Rho;"
- ["Σ"]=>
- string(7) "&Sigma;"
- ["Τ"]=>
- string(5) "&Tau;"
- ["Î¥"]=>
- string(9) "&Upsilon;"
- ["Φ"]=>
- string(5) "&Phi;"
- ["Χ"]=>
- string(5) "&Chi;"
- ["Ψ"]=>
- string(5) "&Psi;"
- ["Ω"]=>
- string(7) "&Omega;"
- ["α"]=>
- string(7) "&alpha;"
- ["β"]=>
- string(6) "&beta;"
+ ["∀"]=>
+ string(8) "&forall;"
+ ["½"]=>
+ string(8) "&frac12;"
+ ["¼"]=>
+ string(8) "&frac14;"
+ ["¾"]=>
+ string(8) "&frac34;"
+ ["â„"]=>
+ string(7) "&frasl;"
["γ"]=>
string(7) "&gamma;"
- ["δ"]=>
- string(7) "&delta;"
- ["ε"]=>
- string(9) "&epsilon;"
- ["ζ"]=>
- string(6) "&zeta;"
- ["η"]=>
- string(5) "&eta;"
- ["θ"]=>
- string(7) "&theta;"
+ ["≥"]=>
+ string(4) "&ge;"
+ [">"]=>
+ string(4) "&gt;"
+ ["⇔"]=>
+ string(6) "&hArr;"
+ ["↔"]=>
+ string(6) "&harr;"
+ ["♥"]=>
+ string(8) "&hearts;"
+ ["…"]=>
+ string(8) "&hellip;"
+ ["í"]=>
+ string(8) "&iacute;"
+ ["î"]=>
+ string(7) "&icirc;"
+ ["¡"]=>
+ string(7) "&iexcl;"
+ ["ì"]=>
+ string(8) "&igrave;"
+ ["â„‘"]=>
+ string(7) "&image;"
+ ["∞"]=>
+ string(7) "&infin;"
+ ["∫"]=>
+ string(5) "&int;"
["ι"]=>
string(6) "&iota;"
+ ["¿"]=>
+ string(8) "&iquest;"
+ ["∈"]=>
+ string(6) "&isin;"
+ ["ï"]=>
+ string(6) "&iuml;"
["κ"]=>
string(7) "&kappa;"
+ ["â‡"]=>
+ string(6) "&lArr;"
["λ"]=>
string(8) "&lambda;"
- ["μ"]=>
- string(4) "&mu;"
- ["ν"]=>
- string(4) "&nu;"
- ["ξ"]=>
- string(4) "&xi;"
- ["ο"]=>
- string(9) "&omicron;"
- ["Ï€"]=>
- string(4) "&pi;"
- ["Ï"]=>
- string(5) "&rho;"
- ["Ï‚"]=>
- string(8) "&sigmaf;"
- ["σ"]=>
- string(7) "&sigma;"
- ["Ï„"]=>
- string(5) "&tau;"
- ["Ï…"]=>
- string(9) "&upsilon;"
- ["φ"]=>
- string(5) "&phi;"
- ["χ"]=>
- string(5) "&chi;"
- ["ψ"]=>
- string(5) "&psi;"
- ["ω"]=>
- string(7) "&omega;"
- ["Ï‘"]=>
- string(10) "&thetasym;"
- ["Ï’"]=>
- string(7) "&upsih;"
- ["Ï–"]=>
- string(5) "&piv;"
- [" "]=>
- string(6) "&ensp;"
- [" "]=>
- string(6) "&emsp;"
- [" "]=>
- string(8) "&thinsp;"
- ["‌"]=>
- string(6) "&zwnj;"
- ["â€"]=>
- string(5) "&zwj;"
- ["‎"]=>
- string(5) "&lrm;"
- ["â€"]=>
- string(5) "&rlm;"
- ["–"]=>
- string(7) "&ndash;"
- ["—"]=>
- string(7) "&mdash;"
- ["‘"]=>
- string(7) "&lsquo;"
- ["’"]=>
- string(7) "&rsquo;"
- ["‚"]=>
- string(7) "&sbquo;"
+ ["〈"]=>
+ string(6) "&lang;"
+ ["«"]=>
+ string(7) "&laquo;"
+ ["â†"]=>
+ string(6) "&larr;"
+ ["⌈"]=>
+ string(7) "&lceil;"
["“"]=>
string(7) "&ldquo;"
- ["â€"]=>
- string(7) "&rdquo;"
- ["„"]=>
- string(7) "&bdquo;"
- ["†"]=>
- string(8) "&dagger;"
- ["‡"]=>
- string(8) "&Dagger;"
- ["•"]=>
- string(6) "&bull;"
- ["…"]=>
- string(8) "&hellip;"
- ["‰"]=>
- string(8) "&permil;"
- ["′"]=>
- string(7) "&prime;"
- ["″"]=>
- string(7) "&Prime;"
+ ["≤"]=>
+ string(4) "&le;"
+ ["⌊"]=>
+ string(8) "&lfloor;"
+ ["∗"]=>
+ string(8) "&lowast;"
+ ["â—Š"]=>
+ string(5) "&loz;"
+ ["‎"]=>
+ string(5) "&lrm;"
["‹"]=>
string(8) "&lsaquo;"
- ["›"]=>
- string(8) "&rsaquo;"
- ["‾"]=>
- string(7) "&oline;"
- ["â„"]=>
- string(7) "&frasl;"
- ["€"]=>
- string(6) "&euro;"
- ["â„‘"]=>
- string(7) "&image;"
- ["℘"]=>
- string(8) "&weierp;"
- ["ℜ"]=>
- string(6) "&real;"
- ["â„¢"]=>
- string(7) "&trade;"
- ["ℵ"]=>
- string(9) "&alefsym;"
- ["â†"]=>
- string(6) "&larr;"
- ["↑"]=>
- string(6) "&uarr;"
- ["→"]=>
- string(6) "&rarr;"
- ["↓"]=>
- string(6) "&darr;"
- ["↔"]=>
- string(6) "&harr;"
- ["↵"]=>
- string(7) "&crarr;"
- ["â‡"]=>
- string(6) "&lArr;"
- ["⇑"]=>
- string(6) "&uArr;"
- ["⇒"]=>
- string(6) "&rArr;"
- ["⇓"]=>
- string(6) "&dArr;"
- ["⇔"]=>
- string(6) "&hArr;"
- ["∀"]=>
- string(8) "&forall;"
- ["∂"]=>
- string(6) "&part;"
- ["∃"]=>
- string(7) "&exist;"
- ["∅"]=>
- string(7) "&empty;"
- ["∇"]=>
- string(7) "&nabla;"
- ["∈"]=>
- string(6) "&isin;"
- ["∉"]=>
- string(7) "&notin;"
- ["∋"]=>
- string(4) "&ni;"
- ["âˆ"]=>
- string(6) "&prod;"
- ["∑"]=>
- string(5) "&sum;"
+ ["‘"]=>
+ string(7) "&lsquo;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["¯"]=>
+ string(6) "&macr;"
+ ["—"]=>
+ string(7) "&mdash;"
+ ["µ"]=>
+ string(7) "&micro;"
+ ["·"]=>
+ string(8) "&middot;"
["−"]=>
string(7) "&minus;"
- ["∗"]=>
- string(8) "&lowast;"
- ["√"]=>
- string(7) "&radic;"
- ["âˆ"]=>
- string(6) "&prop;"
- ["∞"]=>
- string(7) "&infin;"
- ["∠"]=>
- string(5) "&ang;"
- ["∧"]=>
- string(5) "&and;"
- ["∨"]=>
- string(4) "&or;"
- ["∩"]=>
- string(5) "&cap;"
- ["∪"]=>
- string(5) "&cup;"
- ["∫"]=>
- string(5) "&int;"
- ["∴"]=>
- string(8) "&there4;"
- ["∼"]=>
- string(5) "&sim;"
- ["≅"]=>
- string(6) "&cong;"
- ["≈"]=>
- string(7) "&asymp;"
+ ["μ"]=>
+ string(4) "&mu;"
+ ["∇"]=>
+ string(7) "&nabla;"
+ [" "]=>
+ string(6) "&nbsp;"
+ ["–"]=>
+ string(7) "&ndash;"
["≠"]=>
string(4) "&ne;"
- ["≡"]=>
- string(7) "&equiv;"
- ["≤"]=>
- string(4) "&le;"
- ["≥"]=>
- string(4) "&ge;"
- ["⊂"]=>
- string(5) "&sub;"
- ["⊃"]=>
- string(5) "&sup;"
+ ["∋"]=>
+ string(4) "&ni;"
+ ["¬"]=>
+ string(5) "&not;"
+ ["∉"]=>
+ string(7) "&notin;"
["⊄"]=>
string(6) "&nsub;"
- ["⊆"]=>
- string(6) "&sube;"
- ["⊇"]=>
- string(6) "&supe;"
+ ["ñ"]=>
+ string(8) "&ntilde;"
+ ["ν"]=>
+ string(4) "&nu;"
+ ["ó"]=>
+ string(8) "&oacute;"
+ ["ô"]=>
+ string(7) "&ocirc;"
+ ["Å“"]=>
+ string(7) "&oelig;"
+ ["ò"]=>
+ string(8) "&ograve;"
+ ["‾"]=>
+ string(7) "&oline;"
+ ["ω"]=>
+ string(7) "&omega;"
+ ["ο"]=>
+ string(9) "&omicron;"
["⊕"]=>
string(7) "&oplus;"
+ ["∨"]=>
+ string(4) "&or;"
+ ["ª"]=>
+ string(6) "&ordf;"
+ ["º"]=>
+ string(6) "&ordm;"
+ ["ø"]=>
+ string(8) "&oslash;"
+ ["õ"]=>
+ string(8) "&otilde;"
["⊗"]=>
string(8) "&otimes;"
+ ["ö"]=>
+ string(6) "&ouml;"
+ ["¶"]=>
+ string(6) "&para;"
+ ["∂"]=>
+ string(6) "&part;"
+ ["‰"]=>
+ string(8) "&permil;"
["⊥"]=>
string(6) "&perp;"
- ["â‹…"]=>
- string(6) "&sdot;"
- ["⌈"]=>
- string(7) "&lceil;"
+ ["φ"]=>
+ string(5) "&phi;"
+ ["Ï€"]=>
+ string(4) "&pi;"
+ ["Ï–"]=>
+ string(5) "&piv;"
+ ["±"]=>
+ string(8) "&plusmn;"
+ ["£"]=>
+ string(7) "&pound;"
+ ["′"]=>
+ string(7) "&prime;"
+ ["âˆ"]=>
+ string(6) "&prod;"
+ ["âˆ"]=>
+ string(6) "&prop;"
+ ["ψ"]=>
+ string(5) "&psi;"
+ ["""]=>
+ string(6) "&quot;"
+ ["⇒"]=>
+ string(6) "&rArr;"
+ ["√"]=>
+ string(7) "&radic;"
+ ["〉"]=>
+ string(6) "&rang;"
+ ["»"]=>
+ string(7) "&raquo;"
+ ["→"]=>
+ string(6) "&rarr;"
["⌉"]=>
string(7) "&rceil;"
- ["⌊"]=>
- string(8) "&lfloor;"
+ ["â€"]=>
+ string(7) "&rdquo;"
+ ["ℜ"]=>
+ string(6) "&real;"
+ ["®"]=>
+ string(5) "&reg;"
["⌋"]=>
string(8) "&rfloor;"
- ["〈"]=>
- string(6) "&lang;"
- ["〉"]=>
- string(6) "&rang;"
- ["â—Š"]=>
- string(5) "&loz;"
- ["â™ "]=>
- string(8) "&spades;"
- ["♣"]=>
- string(7) "&clubs;"
- ["♥"]=>
- string(8) "&hearts;"
- ["♦"]=>
- string(7) "&diams;"
- ["&"]=>
- string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["'"]=>
- string(6) "&#039;"
- ["<"]=>
- string(4) "&lt;"
- [">"]=>
- string(4) "&gt;"
-}
--- with table = HTML_ENTITIES & quote_style = ENT_NOQUOTES --
-array(251) {
- [" "]=>
- string(6) "&nbsp;"
- ["¡"]=>
- string(7) "&iexcl;"
- ["¢"]=>
- string(6) "&cent;"
- ["£"]=>
- string(7) "&pound;"
- ["¤"]=>
- string(8) "&curren;"
- ["Â¥"]=>
- string(5) "&yen;"
- ["¦"]=>
- string(8) "&brvbar;"
+ ["Ï"]=>
+ string(5) "&rho;"
+ ["â€"]=>
+ string(5) "&rlm;"
+ ["›"]=>
+ string(8) "&rsaquo;"
+ ["’"]=>
+ string(7) "&rsquo;"
+ ["‚"]=>
+ string(7) "&sbquo;"
+ ["Å¡"]=>
+ string(8) "&scaron;"
+ ["â‹…"]=>
+ string(6) "&sdot;"
["§"]=>
string(6) "&sect;"
- ["¨"]=>
- string(5) "&uml;"
- ["©"]=>
- string(6) "&copy;"
- ["ª"]=>
- string(6) "&ordf;"
- ["«"]=>
- string(7) "&laquo;"
- ["¬"]=>
- string(5) "&not;"
["­"]=>
string(5) "&shy;"
- ["®"]=>
- string(5) "&reg;"
- ["¯"]=>
- string(6) "&macr;"
- ["°"]=>
- string(5) "&deg;"
- ["±"]=>
- string(8) "&plusmn;"
+ ["σ"]=>
+ string(7) "&sigma;"
+ ["Ï‚"]=>
+ string(8) "&sigmaf;"
+ ["∼"]=>
+ string(5) "&sim;"
+ ["â™ "]=>
+ string(8) "&spades;"
+ ["⊂"]=>
+ string(5) "&sub;"
+ ["⊆"]=>
+ string(6) "&sube;"
+ ["∑"]=>
+ string(5) "&sum;"
+ ["¹"]=>
+ string(6) "&sup1;"
["²"]=>
string(6) "&sup2;"
["³"]=>
string(6) "&sup3;"
- ["´"]=>
- string(7) "&acute;"
- ["µ"]=>
- string(7) "&micro;"
- ["¶"]=>
- string(6) "&para;"
- ["·"]=>
- string(8) "&middot;"
- ["¸"]=>
- string(7) "&cedil;"
- ["¹"]=>
- string(6) "&sup1;"
- ["º"]=>
- string(6) "&ordm;"
- ["»"]=>
- string(7) "&raquo;"
- ["¼"]=>
- string(8) "&frac14;"
- ["½"]=>
- string(8) "&frac12;"
- ["¾"]=>
- string(8) "&frac34;"
- ["¿"]=>
- string(8) "&iquest;"
- ["À"]=>
- string(8) "&Agrave;"
+ ["⊃"]=>
+ string(5) "&sup;"
+ ["⊇"]=>
+ string(6) "&supe;"
+ ["ß"]=>
+ string(7) "&szlig;"
+ ["Ï„"]=>
+ string(5) "&tau;"
+ ["∴"]=>
+ string(8) "&there4;"
+ ["θ"]=>
+ string(7) "&theta;"
+ ["Ï‘"]=>
+ string(10) "&thetasym;"
+ [" "]=>
+ string(8) "&thinsp;"
+ ["þ"]=>
+ string(7) "&thorn;"
+ ["˜"]=>
+ string(7) "&tilde;"
+ ["×"]=>
+ string(7) "&times;"
+ ["â„¢"]=>
+ string(7) "&trade;"
+ ["⇑"]=>
+ string(6) "&uArr;"
+ ["ú"]=>
+ string(8) "&uacute;"
+ ["↑"]=>
+ string(6) "&uarr;"
+ ["û"]=>
+ string(7) "&ucirc;"
+ ["ù"]=>
+ string(8) "&ugrave;"
+ ["¨"]=>
+ string(5) "&uml;"
+ ["Ï’"]=>
+ string(7) "&upsih;"
+ ["Ï…"]=>
+ string(9) "&upsilon;"
+ ["ü"]=>
+ string(6) "&uuml;"
+ ["℘"]=>
+ string(8) "&weierp;"
+ ["ξ"]=>
+ string(4) "&xi;"
+ ["ý"]=>
+ string(8) "&yacute;"
+ ["Â¥"]=>
+ string(5) "&yen;"
+ ["ÿ"]=>
+ string(6) "&yuml;"
+ ["ζ"]=>
+ string(6) "&zeta;"
+ ["â€"]=>
+ string(5) "&zwj;"
+ ["‌"]=>
+ string(6) "&zwnj;"
+}
+-- with table = HTML_ENTITIES & quote_style = ENT_NOQUOTES --
+array(251) {
+ ["Æ"]=>
+ string(7) "&AElig;"
["Ã"]=>
string(8) "&Aacute;"
["Â"]=>
string(7) "&Acirc;"
+ ["À"]=>
+ string(8) "&Agrave;"
+ ["Α"]=>
+ string(7) "&Alpha;"
+ ["Ã…"]=>
+ string(7) "&Aring;"
["Ã"]=>
string(8) "&Atilde;"
["Ä"]=>
string(6) "&Auml;"
- ["Ã…"]=>
- string(7) "&Aring;"
- ["Æ"]=>
- string(7) "&AElig;"
+ ["Î’"]=>
+ string(6) "&Beta;"
["Ç"]=>
string(8) "&Ccedil;"
- ["È"]=>
- string(8) "&Egrave;"
+ ["Χ"]=>
+ string(5) "&Chi;"
+ ["‡"]=>
+ string(8) "&Dagger;"
+ ["Δ"]=>
+ string(7) "&Delta;"
+ ["Ã"]=>
+ string(5) "&ETH;"
["É"]=>
string(8) "&Eacute;"
["Ê"]=>
string(7) "&Ecirc;"
+ ["È"]=>
+ string(8) "&Egrave;"
+ ["Ε"]=>
+ string(9) "&Epsilon;"
+ ["Η"]=>
+ string(5) "&Eta;"
["Ë"]=>
string(6) "&Euml;"
- ["Ì"]=>
- string(8) "&Igrave;"
+ ["Γ"]=>
+ string(7) "&Gamma;"
["Ã"]=>
string(8) "&Iacute;"
["ÃŽ"]=>
string(7) "&Icirc;"
+ ["Ì"]=>
+ string(8) "&Igrave;"
+ ["Ι"]=>
+ string(6) "&Iota;"
["Ã"]=>
string(6) "&Iuml;"
- ["Ã"]=>
- string(5) "&ETH;"
+ ["Κ"]=>
+ string(7) "&Kappa;"
+ ["Λ"]=>
+ string(8) "&Lambda;"
+ ["Μ"]=>
+ string(4) "&Mu;"
["Ñ"]=>
string(8) "&Ntilde;"
- ["Ã’"]=>
- string(8) "&Ograve;"
+ ["Î"]=>
+ string(4) "&Nu;"
+ ["Å’"]=>
+ string(7) "&OElig;"
["Ó"]=>
string(8) "&Oacute;"
["Ô"]=>
string(7) "&Ocirc;"
+ ["Ã’"]=>
+ string(8) "&Ograve;"
+ ["Ω"]=>
+ string(7) "&Omega;"
+ ["Ο"]=>
+ string(9) "&Omicron;"
+ ["Ø"]=>
+ string(8) "&Oslash;"
["Õ"]=>
string(8) "&Otilde;"
["Ö"]=>
string(6) "&Ouml;"
- ["×"]=>
- string(7) "&times;"
- ["Ø"]=>
- string(8) "&Oslash;"
- ["Ù"]=>
- string(8) "&Ugrave;"
+ ["Φ"]=>
+ string(5) "&Phi;"
+ ["Π"]=>
+ string(4) "&Pi;"
+ ["″"]=>
+ string(7) "&Prime;"
+ ["Ψ"]=>
+ string(5) "&Psi;"
+ ["Ρ"]=>
+ string(5) "&Rho;"
+ ["Å "]=>
+ string(8) "&Scaron;"
+ ["Σ"]=>
+ string(7) "&Sigma;"
+ ["Þ"]=>
+ string(7) "&THORN;"
+ ["Τ"]=>
+ string(5) "&Tau;"
+ ["Θ"]=>
+ string(7) "&Theta;"
["Ú"]=>
string(8) "&Uacute;"
["Û"]=>
string(7) "&Ucirc;"
+ ["Ù"]=>
+ string(8) "&Ugrave;"
+ ["Î¥"]=>
+ string(9) "&Upsilon;"
["Ü"]=>
string(6) "&Uuml;"
+ ["Ξ"]=>
+ string(4) "&Xi;"
["Ã"]=>
string(8) "&Yacute;"
- ["Þ"]=>
- string(7) "&THORN;"
- ["ß"]=>
- string(7) "&szlig;"
- ["à"]=>
- string(8) "&agrave;"
+ ["Ÿ"]=>
+ string(6) "&Yuml;"
+ ["Ζ"]=>
+ string(6) "&Zeta;"
["á"]=>
string(8) "&aacute;"
["â"]=>
string(7) "&acirc;"
+ ["´"]=>
+ string(7) "&acute;"
+ ["æ"]=>
+ string(7) "&aelig;"
+ ["à"]=>
+ string(8) "&agrave;"
+ ["ℵ"]=>
+ string(9) "&alefsym;"
+ ["α"]=>
+ string(7) "&alpha;"
+ ["&"]=>
+ string(5) "&amp;"
+ ["∧"]=>
+ string(5) "&and;"
+ ["∠"]=>
+ string(5) "&ang;"
+ ["Ã¥"]=>
+ string(7) "&aring;"
+ ["≈"]=>
+ string(7) "&asymp;"
["ã"]=>
string(8) "&atilde;"
["ä"]=>
string(6) "&auml;"
- ["Ã¥"]=>
- string(7) "&aring;"
- ["æ"]=>
- string(7) "&aelig;"
+ ["„"]=>
+ string(7) "&bdquo;"
+ ["β"]=>
+ string(6) "&beta;"
+ ["¦"]=>
+ string(8) "&brvbar;"
+ ["•"]=>
+ string(6) "&bull;"
+ ["∩"]=>
+ string(5) "&cap;"
["ç"]=>
string(8) "&ccedil;"
- ["è"]=>
- string(8) "&egrave;"
+ ["¸"]=>
+ string(7) "&cedil;"
+ ["¢"]=>
+ string(6) "&cent;"
+ ["χ"]=>
+ string(5) "&chi;"
+ ["ˆ"]=>
+ string(6) "&circ;"
+ ["♣"]=>
+ string(7) "&clubs;"
+ ["≅"]=>
+ string(6) "&cong;"
+ ["©"]=>
+ string(6) "&copy;"
+ ["↵"]=>
+ string(7) "&crarr;"
+ ["∪"]=>
+ string(5) "&cup;"
+ ["¤"]=>
+ string(8) "&curren;"
+ ["⇓"]=>
+ string(6) "&dArr;"
+ ["†"]=>
+ string(8) "&dagger;"
+ ["↓"]=>
+ string(6) "&darr;"
+ ["°"]=>
+ string(5) "&deg;"
+ ["δ"]=>
+ string(7) "&delta;"
+ ["♦"]=>
+ string(7) "&diams;"
+ ["÷"]=>
+ string(8) "&divide;"
["é"]=>
string(8) "&eacute;"
["ê"]=>
string(7) "&ecirc;"
- ["ë"]=>
- string(6) "&euml;"
- ["ì"]=>
- string(8) "&igrave;"
- ["í"]=>
- string(8) "&iacute;"
- ["î"]=>
- string(7) "&icirc;"
- ["ï"]=>
- string(6) "&iuml;"
+ ["è"]=>
+ string(8) "&egrave;"
+ ["∅"]=>
+ string(7) "&empty;"
+ [" "]=>
+ string(6) "&emsp;"
+ [" "]=>
+ string(6) "&ensp;"
+ ["ε"]=>
+ string(9) "&epsilon;"
+ ["≡"]=>
+ string(7) "&equiv;"
+ ["η"]=>
+ string(5) "&eta;"
["ð"]=>
string(5) "&eth;"
- ["ñ"]=>
- string(8) "&ntilde;"
- ["ò"]=>
- string(8) "&ograve;"
- ["ó"]=>
- string(8) "&oacute;"
- ["ô"]=>
- string(7) "&ocirc;"
- ["õ"]=>
- string(8) "&otilde;"
- ["ö"]=>
- string(6) "&ouml;"
- ["÷"]=>
- string(8) "&divide;"
- ["ø"]=>
- string(8) "&oslash;"
- ["ù"]=>
- string(8) "&ugrave;"
- ["ú"]=>
- string(8) "&uacute;"
- ["û"]=>
- string(7) "&ucirc;"
- ["ü"]=>
- string(6) "&uuml;"
- ["ý"]=>
- string(8) "&yacute;"
- ["þ"]=>
- string(7) "&thorn;"
- ["ÿ"]=>
- string(6) "&yuml;"
- ["Å’"]=>
- string(7) "&OElig;"
- ["Å“"]=>
- string(7) "&oelig;"
- ["Å "]=>
- string(8) "&Scaron;"
- ["Å¡"]=>
- string(8) "&scaron;"
- ["Ÿ"]=>
- string(6) "&Yuml;"
+ ["ë"]=>
+ string(6) "&euml;"
+ ["€"]=>
+ string(6) "&euro;"
+ ["∃"]=>
+ string(7) "&exist;"
["Æ’"]=>
string(6) "&fnof;"
- ["ˆ"]=>
- string(6) "&circ;"
- ["˜"]=>
- string(7) "&tilde;"
- ["Α"]=>
- string(7) "&Alpha;"
- ["Î’"]=>
- string(6) "&Beta;"
- ["Γ"]=>
- string(7) "&Gamma;"
- ["Δ"]=>
- string(7) "&Delta;"
- ["Ε"]=>
- string(9) "&Epsilon;"
- ["Ζ"]=>
- string(6) "&Zeta;"
- ["Η"]=>
- string(5) "&Eta;"
- ["Θ"]=>
- string(7) "&Theta;"
- ["Ι"]=>
- string(6) "&Iota;"
- ["Κ"]=>
- string(7) "&Kappa;"
- ["Λ"]=>
- string(8) "&Lambda;"
- ["Μ"]=>
- string(4) "&Mu;"
- ["Î"]=>
- string(4) "&Nu;"
- ["Ξ"]=>
- string(4) "&Xi;"
- ["Ο"]=>
- string(9) "&Omicron;"
- ["Π"]=>
- string(4) "&Pi;"
- ["Ρ"]=>
- string(5) "&Rho;"
- ["Σ"]=>
- string(7) "&Sigma;"
- ["Τ"]=>
- string(5) "&Tau;"
- ["Î¥"]=>
- string(9) "&Upsilon;"
- ["Φ"]=>
- string(5) "&Phi;"
- ["Χ"]=>
- string(5) "&Chi;"
- ["Ψ"]=>
- string(5) "&Psi;"
- ["Ω"]=>
- string(7) "&Omega;"
- ["α"]=>
- string(7) "&alpha;"
- ["β"]=>
- string(6) "&beta;"
+ ["∀"]=>
+ string(8) "&forall;"
+ ["½"]=>
+ string(8) "&frac12;"
+ ["¼"]=>
+ string(8) "&frac14;"
+ ["¾"]=>
+ string(8) "&frac34;"
+ ["â„"]=>
+ string(7) "&frasl;"
["γ"]=>
string(7) "&gamma;"
- ["δ"]=>
- string(7) "&delta;"
- ["ε"]=>
- string(9) "&epsilon;"
- ["ζ"]=>
- string(6) "&zeta;"
- ["η"]=>
- string(5) "&eta;"
- ["θ"]=>
- string(7) "&theta;"
+ ["≥"]=>
+ string(4) "&ge;"
+ [">"]=>
+ string(4) "&gt;"
+ ["⇔"]=>
+ string(6) "&hArr;"
+ ["↔"]=>
+ string(6) "&harr;"
+ ["♥"]=>
+ string(8) "&hearts;"
+ ["…"]=>
+ string(8) "&hellip;"
+ ["í"]=>
+ string(8) "&iacute;"
+ ["î"]=>
+ string(7) "&icirc;"
+ ["¡"]=>
+ string(7) "&iexcl;"
+ ["ì"]=>
+ string(8) "&igrave;"
+ ["â„‘"]=>
+ string(7) "&image;"
+ ["∞"]=>
+ string(7) "&infin;"
+ ["∫"]=>
+ string(5) "&int;"
["ι"]=>
string(6) "&iota;"
+ ["¿"]=>
+ string(8) "&iquest;"
+ ["∈"]=>
+ string(6) "&isin;"
+ ["ï"]=>
+ string(6) "&iuml;"
["κ"]=>
string(7) "&kappa;"
+ ["â‡"]=>
+ string(6) "&lArr;"
["λ"]=>
string(8) "&lambda;"
+ ["〈"]=>
+ string(6) "&lang;"
+ ["«"]=>
+ string(7) "&laquo;"
+ ["â†"]=>
+ string(6) "&larr;"
+ ["⌈"]=>
+ string(7) "&lceil;"
+ ["“"]=>
+ string(7) "&ldquo;"
+ ["≤"]=>
+ string(4) "&le;"
+ ["⌊"]=>
+ string(8) "&lfloor;"
+ ["∗"]=>
+ string(8) "&lowast;"
+ ["â—Š"]=>
+ string(5) "&loz;"
+ ["‎"]=>
+ string(5) "&lrm;"
+ ["‹"]=>
+ string(8) "&lsaquo;"
+ ["‘"]=>
+ string(7) "&lsquo;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["¯"]=>
+ string(6) "&macr;"
+ ["—"]=>
+ string(7) "&mdash;"
+ ["µ"]=>
+ string(7) "&micro;"
+ ["·"]=>
+ string(8) "&middot;"
+ ["−"]=>
+ string(7) "&minus;"
["μ"]=>
string(4) "&mu;"
+ ["∇"]=>
+ string(7) "&nabla;"
+ [" "]=>
+ string(6) "&nbsp;"
+ ["–"]=>
+ string(7) "&ndash;"
+ ["≠"]=>
+ string(4) "&ne;"
+ ["∋"]=>
+ string(4) "&ni;"
+ ["¬"]=>
+ string(5) "&not;"
+ ["∉"]=>
+ string(7) "&notin;"
+ ["⊄"]=>
+ string(6) "&nsub;"
+ ["ñ"]=>
+ string(8) "&ntilde;"
["ν"]=>
string(4) "&nu;"
- ["ξ"]=>
- string(4) "&xi;"
+ ["ó"]=>
+ string(8) "&oacute;"
+ ["ô"]=>
+ string(7) "&ocirc;"
+ ["Å“"]=>
+ string(7) "&oelig;"
+ ["ò"]=>
+ string(8) "&ograve;"
+ ["‾"]=>
+ string(7) "&oline;"
+ ["ω"]=>
+ string(7) "&omega;"
["ο"]=>
string(9) "&omicron;"
- ["Ï€"]=>
- string(4) "&pi;"
- ["Ï"]=>
- string(5) "&rho;"
- ["Ï‚"]=>
- string(8) "&sigmaf;"
- ["σ"]=>
- string(7) "&sigma;"
- ["Ï„"]=>
- string(5) "&tau;"
- ["Ï…"]=>
- string(9) "&upsilon;"
+ ["⊕"]=>
+ string(7) "&oplus;"
+ ["∨"]=>
+ string(4) "&or;"
+ ["ª"]=>
+ string(6) "&ordf;"
+ ["º"]=>
+ string(6) "&ordm;"
+ ["ø"]=>
+ string(8) "&oslash;"
+ ["õ"]=>
+ string(8) "&otilde;"
+ ["⊗"]=>
+ string(8) "&otimes;"
+ ["ö"]=>
+ string(6) "&ouml;"
+ ["¶"]=>
+ string(6) "&para;"
+ ["∂"]=>
+ string(6) "&part;"
+ ["‰"]=>
+ string(8) "&permil;"
+ ["⊥"]=>
+ string(6) "&perp;"
["φ"]=>
string(5) "&phi;"
- ["χ"]=>
- string(5) "&chi;"
- ["ψ"]=>
- string(5) "&psi;"
- ["ω"]=>
- string(7) "&omega;"
- ["Ï‘"]=>
- string(10) "&thetasym;"
- ["Ï’"]=>
- string(7) "&upsih;"
+ ["Ï€"]=>
+ string(4) "&pi;"
["Ï–"]=>
string(5) "&piv;"
- [" "]=>
- string(6) "&ensp;"
- [" "]=>
- string(6) "&emsp;"
- [" "]=>
- string(8) "&thinsp;"
- ["‌"]=>
- string(6) "&zwnj;"
- ["â€"]=>
- string(5) "&zwj;"
- ["‎"]=>
- string(5) "&lrm;"
- ["â€"]=>
- string(5) "&rlm;"
- ["–"]=>
- string(7) "&ndash;"
- ["—"]=>
- string(7) "&mdash;"
- ["‘"]=>
- string(7) "&lsquo;"
- ["’"]=>
- string(7) "&rsquo;"
- ["‚"]=>
- string(7) "&sbquo;"
- ["“"]=>
- string(7) "&ldquo;"
- ["â€"]=>
- string(7) "&rdquo;"
- ["„"]=>
- string(7) "&bdquo;"
- ["†"]=>
- string(8) "&dagger;"
- ["‡"]=>
- string(8) "&Dagger;"
- ["•"]=>
- string(6) "&bull;"
- ["…"]=>
- string(8) "&hellip;"
- ["‰"]=>
- string(8) "&permil;"
+ ["±"]=>
+ string(8) "&plusmn;"
+ ["£"]=>
+ string(7) "&pound;"
["′"]=>
string(7) "&prime;"
- ["″"]=>
- string(7) "&Prime;"
- ["‹"]=>
- string(8) "&lsaquo;"
- ["›"]=>
- string(8) "&rsaquo;"
- ["‾"]=>
- string(7) "&oline;"
- ["â„"]=>
- string(7) "&frasl;"
- ["€"]=>
- string(6) "&euro;"
- ["â„‘"]=>
- string(7) "&image;"
- ["℘"]=>
- string(8) "&weierp;"
- ["ℜ"]=>
- string(6) "&real;"
- ["â„¢"]=>
- string(7) "&trade;"
- ["ℵ"]=>
- string(9) "&alefsym;"
- ["â†"]=>
- string(6) "&larr;"
- ["↑"]=>
- string(6) "&uarr;"
- ["→"]=>
- string(6) "&rarr;"
- ["↓"]=>
- string(6) "&darr;"
- ["↔"]=>
- string(6) "&harr;"
- ["↵"]=>
- string(7) "&crarr;"
- ["â‡"]=>
- string(6) "&lArr;"
- ["⇑"]=>
- string(6) "&uArr;"
- ["⇒"]=>
- string(6) "&rArr;"
- ["⇓"]=>
- string(6) "&dArr;"
- ["⇔"]=>
- string(6) "&hArr;"
- ["∀"]=>
- string(8) "&forall;"
- ["∂"]=>
- string(6) "&part;"
- ["∃"]=>
- string(7) "&exist;"
- ["∅"]=>
- string(7) "&empty;"
- ["∇"]=>
- string(7) "&nabla;"
- ["∈"]=>
- string(6) "&isin;"
- ["∉"]=>
- string(7) "&notin;"
- ["∋"]=>
- string(4) "&ni;"
["âˆ"]=>
string(6) "&prod;"
- ["∑"]=>
- string(5) "&sum;"
- ["−"]=>
- string(7) "&minus;"
- ["∗"]=>
- string(8) "&lowast;"
- ["√"]=>
- string(7) "&radic;"
["âˆ"]=>
string(6) "&prop;"
- ["∞"]=>
- string(7) "&infin;"
- ["∠"]=>
- string(5) "&ang;"
- ["∧"]=>
- string(5) "&and;"
- ["∨"]=>
- string(4) "&or;"
- ["∩"]=>
- string(5) "&cap;"
- ["∪"]=>
- string(5) "&cup;"
- ["∫"]=>
- string(5) "&int;"
- ["∴"]=>
- string(8) "&there4;"
+ ["ψ"]=>
+ string(5) "&psi;"
+ ["⇒"]=>
+ string(6) "&rArr;"
+ ["√"]=>
+ string(7) "&radic;"
+ ["〉"]=>
+ string(6) "&rang;"
+ ["»"]=>
+ string(7) "&raquo;"
+ ["→"]=>
+ string(6) "&rarr;"
+ ["⌉"]=>
+ string(7) "&rceil;"
+ ["â€"]=>
+ string(7) "&rdquo;"
+ ["ℜ"]=>
+ string(6) "&real;"
+ ["®"]=>
+ string(5) "&reg;"
+ ["⌋"]=>
+ string(8) "&rfloor;"
+ ["Ï"]=>
+ string(5) "&rho;"
+ ["â€"]=>
+ string(5) "&rlm;"
+ ["›"]=>
+ string(8) "&rsaquo;"
+ ["’"]=>
+ string(7) "&rsquo;"
+ ["‚"]=>
+ string(7) "&sbquo;"
+ ["Å¡"]=>
+ string(8) "&scaron;"
+ ["â‹…"]=>
+ string(6) "&sdot;"
+ ["§"]=>
+ string(6) "&sect;"
+ ["­"]=>
+ string(5) "&shy;"
+ ["σ"]=>
+ string(7) "&sigma;"
+ ["Ï‚"]=>
+ string(8) "&sigmaf;"
["∼"]=>
string(5) "&sim;"
- ["≅"]=>
- string(6) "&cong;"
- ["≈"]=>
- string(7) "&asymp;"
- ["≠"]=>
- string(4) "&ne;"
- ["≡"]=>
- string(7) "&equiv;"
- ["≤"]=>
- string(4) "&le;"
- ["≥"]=>
- string(4) "&ge;"
+ ["â™ "]=>
+ string(8) "&spades;"
["⊂"]=>
string(5) "&sub;"
- ["⊃"]=>
- string(5) "&sup;"
- ["⊄"]=>
- string(6) "&nsub;"
["⊆"]=>
string(6) "&sube;"
+ ["∑"]=>
+ string(5) "&sum;"
+ ["¹"]=>
+ string(6) "&sup1;"
+ ["²"]=>
+ string(6) "&sup2;"
+ ["³"]=>
+ string(6) "&sup3;"
+ ["⊃"]=>
+ string(5) "&sup;"
["⊇"]=>
string(6) "&supe;"
- ["⊕"]=>
- string(7) "&oplus;"
- ["⊗"]=>
- string(8) "&otimes;"
- ["⊥"]=>
- string(6) "&perp;"
- ["â‹…"]=>
- string(6) "&sdot;"
- ["⌈"]=>
- string(7) "&lceil;"
- ["⌉"]=>
- string(7) "&rceil;"
- ["⌊"]=>
- string(8) "&lfloor;"
- ["⌋"]=>
- string(8) "&rfloor;"
- ["〈"]=>
- string(6) "&lang;"
- ["〉"]=>
- string(6) "&rang;"
- ["â—Š"]=>
- string(5) "&loz;"
- ["â™ "]=>
- string(8) "&spades;"
- ["♣"]=>
- string(7) "&clubs;"
- ["♥"]=>
- string(8) "&hearts;"
- ["♦"]=>
- string(7) "&diams;"
- ["&"]=>
- string(5) "&amp;"
- ["<"]=>
- string(4) "&lt;"
- [">"]=>
- string(4) "&gt;"
+ ["ß"]=>
+ string(7) "&szlig;"
+ ["Ï„"]=>
+ string(5) "&tau;"
+ ["∴"]=>
+ string(8) "&there4;"
+ ["θ"]=>
+ string(7) "&theta;"
+ ["Ï‘"]=>
+ string(10) "&thetasym;"
+ [" "]=>
+ string(8) "&thinsp;"
+ ["þ"]=>
+ string(7) "&thorn;"
+ ["˜"]=>
+ string(7) "&tilde;"
+ ["×"]=>
+ string(7) "&times;"
+ ["â„¢"]=>
+ string(7) "&trade;"
+ ["⇑"]=>
+ string(6) "&uArr;"
+ ["ú"]=>
+ string(8) "&uacute;"
+ ["↑"]=>
+ string(6) "&uarr;"
+ ["û"]=>
+ string(7) "&ucirc;"
+ ["ù"]=>
+ string(8) "&ugrave;"
+ ["¨"]=>
+ string(5) "&uml;"
+ ["Ï’"]=>
+ string(7) "&upsih;"
+ ["Ï…"]=>
+ string(9) "&upsilon;"
+ ["ü"]=>
+ string(6) "&uuml;"
+ ["℘"]=>
+ string(8) "&weierp;"
+ ["ξ"]=>
+ string(4) "&xi;"
+ ["ý"]=>
+ string(8) "&yacute;"
+ ["Â¥"]=>
+ string(5) "&yen;"
+ ["ÿ"]=>
+ string(6) "&yuml;"
+ ["ζ"]=>
+ string(6) "&zeta;"
+ ["â€"]=>
+ string(5) "&zwj;"
+ ["‌"]=>
+ string(6) "&zwnj;"
}
Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic3.phpt b/ext/standard/tests/strings/get_html_translation_table_basic3.phpt
index e7c66b5b09..4e1cdddd29 100644
--- a/ext/standard/tests/strings/get_html_translation_table_basic3.phpt
+++ b/ext/standard/tests/strings/get_html_translation_table_basic3.phpt
@@ -15,15 +15,21 @@ echo "*** Testing get_html_translation_table() : basic functionality ***\n";
echo "-- with table = HTML_SPECIALCHARS & quote_style = ENT_COMPAT --\n";
$table = HTML_SPECIALCHARS;
$quote_style = ENT_COMPAT;
-var_dump( get_html_translation_table($table, $quote_style, "UTF-8") );
+$tt = get_html_translation_table($table, $quote_style, "UTF-8");
+asort( $tt );
+var_dump( $tt );
echo "-- with table = HTML_SPECIALCHARS & quote_style = ENT_QUOTES --\n";
$quote_style = ENT_QUOTES;
-var_dump( get_html_translation_table($table, $quote_style, "UTF-8") );
+$tt = get_html_translation_table($table, $quote_style, "UTF-8");
+asort( $tt );
+var_dump( $tt );
echo "-- with table = HTML_SPECIALCHARS & quote_style = ENT_NOQUOTES --\n";
$quote_style = ENT_NOQUOTES;
-var_dump( get_html_translation_table($table, $quote_style, "UTF-8") );
+$tt = get_html_translation_table($table, $quote_style, "UTF-8");
+asort( $tt );
+var_dump( $tt );
echo "Done\n";
?>
@@ -33,33 +39,33 @@ echo "Done\n";
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- with table = HTML_SPECIALCHARS & quote_style = ENT_QUOTES --
array(5) {
- ["&"]=>
- string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
["'"]=>
string(6) "&#039;"
- ["<"]=>
- string(4) "&lt;"
+ ["&"]=>
+ string(5) "&amp;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- with table = HTML_SPECIALCHARS & quote_style = ENT_NOQUOTES --
array(3) {
["&"]=>
string(5) "&amp;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
}
Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic4.phpt b/ext/standard/tests/strings/get_html_translation_table_basic4.phpt
index 938fff4f5c..1a908efdb4 100644
--- a/ext/standard/tests/strings/get_html_translation_table_basic4.phpt
+++ b/ext/standard/tests/strings/get_html_translation_table_basic4.phpt
@@ -12,11 +12,15 @@ echo "*** Testing get_html_translation_table() : basic functionality/Windows-125
echo "-- with table = HTML_ENTITIES --\n";
$table = HTML_ENTITIES;
-var_dump( get_html_translation_table($table, ENT_COMPAT, "WINDOWS-1252") );
+$tt = get_html_translation_table($table, ENT_COMPAT, "WINDOWS-1252");
+asort( $tt );
+var_dump( $tt );
echo "-- with table = HTML_SPECIALCHARS --\n";
$table = HTML_SPECIALCHARS;
-var_dump( get_html_translation_table($table, ENT_COMPAT, "WINDOWS-1252") );
+$tt = get_html_translation_table($table, ENT_COMPAT, "WINDOWS-1252");
+asort( $tt );
+var_dump( $tt );
echo "Done\n";
?>
@@ -24,266 +28,266 @@ echo "Done\n";
*** Testing get_html_translation_table() : basic functionality/Windows-1252 ***
-- with table = HTML_ENTITIES --
array(125) {
- ["€"]=>
- string(6) "&euro;"
- ["‚"]=>
- string(7) "&sbquo;"
- ["ƒ"]=>
- string(6) "&fnof;"
- ["„"]=>
- string(7) "&bdquo;"
- ["…"]=>
- string(8) "&hellip;"
- ["†"]=>
- string(8) "&dagger;"
- ["‡"]=>
- string(8) "&Dagger;"
- ["ˆ"]=>
- string(6) "&circ;"
- ["‰"]=>
- string(8) "&permil;"
- ["Š"]=>
- string(8) "&Scaron;"
- ["‹"]=>
- string(8) "&lsaquo;"
- ["Œ"]=>
- string(7) "&OElig;"
- ["‘"]=>
- string(7) "&lsquo;"
- ["’"]=>
- string(7) "&rsquo;"
- ["“"]=>
- string(7) "&ldquo;"
- ["”"]=>
- string(7) "&rdquo;"
- ["•"]=>
- string(6) "&bull;"
- ["–"]=>
- string(7) "&ndash;"
- ["—"]=>
- string(7) "&mdash;"
- ["˜"]=>
- string(7) "&tilde;"
- ["™"]=>
- string(7) "&trade;"
- ["š"]=>
- string(8) "&scaron;"
- ["›"]=>
- string(8) "&rsaquo;"
- ["œ"]=>
- string(7) "&oelig;"
- ["Ÿ"]=>
- string(6) "&Yuml;"
- [" "]=>
- string(6) "&nbsp;"
- ["¡"]=>
- string(7) "&iexcl;"
- ["¢"]=>
- string(6) "&cent;"
- ["£"]=>
- string(7) "&pound;"
- ["¤"]=>
- string(8) "&curren;"
- ["¥"]=>
- string(5) "&yen;"
- ["¦"]=>
- string(8) "&brvbar;"
- ["§"]=>
- string(6) "&sect;"
- ["¨"]=>
- string(5) "&uml;"
- ["©"]=>
- string(6) "&copy;"
- ["ª"]=>
- string(6) "&ordf;"
- ["«"]=>
- string(7) "&laquo;"
- ["¬"]=>
- string(5) "&not;"
- ["­"]=>
- string(5) "&shy;"
- ["®"]=>
- string(5) "&reg;"
- ["¯"]=>
- string(6) "&macr;"
- ["°"]=>
- string(5) "&deg;"
- ["±"]=>
- string(8) "&plusmn;"
- ["²"]=>
- string(6) "&sup2;"
- ["³"]=>
- string(6) "&sup3;"
- ["´"]=>
- string(7) "&acute;"
- ["µ"]=>
- string(7) "&micro;"
- ["¶"]=>
- string(6) "&para;"
- ["·"]=>
- string(8) "&middot;"
- ["¸"]=>
- string(7) "&cedil;"
- ["¹"]=>
- string(6) "&sup1;"
- ["º"]=>
- string(6) "&ordm;"
- ["»"]=>
- string(7) "&raquo;"
- ["¼"]=>
- string(8) "&frac14;"
- ["½"]=>
- string(8) "&frac12;"
- ["¾"]=>
- string(8) "&frac34;"
- ["¿"]=>
- string(8) "&iquest;"
- ["À"]=>
- string(8) "&Agrave;"
+ ["Æ"]=>
+ string(7) "&AElig;"
["Á"]=>
string(8) "&Aacute;"
["Â"]=>
string(7) "&Acirc;"
+ ["À"]=>
+ string(8) "&Agrave;"
+ ["Å"]=>
+ string(7) "&Aring;"
["Ã"]=>
string(8) "&Atilde;"
["Ä"]=>
string(6) "&Auml;"
- ["Å"]=>
- string(7) "&Aring;"
- ["Æ"]=>
- string(7) "&AElig;"
["Ç"]=>
string(8) "&Ccedil;"
- ["È"]=>
- string(8) "&Egrave;"
+ ["‡"]=>
+ string(8) "&Dagger;"
+ ["Ð"]=>
+ string(5) "&ETH;"
["É"]=>
string(8) "&Eacute;"
["Ê"]=>
string(7) "&Ecirc;"
+ ["È"]=>
+ string(8) "&Egrave;"
["Ë"]=>
string(6) "&Euml;"
- ["Ì"]=>
- string(8) "&Igrave;"
["Í"]=>
string(8) "&Iacute;"
["Î"]=>
string(7) "&Icirc;"
+ ["Ì"]=>
+ string(8) "&Igrave;"
["Ï"]=>
string(6) "&Iuml;"
- ["Ð"]=>
- string(5) "&ETH;"
["Ñ"]=>
string(8) "&Ntilde;"
- ["Ò"]=>
- string(8) "&Ograve;"
+ ["Œ"]=>
+ string(7) "&OElig;"
["Ó"]=>
string(8) "&Oacute;"
["Ô"]=>
string(7) "&Ocirc;"
+ ["Ò"]=>
+ string(8) "&Ograve;"
+ ["Ø"]=>
+ string(8) "&Oslash;"
["Õ"]=>
string(8) "&Otilde;"
["Ö"]=>
string(6) "&Ouml;"
- ["×"]=>
- string(7) "&times;"
- ["Ø"]=>
- string(8) "&Oslash;"
- ["Ù"]=>
- string(8) "&Ugrave;"
+ ["Š"]=>
+ string(8) "&Scaron;"
+ ["Þ"]=>
+ string(7) "&THORN;"
["Ú"]=>
string(8) "&Uacute;"
["Û"]=>
string(7) "&Ucirc;"
+ ["Ù"]=>
+ string(8) "&Ugrave;"
["Ü"]=>
string(6) "&Uuml;"
["Ý"]=>
string(8) "&Yacute;"
- ["Þ"]=>
- string(7) "&THORN;"
- ["ß"]=>
- string(7) "&szlig;"
- ["à"]=>
- string(8) "&agrave;"
+ ["Ÿ"]=>
+ string(6) "&Yuml;"
["á"]=>
string(8) "&aacute;"
["â"]=>
string(7) "&acirc;"
+ ["´"]=>
+ string(7) "&acute;"
+ ["æ"]=>
+ string(7) "&aelig;"
+ ["à"]=>
+ string(8) "&agrave;"
+ ["&"]=>
+ string(5) "&amp;"
+ ["å"]=>
+ string(7) "&aring;"
["ã"]=>
string(8) "&atilde;"
["ä"]=>
string(6) "&auml;"
- ["å"]=>
- string(7) "&aring;"
- ["æ"]=>
- string(7) "&aelig;"
+ ["„"]=>
+ string(7) "&bdquo;"
+ ["¦"]=>
+ string(8) "&brvbar;"
+ ["•"]=>
+ string(6) "&bull;"
["ç"]=>
string(8) "&ccedil;"
- ["è"]=>
- string(8) "&egrave;"
+ ["¸"]=>
+ string(7) "&cedil;"
+ ["¢"]=>
+ string(6) "&cent;"
+ ["ˆ"]=>
+ string(6) "&circ;"
+ ["©"]=>
+ string(6) "&copy;"
+ ["¤"]=>
+ string(8) "&curren;"
+ ["†"]=>
+ string(8) "&dagger;"
+ ["°"]=>
+ string(5) "&deg;"
+ ["÷"]=>
+ string(8) "&divide;"
["é"]=>
string(8) "&eacute;"
["ê"]=>
string(7) "&ecirc;"
+ ["è"]=>
+ string(8) "&egrave;"
+ ["ð"]=>
+ string(5) "&eth;"
["ë"]=>
string(6) "&euml;"
- ["ì"]=>
- string(8) "&igrave;"
+ ["€"]=>
+ string(6) "&euro;"
+ ["ƒ"]=>
+ string(6) "&fnof;"
+ ["½"]=>
+ string(8) "&frac12;"
+ ["¼"]=>
+ string(8) "&frac14;"
+ ["¾"]=>
+ string(8) "&frac34;"
+ [">"]=>
+ string(4) "&gt;"
+ ["…"]=>
+ string(8) "&hellip;"
["í"]=>
string(8) "&iacute;"
["î"]=>
string(7) "&icirc;"
+ ["¡"]=>
+ string(7) "&iexcl;"
+ ["ì"]=>
+ string(8) "&igrave;"
+ ["¿"]=>
+ string(8) "&iquest;"
["ï"]=>
string(6) "&iuml;"
- ["ð"]=>
- string(5) "&eth;"
+ ["«"]=>
+ string(7) "&laquo;"
+ ["“"]=>
+ string(7) "&ldquo;"
+ ["‹"]=>
+ string(8) "&lsaquo;"
+ ["‘"]=>
+ string(7) "&lsquo;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["¯"]=>
+ string(6) "&macr;"
+ ["—"]=>
+ string(7) "&mdash;"
+ ["µ"]=>
+ string(7) "&micro;"
+ ["·"]=>
+ string(8) "&middot;"
+ [" "]=>
+ string(6) "&nbsp;"
+ ["–"]=>
+ string(7) "&ndash;"
+ ["¬"]=>
+ string(5) "&not;"
["ñ"]=>
string(8) "&ntilde;"
- ["ò"]=>
- string(8) "&ograve;"
["ó"]=>
string(8) "&oacute;"
["ô"]=>
string(7) "&ocirc;"
+ ["œ"]=>
+ string(7) "&oelig;"
+ ["ò"]=>
+ string(8) "&ograve;"
+ ["ª"]=>
+ string(6) "&ordf;"
+ ["º"]=>
+ string(6) "&ordm;"
+ ["ø"]=>
+ string(8) "&oslash;"
["õ"]=>
string(8) "&otilde;"
["ö"]=>
string(6) "&ouml;"
- ["÷"]=>
- string(8) "&divide;"
- ["ø"]=>
- string(8) "&oslash;"
- ["ù"]=>
- string(8) "&ugrave;"
+ ["¶"]=>
+ string(6) "&para;"
+ ["‰"]=>
+ string(8) "&permil;"
+ ["±"]=>
+ string(8) "&plusmn;"
+ ["£"]=>
+ string(7) "&pound;"
+ ["""]=>
+ string(6) "&quot;"
+ ["»"]=>
+ string(7) "&raquo;"
+ ["”"]=>
+ string(7) "&rdquo;"
+ ["®"]=>
+ string(5) "&reg;"
+ ["›"]=>
+ string(8) "&rsaquo;"
+ ["’"]=>
+ string(7) "&rsquo;"
+ ["‚"]=>
+ string(7) "&sbquo;"
+ ["š"]=>
+ string(8) "&scaron;"
+ ["§"]=>
+ string(6) "&sect;"
+ ["­"]=>
+ string(5) "&shy;"
+ ["¹"]=>
+ string(6) "&sup1;"
+ ["²"]=>
+ string(6) "&sup2;"
+ ["³"]=>
+ string(6) "&sup3;"
+ ["ß"]=>
+ string(7) "&szlig;"
+ ["þ"]=>
+ string(7) "&thorn;"
+ ["˜"]=>
+ string(7) "&tilde;"
+ ["×"]=>
+ string(7) "&times;"
+ ["™"]=>
+ string(7) "&trade;"
["ú"]=>
string(8) "&uacute;"
["û"]=>
string(7) "&ucirc;"
+ ["ù"]=>
+ string(8) "&ugrave;"
+ ["¨"]=>
+ string(5) "&uml;"
["ü"]=>
string(6) "&uuml;"
["ý"]=>
string(8) "&yacute;"
- ["þ"]=>
- string(7) "&thorn;"
+ ["¥"]=>
+ string(5) "&yen;"
["ÿ"]=>
string(6) "&yuml;"
- ["&"]=>
- string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
- [">"]=>
- string(4) "&gt;"
}
-- with table = HTML_SPECIALCHARS --
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic5.phpt b/ext/standard/tests/strings/get_html_translation_table_basic5.phpt
new file mode 100644
index 0000000000..600ad43635
--- /dev/null
+++ b/ext/standard/tests/strings/get_html_translation_table_basic5.phpt
@@ -0,0 +1,1598 @@
+--TEST--
+Test get_html_translation_table() function : basic functionality - HTML 5
+--FILE--
+<?php
+echo "*** Testing get_html_translation_table() : basic functionality/HTML 5 ***\n";
+
+echo "-- with table = HTML_ENTITIES, ENT_COMPAT --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_COMPAT | ENT_HTML5, "UTF-8");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_ENTITIES, ENT_QUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_HTML5, "UTF-8");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_ENTITIES, ENT_NOQUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_HTML5, "UTF-8");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_COMPAT --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_COMPAT, "UTF-8");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_QUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_HTML5, "UTF-8");
+asort( $tt );
+var_dump( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_HTML5, "UTF-8");
+asort( $tt );
+var_dump( $tt );
+
+
+echo "Done\n";
+?>
+--EXPECT--
+*** Testing get_html_translation_table() : basic functionality/HTML 5 ***
+-- with table = HTML_ENTITIES, ENT_COMPAT --
+int(1509)
+Array
+(
+ [Æ] => &AElig;
+ [Ã] => &Aacute;
+ [Ä‚] => &Abreve;
+ [Â] => &Acirc;
+ [Ð] => &Acy;
+ [ð”„] => &Afr;
+ [À] => &Agrave;
+ [Α] => &Alpha;
+ [Ä€] => &Amacr;
+ [â©“] => &And;
+ [Ä„] => &Aogon;
+ [ð”¸] => &Aopf;
+ [Ã…] => &Aring;
+ [ð’œ] => &Ascr;
+ [Ã] => &Atilde;
+ [Ä] => &Auml;
+ [⫧] => &Barv;
+ [Б] => &Bcy;
+ [∵] => &Because;
+ [Î’] => &Beta;
+ [ð”…] => &Bfr;
+ [ð”¹] => &Bopf;
+ [˘] => &Breve;
+ [ℬ] => &Bscr;
+ [Ч] => &CHcy;
+ [Ć] => &Cacute;
+ [â‹’] => &Cap;
+ [â……] => &CapitalDifferentialD;
+ [Č] => &Ccaron;
+ [Ç] => &Ccedil;
+ [Ĉ] => &Ccirc;
+ [∰] => &Cconint;
+ [ÄŠ] => &Cdot;
+ [¸] => &Cedilla;
+ [·] => &CenterDot;
+ [â„­] => &Cfr;
+ [Χ] => &Chi;
+ [⊙] => &CircleDot;
+ [⊕] => &CirclePlus;
+ [⊗] => &CircleTimes;
+ [∷] => &Colon;
+ [â©´] => &Colone;
+ [≡] => &Congruent;
+ [∮] => &ContourIntegral;
+ [âˆ] => &Coproduct;
+ [⨯] => &Cross;
+ [ð’ž] => &Cscr;
+ [â‹“] => &Cup;
+ [â‰] => &CupCap;
+ [⤑] => &DDotrahd;
+ [Ђ] => &DJcy;
+ [Ð…] => &DScy;
+ [Ð] => &DZcy;
+ [‡] => &Dagger;
+ [↡] => &Darr;
+ [⫤] => &Dashv;
+ [ÄŽ] => &Dcaron;
+ [Д] => &Dcy;
+ [Δ] => &Delta;
+ [ð”‡] => &Dfr;
+ [´] => &DiacriticalAcute;
+ [Ë] => &DiacriticalDoubleAcute;
+ [˜] => &DiacriticalTilde;
+ [â…†] => &DifferentialD;
+ [ð”»] => &Dopf;
+ [⃜] => &DotDot;
+ [∯] => &DoubleContourIntegral;
+ [¨] => &DoubleDot;
+ [â‡] => &DoubleLeftArrow;
+ [⟹] => &DoubleLongRightArrow;
+ [⊨] => &DoubleRightTee;
+ [⇑] => &DoubleUpArrow;
+ [⤓] => &DownArrowBar;
+ [⇵] => &DownArrowUpArrow;
+ [Ì‘] => &DownBreve;
+ [â¥] => &DownLeftRightVector;
+ [⥞] => &DownLeftTeeVector;
+ [⥖] => &DownLeftVectorBar;
+ [⥟] => &DownRightTeeVector;
+ [⥗] => &DownRightVectorBar;
+ [⊤] => &DownTee;
+ [↧] => &DownTeeArrow;
+ [⇓] => &Downarrow;
+ [ð’Ÿ] => &Dscr;
+ [Ä] => &Dstrok;
+ [ÅŠ] => &ENG;
+ [Ã] => &ETH;
+ [É] => &Eacute;
+ [Äš] => &Ecaron;
+ [Ê] => &Ecirc;
+ [Э] => &Ecy;
+ [Ä–] => &Edot;
+ [ð”ˆ] => &Efr;
+ [È] => &Egrave;
+ [Ä’] => &Emacr;
+ [â—»] => &EmptySmallSquare;
+ [â–«] => &EmptyVerySmallSquare;
+ [Ę] => &Eogon;
+ [ð”¼] => &Eopf;
+ [Ε] => &Epsilon;
+ [⩵] => &Equal;
+ [⩳] => &Esim;
+ [Η] => &Eta;
+ [Ë] => &Euml;
+ [∃] => &Exists;
+ [Ф] => &Fcy;
+ [ð”‰] => &Ffr;
+ [â—¼] => &FilledSmallSquare;
+ [ð”½] => &Fopf;
+ [ℱ] => &Fouriertrf;
+ [Ѓ] => &GJcy;
+ [Γ] => &Gamma;
+ [Ϝ] => &Gammad;
+ [Äž] => &Gbreve;
+ [Ä¢] => &Gcedil;
+ [Ĝ] => &Gcirc;
+ [Г] => &Gcy;
+ [Ä ] => &Gdot;
+ [ð”Š] => &Gfr;
+ [â‹™] => &Gg;
+ [ð”¾] => &Gopf;
+ [⪢] => &GreaterGreater;
+ [≳] => &GreaterTilde;
+ [ð’¢] => &Gscr;
+ [Ъ] => &HARDcy;
+ [ˇ] => &Hacek;
+ [^] => &Hat;
+ [Ĥ] => &Hcirc;
+ [ℌ] => &Hfr;
+ [â„‹] => &HilbertSpace;
+ [â„] => &Hopf;
+ [─] => &HorizontalLine;
+ [Ħ] => &Hstrok;
+ [â‰] => &HumpEqual;
+ [Е] => &IEcy;
+ [IJ] => &IJlig;
+ [Ð] => &IOcy;
+ [Ã] => &Iacute;
+ [ÃŽ] => &Icirc;
+ [И] => &Icy;
+ [Ä°] => &Idot;
+ [â„‘] => &Ifr;
+ [Ì] => &Igrave;
+ [Ī] => &Imacr;
+ [â…ˆ] => &ImaginaryI;
+ [⇒] => &Implies;
+ [∬] => &Int;
+ [∫] => &Integral;
+ [â¢] => &InvisibleTimes;
+ [Ä®] => &Iogon;
+ [ð•€] => &Iopf;
+ [Ι] => &Iota;
+ [Ĩ] => &Itilde;
+ [І] => &Iukcy;
+ [Ã] => &Iuml;
+ [Ä´] => &Jcirc;
+ [Й] => &Jcy;
+ [ð”] => &Jfr;
+ [ð•] => &Jopf;
+ [ð’¥] => &Jscr;
+ [Ј] => &Jsercy;
+ [Є] => &Jukcy;
+ [Ð¥] => &KHcy;
+ [Ќ] => &KJcy;
+ [Κ] => &Kappa;
+ [Ķ] => &Kcedil;
+ [К] => &Kcy;
+ [ð”Ž] => &Kfr;
+ [ð•‚] => &Kopf;
+ [ð’¦] => &Kscr;
+ [Љ] => &LJcy;
+ [Ĺ] => &Lacute;
+ [Λ] => &Lambda;
+ [⟪] => &Lang;
+ [↞] => &Larr;
+ [Ľ] => &Lcaron;
+ [Ä»] => &Lcedil;
+ [Л] => &Lcy;
+ [⇤] => &LeftArrowBar;
+ [⟦] => &LeftDoubleBracket;
+ [⥡] => &LeftDownTeeVector;
+ [⥙] => &LeftDownVectorBar;
+ [⌊] => &LeftFloor;
+ [⥎] => &LeftRightVector;
+ [↤] => &LeftTeeArrow;
+ [⥚] => &LeftTeeVector;
+ [â§] => &LeftTriangleBar;
+ [⊴] => &LeftTriangleEqual;
+ [⥑] => &LeftUpDownVector;
+ [⥠] => &LeftUpTeeVector;
+ [⥘] => &LeftUpVectorBar;
+ [⥒] => &LeftVectorBar;
+ [⪡] => &LessLess;
+ [≲] => &LessTilde;
+ [ð”] => &Lfr;
+ [⋘] => &Ll;
+ [Ä¿] => &Lmidot;
+ [⟷] => &LongLeftRightArrow;
+ [⟶] => &LongRightArrow;
+ [ð•ƒ] => &Lopf;
+ [↘] => &LowerRightArrow;
+ [↰] => &Lsh;
+ [Å] => &Lstrok;
+ [⤅] => &Map;
+ [М] => &Mcy;
+ [âŸ] => &MediumSpace;
+ [ℳ] => &Mellintrf;
+ [ð”] => &Mfr;
+ [∓] => &MinusPlus;
+ [ð•„] => &Mopf;
+ [Μ] => &Mu;
+ [Њ] => &NJcy;
+ [Ń] => &Nacute;
+ [Ň] => &Ncaron;
+ [Å…] => &Ncedil;
+ [Ð] => &Ncy;
+ [
+] => &NewLine;
+ [ð”‘] => &Nfr;
+ [â ] => &NoBreak;
+ [⫬] => &Not;
+ [≢] => &NotCongruent;
+ [≭] => &NotCupCap;
+ [≠] => &NotEqual;
+ [≧̸] => &NotGreaterFullEqual
+ [≫̸] => &NotGreaterGreater
+ [≹] => &NotGreaterLess;
+ [â§Ì¸] => &NotLeftTriangleBar
+ [≮] => &NotLess;
+ [≰] => &NotLessEqual;
+ [⪢̸] => &NotNestedGreaterGreater
+ [⪡̸] => &NotNestedLessLess
+ [⪯̸] => &NotPrecedesEqual
+ [â‹ ] => &NotPrecedesSlantEqual;
+ [â§Ì¸] => &NotRightTriangleBar
+ [â‹­] => &NotRightTriangleEqual;
+ [âŠÌ¸] => &NotSquareSubset
+ [â‹¢] => &NotSquareSubsetEqual;
+ [âŠÌ¸] => &NotSquareSuperset
+ [â‹£] => &NotSquareSupersetEqual;
+ [⊈] => &NotSubsetEqual;
+ [âŠ] => &NotSucceeds;
+ [⪰̸] => &NotSucceedsEqual
+ [â‹¡] => &NotSucceedsSlantEqual;
+ [≿̸] => &NotSucceedsTilde
+ [⊉] => &NotSupersetEqual;
+ [â‰] => &NotTilde;
+ [ð’©] => &Nscr;
+ [Ñ] => &Ntilde;
+ [Î] => &Nu;
+ [Å’] => &OElig;
+ [Ó] => &Oacute;
+ [Ô] => &Ocirc;
+ [О] => &Ocy;
+ [Å] => &Odblac;
+ [ð”’] => &Ofr;
+ [Ã’] => &Ograve;
+ [Ō] => &Omacr;
+ [Ω] => &Omega;
+ [Ο] => &Omicron;
+ [ð•†] => &Oopf;
+ [“] => &OpenCurlyDoubleQuote;
+ [‘] => &OpenCurlyQuote;
+ [â©”] => &Or;
+ [ð’ª] => &Oscr;
+ [Ø] => &Oslash;
+ [Õ] => &Otilde;
+ [⨷] => &Otimes;
+ [Ö] => &Ouml;
+ [âž] => &OverBrace;
+ [⎴] => &OverBracket;
+ [âœ] => &OverParenthesis;
+ [П] => &Pcy;
+ [ð”“] => &Pfr;
+ [Φ] => &Phi;
+ [Π] => &Pi;
+ [⪻] => &Pr;
+ [≼] => &PrecedesSlantEqual;
+ [″] => &Prime;
+ [ð’«] => &Pscr;
+ [Ψ] => &Psi;
+ [ð””] => &Qfr;
+ [ð’¬] => &Qscr;
+ [Å”] => &Racute;
+ [⟫] => &Rang;
+ [⤖] => &Rarrtl;
+ [Ř] => &Rcaron;
+ [Å–] => &Rcedil;
+ [Р] => &Rcy;
+ [∋] => &ReverseElement;
+ [⥯] => &ReverseUpEquilibrium;
+ [ℜ] => &Rfr;
+ [Ρ] => &Rho;
+ [⟩] => &RightAngleBracket;
+ [⇥] => &RightArrowBar;
+ [⌉] => &RightCeiling;
+ [⟧] => &RightDoubleBracket;
+ [â¥] => &RightDownTeeVector;
+ [⇂] => &RightDownVector;
+ [⥕] => &RightDownVectorBar;
+ [⌋] => &RightFloor;
+ [⥛] => &RightTeeVector;
+ [â§] => &RightTriangleBar;
+ [⊵] => &RightTriangleEqual;
+ [â¥] => &RightUpDownVector;
+ [⥜] => &RightUpTeeVector;
+ [↾] => &RightUpVector;
+ [⥔] => &RightUpVectorBar;
+ [⥓] => &RightVectorBar;
+ [â„] => &Ropf;
+ [⥰] => &RoundImplies;
+ [⧴] => &RuleDelayed;
+ [Щ] => &SHCHcy;
+ [Ш] => &SHcy;
+ [Ь] => &SOFTcy;
+ [Åš] => &Sacute;
+ [⪼] => &Sc;
+ [Å ] => &Scaron;
+ [Åž] => &Scedil;
+ [Ŝ] => &Scirc;
+ [С] => &Scy;
+ [ð”–] => &Sfr;
+ [Σ] => &Sigma;
+ [ð•Š] => &Sopf;
+ [√] => &Sqrt;
+ [â–¡] => &Square;
+ [⊑] => &SquareSubsetEqual;
+ [⊒] => &SquareSupersetEqual;
+ [ð’®] => &Sscr;
+ [⋆] => &Star;
+ [â‹] => &Sub;
+ [⊆] => &SubsetEqual;
+ [⪰] => &SucceedsEqual;
+ [≿] => &SucceedsTilde;
+ [â‹‘] => &Supset;
+ [Þ] => &THORN;
+ [Ћ] => &TSHcy;
+ [Ц] => &TScy;
+ [ ] => &Tab;
+ [Τ] => &Tau;
+ [Ť] => &Tcaron;
+ [Å¢] => &Tcedil;
+ [Т] => &Tcy;
+ [ð”—] => &Tfr;
+ [Θ] => &Theta;
+ [âŸâ€Š] => &ThickSpace
+ [ ] => &ThinSpace;
+ [≅] => &TildeFullEqual;
+ [ð•‹] => &Topf;
+ [⃛] => &TripleDot;
+ [ð’¯] => &Tscr;
+ [Ŧ] => &Tstrok;
+ [Ú] => &Uacute;
+ [↟] => &Uarr;
+ [⥉] => &Uarrocir;
+ [ÐŽ] => &Ubrcy;
+ [Ŭ] => &Ubreve;
+ [Û] => &Ucirc;
+ [У] => &Ucy;
+ [Å°] => &Udblac;
+ [ð”˜] => &Ufr;
+ [Ù] => &Ugrave;
+ [Ū] => &Umacr;
+ [âŸ] => &UnderBrace;
+ [â] => &UnderParenthesis;
+ [⊎] => &UnionPlus;
+ [Ų] => &Uogon;
+ [ð•Œ] => &Uopf;
+ [⤒] => &UpArrowBar;
+ [↕] => &UpDownArrow;
+ [↥] => &UpTeeArrow;
+ [⇕] => &Updownarrow;
+ [↗] => &UpperRightArrow;
+ [Î¥] => &Upsilon;
+ [Å®] => &Uring;
+ [ð’°] => &Uscr;
+ [Ũ] => &Utilde;
+ [Ü] => &Uuml;
+ [⊫] => &VDash;
+ [â««] => &Vbar;
+ [Ð’] => &Vcy;
+ [⊩] => &Vdash;
+ [⫦] => &Vdashl;
+ [‖] => &Verbar;
+ [â˜] => &VerticalSeparator;
+ [ð”™] => &Vfr;
+ [ð•] => &Vopf;
+ [ð’±] => &Vscr;
+ [⊪] => &Vvdash;
+ [Å´] => &Wcirc;
+ [ð”š] => &Wfr;
+ [ð•Ž] => &Wopf;
+ [ð’²] => &Wscr;
+ [ð”›] => &Xfr;
+ [Ξ] => &Xi;
+ [ð•] => &Xopf;
+ [ð’³] => &Xscr;
+ [Я] => &YAcy;
+ [Ї] => &YIcy;
+ [Ю] => &YUcy;
+ [Ã] => &Yacute;
+ [Ŷ] => &Ycirc;
+ [Ы] => &Ycy;
+ [ð”œ] => &Yfr;
+ [ð•] => &Yopf;
+ [ð’´] => &Yscr;
+ [Ÿ] => &Yuml;
+ [Ж] => &ZHcy;
+ [Ź] => &Zacute;
+ [Ž] => &Zcaron;
+ [З] => &Zcy;
+ [Å»] => &Zdot;
+ [​] => &ZeroWidthSpace;
+ [Ζ] => &Zeta;
+ [ℨ] => &Zfr;
+ [ℤ] => &Zopf;
+ [ð’µ] => &Zscr;
+ [á] => &aacute;
+ [ă] => &abreve;
+ [∾] => &ac;
+ [∾̳] => &acE
+ [∿] => &acd;
+ [â] => &acirc;
+ [а] => &acy;
+ [æ] => &aelig;
+ [â¡] => &af;
+ [ð”ž] => &afr;
+ [à] => &agrave;
+ [ℵ] => &aleph;
+ [α] => &alpha;
+ [Ä] => &amacr;
+ [⨿] => &amalg;
+ [&] => &amp;
+ [∧] => &and;
+ [â©•] => &andand;
+ [⩜] => &andd;
+ [⩘] => &andslope;
+ [â©š] => &andv;
+ [⦤] => &ange;
+ [∠] => &angle;
+ [∡] => &angmsd;
+ [⦨] => &angmsdaa;
+ [⦩] => &angmsdab;
+ [⦪] => &angmsdac;
+ [⦫] => &angmsdad;
+ [⦬] => &angmsdae;
+ [⦭] => &angmsdaf;
+ [⦮] => &angmsdag;
+ [⦯] => &angmsdah;
+ [∟] => &angrt;
+ [⊾] => &angrtvb;
+ [â¦] => &angrtvbd;
+ [∢] => &angsph;
+ [â¼] => &angzarr;
+ [Ä…] => &aogon;
+ [ð•’] => &aopf;
+ [â©°] => &apE;
+ [⩯] => &apacir;
+ [≊] => &ape;
+ [≋] => &apid;
+ [≈] => &approx;
+ [Ã¥] => &aring;
+ [ð’¶] => &ascr;
+ [*] => &ast;
+ [ã] => &atilde;
+ [ä] => &auml;
+ [∳] => &awconint;
+ [⨑] => &awint;
+ [â«­] => &bNot;
+ [϶] => &backepsilon;
+ [‵] => &backprime;
+ [â‹] => &backsimeq;
+ [⊽] => &barvee;
+ [⌅] => &barwed;
+ [⎵] => &bbrk;
+ [⎶] => &bbrktbrk;
+ [≌] => &bcong;
+ [б] => &bcy;
+ [„] => &bdquo;
+ [⦰] => &bemptyv;
+ [β] => &beta;
+ [ℶ] => &beth;
+ [≬] => &between;
+ [ð”Ÿ] => &bfr;
+ [â‹‚] => &bigcap;
+ [â—¯] => &bigcirc;
+ [⋃] => &bigcup;
+ [â¨] => &bigoplus;
+ [⨂] => &bigotimes;
+ [⨆] => &bigsqcup;
+ [â–½] => &bigtriangledown;
+ [â–³] => &bigtriangleup;
+ [⨄] => &biguplus;
+ [â¤] => &bkarow;
+ [â–´] => &blacktriangle;
+ [â–¾] => &blacktriangledown;
+ [â—‚] => &blacktriangleleft;
+ [â–¸] => &blacktriangleright;
+ [â£] => &blank;
+ [â–’] => &blk12;
+ [â–‘] => &blk14;
+ [â–“] => &blk34;
+ [â–ˆ] => &block;
+ [=⃥] => &bne
+ [≡⃥] => &bnequiv
+ [âŒ] => &bnot;
+ [ð•“] => &bopf;
+ [⋈] => &bowtie;
+ [â•—] => &boxDL;
+ [â•”] => &boxDR;
+ [â•–] => &boxDl;
+ [â•“] => &boxDr;
+ [â•] => &boxH;
+ [╦] => &boxHD;
+ [â•©] => &boxHU;
+ [╤] => &boxHd;
+ [╧] => &boxHu;
+ [â•] => &boxUL;
+ [â•š] => &boxUR;
+ [╜] => &boxUl;
+ [â•™] => &boxUr;
+ [â•‘] => &boxV;
+ [╬] => &boxVH;
+ [â•£] => &boxVL;
+ [â• ] => &boxVR;
+ [â•«] => &boxVh;
+ [â•¢] => &boxVl;
+ [â•Ÿ] => &boxVr;
+ [⧉] => &boxbox;
+ [â••] => &boxdL;
+ [â•’] => &boxdR;
+ [â”] => &boxdl;
+ [┌] => &boxdr;
+ [â•¥] => &boxhD;
+ [╨] => &boxhU;
+ [┬] => &boxhd;
+ [â”´] => &boxhu;
+ [⊟] => &boxminus;
+ [⊞] => &boxplus;
+ [â•›] => &boxuL;
+ [╘] => &boxuR;
+ [┘] => &boxul;
+ [â””] => &boxur;
+ [│] => &boxv;
+ [╪] => &boxvH;
+ [â•¡] => &boxvL;
+ [â•ž] => &boxvR;
+ [┼] => &boxvh;
+ [┤] => &boxvl;
+ [├] => &boxvr;
+ [¦] => &brvbar;
+ [ð’·] => &bscr;
+ [â] => &bsemi;
+ [∽] => &bsim;
+ [\] => &bsol;
+ [⧅] => &bsolb;
+ [⟈] => &bsolhsub;
+ [•] => &bull;
+ [≎] => &bump;
+ [⪮] => &bumpE;
+ [ć] => &cacute;
+ [∩] => &cap;
+ [â©„] => &capand;
+ [⩉] => &capbrcup;
+ [â©‹] => &capcap;
+ [⩇] => &capcup;
+ [â©€] => &capdot;
+ [∩︀] => &caps
+ [â] => &caret;
+ [â©] => &ccaps;
+ [Ä] => &ccaron;
+ [ç] => &ccedil;
+ [ĉ] => &ccirc;
+ [⩌] => &ccups;
+ [â©] => &ccupssm;
+ [Ä‹] => &cdot;
+ [⦲] => &cemptyv;
+ [¢] => &cent;
+ [ð” ] => &cfr;
+ [ч] => &chcy;
+ [✓] => &check;
+ [χ] => &chi;
+ [â—‹] => &cir;
+ [⧃] => &cirE;
+ [ˆ] => &circ;
+ [≗] => &circeq;
+ [â¨] => &cirfnint;
+ [⫯] => &cirmid;
+ [⧂] => &cirscir;
+ [♣] => &clubs;
+ [:] => &colon;
+ [≔] => &coloneq;
+ [,] => &comma;
+ [@] => &commat;
+ [âˆ] => &comp;
+ [∘] => &compfn;
+ [â„‚] => &complexes;
+ [â©­] => &congdot;
+ [ð•”] => &copf;
+ [©] => &copy;
+ [â„—] => &copysr;
+ [↵] => &crarr;
+ [✗] => &cross;
+ [ð’¸] => &cscr;
+ [â«] => &csub;
+ [â«‘] => &csube;
+ [â«] => &csup;
+ [â«’] => &csupe;
+ [⋯] => &ctdot;
+ [⤸] => &cudarrl;
+ [⤵] => &cudarrr;
+ [â‹Ÿ] => &cuesc;
+ [⤽] => &cularrp;
+ [∪] => &cup;
+ [⩈] => &cupbrcap;
+ [⩆] => &cupcap;
+ [â©Š] => &cupcup;
+ [âŠ] => &cupdot;
+ [â©…] => &cupor;
+ [∪︀] => &cups
+ [↷] => &curarr;
+ [⤼] => &curarrm;
+ [â‹ž] => &curlyeqprec;
+ [â‹Ž] => &curlyvee;
+ [â‹] => &curlywedge;
+ [¤] => &curren;
+ [↶] => &curvearrowleft;
+ [∲] => &cwconint;
+ [∱] => &cwint;
+ [⌭] => &cylcty;
+ [⥥] => &dHar;
+ [†] => &dagger;
+ [ℸ] => &daleth;
+ [↓] => &darr;
+ [⊣] => &dashv;
+ [â¤] => &dbkarow;
+ [Ä] => &dcaron;
+ [д] => &dcy;
+ [â©·] => &ddotseq;
+ [°] => &deg;
+ [δ] => &delta;
+ [⦱] => &demptyv;
+ [⥿] => &dfisht;
+ [ð”¡] => &dfr;
+ [⇃] => &dharl;
+ [â‹„] => &diamond;
+ [♦] => &diamondsuit;
+ [⋲] => &disin;
+ [÷] => &divide;
+ [⋇] => &divonx;
+ [Ñ’] => &djcy;
+ [âŒ] => &dlcrop;
+ [$] => &dollar;
+ [ð••] => &dopf;
+ [Ë™] => &dot;
+ [≑] => &doteqdot;
+ [⌆] => &doublebarwedge;
+ [⇊] => &downdownarrows;
+ [â¤] => &drbkarow;
+ [⌟] => &drcorn;
+ [⌌] => &drcrop;
+ [ð’¹] => &dscr;
+ [Ñ•] => &dscy;
+ [⧶] => &dsol;
+ [Ä‘] => &dstrok;
+ [⋱] => &dtdot;
+ [⦦] => &dwangle;
+ [ÑŸ] => &dzcy;
+ [⟿] => &dzigrarr;
+ [é] => &eacute;
+ [â©®] => &easter;
+ [Ä›] => &ecaron;
+ [≖] => &ecir;
+ [ê] => &ecirc;
+ [Ñ] => &ecy;
+ [Ä—] => &edot;
+ [ð”¢] => &efr;
+ [⪚] => &eg;
+ [è] => &egrave;
+ [⪖] => &egs;
+ [⪘] => &egsdot;
+ [⪙] => &el;
+ [â§] => &elinters;
+ [â„“] => &ell;
+ [⪕] => &els;
+ [⪗] => &elsdot;
+ [Ä“] => &emacr;
+ [∅] => &empty;
+ [ ] => &emsp13;
+ [ ] => &emsp14;
+ [ ] => &emsp;
+ [Å‹] => &eng;
+ [ ] => &ensp;
+ [Ä™] => &eogon;
+ [ð•–] => &eopf;
+ [â‹•] => &epar;
+ [⧣] => &eparsl;
+ [⩱] => &eplus;
+ [ε] => &epsi;
+ [≕] => &eqcolon;
+ [=] => &equals;
+ [≟] => &equest;
+ [⩸] => &equivDD;
+ [⧥] => &eqvparsl;
+ [⥱] => &erarr;
+ [ℯ] => &escr;
+ [â‰] => &esdot;
+ [≂] => &esim;
+ [η] => &eta;
+ [ð] => &eth;
+ [ë] => &euml;
+ [€] => &euro;
+ [!] => &excl;
+ [â„°] => &expectation;
+ [â…‡] => &exponentiale;
+ [≒] => &fallingdotseq;
+ [Ñ„] => &fcy;
+ [♀] => &female;
+ [ffi] => &ffilig;
+ [ff] => &fflig;
+ [ffl] => &ffllig;
+ [ð”£] => &ffr;
+ [ï¬] => &filig;
+ [fj] => &fjlig
+ [â™­] => &flat;
+ [fl] => &fllig;
+ [â–±] => &fltns;
+ [Æ’] => &fnof;
+ [ð•—] => &fopf;
+ [∀] => &forall;
+ [â«™] => &forkv;
+ [â¨] => &fpartint;
+ [â…“] => &frac13;
+ [¼] => &frac14;
+ [â…•] => &frac15;
+ [â…™] => &frac16;
+ [â…›] => &frac18;
+ [â…”] => &frac23;
+ [â…–] => &frac25;
+ [¾] => &frac34;
+ [â…—] => &frac35;
+ [⅜] => &frac38;
+ [â…˜] => &frac45;
+ [â…š] => &frac56;
+ [â…] => &frac58;
+ [â…ž] => &frac78;
+ [â„] => &frasl;
+ [⌢] => &frown;
+ [ð’»] => &fscr;
+ [⪌] => &gEl;
+ [ǵ] => &gacute;
+ [γ] => &gamma;
+ [Ï] => &gammad;
+ [⪆] => &gap;
+ [ÄŸ] => &gbreve;
+ [Ä] => &gcirc;
+ [г] => &gcy;
+ [Ä¡] => &gdot;
+ [≥] => &ge;
+ [≧] => &geqq;
+ [⩾] => &ges;
+ [⪩] => &gescc;
+ [⪀] => &gesdot;
+ [⪂] => &gesdoto;
+ [⪄] => &gesdotol;
+ [⋛︀] => &gesl
+ [⪔] => &gesles;
+ [ð”¤] => &gfr;
+ [≫] => &gg;
+ [â„·] => &gimel;
+ [Ñ“] => &gjcy;
+ [≷] => &gl;
+ [⪒] => &glE;
+ [⪥] => &gla;
+ [⪤] => &glj;
+ [⪊] => &gnap;
+ [⪈] => &gne;
+ [≩] => &gneqq;
+ [⋧] => &gnsim;
+ [ð•˜] => &gopf;
+ [`] => &grave;
+ [â„Š] => &gscr;
+ [⪎] => &gsime;
+ [âª] => &gsiml;
+ [>] => &gt;
+ [⪧] => &gtcc;
+ [⩺] => &gtcir;
+ [⦕] => &gtlPar;
+ [⩼] => &gtquest;
+ [⥸] => &gtrarr;
+ [â‹—] => &gtrdot;
+ [â‹›] => &gtreqless;
+ [≩︀] => &gvertneqq
+ [⇔] => &hArr;
+ [ ] => &hairsp;
+ [½] => &half;
+ [ÑŠ] => &hardcy;
+ [↔] => &harr;
+ [⥈] => &harrcir;
+ [↭] => &harrw;
+ [Ä¥] => &hcirc;
+ [♥] => &hearts;
+ […] => &hellip;
+ [⊹] => &hercon;
+ [ð”¥] => &hfr;
+ [⇿] => &hoarr;
+ [∻] => &homtht;
+ [ð•™] => &hopf;
+ [―] => &horbar;
+ [ð’½] => &hscr;
+ [ħ] => &hstrok;
+ [âƒ] => &hybull;
+ [â€] => &hyphen;
+ [í] => &iacute;
+ [â£] => &ic;
+ [î] => &icirc;
+ [и] => &icy;
+ [е] => &iecy;
+ [¡] => &iexcl;
+ [ð”¦] => &ifr;
+ [ì] => &igrave;
+ [⨌] => &iiiint;
+ [⧜] => &iinfin;
+ [â„©] => &iiota;
+ [ij] => &ijlig;
+ [Ä«] => &imacr;
+ [â„] => &imagline;
+ [⊷] => &imof;
+ [Ƶ] => &imped;
+ [â„…] => &incare;
+ [∞] => &infin;
+ [â§] => &infintie;
+ [ı] => &inodot;
+ [⊺] => &intcal;
+ [⨗] => &intlarhk;
+ [Ñ‘] => &iocy;
+ [į] => &iogon;
+ [ð•š] => &iopf;
+ [ι] => &iota;
+ [⨼] => &iprod;
+ [¿] => &iquest;
+ [ð’¾] => &iscr;
+ [⋹] => &isinE;
+ [⋵] => &isindot;
+ [â‹´] => &isins;
+ [⋳] => &isinsv;
+ [∈] => &isinv;
+ [Ä©] => &itilde;
+ [Ñ–] => &iukcy;
+ [ï] => &iuml;
+ [ĵ] => &jcirc;
+ [й] => &jcy;
+ [ð”§] => &jfr;
+ [È·] => &jmath;
+ [ð•›] => &jopf;
+ [ð’¿] => &jscr;
+ [ј] => &jsercy;
+ [Ñ”] => &jukcy;
+ [κ] => &kappa;
+ [Ä·] => &kcedil;
+ [к] => &kcy;
+ [ð”¨] => &kfr;
+ [ĸ] => &kgreen;
+ [Ñ…] => &khcy;
+ [ќ] => &kjcy;
+ [ð•œ] => &kopf;
+ [ð“€] => &kscr;
+ [⇚] => &lAarr;
+ [⤛] => &lAtail;
+ [⤎] => &lBarr;
+ [≦] => &lE;
+ [⥢] => &lHar;
+ [ĺ] => &lacute;
+ [⦴] => &laemptyv;
+ [â„’] => &lagran;
+ [λ] => &lambda;
+ [⦑] => &langd;
+ [⟨] => &langle;
+ [⪅] => &lap;
+ [«] => &laquo;
+ [â†] => &larr;
+ [⤟] => &larrbfs;
+ [â¤] => &larrfs;
+ [↩] => &larrhk;
+ [↫] => &larrlp;
+ [⤹] => &larrpl;
+ [⥳] => &larrsim;
+ [↢] => &larrtl;
+ [⪫] => &lat;
+ [⤙] => &latail;
+ [⪭] => &late;
+ [⪭︀] => &lates
+ [⤌] => &lbarr;
+ [â²] => &lbbrk;
+ [{] => &lbrace;
+ [[] => &lbrack;
+ [⦋] => &lbrke;
+ [â¦] => &lbrksld;
+ [â¦] => &lbrkslu;
+ [ľ] => &lcaron;
+ [ļ] => &lcedil;
+ [⌈] => &lceil;
+ [л] => &lcy;
+ [⤶] => &ldca;
+ [⥧] => &ldrdhar;
+ [⥋] => &ldrushar;
+ [↲] => &ldsh;
+ [↽] => &leftharpoondown;
+ [↼] => &leftharpoonup;
+ [⇋] => &leftrightharpoons;
+ [≤] => &leq;
+ [⩽] => &les;
+ [⪨] => &lescc;
+ [â©¿] => &lesdot;
+ [âª] => &lesdoto;
+ [⪃] => &lesdotor;
+ [⋚︀] => &lesg
+ [⪓] => &lesges;
+ [â‹–] => &lessdot;
+ [â‹š] => &lesseqgtr;
+ [⪋] => &lesseqqgtr;
+ [≶] => &lessgtr;
+ [⥼] => &lfisht;
+ [ð”©] => &lfr;
+ [⪑] => &lgE;
+ [⥪] => &lharul;
+ [â–„] => &lhblk;
+ [Ñ™] => &ljcy;
+ [≪] => &ll;
+ [⇇] => &llarr;
+ [⌞] => &llcorner;
+ [⥫] => &llhard;
+ [â—º] => &lltri;
+ [Å€] => &lmidot;
+ [⎰] => &lmoust;
+ [⪉] => &lnap;
+ [⪇] => &lne;
+ [≨] => &lneqq;
+ [⋦] => &lnsim;
+ [⟬] => &loang;
+ [⇽] => &loarr;
+ [⟵] => &longleftarrow;
+ [↬] => &looparrowright;
+ [⦅] => &lopar;
+ [ð•] => &lopf;
+ [⨭] => &loplus;
+ [⨴] => &lotimes;
+ [∗] => &lowast;
+ [_] => &lowbar;
+ [â—Š] => &lozenge;
+ [⧫] => &lozf;
+ [(] => &lpar;
+ [⦓] => &lparlt;
+ [⇆] => &lrarr;
+ [⥭] => &lrhard;
+ [‎] => &lrm;
+ [⊿] => &lrtri;
+ [‹] => &lsaquo;
+ [ð“] => &lscr;
+ [âª] => &lsime;
+ [âª] => &lsimg;
+ [Å‚] => &lstrok;
+ [<] => &lt;
+ [⪦] => &ltcc;
+ [⩹] => &ltcir;
+ [â‹‹] => &lthree;
+ [⋉] => &ltimes;
+ [⥶] => &ltlarr;
+ [â©»] => &ltquest;
+ [⦖] => &ltrPar;
+ [â—ƒ] => &ltri;
+ [⥊] => &lurdshar;
+ [⥦] => &luruhar;
+ [≨︀] => &lvertneqq
+ [∺] => &mDDot;
+ [¯] => &macr;
+ [♂] => &male;
+ [✠] => &maltese;
+ [↦] => &map;
+ [â–®] => &marker;
+ [⨩] => &mcomma;
+ [м] => &mcy;
+ [—] => &mdash;
+ [ð”ª] => &mfr;
+ [℧] => &mho;
+ [µ] => &micro;
+ [∣] => &mid;
+ [â«°] => &midcir;
+ [−] => &minus;
+ [∸] => &minusd;
+ [⨪] => &minusdu;
+ [â«›] => &mlcp;
+ [⊧] => &models;
+ [ð•ž] => &mopf;
+ [ð“‚] => &mscr;
+ [μ] => &mu;
+ [⊸] => &mumap;
+ [⋙̸] => &nGg
+ [≫⃒] => &nGt
+ [â‡] => &nLeftarrow;
+ [⋘̸] => &nLl
+ [≪⃒] => &nLt
+ [≪̸] => &nLtv
+ [⊯] => &nVDash;
+ [⊮] => &nVdash;
+ [∇] => &nabla;
+ [Å„] => &nacute;
+ [∠⃒] => &nang
+ [⩰̸] => &napE
+ [≋̸] => &napid
+ [ʼn] => &napos;
+ [≉] => &napprox;
+ [â™®] => &natur;
+ [â„•] => &naturals;
+ [ ] => &nbsp;
+ [≎̸] => &nbump
+ [â‰Ì¸] => &nbumpe
+ [⩃] => &ncap;
+ [ň] => &ncaron;
+ [ņ] => &ncedil;
+ [≇] => &ncong;
+ [⩭̸] => &ncongdot
+ [â©‚] => &ncup;
+ [н] => &ncy;
+ [–] => &ndash;
+ [⇗] => &neArr;
+ [⤤] => &nearhk;
+ [â‰Ì¸] => &nedot
+ [≂̸] => &nesim
+ [∄] => &nexist;
+ [ð”«] => &nfr;
+ [≱] => &ngeq;
+ [⩾̸] => &nges
+ [≵] => &ngsim;
+ [≯] => &ngtr;
+ [⇎] => &nhArr;
+ [⫲] => &nhpar;
+ [⋼] => &nis;
+ [⋺] => &nisd;
+ [Ñš] => &njcy;
+ [≦̸] => &nlE
+ [‥] => &nldr;
+ [↚] => &nleftarrow;
+ [↮] => &nleftrightarrow;
+ [⩽̸] => &nles
+ [≴] => &nlsim;
+ [⋪] => &nltri;
+ [⋬] => &nltrie;
+ [ð•Ÿ] => &nopf;
+ [¬] => &not;
+ [∉] => &notin;
+ [⋹̸] => &notinE
+ [⋵̸] => &notindot
+ [â‹·] => &notinvb;
+ [⋶] => &notinvc;
+ [∌] => &notniva;
+ [⋾] => &notnivb;
+ [⋽] => &notnivc;
+ [∦] => &nparallel;
+ [∂̸] => &npart
+ [⨔] => &npolint;
+ [⊀] => &npr;
+ [â‡] => &nrArr;
+ [↛] => &nrarr;
+ [⤳̸] => &nrarrc
+ [â†Ì¸] => &nrarrw
+ [ð“ƒ] => &nscr;
+ [∤] => &nshortmid;
+ [≄] => &nsime;
+ [⊄] => &nsub;
+ [⫅̸] => &nsubE
+ [⊅] => &nsup;
+ [⊃⃒] => &nsupset
+ [⫆̸] => &nsupseteqq
+ [ñ] => &ntilde;
+ [≸] => &ntlg;
+ [â‹«] => &ntriangleright;
+ [ν] => &nu;
+ [#] => &num;
+ [â„–] => &numero;
+ [ ] => &numsp;
+ [⊭] => &nvDash;
+ [⤄] => &nvHarr;
+ [â‰âƒ’] => &nvap
+ [⊬] => &nvdash;
+ [≥⃒] => &nvge
+ [>⃒] => &nvgt
+ [⧞] => &nvinfin;
+ [⤂] => &nvlArr;
+ [≤⃒] => &nvle
+ [<⃒] => &nvlt
+ [⊴⃒] => &nvltrie
+ [⤃] => &nvrArr;
+ [⊵⃒] => &nvrtrie
+ [∼⃒] => &nvsim
+ [⇖] => &nwArr;
+ [⤣] => &nwarhk;
+ [↖] => &nwarrow;
+ [⤧] => &nwnear;
+ [Ⓢ] => &oS;
+ [ó] => &oacute;
+ [⊛] => &oast;
+ [⊚] => &ocir;
+ [ô] => &ocirc;
+ [о] => &ocy;
+ [âŠ] => &odash;
+ [Å‘] => &odblac;
+ [⨸] => &odiv;
+ [⦼] => &odsold;
+ [Å“] => &oelig;
+ [⦿] => &ofcir;
+ [ð”¬] => &ofr;
+ [Ë›] => &ogon;
+ [ò] => &ograve;
+ [â§] => &ogt;
+ [⦵] => &ohbar;
+ [↺] => &olarr;
+ [⦾] => &olcir;
+ [⦻] => &olcross;
+ [‾] => &oline;
+ [⧀] => &olt;
+ [Å] => &omacr;
+ [ω] => &omega;
+ [ο] => &omicron;
+ [⦶] => &omid;
+ [⊖] => &ominus;
+ [ð• ] => &oopf;
+ [⦷] => &opar;
+ [⦹] => &operp;
+ [∨] => &or;
+ [↻] => &orarr;
+ [â©] => &ord;
+ [â„´] => &orderof;
+ [ª] => &ordf;
+ [º] => &ordm;
+ [⊶] => &origof;
+ [â©–] => &oror;
+ [â©—] => &orslope;
+ [â©›] => &orv;
+ [ø] => &oslash;
+ [⊘] => &osol;
+ [õ] => &otilde;
+ [⨶] => &otimesas;
+ [ö] => &ouml;
+ [⌽] => &ovbar;
+ [¶] => &para;
+ [⫳] => &parsim;
+ [∂] => &part;
+ [п] => &pcy;
+ [%] => &percnt;
+ [.] => &period;
+ [‰] => &permil;
+ [⊥] => &perp;
+ [‱] => &pertenk;
+ [ð”­] => &pfr;
+ [φ] => &phi;
+ [☎] => &phone;
+ [Ï€] => &pi;
+ [â‹”] => &pitchfork;
+ [Ï–] => &piv;
+ [â„] => &planck;
+ [â„Ž] => &planckh;
+ [+] => &plus;
+ [⨣] => &plusacir;
+ [⨢] => &pluscir;
+ [∔] => &plusdo;
+ [⨥] => &plusdu;
+ [⩲] => &pluse;
+ [±] => &plusmn;
+ [⨦] => &plussim;
+ [⨧] => &plustwo;
+ [⨕] => &pointint;
+ [ð•¡] => &popf;
+ [£] => &pound;
+ [⪳] => &prE;
+ [≺] => &prec;
+ [⪷] => &precapprox;
+ [⪯] => &preceq;
+ [⪹] => &precnapprox;
+ [⪵] => &precneqq;
+ [⋨] => &precnsim;
+ [≾] => &precsim;
+ [′] => &prime;
+ [â„™] => &primes;
+ [âˆ] => &prod;
+ [⌮] => &profalar;
+ [⌒] => &profline;
+ [⌓] => &profsurf;
+ [âˆ] => &prop;
+ [⊰] => &prurel;
+ [ð“…] => &pscr;
+ [ψ] => &psi;
+ [ ] => &puncsp;
+ [ð”®] => &qfr;
+ [ð•¢] => &qopf;
+ [â—] => &qprime;
+ [ð“†] => &qscr;
+ [⨖] => &quatint;
+ [?] => &quest;
+ ["] => &quot;
+ [⇛] => &rAarr;
+ [⤜] => &rAtail;
+ [⥤] => &rHar;
+ [∽̱] => &race
+ [Å•] => &racute;
+ [⦳] => &raemptyv;
+ [⦒] => &rangd;
+ [⦥] => &range;
+ [»] => &raquo;
+ [⥵] => &rarrap;
+ [⤠] => &rarrbfs;
+ [⤳] => &rarrc;
+ [⤞] => &rarrfs;
+ [↪] => &rarrhk;
+ [⥅] => &rarrpl;
+ [⥴] => &rarrsim;
+ [↣] => &rarrtl;
+ [â†] => &rarrw;
+ [⤚] => &ratail;
+ [∶] => &ratio;
+ [â„š] => &rationals;
+ [â³] => &rbbrk;
+ [⦌] => &rbrke;
+ [⦎] => &rbrksld;
+ [â¦] => &rbrkslu;
+ [Å™] => &rcaron;
+ [Å—] => &rcedil;
+ [}] => &rcub;
+ [Ñ€] => &rcy;
+ [⤷] => &rdca;
+ [⥩] => &rdldhar;
+ [â€] => &rdquo;
+ [↳] => &rdsh;
+ [â„›] => &realine;
+ [â–­] => &rect;
+ [®] => &reg;
+ [⥽] => &rfisht;
+ [ð”¯] => &rfr;
+ [â‡] => &rhard;
+ [⇀] => &rharu;
+ [⥬] => &rharul;
+ [Ï] => &rho;
+ [ϱ] => &rhov;
+ [⇄] => &rightleftarrows;
+ [⇌] => &rightleftharpoons;
+ [Ëš] => &ring;
+ [≓] => &risingdotseq;
+ [â€] => &rlm;
+ [⎱] => &rmoust;
+ [â«®] => &rnmid;
+ [⟭] => &roang;
+ [⇾] => &roarr;
+ [⦆] => &ropar;
+ [ð•£] => &ropf;
+ [⨮] => &roplus;
+ [⨵] => &rotimes;
+ [)] => &rpar;
+ [⦔] => &rpargt;
+ [⨒] => &rppolint;
+ [⇉] => &rrarr;
+ [›] => &rsaquo;
+ [ð“‡] => &rscr;
+ [↱] => &rsh;
+ []] => &rsqb;
+ [’] => &rsquo;
+ [⋌] => &rthree;
+ [â‹Š] => &rtimes;
+ [â–¹] => &rtri;
+ [⧎] => &rtriltri;
+ [⥨] => &ruluhar;
+ [â„ž] => &rx;
+ [Å›] => &sacute;
+ [‚] => &sbquo;
+ [⪴] => &scE;
+ [Å¡] => &scaron;
+ [ÅŸ] => &scedil;
+ [Å] => &scirc;
+ [⪶] => &scnE;
+ [â‹©] => &scnsim;
+ [⨓] => &scpolint;
+ [Ñ] => &scy;
+ [â‹…] => &sdot;
+ [⊡] => &sdotb;
+ [⩦] => &sdote;
+ [⇘] => &seArr;
+ [⤥] => &searhk;
+ [§] => &sect;
+ [;] => &semi;
+ [⤩] => &seswar;
+ [✶] => &sext;
+ [ð”°] => &sfr;
+ [♯] => &sharp;
+ [щ] => &shchcy;
+ [ш] => &shcy;
+ [∥] => &shortparallel;
+ [­] => &shy;
+ [σ] => &sigma;
+ [Ï‚] => &sigmav;
+ [∼] => &sim;
+ [⩪] => &simdot;
+ [≃] => &simeq;
+ [⪞] => &simg;
+ [⪠] => &simgE;
+ [âª] => &siml;
+ [⪟] => &simlE;
+ [≆] => &simne;
+ [⨤] => &simplus;
+ [⥲] => &simrarr;
+ [⨳] => &smashp;
+ [⧤] => &smeparsl;
+ [⌣] => &smile;
+ [⪪] => &smt;
+ [⪬] => &smte;
+ [⪬︀] => &smtes
+ [ь] => &softcy;
+ [/] => &sol;
+ [⧄] => &solb;
+ [⌿] => &solbar;
+ [ð•¤] => &sopf;
+ [â™ ] => &spadesuit;
+ [⊓] => &sqcap;
+ [⊓︀] => &sqcaps
+ [⊔] => &sqcup;
+ [⊔︀] => &sqcups
+ [âŠ] => &sqsub;
+ [âŠ] => &sqsupset;
+ [â–ª] => &squarf;
+ [→] => &srarr;
+ [ð“ˆ] => &sscr;
+ [∖] => &ssetmn;
+ [☆] => &star;
+ [★] => &starf;
+ [ϵ] => &straightepsilon;
+ [Ï•] => &straightphi;
+ [⊂] => &sub;
+ [â«…] => &subE;
+ [⪽] => &subdot;
+ [⫃] => &subedot;
+ [â«] => &submult;
+ [⪿] => &subplus;
+ [⥹] => &subrarr;
+ [⊊] => &subsetneq;
+ [â«‹] => &subsetneqq;
+ [⫇] => &subsim;
+ [â«•] => &subsub;
+ [â«“] => &subsup;
+ [≻] => &succ;
+ [⪸] => &succapprox;
+ [≽] => &succcurlyeq;
+ [⪺] => &succnapprox;
+ [∑] => &sum;
+ [♪] => &sung;
+ [¹] => &sup1;
+ [²] => &sup2;
+ [³] => &sup3;
+ [⊃] => &sup;
+ [⪾] => &supdot;
+ [⫘] => &supdsub;
+ [⊇] => &supe;
+ [â«„] => &supedot;
+ [⟉] => &suphsol;
+ [â«—] => &suphsub;
+ [⥻] => &suplarr;
+ [â«‚] => &supmult;
+ [⫌] => &supnE;
+ [â«€] => &supplus;
+ [⫆] => &supseteqq;
+ [⊋] => &supsetneq;
+ [⫈] => &supsim;
+ [â«”] => &supsub;
+ [â«–] => &supsup;
+ [⇙] => &swArr;
+ [⤦] => &swarhk;
+ [↙] => &swarr;
+ [⤪] => &swnwar;
+ [ß] => &szlig;
+ [⌖] => &target;
+ [Ï„] => &tau;
+ [Å¥] => &tcaron;
+ [Å£] => &tcedil;
+ [Ñ‚] => &tcy;
+ [⌕] => &telrec;
+ [ð”±] => &tfr;
+ [∴] => &there4;
+ [θ] => &theta;
+ [Ï‘] => &thetasym;
+ [þ] => &thorn;
+ [×] => &times;
+ [⊠] => &timesb;
+ [⨱] => &timesbar;
+ [⨰] => &timesd;
+ [∭] => &tint;
+ [⤨] => &toea;
+ [⌶] => &topbot;
+ [⫱] => &topcir;
+ [ð•¥] => &topf;
+ [â«š] => &topfork;
+ [‴] => &tprime;
+ [â„¢] => &trade;
+ [â–µ] => &triangle;
+ [â–¿] => &triangledown;
+ [≜] => &triangleq;
+ [â—¬] => &tridot;
+ [⨺] => &triminus;
+ [⨹] => &triplus;
+ [â§] => &trisb;
+ [⨻] => &tritime;
+ [â¢] => &trpezium;
+ [ð“‰] => &tscr;
+ [ц] => &tscy;
+ [Ñ›] => &tshcy;
+ [ŧ] => &tstrok;
+ [↠] => &twoheadrightarrow;
+ [⥣] => &uHar;
+ [ú] => &uacute;
+ [↑] => &uarr;
+ [Ñž] => &ubrcy;
+ [Å­] => &ubreve;
+ [û] => &ucirc;
+ [у] => &ucy;
+ [⇅] => &udarr;
+ [ű] => &udblac;
+ [⥮] => &udhar;
+ [⥾] => &ufisht;
+ [ð”²] => &ufr;
+ [ù] => &ugrave;
+ [↿] => &uharl;
+ [â–€] => &uhblk;
+ [⌜] => &ulcorner;
+ [âŒ] => &ulcrop;
+ [â—¸] => &ultri;
+ [Å«] => &umacr;
+ [ų] => &uogon;
+ [ð•¦] => &uopf;
+ [Ï…] => &upsi;
+ [Ï’] => &upsih;
+ [⇈] => &upuparrows;
+ [âŒ] => &urcorner;
+ [⌎] => &urcrop;
+ [ů] => &uring;
+ [â—¹] => &urtri;
+ [ð“Š] => &uscr;
+ [â‹°] => &utdot;
+ [Å©] => &utilde;
+ [ü] => &uuml;
+ [⦧] => &uwangle;
+ [⫨] => &vBar;
+ [â«©] => &vBarv;
+ [⦜] => &vangrt;
+ [Ï°] => &varkappa;
+ [⫌︀] => &varsupsetneqq
+ [⫽︀] => &varsupsetneqq
+ [⊲] => &vartriangleleft;
+ [в] => &vcy;
+ [⊢] => &vdash;
+ [⊻] => &veebar;
+ [≚] => &veeeq;
+ [â‹®] => &vellip;
+ [|] => &vert;
+ [ð”³] => &vfr;
+ [⊂⃒] => &vnsub
+ [ð•§] => &vopf;
+ [⊳] => &vrtri;
+ [ð“‹] => &vscr;
+ [⫋︀] => &vsubnE
+ [⊊︀] => &vsubne
+ [⊋︀] => &vsupne
+ [⦚] => &vzigzag;
+ [ŵ] => &wcirc;
+ [â©Ÿ] => &wedbar;
+ [≙] => &wedgeq;
+ [ð”´] => &wfr;
+ [ð•¨] => &wopf;
+ [℘] => &wp;
+ [≀] => &wr;
+ [ð“Œ] => &wscr;
+ [ð”µ] => &xfr;
+ [⟺] => &xhArr;
+ [ξ] => &xi;
+ [⟸] => &xlArr;
+ [⟼] => &xmap;
+ [â‹»] => &xnis;
+ [⨀] => &xodot;
+ [ð•©] => &xopf;
+ [ð“] => &xscr;
+ [â‹] => &xvee;
+ [â‹€] => &xwedge;
+ [ý] => &yacute;
+ [Ñ] => &yacy;
+ [Å·] => &ycirc;
+ [Ñ‹] => &ycy;
+ [Â¥] => &yen;
+ [ð”¶] => &yfr;
+ [Ñ—] => &yicy;
+ [ð•ª] => &yopf;
+ [ð“Ž] => &yscr;
+ [ÑŽ] => &yucy;
+ [ÿ] => &yuml;
+ [ź] => &zacute;
+ [ž] => &zcaron;
+ [з] => &zcy;
+ [ż] => &zdot;
+ [ζ] => &zeta;
+ [ð”·] => &zfr;
+ [ж] => &zhcy;
+ [â‡] => &zigrarr;
+ [ð•«] => &zopf;
+ [ð“] => &zscr;
+ [â€] => &zwj;
+ [‌] => &zwnj;
+)
+-- with table = HTML_ENTITIES, ENT_QUOTES --
+int(1510)
+-- with table = HTML_ENTITIES, ENT_NOQUOTES --
+int(1508)
+-- with table = HTML_SPECIALCHARS, ENT_COMPAT --
+int(4)
+Array
+(
+ [&] => &amp;
+ [>] => &gt;
+ [<] => &lt;
+ ["] => &quot;
+)
+-- with table = HTML_SPECIALCHARS, ENT_QUOTES --
+array(5) {
+ ["&"]=>
+ string(5) "&amp;"
+ ["'"]=>
+ string(6) "&apos;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
+}
+-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --
+array(3) {
+ ["&"]=>
+ string(5) "&amp;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+}
+Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic6.phpt b/ext/standard/tests/strings/get_html_translation_table_basic6.phpt
new file mode 100644
index 0000000000..a4b2909f23
--- /dev/null
+++ b/ext/standard/tests/strings/get_html_translation_table_basic6.phpt
@@ -0,0 +1,249 @@
+--TEST--
+Test get_html_translation_table() function : basic functionality - HTML 5/Windows-1251
+--FILE--
+<?php
+
+function so($a,$b) { return ord($a) - ord($b); }
+
+echo "*** Testing get_html_translation_table() : basic functionality - HTML 5/Windows-1251 ***\n";
+
+echo "-- with table = HTML_ENTITIES, ENT_COMPAT --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_COMPAT | ENT_HTML5, "Windows-1251");
+uksort( $tt, 'so' );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_ENTITIES, ENT_QUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_HTML5, "Windows-1251");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_ENTITIES, ENT_NOQUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_HTML5, "Windows-1251");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_COMPAT --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_COMPAT, "Windows-1251");
+uksort( $tt, 'so' );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_QUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_HTML5, "Windows-1251");
+uksort( $tt, 'so' );
+var_dump( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_HTML5, "Windows-1251");
+uasort( $tt, 'so' );
+var_dump( $tt );
+
+
+echo "Done\n";
+?>
+--EXPECT--
+*** Testing get_html_translation_table() : basic functionality - HTML 5/Windows-1251 ***
+-- with table = HTML_ENTITIES, ENT_COMPAT --
+int(157)
+Array
+(
+ [ ] => &Tab;
+ [
+] => &NewLine;
+ [!] => &excl;
+ ["] => &quot;
+ [#] => &num;
+ [$] => &dollar;
+ [%] => &percnt;
+ [&] => &amp;
+ [(] => &lpar;
+ [)] => &rpar;
+ [*] => &ast;
+ [+] => &plus;
+ [,] => &comma;
+ [.] => &period;
+ [/] => &sol;
+ [:] => &colon;
+ [;] => &semi;
+ [<] => &lt;
+ [=] => &equals;
+ [>] => &gt;
+ [?] => &quest;
+ [@] => &commat;
+ [[] => &lbrack;
+ [\] => &bsol;
+ []] => &rsqb;
+ [^] => &Hat;
+ [_] => &lowbar;
+ [`] => &grave;
+ [fj] => &fjlig
+ [{] => &lbrace;
+ [|] => &vert;
+ [}] => &rcub;
+ [€] => &DJcy;
+ [] => &GJcy;
+ [‚] => &sbquo;
+ [ƒ] => &gjcy;
+ [„] => &bdquo;
+ […] => &hellip;
+ [†] => &dagger;
+ [‡] => &Dagger;
+ [ˆ] => &euro;
+ [‰] => &permil;
+ [Š] => &LJcy;
+ [‹] => &lsaquo;
+ [Œ] => &NJcy;
+ [] => &KJcy;
+ [Ž] => &TSHcy;
+ [] => &DZcy;
+ [] => &djcy;
+ [‘] => &OpenCurlyQuote;
+ [’] => &rsquo;
+ [“] => &OpenCurlyDoubleQuote;
+ [”] => &rdquo;
+ [•] => &bull;
+ [–] => &ndash;
+ [—] => &mdash;
+ [™] => &trade;
+ [š] => &ljcy;
+ [›] => &rsaquo;
+ [œ] => &njcy;
+ [] => &kjcy;
+ [ž] => &tshcy;
+ [Ÿ] => &dzcy;
+ [ ] => &nbsp;
+ [¡] => &Ubrcy;
+ [¢] => &ubrcy;
+ [£] => &Jsercy;
+ [¤] => &curren;
+ [¦] => &brvbar;
+ [§] => &sect;
+ [¨] => &IOcy;
+ [©] => &copy;
+ [ª] => &Jukcy;
+ [«] => &laquo;
+ [¬] => &not;
+ [­] => &shy;
+ [®] => &reg;
+ [¯] => &YIcy;
+ [°] => &deg;
+ [±] => &plusmn;
+ [²] => &Iukcy;
+ [³] => &iukcy;
+ [µ] => &micro;
+ [¶] => &para;
+ [·] => &CenterDot;
+ [¸] => &iocy;
+ [¹] => &numero;
+ [º] => &jukcy;
+ [»] => &raquo;
+ [¼] => &jsercy;
+ [½] => &DScy;
+ [¾] => &dscy;
+ [¿] => &yicy;
+ [À] => &Acy;
+ [Á] => &Bcy;
+ [Â] => &Vcy;
+ [Ã] => &Gcy;
+ [Ä] => &Dcy;
+ [Å] => &IEcy;
+ [Æ] => &ZHcy;
+ [Ç] => &Zcy;
+ [È] => &Icy;
+ [É] => &Jcy;
+ [Ê] => &Kcy;
+ [Ë] => &Lcy;
+ [Ì] => &Mcy;
+ [Í] => &Ncy;
+ [Î] => &Ocy;
+ [Ï] => &Pcy;
+ [Ð] => &Rcy;
+ [Ñ] => &Scy;
+ [Ò] => &Tcy;
+ [Ó] => &Ucy;
+ [Ô] => &Fcy;
+ [Õ] => &KHcy;
+ [Ö] => &TScy;
+ [×] => &CHcy;
+ [Ø] => &SHcy;
+ [Ù] => &SHCHcy;
+ [Ú] => &HARDcy;
+ [Û] => &Ycy;
+ [Ü] => &SOFTcy;
+ [Ý] => &Ecy;
+ [Þ] => &YUcy;
+ [ß] => &YAcy;
+ [à] => &acy;
+ [á] => &bcy;
+ [â] => &vcy;
+ [ã] => &gcy;
+ [ä] => &dcy;
+ [å] => &iecy;
+ [æ] => &zhcy;
+ [ç] => &zcy;
+ [è] => &icy;
+ [é] => &jcy;
+ [ê] => &kcy;
+ [ë] => &lcy;
+ [ì] => &mcy;
+ [í] => &ncy;
+ [î] => &ocy;
+ [ï] => &pcy;
+ [ð] => &rcy;
+ [ñ] => &scy;
+ [ò] => &tcy;
+ [ó] => &ucy;
+ [ô] => &fcy;
+ [õ] => &khcy;
+ [ö] => &tscy;
+ [÷] => &chcy;
+ [ø] => &shcy;
+ [ù] => &shchcy;
+ [ú] => &hardcy;
+ [û] => &ycy;
+ [ü] => &softcy;
+ [ý] => &ecy;
+ [þ] => &yucy;
+ [ÿ] => &yacy;
+)
+-- with table = HTML_ENTITIES, ENT_QUOTES --
+int(158)
+-- with table = HTML_ENTITIES, ENT_NOQUOTES --
+int(156)
+-- with table = HTML_SPECIALCHARS, ENT_COMPAT --
+int(4)
+Array
+(
+ ["] => &quot;
+ [&] => &amp;
+ [<] => &lt;
+ [>] => &gt;
+)
+-- with table = HTML_SPECIALCHARS, ENT_QUOTES --
+array(5) {
+ ["""]=>
+ string(6) "&quot;"
+ ["&"]=>
+ string(5) "&amp;"
+ ["'"]=>
+ string(6) "&apos;"
+ ["<"]=>
+ string(4) "&lt;"
+ [">"]=>
+ string(4) "&gt;"
+}
+-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --
+array(3) {
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["&"]=>
+ string(5) "&amp;"
+}
+Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic7.phpt b/ext/standard/tests/strings/get_html_translation_table_basic7.phpt
new file mode 100644
index 0000000000..98ebbb9ac4
--- /dev/null
+++ b/ext/standard/tests/strings/get_html_translation_table_basic7.phpt
@@ -0,0 +1,342 @@
+--TEST--
+Test get_html_translation_table() function : basic functionality - XHTML 1.0
+--FILE--
+<?php
+echo "*** Testing get_html_translation_table() : basic functionality/XHTML 1.0 ***\n";
+
+echo "-- with table = HTML_ENTITIES, ENT_QUOTES --\n";
+$table = HTML_ENTITIES;
+/* uses &#039; to share the code path with HTML 4.01 */
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_XHTML, "UTF-8");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_ENTITIES, ENT_COMPAT --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_COMPAT | ENT_XHTML, "UTF-8");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_ENTITIES, ENT_NOQUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_XHTML, "UTF-8");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_COMPAT --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_COMPAT, "UTF-8");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_QUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_XHTML, "UTF-8");
+asort( $tt );
+var_dump( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_XHTML, "UTF-8");
+asort( $tt );
+var_dump( $tt );
+
+
+echo "Done\n";
+?>
+--EXPECT--
+*** Testing get_html_translation_table() : basic functionality/XHTML 1.0 ***
+-- with table = HTML_ENTITIES, ENT_QUOTES --
+int(253)
+Array
+(
+ ['] => &#039;
+ [Æ] => &AElig;
+ [Ã] => &Aacute;
+ [Â] => &Acirc;
+ [À] => &Agrave;
+ [Α] => &Alpha;
+ [Ã…] => &Aring;
+ [Ã] => &Atilde;
+ [Ä] => &Auml;
+ [Î’] => &Beta;
+ [Ç] => &Ccedil;
+ [Χ] => &Chi;
+ [‡] => &Dagger;
+ [Δ] => &Delta;
+ [Ã] => &ETH;
+ [É] => &Eacute;
+ [Ê] => &Ecirc;
+ [È] => &Egrave;
+ [Ε] => &Epsilon;
+ [Η] => &Eta;
+ [Ë] => &Euml;
+ [Γ] => &Gamma;
+ [Ã] => &Iacute;
+ [ÃŽ] => &Icirc;
+ [Ì] => &Igrave;
+ [Ι] => &Iota;
+ [Ã] => &Iuml;
+ [Κ] => &Kappa;
+ [Λ] => &Lambda;
+ [Μ] => &Mu;
+ [Ñ] => &Ntilde;
+ [Î] => &Nu;
+ [Å’] => &OElig;
+ [Ó] => &Oacute;
+ [Ô] => &Ocirc;
+ [Ã’] => &Ograve;
+ [Ω] => &Omega;
+ [Ο] => &Omicron;
+ [Ø] => &Oslash;
+ [Õ] => &Otilde;
+ [Ö] => &Ouml;
+ [Φ] => &Phi;
+ [Π] => &Pi;
+ [″] => &Prime;
+ [Ψ] => &Psi;
+ [Ρ] => &Rho;
+ [Å ] => &Scaron;
+ [Σ] => &Sigma;
+ [Þ] => &THORN;
+ [Τ] => &Tau;
+ [Θ] => &Theta;
+ [Ú] => &Uacute;
+ [Û] => &Ucirc;
+ [Ù] => &Ugrave;
+ [Î¥] => &Upsilon;
+ [Ü] => &Uuml;
+ [Ξ] => &Xi;
+ [Ã] => &Yacute;
+ [Ÿ] => &Yuml;
+ [Ζ] => &Zeta;
+ [á] => &aacute;
+ [â] => &acirc;
+ [´] => &acute;
+ [æ] => &aelig;
+ [à] => &agrave;
+ [ℵ] => &alefsym;
+ [α] => &alpha;
+ [&] => &amp;
+ [∧] => &and;
+ [∠] => &ang;
+ [Ã¥] => &aring;
+ [≈] => &asymp;
+ [ã] => &atilde;
+ [ä] => &auml;
+ [„] => &bdquo;
+ [β] => &beta;
+ [¦] => &brvbar;
+ [•] => &bull;
+ [∩] => &cap;
+ [ç] => &ccedil;
+ [¸] => &cedil;
+ [¢] => &cent;
+ [χ] => &chi;
+ [ˆ] => &circ;
+ [♣] => &clubs;
+ [≅] => &cong;
+ [©] => &copy;
+ [↵] => &crarr;
+ [∪] => &cup;
+ [¤] => &curren;
+ [⇓] => &dArr;
+ [†] => &dagger;
+ [↓] => &darr;
+ [°] => &deg;
+ [δ] => &delta;
+ [♦] => &diams;
+ [÷] => &divide;
+ [é] => &eacute;
+ [ê] => &ecirc;
+ [è] => &egrave;
+ [∅] => &empty;
+ [ ] => &emsp;
+ [ ] => &ensp;
+ [ε] => &epsilon;
+ [≡] => &equiv;
+ [η] => &eta;
+ [ð] => &eth;
+ [ë] => &euml;
+ [€] => &euro;
+ [∃] => &exist;
+ [Æ’] => &fnof;
+ [∀] => &forall;
+ [½] => &frac12;
+ [¼] => &frac14;
+ [¾] => &frac34;
+ [â„] => &frasl;
+ [γ] => &gamma;
+ [≥] => &ge;
+ [>] => &gt;
+ [⇔] => &hArr;
+ [↔] => &harr;
+ [♥] => &hearts;
+ […] => &hellip;
+ [í] => &iacute;
+ [î] => &icirc;
+ [¡] => &iexcl;
+ [ì] => &igrave;
+ [â„‘] => &image;
+ [∞] => &infin;
+ [∫] => &int;
+ [ι] => &iota;
+ [¿] => &iquest;
+ [∈] => &isin;
+ [ï] => &iuml;
+ [κ] => &kappa;
+ [â‡] => &lArr;
+ [λ] => &lambda;
+ [〈] => &lang;
+ [«] => &laquo;
+ [â†] => &larr;
+ [⌈] => &lceil;
+ [“] => &ldquo;
+ [≤] => &le;
+ [⌊] => &lfloor;
+ [∗] => &lowast;
+ [â—Š] => &loz;
+ [‎] => &lrm;
+ [‹] => &lsaquo;
+ [‘] => &lsquo;
+ [<] => &lt;
+ [¯] => &macr;
+ [—] => &mdash;
+ [µ] => &micro;
+ [·] => &middot;
+ [−] => &minus;
+ [μ] => &mu;
+ [∇] => &nabla;
+ [ ] => &nbsp;
+ [–] => &ndash;
+ [≠] => &ne;
+ [∋] => &ni;
+ [¬] => &not;
+ [∉] => &notin;
+ [⊄] => &nsub;
+ [ñ] => &ntilde;
+ [ν] => &nu;
+ [ó] => &oacute;
+ [ô] => &ocirc;
+ [Å“] => &oelig;
+ [ò] => &ograve;
+ [‾] => &oline;
+ [ω] => &omega;
+ [ο] => &omicron;
+ [⊕] => &oplus;
+ [∨] => &or;
+ [ª] => &ordf;
+ [º] => &ordm;
+ [ø] => &oslash;
+ [õ] => &otilde;
+ [⊗] => &otimes;
+ [ö] => &ouml;
+ [¶] => &para;
+ [∂] => &part;
+ [‰] => &permil;
+ [⊥] => &perp;
+ [φ] => &phi;
+ [Ï€] => &pi;
+ [Ï–] => &piv;
+ [±] => &plusmn;
+ [£] => &pound;
+ [′] => &prime;
+ [âˆ] => &prod;
+ [âˆ] => &prop;
+ [ψ] => &psi;
+ ["] => &quot;
+ [⇒] => &rArr;
+ [√] => &radic;
+ [〉] => &rang;
+ [»] => &raquo;
+ [→] => &rarr;
+ [⌉] => &rceil;
+ [â€] => &rdquo;
+ [ℜ] => &real;
+ [®] => &reg;
+ [⌋] => &rfloor;
+ [Ï] => &rho;
+ [â€] => &rlm;
+ [›] => &rsaquo;
+ [’] => &rsquo;
+ [‚] => &sbquo;
+ [Å¡] => &scaron;
+ [â‹…] => &sdot;
+ [§] => &sect;
+ [­] => &shy;
+ [σ] => &sigma;
+ [Ï‚] => &sigmaf;
+ [∼] => &sim;
+ [â™ ] => &spades;
+ [⊂] => &sub;
+ [⊆] => &sube;
+ [∑] => &sum;
+ [¹] => &sup1;
+ [²] => &sup2;
+ [³] => &sup3;
+ [⊃] => &sup;
+ [⊇] => &supe;
+ [ß] => &szlig;
+ [Ï„] => &tau;
+ [∴] => &there4;
+ [θ] => &theta;
+ [Ï‘] => &thetasym;
+ [ ] => &thinsp;
+ [þ] => &thorn;
+ [˜] => &tilde;
+ [×] => &times;
+ [â„¢] => &trade;
+ [⇑] => &uArr;
+ [ú] => &uacute;
+ [↑] => &uarr;
+ [û] => &ucirc;
+ [ù] => &ugrave;
+ [¨] => &uml;
+ [Ï’] => &upsih;
+ [Ï…] => &upsilon;
+ [ü] => &uuml;
+ [℘] => &weierp;
+ [ξ] => &xi;
+ [ý] => &yacute;
+ [Â¥] => &yen;
+ [ÿ] => &yuml;
+ [ζ] => &zeta;
+ [â€] => &zwj;
+ [‌] => &zwnj;
+)
+-- with table = HTML_ENTITIES, ENT_COMPAT --
+int(252)
+-- with table = HTML_ENTITIES, ENT_NOQUOTES --
+int(251)
+-- with table = HTML_SPECIALCHARS, ENT_COMPAT --
+int(4)
+Array
+(
+ [&] => &amp;
+ [>] => &gt;
+ [<] => &lt;
+ ["] => &quot;
+)
+-- with table = HTML_SPECIALCHARS, ENT_QUOTES --
+array(5) {
+ ["&"]=>
+ string(5) "&amp;"
+ ["'"]=>
+ string(6) "&apos;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
+}
+-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --
+array(3) {
+ ["&"]=>
+ string(5) "&amp;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+}
+Done \ No newline at end of file
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic8.phpt b/ext/standard/tests/strings/get_html_translation_table_basic8.phpt
new file mode 100644
index 0000000000..8f8ca580ea
--- /dev/null
+++ b/ext/standard/tests/strings/get_html_translation_table_basic8.phpt
@@ -0,0 +1,93 @@
+--TEST--
+Test get_html_translation_table() function : basic functionality - XML 1.0
+--FILE--
+<?php
+echo "*** Testing get_html_translation_table() : basic functionality/XML 1.0 ***\n";
+
+echo "-- with table = HTML_ENTITIES, ENT_QUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_XML1, "UTF-8");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_ENTITIES, ENT_COMPAT --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_COMPAT | ENT_XML1, "UTF-8");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_ENTITIES, ENT_NOQUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_XML1, "UTF-8");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_COMPAT --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_COMPAT, "UTF-8");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_QUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_XML1, "UTF-8");
+asort( $tt );
+var_dump( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_XML1, "UTF-8");
+asort( $tt );
+var_dump( $tt );
+
+
+echo "Done\n";
+?>
+--EXPECT--
+*** Testing get_html_translation_table() : basic functionality/XML 1.0 ***
+-- with table = HTML_ENTITIES, ENT_QUOTES --
+int(5)
+Array
+(
+ [&] => &amp;
+ ['] => &apos;
+ [>] => &gt;
+ [<] => &lt;
+ ["] => &quot;
+)
+-- with table = HTML_ENTITIES, ENT_COMPAT --
+int(4)
+-- with table = HTML_ENTITIES, ENT_NOQUOTES --
+int(3)
+-- with table = HTML_SPECIALCHARS, ENT_COMPAT --
+int(4)
+Array
+(
+ [&] => &amp;
+ [>] => &gt;
+ [<] => &lt;
+ ["] => &quot;
+)
+-- with table = HTML_SPECIALCHARS, ENT_QUOTES --
+array(5) {
+ ["&"]=>
+ string(5) "&amp;"
+ ["'"]=>
+ string(6) "&apos;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
+}
+-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --
+array(3) {
+ ["&"]=>
+ string(5) "&amp;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+}
+Done
diff --git a/ext/standard/tests/strings/get_html_translation_table_basic9.phpt b/ext/standard/tests/strings/get_html_translation_table_basic9.phpt
new file mode 100644
index 0000000000..cd32cccd5f
--- /dev/null
+++ b/ext/standard/tests/strings/get_html_translation_table_basic9.phpt
@@ -0,0 +1,95 @@
+--TEST--
+Test get_html_translation_table() function : basic functionality - HTML5 /sjis
+--FILE--
+<?php
+echo "*** Testing get_html_translation_table() : basic functionality/HTML5/SJIS ***\n";
+echo "*** Only basic entities supported! ***\n";
+
+echo "-- with table = HTML_ENTITIES, ENT_QUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_HTML5, "SJIS");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_ENTITIES, ENT_COMPAT --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_COMPAT | ENT_HTML5, "SJIS");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_ENTITIES, ENT_NOQUOTES --\n";
+$table = HTML_ENTITIES;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_HTML5, "SJIS");
+var_dump( count($tt) );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_COMPAT --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_COMPAT, "SJIS");
+asort( $tt );
+var_dump( count($tt) );
+print_r( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_QUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_QUOTES | ENT_HTML5, "SJIS");
+asort( $tt );
+var_dump( $tt );
+
+echo "-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --\n";
+$table = HTML_SPECIALCHARS;
+$tt = get_html_translation_table($table, ENT_NOQUOTES | ENT_HTML5, "SJIS");
+asort( $tt );
+var_dump( $tt );
+
+
+echo "Done\n";
+?>
+--EXPECT--
+*** Testing get_html_translation_table() : basic functionality/HTML5/SJIS ***
+*** Only basic entities supported! ***
+-- with table = HTML_ENTITIES, ENT_QUOTES --
+int(5)
+Array
+(
+ [&] => &amp;
+ ['] => &apos;
+ [>] => &gt;
+ [<] => &lt;
+ ["] => &quot;
+)
+-- with table = HTML_ENTITIES, ENT_COMPAT --
+int(4)
+-- with table = HTML_ENTITIES, ENT_NOQUOTES --
+int(3)
+-- with table = HTML_SPECIALCHARS, ENT_COMPAT --
+int(4)
+Array
+(
+ [&] => &amp;
+ [>] => &gt;
+ [<] => &lt;
+ ["] => &quot;
+)
+-- with table = HTML_SPECIALCHARS, ENT_QUOTES --
+array(5) {
+ ["&"]=>
+ string(5) "&amp;"
+ ["'"]=>
+ string(6) "&apos;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
+}
+-- with table = HTML_SPECIALCHARS, ENT_NOQUOTES --
+array(3) {
+ ["&"]=>
+ string(5) "&amp;"
+ [">"]=>
+ string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+}
+Done \ No newline at end of file
diff --git a/ext/standard/tests/strings/get_html_translation_table_variation1.phpt b/ext/standard/tests/strings/get_html_translation_table_variation1.phpt
index edae95a2e8..7f7e229354 100644
--- a/ext/standard/tests/strings/get_html_translation_table_variation1.phpt
+++ b/ext/standard/tests/strings/get_html_translation_table_variation1.phpt
@@ -75,14 +75,22 @@ for($index = 0; $index < count($values); $index ++) {
$v = get_html_translation_table($table, ENT_COMPAT, "UTF-8");
if (is_array($v) && count($v) > 100)
var_dump(count($v));
- else
+ elseif (is_array($v)) {
+ asort($v);
var_dump($v);
+ } else {
+ var_dump($v);
+ }
$v = get_html_translation_table($table, $quote_style, "UTF-8");
if (is_array($v) && count($v) > 100)
var_dump(count($v));
- else
+ elseif (is_array($v)) {
+ asort($v);
+ var_dump($v);
+ } else {
var_dump($v);
+ }
$counter ++;
}
@@ -138,22 +146,22 @@ int(252)
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- Iteration 8 --
int(252)
@@ -162,22 +170,22 @@ int(252)
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- Iteration 10 --
@@ -218,43 +226,43 @@ NULL
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- Iteration 16 --
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- Iteration 17 --
@@ -267,42 +275,42 @@ NULL
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
-- Iteration 19 --
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
array(4) {
["&"]=>
string(5) "&amp;"
- ["""]=>
- string(6) "&quot;"
- ["<"]=>
- string(4) "&lt;"
[">"]=>
string(4) "&gt;"
+ ["<"]=>
+ string(4) "&lt;"
+ ["""]=>
+ string(6) "&quot;"
}
Done
diff --git a/ext/standard/tests/strings/highlight_file.phpt b/ext/standard/tests/strings/highlight_file.phpt
index 709e57dc00..d1a0323c58 100644
--- a/ext/standard/tests/strings/highlight_file.phpt
+++ b/ext/standard/tests/strings/highlight_file.phpt
@@ -4,7 +4,6 @@ highlight_file() tests
highlight.string=#DD0000
highlight.comment=#FF9900
highlight.keyword=#007700
-highlight.bg=#FFFFFF
highlight.default=#0000BB
highlight.html=#000000
allow_url_include=1
diff --git a/ext/standard/tests/strings/html_entity_decode1.phpt b/ext/standard/tests/strings/html_entity_decode1.phpt
new file mode 100644
index 0000000000..5eabfc35a5
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode1.phpt
@@ -0,0 +1,67 @@
+--TEST--
+html_entity_decode: Decoding of entities after invalid entities
+--FILE--
+<?php
+$arr = array(
+ "&",
+ "&&amp;",
+ "&&#x24;",
+ "&#&amp;",
+ "&#&#x24;",
+ "&#x&amp;",
+ "&#x&#x24;",
+ "&#x1&amp;",
+ "&#x1&#x24;",
+ "&#x20&amp;",
+ "&#x20&#x24;",
+ "&#1&amp;",
+ "&#1&#x24;",
+ "&#20&amp;",
+ "&#20&#x24;",
+ "&a&amp;",
+ "&a&#x24;",
+ "&aa&amp;",
+ "&aa&#x24;",
+ "&aa;&amp;",
+ "&aa;&#x24;",
+ "&;&amp;",
+ "&;&#x24;",
+);
+
+$i = 0;
+foreach ($arr as $ent) {
+ if ($i % 2 == 1) {
+ if (($a = html_entity_decode($ent, ENT_QUOTES, 'UTF-8')) !=
+ ($b = htmlspecialchars_decode($ent, ENT_QUOTES))) {
+ echo "htmlspecialchars_decode <-> html_entity_decode inconsistency","\n",
+ "$b <-> $a","\n";
+ }
+ }
+ echo html_entity_decode($ent, ENT_QUOTES, 'UTF-8'), "\n";
+}
+echo "Done.\n";
+--EXPECT--
+&
+&&
+&$
+&#&
+&#$
+&#x&
+&#x$
+&#x1&
+&#x1$
+&#x20&
+&#x20$
+&#1&
+&#1$
+&#20&
+&#20$
+&a&
+&a$
+&aa&
+&aa$
+&aa;&
+&aa;$
+&;&
+&;$
+Done. \ No newline at end of file
diff --git a/ext/standard/tests/strings/html_entity_decode2.phpt b/ext/standard/tests/strings/html_entity_decode2.phpt
new file mode 100644
index 0000000000..b8a6e49eb3
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode2.phpt
@@ -0,0 +1,33 @@
+--TEST--
+html_entity_decode: Handling of &apos;
+--FILE--
+<?php
+
+echo "*** HTML 4.01 implicit (shouldn't decode) ***\n";
+echo html_entity_decode("&apos;", ENT_QUOTES, "UTF-8"), "\n";
+
+echo "*** HTML 4.01 (shouldn't decode) ***\n";
+echo html_entity_decode("&apos;", ENT_QUOTES | ENT_HTML401, "UTF-8"), "\n";
+
+echo "*** HTML 5 ***\n";
+echo html_entity_decode("&apos;", ENT_QUOTES | ENT_HTML5, "UTF-8"), "\n";
+
+echo "*** XHTML 1.0 ***\n";
+echo html_entity_decode("&apos;", ENT_QUOTES | ENT_XHTML, "UTF-8"), "\n";
+
+echo "*** XML 1.0 ***\n";
+echo html_entity_decode("&apos;", ENT_QUOTES | ENT_XML1, "UTF-8"), "\n";
+
+echo "Done.\n";
+--EXPECT--
+*** HTML 4.01 implicit (shouldn't decode) ***
+&apos;
+*** HTML 4.01 (shouldn't decode) ***
+&apos;
+*** HTML 5 ***
+'
+*** XHTML 1.0 ***
+'
+*** XML 1.0 ***
+'
+Done. \ No newline at end of file
diff --git a/ext/standard/tests/strings/html_entity_decode3.phpt b/ext/standard/tests/strings/html_entity_decode3.phpt
new file mode 100644
index 0000000000..fcf2710679
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode3.phpt
@@ -0,0 +1,193 @@
+--TEST--
+html_entity_decode: Do not decode numerical entities that refer to non-SGML or otherwise disallowed chars
+--FILE--
+<?php
+
+$tests = array(
+ "&#0;", //C0
+ "&#1;",
+ "&#x09;",
+ "&#x0A;",
+ "&#x0B;",
+ "&#x0C;",
+ "&#x0D;", //note that HTML5 is unique in that it forbids this entity, but allows a literal U+0D
+ "&#x0E;",
+ "&#x1F;",
+ "&#x20;", //allowed always
+ "&#x7F;", //DEL
+ "&#x80;", //C1
+ "&#x9F;",
+ "&#xA0;", //allowed always
+ "&#xD7FF;", //surrogates
+ "&#xD800;",
+ "&#xDFFF;",
+ "&#xE000;", //allowed always
+ "&#xFFFE;", //nonchar
+ "&#xFFFF;",
+ "&#xFDCF;", //allowed always
+ "&#xFDD0;", //nonchar
+ "&#xFDEF;",
+ "&#xFDF0;", //allowed always
+ "&#x2FFFE;", //nonchar
+ "&#x2FFFF;",
+);
+
+echo "*** HTML 4.01 ***\n";
+
+foreach ($tests as $t) {
+ $dec = html_entity_decode($t, ENT_QUOTES | ENT_HTML401, "UTF-8");
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** XHTML 1.0 ***\n";
+
+foreach ($tests as $t) {
+ $dec = html_entity_decode($t, ENT_QUOTES | ENT_XHTML, "UTF-8");
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** HTML5 ***\n";
+
+foreach ($tests as $t) {
+ $dec = html_entity_decode($t, ENT_QUOTES | ENT_HTML5, "UTF-8");
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** XML 1.0 ***\n";
+
+foreach ($tests as $t) {
+ $dec = html_entity_decode($t, ENT_QUOTES | ENT_XML1, "UTF-8");
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\nDone.\n";
+--EXPECT--
+*** HTML 4.01 ***
+&#0; NOT DECODED
+&#1; NOT DECODED
+&#x09; DECODED
+&#x0A; DECODED
+&#x0B; NOT DECODED
+&#x0C; NOT DECODED
+&#x0D; DECODED
+&#x0E; NOT DECODED
+&#x1F; NOT DECODED
+&#x20; DECODED
+&#x7F; NOT DECODED
+&#x80; NOT DECODED
+&#x9F; NOT DECODED
+&#xA0; DECODED
+&#xD7FF; DECODED
+&#xD800; NOT DECODED
+&#xDFFF; NOT DECODED
+&#xE000; DECODED
+&#xFFFE; DECODED
+&#xFFFF; DECODED
+&#xFDCF; DECODED
+&#xFDD0; DECODED
+&#xFDEF; DECODED
+&#xFDF0; DECODED
+&#x2FFFE; DECODED
+&#x2FFFF; DECODED
+
+*** XHTML 1.0 ***
+&#0; NOT DECODED
+&#1; NOT DECODED
+&#x09; DECODED
+&#x0A; DECODED
+&#x0B; NOT DECODED
+&#x0C; NOT DECODED
+&#x0D; DECODED
+&#x0E; NOT DECODED
+&#x1F; NOT DECODED
+&#x20; DECODED
+&#x7F; DECODED
+&#x80; DECODED
+&#x9F; DECODED
+&#xA0; DECODED
+&#xD7FF; DECODED
+&#xD800; NOT DECODED
+&#xDFFF; NOT DECODED
+&#xE000; DECODED
+&#xFFFE; NOT DECODED
+&#xFFFF; NOT DECODED
+&#xFDCF; DECODED
+&#xFDD0; DECODED
+&#xFDEF; DECODED
+&#xFDF0; DECODED
+&#x2FFFE; DECODED
+&#x2FFFF; DECODED
+
+*** HTML5 ***
+&#0; NOT DECODED
+&#1; NOT DECODED
+&#x09; DECODED
+&#x0A; DECODED
+&#x0B; NOT DECODED
+&#x0C; DECODED
+&#x0D; NOT DECODED
+&#x0E; NOT DECODED
+&#x1F; NOT DECODED
+&#x20; DECODED
+&#x7F; NOT DECODED
+&#x80; NOT DECODED
+&#x9F; NOT DECODED
+&#xA0; DECODED
+&#xD7FF; DECODED
+&#xD800; NOT DECODED
+&#xDFFF; NOT DECODED
+&#xE000; DECODED
+&#xFFFE; NOT DECODED
+&#xFFFF; NOT DECODED
+&#xFDCF; DECODED
+&#xFDD0; NOT DECODED
+&#xFDEF; NOT DECODED
+&#xFDF0; DECODED
+&#x2FFFE; NOT DECODED
+&#x2FFFF; NOT DECODED
+
+*** XML 1.0 ***
+&#0; NOT DECODED
+&#1; NOT DECODED
+&#x09; DECODED
+&#x0A; DECODED
+&#x0B; NOT DECODED
+&#x0C; NOT DECODED
+&#x0D; DECODED
+&#x0E; NOT DECODED
+&#x1F; NOT DECODED
+&#x20; DECODED
+&#x7F; DECODED
+&#x80; DECODED
+&#x9F; DECODED
+&#xA0; DECODED
+&#xD7FF; DECODED
+&#xD800; NOT DECODED
+&#xDFFF; NOT DECODED
+&#xE000; DECODED
+&#xFFFE; NOT DECODED
+&#xFFFF; NOT DECODED
+&#xFDCF; DECODED
+&#xFDD0; DECODED
+&#xFDEF; DECODED
+&#xFDF0; DECODED
+&#x2FFFE; DECODED
+&#x2FFFF; DECODED
+
+Done.
diff --git a/ext/standard/tests/strings/html_entity_decode_cp866.phpt b/ext/standard/tests/strings/html_entity_decode_cp866.phpt
new file mode 100644
index 0000000000..76323be30b
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_cp866.phpt
@@ -0,0 +1,533 @@
+--TEST--
+Translation of HTML entities for encoding CP866
+--FILE--
+<?php
+$arr = array(
+0x0410 => array(0x80, "CYRILLIC CAPITAL LETTER A"),
+0x0411 => array(0x81, "CYRILLIC CAPITAL LETTER BE"),
+0x0412 => array(0x82, "CYRILLIC CAPITAL LETTER VE"),
+0x0413 => array(0x83, "CYRILLIC CAPITAL LETTER GHE"),
+0x0414 => array(0x84, "CYRILLIC CAPITAL LETTER DE"),
+0x0415 => array(0x85, "CYRILLIC CAPITAL LETTER IE"),
+0x0416 => array(0x86, "CYRILLIC CAPITAL LETTER ZHE"),
+0x0417 => array(0x87, "CYRILLIC CAPITAL LETTER ZE"),
+0x0418 => array(0x88, "CYRILLIC CAPITAL LETTER I"),
+0x0419 => array(0x89, "CYRILLIC CAPITAL LETTER SHORT I"),
+0x041a => array(0x8a, "CYRILLIC CAPITAL LETTER KA"),
+0x041b => array(0x8b, "CYRILLIC CAPITAL LETTER EL"),
+0x041c => array(0x8c, "CYRILLIC CAPITAL LETTER EM"),
+0x041d => array(0x8d, "CYRILLIC CAPITAL LETTER EN"),
+0x041e => array(0x8e, "CYRILLIC CAPITAL LETTER O"),
+0x041f => array(0x8f, "CYRILLIC CAPITAL LETTER PE"),
+0x0420 => array(0x90, "CYRILLIC CAPITAL LETTER ER"),
+0x0421 => array(0x91, "CYRILLIC CAPITAL LETTER ES"),
+0x0422 => array(0x92, "CYRILLIC CAPITAL LETTER TE"),
+0x0423 => array(0x93, "CYRILLIC CAPITAL LETTER U"),
+0x0424 => array(0x94, "CYRILLIC CAPITAL LETTER EF"),
+0x0425 => array(0x95, "CYRILLIC CAPITAL LETTER HA"),
+0x0426 => array(0x96, "CYRILLIC CAPITAL LETTER TSE"),
+0x0427 => array(0x97, "CYRILLIC CAPITAL LETTER CHE"),
+0x0428 => array(0x98, "CYRILLIC CAPITAL LETTER SHA"),
+0x0429 => array(0x99, "CYRILLIC CAPITAL LETTER SHCHA"),
+0x042a => array(0x9a, "CYRILLIC CAPITAL LETTER HARD SIGN"),
+0x042b => array(0x9b, "CYRILLIC CAPITAL LETTER YERU"),
+0x042c => array(0x9c, "CYRILLIC CAPITAL LETTER SOFT SIGN"),
+0x042d => array(0x9d, "CYRILLIC CAPITAL LETTER E"),
+0x042e => array(0x9e, "CYRILLIC CAPITAL LETTER YU"),
+0x042f => array(0x9f, "CYRILLIC CAPITAL LETTER YA"),
+0x0430 => array(0xa0, "CYRILLIC SMALL LETTER A"),
+0x0431 => array(0xa1, "CYRILLIC SMALL LETTER BE"),
+0x0432 => array(0xa2, "CYRILLIC SMALL LETTER VE"),
+0x0433 => array(0xa3, "CYRILLIC SMALL LETTER GHE"),
+0x0434 => array(0xa4, "CYRILLIC SMALL LETTER DE"),
+0x0435 => array(0xa5, "CYRILLIC SMALL LETTER IE"),
+0x0436 => array(0xa6, "CYRILLIC SMALL LETTER ZHE"),
+0x0437 => array(0xa7, "CYRILLIC SMALL LETTER ZE"),
+0x0438 => array(0xa8, "CYRILLIC SMALL LETTER I"),
+0x0439 => array(0xa9, "CYRILLIC SMALL LETTER SHORT I"),
+0x043a => array(0xaa, "CYRILLIC SMALL LETTER KA"),
+0x043b => array(0xab, "CYRILLIC SMALL LETTER EL"),
+0x043c => array(0xac, "CYRILLIC SMALL LETTER EM"),
+0x043d => array(0xad, "CYRILLIC SMALL LETTER EN"),
+0x043e => array(0xae, "CYRILLIC SMALL LETTER O"),
+0x043f => array(0xaf, "CYRILLIC SMALL LETTER PE"),
+0x2591 => array(0xb0, "LIGHT SHADE"),
+0x2592 => array(0xb1, "MEDIUM SHADE"),
+0x2593 => array(0xb2, "DARK SHADE"),
+0x2502 => array(0xb3, "BOX DRAWINGS LIGHT VERTICAL"),
+0x2524 => array(0xb4, "BOX DRAWINGS LIGHT VERTICAL AND LEFT"),
+0x2561 => array(0xb5, "BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE"),
+0x2562 => array(0xb6, "BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE"),
+0x2556 => array(0xb7, "BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE"),
+0x2555 => array(0xb8, "BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE"),
+0x2563 => array(0xb9, "BOX DRAWINGS DOUBLE VERTICAL AND LEFT"),
+0x2551 => array(0xba, "BOX DRAWINGS DOUBLE VERTICAL"),
+0x2557 => array(0xbb, "BOX DRAWINGS DOUBLE DOWN AND LEFT"),
+0x255d => array(0xbc, "BOX DRAWINGS DOUBLE UP AND LEFT"),
+0x255c => array(0xbd, "BOX DRAWINGS UP DOUBLE AND LEFT SINGLE"),
+0x255b => array(0xbe, "BOX DRAWINGS UP SINGLE AND LEFT DOUBLE"),
+0x2510 => array(0xbf, "BOX DRAWINGS LIGHT DOWN AND LEFT"),
+0x2514 => array(0xc0, "BOX DRAWINGS LIGHT UP AND RIGHT"),
+0x2534 => array(0xc1, "BOX DRAWINGS LIGHT UP AND HORIZONTAL"),
+0x252c => array(0xc2, "BOX DRAWINGS LIGHT DOWN AND HORIZONTAL"),
+0x251c => array(0xc3, "BOX DRAWINGS LIGHT VERTICAL AND RIGHT"),
+0x2500 => array(0xc4, "BOX DRAWINGS LIGHT HORIZONTAL"),
+0x253c => array(0xc5, "BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL"),
+0x255e => array(0xc6, "BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE"),
+0x255f => array(0xc7, "BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE"),
+0x255a => array(0xc8, "BOX DRAWINGS DOUBLE UP AND RIGHT"),
+0x2554 => array(0xc9, "BOX DRAWINGS DOUBLE DOWN AND RIGHT"),
+0x2569 => array(0xca, "BOX DRAWINGS DOUBLE UP AND HORIZONTAL"),
+0x2566 => array(0xcb, "BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL"),
+0x2560 => array(0xcc, "BOX DRAWINGS DOUBLE VERTICAL AND RIGHT"),
+0x2550 => array(0xcd, "BOX DRAWINGS DOUBLE HORIZONTAL"),
+0x256c => array(0xce, "BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL"),
+0x2567 => array(0xcf, "BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE"),
+0x2568 => array(0xd0, "BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE"),
+0x2564 => array(0xd1, "BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE"),
+0x2565 => array(0xd2, "BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE"),
+0x2559 => array(0xd3, "BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE"),
+0x2558 => array(0xd4, "BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE"),
+0x2552 => array(0xd5, "BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE"),
+0x2553 => array(0xd6, "BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE"),
+0x256b => array(0xd7, "BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE"),
+0x256a => array(0xd8, "BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE"),
+0x2518 => array(0xd9, "BOX DRAWINGS LIGHT UP AND LEFT"),
+0x250c => array(0xda, "BOX DRAWINGS LIGHT DOWN AND RIGHT"),
+0x2588 => array(0xdb, "FULL BLOCK"),
+0x2584 => array(0xdc, "LOWER HALF BLOCK"),
+0x258c => array(0xdd, "LEFT HALF BLOCK"),
+0x2590 => array(0xde, "RIGHT HALF BLOCK"),
+0x2580 => array(0xdf, "UPPER HALF BLOCK"),
+0x0440 => array(0xe0, "CYRILLIC SMALL LETTER ER"),
+0x0441 => array(0xe1, "CYRILLIC SMALL LETTER ES"),
+0x0442 => array(0xe2, "CYRILLIC SMALL LETTER TE"),
+0x0443 => array(0xe3, "CYRILLIC SMALL LETTER U"),
+0x0444 => array(0xe4, "CYRILLIC SMALL LETTER EF"),
+0x0445 => array(0xe5, "CYRILLIC SMALL LETTER HA"),
+0x0446 => array(0xe6, "CYRILLIC SMALL LETTER TSE"),
+0x0447 => array(0xe7, "CYRILLIC SMALL LETTER CHE"),
+0x0448 => array(0xe8, "CYRILLIC SMALL LETTER SHA"),
+0x0449 => array(0xe9, "CYRILLIC SMALL LETTER SHCHA"),
+0x044a => array(0xea, "CYRILLIC SMALL LETTER HARD SIGN"),
+0x044b => array(0xeb, "CYRILLIC SMALL LETTER YERU"),
+0x044c => array(0xec, "CYRILLIC SMALL LETTER SOFT SIGN"),
+0x044d => array(0xed, "CYRILLIC SMALL LETTER E"),
+0x044e => array(0xee, "CYRILLIC SMALL LETTER YU"),
+0x044f => array(0xef, "CYRILLIC SMALL LETTER YA"),
+0x0401 => array(0xf0, "CYRILLIC CAPITAL LETTER IO"),
+0x0451 => array(0xf1, "CYRILLIC SMALL LETTER IO"),
+0x0404 => array(0xf2, "CYRILLIC CAPITAL LETTER UKRAINIAN IE"),
+0x0454 => array(0xf3, "CYRILLIC SMALL LETTER UKRAINIAN IE"),
+0x0407 => array(0xf4, "CYRILLIC CAPITAL LETTER YI"),
+0x0457 => array(0xf5, "CYRILLIC SMALL LETTER YI"),
+0x040e => array(0xf6, "CYRILLIC CAPITAL LETTER SHORT U"),
+0x045e => array(0xf7, "CYRILLIC SMALL LETTER SHORT U"),
+0x00b0 => array(0xf8, "DEGREE SIGN"),
+0x2219 => array(0xf9, "BULLET OPERATOR"),
+0x00b7 => array(0xfa, "MIDDLE DOT"),
+0x221a => array(0xfb, "SQUARE ROOT"),
+0x2116 => array(0xfc, "NUMERO SIGN"),
+0x00a4 => array(0xfd, "CURRENCY SIGN"),
+0x25a0 => array(0xfe, "BLACK SQUARE"),
+0x00a0 => array(0xff, "NO-BREAK SPACE"),
+);
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'CP866');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'CP866');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+CYRILLIC CAPITAL LETTER A: &#x410; => 80
+&#x80; => &#x80;
+
+CYRILLIC CAPITAL LETTER BE: &#x411; => 81
+&#x81; => &#x81;
+
+CYRILLIC CAPITAL LETTER VE: &#x412; => 82
+&#x82; => &#x82;
+
+CYRILLIC CAPITAL LETTER GHE: &#x413; => 83
+&#x83; => &#x83;
+
+CYRILLIC CAPITAL LETTER DE: &#x414; => 84
+&#x84; => &#x84;
+
+CYRILLIC CAPITAL LETTER IE: &#x415; => 85
+&#x85; => &#x85;
+
+CYRILLIC CAPITAL LETTER ZHE: &#x416; => 86
+&#x86; => &#x86;
+
+CYRILLIC CAPITAL LETTER ZE: &#x417; => 87
+&#x87; => &#x87;
+
+CYRILLIC CAPITAL LETTER I: &#x418; => 88
+&#x88; => &#x88;
+
+CYRILLIC CAPITAL LETTER SHORT I: &#x419; => 89
+&#x89; => &#x89;
+
+CYRILLIC CAPITAL LETTER KA: &#x41A; => 8a
+&#x8A; => &#x8A;
+
+CYRILLIC CAPITAL LETTER EL: &#x41B; => 8b
+&#x8B; => &#x8B;
+
+CYRILLIC CAPITAL LETTER EM: &#x41C; => 8c
+&#x8C; => &#x8C;
+
+CYRILLIC CAPITAL LETTER EN: &#x41D; => 8d
+&#x8D; => &#x8D;
+
+CYRILLIC CAPITAL LETTER O: &#x41E; => 8e
+&#x8E; => &#x8E;
+
+CYRILLIC CAPITAL LETTER PE: &#x41F; => 8f
+&#x8F; => &#x8F;
+
+CYRILLIC CAPITAL LETTER ER: &#x420; => 90
+&#x90; => &#x90;
+
+CYRILLIC CAPITAL LETTER ES: &#x421; => 91
+&#x91; => &#x91;
+
+CYRILLIC CAPITAL LETTER TE: &#x422; => 92
+&#x92; => &#x92;
+
+CYRILLIC CAPITAL LETTER U: &#x423; => 93
+&#x93; => &#x93;
+
+CYRILLIC CAPITAL LETTER EF: &#x424; => 94
+&#x94; => &#x94;
+
+CYRILLIC CAPITAL LETTER HA: &#x425; => 95
+&#x95; => &#x95;
+
+CYRILLIC CAPITAL LETTER TSE: &#x426; => 96
+&#x96; => &#x96;
+
+CYRILLIC CAPITAL LETTER CHE: &#x427; => 97
+&#x97; => &#x97;
+
+CYRILLIC CAPITAL LETTER SHA: &#x428; => 98
+&#x98; => &#x98;
+
+CYRILLIC CAPITAL LETTER SHCHA: &#x429; => 99
+&#x99; => &#x99;
+
+CYRILLIC CAPITAL LETTER HARD SIGN: &#x42A; => 9a
+&#x9A; => &#x9A;
+
+CYRILLIC CAPITAL LETTER YERU: &#x42B; => 9b
+&#x9B; => &#x9B;
+
+CYRILLIC CAPITAL LETTER SOFT SIGN: &#x42C; => 9c
+&#x9C; => &#x9C;
+
+CYRILLIC CAPITAL LETTER E: &#x42D; => 9d
+&#x9D; => &#x9D;
+
+CYRILLIC CAPITAL LETTER YU: &#x42E; => 9e
+&#x9E; => &#x9E;
+
+CYRILLIC CAPITAL LETTER YA: &#x42F; => 9f
+&#x9F; => &#x9F;
+
+CYRILLIC SMALL LETTER A: &#x430; => a0
+&#xA0; => ff
+
+CYRILLIC SMALL LETTER BE: &#x431; => a1
+&#xA1; => &#xA1;
+
+CYRILLIC SMALL LETTER VE: &#x432; => a2
+&#xA2; => &#xA2;
+
+CYRILLIC SMALL LETTER GHE: &#x433; => a3
+&#xA3; => &#xA3;
+
+CYRILLIC SMALL LETTER DE: &#x434; => a4
+&#xA4; => fd
+
+CYRILLIC SMALL LETTER IE: &#x435; => a5
+&#xA5; => &#xA5;
+
+CYRILLIC SMALL LETTER ZHE: &#x436; => a6
+&#xA6; => &#xA6;
+
+CYRILLIC SMALL LETTER ZE: &#x437; => a7
+&#xA7; => &#xA7;
+
+CYRILLIC SMALL LETTER I: &#x438; => a8
+&#xA8; => &#xA8;
+
+CYRILLIC SMALL LETTER SHORT I: &#x439; => a9
+&#xA9; => &#xA9;
+
+CYRILLIC SMALL LETTER KA: &#x43A; => aa
+&#xAA; => &#xAA;
+
+CYRILLIC SMALL LETTER EL: &#x43B; => ab
+&#xAB; => &#xAB;
+
+CYRILLIC SMALL LETTER EM: &#x43C; => ac
+&#xAC; => &#xAC;
+
+CYRILLIC SMALL LETTER EN: &#x43D; => ad
+&#xAD; => &#xAD;
+
+CYRILLIC SMALL LETTER O: &#x43E; => ae
+&#xAE; => &#xAE;
+
+CYRILLIC SMALL LETTER PE: &#x43F; => af
+&#xAF; => &#xAF;
+
+LIGHT SHADE: &#x2591; => b0
+&#xB0; => f8
+
+MEDIUM SHADE: &#x2592; => b1
+&#xB1; => &#xB1;
+
+DARK SHADE: &#x2593; => b2
+&#xB2; => &#xB2;
+
+BOX DRAWINGS LIGHT VERTICAL: &#x2502; => b3
+&#xB3; => &#xB3;
+
+BOX DRAWINGS LIGHT VERTICAL AND LEFT: &#x2524; => b4
+&#xB4; => &#xB4;
+
+BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE: &#x2561; => b5
+&#xB5; => &#xB5;
+
+BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE: &#x2562; => b6
+&#xB6; => &#xB6;
+
+BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE: &#x2556; => b7
+&#xB7; => fa
+
+BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE: &#x2555; => b8
+&#xB8; => &#xB8;
+
+BOX DRAWINGS DOUBLE VERTICAL AND LEFT: &#x2563; => b9
+&#xB9; => &#xB9;
+
+BOX DRAWINGS DOUBLE VERTICAL: &#x2551; => ba
+&#xBA; => &#xBA;
+
+BOX DRAWINGS DOUBLE DOWN AND LEFT: &#x2557; => bb
+&#xBB; => &#xBB;
+
+BOX DRAWINGS DOUBLE UP AND LEFT: &#x255D; => bc
+&#xBC; => &#xBC;
+
+BOX DRAWINGS UP DOUBLE AND LEFT SINGLE: &#x255C; => bd
+&#xBD; => &#xBD;
+
+BOX DRAWINGS UP SINGLE AND LEFT DOUBLE: &#x255B; => be
+&#xBE; => &#xBE;
+
+BOX DRAWINGS LIGHT DOWN AND LEFT: &#x2510; => bf
+&#xBF; => &#xBF;
+
+BOX DRAWINGS LIGHT UP AND RIGHT: &#x2514; => c0
+&#xC0; => &#xC0;
+
+BOX DRAWINGS LIGHT UP AND HORIZONTAL: &#x2534; => c1
+&#xC1; => &#xC1;
+
+BOX DRAWINGS LIGHT DOWN AND HORIZONTAL: &#x252C; => c2
+&#xC2; => &#xC2;
+
+BOX DRAWINGS LIGHT VERTICAL AND RIGHT: &#x251C; => c3
+&#xC3; => &#xC3;
+
+BOX DRAWINGS LIGHT HORIZONTAL: &#x2500; => c4
+&#xC4; => &#xC4;
+
+BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL: &#x253C; => c5
+&#xC5; => &#xC5;
+
+BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE: &#x255E; => c6
+&#xC6; => &#xC6;
+
+BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE: &#x255F; => c7
+&#xC7; => &#xC7;
+
+BOX DRAWINGS DOUBLE UP AND RIGHT: &#x255A; => c8
+&#xC8; => &#xC8;
+
+BOX DRAWINGS DOUBLE DOWN AND RIGHT: &#x2554; => c9
+&#xC9; => &#xC9;
+
+BOX DRAWINGS DOUBLE UP AND HORIZONTAL: &#x2569; => ca
+&#xCA; => &#xCA;
+
+BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL: &#x2566; => cb
+&#xCB; => &#xCB;
+
+BOX DRAWINGS DOUBLE VERTICAL AND RIGHT: &#x2560; => cc
+&#xCC; => &#xCC;
+
+BOX DRAWINGS DOUBLE HORIZONTAL: &#x2550; => cd
+&#xCD; => &#xCD;
+
+BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL: &#x256C; => ce
+&#xCE; => &#xCE;
+
+BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE: &#x2567; => cf
+&#xCF; => &#xCF;
+
+BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE: &#x2568; => d0
+&#xD0; => &#xD0;
+
+BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE: &#x2564; => d1
+&#xD1; => &#xD1;
+
+BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE: &#x2565; => d2
+&#xD2; => &#xD2;
+
+BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE: &#x2559; => d3
+&#xD3; => &#xD3;
+
+BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE: &#x2558; => d4
+&#xD4; => &#xD4;
+
+BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE: &#x2552; => d5
+&#xD5; => &#xD5;
+
+BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE: &#x2553; => d6
+&#xD6; => &#xD6;
+
+BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE: &#x256B; => d7
+&#xD7; => &#xD7;
+
+BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE: &#x256A; => d8
+&#xD8; => &#xD8;
+
+BOX DRAWINGS LIGHT UP AND LEFT: &#x2518; => d9
+&#xD9; => &#xD9;
+
+BOX DRAWINGS LIGHT DOWN AND RIGHT: &#x250C; => da
+&#xDA; => &#xDA;
+
+FULL BLOCK: &#x2588; => db
+&#xDB; => &#xDB;
+
+LOWER HALF BLOCK: &#x2584; => dc
+&#xDC; => &#xDC;
+
+LEFT HALF BLOCK: &#x258C; => dd
+&#xDD; => &#xDD;
+
+RIGHT HALF BLOCK: &#x2590; => de
+&#xDE; => &#xDE;
+
+UPPER HALF BLOCK: &#x2580; => df
+&#xDF; => &#xDF;
+
+CYRILLIC SMALL LETTER ER: &#x440; => e0
+&#xE0; => &#xE0;
+
+CYRILLIC SMALL LETTER ES: &#x441; => e1
+&#xE1; => &#xE1;
+
+CYRILLIC SMALL LETTER TE: &#x442; => e2
+&#xE2; => &#xE2;
+
+CYRILLIC SMALL LETTER U: &#x443; => e3
+&#xE3; => &#xE3;
+
+CYRILLIC SMALL LETTER EF: &#x444; => e4
+&#xE4; => &#xE4;
+
+CYRILLIC SMALL LETTER HA: &#x445; => e5
+&#xE5; => &#xE5;
+
+CYRILLIC SMALL LETTER TSE: &#x446; => e6
+&#xE6; => &#xE6;
+
+CYRILLIC SMALL LETTER CHE: &#x447; => e7
+&#xE7; => &#xE7;
+
+CYRILLIC SMALL LETTER SHA: &#x448; => e8
+&#xE8; => &#xE8;
+
+CYRILLIC SMALL LETTER SHCHA: &#x449; => e9
+&#xE9; => &#xE9;
+
+CYRILLIC SMALL LETTER HARD SIGN: &#x44A; => ea
+&#xEA; => &#xEA;
+
+CYRILLIC SMALL LETTER YERU: &#x44B; => eb
+&#xEB; => &#xEB;
+
+CYRILLIC SMALL LETTER SOFT SIGN: &#x44C; => ec
+&#xEC; => &#xEC;
+
+CYRILLIC SMALL LETTER E: &#x44D; => ed
+&#xED; => &#xED;
+
+CYRILLIC SMALL LETTER YU: &#x44E; => ee
+&#xEE; => &#xEE;
+
+CYRILLIC SMALL LETTER YA: &#x44F; => ef
+&#xEF; => &#xEF;
+
+CYRILLIC CAPITAL LETTER IO: &#x401; => f0
+&#xF0; => &#xF0;
+
+CYRILLIC SMALL LETTER IO: &#x451; => f1
+&#xF1; => &#xF1;
+
+CYRILLIC CAPITAL LETTER UKRAINIAN IE: &#x404; => f2
+&#xF2; => &#xF2;
+
+CYRILLIC SMALL LETTER UKRAINIAN IE: &#x454; => f3
+&#xF3; => &#xF3;
+
+CYRILLIC CAPITAL LETTER YI: &#x407; => f4
+&#xF4; => &#xF4;
+
+CYRILLIC SMALL LETTER YI: &#x457; => f5
+&#xF5; => &#xF5;
+
+CYRILLIC CAPITAL LETTER SHORT U: &#x40E; => f6
+&#xF6; => &#xF6;
+
+CYRILLIC SMALL LETTER SHORT U: &#x45E; => f7
+&#xF7; => &#xF7;
+
+DEGREE SIGN: &#xB0; => f8
+&#xF8; => &#xF8;
+
+BULLET OPERATOR: &#x2219; => f9
+&#xF9; => &#xF9;
+
+MIDDLE DOT: &#xB7; => fa
+&#xFA; => &#xFA;
+
+SQUARE ROOT: &#x221A; => fb
+&#xFB; => &#xFB;
+
+NUMERO SIGN: &#x2116; => fc
+&#xFC; => &#xFC;
+
+CURRENCY SIGN: &#xA4; => fd
+&#xFD; => &#xFD;
+
+BLACK SQUARE: &#x25A0; => fe
+&#xFE; => &#xFE;
+
+NO-BREAK SPACE: &#xA0; => ff
+&#xFF; => &#xFF;
+
+
diff --git a/ext/standard/tests/strings/html_entity_decode_html4.phpt b/ext/standard/tests/strings/html_entity_decode_html4.phpt
index 3c92bf6fb7..34753396de 100644
--- a/ext/standard/tests/strings/html_entity_decode_html4.phpt
+++ b/ext/standard/tests/strings/html_entity_decode_html4.phpt
@@ -3,258 +3,258 @@ html_entity_decode() conformance check (HTML 4)
--FILE--
<?php
$map = array(
- "&quot;",
- "&amp;",
- "&lt;",
- "&gt;",
- "&nbsp;",
- "&iexcl;",
- "&cent;",
- "&pound;",
- "&curren;",
- "&yen;",
- "&brvbar;",
- "&sect;",
- "&uml;",
- "&copy;",
- "&ordf;",
- "&laquo;",
- "&not;",
- "&shy;",
- "&reg;",
- "&macr;",
- "&deg;",
- "&plusmn;",
- "&sup2;",
- "&sup3;",
- "&acute;",
- "&micro;",
- "&para;",
- "&middot;",
- "&cedil;",
- "&sup1;",
- "&ordm;",
- "&raquo;",
- "&frac14;",
- "&frac12;",
- "&frac34;",
- "&iquest;",
- "&Agrave;",
- "&Aacute;",
- "&Acirc;",
- "&Atilde;",
- "&Auml;",
- "&Aring;",
- "&AElig;",
- "&Ccedil;",
- "&Egrave;",
- "&Eacute;",
- "&Ecirc;",
- "&Euml;",
- "&Igrave;",
- "&Iacute;",
- "&Icirc;",
- "&Iuml;",
- "&ETH;",
- "&Ntilde;",
- "&Ograve;",
- "&Oacute;",
- "&Ocirc;",
- "&Otilde;",
- "&Ouml;",
- "&times;",
- "&Oslash;",
- "&Ugrave;",
- "&Uacute;",
- "&Ucirc;",
- "&Uuml;",
- "&Yacute;",
- "&THORN;",
- "&szlig;",
- "&agrave;",
- "&aacute;",
- "&acirc;",
- "&atilde;",
- "&auml;",
- "&aring;",
- "&aelig;",
- "&ccedil;",
- "&egrave;",
- "&eacute;",
- "&ecirc;",
- "&euml;",
- "&igrave;",
- "&iacute;",
- "&icirc;",
- "&iuml;",
- "&eth;",
- "&ntilde;",
- "&ograve;",
- "&oacute;",
- "&ocirc;",
- "&otilde;",
- "&ouml;",
- "&divide;",
- "&oslash;",
- "&ugrave;",
- "&uacute;",
- "&ucirc;",
- "&uuml;",
- "&yacute;",
- "&thorn;",
- "&yuml;",
- "&OElig;",
- "&oelig;",
- "&Scaron;",
- "&scaron;",
- "&Yuml;",
- "&fnof;",
- "&circ;",
- "&tilde;",
- "&Alpha;",
- "&Beta;",
- "&Gamma;",
- "&Delta;",
- "&Epsilon;",
- "&Zeta;",
- "&Eta;",
- "&Theta;",
- "&Iota;",
- "&Kappa;",
- "&Lambda;",
- "&Mu;",
- "&Nu;",
- "&Xi;",
- "&Omicron;",
- "&Pi;",
- "&Rho;",
- "&Sigma;",
- "&Tau;",
- "&Upsilon;",
- "&Phi;",
- "&Chi;",
- "&Psi;",
- "&Omega;",
- "&alpha;",
- "&beta;",
- "&gamma;",
- "&delta;",
- "&epsilon;",
- "&zeta;",
- "&eta;",
- "&theta;",
- "&iota;",
- "&kappa;",
- "&lambda;",
- "&mu;",
- "&nu;",
- "&xi;",
- "&omicron;",
- "&pi;",
- "&rho;",
- "&sigmaf;",
- "&sigma;",
- "&tau;",
- "&upsilon;",
- "&phi;",
- "&chi;",
- "&psi;",
- "&omega;",
- "&thetasym;",
- "&upsih;",
- "&piv;",
- "&ensp;",
- "&emsp;",
- "&thinsp;",
- "&zwnj;",
- "&zwj;",
- "&lrm;",
- "&rlm;",
- "&ndash;",
- "&mdash;",
- "&lsquo;",
- "&rsquo;",
- "&sbquo;",
- "&ldquo;",
- "&rdquo;",
- "&bdquo;",
- "&dagger;",
- "&Dagger;",
- "&bull;",
- "&hellip;",
- "&permil;",
- "&prime;",
- "&Prime;",
- "&lsaquo;",
- "&rsaquo;",
- "&oline;",
- "&frasl;",
- "&euro;",
- "&image;",
- "&weierp;",
- "&real;",
- "&trade;",
- "&alefsym;",
- "&larr;",
- "&uarr;",
- "&rarr;",
- "&darr;",
- "&harr;",
- "&crarr;",
- "&lArr;",
- "&uArr;",
- "&rArr;",
- "&dArr;",
- "&hArr;",
- "&forall;",
- "&part;",
- "&exist;",
- "&empty;",
- "&nabla;",
- "&isin;",
- "&notin;",
- "&ni;",
- "&prod;",
- "&sum;",
- "&minus;",
- "&lowast;",
- "&radic;",
- "&prop;",
- "&infin;",
- "&ang;",
- "&and;",
- "&or;",
- "&cap;",
- "&cup;",
- "&int;",
- "&there4;",
- "&sim;",
- "&cong;",
- "&asymp;",
- "&ne;",
- "&equiv;",
- "&le;",
- "&ge;",
- "&sub;",
- "&sup;",
- "&nsub;",
- "&sube;",
- "&supe;",
- "&oplus;",
- "&otimes;",
- "&perp;",
- "&sdot;",
- "&lceil;",
- "&rceil;",
- "&lfloor;",
- "&rfloor;",
- "&lang;",
- "&rang;",
- "&loz;",
- "&spades;",
- "&clubs;",
- "&hearts;",
- "&diams;",
+ "&quot;",
+ "&amp;",
+ "&lt;",
+ "&gt;",
+ "&nbsp;",
+ "&iexcl;",
+ "&cent;",
+ "&pound;",
+ "&curren;",
+ "&yen;",
+ "&brvbar;",
+ "&sect;",
+ "&uml;",
+ "&copy;",
+ "&ordf;",
+ "&laquo;",
+ "&not;",
+ "&shy;",
+ "&reg;",
+ "&macr;",
+ "&deg;",
+ "&plusmn;",
+ "&sup2;",
+ "&sup3;",
+ "&acute;",
+ "&micro;",
+ "&para;",
+ "&middot;",
+ "&cedil;",
+ "&sup1;",
+ "&ordm;",
+ "&raquo;",
+ "&frac14;",
+ "&frac12;",
+ "&frac34;",
+ "&iquest;",
+ "&Agrave;",
+ "&Aacute;",
+ "&Acirc;",
+ "&Atilde;",
+ "&Auml;",
+ "&Aring;",
+ "&AElig;",
+ "&Ccedil;",
+ "&Egrave;",
+ "&Eacute;",
+ "&Ecirc;",
+ "&Euml;",
+ "&Igrave;",
+ "&Iacute;",
+ "&Icirc;",
+ "&Iuml;",
+ "&ETH;",
+ "&Ntilde;",
+ "&Ograve;",
+ "&Oacute;",
+ "&Ocirc;",
+ "&Otilde;",
+ "&Ouml;",
+ "&times;",
+ "&Oslash;",
+ "&Ugrave;",
+ "&Uacute;",
+ "&Ucirc;",
+ "&Uuml;",
+ "&Yacute;",
+ "&THORN;",
+ "&szlig;",
+ "&agrave;",
+ "&aacute;",
+ "&acirc;",
+ "&atilde;",
+ "&auml;",
+ "&aring;",
+ "&aelig;",
+ "&ccedil;",
+ "&egrave;",
+ "&eacute;",
+ "&ecirc;",
+ "&euml;",
+ "&igrave;",
+ "&iacute;",
+ "&icirc;",
+ "&iuml;",
+ "&eth;",
+ "&ntilde;",
+ "&ograve;",
+ "&oacute;",
+ "&ocirc;",
+ "&otilde;",
+ "&ouml;",
+ "&divide;",
+ "&oslash;",
+ "&ugrave;",
+ "&uacute;",
+ "&ucirc;",
+ "&uuml;",
+ "&yacute;",
+ "&thorn;",
+ "&yuml;",
+ "&OElig;",
+ "&oelig;",
+ "&Scaron;",
+ "&scaron;",
+ "&Yuml;",
+ "&fnof;",
+ "&circ;",
+ "&tilde;",
+ "&Alpha;",
+ "&Beta;",
+ "&Gamma;",
+ "&Delta;",
+ "&Epsilon;",
+ "&Zeta;",
+ "&Eta;",
+ "&Theta;",
+ "&Iota;",
+ "&Kappa;",
+ "&Lambda;",
+ "&Mu;",
+ "&Nu;",
+ "&Xi;",
+ "&Omicron;",
+ "&Pi;",
+ "&Rho;",
+ "&Sigma;",
+ "&Tau;",
+ "&Upsilon;",
+ "&Phi;",
+ "&Chi;",
+ "&Psi;",
+ "&Omega;",
+ "&alpha;",
+ "&beta;",
+ "&gamma;",
+ "&delta;",
+ "&epsilon;",
+ "&zeta;",
+ "&eta;",
+ "&theta;",
+ "&iota;",
+ "&kappa;",
+ "&lambda;",
+ "&mu;",
+ "&nu;",
+ "&xi;",
+ "&omicron;",
+ "&pi;",
+ "&rho;",
+ "&sigmaf;",
+ "&sigma;",
+ "&tau;",
+ "&upsilon;",
+ "&phi;",
+ "&chi;",
+ "&psi;",
+ "&omega;",
+ "&thetasym;",
+ "&upsih;",
+ "&piv;",
+ "&ensp;",
+ "&emsp;",
+ "&thinsp;",
+ "&zwnj;",
+ "&zwj;",
+ "&lrm;",
+ "&rlm;",
+ "&ndash;",
+ "&mdash;",
+ "&lsquo;",
+ "&rsquo;",
+ "&sbquo;",
+ "&ldquo;",
+ "&rdquo;",
+ "&bdquo;",
+ "&dagger;",
+ "&Dagger;",
+ "&bull;",
+ "&hellip;",
+ "&permil;",
+ "&prime;",
+ "&Prime;",
+ "&lsaquo;",
+ "&rsaquo;",
+ "&oline;",
+ "&frasl;",
+ "&euro;",
+ "&image;",
+ "&weierp;",
+ "&real;",
+ "&trade;",
+ "&alefsym;",
+ "&larr;",
+ "&uarr;",
+ "&rarr;",
+ "&darr;",
+ "&harr;",
+ "&crarr;",
+ "&lArr;",
+ "&uArr;",
+ "&rArr;",
+ "&dArr;",
+ "&hArr;",
+ "&forall;",
+ "&part;",
+ "&exist;",
+ "&empty;",
+ "&nabla;",
+ "&isin;",
+ "&notin;",
+ "&ni;",
+ "&prod;",
+ "&sum;",
+ "&minus;",
+ "&lowast;",
+ "&radic;",
+ "&prop;",
+ "&infin;",
+ "&ang;",
+ "&and;",
+ "&or;",
+ "&cap;",
+ "&cup;",
+ "&int;",
+ "&there4;",
+ "&sim;",
+ "&cong;",
+ "&asymp;",
+ "&ne;",
+ "&equiv;",
+ "&le;",
+ "&ge;",
+ "&sub;",
+ "&sup;",
+ "&nsub;",
+ "&sube;",
+ "&supe;",
+ "&oplus;",
+ "&otimes;",
+ "&perp;",
+ "&sdot;",
+ "&lceil;",
+ "&rceil;",
+ "&lfloor;",
+ "&rfloor;",
+ "&lang;",
+ "&rang;",
+ "&loz;",
+ "&spades;",
+ "&clubs;",
+ "&hearts;",
+ "&diams;"
);
foreach ($map as $str) {
diff --git a/ext/standard/tests/strings/html_entity_decode_html5.phpt b/ext/standard/tests/strings/html_entity_decode_html5.phpt
new file mode 100644
index 0000000000..6e0d4cf167
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_html5.phpt
@@ -0,0 +1,4264 @@
+--TEST--
+html_entity_decode() conformance check (HTML 5)
+--FILE--
+<?php
+$map = array(
+ "&AElig;",
+ "&AMP;",
+ "&Aacute;",
+ "&Abreve;",
+ "&Acirc;",
+ "&Acy;",
+ "&Afr;",
+ "&Agrave;",
+ "&Alpha;",
+ "&Amacr;",
+ "&And;",
+ "&Aogon;",
+ "&Aopf;",
+ "&ApplyFunction;",
+ "&Aring;",
+ "&Ascr;",
+ "&Assign;",
+ "&Atilde;",
+ "&Auml;",
+ "&Backslash;",
+ "&Barv;",
+ "&Barwed;",
+ "&Bcy;",
+ "&Because;",
+ "&Bernoullis;",
+ "&Beta;",
+ "&Bfr;",
+ "&Bopf;",
+ "&Breve;",
+ "&Bscr;",
+ "&Bumpeq;",
+ "&CHcy;",
+ "&COPY;",
+ "&Cacute;",
+ "&Cap;",
+ "&CapitalDifferentialD;",
+ "&Cayleys;",
+ "&Ccaron;",
+ "&Ccedil;",
+ "&Ccirc;",
+ "&Cconint;",
+ "&Cdot;",
+ "&Cedilla;",
+ "&CenterDot;",
+ "&Cfr;",
+ "&Chi;",
+ "&CircleDot;",
+ "&CircleMinus;",
+ "&CirclePlus;",
+ "&CircleTimes;",
+ "&ClockwiseContourIntegral;",
+ "&CloseCurlyDoubleQuote;",
+ "&CloseCurlyQuote;",
+ "&Colon;",
+ "&Colone;",
+ "&Congruent;",
+ "&Conint;",
+ "&ContourIntegral;",
+ "&Copf;",
+ "&Coproduct;",
+ "&CounterClockwiseContourIntegral;",
+ "&Cross;",
+ "&Cscr;",
+ "&Cup;",
+ "&CupCap;",
+ "&DD;",
+ "&DDotrahd;",
+ "&DJcy;",
+ "&DScy;",
+ "&DZcy;",
+ "&Dagger;",
+ "&Darr;",
+ "&Dashv;",
+ "&Dcaron;",
+ "&Dcy;",
+ "&Del;",
+ "&Delta;",
+ "&Dfr;",
+ "&DiacriticalAcute;",
+ "&DiacriticalDot;",
+ "&DiacriticalDoubleAcute;",
+ "&DiacriticalGrave;",
+ "&DiacriticalTilde;",
+ "&Diamond;",
+ "&DifferentialD;",
+ "&Dopf;",
+ "&Dot;",
+ "&DotDot;",
+ "&DotEqual;",
+ "&DoubleContourIntegral;",
+ "&DoubleDot;",
+ "&DoubleDownArrow;",
+ "&DoubleLeftArrow;",
+ "&DoubleLeftRightArrow;",
+ "&DoubleLeftTee;",
+ "&DoubleLongLeftArrow;",
+ "&DoubleLongLeftRightArrow;",
+ "&DoubleLongRightArrow;",
+ "&DoubleRightArrow;",
+ "&DoubleRightTee;",
+ "&DoubleUpArrow;",
+ "&DoubleUpDownArrow;",
+ "&DoubleVerticalBar;",
+ "&DownArrow;",
+ "&DownArrowBar;",
+ "&DownArrowUpArrow;",
+ "&DownBreve;",
+ "&DownLeftRightVector;",
+ "&DownLeftTeeVector;",
+ "&DownLeftVector;",
+ "&DownLeftVectorBar;",
+ "&DownRightTeeVector;",
+ "&DownRightVector;",
+ "&DownRightVectorBar;",
+ "&DownTee;",
+ "&DownTeeArrow;",
+ "&Downarrow;",
+ "&Dscr;",
+ "&Dstrok;",
+ "&ENG;",
+ "&ETH;",
+ "&Eacute;",
+ "&Ecaron;",
+ "&Ecirc;",
+ "&Ecy;",
+ "&Edot;",
+ "&Efr;",
+ "&Egrave;",
+ "&Element;",
+ "&Emacr;",
+ "&EmptySmallSquare;",
+ "&EmptyVerySmallSquare;",
+ "&Eogon;",
+ "&Eopf;",
+ "&Epsilon;",
+ "&Equal;",
+ "&EqualTilde;",
+ "&Equilibrium;",
+ "&Escr;",
+ "&Esim;",
+ "&Eta;",
+ "&Euml;",
+ "&Exists;",
+ "&ExponentialE;",
+ "&Fcy;",
+ "&Ffr;",
+ "&FilledSmallSquare;",
+ "&FilledVerySmallSquare;",
+ "&Fopf;",
+ "&ForAll;",
+ "&Fouriertrf;",
+ "&Fscr;",
+ "&GJcy;",
+ "&GT;",
+ "&Gamma;",
+ "&Gammad;",
+ "&Gbreve;",
+ "&Gcedil;",
+ "&Gcirc;",
+ "&Gcy;",
+ "&Gdot;",
+ "&Gfr;",
+ "&Gg;",
+ "&Gopf;",
+ "&GreaterEqual;",
+ "&GreaterEqualLess;",
+ "&GreaterFullEqual;",
+ "&GreaterGreater;",
+ "&GreaterLess;",
+ "&GreaterSlantEqual;",
+ "&GreaterTilde;",
+ "&Gscr;",
+ "&Gt;",
+ "&HARDcy;",
+ "&Hacek;",
+ "&Hat;",
+ "&Hcirc;",
+ "&Hfr;",
+ "&HilbertSpace;",
+ "&Hopf;",
+ "&HorizontalLine;",
+ "&Hscr;",
+ "&Hstrok;",
+ "&HumpDownHump;",
+ "&HumpEqual;",
+ "&IEcy;",
+ "&IJlig;",
+ "&IOcy;",
+ "&Iacute;",
+ "&Icirc;",
+ "&Icy;",
+ "&Idot;",
+ "&Ifr;",
+ "&Igrave;",
+ "&Im;",
+ "&Imacr;",
+ "&ImaginaryI;",
+ "&Implies;",
+ "&Int;",
+ "&Integral;",
+ "&Intersection;",
+ "&InvisibleComma;",
+ "&InvisibleTimes;",
+ "&Iogon;",
+ "&Iopf;",
+ "&Iota;",
+ "&Iscr;",
+ "&Itilde;",
+ "&Iukcy;",
+ "&Iuml;",
+ "&Jcirc;",
+ "&Jcy;",
+ "&Jfr;",
+ "&Jopf;",
+ "&Jscr;",
+ "&Jsercy;",
+ "&Jukcy;",
+ "&KHcy;",
+ "&KJcy;",
+ "&Kappa;",
+ "&Kcedil;",
+ "&Kcy;",
+ "&Kfr;",
+ "&Kopf;",
+ "&Kscr;",
+ "&LJcy;",
+ "&LT;",
+ "&Lacute;",
+ "&Lambda;",
+ "&Lang;",
+ "&Laplacetrf;",
+ "&Larr;",
+ "&Lcaron;",
+ "&Lcedil;",
+ "&Lcy;",
+ "&LeftAngleBracket;",
+ "&LeftArrow;",
+ "&LeftArrowBar;",
+ "&LeftArrowRightArrow;",
+ "&LeftCeiling;",
+ "&LeftDoubleBracket;",
+ "&LeftDownTeeVector;",
+ "&LeftDownVector;",
+ "&LeftDownVectorBar;",
+ "&LeftFloor;",
+ "&LeftRightArrow;",
+ "&LeftRightVector;",
+ "&LeftTee;",
+ "&LeftTeeArrow;",
+ "&LeftTeeVector;",
+ "&LeftTriangle;",
+ "&LeftTriangleBar;",
+ "&LeftTriangleEqual;",
+ "&LeftUpDownVector;",
+ "&LeftUpTeeVector;",
+ "&LeftUpVector;",
+ "&LeftUpVectorBar;",
+ "&LeftVector;",
+ "&LeftVectorBar;",
+ "&Leftarrow;",
+ "&Leftrightarrow;",
+ "&LessEqualGreater;",
+ "&LessFullEqual;",
+ "&LessGreater;",
+ "&LessLess;",
+ "&LessSlantEqual;",
+ "&LessTilde;",
+ "&Lfr;",
+ "&Ll;",
+ "&Lleftarrow;",
+ "&Lmidot;",
+ "&LongLeftArrow;",
+ "&LongLeftRightArrow;",
+ "&LongRightArrow;",
+ "&Longleftarrow;",
+ "&Longleftrightarrow;",
+ "&Longrightarrow;",
+ "&Lopf;",
+ "&LowerLeftArrow;",
+ "&LowerRightArrow;",
+ "&Lscr;",
+ "&Lsh;",
+ "&Lstrok;",
+ "&Lt;",
+ "&Map;",
+ "&Mcy;",
+ "&MediumSpace;",
+ "&Mellintrf;",
+ "&Mfr;",
+ "&MinusPlus;",
+ "&Mopf;",
+ "&Mscr;",
+ "&Mu;",
+ "&NJcy;",
+ "&Nacute;",
+ "&Ncaron;",
+ "&Ncedil;",
+ "&Ncy;",
+ "&NegativeMediumSpace;",
+ "&NegativeThickSpace;",
+ "&NegativeThinSpace;",
+ "&NegativeVeryThinSpace;",
+ "&NestedGreaterGreater;",
+ "&NestedLessLess;",
+ "&NewLine;",
+ "&Nfr;",
+ "&NoBreak;",
+ "&NonBreakingSpace;",
+ "&Nopf;",
+ "&Not;",
+ "&NotCongruent;",
+ "&NotCupCap;",
+ "&NotDoubleVerticalBar;",
+ "&NotElement;",
+ "&NotEqual;",
+ "&NotEqualTilde;",
+ "&NotExists;",
+ "&NotGreater;",
+ "&NotGreaterEqual;",
+ "&NotGreaterFullEqual;",
+ "&NotGreaterGreater;",
+ "&NotGreaterLess;",
+ "&NotGreaterSlantEqual;",
+ "&NotGreaterTilde;",
+ "&NotHumpDownHump;",
+ "&NotHumpEqual;",
+ "&NotLeftTriangle;",
+ "&NotLeftTriangleBar;",
+ "&NotLeftTriangleEqual;",
+ "&NotLess;",
+ "&NotLessEqual;",
+ "&NotLessGreater;",
+ "&NotLessLess;",
+ "&NotLessSlantEqual;",
+ "&NotLessTilde;",
+ "&NotNestedGreaterGreater;",
+ "&NotNestedLessLess;",
+ "&NotPrecedes;",
+ "&NotPrecedesEqual;",
+ "&NotPrecedesSlantEqual;",
+ "&NotReverseElement;",
+ "&NotRightTriangle;",
+ "&NotRightTriangleBar;",
+ "&NotRightTriangleEqual;",
+ "&NotSquareSubset;",
+ "&NotSquareSubsetEqual;",
+ "&NotSquareSuperset;",
+ "&NotSquareSupersetEqual;",
+ "&NotSubset;",
+ "&NotSubsetEqual;",
+ "&NotSucceeds;",
+ "&NotSucceedsEqual;",
+ "&NotSucceedsSlantEqual;",
+ "&NotSucceedsTilde;",
+ "&NotSuperset;",
+ "&NotSupersetEqual;",
+ "&NotTilde;",
+ "&NotTildeEqual;",
+ "&NotTildeFullEqual;",
+ "&NotTildeTilde;",
+ "&NotVerticalBar;",
+ "&Nscr;",
+ "&Ntilde;",
+ "&Nu;",
+ "&OElig;",
+ "&Oacute;",
+ "&Ocirc;",
+ "&Ocy;",
+ "&Odblac;",
+ "&Ofr;",
+ "&Ograve;",
+ "&Omacr;",
+ "&Omega;",
+ "&Omicron;",
+ "&Oopf;",
+ "&OpenCurlyDoubleQuote;",
+ "&OpenCurlyQuote;",
+ "&Or;",
+ "&Oscr;",
+ "&Oslash;",
+ "&Otilde;",
+ "&Otimes;",
+ "&Ouml;",
+ "&OverBar;",
+ "&OverBrace;",
+ "&OverBracket;",
+ "&OverParenthesis;",
+ "&PartialD;",
+ "&Pcy;",
+ "&Pfr;",
+ "&Phi;",
+ "&Pi;",
+ "&PlusMinus;",
+ "&Poincareplane;",
+ "&Popf;",
+ "&Pr;",
+ "&Precedes;",
+ "&PrecedesEqual;",
+ "&PrecedesSlantEqual;",
+ "&PrecedesTilde;",
+ "&Prime;",
+ "&Product;",
+ "&Proportion;",
+ "&Proportional;",
+ "&Pscr;",
+ "&Psi;",
+ "&QUOT;",
+ "&Qfr;",
+ "&Qopf;",
+ "&Qscr;",
+ "&RBarr;",
+ "&REG;",
+ "&Racute;",
+ "&Rang;",
+ "&Rarr;",
+ "&Rarrtl;",
+ "&Rcaron;",
+ "&Rcedil;",
+ "&Rcy;",
+ "&Re;",
+ "&ReverseElement;",
+ "&ReverseEquilibrium;",
+ "&ReverseUpEquilibrium;",
+ "&Rfr;",
+ "&Rho;",
+ "&RightAngleBracket;",
+ "&RightArrow;",
+ "&RightArrowBar;",
+ "&RightArrowLeftArrow;",
+ "&RightCeiling;",
+ "&RightDoubleBracket;",
+ "&RightDownTeeVector;",
+ "&RightDownVector;",
+ "&RightDownVectorBar;",
+ "&RightFloor;",
+ "&RightTee;",
+ "&RightTeeArrow;",
+ "&RightTeeVector;",
+ "&RightTriangle;",
+ "&RightTriangleBar;",
+ "&RightTriangleEqual;",
+ "&RightUpDownVector;",
+ "&RightUpTeeVector;",
+ "&RightUpVector;",
+ "&RightUpVectorBar;",
+ "&RightVector;",
+ "&RightVectorBar;",
+ "&Rightarrow;",
+ "&Ropf;",
+ "&RoundImplies;",
+ "&Rrightarrow;",
+ "&Rscr;",
+ "&Rsh;",
+ "&RuleDelayed;",
+ "&SHCHcy;",
+ "&SHcy;",
+ "&SOFTcy;",
+ "&Sacute;",
+ "&Sc;",
+ "&Scaron;",
+ "&Scedil;",
+ "&Scirc;",
+ "&Scy;",
+ "&Sfr;",
+ "&ShortDownArrow;",
+ "&ShortLeftArrow;",
+ "&ShortRightArrow;",
+ "&ShortUpArrow;",
+ "&Sigma;",
+ "&SmallCircle;",
+ "&Sopf;",
+ "&Sqrt;",
+ "&Square;",
+ "&SquareIntersection;",
+ "&SquareSubset;",
+ "&SquareSubsetEqual;",
+ "&SquareSuperset;",
+ "&SquareSupersetEqual;",
+ "&SquareUnion;",
+ "&Sscr;",
+ "&Star;",
+ "&Sub;",
+ "&Subset;",
+ "&SubsetEqual;",
+ "&Succeeds;",
+ "&SucceedsEqual;",
+ "&SucceedsSlantEqual;",
+ "&SucceedsTilde;",
+ "&SuchThat;",
+ "&Sum;",
+ "&Sup;",
+ "&Superset;",
+ "&SupersetEqual;",
+ "&Supset;",
+ "&THORN;",
+ "&TRADE;",
+ "&TSHcy;",
+ "&TScy;",
+ "&Tab;",
+ "&Tau;",
+ "&Tcaron;",
+ "&Tcedil;",
+ "&Tcy;",
+ "&Tfr;",
+ "&Therefore;",
+ "&Theta;",
+ "&ThickSpace;",
+ "&ThinSpace;",
+ "&Tilde;",
+ "&TildeEqual;",
+ "&TildeFullEqual;",
+ "&TildeTilde;",
+ "&Topf;",
+ "&TripleDot;",
+ "&Tscr;",
+ "&Tstrok;",
+ "&Uacute;",
+ "&Uarr;",
+ "&Uarrocir;",
+ "&Ubrcy;",
+ "&Ubreve;",
+ "&Ucirc;",
+ "&Ucy;",
+ "&Udblac;",
+ "&Ufr;",
+ "&Ugrave;",
+ "&Umacr;",
+ "&UnderBar;",
+ "&UnderBrace;",
+ "&UnderBracket;",
+ "&UnderParenthesis;",
+ "&Union;",
+ "&UnionPlus;",
+ "&Uogon;",
+ "&Uopf;",
+ "&UpArrow;",
+ "&UpArrowBar;",
+ "&UpArrowDownArrow;",
+ "&UpDownArrow;",
+ "&UpEquilibrium;",
+ "&UpTee;",
+ "&UpTeeArrow;",
+ "&Uparrow;",
+ "&Updownarrow;",
+ "&UpperLeftArrow;",
+ "&UpperRightArrow;",
+ "&Upsi;",
+ "&Upsilon;",
+ "&Uring;",
+ "&Uscr;",
+ "&Utilde;",
+ "&Uuml;",
+ "&VDash;",
+ "&Vbar;",
+ "&Vcy;",
+ "&Vdash;",
+ "&Vdashl;",
+ "&Vee;",
+ "&Verbar;",
+ "&Vert;",
+ "&VerticalBar;",
+ "&VerticalLine;",
+ "&VerticalSeparator;",
+ "&VerticalTilde;",
+ "&VeryThinSpace;",
+ "&Vfr;",
+ "&Vopf;",
+ "&Vscr;",
+ "&Vvdash;",
+ "&Wcirc;",
+ "&Wedge;",
+ "&Wfr;",
+ "&Wopf;",
+ "&Wscr;",
+ "&Xfr;",
+ "&Xi;",
+ "&Xopf;",
+ "&Xscr;",
+ "&YAcy;",
+ "&YIcy;",
+ "&YUcy;",
+ "&Yacute;",
+ "&Ycirc;",
+ "&Ycy;",
+ "&Yfr;",
+ "&Yopf;",
+ "&Yscr;",
+ "&Yuml;",
+ "&ZHcy;",
+ "&Zacute;",
+ "&Zcaron;",
+ "&Zcy;",
+ "&Zdot;",
+ "&ZeroWidthSpace;",
+ "&Zeta;",
+ "&Zfr;",
+ "&Zopf;",
+ "&Zscr;",
+ "&aacute;",
+ "&abreve;",
+ "&ac;",
+ "&acE;",
+ "&acd;",
+ "&acirc;",
+ "&acute;",
+ "&acy;",
+ "&aelig;",
+ "&af;",
+ "&afr;",
+ "&agrave;",
+ "&alefsym;",
+ "&aleph;",
+ "&alpha;",
+ "&amacr;",
+ "&amalg;",
+ "&amp;",
+ "&and;",
+ "&andand;",
+ "&andd;",
+ "&andslope;",
+ "&andv;",
+ "&ang;",
+ "&ange;",
+ "&angle;",
+ "&angmsd;",
+ "&angmsdaa;",
+ "&angmsdab;",
+ "&angmsdac;",
+ "&angmsdad;",
+ "&angmsdae;",
+ "&angmsdaf;",
+ "&angmsdag;",
+ "&angmsdah;",
+ "&angrt;",
+ "&angrtvb;",
+ "&angrtvbd;",
+ "&angsph;",
+ "&angst;",
+ "&angzarr;",
+ "&aogon;",
+ "&aopf;",
+ "&ap;",
+ "&apE;",
+ "&apacir;",
+ "&ape;",
+ "&apid;",
+ "&apos;",
+ "&approx;",
+ "&approxeq;",
+ "&aring;",
+ "&ascr;",
+ "&ast;",
+ "&asymp;",
+ "&asympeq;",
+ "&atilde;",
+ "&auml;",
+ "&awconint;",
+ "&awint;",
+ "&bNot;",
+ "&backcong;",
+ "&backepsilon;",
+ "&backprime;",
+ "&backsim;",
+ "&backsimeq;",
+ "&barvee;",
+ "&barwed;",
+ "&barwedge;",
+ "&bbrk;",
+ "&bbrktbrk;",
+ "&bcong;",
+ "&bcy;",
+ "&bdquo;",
+ "&becaus;",
+ "&because;",
+ "&bemptyv;",
+ "&bepsi;",
+ "&bernou;",
+ "&beta;",
+ "&beth;",
+ "&between;",
+ "&bfr;",
+ "&bigcap;",
+ "&bigcirc;",
+ "&bigcup;",
+ "&bigodot;",
+ "&bigoplus;",
+ "&bigotimes;",
+ "&bigsqcup;",
+ "&bigstar;",
+ "&bigtriangledown;",
+ "&bigtriangleup;",
+ "&biguplus;",
+ "&bigvee;",
+ "&bigwedge;",
+ "&bkarow;",
+ "&blacklozenge;",
+ "&blacksquare;",
+ "&blacktriangle;",
+ "&blacktriangledown;",
+ "&blacktriangleleft;",
+ "&blacktriangleright;",
+ "&blank;",
+ "&blk12;",
+ "&blk14;",
+ "&blk34;",
+ "&block;",
+ "&bne;",
+ "&bnequiv;",
+ "&bnot;",
+ "&bopf;",
+ "&bot;",
+ "&bottom;",
+ "&bowtie;",
+ "&boxDL;",
+ "&boxDR;",
+ "&boxDl;",
+ "&boxDr;",
+ "&boxH;",
+ "&boxHD;",
+ "&boxHU;",
+ "&boxHd;",
+ "&boxHu;",
+ "&boxUL;",
+ "&boxUR;",
+ "&boxUl;",
+ "&boxUr;",
+ "&boxV;",
+ "&boxVH;",
+ "&boxVL;",
+ "&boxVR;",
+ "&boxVh;",
+ "&boxVl;",
+ "&boxVr;",
+ "&boxbox;",
+ "&boxdL;",
+ "&boxdR;",
+ "&boxdl;",
+ "&boxdr;",
+ "&boxh;",
+ "&boxhD;",
+ "&boxhU;",
+ "&boxhd;",
+ "&boxhu;",
+ "&boxminus;",
+ "&boxplus;",
+ "&boxtimes;",
+ "&boxuL;",
+ "&boxuR;",
+ "&boxul;",
+ "&boxur;",
+ "&boxv;",
+ "&boxvH;",
+ "&boxvL;",
+ "&boxvR;",
+ "&boxvh;",
+ "&boxvl;",
+ "&boxvr;",
+ "&bprime;",
+ "&breve;",
+ "&brvbar;",
+ "&bscr;",
+ "&bsemi;",
+ "&bsim;",
+ "&bsime;",
+ "&bsol;",
+ "&bsolb;",
+ "&bsolhsub;",
+ "&bull;",
+ "&bullet;",
+ "&bump;",
+ "&bumpE;",
+ "&bumpe;",
+ "&bumpeq;",
+ "&cacute;",
+ "&cap;",
+ "&capand;",
+ "&capbrcup;",
+ "&capcap;",
+ "&capcup;",
+ "&capdot;",
+ "&caps;",
+ "&caret;",
+ "&caron;",
+ "&ccaps;",
+ "&ccaron;",
+ "&ccedil;",
+ "&ccirc;",
+ "&ccups;",
+ "&ccupssm;",
+ "&cdot;",
+ "&cedil;",
+ "&cemptyv;",
+ "&cent;",
+ "&centerdot;",
+ "&cfr;",
+ "&chcy;",
+ "&check;",
+ "&checkmark;",
+ "&chi;",
+ "&cir;",
+ "&cirE;",
+ "&circ;",
+ "&circeq;",
+ "&circlearrowleft;",
+ "&circlearrowright;",
+ "&circledR;",
+ "&circledS;",
+ "&circledast;",
+ "&circledcirc;",
+ "&circleddash;",
+ "&cire;",
+ "&cirfnint;",
+ "&cirmid;",
+ "&cirscir;",
+ "&clubs;",
+ "&clubsuit;",
+ "&colon;",
+ "&colone;",
+ "&coloneq;",
+ "&comma;",
+ "&commat;",
+ "&comp;",
+ "&compfn;",
+ "&complement;",
+ "&complexes;",
+ "&cong;",
+ "&congdot;",
+ "&conint;",
+ "&copf;",
+ "&coprod;",
+ "&copy;",
+ "&copysr;",
+ "&crarr;",
+ "&cross;",
+ "&cscr;",
+ "&csub;",
+ "&csube;",
+ "&csup;",
+ "&csupe;",
+ "&ctdot;",
+ "&cudarrl;",
+ "&cudarrr;",
+ "&cuepr;",
+ "&cuesc;",
+ "&cularr;",
+ "&cularrp;",
+ "&cup;",
+ "&cupbrcap;",
+ "&cupcap;",
+ "&cupcup;",
+ "&cupdot;",
+ "&cupor;",
+ "&cups;",
+ "&curarr;",
+ "&curarrm;",
+ "&curlyeqprec;",
+ "&curlyeqsucc;",
+ "&curlyvee;",
+ "&curlywedge;",
+ "&curren;",
+ "&curvearrowleft;",
+ "&curvearrowright;",
+ "&cuvee;",
+ "&cuwed;",
+ "&cwconint;",
+ "&cwint;",
+ "&cylcty;",
+ "&dArr;",
+ "&dHar;",
+ "&dagger;",
+ "&daleth;",
+ "&darr;",
+ "&dash;",
+ "&dashv;",
+ "&dbkarow;",
+ "&dblac;",
+ "&dcaron;",
+ "&dcy;",
+ "&dd;",
+ "&ddagger;",
+ "&ddarr;",
+ "&ddotseq;",
+ "&deg;",
+ "&delta;",
+ "&demptyv;",
+ "&dfisht;",
+ "&dfr;",
+ "&dharl;",
+ "&dharr;",
+ "&diam;",
+ "&diamond;",
+ "&diamondsuit;",
+ "&diams;",
+ "&die;",
+ "&digamma;",
+ "&disin;",
+ "&div;",
+ "&divide;",
+ "&divideontimes;",
+ "&divonx;",
+ "&djcy;",
+ "&dlcorn;",
+ "&dlcrop;",
+ "&dollar;",
+ "&dopf;",
+ "&dot;",
+ "&doteq;",
+ "&doteqdot;",
+ "&dotminus;",
+ "&dotplus;",
+ "&dotsquare;",
+ "&doublebarwedge;",
+ "&downarrow;",
+ "&downdownarrows;",
+ "&downharpoonleft;",
+ "&downharpoonright;",
+ "&drbkarow;",
+ "&drcorn;",
+ "&drcrop;",
+ "&dscr;",
+ "&dscy;",
+ "&dsol;",
+ "&dstrok;",
+ "&dtdot;",
+ "&dtri;",
+ "&dtrif;",
+ "&duarr;",
+ "&duhar;",
+ "&dwangle;",
+ "&dzcy;",
+ "&dzigrarr;",
+ "&eDDot;",
+ "&eDot;",
+ "&eacute;",
+ "&easter;",
+ "&ecaron;",
+ "&ecir;",
+ "&ecirc;",
+ "&ecolon;",
+ "&ecy;",
+ "&edot;",
+ "&ee;",
+ "&efDot;",
+ "&efr;",
+ "&eg;",
+ "&egrave;",
+ "&egs;",
+ "&egsdot;",
+ "&el;",
+ "&elinters;",
+ "&ell;",
+ "&els;",
+ "&elsdot;",
+ "&emacr;",
+ "&empty;",
+ "&emptyset;",
+ "&emptyv;",
+ "&emsp;",
+ "&emsp13;",
+ "&emsp14;",
+ "&eng;",
+ "&ensp;",
+ "&eogon;",
+ "&eopf;",
+ "&epar;",
+ "&eparsl;",
+ "&eplus;",
+ "&epsi;",
+ "&epsilon;",
+ "&epsiv;",
+ "&eqcirc;",
+ "&eqcolon;",
+ "&eqsim;",
+ "&eqslantgtr;",
+ "&eqslantless;",
+ "&equals;",
+ "&equest;",
+ "&equiv;",
+ "&equivDD;",
+ "&eqvparsl;",
+ "&erDot;",
+ "&erarr;",
+ "&escr;",
+ "&esdot;",
+ "&esim;",
+ "&eta;",
+ "&eth;",
+ "&euml;",
+ "&euro;",
+ "&excl;",
+ "&exist;",
+ "&expectation;",
+ "&exponentiale;",
+ "&fallingdotseq;",
+ "&fcy;",
+ "&female;",
+ "&ffilig;",
+ "&fflig;",
+ "&ffllig;",
+ "&ffr;",
+ "&filig;",
+ "&fjlig;",
+ "&flat;",
+ "&fllig;",
+ "&fltns;",
+ "&fnof;",
+ "&fopf;",
+ "&forall;",
+ "&fork;",
+ "&forkv;",
+ "&fpartint;",
+ "&frac12;",
+ "&frac13;",
+ "&frac14;",
+ "&frac15;",
+ "&frac16;",
+ "&frac18;",
+ "&frac23;",
+ "&frac25;",
+ "&frac34;",
+ "&frac35;",
+ "&frac38;",
+ "&frac45;",
+ "&frac56;",
+ "&frac58;",
+ "&frac78;",
+ "&frasl;",
+ "&frown;",
+ "&fscr;",
+ "&gE;",
+ "&gEl;",
+ "&gacute;",
+ "&gamma;",
+ "&gammad;",
+ "&gap;",
+ "&gbreve;",
+ "&gcirc;",
+ "&gcy;",
+ "&gdot;",
+ "&ge;",
+ "&gel;",
+ "&geq;",
+ "&geqq;",
+ "&geqslant;",
+ "&ges;",
+ "&gescc;",
+ "&gesdot;",
+ "&gesdoto;",
+ "&gesdotol;",
+ "&gesl;",
+ "&gesles;",
+ "&gfr;",
+ "&gg;",
+ "&ggg;",
+ "&gimel;",
+ "&gjcy;",
+ "&gl;",
+ "&glE;",
+ "&gla;",
+ "&glj;",
+ "&gnE;",
+ "&gnap;",
+ "&gnapprox;",
+ "&gne;",
+ "&gneq;",
+ "&gneqq;",
+ "&gnsim;",
+ "&gopf;",
+ "&grave;",
+ "&gscr;",
+ "&gsim;",
+ "&gsime;",
+ "&gsiml;",
+ "&gt;",
+ "&gtcc;",
+ "&gtcir;",
+ "&gtdot;",
+ "&gtlPar;",
+ "&gtquest;",
+ "&gtrapprox;",
+ "&gtrarr;",
+ "&gtrdot;",
+ "&gtreqless;",
+ "&gtreqqless;",
+ "&gtrless;",
+ "&gtrsim;",
+ "&gvertneqq;",
+ "&gvnE;",
+ "&hArr;",
+ "&hairsp;",
+ "&half;",
+ "&hamilt;",
+ "&hardcy;",
+ "&harr;",
+ "&harrcir;",
+ "&harrw;",
+ "&hbar;",
+ "&hcirc;",
+ "&hearts;",
+ "&heartsuit;",
+ "&hellip;",
+ "&hercon;",
+ "&hfr;",
+ "&hksearow;",
+ "&hkswarow;",
+ "&hoarr;",
+ "&homtht;",
+ "&hookleftarrow;",
+ "&hookrightarrow;",
+ "&hopf;",
+ "&horbar;",
+ "&hscr;",
+ "&hslash;",
+ "&hstrok;",
+ "&hybull;",
+ "&hyphen;",
+ "&iacute;",
+ "&ic;",
+ "&icirc;",
+ "&icy;",
+ "&iecy;",
+ "&iexcl;",
+ "&iff;",
+ "&ifr;",
+ "&igrave;",
+ "&ii;",
+ "&iiiint;",
+ "&iiint;",
+ "&iinfin;",
+ "&iiota;",
+ "&ijlig;",
+ "&imacr;",
+ "&image;",
+ "&imagline;",
+ "&imagpart;",
+ "&imath;",
+ "&imof;",
+ "&imped;",
+ "&in;",
+ "&incare;",
+ "&infin;",
+ "&infintie;",
+ "&inodot;",
+ "&int;",
+ "&intcal;",
+ "&integers;",
+ "&intercal;",
+ "&intlarhk;",
+ "&intprod;",
+ "&iocy;",
+ "&iogon;",
+ "&iopf;",
+ "&iota;",
+ "&iprod;",
+ "&iquest;",
+ "&iscr;",
+ "&isin;",
+ "&isinE;",
+ "&isindot;",
+ "&isins;",
+ "&isinsv;",
+ "&isinv;",
+ "&it;",
+ "&itilde;",
+ "&iukcy;",
+ "&iuml;",
+ "&jcirc;",
+ "&jcy;",
+ "&jfr;",
+ "&jmath;",
+ "&jopf;",
+ "&jscr;",
+ "&jsercy;",
+ "&jukcy;",
+ "&kappa;",
+ "&kappav;",
+ "&kcedil;",
+ "&kcy;",
+ "&kfr;",
+ "&kgreen;",
+ "&khcy;",
+ "&kjcy;",
+ "&kopf;",
+ "&kscr;",
+ "&lAarr;",
+ "&lArr;",
+ "&lAtail;",
+ "&lBarr;",
+ "&lE;",
+ "&lEg;",
+ "&lHar;",
+ "&lacute;",
+ "&laemptyv;",
+ "&lagran;",
+ "&lambda;",
+ "&lang;",
+ "&langd;",
+ "&langle;",
+ "&lap;",
+ "&laquo;",
+ "&larr;",
+ "&larrb;",
+ "&larrbfs;",
+ "&larrfs;",
+ "&larrhk;",
+ "&larrlp;",
+ "&larrpl;",
+ "&larrsim;",
+ "&larrtl;",
+ "&lat;",
+ "&latail;",
+ "&late;",
+ "&lates;",
+ "&lbarr;",
+ "&lbbrk;",
+ "&lbrace;",
+ "&lbrack;",
+ "&lbrke;",
+ "&lbrksld;",
+ "&lbrkslu;",
+ "&lcaron;",
+ "&lcedil;",
+ "&lceil;",
+ "&lcub;",
+ "&lcy;",
+ "&ldca;",
+ "&ldquo;",
+ "&ldquor;",
+ "&ldrdhar;",
+ "&ldrushar;",
+ "&ldsh;",
+ "&le;",
+ "&leftarrow;",
+ "&leftarrowtail;",
+ "&leftharpoondown;",
+ "&leftharpoonup;",
+ "&leftleftarrows;",
+ "&leftrightarrow;",
+ "&leftrightarrows;",
+ "&leftrightharpoons;",
+ "&leftrightsquigarrow;",
+ "&leftthreetimes;",
+ "&leg;",
+ "&leq;",
+ "&leqq;",
+ "&leqslant;",
+ "&les;",
+ "&lescc;",
+ "&lesdot;",
+ "&lesdoto;",
+ "&lesdotor;",
+ "&lesg;",
+ "&lesges;",
+ "&lessapprox;",
+ "&lessdot;",
+ "&lesseqgtr;",
+ "&lesseqqgtr;",
+ "&lessgtr;",
+ "&lesssim;",
+ "&lfisht;",
+ "&lfloor;",
+ "&lfr;",
+ "&lg;",
+ "&lgE;",
+ "&lhard;",
+ "&lharu;",
+ "&lharul;",
+ "&lhblk;",
+ "&ljcy;",
+ "&ll;",
+ "&llarr;",
+ "&llcorner;",
+ "&llhard;",
+ "&lltri;",
+ "&lmidot;",
+ "&lmoust;",
+ "&lmoustache;",
+ "&lnE;",
+ "&lnap;",
+ "&lnapprox;",
+ "&lne;",
+ "&lneq;",
+ "&lneqq;",
+ "&lnsim;",
+ "&loang;",
+ "&loarr;",
+ "&lobrk;",
+ "&longleftarrow;",
+ "&longleftrightarrow;",
+ "&longmapsto;",
+ "&longrightarrow;",
+ "&looparrowleft;",
+ "&looparrowright;",
+ "&lopar;",
+ "&lopf;",
+ "&loplus;",
+ "&lotimes;",
+ "&lowast;",
+ "&lowbar;",
+ "&loz;",
+ "&lozenge;",
+ "&lozf;",
+ "&lpar;",
+ "&lparlt;",
+ "&lrarr;",
+ "&lrcorner;",
+ "&lrhar;",
+ "&lrhard;",
+ "&lrm;",
+ "&lrtri;",
+ "&lsaquo;",
+ "&lscr;",
+ "&lsh;",
+ "&lsim;",
+ "&lsime;",
+ "&lsimg;",
+ "&lsqb;",
+ "&lsquo;",
+ "&lsquor;",
+ "&lstrok;",
+ "&lt;",
+ "&ltcc;",
+ "&ltcir;",
+ "&ltdot;",
+ "&lthree;",
+ "&ltimes;",
+ "&ltlarr;",
+ "&ltquest;",
+ "&ltrPar;",
+ "&ltri;",
+ "&ltrie;",
+ "&ltrif;",
+ "&lurdshar;",
+ "&luruhar;",
+ "&lvertneqq;",
+ "&lvnE;",
+ "&mDDot;",
+ "&macr;",
+ "&male;",
+ "&malt;",
+ "&maltese;",
+ "&map;",
+ "&mapsto;",
+ "&mapstodown;",
+ "&mapstoleft;",
+ "&mapstoup;",
+ "&marker;",
+ "&mcomma;",
+ "&mcy;",
+ "&mdash;",
+ "&measuredangle;",
+ "&mfr;",
+ "&mho;",
+ "&micro;",
+ "&mid;",
+ "&midast;",
+ "&midcir;",
+ "&middot;",
+ "&minus;",
+ "&minusb;",
+ "&minusd;",
+ "&minusdu;",
+ "&mlcp;",
+ "&mldr;",
+ "&mnplus;",
+ "&models;",
+ "&mopf;",
+ "&mp;",
+ "&mscr;",
+ "&mstpos;",
+ "&mu;",
+ "&multimap;",
+ "&mumap;",
+ "&nGg;",
+ "&nGt;",
+ "&nGtv;",
+ "&nLeftarrow;",
+ "&nLeftrightarrow;",
+ "&nLl;",
+ "&nLt;",
+ "&nLtv;",
+ "&nRightarrow;",
+ "&nVDash;",
+ "&nVdash;",
+ "&nabla;",
+ "&nacute;",
+ "&nang;",
+ "&nap;",
+ "&napE;",
+ "&napid;",
+ "&napos;",
+ "&napprox;",
+ "&natur;",
+ "&natural;",
+ "&naturals;",
+ "&nbsp;",
+ "&nbump;",
+ "&nbumpe;",
+ "&ncap;",
+ "&ncaron;",
+ "&ncedil;",
+ "&ncong;",
+ "&ncongdot;",
+ "&ncup;",
+ "&ncy;",
+ "&ndash;",
+ "&ne;",
+ "&neArr;",
+ "&nearhk;",
+ "&nearr;",
+ "&nearrow;",
+ "&nedot;",
+ "&nequiv;",
+ "&nesear;",
+ "&nesim;",
+ "&nexist;",
+ "&nexists;",
+ "&nfr;",
+ "&ngE;",
+ "&nge;",
+ "&ngeq;",
+ "&ngeqq;",
+ "&ngeqslant;",
+ "&nges;",
+ "&ngsim;",
+ "&ngt;",
+ "&ngtr;",
+ "&nhArr;",
+ "&nharr;",
+ "&nhpar;",
+ "&ni;",
+ "&nis;",
+ "&nisd;",
+ "&niv;",
+ "&njcy;",
+ "&nlArr;",
+ "&nlE;",
+ "&nlarr;",
+ "&nldr;",
+ "&nle;",
+ "&nleftarrow;",
+ "&nleftrightarrow;",
+ "&nleq;",
+ "&nleqq;",
+ "&nleqslant;",
+ "&nles;",
+ "&nless;",
+ "&nlsim;",
+ "&nlt;",
+ "&nltri;",
+ "&nltrie;",
+ "&nmid;",
+ "&nopf;",
+ "&not;",
+ "&notin;",
+ "&notinE;",
+ "&notindot;",
+ "&notinva;",
+ "&notinvb;",
+ "&notinvc;",
+ "&notni;",
+ "&notniva;",
+ "&notnivb;",
+ "&notnivc;",
+ "&npar;",
+ "&nparallel;",
+ "&nparsl;",
+ "&npart;",
+ "&npolint;",
+ "&npr;",
+ "&nprcue;",
+ "&npre;",
+ "&nprec;",
+ "&npreceq;",
+ "&nrArr;",
+ "&nrarr;",
+ "&nrarrc;",
+ "&nrarrw;",
+ "&nrightarrow;",
+ "&nrtri;",
+ "&nrtrie;",
+ "&nsc;",
+ "&nsccue;",
+ "&nsce;",
+ "&nscr;",
+ "&nshortmid;",
+ "&nshortparallel;",
+ "&nsim;",
+ "&nsime;",
+ "&nsimeq;",
+ "&nsmid;",
+ "&nspar;",
+ "&nsqsube;",
+ "&nsqsupe;",
+ "&nsub;",
+ "&nsubE;",
+ "&nsube;",
+ "&nsubset;",
+ "&nsubseteq;",
+ "&nsubseteqq;",
+ "&nsucc;",
+ "&nsucceq;",
+ "&nsup;",
+ "&nsupE;",
+ "&nsupe;",
+ "&nsupset;",
+ "&nsupseteq;",
+ "&nsupseteqq;",
+ "&ntgl;",
+ "&ntilde;",
+ "&ntlg;",
+ "&ntriangleleft;",
+ "&ntrianglelefteq;",
+ "&ntriangleright;",
+ "&ntrianglerighteq;",
+ "&nu;",
+ "&num;",
+ "&numero;",
+ "&numsp;",
+ "&nvDash;",
+ "&nvHarr;",
+ "&nvap;",
+ "&nvdash;",
+ "&nvge;",
+ "&nvgt;",
+ "&nvinfin;",
+ "&nvlArr;",
+ "&nvle;",
+ "&nvlt;",
+ "&nvltrie;",
+ "&nvrArr;",
+ "&nvrtrie;",
+ "&nvsim;",
+ "&nwArr;",
+ "&nwarhk;",
+ "&nwarr;",
+ "&nwarrow;",
+ "&nwnear;",
+ "&oS;",
+ "&oacute;",
+ "&oast;",
+ "&ocir;",
+ "&ocirc;",
+ "&ocy;",
+ "&odash;",
+ "&odblac;",
+ "&odiv;",
+ "&odot;",
+ "&odsold;",
+ "&oelig;",
+ "&ofcir;",
+ "&ofr;",
+ "&ogon;",
+ "&ograve;",
+ "&ogt;",
+ "&ohbar;",
+ "&ohm;",
+ "&oint;",
+ "&olarr;",
+ "&olcir;",
+ "&olcross;",
+ "&oline;",
+ "&olt;",
+ "&omacr;",
+ "&omega;",
+ "&omicron;",
+ "&omid;",
+ "&ominus;",
+ "&oopf;",
+ "&opar;",
+ "&operp;",
+ "&oplus;",
+ "&or;",
+ "&orarr;",
+ "&ord;",
+ "&order;",
+ "&orderof;",
+ "&ordf;",
+ "&ordm;",
+ "&origof;",
+ "&oror;",
+ "&orslope;",
+ "&orv;",
+ "&oscr;",
+ "&oslash;",
+ "&osol;",
+ "&otilde;",
+ "&otimes;",
+ "&otimesas;",
+ "&ouml;",
+ "&ovbar;",
+ "&par;",
+ "&para;",
+ "&parallel;",
+ "&parsim;",
+ "&parsl;",
+ "&part;",
+ "&pcy;",
+ "&percnt;",
+ "&period;",
+ "&permil;",
+ "&perp;",
+ "&pertenk;",
+ "&pfr;",
+ "&phi;",
+ "&phiv;",
+ "&phmmat;",
+ "&phone;",
+ "&pi;",
+ "&pitchfork;",
+ "&piv;",
+ "&planck;",
+ "&planckh;",
+ "&plankv;",
+ "&plus;",
+ "&plusacir;",
+ "&plusb;",
+ "&pluscir;",
+ "&plusdo;",
+ "&plusdu;",
+ "&pluse;",
+ "&plusmn;",
+ "&plussim;",
+ "&plustwo;",
+ "&pm;",
+ "&pointint;",
+ "&popf;",
+ "&pound;",
+ "&pr;",
+ "&prE;",
+ "&prap;",
+ "&prcue;",
+ "&pre;",
+ "&prec;",
+ "&precapprox;",
+ "&preccurlyeq;",
+ "&preceq;",
+ "&precnapprox;",
+ "&precneqq;",
+ "&precnsim;",
+ "&precsim;",
+ "&prime;",
+ "&primes;",
+ "&prnE;",
+ "&prnap;",
+ "&prnsim;",
+ "&prod;",
+ "&profalar;",
+ "&profline;",
+ "&profsurf;",
+ "&prop;",
+ "&propto;",
+ "&prsim;",
+ "&prurel;",
+ "&pscr;",
+ "&psi;",
+ "&puncsp;",
+ "&qfr;",
+ "&qint;",
+ "&qopf;",
+ "&qprime;",
+ "&qscr;",
+ "&quaternions;",
+ "&quatint;",
+ "&quest;",
+ "&questeq;",
+ "&quot;",
+ "&rAarr;",
+ "&rArr;",
+ "&rAtail;",
+ "&rBarr;",
+ "&rHar;",
+ "&race;",
+ "&racute;",
+ "&radic;",
+ "&raemptyv;",
+ "&rang;",
+ "&rangd;",
+ "&range;",
+ "&rangle;",
+ "&raquo;",
+ "&rarr;",
+ "&rarrap;",
+ "&rarrb;",
+ "&rarrbfs;",
+ "&rarrc;",
+ "&rarrfs;",
+ "&rarrhk;",
+ "&rarrlp;",
+ "&rarrpl;",
+ "&rarrsim;",
+ "&rarrtl;",
+ "&rarrw;",
+ "&ratail;",
+ "&ratio;",
+ "&rationals;",
+ "&rbarr;",
+ "&rbbrk;",
+ "&rbrace;",
+ "&rbrack;",
+ "&rbrke;",
+ "&rbrksld;",
+ "&rbrkslu;",
+ "&rcaron;",
+ "&rcedil;",
+ "&rceil;",
+ "&rcub;",
+ "&rcy;",
+ "&rdca;",
+ "&rdldhar;",
+ "&rdquo;",
+ "&rdquor;",
+ "&rdsh;",
+ "&real;",
+ "&realine;",
+ "&realpart;",
+ "&reals;",
+ "&rect;",
+ "&reg;",
+ "&rfisht;",
+ "&rfloor;",
+ "&rfr;",
+ "&rhard;",
+ "&rharu;",
+ "&rharul;",
+ "&rho;",
+ "&rhov;",
+ "&rightarrow;",
+ "&rightarrowtail;",
+ "&rightharpoondown;",
+ "&rightharpoonup;",
+ "&rightleftarrows;",
+ "&rightleftharpoons;",
+ "&rightrightarrows;",
+ "&rightsquigarrow;",
+ "&rightthreetimes;",
+ "&ring;",
+ "&risingdotseq;",
+ "&rlarr;",
+ "&rlhar;",
+ "&rlm;",
+ "&rmoust;",
+ "&rmoustache;",
+ "&rnmid;",
+ "&roang;",
+ "&roarr;",
+ "&robrk;",
+ "&ropar;",
+ "&ropf;",
+ "&roplus;",
+ "&rotimes;",
+ "&rpar;",
+ "&rpargt;",
+ "&rppolint;",
+ "&rrarr;",
+ "&rsaquo;",
+ "&rscr;",
+ "&rsh;",
+ "&rsqb;",
+ "&rsquo;",
+ "&rsquor;",
+ "&rthree;",
+ "&rtimes;",
+ "&rtri;",
+ "&rtrie;",
+ "&rtrif;",
+ "&rtriltri;",
+ "&ruluhar;",
+ "&rx;",
+ "&sacute;",
+ "&sbquo;",
+ "&sc;",
+ "&scE;",
+ "&scap;",
+ "&scaron;",
+ "&sccue;",
+ "&sce;",
+ "&scedil;",
+ "&scirc;",
+ "&scnE;",
+ "&scnap;",
+ "&scnsim;",
+ "&scpolint;",
+ "&scsim;",
+ "&scy;",
+ "&sdot;",
+ "&sdotb;",
+ "&sdote;",
+ "&seArr;",
+ "&searhk;",
+ "&searr;",
+ "&searrow;",
+ "&sect;",
+ "&semi;",
+ "&seswar;",
+ "&setminus;",
+ "&setmn;",
+ "&sext;",
+ "&sfr;",
+ "&sfrown;",
+ "&sharp;",
+ "&shchcy;",
+ "&shcy;",
+ "&shortmid;",
+ "&shortparallel;",
+ "&shy;",
+ "&sigma;",
+ "&sigmaf;",
+ "&sigmav;",
+ "&sim;",
+ "&simdot;",
+ "&sime;",
+ "&simeq;",
+ "&simg;",
+ "&simgE;",
+ "&siml;",
+ "&simlE;",
+ "&simne;",
+ "&simplus;",
+ "&simrarr;",
+ "&slarr;",
+ "&smallsetminus;",
+ "&smashp;",
+ "&smeparsl;",
+ "&smid;",
+ "&smile;",
+ "&smt;",
+ "&smte;",
+ "&smtes;",
+ "&softcy;",
+ "&sol;",
+ "&solb;",
+ "&solbar;",
+ "&sopf;",
+ "&spades;",
+ "&spadesuit;",
+ "&spar;",
+ "&sqcap;",
+ "&sqcaps;",
+ "&sqcup;",
+ "&sqcups;",
+ "&sqsub;",
+ "&sqsube;",
+ "&sqsubset;",
+ "&sqsubseteq;",
+ "&sqsup;",
+ "&sqsupe;",
+ "&sqsupset;",
+ "&sqsupseteq;",
+ "&squ;",
+ "&square;",
+ "&squarf;",
+ "&squf;",
+ "&srarr;",
+ "&sscr;",
+ "&ssetmn;",
+ "&ssmile;",
+ "&sstarf;",
+ "&star;",
+ "&starf;",
+ "&straightepsilon;",
+ "&straightphi;",
+ "&strns;",
+ "&sub;",
+ "&subE;",
+ "&subdot;",
+ "&sube;",
+ "&subedot;",
+ "&submult;",
+ "&subnE;",
+ "&subne;",
+ "&subplus;",
+ "&subrarr;",
+ "&subset;",
+ "&subseteq;",
+ "&subseteqq;",
+ "&subsetneq;",
+ "&subsetneqq;",
+ "&subsim;",
+ "&subsub;",
+ "&subsup;",
+ "&succ;",
+ "&succapprox;",
+ "&succcurlyeq;",
+ "&succeq;",
+ "&succnapprox;",
+ "&succneqq;",
+ "&succnsim;",
+ "&succsim;",
+ "&sum;",
+ "&sung;",
+ "&sup;",
+ "&sup1;",
+ "&sup2;",
+ "&sup3;",
+ "&supE;",
+ "&supdot;",
+ "&supdsub;",
+ "&supe;",
+ "&supedot;",
+ "&suphsol;",
+ "&suphsub;",
+ "&suplarr;",
+ "&supmult;",
+ "&supnE;",
+ "&supne;",
+ "&supplus;",
+ "&supset;",
+ "&supseteq;",
+ "&supseteqq;",
+ "&supsetneq;",
+ "&supsetneqq;",
+ "&supsim;",
+ "&supsub;",
+ "&supsup;",
+ "&swArr;",
+ "&swarhk;",
+ "&swarr;",
+ "&swarrow;",
+ "&swnwar;",
+ "&szlig;",
+ "&target;",
+ "&tau;",
+ "&tbrk;",
+ "&tcaron;",
+ "&tcedil;",
+ "&tcy;",
+ "&tdot;",
+ "&telrec;",
+ "&tfr;",
+ "&there4;",
+ "&therefore;",
+ "&theta;",
+ "&thetasym;",
+ "&thetav;",
+ "&thickapprox;",
+ "&thicksim;",
+ "&thinsp;",
+ "&thkap;",
+ "&thksim;",
+ "&thorn;",
+ "&tilde;",
+ "&times;",
+ "&timesb;",
+ "&timesbar;",
+ "&timesd;",
+ "&tint;",
+ "&toea;",
+ "&top;",
+ "&topbot;",
+ "&topcir;",
+ "&topf;",
+ "&topfork;",
+ "&tosa;",
+ "&tprime;",
+ "&trade;",
+ "&triangle;",
+ "&triangledown;",
+ "&triangleleft;",
+ "&trianglelefteq;",
+ "&triangleq;",
+ "&triangleright;",
+ "&trianglerighteq;",
+ "&tridot;",
+ "&trie;",
+ "&triminus;",
+ "&triplus;",
+ "&trisb;",
+ "&tritime;",
+ "&trpezium;",
+ "&tscr;",
+ "&tscy;",
+ "&tshcy;",
+ "&tstrok;",
+ "&twixt;",
+ "&twoheadleftarrow;",
+ "&twoheadrightarrow;",
+ "&uArr;",
+ "&uHar;",
+ "&uacute;",
+ "&uarr;",
+ "&ubrcy;",
+ "&ubreve;",
+ "&ucirc;",
+ "&ucy;",
+ "&udarr;",
+ "&udblac;",
+ "&udhar;",
+ "&ufisht;",
+ "&ufr;",
+ "&ugrave;",
+ "&uharl;",
+ "&uharr;",
+ "&uhblk;",
+ "&ulcorn;",
+ "&ulcorner;",
+ "&ulcrop;",
+ "&ultri;",
+ "&umacr;",
+ "&uml;",
+ "&uogon;",
+ "&uopf;",
+ "&uparrow;",
+ "&updownarrow;",
+ "&upharpoonleft;",
+ "&upharpoonright;",
+ "&uplus;",
+ "&upsi;",
+ "&upsih;",
+ "&upsilon;",
+ "&upuparrows;",
+ "&urcorn;",
+ "&urcorner;",
+ "&urcrop;",
+ "&uring;",
+ "&urtri;",
+ "&uscr;",
+ "&utdot;",
+ "&utilde;",
+ "&utri;",
+ "&utrif;",
+ "&uuarr;",
+ "&uuml;",
+ "&uwangle;",
+ "&vArr;",
+ "&vBar;",
+ "&vBarv;",
+ "&vDash;",
+ "&vangrt;",
+ "&varepsilon;",
+ "&varkappa;",
+ "&varnothing;",
+ "&varphi;",
+ "&varpi;",
+ "&varpropto;",
+ "&varr;",
+ "&varrho;",
+ "&varsigma;",
+ "&varsubsetneq;",
+ "&varsubsetneqq;",
+ "&varsupsetneq;",
+ "&varsupsetneqq;",
+ "&vartheta;",
+ "&vartriangleleft;",
+ "&vartriangleright;",
+ "&vcy;",
+ "&vdash;",
+ "&vee;",
+ "&veebar;",
+ "&veeeq;",
+ "&vellip;",
+ "&verbar;",
+ "&vert;",
+ "&vfr;",
+ "&vltri;",
+ "&vnsub;",
+ "&vnsup;",
+ "&vopf;",
+ "&vprop;",
+ "&vrtri;",
+ "&vscr;",
+ "&vsubnE;",
+ "&vsubne;",
+ "&vsupnE;",
+ "&vsupne;",
+ "&vzigzag;",
+ "&wcirc;",
+ "&wedbar;",
+ "&wedge;",
+ "&wedgeq;",
+ "&weierp;",
+ "&wfr;",
+ "&wopf;",
+ "&wp;",
+ "&wr;",
+ "&wreath;",
+ "&wscr;",
+ "&xcap;",
+ "&xcirc;",
+ "&xcup;",
+ "&xdtri;",
+ "&xfr;",
+ "&xhArr;",
+ "&xharr;",
+ "&xi;",
+ "&xlArr;",
+ "&xlarr;",
+ "&xmap;",
+ "&xnis;",
+ "&xodot;",
+ "&xopf;",
+ "&xoplus;",
+ "&xotime;",
+ "&xrArr;",
+ "&xrarr;",
+ "&xscr;",
+ "&xsqcup;",
+ "&xuplus;",
+ "&xutri;",
+ "&xvee;",
+ "&xwedge;",
+ "&yacute;",
+ "&yacy;",
+ "&ycirc;",
+ "&ycy;",
+ "&yen;",
+ "&yfr;",
+ "&yicy;",
+ "&yopf;",
+ "&yscr;",
+ "&yucy;",
+ "&yuml;",
+ "&zacute;",
+ "&zcaron;",
+ "&zcy;",
+ "&zdot;",
+ "&zeetrf;",
+ "&zeta;",
+ "&zfr;",
+ "&zhcy;",
+ "&zigrarr;",
+ "&zopf;",
+ "&zscr;",
+ "&zwj;",
+ "&zwnj;",
+);
+
+foreach ($map as $str) {
+ $de = html_entity_decode($str, ENT_QUOTES | ENT_HTML5, "UTF-8");
+ echo "$str => $de ", bin2hex($de), "\n";
+}
+?>
+--EXPECT--
+&AElig; => Æ c386
+&AMP; => & 26
+&Aacute; => Ã c381
+&Abreve; => Ä‚ c482
+&Acirc; => Â c382
+&Acy; => Ð d090
+&Afr; => 𔄠f09d9484
+&Agrave; => À c380
+&Alpha; => Α ce91
+&Amacr; => Ā c480
+&And; => â©“ e2a993
+&Aogon; => Ä„ c484
+&Aopf; => 𔸠f09d94b8
+&ApplyFunction; => â¡ e281a1
+&Aring; => Ã… c385
+&Ascr; => 𒜠f09d929c
+&Assign; => ≔ e28994
+&Atilde; => Ã c383
+&Auml; => Ä c384
+&Backslash; => ∖ e28896
+&Barv; => ⫧ e2aba7
+&Barwed; => ⌆ e28c86
+&Bcy; => Б d091
+&Because; => ∵ e288b5
+&Bernoullis; => ℬ e284ac
+&Beta; => Î’ ce92
+&Bfr; => ð”… f09d9485
+&Bopf; => 𔹠f09d94b9
+&Breve; => ˘ cb98
+&Bscr; => ℬ e284ac
+&Bumpeq; => ≎ e2898e
+&CHcy; => Ч d0a7
+&COPY; => © c2a9
+&Cacute; => Ć c486
+&Cap; => â‹’ e28b92
+&CapitalDifferentialD; => â…… e28585
+&Cayleys; => â„­ e284ad
+&Ccaron; => Č c48c
+&Ccedil; => Ç c387
+&Ccirc; => Ĉ c488
+&Cconint; => ∰ e288b0
+&Cdot; => ÄŠ c48a
+&Cedilla; => ¸ c2b8
+&CenterDot; => · c2b7
+&Cfr; => â„­ e284ad
+&Chi; => Χ cea7
+&CircleDot; => ⊙ e28a99
+&CircleMinus; => ⊖ e28a96
+&CirclePlus; => ⊕ e28a95
+&CircleTimes; => ⊗ e28a97
+&ClockwiseContourIntegral; => ∲ e288b2
+&CloseCurlyDoubleQuote; => †e2809d
+&CloseCurlyQuote; => ’ e28099
+&Colon; => ∷ e288b7
+&Colone; => â©´ e2a9b4
+&Congruent; => ≡ e289a1
+&Conint; => ∯ e288af
+&ContourIntegral; => ∮ e288ae
+&Copf; => â„‚ e28482
+&Coproduct; => ∠e28890
+&CounterClockwiseContourIntegral; => ∳ e288b3
+&Cross; => ⨯ e2a8af
+&Cscr; => ð’ž f09d929e
+&Cup; => â‹“ e28b93
+&CupCap; => ≠e2898d
+&DD; => â…… e28585
+&DDotrahd; => ⤑ e2a491
+&DJcy; => Ђ d082
+&DScy; => Ð… d085
+&DZcy; => Ð d08f
+&Dagger; => ‡ e280a1
+&Darr; => ↡ e286a1
+&Dashv; => ⫤ e2aba4
+&Dcaron; => ÄŽ c48e
+&Dcy; => Д d094
+&Del; => ∇ e28887
+&Delta; => Δ ce94
+&Dfr; => 𔇠f09d9487
+&DiacriticalAcute; => ´ c2b4
+&DiacriticalDot; => Ë™ cb99
+&DiacriticalDoubleAcute; => Ë cb9d
+&DiacriticalGrave; => ` 60
+&DiacriticalTilde; => ˜ cb9c
+&Diamond; => â‹„ e28b84
+&DifferentialD; => â…† e28586
+&Dopf; => ð”» f09d94bb
+&Dot; => ¨ c2a8
+&DotDot; => ⃜ e2839c
+&DotEqual; => ≠e28990
+&DoubleContourIntegral; => ∯ e288af
+&DoubleDot; => ¨ c2a8
+&DoubleDownArrow; => ⇓ e28793
+&DoubleLeftArrow; => ⇠e28790
+&DoubleLeftRightArrow; => ⇔ e28794
+&DoubleLeftTee; => ⫤ e2aba4
+&DoubleLongLeftArrow; => ⟸ e29fb8
+&DoubleLongLeftRightArrow; => ⟺ e29fba
+&DoubleLongRightArrow; => ⟹ e29fb9
+&DoubleRightArrow; => ⇒ e28792
+&DoubleRightTee; => ⊨ e28aa8
+&DoubleUpArrow; => ⇑ e28791
+&DoubleUpDownArrow; => ⇕ e28795
+&DoubleVerticalBar; => ∥ e288a5
+&DownArrow; => ↓ e28693
+&DownArrowBar; => ⤓ e2a493
+&DownArrowUpArrow; => ⇵ e287b5
+&DownBreve; => Ì‘ cc91
+&DownLeftRightVector; => ⥠e2a590
+&DownLeftTeeVector; => ⥞ e2a59e
+&DownLeftVector; => ↽ e286bd
+&DownLeftVectorBar; => ⥖ e2a596
+&DownRightTeeVector; => ⥟ e2a59f
+&DownRightVector; => ⇠e28781
+&DownRightVectorBar; => ⥗ e2a597
+&DownTee; => ⊤ e28aa4
+&DownTeeArrow; => ↧ e286a7
+&Downarrow; => ⇓ e28793
+&Dscr; => ð’Ÿ f09d929f
+&Dstrok; => Ä c490
+&ENG; => ÅŠ c58a
+&ETH; => Ã c390
+&Eacute; => É c389
+&Ecaron; => Äš c49a
+&Ecirc; => Ê c38a
+&Ecy; => Э d0ad
+&Edot; => Ä– c496
+&Efr; => 𔈠f09d9488
+&Egrave; => È c388
+&Element; => ∈ e28888
+&Emacr; => Ä’ c492
+&EmptySmallSquare; => â—» e297bb
+&EmptyVerySmallSquare; => â–« e296ab
+&Eogon; => Ę c498
+&Eopf; => 𔼠f09d94bc
+&Epsilon; => Ε ce95
+&Equal; => ⩵ e2a9b5
+&EqualTilde; => ≂ e28982
+&Equilibrium; => ⇌ e2878c
+&Escr; => â„° e284b0
+&Esim; => ⩳ e2a9b3
+&Eta; => Η ce97
+&Euml; => Ë c38b
+&Exists; => ∃ e28883
+&ExponentialE; => â…‡ e28587
+&Fcy; => Ф d0a4
+&Ffr; => 𔉠f09d9489
+&FilledSmallSquare; => â—¼ e297bc
+&FilledVerySmallSquare; => â–ª e296aa
+&Fopf; => 𔽠f09d94bd
+&ForAll; => ∀ e28880
+&Fouriertrf; => ℱ e284b1
+&Fscr; => ℱ e284b1
+&GJcy; => Ѓ d083
+&GT; => > 3e
+&Gamma; => Γ ce93
+&Gammad; => Ϝ cf9c
+&Gbreve; => Äž c49e
+&Gcedil; => Ģ c4a2
+&Gcirc; => Ĝ c49c
+&Gcy; => Г d093
+&Gdot; => Ä  c4a0
+&Gfr; => 𔊠f09d948a
+&Gg; => â‹™ e28b99
+&Gopf; => 𔾠f09d94be
+&GreaterEqual; => ≥ e289a5
+&GreaterEqualLess; => â‹› e28b9b
+&GreaterFullEqual; => ≧ e289a7
+&GreaterGreater; => ⪢ e2aaa2
+&GreaterLess; => ≷ e289b7
+&GreaterSlantEqual; => ⩾ e2a9be
+&GreaterTilde; => ≳ e289b3
+&Gscr; => ð’¢ f09d92a2
+&Gt; => ≫ e289ab
+&HARDcy; => Ъ d0aa
+&Hacek; => ˇ cb87
+&Hat; => ^ 5e
+&Hcirc; => Ĥ c4a4
+&Hfr; => ℌ e2848c
+&HilbertSpace; => â„‹ e2848b
+&Hopf; => â„ e2848d
+&HorizontalLine; => ─ e29480
+&Hscr; => â„‹ e2848b
+&Hstrok; => Ħ c4a6
+&HumpDownHump; => ≎ e2898e
+&HumpEqual; => ≠e2898f
+&IEcy; => Е d095
+&IJlig; => IJ c4b2
+&IOcy; => Ð d081
+&Iacute; => Ã c38d
+&Icirc; => ÃŽ c38e
+&Icy; => И d098
+&Idot; => Ä° c4b0
+&Ifr; => â„‘ e28491
+&Igrave; => Ì c38c
+&Im; => â„‘ e28491
+&Imacr; => Ī c4aa
+&ImaginaryI; => â…ˆ e28588
+&Implies; => ⇒ e28792
+&Int; => ∬ e288ac
+&Integral; => ∫ e288ab
+&Intersection; => â‹‚ e28b82
+&InvisibleComma; => ⣠e281a3
+&InvisibleTimes; => ⢠e281a2
+&Iogon; => Ä® c4ae
+&Iopf; => ð•€ f09d9580
+&Iota; => Ι ce99
+&Iscr; => â„ e28490
+&Itilde; => Ĩ c4a8
+&Iukcy; => І d086
+&Iuml; => Ã c38f
+&Jcirc; => Ä´ c4b4
+&Jcy; => Й d099
+&Jfr; => ð” f09d948d
+&Jopf; => ð• f09d9581
+&Jscr; => ð’¥ f09d92a5
+&Jsercy; => Ј d088
+&Jukcy; => Є d084
+&KHcy; => Х d0a5
+&KJcy; => Ќ d08c
+&Kappa; => Κ ce9a
+&Kcedil; => Ķ c4b6
+&Kcy; => К d09a
+&Kfr; => 𔎠f09d948e
+&Kopf; => ð•‚ f09d9582
+&Kscr; => ð’¦ f09d92a6
+&LJcy; => Љ d089
+&LT; => < 3c
+&Lacute; => Ĺ c4b9
+&Lambda; => Λ ce9b
+&Lang; => ⟪ e29faa
+&Laplacetrf; => â„’ e28492
+&Larr; => ↞ e2869e
+&Lcaron; => Ľ c4bd
+&Lcedil; => Ä» c4bb
+&Lcy; => Л d09b
+&LeftAngleBracket; => ⟨ e29fa8
+&LeftArrow; => ↠e28690
+&LeftArrowBar; => ⇤ e287a4
+&LeftArrowRightArrow; => ⇆ e28786
+&LeftCeiling; => ⌈ e28c88
+&LeftDoubleBracket; => ⟦ e29fa6
+&LeftDownTeeVector; => ⥡ e2a5a1
+&LeftDownVector; => ⇃ e28783
+&LeftDownVectorBar; => ⥙ e2a599
+&LeftFloor; => ⌊ e28c8a
+&LeftRightArrow; => ↔ e28694
+&LeftRightVector; => ⥎ e2a58e
+&LeftTee; => ⊣ e28aa3
+&LeftTeeArrow; => ↤ e286a4
+&LeftTeeVector; => ⥚ e2a59a
+&LeftTriangle; => ⊲ e28ab2
+&LeftTriangleBar; => ⧠e2a78f
+&LeftTriangleEqual; => ⊴ e28ab4
+&LeftUpDownVector; => ⥑ e2a591
+&LeftUpTeeVector; => ⥠ e2a5a0
+&LeftUpVector; => ↿ e286bf
+&LeftUpVectorBar; => ⥘ e2a598
+&LeftVector; => ↼ e286bc
+&LeftVectorBar; => ⥒ e2a592
+&Leftarrow; => ⇠e28790
+&Leftrightarrow; => ⇔ e28794
+&LessEqualGreater; => â‹š e28b9a
+&LessFullEqual; => ≦ e289a6
+&LessGreater; => ≶ e289b6
+&LessLess; => ⪡ e2aaa1
+&LessSlantEqual; => ⩽ e2a9bd
+&LessTilde; => ≲ e289b2
+&Lfr; => ð” f09d948f
+&Ll; => ⋘ e28b98
+&Lleftarrow; => ⇚ e2879a
+&Lmidot; => Ä¿ c4bf
+&LongLeftArrow; => ⟵ e29fb5
+&LongLeftRightArrow; => ⟷ e29fb7
+&LongRightArrow; => ⟶ e29fb6
+&Longleftarrow; => ⟸ e29fb8
+&Longleftrightarrow; => ⟺ e29fba
+&Longrightarrow; => ⟹ e29fb9
+&Lopf; => 𕃠f09d9583
+&LowerLeftArrow; => ↙ e28699
+&LowerRightArrow; => ↘ e28698
+&Lscr; => â„’ e28492
+&Lsh; => ↰ e286b0
+&Lstrok; => Å c581
+&Lt; => ≪ e289aa
+&Map; => ⤅ e2a485
+&Mcy; => М d09c
+&MediumSpace; => ⟠e2819f
+&Mellintrf; => ℳ e284b3
+&Mfr; => ð” f09d9490
+&MinusPlus; => ∓ e28893
+&Mopf; => ð•„ f09d9584
+&Mscr; => ℳ e284b3
+&Mu; => Μ ce9c
+&NJcy; => Њ d08a
+&Nacute; => Ń c583
+&Ncaron; => Ň c587
+&Ncedil; => Å… c585
+&Ncy; => Ð d09d
+&NegativeMediumSpace; => ​ e2808b
+&NegativeThickSpace; => ​ e2808b
+&NegativeThinSpace; => ​ e2808b
+&NegativeVeryThinSpace; => ​ e2808b
+&NestedGreaterGreater; => ≫ e289ab
+&NestedLessLess; => ≪ e289aa
+&NewLine; =>
+ 0a
+&Nfr; => 𔑠f09d9491
+&NoBreak; => â  e281a0
+&NonBreakingSpace; =>   c2a0
+&Nopf; => â„• e28495
+&Not; => ⫬ e2abac
+&NotCongruent; => ≢ e289a2
+&NotCupCap; => ≭ e289ad
+&NotDoubleVerticalBar; => ∦ e288a6
+&NotElement; => ∉ e28889
+&NotEqual; => ≠ e289a0
+&NotEqualTilde; => ≂̸ e28982ccb8
+&NotExists; => ∄ e28884
+&NotGreater; => ≯ e289af
+&NotGreaterEqual; => ≱ e289b1
+&NotGreaterFullEqual; => ≧̸ e289a7ccb8
+&NotGreaterGreater; => ≫̸ e289abccb8
+&NotGreaterLess; => ≹ e289b9
+&NotGreaterSlantEqual; => ⩾̸ e2a9beccb8
+&NotGreaterTilde; => ≵ e289b5
+&NotHumpDownHump; => ≎̸ e2898eccb8
+&NotHumpEqual; => â‰Ì¸ e2898fccb8
+&NotLeftTriangle; => ⋪ e28baa
+&NotLeftTriangleBar; => â§Ì¸ e2a78fccb8
+&NotLeftTriangleEqual; => ⋬ e28bac
+&NotLess; => ≮ e289ae
+&NotLessEqual; => ≰ e289b0
+&NotLessGreater; => ≸ e289b8
+&NotLessLess; => ≪̸ e289aaccb8
+&NotLessSlantEqual; => ⩽̸ e2a9bdccb8
+&NotLessTilde; => ≴ e289b4
+&NotNestedGreaterGreater; => ⪢̸ e2aaa2ccb8
+&NotNestedLessLess; => ⪡̸ e2aaa1ccb8
+&NotPrecedes; => ⊀ e28a80
+&NotPrecedesEqual; => ⪯̸ e2aaafccb8
+&NotPrecedesSlantEqual; => â‹  e28ba0
+&NotReverseElement; => ∌ e2888c
+&NotRightTriangle; => â‹« e28bab
+&NotRightTriangleBar; => â§Ì¸ e2a790ccb8
+&NotRightTriangleEqual; => â‹­ e28bad
+&NotSquareSubset; => âŠÌ¸ e28a8fccb8
+&NotSquareSubsetEqual; => â‹¢ e28ba2
+&NotSquareSuperset; => âŠÌ¸ e28a90ccb8
+&NotSquareSupersetEqual; => â‹£ e28ba3
+&NotSubset; => ⊂⃒ e28a82e28392
+&NotSubsetEqual; => ⊈ e28a88
+&NotSucceeds; => ⊠e28a81
+&NotSucceedsEqual; => ⪰̸ e2aab0ccb8
+&NotSucceedsSlantEqual; => â‹¡ e28ba1
+&NotSucceedsTilde; => ≿̸ e289bfccb8
+&NotSuperset; => ⊃⃒ e28a83e28392
+&NotSupersetEqual; => ⊉ e28a89
+&NotTilde; => ≠e28981
+&NotTildeEqual; => ≄ e28984
+&NotTildeFullEqual; => ≇ e28987
+&NotTildeTilde; => ≉ e28989
+&NotVerticalBar; => ∤ e288a4
+&Nscr; => ð’© f09d92a9
+&Ntilde; => Ñ c391
+&Nu; => Î ce9d
+&OElig; => Å’ c592
+&Oacute; => Ó c393
+&Ocirc; => Ô c394
+&Ocy; => О d09e
+&Odblac; => Å c590
+&Ofr; => ð”’ f09d9492
+&Ograve; => Ã’ c392
+&Omacr; => Ō c58c
+&Omega; => Ω cea9
+&Omicron; => Ο ce9f
+&Oopf; => 𕆠f09d9586
+&OpenCurlyDoubleQuote; => “ e2809c
+&OpenCurlyQuote; => ‘ e28098
+&Or; => â©” e2a994
+&Oscr; => ð’ª f09d92aa
+&Oslash; => Ø c398
+&Otilde; => Õ c395
+&Otimes; => ⨷ e2a8b7
+&Ouml; => Ö c396
+&OverBar; => ‾ e280be
+&OverBrace; => âž e28f9e
+&OverBracket; => ⎴ e28eb4
+&OverParenthesis; => ✠e28f9c
+&PartialD; => ∂ e28882
+&Pcy; => П d09f
+&Pfr; => 𔓠f09d9493
+&Phi; => Φ cea6
+&Pi; => Π cea0
+&PlusMinus; => ± c2b1
+&Poincareplane; => ℌ e2848c
+&Popf; => â„™ e28499
+&Pr; => ⪻ e2aabb
+&Precedes; => ≺ e289ba
+&PrecedesEqual; => ⪯ e2aaaf
+&PrecedesSlantEqual; => ≼ e289bc
+&PrecedesTilde; => ≾ e289be
+&Prime; => ″ e280b3
+&Product; => ∠e2888f
+&Proportion; => ∷ e288b7
+&Proportional; => ∠e2889d
+&Pscr; => ð’« f09d92ab
+&Psi; => Ψ cea8
+&QUOT; => " 22
+&Qfr; => ð”” f09d9494
+&Qopf; => â„š e2849a
+&Qscr; => ð’¬ f09d92ac
+&RBarr; => ⤠e2a490
+&REG; => ® c2ae
+&Racute; => Å” c594
+&Rang; => ⟫ e29fab
+&Rarr; => ↠ e286a0
+&Rarrtl; => ⤖ e2a496
+&Rcaron; => Ř c598
+&Rcedil; => Å– c596
+&Rcy; => Р d0a0
+&Re; => ℜ e2849c
+&ReverseElement; => ∋ e2888b
+&ReverseEquilibrium; => ⇋ e2878b
+&ReverseUpEquilibrium; => ⥯ e2a5af
+&Rfr; => ℜ e2849c
+&Rho; => Ρ cea1
+&RightAngleBracket; => ⟩ e29fa9
+&RightArrow; => → e28692
+&RightArrowBar; => ⇥ e287a5
+&RightArrowLeftArrow; => ⇄ e28784
+&RightCeiling; => ⌉ e28c89
+&RightDoubleBracket; => ⟧ e29fa7
+&RightDownTeeVector; => ⥠e2a59d
+&RightDownVector; => ⇂ e28782
+&RightDownVectorBar; => ⥕ e2a595
+&RightFloor; => ⌋ e28c8b
+&RightTee; => ⊢ e28aa2
+&RightTeeArrow; => ↦ e286a6
+&RightTeeVector; => ⥛ e2a59b
+&RightTriangle; => ⊳ e28ab3
+&RightTriangleBar; => ⧠e2a790
+&RightTriangleEqual; => ⊵ e28ab5
+&RightUpDownVector; => ⥠e2a58f
+&RightUpTeeVector; => ⥜ e2a59c
+&RightUpVector; => ↾ e286be
+&RightUpVectorBar; => ⥔ e2a594
+&RightVector; => ⇀ e28780
+&RightVectorBar; => ⥓ e2a593
+&Rightarrow; => ⇒ e28792
+&Ropf; => â„ e2849d
+&RoundImplies; => ⥰ e2a5b0
+&Rrightarrow; => ⇛ e2879b
+&Rscr; => â„› e2849b
+&Rsh; => ↱ e286b1
+&RuleDelayed; => ⧴ e2a7b4
+&SHCHcy; => Щ d0a9
+&SHcy; => Ш d0a8
+&SOFTcy; => Ь d0ac
+&Sacute; => Åš c59a
+&Sc; => ⪼ e2aabc
+&Scaron; => Å  c5a0
+&Scedil; => Åž c59e
+&Scirc; => Ŝ c59c
+&Scy; => С d0a1
+&Sfr; => ð”– f09d9496
+&ShortDownArrow; => ↓ e28693
+&ShortLeftArrow; => ↠e28690
+&ShortRightArrow; => → e28692
+&ShortUpArrow; => ↑ e28691
+&Sigma; => Σ cea3
+&SmallCircle; => ∘ e28898
+&Sopf; => ð•Š f09d958a
+&Sqrt; => √ e2889a
+&Square; => â–¡ e296a1
+&SquareIntersection; => ⊓ e28a93
+&SquareSubset; => ⊠e28a8f
+&SquareSubsetEqual; => ⊑ e28a91
+&SquareSuperset; => ⊠e28a90
+&SquareSupersetEqual; => ⊒ e28a92
+&SquareUnion; => ⊔ e28a94
+&Sscr; => ð’® f09d92ae
+&Star; => ⋆ e28b86
+&Sub; => â‹ e28b90
+&Subset; => â‹ e28b90
+&SubsetEqual; => ⊆ e28a86
+&Succeeds; => ≻ e289bb
+&SucceedsEqual; => ⪰ e2aab0
+&SucceedsSlantEqual; => ≽ e289bd
+&SucceedsTilde; => ≿ e289bf
+&SuchThat; => ∋ e2888b
+&Sum; => ∑ e28891
+&Sup; => â‹‘ e28b91
+&Superset; => ⊃ e28a83
+&SupersetEqual; => ⊇ e28a87
+&Supset; => â‹‘ e28b91
+&THORN; => Þ c39e
+&TRADE; => â„¢ e284a2
+&TSHcy; => Ћ d08b
+&TScy; => Ц d0a6
+&Tab; => 09
+&Tau; => Τ cea4
+&Tcaron; => Ť c5a4
+&Tcedil; => Ţ c5a2
+&Tcy; => Т d0a2
+&Tfr; => ð”— f09d9497
+&Therefore; => ∴ e288b4
+&Theta; => Θ ce98
+&ThickSpace; => âŸâ€Š e2819fe2808a
+&ThinSpace; =>   e28089
+&Tilde; => ∼ e288bc
+&TildeEqual; => ≃ e28983
+&TildeFullEqual; => ≅ e28985
+&TildeTilde; => ≈ e28988
+&Topf; => ð•‹ f09d958b
+&TripleDot; => ⃛ e2839b
+&Tscr; => ð’¯ f09d92af
+&Tstrok; => Ŧ c5a6
+&Uacute; => Ú c39a
+&Uarr; => ↟ e2869f
+&Uarrocir; => ⥉ e2a589
+&Ubrcy; => ÐŽ d08e
+&Ubreve; => Ŭ c5ac
+&Ucirc; => Û c39b
+&Ucy; => У d0a3
+&Udblac; => Å° c5b0
+&Ufr; => 𔘠f09d9498
+&Ugrave; => Ù c399
+&Umacr; => Ū c5aa
+&UnderBar; => _ 5f
+&UnderBrace; => ⟠e28f9f
+&UnderBracket; => ⎵ e28eb5
+&UnderParenthesis; => â e28f9d
+&Union; => ⋃ e28b83
+&UnionPlus; => ⊎ e28a8e
+&Uogon; => Ų c5b2
+&Uopf; => 𕌠f09d958c
+&UpArrow; => ↑ e28691
+&UpArrowBar; => ⤒ e2a492
+&UpArrowDownArrow; => ⇅ e28785
+&UpDownArrow; => ↕ e28695
+&UpEquilibrium; => ⥮ e2a5ae
+&UpTee; => ⊥ e28aa5
+&UpTeeArrow; => ↥ e286a5
+&Uparrow; => ⇑ e28791
+&Updownarrow; => ⇕ e28795
+&UpperLeftArrow; => ↖ e28696
+&UpperRightArrow; => ↗ e28697
+&Upsi; => Ï’ cf92
+&Upsilon; => Υ cea5
+&Uring; => Å® c5ae
+&Uscr; => ð’° f09d92b0
+&Utilde; => Ũ c5a8
+&Uuml; => Ü c39c
+&VDash; => ⊫ e28aab
+&Vbar; => â«« e2abab
+&Vcy; => Ð’ d092
+&Vdash; => ⊩ e28aa9
+&Vdashl; => ⫦ e2aba6
+&Vee; => â‹ e28b81
+&Verbar; => ‖ e28096
+&Vert; => ‖ e28096
+&VerticalBar; => ∣ e288a3
+&VerticalLine; => | 7c
+&VerticalSeparator; => ☠e29d98
+&VerticalTilde; => ≀ e28980
+&VeryThinSpace; =>   e2808a
+&Vfr; => ð”™ f09d9499
+&Vopf; => ð• f09d958d
+&Vscr; => ð’± f09d92b1
+&Vvdash; => ⊪ e28aaa
+&Wcirc; => Å´ c5b4
+&Wedge; => â‹€ e28b80
+&Wfr; => 𔚠f09d949a
+&Wopf; => ð•Ž f09d958e
+&Wscr; => ð’² f09d92b2
+&Xfr; => ð”› f09d949b
+&Xi; => Ξ ce9e
+&Xopf; => ð• f09d958f
+&Xscr; => ð’³ f09d92b3
+&YAcy; => Я d0af
+&YIcy; => Ї d087
+&YUcy; => Ю d0ae
+&Yacute; => Ã c39d
+&Ycirc; => Ŷ c5b6
+&Ycy; => Ы d0ab
+&Yfr; => 𔜠f09d949c
+&Yopf; => ð• f09d9590
+&Yscr; => ð’´ f09d92b4
+&Yuml; => Ÿ c5b8
+&ZHcy; => Ж d096
+&Zacute; => Ź c5b9
+&Zcaron; => Ž c5bd
+&Zcy; => З d097
+&Zdot; => Å» c5bb
+&ZeroWidthSpace; => ​ e2808b
+&Zeta; => Ζ ce96
+&Zfr; => ℨ e284a8
+&Zopf; => ℤ e284a4
+&Zscr; => ð’µ f09d92b5
+&aacute; => á c3a1
+&abreve; => ă c483
+&ac; => ∾ e288be
+&acE; => ∾̳ e288beccb3
+&acd; => ∿ e288bf
+&acirc; => â c3a2
+&acute; => ´ c2b4
+&acy; => а d0b0
+&aelig; => æ c3a6
+&af; => â¡ e281a1
+&afr; => 𔞠f09d949e
+&agrave; => à c3a0
+&alefsym; => ℵ e284b5
+&aleph; => ℵ e284b5
+&alpha; => α ceb1
+&amacr; => Ä c481
+&amalg; => ⨿ e2a8bf
+&amp; => & 26
+&and; => ∧ e288a7
+&andand; => â©• e2a995
+&andd; => ⩜ e2a99c
+&andslope; => ⩘ e2a998
+&andv; => â©š e2a99a
+&ang; => ∠ e288a0
+&ange; => ⦤ e2a6a4
+&angle; => ∠ e288a0
+&angmsd; => ∡ e288a1
+&angmsdaa; => ⦨ e2a6a8
+&angmsdab; => ⦩ e2a6a9
+&angmsdac; => ⦪ e2a6aa
+&angmsdad; => ⦫ e2a6ab
+&angmsdae; => ⦬ e2a6ac
+&angmsdaf; => ⦭ e2a6ad
+&angmsdag; => ⦮ e2a6ae
+&angmsdah; => ⦯ e2a6af
+&angrt; => ∟ e2889f
+&angrtvb; => ⊾ e28abe
+&angrtvbd; => ⦠e2a69d
+&angsph; => ∢ e288a2
+&angst; => Ã… c385
+&angzarr; => â¼ e28dbc
+&aogon; => Ä… c485
+&aopf; => ð•’ f09d9592
+&ap; => ≈ e28988
+&apE; => â©° e2a9b0
+&apacir; => ⩯ e2a9af
+&ape; => ≊ e2898a
+&apid; => ≋ e2898b
+&apos; => ' 27
+&approx; => ≈ e28988
+&approxeq; => ≊ e2898a
+&aring; => å c3a5
+&ascr; => ð’¶ f09d92b6
+&ast; => * 2a
+&asymp; => ≈ e28988
+&asympeq; => ≠e2898d
+&atilde; => ã c3a3
+&auml; => ä c3a4
+&awconint; => ∳ e288b3
+&awint; => ⨑ e2a891
+&bNot; => â«­ e2abad
+&backcong; => ≌ e2898c
+&backepsilon; => ϶ cfb6
+&backprime; => ‵ e280b5
+&backsim; => ∽ e288bd
+&backsimeq; => â‹ e28b8d
+&barvee; => ⊽ e28abd
+&barwed; => ⌅ e28c85
+&barwedge; => ⌅ e28c85
+&bbrk; => ⎵ e28eb5
+&bbrktbrk; => ⎶ e28eb6
+&bcong; => ≌ e2898c
+&bcy; => б d0b1
+&bdquo; => „ e2809e
+&becaus; => ∵ e288b5
+&because; => ∵ e288b5
+&bemptyv; => ⦰ e2a6b0
+&bepsi; => ϶ cfb6
+&bernou; => ℬ e284ac
+&beta; => β ceb2
+&beth; => ℶ e284b6
+&between; => ≬ e289ac
+&bfr; => 𔟠f09d949f
+&bigcap; => â‹‚ e28b82
+&bigcirc; => â—¯ e297af
+&bigcup; => ⋃ e28b83
+&bigodot; => ⨀ e2a880
+&bigoplus; => ⨠e2a881
+&bigotimes; => ⨂ e2a882
+&bigsqcup; => ⨆ e2a886
+&bigstar; => ★ e29885
+&bigtriangledown; => â–½ e296bd
+&bigtriangleup; => â–³ e296b3
+&biguplus; => ⨄ e2a884
+&bigvee; => â‹ e28b81
+&bigwedge; => â‹€ e28b80
+&bkarow; => ⤠e2a48d
+&blacklozenge; => ⧫ e2a7ab
+&blacksquare; => â–ª e296aa
+&blacktriangle; => â–´ e296b4
+&blacktriangledown; => â–¾ e296be
+&blacktriangleleft; => â—‚ e29782
+&blacktriangleright; => â–¸ e296b8
+&blank; => ⣠e290a3
+&blk12; => â–’ e29692
+&blk14; => â–‘ e29691
+&blk34; => â–“ e29693
+&block; => â–ˆ e29688
+&bne; => =⃥ 3de283a5
+&bnequiv; => ≡⃥ e289a1e283a5
+&bnot; => ⌠e28c90
+&bopf; => ð•“ f09d9593
+&bot; => ⊥ e28aa5
+&bottom; => ⊥ e28aa5
+&bowtie; => ⋈ e28b88
+&boxDL; => â•— e29597
+&boxDR; => â•” e29594
+&boxDl; => â•– e29596
+&boxDr; => â•“ e29593
+&boxH; => â• e29590
+&boxHD; => ╦ e295a6
+&boxHU; => â•© e295a9
+&boxHd; => ╤ e295a4
+&boxHu; => ╧ e295a7
+&boxUL; => â• e2959d
+&boxUR; => â•š e2959a
+&boxUl; => ╜ e2959c
+&boxUr; => â•™ e29599
+&boxV; => â•‘ e29591
+&boxVH; => ╬ e295ac
+&boxVL; => â•£ e295a3
+&boxVR; => â•  e295a0
+&boxVh; => â•« e295ab
+&boxVl; => â•¢ e295a2
+&boxVr; => â•Ÿ e2959f
+&boxbox; => ⧉ e2a789
+&boxdL; => â•• e29595
+&boxdR; => â•’ e29592
+&boxdl; => â” e29490
+&boxdr; => ┌ e2948c
+&boxh; => ─ e29480
+&boxhD; => â•¥ e295a5
+&boxhU; => ╨ e295a8
+&boxhd; => ┬ e294ac
+&boxhu; => â”´ e294b4
+&boxminus; => ⊟ e28a9f
+&boxplus; => ⊞ e28a9e
+&boxtimes; => ⊠ e28aa0
+&boxuL; => â•› e2959b
+&boxuR; => ╘ e29598
+&boxul; => ┘ e29498
+&boxur; => â”” e29494
+&boxv; => │ e29482
+&boxvH; => ╪ e295aa
+&boxvL; => â•¡ e295a1
+&boxvR; => â•ž e2959e
+&boxvh; => ┼ e294bc
+&boxvl; => ┤ e294a4
+&boxvr; => ├ e2949c
+&bprime; => ‵ e280b5
+&breve; => ˘ cb98
+&brvbar; => ¦ c2a6
+&bscr; => ð’· f09d92b7
+&bsemi; => â e2818f
+&bsim; => ∽ e288bd
+&bsime; => â‹ e28b8d
+&bsol; => \ 5c
+&bsolb; => ⧅ e2a785
+&bsolhsub; => ⟈ e29f88
+&bull; => • e280a2
+&bullet; => • e280a2
+&bump; => ≎ e2898e
+&bumpE; => ⪮ e2aaae
+&bumpe; => ≠e2898f
+&bumpeq; => ≠e2898f
+&cacute; => ć c487
+&cap; => ∩ e288a9
+&capand; => â©„ e2a984
+&capbrcup; => ⩉ e2a989
+&capcap; => â©‹ e2a98b
+&capcup; => ⩇ e2a987
+&capdot; => â©€ e2a980
+&caps; => ∩︀ e288a9efb880
+&caret; => â e28181
+&caron; => ˇ cb87
+&ccaps; => â© e2a98d
+&ccaron; => Ä c48d
+&ccedil; => ç c3a7
+&ccirc; => ĉ c489
+&ccups; => ⩌ e2a98c
+&ccupssm; => â© e2a990
+&cdot; => Ä‹ c48b
+&cedil; => ¸ c2b8
+&cemptyv; => ⦲ e2a6b2
+&cent; => ¢ c2a2
+&centerdot; => · c2b7
+&cfr; => ð”  f09d94a0
+&chcy; => ч d187
+&check; => ✓ e29c93
+&checkmark; => ✓ e29c93
+&chi; => χ cf87
+&cir; => â—‹ e2978b
+&cirE; => ⧃ e2a783
+&circ; => ˆ cb86
+&circeq; => ≗ e28997
+&circlearrowleft; => ↺ e286ba
+&circlearrowright; => ↻ e286bb
+&circledR; => ® c2ae
+&circledS; => Ⓢ e29388
+&circledast; => ⊛ e28a9b
+&circledcirc; => ⊚ e28a9a
+&circleddash; => ⊠e28a9d
+&cire; => ≗ e28997
+&cirfnint; => ⨠e2a890
+&cirmid; => ⫯ e2abaf
+&cirscir; => ⧂ e2a782
+&clubs; => ♣ e299a3
+&clubsuit; => ♣ e299a3
+&colon; => : 3a
+&colone; => ≔ e28994
+&coloneq; => ≔ e28994
+&comma; => , 2c
+&commat; => @ 40
+&comp; => ∠e28881
+&compfn; => ∘ e28898
+&complement; => ∠e28881
+&complexes; => â„‚ e28482
+&cong; => ≅ e28985
+&congdot; => â©­ e2a9ad
+&conint; => ∮ e288ae
+&copf; => ð•” f09d9594
+&coprod; => ∠e28890
+&copy; => © c2a9
+&copysr; => â„— e28497
+&crarr; => ↵ e286b5
+&cross; => ✗ e29c97
+&cscr; => ð’¸ f09d92b8
+&csub; => â« e2ab8f
+&csube; => â«‘ e2ab91
+&csup; => â« e2ab90
+&csupe; => â«’ e2ab92
+&ctdot; => ⋯ e28baf
+&cudarrl; => ⤸ e2a4b8
+&cudarrr; => ⤵ e2a4b5
+&cuepr; => â‹ž e28b9e
+&cuesc; => â‹Ÿ e28b9f
+&cularr; => ↶ e286b6
+&cularrp; => ⤽ e2a4bd
+&cup; => ∪ e288aa
+&cupbrcap; => ⩈ e2a988
+&cupcap; => ⩆ e2a986
+&cupcup; => â©Š e2a98a
+&cupdot; => ⊠e28a8d
+&cupor; => â©… e2a985
+&cups; => ∪︀ e288aaefb880
+&curarr; => ↷ e286b7
+&curarrm; => ⤼ e2a4bc
+&curlyeqprec; => â‹ž e28b9e
+&curlyeqsucc; => â‹Ÿ e28b9f
+&curlyvee; => â‹Ž e28b8e
+&curlywedge; => â‹ e28b8f
+&curren; => ¤ c2a4
+&curvearrowleft; => ↶ e286b6
+&curvearrowright; => ↷ e286b7
+&cuvee; => â‹Ž e28b8e
+&cuwed; => â‹ e28b8f
+&cwconint; => ∲ e288b2
+&cwint; => ∱ e288b1
+&cylcty; => ⌭ e28cad
+&dArr; => ⇓ e28793
+&dHar; => ⥥ e2a5a5
+&dagger; => † e280a0
+&daleth; => ℸ e284b8
+&darr; => ↓ e28693
+&dash; => †e28090
+&dashv; => ⊣ e28aa3
+&dbkarow; => ⤠e2a48f
+&dblac; => Ë cb9d
+&dcaron; => Ä c48f
+&dcy; => д d0b4
+&dd; => â…† e28586
+&ddagger; => ‡ e280a1
+&ddarr; => ⇊ e2878a
+&ddotseq; => â©· e2a9b7
+&deg; => ° c2b0
+&delta; => δ ceb4
+&demptyv; => ⦱ e2a6b1
+&dfisht; => ⥿ e2a5bf
+&dfr; => 𔡠f09d94a1
+&dharl; => ⇃ e28783
+&dharr; => ⇂ e28782
+&diam; => â‹„ e28b84
+&diamond; => â‹„ e28b84
+&diamondsuit; => ♦ e299a6
+&diams; => ♦ e299a6
+&die; => ¨ c2a8
+&digamma; => Ï cf9d
+&disin; => ⋲ e28bb2
+&div; => ÷ c3b7
+&divide; => ÷ c3b7
+&divideontimes; => ⋇ e28b87
+&divonx; => ⋇ e28b87
+&djcy; => Ñ’ d192
+&dlcorn; => ⌞ e28c9e
+&dlcrop; => ⌠e28c8d
+&dollar; => $ 24
+&dopf; => ð•• f09d9595
+&dot; => Ë™ cb99
+&doteq; => ≠e28990
+&doteqdot; => ≑ e28991
+&dotminus; => ∸ e288b8
+&dotplus; => ∔ e28894
+&dotsquare; => ⊡ e28aa1
+&doublebarwedge; => ⌆ e28c86
+&downarrow; => ↓ e28693
+&downdownarrows; => ⇊ e2878a
+&downharpoonleft; => ⇃ e28783
+&downharpoonright; => ⇂ e28782
+&drbkarow; => ⤠e2a490
+&drcorn; => ⌟ e28c9f
+&drcrop; => ⌌ e28c8c
+&dscr; => ð’¹ f09d92b9
+&dscy; => Ñ• d195
+&dsol; => ⧶ e2a7b6
+&dstrok; => Ä‘ c491
+&dtdot; => ⋱ e28bb1
+&dtri; => â–¿ e296bf
+&dtrif; => â–¾ e296be
+&duarr; => ⇵ e287b5
+&duhar; => ⥯ e2a5af
+&dwangle; => ⦦ e2a6a6
+&dzcy; => ÑŸ d19f
+&dzigrarr; => ⟿ e29fbf
+&eDDot; => â©· e2a9b7
+&eDot; => ≑ e28991
+&eacute; => é c3a9
+&easter; => â©® e2a9ae
+&ecaron; => Ä› c49b
+&ecir; => ≖ e28996
+&ecirc; => ê c3aa
+&ecolon; => ≕ e28995
+&ecy; => Ñ d18d
+&edot; => Ä— c497
+&ee; => â…‡ e28587
+&efDot; => ≒ e28992
+&efr; => 𔢠f09d94a2
+&eg; => ⪚ e2aa9a
+&egrave; => è c3a8
+&egs; => ⪖ e2aa96
+&egsdot; => ⪘ e2aa98
+&el; => ⪙ e2aa99
+&elinters; => ⧠e28fa7
+&ell; => â„“ e28493
+&els; => ⪕ e2aa95
+&elsdot; => ⪗ e2aa97
+&emacr; => Ä“ c493
+&empty; => ∅ e28885
+&emptyset; => ∅ e28885
+&emptyv; => ∅ e28885
+&emsp; =>   e28083
+&emsp13; =>   e28084
+&emsp14; =>   e28085
+&eng; => Å‹ c58b
+&ensp; =>   e28082
+&eogon; => Ä™ c499
+&eopf; => ð•– f09d9596
+&epar; => â‹• e28b95
+&eparsl; => ⧣ e2a7a3
+&eplus; => ⩱ e2a9b1
+&epsi; => ε ceb5
+&epsilon; => ε ceb5
+&epsiv; => ϵ cfb5
+&eqcirc; => ≖ e28996
+&eqcolon; => ≕ e28995
+&eqsim; => ≂ e28982
+&eqslantgtr; => ⪖ e2aa96
+&eqslantless; => ⪕ e2aa95
+&equals; => = 3d
+&equest; => ≟ e2899f
+&equiv; => ≡ e289a1
+&equivDD; => ⩸ e2a9b8
+&eqvparsl; => ⧥ e2a7a5
+&erDot; => ≓ e28993
+&erarr; => ⥱ e2a5b1
+&escr; => ℯ e284af
+&esdot; => ≠e28990
+&esim; => ≂ e28982
+&eta; => η ceb7
+&eth; => ð c3b0
+&euml; => ë c3ab
+&euro; => € e282ac
+&excl; => ! 21
+&exist; => ∃ e28883
+&expectation; => â„° e284b0
+&exponentiale; => â…‡ e28587
+&fallingdotseq; => ≒ e28992
+&fcy; => Ñ„ d184
+&female; => ♀ e29980
+&ffilig; => ffi efac83
+&fflig; => ff efac80
+&ffllig; => ffl efac84
+&ffr; => 𔣠f09d94a3
+&filig; => ï¬ efac81
+&fjlig; => fj 666a
+&flat; => â™­ e299ad
+&fllig; => fl efac82
+&fltns; => â–± e296b1
+&fnof; => Æ’ c692
+&fopf; => ð•— f09d9597
+&forall; => ∀ e28880
+&fork; => â‹” e28b94
+&forkv; => â«™ e2ab99
+&fpartint; => ⨠e2a88d
+&frac12; => ½ c2bd
+&frac13; => â…“ e28593
+&frac14; => ¼ c2bc
+&frac15; => â…• e28595
+&frac16; => â…™ e28599
+&frac18; => â…› e2859b
+&frac23; => â…” e28594
+&frac25; => â…– e28596
+&frac34; => ¾ c2be
+&frac35; => â…— e28597
+&frac38; => ⅜ e2859c
+&frac45; => â…˜ e28598
+&frac56; => â…š e2859a
+&frac58; => â… e2859d
+&frac78; => â…ž e2859e
+&frasl; => â„ e28184
+&frown; => ⌢ e28ca2
+&fscr; => ð’» f09d92bb
+&gE; => ≧ e289a7
+&gEl; => ⪌ e2aa8c
+&gacute; => ǵ c7b5
+&gamma; => γ ceb3
+&gammad; => Ï cf9d
+&gap; => ⪆ e2aa86
+&gbreve; => ÄŸ c49f
+&gcirc; => Ä c49d
+&gcy; => г d0b3
+&gdot; => Ä¡ c4a1
+&ge; => ≥ e289a5
+&gel; => â‹› e28b9b
+&geq; => ≥ e289a5
+&geqq; => ≧ e289a7
+&geqslant; => ⩾ e2a9be
+&ges; => ⩾ e2a9be
+&gescc; => ⪩ e2aaa9
+&gesdot; => ⪀ e2aa80
+&gesdoto; => ⪂ e2aa82
+&gesdotol; => ⪄ e2aa84
+&gesl; => ⋛︀ e28b9befb880
+&gesles; => ⪔ e2aa94
+&gfr; => 𔤠f09d94a4
+&gg; => ≫ e289ab
+&ggg; => â‹™ e28b99
+&gimel; => â„· e284b7
+&gjcy; => Ñ“ d193
+&gl; => ≷ e289b7
+&glE; => ⪒ e2aa92
+&gla; => ⪥ e2aaa5
+&glj; => ⪤ e2aaa4
+&gnE; => ≩ e289a9
+&gnap; => ⪊ e2aa8a
+&gnapprox; => ⪊ e2aa8a
+&gne; => ⪈ e2aa88
+&gneq; => ⪈ e2aa88
+&gneqq; => ≩ e289a9
+&gnsim; => ⋧ e28ba7
+&gopf; => 𕘠f09d9598
+&grave; => ` 60
+&gscr; => â„Š e2848a
+&gsim; => ≳ e289b3
+&gsime; => ⪎ e2aa8e
+&gsiml; => ⪠e2aa90
+&gt; => > 3e
+&gtcc; => ⪧ e2aaa7
+&gtcir; => ⩺ e2a9ba
+&gtdot; => â‹— e28b97
+&gtlPar; => ⦕ e2a695
+&gtquest; => ⩼ e2a9bc
+&gtrapprox; => ⪆ e2aa86
+&gtrarr; => ⥸ e2a5b8
+&gtrdot; => â‹— e28b97
+&gtreqless; => â‹› e28b9b
+&gtreqqless; => ⪌ e2aa8c
+&gtrless; => ≷ e289b7
+&gtrsim; => ≳ e289b3
+&gvertneqq; => ≩︀ e289a9efb880
+&gvnE; => ≩︀ e289a9efb880
+&hArr; => ⇔ e28794
+&hairsp; =>   e2808a
+&half; => ½ c2bd
+&hamilt; => â„‹ e2848b
+&hardcy; => ÑŠ d18a
+&harr; => ↔ e28694
+&harrcir; => ⥈ e2a588
+&harrw; => ↭ e286ad
+&hbar; => â„ e2848f
+&hcirc; => ĥ c4a5
+&hearts; => ♥ e299a5
+&heartsuit; => ♥ e299a5
+&hellip; => … e280a6
+&hercon; => ⊹ e28ab9
+&hfr; => 𔥠f09d94a5
+&hksearow; => ⤥ e2a4a5
+&hkswarow; => ⤦ e2a4a6
+&hoarr; => ⇿ e287bf
+&homtht; => ∻ e288bb
+&hookleftarrow; => ↩ e286a9
+&hookrightarrow; => ↪ e286aa
+&hopf; => ð•™ f09d9599
+&horbar; => ― e28095
+&hscr; => ð’½ f09d92bd
+&hslash; => â„ e2848f
+&hstrok; => ħ c4a7
+&hybull; => ⃠e28183
+&hyphen; => †e28090
+&iacute; => í c3ad
+&ic; => ⣠e281a3
+&icirc; => î c3ae
+&icy; => и d0b8
+&iecy; => е d0b5
+&iexcl; => ¡ c2a1
+&iff; => ⇔ e28794
+&ifr; => 𔦠f09d94a6
+&igrave; => ì c3ac
+&ii; => â…ˆ e28588
+&iiiint; => ⨌ e2a88c
+&iiint; => ∭ e288ad
+&iinfin; => ⧜ e2a79c
+&iiota; => â„© e284a9
+&ijlig; => ij c4b3
+&imacr; => Ä« c4ab
+&image; => â„‘ e28491
+&imagline; => â„ e28490
+&imagpart; => â„‘ e28491
+&imath; => ı c4b1
+&imof; => ⊷ e28ab7
+&imped; => Ƶ c6b5
+&in; => ∈ e28888
+&incare; => â„… e28485
+&infin; => ∞ e2889e
+&infintie; => ⧠e2a79d
+&inodot; => ı c4b1
+&int; => ∫ e288ab
+&intcal; => ⊺ e28aba
+&integers; => ℤ e284a4
+&intercal; => ⊺ e28aba
+&intlarhk; => ⨗ e2a897
+&intprod; => ⨼ e2a8bc
+&iocy; => Ñ‘ d191
+&iogon; => į c4af
+&iopf; => ð•š f09d959a
+&iota; => ι ceb9
+&iprod; => ⨼ e2a8bc
+&iquest; => ¿ c2bf
+&iscr; => ð’¾ f09d92be
+&isin; => ∈ e28888
+&isinE; => ⋹ e28bb9
+&isindot; => ⋵ e28bb5
+&isins; => â‹´ e28bb4
+&isinsv; => ⋳ e28bb3
+&isinv; => ∈ e28888
+&it; => ⢠e281a2
+&itilde; => Ä© c4a9
+&iukcy; => Ñ– d196
+&iuml; => ï c3af
+&jcirc; => ĵ c4b5
+&jcy; => й d0b9
+&jfr; => 𔧠f09d94a7
+&jmath; => È· c8b7
+&jopf; => ð•› f09d959b
+&jscr; => ð’¿ f09d92bf
+&jsercy; => ј d198
+&jukcy; => Ñ” d194
+&kappa; => κ ceba
+&kappav; => Ï° cfb0
+&kcedil; => Ä· c4b7
+&kcy; => к d0ba
+&kfr; => 𔨠f09d94a8
+&kgreen; => ĸ c4b8
+&khcy; => Ñ… d185
+&kjcy; => ќ d19c
+&kopf; => 𕜠f09d959c
+&kscr; => ð“€ f09d9380
+&lAarr; => ⇚ e2879a
+&lArr; => ⇠e28790
+&lAtail; => ⤛ e2a49b
+&lBarr; => ⤎ e2a48e
+&lE; => ≦ e289a6
+&lEg; => ⪋ e2aa8b
+&lHar; => ⥢ e2a5a2
+&lacute; => ĺ c4ba
+&laemptyv; => ⦴ e2a6b4
+&lagran; => â„’ e28492
+&lambda; => λ cebb
+&lang; => ⟨ e29fa8
+&langd; => ⦑ e2a691
+&langle; => ⟨ e29fa8
+&lap; => ⪅ e2aa85
+&laquo; => « c2ab
+&larr; => ↠e28690
+&larrb; => ⇤ e287a4
+&larrbfs; => ⤟ e2a49f
+&larrfs; => ⤠e2a49d
+&larrhk; => ↩ e286a9
+&larrlp; => ↫ e286ab
+&larrpl; => ⤹ e2a4b9
+&larrsim; => ⥳ e2a5b3
+&larrtl; => ↢ e286a2
+&lat; => ⪫ e2aaab
+&latail; => ⤙ e2a499
+&late; => ⪭ e2aaad
+&lates; => ⪭︀ e2aaadefb880
+&lbarr; => ⤌ e2a48c
+&lbbrk; => â² e29db2
+&lbrace; => { 7b
+&lbrack; => [ 5b
+&lbrke; => ⦋ e2a68b
+&lbrksld; => ⦠e2a68f
+&lbrkslu; => ⦠e2a68d
+&lcaron; => ľ c4be
+&lcedil; => ļ c4bc
+&lceil; => ⌈ e28c88
+&lcub; => { 7b
+&lcy; => л d0bb
+&ldca; => ⤶ e2a4b6
+&ldquo; => “ e2809c
+&ldquor; => „ e2809e
+&ldrdhar; => ⥧ e2a5a7
+&ldrushar; => ⥋ e2a58b
+&ldsh; => ↲ e286b2
+&le; => ≤ e289a4
+&leftarrow; => ↠e28690
+&leftarrowtail; => ↢ e286a2
+&leftharpoondown; => ↽ e286bd
+&leftharpoonup; => ↼ e286bc
+&leftleftarrows; => ⇇ e28787
+&leftrightarrow; => ↔ e28694
+&leftrightarrows; => ⇆ e28786
+&leftrightharpoons; => ⇋ e2878b
+&leftrightsquigarrow; => ↭ e286ad
+&leftthreetimes; => â‹‹ e28b8b
+&leg; => â‹š e28b9a
+&leq; => ≤ e289a4
+&leqq; => ≦ e289a6
+&leqslant; => ⩽ e2a9bd
+&les; => ⩽ e2a9bd
+&lescc; => ⪨ e2aaa8
+&lesdot; => â©¿ e2a9bf
+&lesdoto; => ⪠e2aa81
+&lesdotor; => ⪃ e2aa83
+&lesg; => ⋚︀ e28b9aefb880
+&lesges; => ⪓ e2aa93
+&lessapprox; => ⪅ e2aa85
+&lessdot; => â‹– e28b96
+&lesseqgtr; => â‹š e28b9a
+&lesseqqgtr; => ⪋ e2aa8b
+&lessgtr; => ≶ e289b6
+&lesssim; => ≲ e289b2
+&lfisht; => ⥼ e2a5bc
+&lfloor; => ⌊ e28c8a
+&lfr; => 𔩠f09d94a9
+&lg; => ≶ e289b6
+&lgE; => ⪑ e2aa91
+&lhard; => ↽ e286bd
+&lharu; => ↼ e286bc
+&lharul; => ⥪ e2a5aa
+&lhblk; => â–„ e29684
+&ljcy; => Ñ™ d199
+&ll; => ≪ e289aa
+&llarr; => ⇇ e28787
+&llcorner; => ⌞ e28c9e
+&llhard; => ⥫ e2a5ab
+&lltri; => â—º e297ba
+&lmidot; => ŀ c580
+&lmoust; => ⎰ e28eb0
+&lmoustache; => ⎰ e28eb0
+&lnE; => ≨ e289a8
+&lnap; => ⪉ e2aa89
+&lnapprox; => ⪉ e2aa89
+&lne; => ⪇ e2aa87
+&lneq; => ⪇ e2aa87
+&lneqq; => ≨ e289a8
+&lnsim; => ⋦ e28ba6
+&loang; => ⟬ e29fac
+&loarr; => ⇽ e287bd
+&lobrk; => ⟦ e29fa6
+&longleftarrow; => ⟵ e29fb5
+&longleftrightarrow; => ⟷ e29fb7
+&longmapsto; => ⟼ e29fbc
+&longrightarrow; => ⟶ e29fb6
+&looparrowleft; => ↫ e286ab
+&looparrowright; => ↬ e286ac
+&lopar; => ⦅ e2a685
+&lopf; => ð• f09d959d
+&loplus; => ⨭ e2a8ad
+&lotimes; => ⨴ e2a8b4
+&lowast; => ∗ e28897
+&lowbar; => _ 5f
+&loz; => â—Š e2978a
+&lozenge; => â—Š e2978a
+&lozf; => ⧫ e2a7ab
+&lpar; => ( 28
+&lparlt; => ⦓ e2a693
+&lrarr; => ⇆ e28786
+&lrcorner; => ⌟ e28c9f
+&lrhar; => ⇋ e2878b
+&lrhard; => ⥭ e2a5ad
+&lrm; => ‎ e2808e
+&lrtri; => ⊿ e28abf
+&lsaquo; => ‹ e280b9
+&lscr; => ð“ f09d9381
+&lsh; => ↰ e286b0
+&lsim; => ≲ e289b2
+&lsime; => ⪠e2aa8d
+&lsimg; => ⪠e2aa8f
+&lsqb; => [ 5b
+&lsquo; => ‘ e28098
+&lsquor; => ‚ e2809a
+&lstrok; => Å‚ c582
+&lt; => < 3c
+&ltcc; => ⪦ e2aaa6
+&ltcir; => ⩹ e2a9b9
+&ltdot; => â‹– e28b96
+&lthree; => â‹‹ e28b8b
+&ltimes; => ⋉ e28b89
+&ltlarr; => ⥶ e2a5b6
+&ltquest; => â©» e2a9bb
+&ltrPar; => ⦖ e2a696
+&ltri; => â—ƒ e29783
+&ltrie; => ⊴ e28ab4
+&ltrif; => â—‚ e29782
+&lurdshar; => ⥊ e2a58a
+&luruhar; => ⥦ e2a5a6
+&lvertneqq; => ≨︀ e289a8efb880
+&lvnE; => ≨︀ e289a8efb880
+&mDDot; => ∺ e288ba
+&macr; => ¯ c2af
+&male; => ♂ e29982
+&malt; => ✠ e29ca0
+&maltese; => ✠ e29ca0
+&map; => ↦ e286a6
+&mapsto; => ↦ e286a6
+&mapstodown; => ↧ e286a7
+&mapstoleft; => ↤ e286a4
+&mapstoup; => ↥ e286a5
+&marker; => â–® e296ae
+&mcomma; => ⨩ e2a8a9
+&mcy; => м d0bc
+&mdash; => — e28094
+&measuredangle; => ∡ e288a1
+&mfr; => 𔪠f09d94aa
+&mho; => ℧ e284a7
+&micro; => µ c2b5
+&mid; => ∣ e288a3
+&midast; => * 2a
+&midcir; => â«° e2abb0
+&middot; => · c2b7
+&minus; => − e28892
+&minusb; => ⊟ e28a9f
+&minusd; => ∸ e288b8
+&minusdu; => ⨪ e2a8aa
+&mlcp; => â«› e2ab9b
+&mldr; => … e280a6
+&mnplus; => ∓ e28893
+&models; => ⊧ e28aa7
+&mopf; => ð•ž f09d959e
+&mp; => ∓ e28893
+&mscr; => ð“‚ f09d9382
+&mstpos; => ∾ e288be
+&mu; => μ cebc
+&multimap; => ⊸ e28ab8
+&mumap; => ⊸ e28ab8
+&nGg; => ⋙̸ e28b99ccb8
+&nGt; => ≫⃒ e289abe28392
+&nGtv; => ≫̸ e289abccb8
+&nLeftarrow; => ⇠e2878d
+&nLeftrightarrow; => ⇎ e2878e
+&nLl; => ⋘̸ e28b98ccb8
+&nLt; => ≪⃒ e289aae28392
+&nLtv; => ≪̸ e289aaccb8
+&nRightarrow; => ⇠e2878f
+&nVDash; => ⊯ e28aaf
+&nVdash; => ⊮ e28aae
+&nabla; => ∇ e28887
+&nacute; => Å„ c584
+&nang; => ∠⃒ e288a0e28392
+&nap; => ≉ e28989
+&napE; => ⩰̸ e2a9b0ccb8
+&napid; => ≋̸ e2898bccb8
+&napos; => ʼn c589
+&napprox; => ≉ e28989
+&natur; => â™® e299ae
+&natural; => â™® e299ae
+&naturals; => â„• e28495
+&nbsp; =>   c2a0
+&nbump; => ≎̸ e2898eccb8
+&nbumpe; => â‰Ì¸ e2898fccb8
+&ncap; => ⩃ e2a983
+&ncaron; => ň c588
+&ncedil; => ņ c586
+&ncong; => ≇ e28987
+&ncongdot; => ⩭̸ e2a9adccb8
+&ncup; => â©‚ e2a982
+&ncy; => н d0bd
+&ndash; => – e28093
+&ne; => ≠ e289a0
+&neArr; => ⇗ e28797
+&nearhk; => ⤤ e2a4a4
+&nearr; => ↗ e28697
+&nearrow; => ↗ e28697
+&nedot; => â‰Ì¸ e28990ccb8
+&nequiv; => ≢ e289a2
+&nesear; => ⤨ e2a4a8
+&nesim; => ≂̸ e28982ccb8
+&nexist; => ∄ e28884
+&nexists; => ∄ e28884
+&nfr; => 𔫠f09d94ab
+&ngE; => ≧̸ e289a7ccb8
+&nge; => ≱ e289b1
+&ngeq; => ≱ e289b1
+&ngeqq; => ≧̸ e289a7ccb8
+&ngeqslant; => ⩾̸ e2a9beccb8
+&nges; => ⩾̸ e2a9beccb8
+&ngsim; => ≵ e289b5
+&ngt; => ≯ e289af
+&ngtr; => ≯ e289af
+&nhArr; => ⇎ e2878e
+&nharr; => ↮ e286ae
+&nhpar; => ⫲ e2abb2
+&ni; => ∋ e2888b
+&nis; => ⋼ e28bbc
+&nisd; => ⋺ e28bba
+&niv; => ∋ e2888b
+&njcy; => Ñš d19a
+&nlArr; => ⇠e2878d
+&nlE; => ≦̸ e289a6ccb8
+&nlarr; => ↚ e2869a
+&nldr; => ‥ e280a5
+&nle; => ≰ e289b0
+&nleftarrow; => ↚ e2869a
+&nleftrightarrow; => ↮ e286ae
+&nleq; => ≰ e289b0
+&nleqq; => ≦̸ e289a6ccb8
+&nleqslant; => ⩽̸ e2a9bdccb8
+&nles; => ⩽̸ e2a9bdccb8
+&nless; => ≮ e289ae
+&nlsim; => ≴ e289b4
+&nlt; => ≮ e289ae
+&nltri; => ⋪ e28baa
+&nltrie; => ⋬ e28bac
+&nmid; => ∤ e288a4
+&nopf; => ð•Ÿ f09d959f
+&not; => ¬ c2ac
+&notin; => ∉ e28889
+&notinE; => ⋹̸ e28bb9ccb8
+&notindot; => ⋵̸ e28bb5ccb8
+&notinva; => ∉ e28889
+&notinvb; => â‹· e28bb7
+&notinvc; => ⋶ e28bb6
+&notni; => ∌ e2888c
+&notniva; => ∌ e2888c
+&notnivb; => ⋾ e28bbe
+&notnivc; => ⋽ e28bbd
+&npar; => ∦ e288a6
+&nparallel; => ∦ e288a6
+&nparsl; => ⫽⃥ e2abbde283a5
+&npart; => ∂̸ e28882ccb8
+&npolint; => ⨔ e2a894
+&npr; => ⊀ e28a80
+&nprcue; => â‹  e28ba0
+&npre; => ⪯̸ e2aaafccb8
+&nprec; => ⊀ e28a80
+&npreceq; => ⪯̸ e2aaafccb8
+&nrArr; => ⇠e2878f
+&nrarr; => ↛ e2869b
+&nrarrc; => ⤳̸ e2a4b3ccb8
+&nrarrw; => â†Ì¸ e2869dccb8
+&nrightarrow; => ↛ e2869b
+&nrtri; => â‹« e28bab
+&nrtrie; => â‹­ e28bad
+&nsc; => ⊠e28a81
+&nsccue; => â‹¡ e28ba1
+&nsce; => ⪰̸ e2aab0ccb8
+&nscr; => 𓃠f09d9383
+&nshortmid; => ∤ e288a4
+&nshortparallel; => ∦ e288a6
+&nsim; => ≠e28981
+&nsime; => ≄ e28984
+&nsimeq; => ≄ e28984
+&nsmid; => ∤ e288a4
+&nspar; => ∦ e288a6
+&nsqsube; => â‹¢ e28ba2
+&nsqsupe; => â‹£ e28ba3
+&nsub; => ⊄ e28a84
+&nsubE; => ⫅̸ e2ab85ccb8
+&nsube; => ⊈ e28a88
+&nsubset; => ⊂⃒ e28a82e28392
+&nsubseteq; => ⊈ e28a88
+&nsubseteqq; => ⫅̸ e2ab85ccb8
+&nsucc; => ⊠e28a81
+&nsucceq; => ⪰̸ e2aab0ccb8
+&nsup; => ⊅ e28a85
+&nsupE; => ⫆̸ e2ab86ccb8
+&nsupe; => ⊉ e28a89
+&nsupset; => ⊃⃒ e28a83e28392
+&nsupseteq; => ⊉ e28a89
+&nsupseteqq; => ⫆̸ e2ab86ccb8
+&ntgl; => ≹ e289b9
+&ntilde; => ñ c3b1
+&ntlg; => ≸ e289b8
+&ntriangleleft; => ⋪ e28baa
+&ntrianglelefteq; => ⋬ e28bac
+&ntriangleright; => â‹« e28bab
+&ntrianglerighteq; => â‹­ e28bad
+&nu; => ν cebd
+&num; => # 23
+&numero; => â„– e28496
+&numsp; =>   e28087
+&nvDash; => ⊭ e28aad
+&nvHarr; => ⤄ e2a484
+&nvap; => â‰âƒ’ e2898de28392
+&nvdash; => ⊬ e28aac
+&nvge; => ≥⃒ e289a5e28392
+&nvgt; => >⃒ 3ee28392
+&nvinfin; => ⧞ e2a79e
+&nvlArr; => ⤂ e2a482
+&nvle; => ≤⃒ e289a4e28392
+&nvlt; => <⃒ 3ce28392
+&nvltrie; => ⊴⃒ e28ab4e28392
+&nvrArr; => ⤃ e2a483
+&nvrtrie; => ⊵⃒ e28ab5e28392
+&nvsim; => ∼⃒ e288bce28392
+&nwArr; => ⇖ e28796
+&nwarhk; => ⤣ e2a4a3
+&nwarr; => ↖ e28696
+&nwarrow; => ↖ e28696
+&nwnear; => ⤧ e2a4a7
+&oS; => Ⓢ e29388
+&oacute; => ó c3b3
+&oast; => ⊛ e28a9b
+&ocir; => ⊚ e28a9a
+&ocirc; => ô c3b4
+&ocy; => о d0be
+&odash; => ⊠e28a9d
+&odblac; => Å‘ c591
+&odiv; => ⨸ e2a8b8
+&odot; => ⊙ e28a99
+&odsold; => ⦼ e2a6bc
+&oelig; => Å“ c593
+&ofcir; => ⦿ e2a6bf
+&ofr; => 𔬠f09d94ac
+&ogon; => Ë› cb9b
+&ograve; => ò c3b2
+&ogt; => ⧠e2a781
+&ohbar; => ⦵ e2a6b5
+&ohm; => Ω cea9
+&oint; => ∮ e288ae
+&olarr; => ↺ e286ba
+&olcir; => ⦾ e2a6be
+&olcross; => ⦻ e2a6bb
+&oline; => ‾ e280be
+&olt; => ⧀ e2a780
+&omacr; => Å c58d
+&omega; => ω cf89
+&omicron; => ο cebf
+&omid; => ⦶ e2a6b6
+&ominus; => ⊖ e28a96
+&oopf; => ð•  f09d95a0
+&opar; => ⦷ e2a6b7
+&operp; => ⦹ e2a6b9
+&oplus; => ⊕ e28a95
+&or; => ∨ e288a8
+&orarr; => ↻ e286bb
+&ord; => â© e2a99d
+&order; => â„´ e284b4
+&orderof; => â„´ e284b4
+&ordf; => ª c2aa
+&ordm; => º c2ba
+&origof; => ⊶ e28ab6
+&oror; => â©– e2a996
+&orslope; => â©— e2a997
+&orv; => â©› e2a99b
+&oscr; => â„´ e284b4
+&oslash; => ø c3b8
+&osol; => ⊘ e28a98
+&otilde; => õ c3b5
+&otimes; => ⊗ e28a97
+&otimesas; => ⨶ e2a8b6
+&ouml; => ö c3b6
+&ovbar; => ⌽ e28cbd
+&par; => ∥ e288a5
+&para; => ¶ c2b6
+&parallel; => ∥ e288a5
+&parsim; => ⫳ e2abb3
+&parsl; => ⫽ e2abbd
+&part; => ∂ e28882
+&pcy; => п d0bf
+&percnt; => % 25
+&period; => . 2e
+&permil; => ‰ e280b0
+&perp; => ⊥ e28aa5
+&pertenk; => ‱ e280b1
+&pfr; => ð”­ f09d94ad
+&phi; => φ cf86
+&phiv; => Ï• cf95
+&phmmat; => ℳ e284b3
+&phone; => ☎ e2988e
+&pi; => π cf80
+&pitchfork; => â‹” e28b94
+&piv; => Ï– cf96
+&planck; => â„ e2848f
+&planckh; => â„Ž e2848e
+&plankv; => â„ e2848f
+&plus; => + 2b
+&plusacir; => ⨣ e2a8a3
+&plusb; => ⊞ e28a9e
+&pluscir; => ⨢ e2a8a2
+&plusdo; => ∔ e28894
+&plusdu; => ⨥ e2a8a5
+&pluse; => ⩲ e2a9b2
+&plusmn; => ± c2b1
+&plussim; => ⨦ e2a8a6
+&plustwo; => ⨧ e2a8a7
+&pm; => ± c2b1
+&pointint; => ⨕ e2a895
+&popf; => ð•¡ f09d95a1
+&pound; => £ c2a3
+&pr; => ≺ e289ba
+&prE; => ⪳ e2aab3
+&prap; => ⪷ e2aab7
+&prcue; => ≼ e289bc
+&pre; => ⪯ e2aaaf
+&prec; => ≺ e289ba
+&precapprox; => ⪷ e2aab7
+&preccurlyeq; => ≼ e289bc
+&preceq; => ⪯ e2aaaf
+&precnapprox; => ⪹ e2aab9
+&precneqq; => ⪵ e2aab5
+&precnsim; => ⋨ e28ba8
+&precsim; => ≾ e289be
+&prime; => ′ e280b2
+&primes; => â„™ e28499
+&prnE; => ⪵ e2aab5
+&prnap; => ⪹ e2aab9
+&prnsim; => ⋨ e28ba8
+&prod; => ∠e2888f
+&profalar; => ⌮ e28cae
+&profline; => ⌒ e28c92
+&profsurf; => ⌓ e28c93
+&prop; => ∠e2889d
+&propto; => ∠e2889d
+&prsim; => ≾ e289be
+&prurel; => ⊰ e28ab0
+&pscr; => ð“… f09d9385
+&psi; => ψ cf88
+&puncsp; =>   e28088
+&qfr; => ð”® f09d94ae
+&qint; => ⨌ e2a88c
+&qopf; => ð•¢ f09d95a2
+&qprime; => â— e28197
+&qscr; => 𓆠f09d9386
+&quaternions; => â„ e2848d
+&quatint; => ⨖ e2a896
+&quest; => ? 3f
+&questeq; => ≟ e2899f
+&quot; => " 22
+&rAarr; => ⇛ e2879b
+&rArr; => ⇒ e28792
+&rAtail; => ⤜ e2a49c
+&rBarr; => ⤠e2a48f
+&rHar; => ⥤ e2a5a4
+&race; => ∽̱ e288bdccb1
+&racute; => Å• c595
+&radic; => √ e2889a
+&raemptyv; => ⦳ e2a6b3
+&rang; => ⟩ e29fa9
+&rangd; => ⦒ e2a692
+&range; => ⦥ e2a6a5
+&rangle; => ⟩ e29fa9
+&raquo; => » c2bb
+&rarr; => → e28692
+&rarrap; => ⥵ e2a5b5
+&rarrb; => ⇥ e287a5
+&rarrbfs; => ⤠ e2a4a0
+&rarrc; => ⤳ e2a4b3
+&rarrfs; => ⤞ e2a49e
+&rarrhk; => ↪ e286aa
+&rarrlp; => ↬ e286ac
+&rarrpl; => ⥅ e2a585
+&rarrsim; => ⥴ e2a5b4
+&rarrtl; => ↣ e286a3
+&rarrw; => ↠e2869d
+&ratail; => ⤚ e2a49a
+&ratio; => ∶ e288b6
+&rationals; => â„š e2849a
+&rbarr; => ⤠e2a48d
+&rbbrk; => â³ e29db3
+&rbrace; => } 7d
+&rbrack; => ] 5d
+&rbrke; => ⦌ e2a68c
+&rbrksld; => ⦎ e2a68e
+&rbrkslu; => ⦠e2a690
+&rcaron; => Å™ c599
+&rcedil; => Å— c597
+&rceil; => ⌉ e28c89
+&rcub; => } 7d
+&rcy; => р d180
+&rdca; => ⤷ e2a4b7
+&rdldhar; => ⥩ e2a5a9
+&rdquo; => †e2809d
+&rdquor; => †e2809d
+&rdsh; => ↳ e286b3
+&real; => ℜ e2849c
+&realine; => â„› e2849b
+&realpart; => ℜ e2849c
+&reals; => â„ e2849d
+&rect; => â–­ e296ad
+&reg; => ® c2ae
+&rfisht; => ⥽ e2a5bd
+&rfloor; => ⌋ e28c8b
+&rfr; => 𔯠f09d94af
+&rhard; => ⇠e28781
+&rharu; => ⇀ e28780
+&rharul; => ⥬ e2a5ac
+&rho; => Ï cf81
+&rhov; => ϱ cfb1
+&rightarrow; => → e28692
+&rightarrowtail; => ↣ e286a3
+&rightharpoondown; => ⇠e28781
+&rightharpoonup; => ⇀ e28780
+&rightleftarrows; => ⇄ e28784
+&rightleftharpoons; => ⇌ e2878c
+&rightrightarrows; => ⇉ e28789
+&rightsquigarrow; => ↠e2869d
+&rightthreetimes; => ⋌ e28b8c
+&ring; => Ëš cb9a
+&risingdotseq; => ≓ e28993
+&rlarr; => ⇄ e28784
+&rlhar; => ⇌ e2878c
+&rlm; => †e2808f
+&rmoust; => ⎱ e28eb1
+&rmoustache; => ⎱ e28eb1
+&rnmid; => â«® e2abae
+&roang; => ⟭ e29fad
+&roarr; => ⇾ e287be
+&robrk; => ⟧ e29fa7
+&ropar; => ⦆ e2a686
+&ropf; => ð•£ f09d95a3
+&roplus; => ⨮ e2a8ae
+&rotimes; => ⨵ e2a8b5
+&rpar; => ) 29
+&rpargt; => ⦔ e2a694
+&rppolint; => ⨒ e2a892
+&rrarr; => ⇉ e28789
+&rsaquo; => › e280ba
+&rscr; => 𓇠f09d9387
+&rsh; => ↱ e286b1
+&rsqb; => ] 5d
+&rsquo; => ’ e28099
+&rsquor; => ’ e28099
+&rthree; => ⋌ e28b8c
+&rtimes; => â‹Š e28b8a
+&rtri; => â–¹ e296b9
+&rtrie; => ⊵ e28ab5
+&rtrif; => â–¸ e296b8
+&rtriltri; => ⧎ e2a78e
+&ruluhar; => ⥨ e2a5a8
+&rx; => â„ž e2849e
+&sacute; => Å› c59b
+&sbquo; => ‚ e2809a
+&sc; => ≻ e289bb
+&scE; => ⪴ e2aab4
+&scap; => ⪸ e2aab8
+&scaron; => Å¡ c5a1
+&sccue; => ≽ e289bd
+&sce; => ⪰ e2aab0
+&scedil; => ÅŸ c59f
+&scirc; => Å c59d
+&scnE; => ⪶ e2aab6
+&scnap; => ⪺ e2aaba
+&scnsim; => â‹© e28ba9
+&scpolint; => ⨓ e2a893
+&scsim; => ≿ e289bf
+&scy; => Ñ d181
+&sdot; => â‹… e28b85
+&sdotb; => ⊡ e28aa1
+&sdote; => ⩦ e2a9a6
+&seArr; => ⇘ e28798
+&searhk; => ⤥ e2a4a5
+&searr; => ↘ e28698
+&searrow; => ↘ e28698
+&sect; => § c2a7
+&semi; => ; 3b
+&seswar; => ⤩ e2a4a9
+&setminus; => ∖ e28896
+&setmn; => ∖ e28896
+&sext; => ✶ e29cb6
+&sfr; => ð”° f09d94b0
+&sfrown; => ⌢ e28ca2
+&sharp; => ♯ e299af
+&shchcy; => щ d189
+&shcy; => ш d188
+&shortmid; => ∣ e288a3
+&shortparallel; => ∥ e288a5
+&shy; => ­ c2ad
+&sigma; => σ cf83
+&sigmaf; => Ï‚ cf82
+&sigmav; => Ï‚ cf82
+&sim; => ∼ e288bc
+&simdot; => ⩪ e2a9aa
+&sime; => ≃ e28983
+&simeq; => ≃ e28983
+&simg; => ⪞ e2aa9e
+&simgE; => ⪠ e2aaa0
+&siml; => ⪠e2aa9d
+&simlE; => ⪟ e2aa9f
+&simne; => ≆ e28986
+&simplus; => ⨤ e2a8a4
+&simrarr; => ⥲ e2a5b2
+&slarr; => ↠e28690
+&smallsetminus; => ∖ e28896
+&smashp; => ⨳ e2a8b3
+&smeparsl; => ⧤ e2a7a4
+&smid; => ∣ e288a3
+&smile; => ⌣ e28ca3
+&smt; => ⪪ e2aaaa
+&smte; => ⪬ e2aaac
+&smtes; => ⪬︀ e2aaacefb880
+&softcy; => ь d18c
+&sol; => / 2f
+&solb; => ⧄ e2a784
+&solbar; => ⌿ e28cbf
+&sopf; => 𕤠f09d95a4
+&spades; => â™  e299a0
+&spadesuit; => â™  e299a0
+&spar; => ∥ e288a5
+&sqcap; => ⊓ e28a93
+&sqcaps; => ⊓︀ e28a93efb880
+&sqcup; => ⊔ e28a94
+&sqcups; => ⊔︀ e28a94efb880
+&sqsub; => ⊠e28a8f
+&sqsube; => ⊑ e28a91
+&sqsubset; => ⊠e28a8f
+&sqsubseteq; => ⊑ e28a91
+&sqsup; => ⊠e28a90
+&sqsupe; => ⊒ e28a92
+&sqsupset; => ⊠e28a90
+&sqsupseteq; => ⊒ e28a92
+&squ; => â–¡ e296a1
+&square; => â–¡ e296a1
+&squarf; => â–ª e296aa
+&squf; => â–ª e296aa
+&srarr; => → e28692
+&sscr; => 𓈠f09d9388
+&ssetmn; => ∖ e28896
+&ssmile; => ⌣ e28ca3
+&sstarf; => ⋆ e28b86
+&star; => ☆ e29886
+&starf; => ★ e29885
+&straightepsilon; => ϵ cfb5
+&straightphi; => Ï• cf95
+&strns; => ¯ c2af
+&sub; => ⊂ e28a82
+&subE; => â«… e2ab85
+&subdot; => ⪽ e2aabd
+&sube; => ⊆ e28a86
+&subedot; => ⫃ e2ab83
+&submult; => â« e2ab81
+&subnE; => â«‹ e2ab8b
+&subne; => ⊊ e28a8a
+&subplus; => ⪿ e2aabf
+&subrarr; => ⥹ e2a5b9
+&subset; => ⊂ e28a82
+&subseteq; => ⊆ e28a86
+&subseteqq; => â«… e2ab85
+&subsetneq; => ⊊ e28a8a
+&subsetneqq; => â«‹ e2ab8b
+&subsim; => ⫇ e2ab87
+&subsub; => â«• e2ab95
+&subsup; => â«“ e2ab93
+&succ; => ≻ e289bb
+&succapprox; => ⪸ e2aab8
+&succcurlyeq; => ≽ e289bd
+&succeq; => ⪰ e2aab0
+&succnapprox; => ⪺ e2aaba
+&succneqq; => ⪶ e2aab6
+&succnsim; => â‹© e28ba9
+&succsim; => ≿ e289bf
+&sum; => ∑ e28891
+&sung; => ♪ e299aa
+&sup; => ⊃ e28a83
+&sup1; => ¹ c2b9
+&sup2; => ² c2b2
+&sup3; => ³ c2b3
+&supE; => ⫆ e2ab86
+&supdot; => ⪾ e2aabe
+&supdsub; => ⫘ e2ab98
+&supe; => ⊇ e28a87
+&supedot; => â«„ e2ab84
+&suphsol; => ⟉ e29f89
+&suphsub; => â«— e2ab97
+&suplarr; => ⥻ e2a5bb
+&supmult; => â«‚ e2ab82
+&supnE; => ⫌ e2ab8c
+&supne; => ⊋ e28a8b
+&supplus; => â«€ e2ab80
+&supset; => ⊃ e28a83
+&supseteq; => ⊇ e28a87
+&supseteqq; => ⫆ e2ab86
+&supsetneq; => ⊋ e28a8b
+&supsetneqq; => ⫌ e2ab8c
+&supsim; => ⫈ e2ab88
+&supsub; => â«” e2ab94
+&supsup; => â«– e2ab96
+&swArr; => ⇙ e28799
+&swarhk; => ⤦ e2a4a6
+&swarr; => ↙ e28699
+&swarrow; => ↙ e28699
+&swnwar; => ⤪ e2a4aa
+&szlig; => ß c39f
+&target; => ⌖ e28c96
+&tau; => Ï„ cf84
+&tbrk; => ⎴ e28eb4
+&tcaron; => ť c5a5
+&tcedil; => ţ c5a3
+&tcy; => Ñ‚ d182
+&tdot; => ⃛ e2839b
+&telrec; => ⌕ e28c95
+&tfr; => ð”± f09d94b1
+&there4; => ∴ e288b4
+&therefore; => ∴ e288b4
+&theta; => θ ceb8
+&thetasym; => Ï‘ cf91
+&thetav; => Ï‘ cf91
+&thickapprox; => ≈ e28988
+&thicksim; => ∼ e288bc
+&thinsp; =>   e28089
+&thkap; => ≈ e28988
+&thksim; => ∼ e288bc
+&thorn; => þ c3be
+&tilde; => ˜ cb9c
+&times; => × c397
+&timesb; => ⊠ e28aa0
+&timesbar; => ⨱ e2a8b1
+&timesd; => ⨰ e2a8b0
+&tint; => ∭ e288ad
+&toea; => ⤨ e2a4a8
+&top; => ⊤ e28aa4
+&topbot; => ⌶ e28cb6
+&topcir; => ⫱ e2abb1
+&topf; => ð•¥ f09d95a5
+&topfork; => â«š e2ab9a
+&tosa; => ⤩ e2a4a9
+&tprime; => ‴ e280b4
+&trade; => â„¢ e284a2
+&triangle; => â–µ e296b5
+&triangledown; => â–¿ e296bf
+&triangleleft; => â—ƒ e29783
+&trianglelefteq; => ⊴ e28ab4
+&triangleq; => ≜ e2899c
+&triangleright; => â–¹ e296b9
+&trianglerighteq; => ⊵ e28ab5
+&tridot; => â—¬ e297ac
+&trie; => ≜ e2899c
+&triminus; => ⨺ e2a8ba
+&triplus; => ⨹ e2a8b9
+&trisb; => ⧠e2a78d
+&tritime; => ⨻ e2a8bb
+&trpezium; => ⢠e28fa2
+&tscr; => 𓉠f09d9389
+&tscy; => ц d186
+&tshcy; => Ñ› d19b
+&tstrok; => ŧ c5a7
+&twixt; => ≬ e289ac
+&twoheadleftarrow; => ↞ e2869e
+&twoheadrightarrow; => ↠ e286a0
+&uArr; => ⇑ e28791
+&uHar; => ⥣ e2a5a3
+&uacute; => ú c3ba
+&uarr; => ↑ e28691
+&ubrcy; => Ñž d19e
+&ubreve; => Å­ c5ad
+&ucirc; => û c3bb
+&ucy; => у d183
+&udarr; => ⇅ e28785
+&udblac; => ű c5b1
+&udhar; => ⥮ e2a5ae
+&ufisht; => ⥾ e2a5be
+&ufr; => 𔲠f09d94b2
+&ugrave; => ù c3b9
+&uharl; => ↿ e286bf
+&uharr; => ↾ e286be
+&uhblk; => â–€ e29680
+&ulcorn; => ⌜ e28c9c
+&ulcorner; => ⌜ e28c9c
+&ulcrop; => ⌠e28c8f
+&ultri; => â—¸ e297b8
+&umacr; => Å« c5ab
+&uml; => ¨ c2a8
+&uogon; => ų c5b3
+&uopf; => 𕦠f09d95a6
+&uparrow; => ↑ e28691
+&updownarrow; => ↕ e28695
+&upharpoonleft; => ↿ e286bf
+&upharpoonright; => ↾ e286be
+&uplus; => ⊎ e28a8e
+&upsi; => Ï… cf85
+&upsih; => Ï’ cf92
+&upsilon; => Ï… cf85
+&upuparrows; => ⇈ e28788
+&urcorn; => ⌠e28c9d
+&urcorner; => ⌠e28c9d
+&urcrop; => ⌎ e28c8e
+&uring; => ů c5af
+&urtri; => â—¹ e297b9
+&uscr; => ð“Š f09d938a
+&utdot; => â‹° e28bb0
+&utilde; => Å© c5a9
+&utri; => â–µ e296b5
+&utrif; => â–´ e296b4
+&uuarr; => ⇈ e28788
+&uuml; => ü c3bc
+&uwangle; => ⦧ e2a6a7
+&vArr; => ⇕ e28795
+&vBar; => ⫨ e2aba8
+&vBarv; => â«© e2aba9
+&vDash; => ⊨ e28aa8
+&vangrt; => ⦜ e2a69c
+&varepsilon; => ϵ cfb5
+&varkappa; => Ï° cfb0
+&varnothing; => ∅ e28885
+&varphi; => Ï• cf95
+&varpi; => Ï– cf96
+&varpropto; => ∠e2889d
+&varr; => ↕ e28695
+&varrho; => ϱ cfb1
+&varsigma; => Ï‚ cf82
+&varsubsetneq; => ⊊︀ e28a8aefb880
+&varsubsetneqq; => ⫋︀ e2ab8befb880
+&varsupsetneq; => ⊋︀ e28a8befb880
+&varsupsetneqq; => ⫌︀ e2ab8cefb880
+&vartheta; => Ï‘ cf91
+&vartriangleleft; => ⊲ e28ab2
+&vartriangleright; => ⊳ e28ab3
+&vcy; => в d0b2
+&vdash; => ⊢ e28aa2
+&vee; => ∨ e288a8
+&veebar; => ⊻ e28abb
+&veeeq; => ≚ e2899a
+&vellip; => â‹® e28bae
+&verbar; => | 7c
+&vert; => | 7c
+&vfr; => 𔳠f09d94b3
+&vltri; => ⊲ e28ab2
+&vnsub; => ⊂⃒ e28a82e28392
+&vnsup; => ⊃⃒ e28a83e28392
+&vopf; => 𕧠f09d95a7
+&vprop; => ∠e2889d
+&vrtri; => ⊳ e28ab3
+&vscr; => ð“‹ f09d938b
+&vsubnE; => ⫋︀ e2ab8befb880
+&vsubne; => ⊊︀ e28a8aefb880
+&vsupnE; => ⫌︀ e2ab8cefb880
+&vsupne; => ⊋︀ e28a8befb880
+&vzigzag; => ⦚ e2a69a
+&wcirc; => ŵ c5b5
+&wedbar; => â©Ÿ e2a99f
+&wedge; => ∧ e288a7
+&wedgeq; => ≙ e28999
+&weierp; => ℘ e28498
+&wfr; => ð”´ f09d94b4
+&wopf; => 𕨠f09d95a8
+&wp; => ℘ e28498
+&wr; => ≀ e28980
+&wreath; => ≀ e28980
+&wscr; => 𓌠f09d938c
+&xcap; => â‹‚ e28b82
+&xcirc; => â—¯ e297af
+&xcup; => ⋃ e28b83
+&xdtri; => â–½ e296bd
+&xfr; => 𔵠f09d94b5
+&xhArr; => ⟺ e29fba
+&xharr; => ⟷ e29fb7
+&xi; => ξ cebe
+&xlArr; => ⟸ e29fb8
+&xlarr; => ⟵ e29fb5
+&xmap; => ⟼ e29fbc
+&xnis; => â‹» e28bbb
+&xodot; => ⨀ e2a880
+&xopf; => ð•© f09d95a9
+&xoplus; => ⨠e2a881
+&xotime; => ⨂ e2a882
+&xrArr; => ⟹ e29fb9
+&xrarr; => ⟶ e29fb6
+&xscr; => ð“ f09d938d
+&xsqcup; => ⨆ e2a886
+&xuplus; => ⨄ e2a884
+&xutri; => â–³ e296b3
+&xvee; => â‹ e28b81
+&xwedge; => â‹€ e28b80
+&yacute; => ý c3bd
+&yacy; => Ñ d18f
+&ycirc; => Å· c5b7
+&ycy; => Ñ‹ d18b
+&yen; => ¥ c2a5
+&yfr; => 𔶠f09d94b6
+&yicy; => Ñ— d197
+&yopf; => 𕪠f09d95aa
+&yscr; => ð“Ž f09d938e
+&yucy; => ÑŽ d18e
+&yuml; => ÿ c3bf
+&zacute; => ź c5ba
+&zcaron; => ž c5be
+&zcy; => з d0b7
+&zdot; => ż c5bc
+&zeetrf; => ℨ e284a8
+&zeta; => ζ ceb6
+&zfr; => ð”· f09d94b7
+&zhcy; => ж d0b6
+&zigrarr; => ⇠e2879d
+&zopf; => ð•« f09d95ab
+&zscr; => ð“ f09d938f
+&zwj; => †e2808d
+&zwnj; => ‌ e2808c
diff --git a/ext/standard/tests/strings/html_entity_decode_iso8859-15.phpt b/ext/standard/tests/strings/html_entity_decode_iso8859-15.phpt
new file mode 100644
index 0000000000..a3be8f3668
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_iso8859-15.phpt
@@ -0,0 +1,405 @@
+--TEST--
+Translation of HTML entities for encoding ISO-8859-15
+--FILE--
+<?php
+$arr = array(
+0x00A0 => array(0xA0, "NO-BREAK SPACE"),
+0x00A1 => array(0xA1, "INVERTED EXCLAMATION MARK"),
+0x00A2 => array(0xA2, "CENT SIGN"),
+0x00A3 => array(0xA3, "POUND SIGN"),
+0x20AC => array(0xA4, "EURO SIGN"),
+0x00A5 => array(0xA5, "YEN SIGN"),
+0x0160 => array(0xA6, "LATIN CAPITAL LETTER S WITH CARON"),
+0x00A7 => array(0xA7, "SECTION SIGN"),
+0x0161 => array(0xA8, "LATIN SMALL LETTER S WITH CARON"),
+0x00A9 => array(0xA9, "COPYRIGHT SIGN"),
+0x00AA => array(0xAA, "FEMININE ORDINAL INDICATOR"),
+0x00AB => array(0xAB, "LEFT-POINTING DOUBLE ANGLE QUOTATION MARK"),
+0x00AC => array(0xAC, "NOT SIGN"),
+0x00AD => array(0xAD, "SOFT HYPHEN"),
+0x00AE => array(0xAE, "REGISTERED SIGN"),
+0x00AF => array(0xAF, "MACRON"),
+0x00B0 => array(0xB0, "DEGREE SIGN"),
+0x00B1 => array(0xB1, "PLUS-MINUS SIGN"),
+0x00B2 => array(0xB2, "SUPERSCRIPT TWO"),
+0x00B3 => array(0xB3, "SUPERSCRIPT THREE"),
+0x017D => array(0xB4, "LATIN CAPITAL LETTER Z WITH CARON"),
+0x00B5 => array(0xB5, "MICRO SIGN"),
+0x00B6 => array(0xB6, "PILCROW SIGN"),
+0x00B7 => array(0xB7, "MIDDLE DOT"),
+0x017E => array(0xB8, "LATIN SMALL LETTER Z WITH CARON"),
+0x00B9 => array(0xB9, "SUPERSCRIPT ONE"),
+0x00BA => array(0xBA, "MASCULINE ORDINAL INDICATOR"),
+0x00BB => array(0xBB, "RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK"),
+0x0152 => array(0xBC, "LATIN CAPITAL LIGATURE OE"),
+0x0153 => array(0xBD, "LATIN SMALL LIGATURE OE"),
+0x0178 => array(0xBE, "LATIN CAPITAL LETTER Y WITH DIAERESIS"),
+0x00BF => array(0xBF, "INVERTED QUESTION MARK"),
+0x00C0 => array(0xC0, "LATIN CAPITAL LETTER A WITH GRAVE"),
+0x00C1 => array(0xC1, "LATIN CAPITAL LETTER A WITH ACUTE"),
+0x00C2 => array(0xC2, "LATIN CAPITAL LETTER A WITH CIRCUMFLEX"),
+0x00C3 => array(0xC3, "LATIN CAPITAL LETTER A WITH TILDE"),
+0x00C4 => array(0xC4, "LATIN CAPITAL LETTER A WITH DIAERESIS"),
+0x00C5 => array(0xC5, "LATIN CAPITAL LETTER A WITH RING ABOVE"),
+0x00C6 => array(0xC6, "LATIN CAPITAL LETTER AE"),
+0x00C7 => array(0xC7, "LATIN CAPITAL LETTER C WITH CEDILLA"),
+0x00C8 => array(0xC8, "LATIN CAPITAL LETTER E WITH GRAVE"),
+0x00C9 => array(0xC9, "LATIN CAPITAL LETTER E WITH ACUTE"),
+0x00CA => array(0xCA, "LATIN CAPITAL LETTER E WITH CIRCUMFLEX"),
+0x00CB => array(0xCB, "LATIN CAPITAL LETTER E WITH DIAERESIS"),
+0x00CC => array(0xCC, "LATIN CAPITAL LETTER I WITH GRAVE"),
+0x00CD => array(0xCD, "LATIN CAPITAL LETTER I WITH ACUTE"),
+0x00CE => array(0xCE, "LATIN CAPITAL LETTER I WITH CIRCUMFLEX"),
+0x00CF => array(0xCF, "LATIN CAPITAL LETTER I WITH DIAERESIS"),
+0x00D0 => array(0xD0, "LATIN CAPITAL LETTER ETH"),
+0x00D1 => array(0xD1, "LATIN CAPITAL LETTER N WITH TILDE"),
+0x00D2 => array(0xD2, "LATIN CAPITAL LETTER O WITH GRAVE"),
+0x00D3 => array(0xD3, "LATIN CAPITAL LETTER O WITH ACUTE"),
+0x00D4 => array(0xD4, "LATIN CAPITAL LETTER O WITH CIRCUMFLEX"),
+0x00D5 => array(0xD5, "LATIN CAPITAL LETTER O WITH TILDE"),
+0x00D6 => array(0xD6, "LATIN CAPITAL LETTER O WITH DIAERESIS"),
+0x00D7 => array(0xD7, "MULTIPLICATION SIGN"),
+0x00D8 => array(0xD8, "LATIN CAPITAL LETTER O WITH STROKE"),
+0x00D9 => array(0xD9, "LATIN CAPITAL LETTER U WITH GRAVE"),
+0x00DA => array(0xDA, "LATIN CAPITAL LETTER U WITH ACUTE"),
+0x00DB => array(0xDB, "LATIN CAPITAL LETTER U WITH CIRCUMFLEX"),
+0x00DC => array(0xDC, "LATIN CAPITAL LETTER U WITH DIAERESIS"),
+0x00DD => array(0xDD, "LATIN CAPITAL LETTER Y WITH ACUTE"),
+0x00DE => array(0xDE, "LATIN CAPITAL LETTER THORN"),
+0x00DF => array(0xDF, "LATIN SMALL LETTER SHARP S"),
+0x00E0 => array(0xE0, "LATIN SMALL LETTER A WITH GRAVE"),
+0x00E1 => array(0xE1, "LATIN SMALL LETTER A WITH ACUTE"),
+0x00E2 => array(0xE2, "LATIN SMALL LETTER A WITH CIRCUMFLEX"),
+0x00E3 => array(0xE3, "LATIN SMALL LETTER A WITH TILDE"),
+0x00E4 => array(0xE4, "LATIN SMALL LETTER A WITH DIAERESIS"),
+0x00E5 => array(0xE5, "LATIN SMALL LETTER A WITH RING ABOVE"),
+0x00E6 => array(0xE6, "LATIN SMALL LETTER AE"),
+0x00E7 => array(0xE7, "LATIN SMALL LETTER C WITH CEDILLA"),
+0x00E8 => array(0xE8, "LATIN SMALL LETTER E WITH GRAVE"),
+0x00E9 => array(0xE9, "LATIN SMALL LETTER E WITH ACUTE"),
+0x00EA => array(0xEA, "LATIN SMALL LETTER E WITH CIRCUMFLEX"),
+0x00EB => array(0xEB, "LATIN SMALL LETTER E WITH DIAERESIS"),
+0x00EC => array(0xEC, "LATIN SMALL LETTER I WITH GRAVE"),
+0x00ED => array(0xED, "LATIN SMALL LETTER I WITH ACUTE"),
+0x00EE => array(0xEE, "LATIN SMALL LETTER I WITH CIRCUMFLEX"),
+0x00EF => array(0xEF, "LATIN SMALL LETTER I WITH DIAERESIS"),
+0x00F0 => array(0xF0, "LATIN SMALL LETTER ETH"),
+0x00F1 => array(0xF1, "LATIN SMALL LETTER N WITH TILDE"),
+0x00F2 => array(0xF2, "LATIN SMALL LETTER O WITH GRAVE"),
+0x00F3 => array(0xF3, "LATIN SMALL LETTER O WITH ACUTE"),
+0x00F4 => array(0xF4, "LATIN SMALL LETTER O WITH CIRCUMFLEX"),
+0x00F5 => array(0xF5, "LATIN SMALL LETTER O WITH TILDE"),
+0x00F6 => array(0xF6, "LATIN SMALL LETTER O WITH DIAERESIS"),
+0x00F7 => array(0xF7, "DIVISION SIGN"),
+0x00F8 => array(0xF8, "LATIN SMALL LETTER O WITH STROKE"),
+0x00F9 => array(0xF9, "LATIN SMALL LETTER U WITH GRAVE"),
+0x00FA => array(0xFA, "LATIN SMALL LETTER U WITH ACUTE"),
+0x00FB => array(0xFB, "LATIN SMALL LETTER U WITH CIRCUMFLEX"),
+0x00FC => array(0xFC, "LATIN SMALL LETTER U WITH DIAERESIS"),
+0x00FD => array(0xFD, "LATIN SMALL LETTER Y WITH ACUTE"),
+0x00FE => array(0xFE, "LATIN SMALL LETTER THORN"),
+0x00FF => array(0xFF, "LATIN SMALL LETTER Y WITH DIAERESIS"),
+);
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'ISO-8859-15');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'ISO-8859-15');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+NO-BREAK SPACE: &#xA0; => a0
+&#xA0; => a0
+
+INVERTED EXCLAMATION MARK: &#xA1; => a1
+&#xA1; => a1
+
+CENT SIGN: &#xA2; => a2
+&#xA2; => a2
+
+POUND SIGN: &#xA3; => a3
+&#xA3; => a3
+
+EURO SIGN: &#x20AC; => a4
+&#xA4; => &#xA4;
+
+YEN SIGN: &#xA5; => a5
+&#xA5; => a5
+
+LATIN CAPITAL LETTER S WITH CARON: &#x160; => a6
+&#xA6; => &#xA6;
+
+SECTION SIGN: &#xA7; => a7
+&#xA7; => a7
+
+LATIN SMALL LETTER S WITH CARON: &#x161; => a8
+&#xA8; => &#xA8;
+
+COPYRIGHT SIGN: &#xA9; => a9
+&#xA9; => a9
+
+FEMININE ORDINAL INDICATOR: &#xAA; => aa
+&#xAA; => aa
+
+LEFT-POINTING DOUBLE ANGLE QUOTATION MARK: &#xAB; => ab
+&#xAB; => ab
+
+NOT SIGN: &#xAC; => ac
+&#xAC; => ac
+
+SOFT HYPHEN: &#xAD; => ad
+&#xAD; => ad
+
+REGISTERED SIGN: &#xAE; => ae
+&#xAE; => ae
+
+MACRON: &#xAF; => af
+&#xAF; => af
+
+DEGREE SIGN: &#xB0; => b0
+&#xB0; => b0
+
+PLUS-MINUS SIGN: &#xB1; => b1
+&#xB1; => b1
+
+SUPERSCRIPT TWO: &#xB2; => b2
+&#xB2; => b2
+
+SUPERSCRIPT THREE: &#xB3; => b3
+&#xB3; => b3
+
+LATIN CAPITAL LETTER Z WITH CARON: &#x17D; => b4
+&#xB4; => &#xB4;
+
+MICRO SIGN: &#xB5; => b5
+&#xB5; => b5
+
+PILCROW SIGN: &#xB6; => b6
+&#xB6; => b6
+
+MIDDLE DOT: &#xB7; => b7
+&#xB7; => b7
+
+LATIN SMALL LETTER Z WITH CARON: &#x17E; => b8
+&#xB8; => &#xB8;
+
+SUPERSCRIPT ONE: &#xB9; => b9
+&#xB9; => b9
+
+MASCULINE ORDINAL INDICATOR: &#xBA; => ba
+&#xBA; => ba
+
+RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK: &#xBB; => bb
+&#xBB; => bb
+
+LATIN CAPITAL LIGATURE OE: &#x152; => bc
+&#xBC; => &#xBC;
+
+LATIN SMALL LIGATURE OE: &#x153; => bd
+&#xBD; => &#xBD;
+
+LATIN CAPITAL LETTER Y WITH DIAERESIS: &#x178; => be
+&#xBE; => &#xBE;
+
+INVERTED QUESTION MARK: &#xBF; => bf
+&#xBF; => bf
+
+LATIN CAPITAL LETTER A WITH GRAVE: &#xC0; => c0
+&#xC0; => c0
+
+LATIN CAPITAL LETTER A WITH ACUTE: &#xC1; => c1
+&#xC1; => c1
+
+LATIN CAPITAL LETTER A WITH CIRCUMFLEX: &#xC2; => c2
+&#xC2; => c2
+
+LATIN CAPITAL LETTER A WITH TILDE: &#xC3; => c3
+&#xC3; => c3
+
+LATIN CAPITAL LETTER A WITH DIAERESIS: &#xC4; => c4
+&#xC4; => c4
+
+LATIN CAPITAL LETTER A WITH RING ABOVE: &#xC5; => c5
+&#xC5; => c5
+
+LATIN CAPITAL LETTER AE: &#xC6; => c6
+&#xC6; => c6
+
+LATIN CAPITAL LETTER C WITH CEDILLA: &#xC7; => c7
+&#xC7; => c7
+
+LATIN CAPITAL LETTER E WITH GRAVE: &#xC8; => c8
+&#xC8; => c8
+
+LATIN CAPITAL LETTER E WITH ACUTE: &#xC9; => c9
+&#xC9; => c9
+
+LATIN CAPITAL LETTER E WITH CIRCUMFLEX: &#xCA; => ca
+&#xCA; => ca
+
+LATIN CAPITAL LETTER E WITH DIAERESIS: &#xCB; => cb
+&#xCB; => cb
+
+LATIN CAPITAL LETTER I WITH GRAVE: &#xCC; => cc
+&#xCC; => cc
+
+LATIN CAPITAL LETTER I WITH ACUTE: &#xCD; => cd
+&#xCD; => cd
+
+LATIN CAPITAL LETTER I WITH CIRCUMFLEX: &#xCE; => ce
+&#xCE; => ce
+
+LATIN CAPITAL LETTER I WITH DIAERESIS: &#xCF; => cf
+&#xCF; => cf
+
+LATIN CAPITAL LETTER ETH: &#xD0; => d0
+&#xD0; => d0
+
+LATIN CAPITAL LETTER N WITH TILDE: &#xD1; => d1
+&#xD1; => d1
+
+LATIN CAPITAL LETTER O WITH GRAVE: &#xD2; => d2
+&#xD2; => d2
+
+LATIN CAPITAL LETTER O WITH ACUTE: &#xD3; => d3
+&#xD3; => d3
+
+LATIN CAPITAL LETTER O WITH CIRCUMFLEX: &#xD4; => d4
+&#xD4; => d4
+
+LATIN CAPITAL LETTER O WITH TILDE: &#xD5; => d5
+&#xD5; => d5
+
+LATIN CAPITAL LETTER O WITH DIAERESIS: &#xD6; => d6
+&#xD6; => d6
+
+MULTIPLICATION SIGN: &#xD7; => d7
+&#xD7; => d7
+
+LATIN CAPITAL LETTER O WITH STROKE: &#xD8; => d8
+&#xD8; => d8
+
+LATIN CAPITAL LETTER U WITH GRAVE: &#xD9; => d9
+&#xD9; => d9
+
+LATIN CAPITAL LETTER U WITH ACUTE: &#xDA; => da
+&#xDA; => da
+
+LATIN CAPITAL LETTER U WITH CIRCUMFLEX: &#xDB; => db
+&#xDB; => db
+
+LATIN CAPITAL LETTER U WITH DIAERESIS: &#xDC; => dc
+&#xDC; => dc
+
+LATIN CAPITAL LETTER Y WITH ACUTE: &#xDD; => dd
+&#xDD; => dd
+
+LATIN CAPITAL LETTER THORN: &#xDE; => de
+&#xDE; => de
+
+LATIN SMALL LETTER SHARP S: &#xDF; => df
+&#xDF; => df
+
+LATIN SMALL LETTER A WITH GRAVE: &#xE0; => e0
+&#xE0; => e0
+
+LATIN SMALL LETTER A WITH ACUTE: &#xE1; => e1
+&#xE1; => e1
+
+LATIN SMALL LETTER A WITH CIRCUMFLEX: &#xE2; => e2
+&#xE2; => e2
+
+LATIN SMALL LETTER A WITH TILDE: &#xE3; => e3
+&#xE3; => e3
+
+LATIN SMALL LETTER A WITH DIAERESIS: &#xE4; => e4
+&#xE4; => e4
+
+LATIN SMALL LETTER A WITH RING ABOVE: &#xE5; => e5
+&#xE5; => e5
+
+LATIN SMALL LETTER AE: &#xE6; => e6
+&#xE6; => e6
+
+LATIN SMALL LETTER C WITH CEDILLA: &#xE7; => e7
+&#xE7; => e7
+
+LATIN SMALL LETTER E WITH GRAVE: &#xE8; => e8
+&#xE8; => e8
+
+LATIN SMALL LETTER E WITH ACUTE: &#xE9; => e9
+&#xE9; => e9
+
+LATIN SMALL LETTER E WITH CIRCUMFLEX: &#xEA; => ea
+&#xEA; => ea
+
+LATIN SMALL LETTER E WITH DIAERESIS: &#xEB; => eb
+&#xEB; => eb
+
+LATIN SMALL LETTER I WITH GRAVE: &#xEC; => ec
+&#xEC; => ec
+
+LATIN SMALL LETTER I WITH ACUTE: &#xED; => ed
+&#xED; => ed
+
+LATIN SMALL LETTER I WITH CIRCUMFLEX: &#xEE; => ee
+&#xEE; => ee
+
+LATIN SMALL LETTER I WITH DIAERESIS: &#xEF; => ef
+&#xEF; => ef
+
+LATIN SMALL LETTER ETH: &#xF0; => f0
+&#xF0; => f0
+
+LATIN SMALL LETTER N WITH TILDE: &#xF1; => f1
+&#xF1; => f1
+
+LATIN SMALL LETTER O WITH GRAVE: &#xF2; => f2
+&#xF2; => f2
+
+LATIN SMALL LETTER O WITH ACUTE: &#xF3; => f3
+&#xF3; => f3
+
+LATIN SMALL LETTER O WITH CIRCUMFLEX: &#xF4; => f4
+&#xF4; => f4
+
+LATIN SMALL LETTER O WITH TILDE: &#xF5; => f5
+&#xF5; => f5
+
+LATIN SMALL LETTER O WITH DIAERESIS: &#xF6; => f6
+&#xF6; => f6
+
+DIVISION SIGN: &#xF7; => f7
+&#xF7; => f7
+
+LATIN SMALL LETTER O WITH STROKE: &#xF8; => f8
+&#xF8; => f8
+
+LATIN SMALL LETTER U WITH GRAVE: &#xF9; => f9
+&#xF9; => f9
+
+LATIN SMALL LETTER U WITH ACUTE: &#xFA; => fa
+&#xFA; => fa
+
+LATIN SMALL LETTER U WITH CIRCUMFLEX: &#xFB; => fb
+&#xFB; => fb
+
+LATIN SMALL LETTER U WITH DIAERESIS: &#xFC; => fc
+&#xFC; => fc
+
+LATIN SMALL LETTER Y WITH ACUTE: &#xFD; => fd
+&#xFD; => fd
+
+LATIN SMALL LETTER THORN: &#xFE; => fe
+&#xFE; => fe
+
+LATIN SMALL LETTER Y WITH DIAERESIS: &#xFF; => ff
+&#xFF; => ff
+
+
diff --git a/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt b/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt
new file mode 100644
index 0000000000..6a65413c9c
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_iso8859-5.phpt
@@ -0,0 +1,405 @@
+--TEST--
+Translation of HTML entities for encoding ISO-8859-5
+--FILE--
+<?php
+$arr = array(
+0x00A0 => array(0xA0, "NO-BREAK SPACE"),
+0x0401 => array(0xA1, "CYRILLIC CAPITAL LETTER IO"),
+0x0402 => array(0xA2, "CYRILLIC CAPITAL LETTER DJE"),
+0x0403 => array(0xA3, "CYRILLIC CAPITAL LETTER GJE"),
+0x0404 => array(0xA4, "CYRILLIC CAPITAL LETTER UKRAINIAN IE"),
+0x0405 => array(0xA5, "CYRILLIC CAPITAL LETTER DZE"),
+0x0406 => array(0xA6, "CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I"),
+0x0407 => array(0xA7, "CYRILLIC CAPITAL LETTER YI"),
+0x0408 => array(0xA8, "CYRILLIC CAPITAL LETTER JE"),
+0x0409 => array(0xA9, "CYRILLIC CAPITAL LETTER LJE"),
+0x040A => array(0xAA, "CYRILLIC CAPITAL LETTER NJE"),
+0x040B => array(0xAB, "CYRILLIC CAPITAL LETTER TSHE"),
+0x040C => array(0xAC, "CYRILLIC CAPITAL LETTER KJE"),
+0x00AD => array(0xAD, "SOFT HYPHEN"),
+0x040E => array(0xAE, "CYRILLIC CAPITAL LETTER SHORT U"),
+0x040F => array(0xAF, "CYRILLIC CAPITAL LETTER DZHE"),
+0x0410 => array(0xB0, "CYRILLIC CAPITAL LETTER A"),
+0x0411 => array(0xB1, "CYRILLIC CAPITAL LETTER BE"),
+0x0412 => array(0xB2, "CYRILLIC CAPITAL LETTER VE"),
+0x0413 => array(0xB3, "CYRILLIC CAPITAL LETTER GHE"),
+0x0414 => array(0xB4, "CYRILLIC CAPITAL LETTER DE"),
+0x0415 => array(0xB5, "CYRILLIC CAPITAL LETTER IE"),
+0x0416 => array(0xB6, "CYRILLIC CAPITAL LETTER ZHE"),
+0x0417 => array(0xB7, "CYRILLIC CAPITAL LETTER ZE"),
+0x0418 => array(0xB8, "CYRILLIC CAPITAL LETTER I"),
+0x0419 => array(0xB9, "CYRILLIC CAPITAL LETTER SHORT I"),
+0x041A => array(0xBA, "CYRILLIC CAPITAL LETTER KA"),
+0x041B => array(0xBB, "CYRILLIC CAPITAL LETTER EL"),
+0x041C => array(0xBC, "CYRILLIC CAPITAL LETTER EM"),
+0x041D => array(0xBD, "CYRILLIC CAPITAL LETTER EN"),
+0x041E => array(0xBE, "CYRILLIC CAPITAL LETTER O"),
+0x041F => array(0xBF, "CYRILLIC CAPITAL LETTER PE"),
+0x0420 => array(0xC0, "CYRILLIC CAPITAL LETTER ER"),
+0x0421 => array(0xC1, "CYRILLIC CAPITAL LETTER ES"),
+0x0422 => array(0xC2, "CYRILLIC CAPITAL LETTER TE"),
+0x0423 => array(0xC3, "CYRILLIC CAPITAL LETTER U"),
+0x0424 => array(0xC4, "CYRILLIC CAPITAL LETTER EF"),
+0x0425 => array(0xC5, "CYRILLIC CAPITAL LETTER HA"),
+0x0426 => array(0xC6, "CYRILLIC CAPITAL LETTER TSE"),
+0x0427 => array(0xC7, "CYRILLIC CAPITAL LETTER CHE"),
+0x0428 => array(0xC8, "CYRILLIC CAPITAL LETTER SHA"),
+0x0429 => array(0xC9, "CYRILLIC CAPITAL LETTER SHCHA"),
+0x042A => array(0xCA, "CYRILLIC CAPITAL LETTER HARD SIGN"),
+0x042B => array(0xCB, "CYRILLIC CAPITAL LETTER YERU"),
+0x042C => array(0xCC, "CYRILLIC CAPITAL LETTER SOFT SIGN"),
+0x042D => array(0xCD, "CYRILLIC CAPITAL LETTER E"),
+0x042E => array(0xCE, "CYRILLIC CAPITAL LETTER YU"),
+0x042F => array(0xCF, "CYRILLIC CAPITAL LETTER YA"),
+0x0430 => array(0xD0, "CYRILLIC SMALL LETTER A"),
+0x0431 => array(0xD1, "CYRILLIC SMALL LETTER BE"),
+0x0432 => array(0xD2, "CYRILLIC SMALL LETTER VE"),
+0x0433 => array(0xD3, "CYRILLIC SMALL LETTER GHE"),
+0x0434 => array(0xD4, "CYRILLIC SMALL LETTER DE"),
+0x0435 => array(0xD5, "CYRILLIC SMALL LETTER IE"),
+0x0436 => array(0xD6, "CYRILLIC SMALL LETTER ZHE"),
+0x0437 => array(0xD7, "CYRILLIC SMALL LETTER ZE"),
+0x0438 => array(0xD8, "CYRILLIC SMALL LETTER I"),
+0x0439 => array(0xD9, "CYRILLIC SMALL LETTER SHORT I"),
+0x043A => array(0xDA, "CYRILLIC SMALL LETTER KA"),
+0x043B => array(0xDB, "CYRILLIC SMALL LETTER EL"),
+0x043C => array(0xDC, "CYRILLIC SMALL LETTER EM"),
+0x043D => array(0xDD, "CYRILLIC SMALL LETTER EN"),
+0x043E => array(0xDE, "CYRILLIC SMALL LETTER O"),
+0x043F => array(0xDF, "CYRILLIC SMALL LETTER PE"),
+0x0440 => array(0xE0, "CYRILLIC SMALL LETTER ER"),
+0x0441 => array(0xE1, "CYRILLIC SMALL LETTER ES"),
+0x0442 => array(0xE2, "CYRILLIC SMALL LETTER TE"),
+0x0443 => array(0xE3, "CYRILLIC SMALL LETTER U"),
+0x0444 => array(0xE4, "CYRILLIC SMALL LETTER EF"),
+0x0445 => array(0xE5, "CYRILLIC SMALL LETTER HA"),
+0x0446 => array(0xE6, "CYRILLIC SMALL LETTER TSE"),
+0x0447 => array(0xE7, "CYRILLIC SMALL LETTER CHE"),
+0x0448 => array(0xE8, "CYRILLIC SMALL LETTER SHA"),
+0x0449 => array(0xE9, "CYRILLIC SMALL LETTER SHCHA"),
+0x044A => array(0xEA, "CYRILLIC SMALL LETTER HARD SIGN"),
+0x044B => array(0xEB, "CYRILLIC SMALL LETTER YERU"),
+0x044C => array(0xEC, "CYRILLIC SMALL LETTER SOFT SIGN"),
+0x044D => array(0xED, "CYRILLIC SMALL LETTER E"),
+0x044E => array(0xEE, "CYRILLIC SMALL LETTER YU"),
+0x044F => array(0xEF, "CYRILLIC SMALL LETTER YA"),
+0x2116 => array(0xF0, "NUMERO SIGN"),
+0x0451 => array(0xF1, "CYRILLIC SMALL LETTER IO"),
+0x0452 => array(0xF2, "CYRILLIC SMALL LETTER DJE"),
+0x0453 => array(0xF3, "CYRILLIC SMALL LETTER GJE"),
+0x0454 => array(0xF4, "CYRILLIC SMALL LETTER UKRAINIAN IE"),
+0x0455 => array(0xF5, "CYRILLIC SMALL LETTER DZE"),
+0x0456 => array(0xF6, "CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I"),
+0x0457 => array(0xF7, "CYRILLIC SMALL LETTER YI"),
+0x0458 => array(0xF8, "CYRILLIC SMALL LETTER JE"),
+0x0459 => array(0xF9, "CYRILLIC SMALL LETTER LJE"),
+0x045A => array(0xFA, "CYRILLIC SMALL LETTER NJE"),
+0x045B => array(0xFB, "CYRILLIC SMALL LETTER TSHE"),
+0x045C => array(0xFC, "CYRILLIC SMALL LETTER KJE"),
+0x00A7 => array(0xFD, "SECTION SIGN"),
+0x045E => array(0xFE, "CYRILLIC SMALL LETTER SHORT U"),
+0x045F => array(0xFF, "CYRILLIC SMALL LETTER DZHE"),
+);
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'ISO-8859-5');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'ISO-8859-5');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+NO-BREAK SPACE: &#xA0; => a0
+&#xA0; => a0
+
+CYRILLIC CAPITAL LETTER IO: &#x401; => a1
+&#xA1; => &#xA1;
+
+CYRILLIC CAPITAL LETTER DJE: &#x402; => a2
+&#xA2; => &#xA2;
+
+CYRILLIC CAPITAL LETTER GJE: &#x403; => a3
+&#xA3; => &#xA3;
+
+CYRILLIC CAPITAL LETTER UKRAINIAN IE: &#x404; => a4
+&#xA4; => &#xA4;
+
+CYRILLIC CAPITAL LETTER DZE: &#x405; => a5
+&#xA5; => &#xA5;
+
+CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I: &#x406; => a6
+&#xA6; => &#xA6;
+
+CYRILLIC CAPITAL LETTER YI: &#x407; => a7
+&#xA7; => fd
+
+CYRILLIC CAPITAL LETTER JE: &#x408; => a8
+&#xA8; => &#xA8;
+
+CYRILLIC CAPITAL LETTER LJE: &#x409; => a9
+&#xA9; => &#xA9;
+
+CYRILLIC CAPITAL LETTER NJE: &#x40A; => aa
+&#xAA; => &#xAA;
+
+CYRILLIC CAPITAL LETTER TSHE: &#x40B; => ab
+&#xAB; => &#xAB;
+
+CYRILLIC CAPITAL LETTER KJE: &#x40C; => ac
+&#xAC; => &#xAC;
+
+SOFT HYPHEN: &#xAD; => ad
+&#xAD; => ad
+
+CYRILLIC CAPITAL LETTER SHORT U: &#x40E; => ae
+&#xAE; => &#xAE;
+
+CYRILLIC CAPITAL LETTER DZHE: &#x40F; => af
+&#xAF; => &#xAF;
+
+CYRILLIC CAPITAL LETTER A: &#x410; => b0
+&#xB0; => &#xB0;
+
+CYRILLIC CAPITAL LETTER BE: &#x411; => b1
+&#xB1; => &#xB1;
+
+CYRILLIC CAPITAL LETTER VE: &#x412; => b2
+&#xB2; => &#xB2;
+
+CYRILLIC CAPITAL LETTER GHE: &#x413; => b3
+&#xB3; => &#xB3;
+
+CYRILLIC CAPITAL LETTER DE: &#x414; => b4
+&#xB4; => &#xB4;
+
+CYRILLIC CAPITAL LETTER IE: &#x415; => b5
+&#xB5; => &#xB5;
+
+CYRILLIC CAPITAL LETTER ZHE: &#x416; => b6
+&#xB6; => &#xB6;
+
+CYRILLIC CAPITAL LETTER ZE: &#x417; => b7
+&#xB7; => &#xB7;
+
+CYRILLIC CAPITAL LETTER I: &#x418; => b8
+&#xB8; => &#xB8;
+
+CYRILLIC CAPITAL LETTER SHORT I: &#x419; => b9
+&#xB9; => &#xB9;
+
+CYRILLIC CAPITAL LETTER KA: &#x41A; => ba
+&#xBA; => &#xBA;
+
+CYRILLIC CAPITAL LETTER EL: &#x41B; => bb
+&#xBB; => &#xBB;
+
+CYRILLIC CAPITAL LETTER EM: &#x41C; => bc
+&#xBC; => &#xBC;
+
+CYRILLIC CAPITAL LETTER EN: &#x41D; => bd
+&#xBD; => &#xBD;
+
+CYRILLIC CAPITAL LETTER O: &#x41E; => be
+&#xBE; => &#xBE;
+
+CYRILLIC CAPITAL LETTER PE: &#x41F; => bf
+&#xBF; => &#xBF;
+
+CYRILLIC CAPITAL LETTER ER: &#x420; => c0
+&#xC0; => &#xC0;
+
+CYRILLIC CAPITAL LETTER ES: &#x421; => c1
+&#xC1; => &#xC1;
+
+CYRILLIC CAPITAL LETTER TE: &#x422; => c2
+&#xC2; => &#xC2;
+
+CYRILLIC CAPITAL LETTER U: &#x423; => c3
+&#xC3; => &#xC3;
+
+CYRILLIC CAPITAL LETTER EF: &#x424; => c4
+&#xC4; => &#xC4;
+
+CYRILLIC CAPITAL LETTER HA: &#x425; => c5
+&#xC5; => &#xC5;
+
+CYRILLIC CAPITAL LETTER TSE: &#x426; => c6
+&#xC6; => &#xC6;
+
+CYRILLIC CAPITAL LETTER CHE: &#x427; => c7
+&#xC7; => &#xC7;
+
+CYRILLIC CAPITAL LETTER SHA: &#x428; => c8
+&#xC8; => &#xC8;
+
+CYRILLIC CAPITAL LETTER SHCHA: &#x429; => c9
+&#xC9; => &#xC9;
+
+CYRILLIC CAPITAL LETTER HARD SIGN: &#x42A; => ca
+&#xCA; => &#xCA;
+
+CYRILLIC CAPITAL LETTER YERU: &#x42B; => cb
+&#xCB; => &#xCB;
+
+CYRILLIC CAPITAL LETTER SOFT SIGN: &#x42C; => cc
+&#xCC; => &#xCC;
+
+CYRILLIC CAPITAL LETTER E: &#x42D; => cd
+&#xCD; => &#xCD;
+
+CYRILLIC CAPITAL LETTER YU: &#x42E; => ce
+&#xCE; => &#xCE;
+
+CYRILLIC CAPITAL LETTER YA: &#x42F; => cf
+&#xCF; => &#xCF;
+
+CYRILLIC SMALL LETTER A: &#x430; => d0
+&#xD0; => &#xD0;
+
+CYRILLIC SMALL LETTER BE: &#x431; => d1
+&#xD1; => &#xD1;
+
+CYRILLIC SMALL LETTER VE: &#x432; => d2
+&#xD2; => &#xD2;
+
+CYRILLIC SMALL LETTER GHE: &#x433; => d3
+&#xD3; => &#xD3;
+
+CYRILLIC SMALL LETTER DE: &#x434; => d4
+&#xD4; => &#xD4;
+
+CYRILLIC SMALL LETTER IE: &#x435; => d5
+&#xD5; => &#xD5;
+
+CYRILLIC SMALL LETTER ZHE: &#x436; => d6
+&#xD6; => &#xD6;
+
+CYRILLIC SMALL LETTER ZE: &#x437; => d7
+&#xD7; => &#xD7;
+
+CYRILLIC SMALL LETTER I: &#x438; => d8
+&#xD8; => &#xD8;
+
+CYRILLIC SMALL LETTER SHORT I: &#x439; => d9
+&#xD9; => &#xD9;
+
+CYRILLIC SMALL LETTER KA: &#x43A; => da
+&#xDA; => &#xDA;
+
+CYRILLIC SMALL LETTER EL: &#x43B; => db
+&#xDB; => &#xDB;
+
+CYRILLIC SMALL LETTER EM: &#x43C; => dc
+&#xDC; => &#xDC;
+
+CYRILLIC SMALL LETTER EN: &#x43D; => dd
+&#xDD; => &#xDD;
+
+CYRILLIC SMALL LETTER O: &#x43E; => de
+&#xDE; => &#xDE;
+
+CYRILLIC SMALL LETTER PE: &#x43F; => df
+&#xDF; => &#xDF;
+
+CYRILLIC SMALL LETTER ER: &#x440; => e0
+&#xE0; => &#xE0;
+
+CYRILLIC SMALL LETTER ES: &#x441; => e1
+&#xE1; => &#xE1;
+
+CYRILLIC SMALL LETTER TE: &#x442; => e2
+&#xE2; => &#xE2;
+
+CYRILLIC SMALL LETTER U: &#x443; => e3
+&#xE3; => &#xE3;
+
+CYRILLIC SMALL LETTER EF: &#x444; => e4
+&#xE4; => &#xE4;
+
+CYRILLIC SMALL LETTER HA: &#x445; => e5
+&#xE5; => &#xE5;
+
+CYRILLIC SMALL LETTER TSE: &#x446; => e6
+&#xE6; => &#xE6;
+
+CYRILLIC SMALL LETTER CHE: &#x447; => e7
+&#xE7; => &#xE7;
+
+CYRILLIC SMALL LETTER SHA: &#x448; => e8
+&#xE8; => &#xE8;
+
+CYRILLIC SMALL LETTER SHCHA: &#x449; => e9
+&#xE9; => &#xE9;
+
+CYRILLIC SMALL LETTER HARD SIGN: &#x44A; => ea
+&#xEA; => &#xEA;
+
+CYRILLIC SMALL LETTER YERU: &#x44B; => eb
+&#xEB; => &#xEB;
+
+CYRILLIC SMALL LETTER SOFT SIGN: &#x44C; => ec
+&#xEC; => &#xEC;
+
+CYRILLIC SMALL LETTER E: &#x44D; => ed
+&#xED; => &#xED;
+
+CYRILLIC SMALL LETTER YU: &#x44E; => ee
+&#xEE; => &#xEE;
+
+CYRILLIC SMALL LETTER YA: &#x44F; => ef
+&#xEF; => &#xEF;
+
+NUMERO SIGN: &#x2116; => f0
+&#xF0; => &#xF0;
+
+CYRILLIC SMALL LETTER IO: &#x451; => 2623783435313b
+&#xF1; => &#xF1;
+
+CYRILLIC SMALL LETTER DJE: &#x452; => 2623783435323b
+&#xF2; => &#xF2;
+
+CYRILLIC SMALL LETTER GJE: &#x453; => 2623783435333b
+&#xF3; => &#xF3;
+
+CYRILLIC SMALL LETTER UKRAINIAN IE: &#x454; => 2623783435343b
+&#xF4; => &#xF4;
+
+CYRILLIC SMALL LETTER DZE: &#x455; => 2623783435353b
+&#xF5; => &#xF5;
+
+CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I: &#x456; => 2623783435363b
+&#xF6; => &#xF6;
+
+CYRILLIC SMALL LETTER YI: &#x457; => 2623783435373b
+&#xF7; => &#xF7;
+
+CYRILLIC SMALL LETTER JE: &#x458; => 2623783435383b
+&#xF8; => &#xF8;
+
+CYRILLIC SMALL LETTER LJE: &#x459; => 2623783435393b
+&#xF9; => &#xF9;
+
+CYRILLIC SMALL LETTER NJE: &#x45A; => 2623783435413b
+&#xFA; => &#xFA;
+
+CYRILLIC SMALL LETTER TSHE: &#x45B; => 2623783435423b
+&#xFB; => &#xFB;
+
+CYRILLIC SMALL LETTER KJE: &#x45C; => 2623783435433b
+&#xFC; => &#xFC;
+
+SECTION SIGN: &#xA7; => fd
+&#xFD; => &#xFD;
+
+CYRILLIC SMALL LETTER SHORT U: &#x45E; => 2623783435453b
+&#xFE; => &#xFE;
+
+CYRILLIC SMALL LETTER DZHE: &#x45F; => 2623783435463b
+&#xFF; => &#xFF;
+
+
diff --git a/ext/standard/tests/strings/html_entity_decode_koi8-r.phpt b/ext/standard/tests/strings/html_entity_decode_koi8-r.phpt
new file mode 100644
index 0000000000..cb7fc7d1d8
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_koi8-r.phpt
@@ -0,0 +1,533 @@
+--TEST--
+Translation of HTML entities for encoding KOI8-R
+--FILE--
+<?php
+$arr = array(
+0x2500 => array(0x80, "BOX DRAWINGS LIGHT HORIZONTAL"),
+0x2502 => array(0x81, "BOX DRAWINGS LIGHT VERTICAL"),
+0x250C => array(0x82, "BOX DRAWINGS LIGHT DOWN AND RIGHT"),
+0x2510 => array(0x83, "BOX DRAWINGS LIGHT DOWN AND LEFT"),
+0x2514 => array(0x84, "BOX DRAWINGS LIGHT UP AND RIGHT"),
+0x2518 => array(0x85, "BOX DRAWINGS LIGHT UP AND LEFT"),
+0x251C => array(0x86, "BOX DRAWINGS LIGHT VERTICAL AND RIGHT"),
+0x2524 => array(0x87, "BOX DRAWINGS LIGHT VERTICAL AND LEFT"),
+0x252C => array(0x88, "BOX DRAWINGS LIGHT DOWN AND HORIZONTAL"),
+0x2534 => array(0x89, "BOX DRAWINGS LIGHT UP AND HORIZONTAL"),
+0x253C => array(0x8A, "BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL"),
+0x2580 => array(0x8B, "UPPER HALF BLOCK"),
+0x2584 => array(0x8C, "LOWER HALF BLOCK"),
+0x2588 => array(0x8D, "FULL BLOCK"),
+0x258C => array(0x8E, "LEFT HALF BLOCK"),
+0x2590 => array(0x8F, "RIGHT HALF BLOCK"),
+0x2591 => array(0x90, "LIGHT SHADE"),
+0x2592 => array(0x91, "MEDIUM SHADE"),
+0x2593 => array(0x92, "DARK SHADE"),
+0x2320 => array(0x93, "TOP HALF INTEGRAL"),
+0x25A0 => array(0x94, "BLACK SQUARE"),
+0x2219 => array(0x95, "BULLET OPERATOR"),
+0x221A => array(0x96, "SQUARE ROOT"),
+0x2248 => array(0x97, "ALMOST EQUAL TO"),
+0x2264 => array(0x98, "LESS-THAN OR EQUAL TO"),
+0x2265 => array(0x99, "GREATER-THAN OR EQUAL TO"),
+0x00A0 => array(0x9A, "NO-BREAK SPACE"),
+0x2321 => array(0x9B, "BOTTOM HALF INTEGRAL"),
+0x00B0 => array(0x9C, "DEGREE SIGN"),
+0x00B2 => array(0x9D, "SUPERSCRIPT TWO"),
+0x00B7 => array(0x9E, "MIDDLE DOT"),
+0x00F7 => array(0x9F, "DIVISION SIGN"),
+0x2550 => array(0xA0, "BOX DRAWINGS DOUBLE HORIZONTAL"),
+0x2551 => array(0xA1, "BOX DRAWINGS DOUBLE VERTICAL"),
+0x2552 => array(0xA2, "BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE"),
+0x0451 => array(0xA3, "CYRILLIC SMALL LETTER IO"),
+0x2553 => array(0xA4, "BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE"),
+0x2554 => array(0xA5, "BOX DRAWINGS DOUBLE DOWN AND RIGHT"),
+0x2555 => array(0xA6, "BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE"),
+0x2556 => array(0xA7, "BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE"),
+0x2557 => array(0xA8, "BOX DRAWINGS DOUBLE DOWN AND LEFT"),
+0x2558 => array(0xA9, "BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE"),
+0x2559 => array(0xAA, "BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE"),
+0x255A => array(0xAB, "BOX DRAWINGS DOUBLE UP AND RIGHT"),
+0x255B => array(0xAC, "BOX DRAWINGS UP SINGLE AND LEFT DOUBLE"),
+0x255C => array(0xAD, "BOX DRAWINGS UP DOUBLE AND LEFT SINGLE"),
+0x255D => array(0xAE, "BOX DRAWINGS DOUBLE UP AND LEFT"),
+0x255E => array(0xAF, "BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE"),
+0x255F => array(0xB0, "BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE"),
+0x2560 => array(0xB1, "BOX DRAWINGS DOUBLE VERTICAL AND RIGHT"),
+0x2561 => array(0xB2, "BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE"),
+0x0401 => array(0xB3, "CYRILLIC CAPITAL LETTER IO"),
+0x2562 => array(0xB4, "BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE"),
+0x2563 => array(0xB5, "BOX DRAWINGS DOUBLE VERTICAL AND LEFT"),
+0x2564 => array(0xB6, "BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE"),
+0x2565 => array(0xB7, "BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE"),
+0x2566 => array(0xB8, "BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL"),
+0x2567 => array(0xB9, "BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE"),
+0x2568 => array(0xBA, "BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE"),
+0x2569 => array(0xBB, "BOX DRAWINGS DOUBLE UP AND HORIZONTAL"),
+0x256A => array(0xBC, "BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE"),
+0x256B => array(0xBD, "BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE"),
+0x256C => array(0xBE, "BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL"),
+0x00A9 => array(0xBF, "COPYRIGHT SIGN"),
+0x044E => array(0xC0, "CYRILLIC SMALL LETTER YU"),
+0x0430 => array(0xC1, "CYRILLIC SMALL LETTER A"),
+0x0431 => array(0xC2, "CYRILLIC SMALL LETTER BE"),
+0x0446 => array(0xC3, "CYRILLIC SMALL LETTER TSE"),
+0x0434 => array(0xC4, "CYRILLIC SMALL LETTER DE"),
+0x0435 => array(0xC5, "CYRILLIC SMALL LETTER IE"),
+0x0444 => array(0xC6, "CYRILLIC SMALL LETTER EF"),
+0x0433 => array(0xC7, "CYRILLIC SMALL LETTER GHE"),
+0x0445 => array(0xC8, "CYRILLIC SMALL LETTER HA"),
+0x0438 => array(0xC9, "CYRILLIC SMALL LETTER I"),
+0x0439 => array(0xCA, "CYRILLIC SMALL LETTER SHORT I"),
+0x043A => array(0xCB, "CYRILLIC SMALL LETTER KA"),
+0x043B => array(0xCC, "CYRILLIC SMALL LETTER EL"),
+0x043C => array(0xCD, "CYRILLIC SMALL LETTER EM"),
+0x043D => array(0xCE, "CYRILLIC SMALL LETTER EN"),
+0x043E => array(0xCF, "CYRILLIC SMALL LETTER O"),
+0x043F => array(0xD0, "CYRILLIC SMALL LETTER PE"),
+0x044F => array(0xD1, "CYRILLIC SMALL LETTER YA"),
+0x0440 => array(0xD2, "CYRILLIC SMALL LETTER ER"),
+0x0441 => array(0xD3, "CYRILLIC SMALL LETTER ES"),
+0x0442 => array(0xD4, "CYRILLIC SMALL LETTER TE"),
+0x0443 => array(0xD5, "CYRILLIC SMALL LETTER U"),
+0x0436 => array(0xD6, "CYRILLIC SMALL LETTER ZHE"),
+0x0432 => array(0xD7, "CYRILLIC SMALL LETTER VE"),
+0x044C => array(0xD8, "CYRILLIC SMALL LETTER SOFT SIGN"),
+0x044B => array(0xD9, "CYRILLIC SMALL LETTER YERU"),
+0x0437 => array(0xDA, "CYRILLIC SMALL LETTER ZE"),
+0x0448 => array(0xDB, "CYRILLIC SMALL LETTER SHA"),
+0x044D => array(0xDC, "CYRILLIC SMALL LETTER E"),
+0x0449 => array(0xDD, "CYRILLIC SMALL LETTER SHCHA"),
+0x0447 => array(0xDE, "CYRILLIC SMALL LETTER CHE"),
+0x044A => array(0xDF, "CYRILLIC SMALL LETTER HARD SIGN"),
+0x042E => array(0xE0, "CYRILLIC CAPITAL LETTER YU"),
+0x0410 => array(0xE1, "CYRILLIC CAPITAL LETTER A"),
+0x0411 => array(0xE2, "CYRILLIC CAPITAL LETTER BE"),
+0x0426 => array(0xE3, "CYRILLIC CAPITAL LETTER TSE"),
+0x0414 => array(0xE4, "CYRILLIC CAPITAL LETTER DE"),
+0x0415 => array(0xE5, "CYRILLIC CAPITAL LETTER IE"),
+0x0424 => array(0xE6, "CYRILLIC CAPITAL LETTER EF"),
+0x0413 => array(0xE7, "CYRILLIC CAPITAL LETTER GHE"),
+0x0425 => array(0xE8, "CYRILLIC CAPITAL LETTER HA"),
+0x0418 => array(0xE9, "CYRILLIC CAPITAL LETTER I"),
+0x0419 => array(0xEA, "CYRILLIC CAPITAL LETTER SHORT I"),
+0x041A => array(0xEB, "CYRILLIC CAPITAL LETTER KA"),
+0x041B => array(0xEC, "CYRILLIC CAPITAL LETTER EL"),
+0x041C => array(0xED, "CYRILLIC CAPITAL LETTER EM"),
+0x041D => array(0xEE, "CYRILLIC CAPITAL LETTER EN"),
+0x041E => array(0xEF, "CYRILLIC CAPITAL LETTER O"),
+0x041F => array(0xF0, "CYRILLIC CAPITAL LETTER PE"),
+0x042F => array(0xF1, "CYRILLIC CAPITAL LETTER YA"),
+0x0420 => array(0xF2, "CYRILLIC CAPITAL LETTER ER"),
+0x0421 => array(0xF3, "CYRILLIC CAPITAL LETTER ES"),
+0x0422 => array(0xF4, "CYRILLIC CAPITAL LETTER TE"),
+0x0423 => array(0xF5, "CYRILLIC CAPITAL LETTER U"),
+0x0416 => array(0xF6, "CYRILLIC CAPITAL LETTER ZHE"),
+0x0412 => array(0xF7, "CYRILLIC CAPITAL LETTER VE"),
+0x042C => array(0xF8, "CYRILLIC CAPITAL LETTER SOFT SIGN"),
+0x042B => array(0xF9, "CYRILLIC CAPITAL LETTER YERU"),
+0x0417 => array(0xFA, "CYRILLIC CAPITAL LETTER ZE"),
+0x0428 => array(0xFB, "CYRILLIC CAPITAL LETTER SHA"),
+0x042D => array(0xFC, "CYRILLIC CAPITAL LETTER E"),
+0x0429 => array(0xFD, "CYRILLIC CAPITAL LETTER SHCHA"),
+0x0427 => array(0xFE, "CYRILLIC CAPITAL LETTER CHE"),
+0x042A => array(0xFF, "CYRILLIC CAPITAL LETTER HARD SIGN"),
+);
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'KOI8-R');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'KOI8-R');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+BOX DRAWINGS LIGHT HORIZONTAL: &#x2500; => 80
+&#x80; => &#x80;
+
+BOX DRAWINGS LIGHT VERTICAL: &#x2502; => 81
+&#x81; => &#x81;
+
+BOX DRAWINGS LIGHT DOWN AND RIGHT: &#x250C; => 82
+&#x82; => &#x82;
+
+BOX DRAWINGS LIGHT DOWN AND LEFT: &#x2510; => 83
+&#x83; => &#x83;
+
+BOX DRAWINGS LIGHT UP AND RIGHT: &#x2514; => 84
+&#x84; => &#x84;
+
+BOX DRAWINGS LIGHT UP AND LEFT: &#x2518; => 85
+&#x85; => &#x85;
+
+BOX DRAWINGS LIGHT VERTICAL AND RIGHT: &#x251C; => 86
+&#x86; => &#x86;
+
+BOX DRAWINGS LIGHT VERTICAL AND LEFT: &#x2524; => 87
+&#x87; => &#x87;
+
+BOX DRAWINGS LIGHT DOWN AND HORIZONTAL: &#x252C; => 88
+&#x88; => &#x88;
+
+BOX DRAWINGS LIGHT UP AND HORIZONTAL: &#x2534; => 89
+&#x89; => &#x89;
+
+BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL: &#x253C; => 8a
+&#x8A; => &#x8A;
+
+UPPER HALF BLOCK: &#x2580; => 8b
+&#x8B; => &#x8B;
+
+LOWER HALF BLOCK: &#x2584; => 8c
+&#x8C; => &#x8C;
+
+FULL BLOCK: &#x2588; => 8d
+&#x8D; => &#x8D;
+
+LEFT HALF BLOCK: &#x258C; => 8e
+&#x8E; => &#x8E;
+
+RIGHT HALF BLOCK: &#x2590; => 8f
+&#x8F; => &#x8F;
+
+LIGHT SHADE: &#x2591; => 90
+&#x90; => &#x90;
+
+MEDIUM SHADE: &#x2592; => 91
+&#x91; => &#x91;
+
+DARK SHADE: &#x2593; => 92
+&#x92; => &#x92;
+
+TOP HALF INTEGRAL: &#x2320; => 93
+&#x93; => &#x93;
+
+BLACK SQUARE: &#x25A0; => 94
+&#x94; => &#x94;
+
+BULLET OPERATOR: &#x2219; => 95
+&#x95; => &#x95;
+
+SQUARE ROOT: &#x221A; => 96
+&#x96; => &#x96;
+
+ALMOST EQUAL TO: &#x2248; => 97
+&#x97; => &#x97;
+
+LESS-THAN OR EQUAL TO: &#x2264; => 98
+&#x98; => &#x98;
+
+GREATER-THAN OR EQUAL TO: &#x2265; => 99
+&#x99; => &#x99;
+
+NO-BREAK SPACE: &#xA0; => 9a
+&#x9A; => &#x9A;
+
+BOTTOM HALF INTEGRAL: &#x2321; => 9b
+&#x9B; => &#x9B;
+
+DEGREE SIGN: &#xB0; => 9c
+&#x9C; => &#x9C;
+
+SUPERSCRIPT TWO: &#xB2; => 9d
+&#x9D; => &#x9D;
+
+MIDDLE DOT: &#xB7; => 9e
+&#x9E; => &#x9E;
+
+DIVISION SIGN: &#xF7; => 9f
+&#x9F; => &#x9F;
+
+BOX DRAWINGS DOUBLE HORIZONTAL: &#x2550; => a0
+&#xA0; => 9a
+
+BOX DRAWINGS DOUBLE VERTICAL: &#x2551; => a1
+&#xA1; => &#xA1;
+
+BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE: &#x2552; => a2
+&#xA2; => &#xA2;
+
+CYRILLIC SMALL LETTER IO: &#x451; => a3
+&#xA3; => &#xA3;
+
+BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE: &#x2553; => a4
+&#xA4; => &#xA4;
+
+BOX DRAWINGS DOUBLE DOWN AND RIGHT: &#x2554; => a5
+&#xA5; => &#xA5;
+
+BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE: &#x2555; => a6
+&#xA6; => &#xA6;
+
+BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE: &#x2556; => a7
+&#xA7; => &#xA7;
+
+BOX DRAWINGS DOUBLE DOWN AND LEFT: &#x2557; => a8
+&#xA8; => &#xA8;
+
+BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE: &#x2558; => a9
+&#xA9; => bf
+
+BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE: &#x2559; => aa
+&#xAA; => &#xAA;
+
+BOX DRAWINGS DOUBLE UP AND RIGHT: &#x255A; => ab
+&#xAB; => &#xAB;
+
+BOX DRAWINGS UP SINGLE AND LEFT DOUBLE: &#x255B; => ac
+&#xAC; => &#xAC;
+
+BOX DRAWINGS UP DOUBLE AND LEFT SINGLE: &#x255C; => ad
+&#xAD; => &#xAD;
+
+BOX DRAWINGS DOUBLE UP AND LEFT: &#x255D; => ae
+&#xAE; => &#xAE;
+
+BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE: &#x255E; => af
+&#xAF; => &#xAF;
+
+BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE: &#x255F; => b0
+&#xB0; => 9c
+
+BOX DRAWINGS DOUBLE VERTICAL AND RIGHT: &#x2560; => b1
+&#xB1; => &#xB1;
+
+BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE: &#x2561; => b2
+&#xB2; => 9d
+
+CYRILLIC CAPITAL LETTER IO: &#x401; => b3
+&#xB3; => &#xB3;
+
+BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE: &#x2562; => b4
+&#xB4; => &#xB4;
+
+BOX DRAWINGS DOUBLE VERTICAL AND LEFT: &#x2563; => b5
+&#xB5; => &#xB5;
+
+BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE: &#x2564; => b6
+&#xB6; => &#xB6;
+
+BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE: &#x2565; => b7
+&#xB7; => 9e
+
+BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL: &#x2566; => b8
+&#xB8; => &#xB8;
+
+BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE: &#x2567; => b9
+&#xB9; => &#xB9;
+
+BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE: &#x2568; => ba
+&#xBA; => &#xBA;
+
+BOX DRAWINGS DOUBLE UP AND HORIZONTAL: &#x2569; => bb
+&#xBB; => &#xBB;
+
+BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE: &#x256A; => bc
+&#xBC; => &#xBC;
+
+BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE: &#x256B; => bd
+&#xBD; => &#xBD;
+
+BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL: &#x256C; => be
+&#xBE; => &#xBE;
+
+COPYRIGHT SIGN: &#xA9; => bf
+&#xBF; => &#xBF;
+
+CYRILLIC SMALL LETTER YU: &#x44E; => c0
+&#xC0; => &#xC0;
+
+CYRILLIC SMALL LETTER A: &#x430; => c1
+&#xC1; => &#xC1;
+
+CYRILLIC SMALL LETTER BE: &#x431; => c2
+&#xC2; => &#xC2;
+
+CYRILLIC SMALL LETTER TSE: &#x446; => c3
+&#xC3; => &#xC3;
+
+CYRILLIC SMALL LETTER DE: &#x434; => c4
+&#xC4; => &#xC4;
+
+CYRILLIC SMALL LETTER IE: &#x435; => c5
+&#xC5; => &#xC5;
+
+CYRILLIC SMALL LETTER EF: &#x444; => c6
+&#xC6; => &#xC6;
+
+CYRILLIC SMALL LETTER GHE: &#x433; => c7
+&#xC7; => &#xC7;
+
+CYRILLIC SMALL LETTER HA: &#x445; => c8
+&#xC8; => &#xC8;
+
+CYRILLIC SMALL LETTER I: &#x438; => c9
+&#xC9; => &#xC9;
+
+CYRILLIC SMALL LETTER SHORT I: &#x439; => ca
+&#xCA; => &#xCA;
+
+CYRILLIC SMALL LETTER KA: &#x43A; => cb
+&#xCB; => &#xCB;
+
+CYRILLIC SMALL LETTER EL: &#x43B; => cc
+&#xCC; => &#xCC;
+
+CYRILLIC SMALL LETTER EM: &#x43C; => cd
+&#xCD; => &#xCD;
+
+CYRILLIC SMALL LETTER EN: &#x43D; => ce
+&#xCE; => &#xCE;
+
+CYRILLIC SMALL LETTER O: &#x43E; => cf
+&#xCF; => &#xCF;
+
+CYRILLIC SMALL LETTER PE: &#x43F; => d0
+&#xD0; => &#xD0;
+
+CYRILLIC SMALL LETTER YA: &#x44F; => d1
+&#xD1; => &#xD1;
+
+CYRILLIC SMALL LETTER ER: &#x440; => d2
+&#xD2; => &#xD2;
+
+CYRILLIC SMALL LETTER ES: &#x441; => d3
+&#xD3; => &#xD3;
+
+CYRILLIC SMALL LETTER TE: &#x442; => d4
+&#xD4; => &#xD4;
+
+CYRILLIC SMALL LETTER U: &#x443; => d5
+&#xD5; => &#xD5;
+
+CYRILLIC SMALL LETTER ZHE: &#x436; => d6
+&#xD6; => &#xD6;
+
+CYRILLIC SMALL LETTER VE: &#x432; => d7
+&#xD7; => &#xD7;
+
+CYRILLIC SMALL LETTER SOFT SIGN: &#x44C; => d8
+&#xD8; => &#xD8;
+
+CYRILLIC SMALL LETTER YERU: &#x44B; => d9
+&#xD9; => &#xD9;
+
+CYRILLIC SMALL LETTER ZE: &#x437; => da
+&#xDA; => &#xDA;
+
+CYRILLIC SMALL LETTER SHA: &#x448; => db
+&#xDB; => &#xDB;
+
+CYRILLIC SMALL LETTER E: &#x44D; => dc
+&#xDC; => &#xDC;
+
+CYRILLIC SMALL LETTER SHCHA: &#x449; => dd
+&#xDD; => &#xDD;
+
+CYRILLIC SMALL LETTER CHE: &#x447; => de
+&#xDE; => &#xDE;
+
+CYRILLIC SMALL LETTER HARD SIGN: &#x44A; => df
+&#xDF; => &#xDF;
+
+CYRILLIC CAPITAL LETTER YU: &#x42E; => e0
+&#xE0; => &#xE0;
+
+CYRILLIC CAPITAL LETTER A: &#x410; => e1
+&#xE1; => &#xE1;
+
+CYRILLIC CAPITAL LETTER BE: &#x411; => e2
+&#xE2; => &#xE2;
+
+CYRILLIC CAPITAL LETTER TSE: &#x426; => e3
+&#xE3; => &#xE3;
+
+CYRILLIC CAPITAL LETTER DE: &#x414; => e4
+&#xE4; => &#xE4;
+
+CYRILLIC CAPITAL LETTER IE: &#x415; => e5
+&#xE5; => &#xE5;
+
+CYRILLIC CAPITAL LETTER EF: &#x424; => e6
+&#xE6; => &#xE6;
+
+CYRILLIC CAPITAL LETTER GHE: &#x413; => e7
+&#xE7; => &#xE7;
+
+CYRILLIC CAPITAL LETTER HA: &#x425; => e8
+&#xE8; => &#xE8;
+
+CYRILLIC CAPITAL LETTER I: &#x418; => e9
+&#xE9; => &#xE9;
+
+CYRILLIC CAPITAL LETTER SHORT I: &#x419; => ea
+&#xEA; => &#xEA;
+
+CYRILLIC CAPITAL LETTER KA: &#x41A; => eb
+&#xEB; => &#xEB;
+
+CYRILLIC CAPITAL LETTER EL: &#x41B; => ec
+&#xEC; => &#xEC;
+
+CYRILLIC CAPITAL LETTER EM: &#x41C; => ed
+&#xED; => &#xED;
+
+CYRILLIC CAPITAL LETTER EN: &#x41D; => ee
+&#xEE; => &#xEE;
+
+CYRILLIC CAPITAL LETTER O: &#x41E; => ef
+&#xEF; => &#xEF;
+
+CYRILLIC CAPITAL LETTER PE: &#x41F; => f0
+&#xF0; => &#xF0;
+
+CYRILLIC CAPITAL LETTER YA: &#x42F; => f1
+&#xF1; => &#xF1;
+
+CYRILLIC CAPITAL LETTER ER: &#x420; => f2
+&#xF2; => &#xF2;
+
+CYRILLIC CAPITAL LETTER ES: &#x421; => f3
+&#xF3; => &#xF3;
+
+CYRILLIC CAPITAL LETTER TE: &#x422; => f4
+&#xF4; => &#xF4;
+
+CYRILLIC CAPITAL LETTER U: &#x423; => f5
+&#xF5; => &#xF5;
+
+CYRILLIC CAPITAL LETTER ZHE: &#x416; => f6
+&#xF6; => &#xF6;
+
+CYRILLIC CAPITAL LETTER VE: &#x412; => f7
+&#xF7; => 9f
+
+CYRILLIC CAPITAL LETTER SOFT SIGN: &#x42C; => f8
+&#xF8; => &#xF8;
+
+CYRILLIC CAPITAL LETTER YERU: &#x42B; => f9
+&#xF9; => &#xF9;
+
+CYRILLIC CAPITAL LETTER ZE: &#x417; => fa
+&#xFA; => &#xFA;
+
+CYRILLIC CAPITAL LETTER SHA: &#x428; => fb
+&#xFB; => &#xFB;
+
+CYRILLIC CAPITAL LETTER E: &#x42D; => fc
+&#xFC; => &#xFC;
+
+CYRILLIC CAPITAL LETTER SHCHA: &#x429; => fd
+&#xFD; => &#xFD;
+
+CYRILLIC CAPITAL LETTER CHE: &#x427; => fe
+&#xFE; => &#xFE;
+
+CYRILLIC CAPITAL LETTER HARD SIGN: &#x42A; => ff
+&#xFF; => &#xFF;
+
+
diff --git a/ext/standard/tests/strings/html_entity_decode_macroman.phpt b/ext/standard/tests/strings/html_entity_decode_macroman.phpt
new file mode 100644
index 0000000000..4691bcf1a7
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_macroman.phpt
@@ -0,0 +1,540 @@
+--TEST--
+Translation of HTML entities for encoding MacRoman
+--FILE--
+<?php
+$arr = array(
+0x00C4 => array(0x80, "LATIN CAPITAL LETTER A WITH DIAERESIS"),
+0x00C5 => array(0x81, "LATIN CAPITAL LETTER A WITH RING ABOVE"),
+0x00C7 => array(0x82, "LATIN CAPITAL LETTER C WITH CEDILLA"),
+0x00C9 => array(0x83, "LATIN CAPITAL LETTER E WITH ACUTE"),
+0x00D1 => array(0x84, "LATIN CAPITAL LETTER N WITH TILDE"),
+0x00D6 => array(0x85, "LATIN CAPITAL LETTER O WITH DIAERESIS"),
+0x00DC => array(0x86, "LATIN CAPITAL LETTER U WITH DIAERESIS"),
+0x00E1 => array(0x87, "LATIN SMALL LETTER A WITH ACUTE"),
+0x00E0 => array(0x88, "LATIN SMALL LETTER A WITH GRAVE"),
+0x00E2 => array(0x89, "LATIN SMALL LETTER A WITH CIRCUMFLEX"),
+0x00E4 => array(0x8A, "LATIN SMALL LETTER A WITH DIAERESIS"),
+0x00E3 => array(0x8B, "LATIN SMALL LETTER A WITH TILDE"),
+0x00E5 => array(0x8C, "LATIN SMALL LETTER A WITH RING ABOVE"),
+0x00E7 => array(0x8D, "LATIN SMALL LETTER C WITH CEDILLA"),
+0x00E9 => array(0x8E, "LATIN SMALL LETTER E WITH ACUTE"),
+0x00E8 => array(0x8F, "LATIN SMALL LETTER E WITH GRAVE"),
+0x00EA => array(0x90, "LATIN SMALL LETTER E WITH CIRCUMFLEX"),
+0x00EB => array(0x91, "LATIN SMALL LETTER E WITH DIAERESIS"),
+0x00ED => array(0x92, "LATIN SMALL LETTER I WITH ACUTE"),
+0x00EC => array(0x93, "LATIN SMALL LETTER I WITH GRAVE"),
+0x00EE => array(0x94, "LATIN SMALL LETTER I WITH CIRCUMFLEX"),
+0x00EF => array(0x95, "LATIN SMALL LETTER I WITH DIAERESIS"),
+0x00F1 => array(0x96, "LATIN SMALL LETTER N WITH TILDE"),
+0x00F3 => array(0x97, "LATIN SMALL LETTER O WITH ACUTE"),
+0x00F2 => array(0x98, "LATIN SMALL LETTER O WITH GRAVE"),
+0x00F4 => array(0x99, "LATIN SMALL LETTER O WITH CIRCUMFLEX"),
+0x00F6 => array(0x9A, "LATIN SMALL LETTER O WITH DIAERESIS"),
+0x00F5 => array(0x9B, "LATIN SMALL LETTER O WITH TILDE"),
+0x00FA => array(0x9C, "LATIN SMALL LETTER U WITH ACUTE"),
+0x00F9 => array(0x9D, "LATIN SMALL LETTER U WITH GRAVE"),
+0x00FB => array(0x9E, "LATIN SMALL LETTER U WITH CIRCUMFLEX"),
+0x00FC => array(0x9F, "LATIN SMALL LETTER U WITH DIAERESIS"),
+0x2020 => array(0xA0, "DAGGER"),
+0x00B0 => array(0xA1, "DEGREE SIGN"),
+0x00A2 => array(0xA2, "CENT SIGN"),
+0x00A3 => array(0xA3, "POUND SIGN"),
+0x00A7 => array(0xA4, "SECTION SIGN"),
+0x2022 => array(0xA5, "BULLET"),
+0x00B6 => array(0xA6, "PILCROW SIGN"),
+0x00DF => array(0xA7, "LATIN SMALL LETTER SHARP S"),
+0x00AE => array(0xA8, "REGISTERED SIGN"),
+0x00A9 => array(0xA9, "COPYRIGHT SIGN"),
+0x2122 => array(0xAA, "TRADE MARK SIGN"),
+0x00B4 => array(0xAB, "ACUTE ACCENT"),
+0x00A8 => array(0xAC, "DIAERESIS"),
+0x2260 => array(0xAD, "NOT EQUAL TO"),
+0x00C6 => array(0xAE, "LATIN CAPITAL LETTER AE"),
+0x00D8 => array(0xAF, "LATIN CAPITAL LETTER O WITH STROKE"),
+0x221E => array(0xB0, "INFINITY"),
+0x00B1 => array(0xB1, "PLUS-MINUS SIGN"),
+0x2264 => array(0xB2, "LESS-THAN OR EQUAL TO"),
+0x2265 => array(0xB3, "GREATER-THAN OR EQUAL TO"),
+0x00A5 => array(0xB4, "YEN SIGN"),
+0x00B5 => array(0xB5, "MICRO SIGN"),
+0x2202 => array(0xB6, "PARTIAL DIFFERENTIAL"),
+0x2211 => array(0xB7, "N-ARY SUMMATION"),
+0x220F => array(0xB8, "N-ARY PRODUCT"),
+0x03C0 => array(0xB9, "GREEK SMALL LETTER PI"),
+0x222B => array(0xBA, "INTEGRAL"),
+0x00AA => array(0xBB, "FEMININE ORDINAL INDICATOR"),
+0x00BA => array(0xBC, "MASCULINE ORDINAL INDICATOR"),
+0x03A9 => array(0xBD, "GREEK CAPITAL LETTER OMEGA"),
+0x00E6 => array(0xBE, "LATIN SMALL LETTER AE"),
+0x00F8 => array(0xBF, "LATIN SMALL LETTER O WITH STROKE"),
+0x00BF => array(0xC0, "INVERTED QUESTION MARK"),
+0x00A1 => array(0xC1, "INVERTED EXCLAMATION MARK"),
+0x00AC => array(0xC2, "NOT SIGN"),
+0x221A => array(0xC3, "SQUARE ROOT"),
+0x0192 => array(0xC4, "LATIN SMALL LETTER F WITH HOOK"),
+0x2248 => array(0xC5, "ALMOST EQUAL TO"),
+0x2206 => array(0xC6, "INCREMENT"),
+0x00AB => array(0xC7, "LEFT-POINTING DOUBLE ANGLE QUOTATION MARK"),
+0x00BB => array(0xC8, "RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK"),
+0x2026 => array(0xC9, "HORIZONTAL ELLIPSIS"),
+0x00A0 => array(0xCA, "NO-BREAK SPACE"),
+0x00C0 => array(0xCB, "LATIN CAPITAL LETTER A WITH GRAVE"),
+0x00C3 => array(0xCC, "LATIN CAPITAL LETTER A WITH TILDE"),
+0x00D5 => array(0xCD, "LATIN CAPITAL LETTER O WITH TILDE"),
+0x0152 => array(0xCE, "LATIN CAPITAL LIGATURE OE"),
+0x0153 => array(0xCF, "LATIN SMALL LIGATURE OE"),
+0x2013 => array(0xD0, "EN DASH"),
+0x2014 => array(0xD1, "EM DASH"),
+0x201C => array(0xD2, "LEFT DOUBLE QUOTATION MARK"),
+0x201D => array(0xD3, "RIGHT DOUBLE QUOTATION MARK"),
+0x2018 => array(0xD4, "LEFT SINGLE QUOTATION MARK"),
+0x2019 => array(0xD5, "RIGHT SINGLE QUOTATION MARK"),
+0x00F7 => array(0xD6, "DIVISION SIGN"),
+0x25CA => array(0xD7, "LOZENGE"),
+0x00FF => array(0xD8, "LATIN SMALL LETTER Y WITH DIAERESIS"),
+0x0178 => array(0xD9, "LATIN CAPITAL LETTER Y WITH DIAERESIS"),
+0x2044 => array(0xDA, "FRACTION SLASH"),
+0x20AC => array(0xDB, "EURO SIGN"),
+0x2039 => array(0xDC, "SINGLE LEFT-POINTING ANGLE QUOTATION MARK"),
+0x203A => array(0xDD, "SINGLE RIGHT-POINTING ANGLE QUOTATION MARK"),
+0xFB01 => array(0xDE, "LATIN SMALL LIGATURE FI"),
+0xFB02 => array(0xDF, "LATIN SMALL LIGATURE FL"),
+0x2021 => array(0xE0, "DOUBLE DAGGER"),
+0x00B7 => array(0xE1, "MIDDLE DOT"),
+0x201A => array(0xE2, "SINGLE LOW-9 QUOTATION MARK"),
+0x201E => array(0xE3, "DOUBLE LOW-9 QUOTATION MARK"),
+0x2030 => array(0xE4, "PER MILLE SIGN"),
+0x00C2 => array(0xE5, "LATIN CAPITAL LETTER A WITH CIRCUMFLEX"),
+0x00CA => array(0xE6, "LATIN CAPITAL LETTER E WITH CIRCUMFLEX"),
+0x00C1 => array(0xE7, "LATIN CAPITAL LETTER A WITH ACUTE"),
+0x00CB => array(0xE8, "LATIN CAPITAL LETTER E WITH DIAERESIS"),
+0x00C8 => array(0xE9, "LATIN CAPITAL LETTER E WITH GRAVE"),
+0x00CD => array(0xEA, "LATIN CAPITAL LETTER I WITH ACUTE"),
+0x00CE => array(0xEB, "LATIN CAPITAL LETTER I WITH CIRCUMFLEX"),
+0x00CF => array(0xEC, "LATIN CAPITAL LETTER I WITH DIAERESIS"),
+0x00CC => array(0xED, "LATIN CAPITAL LETTER I WITH GRAVE"),
+0x00D3 => array(0xEE, "LATIN CAPITAL LETTER O WITH ACUTE"),
+0x00D4 => array(0xEF, "LATIN CAPITAL LETTER O WITH CIRCUMFLEX"),
+0xF8FF => array(0xF0, "Apple logo"),
+0x00D2 => array(0xF1, "LATIN CAPITAL LETTER O WITH GRAVE"),
+0x00DA => array(0xF2, "LATIN CAPITAL LETTER U WITH ACUTE"),
+0x00DB => array(0xF3, "LATIN CAPITAL LETTER U WITH CIRCUMFLEX"),
+0x00D9 => array(0xF4, "LATIN CAPITAL LETTER U WITH GRAVE"),
+0x0131 => array(0xF5, "LATIN SMALL LETTER DOTLESS I"),
+0x02C6 => array(0xF6, "MODIFIER LETTER CIRCUMFLEX ACCENT"),
+0x02DC => array(0xF7, "SMALL TILDE"),
+0x00AF => array(0xF8, "MACRON"),
+0x02D8 => array(0xF9, "BREVE"),
+0x02D9 => array(0xFA, "DOT ABOVE"),
+0x02DA => array(0xFB, "RING ABOVE"),
+0x00B8 => array(0xFC, "CEDILLA"),
+0x02DD => array(0xFD, "DOUBLE ACUTE ACCENT"),
+0x02DB => array(0xFE, "OGONEK"),
+0x02C7 => array(0xFF, "CARON"),
+);
+
+$res = html_entity_decode("&#x7F;", ENT_QUOTES, 'MacRoman');
+echo "Special test for &#x7F; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'MacRoman');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'MacRoman');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+Special test for &#x7F; (shouldn't decode):
+&#x7F;
+
+LATIN CAPITAL LETTER A WITH DIAERESIS: &#xC4; => 80
+&#x80; => &#x80;
+
+LATIN CAPITAL LETTER A WITH RING ABOVE: &#xC5; => 81
+&#x81; => &#x81;
+
+LATIN CAPITAL LETTER C WITH CEDILLA: &#xC7; => 82
+&#x82; => &#x82;
+
+LATIN CAPITAL LETTER E WITH ACUTE: &#xC9; => 83
+&#x83; => &#x83;
+
+LATIN CAPITAL LETTER N WITH TILDE: &#xD1; => 84
+&#x84; => &#x84;
+
+LATIN CAPITAL LETTER O WITH DIAERESIS: &#xD6; => 85
+&#x85; => &#x85;
+
+LATIN CAPITAL LETTER U WITH DIAERESIS: &#xDC; => 86
+&#x86; => &#x86;
+
+LATIN SMALL LETTER A WITH ACUTE: &#xE1; => 87
+&#x87; => &#x87;
+
+LATIN SMALL LETTER A WITH GRAVE: &#xE0; => 88
+&#x88; => &#x88;
+
+LATIN SMALL LETTER A WITH CIRCUMFLEX: &#xE2; => 89
+&#x89; => &#x89;
+
+LATIN SMALL LETTER A WITH DIAERESIS: &#xE4; => 8a
+&#x8A; => &#x8A;
+
+LATIN SMALL LETTER A WITH TILDE: &#xE3; => 8b
+&#x8B; => &#x8B;
+
+LATIN SMALL LETTER A WITH RING ABOVE: &#xE5; => 8c
+&#x8C; => &#x8C;
+
+LATIN SMALL LETTER C WITH CEDILLA: &#xE7; => 8d
+&#x8D; => &#x8D;
+
+LATIN SMALL LETTER E WITH ACUTE: &#xE9; => 8e
+&#x8E; => &#x8E;
+
+LATIN SMALL LETTER E WITH GRAVE: &#xE8; => 8f
+&#x8F; => &#x8F;
+
+LATIN SMALL LETTER E WITH CIRCUMFLEX: &#xEA; => 90
+&#x90; => &#x90;
+
+LATIN SMALL LETTER E WITH DIAERESIS: &#xEB; => 91
+&#x91; => &#x91;
+
+LATIN SMALL LETTER I WITH ACUTE: &#xED; => 92
+&#x92; => &#x92;
+
+LATIN SMALL LETTER I WITH GRAVE: &#xEC; => 93
+&#x93; => &#x93;
+
+LATIN SMALL LETTER I WITH CIRCUMFLEX: &#xEE; => 94
+&#x94; => &#x94;
+
+LATIN SMALL LETTER I WITH DIAERESIS: &#xEF; => 95
+&#x95; => &#x95;
+
+LATIN SMALL LETTER N WITH TILDE: &#xF1; => 96
+&#x96; => &#x96;
+
+LATIN SMALL LETTER O WITH ACUTE: &#xF3; => 97
+&#x97; => &#x97;
+
+LATIN SMALL LETTER O WITH GRAVE: &#xF2; => 98
+&#x98; => &#x98;
+
+LATIN SMALL LETTER O WITH CIRCUMFLEX: &#xF4; => 99
+&#x99; => &#x99;
+
+LATIN SMALL LETTER O WITH DIAERESIS: &#xF6; => 9a
+&#x9A; => &#x9A;
+
+LATIN SMALL LETTER O WITH TILDE: &#xF5; => 9b
+&#x9B; => &#x9B;
+
+LATIN SMALL LETTER U WITH ACUTE: &#xFA; => 9c
+&#x9C; => &#x9C;
+
+LATIN SMALL LETTER U WITH GRAVE: &#xF9; => 9d
+&#x9D; => &#x9D;
+
+LATIN SMALL LETTER U WITH CIRCUMFLEX: &#xFB; => 9e
+&#x9E; => &#x9E;
+
+LATIN SMALL LETTER U WITH DIAERESIS: &#xFC; => 9f
+&#x9F; => &#x9F;
+
+DAGGER: &#x2020; => a0
+&#xA0; => ca
+
+DEGREE SIGN: &#xB0; => a1
+&#xA1; => c1
+
+CENT SIGN: &#xA2; => a2
+&#xA2; => a2
+
+POUND SIGN: &#xA3; => a3
+&#xA3; => a3
+
+SECTION SIGN: &#xA7; => a4
+&#xA4; => &#xA4;
+
+BULLET: &#x2022; => a5
+&#xA5; => b4
+
+PILCROW SIGN: &#xB6; => a6
+&#xA6; => &#xA6;
+
+LATIN SMALL LETTER SHARP S: &#xDF; => a7
+&#xA7; => a4
+
+REGISTERED SIGN: &#xAE; => a8
+&#xA8; => ac
+
+COPYRIGHT SIGN: &#xA9; => a9
+&#xA9; => a9
+
+TRADE MARK SIGN: &#x2122; => aa
+&#xAA; => bb
+
+ACUTE ACCENT: &#xB4; => ab
+&#xAB; => c7
+
+DIAERESIS: &#xA8; => ac
+&#xAC; => c2
+
+NOT EQUAL TO: &#x2260; => ad
+&#xAD; => &#xAD;
+
+LATIN CAPITAL LETTER AE: &#xC6; => ae
+&#xAE; => a8
+
+LATIN CAPITAL LETTER O WITH STROKE: &#xD8; => af
+&#xAF; => f8
+
+INFINITY: &#x221E; => b0
+&#xB0; => a1
+
+PLUS-MINUS SIGN: &#xB1; => b1
+&#xB1; => b1
+
+LESS-THAN OR EQUAL TO: &#x2264; => b2
+&#xB2; => &#xB2;
+
+GREATER-THAN OR EQUAL TO: &#x2265; => b3
+&#xB3; => &#xB3;
+
+YEN SIGN: &#xA5; => b4
+&#xB4; => ab
+
+MICRO SIGN: &#xB5; => b5
+&#xB5; => b5
+
+PARTIAL DIFFERENTIAL: &#x2202; => b6
+&#xB6; => a6
+
+N-ARY SUMMATION: &#x2211; => b7
+&#xB7; => e1
+
+N-ARY PRODUCT: &#x220F; => b8
+&#xB8; => fc
+
+GREEK SMALL LETTER PI: &#x3C0; => b9
+&#xB9; => &#xB9;
+
+INTEGRAL: &#x222B; => ba
+&#xBA; => bc
+
+FEMININE ORDINAL INDICATOR: &#xAA; => bb
+&#xBB; => c8
+
+MASCULINE ORDINAL INDICATOR: &#xBA; => bc
+&#xBC; => &#xBC;
+
+GREEK CAPITAL LETTER OMEGA: &#x3A9; => bd
+&#xBD; => &#xBD;
+
+LATIN SMALL LETTER AE: &#xE6; => be
+&#xBE; => &#xBE;
+
+LATIN SMALL LETTER O WITH STROKE: &#xF8; => bf
+&#xBF; => c0
+
+INVERTED QUESTION MARK: &#xBF; => c0
+&#xC0; => cb
+
+INVERTED EXCLAMATION MARK: &#xA1; => c1
+&#xC1; => e7
+
+NOT SIGN: &#xAC; => c2
+&#xC2; => e5
+
+SQUARE ROOT: &#x221A; => c3
+&#xC3; => cc
+
+LATIN SMALL LETTER F WITH HOOK: &#x192; => c4
+&#xC4; => 80
+
+ALMOST EQUAL TO: &#x2248; => c5
+&#xC5; => 81
+
+INCREMENT: &#x2206; => c6
+&#xC6; => ae
+
+LEFT-POINTING DOUBLE ANGLE QUOTATION MARK: &#xAB; => c7
+&#xC7; => 82
+
+RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK: &#xBB; => c8
+&#xC8; => e9
+
+HORIZONTAL ELLIPSIS: &#x2026; => c9
+&#xC9; => 83
+
+NO-BREAK SPACE: &#xA0; => ca
+&#xCA; => e6
+
+LATIN CAPITAL LETTER A WITH GRAVE: &#xC0; => cb
+&#xCB; => e8
+
+LATIN CAPITAL LETTER A WITH TILDE: &#xC3; => cc
+&#xCC; => ed
+
+LATIN CAPITAL LETTER O WITH TILDE: &#xD5; => cd
+&#xCD; => ea
+
+LATIN CAPITAL LIGATURE OE: &#x152; => ce
+&#xCE; => eb
+
+LATIN SMALL LIGATURE OE: &#x153; => cf
+&#xCF; => ec
+
+EN DASH: &#x2013; => d0
+&#xD0; => &#xD0;
+
+EM DASH: &#x2014; => d1
+&#xD1; => 84
+
+LEFT DOUBLE QUOTATION MARK: &#x201C; => d2
+&#xD2; => f1
+
+RIGHT DOUBLE QUOTATION MARK: &#x201D; => d3
+&#xD3; => ee
+
+LEFT SINGLE QUOTATION MARK: &#x2018; => d4
+&#xD4; => ef
+
+RIGHT SINGLE QUOTATION MARK: &#x2019; => d5
+&#xD5; => cd
+
+DIVISION SIGN: &#xF7; => d6
+&#xD6; => 85
+
+LOZENGE: &#x25CA; => d7
+&#xD7; => &#xD7;
+
+LATIN SMALL LETTER Y WITH DIAERESIS: &#xFF; => d8
+&#xD8; => af
+
+LATIN CAPITAL LETTER Y WITH DIAERESIS: &#x178; => d9
+&#xD9; => f4
+
+FRACTION SLASH: &#x2044; => da
+&#xDA; => f2
+
+EURO SIGN: &#x20AC; => db
+&#xDB; => f3
+
+SINGLE LEFT-POINTING ANGLE QUOTATION MARK: &#x2039; => dc
+&#xDC; => 86
+
+SINGLE RIGHT-POINTING ANGLE QUOTATION MARK: &#x203A; => dd
+&#xDD; => &#xDD;
+
+LATIN SMALL LIGATURE FI: &#xFB01; => de
+&#xDE; => &#xDE;
+
+LATIN SMALL LIGATURE FL: &#xFB02; => df
+&#xDF; => a7
+
+DOUBLE DAGGER: &#x2021; => e0
+&#xE0; => 88
+
+MIDDLE DOT: &#xB7; => e1
+&#xE1; => 87
+
+SINGLE LOW-9 QUOTATION MARK: &#x201A; => e2
+&#xE2; => 89
+
+DOUBLE LOW-9 QUOTATION MARK: &#x201E; => e3
+&#xE3; => 8b
+
+PER MILLE SIGN: &#x2030; => e4
+&#xE4; => 8a
+
+LATIN CAPITAL LETTER A WITH CIRCUMFLEX: &#xC2; => e5
+&#xE5; => 8c
+
+LATIN CAPITAL LETTER E WITH CIRCUMFLEX: &#xCA; => e6
+&#xE6; => be
+
+LATIN CAPITAL LETTER A WITH ACUTE: &#xC1; => e7
+&#xE7; => 8d
+
+LATIN CAPITAL LETTER E WITH DIAERESIS: &#xCB; => e8
+&#xE8; => 8f
+
+LATIN CAPITAL LETTER E WITH GRAVE: &#xC8; => e9
+&#xE9; => 8e
+
+LATIN CAPITAL LETTER I WITH ACUTE: &#xCD; => ea
+&#xEA; => 90
+
+LATIN CAPITAL LETTER I WITH CIRCUMFLEX: &#xCE; => eb
+&#xEB; => 91
+
+LATIN CAPITAL LETTER I WITH DIAERESIS: &#xCF; => ec
+&#xEC; => 93
+
+LATIN CAPITAL LETTER I WITH GRAVE: &#xCC; => ed
+&#xED; => 92
+
+LATIN CAPITAL LETTER O WITH ACUTE: &#xD3; => ee
+&#xEE; => 94
+
+LATIN CAPITAL LETTER O WITH CIRCUMFLEX: &#xD4; => ef
+&#xEF; => 95
+
+Apple logo: &#xF8FF; => f0
+&#xF0; => &#xF0;
+
+LATIN CAPITAL LETTER O WITH GRAVE: &#xD2; => f1
+&#xF1; => 96
+
+LATIN CAPITAL LETTER U WITH ACUTE: &#xDA; => f2
+&#xF2; => 98
+
+LATIN CAPITAL LETTER U WITH CIRCUMFLEX: &#xDB; => f3
+&#xF3; => 97
+
+LATIN CAPITAL LETTER U WITH GRAVE: &#xD9; => f4
+&#xF4; => 99
+
+LATIN SMALL LETTER DOTLESS I: &#x131; => f5
+&#xF5; => 9b
+
+MODIFIER LETTER CIRCUMFLEX ACCENT: &#x2C6; => f6
+&#xF6; => 9a
+
+SMALL TILDE: &#x2DC; => f7
+&#xF7; => d6
+
+MACRON: &#xAF; => f8
+&#xF8; => bf
+
+BREVE: &#x2D8; => f9
+&#xF9; => 9d
+
+DOT ABOVE: &#x2D9; => fa
+&#xFA; => 9c
+
+RING ABOVE: &#x2DA; => fb
+&#xFB; => 9e
+
+CEDILLA: &#xB8; => fc
+&#xFC; => 9f
+
+DOUBLE ACUTE ACCENT: &#x2DD; => fd
+&#xFD; => &#xFD;
+
+OGONEK: &#x2DB; => fe
+&#xFE; => &#xFE;
+
+CARON: &#x2C7; => ff
+&#xFF; => d8
+
+
diff --git a/ext/standard/tests/strings/html_entity_decode_win1251.phpt b/ext/standard/tests/strings/html_entity_decode_win1251.phpt
new file mode 100644
index 0000000000..e47392623c
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_win1251.phpt
@@ -0,0 +1,537 @@
+--TEST--
+Translation of HTML entities for encoding WIN-1251
+--FILE--
+<?php
+$arr = array(
+0x0402 => array(0x80, "CYRILLIC CAPITAL LETTER DJE"),
+0x0403 => array(0x81, "CYRILLIC CAPITAL LETTER GJE"),
+0x201A => array(0x82, "SINGLE LOW-9 QUOTATION MARK"),
+0x0453 => array(0x83, "CYRILLIC SMALL LETTER GJE"),
+0x201E => array(0x84, "DOUBLE LOW-9 QUOTATION MARK"),
+0x2026 => array(0x85, "HORIZONTAL ELLIPSIS"),
+0x2020 => array(0x86, "DAGGER"),
+0x2021 => array(0x87, "DOUBLE DAGGER"),
+0x20AC => array(0x88, "EURO SIGN"),
+0x2030 => array(0x89, "PER MILLE SIGN"),
+0x0409 => array(0x8A, "CYRILLIC CAPITAL LETTER LJE"),
+0x2039 => array(0x8B, "SINGLE LEFT-POINTING ANGLE QUOTATION MARK"),
+0x040A => array(0x8C, "CYRILLIC CAPITAL LETTER NJE"),
+0x040C => array(0x8D, "CYRILLIC CAPITAL LETTER KJE"),
+0x040B => array(0x8E, "CYRILLIC CAPITAL LETTER TSHE"),
+0x040F => array(0x8F, "CYRILLIC CAPITAL LETTER DZHE"),
+0x0452 => array(0x90, "CYRILLIC SMALL LETTER DJE"),
+0x2018 => array(0x91, "LEFT SINGLE QUOTATION MARK"),
+0x2019 => array(0x92, "RIGHT SINGLE QUOTATION MARK"),
+0x201C => array(0x93, "LEFT DOUBLE QUOTATION MARK"),
+0x201D => array(0x94, "RIGHT DOUBLE QUOTATION MARK"),
+0x2022 => array(0x95, "BULLET"),
+0x2013 => array(0x96, "EN DASH"),
+0x2014 => array(0x97, "EM DASH"),
+//0x98 #UNDEFINED
+0x2122 => array(0x99, "TRADE MARK SIGN"),
+0x0459 => array(0x9A, "CYRILLIC SMALL LETTER LJE"),
+0x203A => array(0x9B, "SINGLE RIGHT-POINTING ANGLE QUOTATION MARK"),
+0x045A => array(0x9C, "CYRILLIC SMALL LETTER NJE"),
+0x045C => array(0x9D, "CYRILLIC SMALL LETTER KJE"),
+0x045B => array(0x9E, "CYRILLIC SMALL LETTER TSHE"),
+0x045F => array(0x9F, "CYRILLIC SMALL LETTER DZHE"),
+0x00A0 => array(0xA0, "NO-BREAK SPACE"),
+0x040E => array(0xA1, "CYRILLIC CAPITAL LETTER SHORT U"),
+0x045E => array(0xA2, "CYRILLIC SMALL LETTER SHORT U"),
+0x0408 => array(0xA3, "CYRILLIC CAPITAL LETTER JE"),
+0x00A4 => array(0xA4, "CURRENCY SIGN"),
+0x0490 => array(0xA5, "CYRILLIC CAPITAL LETTER GHE WITH UPTURN"),
+0x00A6 => array(0xA6, "BROKEN BAR"),
+0x00A7 => array(0xA7, "SECTION SIGN"),
+0x0401 => array(0xA8, "CYRILLIC CAPITAL LETTER IO"),
+0x00A9 => array(0xA9, "COPYRIGHT SIGN"),
+0x0404 => array(0xAA, "CYRILLIC CAPITAL LETTER UKRAINIAN IE"),
+0x00AB => array(0xAB, "LEFT-POINTING DOUBLE ANGLE QUOTATION MARK"),
+0x00AC => array(0xAC, "NOT SIGN"),
+0x00AD => array(0xAD, "SOFT HYPHEN"),
+0x00AE => array(0xAE, "REGISTERED SIGN"),
+0x0407 => array(0xAF, "CYRILLIC CAPITAL LETTER YI"),
+0x00B0 => array(0xB0, "DEGREE SIGN"),
+0x00B1 => array(0xB1, "PLUS-MINUS SIGN"),
+0x0406 => array(0xB2, "CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I"),
+0x0456 => array(0xB3, "CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I"),
+0x0491 => array(0xB4, "CYRILLIC SMALL LETTER GHE WITH UPTURN"),
+0x00B5 => array(0xB5, "MICRO SIGN"),
+0x00B6 => array(0xB6, "PILCROW SIGN"),
+0x00B7 => array(0xB7, "MIDDLE DOT"),
+0x0451 => array(0xB8, "CYRILLIC SMALL LETTER IO"),
+0x2116 => array(0xB9, "NUMERO SIGN"),
+0x0454 => array(0xBA, "CYRILLIC SMALL LETTER UKRAINIAN IE"),
+0x00BB => array(0xBB, "RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK"),
+0x0458 => array(0xBC, "CYRILLIC SMALL LETTER JE"),
+0x0405 => array(0xBD, "CYRILLIC CAPITAL LETTER DZE"),
+0x0455 => array(0xBE, "CYRILLIC SMALL LETTER DZE"),
+0x0457 => array(0xBF, "CYRILLIC SMALL LETTER YI"),
+0x0410 => array(0xC0, "CYRILLIC CAPITAL LETTER A"),
+0x0411 => array(0xC1, "CYRILLIC CAPITAL LETTER BE"),
+0x0412 => array(0xC2, "CYRILLIC CAPITAL LETTER VE"),
+0x0413 => array(0xC3, "CYRILLIC CAPITAL LETTER GHE"),
+0x0414 => array(0xC4, "CYRILLIC CAPITAL LETTER DE"),
+0x0415 => array(0xC5, "CYRILLIC CAPITAL LETTER IE"),
+0x0416 => array(0xC6, "CYRILLIC CAPITAL LETTER ZHE"),
+0x0417 => array(0xC7, "CYRILLIC CAPITAL LETTER ZE"),
+0x0418 => array(0xC8, "CYRILLIC CAPITAL LETTER I"),
+0x0419 => array(0xC9, "CYRILLIC CAPITAL LETTER SHORT I"),
+0x041A => array(0xCA, "CYRILLIC CAPITAL LETTER KA"),
+0x041B => array(0xCB, "CYRILLIC CAPITAL LETTER EL"),
+0x041C => array(0xCC, "CYRILLIC CAPITAL LETTER EM"),
+0x041D => array(0xCD, "CYRILLIC CAPITAL LETTER EN"),
+0x041E => array(0xCE, "CYRILLIC CAPITAL LETTER O"),
+0x041F => array(0xCF, "CYRILLIC CAPITAL LETTER PE"),
+0x0420 => array(0xD0, "CYRILLIC CAPITAL LETTER ER"),
+0x0421 => array(0xD1, "CYRILLIC CAPITAL LETTER ES"),
+0x0422 => array(0xD2, "CYRILLIC CAPITAL LETTER TE"),
+0x0423 => array(0xD3, "CYRILLIC CAPITAL LETTER U"),
+0x0424 => array(0xD4, "CYRILLIC CAPITAL LETTER EF"),
+0x0425 => array(0xD5, "CYRILLIC CAPITAL LETTER HA"),
+0x0426 => array(0xD6, "CYRILLIC CAPITAL LETTER TSE"),
+0x0427 => array(0xD7, "CYRILLIC CAPITAL LETTER CHE"),
+0x0428 => array(0xD8, "CYRILLIC CAPITAL LETTER SHA"),
+0x0429 => array(0xD9, "CYRILLIC CAPITAL LETTER SHCHA"),
+0x042A => array(0xDA, "CYRILLIC CAPITAL LETTER HARD SIGN"),
+0x042B => array(0xDB, "CYRILLIC CAPITAL LETTER YERU"),
+0x042C => array(0xDC, "CYRILLIC CAPITAL LETTER SOFT SIGN"),
+0x042D => array(0xDD, "CYRILLIC CAPITAL LETTER E"),
+0x042E => array(0xDE, "CYRILLIC CAPITAL LETTER YU"),
+0x042F => array(0xDF, "CYRILLIC CAPITAL LETTER YA"),
+0x0430 => array(0xE0, "CYRILLIC SMALL LETTER A"),
+0x0431 => array(0xE1, "CYRILLIC SMALL LETTER BE"),
+0x0432 => array(0xE2, "CYRILLIC SMALL LETTER VE"),
+0x0433 => array(0xE3, "CYRILLIC SMALL LETTER GHE"),
+0x0434 => array(0xE4, "CYRILLIC SMALL LETTER DE"),
+0x0435 => array(0xE5, "CYRILLIC SMALL LETTER IE"),
+0x0436 => array(0xE6, "CYRILLIC SMALL LETTER ZHE"),
+0x0437 => array(0xE7, "CYRILLIC SMALL LETTER ZE"),
+0x0438 => array(0xE8, "CYRILLIC SMALL LETTER I"),
+0x0439 => array(0xE9, "CYRILLIC SMALL LETTER SHORT I"),
+0x043A => array(0xEA, "CYRILLIC SMALL LETTER KA"),
+0x043B => array(0xEB, "CYRILLIC SMALL LETTER EL"),
+0x043C => array(0xEC, "CYRILLIC SMALL LETTER EM"),
+0x043D => array(0xED, "CYRILLIC SMALL LETTER EN"),
+0x043E => array(0xEE, "CYRILLIC SMALL LETTER O"),
+0x043F => array(0xEF, "CYRILLIC SMALL LETTER PE"),
+0x0440 => array(0xF0, "CYRILLIC SMALL LETTER ER"),
+0x0441 => array(0xF1, "CYRILLIC SMALL LETTER ES"),
+0x0442 => array(0xF2, "CYRILLIC SMALL LETTER TE"),
+0x0443 => array(0xF3, "CYRILLIC SMALL LETTER U"),
+0x0444 => array(0xF4, "CYRILLIC SMALL LETTER EF"),
+0x0445 => array(0xF5, "CYRILLIC SMALL LETTER HA"),
+0x0446 => array(0xF6, "CYRILLIC SMALL LETTER TSE"),
+0x0447 => array(0xF7, "CYRILLIC SMALL LETTER CHE"),
+0x0448 => array(0xF8, "CYRILLIC SMALL LETTER SHA"),
+0x0449 => array(0xF9, "CYRILLIC SMALL LETTER SHCHA"),
+0x044A => array(0xFA, "CYRILLIC SMALL LETTER HARD SIGN"),
+0x044B => array(0xFB, "CYRILLIC SMALL LETTER YERU"),
+0x044C => array(0xFC, "CYRILLIC SMALL LETTER SOFT SIGN"),
+0x044D => array(0xFD, "CYRILLIC SMALL LETTER E"),
+0x044E => array(0xFE, "CYRILLIC SMALL LETTER YU"),
+0x044F => array(0xFF, "CYRILLIC SMALL LETTER YA"),
+);
+
+$res = html_entity_decode("&#x98;", ENT_QUOTES, 'WINDOWS-1251');
+echo "Special test for &#x98; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'WINDOWS-1251');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'WINDOWS-1251');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+Special test for &#x98; (shouldn't decode):
+&#x98;
+
+CYRILLIC CAPITAL LETTER DJE: &#x402; => 80
+&#x80; => &#x80;
+
+CYRILLIC CAPITAL LETTER GJE: &#x403; => 81
+&#x81; => &#x81;
+
+SINGLE LOW-9 QUOTATION MARK: &#x201A; => 82
+&#x82; => &#x82;
+
+CYRILLIC SMALL LETTER GJE: &#x453; => 83
+&#x83; => &#x83;
+
+DOUBLE LOW-9 QUOTATION MARK: &#x201E; => 84
+&#x84; => &#x84;
+
+HORIZONTAL ELLIPSIS: &#x2026; => 85
+&#x85; => &#x85;
+
+DAGGER: &#x2020; => 86
+&#x86; => &#x86;
+
+DOUBLE DAGGER: &#x2021; => 87
+&#x87; => &#x87;
+
+EURO SIGN: &#x20AC; => 88
+&#x88; => &#x88;
+
+PER MILLE SIGN: &#x2030; => 89
+&#x89; => &#x89;
+
+CYRILLIC CAPITAL LETTER LJE: &#x409; => 8a
+&#x8A; => &#x8A;
+
+SINGLE LEFT-POINTING ANGLE QUOTATION MARK: &#x2039; => 8b
+&#x8B; => &#x8B;
+
+CYRILLIC CAPITAL LETTER NJE: &#x40A; => 8c
+&#x8C; => &#x8C;
+
+CYRILLIC CAPITAL LETTER KJE: &#x40C; => 8d
+&#x8D; => &#x8D;
+
+CYRILLIC CAPITAL LETTER TSHE: &#x40B; => 8e
+&#x8E; => &#x8E;
+
+CYRILLIC CAPITAL LETTER DZHE: &#x40F; => 8f
+&#x8F; => &#x8F;
+
+CYRILLIC SMALL LETTER DJE: &#x452; => 90
+&#x90; => &#x90;
+
+LEFT SINGLE QUOTATION MARK: &#x2018; => 91
+&#x91; => &#x91;
+
+RIGHT SINGLE QUOTATION MARK: &#x2019; => 92
+&#x92; => &#x92;
+
+LEFT DOUBLE QUOTATION MARK: &#x201C; => 93
+&#x93; => &#x93;
+
+RIGHT DOUBLE QUOTATION MARK: &#x201D; => 94
+&#x94; => &#x94;
+
+BULLET: &#x2022; => 95
+&#x95; => &#x95;
+
+EN DASH: &#x2013; => 96
+&#x96; => &#x96;
+
+EM DASH: &#x2014; => 97
+&#x97; => &#x97;
+
+TRADE MARK SIGN: &#x2122; => 99
+&#x99; => &#x99;
+
+CYRILLIC SMALL LETTER LJE: &#x459; => 9a
+&#x9A; => &#x9A;
+
+SINGLE RIGHT-POINTING ANGLE QUOTATION MARK: &#x203A; => 9b
+&#x9B; => &#x9B;
+
+CYRILLIC SMALL LETTER NJE: &#x45A; => 9c
+&#x9C; => &#x9C;
+
+CYRILLIC SMALL LETTER KJE: &#x45C; => 9d
+&#x9D; => &#x9D;
+
+CYRILLIC SMALL LETTER TSHE: &#x45B; => 9e
+&#x9E; => &#x9E;
+
+CYRILLIC SMALL LETTER DZHE: &#x45F; => 9f
+&#x9F; => &#x9F;
+
+NO-BREAK SPACE: &#xA0; => a0
+&#xA0; => a0
+
+CYRILLIC CAPITAL LETTER SHORT U: &#x40E; => a1
+&#xA1; => &#xA1;
+
+CYRILLIC SMALL LETTER SHORT U: &#x45E; => a2
+&#xA2; => &#xA2;
+
+CYRILLIC CAPITAL LETTER JE: &#x408; => a3
+&#xA3; => &#xA3;
+
+CURRENCY SIGN: &#xA4; => a4
+&#xA4; => a4
+
+CYRILLIC CAPITAL LETTER GHE WITH UPTURN: &#x490; => a5
+&#xA5; => &#xA5;
+
+BROKEN BAR: &#xA6; => a6
+&#xA6; => a6
+
+SECTION SIGN: &#xA7; => a7
+&#xA7; => a7
+
+CYRILLIC CAPITAL LETTER IO: &#x401; => a8
+&#xA8; => &#xA8;
+
+COPYRIGHT SIGN: &#xA9; => a9
+&#xA9; => a9
+
+CYRILLIC CAPITAL LETTER UKRAINIAN IE: &#x404; => aa
+&#xAA; => &#xAA;
+
+LEFT-POINTING DOUBLE ANGLE QUOTATION MARK: &#xAB; => ab
+&#xAB; => ab
+
+NOT SIGN: &#xAC; => ac
+&#xAC; => ac
+
+SOFT HYPHEN: &#xAD; => ad
+&#xAD; => ad
+
+REGISTERED SIGN: &#xAE; => ae
+&#xAE; => ae
+
+CYRILLIC CAPITAL LETTER YI: &#x407; => af
+&#xAF; => &#xAF;
+
+DEGREE SIGN: &#xB0; => b0
+&#xB0; => b0
+
+PLUS-MINUS SIGN: &#xB1; => b1
+&#xB1; => b1
+
+CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I: &#x406; => b2
+&#xB2; => &#xB2;
+
+CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I: &#x456; => b3
+&#xB3; => &#xB3;
+
+CYRILLIC SMALL LETTER GHE WITH UPTURN: &#x491; => b4
+&#xB4; => &#xB4;
+
+MICRO SIGN: &#xB5; => b5
+&#xB5; => b5
+
+PILCROW SIGN: &#xB6; => b6
+&#xB6; => b6
+
+MIDDLE DOT: &#xB7; => b7
+&#xB7; => b7
+
+CYRILLIC SMALL LETTER IO: &#x451; => b8
+&#xB8; => &#xB8;
+
+NUMERO SIGN: &#x2116; => b9
+&#xB9; => &#xB9;
+
+CYRILLIC SMALL LETTER UKRAINIAN IE: &#x454; => ba
+&#xBA; => &#xBA;
+
+RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK: &#xBB; => bb
+&#xBB; => bb
+
+CYRILLIC SMALL LETTER JE: &#x458; => bc
+&#xBC; => &#xBC;
+
+CYRILLIC CAPITAL LETTER DZE: &#x405; => bd
+&#xBD; => &#xBD;
+
+CYRILLIC SMALL LETTER DZE: &#x455; => be
+&#xBE; => &#xBE;
+
+CYRILLIC SMALL LETTER YI: &#x457; => bf
+&#xBF; => &#xBF;
+
+CYRILLIC CAPITAL LETTER A: &#x410; => c0
+&#xC0; => &#xC0;
+
+CYRILLIC CAPITAL LETTER BE: &#x411; => c1
+&#xC1; => &#xC1;
+
+CYRILLIC CAPITAL LETTER VE: &#x412; => c2
+&#xC2; => &#xC2;
+
+CYRILLIC CAPITAL LETTER GHE: &#x413; => c3
+&#xC3; => &#xC3;
+
+CYRILLIC CAPITAL LETTER DE: &#x414; => c4
+&#xC4; => &#xC4;
+
+CYRILLIC CAPITAL LETTER IE: &#x415; => c5
+&#xC5; => &#xC5;
+
+CYRILLIC CAPITAL LETTER ZHE: &#x416; => c6
+&#xC6; => &#xC6;
+
+CYRILLIC CAPITAL LETTER ZE: &#x417; => c7
+&#xC7; => &#xC7;
+
+CYRILLIC CAPITAL LETTER I: &#x418; => c8
+&#xC8; => &#xC8;
+
+CYRILLIC CAPITAL LETTER SHORT I: &#x419; => c9
+&#xC9; => &#xC9;
+
+CYRILLIC CAPITAL LETTER KA: &#x41A; => ca
+&#xCA; => &#xCA;
+
+CYRILLIC CAPITAL LETTER EL: &#x41B; => cb
+&#xCB; => &#xCB;
+
+CYRILLIC CAPITAL LETTER EM: &#x41C; => cc
+&#xCC; => &#xCC;
+
+CYRILLIC CAPITAL LETTER EN: &#x41D; => cd
+&#xCD; => &#xCD;
+
+CYRILLIC CAPITAL LETTER O: &#x41E; => ce
+&#xCE; => &#xCE;
+
+CYRILLIC CAPITAL LETTER PE: &#x41F; => cf
+&#xCF; => &#xCF;
+
+CYRILLIC CAPITAL LETTER ER: &#x420; => d0
+&#xD0; => &#xD0;
+
+CYRILLIC CAPITAL LETTER ES: &#x421; => d1
+&#xD1; => &#xD1;
+
+CYRILLIC CAPITAL LETTER TE: &#x422; => d2
+&#xD2; => &#xD2;
+
+CYRILLIC CAPITAL LETTER U: &#x423; => d3
+&#xD3; => &#xD3;
+
+CYRILLIC CAPITAL LETTER EF: &#x424; => d4
+&#xD4; => &#xD4;
+
+CYRILLIC CAPITAL LETTER HA: &#x425; => d5
+&#xD5; => &#xD5;
+
+CYRILLIC CAPITAL LETTER TSE: &#x426; => d6
+&#xD6; => &#xD6;
+
+CYRILLIC CAPITAL LETTER CHE: &#x427; => d7
+&#xD7; => &#xD7;
+
+CYRILLIC CAPITAL LETTER SHA: &#x428; => d8
+&#xD8; => &#xD8;
+
+CYRILLIC CAPITAL LETTER SHCHA: &#x429; => d9
+&#xD9; => &#xD9;
+
+CYRILLIC CAPITAL LETTER HARD SIGN: &#x42A; => da
+&#xDA; => &#xDA;
+
+CYRILLIC CAPITAL LETTER YERU: &#x42B; => db
+&#xDB; => &#xDB;
+
+CYRILLIC CAPITAL LETTER SOFT SIGN: &#x42C; => dc
+&#xDC; => &#xDC;
+
+CYRILLIC CAPITAL LETTER E: &#x42D; => dd
+&#xDD; => &#xDD;
+
+CYRILLIC CAPITAL LETTER YU: &#x42E; => de
+&#xDE; => &#xDE;
+
+CYRILLIC CAPITAL LETTER YA: &#x42F; => df
+&#xDF; => &#xDF;
+
+CYRILLIC SMALL LETTER A: &#x430; => e0
+&#xE0; => &#xE0;
+
+CYRILLIC SMALL LETTER BE: &#x431; => e1
+&#xE1; => &#xE1;
+
+CYRILLIC SMALL LETTER VE: &#x432; => e2
+&#xE2; => &#xE2;
+
+CYRILLIC SMALL LETTER GHE: &#x433; => e3
+&#xE3; => &#xE3;
+
+CYRILLIC SMALL LETTER DE: &#x434; => e4
+&#xE4; => &#xE4;
+
+CYRILLIC SMALL LETTER IE: &#x435; => e5
+&#xE5; => &#xE5;
+
+CYRILLIC SMALL LETTER ZHE: &#x436; => e6
+&#xE6; => &#xE6;
+
+CYRILLIC SMALL LETTER ZE: &#x437; => e7
+&#xE7; => &#xE7;
+
+CYRILLIC SMALL LETTER I: &#x438; => e8
+&#xE8; => &#xE8;
+
+CYRILLIC SMALL LETTER SHORT I: &#x439; => e9
+&#xE9; => &#xE9;
+
+CYRILLIC SMALL LETTER KA: &#x43A; => ea
+&#xEA; => &#xEA;
+
+CYRILLIC SMALL LETTER EL: &#x43B; => eb
+&#xEB; => &#xEB;
+
+CYRILLIC SMALL LETTER EM: &#x43C; => ec
+&#xEC; => &#xEC;
+
+CYRILLIC SMALL LETTER EN: &#x43D; => ed
+&#xED; => &#xED;
+
+CYRILLIC SMALL LETTER O: &#x43E; => ee
+&#xEE; => &#xEE;
+
+CYRILLIC SMALL LETTER PE: &#x43F; => ef
+&#xEF; => &#xEF;
+
+CYRILLIC SMALL LETTER ER: &#x440; => f0
+&#xF0; => &#xF0;
+
+CYRILLIC SMALL LETTER ES: &#x441; => f1
+&#xF1; => &#xF1;
+
+CYRILLIC SMALL LETTER TE: &#x442; => f2
+&#xF2; => &#xF2;
+
+CYRILLIC SMALL LETTER U: &#x443; => f3
+&#xF3; => &#xF3;
+
+CYRILLIC SMALL LETTER EF: &#x444; => f4
+&#xF4; => &#xF4;
+
+CYRILLIC SMALL LETTER HA: &#x445; => f5
+&#xF5; => &#xF5;
+
+CYRILLIC SMALL LETTER TSE: &#x446; => f6
+&#xF6; => &#xF6;
+
+CYRILLIC SMALL LETTER CHE: &#x447; => f7
+&#xF7; => &#xF7;
+
+CYRILLIC SMALL LETTER SHA: &#x448; => f8
+&#xF8; => &#xF8;
+
+CYRILLIC SMALL LETTER SHCHA: &#x449; => f9
+&#xF9; => &#xF9;
+
+CYRILLIC SMALL LETTER HARD SIGN: &#x44A; => fa
+&#xFA; => &#xFA;
+
+CYRILLIC SMALL LETTER YERU: &#x44B; => fb
+&#xFB; => &#xFB;
+
+CYRILLIC SMALL LETTER SOFT SIGN: &#x44C; => fc
+&#xFC; => &#xFC;
+
+CYRILLIC SMALL LETTER E: &#x44D; => fd
+&#xFD; => &#xFD;
+
+CYRILLIC SMALL LETTER YU: &#x44E; => fe
+&#xFE; => &#xFE;
+
+CYRILLIC SMALL LETTER YA: &#x44F; => ff
+&#xFF; => &#xFF;
+
+
diff --git a/ext/standard/tests/strings/html_entity_decode_win1252.phpt b/ext/standard/tests/strings/html_entity_decode_win1252.phpt
new file mode 100644
index 0000000000..2a7a6981dc
--- /dev/null
+++ b/ext/standard/tests/strings/html_entity_decode_win1252.phpt
@@ -0,0 +1,169 @@
+--TEST--
+Translation of HTML entities for encoding WIN-1252
+--FILE--
+<?php
+$arr = array(
+0x20AC => array(0x80, "EURO SIGN"),
+//0x81 #UNDEFINED
+0x201A => array(0x82, "SINGLE LOW-9 QUOTATION MARK"),
+0x0192 => array(0x83, "LATIN SMALL LETTER F WITH HOOK"),
+0x201E => array(0x84, "DOUBLE LOW-9 QUOTATION MARK"),
+0x2026 => array(0x85, "HORIZONTAL ELLIPSIS"),
+0x2020 => array(0x86, "DAGGER"),
+0x2021 => array(0x87, "DOUBLE DAGGER"),
+0x02C6 => array(0x88, "MODIFIER LETTER CIRCUMFLEX ACCENT"),
+0x2030 => array(0x89, "PER MILLE SIGN"),
+0x0160 => array(0x8A, "LATIN CAPITAL LETTER S WITH CARON"),
+0x2039 => array(0x8B, "SINGLE LEFT-POINTING ANGLE QUOTATION MARK"),
+0x0152 => array(0x8C, "LATIN CAPITAL LIGATURE OE"),
+//0x8D #UNDEFINED
+0x017D => array(0x8E, "LATIN CAPITAL LETTER Z WITH CARON"),
+//0x8F #UNDEFINED
+//0x90 #UNDEFINED
+0x2018 => array(0x91, "LEFT SINGLE QUOTATION MARK"),
+0x2019 => array(0x92, "RIGHT SINGLE QUOTATION MARK"),
+0x201C => array(0x93, "LEFT DOUBLE QUOTATION MARK"),
+0x201D => array(0x94, "RIGHT DOUBLE QUOTATION MARK"),
+0x2022 => array(0x95, "BULLET"),
+0x2013 => array(0x96, "EN DASH"),
+0x2014 => array(0x97, "EM DASH"),
+0x02DC => array(0x98, "SMALL TILDE"),
+0x2122 => array(0x99, "TRADE MARK SIGN"),
+0x0161 => array(0x9A, "LATIN SMALL LETTER S WITH CARON"),
+0x203A => array(0x9B, "SINGLE RIGHT-POINTING ANGLE QUOTATION MARK"),
+0x0153 => array(0x9C, "LATIN SMALL LIGATURE OE"),
+//0x9D #UNDEFINED
+0x017E => array(0x9E, "LATIN SMALL LETTER Z WITH CARON"),
+0x0178 => array(0x9F, "LATIN CAPITAL LETTER Y WITH DIAERESIS"),
+);
+
+$res = html_entity_decode("&#x81;", ENT_QUOTES, 'WINDOWS-1252');
+echo "Special test for &#x81; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+$res = html_entity_decode("&#x8D;", ENT_QUOTES, 'WINDOWS-1252');
+echo "Special test for &#x8D; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+$res = html_entity_decode("&#x8F;", ENT_QUOTES, 'WINDOWS-1252');
+echo "Special test for &#x8F; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+$res = html_entity_decode("&#x90;", ENT_QUOTES, 'WINDOWS-1252');
+echo "Special test for &#x90; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+$res = html_entity_decode("&#x9D;", ENT_QUOTES, 'WINDOWS-1252');
+echo "Special test for &#x9D; (shouldn't decode):\n";
+echo $res,"\n\n";
+
+foreach ($arr as $u => $v) {
+ $ent = sprintf("&#x%X;", $u);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'WINDOWS-1252');
+ $d = unpack("H*", $res);
+ echo sprintf("%s: %s => %s\n", $v[1], $ent, $d[1]);
+
+ $ent = sprintf("&#x%X;", $v[0]);
+ $res = html_entity_decode($ent, ENT_QUOTES, 'WINDOWS-1252');
+ if ($res[0] != "&" || $res[1] != "#")
+ $res = unpack("H*", $res)[1];
+ echo sprintf("%s => %s\n\n", $ent, $res);
+}
+--EXPECT--
+Special test for &#x81; (shouldn't decode):
+&#x81;
+
+Special test for &#x8D; (shouldn't decode):
+&#x8D;
+
+Special test for &#x8F; (shouldn't decode):
+&#x8F;
+
+Special test for &#x90; (shouldn't decode):
+&#x90;
+
+Special test for &#x9D; (shouldn't decode):
+&#x9D;
+
+EURO SIGN: &#x20AC; => 80
+&#x80; => &#x80;
+
+SINGLE LOW-9 QUOTATION MARK: &#x201A; => 82
+&#x82; => &#x82;
+
+LATIN SMALL LETTER F WITH HOOK: &#x192; => 83
+&#x83; => &#x83;
+
+DOUBLE LOW-9 QUOTATION MARK: &#x201E; => 84
+&#x84; => &#x84;
+
+HORIZONTAL ELLIPSIS: &#x2026; => 85
+&#x85; => &#x85;
+
+DAGGER: &#x2020; => 86
+&#x86; => &#x86;
+
+DOUBLE DAGGER: &#x2021; => 87
+&#x87; => &#x87;
+
+MODIFIER LETTER CIRCUMFLEX ACCENT: &#x2C6; => 88
+&#x88; => &#x88;
+
+PER MILLE SIGN: &#x2030; => 89
+&#x89; => &#x89;
+
+LATIN CAPITAL LETTER S WITH CARON: &#x160; => 8a
+&#x8A; => &#x8A;
+
+SINGLE LEFT-POINTING ANGLE QUOTATION MARK: &#x2039; => 8b
+&#x8B; => &#x8B;
+
+LATIN CAPITAL LIGATURE OE: &#x152; => 8c
+&#x8C; => &#x8C;
+
+LATIN CAPITAL LETTER Z WITH CARON: &#x17D; => 8e
+&#x8E; => &#x8E;
+
+LEFT SINGLE QUOTATION MARK: &#x2018; => 91
+&#x91; => &#x91;
+
+RIGHT SINGLE QUOTATION MARK: &#x2019; => 92
+&#x92; => &#x92;
+
+LEFT DOUBLE QUOTATION MARK: &#x201C; => 93
+&#x93; => &#x93;
+
+RIGHT DOUBLE QUOTATION MARK: &#x201D; => 94
+&#x94; => &#x94;
+
+BULLET: &#x2022; => 95
+&#x95; => &#x95;
+
+EN DASH: &#x2013; => 96
+&#x96; => &#x96;
+
+EM DASH: &#x2014; => 97
+&#x97; => &#x97;
+
+SMALL TILDE: &#x2DC; => 98
+&#x98; => &#x98;
+
+TRADE MARK SIGN: &#x2122; => 99
+&#x99; => &#x99;
+
+LATIN SMALL LETTER S WITH CARON: &#x161; => 9a
+&#x9A; => &#x9A;
+
+SINGLE RIGHT-POINTING ANGLE QUOTATION MARK: &#x203A; => 9b
+&#x9B; => &#x9B;
+
+LATIN SMALL LIGATURE OE: &#x153; => 9c
+&#x9C; => &#x9C;
+
+LATIN SMALL LETTER Z WITH CARON: &#x17E; => 9e
+&#x9E; => &#x9E;
+
+LATIN CAPITAL LETTER Y WITH DIAERESIS: &#x178; => 9f
+&#x9F; => &#x9F;
+
+
diff --git a/ext/standard/tests/strings/htmlentities.phpt b/ext/standard/tests/strings/htmlentities.phpt
index 743651ecad..f2e107a735 100644
--- a/ext/standard/tests/strings/htmlentities.phpt
+++ b/ext/standard/tests/strings/htmlentities.phpt
@@ -1,16 +1,16 @@
--TEST--
-HTML entities
+HTML entities of ISO-8859 chars
--INI--
output_handler=
--FILE--
<?php
setlocale (LC_CTYPE, "C");
-$sc_encoded = htmlspecialchars ("<>\"&åÄ\n");
+$sc_encoded = htmlspecialchars ("<>\"&åÄ\n",ENT_COMPAT,"ISO-8859-1");
echo $sc_encoded;
-$ent_encoded = htmlentities ("<>\"&åÄ\n");
+$ent_encoded = htmlentities ("<>\"&åÄ\n",ENT_COMPAT,"ISO-8859-1");
echo $ent_encoded;
-echo html_entity_decode($sc_encoded);
-echo html_entity_decode($ent_encoded);
+echo html_entity_decode($sc_encoded,ENT_COMPAT,"ISO-8859-1");
+echo html_entity_decode($ent_encoded,ENT_COMPAT,"ISO-8859-1");
?>
--EXPECT--
&lt;&gt;&quot;&amp;åÄ
diff --git a/ext/standard/tests/strings/htmlentities04.phpt b/ext/standard/tests/strings/htmlentities04.phpt
index 565c11bbc8..2501ff092c 100644
--- a/ext/standard/tests/strings/htmlentities04.phpt
+++ b/ext/standard/tests/strings/htmlentities04.phpt
@@ -16,5 +16,6 @@ mbstring.internal_encoding=pass
setlocale( LC_CTYPE, "ja_JP.EUC-JP", "ja_JP.eucJP" );
var_dump(htmlentities("\xa1\xa2\xa1\xa3\xa1\xa4", ENT_QUOTES, ''));
?>
---EXPECT--
+--EXPECTF--
+Strict Standards: htmlentities(): Only basic entities substitution is supported for multi-byte encodings other than UTF-8; functionality is equivalent to htmlspecialchars in %s line %d
string(6) "¡¢¡£¡¤"
diff --git a/ext/standard/tests/strings/htmlentities05.phpt b/ext/standard/tests/strings/htmlentities05.phpt
index 779cf289b0..7f8adb6b99 100644
--- a/ext/standard/tests/strings/htmlentities05.phpt
+++ b/ext/standard/tests/strings/htmlentities05.phpt
@@ -2,19 +2,12 @@
htmlentities() test 5 (mbstring / cp1252)
--INI--
output_handler=
+mbstring.internal_encoding=cp1252
--SKIPIF--
<?php
extension_loaded("mbstring") or die("skip mbstring not available\n");
- mb_internal_encoding('cp1252');
- $php_errormsg = NULL;
- @htmlentities("\x82\x86\x99\x9f", ENT_QUOTES, '');
- if ($php_errormsg) {
- die("skip cp1252 chracter set is not supported on this platform.\n");
- }
-?>
--FILE--
<?php
- mb_internal_encoding('cp1252');
print mb_internal_encoding()."\n";
var_dump(htmlentities("\x82\x86\x99\x9f", ENT_QUOTES, ''));
var_dump(htmlentities("\x80\xa2\xa3\xa4\xa5", ENT_QUOTES, ''));
diff --git a/ext/standard/tests/strings/htmlentities06.phpt b/ext/standard/tests/strings/htmlentities06.phpt
index 44d1466da9..4cc68d233f 100644
--- a/ext/standard/tests/strings/htmlentities06.phpt
+++ b/ext/standard/tests/strings/htmlentities06.phpt
@@ -2,15 +2,10 @@
htmlentities() test 6 (mbstring / ISO-8859-15)
--INI--
output_handler=
+mbstring.internal_encoding=ISO-8859-15
--SKIPIF--
<?php
extension_loaded("mbstring") or die("skip mbstring not available\n");
- @mb_internal_encoding('ISO-8859-15');
- @htmlentities("\xbc\xbd\xbe", ENT_QUOTES, '');
- if (@$php_errormsg) {
- die("skip ISO-8859-15 chracter set is not supported on this platform.\n");
- }
-?>
--FILE--
<?php
mb_internal_encoding('ISO-8859-15');
diff --git a/ext/standard/tests/strings/htmlentities07.phpt b/ext/standard/tests/strings/htmlentities07.phpt
index efd06f08ad..144734c12e 100644
--- a/ext/standard/tests/strings/htmlentities07.phpt
+++ b/ext/standard/tests/strings/htmlentities07.phpt
@@ -2,16 +2,10 @@
htmlentities() test 7 (mbstring / ISO-8859-1)
--INI--
output_handler=
+mbstring.internal_encoding=ISO-8859-1
--SKIPIF--
<?php
extension_loaded("mbstring") or die("skip mbstring not available\n");
- mb_internal_encoding('ISO-8859-1');
- $php_errormsg = NULL;
- @htmlentities("\xe4\xf6\xfc", ENT_QUOTES, '');
- if ($php_errormsg) {
- die("skip ISO-8859-1 chracter set is not supported on this platform.\n");
- }
-?>
--FILE--
<?php
mb_internal_encoding('ISO-8859-1');
diff --git a/ext/standard/tests/strings/htmlentities08.phpt b/ext/standard/tests/strings/htmlentities08.phpt
index 0f8f912f27..1f6dc90fcb 100644
--- a/ext/standard/tests/strings/htmlentities08.phpt
+++ b/ext/standard/tests/strings/htmlentities08.phpt
@@ -2,16 +2,11 @@
htmlentities() test 8 (mbstring / EUC-JP)
--INI--
output_handler=
+error_reporting=~E_STRICT
+mbstring.internal_encoding=EUC-JP
--SKIPIF--
<?php
extension_loaded("mbstring") or die("skip mbstring not available\n");
- mb_internal_encoding('EUC-JP');
- $php_errormsg = NULL;
- @htmlentities("\xa1\xa2\xa1\xa3\xa1\xa4", ENT_QUOTES, '');
- if ($php_errormsg) {
- die("skip EUC-JP chracter set is not supported on this platform.\n");
- }
-?>
--FILE--
<?php
mb_internal_encoding('EUC-JP');
diff --git a/ext/standard/tests/strings/htmlentities09.phpt b/ext/standard/tests/strings/htmlentities09.phpt
index 9127a71d06..c80a77d40f 100644
--- a/ext/standard/tests/strings/htmlentities09.phpt
+++ b/ext/standard/tests/strings/htmlentities09.phpt
@@ -2,16 +2,11 @@
htmlentities() test 9 (mbstring / Shift_JIS)
--INI--
output_handler=
+error_reporting=~E_STRICT
+mbstring.internal_encoding=Shift_JIS
--SKIPIF--
<?php
extension_loaded("mbstring") or die("skip mbstring not available\n");
- mb_internal_encoding('Shift_JIS');
- $php_errormsg = NULL;
- @htmlentities("\x81\x41\x81\x42\x81\x43", ENT_QUOTES, '');
- if ($php_errormsg) {
- die("skip Shift_JIS chracter set is not supported on this platform.\n");
- }
-?>
--FILE--
<?php
mb_internal_encoding('Shift_JIS');
diff --git a/ext/standard/tests/strings/htmlentities13.phpt b/ext/standard/tests/strings/htmlentities13.phpt
index 2c559916e9..769c77fde9 100644
--- a/ext/standard/tests/strings/htmlentities13.phpt
+++ b/ext/standard/tests/strings/htmlentities13.phpt
@@ -4,11 +4,14 @@ htmlentities() test 13 (default_charset / EUC-JP)
output_handler=
mbstring.internal_encoding=pass
default_charset=EUC-JP
+filter.default=unsafe_raw
--FILE--
<?php
print ini_get('default_charset')."\n";
var_dump(htmlentities("\xa1\xa2\xa1\xa3\xa1\xa4", ENT_QUOTES, ''));
?>
---EXPECT--
+--EXPECTF--
EUC-JP
+
+Strict Standards: htmlentities(): Only basic entities substitution is supported for multi-byte encodings other than UTF-8; functionality is equivalent to htmlspecialchars in %s on line %d
string(6) "¡¢¡£¡¤"
diff --git a/ext/standard/tests/strings/htmlentities14.phpt b/ext/standard/tests/strings/htmlentities14.phpt
index 9190d26515..0928f08488 100644
--- a/ext/standard/tests/strings/htmlentities14.phpt
+++ b/ext/standard/tests/strings/htmlentities14.phpt
@@ -4,11 +4,14 @@ htmlentities() test 14 (default_charset / Shift_JIS)
output_handler=
mbstring.internal_encoding=pass
default_charset=Shift_JIS
+filter.default=unsafe_raw
--FILE--
<?php
print ini_get('default_charset')."\n";
var_dump(htmlentities("\x81\x41\x81\x42\x81\x43", ENT_QUOTES, ''));
?>
---EXPECT--
+--EXPECTF--
Shift_JIS
+
+Strict Standards: htmlentities(): Only basic entities substitution is supported for multi-byte encodings other than UTF-8; functionality is equivalent to htmlspecialchars in %s on line %d
string(6) "ABC"
diff --git a/ext/standard/tests/strings/htmlentities15.phpt b/ext/standard/tests/strings/htmlentities15.phpt
index f45be118c3..e5729f9976 100644
--- a/ext/standard/tests/strings/htmlentities15.phpt
+++ b/ext/standard/tests/strings/htmlentities15.phpt
@@ -11,6 +11,9 @@ if (!$result || preg_match('/koi8/i', setlocale(LC_CTYPE, 0)) == 0) {
die("skip setlocale() failed\n");
}
?>
+--DESCRIPTION--
+As of PHP 5.4, htmlentities() no longer makes replacements with numerical
+entities. Hence, for this input there's no substitution.
--FILE--
<?php
setlocale(LC_CTYPE, "ru_RU.koi8r", "ru_RU.KOI8-R");
@@ -19,4 +22,4 @@ var_dump($str, htmlentities($str, ENT_QUOTES, ''));
?>
--EXPECT--
string(9) "ÒÏÓËÏÛÎÙÊ"
-string(63) "&#1088;&#1086;&#1089;&#1082;&#1086;&#1096;&#1085;&#1099;&#1081;"
+string(9) "ÒÏÓËÏÛÎÙÊ"
diff --git a/ext/standard/tests/strings/htmlentities16.phpt b/ext/standard/tests/strings/htmlentities16.phpt
index 438b0e490b..ed54670520 100644
--- a/ext/standard/tests/strings/htmlentities16.phpt
+++ b/ext/standard/tests/strings/htmlentities16.phpt
@@ -2,22 +2,20 @@
htmlentities() test 16 (mbstring / cp1251)
--INI--
output_handler=
+mbstring.internal_encoding=cp1251
--SKIPIF--
<?php
extension_loaded("mbstring") or die("skip mbstring not available\n");
- if (!@mb_internal_encoding('cp1251') ||
- @htmlentities("\x88\xa9\xd2\xcf\xd3\xcb\xcf\xdb\xce\xd9\xca", ENT_QUOTES, '') == '') {
- die("skip cp1251 character set is not available in this build.\n");
- }
?>
--FILE--
<?php
-mb_internal_encoding('cp1251');
$str = "\x88\xa9\xf0\xee\xf1\xea\xee\xf8\xed\xfb\xe9";
-var_dump(bin2hex($str), htmlentities($str, ENT_QUOTES, ''));
+var_dump(bin2hex($str), bin2hex(htmlentities($str, ENT_QUOTES, '')));
+var_dump(htmlentities($str, ENT_QUOTES | ENT_HTML5, ''));
?>
===DONE===
--EXPECT--
string(22) "88a9f0eef1eaeef8edfbe9"
-string(75) "&euro;&copy;&#1088;&#1086;&#1089;&#1082;&#1086;&#1096;&#1085;&#1099;&#1081;"
+string(42) "266575726f3b26636f70793bf0eef1eaeef8edfbe9"
+string(58) "&euro;&copy;&rcy;&ocy;&scy;&kcy;&ocy;&shcy;&ncy;&ycy;&jcy;"
===DONE===
diff --git a/ext/standard/tests/strings/htmlentities18.phpt b/ext/standard/tests/strings/htmlentities18.phpt
index 8970be8a08..d7bd2302c1 100644
--- a/ext/standard/tests/strings/htmlentities18.phpt
+++ b/ext/standard/tests/strings/htmlentities18.phpt
@@ -29,8 +29,8 @@ string(33) "test&#043;s &amp; some more &#68;"
string(33) "test&#043;s &amp; some more &#68;"
string(34) "test&#x2b;s &amp; some more &#X44;"
string(34) "test&#x2b;s &amp; some more &#X44;"
-string(35) "&; &amp;amp &amp;#a; &9; &amp;#xyz;"
-string(35) "&; &amp;amp &amp;#a; &9; &amp;#xyz;"
+string(43) "&amp;; &amp;amp &amp;#a; &amp;9; &amp;#xyz;"
+string(43) "&amp;; &amp;amp &amp;#a; &amp;9; &amp;#xyz;"
string(32) "&amp;kffjadfdhsjfhjasdhffasdfas;"
string(32) "&amp;kffjadfdhsjfhjasdhffasdfas;"
string(16) "&amp;#8787978789"
diff --git a/ext/standard/tests/strings/htmlentities19.phpt b/ext/standard/tests/strings/htmlentities19.phpt
new file mode 100644
index 0000000000..a90358c613
--- /dev/null
+++ b/ext/standard/tests/strings/htmlentities19.phpt
@@ -0,0 +1,30 @@
+--TEST--
+htmlentities() / htmlspecialchars() ENT_SUBSTITUTE
+--FILE--
+<?php
+$tests = array(
+ "\x41\xC2\x3E\x42", // Unicode TR #36, 3.1.1; do not consume valid successor bytes
+ "\xE3\x80\x22", // Unicode TR #36, 3.6.1; use strategy #2
+ "\x41\x98\xBA\x42\xE2\x98\x43\xE2\x98\xBA\xE2\x98", // example from HTML5, section 2.4
+);
+
+foreach ($tests as $test) {
+ $a = htmlentities($test, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
+ var_dump($a, bin2hex($a));
+ $a = htmlspecialchars($test, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
+ var_dump($a, bin2hex($a));
+}
+?>
+--EXPECT--
+string(9) "A�&gt;B"
+string(18) "41efbfbd2667743b42"
+string(9) "A�&gt;B"
+string(18) "41efbfbd2667743b42"
+string(9) "�&quot;"
+string(18) "efbfbd2671756f743b"
+string(9) "�&quot;"
+string(18) "efbfbd2671756f743b"
+string(18) "A��B�C☺�"
+string(36) "41efbfbdefbfbd42efbfbd43e298baefbfbd"
+string(18) "A��B�C☺�"
+string(36) "41efbfbdefbfbd42efbfbd43e298baefbfbd"
diff --git a/ext/standard/tests/strings/htmlentities20.phpt b/ext/standard/tests/strings/htmlentities20.phpt
new file mode 100644
index 0000000000..92c996bcb4
--- /dev/null
+++ b/ext/standard/tests/strings/htmlentities20.phpt
@@ -0,0 +1,199 @@
+--TEST--
+htmlentities() / htmlspecialchars() ENT_DISALLOWED
+--FILE--
+<?php
+function codepoint_to_utf8($k) {
+ if ($k < 0x80) {
+ $retval = pack('C', $k);
+ } else if ($k < 0x800) {
+ $retval = pack('C2',
+ 0xc0 | ($k >> 6),
+ 0x80 | ($k & 0x3f));
+ } else if ($k < 0x10000) {
+ $retval = pack('C3',
+ 0xe0 | ($k >> 12),
+ 0x80 | (($k >> 6) & 0x3f),
+ 0x80 | ($k & 0x3f));
+ } else {
+ $retval = pack('C4',
+ 0xf0 | ($k >> 18),
+ 0x80 | (($k >> 12) & 0x3f),
+ 0x80 | (($k >> 6) & 0x3f),
+ 0x80 | ($k & 0x3f));
+ }
+ return $retval;
+}
+
+$tests = array(
+ 0x00, //C0
+ 0x01,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+ 0x0D,
+ 0x0E,
+ 0x1F,
+ 0x20, //allowed always
+ 0x7F, //DEL
+ 0x80, //C1
+ 0x9F,
+ 0xA0, //allowed always
+ 0xD7FF, //surrogates
+ 0xD800,
+ 0xDFFF,
+ 0xE000, //allowed always
+ 0xFFFE, //nonchar
+ 0xFFFF,
+ 0xFDCF, //allowed always
+ 0xFDD0, //nonchar
+ 0xFDEF,
+ 0xFDF0, //allowed always
+ 0x2FFFE, //nonchar
+ 0x2FFFF,
+);
+$tests2 = array_map('codepoint_to_utf8', $tests);
+
+$subchr = codepoint_to_utf8(0xFFFD);
+
+function test($flag) {
+ global $tests, $tests2;
+ $i = -1;
+ foreach ($tests2 as $test) {
+ $i++;
+ $a = htmlentities($test, $flag | ENT_DISALLOWED, "UTF-8");
+ $b = htmlspecialchars($test, $flag | ENT_DISALLOWED, "UTF-8");
+ if ($a == "" && $b == "") { echo sprintf("%05X", $tests[$i]), ": INVALID SEQUENCE\n"; continue; }
+ echo sprintf("%05X", $tests[$i]), ": ", bin2hex($a), " ", bin2hex($b), "\n";
+ }
+}
+
+echo "*** Testing HTML 4.01 ***\n";
+
+test(ENT_HTML401);
+
+echo "\n*** Testing XHTML 1.0 ***\n";
+
+test(ENT_XHTML);
+
+echo "\n*** Testing HTML 5 ***\n";
+
+test(ENT_HTML5);
+
+echo "\n*** Testing XML 1.0 ***\n";
+
+test(ENT_XML1);
+
+?>
+--EXPECT--
+*** Testing HTML 4.01 ***
+00000: efbfbd efbfbd
+00001: efbfbd efbfbd
+00009: 09 09
+0000A: 0a 0a
+0000B: efbfbd efbfbd
+0000C: efbfbd efbfbd
+0000D: 0d 0d
+0000E: efbfbd efbfbd
+0001F: efbfbd efbfbd
+00020: 20 20
+0007F: efbfbd efbfbd
+00080: efbfbd efbfbd
+0009F: efbfbd efbfbd
+000A0: 266e6273703b c2a0
+0D7FF: ed9fbf ed9fbf
+0D800: INVALID SEQUENCE
+0DFFF: INVALID SEQUENCE
+0E000: ee8080 ee8080
+0FFFE: efbfbe efbfbe
+0FFFF: efbfbf efbfbf
+0FDCF: efb78f efb78f
+0FDD0: efb790 efb790
+0FDEF: efb7af efb7af
+0FDF0: efb7b0 efb7b0
+2FFFE: f0afbfbe f0afbfbe
+2FFFF: f0afbfbf f0afbfbf
+
+*** Testing XHTML 1.0 ***
+00000: efbfbd efbfbd
+00001: efbfbd efbfbd
+00009: 09 09
+0000A: 0a 0a
+0000B: efbfbd efbfbd
+0000C: efbfbd efbfbd
+0000D: 0d 0d
+0000E: efbfbd efbfbd
+0001F: efbfbd efbfbd
+00020: 20 20
+0007F: 7f 7f
+00080: c280 c280
+0009F: c29f c29f
+000A0: 266e6273703b c2a0
+0D7FF: ed9fbf ed9fbf
+0D800: INVALID SEQUENCE
+0DFFF: INVALID SEQUENCE
+0E000: ee8080 ee8080
+0FFFE: efbfbd efbfbd
+0FFFF: efbfbd efbfbd
+0FDCF: efb78f efb78f
+0FDD0: efb790 efb790
+0FDEF: efb7af efb7af
+0FDF0: efb7b0 efb7b0
+2FFFE: f0afbfbe f0afbfbe
+2FFFF: f0afbfbf f0afbfbf
+
+*** Testing HTML 5 ***
+00000: efbfbd efbfbd
+00001: efbfbd efbfbd
+00009: 265461623b 09
+0000A: 264e65774c696e653b 0a
+0000B: efbfbd efbfbd
+0000C: 0c 0c
+0000D: 0d 0d
+0000E: efbfbd efbfbd
+0001F: efbfbd efbfbd
+00020: 20 20
+0007F: efbfbd efbfbd
+00080: efbfbd efbfbd
+0009F: efbfbd efbfbd
+000A0: 266e6273703b c2a0
+0D7FF: ed9fbf ed9fbf
+0D800: INVALID SEQUENCE
+0DFFF: INVALID SEQUENCE
+0E000: ee8080 ee8080
+0FFFE: efbfbd efbfbd
+0FFFF: efbfbd efbfbd
+0FDCF: efb78f efb78f
+0FDD0: efbfbd efbfbd
+0FDEF: efbfbd efbfbd
+0FDF0: efb7b0 efb7b0
+2FFFE: efbfbd efbfbd
+2FFFF: efbfbd efbfbd
+
+*** Testing XML 1.0 ***
+00000: efbfbd efbfbd
+00001: efbfbd efbfbd
+00009: 09 09
+0000A: 0a 0a
+0000B: efbfbd efbfbd
+0000C: efbfbd efbfbd
+0000D: 0d 0d
+0000E: efbfbd efbfbd
+0001F: efbfbd efbfbd
+00020: 20 20
+0007F: 7f 7f
+00080: c280 c280
+0009F: c29f c29f
+000A0: c2a0 c2a0
+0D7FF: ed9fbf ed9fbf
+0D800: INVALID SEQUENCE
+0DFFF: INVALID SEQUENCE
+0E000: ee8080 ee8080
+0FFFE: efbfbd efbfbd
+0FFFF: efbfbd efbfbd
+0FDCF: efb78f efb78f
+0FDD0: efb790 efb790
+0FDEF: efb7af efb7af
+0FDF0: efb7b0 efb7b0
+2FFFE: f0afbfbe f0afbfbe
+2FFFF: f0afbfbf f0afbfbf
diff --git a/ext/standard/tests/strings/htmlentities21.phpt b/ext/standard/tests/strings/htmlentities21.phpt
new file mode 100644
index 0000000000..f34ff26df0
--- /dev/null
+++ b/ext/standard/tests/strings/htmlentities21.phpt
@@ -0,0 +1,198 @@
+--TEST--
+htmlentities() / htmlspecialchars() ENT_DISALLOWED charset variation
+--FILE--
+<?php
+$tests = array(
+ 0x00, //C0
+ 0x01,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+ 0x0D,
+ 0x0E,
+ 0x1F,
+ 0x20, //allowed always
+ 0x7F, //DEL
+ 0x80, //C1
+ 0x9F,
+ 0xA0, //allowed always
+);
+
+function test($flag, $charset) {
+ global $tests;
+ $i = -1;
+ error_reporting(-1 & ~E_STRICT);
+ foreach ($tests as $test) {
+ $test = chr($test);
+ $i++;
+ $a = htmlentities($test, $flag | ENT_DISALLOWED, $charset);
+ $b = htmlspecialchars($test, $flag | ENT_DISALLOWED, $charset);
+ if ($a == "" && $b == "") { echo sprintf("%05X", $tests[$i]), ": INVALID SEQUENCE\n"; continue; }
+ echo sprintf("%05X", $tests[$i]), ": ", bin2hex($a), " ", bin2hex($b), "\n";
+ }
+ error_reporting(-1);
+}
+
+echo "*** Testing HTML 4.01/Windows-1251 ***\n";
+
+test(ENT_HTML401, "Windows-1251");
+
+echo "\n*** Testing XHTML 1.0/Windows-1251 ***\n";
+
+test(ENT_XHTML, "Windows-1251");
+
+echo "\n*** Testing HTML 5/Windows-1251 ***\n";
+
+test(ENT_HTML5, "Windows-1251");
+
+echo "\n*** Testing XML 1.0/Windows-1251 ***\n";
+
+test(ENT_XML1, "Windows-1251");
+
+echo "\n*** Testing HTML 4.01/SJIS ***\n";
+
+test(ENT_HTML401, "SJIS");
+
+echo "\n*** Testing XHTML 1.0/SJIS ***\n";
+
+test(ENT_XHTML, "SJIS");
+
+echo "\n*** Testing HTML 5/SJIS ***\n";
+
+test(ENT_HTML5, "SJIS");
+
+echo "\n*** Testing XML 1.0/SJIS ***\n";
+
+test(ENT_XML1, "SJIS");
+
+
+?>
+--EXPECT--
+*** Testing HTML 4.01/Windows-1251 ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 262378464646443b 262378464646443b
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 262378464646443b 7f
+00080: 80 80
+0009F: 9f 9f
+000A0: 266e6273703b a0
+
+*** Testing XHTML 1.0/Windows-1251 ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 262378464646443b 262378464646443b
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 7f 7f
+00080: 80 80
+0009F: 9f 9f
+000A0: 266e6273703b a0
+
+*** Testing HTML 5/Windows-1251 ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 265461623b 09
+0000A: 264e65774c696e653b 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 0c 0c
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 262378464646443b 7f
+00080: 26444a63793b 80
+0009F: 26647a63793b 9f
+000A0: 266e6273703b a0
+
+*** Testing XML 1.0/Windows-1251 ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 262378464646443b 262378464646443b
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 7f 7f
+00080: 80 80
+0009F: 9f 9f
+000A0: a0 a0
+
+*** Testing HTML 4.01/SJIS ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 262378464646443b 262378464646443b
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 7f 7f
+00080: INVALID SEQUENCE
+0009F: INVALID SEQUENCE
+000A0: INVALID SEQUENCE
+
+*** Testing XHTML 1.0/SJIS ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 262378464646443b 262378464646443b
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 7f 7f
+00080: INVALID SEQUENCE
+0009F: INVALID SEQUENCE
+000A0: INVALID SEQUENCE
+
+*** Testing HTML 5/SJIS ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 0c 0c
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 7f 7f
+00080: INVALID SEQUENCE
+0009F: INVALID SEQUENCE
+000A0: INVALID SEQUENCE
+
+*** Testing XML 1.0/SJIS ***
+00000: 262378464646443b 262378464646443b
+00001: 262378464646443b 262378464646443b
+00009: 09 09
+0000A: 0a 0a
+0000B: 262378464646443b 262378464646443b
+0000C: 262378464646443b 262378464646443b
+0000D: 0d 0d
+0000E: 262378464646443b 262378464646443b
+0001F: 262378464646443b 262378464646443b
+00020: 20 20
+0007F: 7f 7f
+00080: INVALID SEQUENCE
+0009F: INVALID SEQUENCE
+000A0: INVALID SEQUENCE
diff --git a/ext/standard/tests/strings/htmlentities22.phpt b/ext/standard/tests/strings/htmlentities22.phpt
new file mode 100644
index 0000000000..f11982044d
--- /dev/null
+++ b/ext/standard/tests/strings/htmlentities22.phpt
@@ -0,0 +1,283 @@
+--TEST--
+htmlentities() / htmlspecialchars() ENT_DISALLOWED with entities and no double encode
+--FILE--
+<?php
+$tests = array(
+ "&#0;", //C0
+ "&#1;",
+ "&#x09;",
+ "&#x0A;",
+ "&#x0B;",
+ "&#x0C;",
+ "&#x0D;", //note that HTML5 is unique in that it forbids this entity, but allows a literal U+0D
+ "&#x0E;",
+ "&#x1F;",
+ "&#x20;", //allowed always
+ "&#x7F;", //DEL
+ "&#x80;", //C1
+ "&#x9F;",
+ "&#xA0;", //allowed always
+ "&#xD7FF;", //surrogates
+ "&#xD800;",
+ "&#xDFFF;",
+ "&#xE000;", //allowed always
+ "&#xFFFE;", //nonchar
+ "&#xFFFF;",
+ "&#xFDCF;", //allowed always
+ "&#xFDD0;", //nonchar
+ "&#xFDEF;",
+ "&#xFDF0;", //allowed always
+ "&#x2FFFE;", //nonchar
+ "&#x2FFFF;",
+ "&#x110000;", //bad reference
+);
+
+function test($flag, $flag2=ENT_DISALLOWED, $charset="UTF-8") {
+ global $tests;
+ $i = -1;
+ error_reporting(-1 & ~E_STRICT);
+ foreach ($tests as $test) {
+ $i++;
+ $a = htmlentities($test, $flag | $flag2, $charset, FALSE);
+ $b = htmlspecialchars($test, $flag | $flag2, $charset, FALSE);
+
+ if ($a == $b)
+ echo sprintf("%s\t%s", $test, $a==$test?"NOT CHANGED":"CHANGED"), "\n";
+ else
+ echo sprintf("%s\tCHANGED (%s, %s)", $test, $a, $b), "\n";
+ }
+ error_reporting(-1);
+}
+
+echo "*** Testing HTML 4.01 ***\n";
+
+test(ENT_HTML401);
+
+echo "\n*** Testing XHTML 1.0 ***\n";
+
+test(ENT_XHTML);
+
+echo "\n*** Testing HTML 5 ***\n";
+
+test(ENT_HTML5);
+
+echo "\n*** Testing XML 1.0 ***\n";
+
+test(ENT_XML1);
+
+echo "\n*** Testing 5 without the flag ***\n";
+
+test(ENT_HTML5, 0);
+
+echo "\n*** Testing HTML 5 with another single-byte encoding ***\n";
+
+test(ENT_HTML5, ENT_DISALLOWED, "Windows-1251");
+
+echo "\n*** Testing HTML 5 with another multibyte-byte encoding ***\n";
+
+test(ENT_HTML5, ENT_DISALLOWED, "SJIS");
+
+?>
+--EXPECT--
+*** Testing HTML 4.01 ***
+&#0; NOT CHANGED
+&#1; NOT CHANGED
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; NOT CHANGED
+&#x0C; NOT CHANGED
+&#x0D; NOT CHANGED
+&#x0E; NOT CHANGED
+&#x1F; NOT CHANGED
+&#x20; NOT CHANGED
+&#x7F; NOT CHANGED
+&#x80; NOT CHANGED
+&#x9F; NOT CHANGED
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; NOT CHANGED
+&#xDFFF; NOT CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; NOT CHANGED
+&#xFFFF; NOT CHANGED
+&#xFDCF; NOT CHANGED
+&#xFDD0; NOT CHANGED
+&#xFDEF; NOT CHANGED
+&#xFDF0; NOT CHANGED
+&#x2FFFE; NOT CHANGED
+&#x2FFFF; NOT CHANGED
+&#x110000; CHANGED
+
+*** Testing XHTML 1.0 ***
+&#0; CHANGED
+&#1; CHANGED
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; CHANGED
+&#x0C; CHANGED
+&#x0D; NOT CHANGED
+&#x0E; CHANGED
+&#x1F; CHANGED
+&#x20; NOT CHANGED
+&#x7F; NOT CHANGED
+&#x80; NOT CHANGED
+&#x9F; NOT CHANGED
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; CHANGED
+&#xDFFF; CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; CHANGED
+&#xFFFF; CHANGED
+&#xFDCF; NOT CHANGED
+&#xFDD0; NOT CHANGED
+&#xFDEF; NOT CHANGED
+&#xFDF0; NOT CHANGED
+&#x2FFFE; NOT CHANGED
+&#x2FFFF; NOT CHANGED
+&#x110000; CHANGED
+
+*** Testing HTML 5 ***
+&#0; CHANGED (&amp;&num;0&semi;, &amp;#0;)
+&#1; CHANGED (&amp;&num;1&semi;, &amp;#1;)
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; CHANGED (&amp;&num;x0B&semi;, &amp;#x0B;)
+&#x0C; NOT CHANGED
+&#x0D; CHANGED (&amp;&num;x0D&semi;, &amp;#x0D;)
+&#x0E; CHANGED (&amp;&num;x0E&semi;, &amp;#x0E;)
+&#x1F; CHANGED (&amp;&num;x1F&semi;, &amp;#x1F;)
+&#x20; NOT CHANGED
+&#x7F; CHANGED (&amp;&num;x7F&semi;, &amp;#x7F;)
+&#x80; CHANGED (&amp;&num;x80&semi;, &amp;#x80;)
+&#x9F; CHANGED (&amp;&num;x9F&semi;, &amp;#x9F;)
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; NOT CHANGED
+&#xDFFF; NOT CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; CHANGED (&amp;&num;xFFFE&semi;, &amp;#xFFFE;)
+&#xFFFF; CHANGED (&amp;&num;xFFFF&semi;, &amp;#xFFFF;)
+&#xFDCF; NOT CHANGED
+&#xFDD0; CHANGED (&amp;&num;xFDD0&semi;, &amp;#xFDD0;)
+&#xFDEF; CHANGED (&amp;&num;xFDEF&semi;, &amp;#xFDEF;)
+&#xFDF0; NOT CHANGED
+&#x2FFFE; CHANGED (&amp;&num;x2FFFE&semi;, &amp;#x2FFFE;)
+&#x2FFFF; CHANGED (&amp;&num;x2FFFF&semi;, &amp;#x2FFFF;)
+&#x110000; CHANGED (&amp;&num;x110000&semi;, &amp;#x110000;)
+
+*** Testing XML 1.0 ***
+&#0; CHANGED
+&#1; CHANGED
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; CHANGED
+&#x0C; CHANGED
+&#x0D; NOT CHANGED
+&#x0E; CHANGED
+&#x1F; CHANGED
+&#x20; NOT CHANGED
+&#x7F; NOT CHANGED
+&#x80; NOT CHANGED
+&#x9F; NOT CHANGED
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; CHANGED
+&#xDFFF; CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; CHANGED
+&#xFFFF; CHANGED
+&#xFDCF; NOT CHANGED
+&#xFDD0; NOT CHANGED
+&#xFDEF; NOT CHANGED
+&#xFDF0; NOT CHANGED
+&#x2FFFE; NOT CHANGED
+&#x2FFFF; NOT CHANGED
+&#x110000; CHANGED
+
+*** Testing 5 without the flag ***
+&#0; NOT CHANGED
+&#1; NOT CHANGED
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; NOT CHANGED
+&#x0C; NOT CHANGED
+&#x0D; NOT CHANGED
+&#x0E; NOT CHANGED
+&#x1F; NOT CHANGED
+&#x20; NOT CHANGED
+&#x7F; NOT CHANGED
+&#x80; NOT CHANGED
+&#x9F; NOT CHANGED
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; NOT CHANGED
+&#xDFFF; NOT CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; NOT CHANGED
+&#xFFFF; NOT CHANGED
+&#xFDCF; NOT CHANGED
+&#xFDD0; NOT CHANGED
+&#xFDEF; NOT CHANGED
+&#xFDF0; NOT CHANGED
+&#x2FFFE; NOT CHANGED
+&#x2FFFF; NOT CHANGED
+&#x110000; CHANGED (&amp;&num;x110000&semi;, &amp;#x110000;)
+
+*** Testing HTML 5 with another single-byte encoding ***
+&#0; CHANGED (&amp;&num;0&semi;, &amp;#0;)
+&#1; CHANGED (&amp;&num;1&semi;, &amp;#1;)
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; CHANGED (&amp;&num;x0B&semi;, &amp;#x0B;)
+&#x0C; NOT CHANGED
+&#x0D; CHANGED (&amp;&num;x0D&semi;, &amp;#x0D;)
+&#x0E; CHANGED (&amp;&num;x0E&semi;, &amp;#x0E;)
+&#x1F; CHANGED (&amp;&num;x1F&semi;, &amp;#x1F;)
+&#x20; NOT CHANGED
+&#x7F; CHANGED (&amp;&num;x7F&semi;, &amp;#x7F;)
+&#x80; CHANGED (&amp;&num;x80&semi;, &amp;#x80;)
+&#x9F; CHANGED (&amp;&num;x9F&semi;, &amp;#x9F;)
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; NOT CHANGED
+&#xDFFF; NOT CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; CHANGED (&amp;&num;xFFFE&semi;, &amp;#xFFFE;)
+&#xFFFF; CHANGED (&amp;&num;xFFFF&semi;, &amp;#xFFFF;)
+&#xFDCF; NOT CHANGED
+&#xFDD0; CHANGED (&amp;&num;xFDD0&semi;, &amp;#xFDD0;)
+&#xFDEF; CHANGED (&amp;&num;xFDEF&semi;, &amp;#xFDEF;)
+&#xFDF0; NOT CHANGED
+&#x2FFFE; CHANGED (&amp;&num;x2FFFE&semi;, &amp;#x2FFFE;)
+&#x2FFFF; CHANGED (&amp;&num;x2FFFF&semi;, &amp;#x2FFFF;)
+&#x110000; CHANGED (&amp;&num;x110000&semi;, &amp;#x110000;)
+
+*** Testing HTML 5 with another multibyte-byte encoding ***
+&#0; CHANGED
+&#1; CHANGED
+&#x09; NOT CHANGED
+&#x0A; NOT CHANGED
+&#x0B; CHANGED
+&#x0C; NOT CHANGED
+&#x0D; CHANGED
+&#x0E; CHANGED
+&#x1F; CHANGED
+&#x20; NOT CHANGED
+&#x7F; CHANGED
+&#x80; CHANGED
+&#x9F; CHANGED
+&#xA0; NOT CHANGED
+&#xD7FF; NOT CHANGED
+&#xD800; NOT CHANGED
+&#xDFFF; NOT CHANGED
+&#xE000; NOT CHANGED
+&#xFFFE; CHANGED
+&#xFFFF; CHANGED
+&#xFDCF; NOT CHANGED
+&#xFDD0; CHANGED
+&#xFDEF; CHANGED
+&#xFDF0; NOT CHANGED
+&#x2FFFE; CHANGED
+&#x2FFFF; CHANGED
+&#x110000; CHANGED
diff --git a/ext/standard/tests/strings/htmlentities23.phpt b/ext/standard/tests/strings/htmlentities23.phpt
new file mode 100644
index 0000000000..bcfcd8d8f7
--- /dev/null
+++ b/ext/standard/tests/strings/htmlentities23.phpt
@@ -0,0 +1,95 @@
+--TEST--
+htmlentities() / htmlspecialchars() ENT_SUBSTITUTE EUC-JP
+--FILE--
+<?php
+$tests = array(
+ "\x8F\xA1\xFF", //2 sub as 2nd is potentially valid as lead
+ "\x8F\xA1", //2 sub, as 2nd is potentially valid as lead
+ "\x8F", //1 sub
+ "\x8F\xA0", //1 sub, A0 is not valid as sole/first byte
+ "\x8F\xA1\x21", //2 sub, no consume last
+ "\x8F\x21", //1 sub, no consume last
+ "\x8E\xAE", //valid
+ "\x8E", //1 sub
+ "\x8E\x21", //1 sub, no consume last
+ "\xB2\xFF", //1 sub
+ "\xB2", //1 sub
+ "\xB2\x21", //1 sub, no consume last
+ "\xA0", //1 sub
+);
+
+foreach ($tests as $test) {
+ error_reporting(~E_STRICT);
+ $a = htmlentities($test, ENT_QUOTES | ENT_SUBSTITUTE, "EUC-JP");
+ error_reporting(-1);
+ var_dump($a, bin2hex($a));
+ $a = htmlspecialchars($test, ENT_QUOTES | ENT_SUBSTITUTE, "EUC-JP");
+ var_dump($a, bin2hex($a));
+ echo "\n";
+}
+?>
+--EXPECT--
+string(16) "&#xFFFD;&#xFFFD;"
+string(32) "262378464646443b262378464646443b"
+string(16) "&#xFFFD;&#xFFFD;"
+string(32) "262378464646443b262378464646443b"
+
+string(16) "&#xFFFD;&#xFFFD;"
+string(32) "262378464646443b262378464646443b"
+string(16) "&#xFFFD;&#xFFFD;"
+string(32) "262378464646443b262378464646443b"
+
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+
+string(17) "&#xFFFD;&#xFFFD;!"
+string(34) "262378464646443b262378464646443b21"
+string(17) "&#xFFFD;&#xFFFD;!"
+string(34) "262378464646443b262378464646443b21"
+
+string(9) "&#xFFFD;!"
+string(18) "262378464646443b21"
+string(9) "&#xFFFD;!"
+string(18) "262378464646443b21"
+
+string(2) "Ž®"
+string(4) "8eae"
+string(2) "Ž®"
+string(4) "8eae"
+
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+
+string(9) "&#xFFFD;!"
+string(18) "262378464646443b21"
+string(9) "&#xFFFD;!"
+string(18) "262378464646443b21"
+
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+
+string(9) "&#xFFFD;!"
+string(18) "262378464646443b21"
+string(9) "&#xFFFD;!"
+string(18) "262378464646443b21"
+
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
+string(8) "&#xFFFD;"
+string(16) "262378464646443b"
diff --git a/ext/standard/tests/file/htmlentities19.phpt b/ext/standard/tests/strings/htmlentities24.phpt
index c858ccb7d4..3ffdd65a5f 100644
--- a/ext/standard/tests/file/htmlentities19.phpt
+++ b/ext/standard/tests/strings/htmlentities24.phpt
@@ -14,9 +14,9 @@ for($i=0; $i<256; $i++)
/* giving arguments as NULL */
echo "\n*** Testing htmlentities() with NULL as first,second and third argument ***\n";
var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", NULL, 'cp1252') );
-var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", ENT_QUOTES, NULL) );
-var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", ENT_NOQUOTES, NULL) );
-var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", ENT_COMPAT, NULL) );
+var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", ENT_QUOTES, NULL) ); /* UTF-8 assumed */
+var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", ENT_NOQUOTES, NULL) ); /* UTF-8 assumed */
+var_dump( htmlentities("\x82\x86\x99\x9f\x80\x82\x81", ENT_COMPAT, NULL) ); /* UTF-8 assumed */
var_dump( htmlentities(NULL, NULL, NULL) );
/* giving long string to check for proper memory re-allocation */
@@ -305,9 +305,9 @@ string(16) "6368722832353529"
*** Testing htmlentities() with NULL as first,second and third argument ***
string(42) "&sbquo;&dagger;&trade;&Yuml;&euro;&sbquo;"
-string(7) "‚†™Ÿ€‚"
-string(7) "‚†™Ÿ€‚"
-string(7) "‚†™Ÿ€‚"
+string(0) ""
+string(0) ""
+string(0) ""
string(0) ""
*** Checking for proper memory allocation with long string ***
diff --git a/ext/standard/tests/strings/htmlentities_html5.phpt b/ext/standard/tests/strings/htmlentities_html5.phpt
new file mode 100644
index 0000000000..1f3409723e
--- /dev/null
+++ b/ext/standard/tests/strings/htmlentities_html5.phpt
@@ -0,0 +1,1623 @@
+--TEST--
+htmlentities() conformance check (HTML 5)
+--FILE--
+<?php
+function utf32_utf8($k) {
+ if ($k < 0x80) {
+ $retval = pack('C', $k);
+ } else if ($k < 0x800) {
+ $retval = pack('C2',
+ 0xc0 | ($k >> 6),
+ 0x80 | ($k & 0x3f));
+ } else if ($k < 0x10000) {
+ $retval = pack('C3',
+ 0xe0 | ($k >> 12),
+ 0x80 | (($k >> 6) & 0x3f),
+ 0x80 | ($k & 0x3f));
+ } else {
+ $retval = pack('C4',
+ 0xf0 | ($k >> 18),
+ 0x80 | (($k >> 12) & 0x3f),
+ 0x80 | (($k >> 6) & 0x3f),
+ 0x80 | ($k & 0x3f));
+ }
+ return $retval;
+}
+
+for ($i = 0; $i < 0x1DFFF; $i++) {
+ if ($i >= 0xd800 && $i < 0xe000) //surrogates
+ continue;
+ $str = utf32_utf8($i);
+ $result = htmlentities($str, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ if ($str != $result) {
+ printf("%s\tU+%05X\n", $result, $i);
+ }
+}
+
+/* multicodepoint entities */
+$mpcent = array(
+array(0x0003C, 0x20D2),
+array(0x0003D, 0x20E5),
+array(0x0003E, 0x20D2),
+array(0x00066, 0x6A),
+array(0x0205F, 0x200A),
+array(0x0219D, 0x338),
+array(0x02202, 0x338),
+array(0x02220, 0x20D2),
+array(0x02229, 0xFE00),
+array(0x0222A, 0xFE00),
+array(0x0223C, 0x020D2),
+array(0x0223D, 0x00331),
+array(0x0223E, 0x00333),
+array(0x02242, 0x338),
+array(0x0224B, 0x338),
+array(0x0224D, 0x020D2),
+array(0x0224E, 0x338),
+array(0x0224F, 0x338),
+array(0x02250, 0x338),
+array(0x02261, 0x020E5),
+array(0x02264, 0x20D2),
+array(0x02265, 0x020D2),
+array(0x02266, 0x338),
+array(0x02267, 0x00338),
+array(0x02268, 0xFE00),
+array(0x02269, 0xFE00),
+array(0x0226A, 0x338),
+array(0x0226A, 0x20D2),
+array(0x0226B, 0x338),
+array(0x0226B, 0x20D2),
+array(0x0227F, 0x338),
+array(0x02282, 0x20D2),
+array(0x02283, 0x20D2),
+array(0x0228A, 0xFE00),
+array(0x0228B, 0xFE00),
+array(0x0228F, 0x338),
+array(0x02290, 0x338),
+array(0x02293, 0xFE00),
+array(0x02294, 0xFE00),
+array(0x022B4, 0x20D2),
+array(0x022B5, 0x20D2),
+array(0x022D8, 0x338),
+array(0x022D9, 0x338),
+array(0x022DA, 0xFE00),
+array(0x022DB, 0xFE00),
+array(0x022F5, 0x338),
+array(0x022F9, 0x338),
+array(0x02933, 0x338),
+array(0x029CF, 0x338),
+array(0x029D0, 0x338),
+array(0x02A6D, 0x338),
+array(0x02A70, 0x338),
+array(0x02A7D, 0x338),
+array(0x02A7E, 0x338),
+array(0x02AA1, 0x338),
+array(0x02AA2, 0x338),
+array(0x02AAC, 0xFE00),
+array(0x02AAD, 0xFE00),
+array(0x02AAF, 0x338),
+array(0x02AB0, 0x338),
+array(0x02AC5, 0x338),
+array(0x02AC6, 0x338),
+array(0x02ACB, 0xFE00),
+array(0x02ACC, 0xFE00),
+array(0x02AFD, 0xFE00),
+);
+
+foreach ($mpcent as $i) {
+ $str = utf32_utf8($i[0]);
+ $str .= utf32_utf8($i[1]);
+ $result = htmlentities($str, ENT_QUOTES | ENT_HTML5, 'UTF-8');
+ printf("%s\tU+%05X U+%05X\n", $result, $i[0], $i[1]);
+}
+?>
+--EXPECT--
+&Tab; U+00009
+&NewLine; U+0000A
+&excl; U+00021
+&quot; U+00022
+&num; U+00023
+&dollar; U+00024
+&percnt; U+00025
+&amp; U+00026
+&apos; U+00027
+&lpar; U+00028
+&rpar; U+00029
+&ast; U+0002A
+&plus; U+0002B
+&comma; U+0002C
+&period; U+0002E
+&sol; U+0002F
+&colon; U+0003A
+&semi; U+0003B
+&lt; U+0003C
+&equals; U+0003D
+&gt; U+0003E
+&quest; U+0003F
+&commat; U+00040
+&lbrack; U+0005B
+&bsol; U+0005C
+&rsqb; U+0005D
+&Hat; U+0005E
+&lowbar; U+0005F
+&grave; U+00060
+&lbrace; U+0007B
+&vert; U+0007C
+&rcub; U+0007D
+&nbsp; U+000A0
+&iexcl; U+000A1
+&cent; U+000A2
+&pound; U+000A3
+&curren; U+000A4
+&yen; U+000A5
+&brvbar; U+000A6
+&sect; U+000A7
+&DoubleDot; U+000A8
+&copy; U+000A9
+&ordf; U+000AA
+&laquo; U+000AB
+&not; U+000AC
+&shy; U+000AD
+&reg; U+000AE
+&macr; U+000AF
+&deg; U+000B0
+&plusmn; U+000B1
+&sup2; U+000B2
+&sup3; U+000B3
+&DiacriticalAcute; U+000B4
+&micro; U+000B5
+&para; U+000B6
+&CenterDot; U+000B7
+&Cedilla; U+000B8
+&sup1; U+000B9
+&ordm; U+000BA
+&raquo; U+000BB
+&frac14; U+000BC
+&half; U+000BD
+&frac34; U+000BE
+&iquest; U+000BF
+&Agrave; U+000C0
+&Aacute; U+000C1
+&Acirc; U+000C2
+&Atilde; U+000C3
+&Auml; U+000C4
+&Aring; U+000C5
+&AElig; U+000C6
+&Ccedil; U+000C7
+&Egrave; U+000C8
+&Eacute; U+000C9
+&Ecirc; U+000CA
+&Euml; U+000CB
+&Igrave; U+000CC
+&Iacute; U+000CD
+&Icirc; U+000CE
+&Iuml; U+000CF
+&ETH; U+000D0
+&Ntilde; U+000D1
+&Ograve; U+000D2
+&Oacute; U+000D3
+&Ocirc; U+000D4
+&Otilde; U+000D5
+&Ouml; U+000D6
+&times; U+000D7
+&Oslash; U+000D8
+&Ugrave; U+000D9
+&Uacute; U+000DA
+&Ucirc; U+000DB
+&Uuml; U+000DC
+&Yacute; U+000DD
+&THORN; U+000DE
+&szlig; U+000DF
+&agrave; U+000E0
+&aacute; U+000E1
+&acirc; U+000E2
+&atilde; U+000E3
+&auml; U+000E4
+&aring; U+000E5
+&aelig; U+000E6
+&ccedil; U+000E7
+&egrave; U+000E8
+&eacute; U+000E9
+&ecirc; U+000EA
+&euml; U+000EB
+&igrave; U+000EC
+&iacute; U+000ED
+&icirc; U+000EE
+&iuml; U+000EF
+&eth; U+000F0
+&ntilde; U+000F1
+&ograve; U+000F2
+&oacute; U+000F3
+&ocirc; U+000F4
+&otilde; U+000F5
+&ouml; U+000F6
+&divide; U+000F7
+&oslash; U+000F8
+&ugrave; U+000F9
+&uacute; U+000FA
+&ucirc; U+000FB
+&uuml; U+000FC
+&yacute; U+000FD
+&thorn; U+000FE
+&yuml; U+000FF
+&Amacr; U+00100
+&amacr; U+00101
+&Abreve; U+00102
+&abreve; U+00103
+&Aogon; U+00104
+&aogon; U+00105
+&Cacute; U+00106
+&cacute; U+00107
+&Ccirc; U+00108
+&ccirc; U+00109
+&Cdot; U+0010A
+&cdot; U+0010B
+&Ccaron; U+0010C
+&ccaron; U+0010D
+&Dcaron; U+0010E
+&dcaron; U+0010F
+&Dstrok; U+00110
+&dstrok; U+00111
+&Emacr; U+00112
+&emacr; U+00113
+&Edot; U+00116
+&edot; U+00117
+&Eogon; U+00118
+&eogon; U+00119
+&Ecaron; U+0011A
+&ecaron; U+0011B
+&Gcirc; U+0011C
+&gcirc; U+0011D
+&Gbreve; U+0011E
+&gbreve; U+0011F
+&Gdot; U+00120
+&gdot; U+00121
+&Gcedil; U+00122
+&Hcirc; U+00124
+&hcirc; U+00125
+&Hstrok; U+00126
+&hstrok; U+00127
+&Itilde; U+00128
+&itilde; U+00129
+&Imacr; U+0012A
+&imacr; U+0012B
+&Iogon; U+0012E
+&iogon; U+0012F
+&Idot; U+00130
+&inodot; U+00131
+&IJlig; U+00132
+&ijlig; U+00133
+&Jcirc; U+00134
+&jcirc; U+00135
+&Kcedil; U+00136
+&kcedil; U+00137
+&kgreen; U+00138
+&Lacute; U+00139
+&lacute; U+0013A
+&Lcedil; U+0013B
+&lcedil; U+0013C
+&Lcaron; U+0013D
+&lcaron; U+0013E
+&Lmidot; U+0013F
+&lmidot; U+00140
+&Lstrok; U+00141
+&lstrok; U+00142
+&Nacute; U+00143
+&nacute; U+00144
+&Ncedil; U+00145
+&ncedil; U+00146
+&Ncaron; U+00147
+&ncaron; U+00148
+&napos; U+00149
+&ENG; U+0014A
+&eng; U+0014B
+&Omacr; U+0014C
+&omacr; U+0014D
+&Odblac; U+00150
+&odblac; U+00151
+&OElig; U+00152
+&oelig; U+00153
+&Racute; U+00154
+&racute; U+00155
+&Rcedil; U+00156
+&rcedil; U+00157
+&Rcaron; U+00158
+&rcaron; U+00159
+&Sacute; U+0015A
+&sacute; U+0015B
+&Scirc; U+0015C
+&scirc; U+0015D
+&Scedil; U+0015E
+&scedil; U+0015F
+&Scaron; U+00160
+&scaron; U+00161
+&Tcedil; U+00162
+&tcedil; U+00163
+&Tcaron; U+00164
+&tcaron; U+00165
+&Tstrok; U+00166
+&tstrok; U+00167
+&Utilde; U+00168
+&utilde; U+00169
+&Umacr; U+0016A
+&umacr; U+0016B
+&Ubreve; U+0016C
+&ubreve; U+0016D
+&Uring; U+0016E
+&uring; U+0016F
+&Udblac; U+00170
+&udblac; U+00171
+&Uogon; U+00172
+&uogon; U+00173
+&Wcirc; U+00174
+&wcirc; U+00175
+&Ycirc; U+00176
+&ycirc; U+00177
+&Yuml; U+00178
+&Zacute; U+00179
+&zacute; U+0017A
+&Zdot; U+0017B
+&zdot; U+0017C
+&Zcaron; U+0017D
+&zcaron; U+0017E
+&fnof; U+00192
+&imped; U+001B5
+&gacute; U+001F5
+&jmath; U+00237
+&circ; U+002C6
+&Hacek; U+002C7
+&Breve; U+002D8
+&dot; U+002D9
+&ring; U+002DA
+&ogon; U+002DB
+&DiacriticalTilde; U+002DC
+&DiacriticalDoubleAcute; U+002DD
+&DownBreve; U+00311
+&Alpha; U+00391
+&Beta; U+00392
+&Gamma; U+00393
+&Delta; U+00394
+&Epsilon; U+00395
+&Zeta; U+00396
+&Eta; U+00397
+&Theta; U+00398
+&Iota; U+00399
+&Kappa; U+0039A
+&Lambda; U+0039B
+&Mu; U+0039C
+&Nu; U+0039D
+&Xi; U+0039E
+&Omicron; U+0039F
+&Pi; U+003A0
+&Rho; U+003A1
+&Sigma; U+003A3
+&Tau; U+003A4
+&Upsilon; U+003A5
+&Phi; U+003A6
+&Chi; U+003A7
+&Psi; U+003A8
+&Omega; U+003A9
+&alpha; U+003B1
+&beta; U+003B2
+&gamma; U+003B3
+&delta; U+003B4
+&epsi; U+003B5
+&zeta; U+003B6
+&eta; U+003B7
+&theta; U+003B8
+&iota; U+003B9
+&kappa; U+003BA
+&lambda; U+003BB
+&mu; U+003BC
+&nu; U+003BD
+&xi; U+003BE
+&omicron; U+003BF
+&pi; U+003C0
+&rho; U+003C1
+&sigmav; U+003C2
+&sigma; U+003C3
+&tau; U+003C4
+&upsi; U+003C5
+&phi; U+003C6
+&chi; U+003C7
+&psi; U+003C8
+&omega; U+003C9
+&thetasym; U+003D1
+&upsih; U+003D2
+&straightphi; U+003D5
+&piv; U+003D6
+&Gammad; U+003DC
+&gammad; U+003DD
+&varkappa; U+003F0
+&rhov; U+003F1
+&straightepsilon; U+003F5
+&backepsilon; U+003F6
+&IOcy; U+00401
+&DJcy; U+00402
+&GJcy; U+00403
+&Jukcy; U+00404
+&DScy; U+00405
+&Iukcy; U+00406
+&YIcy; U+00407
+&Jsercy; U+00408
+&LJcy; U+00409
+&NJcy; U+0040A
+&TSHcy; U+0040B
+&KJcy; U+0040C
+&Ubrcy; U+0040E
+&DZcy; U+0040F
+&Acy; U+00410
+&Bcy; U+00411
+&Vcy; U+00412
+&Gcy; U+00413
+&Dcy; U+00414
+&IEcy; U+00415
+&ZHcy; U+00416
+&Zcy; U+00417
+&Icy; U+00418
+&Jcy; U+00419
+&Kcy; U+0041A
+&Lcy; U+0041B
+&Mcy; U+0041C
+&Ncy; U+0041D
+&Ocy; U+0041E
+&Pcy; U+0041F
+&Rcy; U+00420
+&Scy; U+00421
+&Tcy; U+00422
+&Ucy; U+00423
+&Fcy; U+00424
+&KHcy; U+00425
+&TScy; U+00426
+&CHcy; U+00427
+&SHcy; U+00428
+&SHCHcy; U+00429
+&HARDcy; U+0042A
+&Ycy; U+0042B
+&SOFTcy; U+0042C
+&Ecy; U+0042D
+&YUcy; U+0042E
+&YAcy; U+0042F
+&acy; U+00430
+&bcy; U+00431
+&vcy; U+00432
+&gcy; U+00433
+&dcy; U+00434
+&iecy; U+00435
+&zhcy; U+00436
+&zcy; U+00437
+&icy; U+00438
+&jcy; U+00439
+&kcy; U+0043A
+&lcy; U+0043B
+&mcy; U+0043C
+&ncy; U+0043D
+&ocy; U+0043E
+&pcy; U+0043F
+&rcy; U+00440
+&scy; U+00441
+&tcy; U+00442
+&ucy; U+00443
+&fcy; U+00444
+&khcy; U+00445
+&tscy; U+00446
+&chcy; U+00447
+&shcy; U+00448
+&shchcy; U+00449
+&hardcy; U+0044A
+&ycy; U+0044B
+&softcy; U+0044C
+&ecy; U+0044D
+&yucy; U+0044E
+&yacy; U+0044F
+&iocy; U+00451
+&djcy; U+00452
+&gjcy; U+00453
+&jukcy; U+00454
+&dscy; U+00455
+&iukcy; U+00456
+&yicy; U+00457
+&jsercy; U+00458
+&ljcy; U+00459
+&njcy; U+0045A
+&tshcy; U+0045B
+&kjcy; U+0045C
+&ubrcy; U+0045E
+&dzcy; U+0045F
+&ensp; U+02002
+&emsp; U+02003
+&emsp13; U+02004
+&emsp14; U+02005
+&numsp; U+02007
+&puncsp; U+02008
+&ThinSpace; U+02009
+&hairsp; U+0200A
+&ZeroWidthSpace; U+0200B
+&zwnj; U+0200C
+&zwj; U+0200D
+&lrm; U+0200E
+&rlm; U+0200F
+&hyphen; U+02010
+&ndash; U+02013
+&mdash; U+02014
+&horbar; U+02015
+&Verbar; U+02016
+&OpenCurlyQuote; U+02018
+&rsquo; U+02019
+&sbquo; U+0201A
+&OpenCurlyDoubleQuote; U+0201C
+&rdquo; U+0201D
+&bdquo; U+0201E
+&dagger; U+02020
+&Dagger; U+02021
+&bull; U+02022
+&nldr; U+02025
+&hellip; U+02026
+&permil; U+02030
+&pertenk; U+02031
+&prime; U+02032
+&Prime; U+02033
+&tprime; U+02034
+&backprime; U+02035
+&lsaquo; U+02039
+&rsaquo; U+0203A
+&oline; U+0203E
+&caret; U+02041
+&hybull; U+02043
+&frasl; U+02044
+&bsemi; U+0204F
+&qprime; U+02057
+&MediumSpace; U+0205F
+&NoBreak; U+02060
+&af; U+02061
+&InvisibleTimes; U+02062
+&ic; U+02063
+&euro; U+020AC
+&TripleDot; U+020DB
+&DotDot; U+020DC
+&complexes; U+02102
+&incare; U+02105
+&gscr; U+0210A
+&HilbertSpace; U+0210B
+&Hfr; U+0210C
+&Hopf; U+0210D
+&planckh; U+0210E
+&planck; U+0210F
+&imagline; U+02110
+&Ifr; U+02111
+&lagran; U+02112
+&ell; U+02113
+&naturals; U+02115
+&numero; U+02116
+&copysr; U+02117
+&wp; U+02118
+&primes; U+02119
+&rationals; U+0211A
+&realine; U+0211B
+&Rfr; U+0211C
+&Ropf; U+0211D
+&rx; U+0211E
+&trade; U+02122
+&Zopf; U+02124
+&mho; U+02127
+&Zfr; U+02128
+&iiota; U+02129
+&Bscr; U+0212C
+&Cfr; U+0212D
+&escr; U+0212F
+&expectation; U+02130
+&Fouriertrf; U+02131
+&Mellintrf; U+02133
+&orderof; U+02134
+&aleph; U+02135
+&beth; U+02136
+&gimel; U+02137
+&daleth; U+02138
+&CapitalDifferentialD; U+02145
+&DifferentialD; U+02146
+&exponentiale; U+02147
+&ImaginaryI; U+02148
+&frac13; U+02153
+&frac23; U+02154
+&frac15; U+02155
+&frac25; U+02156
+&frac35; U+02157
+&frac45; U+02158
+&frac16; U+02159
+&frac56; U+0215A
+&frac18; U+0215B
+&frac38; U+0215C
+&frac58; U+0215D
+&frac78; U+0215E
+&larr; U+02190
+&uarr; U+02191
+&srarr; U+02192
+&darr; U+02193
+&harr; U+02194
+&UpDownArrow; U+02195
+&nwarrow; U+02196
+&UpperRightArrow; U+02197
+&LowerRightArrow; U+02198
+&swarr; U+02199
+&nleftarrow; U+0219A
+&nrarr; U+0219B
+&rarrw; U+0219D
+&Larr; U+0219E
+&Uarr; U+0219F
+&twoheadrightarrow; U+021A0
+&Darr; U+021A1
+&larrtl; U+021A2
+&rarrtl; U+021A3
+&LeftTeeArrow; U+021A4
+&UpTeeArrow; U+021A5
+&map; U+021A6
+&DownTeeArrow; U+021A7
+&larrhk; U+021A9
+&rarrhk; U+021AA
+&larrlp; U+021AB
+&looparrowright; U+021AC
+&harrw; U+021AD
+&nleftrightarrow; U+021AE
+&Lsh; U+021B0
+&rsh; U+021B1
+&ldsh; U+021B2
+&rdsh; U+021B3
+&crarr; U+021B5
+&curvearrowleft; U+021B6
+&curarr; U+021B7
+&olarr; U+021BA
+&orarr; U+021BB
+&leftharpoonup; U+021BC
+&leftharpoondown; U+021BD
+&RightUpVector; U+021BE
+&uharl; U+021BF
+&rharu; U+021C0
+&rhard; U+021C1
+&RightDownVector; U+021C2
+&dharl; U+021C3
+&rightleftarrows; U+021C4
+&udarr; U+021C5
+&lrarr; U+021C6
+&llarr; U+021C7
+&upuparrows; U+021C8
+&rrarr; U+021C9
+&downdownarrows; U+021CA
+&leftrightharpoons; U+021CB
+&rightleftharpoons; U+021CC
+&nLeftarrow; U+021CD
+&nhArr; U+021CE
+&nrArr; U+021CF
+&DoubleLeftArrow; U+021D0
+&DoubleUpArrow; U+021D1
+&Implies; U+021D2
+&Downarrow; U+021D3
+&hArr; U+021D4
+&Updownarrow; U+021D5
+&nwArr; U+021D6
+&neArr; U+021D7
+&seArr; U+021D8
+&swArr; U+021D9
+&lAarr; U+021DA
+&rAarr; U+021DB
+&zigrarr; U+021DD
+&LeftArrowBar; U+021E4
+&RightArrowBar; U+021E5
+&DownArrowUpArrow; U+021F5
+&loarr; U+021FD
+&roarr; U+021FE
+&hoarr; U+021FF
+&forall; U+02200
+&comp; U+02201
+&part; U+02202
+&Exists; U+02203
+&nexist; U+02204
+&empty; U+02205
+&nabla; U+02207
+&isinv; U+02208
+&notin; U+02209
+&ReverseElement; U+0220B
+&notniva; U+0220C
+&prod; U+0220F
+&Coproduct; U+02210
+&sum; U+02211
+&minus; U+02212
+&MinusPlus; U+02213
+&plusdo; U+02214
+&ssetmn; U+02216
+&lowast; U+02217
+&compfn; U+02218
+&Sqrt; U+0221A
+&prop; U+0221D
+&infin; U+0221E
+&angrt; U+0221F
+&angle; U+02220
+&angmsd; U+02221
+&angsph; U+02222
+&mid; U+02223
+&nshortmid; U+02224
+&shortparallel; U+02225
+&nparallel; U+02226
+&and; U+02227
+&or; U+02228
+&cap; U+02229
+&cup; U+0222A
+&Integral; U+0222B
+&Int; U+0222C
+&tint; U+0222D
+&ContourIntegral; U+0222E
+&DoubleContourIntegral; U+0222F
+&Cconint; U+02230
+&cwint; U+02231
+&cwconint; U+02232
+&awconint; U+02233
+&there4; U+02234
+&Because; U+02235
+&ratio; U+02236
+&Colon; U+02237
+&minusd; U+02238
+&mDDot; U+0223A
+&homtht; U+0223B
+&sim; U+0223C
+&bsim; U+0223D
+&ac; U+0223E
+&acd; U+0223F
+&wr; U+02240
+&NotTilde; U+02241
+&esim; U+02242
+&simeq; U+02243
+&nsime; U+02244
+&TildeFullEqual; U+02245
+&simne; U+02246
+&ncong; U+02247
+&approx; U+02248
+&napprox; U+02249
+&ape; U+0224A
+&apid; U+0224B
+&bcong; U+0224C
+&CupCap; U+0224D
+&bump; U+0224E
+&HumpEqual; U+0224F
+&esdot; U+02250
+&doteqdot; U+02251
+&fallingdotseq; U+02252
+&risingdotseq; U+02253
+&coloneq; U+02254
+&eqcolon; U+02255
+&ecir; U+02256
+&circeq; U+02257
+&wedgeq; U+02259
+&veeeq; U+0225A
+&triangleq; U+0225C
+&equest; U+0225F
+&NotEqual; U+02260
+&Congruent; U+02261
+&NotCongruent; U+02262
+&leq; U+02264
+&ge; U+02265
+&lE; U+02266
+&geqq; U+02267
+&lneqq; U+02268
+&gneqq; U+02269
+&ll; U+0226A
+&gg; U+0226B
+&between; U+0226C
+&NotCupCap; U+0226D
+&NotLess; U+0226E
+&ngtr; U+0226F
+&NotLessEqual; U+02270
+&ngeq; U+02271
+&LessTilde; U+02272
+&GreaterTilde; U+02273
+&nlsim; U+02274
+&ngsim; U+02275
+&lessgtr; U+02276
+&gl; U+02277
+&ntlg; U+02278
+&NotGreaterLess; U+02279
+&prec; U+0227A
+&succ; U+0227B
+&PrecedesSlantEqual; U+0227C
+&succcurlyeq; U+0227D
+&precsim; U+0227E
+&SucceedsTilde; U+0227F
+&npr; U+02280
+&NotSucceeds; U+02281
+&sub; U+02282
+&sup; U+02283
+&nsub; U+02284
+&nsup; U+02285
+&SubsetEqual; U+02286
+&supe; U+02287
+&NotSubsetEqual; U+02288
+&NotSupersetEqual; U+02289
+&subsetneq; U+0228A
+&supsetneq; U+0228B
+&cupdot; U+0228D
+&UnionPlus; U+0228E
+&sqsub; U+0228F
+&sqsupset; U+02290
+&SquareSubsetEqual; U+02291
+&SquareSupersetEqual; U+02292
+&sqcap; U+02293
+&sqcup; U+02294
+&CirclePlus; U+02295
+&ominus; U+02296
+&CircleTimes; U+02297
+&osol; U+02298
+&CircleDot; U+02299
+&ocir; U+0229A
+&oast; U+0229B
+&odash; U+0229D
+&boxplus; U+0229E
+&boxminus; U+0229F
+&timesb; U+022A0
+&sdotb; U+022A1
+&vdash; U+022A2
+&dashv; U+022A3
+&DownTee; U+022A4
+&perp; U+022A5
+&models; U+022A7
+&DoubleRightTee; U+022A8
+&Vdash; U+022A9
+&Vvdash; U+022AA
+&VDash; U+022AB
+&nvdash; U+022AC
+&nvDash; U+022AD
+&nVdash; U+022AE
+&nVDash; U+022AF
+&prurel; U+022B0
+&vartriangleleft; U+022B2
+&vrtri; U+022B3
+&LeftTriangleEqual; U+022B4
+&RightTriangleEqual; U+022B5
+&origof; U+022B6
+&imof; U+022B7
+&mumap; U+022B8
+&hercon; U+022B9
+&intcal; U+022BA
+&veebar; U+022BB
+&barvee; U+022BD
+&angrtvb; U+022BE
+&lrtri; U+022BF
+&xwedge; U+022C0
+&xvee; U+022C1
+&bigcap; U+022C2
+&bigcup; U+022C3
+&diamond; U+022C4
+&sdot; U+022C5
+&Star; U+022C6
+&divonx; U+022C7
+&bowtie; U+022C8
+&ltimes; U+022C9
+&rtimes; U+022CA
+&lthree; U+022CB
+&rthree; U+022CC
+&backsimeq; U+022CD
+&curlyvee; U+022CE
+&curlywedge; U+022CF
+&Sub; U+022D0
+&Supset; U+022D1
+&Cap; U+022D2
+&Cup; U+022D3
+&pitchfork; U+022D4
+&epar; U+022D5
+&lessdot; U+022D6
+&gtrdot; U+022D7
+&Ll; U+022D8
+&Gg; U+022D9
+&lesseqgtr; U+022DA
+&gtreqless; U+022DB
+&curlyeqprec; U+022DE
+&cuesc; U+022DF
+&NotPrecedesSlantEqual; U+022E0
+&NotSucceedsSlantEqual; U+022E1
+&NotSquareSubsetEqual; U+022E2
+&NotSquareSupersetEqual; U+022E3
+&lnsim; U+022E6
+&gnsim; U+022E7
+&precnsim; U+022E8
+&scnsim; U+022E9
+&nltri; U+022EA
+&ntriangleright; U+022EB
+&nltrie; U+022EC
+&NotRightTriangleEqual; U+022ED
+&vellip; U+022EE
+&ctdot; U+022EF
+&utdot; U+022F0
+&dtdot; U+022F1
+&disin; U+022F2
+&isinsv; U+022F3
+&isins; U+022F4
+&isindot; U+022F5
+&notinvc; U+022F6
+&notinvb; U+022F7
+&isinE; U+022F9
+&nisd; U+022FA
+&xnis; U+022FB
+&nis; U+022FC
+&notnivc; U+022FD
+&notnivb; U+022FE
+&barwed; U+02305
+&doublebarwedge; U+02306
+&lceil; U+02308
+&RightCeiling; U+02309
+&LeftFloor; U+0230A
+&RightFloor; U+0230B
+&drcrop; U+0230C
+&dlcrop; U+0230D
+&urcrop; U+0230E
+&ulcrop; U+0230F
+&bnot; U+02310
+&profline; U+02312
+&profsurf; U+02313
+&telrec; U+02315
+&target; U+02316
+&ulcorner; U+0231C
+&urcorner; U+0231D
+&llcorner; U+0231E
+&drcorn; U+0231F
+&frown; U+02322
+&smile; U+02323
+&cylcty; U+0232D
+&profalar; U+0232E
+&topbot; U+02336
+&ovbar; U+0233D
+&solbar; U+0233F
+&angzarr; U+0237C
+&lmoust; U+023B0
+&rmoust; U+023B1
+&OverBracket; U+023B4
+&bbrk; U+023B5
+&bbrktbrk; U+023B6
+&OverParenthesis; U+023DC
+&UnderParenthesis; U+023DD
+&OverBrace; U+023DE
+&UnderBrace; U+023DF
+&trpezium; U+023E2
+&elinters; U+023E7
+&blank; U+02423
+&oS; U+024C8
+&HorizontalLine; U+02500
+&boxv; U+02502
+&boxdr; U+0250C
+&boxdl; U+02510
+&boxur; U+02514
+&boxul; U+02518
+&boxvr; U+0251C
+&boxvl; U+02524
+&boxhd; U+0252C
+&boxhu; U+02534
+&boxvh; U+0253C
+&boxH; U+02550
+&boxV; U+02551
+&boxdR; U+02552
+&boxDr; U+02553
+&boxDR; U+02554
+&boxdL; U+02555
+&boxDl; U+02556
+&boxDL; U+02557
+&boxuR; U+02558
+&boxUr; U+02559
+&boxUR; U+0255A
+&boxuL; U+0255B
+&boxUl; U+0255C
+&boxUL; U+0255D
+&boxvR; U+0255E
+&boxVr; U+0255F
+&boxVR; U+02560
+&boxvL; U+02561
+&boxVl; U+02562
+&boxVL; U+02563
+&boxHd; U+02564
+&boxhD; U+02565
+&boxHD; U+02566
+&boxHu; U+02567
+&boxhU; U+02568
+&boxHU; U+02569
+&boxvH; U+0256A
+&boxVh; U+0256B
+&boxVH; U+0256C
+&uhblk; U+02580
+&lhblk; U+02584
+&block; U+02588
+&blk14; U+02591
+&blk12; U+02592
+&blk34; U+02593
+&Square; U+025A1
+&squarf; U+025AA
+&EmptyVerySmallSquare; U+025AB
+&rect; U+025AD
+&marker; U+025AE
+&fltns; U+025B1
+&bigtriangleup; U+025B3
+&blacktriangle; U+025B4
+&triangle; U+025B5
+&blacktriangleright; U+025B8
+&rtri; U+025B9
+&bigtriangledown; U+025BD
+&blacktriangledown; U+025BE
+&triangledown; U+025BF
+&blacktriangleleft; U+025C2
+&ltri; U+025C3
+&lozenge; U+025CA
+&cir; U+025CB
+&tridot; U+025EC
+&bigcirc; U+025EF
+&ultri; U+025F8
+&urtri; U+025F9
+&lltri; U+025FA
+&EmptySmallSquare; U+025FB
+&FilledSmallSquare; U+025FC
+&starf; U+02605
+&star; U+02606
+&phone; U+0260E
+&female; U+02640
+&male; U+02642
+&spadesuit; U+02660
+&clubs; U+02663
+&hearts; U+02665
+&diamondsuit; U+02666
+&sung; U+0266A
+&flat; U+0266D
+&natur; U+0266E
+&sharp; U+0266F
+&check; U+02713
+&cross; U+02717
+&maltese; U+02720
+&sext; U+02736
+&VerticalSeparator; U+02758
+&lbbrk; U+02772
+&rbbrk; U+02773
+&bsolhsub; U+027C8
+&suphsol; U+027C9
+&LeftDoubleBracket; U+027E6
+&RightDoubleBracket; U+027E7
+&langle; U+027E8
+&RightAngleBracket; U+027E9
+&Lang; U+027EA
+&Rang; U+027EB
+&loang; U+027EC
+&roang; U+027ED
+&longleftarrow; U+027F5
+&LongRightArrow; U+027F6
+&LongLeftRightArrow; U+027F7
+&xlArr; U+027F8
+&DoubleLongRightArrow; U+027F9
+&xhArr; U+027FA
+&xmap; U+027FC
+&dzigrarr; U+027FF
+&nvlArr; U+02902
+&nvrArr; U+02903
+&nvHarr; U+02904
+&Map; U+02905
+&lbarr; U+0290C
+&bkarow; U+0290D
+&lBarr; U+0290E
+&dbkarow; U+0290F
+&drbkarow; U+02910
+&DDotrahd; U+02911
+&UpArrowBar; U+02912
+&DownArrowBar; U+02913
+&Rarrtl; U+02916
+&latail; U+02919
+&ratail; U+0291A
+&lAtail; U+0291B
+&rAtail; U+0291C
+&larrfs; U+0291D
+&rarrfs; U+0291E
+&larrbfs; U+0291F
+&rarrbfs; U+02920
+&nwarhk; U+02923
+&nearhk; U+02924
+&searhk; U+02925
+&swarhk; U+02926
+&nwnear; U+02927
+&toea; U+02928
+&seswar; U+02929
+&swnwar; U+0292A
+&rarrc; U+02933
+&cudarrr; U+02935
+&ldca; U+02936
+&rdca; U+02937
+&cudarrl; U+02938
+&larrpl; U+02939
+&curarrm; U+0293C
+&cularrp; U+0293D
+&rarrpl; U+02945
+&harrcir; U+02948
+&Uarrocir; U+02949
+&lurdshar; U+0294A
+&ldrushar; U+0294B
+&LeftRightVector; U+0294E
+&RightUpDownVector; U+0294F
+&DownLeftRightVector; U+02950
+&LeftUpDownVector; U+02951
+&LeftVectorBar; U+02952
+&RightVectorBar; U+02953
+&RightUpVectorBar; U+02954
+&RightDownVectorBar; U+02955
+&DownLeftVectorBar; U+02956
+&DownRightVectorBar; U+02957
+&LeftUpVectorBar; U+02958
+&LeftDownVectorBar; U+02959
+&LeftTeeVector; U+0295A
+&RightTeeVector; U+0295B
+&RightUpTeeVector; U+0295C
+&RightDownTeeVector; U+0295D
+&DownLeftTeeVector; U+0295E
+&DownRightTeeVector; U+0295F
+&LeftUpTeeVector; U+02960
+&LeftDownTeeVector; U+02961
+&lHar; U+02962
+&uHar; U+02963
+&rHar; U+02964
+&dHar; U+02965
+&luruhar; U+02966
+&ldrdhar; U+02967
+&ruluhar; U+02968
+&rdldhar; U+02969
+&lharul; U+0296A
+&llhard; U+0296B
+&rharul; U+0296C
+&lrhard; U+0296D
+&udhar; U+0296E
+&ReverseUpEquilibrium; U+0296F
+&RoundImplies; U+02970
+&erarr; U+02971
+&simrarr; U+02972
+&larrsim; U+02973
+&rarrsim; U+02974
+&rarrap; U+02975
+&ltlarr; U+02976
+&gtrarr; U+02978
+&subrarr; U+02979
+&suplarr; U+0297B
+&lfisht; U+0297C
+&rfisht; U+0297D
+&ufisht; U+0297E
+&dfisht; U+0297F
+&lopar; U+02985
+&ropar; U+02986
+&lbrke; U+0298B
+&rbrke; U+0298C
+&lbrkslu; U+0298D
+&rbrksld; U+0298E
+&lbrksld; U+0298F
+&rbrkslu; U+02990
+&langd; U+02991
+&rangd; U+02992
+&lparlt; U+02993
+&rpargt; U+02994
+&gtlPar; U+02995
+&ltrPar; U+02996
+&vzigzag; U+0299A
+&vangrt; U+0299C
+&angrtvbd; U+0299D
+&ange; U+029A4
+&range; U+029A5
+&dwangle; U+029A6
+&uwangle; U+029A7
+&angmsdaa; U+029A8
+&angmsdab; U+029A9
+&angmsdac; U+029AA
+&angmsdad; U+029AB
+&angmsdae; U+029AC
+&angmsdaf; U+029AD
+&angmsdag; U+029AE
+&angmsdah; U+029AF
+&bemptyv; U+029B0
+&demptyv; U+029B1
+&cemptyv; U+029B2
+&raemptyv; U+029B3
+&laemptyv; U+029B4
+&ohbar; U+029B5
+&omid; U+029B6
+&opar; U+029B7
+&operp; U+029B9
+&olcross; U+029BB
+&odsold; U+029BC
+&olcir; U+029BE
+&ofcir; U+029BF
+&olt; U+029C0
+&ogt; U+029C1
+&cirscir; U+029C2
+&cirE; U+029C3
+&solb; U+029C4
+&bsolb; U+029C5
+&boxbox; U+029C9
+&trisb; U+029CD
+&rtriltri; U+029CE
+&LeftTriangleBar; U+029CF
+&RightTriangleBar; U+029D0
+&iinfin; U+029DC
+&infintie; U+029DD
+&nvinfin; U+029DE
+&eparsl; U+029E3
+&smeparsl; U+029E4
+&eqvparsl; U+029E5
+&lozf; U+029EB
+&RuleDelayed; U+029F4
+&dsol; U+029F6
+&xodot; U+02A00
+&bigoplus; U+02A01
+&bigotimes; U+02A02
+&biguplus; U+02A04
+&bigsqcup; U+02A06
+&iiiint; U+02A0C
+&fpartint; U+02A0D
+&cirfnint; U+02A10
+&awint; U+02A11
+&rppolint; U+02A12
+&scpolint; U+02A13
+&npolint; U+02A14
+&pointint; U+02A15
+&quatint; U+02A16
+&intlarhk; U+02A17
+&pluscir; U+02A22
+&plusacir; U+02A23
+&simplus; U+02A24
+&plusdu; U+02A25
+&plussim; U+02A26
+&plustwo; U+02A27
+&mcomma; U+02A29
+&minusdu; U+02A2A
+&loplus; U+02A2D
+&roplus; U+02A2E
+&Cross; U+02A2F
+&timesd; U+02A30
+&timesbar; U+02A31
+&smashp; U+02A33
+&lotimes; U+02A34
+&rotimes; U+02A35
+&otimesas; U+02A36
+&Otimes; U+02A37
+&odiv; U+02A38
+&triplus; U+02A39
+&triminus; U+02A3A
+&tritime; U+02A3B
+&iprod; U+02A3C
+&amalg; U+02A3F
+&capdot; U+02A40
+&ncup; U+02A42
+&ncap; U+02A43
+&capand; U+02A44
+&cupor; U+02A45
+&cupcap; U+02A46
+&capcup; U+02A47
+&cupbrcap; U+02A48
+&capbrcup; U+02A49
+&cupcup; U+02A4A
+&capcap; U+02A4B
+&ccups; U+02A4C
+&ccaps; U+02A4D
+&ccupssm; U+02A50
+&And; U+02A53
+&Or; U+02A54
+&andand; U+02A55
+&oror; U+02A56
+&orslope; U+02A57
+&andslope; U+02A58
+&andv; U+02A5A
+&orv; U+02A5B
+&andd; U+02A5C
+&ord; U+02A5D
+&wedbar; U+02A5F
+&sdote; U+02A66
+&simdot; U+02A6A
+&congdot; U+02A6D
+&easter; U+02A6E
+&apacir; U+02A6F
+&apE; U+02A70
+&eplus; U+02A71
+&pluse; U+02A72
+&Esim; U+02A73
+&Colone; U+02A74
+&Equal; U+02A75
+&ddotseq; U+02A77
+&equivDD; U+02A78
+&ltcir; U+02A79
+&gtcir; U+02A7A
+&ltquest; U+02A7B
+&gtquest; U+02A7C
+&les; U+02A7D
+&ges; U+02A7E
+&lesdot; U+02A7F
+&gesdot; U+02A80
+&lesdoto; U+02A81
+&gesdoto; U+02A82
+&lesdotor; U+02A83
+&gesdotol; U+02A84
+&lap; U+02A85
+&gap; U+02A86
+&lne; U+02A87
+&gne; U+02A88
+&lnap; U+02A89
+&gnap; U+02A8A
+&lesseqqgtr; U+02A8B
+&gEl; U+02A8C
+&lsime; U+02A8D
+&gsime; U+02A8E
+&lsimg; U+02A8F
+&gsiml; U+02A90
+&lgE; U+02A91
+&glE; U+02A92
+&lesges; U+02A93
+&gesles; U+02A94
+&els; U+02A95
+&egs; U+02A96
+&elsdot; U+02A97
+&egsdot; U+02A98
+&el; U+02A99
+&eg; U+02A9A
+&siml; U+02A9D
+&simg; U+02A9E
+&simlE; U+02A9F
+&simgE; U+02AA0
+&LessLess; U+02AA1
+&GreaterGreater; U+02AA2
+&glj; U+02AA4
+&gla; U+02AA5
+&ltcc; U+02AA6
+&gtcc; U+02AA7
+&lescc; U+02AA8
+&gescc; U+02AA9
+&smt; U+02AAA
+&lat; U+02AAB
+&smte; U+02AAC
+&late; U+02AAD
+&bumpE; U+02AAE
+&preceq; U+02AAF
+&SucceedsEqual; U+02AB0
+&prE; U+02AB3
+&scE; U+02AB4
+&precneqq; U+02AB5
+&scnE; U+02AB6
+&precapprox; U+02AB7
+&succapprox; U+02AB8
+&precnapprox; U+02AB9
+&succnapprox; U+02ABA
+&Pr; U+02ABB
+&Sc; U+02ABC
+&subdot; U+02ABD
+&supdot; U+02ABE
+&subplus; U+02ABF
+&supplus; U+02AC0
+&submult; U+02AC1
+&supmult; U+02AC2
+&subedot; U+02AC3
+&supedot; U+02AC4
+&subE; U+02AC5
+&supseteqq; U+02AC6
+&subsim; U+02AC7
+&supsim; U+02AC8
+&subsetneqq; U+02ACB
+&supnE; U+02ACC
+&csub; U+02ACF
+&csup; U+02AD0
+&csube; U+02AD1
+&csupe; U+02AD2
+&subsup; U+02AD3
+&supsub; U+02AD4
+&subsub; U+02AD5
+&supsup; U+02AD6
+&suphsub; U+02AD7
+&supdsub; U+02AD8
+&forkv; U+02AD9
+&topfork; U+02ADA
+&mlcp; U+02ADB
+&Dashv; U+02AE4
+&Vdashl; U+02AE6
+&Barv; U+02AE7
+&vBar; U+02AE8
+&vBarv; U+02AE9
+&Vbar; U+02AEB
+&Not; U+02AEC
+&bNot; U+02AED
+&rnmid; U+02AEE
+&cirmid; U+02AEF
+&midcir; U+02AF0
+&topcir; U+02AF1
+&nhpar; U+02AF2
+&parsim; U+02AF3
+&fflig; U+0FB00
+&filig; U+0FB01
+&fllig; U+0FB02
+&ffilig; U+0FB03
+&ffllig; U+0FB04
+&Ascr; U+1D49C
+&Cscr; U+1D49E
+&Dscr; U+1D49F
+&Gscr; U+1D4A2
+&Jscr; U+1D4A5
+&Kscr; U+1D4A6
+&Nscr; U+1D4A9
+&Oscr; U+1D4AA
+&Pscr; U+1D4AB
+&Qscr; U+1D4AC
+&Sscr; U+1D4AE
+&Tscr; U+1D4AF
+&Uscr; U+1D4B0
+&Vscr; U+1D4B1
+&Wscr; U+1D4B2
+&Xscr; U+1D4B3
+&Yscr; U+1D4B4
+&Zscr; U+1D4B5
+&ascr; U+1D4B6
+&bscr; U+1D4B7
+&cscr; U+1D4B8
+&dscr; U+1D4B9
+&fscr; U+1D4BB
+&hscr; U+1D4BD
+&iscr; U+1D4BE
+&jscr; U+1D4BF
+&kscr; U+1D4C0
+&lscr; U+1D4C1
+&mscr; U+1D4C2
+&nscr; U+1D4C3
+&pscr; U+1D4C5
+&qscr; U+1D4C6
+&rscr; U+1D4C7
+&sscr; U+1D4C8
+&tscr; U+1D4C9
+&uscr; U+1D4CA
+&vscr; U+1D4CB
+&wscr; U+1D4CC
+&xscr; U+1D4CD
+&yscr; U+1D4CE
+&zscr; U+1D4CF
+&Afr; U+1D504
+&Bfr; U+1D505
+&Dfr; U+1D507
+&Efr; U+1D508
+&Ffr; U+1D509
+&Gfr; U+1D50A
+&Jfr; U+1D50D
+&Kfr; U+1D50E
+&Lfr; U+1D50F
+&Mfr; U+1D510
+&Nfr; U+1D511
+&Ofr; U+1D512
+&Pfr; U+1D513
+&Qfr; U+1D514
+&Sfr; U+1D516
+&Tfr; U+1D517
+&Ufr; U+1D518
+&Vfr; U+1D519
+&Wfr; U+1D51A
+&Xfr; U+1D51B
+&Yfr; U+1D51C
+&afr; U+1D51E
+&bfr; U+1D51F
+&cfr; U+1D520
+&dfr; U+1D521
+&efr; U+1D522
+&ffr; U+1D523
+&gfr; U+1D524
+&hfr; U+1D525
+&ifr; U+1D526
+&jfr; U+1D527
+&kfr; U+1D528
+&lfr; U+1D529
+&mfr; U+1D52A
+&nfr; U+1D52B
+&ofr; U+1D52C
+&pfr; U+1D52D
+&qfr; U+1D52E
+&rfr; U+1D52F
+&sfr; U+1D530
+&tfr; U+1D531
+&ufr; U+1D532
+&vfr; U+1D533
+&wfr; U+1D534
+&xfr; U+1D535
+&yfr; U+1D536
+&zfr; U+1D537
+&Aopf; U+1D538
+&Bopf; U+1D539
+&Dopf; U+1D53B
+&Eopf; U+1D53C
+&Fopf; U+1D53D
+&Gopf; U+1D53E
+&Iopf; U+1D540
+&Jopf; U+1D541
+&Kopf; U+1D542
+&Lopf; U+1D543
+&Mopf; U+1D544
+&Oopf; U+1D546
+&Sopf; U+1D54A
+&Topf; U+1D54B
+&Uopf; U+1D54C
+&Vopf; U+1D54D
+&Wopf; U+1D54E
+&Xopf; U+1D54F
+&Yopf; U+1D550
+&aopf; U+1D552
+&bopf; U+1D553
+&copf; U+1D554
+&dopf; U+1D555
+&eopf; U+1D556
+&fopf; U+1D557
+&gopf; U+1D558
+&hopf; U+1D559
+&iopf; U+1D55A
+&jopf; U+1D55B
+&kopf; U+1D55C
+&lopf; U+1D55D
+&mopf; U+1D55E
+&nopf; U+1D55F
+&oopf; U+1D560
+&popf; U+1D561
+&qopf; U+1D562
+&ropf; U+1D563
+&sopf; U+1D564
+&topf; U+1D565
+&uopf; U+1D566
+&vopf; U+1D567
+&wopf; U+1D568
+&xopf; U+1D569
+&yopf; U+1D56A
+&zopf; U+1D56B
+&nvlt; U+0003C U+020D2
+&bne; U+0003D U+020E5
+&nvgt; U+0003E U+020D2
+&fjlig; U+00066 U+0006A
+&ThickSpace; U+0205F U+0200A
+&nrarrw; U+0219D U+00338
+&npart; U+02202 U+00338
+&nang; U+02220 U+020D2
+&caps; U+02229 U+0FE00
+&cups; U+0222A U+0FE00
+&nvsim; U+0223C U+020D2
+&race; U+0223D U+00331
+&acE; U+0223E U+00333
+&nesim; U+02242 U+00338
+&napid; U+0224B U+00338
+&nvap; U+0224D U+020D2
+&nbump; U+0224E U+00338
+&nbumpe; U+0224F U+00338
+&nedot; U+02250 U+00338
+&bnequiv; U+02261 U+020E5
+&nvle; U+02264 U+020D2
+&nvge; U+02265 U+020D2
+&nlE; U+02266 U+00338
+&NotGreaterFullEqual; U+02267 U+00338
+&lvertneqq; U+02268 U+0FE00
+&gvertneqq; U+02269 U+0FE00
+&nLtv; U+0226A U+00338
+&nLt; U+0226A U+020D2
+&NotGreaterGreater; U+0226B U+00338
+&nGt; U+0226B U+020D2
+&NotSucceedsTilde; U+0227F U+00338
+&vnsub; U+02282 U+020D2
+&nsupset; U+02283 U+020D2
+&vsubne; U+0228A U+0FE00
+&vsupne; U+0228B U+0FE00
+&NotSquareSubset; U+0228F U+00338
+&NotSquareSuperset; U+02290 U+00338
+&sqcaps; U+02293 U+0FE00
+&sqcups; U+02294 U+0FE00
+&nvltrie; U+022B4 U+020D2
+&nvrtrie; U+022B5 U+020D2
+&nLl; U+022D8 U+00338
+&nGg; U+022D9 U+00338
+&lesg; U+022DA U+0FE00
+&gesl; U+022DB U+0FE00
+&notindot; U+022F5 U+00338
+&notinE; U+022F9 U+00338
+&nrarrc; U+02933 U+00338
+&NotLeftTriangleBar; U+029CF U+00338
+&NotRightTriangleBar; U+029D0 U+00338
+&ncongdot; U+02A6D U+00338
+&napE; U+02A70 U+00338
+&nles; U+02A7D U+00338
+&nges; U+02A7E U+00338
+&NotNestedLessLess; U+02AA1 U+00338
+&NotNestedGreaterGreater; U+02AA2 U+00338
+&smtes; U+02AAC U+0FE00
+&lates; U+02AAD U+0FE00
+&NotPrecedesEqual; U+02AAF U+00338
+&NotSucceedsEqual; U+02AB0 U+00338
+&nsubE; U+02AC5 U+00338
+&nsupseteqq; U+02AC6 U+00338
+&vsubnE; U+02ACB U+0FE00
+&varsupsetneqq; U+02ACC U+0FE00
+&varsupsetneqq; U+02AFD U+0FE00
diff --git a/ext/standard/tests/file/htmlspecialchars.phpt b/ext/standard/tests/strings/htmlspecialchars.phpt
index 5d741e5ecb..5d741e5ecb 100644
--- a/ext/standard/tests/file/htmlspecialchars.phpt
+++ b/ext/standard/tests/strings/htmlspecialchars.phpt
diff --git a/ext/standard/tests/strings/htmlspecialchars_decode_variation7.phpt b/ext/standard/tests/strings/htmlspecialchars_decode_variation7.phpt
new file mode 100644
index 0000000000..20669b3513
--- /dev/null
+++ b/ext/standard/tests/strings/htmlspecialchars_decode_variation7.phpt
@@ -0,0 +1,192 @@
+--TEST--
+Test htmlspecialchars_decode() function : usage variations - numerical entities for basic characters
+--FILE--
+<?php
+$tests = array(
+ "&quot;", "&#x22;", "&#34;",
+ "&apos;", "&#39;", "&#x27;",
+ "&amp;", "&#x26;", "&lt;",
+ "&gt;", "&#x3C;", "&#60;",
+ "&lt;", "&#x3E;", "&#62;",
+ "&#63;"
+);
+
+echo "*** HTML 4.01/ENT_QUOTES ***\n";
+
+foreach ($tests as $t) {
+ $dec = htmlspecialchars_decode($t, ENT_QUOTES | ENT_HTML401);
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** XHTML 1.0/ENT_QUOTES ***\n";
+
+foreach ($tests as $t) {
+ $dec = htmlspecialchars_decode($t, ENT_QUOTES | ENT_XHTML);
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** HTML5/ENT_QUOTES ***\n";
+
+foreach ($tests as $t) {
+ $dec = htmlspecialchars_decode($t, ENT_QUOTES | ENT_HTML5);
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** XML 1.0/ENT_QUOTES ***\n";
+
+foreach ($tests as $t) {
+ $dec = htmlspecialchars_decode($t, ENT_QUOTES | ENT_XML1);
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** HTML5/ENT_NOQUOTES ***\n";
+
+foreach ($tests as $t) {
+ $dec = htmlspecialchars_decode($t, ENT_NOQUOTES | ENT_HTML5);
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+echo "\n*** HTML5/ENT_COMPAT ***\n";
+
+foreach ($tests as $t) {
+ $dec = htmlspecialchars_decode($t, ENT_COMPAT | ENT_HTML5);
+ if ($t == $dec) {
+ echo "$t\tNOT DECODED\n";
+ } else {
+ echo "$t\tDECODED\n";
+ }
+}
+
+
+echo "\nDone.\n";
+?>
+--EXPECT--
+*** HTML 4.01/ENT_QUOTES ***
+&quot; DECODED
+&#x22; DECODED
+&#34; DECODED
+&apos; NOT DECODED
+&#39; DECODED
+&#x27; DECODED
+&amp; DECODED
+&#x26; DECODED
+&lt; DECODED
+&gt; DECODED
+&#x3C; DECODED
+&#60; DECODED
+&lt; DECODED
+&#x3E; DECODED
+&#62; DECODED
+&#63; NOT DECODED
+
+*** XHTML 1.0/ENT_QUOTES ***
+&quot; DECODED
+&#x22; DECODED
+&#34; DECODED
+&apos; DECODED
+&#39; DECODED
+&#x27; DECODED
+&amp; DECODED
+&#x26; DECODED
+&lt; DECODED
+&gt; DECODED
+&#x3C; DECODED
+&#60; DECODED
+&lt; DECODED
+&#x3E; DECODED
+&#62; DECODED
+&#63; NOT DECODED
+
+*** HTML5/ENT_QUOTES ***
+&quot; DECODED
+&#x22; DECODED
+&#34; DECODED
+&apos; DECODED
+&#39; DECODED
+&#x27; DECODED
+&amp; DECODED
+&#x26; DECODED
+&lt; DECODED
+&gt; DECODED
+&#x3C; DECODED
+&#60; DECODED
+&lt; DECODED
+&#x3E; DECODED
+&#62; DECODED
+&#63; NOT DECODED
+
+*** XML 1.0/ENT_QUOTES ***
+&quot; DECODED
+&#x22; DECODED
+&#34; DECODED
+&apos; DECODED
+&#39; DECODED
+&#x27; DECODED
+&amp; DECODED
+&#x26; DECODED
+&lt; DECODED
+&gt; DECODED
+&#x3C; DECODED
+&#60; DECODED
+&lt; DECODED
+&#x3E; DECODED
+&#62; DECODED
+&#63; NOT DECODED
+
+*** HTML5/ENT_NOQUOTES ***
+&quot; NOT DECODED
+&#x22; NOT DECODED
+&#34; NOT DECODED
+&apos; NOT DECODED
+&#39; NOT DECODED
+&#x27; NOT DECODED
+&amp; DECODED
+&#x26; DECODED
+&lt; DECODED
+&gt; DECODED
+&#x3C; DECODED
+&#60; DECODED
+&lt; DECODED
+&#x3E; DECODED
+&#62; DECODED
+&#63; NOT DECODED
+
+*** HTML5/ENT_COMPAT ***
+&quot; DECODED
+&#x22; DECODED
+&#34; DECODED
+&apos; NOT DECODED
+&#39; NOT DECODED
+&#x27; NOT DECODED
+&amp; DECODED
+&#x26; DECODED
+&lt; DECODED
+&gt; DECODED
+&#x3C; DECODED
+&#60; DECODED
+&lt; DECODED
+&#x3E; DECODED
+&#62; DECODED
+&#63; NOT DECODED
+
+Done.
diff --git a/ext/standard/tests/strings/http_build_query_error.phpt b/ext/standard/tests/strings/http_build_query_error.phpt
new file mode 100644
index 0000000000..30155e62a3
--- /dev/null
+++ b/ext/standard/tests/strings/http_build_query_error.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Testing error on null parameter 1 of http_build_query()
+--CREDITS--
+Pawel Krynicki <pawel.krynicki [at] xsolve [dot] pl>
+#testfest AmsterdamPHP 2012-06-23
+--FILE--
+<?php
+
+$result = http_build_query(null);
+
+?>
+--EXPECTF--
+Warning: http_build_query(): Parameter 1 expected to be Array or Object. %s value given in %s on line %d \ No newline at end of file
diff --git a/ext/standard/tests/strings/http_build_query_variation1.phpt b/ext/standard/tests/strings/http_build_query_variation1.phpt
new file mode 100644
index 0000000000..56d81c9fdd
--- /dev/null
+++ b/ext/standard/tests/strings/http_build_query_variation1.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test http_build_query() function: usage variations - first arguments as object
+--CREDITS--
+Adam Gegotek <adam [dot] gegotek [at] gmail [dot] com>
+--FILE--
+<?php
+/* Prototype : string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )
+ * Description: Generates a URL-encoded query string from the associative (or indexed) array provided.
+ * Source code: ext/standard/http.c
+*/
+
+class UrlBuilder
+{
+ public $name = 'homepage';
+ public $page = 1;
+ protected $sort = 'desc,name';
+ private $access = 'admin';
+}
+
+$obj = new stdClass;
+$obj->name = 'homepage';
+$obj->page = 1;
+$obj->sort = 'desc,name';
+
+echo http_build_query($obj) . PHP_EOL;
+echo http_build_query(new UrlBuilder());
+?>
+--EXPECTF--
+name=homepage&page=1&sort=desc%2Cname
+name=homepage&page=1
diff --git a/ext/standard/tests/strings/http_build_query_variation2.phpt b/ext/standard/tests/strings/http_build_query_variation2.phpt
new file mode 100644
index 0000000000..ca1d8f459a
--- /dev/null
+++ b/ext/standard/tests/strings/http_build_query_variation2.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Test http_build_query() function: usage variations - first arguments as multidimensional array and second argument present/not present
+--CREDITS--
+Adam Gegotek <adam [dot] gegotek [at] gmail [dot] com>
+--FILE--
+<?php
+/* Prototype : string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )
+ * Description: Generates a URL-encoded query string from the associative (or indexed) array provided.
+ * Source code: ext/standard/http.c
+*/
+
+$mDimensional = array(
+ 20,
+ 5 => 13,
+ "9" => array(
+ 1 => "val1",
+ 3 => "val2",
+ "string" => "string"
+ ),
+ "name" => "homepage",
+ "page" => 10,
+ "sort" => array(
+ "desc",
+ "admin" => array(
+ "admin1",
+ "admin2" => array(
+ "who" => "admin2",
+ 2 => "test"
+ )
+ )
+ )
+);
+
+echo http_build_query($mDimensional) . PHP_EOL;
+echo http_build_query($mDimensional, 'prefix_');
+?>
+--EXPECTF--
+0=20&5=13&9%5B1%5D=val1&9%5B3%5D=val2&9%5Bstring%5D=string&name=homepage&page=10&sort%5B0%5D=desc&sort%5Badmin%5D%5B0%5D=admin1&sort%5Badmin%5D%5Badmin2%5D%5Bwho%5D=admin2&sort%5Badmin%5D%5Badmin2%5D%5B2%5D=test
+prefix_0=20&prefix_5=13&prefix_9%5B1%5D=val1&prefix_9%5B3%5D=val2&prefix_9%5Bstring%5D=string&name=homepage&page=10&sort%5B0%5D=desc&sort%5Badmin%5D%5B0%5D=admin1&sort%5Badmin%5D%5Badmin2%5D%5Bwho%5D=admin2&sort%5Badmin%5D%5Badmin2%5D%5B2%5D=test
diff --git a/ext/standard/tests/strings/http_build_query_variation3.phpt b/ext/standard/tests/strings/http_build_query_variation3.phpt
new file mode 100644
index 0000000000..107120e084
--- /dev/null
+++ b/ext/standard/tests/strings/http_build_query_variation3.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test http_build_query() function: usage variations - testing four parameter added in PHP 5.4.0
+--CREDITS--
+Adam Gegotek <adam [dot] gegotek [at] gmail [dot] com>
+--SKIPIF--
+<?php
+ if (version_compare(PHP_VERSION, '5.4.0', '<')) die("skip this test if PHP_VERSION is less than 5.4.0");
+?>
+--FILE--
+<?php
+/* Prototype : string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )
+ * Description: Generates a URL-encoded query string from the associative (or indexed) array provided.
+ * Source code: ext/standard/http.c
+*/
+
+$oDimensional = array(
+ "name" => "main page",
+ "sort" => "desc,admin",
+ "equation" => "10 + 10 - 5"
+);
+
+echo http_build_query($oDimensional, '', ini_get('arg_separator.output'), PHP_QUERY_RFC1738) . PHP_EOL;
+echo http_build_query($oDimensional, '', ini_get('arg_separator.output'), PHP_QUERY_RFC3986);
+?>
+--EXPECTF--
+name=main+page&sort=desc%2Cadmin&equation=10+%2B+10+-+5
+name=main%20page&sort=desc%2Cadmin&equation=10%20%2B%2010%20-%205
diff --git a/ext/standard/tests/strings/md5_file.phpt b/ext/standard/tests/strings/md5_file.phpt
index e5d015cdd2..777140957c 100644
--- a/ext/standard/tests/strings/md5_file.phpt
+++ b/ext/standard/tests/strings/md5_file.phpt
Binary files differ
diff --git a/ext/standard/tests/strings/nl_langinfo_variation1.phpt b/ext/standard/tests/strings/nl_langinfo_variation1.phpt
index 41844697f1..98edb1ba1c 100644
--- a/ext/standard/tests/strings/nl_langinfo_variation1.phpt
+++ b/ext/standard/tests/strings/nl_langinfo_variation1.phpt
@@ -34,46 +34,22 @@ $file_handle = fopen(__FILE__, "r");
// array with different values for $input
$items = array (
-
// integer values
-/*1*/ 0,
- 10,
- 2147483647,
+/*1*/ 2147483647,
-2147483648,
+ -20,
- // float values
-/*5*/ 10.5,
- 20.3,
- -20.5,
- 10.1234567e5,
-
- // array values
-/*9*/ array(),
+ // array values
+/*4*/ array(),
array(0),
array(1, 2),
- // boolean values
-/*12*/ true,
- false,
- TRUE,
- FALSE,
-
- // null vlaues
-/*16*/ NULL,
- null,
-
// objects
-/*18*/ new sample(),
+/*7*/ new sample(),
// resource
-/*19*/ $file_handle,
-
- // undefined variable
-/*20*/ @$undefined_var,
-
- // unset variable
-/*21*/ @$unset_var
-);
+/*8*/ $file_handle,
+ );
//defining '$input' argument
$input = "Test string";
@@ -95,86 +71,34 @@ setlocale(LC_ALL, $original);
*** Testing nl_langinfo() : with unexpected inputs for 'item' argument ***
-- Iteration 1 --
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
--- Iteration 2 --
-
-Warning: nl_langinfo(): Item '10' is not valid in %s on line %d
-bool(false)
--- Iteration 3 --
-
Warning: nl_langinfo(): Item '2147483647' is not valid in %s on line %d
bool(false)
--- Iteration 4 --
+-- Iteration 2 --
Warning: nl_langinfo(): Item '-2147483648' is not valid in %s on line %d
bool(false)
--- Iteration 5 --
-
-Warning: nl_langinfo(): Item '10' is not valid in %s on line %d
-bool(false)
--- Iteration 6 --
-
-Warning: nl_langinfo(): Item '20' is not valid in %s on line %d
-bool(false)
--- Iteration 7 --
+-- Iteration 3 --
Warning: nl_langinfo(): Item '-20' is not valid in %s on line %d
bool(false)
--- Iteration 8 --
-
-Warning: nl_langinfo(): Item '1012345' is not valid in %s on line %d
-bool(false)
--- Iteration 9 --
+-- Iteration 4 --
Warning: nl_langinfo() expects parameter 1 to be long, array given in %s on line %d
NULL
--- Iteration 10 --
+-- Iteration 5 --
Warning: nl_langinfo() expects parameter 1 to be long, array given in %s on line %d
NULL
--- Iteration 11 --
+-- Iteration 6 --
Warning: nl_langinfo() expects parameter 1 to be long, array given in %s on line %d
NULL
--- Iteration 12 --
-
-Warning: nl_langinfo(): Item '1' is not valid in %s on line %d
-bool(false)
--- Iteration 13 --
-
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
--- Iteration 14 --
-
-Warning: nl_langinfo(): Item '1' is not valid in %s on line %d
-bool(false)
--- Iteration 15 --
-
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
--- Iteration 16 --
-
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
--- Iteration 17 --
-
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
--- Iteration 18 --
+-- Iteration 7 --
Warning: nl_langinfo() expects parameter 1 to be long, object given in %s on line %d
NULL
--- Iteration 19 --
+-- Iteration 8 --
Warning: nl_langinfo() expects parameter 1 to be long, resource given in %s on line %d
NULL
--- Iteration 20 --
-
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
--- Iteration 21 --
-
-Warning: nl_langinfo(): Item '0' is not valid in %s on line %d
-bool(false)
===DONE===
diff --git a/ext/standard/tests/strings/parse_str_basic3.phpt b/ext/standard/tests/strings/parse_str_basic3.phpt
index d8d556419e..619b1476ab 100644
--- a/ext/standard/tests/strings/parse_str_basic3.phpt
+++ b/ext/standard/tests/strings/parse_str_basic3.phpt
Binary files differ
diff --git a/ext/standard/tests/strings/print_variation1.phpt b/ext/standard/tests/strings/print_variation1.phpt
index 084f22f641..7c499f1084 100644
--- a/ext/standard/tests/strings/print_variation1.phpt
+++ b/ext/standard/tests/strings/print_variation1.phpt
@@ -109,12 +109,18 @@ int(1)
101234567000
int(1)
-- Iteration 9 --
+
+Notice: Array to string conversion in %sprint_variation1.php on line %d
Array
int(1)
-- Iteration 10 --
+
+Notice: Array to string conversion in %sprint_variation1.php on line %d
Array
int(1)
-- Iteration 11 --
+
+Notice: Array to string conversion in %sprint_variation1.php on line %d
Array
int(1)
-- Iteration 12 --
diff --git a/ext/standard/tests/strings/quoted_printable_encode_002.phpt b/ext/standard/tests/strings/quoted_printable_encode_002.phpt
index 5380eb0bff..aaf5608f33 100644
--- a/ext/standard/tests/strings/quoted_printable_encode_002.phpt
+++ b/ext/standard/tests/strings/quoted_printable_encode_002.phpt
Binary files differ
diff --git a/ext/standard/tests/strings/sha1_file.phpt b/ext/standard/tests/strings/sha1_file.phpt
index 574d384c20..fafe106d51 100644
--- a/ext/standard/tests/strings/sha1_file.phpt
+++ b/ext/standard/tests/strings/sha1_file.phpt
@@ -38,7 +38,7 @@ echo "\n-- No filename --\n";
var_dump( sha1_file("") );
echo "\n-- invalid filename --\n";
-var_dump( sha1_file("a") );
+var_dump( sha1_file("rewncwYcn89q") );
echo "\n-- Scalar value as filename --\n";
var_dump( sha1_file(12) );
@@ -82,7 +82,7 @@ bool(false)
-- invalid filename --
-Warning: sha1_file(a): failed to open stream: No such file or directory in %s on line %d
+Warning: sha1_file(rewncwYcn89q): failed to open stream: No such file or directory in %s on line %d
bool(false)
-- Scalar value as filename --
diff --git a/ext/standard/tests/strings/stripslashes_variation5.phpt b/ext/standard/tests/strings/stripslashes_variation5.phpt
deleted file mode 100644
index 0507e04960..0000000000
--- a/ext/standard/tests/strings/stripslashes_variation5.phpt
+++ /dev/null
Binary files differ
diff --git a/ext/standard/tests/strings/strrchr_variation5.phpt b/ext/standard/tests/strings/strrchr_variation5.phpt
index 88a4a84b01..1ef23911e9 100644
--- a/ext/standard/tests/strings/strrchr_variation5.phpt
+++ b/ext/standard/tests/strings/strrchr_variation5.phpt
@@ -34,17 +34,17 @@ echo "*** Done ***";
?>
--EXPECTF--
*** Testing strrchr() function: with heredoc strings ***
-string(33) " st ch using
-\escape \seque
+string(32) " st ch using
+scape \seque
ce"
string(9) "\seque
ce"
-string(25) " using
-\escape \seque
+string(24) " using
+scape \seque
ce"
string(9) "\seque
ce"
-string(33) " st ch using
-\escape \seque
+string(32) " st ch using
+scape \seque
ce"
*** Done ***
diff --git a/ext/standard/tests/strings/strspn_variation6.phpt b/ext/standard/tests/strings/strspn_variation6.phpt
index 3c3c1d8c37..413198d1c0 100644
--- a/ext/standard/tests/strings/strspn_variation6.phpt
+++ b/ext/standard/tests/strings/strspn_variation6.phpt
@@ -137,7 +137,7 @@ int(4)
int(0)
int(0)
int(0)
-int(4)
+int(1)
int(0)
int(4)
@@ -149,7 +149,7 @@ int(4)
int(0)
int(0)
int(0)
-int(4)
+int(1)
int(0)
int(4)
@@ -161,7 +161,7 @@ int(4)
int(0)
int(0)
int(0)
-int(4)
+int(1)
int(0)
int(4)
@@ -173,7 +173,7 @@ int(4)
int(0)
int(0)
int(0)
-int(4)
+int(1)
int(0)
int(4)
-Done \ No newline at end of file
+Done
diff --git a/ext/standard/tests/strings/strtok_variation6.phpt b/ext/standard/tests/strings/strtok_variation6.phpt
index 5a77f6f9e9..73ea3667eb 100644
--- a/ext/standard/tests/strings/strtok_variation6.phpt
+++ b/ext/standard/tests/strings/strtok_variation6.phpt
@@ -25,7 +25,7 @@ $token_array = array(
"/ ",
"/k",
"\k",
- "\\\\\\\k\h\e\l\o\w\r\l\d"
+ "\\\\\\\k\h\\e\l\o\w\r\l\d"
);
// loop through each element of the array and check the working of strtok()
diff --git a/ext/standard/tests/strings/strtolower.phpt b/ext/standard/tests/strings/strtolower.phpt
index f498a95f79..166b5ccc67 100644
--- a/ext/standard/tests/strings/strtolower.phpt
+++ b/ext/standard/tests/strings/strtolower.phpt
Binary files differ
diff --git a/ext/standard/tests/strings/strtoupper1.phpt b/ext/standard/tests/strings/strtoupper1.phpt
index 2890c02ccd..b83a8a3a5d 100644
--- a/ext/standard/tests/strings/strtoupper1.phpt
+++ b/ext/standard/tests/strings/strtoupper1.phpt
Binary files differ
diff --git a/ext/standard/tests/strings/strval.phpt b/ext/standard/tests/strings/strval.phpt
index 3f8b5cc985..b837a079d4 100644
--- a/ext/standard/tests/strings/strval.phpt
+++ b/ext/standard/tests/strings/strval.phpt
@@ -13,7 +13,7 @@ var_dump(strval(true));
var_dump(strval(false));
var_dump(strval(array('foo')));
?>
---EXPECT--
+--EXPECTF--
string(3) "bar"
string(3) "BAR"
string(6) "foobar"
@@ -21,4 +21,6 @@ string(1) "1"
string(3) "1.1"
string(1) "1"
string(0) ""
+
+Notice: Array to string conversion in %sstrval.php on line %d
string(5) "Array"
diff --git a/ext/standard/tests/strings/substr_compare.phpt b/ext/standard/tests/strings/substr_compare.phpt
index 206ccd5ede..c647506b53 100644
--- a/ext/standard/tests/strings/substr_compare.phpt
+++ b/ext/standard/tests/strings/substr_compare.phpt
@@ -27,7 +27,7 @@ int(-1)
Warning: substr_compare(): The start position cannot exceed initial string length in %s on line %d
bool(false)
-int(0)
+int(-1)
Warning: substr_compare() expects parameter 5 to be boolean, object given in %s on line %d
bool(false)
diff --git a/ext/standard/tests/time/strptime_basic.phpt b/ext/standard/tests/time/strptime_basic.phpt
index a3fa435d8c..194a78f82b 100644
--- a/ext/standard/tests/time/strptime_basic.phpt
+++ b/ext/standard/tests/time/strptime_basic.phpt
@@ -5,6 +5,7 @@ Test strptime() function : basic functionality
if (!function_exists('strptime')) {
die("skip - strptime() function not available in this build");
}
+ if(PHP_OS == 'Darwin') die("skip - strptime() behaves differently on Darwin");
?>
--FILE--
diff --git a/ext/standard/tests/time/strptime_parts.phpt b/ext/standard/tests/time/strptime_parts.phpt
new file mode 100644
index 0000000000..fbe684b863
--- /dev/null
+++ b/ext/standard/tests/time/strptime_parts.phpt
@@ -0,0 +1,76 @@
+--TEST--
+Test strptime() function : basic functionality
+--SKIPIF--
+<?php
+ if (!function_exists('strptime')) {
+ die("skip - strptime() function not available in this build");
+ }
+?>
+
+--FILE--
+<?php
+/* Prototype : array strptime ( string $date , string $format )
+ * Description: Parse a time/date generated with strftime()
+ * Source code: ext/standard/datetime.c
+*/
+
+$orig = setlocale(LC_ALL, 'C');
+date_default_timezone_set("GMT");
+putenv("TZ=GMT");
+
+echo "*** Testing strptime() : basic functionality ***\n";
+
+$input = "10:01:20 AM July 2 1963";
+$tstamp = strtotime($input);
+
+$str = strftime("%r %B%e %Y %Z", $tstamp);
+$res = strptime($str, '%H:%M:%S %p %B %d %Y %Z');
+var_dump($res["tm_sec"]);
+var_dump($res["tm_min"]);
+var_dump($res["tm_hour"]);
+var_dump($res["tm_mday"]);
+var_dump($res["tm_mon"]);
+var_dump($res["tm_year"]);
+
+$str = strftime("%T %D", $tstamp);
+$res = strptime($str, '%H:%M:%S %m/%d/%y');
+var_dump($res["tm_sec"]);
+var_dump($res["tm_min"]);
+var_dump($res["tm_hour"]);
+var_dump($res["tm_mday"]);
+var_dump($res["tm_mon"]);
+var_dump($res["tm_year"]);
+
+$str = strftime("%A %B %e %R", $tstamp);
+$res = strptime($str, '%A %B %e %R');
+var_dump($res["tm_sec"]);
+var_dump($res["tm_min"]);
+var_dump($res["tm_hour"]);
+var_dump($res["tm_mday"]);
+var_dump($res["tm_mon"]);
+var_dump($res["tm_year"]);
+
+setlocale(LC_ALL, $orig);
+?>
+===DONE===
+--EXPECT--
+*** Testing strptime() : basic functionality ***
+int(20)
+int(1)
+int(10)
+int(2)
+int(6)
+int(63)
+int(20)
+int(1)
+int(10)
+int(2)
+int(6)
+int(163)
+int(0)
+int(1)
+int(10)
+int(2)
+int(6)
+int(0)
+===DONE===
diff --git a/ext/standard/tests/url/base64_encode_variation_001.phpt b/ext/standard/tests/url/base64_encode_variation_001.phpt
index 30da145a8b..f632bebf5d 100644
--- a/ext/standard/tests/url/base64_encode_variation_001.phpt
+++ b/ext/standard/tests/url/base64_encode_variation_001.phpt
@@ -109,22 +109,27 @@ string(20) "MS4wNzY1NDMyMUUtOQ=="
Arg value 0.5
string(4) "MC41"
+Error: 8 - Array to string conversion, %sbase64_encode_variation_001.php(%d)
Arg value Array
Error: 2 - base64_encode() expects parameter 1 to be string, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sbase64_encode_variation_001.php(%d)
Arg value Array
Error: 2 - base64_encode() expects parameter 1 to be string, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sbase64_encode_variation_001.php(%d)
Arg value Array
Error: 2 - base64_encode() expects parameter 1 to be string, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sbase64_encode_variation_001.php(%d)
Arg value Array
Error: 2 - base64_encode() expects parameter 1 to be string, array given, %s(73)
NULL
+Error: 8 - Array to string conversion, %sbase64_encode_variation_001.php(%d)
Arg value Array
Error: 2 - base64_encode() expects parameter 1 to be string, array given, %s(73)
diff --git a/ext/standard/tests/url/bug63162.phpt b/ext/standard/tests/url/bug63162.phpt
new file mode 100644
index 0000000000..ea5205efd6
--- /dev/null
+++ b/ext/standard/tests/url/bug63162.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Test parse_url() for bug #63162
+--DESCRIPTION--
+This test covers tests the inputs:
+[0]=> http://user:pass@host
+[1]=> //user:pass@host
+[2]=> //user@host
+--FILE--
+<?php
+var_dump(parse_url('http://user:pass@host'));
+var_dump(parse_url('//user:pass@host'));
+var_dump(parse_url('//user@host'));
+?>
+--EXPECT--
+array(4) {
+ ["scheme"]=>
+ string(4) "http"
+ ["host"]=>
+ string(4) "host"
+ ["user"]=>
+ string(4) "user"
+ ["pass"]=>
+ string(4) "pass"
+}
+array(3) {
+ ["host"]=>
+ string(4) "host"
+ ["user"]=>
+ string(4) "user"
+ ["pass"]=>
+ string(4) "pass"
+}
+array(2) {
+ ["host"]=>
+ string(4) "host"
+ ["user"]=>
+ string(4) "user"
+}
diff --git a/ext/standard/tests/url/parse_url_relative_scheme.phpt b/ext/standard/tests/url/parse_url_relative_scheme.phpt
new file mode 100644
index 0000000000..7c8952db71
--- /dev/null
+++ b/ext/standard/tests/url/parse_url_relative_scheme.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Test parse_url() function: Checks relative URL schemes (e.g. "//example.com")
+--FILE--
+<?php
+var_dump(parse_url('//example.org'));
+--EXPECT--
+array(1) {
+ ["host"]=>
+ string(11) "example.org"
+}
+
diff --git a/ext/standard/tests/url/parse_url_variation_001.phpt b/ext/standard/tests/url/parse_url_variation_001.phpt
index 18ef0a547b..0b804eed57 100644
--- a/ext/standard/tests/url/parse_url_variation_001.phpt
+++ b/ext/standard/tests/url/parse_url_variation_001.phpt
@@ -133,22 +133,27 @@ array(1) {
["path"]=>
string(3) "0.5"
}
+Error: 8 - Array to string conversion, %sparse_url_variation_001.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 1 to be string, array given, %s(70)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_001.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 1 to be string, array given, %s(70)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_001.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 1 to be string, array given, %s(70)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_001.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 1 to be string, array given, %s(70)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_001.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 1 to be string, array given, %s(70)
diff --git a/ext/standard/tests/url/parse_url_variation_002_32bit.phpt b/ext/standard/tests/url/parse_url_variation_002_32bit.phpt
index 88971e9642..aefb37a117 100644
--- a/ext/standard/tests/url/parse_url_variation_002_32bit.phpt
+++ b/ext/standard/tests/url/parse_url_variation_002_32bit.phpt
@@ -132,22 +132,27 @@ string(4) "http"
Arg value 0.5
string(4) "http"
+Error: 8 - Array to string conversion, %sparse_url_variation_002_32bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_32bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_32bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_32bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_32bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
diff --git a/ext/standard/tests/url/parse_url_variation_002_64bit.phpt b/ext/standard/tests/url/parse_url_variation_002_64bit.phpt
index 74ea7965cf..35a600cdba 100644
--- a/ext/standard/tests/url/parse_url_variation_002_64bit.phpt
+++ b/ext/standard/tests/url/parse_url_variation_002_64bit.phpt
@@ -116,22 +116,27 @@ string(4) "http"
Arg value 0.5
string(4) "http"
+Error: 8 - Array to string conversion, %sparse_url_variation_002_64bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_64bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_64bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_64bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
NULL
+Error: 8 - Array to string conversion, %sparse_url_variation_002_64bit.php(%d)
Arg value Array
Error: 2 - parse_url() expects parameter 2 to be long, array given, %s(71)
diff --git a/ext/standard/tests/url/rawurldecode_variation_001.phpt b/ext/standard/tests/url/rawurldecode_variation_001.phpt
index 4942e8b357..9527fe6062 100644
--- a/ext/standard/tests/url/rawurldecode_variation_001.phpt
+++ b/ext/standard/tests/url/rawurldecode_variation_001.phpt
@@ -110,22 +110,27 @@ string(13) "1.07654321E-9"
Arg value 0.5
string(3) "0.5"
+Error: 8 - Array to string conversion, %srawurldecode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurldecode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurldecode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurldecode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurldecode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurldecode() expects parameter 1 to be string, array given, %s(74)
diff --git a/ext/standard/tests/url/rawurlencode_variation_001.phpt b/ext/standard/tests/url/rawurlencode_variation_001.phpt
index d90825ba7f..a3443361ec 100644
--- a/ext/standard/tests/url/rawurlencode_variation_001.phpt
+++ b/ext/standard/tests/url/rawurlencode_variation_001.phpt
@@ -110,22 +110,27 @@ string(13) "1.07654321E-9"
Arg value 0.5
string(3) "0.5"
+Error: 8 - Array to string conversion, %srawurlencode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurlencode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurlencode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurlencode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %srawurlencode_variation_001.php(%d)
Arg value Array
Error: 2 - rawurlencode() expects parameter 1 to be string, array given, %s(74)
diff --git a/ext/standard/tests/url/urldecode_variation_001.phpt b/ext/standard/tests/url/urldecode_variation_001.phpt
index 7ebc7bdbef..42026d103c 100644
--- a/ext/standard/tests/url/urldecode_variation_001.phpt
+++ b/ext/standard/tests/url/urldecode_variation_001.phpt
@@ -110,22 +110,27 @@ string(13) "1.07654321E-9"
Arg value 0.5
string(3) "0.5"
+Error: 8 - Array to string conversion, %surldecode_variation_001.php(%d)
Arg value Array
Error: 2 - urldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surldecode_variation_001.php(%d)
Arg value Array
Error: 2 - urldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surldecode_variation_001.php(%d)
Arg value Array
Error: 2 - urldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surldecode_variation_001.php(%d)
Arg value Array
Error: 2 - urldecode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surldecode_variation_001.php(%d)
Arg value Array
Error: 2 - urldecode() expects parameter 1 to be string, array given, %s(74)
diff --git a/ext/standard/tests/url/urlencode_variation_001.phpt b/ext/standard/tests/url/urlencode_variation_001.phpt
index 1f82b65f38..04d0921b2c 100644
--- a/ext/standard/tests/url/urlencode_variation_001.phpt
+++ b/ext/standard/tests/url/urlencode_variation_001.phpt
@@ -110,22 +110,27 @@ string(13) "1.07654321E-9"
Arg value 0.5
string(3) "0.5"
+Error: 8 - Array to string conversion, %surlencode_variation_001.php(%d)
Arg value Array
Error: 2 - urlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surlencode_variation_001.php(%d)
Arg value Array
Error: 2 - urlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surlencode_variation_001.php(%d)
Arg value Array
Error: 2 - urlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surlencode_variation_001.php(%d)
Arg value Array
Error: 2 - urlencode() expects parameter 1 to be string, array given, %s(74)
NULL
+Error: 8 - Array to string conversion, %surlencode_variation_001.php(%d)
Arg value Array
Error: 2 - urlencode() expects parameter 1 to be string, array given, %s(74)
diff --git a/ext/standard/type.c b/ext/standard/type.c
index 062574c984..543fdeac10 100644
--- a/ext/standard/type.c
+++ b/ext/standard/type.c
@@ -72,8 +72,8 @@ PHP_FUNCTION(gettype)
case IS_RESOURCE:
{
- char *type_name;
- type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);
+
if (type_name) {
RETVAL_STRING("resource", 1);
break;
@@ -219,8 +219,7 @@ static void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
}
}
if (type == IS_RESOURCE) {
- char *type_name;
- type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);
if (!type_name) {
RETURN_FALSE;
}
diff --git a/ext/standard/url.c b/ext/standard/url.c
index 2525afb905..c159322837 100644
--- a/ext/standard/url.c
+++ b/ext/standard/url.c
@@ -201,9 +201,13 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
STR_FREE(ret->scheme);
efree(ret);
return NULL;
+ } else if (*s == '/' && *(s+1) == '/') { /* relative-scheme URL */
+ s += 2;
} else {
goto just_path;
}
+ } else if (*s == '/' && *(s+1) == '/') { /* relative-scheme URL */
+ s += 2;
} else {
just_path:
ue = s + length;
@@ -706,7 +710,7 @@ PHP_FUNCTION(get_headers)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &url, &url_len, &format) == FAILURE) {
return;
}
- context = FG(default_context) ? FG(default_context) : (FG(default_context) = php_stream_context_alloc());
+ context = FG(default_context) ? FG(default_context) : (FG(default_context) = php_stream_context_alloc(TSRMLS_C));
if (!(stream = php_stream_open_wrapper_ex(url, "r", REPORT_ERRORS | STREAM_USE_URL | STREAM_ONLY_GET_HEADERS, NULL, context))) {
RETURN_FALSE;
diff --git a/ext/standard/url.h b/ext/standard/url.h
index e2914939e6..3eaca4834f 100644
--- a/ext/standard/url.h
+++ b/ext/standard/url.h
@@ -55,6 +55,9 @@ PHP_FUNCTION(get_headers);
#define PHP_URL_QUERY 6
#define PHP_URL_FRAGMENT 7
+#define PHP_QUERY_RFC1738 1
+#define PHP_QUERY_RFC3986 2
+
#endif /* URL_H */
/*
diff --git a/ext/standard/url_scanner_ex.c b/ext/standard/url_scanner_ex.c
index 943242f343..1ec269de30 100644
--- a/ext/standard/url_scanner_ex.c
+++ b/ext/standard/url_scanner_ex.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Fri Dec 31 23:52:51 2010 */
+/* Generated by re2c 0.13.5 on Mon May 23 12:29:55 2011 */
#line 1 "ext/standard/url_scanner_ex.re"
/*
+----------------------------------------------------------------------+
@@ -312,7 +312,7 @@ static void handle_form(STD_PARA)
static inline void handle_tag(STD_PARA)
{
int ok = 0;
- int i;
+ unsigned int i;
ctx->tag.len = 0;
smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
@@ -996,7 +996,7 @@ static void php_url_scanner_output_handler(char *output, uint output_len, char *
size_t len;
if (BG(url_adapt_state_ex).url_app.len != 0) {
- *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT) ? 1 : 0) TSRMLS_CC);
+ *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT | PHP_OUTPUT_HANDLER_FLUSH | PHP_OUTPUT_HANDLER_FINAL) ? 1 : 0) TSRMLS_CC);
if (sizeof(uint) < sizeof(size_t)) {
if (len > UINT_MAX)
len = UINT_MAX;
@@ -1015,7 +1015,7 @@ static void php_url_scanner_output_handler(char *output, uint output_len, char *
ctx->result.len = 0;
smart_str_free(&ctx->buf);
} else {
- *handled_output = NULL;
+ *handled_output = estrndup(output, *handled_output_len = output_len);
}
} else {
*handled_output = NULL;
@@ -1030,7 +1030,7 @@ PHPAPI int php_url_scanner_add_var(char *name, int name_len, char *value, int va
if (! BG(url_adapt_state_ex).active) {
php_url_scanner_ex_activate(TSRMLS_C);
- php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC);
+ php_output_start_internal(ZEND_STRL("URL-Rewriter"), php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
BG(url_adapt_state_ex).active = 1;
}
diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re
index fdc61033d2..2e37cf0ba4 100644
--- a/ext/standard/url_scanner_ex.re
+++ b/ext/standard/url_scanner_ex.re
@@ -249,7 +249,7 @@ static void handle_form(STD_PARA)
static inline void handle_tag(STD_PARA)
{
int ok = 0;
- int i;
+ unsigned int i;
ctx->tag.len = 0;
smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
@@ -435,7 +435,7 @@ static void php_url_scanner_output_handler(char *output, uint output_len, char *
size_t len;
if (BG(url_adapt_state_ex).url_app.len != 0) {
- *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT) ? 1 : 0) TSRMLS_CC);
+ *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT | PHP_OUTPUT_HANDLER_FLUSH | PHP_OUTPUT_HANDLER_FINAL) ? 1 : 0) TSRMLS_CC);
if (sizeof(uint) < sizeof(size_t)) {
if (len > UINT_MAX)
len = UINT_MAX;
@@ -454,7 +454,7 @@ static void php_url_scanner_output_handler(char *output, uint output_len, char *
ctx->result.len = 0;
smart_str_free(&ctx->buf);
} else {
- *handled_output = NULL;
+ *handled_output = estrndup(output, *handled_output_len = output_len);
}
} else {
*handled_output = NULL;
@@ -469,7 +469,7 @@ PHPAPI int php_url_scanner_add_var(char *name, int name_len, char *value, int va
if (! BG(url_adapt_state_ex).active) {
php_url_scanner_ex_activate(TSRMLS_C);
- php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC);
+ php_output_start_internal(ZEND_STRL("URL-Rewriter"), php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
BG(url_adapt_state_ex).active = 1;
}
diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c
index d2189beda5..bcc484205c 100644
--- a/ext/standard/user_filters.c
+++ b/ext/standard/user_filters.c
@@ -259,7 +259,7 @@ php_stream_filter_status_t userfilter_filter(
* from being destroyed properly */
INIT_ZVAL(zpropname);
ZVAL_STRINGL(&zpropname, "stream", sizeof("stream")-1, 0);
- Z_OBJ_HANDLER_P(obj, unset_property)(obj, &zpropname TSRMLS_CC);
+ Z_OBJ_HANDLER_P(obj, unset_property)(obj, &zpropname, 0 TSRMLS_CC);
zval_ptr_dtor(&zclosing);
zval_ptr_dtor(&zconsumed);
@@ -544,7 +544,8 @@ PHP_FUNCTION(stream_bucket_new)
PHP_FUNCTION(stream_get_filters)
{
char *filter_name;
- int key_flags, filter_name_len = 0;
+ int key_flags;
+ uint filter_name_len = 0;
HashTable *filters_hash;
ulong num_key;
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 9934125dfa..a4fa262e76 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -12,7 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Jani Lehtimäki <jkl@njet.net> |
+ | Authors: Jani Lehtimäki <jkl@njet.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Sascha Schumann <sascha@schumann.cx> |
+----------------------------------------------------------------------+
@@ -56,7 +56,7 @@ static int php_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list arg
static int php_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
int level;
- char *prop_name, *class_name;
+ const char *prop_name, *class_name;
level = va_arg(args, int);
@@ -87,7 +87,7 @@ static int php_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list a
PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
{
HashTable *myht;
- char *class_name;
+ const char *class_name;
zend_uint class_name_len;
int (*php_element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
int is_temp;
@@ -133,9 +133,13 @@ PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
return;
}
- Z_OBJ_HANDLER(**struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
- php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0);
- efree(class_name);
+ if (Z_OBJ_HANDLER(**struc, get_class_name)) {
+ Z_OBJ_HANDLER(**struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
+ php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0);
+ efree((char*)class_name);
+ } else {
+ php_printf("%sobject(unknown class)#%d (%d) {\n", COMMON, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0);
+ }
php_element_dump_func = php_object_property_dump;
head_done:
if (myht) {
@@ -152,9 +156,7 @@ head_done:
PUTS("}\n");
break;
case IS_RESOURCE: {
- char *type_name;
-
- type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
php_printf("%sresource(%ld) of type (%s)\n", COMMON, Z_LVAL_PP(struc), type_name ? type_name : "Unknown");
break;
}
@@ -211,7 +213,7 @@ static int zval_array_element_dump(zval **zv TSRMLS_DC, int num_args, va_list ar
static int zval_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
int level;
- char *prop_name, *class_name;
+ const char *prop_name, *class_name;
level = va_arg(args, int);
@@ -240,7 +242,7 @@ static int zval_object_property_dump(zval **zv TSRMLS_DC, int num_args, va_list
PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
{
HashTable *myht = NULL;
- char *class_name;
+ const char *class_name;
zend_uint class_name_len;
int (*zval_element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
int is_temp = 0;
@@ -282,13 +284,9 @@ PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
PUTS("*RECURSION*\n");
return;
}
- if (Z_OBJ_HANDLER_PP(struc, get_class_name)) {
- Z_OBJ_HANDLER_PP(struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
- php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_PP(struc));
- efree(class_name);
- } else {
- php_printf("%sobject(unknown class)#%d (%d) refcount(%u){\n", COMMON, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_PP(struc));
- }
+ Z_OBJ_HANDLER_PP(struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
+ php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name, Z_OBJ_HANDLE_PP(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_PP(struc));
+ efree((char*)class_name);
zval_element_dump_func = zval_object_property_dump;
head_done:
if (myht) {
@@ -304,9 +302,7 @@ head_done:
PUTS("}\n");
break;
case IS_RESOURCE: {
- char *type_name;
-
- type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(struc) TSRMLS_CC);
php_printf("%sresource(%ld) of type (%s) refcount(%u)\n", COMMON, Z_LVAL_PP(struc), type_name ? type_name : "Unknown", Z_REFCOUNT_PP(struc));
break;
}
@@ -357,6 +353,7 @@ static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list a
buffer_append_spaces(buf, level+1);
smart_str_append_long(buf, (long) hash_key->h);
smart_str_appendl(buf, " => ", 4);
+
} else { /* string key */
char *key, *tmp_str;
int key_len, tmp_len;
@@ -376,7 +373,7 @@ static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list a
smart_str_appendc(buf, ',');
smart_str_appendc(buf, '\n');
-
+
return 0;
}
/* }}} */
@@ -391,9 +388,9 @@ static int php_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list
buffer_append_spaces(buf, level + 2);
if (hash_key->nKeyLength != 0) {
- char *class_name, /* ignored, but must be passed to unmangle */
- *pname,
- *pname_esc;
+ const char *class_name; /* ignored, but must be passed to unmangle */
+ const char *pname;
+ char *pname_esc;
int pname_esc_len;
zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1,
@@ -406,14 +403,12 @@ static int php_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list
smart_str_appendc(buf, '\'');
efree(pname_esc);
} else {
- smart_str_append_long(buf, hash_key->h);
+ smart_str_append_long(buf, (long) hash_key->h);
}
-
smart_str_appendl(buf, " => ", 4);
php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
smart_str_appendc(buf, ',');
smart_str_appendc(buf, '\n');
-
return 0;
}
/* }}} */
@@ -423,16 +418,16 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
HashTable *myht;
char *tmp_str, *tmp_str2;
int tmp_len, tmp_len2;
- char *class_name;
+ const char *class_name;
zend_uint class_name_len;
switch (Z_TYPE_PP(struc)) {
case IS_BOOL:
- if (Z_LVAL_PP(struc)) {
- smart_str_appendl(buf, "true", 4);
- } else {
- smart_str_appendl(buf, "false", 5);
- }
+ if (Z_LVAL_PP(struc)) {
+ smart_str_appendl(buf, "true", 4);
+ } else {
+ smart_str_appendl(buf, "false", 5);
+ }
break;
case IS_NULL:
smart_str_appendl(buf, "NULL", 4);
@@ -458,6 +453,11 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
break;
case IS_ARRAY:
myht = Z_ARRVAL_PP(struc);
+ if(myht && myht->nApplyCount > 0){
+ smart_str_appendl(buf, "NULL", 4);
+ zend_error(E_WARNING, "var_export does not handle circular references");
+ return;
+ }
if (level > 1) {
smart_str_appendc(buf, '\n');
buffer_append_spaces(buf, level - 1);
@@ -469,10 +469,16 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
buffer_append_spaces(buf, level - 1);
}
smart_str_appendc(buf, ')');
-
+
break;
+
case IS_OBJECT:
myht = Z_OBJPROP_PP(struc);
+ if(myht && myht->nApplyCount > 0){
+ smart_str_appendl(buf, "NULL", 4);
+ zend_error(E_WARNING, "var_export does not handle circular references");
+ return;
+ }
if (level > 1) {
smart_str_appendc(buf, '\n');
buffer_append_spaces(buf, level - 1);
@@ -482,9 +488,9 @@ PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC)
smart_str_appendl(buf, class_name, class_name_len);
smart_str_appendl(buf, "::__set_state(array(\n", 21);
- efree(class_name);
+ efree((char*)class_name);
if (myht) {
- zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_object_element_export, 2, level, buf);
+ zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_object_element_export, 1, level, buf);
}
if (level > 1) {
buffer_append_spaces(buf, level - 1);
@@ -510,6 +516,7 @@ PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) /* {{{ */
}
/* }}} */
+
/* {{{ proto mixed var_export(mixed var [, bool return])
Outputs or returns a string representation of a variable */
PHP_FUNCTION(var_export)
@@ -561,12 +568,18 @@ static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old
var_no = -1;
zend_hash_next_index_insert(var_hash, &var_no, sizeof(var_no), NULL);
}
+#if 0
+ fprintf(stderr, "- had var (%d): %lu\n", Z_TYPE_P(var), **(ulong**)var_old);
+#endif
return FAILURE;
}
/* +1 because otherwise hash will think we are trying to store NULL pointer */
var_no = zend_hash_num_elements(var_hash) + 1;
zend_hash_add(var_hash, p, len, &var_no, sizeof(var_no), NULL);
+#if 0
+ fprintf(stderr, "+ add var (%d): %lu\n", Z_TYPE_P(var), var_no);
+#endif
return SUCCESS;
}
/* }}} */
@@ -784,7 +797,9 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
if (ce && ce != PHP_IC_ENTRY && zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) {
INIT_PZVAL(&fname);
ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0);
+ BG(serialize_lock)++;
res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
+ BG(serialize_lock)--;
if (res == SUCCESS && !EG(exception)) {
if (retval_ptr) {
@@ -879,9 +894,9 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, HashTable *var
}
/* }}} */
-PHPAPI void php_var_serialize(smart_str *buf, zval **struc, HashTable *var_hash TSRMLS_DC) /* {{{ */
+PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash TSRMLS_DC) /* {{{ */
{
- php_var_serialize_intern(buf, *struc, var_hash TSRMLS_CC);
+ php_var_serialize_intern(buf, *struc, *var_hash TSRMLS_CC);
smart_str_0(buf);
}
/* }}} */
diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c
index 5102b198c0..2537c5213b 100644
--- a/ext/standard/var_unserializer.c
+++ b/ext/standard/var_unserializer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Wed Sep 28 15:40:15 2011 */
+/* Generated by re2c 0.13.5 on Wed Nov 9 19:37:48 2011 */
#line 1 "ext/standard/var_unserializer.re"
/*
+----------------------------------------------------------------------+
@@ -35,22 +35,23 @@ typedef struct {
static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
{
- var_entries *var_hash = var_hashx->first, *prev = NULL;
-
- while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
- prev = var_hash;
- var_hash = var_hash->next;
- }
+ var_entries *var_hash = (*var_hashx)->last;
+#if 0
+ fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
+#endif
- if (!var_hash) {
+ if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = emalloc(sizeof(var_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
- if (!var_hashx->first)
- var_hashx->first = var_hash;
- else
- prev->next = var_hash;
+ if (!(*var_hashx)->first) {
+ (*var_hashx)->first = var_hash;
+ } else {
+ ((var_entries *) (*var_hashx)->last)->next = var_hash;
+ }
+
+ (*var_hashx)->last = var_hash;
}
var_hash->data[var_hash->used_slots++] = *rval;
@@ -58,22 +59,23 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
{
- var_entries *var_hash = var_hashx->first_dtor, *prev = NULL;
-
- while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
- prev = var_hash;
- var_hash = var_hash->next;
- }
+ var_entries *var_hash = (*var_hashx)->last_dtor;
+#if 0
+ fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
+#endif
- if (!var_hash) {
+ if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = emalloc(sizeof(var_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
- if (!var_hashx->first_dtor)
- var_hashx->first_dtor = var_hash;
- else
- prev->next = var_hash;
+ if (!(*var_hashx)->first_dtor) {
+ (*var_hashx)->first_dtor = var_hash;
+ } else {
+ ((var_entries *) (*var_hashx)->last_dtor)->next = var_hash;
+ }
+
+ (*var_hashx)->last_dtor = var_hash;
}
Z_ADDREF_PP(rval);
@@ -83,7 +85,10 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval)
{
long i;
- var_entries *var_hash = var_hashx->first;
+ var_entries *var_hash = (*var_hashx)->first;
+#if 0
+ fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
+#endif
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
@@ -98,8 +103,11 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n
static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store)
{
- var_entries *var_hash = var_hashx->first;
-
+ var_entries *var_hash = (*var_hashx)->first;
+#if 0
+ fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
+#endif
+
while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = var_hash->next;
id -= VAR_ENTRIES_MAX;
@@ -118,7 +126,10 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
{
void *next;
long i;
- var_entries *var_hash = var_hashx->first;
+ var_entries *var_hash = (*var_hashx)->first;
+#if 0
+ fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
+#endif
while (var_hash) {
next = var_hash->next;
@@ -126,7 +137,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
var_hash = next;
}
- var_hash = var_hashx->first_dtor;
+ var_hash = (*var_hashx)->first_dtor;
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
@@ -190,7 +201,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
#define YYMARKER marker
-#line 198 "ext/standard/var_unserializer.re"
+#line 209 "ext/standard/var_unserializer.re"
@@ -364,6 +375,9 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
return elements;
}
+#ifdef PHP_WIN32
+# pragma optimize("", off)
+#endif
static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
{
zval *retval_ptr = NULL;
@@ -377,7 +391,9 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) {
INIT_PZVAL(&fname);
ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0);
+ BG(serialize_lock)++;
call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
+ BG(serialize_lock)--;
}
if (retval_ptr)
@@ -386,13 +402,21 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
+#ifdef PHP_WIN32
+# pragma optimize("", on)
+#endif
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
zval **rval_ref;
- limit = cursor = *p;
+ limit = max;
+ cursor = *p;
+
+ if (YYCURSOR >= YYLIMIT) {
+ return 0;
+ }
if (var_hash && cursor[0] != 'R') {
var_push(var_hash, rval);
@@ -403,7 +427,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
-#line 407 "ext/standard/var_unserializer.c"
+#line 425 "ext/standard/var_unserializer.c"
{
YYCTYPE yych;
static const unsigned char yybm[] = {
@@ -463,9 +487,9 @@ yy2:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy95;
yy3:
-#line 729 "ext/standard/var_unserializer.re"
+#line 747 "ext/standard/var_unserializer.re"
{ return 0; }
-#line 469 "ext/standard/var_unserializer.c"
+#line 487 "ext/standard/var_unserializer.c"
yy4:
yych = *(YYMARKER = ++YYCURSOR);
if (yych == ':') goto yy89;
@@ -508,13 +532,13 @@ yy13:
goto yy3;
yy14:
++YYCURSOR;
-#line 723 "ext/standard/var_unserializer.re"
+#line 741 "ext/standard/var_unserializer.re"
{
/* this is the case where we have less data than planned */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
return 0; /* not sure if it should be 0 or 1 here? */
}
-#line 518 "ext/standard/var_unserializer.c"
+#line 536 "ext/standard/var_unserializer.c"
yy16:
yych = *++YYCURSOR;
goto yy3;
@@ -544,7 +568,7 @@ yy20:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 606 "ext/standard/var_unserializer.re"
+#line 624 "ext/standard/var_unserializer.re"
{
size_t len, len2, len3, maxlen;
long elements;
@@ -596,10 +620,13 @@ yy20:
do {
/* Try to find class directly */
+ BG(serialize_lock) = 1;
if (zend_lookup_class(class_name, len2, &pce TSRMLS_CC) == SUCCESS) {
+ BG(serialize_lock) = 0;
ce = *pce;
break;
}
+ BG(serialize_lock) = 0;
/* Check for unserialize callback */
if ((PG(unserialize_callback_func) == NULL) || (PG(unserialize_callback_func)[0] == '\0')) {
@@ -614,7 +641,9 @@ yy20:
args[0] = &arg_func_name;
MAKE_STD_ZVAL(arg_func_name);
ZVAL_STRING(arg_func_name, class_name, 1);
+ BG(serialize_lock) = 1;
if (call_user_function_ex(CG(function_table), NULL, user_func, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) != SUCCESS) {
+ BG(serialize_lock) = 0;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "defined (%s) but not found", user_func->value.str.val);
incomplete_class = 1;
ce = PHP_IC_ENTRY;
@@ -622,6 +651,7 @@ yy20:
zval_ptr_dtor(&arg_func_name);
break;
}
+ BG(serialize_lock) = 0;
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
@@ -661,7 +691,7 @@ yy20:
return object_common2(UNSERIALIZE_PASSTHRU, elements);
}
-#line 665 "ext/standard/var_unserializer.c"
+#line 683 "ext/standard/var_unserializer.c"
yy25:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -686,7 +716,7 @@ yy27:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 598 "ext/standard/var_unserializer.re"
+#line 616 "ext/standard/var_unserializer.re"
{
INIT_PZVAL(*rval);
@@ -694,7 +724,7 @@ yy27:
return object_common2(UNSERIALIZE_PASSTHRU,
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
}
-#line 698 "ext/standard/var_unserializer.c"
+#line 716 "ext/standard/var_unserializer.c"
yy32:
yych = *++YYCURSOR;
if (yych == '+') goto yy33;
@@ -715,7 +745,7 @@ yy34:
yych = *++YYCURSOR;
if (yych != '{') goto yy18;
++YYCURSOR;
-#line 578 "ext/standard/var_unserializer.re"
+#line 596 "ext/standard/var_unserializer.re"
{
long elements = parse_iv(start + 2);
/* use iv() not uiv() in order to check data range */
@@ -735,7 +765,7 @@ yy34:
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
-#line 739 "ext/standard/var_unserializer.c"
+#line 757 "ext/standard/var_unserializer.c"
yy39:
yych = *++YYCURSOR;
if (yych == '+') goto yy40;
@@ -756,7 +786,7 @@ yy41:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 549 "ext/standard/var_unserializer.re"
+#line 567 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -785,7 +815,7 @@ yy41:
ZVAL_STRINGL(*rval, str, len, 0);
return 1;
}
-#line 789 "ext/standard/var_unserializer.c"
+#line 807 "ext/standard/var_unserializer.c"
yy46:
yych = *++YYCURSOR;
if (yych == '+') goto yy47;
@@ -806,7 +836,7 @@ yy48:
yych = *++YYCURSOR;
if (yych != '"') goto yy18;
++YYCURSOR;
-#line 521 "ext/standard/var_unserializer.re"
+#line 539 "ext/standard/var_unserializer.re"
{
size_t len, maxlen;
char *str;
@@ -834,7 +864,7 @@ yy48:
ZVAL_STRINGL(*rval, str, len, 1);
return 1;
}
-#line 838 "ext/standard/var_unserializer.c"
+#line 856 "ext/standard/var_unserializer.c"
yy53:
yych = *++YYCURSOR;
if (yych <= '/') {
@@ -922,7 +952,7 @@ yy61:
}
yy63:
++YYCURSOR;
-#line 511 "ext/standard/var_unserializer.re"
+#line 529 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
use_double:
@@ -932,7 +962,7 @@ use_double:
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
return 1;
}
-#line 936 "ext/standard/var_unserializer.c"
+#line 954 "ext/standard/var_unserializer.c"
yy65:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -991,7 +1021,7 @@ yy73:
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 496 "ext/standard/var_unserializer.re"
+#line 514 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
@@ -1006,7 +1036,7 @@ yy73:
return 1;
}
-#line 1010 "ext/standard/var_unserializer.c"
+#line 1028 "ext/standard/var_unserializer.c"
yy76:
yych = *++YYCURSOR;
if (yych == 'N') goto yy73;
@@ -1033,7 +1063,7 @@ yy79:
if (yych <= '9') goto yy79;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 469 "ext/standard/var_unserializer.re"
+#line 487 "ext/standard/var_unserializer.re"
{
#if SIZEOF_LONG == 4
int digits = YYCURSOR - start - 3;
@@ -1060,7 +1090,7 @@ yy79:
ZVAL_LONG(*rval, parse_iv(start + 2));
return 1;
}
-#line 1064 "ext/standard/var_unserializer.c"
+#line 1082 "ext/standard/var_unserializer.c"
yy83:
yych = *++YYCURSOR;
if (yych <= '/') goto yy18;
@@ -1068,24 +1098,24 @@ yy83:
yych = *++YYCURSOR;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 462 "ext/standard/var_unserializer.re"
+#line 480 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_BOOL(*rval, parse_iv(start + 2));
return 1;
}
-#line 1079 "ext/standard/var_unserializer.c"
+#line 1097 "ext/standard/var_unserializer.c"
yy87:
++YYCURSOR;
-#line 455 "ext/standard/var_unserializer.re"
+#line 473 "ext/standard/var_unserializer.re"
{
*p = YYCURSOR;
INIT_PZVAL(*rval);
ZVAL_NULL(*rval);
return 1;
}
-#line 1089 "ext/standard/var_unserializer.c"
+#line 1107 "ext/standard/var_unserializer.c"
yy89:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1108,7 +1138,7 @@ yy91:
if (yych <= '9') goto yy91;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 432 "ext/standard/var_unserializer.re"
+#line 450 "ext/standard/var_unserializer.re"
{
long id;
@@ -1131,7 +1161,7 @@ yy91:
return 1;
}
-#line 1135 "ext/standard/var_unserializer.c"
+#line 1153 "ext/standard/var_unserializer.c"
yy95:
yych = *++YYCURSOR;
if (yych <= ',') {
@@ -1154,7 +1184,7 @@ yy97:
if (yych <= '9') goto yy97;
if (yych != ';') goto yy18;
++YYCURSOR;
-#line 411 "ext/standard/var_unserializer.re"
+#line 429 "ext/standard/var_unserializer.re"
{
long id;
@@ -1175,9 +1205,9 @@ yy97:
return 1;
}
-#line 1179 "ext/standard/var_unserializer.c"
+#line 1197 "ext/standard/var_unserializer.c"
}
-#line 731 "ext/standard/var_unserializer.re"
+#line 749 "ext/standard/var_unserializer.re"
return 0;
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index 83bf6c0d93..860b3947b9 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -33,22 +33,23 @@ typedef struct {
static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
{
- var_entries *var_hash = var_hashx->first, *prev = NULL;
-
- while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
- prev = var_hash;
- var_hash = var_hash->next;
- }
+ var_entries *var_hash = (*var_hashx)->last;
+#if 0
+ fprintf(stderr, "var_push(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
+#endif
- if (!var_hash) {
+ if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = emalloc(sizeof(var_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
- if (!var_hashx->first)
- var_hashx->first = var_hash;
- else
- prev->next = var_hash;
+ if (!(*var_hashx)->first) {
+ (*var_hashx)->first = var_hash;
+ } else {
+ ((var_entries *) (*var_hashx)->last)->next = var_hash;
+ }
+
+ (*var_hashx)->last = var_hash;
}
var_hash->data[var_hash->used_slots++] = *rval;
@@ -56,22 +57,23 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval **rval)
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
{
- var_entries *var_hash = var_hashx->first_dtor, *prev = NULL;
-
- while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
- prev = var_hash;
- var_hash = var_hash->next;
- }
+ var_entries *var_hash = (*var_hashx)->last_dtor;
+#if 0
+ fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
+#endif
- if (!var_hash) {
+ if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = emalloc(sizeof(var_entries));
var_hash->used_slots = 0;
var_hash->next = 0;
- if (!var_hashx->first_dtor)
- var_hashx->first_dtor = var_hash;
- else
- prev->next = var_hash;
+ if (!(*var_hashx)->first_dtor) {
+ (*var_hashx)->first_dtor = var_hash;
+ } else {
+ ((var_entries *) (*var_hashx)->last_dtor)->next = var_hash;
+ }
+
+ (*var_hashx)->last_dtor = var_hash;
}
Z_ADDREF_PP(rval);
@@ -81,7 +83,10 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **nzval)
{
long i;
- var_entries *var_hash = var_hashx->first;
+ var_entries *var_hash = (*var_hashx)->first;
+#if 0
+ fprintf(stderr, "var_replace(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(nzval));
+#endif
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
@@ -96,8 +101,11 @@ PHPAPI void var_replace(php_unserialize_data_t *var_hashx, zval *ozval, zval **n
static int var_access(php_unserialize_data_t *var_hashx, long id, zval ***store)
{
- var_entries *var_hash = var_hashx->first;
-
+ var_entries *var_hash = (*var_hashx)->first;
+#if 0
+ fprintf(stderr, "var_access(%ld): %ld\n", var_hash?var_hash->used_slots:-1L, id);
+#endif
+
while (id >= VAR_ENTRIES_MAX && var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) {
var_hash = var_hash->next;
id -= VAR_ENTRIES_MAX;
@@ -116,7 +124,10 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
{
void *next;
long i;
- var_entries *var_hash = var_hashx->first;
+ var_entries *var_hash = (*var_hashx)->first;
+#if 0
+ fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L);
+#endif
while (var_hash) {
next = var_hash->next;
@@ -124,7 +135,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
var_hash = next;
}
- var_hash = var_hashx->first_dtor;
+ var_hash = (*var_hashx)->first_dtor;
while (var_hash) {
for (i = 0; i < var_hash->used_slots; i++) {
@@ -368,6 +379,9 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce)
return elements;
}
+#ifdef PHP_WIN32
+# pragma optimize("", off)
+#endif
static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
{
zval *retval_ptr = NULL;
@@ -381,7 +395,9 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) {
INIT_PZVAL(&fname);
ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1, 0);
+ BG(serialize_lock)++;
call_user_function_ex(CG(function_table), rval, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
+ BG(serialize_lock)--;
}
if (retval_ptr)
@@ -390,13 +406,21 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements)
return finish_nested_data(UNSERIALIZE_PASSTHRU);
}
+#ifdef PHP_WIN32
+# pragma optimize("", on)
+#endif
PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
{
const unsigned char *cursor, *limit, *marker, *start;
zval **rval_ref;
- limit = cursor = *p;
+ limit = max;
+ cursor = *p;
+
+ if (YYCURSOR >= YYLIMIT) {
+ return 0;
+ }
if (var_hash && cursor[0] != 'R') {
var_push(var_hash, rval);
diff --git a/ext/standard/winver.h b/ext/standard/winver.h
index cb469a91c0..7152d60811 100644
--- a/ext/standard/winver.h
+++ b/ext/standard/winver.h
@@ -1,6 +1,15 @@
#ifndef _PHP_WINVER_H
#define _PHP_WINVER_H
+#ifndef SM_TABLETPC
+#define SM_TABLETPC 86
+#endif
+#ifndef SM_MEDIACENTER
+#define SM_MEDIACENTER 87
+#endif
+#ifndef SM_STARTER
+#define SM_STARTER 88
+#endif
#ifndef SM_SERVERR2
#define SM_SERVERR2 89
#endif
diff --git a/ext/sybase_ct/php_sybase_ct.c b/ext/sybase_ct/php_sybase_ct.c
index cb1753564b..a24e6677a2 100644
--- a/ext/sybase_ct/php_sybase_ct.c
+++ b/ext/sybase_ct/php_sybase_ct.c
@@ -1191,11 +1191,10 @@ static int php_sybase_finish_results(sybase_result *result TSRMLS_DC)
ZVAL_STRINGL(&result, buf, length- 1, 1); \
}
-static int php_sybase_fetch_result_row (sybase_result *result, int numrows)
+static int php_sybase_fetch_result_row(sybase_result *result, int numrows TSRMLS_DC)
{
int i, j;
CS_INT retcode;
- TSRMLS_FETCH();
/* We've already fetched everything */
if (result->last_retcode == CS_END_DATA || result->last_retcode == CS_END_RESULTS) {
@@ -1294,7 +1293,7 @@ static int php_sybase_fetch_result_row (sybase_result *result, int numrows)
return retcode;
}
-static sybase_result * php_sybase_fetch_result_set (sybase_link *sybase_ptr, int buffered, int store)
+static sybase_result * php_sybase_fetch_result_set(sybase_link *sybase_ptr, int buffered, int store TSRMLS_DC)
{
int num_fields;
sybase_result *result;
@@ -1413,7 +1412,7 @@ static sybase_result * php_sybase_fetch_result_set (sybase_link *sybase_ptr, int
if (buffered) {
retcode = CS_SUCCEED;
} else {
- if ((retcode = php_sybase_fetch_result_row(result, -1)) == CS_FAIL) {
+ if ((retcode = php_sybase_fetch_result_row(result, -1 TSRMLS_CC)) == CS_FAIL) {
return NULL;
}
}
@@ -1550,7 +1549,7 @@ static void php_sybase_query (INTERNAL_FUNCTION_PARAMETERS, int buffered)
case CS_PARAM_RESULT:
case CS_ROW_RESULT:
case CS_STATUS_RESULT:
- result = php_sybase_fetch_result_set(sybase_ptr, buffered, store);
+ result = php_sybase_fetch_result_set(sybase_ptr, buffered, store TSRMLS_CC);
if (result == NULL) {
ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
RETURN_FALSE;
@@ -1576,7 +1575,7 @@ static void php_sybase_query (INTERNAL_FUNCTION_PARAMETERS, int buffered)
case CS_PARAM_RESULT:
case CS_ROW_RESULT:
if (status != Q_RESULT) {
- result = php_sybase_fetch_result_set(sybase_ptr, buffered, store);
+ result = php_sybase_fetch_result_set(sybase_ptr, buffered, store TSRMLS_CC);
if (result == NULL) {
ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
sybase_ptr->dead = 1;
@@ -1768,7 +1767,7 @@ PHP_FUNCTION(sybase_fetch_row)
/* Unbuffered? */
if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS) {
- php_sybase_fetch_result_row(result, 1);
+ php_sybase_fetch_result_row(result, 1 TSRMLS_CC);
}
/* At the end? */
@@ -1804,7 +1803,7 @@ static void php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int numerics)
/* Unbuffered ? Fetch next row */
if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS) {
- php_sybase_fetch_result_row(result, 1);
+ php_sybase_fetch_result_row(result, 1 TSRMLS_CC);
}
/* At the end? */
@@ -1819,11 +1818,7 @@ static void php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int numerics)
ALLOC_ZVAL(tmp);
*tmp = result->data[result->store ? result->cur_row : 0][i];
INIT_PZVAL(tmp);
- if (PG(magic_quotes_runtime) && Z_TYPE_P(tmp) == IS_STRING) {
- Z_STRVAL_P(tmp) = php_addslashes(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &Z_STRLEN_P(tmp), 0 TSRMLS_CC);
- } else {
- zval_copy_ctor(tmp);
- }
+ zval_copy_ctor(tmp);
if (numerics) {
zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *) &tmp, sizeof(zval *), NULL);
Z_ADDREF_P(tmp);
@@ -1922,7 +1917,7 @@ PHP_FUNCTION(sybase_data_seek)
/* Unbuffered ? */
if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && offset >= result->num_rows) {
- php_sybase_fetch_result_row(result, offset+ 1);
+ php_sybase_fetch_result_row(result, offset+ 1 TSRMLS_CC);
}
if (offset < 0 || offset >= result->num_rows) {
@@ -2056,7 +2051,7 @@ PHP_FUNCTION(sybase_result)
/* Unbuffered ? */
if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && row >= result->num_rows) {
- php_sybase_fetch_result_row(result, row);
+ php_sybase_fetch_result_row(result, row TSRMLS_CC);
}
if (row < 0 || row >= result->num_rows) {
diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c
index bf99fb053e..6360183f00 100644
--- a/ext/sysvmsg/sysvmsg.c
+++ b/ext/sysvmsg/sysvmsg.c
@@ -271,7 +271,7 @@ PHP_FUNCTION(msg_get_queue)
RETURN_FALSE;
}
}
- RETVAL_RESOURCE(zend_list_insert(mq, le_sysvmsg));
+ RETVAL_RESOURCE(zend_list_insert(mq, le_sysvmsg TSRMLS_CC));
}
/* }}} */
diff --git a/ext/sysvmsg/tests/006.phpt b/ext/sysvmsg/tests/006.phpt
index 675e5e114b..cb4fd2457e 100644
--- a/ext/sysvmsg/tests/006.phpt
+++ b/ext/sysvmsg/tests/006.phpt
@@ -10,7 +10,7 @@ $queue = msg_get_queue (ftok(__FILE__, 'r'), 0600);
$tests = array('foo', 123, PHP_INT_MAX +1, true, 1.01, null, array('bar'));
foreach ($tests as $elem) {
- echo "Sending/receiving '$elem':\n";
+ echo @"Sending/receiving '$elem':\n";
var_dump(msg_send($queue, 1, $elem, false));
unset($msg);
diff --git a/ext/sysvsem/tests/sysv.phpt b/ext/sysvsem/tests/sysv.phpt
index 4245d8ef0c..3a962be31a 100644
--- a/ext/sysvsem/tests/sysv.phpt
+++ b/ext/sysvsem/tests/sysv.phpt
@@ -6,8 +6,6 @@ if(!extension_loaded('sysvsem') || !extension_loaded('sysvshm')) {
die("skip Both sysvsem and sysvshm required");
}
?>
---INI--
-magic_quotes_runtime=0
--FILE--
<?php
$MEMSIZE = 512; // size of shared memory to allocate
diff --git a/ext/tidy/examples/cleanhtml.php b/ext/tidy/examples/cleanhtml.php
index 9a6713dc55..2644210cbf 100644
--- a/ext/tidy/examples/cleanhtml.php
+++ b/ext/tidy/examples/cleanhtml.php
@@ -26,7 +26,7 @@
if(tidy_warning_count() ||
tidy_error_count()) {
- echo "\n\nThe following errors or warnings occured:\n";
+ echo "\n\nThe following errors or warnings occurred:\n";
echo tidy_get_error_buffer();
echo "\n";
}
diff --git a/ext/tidy/examples/cleanhtml5.php b/ext/tidy/examples/cleanhtml5.php
index 4dfd7643e1..2ce683acad 100644
--- a/ext/tidy/examples/cleanhtml5.php
+++ b/ext/tidy/examples/cleanhtml5.php
@@ -25,7 +25,7 @@
if(!empty($tidy->errorBuffer)) {
- echo "\n\nThe following errors or warnings occured:\n";
+ echo "\n\nThe following errors or warnings occurred:\n";
echo "{$tidy->errorBuffer}\n";
}
diff --git a/ext/tidy/php_tidy.h b/ext/tidy/php_tidy.h
index e19de5b7bd..5ec65bb227 100644
--- a/ext/tidy/php_tidy.h
+++ b/ext/tidy/php_tidy.h
@@ -36,6 +36,7 @@ extern zend_module_entry tidy_module_entry;
ZEND_BEGIN_MODULE_GLOBALS(tidy)
char *default_config;
+ zend_bool clean_output;
ZEND_END_MODULE_GLOBALS(tidy)
#ifdef ZTS
diff --git a/ext/tidy/tests/019.phpt b/ext/tidy/tests/019.phpt
index 91bbc016ed..5e9c38d75a 100644
--- a/ext/tidy/tests/019.phpt
+++ b/ext/tidy/tests/019.phpt
@@ -38,5 +38,5 @@ Warning: tidy_repair_file(): Filename cannot be empty in %s on line %d
Warning: tidy_repair_file(): Filename cannot be empty in %s on line %d
-Warning: tidy_repair_file() expects parameter 1 to be string, array given in %s on line %d
+Warning: tidy_repair_file() expects parameter 1 to be a valid path, array given in %s on line %d
Done
diff --git a/ext/tidy/tests/022.phpt b/ext/tidy/tests/022.phpt
index 91bbc016ed..5e9c38d75a 100644
--- a/ext/tidy/tests/022.phpt
+++ b/ext/tidy/tests/022.phpt
@@ -38,5 +38,5 @@ Warning: tidy_repair_file(): Filename cannot be empty in %s on line %d
Warning: tidy_repair_file(): Filename cannot be empty in %s on line %d
-Warning: tidy_repair_file() expects parameter 1 to be string, array given in %s on line %d
+Warning: tidy_repair_file() expects parameter 1 to be a valid path, array given in %s on line %d
Done
diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c
index 529929342f..72d8f5db66 100644
--- a/ext/tidy/tidy.c
+++ b/ext/tidy/tidy.c
@@ -29,7 +29,6 @@
#include "php_ini.h"
#include "ext/standard/info.h"
-#include "safe_mode.h"
#include "tidy.h"
#include "buffio.h"
@@ -43,6 +42,8 @@
/* {{{ ext/tidy macros
*/
+#define FIX_BUFFER(bptr) do { if ((bptr)->size) { (bptr)->bp[(bptr)->size-1] = '\0'; } } while(0)
+
#define TIDY_SET_CONTEXT \
zval *object = getThis();
@@ -74,7 +75,7 @@
_php_tidy_apply_config_array(_doc, HASH_OF(*_val) TSRMLS_CC); \
} else { \
convert_to_string_ex(_val); \
- TIDY_SAFE_MODE_CHECK(Z_STRVAL_PP(_val)); \
+ TIDY_OPEN_BASE_DIR_CHECK(Z_STRVAL_PP(_val)); \
switch (tidyLoadConfig(_doc, Z_STRVAL_PP(_val))) { \
case -1: \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s'", Z_STRVAL_PP(_val)); \
@@ -156,8 +157,8 @@
zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
}
-#define TIDY_SAFE_MODE_CHECK(filename) \
-if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) { \
+#define TIDY_OPEN_BASE_DIR_CHECK(filename) \
+if (php_check_open_basedir(filename TSRMLS_CC)) { \
RETURN_FALSE; \
} \
@@ -187,17 +188,17 @@ typedef enum {
} tidy_base_nodetypes;
struct _PHPTidyDoc {
- TidyDoc doc;
- TidyBuffer *errbuf;
- unsigned int ref_count;
- unsigned int initialized:1;
+ TidyDoc doc;
+ TidyBuffer *errbuf;
+ unsigned int ref_count;
+ unsigned int initialized:1;
};
struct _PHPTidyObj {
- zend_object std;
- TidyNode node;
- tidy_obj_type type;
- PHPTidyDoc *ptdoc;
+ zend_object std;
+ TidyNode node;
+ tidy_obj_type type;
+ PHPTidyDoc *ptdoc;
};
/* }}} */
@@ -218,6 +219,10 @@ static int _php_tidy_set_tidy_opt(TidyDoc, char *, zval * TSRMLS_DC);
static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options TSRMLS_DC);
static void _php_tidy_register_nodetypes(INIT_FUNC_ARGS);
static void _php_tidy_register_tags(INIT_FUNC_ARGS);
+static PHP_INI_MH(php_tidy_set_clean_output);
+static void php_tidy_clean_output_start(const char *name, size_t name_len TSRMLS_DC);
+static php_output_handler *php_tidy_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC);
+static int php_tidy_output_handler(void **nothing, php_output_context *output_context);
static PHP_MINIT_FUNCTION(tidy);
static PHP_MSHUTDOWN_FUNCTION(tidy);
@@ -247,8 +252,6 @@ static PHP_FUNCTION(tidy_warning_count);
static PHP_FUNCTION(tidy_access_count);
static PHP_FUNCTION(tidy_config_count);
-static PHP_FUNCTION(ob_tidyhandler);
-
static PHP_FUNCTION(tidy_get_root);
static PHP_FUNCTION(tidy_get_html);
static PHP_FUNCTION(tidy_get_head);
@@ -273,8 +276,8 @@ static TIDY_NODE_METHOD(__construct);
ZEND_DECLARE_MODULE_GLOBALS(tidy)
PHP_INI_BEGIN()
-STD_PHP_INI_ENTRY("tidy.default_config", "", PHP_INI_SYSTEM, OnUpdateString, default_config, zend_tidy_globals, tidy_globals)
-PHP_INI_ENTRY("tidy.clean_output", "0", PHP_INI_PERDIR, NULL)
+STD_PHP_INI_ENTRY("tidy.default_config", "", PHP_INI_SYSTEM, OnUpdateString, default_config, zend_tidy_globals, tidy_globals)
+STD_PHP_INI_ENTRY("tidy.clean_output", "0", PHP_INI_USER, php_tidy_set_clean_output, clean_output, zend_tidy_globals, tidy_globals)
PHP_INI_END()
/* {{{ arginfo */
@@ -284,8 +287,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_parse_string, 0, 0, 1)
ZEND_ARG_INFO(0, encoding)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_get_error_buffer, 0, 0, 0)
- ZEND_ARG_INFO(0, detailed)
+ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_error_buffer, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_output, 0)
@@ -370,11 +372,6 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_get_body, 0, 0, 1)
ZEND_ARG_INFO(0, tidy)
ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_tidyhandler, 0, 0, 1)
- ZEND_ARG_INFO(0, input)
- ZEND_ARG_INFO(0, mode)
-ZEND_END_ARG_INFO()
/* }}} */
static const zend_function_entry tidy_functions[] = {
@@ -404,7 +401,6 @@ static const zend_function_entry tidy_functions[] = {
PHP_FE(tidy_get_head, arginfo_tidy_get_head)
PHP_FE(tidy_get_html, arginfo_tidy_get_html)
PHP_FE(tidy_get_body, arginfo_tidy_get_body)
- PHP_FE(ob_tidyhandler, arginfo_ob_tidyhandler)
PHP_FE_END
};
@@ -563,18 +559,17 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil
TidyBuffer *errbuf;
zval **config = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &arg1, &arg1_len, &config, &enc, &enc_len, &use_include_path) == FAILURE) {
- RETURN_FALSE;
- }
-
if (is_file) {
- if (strlen(arg1) != arg1_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|Zsb", &arg1, &arg1_len, &config, &enc, &enc_len, &use_include_path) == FAILURE) {
RETURN_FALSE;
}
if (!(data = php_tidy_file_to_mem(arg1, use_include_path, &data_len TSRMLS_CC))) {
RETURN_FALSE;
}
} else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &arg1, &arg1_len, &config, &enc, &enc_len, &use_include_path) == FAILURE) {
+ RETURN_FALSE;
+ }
data = arg1;
data_len = arg1_len;
}
@@ -610,7 +605,7 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil
TidyBuffer buf;
tidyBufInit(&buf);
- tidyBufAppend(&buf, data, data_len);
+ tidyBufAttach(&buf, (byte *) data, data_len);
if (tidyParseBuffer(doc, &buf) < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf->bp);
@@ -621,20 +616,19 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil
tidyBufInit(&output);
tidySaveBuffer (doc, &output);
- RETVAL_STRINGL((char*)output.bp, output.size ? output.size-1 : 0, 1);
+ FIX_BUFFER(&output);
+ RETVAL_STRINGL((char *) output.bp, output.size ? output.size-1 : 0, 1);
tidyBufFree(&output);
} else {
RETVAL_FALSE;
}
}
-
- tidyBufFree(&buf);
}
if (is_file) {
efree(data);
}
-
+
tidyBufFree(errbuf);
efree(errbuf);
tidyRelease(doc);
@@ -645,10 +639,10 @@ static char *php_tidy_file_to_mem(char *filename, zend_bool use_include_path, in
php_stream *stream;
char *data = NULL;
- if (!(stream = php_stream_open_wrapper(filename, "rb", (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE, NULL))) {
+ if (!(stream = php_stream_open_wrapper(filename, "rb", (use_include_path ? USE_PATH : 0), NULL))) {
return NULL;
}
- if ((*len = (int) php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0)) == 0) {
+ if ((*len = (int) php_stream_copy_to_mem(stream, (void*) &data, PHP_STREAM_COPY_ALL, 0)) == 0) {
data = estrdup("");
*len = 0;
}
@@ -681,24 +675,17 @@ static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *
zend_object_value *retval, tidy_obj_type objtype TSRMLS_DC)
{
PHPTidyObj *intern;
- zval *tmp;
intern = emalloc(sizeof(PHPTidyObj));
memset(intern, 0, sizeof(PHPTidyObj));
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
switch(objtype) {
case is_node:
break;
case is_doc:
- tidySetMallocCall(php_tidy_malloc);
- tidySetReallocCall(php_tidy_realloc);
- tidySetFreeCall(php_tidy_free);
- tidySetPanicCall(php_tidy_panic);
-
intern->ptdoc = emalloc(sizeof(PHPTidyDoc));
intern->ptdoc->doc = tidyCreate();
intern->ptdoc->ref_count = 1;
@@ -722,9 +709,6 @@ static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *
tidy_add_default_properties(intern, is_doc TSRMLS_CC);
break;
-
- default:
- break;
}
retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) tidy_object_free_storage, NULL TSRMLS_CC);
@@ -780,7 +764,7 @@ static int tidy_doc_cast_handler(zval *in, zval *out, int type TSRMLS_DC)
obj = (PHPTidyObj *)zend_object_store_get_object(in TSRMLS_CC);
tidyBufInit(&output);
tidySaveBuffer (obj->ptdoc->doc, &output);
- ZVAL_STRINGL(out, (char*)output.bp, output.size ? output.size-1 : 0, TRUE);
+ ZVAL_STRINGL(out, (char *) output.bp, output.size ? output.size-1 : 0, 1);
tidyBufFree(&output);
break;
@@ -814,8 +798,10 @@ static int tidy_node_cast_handler(zval *in, zval *out, int type TSRMLS_DC)
tidyBufInit(&buf);
if (obj->ptdoc) {
tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf);
+ ZVAL_STRINGL(out, (char *) buf.bp, buf.size-1, 1);
+ } else {
+ ZVAL_EMPTY_STRING(out);
}
- ZVAL_STRINGL(out, (char*)buf.bp, buf.size ? buf.size-1 : 0, TRUE);
tidyBufFree(&buf);
break;
@@ -836,6 +822,9 @@ static void tidy_doc_update_properties(PHPTidyObj *obj TSRMLS_DC)
tidySaveBuffer (obj->ptdoc->doc, &output);
if (output.size) {
+ if (!obj->std.properties) {
+ rebuild_object_properties(&obj->std);
+ }
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, (char*)output.bp, output.size-1, TRUE);
zend_hash_update(obj->std.properties, "value", sizeof("value"), (void *)&temp, sizeof(zval *), NULL);
@@ -844,6 +833,9 @@ static void tidy_doc_update_properties(PHPTidyObj *obj TSRMLS_DC)
tidyBufFree(&output);
if (obj->ptdoc->errbuf->size) {
+ if (!obj->std.properties) {
+ rebuild_object_properties(&obj->std);
+ }
MAKE_STD_ZVAL(temp);
ZVAL_STRINGL(temp, (char*)obj->ptdoc->errbuf->bp, obj->ptdoc->errbuf->size-1, TRUE);
zend_hash_update(obj->std.properties, "errorBuffer", sizeof("errorBuffer"), (void *)&temp, sizeof(zval *), NULL);
@@ -862,9 +854,12 @@ static void tidy_add_default_properties(PHPTidyObj *obj, tidy_obj_type type TSRM
switch(type) {
case is_node:
+ if (!obj->std.properties) {
+ rebuild_object_properties(&obj->std);
+ }
tidyBufInit(&buf);
tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf);
- ADD_PROPERTY_STRINGL(obj->std.properties, value, buf.bp, buf.size-1);
+ ADD_PROPERTY_STRINGL(obj->std.properties, value, buf.bp, buf.size ? buf.size-1 : 0);
tidyBufFree(&buf);
ADD_PROPERTY_STRING(obj->std.properties, name, tidyNodeGetName(obj->node));
@@ -931,6 +926,9 @@ static void tidy_add_default_properties(PHPTidyObj *obj, tidy_obj_type type TSRM
break;
case is_doc:
+ if (!obj->std.properties) {
+ rebuild_object_properties(&obj->std);
+ }
ADD_PROPERTY_NULL(obj->std.properties, errorBuffer);
ADD_PROPERTY_NULL(obj->std.properties, value);
break;
@@ -1009,24 +1007,33 @@ static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetyp
static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options TSRMLS_DC)
{
- char *opt_name = NULL;
+ char *opt_name;
zval **opt_val;
ulong opt_indx;
-
+ uint opt_name_len;
+ zend_bool clear_str;
+
for (zend_hash_internal_pointer_reset(ht_options);
- zend_hash_get_current_data(ht_options, (void **)&opt_val) == SUCCESS;
+ zend_hash_get_current_data(ht_options, (void *) &opt_val) == SUCCESS;
zend_hash_move_forward(ht_options)) {
-
- if(zend_hash_get_current_key(ht_options, &opt_name, &opt_indx, FALSE) == FAILURE) {
+
+ switch (zend_hash_get_current_key_ex(ht_options, &opt_name, &opt_name_len, &opt_indx, FALSE, NULL)) {
+ case HASH_KEY_IS_STRING:
+ clear_str = 0;
+ break;
+
+ case HASH_KEY_IS_LONG:
+ continue; /* ignore numeric keys */
+
+ default:
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not retrieve key from option array");
return FAILURE;
}
- if(opt_name) {
- _php_tidy_set_tidy_opt(doc, opt_name, *opt_val TSRMLS_CC);
- opt_name = NULL;
+ _php_tidy_set_tidy_opt(doc, opt_name, *opt_val TSRMLS_CC);
+ if (clear_str) {
+ efree(opt_name);
}
-
}
return SUCCESS;
@@ -1035,7 +1042,7 @@ static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options TSRML
static int php_tidy_parse_string(PHPTidyObj *obj, char *string, int len, char *enc TSRMLS_DC)
{
TidyBuffer buf;
-
+
if(enc) {
if (tidySetCharEncoding(obj->ptdoc->doc, enc) < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not set encoding '%s'", enc);
@@ -1046,14 +1053,11 @@ static int php_tidy_parse_string(PHPTidyObj *obj, char *string, int len, char *e
obj->ptdoc->initialized = 1;
tidyBufInit(&buf);
- tidyBufAppend(&buf, string, len);
+ tidyBufAttach(&buf, (byte *) string, len);
if (tidyParseBuffer(obj->ptdoc->doc, &buf) < 0) {
- tidyBufFree(&buf);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", obj->ptdoc->errbuf->bp);
return FAILURE;
-
}
- tidyBufFree(&buf);
tidy_doc_update_properties(obj TSRMLS_CC);
return SUCCESS;
@@ -1061,6 +1065,11 @@ static int php_tidy_parse_string(PHPTidyObj *obj, char *string, int len, char *e
static PHP_MINIT_FUNCTION(tidy)
{
+ tidySetMallocCall(php_tidy_malloc);
+ tidySetReallocCall(php_tidy_realloc);
+ tidySetFreeCall(php_tidy_free);
+ tidySetPanicCall(php_tidy_panic);
+
REGISTER_INI_ENTRIES();
REGISTER_TIDY_CLASS(tidy, doc, NULL, 0);
REGISTER_TIDY_CLASS(tidyNode, node, NULL, ZEND_ACC_FINAL_CLASS);
@@ -1071,16 +1080,14 @@ static PHP_MINIT_FUNCTION(tidy)
_php_tidy_register_tags(INIT_FUNC_ARGS_PASSTHRU);
_php_tidy_register_nodetypes(INIT_FUNC_ARGS_PASSTHRU);
+ php_output_handler_alias_register(ZEND_STRL("ob_tidyhandler"), php_tidy_output_handler_init TSRMLS_CC);
+
return SUCCESS;
}
static PHP_RINIT_FUNCTION(tidy)
{
- if (INI_BOOL("tidy.clean_output") == TRUE) {
- if (php_start_ob_buffer_named("ob_tidyhandler", 0, 1 TSRMLS_CC) == FAILURE) {
- zend_error(E_NOTICE, "Failure installing Tidy output buffering.");
- }
- }
+ php_tidy_clean_output_start(ZEND_STRL("ob_tidyhandler") TSRMLS_CC);
return SUCCESS;
}
@@ -1102,59 +1109,106 @@ static PHP_MINFO_FUNCTION(tidy)
DISPLAY_INI_ENTRIES();
}
-static PHP_FUNCTION(ob_tidyhandler)
+static PHP_INI_MH(php_tidy_set_clean_output)
{
- char *input;
- int input_len;
- long mode;
- TidyBuffer errbuf;
- TidyDoc doc;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &input, &input_len, &mode) == FAILURE) {
- return;
+ int status;
+ zend_bool value;
+
+ if (new_value_length==2 && strcasecmp("on", new_value)==0) {
+ value = (zend_bool) 1;
+ } else if (new_value_length==3 && strcasecmp("yes", new_value)==0) {
+ value = (zend_bool) 1;
+ } else if (new_value_length==4 && strcasecmp("true", new_value)==0) {
+ value = (zend_bool) 1;
+ } else {
+ value = (zend_bool) atoi(new_value);
}
- doc = tidyCreate();
- tidyBufInit(&errbuf);
+ if (stage == PHP_INI_STAGE_RUNTIME) {
+ status = php_output_get_status(TSRMLS_C);
- tidyOptSetBool(doc, TidyForceOutput, yes);
- tidyOptSetBool(doc, TidyMark, no);
+ if (value && (status & PHP_OUTPUT_WRITTEN)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot enable tidy.clean_output - there has already been output");
+ return FAILURE;
+ }
+ if (status & PHP_OUTPUT_SENT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot change tidy.clean_output - headers already sent");
+ return FAILURE;
+ }
+ }
- if (tidySetErrorBuffer(doc, &errbuf) != 0) {
- tidyRelease(doc);
- tidyBufFree(&errbuf);
+ status = OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not set Tidy error buffer");
+ if (stage == PHP_INI_STAGE_RUNTIME && value) {
+ if (!php_output_handler_started(ZEND_STRL("ob_tidyhandler") TSRMLS_CC)) {
+ php_tidy_clean_output_start(ZEND_STRL("ob_tidyhandler") TSRMLS_CC);
+ }
}
- TIDY_SET_DEFAULT_CONFIG(doc);
+ return status;
+}
- if (input_len > 1) {
- TidyBuffer buf;
-
- tidyBufInit(&buf);
- tidyBufAppend(&buf, input, input_len);
-
- if (tidyParseBuffer(doc, &buf) < 0 || tidyCleanAndRepair(doc) < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf.bp);
- RETVAL_NULL();
- } else {
- TidyBuffer output;
- tidyBufInit(&output);
+/*
+ * NOTE: tidy does not support iterative/cumulative parsing, so chunk-sized output handler is not possible
+ */
- tidySaveBuffer(doc, &output);
- RETVAL_STRINGL((char*)output.bp, output.size ? output.size-1 : 0, 1);
+static void php_tidy_clean_output_start(const char *name, size_t name_len TSRMLS_DC)
+{
+ php_output_handler *h;
- tidyBufFree(&output);
+ if (TG(clean_output) && (h = php_tidy_output_handler_init(name, name_len, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC))) {
+ php_output_handler_start(h TSRMLS_CC);
+ }
+}
+
+static php_output_handler *php_tidy_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC)
+{
+ if (chunk_size) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot use a chunk size for ob_tidyhandler");
+ return NULL;
+ }
+ if (!TG(clean_output)) {
+ TG(clean_output) = 1;
+ }
+ return php_output_handler_create_internal(handler_name, handler_name_len, php_tidy_output_handler, chunk_size, flags TSRMLS_CC);
+}
+
+static int php_tidy_output_handler(void **nothing, php_output_context *output_context)
+{
+ int status = FAILURE;
+ TidyDoc doc;
+ TidyBuffer inbuf, outbuf, errbuf;
+ PHP_OUTPUT_TSRMLS(output_context);
+
+ if (TG(clean_output) && (output_context->op & PHP_OUTPUT_HANDLER_START) && (output_context->op & PHP_OUTPUT_HANDLER_FINAL)) {
+ doc = tidyCreate();
+ tidyBufInit(&errbuf);
+
+ if (0 == tidySetErrorBuffer(doc, &errbuf)) {
+ tidyOptSetBool(doc, TidyForceOutput, yes);
+ tidyOptSetBool(doc, TidyMark, no);
+
+ TIDY_SET_DEFAULT_CONFIG(doc);
+
+ tidyBufInit(&inbuf);
+ tidyBufAttach(&inbuf, (byte *) output_context->in.data, output_context->in.used);
+
+ if (0 <= tidyParseBuffer(doc, &inbuf) && 0 <= tidyCleanAndRepair(doc)) {
+ tidyBufInit(&outbuf);
+ tidySaveBuffer(doc, &outbuf);
+ FIX_BUFFER(&outbuf);
+ output_context->out.data = (char *) outbuf.bp;
+ output_context->out.used = outbuf.size ? outbuf.size-1 : 0;
+ output_context->out.free = 1;
+ status = SUCCESS;
+ }
}
-
- tidyBufFree(&buf);
- } else {
- RETVAL_NULL();
+
+ tidyRelease(doc);
+ tidyBufFree(&errbuf);
}
- tidyRelease(doc);
- tidyBufFree(&errbuf);
+ return status;
}
/* {{{ proto bool tidy_parse_string(string input [, mixed config_options [, string encoding]])
@@ -1164,7 +1218,6 @@ static PHP_FUNCTION(tidy_parse_string)
char *input, *enc = NULL;
int input_len, enc_len = 0;
zval **options = NULL;
-
PHPTidyObj *obj;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zs", &input, &input_len, &options, &enc, &enc_len) == FAILURE) {
@@ -1181,12 +1234,11 @@ static PHP_FUNCTION(tidy_parse_string)
INIT_ZVAL(*return_value);
RETURN_FALSE;
}
-
}
/* }}} */
-/* {{{ proto string tidy_get_error_buffer([boolean detailed])
- Return warnings and errors which occured parsing the specified document*/
+/* {{{ proto string tidy_get_error_buffer()
+ Return warnings and errors which occurred parsing the specified document*/
static PHP_FUNCTION(tidy_get_error_buffer)
{
TIDY_FETCH_OBJECT;
@@ -1208,9 +1260,8 @@ static PHP_FUNCTION(tidy_get_output)
tidyBufInit(&output);
tidySaveBuffer(obj->ptdoc->doc, &output);
-
- RETVAL_STRINGL((char*)output.bp, output.size ? output.size-1 : 0, 1);
-
+ FIX_BUFFER(&output);
+ RETVAL_STRINGL((char *) output.bp, output.size ? output.size-1 : 0, 1);
tidyBufFree(&output);
}
/* }}} */
@@ -1227,14 +1278,11 @@ static PHP_FUNCTION(tidy_parse_file)
PHPTidyObj *obj;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &inputfile, &input_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|Zsb", &inputfile, &input_len,
&options, &enc, &enc_len, &use_include_path) == FAILURE) {
RETURN_FALSE;
}
- if (strlen(inputfile) != input_len) {
- RETURN_FALSE;
- }
tidy_instanciate(tidy_ce_doc, return_value TSRMLS_CC);
obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
@@ -1320,7 +1368,7 @@ static PHP_FUNCTION(tidy_get_release)
static PHP_FUNCTION(tidy_get_opt_doc)
{
PHPTidyObj *obj;
- char *optname, *optval;
+ char *optval, *optname;
int optname_len;
TidyOption opt;
@@ -1356,7 +1404,7 @@ static PHP_FUNCTION(tidy_get_opt_doc)
/* {{{ proto array tidy_get_config()
- Get current Tidy configuarion */
+ Get current Tidy configuration */
static PHP_FUNCTION(tidy_get_config)
{
TidyIterator itOpt;
@@ -1544,19 +1592,16 @@ static TIDY_DOC_METHOD(__construct)
PHPTidyObj *obj;
TIDY_SET_CONTEXT;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sZsb", &inputfile, &input_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|pZsb", &inputfile, &input_len,
&options, &enc, &enc_len, &use_include_path) == FAILURE) {
RETURN_FALSE;
}
-
+
obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
if (inputfile) {
- if (strlen(inputfile) != input_len) {
- RETURN_FALSE;
- }
if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path, &contents_len TSRMLS_CC))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : "");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory%s", inputfile, (use_include_path) ? " (Using include path)" : "");
return;
}
@@ -1581,16 +1626,13 @@ static TIDY_DOC_METHOD(parseFile)
obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &inputfile, &input_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|Zsb", &inputfile, &input_len,
&options, &enc, &enc_len, &use_include_path) == FAILURE) {
RETURN_FALSE;
}
-
- if (strlen(inputfile) != input_len) {
- RETURN_FALSE;
- }
+
if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path, &contents_len TSRMLS_CC))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : "");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory%s", inputfile, (use_include_path) ? " (Using include path)" : "");
RETURN_FALSE;
}
@@ -1797,6 +1839,7 @@ static TIDY_NODE_METHOD(getParent)
}
/* }}} */
+
/* {{{ proto void tidyNode::__construct()
__constructor for tidyNode. */
static TIDY_NODE_METHOD(__construct)
diff --git a/ext/tokenizer/tests/bug54089.phpt b/ext/tokenizer/tests/bug54089.phpt
index e1f6d79e9c..77a4c1f324 100644
--- a/ext/tokenizer/tests/bug54089.phpt
+++ b/ext/tokenizer/tests/bug54089.phpt
@@ -4,17 +4,26 @@ Bug #54089 (token_get_all() does not stop after __halt_compiler)
<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
-$code = "<?php __halt_compiler();\x01?>\x02";
-$tokens = token_get_all($code);
-
-var_dump($tokens);
-
-$code = '';
-foreach ($tokens as $t)
-{
- $code .= isset($t[1]) ? $t[1] : $t;
+$codes = array(
+ "<?php __halt_compiler",
+ "<?php __halt_compiler(",
+ "<?php __halt_compiler();",
+ "<?php __halt_compiler();ABC",
+ "<?php __halt_compiler\n(\n)\n;ABC",
+ "<?php __halt_compiler\nabc\ndef\nghi ABC",
+);
+foreach ($codes as $code) {
+ $tokens = token_get_all($code);
+ var_dump($tokens);
+
+ $code = '';
+ foreach ($tokens as $t)
+ {
+ $code .= isset($t[1]) ? $t[1] : $t;
+ }
+ var_dump($code);
}
-var_dump($code);
+
?>
--EXPECTF--
array(2) {
@@ -38,3 +47,248 @@ array(2) {
}
}
string(21) "<?php __halt_compiler"
+array(3) {
+ [0]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(6) "<?php "
+ [2]=>
+ int(1)
+ }
+ [1]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(15) "__halt_compiler"
+ [2]=>
+ int(1)
+ }
+ [2]=>
+ string(1) "("
+}
+string(22) "<?php __halt_compiler("
+array(5) {
+ [0]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(6) "<?php "
+ [2]=>
+ int(1)
+ }
+ [1]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(15) "__halt_compiler"
+ [2]=>
+ int(1)
+ }
+ [2]=>
+ string(1) "("
+ [3]=>
+ string(1) ")"
+ [4]=>
+ string(1) ";"
+}
+string(24) "<?php __halt_compiler();"
+array(6) {
+ [0]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(6) "<?php "
+ [2]=>
+ int(1)
+ }
+ [1]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(15) "__halt_compiler"
+ [2]=>
+ int(1)
+ }
+ [2]=>
+ string(1) "("
+ [3]=>
+ string(1) ")"
+ [4]=>
+ string(1) ";"
+ [5]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(3) "ABC"
+ [2]=>
+ int(1)
+ }
+}
+string(27) "<?php __halt_compiler();ABC"
+array(9) {
+ [0]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(6) "<?php "
+ [2]=>
+ int(1)
+ }
+ [1]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(15) "__halt_compiler"
+ [2]=>
+ int(1)
+ }
+ [2]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(1)
+ }
+ [3]=>
+ string(1) "("
+ [4]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(2)
+ }
+ [5]=>
+ string(1) ")"
+ [6]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(3)
+ }
+ [7]=>
+ string(1) ";"
+ [8]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(3) "ABC"
+ [2]=>
+ int(4)
+ }
+}
+string(30) "<?php __halt_compiler
+(
+)
+;ABC"
+array(9) {
+ [0]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(6) "<?php "
+ [2]=>
+ int(1)
+ }
+ [1]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(15) "__halt_compiler"
+ [2]=>
+ int(1)
+ }
+ [2]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(1)
+ }
+ [3]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(3) "abc"
+ [2]=>
+ int(2)
+ }
+ [4]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(2)
+ }
+ [5]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(3) "def"
+ [2]=>
+ int(3)
+ }
+ [6]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(3)
+ }
+ [7]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(3) "ghi"
+ [2]=>
+ int(4)
+ }
+ [8]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(4) " ABC"
+ [2]=>
+ int(4)
+ }
+}
+string(37) "<?php __halt_compiler
+abc
+def
+ghi ABC"
diff --git a/ext/tokenizer/tests/token_get_all_basic.phpt b/ext/tokenizer/tests/token_get_all_basic.phpt
index a3bc7ccb7d..7af8109f89 100644
--- a/ext/tokenizer/tests/token_get_all_basic.phpt
+++ b/ext/tokenizer/tests/token_get_all_basic.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : basic functionality
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -28,7 +30,7 @@ array(7) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -37,7 +39,7 @@ array(7) {
[1]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -46,7 +48,7 @@ array(7) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -55,7 +57,7 @@ array(7) {
[3]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(13) ""Hello World""
[2]=>
@@ -66,7 +68,7 @@ array(7) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -75,7 +77,7 @@ array(7) {
[6]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -87,11 +89,11 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(19) "echo 'Hello World';"
[2]=>
int(1)
}
}
-Done
+Done \ No newline at end of file
diff --git a/ext/tokenizer/tests/token_get_all_error.phpt b/ext/tokenizer/tests/token_get_all_error.phpt
index 52b1efc1dd..29e97c38c4 100644
--- a/ext/tokenizer/tests/token_get_all_error.phpt
+++ b/ext/tokenizer/tests/token_get_all_error.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : error conditions
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
diff --git a/ext/tokenizer/tests/token_get_all_variation1.phpt b/ext/tokenizer/tests/token_get_all_variation1.phpt
index f0e10d6d5c..276453fd15 100644
--- a/ext/tokenizer/tests/token_get_all_variation1.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation1.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - unexpected values for 'source' argument
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -95,7 +97,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(1) "0"
[2]=>
@@ -107,7 +109,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -119,7 +121,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(5) "12345"
[2]=>
@@ -131,7 +133,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(5) "-2345"
[2]=>
@@ -143,7 +145,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(4) "10.5"
[2]=>
@@ -155,7 +157,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(5) "-10.5"
[2]=>
@@ -167,7 +169,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(10) "1012345670"
[2]=>
@@ -179,7 +181,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(13) "1.07654321E-7"
[2]=>
@@ -191,7 +193,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(3) "0.5"
[2]=>
@@ -229,7 +231,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -244,7 +246,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -265,7 +267,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(6) "object"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation10.phpt b/ext/tokenizer/tests/token_get_all_variation10.phpt
index 3894901d61..55e9d7edf8 100644
--- a/ext/tokenizer/tests/token_get_all_variation10.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation10.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with constant tokens
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -52,7 +54,7 @@ array(24) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -61,7 +63,7 @@ array(24) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -70,7 +72,7 @@ array(24) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -81,7 +83,7 @@ array(24) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -90,7 +92,7 @@ array(24) {
[5]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -99,7 +101,7 @@ array(24) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -110,7 +112,7 @@ array(24) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -119,7 +121,7 @@ array(24) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(3) "034"
[2]=>
@@ -130,7 +132,7 @@ array(24) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -139,7 +141,7 @@ array(24) {
[12]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -148,7 +150,7 @@ array(24) {
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -159,7 +161,7 @@ array(24) {
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -168,7 +170,7 @@ array(24) {
[16]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -177,7 +179,7 @@ array(24) {
[17]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -188,7 +190,7 @@ array(24) {
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -197,7 +199,7 @@ array(24) {
[20]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(4) "0x3F"
[2]=>
@@ -208,7 +210,7 @@ array(24) {
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -217,7 +219,7 @@ array(24) {
[23]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -229,7 +231,7 @@ array(17) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -238,7 +240,7 @@ array(17) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -247,7 +249,7 @@ array(17) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -258,7 +260,7 @@ array(17) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -267,7 +269,7 @@ array(17) {
[5]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(7) "0.23E-2"
[2]=>
@@ -276,7 +278,7 @@ array(17) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -287,7 +289,7 @@ array(17) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -296,7 +298,7 @@ array(17) {
[9]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(6) "0.43e2"
[2]=>
@@ -305,7 +307,7 @@ array(17) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -316,7 +318,7 @@ array(17) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -325,7 +327,7 @@ array(17) {
[13]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(3) "0.5"
[2]=>
@@ -336,7 +338,7 @@ array(17) {
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -345,7 +347,7 @@ array(17) {
[16]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -357,7 +359,7 @@ array(11) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -366,7 +368,7 @@ array(11) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -375,7 +377,7 @@ array(11) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -386,7 +388,7 @@ array(11) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -395,7 +397,7 @@ array(11) {
[5]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(8) ""hello ""
[2]=>
@@ -406,7 +408,7 @@ array(11) {
[7]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(7) "'world'"
[2]=>
@@ -417,7 +419,7 @@ array(11) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -426,7 +428,7 @@ array(11) {
[10]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -438,7 +440,7 @@ array(18) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -447,7 +449,7 @@ array(18) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -456,7 +458,7 @@ array(18) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -467,7 +469,7 @@ array(18) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -478,7 +480,7 @@ array(18) {
[6]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -491,7 +493,7 @@ array(18) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -500,7 +502,7 @@ array(18) {
[10]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "true"
[2]=>
@@ -509,7 +511,7 @@ array(18) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -520,7 +522,7 @@ array(18) {
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -529,7 +531,7 @@ array(18) {
[14]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(5) "false"
[2]=>
@@ -540,7 +542,7 @@ array(18) {
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -549,7 +551,7 @@ array(18) {
[17]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -561,7 +563,7 @@ array(18) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -570,7 +572,7 @@ array(18) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -579,7 +581,7 @@ array(18) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -590,7 +592,7 @@ array(18) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -601,7 +603,7 @@ array(18) {
[6]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -614,7 +616,7 @@ array(18) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -623,7 +625,7 @@ array(18) {
[10]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(5) "FALSE"
[2]=>
@@ -632,7 +634,7 @@ array(18) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -643,7 +645,7 @@ array(18) {
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -652,7 +654,7 @@ array(18) {
[14]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "TRUE"
[2]=>
@@ -663,7 +665,7 @@ array(18) {
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -672,7 +674,7 @@ array(18) {
[17]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -684,7 +686,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -693,7 +695,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -702,7 +704,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -713,7 +715,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -722,7 +724,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "null"
[2]=>
@@ -731,7 +733,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -742,7 +744,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -751,7 +753,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "NULL"
[2]=>
@@ -762,7 +764,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -771,7 +773,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation11.phpt b/ext/tokenizer/tests/token_get_all_variation11.phpt
index 05fb8d3034..ecc86177a4 100644
--- a/ext/tokenizer/tests/token_get_all_variation11.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation11.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with control structure tokens
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -80,7 +82,7 @@ array(49) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -89,7 +91,7 @@ array(49) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -99,7 +101,7 @@ array(49) {
[2]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -110,7 +112,7 @@ array(49) {
[4]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -119,7 +121,7 @@ array(49) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -137,7 +139,7 @@ array(49) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -146,7 +148,7 @@ array(49) {
[8]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "true"
[2]=>
@@ -157,7 +159,7 @@ array(49) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -168,7 +170,7 @@ array(49) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(6) "
"
@@ -178,40 +180,40 @@ array(49) {
[13]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
- int(3)
+ int(%d)
}
[14]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[15]=>
string(1) """
[16]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
- int(3)
+ int(%d)
}
[17]=>
array(3) {
[0]=>
- int(314)
+ int(%d)
[1]=>
string(7) " = true"
[2]=>
- int(3)
+ int(%d)
}
[18]=>
string(1) """
@@ -220,19 +222,19 @@ array(49) {
[20]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[21]=>
string(1) "}"
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -242,7 +244,7 @@ array(49) {
[23]=>
array(3) {
[0]=>
- int(302)
+ int(%d)
[1]=>
string(6) "elseif"
[2]=>
@@ -253,7 +255,7 @@ array(49) {
[25]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -262,7 +264,7 @@ array(49) {
[26]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -280,7 +282,7 @@ array(49) {
[28]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -289,7 +291,7 @@ array(49) {
[29]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(5) "false"
[2]=>
@@ -300,7 +302,7 @@ array(49) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -311,7 +313,7 @@ array(49) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -321,7 +323,7 @@ array(49) {
[34]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -330,7 +332,7 @@ array(49) {
[35]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -339,7 +341,7 @@ array(49) {
[36]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(5) "false"
[2]=>
@@ -350,7 +352,7 @@ array(49) {
[38]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -362,7 +364,7 @@ array(49) {
[40]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -372,7 +374,7 @@ array(49) {
[41]=>
array(3) {
[0]=>
- int(303)
+ int(%d)
[1]=>
string(4) "else"
[2]=>
@@ -381,7 +383,7 @@ array(49) {
[42]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -391,7 +393,7 @@ array(49) {
[43]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -400,7 +402,7 @@ array(49) {
[44]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -409,7 +411,7 @@ array(49) {
[45]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -420,7 +422,7 @@ array(49) {
[47]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -430,7 +432,7 @@ array(49) {
[48]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -442,7 +444,7 @@ array(33) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -451,7 +453,7 @@ array(33) {
[1]=>
array(3) {
[0]=>
- int(318)
+ int(%d)
[1]=>
string(5) "while"
[2]=>
@@ -462,7 +464,7 @@ array(33) {
[3]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "true"
[2]=>
@@ -473,7 +475,7 @@ array(33) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -484,7 +486,7 @@ array(33) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -494,7 +496,7 @@ array(33) {
[8]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -503,7 +505,7 @@ array(33) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -512,7 +514,7 @@ array(33) {
[10]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(6) "'True'"
[2]=>
@@ -523,7 +525,7 @@ array(33) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -533,30 +535,30 @@ array(33) {
[13]=>
array(3) {
[0]=>
- int(331)
+ int(%d)
[1]=>
string(5) "break"
[2]=>
- int(3)
+ int(%d)
}
[14]=>
string(1) ";"
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[16]=>
string(1) "}"
[17]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -566,7 +568,7 @@ array(33) {
[18]=>
array(3) {
[0]=>
- int(317)
+ int(%d)
[1]=>
string(2) "do"
[2]=>
@@ -575,7 +577,7 @@ array(33) {
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -586,7 +588,7 @@ array(33) {
[21]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -596,7 +598,7 @@ array(33) {
[22]=>
array(3) {
[0]=>
- int(332)
+ int(%d)
[1]=>
string(8) "continue"
[2]=>
@@ -607,7 +609,7 @@ array(33) {
[24]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -619,7 +621,7 @@ array(33) {
[26]=>
array(3) {
[0]=>
- int(318)
+ int(%d)
[1]=>
string(5) "while"
[2]=>
@@ -630,7 +632,7 @@ array(33) {
[28]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(5) "false"
[2]=>
@@ -643,7 +645,7 @@ array(33) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -652,7 +654,7 @@ array(33) {
[32]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -664,7 +666,7 @@ array(45) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -673,7 +675,7 @@ array(45) {
[1]=>
array(3) {
[0]=>
- int(320)
+ int(%d)
[1]=>
string(3) "for"
[2]=>
@@ -684,7 +686,7 @@ array(45) {
[3]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(6) "$count"
[2]=>
@@ -695,7 +697,7 @@ array(45) {
[5]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "0"
[2]=>
@@ -706,7 +708,7 @@ array(45) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -715,7 +717,7 @@ array(45) {
[8]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(6) "$count"
[2]=>
@@ -724,7 +726,7 @@ array(45) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -735,7 +737,7 @@ array(45) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -744,7 +746,7 @@ array(45) {
[12]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "5"
[2]=>
@@ -755,7 +757,7 @@ array(45) {
[14]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -764,7 +766,7 @@ array(45) {
[15]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(6) "$count"
[2]=>
@@ -773,7 +775,7 @@ array(45) {
[16]=>
array(3) {
[0]=>
- int(297)
+ int(%d)
[1]=>
string(2) "++"
[2]=>
@@ -784,7 +786,7 @@ array(45) {
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -795,7 +797,7 @@ array(45) {
[20]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -805,7 +807,7 @@ array(45) {
[21]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -814,7 +816,7 @@ array(45) {
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -823,7 +825,7 @@ array(45) {
[23]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(6) "$count"
[2]=>
@@ -834,7 +836,7 @@ array(45) {
[25]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -846,17 +848,17 @@ array(45) {
[27]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[28]=>
array(3) {
[0]=>
- int(322)
+ int(%d)
[1]=>
string(7) "foreach"
[2]=>
@@ -867,7 +869,7 @@ array(45) {
[30]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(7) "$values"
[2]=>
@@ -876,7 +878,7 @@ array(45) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -885,7 +887,7 @@ array(45) {
[32]=>
array(3) {
[0]=>
- int(326)
+ int(%d)
[1]=>
string(2) "as"
[2]=>
@@ -894,7 +896,7 @@ array(45) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -903,7 +905,7 @@ array(45) {
[34]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(6) "$index"
[2]=>
@@ -914,7 +916,7 @@ array(45) {
[36]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -925,7 +927,7 @@ array(45) {
[38]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -935,7 +937,7 @@ array(45) {
[39]=>
array(3) {
[0]=>
- int(332)
+ int(%d)
[1]=>
string(8) "continue"
[2]=>
@@ -946,7 +948,7 @@ array(45) {
[41]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -958,7 +960,7 @@ array(45) {
[43]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -967,7 +969,7 @@ array(45) {
[44]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -979,7 +981,7 @@ array(23) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -988,7 +990,7 @@ array(23) {
[1]=>
array(3) {
[0]=>
- int(327)
+ int(%d)
[1]=>
string(6) "switch"
[2]=>
@@ -999,7 +1001,7 @@ array(23) {
[3]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(4) "$var"
[2]=>
@@ -1010,7 +1012,7 @@ array(23) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -1020,7 +1022,7 @@ array(23) {
[6]=>
array(3) {
[0]=>
- int(329)
+ int(%d)
[1]=>
string(4) "case"
[2]=>
@@ -1029,7 +1031,7 @@ array(23) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -1038,7 +1040,7 @@ array(23) {
[8]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -1049,7 +1051,7 @@ array(23) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -1058,7 +1060,7 @@ array(23) {
[11]=>
array(3) {
[0]=>
- int(331)
+ int(%d)
[1]=>
string(5) "break"
[2]=>
@@ -1069,7 +1071,7 @@ array(23) {
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -1079,69 +1081,69 @@ array(23) {
[14]=>
array(3) {
[0]=>
- int(330)
+ int(%d)
[1]=>
string(7) "default"
[2]=>
- int(3)
+ int(%d)
}
[15]=>
string(1) ":"
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[17]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
- int(3)
+ int(%d)
}
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[19]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(9) ""default""
[2]=>
- int(3)
+ int(%d)
}
[20]=>
string(1) ";"
[21]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[22]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
- int(3)
+ int(%d)
}
}
Done
diff --git a/ext/tokenizer/tests/token_get_all_variation12.phpt b/ext/tokenizer/tests/token_get_all_variation12.phpt
index 16af5b725b..368fb0867c 100644
--- a/ext/tokenizer/tests/token_get_all_variation12.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation12.phpt
@@ -1,19 +1,22 @@
--TEST--
Test token_get_all() function : usage variations - with predefined language constants
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
- * Description: splits the given source into an array of PHP languange tokens
+ * Description: splits the given source into an array of PHP language tokens
* Source code: ext/tokenizer/tokenizer.c
*/
/*
* Testing token_get_all() with following predefined language constants:
- * __FILE__ - T_FILE(364)
- * __CLASS__ - T_CLASS_C(360)
- * __FUNCTION__ - T_FUNC_C(362)
- * __LINE__ - T_LINE(363)
- * __METHOD__ - T_METHOD_C(361)
+ * __FILE__ - T_FILE
+ * __CLASS__ - T_CLASS_C
+ * __TRAIT__ - T_TRAIT_C
+ * __FUNCTION__ - T_FUNC_C
+ * __LINE__ - T_LINE
+ * __METHOD__ - T_METHOD_C
*/
echo "*** Testing token_get_all() : with language constants ***\n";
@@ -25,12 +28,13 @@ $source = "<?php
?>";
var_dump( token_get_all($source));
-// parsing __CLASS__ and __FUNCTION__ tokens
-echo "-- with CLASS and FUNCTION --\n";
+// parsing __CLASS__, __TRAIT__ and __FUNCTION__ tokens
+echo "-- with CLASS, TRAIT and FUNCTION --\n";
$source = '<?php
class MyClass
{
echo __CLASS__;
+ echo __TRAIT__;
function myFunction()
{ echo __FUNCTION__; }
}
@@ -54,7 +58,7 @@ array(16) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -63,7 +67,7 @@ array(16) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -73,7 +77,7 @@ array(16) {
[2]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(3) "$fp"
[2]=>
@@ -82,7 +86,7 @@ array(16) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -93,7 +97,7 @@ array(16) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(2) " "
[2]=>
@@ -102,7 +106,7 @@ array(16) {
[6]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(5) "fopen"
[2]=>
@@ -113,7 +117,7 @@ array(16) {
[8]=>
array(3) {
[0]=>
- int(365)
+ int(%d)
[1]=>
string(8) "__FILE__"
[2]=>
@@ -124,7 +128,7 @@ array(16) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -133,7 +137,7 @@ array(16) {
[11]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(3) "'r'"
[2]=>
@@ -146,7 +150,7 @@ array(16) {
[14]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -156,19 +160,19 @@ array(16) {
[15]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
- int(3)
+ int(%d)
}
}
--- with CLASS and FUNCTION --
-array(30) {
+-- with CLASS, TRAIT and FUNCTION --
+array(35) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php
"
@@ -178,7 +182,7 @@ array(30) {
[1]=>
array(3) {
[0]=>
- int(353)
+ int(%d)
[1]=>
string(5) "class"
[2]=>
@@ -187,7 +191,7 @@ array(30) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -196,7 +200,7 @@ array(30) {
[3]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "MyClass"
[2]=>
@@ -205,7 +209,7 @@ array(30) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -217,17 +221,17 @@ array(30) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
- int(3)
+ int(%d)
}
[7]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -236,7 +240,7 @@ array(30) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(2) " "
[2]=>
@@ -245,7 +249,7 @@ array(30) {
[9]=>
array(3) {
[0]=>
- int(361)
+ int(%d)
[1]=>
string(9) "__CLASS__"
[2]=>
@@ -256,135 +260,174 @@ array(30) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
- int(4)
+ int(%d)
}
[12]=>
array(3) {
[0]=>
- int(334)
+ int(%d)
[1]=>
- string(8) "function"
+ string(4) "echo"
[2]=>
int(5)
}
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
- string(1) " "
+ string(2) " "
[2]=>
int(5)
}
[14]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
- string(10) "myFunction"
+ string(9) "__TRAIT__"
[2]=>
int(5)
}
[15]=>
- string(1) "("
+ string(1) ";"
[16]=>
- string(1) ")"
- [17]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
int(5)
}
+ [17]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(8) "function"
+ [2]=>
+ int(6)
+ }
[18]=>
- string(1) "{"
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) " "
+ [2]=>
+ int(6)
+ }
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
- string(2) " "
+ string(10) "myFunction"
[2]=>
int(6)
}
[20]=>
+ string(1) "("
+ [21]=>
+ string(1) ")"
+ [22]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
- string(4) "echo"
+ string(3) "
+ "
[2]=>
int(6)
}
- [21]=>
+ [23]=>
+ string(1) "{"
+ [24]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(2) " "
[2]=>
- int(6)
+ int(7)
}
- [22]=>
+ [25]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(4) "echo"
+ [2]=>
+ int(7)
+ }
+ [26]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(2) " "
+ [2]=>
+ int(7)
+ }
+ [27]=>
array(3) {
[0]=>
- int(363)
+ int(%d)
[1]=>
string(12) "__FUNCTION__"
[2]=>
- int(6)
+ int(7)
}
- [23]=>
+ [28]=>
string(1) ";"
- [24]=>
+ [29]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(6)
+ int(7)
}
- [25]=>
+ [30]=>
string(1) "}"
- [26]=>
+ [31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(6)
+ int(7)
}
- [27]=>
+ [32]=>
string(1) "}"
- [28]=>
+ [33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(7)
+ int(8)
}
- [29]=>
+ [34]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
- int(8)
+ int(9)
}
}
-- with LINE and METHOD --
@@ -392,7 +435,7 @@ array(19) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php
"
@@ -402,7 +445,7 @@ array(19) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(2) " "
[2]=>
@@ -411,7 +454,7 @@ array(19) {
[2]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -420,7 +463,7 @@ array(19) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -431,7 +474,7 @@ array(19) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -440,7 +483,7 @@ array(19) {
[6]=>
array(3) {
[0]=>
- int(364)
+ int(%d)
[1]=>
string(8) "__LINE__"
[2]=>
@@ -451,7 +494,7 @@ array(19) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -461,68 +504,68 @@ array(19) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
- int(3)
+ int(%d)
}
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[11]=>
string(1) "="
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[13]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
- int(3)
+ int(%d)
}
[14]=>
string(1) "."
[15]=>
array(3) {
[0]=>
- int(362)
+ int(%d)
[1]=>
string(10) "__METHOD__"
[2]=>
- int(3)
+ int(%d)
}
[16]=>
string(1) ";"
[17]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[18]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation13.phpt b/ext/tokenizer/tests/token_get_all_variation13.phpt
index d30ffce407..9b2f3bc94f 100644
--- a/ext/tokenizer/tests/token_get_all_variation13.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation13.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with class/object constructs
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -59,7 +61,7 @@ array(145) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php
"
@@ -69,7 +71,7 @@ array(145) {
[1]=>
array(3) {
[0]=>
- int(354)
+ int(%d)
[1]=>
string(9) "interface"
[2]=>
@@ -78,7 +80,7 @@ array(145) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -87,7 +89,7 @@ array(145) {
[3]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(11) "MyInterface"
[2]=>
@@ -96,7 +98,7 @@ array(145) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -108,17 +110,17 @@ array(145) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
- int(3)
+ int(%d)
}
[7]=>
array(3) {
[0]=>
- int(342)
+ int(%d)
[1]=>
string(6) "public"
[2]=>
@@ -127,7 +129,7 @@ array(145) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -136,7 +138,7 @@ array(145) {
[9]=>
array(3) {
[0]=>
- int(335)
+ int(%d)
[1]=>
string(5) "const"
[2]=>
@@ -145,7 +147,7 @@ array(145) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -154,7 +156,7 @@ array(145) {
[11]=>
array(3) {
[0]=>
- int(348)
+ int(%d)
[1]=>
string(3) "var"
[2]=>
@@ -163,7 +165,7 @@ array(145) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -172,7 +174,7 @@ array(145) {
[13]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(4) "$var"
[2]=>
@@ -181,7 +183,7 @@ array(145) {
[14]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -192,7 +194,7 @@ array(145) {
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -201,7 +203,7 @@ array(145) {
[17]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -212,7 +214,7 @@ array(145) {
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -224,7 +226,7 @@ array(145) {
[21]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -234,7 +236,7 @@ array(145) {
[22]=>
array(3) {
[0]=>
- int(346)
+ int(%d)
[1]=>
string(8) "abstract"
[2]=>
@@ -243,7 +245,7 @@ array(145) {
[23]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -252,7 +254,7 @@ array(145) {
[24]=>
array(3) {
[0]=>
- int(353)
+ int(%d)
[1]=>
string(5) "class"
[2]=>
@@ -261,7 +263,7 @@ array(145) {
[25]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -270,7 +272,7 @@ array(145) {
[26]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "MyClass"
[2]=>
@@ -279,7 +281,7 @@ array(145) {
[27]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -291,7 +293,7 @@ array(145) {
[29]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -301,7 +303,7 @@ array(145) {
[30]=>
array(3) {
[0]=>
- int(344)
+ int(%d)
[1]=>
string(7) "private"
[2]=>
@@ -310,7 +312,7 @@ array(145) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -319,7 +321,7 @@ array(145) {
[32]=>
array(3) {
[0]=>
- int(348)
+ int(%d)
[1]=>
string(3) "var"
[2]=>
@@ -328,7 +330,7 @@ array(145) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -337,7 +339,7 @@ array(145) {
[34]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -348,7 +350,7 @@ array(145) {
[36]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -358,7 +360,7 @@ array(145) {
[37]=>
array(3) {
[0]=>
- int(342)
+ int(%d)
[1]=>
string(6) "public"
[2]=>
@@ -367,7 +369,7 @@ array(145) {
[38]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -376,7 +378,7 @@ array(145) {
[39]=>
array(3) {
[0]=>
- int(348)
+ int(%d)
[1]=>
string(3) "var"
[2]=>
@@ -385,7 +387,7 @@ array(145) {
[40]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -394,7 +396,7 @@ array(145) {
[41]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -405,7 +407,7 @@ array(145) {
[43]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -415,7 +417,7 @@ array(145) {
[44]=>
array(3) {
[0]=>
- int(343)
+ int(%d)
[1]=>
string(9) "protected"
[2]=>
@@ -424,7 +426,7 @@ array(145) {
[45]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -433,7 +435,7 @@ array(145) {
[46]=>
array(3) {
[0]=>
- int(348)
+ int(%d)
[1]=>
string(3) "var"
[2]=>
@@ -442,7 +444,7 @@ array(145) {
[47]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -451,7 +453,7 @@ array(145) {
[48]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -462,7 +464,7 @@ array(145) {
[50]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -472,7 +474,7 @@ array(145) {
[51]=>
array(3) {
[0]=>
- int(347)
+ int(%d)
[1]=>
string(6) "static"
[2]=>
@@ -481,7 +483,7 @@ array(145) {
[52]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -490,7 +492,7 @@ array(145) {
[53]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$d"
[2]=>
@@ -501,7 +503,7 @@ array(145) {
[55]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -511,7 +513,7 @@ array(145) {
[56]=>
array(3) {
[0]=>
- int(345)
+ int(%d)
[1]=>
string(5) "final"
[2]=>
@@ -520,7 +522,7 @@ array(145) {
[57]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -529,7 +531,7 @@ array(145) {
[58]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$e"
[2]=>
@@ -538,7 +540,7 @@ array(145) {
[59]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -549,7 +551,7 @@ array(145) {
[61]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -558,7 +560,7 @@ array(145) {
[62]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -569,7 +571,7 @@ array(145) {
[64]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(6) "
@@ -580,7 +582,7 @@ array(145) {
[65]=>
array(3) {
[0]=>
- int(346)
+ int(%d)
[1]=>
string(8) "abstract"
[2]=>
@@ -589,7 +591,7 @@ array(145) {
[66]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -598,7 +600,7 @@ array(145) {
[67]=>
array(3) {
[0]=>
- int(342)
+ int(%d)
[1]=>
string(6) "public"
[2]=>
@@ -607,7 +609,7 @@ array(145) {
[68]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -616,7 +618,7 @@ array(145) {
[69]=>
array(3) {
[0]=>
- int(334)
+ int(%d)
[1]=>
string(8) "function"
[2]=>
@@ -625,7 +627,7 @@ array(145) {
[70]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -634,7 +636,7 @@ array(145) {
[71]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "myFunction"
[2]=>
@@ -645,7 +647,7 @@ array(145) {
[73]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -658,7 +660,7 @@ array(145) {
[76]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -670,7 +672,7 @@ array(145) {
[78]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -680,7 +682,7 @@ array(145) {
[79]=>
array(3) {
[0]=>
- int(353)
+ int(%d)
[1]=>
string(5) "class"
[2]=>
@@ -689,7 +691,7 @@ array(145) {
[80]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -698,7 +700,7 @@ array(145) {
[81]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "ChildClass"
[2]=>
@@ -707,7 +709,7 @@ array(145) {
[82]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -716,7 +718,7 @@ array(145) {
[83]=>
array(3) {
[0]=>
- int(355)
+ int(%d)
[1]=>
string(7) "extends"
[2]=>
@@ -725,7 +727,7 @@ array(145) {
[84]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -734,7 +736,7 @@ array(145) {
[85]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "MyClass"
[2]=>
@@ -743,7 +745,7 @@ array(145) {
[86]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -752,7 +754,7 @@ array(145) {
[87]=>
array(3) {
[0]=>
- int(356)
+ int(%d)
[1]=>
string(10) "implements"
[2]=>
@@ -761,7 +763,7 @@ array(145) {
[88]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -770,7 +772,7 @@ array(145) {
[89]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(11) "MyInterface"
[2]=>
@@ -779,7 +781,7 @@ array(145) {
[90]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -791,7 +793,7 @@ array(145) {
[92]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -801,7 +803,7 @@ array(145) {
[93]=>
array(3) {
[0]=>
- int(341)
+ int(%d)
[1]=>
string(6) "global"
[2]=>
@@ -810,7 +812,7 @@ array(145) {
[94]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -819,7 +821,7 @@ array(145) {
[95]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(6) "$value"
[2]=>
@@ -830,7 +832,7 @@ array(145) {
[97]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -840,7 +842,7 @@ array(145) {
[98]=>
array(3) {
[0]=>
- int(334)
+ int(%d)
[1]=>
string(8) "function"
[2]=>
@@ -849,7 +851,7 @@ array(145) {
[99]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -858,7 +860,7 @@ array(145) {
[100]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "myFunction"
[2]=>
@@ -869,7 +871,7 @@ array(145) {
[102]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -880,7 +882,7 @@ array(145) {
[104]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -892,7 +894,7 @@ array(145) {
[106]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -902,7 +904,7 @@ array(145) {
[107]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -911,7 +913,7 @@ array(145) {
[108]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -922,7 +924,7 @@ array(145) {
[110]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -931,7 +933,7 @@ array(145) {
[111]=>
array(3) {
[0]=>
- int(299)
+ int(%d)
[1]=>
string(3) "new"
[2]=>
@@ -940,7 +942,7 @@ array(145) {
[112]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -949,7 +951,7 @@ array(145) {
[113]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "ChildClass"
[2]=>
@@ -964,7 +966,7 @@ array(145) {
[117]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -974,7 +976,7 @@ array(145) {
[118]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -985,7 +987,7 @@ array(145) {
[120]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -994,7 +996,7 @@ array(145) {
[121]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -1012,7 +1014,7 @@ array(145) {
[123]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -1021,7 +1023,7 @@ array(145) {
[124]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "MyClass"
[2]=>
@@ -1032,7 +1034,7 @@ array(145) {
[126]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(7) "
"
@@ -1042,7 +1044,7 @@ array(145) {
[127]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -1051,7 +1053,7 @@ array(145) {
[128]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -1060,7 +1062,7 @@ array(145) {
[129]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(16) ""object created""
[2]=>
@@ -1071,7 +1073,7 @@ array(145) {
[131]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -1083,7 +1085,7 @@ array(145) {
[133]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -1095,7 +1097,7 @@ array(145) {
[135]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -1105,7 +1107,7 @@ array(145) {
[136]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "ChildClass"
[2]=>
@@ -1114,7 +1116,7 @@ array(145) {
[137]=>
array(3) {
[0]=>
- int(376)
+ int(%d)
[1]=>
string(2) "::"
[2]=>
@@ -1123,7 +1125,7 @@ array(145) {
[138]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "myFunction"
[2]=>
@@ -1134,7 +1136,7 @@ array(145) {
[140]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -1147,7 +1149,7 @@ array(145) {
[143]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -1157,7 +1159,7 @@ array(145) {
[144]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation14.phpt b/ext/tokenizer/tests/token_get_all_variation14.phpt
index 5df7eea6c1..5fc390e36c 100644
--- a/ext/tokenizer/tests/token_get_all_variation14.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation14.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - invalid token values
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -44,7 +46,7 @@ array(29) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -53,7 +55,7 @@ array(29) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -63,7 +65,7 @@ array(29) {
[2]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(6) "struct"
[2]=>
@@ -72,7 +74,7 @@ array(29) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -81,7 +83,7 @@ array(29) {
[4]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(8) "myStruct"
[2]=>
@@ -90,7 +92,7 @@ array(29) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -101,7 +103,7 @@ array(29) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -111,46 +113,46 @@ array(29) {
[8]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(8) "variable"
[2]=>
- int(3)
+ int(%d)
}
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[10]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
- int(3)
+ int(%d)
}
[11]=>
string(1) ";"
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
- int(3)
+ int(%d)
}
[13]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(6) "method"
[2]=>
@@ -163,7 +165,7 @@ array(29) {
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -174,7 +176,7 @@ array(29) {
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -183,7 +185,7 @@ array(29) {
[19]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "display"
[2]=>
@@ -192,7 +194,7 @@ array(29) {
[20]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -201,7 +203,7 @@ array(29) {
[21]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -212,7 +214,7 @@ array(29) {
[23]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -223,7 +225,7 @@ array(29) {
[25]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -235,7 +237,7 @@ array(29) {
[27]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -245,7 +247,7 @@ array(29) {
[28]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -257,7 +259,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(28) "<pli
echo "hello world"; ?>"
@@ -270,7 +272,7 @@ array(1) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(19) "<PDP display $a; <"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation15.phpt b/ext/tokenizer/tests/token_get_all_variation15.phpt
index 6c57a49df4..fbb50dee86 100644
--- a/ext/tokenizer/tests/token_get_all_variation15.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation15.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - heredoc string for 'source'
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--INI--
short_open_tag=On
--FILE--
@@ -52,7 +54,7 @@ array(103) {
[0]=>
array(3) {
[0]=>
- int(369)
+ int(%d)
[1]=>
string(3) "<?="
[2]=>
@@ -61,7 +63,7 @@ array(103) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(4) "
"
@@ -71,7 +73,7 @@ array(103) {
[2]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -80,7 +82,7 @@ array(103) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -91,7 +93,7 @@ array(103) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -100,7 +102,7 @@ array(103) {
[6]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -111,7 +113,7 @@ array(103) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -121,57 +123,57 @@ array(103) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
- int(3)
+ int(%d)
}
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[11]=>
string(1) "="
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[13]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
- int(3)
+ int(%d)
}
[14]=>
string(1) ";"
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
- int(3)
+ int(%d)
}
[16]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -180,7 +182,7 @@ array(103) {
[17]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -191,7 +193,7 @@ array(103) {
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -200,7 +202,7 @@ array(103) {
[20]=>
array(3) {
[0]=>
- int(372)
+ int(%d)
[1]=>
string(7) "<<<EOS
"
@@ -210,7 +212,7 @@ array(103) {
[21]=>
array(3) {
[0]=>
- int(314)
+ int(%d)
[1]=>
string(36) " This is to test
heredoc string
@@ -221,7 +223,7 @@ array(103) {
[22]=>
array(3) {
[0]=>
- int(373)
+ int(%d)
[1]=>
string(3) "EOS"
[2]=>
@@ -232,7 +234,7 @@ array(103) {
[24]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -242,7 +244,7 @@ array(103) {
[25]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -251,7 +253,7 @@ array(103) {
[26]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -260,7 +262,7 @@ array(103) {
[27]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -269,7 +271,7 @@ array(103) {
[28]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -280,7 +282,7 @@ array(103) {
[30]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -289,7 +291,7 @@ array(103) {
[31]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -300,7 +302,7 @@ array(103) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -310,7 +312,7 @@ array(103) {
[34]=>
array(3) {
[0]=>
- int(334)
+ int(%d)
[1]=>
string(8) "function"
[2]=>
@@ -319,7 +321,7 @@ array(103) {
[35]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -328,7 +330,7 @@ array(103) {
[36]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "myFunction"
[2]=>
@@ -339,7 +341,7 @@ array(103) {
[38]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -350,7 +352,7 @@ array(103) {
[40]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -362,7 +364,7 @@ array(103) {
[42]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -372,7 +374,7 @@ array(103) {
[43]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(8) "var_dump"
[2]=>
@@ -383,7 +385,7 @@ array(103) {
[45]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -396,7 +398,7 @@ array(103) {
[48]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -408,7 +410,7 @@ array(103) {
[50]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -418,7 +420,7 @@ array(103) {
[51]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -429,7 +431,7 @@ array(103) {
[53]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -438,7 +440,7 @@ array(103) {
[54]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -449,7 +451,7 @@ array(103) {
[56]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -458,7 +460,7 @@ array(103) {
[57]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -469,7 +471,7 @@ array(103) {
[59]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -480,7 +482,7 @@ array(103) {
[61]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -490,7 +492,7 @@ array(103) {
[62]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -499,7 +501,7 @@ array(103) {
[63]=>
array(3) {
[0]=>
- int(297)
+ int(%d)
[1]=>
string(2) "++"
[2]=>
@@ -510,7 +512,7 @@ array(103) {
[65]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -522,7 +524,7 @@ array(103) {
[67]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -532,7 +534,7 @@ array(103) {
[68]=>
array(3) {
[0]=>
- int(303)
+ int(%d)
[1]=>
string(4) "else"
[2]=>
@@ -541,7 +543,7 @@ array(103) {
[69]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -551,7 +553,7 @@ array(103) {
[70]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -560,7 +562,7 @@ array(103) {
[71]=>
array(3) {
[0]=>
- int(296)
+ int(%d)
[1]=>
string(2) "--"
[2]=>
@@ -571,7 +573,7 @@ array(103) {
[73]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -581,7 +583,7 @@ array(103) {
[74]=>
array(3) {
[0]=>
- int(318)
+ int(%d)
[1]=>
string(5) "while"
[2]=>
@@ -592,7 +594,7 @@ array(103) {
[76]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -601,7 +603,7 @@ array(103) {
[77]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -612,7 +614,7 @@ array(103) {
[79]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -621,7 +623,7 @@ array(103) {
[80]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "0"
[2]=>
@@ -632,7 +634,7 @@ array(103) {
[82]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -643,7 +645,7 @@ array(103) {
[84]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -653,7 +655,7 @@ array(103) {
[85]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -662,7 +664,7 @@ array(103) {
[86]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -671,7 +673,7 @@ array(103) {
[87]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(3) ""*""
[2]=>
@@ -682,7 +684,7 @@ array(103) {
[89]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -692,7 +694,7 @@ array(103) {
[90]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -701,7 +703,7 @@ array(103) {
[91]=>
array(3) {
[0]=>
- int(296)
+ int(%d)
[1]=>
string(2) "--"
[2]=>
@@ -712,7 +714,7 @@ array(103) {
[93]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -724,7 +726,7 @@ array(103) {
[95]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -734,7 +736,7 @@ array(103) {
[96]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(10) "myFunction"
[2]=>
@@ -745,7 +747,7 @@ array(103) {
[98]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -758,7 +760,7 @@ array(103) {
[101]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -768,7 +770,7 @@ array(103) {
[102]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation16.phpt b/ext/tokenizer/tests/token_get_all_variation16.phpt
index 4ae694e741..db9bde1ad6 100644
--- a/ext/tokenizer/tests/token_get_all_variation16.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation16.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with function constructs
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -45,17 +47,17 @@ else
list($value1,$value2) = $c;
if(empty($value1) && !isset($value1)) {
- __halt_compiler();
+ myFunction();
}
?>';
$tokens = token_get_all($source);
var_dump($tokens);
-echo "Done"
+echo "Done";
?>
--EXPECTF--
*** Testing token_get_all() : with different function constructs ***
-array(135) {
+array(142) {
[0]=>
array(3) {
[0]=>
@@ -956,9 +958,46 @@ array(135) {
[0]=>
int(%d)
[1]=>
- string(15) "__halt_compiler"
+ string(10) "myFunction"
+ [2]=>
+ int(26)
+ }
+ [135]=>
+ string(1) "("
+ [136]=>
+ string(1) ")"
+ [137]=>
+ string(1) ";"
+ [138]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
[2]=>
int(26)
}
+ [139]=>
+ string(1) "}"
+ [140]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(1) "
+"
+ [2]=>
+ int(27)
+ }
+ [141]=>
+ array(3) {
+ [0]=>
+ int(%d)
+ [1]=>
+ string(2) "?>"
+ [2]=>
+ int(28)
+ }
}
Done
diff --git a/ext/tokenizer/tests/token_get_all_variation17.phpt b/ext/tokenizer/tests/token_get_all_variation17.phpt
index ad73498468..dccc4c9c23 100644
--- a/ext/tokenizer/tests/token_get_all_variation17.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation17.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with exception keywords
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -42,7 +44,7 @@ array(81) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php
"
@@ -52,7 +54,7 @@ array(81) {
[1]=>
array(3) {
[0]=>
- int(334)
+ int(%d)
[1]=>
string(8) "function"
[2]=>
@@ -61,7 +63,7 @@ array(81) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -70,7 +72,7 @@ array(81) {
[3]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "inverse"
[2]=>
@@ -81,7 +83,7 @@ array(81) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$x"
[2]=>
@@ -92,7 +94,7 @@ array(81) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -104,17 +106,17 @@ array(81) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
[2]=>
- int(3)
+ int(%d)
}
[10]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -125,7 +127,7 @@ array(81) {
[12]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$x"
[2]=>
@@ -134,7 +136,7 @@ array(81) {
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -152,7 +154,7 @@ array(81) {
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -161,7 +163,7 @@ array(81) {
[16]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "0"
[2]=>
@@ -172,7 +174,7 @@ array(81) {
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -183,7 +185,7 @@ array(81) {
[20]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -193,7 +195,7 @@ array(81) {
[21]=>
array(3) {
[0]=>
- int(339)
+ int(%d)
[1]=>
string(5) "throw"
[2]=>
@@ -202,7 +204,7 @@ array(81) {
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -211,7 +213,7 @@ array(81) {
[23]=>
array(3) {
[0]=>
- int(299)
+ int(%d)
[1]=>
string(3) "new"
[2]=>
@@ -220,7 +222,7 @@ array(81) {
[24]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -229,7 +231,7 @@ array(81) {
[25]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(9) "Exception"
[2]=>
@@ -240,7 +242,7 @@ array(81) {
[27]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(17) ""Divison by zero""
[2]=>
@@ -253,7 +255,7 @@ array(81) {
[30]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -263,7 +265,7 @@ array(81) {
[31]=>
array(3) {
[0]=>
- int(303)
+ int(%d)
[1]=>
string(4) "else"
[2]=>
@@ -272,7 +274,7 @@ array(81) {
[32]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -282,7 +284,7 @@ array(81) {
[33]=>
array(3) {
[0]=>
- int(336)
+ int(%d)
[1]=>
string(6) "return"
[2]=>
@@ -291,7 +293,7 @@ array(81) {
[34]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -300,7 +302,7 @@ array(81) {
[35]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -311,7 +313,7 @@ array(81) {
[37]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$x"
[2]=>
@@ -322,7 +324,7 @@ array(81) {
[39]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -334,7 +336,7 @@ array(81) {
[41]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -344,7 +346,7 @@ array(81) {
[42]=>
array(3) {
[0]=>
- int(337)
+ int(%d)
[1]=>
string(3) "try"
[2]=>
@@ -353,7 +355,7 @@ array(81) {
[43]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -364,7 +366,7 @@ array(81) {
[45]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -374,7 +376,7 @@ array(81) {
[46]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -383,7 +385,7 @@ array(81) {
[47]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -392,7 +394,7 @@ array(81) {
[48]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "inverse"
[2]=>
@@ -403,7 +405,7 @@ array(81) {
[50]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "0"
[2]=>
@@ -416,7 +418,7 @@ array(81) {
[53]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -426,7 +428,7 @@ array(81) {
[54]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -435,7 +437,7 @@ array(81) {
[55]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -444,7 +446,7 @@ array(81) {
[56]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(7) "inverse"
[2]=>
@@ -455,7 +457,7 @@ array(81) {
[58]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "5"
[2]=>
@@ -468,7 +470,7 @@ array(81) {
[61]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -480,7 +482,7 @@ array(81) {
[63]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -489,7 +491,7 @@ array(81) {
[64]=>
array(3) {
[0]=>
- int(338)
+ int(%d)
[1]=>
string(5) "catch"
[2]=>
@@ -500,7 +502,7 @@ array(81) {
[66]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(9) "Exception"
[2]=>
@@ -509,7 +511,7 @@ array(81) {
[67]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -518,7 +520,7 @@ array(81) {
[68]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$e"
[2]=>
@@ -529,7 +531,7 @@ array(81) {
[70]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -540,7 +542,7 @@ array(81) {
[72]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(5) "
"
@@ -550,7 +552,7 @@ array(81) {
[73]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -559,7 +561,7 @@ array(81) {
[74]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -568,7 +570,7 @@ array(81) {
[75]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(19) ""caught exception:""
[2]=>
@@ -579,7 +581,7 @@ array(81) {
[77]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -591,7 +593,7 @@ array(81) {
[79]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -601,7 +603,7 @@ array(81) {
[80]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation18.phpt b/ext/tokenizer/tests/token_get_all_variation18.phpt
index f26a0433cd..01219ffaa4 100644
--- a/ext/tokenizer/tests/token_get_all_variation18.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation18.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with HTML code
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -34,7 +36,7 @@ array(9) {
[0]=>
array(3) {
[0]=>
- int(311)
+ int(%d)
[1]=>
string(48) "
<html>
@@ -50,7 +52,7 @@ array(9) {
[1]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -59,7 +61,7 @@ array(9) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -69,7 +71,7 @@ array(9) {
[3]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -78,7 +80,7 @@ array(9) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -87,7 +89,7 @@ array(9) {
[5]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(20) ""php code with HTML""
[2]=>
@@ -98,7 +100,7 @@ array(9) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -108,7 +110,7 @@ array(9) {
[8]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation19.phpt b/ext/tokenizer/tests/token_get_all_variation19.phpt
index ae614054f4..9ae6759a8f 100644
--- a/ext/tokenizer/tests/token_get_all_variation19.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation19.phpt
@@ -1,5 +1,7 @@
--TEST--
Reconstructing a script using token_get_all()
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
diff --git a/ext/tokenizer/tests/token_get_all_variation2.phpt b/ext/tokenizer/tests/token_get_all_variation2.phpt
index 897ff2e166..1f206260c7 100644
--- a/ext/tokenizer/tests/token_get_all_variation2.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation2.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with different arithmetic operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -35,7 +37,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -44,7 +46,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -53,7 +55,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -64,7 +66,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -73,7 +75,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -82,7 +84,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -93,7 +95,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -102,7 +104,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -113,7 +115,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -122,7 +124,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -134,7 +136,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -143,7 +145,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -152,7 +154,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -163,7 +165,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -172,7 +174,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -181,7 +183,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -192,7 +194,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -201,7 +203,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -212,7 +214,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -221,7 +223,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -233,7 +235,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -242,7 +244,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -251,7 +253,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -262,7 +264,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -271,7 +273,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -280,7 +282,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -291,7 +293,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -300,7 +302,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -311,7 +313,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -320,7 +322,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -332,7 +334,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -341,7 +343,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -350,7 +352,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -361,7 +363,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -370,7 +372,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -379,7 +381,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -390,7 +392,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -399,7 +401,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -410,7 +412,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -419,7 +421,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation3.phpt b/ext/tokenizer/tests/token_get_all_variation3.phpt
index 386a25bde2..66cf4aa87f 100644
--- a/ext/tokenizer/tests/token_get_all_variation3.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation3.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with logical operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -40,7 +42,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -49,7 +51,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -58,7 +60,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -69,7 +71,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -78,7 +80,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -87,7 +89,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -96,7 +98,7 @@ array(13) {
[7]=>
array(3) {
[0]=>
- int(265)
+ int(%d)
[1]=>
string(3) "and"
[2]=>
@@ -105,7 +107,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -114,7 +116,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(3) "024"
[2]=>
@@ -125,7 +127,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -134,7 +136,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -146,7 +148,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -155,7 +157,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -164,7 +166,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -175,7 +177,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -184,7 +186,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -193,7 +195,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -202,7 +204,7 @@ array(13) {
[7]=>
array(3) {
[0]=>
- int(263)
+ int(%d)
[1]=>
string(2) "or"
[2]=>
@@ -211,7 +213,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -220,7 +222,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(4) "0X1E"
[2]=>
@@ -231,7 +233,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -240,7 +242,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -252,7 +254,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -261,7 +263,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -270,7 +272,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -281,7 +283,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -290,7 +292,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -299,7 +301,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -308,7 +310,7 @@ array(13) {
[7]=>
array(3) {
[0]=>
- int(264)
+ int(%d)
[1]=>
string(3) "xor"
[2]=>
@@ -317,7 +319,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -326,7 +328,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -337,7 +339,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -346,7 +348,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -358,7 +360,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -367,7 +369,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -376,7 +378,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -387,7 +389,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -396,7 +398,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -405,7 +407,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -414,7 +416,7 @@ array(13) {
[7]=>
array(3) {
[0]=>
- int(279)
+ int(%d)
[1]=>
string(2) "&&"
[2]=>
@@ -423,7 +425,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -432,7 +434,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -443,7 +445,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -452,7 +454,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
@@ -464,7 +466,7 @@ array(13) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -473,7 +475,7 @@ array(13) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -482,7 +484,7 @@ array(13) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -493,7 +495,7 @@ array(13) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -502,7 +504,7 @@ array(13) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -511,7 +513,7 @@ array(13) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -520,7 +522,7 @@ array(13) {
[7]=>
array(3) {
[0]=>
- int(278)
+ int(%d)
[1]=>
string(2) "||"
[2]=>
@@ -529,7 +531,7 @@ array(13) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -538,7 +540,7 @@ array(13) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -549,7 +551,7 @@ array(13) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -558,7 +560,7 @@ array(13) {
[12]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation4.phpt b/ext/tokenizer/tests/token_get_all_variation4.phpt
index 40e42a5238..45e6f8afbd 100644
--- a/ext/tokenizer/tests/token_get_all_variation4.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation4.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with comparison operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -39,7 +41,7 @@ array(89) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -48,7 +50,7 @@ array(89) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -58,7 +60,7 @@ array(89) {
[2]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -69,7 +71,7 @@ array(89) {
[4]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -78,7 +80,7 @@ array(89) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -87,7 +89,7 @@ array(89) {
[6]=>
array(3) {
[0]=>
- int(283)
+ int(%d)
[1]=>
string(2) "=="
[2]=>
@@ -96,7 +98,7 @@ array(89) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -105,7 +107,7 @@ array(89) {
[8]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "0"
[2]=>
@@ -116,7 +118,7 @@ array(89) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(4) "
"
@@ -126,46 +128,46 @@ array(89) {
[11]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
- int(3)
+ int(%d)
}
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[13]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(6) ""== 0""
[2]=>
- int(3)
+ int(%d)
}
[14]=>
string(1) ";"
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[16]=>
array(3) {
[0]=>
- int(302)
+ int(%d)
[1]=>
string(6) "elseif"
[2]=>
@@ -176,7 +178,7 @@ array(89) {
[18]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -185,7 +187,7 @@ array(89) {
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -194,7 +196,7 @@ array(89) {
[20]=>
array(3) {
[0]=>
- int(281)
+ int(%d)
[1]=>
string(3) "==="
[2]=>
@@ -203,7 +205,7 @@ array(89) {
[21]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -212,7 +214,7 @@ array(89) {
[22]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -223,7 +225,7 @@ array(89) {
[24]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -233,7 +235,7 @@ array(89) {
[25]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -242,7 +244,7 @@ array(89) {
[26]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -251,7 +253,7 @@ array(89) {
[27]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(7) ""=== 2""
[2]=>
@@ -262,7 +264,7 @@ array(89) {
[29]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -272,7 +274,7 @@ array(89) {
[30]=>
array(3) {
[0]=>
- int(302)
+ int(%d)
[1]=>
string(6) "elseif"
[2]=>
@@ -283,7 +285,7 @@ array(89) {
[32]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -292,7 +294,7 @@ array(89) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -301,7 +303,7 @@ array(89) {
[34]=>
array(3) {
[0]=>
- int(284)
+ int(%d)
[1]=>
string(2) ">="
[2]=>
@@ -310,7 +312,7 @@ array(89) {
[35]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -319,7 +321,7 @@ array(89) {
[36]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -328,7 +330,7 @@ array(89) {
[37]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -346,7 +348,7 @@ array(89) {
[39]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -355,7 +357,7 @@ array(89) {
[40]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -364,7 +366,7 @@ array(89) {
[41]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -373,7 +375,7 @@ array(89) {
[42]=>
array(3) {
[0]=>
- int(285)
+ int(%d)
[1]=>
string(2) "<="
[2]=>
@@ -382,7 +384,7 @@ array(89) {
[43]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -391,7 +393,7 @@ array(89) {
[44]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "20"
[2]=>
@@ -402,7 +404,7 @@ array(89) {
[46]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -412,7 +414,7 @@ array(89) {
[47]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -421,7 +423,7 @@ array(89) {
[48]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -430,7 +432,7 @@ array(89) {
[49]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(14) "">= 10 & <=20""
[2]=>
@@ -441,7 +443,7 @@ array(89) {
[51]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -451,7 +453,7 @@ array(89) {
[52]=>
array(3) {
[0]=>
- int(302)
+ int(%d)
[1]=>
string(6) "elseif"
[2]=>
@@ -462,7 +464,7 @@ array(89) {
[54]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -471,7 +473,7 @@ array(89) {
[55]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -480,7 +482,7 @@ array(89) {
[56]=>
array(3) {
[0]=>
- int(282)
+ int(%d)
[1]=>
string(2) "!="
[2]=>
@@ -489,7 +491,7 @@ array(89) {
[57]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -498,7 +500,7 @@ array(89) {
[58]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -507,7 +509,7 @@ array(89) {
[59]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -525,7 +527,7 @@ array(89) {
[61]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -534,7 +536,7 @@ array(89) {
[62]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -543,7 +545,7 @@ array(89) {
[63]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -552,7 +554,7 @@ array(89) {
[64]=>
array(3) {
[0]=>
- int(282)
+ int(%d)
[1]=>
string(2) "<>"
[2]=>
@@ -561,7 +563,7 @@ array(89) {
[65]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -570,7 +572,7 @@ array(89) {
[66]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -581,7 +583,7 @@ array(89) {
[68]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -591,7 +593,7 @@ array(89) {
[69]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -600,7 +602,7 @@ array(89) {
[70]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -609,7 +611,7 @@ array(89) {
[71]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(6) ""!= 1""
[2]=>
@@ -620,7 +622,7 @@ array(89) {
[73]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -630,7 +632,7 @@ array(89) {
[74]=>
array(3) {
[0]=>
- int(302)
+ int(%d)
[1]=>
string(6) "elseif"
[2]=>
@@ -641,7 +643,7 @@ array(89) {
[76]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -650,7 +652,7 @@ array(89) {
[77]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -659,7 +661,7 @@ array(89) {
[78]=>
array(3) {
[0]=>
- int(280)
+ int(%d)
[1]=>
string(3) "!=="
[2]=>
@@ -668,7 +670,7 @@ array(89) {
[79]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -677,7 +679,7 @@ array(89) {
[80]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -688,7 +690,7 @@ array(89) {
[82]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(3) "
"
@@ -698,7 +700,7 @@ array(89) {
[83]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -707,7 +709,7 @@ array(89) {
[84]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -716,7 +718,7 @@ array(89) {
[85]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(6) ""!==1""
[2]=>
@@ -727,7 +729,7 @@ array(89) {
[87]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -737,7 +739,7 @@ array(89) {
[88]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation5.phpt b/ext/tokenizer/tests/token_get_all_variation5.phpt
index 84080db3f4..0068f2866f 100644
--- a/ext/tokenizer/tests/token_get_all_variation5.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation5.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with assignment operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -43,7 +45,7 @@ array(94) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -52,7 +54,7 @@ array(94) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -62,7 +64,7 @@ array(94) {
[2]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -71,7 +73,7 @@ array(94) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -82,7 +84,7 @@ array(94) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -91,7 +93,7 @@ array(94) {
[6]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -102,7 +104,7 @@ array(94) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -111,7 +113,7 @@ array(94) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -120,7 +122,7 @@ array(94) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -131,7 +133,7 @@ array(94) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -140,7 +142,7 @@ array(94) {
[13]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -151,7 +153,7 @@ array(94) {
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -161,20 +163,20 @@ array(94) {
[16]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
- int(3)
+ int(%d)
}
[17]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[18]=>
array(3) {
@@ -183,42 +185,42 @@ array(94) {
[1]=>
string(2) "+="
[2]=>
- int(3)
+ int(%d)
}
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[20]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
- int(3)
+ int(%d)
}
[21]=>
string(1) ";"
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[23]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -227,7 +229,7 @@ array(94) {
[24]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -245,7 +247,7 @@ array(94) {
[26]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -254,7 +256,7 @@ array(94) {
[27]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -265,7 +267,7 @@ array(94) {
[29]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -275,7 +277,7 @@ array(94) {
[30]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -284,7 +286,7 @@ array(94) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -302,7 +304,7 @@ array(94) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -311,7 +313,7 @@ array(94) {
[34]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -322,7 +324,7 @@ array(94) {
[36]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -332,7 +334,7 @@ array(94) {
[37]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$d"
[2]=>
@@ -341,7 +343,7 @@ array(94) {
[38]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -359,7 +361,7 @@ array(94) {
[40]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -368,7 +370,7 @@ array(94) {
[41]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(5) "10.50"
[2]=>
@@ -379,7 +381,7 @@ array(94) {
[43]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -389,7 +391,7 @@ array(94) {
[44]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -398,7 +400,7 @@ array(94) {
[45]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -416,7 +418,7 @@ array(94) {
[47]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -425,7 +427,7 @@ array(94) {
[48]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(5) "10.50"
[2]=>
@@ -436,7 +438,7 @@ array(94) {
[50]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -446,7 +448,7 @@ array(94) {
[51]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -455,7 +457,7 @@ array(94) {
[52]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -473,7 +475,7 @@ array(94) {
[54]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -482,7 +484,7 @@ array(94) {
[55]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -493,7 +495,7 @@ array(94) {
[57]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -503,7 +505,7 @@ array(94) {
[58]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -512,7 +514,7 @@ array(94) {
[59]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -530,7 +532,7 @@ array(94) {
[61]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -539,7 +541,7 @@ array(94) {
[62]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -550,7 +552,7 @@ array(94) {
[64]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -560,7 +562,7 @@ array(94) {
[65]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$d"
[2]=>
@@ -569,7 +571,7 @@ array(94) {
[66]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -587,7 +589,7 @@ array(94) {
[68]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -596,7 +598,7 @@ array(94) {
[69]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "5"
[2]=>
@@ -607,7 +609,7 @@ array(94) {
[71]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -617,7 +619,7 @@ array(94) {
[72]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -626,7 +628,7 @@ array(94) {
[73]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -644,7 +646,7 @@ array(94) {
[75]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -653,7 +655,7 @@ array(94) {
[76]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -664,7 +666,7 @@ array(94) {
[78]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -674,7 +676,7 @@ array(94) {
[79]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -683,7 +685,7 @@ array(94) {
[80]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -701,7 +703,7 @@ array(94) {
[82]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -710,7 +712,7 @@ array(94) {
[83]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -721,7 +723,7 @@ array(94) {
[85]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -731,7 +733,7 @@ array(94) {
[86]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$d"
[2]=>
@@ -740,7 +742,7 @@ array(94) {
[87]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -758,7 +760,7 @@ array(94) {
[89]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -767,7 +769,7 @@ array(94) {
[90]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(13) ""hello world""
[2]=>
@@ -778,7 +780,7 @@ array(94) {
[92]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -788,7 +790,7 @@ array(94) {
[93]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation6.phpt b/ext/tokenizer/tests/token_get_all_variation6.phpt
index 2c3a5fdb41..54936d0c89 100644
--- a/ext/tokenizer/tests/token_get_all_variation6.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation6.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with bitwise operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -33,7 +35,7 @@ array(50) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php
"
@@ -43,7 +45,7 @@ array(50) {
[1]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -52,7 +54,7 @@ array(50) {
[2]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -63,7 +65,7 @@ array(50) {
[4]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -72,7 +74,7 @@ array(50) {
[5]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -83,7 +85,7 @@ array(50) {
[7]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -92,7 +94,7 @@ array(50) {
[8]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -101,7 +103,7 @@ array(50) {
[9]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -112,7 +114,7 @@ array(50) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -121,7 +123,7 @@ array(50) {
[12]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "4"
[2]=>
@@ -132,7 +134,7 @@ array(50) {
[14]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -142,49 +144,49 @@ array(50) {
[15]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
- int(3)
+ int(%d)
}
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[17]=>
string(1) "="
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[19]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
- int(3)
+ int(%d)
}
[20]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[21]=>
array(3) {
@@ -193,42 +195,42 @@ array(50) {
[1]=>
string(2) "<<"
[2]=>
- int(3)
+ int(%d)
}
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[23]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
- int(3)
+ int(%d)
}
[24]=>
string(1) ";"
[25]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[26]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -237,7 +239,7 @@ array(50) {
[27]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -248,7 +250,7 @@ array(50) {
[29]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -257,7 +259,7 @@ array(50) {
[30]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -266,7 +268,7 @@ array(50) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -284,7 +286,7 @@ array(50) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -293,7 +295,7 @@ array(50) {
[34]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "2"
[2]=>
@@ -304,7 +306,7 @@ array(50) {
[36]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -314,7 +316,7 @@ array(50) {
[37]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(8) "var_dump"
[2]=>
@@ -325,7 +327,7 @@ array(50) {
[39]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -338,7 +340,7 @@ array(50) {
[42]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -348,7 +350,7 @@ array(50) {
[43]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(8) "var_dump"
[2]=>
@@ -359,7 +361,7 @@ array(50) {
[45]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -372,7 +374,7 @@ array(50) {
[48]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -382,7 +384,7 @@ array(50) {
[49]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation7.phpt b/ext/tokenizer/tests/token_get_all_variation7.phpt
index 6ba5d63596..36fda3298c 100644
--- a/ext/tokenizer/tests/token_get_all_variation7.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation7.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with increment/decrement operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -32,7 +34,7 @@ array(30) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -41,7 +43,7 @@ array(30) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -51,7 +53,7 @@ array(30) {
[2]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -60,7 +62,7 @@ array(30) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -71,7 +73,7 @@ array(30) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -80,7 +82,7 @@ array(30) {
[6]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -91,7 +93,7 @@ array(30) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -100,7 +102,7 @@ array(30) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -109,7 +111,7 @@ array(30) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -120,7 +122,7 @@ array(30) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -129,7 +131,7 @@ array(30) {
[13]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "5"
[2]=>
@@ -140,7 +142,7 @@ array(30) {
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -150,37 +152,37 @@ array(30) {
[16]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
- int(3)
+ int(%d)
}
[17]=>
array(3) {
[0]=>
- int(297)
+ int(%d)
[1]=>
string(2) "++"
[2]=>
- int(3)
+ int(%d)
}
[18]=>
string(1) ";"
[19]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[20]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -189,7 +191,7 @@ array(30) {
[21]=>
array(3) {
[0]=>
- int(296)
+ int(%d)
[1]=>
string(2) "--"
[2]=>
@@ -200,7 +202,7 @@ array(30) {
[23]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -210,7 +212,7 @@ array(30) {
[24]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -219,7 +221,7 @@ array(30) {
[25]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -228,7 +230,7 @@ array(30) {
[26]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -239,7 +241,7 @@ array(30) {
[28]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -249,7 +251,7 @@ array(30) {
[29]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation8.phpt b/ext/tokenizer/tests/token_get_all_variation8.phpt
index 542de2948b..0cf1d63471 100644
--- a/ext/tokenizer/tests/token_get_all_variation8.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation8.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with type casting operators
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -38,7 +40,7 @@ array(108) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -47,7 +49,7 @@ array(108) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -57,7 +59,7 @@ array(108) {
[2]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -66,7 +68,7 @@ array(108) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -77,7 +79,7 @@ array(108) {
[5]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -86,7 +88,7 @@ array(108) {
[6]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(1) "1"
[2]=>
@@ -97,7 +99,7 @@ array(108) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -106,7 +108,7 @@ array(108) {
[9]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -115,7 +117,7 @@ array(108) {
[10]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -126,7 +128,7 @@ array(108) {
[12]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -135,7 +137,7 @@ array(108) {
[13]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(4) "10.5"
[2]=>
@@ -144,7 +146,7 @@ array(108) {
[14]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -154,95 +156,95 @@ array(108) {
[15]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
- int(3)
+ int(%d)
}
[16]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[17]=>
string(1) "="
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[19]=>
array(3) {
[0]=>
- int(295)
+ int(%d)
[1]=>
string(5) "(int)"
[2]=>
- int(3)
+ int(%d)
}
[20]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
- int(3)
+ int(%d)
}
[21]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[22]=>
string(1) "+"
[23]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
- int(3)
+ int(%d)
}
[24]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
- int(3)
+ int(%d)
}
[25]=>
string(1) ";"
[26]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
[2]=>
- int(3)
+ int(%d)
}
[27]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$d"
[2]=>
@@ -251,7 +253,7 @@ array(108) {
[28]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -262,7 +264,7 @@ array(108) {
[30]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -271,7 +273,7 @@ array(108) {
[31]=>
array(3) {
[0]=>
- int(294)
+ int(%d)
[1]=>
string(7) "(float)"
[2]=>
@@ -280,7 +282,7 @@ array(108) {
[32]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -289,7 +291,7 @@ array(108) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -300,7 +302,7 @@ array(108) {
[35]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -309,7 +311,7 @@ array(108) {
[36]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -320,7 +322,7 @@ array(108) {
[38]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -330,7 +332,7 @@ array(108) {
[39]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$e"
[2]=>
@@ -339,7 +341,7 @@ array(108) {
[40]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -350,7 +352,7 @@ array(108) {
[42]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -359,7 +361,7 @@ array(108) {
[43]=>
array(3) {
[0]=>
- int(293)
+ int(%d)
[1]=>
string(8) "(string)"
[2]=>
@@ -368,7 +370,7 @@ array(108) {
[44]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -379,7 +381,7 @@ array(108) {
[46]=>
array(3) {
[0]=>
- int(293)
+ int(%d)
[1]=>
string(8) "(string)"
[2]=>
@@ -388,7 +390,7 @@ array(108) {
[47]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -399,7 +401,7 @@ array(108) {
[49]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -409,7 +411,7 @@ array(108) {
[50]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -420,7 +422,7 @@ array(108) {
[52]=>
array(3) {
[0]=>
- int(290)
+ int(%d)
[1]=>
string(6) "(bool)"
[2]=>
@@ -429,7 +431,7 @@ array(108) {
[53]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -440,7 +442,7 @@ array(108) {
[55]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -449,7 +451,7 @@ array(108) {
[56]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -458,7 +460,7 @@ array(108) {
[57]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -467,7 +469,7 @@ array(108) {
[58]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(6) ""true""
[2]=>
@@ -478,7 +480,7 @@ array(108) {
[60]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -488,7 +490,7 @@ array(108) {
[61]=>
array(3) {
[0]=>
- int(301)
+ int(%d)
[1]=>
string(2) "if"
[2]=>
@@ -501,7 +503,7 @@ array(108) {
[64]=>
array(3) {
[0]=>
- int(290)
+ int(%d)
[1]=>
string(9) "(boolean)"
[2]=>
@@ -510,7 +512,7 @@ array(108) {
[65]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -521,7 +523,7 @@ array(108) {
[67]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -530,7 +532,7 @@ array(108) {
[68]=>
array(3) {
[0]=>
- int(316)
+ int(%d)
[1]=>
string(4) "echo"
[2]=>
@@ -539,7 +541,7 @@ array(108) {
[69]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -548,7 +550,7 @@ array(108) {
[70]=>
array(3) {
[0]=>
- int(315)
+ int(%d)
[1]=>
string(7) ""false""
[2]=>
@@ -559,7 +561,7 @@ array(108) {
[72]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -569,7 +571,7 @@ array(108) {
[73]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -578,7 +580,7 @@ array(108) {
[74]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -589,7 +591,7 @@ array(108) {
[76]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -598,7 +600,7 @@ array(108) {
[77]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -607,7 +609,7 @@ array(108) {
[78]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -618,7 +620,7 @@ array(108) {
[80]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -627,7 +629,7 @@ array(108) {
[81]=>
array(3) {
[0]=>
- int(295)
+ int(%d)
[1]=>
string(9) "(integer)"
[2]=>
@@ -636,7 +638,7 @@ array(108) {
[82]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -645,7 +647,7 @@ array(108) {
[83]=>
array(3) {
[0]=>
- int(306)
+ int(%d)
[1]=>
string(7) "123.4e2"
[2]=>
@@ -656,7 +658,7 @@ array(108) {
[85]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -666,7 +668,7 @@ array(108) {
[86]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$d"
[2]=>
@@ -675,7 +677,7 @@ array(108) {
[87]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -686,7 +688,7 @@ array(108) {
[89]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -695,7 +697,7 @@ array(108) {
[90]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -704,7 +706,7 @@ array(108) {
[91]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -715,7 +717,7 @@ array(108) {
[93]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -724,7 +726,7 @@ array(108) {
[94]=>
array(3) {
[0]=>
- int(294)
+ int(%d)
[1]=>
string(6) "(real)"
[2]=>
@@ -733,7 +735,7 @@ array(108) {
[95]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -742,7 +744,7 @@ array(108) {
[96]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "12"
[2]=>
@@ -753,7 +755,7 @@ array(108) {
[98]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -763,7 +765,7 @@ array(108) {
[99]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -772,7 +774,7 @@ array(108) {
[100]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -783,7 +785,7 @@ array(108) {
[102]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -801,7 +803,7 @@ array(108) {
[104]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -812,7 +814,7 @@ array(108) {
[106]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -822,7 +824,7 @@ array(108) {
[107]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tests/token_get_all_variation9.phpt b/ext/tokenizer/tests/token_get_all_variation9.phpt
index 614859f2e9..1662fb27f3 100644
--- a/ext/tokenizer/tests/token_get_all_variation9.phpt
+++ b/ext/tokenizer/tests/token_get_all_variation9.phpt
@@ -1,5 +1,7 @@
--TEST--
Test token_get_all() function : usage variations - with different types of comments
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array token_get_all(string $source)
@@ -47,7 +49,7 @@ array(51) {
[0]=>
array(3) {
[0]=>
- int(368)
+ int(%d)
[1]=>
string(6) "<?php "
[2]=>
@@ -56,7 +58,7 @@ array(51) {
[1]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -66,7 +68,7 @@ array(51) {
[2]=>
array(3) {
[0]=>
- int(367)
+ int(%d)
[1]=>
string(65) "/** Performing addition operation on given values :
* a, b
@@ -77,7 +79,7 @@ array(51) {
[3]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(2) "
@@ -88,7 +90,7 @@ array(51) {
[4]=>
array(3) {
[0]=>
- int(366)
+ int(%d)
[1]=>
string(13) "// int value
"
@@ -98,7 +100,7 @@ array(51) {
[5]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -107,7 +109,7 @@ array(51) {
[6]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -118,7 +120,7 @@ array(51) {
[8]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -127,7 +129,7 @@ array(51) {
[9]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "10"
[2]=>
@@ -138,7 +140,7 @@ array(51) {
[11]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -148,7 +150,7 @@ array(51) {
[12]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -157,7 +159,7 @@ array(51) {
[13]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -168,7 +170,7 @@ array(51) {
[15]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -177,7 +179,7 @@ array(51) {
[16]=>
array(3) {
[0]=>
- int(305)
+ int(%d)
[1]=>
string(2) "20"
[2]=>
@@ -188,7 +190,7 @@ array(51) {
[18]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -198,7 +200,7 @@ array(51) {
[19]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -207,7 +209,7 @@ array(51) {
[20]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -218,7 +220,7 @@ array(51) {
[22]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -227,7 +229,7 @@ array(51) {
[23]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(4) "true"
[2]=>
@@ -238,7 +240,7 @@ array(51) {
[25]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -247,7 +249,7 @@ array(51) {
[26]=>
array(3) {
[0]=>
- int(366)
+ int(%d)
[1]=>
string(14) "// bool value
"
@@ -257,7 +259,7 @@ array(51) {
[27]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -267,7 +269,7 @@ array(51) {
[28]=>
array(3) {
[0]=>
- int(366)
+ int(%d)
[1]=>
string(59) "/*
* Performing operation on $a,$b
@@ -279,7 +281,7 @@ array(51) {
[29]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -289,7 +291,7 @@ array(51) {
[30]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -298,7 +300,7 @@ array(51) {
[31]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -309,7 +311,7 @@ array(51) {
[33]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -318,7 +320,7 @@ array(51) {
[34]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$a"
[2]=>
@@ -327,7 +329,7 @@ array(51) {
[35]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -338,7 +340,7 @@ array(51) {
[37]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -347,7 +349,7 @@ array(51) {
[38]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$b"
[2]=>
@@ -358,7 +360,7 @@ array(51) {
[40]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -368,7 +370,7 @@ array(51) {
[41]=>
array(3) {
[0]=>
- int(307)
+ int(%d)
[1]=>
string(8) "var_dump"
[2]=>
@@ -379,7 +381,7 @@ array(51) {
[43]=>
array(3) {
[0]=>
- int(309)
+ int(%d)
[1]=>
string(2) "$c"
[2]=>
@@ -392,7 +394,7 @@ array(51) {
[46]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) " "
[2]=>
@@ -401,9 +403,9 @@ array(51) {
[47]=>
array(3) {
[0]=>
- int(366)
+ int(%d)
[1]=>
- string(20) "# expected: int(30)
+ string(20) "# expected: int(%d)
"
[2]=>
int(16)
@@ -411,7 +413,7 @@ array(51) {
[48]=>
array(3) {
[0]=>
- int(371)
+ int(%d)
[1]=>
string(1) "
"
@@ -421,7 +423,7 @@ array(51) {
[49]=>
array(3) {
[0]=>
- int(366)
+ int(%d)
[1]=>
string(17) "# end of program
"
@@ -431,7 +433,7 @@ array(51) {
[50]=>
array(3) {
[0]=>
- int(370)
+ int(%d)
[1]=>
string(2) "?>"
[2]=>
diff --git a/ext/tokenizer/tokenizer.c b/ext/tokenizer/tokenizer.c
index cd6b7e134d..c5cbf6c7d2 100644
--- a/ext/tokenizer/tokenizer.c
+++ b/ext/tokenizer/tokenizer.c
@@ -32,8 +32,10 @@
#include "zend_language_scanner_defs.h"
#include <zend_language_parser.h>
-#define zendtext LANG_SCNG(yy_text)
-#define zendleng LANG_SCNG(yy_leng)
+#define zendtext LANG_SCNG(yy_text)
+#define zendleng LANG_SCNG(yy_leng)
+#define zendcursor LANG_SCNG(yy_cursor)
+#define zendlimit LANG_SCNG(yy_limit)
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_token_get_all, 0, 0, 1)
@@ -106,6 +108,7 @@ static void tokenize(zval *return_value TSRMLS_DC)
int token_type;
zend_bool destroy;
int token_line = 1;
+ int need_tokens = -1; // for __halt_compiler lexing. -1 = disabled
array_init(return_value);
@@ -150,11 +153,28 @@ static void tokenize(zval *return_value TSRMLS_DC)
}
ZVAL_NULL(&token);
- token_line = CG(zend_lineno);
-
- if (token_type == T_HALT_COMPILER) {
- break;
+ // after T_HALT_COMPILER collect the next three non-dropped tokens
+ if (need_tokens != -1) {
+ if (token_type != T_WHITESPACE && token_type != T_OPEN_TAG
+ && token_type != T_COMMENT && token_type != T_DOC_COMMENT
+ && --need_tokens == 0
+ ) {
+ // fetch the rest into a T_INLINE_HTML
+ if (zendcursor != zendlimit) {
+ MAKE_STD_ZVAL(keyword);
+ array_init(keyword);
+ add_next_index_long(keyword, T_INLINE_HTML);
+ add_next_index_stringl(keyword, (char *)zendcursor, zendlimit - zendcursor, 1);
+ add_next_index_long(keyword, token_line);
+ add_next_index_zval(return_value, keyword);
+ }
+ break;
+ }
+ } else if (token_type == T_HALT_COMPILER) {
+ need_tokens = 3;
}
+
+ token_line = CG(zend_lineno);
}
}
@@ -168,15 +188,16 @@ PHP_FUNCTION(token_get_all)
zval source_z;
zend_lex_state original_lex_state;
- if (zend_parse_parameters(argc TSRMLS_CC, "s", &source, &source_len) == FAILURE)
+ if (zend_parse_parameters(argc TSRMLS_CC, "s", &source, &source_len) == FAILURE) {
return;
+ }
ZVAL_STRINGL(&source_z, source, source_len, 1);
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
if (zend_prepare_string_for_scanning(&source_z, "" TSRMLS_CC) == FAILURE) {
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
- RETURN_EMPTY_STRING();
+ RETURN_FALSE;
}
LANG_SCNG(yy_state) = yycINITIAL;
diff --git a/ext/tokenizer/tokenizer_data.c b/ext/tokenizer/tokenizer_data.c
index bb28f70696..85822f1994 100644
--- a/ext/tokenizer/tokenizer_data.c
+++ b/ext/tokenizer/tokenizer_data.c
@@ -112,6 +112,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_CATCH", T_CATCH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_THROW", T_THROW, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_USE", T_USE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_INSTEADOF", T_INSTEADOF, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_GLOBAL", T_GLOBAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_PUBLIC", T_PUBLIC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_PROTECTED", T_PROTECTED, CONST_CS | CONST_PERSISTENT);
@@ -125,6 +126,7 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_EMPTY", T_EMPTY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_HALT_COMPILER", T_HALT_COMPILER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_CLASS", T_CLASS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_TRAIT", T_TRAIT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_INTERFACE", T_INTERFACE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_EXTENDS", T_EXTENDS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_IMPLEMENTS", T_IMPLEMENTS, CONST_CS | CONST_PERSISTENT);
@@ -132,7 +134,9 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
REGISTER_LONG_CONSTANT("T_DOUBLE_ARROW", T_DOUBLE_ARROW, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_LIST", T_LIST, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_ARRAY", T_ARRAY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_CALLABLE", T_CALLABLE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_CLASS_C", T_CLASS_C, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("T_TRAIT_C", T_TRAIT_C, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_METHOD_C", T_METHOD_C, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_FUNC_C", T_FUNC_C, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("T_LINE", T_LINE, CONST_CS | CONST_PERSISTENT);
@@ -242,6 +246,7 @@ char *get_token_type_name(int token_type)
case T_CATCH: return "T_CATCH";
case T_THROW: return "T_THROW";
case T_USE: return "T_USE";
+ case T_INSTEADOF: return "T_INSTEADOF";
case T_GLOBAL: return "T_GLOBAL";
case T_PUBLIC: return "T_PUBLIC";
case T_PROTECTED: return "T_PROTECTED";
@@ -255,6 +260,7 @@ char *get_token_type_name(int token_type)
case T_EMPTY: return "T_EMPTY";
case T_HALT_COMPILER: return "T_HALT_COMPILER";
case T_CLASS: return "T_CLASS";
+ case T_TRAIT: return "T_TRAIT";
case T_INTERFACE: return "T_INTERFACE";
case T_EXTENDS: return "T_EXTENDS";
case T_IMPLEMENTS: return "T_IMPLEMENTS";
@@ -262,7 +268,9 @@ char *get_token_type_name(int token_type)
case T_DOUBLE_ARROW: return "T_DOUBLE_ARROW";
case T_LIST: return "T_LIST";
case T_ARRAY: return "T_ARRAY";
+ case T_CALLABLE: return "T_CALLABLE";
case T_CLASS_C: return "T_CLASS_C";
+ case T_TRAIT_C: return "T_TRAIT_C";
case T_METHOD_C: return "T_METHOD_C";
case T_FUNC_C: return "T_FUNC_C";
case T_LINE: return "T_LINE";
diff --git a/ext/tokenizer/tokenizer_data_gen.sh b/ext/tokenizer/tokenizer_data_gen.sh
index 22d8110ae0..4519f9098f 100755
--- a/ext/tokenizer/tokenizer_data_gen.sh
+++ b/ext/tokenizer/tokenizer_data_gen.sh
@@ -30,7 +30,7 @@ echo '/*
+----------------------------------------------------------------------+
*/
-/* $Id: tokenizer_data_gen.sh,v 1.1.2.2.2.1 2008-02-12 00:45:14 stas Exp $ */
+/* $Id$ */
/*
DO NOT EDIT THIS FILE!
diff --git a/ext/wddx/tests/bug48562.phpt b/ext/wddx/tests/bug48562.phpt
index ebd2004e0a..ee9f271d91 100644
--- a/ext/wddx/tests/bug48562.phpt
+++ b/ext/wddx/tests/bug48562.phpt
@@ -16,6 +16,12 @@ $a['x'] = &$a;
var_dump(wddx_serialize_vars($a));
+// replace $a - the recursion detection seems to be causing $a to be not an array here, maybe its internally a pointer
+// replacing $a with a new array() allows this test to still check for 2 things
+// 1. recursion detection in &$a;
+// 2. recursion detection in adding $a to itself and then serializing $a
+// the one thing the test won't check is using $a as an array after doing &$a; which isn't really a wddx problem.
+$a = array();
$a['x'] = 'foo';
$a['x'] = $a;
diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c
index 0ddfd40df9..88990ab02e 100644
--- a/ext/wddx/wddx.c
+++ b/ext/wddx/wddx.c
@@ -457,7 +457,7 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
/* OBJECTS_FIXME */
zval **ent, *fname, **varname;
zval *retval = NULL;
- char *key;
+ const char *key;
ulong idx;
char tmp_buf[WDDX_BUF_LEN];
HashTable *objhash, *sleephash;
@@ -529,7 +529,7 @@ static void php_wddx_serialize_object(wddx_packet *packet, zval *obj)
}
if (zend_hash_get_current_key_ex(objhash, &key, &key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
- char *class_name, *prop_name;
+ const char *class_name, *prop_name;
zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
php_wddx_serialize_var(packet, *ent, prop_name, strlen(prop_name)+1 TSRMLS_CC);
diff --git a/ext/xml/config.w32 b/ext/xml/config.w32
index c0bdfd56ef..4ee0bd1602 100644
--- a/ext/xml/config.w32
+++ b/ext/xml/config.w32
@@ -16,4 +16,4 @@ if (PHP_XML == "yes") {
WARNING("xml support can't be enabled, libraries or headers are missing")
PHP_ZLIB = "no"
}
-} \ No newline at end of file
+}
diff --git a/ext/xml/tests/bug62328.phpt b/ext/xml/tests/bug62328.phpt
new file mode 100644
index 0000000000..e4c3c59d37
--- /dev/null
+++ b/ext/xml/tests/bug62328.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #62328 (implementing __toString and a cast to string fails)
+--SKIPIF--
+<?php
+require_once("skipif.inc");
+?>
+--FILE--
+<?php
+class UberSimpleXML extends SimpleXMLElement {
+ public function __toString() {
+ return 'stringification';
+ }
+}
+
+$xml = new UberSimpleXML('<xml/>');
+
+var_dump((string) $xml);
+var_dump($xml->__toString());
+--EXPECT--
+string(15) "stringification"
+string(15) "stringification"
diff --git a/ext/xml/tests/utf8_decode_variation1.phpt b/ext/xml/tests/utf8_decode_variation1.phpt
index 5966531723..4b9679a895 100644
--- a/ext/xml/tests/utf8_decode_variation1.phpt
+++ b/ext/xml/tests/utf8_decode_variation1.phpt
@@ -79,7 +79,7 @@ $values = array(
// loop through each element of the array for data
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( utf8_decode($value) );
};
diff --git a/ext/xml/tests/utf8_encode_variation1.phpt b/ext/xml/tests/utf8_encode_variation1.phpt
index 4b5d3c5d3c..04b956c422 100644
--- a/ext/xml/tests/utf8_encode_variation1.phpt
+++ b/ext/xml/tests/utf8_encode_variation1.phpt
@@ -79,7 +79,7 @@ $values = array(
// loop through each element of the array for data
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( utf8_encode($value) );
};
diff --git a/ext/xml/tests/xml001.phpt b/ext/xml/tests/xml001.phpt
index 62d597c5f8..9c03b553cc 100644
--- a/ext/xml/tests/xml001.phpt
+++ b/ext/xml/tests/xml001.phpt
@@ -5,8 +5,6 @@ XML parser test, function callbacks
require_once("skipif.inc");
XML_SAX_IMPL == 'libxml' && die('skip this test is not intended for libxml SAX parser');
?>
---INI--
-magic_quotes_runtime=0
--FILE--
<?php
chdir(dirname(__FILE__));
diff --git a/ext/xml/tests/xml002.phpt b/ext/xml/tests/xml002.phpt
index 8ae8dfbe66..ce547e8acc 100644
--- a/ext/xml/tests/xml002.phpt
+++ b/ext/xml/tests/xml002.phpt
@@ -5,8 +5,6 @@ XML parser test, object tuple callbacks
require_once("skipif.inc");
XML_SAX_IMPL == 'libxml' && die('skip this test is not intended for libxml SAX parser');
?>
---INI--
-magic_quotes_runtime=0
--FILE--
<?php
chdir(dirname(__FILE__));
diff --git a/ext/xml/tests/xml003.phpt b/ext/xml/tests/xml003.phpt
index 311c81acfb..6b0c3f5c5a 100644
--- a/ext/xml/tests/xml003.phpt
+++ b/ext/xml/tests/xml003.phpt
@@ -5,8 +5,6 @@ XML parser test, xml_set_object callbacks
require_once("skipif.inc");
XML_SAX_IMPL == 'libxml' && die('skip this test is not intended for libxml SAX parser');
?>
---INI--
-magic_quotes_runtime=0
--FILE--
<?php
chdir(dirname(__FILE__));
diff --git a/ext/xml/tests/xml004.phpt b/ext/xml/tests/xml004.phpt
index 78840ee122..245a93fc10 100644
--- a/ext/xml/tests/xml004.phpt
+++ b/ext/xml/tests/xml004.phpt
@@ -2,8 +2,6 @@
XML parser case folding test
--SKIPIF--
<?php include("skipif.inc"); ?>
---INI--
-magic_quotes_runtime=0
--FILE--
<?php
chdir(dirname(__FILE__));
diff --git a/ext/xml/tests/xml_closures_001.phpt b/ext/xml/tests/xml_closures_001.phpt
index 5439a2a918..37df254190 100644
--- a/ext/xml/tests/xml_closures_001.phpt
+++ b/ext/xml/tests/xml_closures_001.phpt
@@ -2,8 +2,6 @@
XML parser test using closures as callbacks
--SKIPIF--
<?php include("skipif.inc"); ?>
---INI--
-magic_quotes_runtime=0
--FILE--
<?php
chdir(dirname(__FILE__));
diff --git a/ext/xml/tests/xml_error_string_variation1.phpt b/ext/xml/tests/xml_error_string_variation1.phpt
index 2d21cd9c48..40b542c141 100644
--- a/ext/xml/tests/xml_error_string_variation1.phpt
+++ b/ext/xml/tests/xml_error_string_variation1.phpt
@@ -77,7 +77,7 @@ $values = array(
// loop through each element of the array for code
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_error_string($value) );
};
diff --git a/ext/xml/tests/xml_get_current_byte_index_variation1.phpt b/ext/xml/tests/xml_get_current_byte_index_variation1.phpt
index 7f57ee3297..b5c83d78e9 100644
--- a/ext/xml/tests/xml_get_current_byte_index_variation1.phpt
+++ b/ext/xml/tests/xml_get_current_byte_index_variation1.phpt
@@ -87,7 +87,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_get_current_byte_index($value) );
};
diff --git a/ext/xml/tests/xml_get_current_column_number_variation1.phpt b/ext/xml/tests/xml_get_current_column_number_variation1.phpt
index 59db610291..0eeb8d078e 100644
--- a/ext/xml/tests/xml_get_current_column_number_variation1.phpt
+++ b/ext/xml/tests/xml_get_current_column_number_variation1.phpt
@@ -88,7 +88,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_get_current_column_number($value) );
};
diff --git a/ext/xml/tests/xml_get_current_line_number_variation1.phpt b/ext/xml/tests/xml_get_current_line_number_variation1.phpt
index 0878dbb736..af41c6f9e8 100644
--- a/ext/xml/tests/xml_get_current_line_number_variation1.phpt
+++ b/ext/xml/tests/xml_get_current_line_number_variation1.phpt
@@ -87,7 +87,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_get_current_line_number($value) );
};
diff --git a/ext/xml/tests/xml_get_error_code_variation1.phpt b/ext/xml/tests/xml_get_error_code_variation1.phpt
index 32caa52b5f..474921406a 100644
--- a/ext/xml/tests/xml_get_error_code_variation1.phpt
+++ b/ext/xml/tests/xml_get_error_code_variation1.phpt
@@ -87,7 +87,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_get_error_code($value) );
};
diff --git a/ext/xml/tests/xml_parse_into_struct_variation1.phpt b/ext/xml/tests/xml_parse_into_struct_variation1.phpt
index 78b0cf43cd..fa1e8d2990 100644
--- a/ext/xml/tests/xml_parse_into_struct_variation1.phpt
+++ b/ext/xml/tests/xml_parse_into_struct_variation1.phpt
@@ -88,7 +88,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parse_into_struct($value, $data, $struct, $index) );
};
diff --git a/ext/xml/tests/xml_parse_variation1.phpt b/ext/xml/tests/xml_parse_variation1.phpt
index 23f199a4dc..cf36666499 100644
--- a/ext/xml/tests/xml_parse_variation1.phpt
+++ b/ext/xml/tests/xml_parse_variation1.phpt
@@ -89,7 +89,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parse($value, $data, $isFinal) );
};
diff --git a/ext/xml/tests/xml_parser_create_ns_variation1.phpt b/ext/xml/tests/xml_parser_create_ns_variation1.phpt
index 5446a4f3ee..2818b82fe8 100644
--- a/ext/xml/tests/xml_parser_create_ns_variation1.phpt
+++ b/ext/xml/tests/xml_parser_create_ns_variation1.phpt
@@ -91,7 +91,7 @@ $values = array(
// loop through each element of the array for encoding
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
$res = xml_parser_create_ns($value);
var_dump($res);
if ($res !== false) {
diff --git a/ext/xml/tests/xml_parser_create_variation1.phpt b/ext/xml/tests/xml_parser_create_variation1.phpt
index 445b40d08e..c5d588fec3 100644
--- a/ext/xml/tests/xml_parser_create_variation1.phpt
+++ b/ext/xml/tests/xml_parser_create_variation1.phpt
@@ -91,7 +91,7 @@ $values = array(
// loop through each element of the array for encoding
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
$res = xml_parser_create($value);
var_dump($res);
if ($res !== false) {
diff --git a/ext/xml/tests/xml_parser_free_variation1.phpt b/ext/xml/tests/xml_parser_free_variation1.phpt
index 4b4de5d05b..0ecb1092c8 100644
--- a/ext/xml/tests/xml_parser_free_variation1.phpt
+++ b/ext/xml/tests/xml_parser_free_variation1.phpt
@@ -87,7 +87,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parser_free($value) );
};
diff --git a/ext/xml/tests/xml_parser_get_option_variation1.phpt b/ext/xml/tests/xml_parser_get_option_variation1.phpt
index 4edf1d6a0b..b53f803188 100644
--- a/ext/xml/tests/xml_parser_get_option_variation1.phpt
+++ b/ext/xml/tests/xml_parser_get_option_variation1.phpt
@@ -88,7 +88,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parser_get_option($value, $option) );
};
diff --git a/ext/xml/tests/xml_parser_get_option_variation2.phpt b/ext/xml/tests/xml_parser_get_option_variation2.phpt
index de82111f83..2341c413f1 100644
--- a/ext/xml/tests/xml_parser_get_option_variation2.phpt
+++ b/ext/xml/tests/xml_parser_get_option_variation2.phpt
@@ -86,7 +86,7 @@ $values = array(
// loop through each element of the array for option
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parser_get_option($parser, $value) );
};
diff --git a/ext/xml/tests/xml_parser_set_option_variation1.phpt b/ext/xml/tests/xml_parser_set_option_variation1.phpt
index e3e3df8319..6cfce0b4e3 100644
--- a/ext/xml/tests/xml_parser_set_option_variation1.phpt
+++ b/ext/xml/tests/xml_parser_set_option_variation1.phpt
@@ -88,7 +88,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parser_set_option($value, $option, 1) );
};
diff --git a/ext/xml/tests/xml_parser_set_option_variation2.phpt b/ext/xml/tests/xml_parser_set_option_variation2.phpt
index 6f84ebb696..9900d6fe6a 100644
--- a/ext/xml/tests/xml_parser_set_option_variation2.phpt
+++ b/ext/xml/tests/xml_parser_set_option_variation2.phpt
@@ -81,7 +81,7 @@ $values = array(
// loop through each element of the array for option
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parser_set_option($parser, $value, 1) );
};
diff --git a/ext/xml/tests/xml_parser_set_option_variation3.phpt b/ext/xml/tests/xml_parser_set_option_variation3.phpt
index 5f98803905..c215ef5fde 100644
--- a/ext/xml/tests/xml_parser_set_option_variation3.phpt
+++ b/ext/xml/tests/xml_parser_set_option_variation3.phpt
@@ -90,7 +90,7 @@ $values = array(
// loop through each element of the array for value
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_parser_set_option($parser, $option, $value) );
};
diff --git a/ext/xml/tests/xml_set_character_data_handler_variation1.phpt b/ext/xml/tests/xml_set_character_data_handler_variation1.phpt
index bd384c9b62..40cff9193f 100644
--- a/ext/xml/tests/xml_set_character_data_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_character_data_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_character_data_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_default_handler_variation1.phpt b/ext/xml/tests/xml_set_default_handler_variation1.phpt
index a887e01673..35089a066a 100644
--- a/ext/xml/tests/xml_set_default_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_default_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_default_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_element_handler_variation1.phpt b/ext/xml/tests/xml_set_element_handler_variation1.phpt
index 83f370afea..225cf770b3 100644
--- a/ext/xml/tests/xml_set_element_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_element_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_element_handler($value, $hdl, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_end_namespace_decl_handler_variation1.phpt b/ext/xml/tests/xml_set_end_namespace_decl_handler_variation1.phpt
index c2fcacfe8b..c7c2f6f176 100644
--- a/ext/xml/tests/xml_set_end_namespace_decl_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_end_namespace_decl_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_end_namespace_decl_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_external_entity_ref_handler_variation1.phpt b/ext/xml/tests/xml_set_external_entity_ref_handler_variation1.phpt
index 1ad6a11279..10835b33b2 100644
--- a/ext/xml/tests/xml_set_external_entity_ref_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_external_entity_ref_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_external_entity_ref_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_notation_decl_handler_variation1.phpt b/ext/xml/tests/xml_set_notation_decl_handler_variation1.phpt
index d89b04d2a5..d41e691edc 100644
--- a/ext/xml/tests/xml_set_notation_decl_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_notation_decl_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_notation_decl_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_object_variation1.phpt b/ext/xml/tests/xml_set_object_variation1.phpt
index cc40445725..851dfaff10 100644
--- a/ext/xml/tests/xml_set_object_variation1.phpt
+++ b/ext/xml/tests/xml_set_object_variation1.phpt
@@ -88,7 +88,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_object($value, $obj) );
};
diff --git a/ext/xml/tests/xml_set_object_variation2.phpt b/ext/xml/tests/xml_set_object_variation2.phpt
index 210544c45d..0844661786 100644
--- a/ext/xml/tests/xml_set_object_variation2.phpt
+++ b/ext/xml/tests/xml_set_object_variation2.phpt
@@ -80,7 +80,7 @@ $values = array(
// loop through each element of the array for obj
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_object($parser, $value) );
};
diff --git a/ext/xml/tests/xml_set_processing_instruction_handler_variation1.phpt b/ext/xml/tests/xml_set_processing_instruction_handler_variation1.phpt
index 74cc1e5580..9da14cc5fd 100644
--- a/ext/xml/tests/xml_set_processing_instruction_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_processing_instruction_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_processing_instruction_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_start_namespace_decl_handler_variation1.phpt b/ext/xml/tests/xml_set_start_namespace_decl_handler_variation1.phpt
index c0323b36ae..684a0fdac4 100644
--- a/ext/xml/tests/xml_set_start_namespace_decl_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_start_namespace_decl_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_start_namespace_decl_handler($value, $hdl) );
};
diff --git a/ext/xml/tests/xml_set_unparsed_entity_decl_handler_variation1.phpt b/ext/xml/tests/xml_set_unparsed_entity_decl_handler_variation1.phpt
index 04290fa4e1..1804115021 100644
--- a/ext/xml/tests/xml_set_unparsed_entity_decl_handler_variation1.phpt
+++ b/ext/xml/tests/xml_set_unparsed_entity_decl_handler_variation1.phpt
@@ -92,7 +92,7 @@ $values = array(
// loop through each element of the array for parser
foreach($values as $value) {
- echo "\nArg value $value \n";
+ echo @"\nArg value $value \n";
var_dump( xml_set_unparsed_entity_decl_handler($value, $hdl) );
};
diff --git a/ext/xml/xml.c b/ext/xml/xml.c
index b13d8c4087..391e318a2d 100644
--- a/ext/xml/xml.c
+++ b/ext/xml/xml.c
@@ -32,6 +32,7 @@
#include "zend_variables.h"
#include "ext/standard/php_string.h"
#include "ext/standard/info.h"
+#include "ext/standard/html.h"
#if HAVE_XML
@@ -659,107 +660,6 @@ PHPAPI char *xml_utf8_encode(const char *s, int len, int *newlen, const XML_Char
}
/* }}} */
-/* copied from trunk's implementation of get_next_char in ext/standard/html.c */
-#define MB_FAILURE(pos, advance) do { \
- *cursor = pos + (advance); \
- *status = FAILURE; \
- return 0; \
-} while (0)
-
-#define CHECK_LEN(pos, chars_need) ((str_len - (pos)) >= (chars_need))
-#define utf8_lead(c) ((c) < 0x80 || ((c) >= 0xC2 && (c) <= 0xF4))
-#define utf8_trail(c) ((c) >= 0x80 && (c) <= 0xBF)
-
-/* {{{ php_next_utf8_char
- */
-static inline unsigned int php_next_utf8_char(
- const unsigned char *str,
- size_t str_len,
- size_t *cursor,
- int *status)
-{
- size_t pos = *cursor;
- unsigned int this_char = 0;
- unsigned char c;
-
- *status = SUCCESS;
-
- if (!CHECK_LEN(pos, 1))
- MB_FAILURE(pos, 1);
-
- /* We'll follow strategy 2. from section 3.6.1 of UTR #36:
- * "In a reported illegal byte sequence, do not include any
- * non-initial byte that encodes a valid character or is a leading
- * byte for a valid sequence.» */
- c = str[pos];
- if (c < 0x80) {
- this_char = c;
- pos++;
- } else if (c < 0xc2) {
- MB_FAILURE(pos, 1);
- } else if (c < 0xe0) {
- if (!CHECK_LEN(pos, 2))
- MB_FAILURE(pos, 1);
-
- if (!utf8_trail(str[pos + 1])) {
- MB_FAILURE(pos, utf8_lead(str[pos + 1]) ? 1 : 2);
- }
- this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f);
- if (this_char < 0x80) { /* non-shortest form */
- MB_FAILURE(pos, 2);
- }
- pos += 2;
- } else if (c < 0xf0) {
- size_t avail = str_len - pos;
-
- if (avail < 3 ||
- !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2])) {
- if (avail < 2 || utf8_lead(str[pos + 1]))
- MB_FAILURE(pos, 1);
- else if (avail < 3 || utf8_lead(str[pos + 2]))
- MB_FAILURE(pos, 2);
- else
- MB_FAILURE(pos, 3);
- }
-
- this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f);
- if (this_char < 0x800) { /* non-shortest form */
- MB_FAILURE(pos, 3);
- } else if (this_char >= 0xd800 && this_char <= 0xdfff) { /* surrogate */
- MB_FAILURE(pos, 3);
- }
- pos += 3;
- } else if (c < 0xf5) {
- size_t avail = str_len - pos;
-
- if (avail < 4 ||
- !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2]) ||
- !utf8_trail(str[pos + 3])) {
- if (avail < 2 || utf8_lead(str[pos + 1]))
- MB_FAILURE(pos, 1);
- else if (avail < 3 || utf8_lead(str[pos + 2]))
- MB_FAILURE(pos, 2);
- else if (avail < 4 || utf8_lead(str[pos + 3]))
- MB_FAILURE(pos, 3);
- else
- MB_FAILURE(pos, 4);
- }
-
- this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f);
- if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */
- MB_FAILURE(pos, 4);
- }
- pos += 4;
- } else {
- MB_FAILURE(pos, 1);
- }
-
- *cursor = pos;
- return this_char;
-}
-/* }}} */
-
-
/* {{{ xml_utf8_decode */
PHPAPI char *xml_utf8_decode(const XML_Char *s, int len, int *newlen, const XML_Char *encoding)
{
diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c
index 7a4cd0e718..c4a47b5a45 100644
--- a/ext/xmlreader/php_xmlreader.c
+++ b/ext/xmlreader/php_xmlreader.c
@@ -30,6 +30,7 @@
#ifdef HAVE_DOM
#include "ext/dom/xml_common.h"
#endif
+#include <libxml/xmlreader.h>
#include <libxml/uri.h>
zend_class_entry *xmlreader_class_entry;
@@ -112,7 +113,7 @@ static int xmlreader_property_reader(xmlreader_object *obj, xmlreader_prop_handl
/* }}} */
/* {{{ xmlreader_get_property_ptr_ptr */
-zval **xmlreader_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
+zval **xmlreader_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
{
xmlreader_object *obj;
zval tmp_member;
@@ -135,7 +136,7 @@ zval **xmlreader_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
}
if (ret == FAILURE) {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->get_property_ptr_ptr(object, member TSRMLS_CC);
+ retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -146,7 +147,7 @@ zval **xmlreader_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
/* }}} */
/* {{{ xmlreader_read_property */
-zval *xmlreader_read_property(zval *object, zval *member, int type TSRMLS_DC)
+zval *xmlreader_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
{
xmlreader_object *obj;
zval tmp_member;
@@ -178,7 +179,7 @@ zval *xmlreader_read_property(zval *object, zval *member, int type TSRMLS_DC)
}
} else {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->read_property(object, member, type TSRMLS_CC);
+ retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -189,7 +190,7 @@ zval *xmlreader_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* }}} */
/* {{{ xmlreader_write_property */
-void xmlreader_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
+void xmlreader_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
{
xmlreader_object *obj;
zval tmp_member;
@@ -214,7 +215,7 @@ void xmlreader_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write to read-only property");
} else {
std_hnd = zend_get_std_object_handlers();
- std_hnd->write_property(object, member, value TSRMLS_CC);
+ std_hnd->write_property(object, member, value, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -391,7 +392,6 @@ zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
{
zend_object_value retval;
xmlreader_object *intern;
- zval *tmp;
intern = emalloc(sizeof(xmlreader_object));
memset(&intern->std, 0, sizeof(zend_object));
@@ -401,7 +401,7 @@ zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
intern->prop_handler = &xmlreader_prop_handlers;
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) xmlreader_objects_free_storage, xmlreader_objects_clone TSRMLS_CC);
intern->handle = retval.handle;
retval.handlers = &xmlreader_object_handlers;
@@ -495,7 +495,7 @@ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int t
xmlRelaxNGPtr schema = NULL;
char *source;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &source, &source_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p!", &source, &source_len) == FAILURE) {
return;
}
@@ -872,7 +872,7 @@ PHP_METHOD(xmlreader, open)
char resolved_path[MAXPATHLEN + 1];
xmlTextReaderPtr reader = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
return;
}
@@ -958,7 +958,7 @@ PHP_METHOD(xmlreader, setSchema)
xmlreader_object *intern;
char *source;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &source, &source_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p!", &source, &source_len) == FAILURE) {
return;
}
@@ -1133,7 +1133,7 @@ Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader, expand)
{
#ifdef HAVE_DOM
- zval *id, *rv = NULL, *basenode = NULL;
+ zval *id, *basenode = NULL;
int ret;
xmlreader_object *intern;
xmlNode *node, *nodec;
@@ -1163,7 +1163,7 @@ PHP_METHOD(xmlreader, expand)
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot expand this node type");
RETURN_FALSE;
} else {
- DOM_RET_OBJ(rv, nodec, &ret, (dom_object *)domobj);
+ DOM_RET_OBJ(nodec, &ret, (dom_object *)domobj);
}
}
} else {
diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c
index c1152eb113..0514b17ff6 100644
--- a/ext/xmlwriter/php_xmlwriter.c
+++ b/ext/xmlwriter/php_xmlwriter.c
@@ -143,7 +143,6 @@ static void xmlwriter_object_free_storage(void *object TSRMLS_DC)
static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRMLS_DC)
{
ze_xmlwriter_object *intern;
- zval *tmp;
zend_object_value retval;
intern = emalloc(sizeof(ze_xmlwriter_object));
@@ -151,8 +150,7 @@ static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRML
intern->xmlwriter_ptr = NULL;
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,
- (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern,
NULL,
@@ -681,7 +679,7 @@ static void *php_xmlwriter_streams_IO_open_write_wrapper(const char *filename TS
php_stream_wrapper *wrapper = NULL;
void *ret_val = NULL;
- ret_val = php_stream_open_wrapper_ex((char *)filename, "wb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, NULL);
+ ret_val = php_stream_open_wrapper_ex((char *)filename, "wb", REPORT_ERRORS, NULL, NULL);
return ret_val;
}
/* }}} */
diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c
index 6f7237d57d..ce63b80620 100644
--- a/ext/xsl/php_xsl.c
+++ b/ext/xsl/php_xsl.c
@@ -115,7 +115,6 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
{
zend_object_value retval;
xsl_object *intern;
- zval *tmp;
intern = emalloc(sizeof(xsl_object));
intern->ptr = NULL;
@@ -127,9 +126,11 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
intern->node_list = NULL;
intern->doc = NULL;
intern->profiling = NULL;
+ intern->securityPrefs = XSL_SECPREF_DEFAULT;
+ intern->securityPrefsSet = 0;
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
- zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->std, class_type);
ALLOC_HASHTABLE(intern->parameter);
zend_hash_init(intern->parameter, 0, NULL, ZVAL_PTR_DTOR, 0);
ALLOC_HASHTABLE(intern->registered_phpfunctions);
@@ -181,7 +182,7 @@ PHP_MINIT_FUNCTION(xsl)
REGISTER_LONG_CONSTANT("XSL_SECPREF_READ_NETWORK", XSL_SECPREF_READ_NETWORK, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XSL_SECPREF_WRITE_NETWORK", XSL_SECPREF_WRITE_NETWORK, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XSL_SECPREF_DEFAULT", XSL_SECPREF_DEFAULT, CONST_CS | CONST_PERSISTENT);
-
+
REGISTER_LONG_CONSTANT("LIBXSLT_VERSION", LIBXSLT_VERSION, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("LIBXSLT_DOTTED_VERSION", LIBXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT);
diff --git a/ext/xsl/php_xsl.h b/ext/xsl/php_xsl.h
index 1cb36f66b1..b0548b562f 100644
--- a/ext/xsl/php_xsl.h
+++ b/ext/xsl/php_xsl.h
@@ -65,6 +65,8 @@ typedef struct _xsl_object {
HashTable *node_list;
php_libxml_node_object *doc;
char *profiling;
+ long securityPrefs;
+ int securityPrefsSet;
} xsl_object;
void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
diff --git a/ext/xsl/tests/bug54446.phpt b/ext/xsl/tests/bug54446.phpt
new file mode 100644
index 0000000000..f00b118ff8
--- /dev/null
+++ b/ext/xsl/tests/bug54446.phpt
@@ -0,0 +1,95 @@
+--TEST--
+Bug #54446 (Arbitrary file creation via libxslt 'output' extension)
+--SKIPIF--
+<?php
+if (!extension_loaded('xsl')) die("skip Extension XSL is required\n");
+?>
+--FILE--
+<?php
+include("prepare.inc");
+
+$outputfile = dirname(__FILE__)."/bug54446test.txt";
+if (file_exists($outputfile)) {
+ unlink($outputfile);
+}
+
+$sXsl = <<<EOT
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:sax="http://icl.com/saxon"
+ extension-element-prefixes="sax">
+
+ <xsl:template match="/">
+ <sax:output href="$outputfile" method="text">
+ <xsl:value-of select="'0wn3d via PHP and libxslt ...'"/>
+ </sax:output>
+ </xsl:template>
+
+</xsl:stylesheet>
+EOT;
+
+$xsl->loadXML( $sXsl );
+
+# START XSLT
+$proc->importStylesheet( $xsl );
+
+# TRASNFORM & PRINT
+print $proc->transformToXML( $dom );
+
+
+if (file_exists($outputfile)) {
+ print "$outputfile exists, but shouldn't!\n";
+} else {
+ print "OK, no file created\n";
+}
+
+#SET NO SECURITY PREFS
+$proc->setSecurityPrefs(XSL_SECPREF_NONE);
+
+# TRASNFORM & PRINT
+print $proc->transformToXML( $dom );
+
+
+if (file_exists($outputfile)) {
+ print "OK, file exists\n";
+} else {
+ print "$outputfile doesn't exist, but should!\n";
+}
+
+unlink($outputfile);
+
+#SET SECURITY PREFS AGAIN
+$proc->setSecurityPrefs( XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY);
+
+# TRASNFORM & PRINT
+print $proc->transformToXML( $dom );
+
+if (file_exists($outputfile)) {
+ print "$outputfile exists, but shouldn't!\n";
+} else {
+ print "OK, no file created\n";
+}
+
+
+--EXPECTF--
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
+OK, no file created
+OK, file exists
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
+OK, no file created
+--CREDITS--
+Christian Stocker, chregu@php.net
+
diff --git a/ext/xsl/tests/bug54446_with_ini.phpt b/ext/xsl/tests/bug54446_with_ini.phpt
index 31cd1d43be..fbe03659d3 100644
--- a/ext/xsl/tests/bug54446_with_ini.phpt
+++ b/ext/xsl/tests/bug54446_with_ini.phpt
@@ -70,6 +70,30 @@ if (file_exists($outputfile)) {
print "OK, no file created\n";
}
+#SET NO SECURITY PREFS with ini, but set them with ->setSecurityPrefs
+ini_set("xsl.security_prefs", XSL_SECPREF_NONE);
+$proc->setSecurityPrefs( XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY);
+
+print $proc->transformToXML( $dom );
+if (file_exists($outputfile)) {
+ print "$outputfile exists, but shouldn't!\n";
+} else {
+ print "OK, no file created\n";
+}
+
+#don't throw a warning if both ini and through-the-method have the same value
+$proc->setSecurityPrefs(XSL_SECPREF_NONE);
+
+print $proc->transformToXML( $dom );
+
+if (file_exists($outputfile)) {
+ print "OK, file exists\n";
+} else {
+ print "$outputfile doesn't exist, but should!\n";
+}
+unlink($outputfile);
+
+
--EXPECTF--
Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
@@ -80,6 +104,8 @@ Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element
Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
OK, no file created
+
+Deprecated: XSLTProcessor::transformToXml(): The xsl.security_prefs php.ini option is deprecated; use XsltProcessor->setSecurityPrefs() instead in %s on line %d
OK, file exists
Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
@@ -90,6 +116,20 @@ Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element
Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
OK, no file created
+
+Deprecated: XSLTProcessor::transformToXml(): The xsl.security_prefs php.ini option is deprecated; use XsltProcessor->setSecurityPrefs() instead in %s on line %d
+
+Notice: XSLTProcessor::transformToXml(): The xsl.security_prefs php.ini was not used, since the XsltProcessor->setSecurityPrefs() method was used in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d
+
+Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d
+OK, no file created
+OK, file exists
--CREDITS--
Christian Stocker, chregu@php.net
diff --git a/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcnostring.phpt b/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcnostring.phpt
index a0d6bf6b75..90d9c68208 100644
--- a/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcnostring.phpt
+++ b/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcnostring.phpt
@@ -25,12 +25,6 @@ var_dump($proc->transformToXml($dom));
NULL
Warning: XSLTProcessor::transformToXml(): Handler name must be a string in %s on line %d
-
-Warning: XSLTProcessor::transformToXml(): xmlXPathCompiledEval: evaluation failed in %s on line %d
-
-Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element value-of in %s on line %d
-
-Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result. in %s on line %d
NULL
--CREDITS--
Christian Weiske, cweiske@php.net
diff --git a/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcundef.phpt b/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcundef.phpt
index 1aa7bb051d..a26c210333 100644
--- a/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcundef.phpt
+++ b/ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcundef.phpt
@@ -24,12 +24,6 @@ var_dump($proc->transformToXml($dom));
NULL
Warning: XSLTProcessor::transformToXml(): Unable to call handler undefinedfunc() in %s on line %d
-
-Warning: XSLTProcessor::transformToXml(): xmlXPathCompiledEval: evaluation failed in %s on line %d
-
-Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element value-of in %s on line %d
-
-Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result. in %s on line %d
NULL
--CREDITS--
Christian Weiske, cweiske@php.net
diff --git a/ext/xsl/xsl_fe.h b/ext/xsl/xsl_fe.h
index 1c20970279..889706ed66 100644
--- a/ext/xsl/xsl_fe.h
+++ b/ext/xsl/xsl_fe.h
@@ -34,6 +34,9 @@ PHP_FUNCTION(xsl_xsltprocessor_remove_parameter);
PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support);
PHP_FUNCTION(xsl_xsltprocessor_register_php_functions);
PHP_FUNCTION(xsl_xsltprocessor_set_profiling);
+PHP_FUNCTION(xsl_xsltprocessor_set_security_prefs);
+PHP_FUNCTION(xsl_xsltprocessor_get_security_prefs);
+
#endif
/*
diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
index 5ac45531c4..5aa6aa943b 100644
--- a/ext/xsl/xsltprocessor.c
+++ b/ext/xsl/xsltprocessor.c
@@ -71,6 +71,13 @@ ZEND_END_ARG_INFO();
ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_profiling, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_security_prefs, 0, 0, 1)
+ ZEND_ARG_INFO(0, securityPrefs)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_get_security_prefs, 0, 0, 0)
+ZEND_END_ARG_INFO();
/* }}} */
/*
@@ -91,6 +98,8 @@ const zend_function_entry php_xsl_xsltprocessor_class_functions[] = {
PHP_FALIAS(hasExsltSupport, xsl_xsltprocessor_has_exslt_support, arginfo_xsl_xsltprocessor_has_exslt_support)
PHP_FALIAS(registerPHPFunctions, xsl_xsltprocessor_register_php_functions, arginfo_xsl_xsltprocessor_register_php_functions)
PHP_FALIAS(setProfiling, xsl_xsltprocessor_set_profiling, arginfo_xsl_xsltprocessor_set_profiling)
+ PHP_FALIAS(setSecurityPrefs, xsl_xsltprocessor_set_security_prefs, arginfo_xsl_xsltprocessor_set_security_prefs)
+ PHP_FALIAS(getSecurityPrefs, xsl_xsltprocessor_get_security_prefs, arginfo_xsl_xsltprocessor_get_security_prefs)
{NULL, NULL, NULL}
};
@@ -271,7 +280,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
node->parent = nsparent;
node->ns = curns;
}
- child = php_dom_create_object(node, &ret, NULL, child, domintern TSRMLS_CC);
+ child = php_dom_create_object(node, &ret, child, domintern TSRMLS_CC);
add_next_index_zval(args[i], child);
}
}
@@ -293,6 +302,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
if (obj->stringval == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
xmlXPathFreeObject(obj);
+ valuePush(ctxt, xmlXPathNewString(""));
if (fci.param_count > 0) {
for (i = 0; i < nargs - 1; i++) {
zval_ptr_dtor(&args[i]);
@@ -314,7 +324,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
/*fci.function_handler_cache = &function_ptr;*/
if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", callable);
-
+ valuePush(ctxt, xmlXPathNewString(""));
} else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not allowed to call handler '%s()'", callable);
/* Push an empty string, so that we at least have an xslt result... */
@@ -324,8 +334,9 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
if (result == FAILURE) {
if (Z_TYPE(handler) == IS_STRING) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler));
+ valuePush(ctxt, xmlXPathNewString(""));
}
- /* retval is == NULL, when an exception occured, don't report anything, because PHP itself will handle that */
+ /* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */
} else if (retval == NULL) {
} else {
if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) {
@@ -427,7 +438,7 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
std_hnd = zend_get_std_object_handlers();
MAKE_STD_ZVAL(member);
ZVAL_STRING(member, "cloneDocument", 0);
- cloneDocu = std_hnd->read_property(id, member, BP_VAR_IS TSRMLS_CC);
+ cloneDocu = std_hnd->read_property(id, member, BP_VAR_IS, NULL TSRMLS_CC);
if (Z_TYPE_P(cloneDocu) != IS_NULL) {
convert_to_long(cloneDocu);
clone_docu = Z_LVAL_P(cloneDocu);
@@ -476,7 +487,7 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
zend_object_handlers *std_hnd;
FILE *f;
int secPrefsError = 0;
- int secPrefsValue;
+ int secPrefsValue, secPrefsIni;
xsltSecurityPrefsPtr secPrefs = NULL;
node = php_libxml_import_node(docp TSRMLS_CC);
@@ -527,16 +538,32 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
MAKE_STD_ZVAL(member);
ZVAL_STRING(member, "doXInclude", 0);
- doXInclude = std_hnd->read_property(id, member, BP_VAR_IS TSRMLS_CC);
+ doXInclude = std_hnd->read_property(id, member, BP_VAR_IS, NULL TSRMLS_CC);
if (Z_TYPE_P(doXInclude) != IS_NULL) {
convert_to_long(doXInclude);
ctxt->xinclude = Z_LVAL_P(doXInclude);
}
efree(member);
+ secPrefsValue = intern->securityPrefs;
- secPrefsValue = INI_INT("xsl.security_prefs");
-
+ /* This whole if block can be removed, when we remove the xsl.security_prefs php.ini option in PHP 6+ */
+ secPrefsIni= INI_INT("xsl.security_prefs");
+ /* if secPrefsIni has the same value as secPrefsValue, all is fine */
+ if (secPrefsIni != secPrefsValue) {
+ if (secPrefsIni != XSL_SECPREF_DEFAULT) {
+ /* if the ini value is not set to the default, throw an E_DEPRECATED warning */
+ php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "The xsl.security_prefs php.ini option is deprecated; use XsltProcessor->setSecurityPrefs() instead");
+ if (intern->securityPrefsSet == 0) {
+ /* if securityPrefs were not set through the setSecurityPrefs method, take the ini setting */
+ secPrefsValue = secPrefsIni;
+ } else {
+ /* else throw a notice, that the ini setting was not used */
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The xsl.security_prefs php.ini was not used, since the XsltProcessor->setSecurityPrefs() method was used");
+ }
+ }
+ }
+
/* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
if (secPrefsValue != XSL_SECPREF_NONE) {
secPrefs = xsltNewSecurityPrefs();
@@ -614,7 +641,7 @@ Since:
*/
PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
{
- zval *id, *rv = NULL, *docp = NULL;
+ zval *id, *docp = NULL;
xmlDoc *newdocp;
xsltStylesheetPtr sheetp;
int ret, ret_class_len=0;
@@ -658,7 +685,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
php_libxml_increment_doc_ref(interndoc, newdocp TSRMLS_CC);
php_libxml_increment_node_ptr(interndoc, (xmlNodePtr)newdocp, (void *)interndoc TSRMLS_CC);
} else {
- DOM_RET_OBJ(rv, (xmlNodePtr) newdocp, &ret, NULL);
+ DOM_RET_OBJ((xmlNodePtr) newdocp, &ret, NULL);
}
} else {
RETURN_FALSE;
@@ -682,7 +709,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
sheetp = (xsltStylesheetPtr) intern->ptr;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os", &docp, &uri, &uri_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "op", &docp, &uri, &uri_len) == FAILURE) {
RETURN_FALSE;
}
@@ -690,10 +717,6 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
ret = -1;
if (newdocp) {
- if (strlen(uri) != uri_len) {
- xmlFreeDoc(newdocp);
- RETURN_FALSE;
- }
ret = xsltSaveResultToFilename(uri, newdocp, sheetp, 0);
xmlFreeDoc(newdocp);
}
@@ -892,12 +915,12 @@ PHP_FUNCTION(xsl_xsltprocessor_set_profiling)
int filename_len;
DOM_GET_THIS(id);
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s!", &filename, &filename_len) == SUCCESS) {
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "p!", &filename, &filename_len) == SUCCESS) {
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
if (intern->profiling) {
efree(intern->profiling);
}
- if (filename != NULL && strlen(filename) == filename_len) {
+ if (filename != NULL) {
intern->profiling = estrndup(filename,filename_len);
} else {
intern->profiling = NULL;
@@ -909,6 +932,44 @@ PHP_FUNCTION(xsl_xsltprocessor_set_profiling)
}
/* }}} end xsl_xsltprocessor_set_profiling */
+/* {{{ proto long xsl_xsltprocessor_set_security_prefs(long securityPrefs) */
+PHP_FUNCTION(xsl_xsltprocessor_set_security_prefs)
+{
+ zval *id;
+ xsl_object *intern;
+ long securityPrefs, oldSecurityPrefs;
+
+ DOM_GET_THIS(id);
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &securityPrefs) == FAILURE) {
+ return;
+ }
+ intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
+ oldSecurityPrefs = intern->securityPrefs;
+ intern->securityPrefs = securityPrefs;
+ /* set this to 1 so that we know, it was set through this method. Can be removed, when we remove the ini setting */
+ intern->securityPrefsSet = 1;
+ RETURN_LONG(oldSecurityPrefs);
+}
+/* }}} end xsl_xsltprocessor_set_security_prefs */
+
+/* {{{ proto long xsl_xsltprocessor_get_security_prefs() */
+PHP_FUNCTION(xsl_xsltprocessor_get_security_prefs)
+{
+ zval *id;
+ xsl_object *intern;
+
+ DOM_GET_THIS(id);
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "") == SUCCESS) {
+ intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
+ RETURN_LONG(intern->securityPrefs);
+ } else {
+ WRONG_PARAM_COUNT;
+ }
+}
+/* }}} end xsl_xsltprocessor_get_security_prefs */
+
+
+
/* {{{ proto bool xsl_xsltprocessor_has_exslt_support();
*/
PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support)
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 75f98b591f..74f868b5c3 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -160,7 +160,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
/* Clean/normlize the path and then transform any path (absolute or relative)
to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
*/
- virtual_file_ex(&new_state, file, NULL, CWD_EXPAND);
+ virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC);
path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
if(!path_cleaned) {
return 0;
@@ -232,7 +232,6 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
efree(file_dirname_fullpath);
efree(file_basename);
free(new_state.cwd);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot build full extract path");
return 0;
} else if (len > MAXPATHLEN) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
@@ -273,14 +272,6 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
}
n = 0;
- if (stream == NULL) {
- int ret = zip_fclose(zf);
- efree(fullpath);
- efree(file_basename);
- efree(file_dirname_fullpath);
- free(new_state.cwd);
- return 0;
- }
while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
php_stream_write(stream, b, n);
@@ -871,7 +862,7 @@ static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zv
}
/* }}} */
-static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
+static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ze_zip_object *obj;
zval tmp_member;
@@ -886,19 +877,24 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
member = &tmp_member;
+ key = NULL;
}
ret = FAILURE;
obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
if (obj->prop_handler != NULL) {
- ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ if (key) {
+ ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
+ } else {
+ ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ }
}
if (ret == FAILURE) {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->get_property_ptr_ptr(object, member TSRMLS_CC);
+ retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -908,7 +904,7 @@ static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
}
/* }}} */
-static zval* php_zip_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
+static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ze_zip_object *obj;
zval tmp_member;
@@ -922,13 +918,18 @@ static zval* php_zip_read_property(zval *object, zval *member, int type TSRMLS_D
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
member = &tmp_member;
+ key = NULL;
}
ret = FAILURE;
obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
if (obj->prop_handler != NULL) {
- ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ if (key) {
+ ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
+ } else {
+ ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ }
}
if (ret == SUCCESS) {
@@ -941,7 +942,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type TSRMLS_D
}
} else {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->read_property(object, member, type TSRMLS_CC);
+ retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -951,7 +952,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type TSRMLS_D
}
/* }}} */
-static int php_zip_has_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
+static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
{
ze_zip_object *obj;
zval tmp_member;
@@ -964,13 +965,18 @@ static int php_zip_has_property(zval *object, zval *member, int type TSRMLS_DC)
zval_copy_ctor(&tmp_member);
convert_to_string(&tmp_member);
member = &tmp_member;
+ key = NULL;
}
ret = FAILURE;
obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
if (obj->prop_handler != NULL) {
- ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ if (key) {
+ ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
+ } else {
+ ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ }
}
if (ret == SUCCESS) {
@@ -992,7 +998,7 @@ static int php_zip_has_property(zval *object, zval *member, int type TSRMLS_DC)
zval_ptr_dtor(&tmp);
} else {
std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->has_property(object, member, type TSRMLS_CC);
+ retval = std_hnd->has_property(object, member, type, key TSRMLS_CC);
}
if (member == &tmp_member) {
@@ -1015,7 +1021,7 @@ static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
ulong num_key;
obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
- props = obj->zo.properties;
+ props = zend_std_get_properties(object TSRMLS_CC);
if (obj->prop_handler == NULL) {
return NULL;
@@ -1032,7 +1038,7 @@ static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
zend_hash_move_forward_ex(obj->prop_handler, &pos);
}
- return obj->zo.properties;
+ return props;
}
/* }}} */
@@ -1084,7 +1090,6 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
ze_zip_object *intern;
- zval *tmp;
zend_object_value retval;
intern = emalloc(sizeof(ze_zip_object));
@@ -1104,8 +1109,7 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_
intern->zo.ce = class_type;
#endif
- zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor,
- (void *) &tmp, sizeof(zval *));
+ object_properties_init(&intern->zo, class_type);
retval.handle = zend_objects_store_put(intern,
NULL,
@@ -1204,7 +1208,7 @@ static PHP_NAMED_FUNCTION(zif_zip_open)
zip_rsrc *rsrc_int;
int err = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
@@ -1213,10 +1217,6 @@ static PHP_NAMED_FUNCTION(zif_zip_open)
RETURN_FALSE;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
RETURN_FALSE;
}
@@ -1491,7 +1491,7 @@ static ZIPARCHIVE_METHOD(open)
zval *this = getThis();
ze_zip_object *ze_obj = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) {
return;
}
@@ -1505,10 +1505,6 @@ static ZIPARCHIVE_METHOD(open)
RETURN_FALSE;
}
- if (strlen(filename) != filename_len) {
- RETURN_FALSE;
- }
-
if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
RETURN_FALSE;
}
@@ -1664,12 +1660,12 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /*
ZIP_FROM_OBJECT(intern, this);
/* 1 == glob, 2==pcre */
if (type == 1) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
&pattern, &pattern_len, &flags, &options) == FAILURE) {
return;
}
} else {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sa",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
&pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
return;
}
@@ -1783,7 +1779,7 @@ static ZIPARCHIVE_METHOD(addFile)
ZIP_FROM_OBJECT(intern, this);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sll",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll",
&filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
return;
}
@@ -1882,7 +1878,7 @@ static ZIPARCHIVE_METHOD(statName)
ZIP_FROM_OBJECT(intern, this);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
&name, &name_len, &flags) == FAILURE) {
return;
}
@@ -1938,7 +1934,7 @@ static ZIPARCHIVE_METHOD(locateName)
ZIP_FROM_OBJECT(intern, this);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
&name, &name_len, &flags) == FAILURE) {
return;
}
@@ -2435,15 +2431,11 @@ static ZIPARCHIVE_METHOD(extractTo)
RETURN_FALSE;
}
- if (strlen(pathto) != pathto_len) {
- RETURN_FALSE;
- }
-
if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
- ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
- if (!ret) {
- RETURN_FALSE;
- }
+ ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
+ if (!ret) {
+ RETURN_FALSE;
+ }
}
ZIP_FROM_OBJECT(intern, this);
@@ -2479,21 +2471,21 @@ static ZIPARCHIVE_METHOD(extractTo)
break;
}
} else {
- /* Extract all files */
- int filecount = zip_get_num_files(intern);
+ /* Extract all files */
+ int filecount = zip_get_num_files(intern);
- if (filecount == -1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
- RETURN_FALSE;
- }
+ if (filecount == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
+ RETURN_FALSE;
+ }
- for (i = 0; i < filecount; i++) {
- char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
- if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
- RETURN_FALSE;
- }
- }
+ for (i = 0; i < filecount; i++) {
+ char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
+ if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
}
+ }
RETURN_TRUE;
}
/* }}} */
@@ -2522,10 +2514,7 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
ZIP_FROM_OBJECT(intern, this);
if (type == 1) {
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
- return;
- }
- if (strlen(filename) != filename_len) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
return;
}
PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
@@ -2601,7 +2590,7 @@ static ZIPARCHIVE_METHOD(getStream)
ZIP_FROM_OBJECT(intern, this);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
diff --git a/ext/zlib/CREDITS b/ext/zlib/CREDITS
index c0a47dd293..a1773c463d 100644
--- a/ext/zlib/CREDITS
+++ b/ext/zlib/CREDITS
@@ -1,2 +1,2 @@
Zlib
-Rasmus Lerdorf, Stefan Roehrich, Zeev Suraski, Jade Nicoletti
+Rasmus Lerdorf, Stefan Roehrich, Zeev Suraski, Jade Nicoletti, Michael Wallner
diff --git a/ext/zlib/config0.m4 b/ext/zlib/config0.m4
index 62e05fbd02..25c7f4f420 100644
--- a/ext/zlib/config0.m4
+++ b/ext/zlib/config0.m4
@@ -41,10 +41,17 @@ if test "$PHP_ZLIB" != "no" || test "$PHP_ZLIB_DIR" != "no"; then
*) ac_extra=-L$ZLIB_DIR/$PHP_LIBDIR ;;
esac
+ AC_MSG_CHECKING([for zlib version >= 1.2.0.4])
+ ZLIB_VERSION=`$EGREP "define ZLIB_VERSION" $ZLIB_DIR/include/zlib.h | $SED -e 's/[[^0-9\.]]//g'`
+ AC_MSG_RESULT([$ZLIB_VERSION])
+ if test `echo $ZLIB_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*1000000 + $2*10000 + $3*100 + $4}'` -lt 1020004; then
+ AC_MSG_ERROR([libz version greater or equal to 1.2.0.4 required])
+ fi
+
PHP_CHECK_LIBRARY(z, gzgets, [
AC_DEFINE(HAVE_ZLIB,1,[ ])
],[
- AC_MSG_ERROR(ZLIB extension requires zlib >= 1.0.9)
+ AC_MSG_ERROR(ZLIB extension requires gzgets in zlib)
],[
$ac_extra
])
diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h
index 7c4bd54037..e895e0e482 100644
--- a/ext/zlib/php_zlib.h
+++ b/ext/zlib/php_zlib.h
@@ -13,7 +13,8 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
- | Stefan Röhrich <sr@linux.de> |
+ | Stefan R�hrich <sr@linux.de> |
+ | Michael Wallner <mike@php.net> |
+----------------------------------------------------------------------+
*/
@@ -24,39 +25,54 @@
#include <zlib.h>
+#define PHP_ZLIB_ENCODING_RAW -0xf
+#define PHP_ZLIB_ENCODING_GZIP 0x1f
+#define PHP_ZLIB_ENCODING_DEFLATE 0x0f
+
+#define PHP_ZLIB_ENCODING_ANY 0x2f
+
+#define PHP_ZLIB_OUTPUT_HANDLER_NAME "zlib output compression"
+#define PHP_ZLIB_BUFFER_SIZE_GUESS(in_len) (((size_t) ((double) in_len * (double) 1.015)) + 10 + 8 + 4 + 1)
+
+typedef struct _php_zlib_buffer {
+ char *data;
+ char *aptr;
+ size_t used;
+ size_t free;
+ size_t size;
+} php_zlib_buffer;
+
+typedef struct _php_zlib_context {
+ z_stream Z;
+ php_zlib_buffer buffer;
+} php_zlib_context;
+
ZEND_BEGIN_MODULE_GLOBALS(zlib)
/* variables for transparent gzip encoding */
int compression_coding;
- z_stream stream;
- uLong crc;
- int ob_gzhandler_status;
long output_compression;
long output_compression_level;
char *output_handler;
-ZEND_END_MODULE_GLOBALS(zlib)
-
-PHPAPI ZEND_EXTERN_MODULE_GLOBALS(zlib)
+ php_zlib_context *ob_gzhandler;
+ long output_compression_default;
+ zend_bool handler_registered;
+ZEND_END_MODULE_GLOBALS(zlib);
+php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
+extern php_stream_ops php_stream_gzio_ops;
+extern php_stream_wrapper php_stream_gzip_wrapper;
extern php_stream_filter_factory php_zlib_filter_factory;
extern zend_module_entry php_zlib_module_entry;
#define zlib_module_ptr &php_zlib_module_entry
-
-int php_ob_gzhandler_check(TSRMLS_D);
-
-php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
-extern php_stream_wrapper php_stream_gzip_wrapper;
+#define phpext_zlib_ptr zlib_module_ptr
#ifdef ZTS
-#define ZLIBG(v) TSRMG(zlib_globals_id, zend_zlib_globals *, v)
+# include "TSRM.h"
+# define ZLIBG(v) TSRMG(zlib_globals_id, zend_zlib_globals *, v)
#else
-#define ZLIBG(v) (zlib_globals.v)
+# define ZLIBG(v) (zlib_globals.v)
#endif
-#define phpext_zlib_ptr zlib_module_ptr
-
-#define CODING_GZIP 1
-#define CODING_DEFLATE 2
-
#endif /* PHP_ZLIB_H */
/*
diff --git a/ext/zlib/tests/001.phpt b/ext/zlib/tests/001.phpt
index 4850a65a5a..0c2ca28c78 100644
--- a/ext/zlib/tests/001.phpt
+++ b/ext/zlib/tests/001.phpt
@@ -29,4 +29,4 @@ Strings are equal
100 36864
Strings are equal
5 15
-Strings are equal \ No newline at end of file
+Strings are equal
diff --git a/ext/zlib/tests/003.phpt b/ext/zlib/tests/003.phpt
index 9fe943659f..d9275d9f1f 100644
--- a/ext/zlib/tests/003.phpt
+++ b/ext/zlib/tests/003.phpt
@@ -1,7 +1,7 @@
--TEST--
gzencode()
--SKIPIF--
-<?php if (!extension_loaded("zlib") || !function_exists("gzdecode")) print "skip"; ?>
+<?php if (!extension_loaded("zlib")) print "skip"; ?>
--FILE--
<?php
$original = str_repeat("hallo php",4096);
diff --git a/ext/zlib/tests/004.phpt b/ext/zlib/tests/004.phpt
index a758b8c7b3..ebc7d82b95 100644
--- a/ext/zlib/tests/004.phpt
+++ b/ext/zlib/tests/004.phpt
@@ -12,9 +12,6 @@ var_dump(gzfile(1,1,1));
var_dump(gzfile(dirname(__FILE__)."/004.txt.gz"));
var_dump(gzfile(dirname(__FILE__)."/004.txt.gz", 1));
-ini_set("magic_quotes_runtime", 1);
-var_dump(gzfile(dirname(__FILE__)."/004.txt.gz", -1));
-
echo "Done\n";
?>
--EXPECTF--
@@ -66,24 +63,4 @@ array(6) {
string(39) "and I know that it descends down on me
"
}
-array(6) {
- [0]=>
- string(37) "When you\'re taught through feelings
-"
- [1]=>
- string(26) "Destiny flying high above
-"
- [2]=>
- string(38) "all I know is that you can realize it
-"
- [3]=>
- string(18) "Destiny who cares
-"
- [4]=>
- string(19) "as it turns around
-"
- [5]=>
- string(39) "and I know that it descends down on me
-"
-}
Done
diff --git a/ext/zlib/tests/006.phpt b/ext/zlib/tests/006.phpt
index 6a4e0f4e67..8c03ea068d 100644
--- a/ext/zlib/tests/006.phpt
+++ b/ext/zlib/tests/006.phpt
@@ -48,6 +48,8 @@ string(%d) "%a"
Warning: gzinflate() expects at least 1 parameter, 0 given in %s on line %d
NULL
+
+Warning: gzinflate(): data error in %s on line %d
bool(false)
Warning: gzinflate(): data error in %s on line %d
diff --git a/ext/zlib/tests/007.phpt b/ext/zlib/tests/007.phpt
index ec37b99de6..09207a583e 100644
--- a/ext/zlib/tests/007.phpt
+++ b/ext/zlib/tests/007.phpt
@@ -11,8 +11,8 @@ var_dump(gzencode("", -10));
var_dump(gzencode("", 100));
var_dump(gzencode("", 1, 100));
-var_dump(gzencode("", -1, 1));
-var_dump(gzencode("", 9, 2));
+var_dump(gzencode("", -1, ZLIB_ENCODING_GZIP));
+var_dump(gzencode("", 9, ZLIB_ENCODING_DEFLATE));
$string = "Light of my sun
Light in this temple
@@ -21,8 +21,8 @@ Lies in the darkness";
var_dump(gzencode($string, 9, 3));
-var_dump(gzencode($string, -1, 1));
-var_dump(gzencode($string, 9, 2));
+var_dump(gzencode($string, -1, ZLIB_ENCODING_GZIP));
+var_dump(gzencode($string, 9, ZLIB_ENCODING_DEFLATE));
echo "Done\n";
?>
@@ -33,18 +33,18 @@ NULL
Warning: gzencode() expects at most 3 parameters, 4 given in %s on line %d
NULL
-Warning: gzencode(): compression level(-10) must be within -1..9 in %s on line %d
+Warning: gzencode(): compression level (-10) must be within -1..9 in %s on line %d
bool(false)
-Warning: gzencode(): compression level(100) must be within -1..9 in %s on line %d
+Warning: gzencode(): compression level (100) must be within -1..9 in %s on line %d
bool(false)
-Warning: gzencode(): encoding mode must be FORCE_GZIP or FORCE_DEFLATE in %s on line %d
+Warning: gzencode(): encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE in %s on line %d
bool(false)
string(%d) "%s"
string(%d) "%s"
-Warning: gzencode(): encoding mode must be FORCE_GZIP or FORCE_DEFLATE in %s on line %d
+Warning: gzencode(): encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE in %s on line %d
bool(false)
string(%d) "%s"
string(%d) "%s"
diff --git a/ext/zlib/tests/bug55544-win.phpt b/ext/zlib/tests/bug55544-win.phpt
new file mode 100644
index 0000000000..03fd6b1c90
--- /dev/null
+++ b/ext/zlib/tests/bug55544-win.phpt
Binary files differ
diff --git a/ext/zlib/tests/bug55544.phpt b/ext/zlib/tests/bug55544.phpt
new file mode 100644
index 0000000000..a0d22f4fce
--- /dev/null
+++ b/ext/zlib/tests/bug55544.phpt
Binary files differ
diff --git a/ext/zlib/tests/bug60761.phpt b/ext/zlib/tests/bug60761.phpt
index 340d878a2b..1e9fe69a01 100644
--- a/ext/zlib/tests/bug60761.phpt
+++ b/ext/zlib/tests/bug60761.phpt
@@ -1,54 +1,54 @@
---TEST--
-checks zlib compression output size is always the same
---SKIPIF--
-<?php if (!extension_loaded("zlib")) print "skip"; ?>
---CGI--
-1
---FILE--
-<?php
-
-// the INI directives from bug #60761 report
-ini_set('zlib.output_compression', '4096');
-ini_set('zlib.output_compression_level', '9');
-
-// try to duplicate the original bug by running this as a CGI
-// test using ob_start and zlib.output_compression(or ob_gzhandler)
-// so it follows more of the original code-path than just calling
-// gzcompress on CLI or CGI
-
-$lens = array();
-
-for ( $i=0 ; $i < 100 ; $i++ ) {
-
- // can't use ob_gzhandler with zlib.output_compression
- ob_start();//"ob_gzhandler");
- phpinfo();
- $html = ob_get_clean();
-
- $len = strlen($html);
-
- $lens[$len] = $len;
-}
-
-$lens = array_values($lens);
-
-echo "Compressed Lengths\n";
-
-// pass == only ONE length for all iterations
-// (length didn't change during run)
-//
-// hard to anticipate what 'correct' length should be since
-// return value of phpinfo() will vary between installations...
-// just check that there is only one length
-//
-var_dump($lens); // show lengths to help triage in case of failure
-
-// expected headers since its CGI
-
-?>
---EXPECTF--
-%s
-array(1) {
- [0]=>
- int(%d)
-}
+--TEST--
+checks zlib compression output size is always the same
+--SKIPIF--
+<?php if (!extension_loaded("zlib")) print "skip"; ?>
+--CGI--
+1
+--FILE--
+<?php
+
+// the INI directives from bug #60761 report
+ini_set('zlib.output_compression', '4096');
+ini_set('zlib.output_compression_level', '9');
+
+// try to duplicate the original bug by running this as a CGI
+// test using ob_start and zlib.output_compression(or ob_gzhandler)
+// so it follows more of the original code-path than just calling
+// gzcompress on CLI or CGI
+
+$lens = array();
+
+for ( $i=0 ; $i < 100 ; $i++ ) {
+
+ // can't use ob_gzhandler with zlib.output_compression
+ ob_start();//"ob_gzhandler");
+ phpinfo();
+ $html = ob_get_clean();
+
+ $len = strlen($html);
+
+ $lens[$len] = $len;
+}
+
+$lens = array_values($lens);
+
+echo "Compressed Lengths\n";
+
+// pass == only ONE length for all iterations
+// (length didn't change during run)
+//
+// hard to anticipate what 'correct' length should be since
+// return value of phpinfo() will vary between installations...
+// just check that there is only one length
+//
+var_dump($lens); // show lengths to help triage in case of failure
+
+// expected headers since its CGI
+
+?>
+--EXPECTF--
+%s
+array(1) {
+ [0]=>
+ int(%d)
+}
diff --git a/ext/zlib/tests/bug61287.phpt b/ext/zlib/tests/bug61287.phpt
new file mode 100644
index 0000000000..769446a8cd
--- /dev/null
+++ b/ext/zlib/tests/bug61287.phpt
@@ -0,0 +1,24 @@
+--TEST--
+bug #61287 - inflate needs the terminating null byte
+--SKIPIF--
+<?php extension_loaded("zlib") or die("SKIP need zlib");
+--FILE--
+<?php
+$array = array(
+ 'region_id' => 1,
+ 'discipline' => 23,
+ 'degrees' => array(),
+ 'country_id' => 27
+);
+
+$serialized = serialize($array);
+
+$deflated = gzdeflate($serialized, 9);
+$inflated = gzinflate($deflated);
+
+echo strlen($inflated),"\n";
+?>
+Done
+--EXPECT--
+92
+Done
diff --git a/ext/zlib/tests/bug61443.phpt b/ext/zlib/tests/bug61443.phpt
new file mode 100644
index 0000000000..ea2fa68c89
--- /dev/null
+++ b/ext/zlib/tests/bug61443.phpt
@@ -0,0 +1,15 @@
+--TEST--
+bug #61443
+--SKIPIF--
+<?php
+extension_loaded("zlib") or die("skip");
+?>
+--FILE--
+<?php
+ob_start(); echo "foo\n"; ob_get_clean();
+if(!headers_sent()) ini_set('zlib.output_compression', true); echo "end\n";
+?>
+DONE
+--EXPECTF--
+end
+DONE
diff --git a/ext/zlib/tests/bug61820.phpt b/ext/zlib/tests/bug61820.phpt
new file mode 100644
index 0000000000..6f33b54553
--- /dev/null
+++ b/ext/zlib/tests/bug61820.phpt
@@ -0,0 +1,23 @@
+--TEST--
+bug #61820 using ob_gzhandler will complain about headers already sent when no compression
+--SKIPIF--
+<?php
+extension_loaded("zlib") or die("skip");
+?>
+--FILE--
+<?php
+ob_start('ob_gzhandler');
+
+echo "Hi there.\n";
+ob_flush();
+flush();
+
+echo "This is confusing...\n";
+ob_flush();
+flush();
+?>
+DONE
+--EXPECT--
+Hi there.
+This is confusing...
+DONE
diff --git a/ext/zlib/tests/data.inc b/ext/zlib/tests/data.inc
index 441199ff08..fb20f0bcdf 100644
--- a/ext/zlib/tests/data.inc
+++ b/ext/zlib/tests/data.inc
@@ -85,4 +85,4 @@ That summons thee to heaven or to hell.
QUOTE;
-?> \ No newline at end of file
+?>
diff --git a/ext/zlib/tests/gzcompress_basic1.phpt b/ext/zlib/tests/gzcompress_basic1.phpt
index dddeb1d55d..1506d0c1ee 100644
--- a/ext/zlib/tests/gzcompress_basic1.phpt
+++ b/ext/zlib/tests/gzcompress_basic1.phpt
@@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) {
?>
--FILE--
<?php
-/* Prototype : string gzcompress(string data [, int level])
+/* Prototype : string gzcompress(string data [, int level, [int encoding]])
* Description: Gzip-compress a string
* Source code: ext/zlib/zlib.c
* Alias to functions:
@@ -63,7 +63,7 @@ int(0)
string(32) "c2e070f4320d1f674965eaab95b53d9c"
int(0)
-- Compression level 2 --
-string(32) "400a53d19ca337727f8cd362f5cd3ee0"
+string(32) "36922f486410d08209d0d0d21b26030e"
int(0)
-- Compression level 3 --
string(32) "a441a2f5169bb303cd45b860a5a9dbf9"
@@ -122,4 +122,4 @@ int(0)
-- Testing with no specified compression level --
string(70) "789c735428ce4dccc951282e29cacc4b5728c95748cecf2d284a2d2ee6020087a509cb"
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/zlib/tests/gzcompress_error1.phpt b/ext/zlib/tests/gzcompress_error1.phpt
index 7fa60b9003..9db0a56fa1 100644
--- a/ext/zlib/tests/gzcompress_error1.phpt
+++ b/ext/zlib/tests/gzcompress_error1.phpt
@@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) {
?>
--FILE--
<?php
-/* Prototype : string gzcompress(string data [, int level])
+/* Prototype : string gzcompress(string data [, int level, [int encoding]])
* Description: Gzip-compress a string
* Source code: ext/zlib/zlib.c
* Alias to functions:
@@ -28,26 +28,30 @@ var_dump( gzcompress() );
echo "\n-- Testing gzcompress() function with more than expected no. of arguments --\n";
$data = 'string_val';
$level = 2;
+$encoding = ZLIB_ENCODING_RAW;
$extra_arg = 10;
-var_dump( gzcompress($data, $level, $extra_arg) );
+var_dump( gzcompress($data, $level, $encoding, $extra_arg) );
echo "\n-- Testing with incorrect compression level --\n";
$bad_level = 99;
var_dump(gzcompress($data, $bad_level));
+echo "\n-- Testing with invalid encoding --\n";
+$data = 'string_val';
+$encoding = 99;
+var_dump(gzcompress($data, $level, $encoding));
+
+echo "\n-- Testing with incorrect parameters --\n";
+
class Tester {
function Hello() {
echo "Hello\n";
}
}
-echo "\n-- Testing with incorrect parameters --\n";
$testclass = new Tester();
var_dump(gzcompress($testclass));
-var_dump(gzcompress($data, $testclass));
-
-
?>
===Done===
--EXPECTF--
@@ -60,7 +64,7 @@ NULL
-- Testing gzcompress() function with more than expected no. of arguments --
-Warning: gzcompress() expects at most 2 parameters, 3 given in %s on line %d
+Warning: gzcompress() expects at most 3 parameters, 4 given in %s on line %d
NULL
-- Testing with incorrect compression level --
@@ -68,11 +72,13 @@ NULL
Warning: gzcompress(): compression level (99) must be within -1..9 in %s on line %d
bool(false)
+-- Testing with invalid encoding --
+
+Warning: gzcompress(): encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE in %s on line %d
+bool(false)
+
-- Testing with incorrect parameters --
Warning: gzcompress() expects parameter 1 to be string, object given in %s on line %d
NULL
-
-Warning: gzcompress() expects parameter 2 to be long, object given in %s on line %d
-NULL
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/zlib/tests/gzcompress_variation1.phpt b/ext/zlib/tests/gzcompress_variation1.phpt
index 04aac01085..7a8457c24f 100644
--- a/ext/zlib/tests/gzcompress_variation1.phpt
+++ b/ext/zlib/tests/gzcompress_variation1.phpt
@@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) {
?>
--FILE--
<?php
-/* Prototype : string gzcompress(string data [, int level])
+/* Prototype : string gzcompress(string data [, int level, [int encoding]])
* Description: Gzip-compress a string
* Source code: ext/zlib/zlib.c
* Alias to functions:
@@ -18,8 +18,6 @@ include(dirname(__FILE__) . '/data.inc');
echo "*** Testing gzcompress() : variation ***\n";
-
-
echo "\n-- Testing multiple compression --\n";
$output = gzcompress($data);
var_dump( md5($output));
@@ -33,4 +31,4 @@ var_dump(md5(gzcompress($output)));
-- Testing multiple compression --
string(32) "764809aef15bb34cb73ad49ecb600d99"
string(32) "eba942bc2061f23ea8688cc5101872a4"
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/zlib/tests/gzdeflate_basic1.phpt b/ext/zlib/tests/gzdeflate_basic1.phpt
index 823f320352..a2ae0f01da 100644
--- a/ext/zlib/tests/gzdeflate_basic1.phpt
+++ b/ext/zlib/tests/gzdeflate_basic1.phpt
@@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) {
?>
--FILE--
<?php
-/* Prototype : proto string gzdeflate(string data [, int level])
+/* Prototype : string gzdeflate(string data [, int level, [int encoding]])
* Description: Gzip-compress a string
* Source code: ext/zlib/zlib.c
* Alias to functions:
diff --git a/ext/zlib/tests/gzdeflate_error1.phpt b/ext/zlib/tests/gzdeflate_error1.phpt
index 78491af9f1..8abd5bec25 100644
--- a/ext/zlib/tests/gzdeflate_error1.phpt
+++ b/ext/zlib/tests/gzdeflate_error1.phpt
@@ -8,7 +8,7 @@ if (!extension_loaded("zlib")) {
?>
--FILE--
<?php
-/* Prototype : string gzdeflate(string data [, int level])
+/* Prototype : string gzdeflate(string data [, int level, [int encoding]])
* Description: Gzip-compress a string
* Source code: ext/zlib/zlib.c
* Alias to functions:
@@ -28,13 +28,18 @@ var_dump( gzdeflate() );
echo "\n-- Testing gzdeflate() function with more than expected no. of arguments --\n";
$data = 'string_val';
$level = 2;
+$encoding = ZLIB_ENCODING_RAW;
$extra_arg = 10;
-var_dump( gzdeflate($data, $level, $extra_arg) );
+var_dump( gzdeflate($data, $level, $encoding, $extra_arg) );
echo "\n-- Testing with incorrect compression level --\n";
$bad_level = 99;
var_dump(gzdeflate($data, $bad_level));
+echo "\n-- Testing with incorrect encoding --\n";
+$bad_encoding = 99;
+var_dump(gzdeflate($data, $level, $bad_encoding));
+
class Tester {
function Hello() {
echo "Hello\n";
@@ -58,7 +63,7 @@ NULL
-- Testing gzdeflate() function with more than expected no. of arguments --
-Warning: gzdeflate() expects at most 2 parameters, 3 given in %s on line %d
+Warning: gzdeflate() expects at most 3 parameters, 4 given in %s on line %d
NULL
-- Testing with incorrect compression level --
@@ -66,6 +71,11 @@ NULL
Warning: gzdeflate(): compression level (99) must be within -1..9 in %s on line %d
bool(false)
+-- Testing with incorrect encoding --
+
+Warning: gzdeflate(): encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE in %s on line %d
+bool(false)
+
-- Testing with incorrect parameters --
Warning: gzdeflate() expects parameter 1 to be string, object given in %s on line %d
@@ -73,4 +83,4 @@ NULL
Warning: gzdeflate() expects parameter 2 to be long, object given in %s on line %d
NULL
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/zlib/tests/gzencode_basic1.phpt b/ext/zlib/tests/gzencode_basic1.phpt
index 9b3dcc8a38..3c0ec559e9 100644
--- a/ext/zlib/tests/gzencode_basic1.phpt
+++ b/ext/zlib/tests/gzencode_basic1.phpt
@@ -51,6 +51,13 @@ for($i = -1; $i < 10; $i++) {
var_dump(md5($output));
}
+// Calling gzencode() with mandatory arguments
+echo "\n-- Testing with no specified compression level --\n";
+var_dump(bin2hex(gzencode($smallstring)));
+
+echo "\n-- Testing gzencode with mode specified --\n";
+var_dump(bin2hex(gzencode($smallstring, -1, FORCE_GZIP)));
+
?>
===Done===
--EXPECTF--
@@ -58,9 +65,9 @@ for($i = -1; $i < 10; $i++) {
-- Compression level -1 --
string(32) "d9ede02415ce91d21e5a94274e2b9c42"
-- Compression level 0 --
-string(32) "67aaf60426bb2cbd86d7fe530cb12306"
+string(32) "bbf32d5508e5f1f4e6d42790489dae15"
-- Compression level 1 --
-string(32) "bce9c439cf767c1988ff4881b287d1ce"
+string(32) "0bfaaa7a5a57f8fb533074fca6c85eeb"
-- Compression level 2 --
string(32) "7ddbfed63a76c42808722b66f1c133fc"
-- Compression level 3 --
@@ -76,13 +83,13 @@ string(32) "d9ede02415ce91d21e5a94274e2b9c42"
-- Compression level 8 --
string(32) "d9ede02415ce91d21e5a94274e2b9c42"
-- Compression level 9 --
-string(32) "d9ede02415ce91d21e5a94274e2b9c42"
+string(32) "0f220a09e9895bcb3a1308d2bc99cfdf"
-- Compression level -1 --
string(32) "f77bd31e1e4dd11d12828fb661a08010"
-- Compression level 0 --
-string(32) "36220d650930849b67e8e0622f9bf270"
+string(32) "9c5005db88490d6fe102ea2c233b2872"
-- Compression level 1 --
-string(32) "f77bd31e1e4dd11d12828fb661a08010"
+string(32) "d24ff7c4c20cef69b9c3abd603368db9"
-- Compression level 2 --
string(32) "f77bd31e1e4dd11d12828fb661a08010"
-- Compression level 3 --
@@ -98,5 +105,11 @@ string(32) "f77bd31e1e4dd11d12828fb661a08010"
-- Compression level 8 --
string(32) "f77bd31e1e4dd11d12828fb661a08010"
-- Compression level 9 --
-string(32) "f77bd31e1e4dd11d12828fb661a08010"
-===Done=== \ No newline at end of file
+string(32) "8849e9a1543c04b3f882b5ce20839ed2"
+
+-- Testing with no specified compression level --
+string(94) "1f8b08000000000000%c%c735428ce4dccc951282e29cacc4b5728c95748cecf2d284a2d2ee60200edc4e40b1b000000"
+
+-- Testing gzencode with mode specified --
+string(94) "1f8b08000000000000%c%c735428ce4dccc951282e29cacc4b5728c95748cecf2d284a2d2ee60200edc4e40b1b000000"
+===Done===
diff --git a/ext/zlib/tests/gzencode_error1.phpt b/ext/zlib/tests/gzencode_error1.phpt
index ed8c977477..9ecf4b8f08 100644
--- a/ext/zlib/tests/gzencode_error1.phpt
+++ b/ext/zlib/tests/gzencode_error1.phpt
@@ -71,12 +71,12 @@ NULL
-- Testing with incorrect compression level --
-Warning: gzencode(): compression level(99) must be within -1..9 in %s on line %d
+Warning: gzencode(): compression level (99) must be within -1..9 in %s on line %d
bool(false)
-- Testing with incorrect encoding_mode --
-Warning: gzencode(): encoding mode must be FORCE_GZIP or FORCE_DEFLATE in %s on line %d
+Warning: gzencode(): encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE in %s on line %d
bool(false)
-- Testing with incorrect parameters --
@@ -87,7 +87,7 @@ NULL
Warning: gzencode() expects parameter 2 to be long, object given in %s on line %d
NULL
-Warning: gzencode(): encoding mode must be FORCE_GZIP or FORCE_DEFLATE in %s on line %d
+Warning: gzencode(): encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE in %s on line %d
bool(false)
Warning: gzencode() expects parameter 3 to be long, object given in %s on line %d
@@ -95,4 +95,4 @@ NULL
Warning: gzencode() expects parameter 2 to be long, string given in %s on line %d
NULL
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/zlib/tests/gzencode_variation1.phpt b/ext/zlib/tests/gzencode_variation1.phpt
index 47e2097f5f..ef1d3a77f7 100644
--- a/ext/zlib/tests/gzencode_variation1.phpt
+++ b/ext/zlib/tests/gzencode_variation1.phpt
@@ -3,6 +3,10 @@ Test gzencode() function : variation
--SKIPIF--
<?php
+if( substr(PHP_OS, 0, 3) == "WIN" ) {
+ die("skip.. Do not run on Windows");
+}
+
if (!extension_loaded("zlib")) {
print "skip - ZLIB extension not loaded";
}
@@ -30,4 +34,4 @@ var_dump(bin2hex(gzencode($output)));
-- Testing multiple compression --
string(3658) "1f8b0800000000000003010e07f1f81f8b08000000000000036d574d6fe4c80dbdeb57d4ad2f3dfe01eb83e1ec22980e309b4562c067b64449159754dafab0b6e7d7e73d96da1e4c72184c4b2ab2c8f7c847fa25baabba98dc1a8b2b7c38bb324b713ee37f757f56cdc5c7f5b17b9d152f923b157c5ae335e0b75fedd0e2d781c6b98ea3a6ee05affe1dfc3a6527f8f09c52dcb38ba38bb5249934d6ecfe1e53a9ab76ff4c342cf2a64ed2028349fc9a8b139755685352acb82b9fbb67f8bade5cdcb698e1fcec94b7ceba3cb897e806cfc8114350dd1ebbdfa35b62d2478b0056d23ed809b9b95d696d91ce2aa97c911e3fa539c43f84c887554a4d125c9e63ff96711cc08c0866263cb37a0bbe2122ae8f6baecb2284abfb4ddf916db8354cddeef37c1afe5fa02fc7afb3db34f5b3acbdf2eb905490d8f38d7468d253a323d5ebb903760d7944d3b2024e834a99ddce77669bdd823cfbb8e899d4ad4c799677452e6029e80023a03b2374005590641f7d3877df2ad09f3c0e82a54d6a5644fd63049a37ed4bc362016fd9f51264f1e5c630727421ae930b7ed416e93e47b7c71a400390361ffbecb7561bb98f69b5da289e91becc27f08b3b724cb8704f9144d366431d0cb870c56b205deaa2e17636063761a911039fb7e4bf9f06c4f0aecd2ec80e8b41831ca7515e31286166458ea3ef71f2ce7cde2ae269c96d60525724a9c9170b713ed5750758f3cd2a361fc8b288fc92358ce884692e8ea0fe59bd969a0da2eed5831b715749eaae7178f3ebd30fb88c92105f367cce2c882955dc6bf8eca0d5d57540b3092894743ba0fd5b2dad021836191f1afc0bba14dde1642cb0b1aa6879c38907dcefa0720082b801bec61417469219175267dfa047df35b0bd1332001c28cdfafd3bcabe91e74368cdd8d8478e494c190e7ee90c67f2bde288e68ab6b15e883c995be4f8feb6c6dda4278e4f38578ddbdc7be36788daf0c3cb1d1819c73822f7000a0d1813fa94153b572315e51343b536bc64977dff163cebfd8418773261f524017e251fccc60ae29a5770ae097594d52e9c1229d87ce967a36401c46b69945afb249d101c9d420ffa9a123e232c20e76467d5d169202a2dd4c582949e013e745df7958d4b0cc4fd4377a737cd4feea7974070000f314d423e0634cb9a618fdf5dc64fd422181fd59c9230c9f6f9d18dc8fc23e9cccbc7188733b04aa57de83ebea0be3633cff5fa1ff83269be7f44f5a8d84550cc703255fd345dd402034d0b3e11a73ec6e3d4a77f4f685b614329f1b3132ae7af33d02e1e55e291fa6574b758d1f0200e7423dbc852211818043a7c9ce80aa9d59fce0401959f5ea2cf71fde90824f8c9192dbe9d329db143794675ddcf257dd7755273b67340414e3ccad12e3f661f8aad9cf9957dc1275d10a51d3934fa81e68dc6768fb8ee23e373936c8e13feab8b0f50d227f7af76f561fb0950f3d099bbc316c3892a42fb36806d8660e800fa4f43fd4b962d2097d71933a54b77ff948677848eb17bb3a88b621682cfb3bbb49cf42fed6b3944124ad8358ca688aa44dd5f2144c7c9ab16f25b9aca9654ef357ec9ad55c40d324d6cc3d9e3920b863c231d31a95d937fb5520f9c816c79b7dcecc593fb9593cc05a51ebb1eeddd5b49eb437769738d0f64adc579d372b8b7f7c0208487ee3915ebf5766e148ebd77cf4e01f3ec285047011e55838968b6494d517fe29224777b24dd3ddf933101695b102e87db805eef291b74dcfd91628fb2a53f93dbd2968ef2e598746c9204f89fba1f0246fc671610a0591806e46a1346f77c40d910a47c5e20ffb23f003c04b648327a4ed98032c1965bd35bb0044f5344248f56fdb99aa61d6451d68e33489a83bffbe6573541b2da5f64681ea12090f778b2075374778810f73965fa3626a9d41f4df2f83f7c34658cec921b5a9bde49dd5007ec882b02adc514f81aa85898b5cc98e1b137733c0a8789b7f5648d2d231b80bf74978f25d61ce08a8abd11801fd8f995e066676307192ff7641f1cc6e0dee68565b8b22ac3889cd067bf732754a6b270af1044c6a8776811a4f6d8bd0477a9f516064201b920b92d7cd4dc7eee13e6b3eb3528a82f9abb3f388ebe6a8f871393461b73816ec54c99d604174bc5a6801de13908f86aea6a7d0fea107d682bcf1ec348b83872e6b8a316ecd02eb8f8dc86a609bf59a2dd03f1dfa4079436d55e24617be1a2854d008b2b2b1705e2078a7f3946318df1c24f6bf70d4b456eca286ec2b585b28262cc048a098c3e2d5f325a92bb36f691afdc14c822da1b116c9c1c07bb362eb0a04b78834c812134230ebf2044ac2e3c0e3ad00f848dc5010f3bf917ec2fc700b7bf26dacea8440620e04f90f4d97d6dd77cfde8a05c7d3930f1e5811fb8ec5c70964dcc8187ec90e32fdd6b64eec7586413b7d55bed65c4cce39a9b6c15e70e9da94e53fc904e6286f01f5b5562c94211befbc23507e01b2a3865e2f45b5d7b591f290087a5605b82495b4e393f31aa5b37211ec40241a746d903c5eebf117a4d3ddb0d00007b64cbc70e070000"
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/zlib/tests/gzencode_variation2-win32.phpt b/ext/zlib/tests/gzencode_variation2-win32.phpt
new file mode 100644
index 0000000000..7adda31049
--- /dev/null
+++ b/ext/zlib/tests/gzencode_variation2-win32.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Test gzencode() function : variation - verify header contents with all encoding modes
+--SKIPIF--
+<?php
+
+if( substr(PHP_OS, 0, 3) != "WIN" ) {
+ die("skip.. only for Windows");
+}
+
+if (!extension_loaded("zlib")) {
+ print "skip - ZLIB extension not loaded";
+}
+?>
+--FILE--
+<?php
+/* Prototype : string gzencode ( string $data [, int $level [, int $encoding_mode ]] )
+ * Description: Gzip-compress a string
+ * Source code: ext/zlib/zlib.c
+ * Alias to functions:
+ */
+
+echo "*** Testing gzencode() : variation ***\n";
+
+$data = "A small string to encode\n";
+
+echo "\n-- Testing with each encoding_mode --\n";
+var_dump(bin2hex(gzencode($data, -1)));
+var_dump(bin2hex(gzencode($data, -1, FORCE_GZIP)));
+var_dump(bin2hex(gzencode($data, -1, FORCE_DEFLATE)));
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing gzencode() : variation ***
+
+-- Testing with each encoding_mode --
+string(90) "1f8b080000000000000b735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200d7739de519000000"
+string(90) "1f8b080000000000000b735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200d7739de519000000"
+string(66) "789c735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200735808cd"
+===DONE===
diff --git a/ext/zlib/tests/gzencode_variation2.phpt b/ext/zlib/tests/gzencode_variation2.phpt
index 901cd53c19..de63b7170f 100644
--- a/ext/zlib/tests/gzencode_variation2.phpt
+++ b/ext/zlib/tests/gzencode_variation2.phpt
@@ -3,6 +3,10 @@ Test gzencode() function : variation - verify header contents with all encoding
--SKIPIF--
<?php
+if( substr(PHP_OS, 0, 3) == "WIN" ) {
+ die("skip.. Do not run on Windows");
+}
+
if (!extension_loaded("zlib")) {
print "skip - ZLIB extension not loaded";
}
@@ -32,5 +36,5 @@ var_dump(bin2hex(gzencode($data, -1, FORCE_DEFLATE)));
-- Testing with each encoding_mode --
string(90) "1f8b0800000000000003735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200d7739de519000000"
string(90) "1f8b0800000000000003735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200d7739de519000000"
-string(86) "1f8b0800000000000003789c735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200735808cd"
-===DONE=== \ No newline at end of file
+string(66) "789c735428ce4dccc951282e29cacc4b5728c95748cd4bce4f49e50200735808cd"
+===DONE===
diff --git a/ext/zlib/tests/gzfile_basic.phpt b/ext/zlib/tests/gzfile_basic.phpt
index 1fceea5b90..fd7ba18058 100644
--- a/ext/zlib/tests/gzfile_basic.phpt
+++ b/ext/zlib/tests/gzfile_basic.phpt
@@ -36,4 +36,4 @@ array(3) {
[2]=>
string(17) "for all languages"
}
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/zlib/tests/gzfile_basic2.phpt b/ext/zlib/tests/gzfile_basic2.phpt
index 9f31eb0f87..9124d336b0 100644
--- a/ext/zlib/tests/gzfile_basic2.phpt
+++ b/ext/zlib/tests/gzfile_basic2.phpt
@@ -36,4 +36,4 @@ array(3) {
[2]=>
string(17) "for all languages"
}
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/zlib/tests/gzfile_variation1.phpt b/ext/zlib/tests/gzfile_variation1.phpt
index b573030f92..767abb7e30 100644
--- a/ext/zlib/tests/gzfile_variation1.phpt
+++ b/ext/zlib/tests/gzfile_variation1.phpt
@@ -29,15 +29,15 @@ foreach ( $variation as $var ) {
===DONE===
--EXPECTF--
-Warning: gzfile() expects parameter 1 to be string, array given in %s on line %d
+Warning: gzfile() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-Warning: gzfile() expects parameter 1 to be string, array given in %s on line %d
+Warning: gzfile() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-Warning: gzfile() expects parameter 1 to be string, array given in %s on line %d
+Warning: gzfile() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-Warning: gzfile() expects parameter 1 to be string, array given in %s on line %d
+Warning: gzfile() expects parameter 1 to be a valid path, array given in %s on line %d
NULL
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/zlib/tests/gzfile_variation6.phpt b/ext/zlib/tests/gzfile_variation6.phpt
index 174524b3d8..1ce1be6591 100644
--- a/ext/zlib/tests/gzfile_variation6.phpt
+++ b/ext/zlib/tests/gzfile_variation6.phpt
@@ -45,5 +45,5 @@ foreach ( $variation as $var ) {
--EXPECTF--
Error: 2 - gzfile(Class A object): failed to open stream: No such file or directory, %s(%d)
bool(false)
-Error: 2 - gzfile() expects parameter 1 to be string, object given, %s(%d)
-NULL \ No newline at end of file
+Error: 2 - gzfile() expects parameter 1 to be a valid path, object given, %s(%d)
+NULL
diff --git a/ext/zlib/tests/gzinflate-bug42663.phpt b/ext/zlib/tests/gzinflate-bug42663.phpt
index dd53c78f4e..4f0ca9fa7f 100644
--- a/ext/zlib/tests/gzinflate-bug42663.phpt
+++ b/ext/zlib/tests/gzinflate-bug42663.phpt
@@ -5,8 +5,8 @@ Bug #42663 (gzinflate() try to allocate all memory with truncated $data)
--FILE--
<?php
// build a predictable string
-$string = b'';
-for($i=0; $i<30000; ++$i) $string .= (binary)$i . b' ';
+$string = '';
+for($i=0; $i<30000; ++$i) $string .= $i . ' ';
var_dump(strlen($string));
// deflate string
$deflated = gzdeflate($string,9);
@@ -15,9 +15,12 @@ var_dump(strlen($deflated));
$truncated = substr($deflated, 0, 65535);
var_dump(strlen($truncated));
// inflate $truncated string (check if it will not eat all memory)
-gzinflate($truncated);
+var_dump(gzinflate($truncated));
?>
---EXPECT--
+--EXPECTF--
int(168890)
int(66743)
int(65535)
+
+Warning: gzinflate(): data error in %s on line %d
+bool(false)
diff --git a/ext/zlib/tests/gzinflate_length.phpt b/ext/zlib/tests/gzinflate_length.phpt
index 436025d13a..6e86d865ee 100644
--- a/ext/zlib/tests/gzinflate_length.phpt
+++ b/ext/zlib/tests/gzinflate_length.phpt
@@ -4,7 +4,7 @@ gzinflate() and $length argument
<?php if (!extension_loaded("zlib")) print "skip"; ?>
--FILE--
<?php
-$original = b'aaaaaaaaaaaaaaa';
+$original = 'aaaaaaaaaaaaaaa';
$packed=gzdeflate($original);
echo strlen($packed)." ".strlen($original)."\n";
$unpacked=gzinflate($packed, strlen($original));
diff --git a/ext/zlib/tests/gzreadgzwrite.phpt b/ext/zlib/tests/gzreadgzwrite.phpt
index 6d6729a72f..71d728b6ed 100644
--- a/ext/zlib/tests/gzreadgzwrite.phpt
+++ b/ext/zlib/tests/gzreadgzwrite.phpt
@@ -5,7 +5,7 @@ gzopen(), gzread(), gzwrite()
if (!extension_loaded("zlib")) print "skip"; ?>
--FILE--
<?php
-$original = str_repeat("hallo php",4096);
+$original = str_repeat(b"hallo php",4096);
$filename = tempnam("/tmp", "phpt");
$fp = gzopen($filename, "wb");
@@ -15,7 +15,12 @@ var_dump(gztell($fp));
fclose($fp);
$fp = gzopen($filename, "rb");
-$data = gzread($fp, strlen($original));
+
+$data = '';
+while ($buf = gzread($fp, 8092)) {
+ $data .= $buf;
+}
+
if ($data == $original) {
echo "Strings are equal\n";
} else {
diff --git a/ext/zlib/tests/gzreadgzwriteplain.phpt b/ext/zlib/tests/gzreadgzwriteplain.phpt
index 7bb567d889..6a752b6212 100644
--- a/ext/zlib/tests/gzreadgzwriteplain.phpt
+++ b/ext/zlib/tests/gzreadgzwriteplain.phpt
@@ -5,7 +5,7 @@ gzopen(), gzread(), gzwrite() for non-compressed data
if (!extension_loaded("zlib")) print "skip"; ?>
--FILE--
<?php
-$original = str_repeat("hallo php",4096);
+$original = str_repeat(b"hallo php",4096);
$filename = tempnam("/tmp", "phpt");
$fp = fopen($filename, "wb");
@@ -15,7 +15,12 @@ var_dump(ftell($fp));
fclose($fp);
$fp = gzopen($filename, "rb");
-$data = gzread($fp, strlen($original));
+
+$data = '';
+while ($buf = gzread($fp, 8192)) {
+ $data .= $buf;
+}
+
if ($data == $original) {
echo "Strings are equal\n";
} else {
@@ -24,7 +29,11 @@ if ($data == $original) {
}
gzseek($fp, strlen($original) / 2);
-$data = gzread($fp, strlen($original));
+
+$data = '';
+while ($buf = gzread($fp, 8192)) {
+ $data .= $buf;
+}
var_dump(strlen($data));
if ($data == substr($original, strlen($original) / 2)) {
diff --git a/ext/zlib/tests/gzuncompress_error1.phpt b/ext/zlib/tests/gzuncompress_error1.phpt
index 66e5b2ac43..f26a4f5dcd 100644
--- a/ext/zlib/tests/gzuncompress_error1.phpt
+++ b/ext/zlib/tests/gzuncompress_error1.phpt
@@ -14,8 +14,6 @@ if (!extension_loaded("zlib")) {
* Alias to functions:
*/
-
-
echo "*** Testing gzuncompress() : error conditions ***\n";
// Zero arguments
@@ -29,14 +27,12 @@ $length = 10;
$extra_arg = 10;
var_dump( gzuncompress($data, $length, $extra_arg) );
-
echo "\n-- Testing with a buffer that is too small --\n";
$short_len = strlen($data) - 1;
$compressed = gzcompress($data);
var_dump(gzuncompress($compressed, $short_len));
-
echo "\n-- Testing with incorrect arguments --\n";
var_dump(gzuncompress(123));
@@ -68,7 +64,7 @@ NULL
-- Testing with a buffer that is too small --
-Warning: gzuncompress(): buffer error in %s on line %d
+Warning: gzuncompress(): insufficient memory in %s on line %d
bool(false)
-- Testing with incorrect arguments --
@@ -81,4 +77,4 @@ NULL
Warning: gzuncompress() expects parameter 2 to be long, string given in %s on line %d
NULL
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/zlib/tests/gzwrite_variation1.phpt b/ext/zlib/tests/gzwrite_variation1.phpt
index bd3778e366..ab6c2606b4 100644
--- a/ext/zlib/tests/gzwrite_variation1.phpt
+++ b/ext/zlib/tests/gzwrite_variation1.phpt
@@ -11,7 +11,7 @@ if (!extension_loaded("zlib")) {
$filename = dirname(__FILE__)."/004.txt.gz";
$h = gzopen($filename, 'r');
-$str = "Here is the string to be written. ";
+$str = b"Here is the string to be written. ";
$length = 10;
var_dump(gzwrite( $h, $str ) );
var_dump(gzread($h, 10));
diff --git a/ext/zlib/tests/ob_001.phpt b/ext/zlib/tests/ob_001.phpt
new file mode 100644
index 0000000000..b074a4f55b
--- /dev/null
+++ b/ext/zlib/tests/ob_001.phpt
@@ -0,0 +1,20 @@
+--TEST--
+zlib.output_compression
+--SKIPIF--
+<?php
+if (!extension_loaded("zlib")) die("skip need ext/zlib");
+if (false === stristr(PHP_SAPI, "cgi")) die("skip need sapi/cgi");
+?>
+--GET--
+a=b
+--INI--
+zlib.output_compression=1
+--ENV--
+HTTP_ACCEPT_ENCODING=gzip
+--FILE--
+<?php
+echo "hi\n";
+?>
+--EXPECTF--
+‹%s
+
diff --git a/ext/zlib/tests/ob_002.phpt b/ext/zlib/tests/ob_002.phpt
new file mode 100644
index 0000000000..53cf25ceb1
--- /dev/null
+++ b/ext/zlib/tests/ob_002.phpt
@@ -0,0 +1,18 @@
+--TEST--
+zlib.output_compression
+--SKIPIF--
+<?php
+if (!extension_loaded("zlib")) die("skip need ext/zlib");
+?>
+--INI--
+zlib.output_compression=1
+--ENV--
+HTTP_ACCEPT_ENCODING=gzip
+--FILE--
+<?php
+ini_set("zlib.output_compression", 0);
+echo "hi\n";
+?>
+--EXPECTF--
+hi
+
diff --git a/ext/zlib/tests/ob_003.phpt b/ext/zlib/tests/ob_003.phpt
new file mode 100644
index 0000000000..7142df7f0e
--- /dev/null
+++ b/ext/zlib/tests/ob_003.phpt
@@ -0,0 +1,23 @@
+--TEST--
+zlib.output_compression
+--SKIPIF--
+<?php
+if (!extension_loaded("zlib")) die("skip need ext/zlib");
+if (false === stristr(PHP_SAPI, "cgi")) die("skip need sapi/cgi");
+?>
+--INI--
+zlib.output_compression=0
+--ENV--
+HTTP_ACCEPT_ENCODING=gzip
+--POST--
+dummy=42
+--FILE--
+<?php
+ini_set("zlib.output_compression", 1);
+echo "hi\n";
+?>
+--EXPECTF--
+‹%s
+--EXPECTHEADERS--
+Content-Encoding: gzip
+Vary: Accept-Encoding
diff --git a/ext/zlib/tests/ob_004.phpt b/ext/zlib/tests/ob_004.phpt
new file mode 100644
index 0000000000..f5e6af552b
--- /dev/null
+++ b/ext/zlib/tests/ob_004.phpt
@@ -0,0 +1,24 @@
+--TEST--
+ob_gzhandler
+--SKIPIF--
+<?php
+if (!extension_loaded("zlib")) die("skip need ext/zlib");
+if (false === stristr(PHP_SAPI, "cgi")) die("skip need sapi/cgi");
+?>
+--INI--
+zlib.output_compression=0
+--ENV--
+HTTP_ACCEPT_ENCODING=gzip
+--POST--
+dummy=42
+--FILE--
+<?php
+ob_start("ob_gzhandler");
+echo "hi\n";
+?>
+--EXPECTF--
+‹%s
+--EXPECTHEADERS--
+Content-Encoding: gzip
+Vary: Accept-Encoding
+
diff --git a/ext/zlib/tests/ob_005.phpt b/ext/zlib/tests/ob_005.phpt
new file mode 100644
index 0000000000..19793936f9
--- /dev/null
+++ b/ext/zlib/tests/ob_005.phpt
@@ -0,0 +1,22 @@
+--TEST--
+ob_gzhandler
+--SKIPIF--
+<?php
+if (!extension_loaded("zlib")) die("skip need ext/zlib");
+if (false === stristr(PHP_SAPI, "cgi")) die("skip need sapi/cgi");
+?>
+--INI--
+zlib.output_compression=0
+--ENV--
+HTTP_ACCEPT_ENCODING=gzip
+--POST--
+dummy=42
+--FILE--
+<?php
+ob_start("ob_gzhandler");
+ini_set("zlib.output_compression", 0);
+echo "hi\n";
+?>
+--EXPECTF--
+hi
+--EXPECTHEADERS--
diff --git a/ext/zlib/tests/ob_gzhandler_legacy_002.phpt b/ext/zlib/tests/ob_gzhandler_legacy_002.phpt
new file mode 100644
index 0000000000..dad282188e
--- /dev/null
+++ b/ext/zlib/tests/ob_gzhandler_legacy_002.phpt
@@ -0,0 +1,24 @@
+--TEST--
+ob_gzhandler legacy
+--SKIPIF--
+<?php
+if (!extension_loaded("zlib")) die("skip need ext/zlib");
+if (false === stristr(PHP_SAPI, "cgi")) die("skip need sapi/cgi");
+?>
+--INI--
+zlib.output_compression=0
+--ENV--
+HTTP_ACCEPT_ENCODING=
+--POST--
+dummy=42
+--FILE--
+<?php
+if (false !== ob_gzhandler("", PHP_OUTPUT_HANDLER_START)) {
+ ini_set("zlib.output_compression", 0);
+ ob_start("ob_gzhandler");
+}
+echo "hi\n";
+?>
+--EXPECTF--
+hi
+--EXPECTHEADERS--
diff --git a/ext/zlib/tests/readgzfile_variation14.phpt b/ext/zlib/tests/readgzfile_variation14.phpt
index 165bf59b89..ee0d6d6d4e 100644
--- a/ext/zlib/tests/readgzfile_variation14.phpt
+++ b/ext/zlib/tests/readgzfile_variation14.phpt
@@ -41,4 +41,4 @@ NULL
Warning: readgzfile() expects parameter 2 to be long, string given in %s on line %d
NULL
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/zlib/tests/readgzfile_variation4.phpt b/ext/zlib/tests/readgzfile_variation4.phpt
index cbc561c71d..ece84a990e 100644
--- a/ext/zlib/tests/readgzfile_variation4.phpt
+++ b/ext/zlib/tests/readgzfile_variation4.phpt
@@ -26,9 +26,18 @@ foreach ( $variation as $var ) {
?>
===DONE===
--EXPECTF--
+Warning: readgzfile(10.5): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(-10.5): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(123456789000): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(-123456789000): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(0.5): failed to open stream: No such file or directory in %s on line %d
bool(false)
===DONE===
diff --git a/ext/zlib/tests/readgzfile_variation5.phpt b/ext/zlib/tests/readgzfile_variation5.phpt
index dde0dabdd0..460e188930 100644
--- a/ext/zlib/tests/readgzfile_variation5.phpt
+++ b/ext/zlib/tests/readgzfile_variation5.phpt
@@ -25,8 +25,15 @@ foreach ( $variation as $var ) {
?>
===DONE===
--EXPECTF--
+Warning: readgzfile(0): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(1): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(12345): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(-2345): failed to open stream: No such file or directory in %s on line %d
bool(false)
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/zlib/tests/readgzfile_variation6.phpt b/ext/zlib/tests/readgzfile_variation6.phpt
index 1beeca764b..69a4dc190a 100644
--- a/ext/zlib/tests/readgzfile_variation6.phpt
+++ b/ext/zlib/tests/readgzfile_variation6.phpt
@@ -43,6 +43,7 @@ foreach ( $variation as $var ) {
}
?>
--EXPECTF--
+Error: 2 - readgzfile(Class A object): failed to open stream: No such file or directory, %s(%d)
bool(false)
Error: 2 - readgzfile() expects parameter 1 to be string, object given, %s(%d)
NULL \ No newline at end of file
diff --git a/ext/zlib/tests/readgzfile_variation7.phpt b/ext/zlib/tests/readgzfile_variation7.phpt
index df244d3954..20162b5cb5 100644
--- a/ext/zlib/tests/readgzfile_variation7.phpt
+++ b/ext/zlib/tests/readgzfile_variation7.phpt
@@ -29,8 +29,15 @@ foreach ( $variation_array as $var ) {
?>
===DONE===
--EXPECTF--
+Warning: readgzfile(string): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(string): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(sTrInG): failed to open stream: No such file or directory in %s on line %d
bool(false)
+
+Warning: readgzfile(hello world): failed to open stream: No such file or directory in %s on line %d
bool(false)
===DONE===
diff --git a/ext/zlib/tests/zlib_filter_inflate2.phpt b/ext/zlib/tests/zlib_filter_inflate2.phpt
index 4332d8e5e6..a2099b6f7a 100644
--- a/ext/zlib/tests/zlib_filter_inflate2.phpt
+++ b/ext/zlib/tests/zlib_filter_inflate2.phpt
@@ -6,7 +6,7 @@ zlib.inflate of gzip-encoded stream
<?php /* $Id$ */
$a = gzopen(dirname(__FILE__) . '/test.txt.gz', 'w');
-fwrite($a, "This is quite the thing ain't it\n");
+fwrite($a, b"This is quite the thing ain't it\n");
fclose($a);
$fp = fopen(dirname(__FILE__) . '/test.txt.gz', 'r');
@@ -38,4 +38,4 @@ fclose($fp);
2
This is quite the thing ain't it
3
-This is quite the thing ain't it \ No newline at end of file
+This is quite the thing ain't it
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 4dca862948..7ff2b30c4c 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -13,9 +13,10 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
- | Stefan Röhrich <sr@linux.de> |
+ | Stefan Röhrich <sr@linux.de> |
| Zeev Suraski <zeev@zend.com> |
| Jade Nicoletti <nicoletti@nns.ch> |
+ | Michael Wallner <mike@php.net> |
+----------------------------------------------------------------------+
*/
@@ -28,385 +29,530 @@
#include "php.h"
#include "SAPI.h"
#include "php_ini.h"
-
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#ifdef PHP_WIN32
-# define O_RDONLY _O_RDONLY
-# include "win32/param.h"
-#else
-# include <sys/param.h>
-/* #include <sys/uio.h> */
-#endif
-
-#include "ext/standard/head.h"
-#include "safe_mode.h"
-#include "ext/standard/php_standard.h"
#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "ext/standard/php_string.h"
#include "php_zlib.h"
-#include "fopen_wrappers.h"
-
-#if HAVE_PWD_H
-# ifdef PHP_WIN32
-# include "win32/pwd.h"
-# else
-# include <pwd.h>
-# endif
-#endif
-
-#if defined(HAVE_UNISTD_H) && defined(PHP_WIN32)
-# undef HAVE_UNISTD_H
-#endif
-
-#ifdef COMPILE_DL_ZLIB
-# ifndef PUTS
-# define PUTS(a) php_printf("%s",a)
-# endif
-# ifndef PUTC
-# define PUTC(a) PUTS(a)
-# endif
-# ifndef PHPWRITE
-# define PHPWRITE(a,n) php_write((a),(n) TSRMLS_CC)
-# endif
-#endif
-
-/* Win32 needs some more memory */
-#ifdef PHP_WIN32
-# define PHP_ZLIB_MODIFIER 100
-#else
-# define PHP_ZLIB_MODIFIER 1000
-#endif
-
-#define OS_CODE 0x03 /* FIXME */
-#define GZIP_HEADER_LENGTH 10
-#define GZIP_FOOTER_LENGTH 8
-
-/* True globals, no need for thread safety */
-static const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
-
-static int php_zlib_output_compression_start(TSRMLS_D);
-
-static PHP_MINIT_FUNCTION(zlib);
-static PHP_MSHUTDOWN_FUNCTION(zlib);
-static PHP_RINIT_FUNCTION(zlib);
-static PHP_MINFO_FUNCTION(zlib);
-static PHP_FUNCTION(gzopen);
-static PHP_FUNCTION(readgzfile);
-static PHP_FUNCTION(gzfile);
-static PHP_FUNCTION(gzcompress);
-static PHP_FUNCTION(gzuncompress);
-static PHP_FUNCTION(gzdeflate);
-static PHP_FUNCTION(gzinflate);
-static PHP_FUNCTION(gzencode);
-static PHP_FUNCTION(ob_gzhandler);
-static PHP_FUNCTION(zlib_get_coding_type);
-/* {{{ arginfo */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, use_include_path)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, mode)
- ZEND_ARG_INFO(0, use_include_path)
-ZEND_END_ARG_INFO()
+ZEND_DECLARE_MODULE_GLOBALS(zlib);
-ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)
- ZEND_ARG_INFO(0, filename)
- ZEND_ARG_INFO(0, use_include_path)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
- ZEND_ARG_INFO(0, level)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
- ZEND_ARG_INFO(0, length)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
- ZEND_ARG_INFO(0, level)
-ZEND_END_ARG_INFO()
+/* {{{ Memory management wrappers */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
- ZEND_ARG_INFO(0, length)
-ZEND_END_ARG_INFO()
+static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
+{
+ return (voidpf)safe_emalloc(items, size, 0);
+}
-ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)
-ZEND_END_ARG_INFO()
+static void php_zlib_free(voidpf opaque, voidpf address)
+{
+ efree((void*)address);
+}
+/* }}} */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
- ZEND_ARG_INFO(0, level)
- ZEND_ARG_INFO(0, encoding_mode)
-ZEND_END_ARG_INFO()
+/* {{{ php_zlib_output_conflict_check() */
+static int php_zlib_output_conflict_check(const char *handler_name, size_t handler_name_len TSRMLS_DC)
+{
+ if (php_output_get_level(TSRMLS_C) > 0) {
+ if (php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME) TSRMLS_CC)
+ || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("ob_gzhandler") TSRMLS_CC)
+ || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("mb_output_handler") TSRMLS_CC)
+ || php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("URL-Rewriter") TSRMLS_CC)) {
+ return FAILURE;
+ }
+ }
+ return SUCCESS;
+}
+/* }}} */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2)
- ZEND_ARG_INFO(0, str)
- ZEND_ARG_INFO(0, mode)
-ZEND_END_ARG_INFO()
+/* {{{ php_zlib_output_encoding() */
+static int php_zlib_output_encoding(TSRMLS_D)
+{
+ zval **enc;
+
+ if (!ZLIBG(compression_coding)) {
+ zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC);
+ if (PG(http_globals)[TRACK_VARS_SERVER] && SUCCESS == zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void *) &enc)) {
+ convert_to_string(*enc);
+ if (strstr(Z_STRVAL_PP(enc), "gzip")) {
+ ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_GZIP;
+ } else if (strstr(Z_STRVAL_PP(enc), "deflate")) {
+ ZLIBG(compression_coding) = PHP_ZLIB_ENCODING_DEFLATE;
+ }
+ }
+ }
+ return ZLIBG(compression_coding);
+}
+/* }}} */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)
- ZEND_ARG_INFO(0, fp)
- ZEND_ARG_INFO(0, str)
- ZEND_ARG_INFO(0, length)
-ZEND_END_ARG_INFO()
+/* {{{ php_zlib_output_handler_ex() */
+static int php_zlib_output_handler_ex(php_zlib_context *ctx, php_output_context *output_context)
+{
+ int flags = Z_SYNC_FLUSH;
+ PHP_OUTPUT_TSRMLS(output_context);
-ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)
- ZEND_ARG_INFO(0, fp)
-ZEND_END_ARG_INFO()
+ if (output_context->op & PHP_OUTPUT_HANDLER_START) {
+ /* start up */
+ if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
+ return FAILURE;
+ }
+ }
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)
- ZEND_ARG_INFO(0, fp)
- ZEND_ARG_INFO(0, offset)
- ZEND_ARG_INFO(0, whence)
-ZEND_END_ARG_INFO()
+ if (output_context->op & PHP_OUTPUT_HANDLER_CLEAN) {
+ /* free buffers */
+ deflateEnd(&ctx->Z);
-ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)
- ZEND_ARG_INFO(0, fp)
- ZEND_ARG_INFO(0, length)
-ZEND_END_ARG_INFO()
+ if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
+ /* discard */
+ return SUCCESS;
+ } else {
+ /* restart */
+ if (Z_OK != deflateInit2(&ctx->Z, ZLIBG(output_compression_level), Z_DEFLATED, ZLIBG(compression_coding), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) {
+ return FAILURE;
+ }
+ ctx->buffer.used = 0;
+ }
+ } else {
+ if (output_context->in.used) {
+ /* append input */
+ if (ctx->buffer.free < output_context->in.used) {
+ if (!(ctx->buffer.aptr = erealloc_recoverable(ctx->buffer.data, ctx->buffer.used + ctx->buffer.free + output_context->in.used))) {
+ deflateEnd(&ctx->Z);
+ return FAILURE;
+ }
+ ctx->buffer.data = ctx->buffer.aptr;
+ ctx->buffer.free += output_context->in.used;
+ }
+ memcpy(ctx->buffer.data + ctx->buffer.used, output_context->in.data, output_context->in.used);
+ ctx->buffer.free -= output_context->in.used;
+ ctx->buffer.used += output_context->in.used;
+ }
+ output_context->out.size = PHP_ZLIB_BUFFER_SIZE_GUESS(output_context->in.used);
+ output_context->out.data = emalloc(output_context->out.size);
+ output_context->out.free = 1;
+ output_context->out.used = 0;
+
+ ctx->Z.avail_in = ctx->buffer.used;
+ ctx->Z.next_in = (Bytef *) ctx->buffer.data;
+ ctx->Z.avail_out = output_context->out.size;
+ ctx->Z.next_out = (Bytef *) output_context->out.data;
+
+ if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
+ flags = Z_FINISH;
+ } else if (output_context->op & PHP_OUTPUT_HANDLER_FLUSH) {
+ flags = Z_FULL_FLUSH;
+ }
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)
- ZEND_ARG_INFO(0, fp)
- ZEND_ARG_INFO(0, length)
- ZEND_ARG_INFO(0, allowable_tags)
-ZEND_END_ARG_INFO()
+ switch (deflate(&ctx->Z, flags)) {
+ case Z_OK:
+ if (flags == Z_FINISH) {
+ deflateEnd(&ctx->Z);
+ return FAILURE;
+ }
+ case Z_STREAM_END:
+ if (ctx->Z.avail_in) {
+ memmove(ctx->buffer.data, ctx->buffer.data + ctx->buffer.used - ctx->Z.avail_in, ctx->Z.avail_in);
+ }
+ ctx->buffer.free += ctx->buffer.used - ctx->Z.avail_in;
+ ctx->buffer.used = ctx->Z.avail_in;
+ output_context->out.used = output_context->out.size - ctx->Z.avail_out;
+ break;
+ default:
+ deflateEnd(&ctx->Z);
+ return FAILURE;
+ }
-ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1)
- ZEND_ARG_INFO(0, fp)
- ZEND_ARG_INFO(0, length)
-ZEND_END_ARG_INFO()
-/* }}} */
+ if (output_context->op & PHP_OUTPUT_HANDLER_FINAL) {
+ deflateEnd(&ctx->Z);
+ }
+ }
-/* {{{ php_zlib_functions[]
- */
-static const zend_function_entry php_zlib_functions[] = {
- PHP_FE(readgzfile, arginfo_readgzfile)
- PHP_FALIAS(gzrewind, rewind, arginfo_gzpassthru)
- PHP_FALIAS(gzclose, fclose, arginfo_gzpassthru)
- PHP_FALIAS(gzeof, feof, arginfo_gzpassthru)
- PHP_FALIAS(gzgetc, fgetc, arginfo_gzpassthru)
- PHP_FALIAS(gzgets, fgets, arginfo_gzgets)
- PHP_FALIAS(gzgetss, fgetss, arginfo_gzgetss)
- PHP_FALIAS(gzread, fread, arginfo_gzread)
- PHP_FE(gzopen, arginfo_gzopen)
- PHP_FALIAS(gzpassthru, fpassthru, arginfo_gzpassthru)
- PHP_FALIAS(gzseek, fseek, arginfo_gzseek)
- PHP_FALIAS(gztell, ftell, arginfo_gzpassthru)
- PHP_FALIAS(gzwrite, fwrite, arginfo_gzputs)
- PHP_FALIAS(gzputs, fwrite, arginfo_gzputs)
- PHP_FE(gzfile, arginfo_gzfile)
- PHP_FE(gzcompress, arginfo_gzcompress)
- PHP_FE(gzuncompress, arginfo_gzuncompress)
- PHP_FE(gzdeflate, arginfo_gzdeflate)
- PHP_FE(gzinflate, arginfo_gzinflate)
- PHP_FE(gzencode, arginfo_gzencode)
- PHP_FE(ob_gzhandler, arginfo_ob_gzhandler)
- PHP_FE(zlib_get_coding_type, arginfo_zlib_get_coding_type)
- PHP_FE_END
-};
+ return SUCCESS;
+}
/* }}} */
-ZEND_DECLARE_MODULE_GLOBALS(zlib)
+/* {{{ php_zlib_output_handler() */
+static int php_zlib_output_handler(void **handler_context, php_output_context *output_context)
+{
+ php_zlib_context *ctx = *(php_zlib_context **) handler_context;
+ PHP_OUTPUT_TSRMLS(output_context);
+
+ if (!php_zlib_output_encoding(TSRMLS_C)) {
+ /* "Vary: Accept-Encoding" header sent along uncompressed content breaks caching in MSIE,
+ so let's just send it with successfully compressed content or unless the complete
+ buffer gets discarded, see http://bugs.php.net/40325;
+
+ Test as follows:
+ +Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
+ +Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n";'
+ -Vary: $ HTTP_ACCEPT_ENCODING=gzip ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
+ -Vary: $ HTTP_ACCEPT_ENCODING= ./sapi/cgi/php <<<'<?php ob_start("ob_gzhandler"); echo "foo\n"; ob_end_clean();'
+ */
+ if ((output_context->op & PHP_OUTPUT_HANDLER_START)
+ && (output_context->op != (PHP_OUTPUT_HANDLER_START|PHP_OUTPUT_HANDLER_CLEAN|PHP_OUTPUT_HANDLER_FINAL))
+ ) {
+ sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC);
+ }
+ return FAILURE;
+ }
-/* {{{ php_zlib_module_entry
- */
-zend_module_entry php_zlib_module_entry = {
- STANDARD_MODULE_HEADER,
- "zlib",
- php_zlib_functions,
- PHP_MINIT(zlib),
- PHP_MSHUTDOWN(zlib),
- PHP_RINIT(zlib),
- NULL,
- PHP_MINFO(zlib),
- "1.1",
- PHP_MODULE_GLOBALS(zlib),
- NULL,
- NULL,
- NULL,
- STANDARD_MODULE_PROPERTIES_EX
-};
-/* }}} */
+ if (SUCCESS != php_zlib_output_handler_ex(ctx, output_context)) {
+ return FAILURE;
+ }
-#ifdef COMPILE_DL_ZLIB
-ZEND_GET_MODULE(php_zlib)
-#endif
+ if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) {
+ int flags;
-/* {{{ Memory management wrappers */
+ if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags TSRMLS_CC)) {
+ /* only run this once */
+ if (!(flags & PHP_OUTPUT_HANDLER_STARTED)) {
+ if (SG(headers_sent) || !ZLIBG(output_compression)) {
+ deflateEnd(&ctx->Z);
+ return FAILURE;
+ }
+ switch (ZLIBG(compression_coding)) {
+ case PHP_ZLIB_ENCODING_GZIP:
+ sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
+ break;
+ case PHP_ZLIB_ENCODING_DEFLATE:
+ sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
+ break;
+ default:
+ deflateEnd(&ctx->Z);
+ return FAILURE;
+ }
+ sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC);
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
+ }
+ }
+ }
-static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size)
-{
- return (voidpf)safe_emalloc(items, size, 0);
+ return SUCCESS;
}
+/* }}} */
-static void php_zlib_free(voidpf opaque, voidpf address)
+/* {{{ php_zlib_output_handler_context_init() */
+static php_zlib_context *php_zlib_output_handler_context_init(TSRMLS_D)
{
- efree((void*)address);
+ php_zlib_context *ctx = (php_zlib_context *) ecalloc(1, sizeof(php_zlib_context));
+ ctx->Z.zalloc = php_zlib_alloc;
+ ctx->Z.zfree = php_zlib_free;
+ return ctx;
}
/* }}} */
-/* {{{ OnUpdate_zlib_output_compression */
-static PHP_INI_MH(OnUpdate_zlib_output_compression)
+/* {{{ php_zlib_output_handler_context_dtor() */
+static void php_zlib_output_handler_context_dtor(void *opaq TSRMLS_DC)
{
- int status, int_value;
- char *ini_value;
+ php_zlib_context *ctx = (php_zlib_context *) opaq;
- if (new_value == NULL) {
- return FAILURE;
- }
-
- if (!strncasecmp(new_value, "off", sizeof("off"))) {
- new_value = "0";
- new_value_length = sizeof("0");
- } else if (!strncasecmp(new_value, "on", sizeof("on"))) {
- new_value = "1";
- new_value_length = sizeof("1");
+ if (ctx) {
+ if (ctx->buffer.data) {
+ efree(ctx->buffer.data);
+ }
+ efree(ctx);
}
+}
+/* }}} */
- int_value = zend_atoi(new_value, new_value_length);
- ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
-
- if (ini_value && *ini_value && int_value) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
- return FAILURE;
- }
+/* {{{ php_zlib_output_handler_init() */
+static php_output_handler *php_zlib_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC)
+{
+ php_output_handler *h = NULL;
- if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");
- return FAILURE;
+ if (!ZLIBG(output_compression)) {
+ ZLIBG(output_compression) = chunk_size ? chunk_size : PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
}
- status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ ZLIBG(handler_registered) = 1;
- if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
- status = php_zlib_output_compression_start(TSRMLS_C);
+ if ((h = php_output_handler_create_internal(handler_name, handler_name_len, php_zlib_output_handler, chunk_size, flags TSRMLS_CC))) {
+ php_output_handler_set_context(h, php_zlib_output_handler_context_init(TSRMLS_C), php_zlib_output_handler_context_dtor TSRMLS_CC);
}
- return status;
+ return h;
}
/* }}} */
-/* {{{ OnUpdate_zlib_output_compression_level */
-static PHP_INI_MH(OnUpdate_zlib_output_compression_level)
+/* {{{ php_zlib_output_compression_start() */
+static void php_zlib_output_compression_start(TSRMLS_D)
{
- OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ zval *zoh;
+ php_output_handler *h;
- return SUCCESS;
+ switch (ZLIBG(output_compression)) {
+ case 0:
+ break;
+ case 1:
+ ZLIBG(output_compression) = PHP_OUTPUT_HANDLER_DEFAULT_SIZE;
+ /* break omitted intentionally */
+ default:
+ if ( php_zlib_output_encoding(TSRMLS_C) &&
+ (h = php_zlib_output_handler_init(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC)) &&
+ (SUCCESS == php_output_handler_start(h TSRMLS_CC))) {
+ if (ZLIBG(output_handler) && *ZLIBG(output_handler)) {
+ MAKE_STD_ZVAL(zoh);
+ ZVAL_STRING(zoh, ZLIBG(output_handler), 1);
+ php_output_start_user(zoh, ZLIBG(output_compression), PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
+ zval_ptr_dtor(&zoh);
+ }
+ }
+ break;
+ }
}
/* }}} */
-/* {{{ OnUpdate_zlib_output_handler */
-static PHP_INI_MH(OnUpdate_zlib_output_handler)
+/* {{{ php_zlib_encode() */
+static int php_zlib_encode(const char *in_buf, size_t in_len, char **out_buf, size_t *out_len, int encoding, int level TSRMLS_DC)
{
- if (stage == PHP_INI_STAGE_RUNTIME && SG(headers_sent) && !SG(request_info).no_headers) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent");
- return FAILURE;
+ int status;
+ z_stream Z;
+
+ memset(&Z, 0, sizeof(z_stream));
+ Z.zalloc = php_zlib_alloc;
+ Z.zfree = php_zlib_free;
+
+ if (Z_OK == (status = deflateInit2(&Z, level, Z_DEFLATED, encoding, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY))) {
+ *out_len = PHP_ZLIB_BUFFER_SIZE_GUESS(in_len);
+ *out_buf = emalloc(*out_len);
+
+ Z.next_in = (Bytef *) in_buf;
+ Z.next_out = (Bytef *) *out_buf;
+ Z.avail_in = in_len;
+ Z.avail_out = *out_len;
+
+ status = deflate(&Z, Z_FINISH);
+ deflateEnd(&Z);
+
+ if (Z_STREAM_END == status) {
+ /* size buffer down to actual length */
+ *out_buf = erealloc(*out_buf, Z.total_out + 1);
+ (*out_buf)[*out_len = Z.total_out] = '\0';
+ return SUCCESS;
+ } else {
+ efree(*out_buf);
+ }
}
- OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ *out_buf = NULL;
+ *out_len = 0;
- return SUCCESS;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
+ return FAILURE;
}
/* }}} */
+/* {{{ php_zlib_inflate_rounds() */
+static inline int php_zlib_inflate_rounds(z_stream *Z, size_t max, char **buf, size_t *len)
+{
+ int status, round = 0;
+ php_zlib_buffer buffer = {NULL, NULL, 0, 0, 0};
-PHP_INI_BEGIN()
- STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression, zend_zlib_globals, zlib_globals)
- STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdate_zlib_output_compression_level, output_compression_level, zend_zlib_globals, zlib_globals)
- STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals)
-PHP_INI_END()
+ *buf = NULL;
+ *len = 0;
-/* {{{ PHP_MINIT_FUNCTION
- */
-static PHP_MINIT_FUNCTION(zlib)
-{
- php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);
- php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);
+ buffer.size = (max && (max < Z->avail_in)) ? max : Z->avail_in;
- REGISTER_LONG_CONSTANT("FORCE_GZIP", CODING_GZIP, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("FORCE_DEFLATE", CODING_DEFLATE, CONST_CS | CONST_PERSISTENT);
+ do {
+ if ((max && (max <= buffer.used)) || !(buffer.aptr = erealloc_recoverable(buffer.data, buffer.size))) {
+ status = Z_MEM_ERROR;
+ } else {
+ buffer.data = buffer.aptr;
+ Z->avail_out = buffer.free = buffer.size - buffer.used;
+ Z->next_out = (Bytef *) buffer.data + buffer.used;
+#if 0
+ fprintf(stderr, "\n%3d: %3d PRIOR: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
+#endif
+ status = inflate(Z, Z_NO_FLUSH);
- REGISTER_INI_ENTRIES();
+ buffer.used += buffer.free - Z->avail_out;
+ buffer.free = Z->avail_out;
+#if 0
+ fprintf(stderr, "%3d: %3d AFTER: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
+#endif
+ buffer.size += (buffer.size >> 3) + 1;
+ }
+ } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < 100);
- return SUCCESS;
+ if (status == Z_STREAM_END) {
+ buffer.data = erealloc(buffer.data, buffer.used + 1);
+ buffer.data[buffer.used] = '\0';
+ *buf = buffer.data;
+ *len = buffer.used;
+ } else {
+ if (buffer.data) {
+ efree(buffer.data);
+ }
+ /* HACK: See zlib/examples/zpipe.c inf() function for explanation. */
+ /* This works as long as this function is not used for streaming. Required to catch very short invalid data. */
+ status = (status == Z_OK) ? Z_DATA_ERROR : status;
+ }
+ return status;
}
/* }}} */
-/* {{{ PHP_RINIT_FUNCTION
- */
-static PHP_RINIT_FUNCTION(zlib)
+/* {{{ php_zlib_decode() */
+static int php_zlib_decode(const char *in_buf, size_t in_len, char **out_buf, size_t *out_len, int encoding, size_t max_len TSRMLS_DC)
{
- ZLIBG(ob_gzhandler_status) = 0;
- ZLIBG(compression_coding) = 0;
+ int status = Z_DATA_ERROR;
+ z_stream Z;
+
+ memset(&Z, 0, sizeof(z_stream));
+ Z.zalloc = php_zlib_alloc;
+ Z.zfree = php_zlib_free;
+
+ if (in_len) {
+retry_raw_inflate:
+ status = inflateInit2(&Z, encoding);
+ if (Z_OK == status) {
+ Z.next_in = (Bytef *) in_buf;
+ Z.avail_in = in_len + 1; /* NOTE: data must be zero terminated */
+
+ switch (status = php_zlib_inflate_rounds(&Z, max_len, out_buf, out_len)) {
+ case Z_STREAM_END:
+ inflateEnd(&Z);
+ return SUCCESS;
+
+ case Z_DATA_ERROR:
+ /* raw deflated data? */
+ if (PHP_ZLIB_ENCODING_ANY == encoding) {
+ inflateEnd(&Z);
+ encoding = PHP_ZLIB_ENCODING_RAW;
+ goto retry_raw_inflate;
+ }
+ }
+ inflateEnd(&Z);
+ }
+ }
- php_zlib_output_compression_start(TSRMLS_C);
+ *out_buf = NULL;
+ *out_len = 0;
- return SUCCESS;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
+ return FAILURE;
}
/* }}} */
-/* {{{ PHP_MSHUTDOWN_FUNCTION
- */
-static PHP_MSHUTDOWN_FUNCTION(zlib)
+/* {{{ php_zlib_cleanup_ob_gzhandler_mess() */
+static void php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_D)
{
- php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
- php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
+ if (ZLIBG(ob_gzhandler)) {
+ deflateEnd(&(ZLIBG(ob_gzhandler)->Z));
+ php_zlib_output_handler_context_dtor(ZLIBG(ob_gzhandler) TSRMLS_CC);
+ ZLIBG(ob_gzhandler) = NULL;
+ }
+}
+/* }}} */
- UNREGISTER_INI_ENTRIES();
+/* {{{ proto string ob_gzhandler(string data, int flags)
+ Legacy hack */
+static PHP_FUNCTION(ob_gzhandler)
+{
+ char *in_str;
+ int in_len;
+ long flags = 0;
+ php_output_context ctx = {0};
+ int encoding, rv;
- return SUCCESS;
+ /*
+ * NOTE that the real ob_gzhandler is an alias to "zlib output compression".
+ * This is a really bad hack, because
+ * - we have to initialize a php_zlib_context on demand
+ * - we have to clean it up in RSHUTDOWN
+ * - OG(running) is not set or set to any other output handler
+ * - we have to mess around with php_output_context */
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &in_str, &in_len, &flags)) {
+ RETURN_FALSE;
+ }
+
+ if (!(encoding = php_zlib_output_encoding(TSRMLS_C))) {
+ RETURN_FALSE;
+ }
+
+ if (flags & PHP_OUTPUT_HANDLER_START) {
+ switch (encoding) {
+ case PHP_ZLIB_ENCODING_GZIP:
+ sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
+ break;
+ case PHP_ZLIB_ENCODING_DEFLATE:
+ sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
+ break;
+ }
+ sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 1 TSRMLS_CC);
+ }
+
+ if (!ZLIBG(ob_gzhandler)) {
+ ZLIBG(ob_gzhandler) = php_zlib_output_handler_context_init(TSRMLS_C);
+ }
+
+ TSRMLS_SET_CTX(ctx.tsrm_ls);
+ ctx.op = flags;
+ ctx.in.data = in_str;
+ ctx.in.used = in_len;
+
+ rv = php_zlib_output_handler_ex(ZLIBG(ob_gzhandler), &ctx);
+
+ if (SUCCESS != rv) {
+ if (ctx.out.data && ctx.out.free) {
+ efree(ctx.out.data);
+ }
+ php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C);
+ RETURN_FALSE;
+ }
+
+ if (ctx.out.data) {
+ RETVAL_STRINGL(ctx.out.data, ctx.out.used, 1);
+ if (ctx.out.free) {
+ efree(ctx.out.data);
+ }
+ } else {
+ RETVAL_EMPTY_STRING();
+ }
}
/* }}} */
-/* {{{ PHP_MINFO_FUNCTION
- */
-static PHP_MINFO_FUNCTION(zlib)
+/* {{{ proto string zlib_get_coding_type(void)
+ Returns the coding type used for output compression */
+static PHP_FUNCTION(zlib_get_coding_type)
{
- php_info_print_table_start();
- php_info_print_table_row(2, "ZLib Support", "enabled");
- php_info_print_table_row(2, "Stream Wrapper support", "compress.zlib://");
- php_info_print_table_row(2, "Stream Filter support", "zlib.inflate, zlib.deflate");
- php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
- php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
- php_info_print_table_end();
-
- DISPLAY_INI_ENTRIES();
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ switch (ZLIBG(compression_coding)) {
+ case PHP_ZLIB_ENCODING_GZIP:
+ RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1);
+ case PHP_ZLIB_ENCODING_DEFLATE:
+ RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);
+ default:
+ RETURN_FALSE;
+ }
}
/* }}} */
/* {{{ proto array gzfile(string filename [, int use_include_path])
- Read und uncompress entire .gz-file into an array */
+ Read and uncompress entire .gz-file into an array */
static PHP_FUNCTION(gzfile)
{
char *filename;
int filename_len;
- long flags = 0;
- char *slashed, buf[8192];
+ int flags = REPORT_ERRORS;
+ char buf[8192] = {0};
register int i = 0;
- int use_include_path = 0;
+ long use_include_path = 0;
php_stream *stream;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &use_include_path)) {
return;
}
- use_include_path = flags ? USE_PATH : 0;
+ if (use_include_path) {
+ flags |= USE_PATH;
+ }
/* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */
- stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);
- if (stream == NULL) {
+ stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC TSRMLS_CC);
+
+ if (!stream) {
/* Error reporting is already done by stream code */
RETURN_FALSE;
}
@@ -415,17 +561,10 @@ static PHP_FUNCTION(gzfile)
array_init(return_value);
/* Now loop through the file and do the magic quotes thing if needed */
- memset(buf,0,sizeof(buf));
-
+ memset(buf, 0, sizeof(buf));
+
while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) {
- if (PG(magic_quotes_runtime)) {
- int len;
-
- slashed = php_addslashes(buf, 0, &len, 0 TSRMLS_CC); /* 0 = don't free source string */
- add_index_stringl(return_value, i++, slashed, len, 0);
- } else {
- add_index_string(return_value, i++, buf, 1);
- }
+ add_index_string(return_value, i++, buf, 1);
}
php_stream_close(stream);
}
@@ -435,19 +574,22 @@ static PHP_FUNCTION(gzfile)
Open a .gz-file and return a .gz-file pointer */
static PHP_FUNCTION(gzopen)
{
- char *filename, *mode;
+ char *filename;
+ char *mode;
int filename_len, mode_len;
- long flags = 0;
+ int flags = REPORT_ERRORS;
php_stream *stream;
- int use_include_path = 0;
+ long use_include_path = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &use_include_path) == FAILURE) {
return;
}
- use_include_path = flags ? USE_PATH : 0;
+ if (use_include_path) {
+ flags |= USE_PATH;
+ }
- stream = php_stream_gzopen(NULL, filename, mode, use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC);
+ stream = php_stream_gzopen(NULL, filename, mode, flags, NULL, NULL STREAMS_CC TSRMLS_CC);
if (!stream) {
RETURN_FALSE;
@@ -456,27 +598,27 @@ static PHP_FUNCTION(gzopen)
}
/* }}} */
-/*
- * Read a file and write the ouput to stdout
- */
/* {{{ proto int readgzfile(string filename [, int use_include_path])
Output a .gz-file */
static PHP_FUNCTION(readgzfile)
{
char *filename;
int filename_len;
- long flags = 0;
+ int flags = REPORT_ERRORS;
php_stream *stream;
int size;
- int use_include_path = 0;
+ long use_include_path = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &use_include_path) == FAILURE) {
return;
}
- use_include_path = flags ? USE_PATH : 0;
+ if (use_include_path) {
+ flags |= USE_PATH;
+ }
+
+ stream = php_stream_gzopen(NULL, filename, "rb", flags, NULL, NULL STREAMS_CC TSRMLS_CC);
- stream = php_stream_gzopen(NULL, filename, "rb", use_include_path | ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC);
if (!stream) {
RETURN_FALSE;
}
@@ -486,676 +628,405 @@ static PHP_FUNCTION(readgzfile)
}
/* }}} */
-/* {{{ proto string gzcompress(string data [, int level])
- Gzip-compress a string */
-static PHP_FUNCTION(gzcompress)
-{
- int data_len, status;
- long level = Z_DEFAULT_COMPRESSION;
- unsigned long l2;
- char *data, *s2;
+#define PHP_ZLIB_ENCODE_FUNC(name, default_encoding) \
+static PHP_FUNCTION(name) \
+{ \
+ char *in_buf, *out_buf; \
+ int in_len; \
+ size_t out_len; \
+ long level = -1; \
+ long encoding = default_encoding; \
+ if (default_encoding) { \
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &in_buf, &in_len, &level, &encoding)) { \
+ return; \
+ } \
+ } else { \
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &in_buf, &in_len, &encoding, &level)) { \
+ return; \
+ } \
+ } \
+ if (level < -1 || level > 9) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level); \
+ RETURN_FALSE; \
+ } \
+ switch (encoding) { \
+ case PHP_ZLIB_ENCODING_RAW: \
+ case PHP_ZLIB_ENCODING_GZIP: \
+ case PHP_ZLIB_ENCODING_DEFLATE: \
+ break; \
+ default: \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); \
+ RETURN_FALSE; \
+ } \
+ if (SUCCESS != php_zlib_encode(in_buf, in_len, &out_buf, &out_len, encoding, level TSRMLS_CC)) { \
+ RETURN_FALSE; \
+ } \
+ RETURN_STRINGL(out_buf, out_len, 0); \
+}
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {
- return;
- }
+#define PHP_ZLIB_DECODE_FUNC(name, encoding) \
+static PHP_FUNCTION(name) \
+{ \
+ char *in_buf, *out_buf; \
+ int in_len; \
+ size_t out_len; \
+ long max_len = 0; \
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &in_buf, &in_len, &max_len)) { \
+ return; \
+ } \
+ if (max_len < 0) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", max_len); \
+ RETURN_FALSE; \
+ } \
+ if (SUCCESS != php_zlib_decode(in_buf, in_len, &out_buf, &out_len, encoding, max_len TSRMLS_CC)) { \
+ RETURN_FALSE; \
+ } \
+ RETURN_STRINGL(out_buf, out_len, 0); \
+}
- if ((level < -1) || (level > 9)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);
- RETURN_FALSE;
- }
+/* {{{ proto binary zlib_encode(binary data, int encoding[, int level = -1])
+ Compress data with the specified encoding */
+PHP_ZLIB_ENCODE_FUNC(zlib_encode, 0);
+/* }}} */
- l2 = data_len + (data_len / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
- s2 = (char *) emalloc(l2);
- if (!s2) {
- RETURN_FALSE;
- }
+/* {{{ proto binary zlib_decode(binary data[, int max_decoded_len])
+ Uncompress any raw/gzip/zlib encoded data */
+PHP_ZLIB_DECODE_FUNC(zlib_decode, PHP_ZLIB_ENCODING_ANY);
+/* }}} */
- if (level >= 0) {
- status = compress2(s2, &l2, data, data_len, level);
- } else {
- status = compress(s2, &l2, data, data_len);
- }
+/* NOTE: The naming of these userland functions was quite unlucky */
+/* {{{ proto binary gzdeflate(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_RAW])
+ Encode data with the raw deflate encoding */
+PHP_ZLIB_ENCODE_FUNC(gzdeflate, PHP_ZLIB_ENCODING_RAW);
+/* }}} */
- if (status == Z_OK) {
- s2 = erealloc(s2, l2 + 1);
- s2[l2] = '\0';
- RETURN_STRINGL(s2, l2, 0);
- } else {
- efree(s2);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
-}
+/* {{{ proto binary gzencode(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_GZIP])
+ Encode data with the gzip encoding */
+PHP_ZLIB_ENCODE_FUNC(gzencode, PHP_ZLIB_ENCODING_GZIP);
/* }}} */
-/* {{{ proto string gzuncompress(string data [, int length])
- Unzip a gzip-compressed string */
-static PHP_FUNCTION(gzuncompress)
-{
- int data_len, status;
- unsigned int factor=1, maxfactor=16;
- long limit = 0;
- unsigned long plength=0, length;
- char *data, *s1=NULL, *s2=NULL;
+/* {{{ proto binary gzcompress(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_DEFLATE])
+ Encode data with the zlib encoding */
+PHP_ZLIB_ENCODE_FUNC(gzcompress, PHP_ZLIB_ENCODING_DEFLATE);
+/* }}} */
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {
- return;
- }
+/* {{{ proto binary gzinflate(binary data[, int max_decoded_len])
+ Decode raw deflate encoded data */
+PHP_ZLIB_DECODE_FUNC(gzinflate, PHP_ZLIB_ENCODING_RAW);
+/* }}} */
- if (limit < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);
- RETURN_FALSE;
- }
- plength = limit;
+/* {{{ proto binary gzdecode(binary data[, int max_decoded_len])
+ Decode gzip encoded data */
+PHP_ZLIB_DECODE_FUNC(gzdecode, PHP_ZLIB_ENCODING_GZIP);
+/* }}} */
- /*
- zlib::uncompress() wants to know the output data length
- if none was given as a parameter
- we try from input length * 2 up to input length * 2^15
- doubling it whenever it wasn't big enough
- that should be eneugh for all real life cases
- */
- do {
- length = plength ? plength : (unsigned long)data_len * (1 << factor++);
- s2 = (char *) erealloc(s1, length);
- status = uncompress(s2, &length, data, data_len);
- s1 = s2;
- } while ((status == Z_BUF_ERROR) && (!plength) && (factor < maxfactor));
-
- if (status == Z_OK) {
- s2 = erealloc(s2, length + 1); /* space for \0 */
- s2[ length ] = '\0';
- RETURN_STRINGL(s2, length, 0);
- } else {
- efree(s2);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
-}
+/* {{{ proto binary gzuncompress(binary data[, int max_decoded_len])
+ Decode zlib encoded data */
+PHP_ZLIB_DECODE_FUNC(gzuncompress, PHP_ZLIB_ENCODING_DEFLATE);
/* }}} */
-/* {{{ proto string gzdeflate(string data [, int level])
- Gzip-compress a string */
-static PHP_FUNCTION(gzdeflate)
-{
- int data_len,status;
- long level = Z_DEFAULT_COMPRESSION;
- z_stream stream;
- char *data, *s2;
+#ifdef COMPILE_DL_ZLIB
+ZEND_GET_MODULE(php_zlib)
+#endif
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level) == FAILURE) {
- return;
- }
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_gzhandler, 0, 0, 2)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
- if ((level < -1) || (level > 9)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level);
- RETURN_FALSE;
- }
+ZEND_BEGIN_ARG_INFO(arginfo_zlib_get_coding_type, 0)
+ZEND_END_ARG_INFO()
- stream.data_type = Z_ASCII;
- stream.zalloc = php_zlib_alloc;
- stream.zfree = php_zlib_free;
- stream.opaque = (voidpf) Z_NULL;
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzfile, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, use_include_path)
+ZEND_END_ARG_INFO()
- stream.next_in = (Bytef *) data;
- stream.avail_in = data_len;
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzopen, 0, 0, 2)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, mode)
+ ZEND_ARG_INFO(0, use_include_path)
+ZEND_END_ARG_INFO()
- stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_readgzfile, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, use_include_path)
+ZEND_END_ARG_INFO()
- s2 = (char *) emalloc(stream.avail_out);
- if (!s2) {
- RETURN_FALSE;
- }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_encode, 0, 0, 2)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, encoding)
+ ZEND_ARG_INFO(0, level)
+ZEND_END_ARG_INFO()
- stream.next_out = s2;
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zlib_decode, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, max_decoded_len)
+ZEND_END_ARG_INFO()
- /* init with -MAX_WBITS disables the zlib internal headers */
- status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, 0);
- if (status == Z_OK) {
- status = deflate(&stream, Z_FINISH);
- if (status != Z_STREAM_END) {
- deflateEnd(&stream);
- if (status == Z_OK) {
- status = Z_BUF_ERROR;
- }
- } else {
- status = deflateEnd(&stream);
- }
- }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdeflate, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, level)
+ ZEND_ARG_INFO(0, encoding)
+ZEND_END_ARG_INFO()
- if (status == Z_OK) {
- s2 = erealloc(s2,stream.total_out + 1); /* resize to buffer to the "right" size */
- s2[ stream.total_out ] = '\0';
- RETURN_STRINGL(s2, stream.total_out, 0);
- } else {
- efree(s2);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
-}
-/* }}} */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzencode, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, level)
+ ZEND_ARG_INFO(0, encoding)
+ZEND_END_ARG_INFO()
-/* {{{ proto string gzinflate(string data [, int length])
- Unzip a gzip-compressed string */
-static PHP_FUNCTION(gzinflate)
-{
- int data_len, status;
- unsigned int factor=1, maxfactor=16;
- long limit = 0;
- unsigned long plength=0, length;
- char *data, *s1=NULL, *s2=NULL;
- z_stream stream;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &limit) == FAILURE) {
- return;
- }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzcompress, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, level)
+ ZEND_ARG_INFO(0, encoding)
+ZEND_END_ARG_INFO()
- if (!data_len) {
- RETURN_FALSE;
- }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzinflate, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, max_decoded_len)
+ZEND_END_ARG_INFO()
- if (limit < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "length (%ld) must be greater or equal zero", limit);
- RETURN_FALSE;
- }
- plength = limit;
-
- stream.zalloc = php_zlib_alloc;
- stream.zfree = php_zlib_free;
- stream.opaque = Z_NULL;
- stream.avail_in = data_len + 1; /* there is room for \0 */
- stream.next_in = (Bytef *) data;
- stream.total_out = 0;
-
- /* init with -MAX_WBITS disables the zlib internal headers */
- status = inflateInit2(&stream, -MAX_WBITS);
- if (status != Z_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzdecode, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, max_decoded_len)
+ZEND_END_ARG_INFO()
- /*
- stream.avail_out wants to know the output data length
- if none was given as a parameter
- we try from input length * 2 up to input length * 2^15
- doubling it whenever it wasn't big enough
- that should be enaugh for all real life cases
- */
- do {
- length = plength ? plength : (unsigned long)data_len * (1 << factor++);
- s2 = (char *) erealloc(s1, length);
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzuncompress, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, max_decoded_len)
+ZEND_END_ARG_INFO()
- if (!s2) {
- if (s1) {
- efree(s1);
- }
- inflateEnd(&stream);
- RETURN_FALSE;
- }
- s1 = s2;
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzputs, 0, 0, 2)
+ ZEND_ARG_INFO(0, fp)
+ ZEND_ARG_INFO(0, str)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
- stream.next_out = (Bytef *) &s2[stream.total_out];
- stream.avail_out = length - stream.total_out;
- status = inflate(&stream, Z_NO_FLUSH);
+ZEND_BEGIN_ARG_INFO(arginfo_gzpassthru, 0)
+ ZEND_ARG_INFO(0, fp)
+ZEND_END_ARG_INFO()
- } while ((Z_BUF_ERROR == status || (Z_OK == status && stream.avail_in)) && !plength && factor < maxfactor);
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzseek, 0, 0, 2)
+ ZEND_ARG_INFO(0, fp)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, whence)
+ZEND_END_ARG_INFO()
- inflateEnd(&stream);
+ZEND_BEGIN_ARG_INFO(arginfo_gzread, 0)
+ ZEND_ARG_INFO(0, fp)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
- if ((plength && Z_OK == status) || factor >= maxfactor) {
- status = Z_MEM_ERROR;
- }
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgetss, 0, 0, 1)
+ ZEND_ARG_INFO(0, fp)
+ ZEND_ARG_INFO(0, length)
+ ZEND_ARG_INFO(0, allowable_tags)
+ZEND_END_ARG_INFO()
- if (Z_STREAM_END == status || Z_OK == status) {
- s2 = erealloc(s2, stream.total_out + 1); /* room for \0 */
- s2[ stream.total_out ] = '\0';
- RETURN_STRINGL(s2, stream.total_out, 0);
- } else {
- efree(s2);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
-}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_gzgets, 0, 0, 1)
+ ZEND_ARG_INFO(0, fp)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
/* }}} */
-/* {{{ proto string zlib_get_coding_type(void)
- Returns the coding type used for output compression */
-static PHP_FUNCTION(zlib_get_coding_type)
-{
- switch (ZLIBG(compression_coding)) {
- case CODING_GZIP:
- RETURN_STRINGL("gzip", sizeof("gzip") - 1, 1);
-
- case CODING_DEFLATE:
- RETURN_STRINGL("deflate", sizeof("deflate") - 1, 1);
- }
-
- RETURN_FALSE;
-}
+/* {{{ php_zlib_functions[] */
+static const zend_function_entry php_zlib_functions[] = {
+ PHP_FE(readgzfile, arginfo_readgzfile)
+ PHP_FALIAS(gzrewind, rewind, arginfo_gzpassthru)
+ PHP_FALIAS(gzclose, fclose, arginfo_gzpassthru)
+ PHP_FALIAS(gzeof, feof, arginfo_gzpassthru)
+ PHP_FALIAS(gzgetc, fgetc, arginfo_gzpassthru)
+ PHP_FALIAS(gzgets, fgets, arginfo_gzgets)
+ PHP_FALIAS(gzgetss, fgetss, arginfo_gzgetss)
+ PHP_FALIAS(gzread, fread, arginfo_gzread)
+ PHP_FE(gzopen, arginfo_gzopen)
+ PHP_FALIAS(gzpassthru, fpassthru, arginfo_gzpassthru)
+ PHP_FALIAS(gzseek, fseek, arginfo_gzseek)
+ PHP_FALIAS(gztell, ftell, arginfo_gzpassthru)
+ PHP_FALIAS(gzwrite, fwrite, arginfo_gzputs)
+ PHP_FALIAS(gzputs, fwrite, arginfo_gzputs)
+ PHP_FE(gzfile, arginfo_gzfile)
+ PHP_FE(gzcompress, arginfo_gzcompress)
+ PHP_FE(gzuncompress, arginfo_gzuncompress)
+ PHP_FE(gzdeflate, arginfo_gzdeflate)
+ PHP_FE(gzinflate, arginfo_gzinflate)
+ PHP_FE(gzencode, arginfo_gzencode)
+ PHP_FE(gzdecode, arginfo_gzdecode)
+ PHP_FE(zlib_encode, arginfo_zlib_encode)
+ PHP_FE(zlib_decode, arginfo_zlib_decode)
+ PHP_FE(zlib_get_coding_type, arginfo_zlib_get_coding_type)
+ PHP_FE(ob_gzhandler, arginfo_ob_gzhandler)
+ PHP_FE_END
+};
+/* }}} */
-/* {{{ php_do_deflate
- */
-static int php_do_deflate(uint str_length, Bytef **p_buffer, uint *p_buffer_len, zend_bool do_start, zend_bool do_end TSRMLS_DC)
+/* {{{ OnUpdate_zlib_output_compression */
+static PHP_INI_MH(OnUpdate_zlib_output_compression)
{
- Bytef *buffer;
- uInt prev_outlen, outlen;
- int err;
- int start_offset = ((do_start && ZLIBG(compression_coding) == CODING_GZIP) ? 10 : 0);
- int end_offset = (do_end ? 8 : 0);
-
- outlen = (uint) (str_length + (str_length / PHP_ZLIB_MODIFIER) + 12 + 1); /* leave some room for a trailing \0 */
- if ((outlen + start_offset + end_offset) > *p_buffer_len) {
- buffer = (Bytef *) emalloc(outlen + start_offset + end_offset);
- } else {
- buffer = *p_buffer;
- }
-
- ZLIBG(stream).next_out = buffer + start_offset;
- ZLIBG(stream).avail_out = outlen;
-
- err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);
- while (err == Z_OK && !ZLIBG(stream).avail_out) {
- prev_outlen = outlen;
- outlen *= 3;
- if ((outlen + start_offset + end_offset) > *p_buffer_len) {
- buffer = erealloc(buffer, outlen + start_offset + end_offset);
- }
-
- ZLIBG(stream).next_out = buffer + start_offset + prev_outlen;
- ZLIBG(stream).avail_out = prev_outlen * 2;
+ int status, int_value;
+ char *ini_value;
- err = deflate(&ZLIBG(stream), Z_SYNC_FLUSH);
+ if (new_value == NULL) {
+ return FAILURE;
}
- if (do_end) {
- err = deflate(&ZLIBG(stream), Z_FINISH);
- buffer[outlen + start_offset - ZLIBG(stream).avail_out] = '\0';
+ if (!strncasecmp(new_value, "off", sizeof("off"))) {
+ new_value = "0";
+ new_value_length = sizeof("0");
+ } else if (!strncasecmp(new_value, "on", sizeof("on"))) {
+ new_value = "1";
+ new_value_length = sizeof("1");
}
- *p_buffer = buffer;
- *p_buffer_len = outlen - ZLIBG(stream).avail_out;
-
- return err;
-}
-/* }}} */
-
-/* {{{ php_deflate_string
- */
-static int php_deflate_string(const char *str, uint str_length, char **newstr, uint *new_length, zend_bool do_start, zend_bool do_end TSRMLS_DC)
-{
- int err;
-
- if (do_start) {
- ZLIBG(stream).zalloc = php_zlib_alloc;
- ZLIBG(stream).zfree = php_zlib_free;
- ZLIBG(stream).opaque = Z_NULL;
-
- switch (ZLIBG(compression_coding)) {
- case CODING_GZIP:
- /* windowBits is passed < 0 to suppress zlib header & trailer */
- if (deflateInit2(&ZLIBG(stream), ZLIBG(output_compression_level), Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
- /* TODO: print out error */
- return FAILURE;
- }
-
- ZLIBG(crc) = crc32(0L, Z_NULL, 0);
- break;
+ int_value = zend_atoi(new_value, new_value_length);
+ ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
- case CODING_DEFLATE:
- if (deflateInit(&ZLIBG(stream), ZLIBG(output_compression_level)) != Z_OK) {
- /* TODO: print out error */
- return FAILURE;
- }
- break;
+ if (ini_value && *ini_value && int_value) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_CORE_ERROR, "Cannot use both zlib.output_compression and output_handler together!!");
+ return FAILURE;
+ }
+ if (stage == PHP_INI_STAGE_RUNTIME) {
+ status = php_output_get_status(TSRMLS_C);
+ if (status & PHP_OUTPUT_SENT) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_compression - headers already sent");
+ return FAILURE;
}
}
- ZLIBG(stream).next_in = (Bytef *) str;
- ZLIBG(stream).avail_in = (uInt) str_length;
-
- if (ZLIBG(compression_coding) == CODING_GZIP) {
- ZLIBG(crc) = crc32(ZLIBG(crc), (const Bytef *) str, str_length);
- }
+ status = OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
- err = php_do_deflate(str_length, (Bytef **) newstr, new_length, do_start, do_end TSRMLS_CC);
- /* TODO: error handling (err may be Z_STREAM_ERROR, Z_BUF_ERROR, ?) */
-
- if (do_start && ZLIBG(compression_coding) == CODING_GZIP) {
- /* Write a very simple .gz header: */
- (*newstr)[0] = gz_magic[0];
- (*newstr)[1] = gz_magic[1];
- (*newstr)[2] = Z_DEFLATED;
- (*newstr)[3] = (*newstr)[4] = (*newstr)[5] = (*newstr)[6] = (*newstr)[7] = (*newstr)[8] = 0;
- (*newstr)[9] = OS_CODE;
- *new_length += 10;
- }
- if (do_end) {
- if (ZLIBG(compression_coding) == CODING_GZIP) {
- char *trailer = (*newstr) + (*new_length);
-
- /* write crc & stream.total_in in LSB order */
- trailer[0] = (char) ZLIBG(crc) & 0xFF;
- trailer[1] = (char) (ZLIBG(crc) >> 8) & 0xFF;
- trailer[2] = (char) (ZLIBG(crc) >> 16) & 0xFF;
- trailer[3] = (char) (ZLIBG(crc) >> 24) & 0xFF;
- trailer[4] = (char) ZLIBG(stream).total_in & 0xFF;
- trailer[5] = (char) (ZLIBG(stream).total_in >> 8) & 0xFF;
- trailer[6] = (char) (ZLIBG(stream).total_in >> 16) & 0xFF;
- trailer[7] = (char) (ZLIBG(stream).total_in >> 24) & 0xFF;
- trailer[8] = '\0';
- *new_length += 8;
+ ZLIBG(output_compression) = ZLIBG(output_compression_default);
+ if (stage == PHP_INI_STAGE_RUNTIME && int_value) {
+ if (!php_output_handler_started(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME) TSRMLS_CC)) {
+ php_zlib_output_compression_start(TSRMLS_C);
}
- deflateEnd(&ZLIBG(stream));
}
- return SUCCESS;
+ return status;
}
/* }}} */
-/* {{{ proto string gzencode(string data [, int level [, int encoding_mode]])
- GZ encode a string */
-static PHP_FUNCTION(gzencode)
+/* {{{ OnUpdate_zlib_output_handler */
+static PHP_INI_MH(OnUpdate_zlib_output_handler)
{
- char *data, *s2;
- int data_len;
- long level = Z_DEFAULT_COMPRESSION, coding = CODING_GZIP;
- int status;
- z_stream stream;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &coding) == FAILURE) {
- return;
- }
-
- if ((level < -1) || (level > 9)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level(%ld) must be within -1..9", level);
- RETURN_FALSE;
- }
-
- if ((coding != CODING_GZIP) && (coding != CODING_DEFLATE)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be FORCE_GZIP or FORCE_DEFLATE");
- RETURN_FALSE;
+ if (stage == PHP_INI_STAGE_RUNTIME && (php_output_get_status(TSRMLS_C) & PHP_OUTPUT_SENT)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "Cannot change zlib.output_handler - headers already sent");
+ return FAILURE;
}
- stream.zalloc = php_zlib_alloc;
- stream.zfree = php_zlib_free;
- stream.opaque = Z_NULL;
-
- stream.next_in = (Bytef *) data;
- stream.avail_in = data_len;
-
- stream.avail_out = stream.avail_in + (stream.avail_in / PHP_ZLIB_MODIFIER) + 15 + 1; /* room for \0 */
- s2 = (char *) emalloc(stream.avail_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0));
-
- /* add gzip file header */
- s2[0] = gz_magic[0];
- s2[1] = gz_magic[1];
- s2[2] = Z_DEFLATED;
- s2[3] = s2[4] = s2[5] = s2[6] = s2[7] = s2[8] = 0; /* time set to 0 */
- s2[9] = OS_CODE;
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ INI */
+PHP_INI_BEGIN()
+ STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression_default, zend_zlib_globals, zlib_globals)
+ STD_PHP_INI_ENTRY("zlib.output_compression_level", "-1", PHP_INI_ALL, OnUpdateLong, output_compression_level, zend_zlib_globals, zlib_globals)
+ STD_PHP_INI_ENTRY("zlib.output_handler", "", PHP_INI_ALL, OnUpdate_zlib_output_handler, output_handler, zend_zlib_globals, zlib_globals)
+PHP_INI_END()
- stream.next_out = &(s2[GZIP_HEADER_LENGTH]);
+/* }}} */
- switch (coding) {
- case CODING_GZIP:
- /* windowBits is passed < 0 to suppress zlib header & trailer */
- if ((status = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)) != Z_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
+/* {{{ PHP_MINIT_FUNCTION */
+static PHP_MINIT_FUNCTION(zlib)
+{
+ php_register_url_stream_wrapper("compress.zlib", &php_stream_gzip_wrapper TSRMLS_CC);
+ php_stream_filter_register_factory("zlib.*", &php_zlib_filter_factory TSRMLS_CC);
- break;
- case CODING_DEFLATE:
- if ((status = deflateInit(&stream, level)) != Z_OK) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
- break;
- }
+ php_output_handler_alias_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_handler_init TSRMLS_CC);
+ php_output_handler_conflict_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_conflict_check TSRMLS_CC);
+ php_output_handler_conflict_register(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), php_zlib_output_conflict_check TSRMLS_CC);
- status = deflate(&stream, Z_FINISH);
- if (status != Z_STREAM_END) {
- deflateEnd(&stream);
- if (status == Z_OK) {
- status = Z_BUF_ERROR;
- }
- } else {
- status = deflateEnd(&stream);
- }
+ REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
- if (status == Z_OK) {
- /* resize to buffer to the "right" size */
- s2 = erealloc(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0) + 1);
-
- if (coding == CODING_GZIP) {
- char *trailer = s2 + (stream.total_out + GZIP_HEADER_LENGTH);
- uLong crc = crc32(0L, Z_NULL, 0);
-
- crc = crc32(crc, (const Bytef *) data, data_len);
-
- /* write crc & stream.total_in in LSB order */
- trailer[0] = (char) crc & 0xFF;
- trailer[1] = (char) (crc >> 8) & 0xFF;
- trailer[2] = (char) (crc >> 16) & 0xFF;
- trailer[3] = (char) (crc >> 24) & 0xFF;
- trailer[4] = (char) stream.total_in & 0xFF;
- trailer[5] = (char) (stream.total_in >> 8) & 0xFF;
- trailer[6] = (char) (stream.total_in >> 16) & 0xFF;
- trailer[7] = (char) (stream.total_in >> 24) & 0xFF;
- trailer[8] = '\0';
- } else {
- s2[stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0)] = '\0';
- }
- RETURN_STRINGL(s2, stream.total_out + GZIP_HEADER_LENGTH + (coding == CODING_GZIP ? GZIP_FOOTER_LENGTH : 0), 0);
- } else {
- efree(s2);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zError(status));
- RETURN_FALSE;
- }
+ REGISTER_LONG_CONSTANT("ZLIB_ENCODING_RAW", PHP_ZLIB_ENCODING_RAW, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_ENCODING_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ZLIB_ENCODING_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_INI_ENTRIES();
+ return SUCCESS;
}
/* }}} */
-/* {{{ php_ob_gzhandler_check
- */
-int php_ob_gzhandler_check(TSRMLS_D)
+/* {{{ PHP_MSHUTDOWN_FUNCTION */
+static PHP_MSHUTDOWN_FUNCTION(zlib)
{
- /* check for wrong usages */
- if (OG(ob_nesting_level > 0)) {
- if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice");
- return FAILURE;
- }
- if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'mb_output_handler'");
- return FAILURE;
- }
- if (php_ob_handler_used("URL-Rewriter" TSRMLS_CC)) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'URL-Rewriter'");
- return FAILURE;
- }
- if (php_ob_init_conflict("ob_gzhandler", "zlib output compression" TSRMLS_CC)) {
- return FAILURE;
- }
- }
+ php_unregister_url_stream_wrapper("zlib" TSRMLS_CC);
+ php_stream_filter_unregister_factory("zlib.*" TSRMLS_CC);
+
+ UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
-
/* }}} */
-/* {{{ proto string ob_gzhandler(string str, int mode)
- Encode str based on accept-encoding setting - designed to be called from ob_start() */
-static PHP_FUNCTION(ob_gzhandler)
+/* {{{ PHP_RINIT_FUNCTION */
+static PHP_RINIT_FUNCTION(zlib)
{
- char *string;
- int string_len;
- long mode;
- zval **a_encoding;
- zend_bool return_original = 0;
- zend_bool do_start, do_end;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &string, &string_len, &mode) == FAILURE) {
- return;
- }
-
- if (ZLIBG(ob_gzhandler_status) == -1) {
- RETURN_FALSE;
- }
-
- zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
-
- if (!PG(http_globals)[TRACK_VARS_SERVER]
- || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE
- ) {
- ZLIBG(ob_gzhandler_status) = -1;
- RETURN_FALSE;
- }
-
- convert_to_string_ex(a_encoding);
- if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
- ZLIBG(compression_coding) = CODING_GZIP;
- } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
- ZLIBG(compression_coding) = CODING_DEFLATE;
- } else {
- ZLIBG(ob_gzhandler_status) = -1;
- RETURN_FALSE;
- }
-
- do_start = ((mode & PHP_OUTPUT_HANDLER_START) ? 1 : 0);
- do_end = ((mode & PHP_OUTPUT_HANDLER_END) ? 1 : 0);
- Z_STRVAL_P(return_value) = NULL;
- Z_STRLEN_P(return_value) = 0;
-
- if (php_deflate_string(string, string_len, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), do_start, do_end TSRMLS_CC) == SUCCESS) {
- Z_TYPE_P(return_value) = IS_STRING;
- if (do_start) {
- switch (ZLIBG(compression_coding)) {
- case CODING_GZIP:
- if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1) == FAILURE) {
- return_original = 1;
- }
- if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
- return_original = 1;
- }
- break;
- case CODING_DEFLATE:
- if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1) == FAILURE) {
- return_original = 1;
- }
- if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
- return_original = 1;
- }
- break;
- default:
- return_original = 1;
- break;
- }
- }
-
- if (return_original) {
- zval_dtor(return_value);
- }
-
- } else {
- return_original = 1;
- }
+ ZLIBG(compression_coding) = 0;
+ if (!ZLIBG(handler_registered)) {
+ ZLIBG(output_compression) = ZLIBG(output_compression_default);
+ php_zlib_output_compression_start(TSRMLS_C);
+ }
- if (return_original) {
- /* return the original string */
- RETURN_STRINGL(string, string_len, 1);
- }
+ return SUCCESS;
}
/* }}} */
-/* {{{ php_gzip_output_handler
- */
-static void php_gzip_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
+/* {{{ PHP_RSHUTDOWN_FUNCTION */
+static PHP_RSHUTDOWN_FUNCTION(zlib)
{
- zend_bool do_start, do_end;
-
- if (!ZLIBG(output_compression) || SG(sapi_headers).http_response_code == 204 || SG(sapi_headers).http_response_code == 304) {
- *handled_output = NULL;
- } else {
- do_start = (mode & PHP_OUTPUT_HANDLER_START ? 1 : 0);
- do_end = (mode & PHP_OUTPUT_HANDLER_END ? 1 : 0);
+ php_zlib_cleanup_ob_gzhandler_mess(TSRMLS_C);
+ ZLIBG(handler_registered) = 0;
- if (do_start) {
- if (!SG(headers_sent) && !SG(request_info).no_headers) {
- switch (ZLIBG(compression_coding)) {
- case CODING_GZIP:
- sapi_add_header_ex(ZEND_STRL("Content-Encoding: gzip"), 1, 1 TSRMLS_CC);
- break;
- case CODING_DEFLATE:
- sapi_add_header_ex(ZEND_STRL("Content-Encoding: deflate"), 1, 1 TSRMLS_CC);
- break;
- }
- sapi_add_header_ex(ZEND_STRL("Vary: Accept-Encoding"), 1, 0 TSRMLS_CC);
- } else {
- /* Disable compression if headers can not be set (Fix for bug #49816) */
- ZLIBG(output_compression) = 0;
- *handled_output = NULL;
- return;
- }
- }
-
- if (php_deflate_string(output, output_len, handled_output, handled_output_len, do_start, do_end TSRMLS_CC) != SUCCESS) {
- zend_error(E_ERROR, "Compression failed");
- }
- }
+ return SUCCESS;
}
/* }}} */
-/* {{{ php_enable_output_compression
- */
-static int php_enable_output_compression(int buffer_size TSRMLS_DC)
+/* {{{ PHP_MINFO_FUNCTION */
+static PHP_MINFO_FUNCTION(zlib)
{
- zval **a_encoding;
-
- zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
-
- if (!PG(http_globals)[TRACK_VARS_SERVER]
- || zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &a_encoding) == FAILURE
- ) {
- return FAILURE;
- }
-
- convert_to_string_ex(a_encoding);
-
- if (php_memnstr(Z_STRVAL_PP(a_encoding), "gzip", 4, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
- ZLIBG(compression_coding) = CODING_GZIP;
- } else if (php_memnstr(Z_STRVAL_PP(a_encoding), "deflate", 7, Z_STRVAL_PP(a_encoding) + Z_STRLEN_PP(a_encoding))) {
- ZLIBG(compression_coding) = CODING_DEFLATE;
- } else {
- return FAILURE;
- }
-
- php_ob_set_internal_handler(php_gzip_output_handler, (uint)buffer_size, "zlib output compression", 0 TSRMLS_CC);
+ php_info_print_table_start();
+ php_info_print_table_header(2, "ZLib Support", "enabled");
+ php_info_print_table_row(2, "Stream Wrapper", "compress.zlib://");
+ php_info_print_table_row(2, "Stream Filter", "zlib.inflate, zlib.deflate");
+ php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION);
+ php_info_print_table_row(2, "Linked Version", (char *) zlibVersion());
+ php_info_print_table_end();
- if (ZLIBG(output_handler) && strlen(ZLIBG(output_handler))) {
- php_start_ob_buffer_named(ZLIBG(output_handler), 0, 1 TSRMLS_CC);
- }
- return SUCCESS;
+ DISPLAY_INI_ENTRIES();
}
/* }}} */
-/* {{{ php_zlib_output_compression_start() */
-static int php_zlib_output_compression_start(TSRMLS_D)
+/* {{{ ZEND_MODULE_GLOBALS_CTOR */
+static ZEND_MODULE_GLOBALS_CTOR_D(zlib)
{
- switch (ZLIBG(output_compression)) {
- case 0:
- break;
- case 1:
- ZLIBG(output_compression) = 4096;
- /* break omitted intentionally */
- default:
- /* ZLIBG(compression_coding) should be 0 when zlib compression hasn't been started yet.. */
- if (ZLIBG(compression_coding) == 0) {
- return php_enable_output_compression(ZLIBG(output_compression) TSRMLS_CC);
- }
- }
- return SUCCESS;
+ zlib_globals->ob_gzhandler = NULL;
+ zlib_globals->handler_registered = 0;
}
/* }}} */
+/* {{{ php_zlib_module_entry */
+zend_module_entry php_zlib_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "zlib",
+ php_zlib_functions,
+ PHP_MINIT(zlib),
+ PHP_MSHUTDOWN(zlib),
+ PHP_RINIT(zlib),
+ PHP_RSHUTDOWN(zlib),
+ PHP_MINFO(zlib),
+ "2.0",
+ PHP_MODULE_GLOBALS(zlib),
+ ZEND_MODULE_GLOBALS_CTOR_N(zlib),
+ NULL,
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c
index 4b07152978..b9c55d3309 100644
--- a/ext/zlib/zlib_filter.c
+++ b/ext/zlib/zlib_filter.c
@@ -80,8 +80,11 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
while (buckets_in->head) {
size_t bin = 0, desired;
+ bucket = buckets_in->head;
+
bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
- while (bin < bucket->buflen) {
+
+ while (bin < (unsigned int) bucket->buflen) {
if (data->finished) {
consumed += bucket->buflen;
@@ -110,7 +113,6 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */
data->strm.next_in = data->inbuf;
data->strm.avail_in = 0;
- consumed += desired;
bin += desired;
if (data->strm.avail_out < data->outbuf_len) {
@@ -126,7 +128,9 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
php_stream_bucket_delref(bucket TSRMLS_CC);
return PSFS_PASS_ON;
}
+
}
+ consumed += bucket->buflen;
php_stream_bucket_delref(bucket TSRMLS_CC);
}
@@ -205,9 +209,11 @@ static php_stream_filter_status_t php_zlib_deflate_filter(
while (buckets_in->head) {
size_t bin = 0, desired;
- bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
+ bucket = buckets_in->head;
+
+ bucket = php_stream_bucket_make_writeable(bucket TSRMLS_CC);
- while (bin < bucket->buflen) {
+ while (bin < (unsigned int) bucket->buflen) {
desired = bucket->buflen - bin;
if (desired > data->inbuf_len) {
desired = data->inbuf_len;
@@ -224,7 +230,6 @@ static php_stream_filter_status_t php_zlib_deflate_filter(
desired -= data->strm.avail_in; /* desired becomes what we consumed this round through */
data->strm.next_in = data->inbuf;
data->strm.avail_in = 0;
- consumed += desired;
bin += desired;
if (data->strm.avail_out < data->outbuf_len) {
@@ -238,6 +243,7 @@ static php_stream_filter_status_t php_zlib_deflate_filter(
exit_status = PSFS_PASS_ON;
}
}
+ consumed += bucket->buflen;
php_stream_bucket_delref(bucket TSRMLS_CC);
}
@@ -261,6 +267,7 @@ static php_stream_filter_status_t php_zlib_deflate_filter(
if (bytes_consumed) {
*bytes_consumed = consumed;
}
+
return exit_status;
}
@@ -294,7 +301,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
/* Create this filter */
data = pecalloc(1, sizeof(php_zlib_filter_data), persistent);
if (!data) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes.", sizeof(php_zlib_filter_data));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes", sizeof(php_zlib_filter_data));
return NULL;
}
@@ -306,14 +313,14 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
data->strm.avail_out = data->outbuf_len = data->inbuf_len = 2048;
data->strm.next_in = data->inbuf = (Bytef *) pemalloc(data->inbuf_len, persistent);
if (!data->inbuf) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes.", data->inbuf_len);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes", data->inbuf_len);
pefree(data, persistent);
return NULL;
}
data->strm.avail_in = 0;
data->strm.next_out = data->outbuf = (Bytef *) pemalloc(data->outbuf_len, persistent);
if (!data->outbuf) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes.", data->outbuf_len);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed allocating %zd bytes", data->outbuf_len);
pefree(data->inbuf, persistent);
pefree(data, persistent);
return NULL;
@@ -412,7 +419,7 @@ factory_setlevel:
}
break;
default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid filter parameter, ignored.");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid filter parameter, ignored");
}
}
status = deflateInit2(&(data->strm), level, Z_DEFLATED, windowBits, memLevel, 0);
diff --git a/ext/zlib/zlib_fopen_wrapper.c b/ext/zlib/zlib_fopen_wrapper.c
index 71958d82e9..039e3d1aaa 100644
--- a/ext/zlib/zlib_fopen_wrapper.c
+++ b/ext/zlib/zlib_fopen_wrapper.c
@@ -96,7 +96,7 @@ static int php_gziop_flush(php_stream *stream TSRMLS_DC)
return gzflush(self->gz_file, Z_SYNC_FLUSH);
}
-static php_stream_ops php_stream_gzio_ops = {
+php_stream_ops php_stream_gzio_ops = {
php_gziop_write, php_gziop_read,
php_gziop_close, php_gziop_flush,
"ZLIB",
diff --git a/main/SAPI.c b/main/SAPI.c
index 05644df11d..fc4b7bee84 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -37,6 +37,8 @@
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
+#elif defined(PHP_WIN32)
+#include "win32/time.h"
#endif
#include "rfc1867.h"
@@ -73,6 +75,10 @@ SAPI_API sapi_module_struct sapi_module;
SAPI_API void sapi_startup(sapi_module_struct *sf)
{
+#ifdef ZEND_SIGNALS
+ zend_signal_startup();
+#endif
+
sf->ini_entries = NULL;
sapi_module = *sf;
@@ -117,6 +123,58 @@ SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
efree(sapi_header->header);
}
+/* {{{ proto bool header_register_callback(mixed callback)
+ call a header function */
+PHP_FUNCTION(header_register_callback)
+{
+ zval *callback_func;
+ char *callback_name;
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback_func) == FAILURE) {
+ return;
+ }
+
+ if (!zend_is_callable(callback_func, 0, &callback_name TSRMLS_CC)) {
+ efree(callback_name);
+ RETURN_FALSE;
+ }
+ efree(callback_name);
+
+ if (SG(callback_func)) {
+ zval_ptr_dtor(&SG(callback_func));
+ SG(fci_cache) = empty_fcall_info_cache;
+ }
+
+ Z_ADDREF_P(callback_func);
+
+ SG(callback_func) = callback_func;
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+static void sapi_run_header_callback(TSRMLS_D)
+{
+ int error;
+ zend_fcall_info fci;
+ zval *retval_ptr = NULL;
+
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.object_ptr = NULL;
+ fci.function_name = SG(callback_func);
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = 0;
+ fci.params = NULL;
+ fci.no_separation = 0;
+ fci.symbol_table = NULL;
+
+ error = zend_call_function(&fci, &SG(fci_cache) TSRMLS_CC);
+ if (error == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the sapi_header_callback");
+ } else if (retval_ptr) {
+ zval_ptr_dtor(&retval_ptr);
+ }
+}
SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
{
@@ -227,35 +285,61 @@ SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
}
-SAPI_API char *sapi_get_default_content_type(TSRMLS_D)
+static inline char *get_default_content_type(uint prefix_len, uint *len TSRMLS_DC)
{
char *mimetype, *charset, *content_type;
+ uint mimetype_len, charset_len;
- mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
- charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
+ if (SG(default_mimetype)) {
+ mimetype = SG(default_mimetype);
+ mimetype_len = strlen(SG(default_mimetype));
+ } else {
+ mimetype = SAPI_DEFAULT_MIMETYPE;
+ mimetype_len = sizeof(SAPI_DEFAULT_MIMETYPE) - 1;
+ }
+ if (SG(default_charset)) {
+ charset = SG(default_charset);
+ charset_len = strlen(SG(default_charset));
+ } else {
+ charset = SAPI_DEFAULT_CHARSET;
+ charset_len = sizeof(SAPI_DEFAULT_CHARSET) - 1;
+ }
- if (strncasecmp(mimetype, "text/", 5) == 0 && *charset) {
- int len = strlen(mimetype) + sizeof("; charset=") + strlen(charset); /* sizeof() includes \0 */
- content_type = emalloc(len);
- snprintf(content_type, len, "%s; charset=%s", mimetype, charset);
+ if (*charset && strncasecmp(mimetype, "text/", 5) == 0) {
+ char *p;
+
+ *len = prefix_len + mimetype_len + sizeof("; charset=") - 1 + charset_len;
+ content_type = (char*)emalloc(*len + 1);
+ p = content_type + prefix_len;
+ memcpy(p, mimetype, mimetype_len);
+ p += mimetype_len;
+ memcpy(p, "; charset=", sizeof("; charset=") - 1);
+ p += sizeof("; charset=") - 1;
+ memcpy(p, charset, charset_len + 1);
} else {
- content_type = estrdup(mimetype);
+ *len = prefix_len + mimetype_len;
+ content_type = (char*)emalloc(*len + 1);
+ memcpy(content_type + prefix_len, mimetype, mimetype_len + 1);
}
return content_type;
}
+SAPI_API char *sapi_get_default_content_type(TSRMLS_D)
+{
+ uint len;
+
+ return get_default_content_type(0, &len TSRMLS_CC);
+}
+
+
SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header TSRMLS_DC)
{
- char *default_content_type = sapi_get_default_content_type(TSRMLS_C);
- int default_content_type_len = strlen(default_content_type);
-
- default_header->header_len = (sizeof("Content-type: ")-1) + default_content_type_len;
- default_header->header = emalloc(default_header->header_len+1);
- memcpy(default_header->header, "Content-type: ", sizeof("Content-type: "));
- memcpy(default_header->header+sizeof("Content-type: ")-1, default_content_type, default_content_type_len);
- default_header->header[default_header->header_len] = 0;
- efree(default_content_type);
+ uint len;
+
+ default_header->header = get_default_content_type(sizeof("Content-type: ")-1, &len TSRMLS_CC);
+ default_header->header_len = len;
+ memcpy(default_header->header, "Content-type: ", sizeof("Content-type: ") - 1);
}
/*
@@ -346,6 +430,8 @@ SAPI_API void sapi_activate(TSRMLS_D)
SG(sapi_headers).http_status_line = NULL;
SG(sapi_headers).mimetype = NULL;
SG(headers_sent) = 0;
+ SG(callback_run) = 0;
+ SG(callback_func) = NULL;
SG(read_post_bytes) = 0;
SG(request_info).post_data = NULL;
SG(request_info).raw_post_data = NULL;
@@ -356,9 +442,7 @@ SAPI_API void sapi_activate(TSRMLS_D)
SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
SG(global_request_time) = 0;
- /* It's possible to override this general case in the activate() callback, if
- * necessary.
- */
+ /* It's possible to override this general case in the activate() callback, if necessary. */
if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
SG(request_info).headers_only = 1;
} else {
@@ -366,22 +450,19 @@ SAPI_API void sapi_activate(TSRMLS_D)
}
SG(rfc1867_uploaded_files) = NULL;
- /* handle request mehtod */
+ /* Handle request method */
if (SG(server_context)) {
- if ( SG(request_info).request_method) {
- if(!strcmp(SG(request_info).request_method, "POST")
- && (SG(request_info).content_type)) {
- /* HTTP POST -> may contain form data to be read into variables
- depending on content type given
- */
+ if (PG(enable_post_data_reading) && SG(request_info).request_method) {
+ if (SG(request_info).content_type && !strcmp(SG(request_info).request_method, "POST")) {
+ /* HTTP POST may contain form data to be processed into variables
+ * depending on given content type */
sapi_read_post_data(TSRMLS_C);
} else {
- /* any other method with content payload will fill
- $HTTP_RAW_POST_DATA if enabled by always_populate_raw_post_data
- it is up to the webserver to decide whether to allow a method or not
- */
+ /* Any other method with content payload will fill $HTTP_RAW_POST_DATA
+ * if it is enabled by always_populate_raw_post_data.
+ * It's up to the webserver to decide whether to allow a method or not. */
SG(request_info).content_type_dup = NULL;
- if(sapi_module.default_post_reader) {
+ if (sapi_module.default_post_reader) {
sapi_module.default_post_reader(TSRMLS_C);
}
}
@@ -391,11 +472,12 @@ SAPI_API void sapi_activate(TSRMLS_D)
/* Cookies */
SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
+
if (sapi_module.activate) {
sapi_module.activate(TSRMLS_C);
}
}
- if (sapi_module.input_filter_init ) {
+ if (sapi_module.input_filter_init) {
sapi_module.input_filter_init(TSRMLS_C);
}
}
@@ -456,6 +538,10 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
sapi_send_headers_free(TSRMLS_C);
SG(sapi_started) = 0;
SG(headers_sent) = 0;
+ SG(callback_run) = 0;
+ if (SG(callback_func)) {
+ zval_ptr_dtor(&SG(callback_func));
+ }
SG(request_info).headers_read = 0;
SG(global_request_time) = 0;
}
@@ -550,19 +636,38 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
return r;
}
+static void sapi_header_add_op(sapi_header_op_enum op, sapi_header_struct *sapi_header TSRMLS_DC)
+{
+ if (!sapi_module.header_handler ||
+ (SAPI_HEADER_ADD & sapi_module.header_handler(sapi_header, op, &SG(sapi_headers) TSRMLS_CC))) {
+ if (op == SAPI_HEADER_REPLACE) {
+ char *colon_offset = strchr(sapi_header->header, ':');
+
+ if (colon_offset) {
+ char sav = *colon_offset;
+
+ *colon_offset = 0;
+ sapi_remove_header(&SG(sapi_headers).headers, sapi_header->header, strlen(sapi_header->header));
+ *colon_offset = sav;
+ }
+ }
+ zend_llist_add_element(&SG(sapi_headers).headers, (void *) sapi_header);
+ } else {
+ sapi_free_header(sapi_header);
+ }
+}
+
SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
{
- int retval;
sapi_header_struct sapi_header;
char *colon_offset;
- long myuid = 0L;
char *header_line;
uint header_line_len;
int http_response_code;
-
+
if (SG(headers_sent) && !SG(request_info).no_headers) {
- char *output_start_filename = php_get_output_start_filename(TSRMLS_C);
- int output_start_lineno = php_get_output_start_lineno(TSRMLS_C);
+ const char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
+ int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
if (output_start_filename) {
sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)",
@@ -606,8 +711,12 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
header_line = estrndup(header_line, header_line_len);
/* cut of trailing spaces, linefeeds and carriage-returns */
- while(header_line_len && isspace(header_line[header_line_len-1]))
- header_line[--header_line_len]='\0';
+ if (header_line_len && isspace(header_line[header_line_len-1])) {
+ do {
+ header_line_len--;
+ } while(header_line_len && isspace(header_line[header_line_len-1]));
+ header_line[header_line_len]='\0';
+ }
if (op == SAPI_HEADER_DELETE) {
if (strchr(header_line, ':')) {
@@ -615,6 +724,14 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
return FAILURE;
}
+ if (sapi_module.header_handler) {
+ sapi_header.header = header_line;
+ sapi_header.header_len = header_line_len;
+ sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
+ }
+ sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len);
+ efree(header_line);
+ return SUCCESS;
} else {
/* new line/NUL character safety check */
int i;
@@ -642,15 +759,6 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
sapi_header.header = header_line;
sapi_header.header_len = header_line_len;
- if (op == SAPI_HEADER_DELETE) {
- if (sapi_module.header_handler) {
- sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
- }
- sapi_remove_header(&SG(sapi_headers).headers, sapi_header.header, sapi_header.header_len);
- sapi_free_header(&sapi_header);
- return SUCCESS;
- }
-
/* Check the header for a few cases that we have special support for in SAPI */
if (header_line_len>=5
&& !strncasecmp(header_line, "HTTP/", 5)) {
@@ -696,6 +804,14 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
}
efree(mimetype);
SG(sapi_headers).send_default_content_type = 0;
+ } else if (!STRCASECMP(header_line, "Content-Length")) {
+ /* Script is setting Content-length. The script cannot reasonably
+ * know the size of the message body after compression, so it's best
+ * do disable compression altogether. This contributes to making scripts
+ * portable between setups that have and don't have zlib compression
+ * enabled globally. See req #44164 */
+ zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"),
+ "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
} else if (!STRCASECMP(header_line, "Location")) {
if ((SG(sapi_headers).http_response_code < 300 ||
SG(sapi_headers).http_response_code > 307) &&
@@ -713,75 +829,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
}
}
} else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
-
sapi_update_response_code(401 TSRMLS_CC); /* authentication-required */
-
- if(PG(safe_mode))
-#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
- {
- zval *repl_temp;
- char *ptr = colon_offset+1, *result, *newheader;
- int ptr_len=0, result_len = 0, newlen = 0;
-
- /* skip white space */
- while (isspace(*ptr)) {
- ptr++;
- }
-
- myuid = php_getuid();
-
- ptr_len = strlen(ptr);
- MAKE_STD_ZVAL(repl_temp);
- Z_TYPE_P(repl_temp) = IS_STRING;
- Z_STRLEN_P(repl_temp) = spprintf(&Z_STRVAL_P(repl_temp), 0, "realm=\"\\1-%ld\"", myuid);
- /* Modify quoted realm value */
- result = php_pcre_replace("/realm=\"(.*?)\"/i", 16,
- ptr, ptr_len,
- repl_temp,
- 0, &result_len, -1, NULL TSRMLS_CC);
- if(result_len==ptr_len) {
- efree(result);
- efree(Z_STRVAL_P(repl_temp));
- Z_STRLEN_P(repl_temp) = spprintf(&Z_STRVAL_P(repl_temp), 0, "realm=\\1-%ld\\2", myuid);
- /* modify unquoted realm value */
- result = php_pcre_replace("/realm=([^\\s]+)(.*)/i", 21,
- ptr, ptr_len,
- repl_temp,
- 0, &result_len, -1, NULL TSRMLS_CC);
- if(result_len==ptr_len) {
- char *lower_temp = estrdup(ptr);
- char conv_temp[32];
- int conv_len;
-
- php_strtolower(lower_temp,strlen(lower_temp));
- /* If there is no realm string at all, append one */
- if(!strstr(lower_temp,"realm")) {
- efree(result);
- conv_len = slprintf(conv_temp, sizeof(conv_temp), " realm=\"%ld\"",myuid);
- result = emalloc(ptr_len+conv_len+1);
- result_len = ptr_len+conv_len;
- memcpy(result, ptr, ptr_len);
- memcpy(result+ptr_len, conv_temp, conv_len);
- *(result+ptr_len+conv_len) = '\0';
- }
- efree(lower_temp);
- }
- }
- newlen = spprintf(&newheader, 0, "WWW-Authenticate: %s", result);
- efree(header_line);
- sapi_header.header = newheader;
- sapi_header.header_len = newlen;
- efree(result);
- efree(Z_STRVAL_P(repl_temp));
- efree(repl_temp);
- }
-#else
- {
- myuid = php_getuid();
- efree(header_line);
- sapi_header.header_len = spprintf(&sapi_header.header, 0, "WWW-Authenticate: Basic realm=\"%ld\"", myuid);
- }
-#endif
}
if (sapi_header.header==header_line) {
*colon_offset = ':';
@@ -791,28 +839,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
if (http_response_code) {
sapi_update_response_code(http_response_code TSRMLS_CC);
}
- if (sapi_module.header_handler) {
- retval = sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
- } else {
- retval = SAPI_HEADER_ADD;
- }
- if (retval & SAPI_HEADER_ADD) {
- /* in replace mode first remove the header if it already exists in the headers llist */
- if (op == SAPI_HEADER_REPLACE) {
- colon_offset = strchr(sapi_header.header, ':');
- if (colon_offset) {
- char sav;
- sav = *colon_offset;
- *colon_offset = 0;
- sapi_remove_header(&SG(sapi_headers).headers, sapi_header.header, strlen(sapi_header.header));
- *colon_offset = sav;
- }
- }
-
- zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header);
- } else {
- sapi_free_header(&sapi_header);
- }
+ sapi_header_add_op(op, &sapi_header TSRMLS_CC);
return SUCCESS;
}
@@ -822,7 +849,7 @@ SAPI_API int sapi_send_headers(TSRMLS_D)
int retval;
int ret = FAILURE;
- if (SG(headers_sent) || SG(request_info).no_headers) {
+ if (SG(headers_sent) || SG(request_info).no_headers || SG(callback_run)) {
return SUCCESS;
}
@@ -831,8 +858,20 @@ SAPI_API int sapi_send_headers(TSRMLS_D)
*/
if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) {
sapi_header_struct default_header;
- sapi_get_default_content_type_header(&default_header TSRMLS_CC);
- sapi_add_header_ex(default_header.header, default_header.header_len, 0, 0 TSRMLS_CC);
+ uint len;
+
+ SG(sapi_headers).mimetype = get_default_content_type(0, &len TSRMLS_CC);
+ default_header.header_len = sizeof("Content-type: ") - 1 + len;
+ default_header.header = emalloc(default_header.header_len + 1);
+ memcpy(default_header.header, "Content-type: ", sizeof("Content-type: ") - 1);
+ memcpy(default_header.header + sizeof("Content-type: ") - 1, SG(sapi_headers).mimetype, len + 1);
+ sapi_header_add_op(SAPI_HEADER_ADD, &default_header TSRMLS_CC);
+ SG(sapi_headers).send_default_content_type = 0;
+ }
+
+ if (SG(callback_func) && !SG(callback_run)) {
+ SG(callback_run) = 1;
+ sapi_run_header_callback(TSRMLS_C);
}
SG(headers_sent) = 1;
@@ -917,9 +956,8 @@ SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
}
-SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
+SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D) TSRMLS_DC)
{
- TSRMLS_FETCH();
if (SG(sapi_started) && EG(in_execution)) {
return FAILURE;
}
@@ -928,9 +966,8 @@ SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRML
}
-SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC))
+SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC) TSRMLS_DC)
{
- TSRMLS_FETCH();
if (SG(sapi_started) && EG(in_execution)) {
return FAILURE;
}
@@ -938,9 +975,8 @@ SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zva
return SUCCESS;
}
-SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D))
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D) TSRMLS_DC)
{
- TSRMLS_FETCH();
if (SG(sapi_started) && EG(in_execution)) {
return FAILURE;
}
@@ -1025,14 +1061,19 @@ SAPI_API int sapi_get_target_gid(gid_t *obj TSRMLS_DC)
}
}
-SAPI_API time_t sapi_get_request_time(TSRMLS_D)
+SAPI_API double sapi_get_request_time(TSRMLS_D)
{
if(SG(global_request_time)) return SG(global_request_time);
if (sapi_module.get_request_time && SG(server_context)) {
SG(global_request_time) = sapi_module.get_request_time(TSRMLS_C);
} else {
- SG(global_request_time) = time(0);
+ struct timeval tp = {0};
+ if (!gettimeofday(&tp, NULL)) {
+ SG(global_request_time) = (double)(tp.tv_sec + tp.tv_usec / 1000000.00);
+ } else {
+ SG(global_request_time) = (double)time(0);
+ }
}
return SG(global_request_time);
}
diff --git a/main/SAPI.h b/main/SAPI.h
index 9a063d396a..8f2536b84f 100644
--- a/main/SAPI.h
+++ b/main/SAPI.h
@@ -128,8 +128,11 @@ typedef struct _sapi_globals_struct {
long post_max_size;
int options;
zend_bool sapi_started;
- time_t global_request_time;
+ double global_request_time;
HashTable known_post_content_types;
+ zval *callback_func;
+ zend_fcall_info_cache fci_cache;
+ zend_bool callback_run;
} sapi_globals_struct;
@@ -189,9 +192,9 @@ SAPI_API void sapi_handle_post(void *arg TSRMLS_DC);
SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entry TSRMLS_DC);
SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC);
SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC);
-SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
-SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
-SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D));
+SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D) TSRMLS_DC);
+SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC) TSRMLS_DC);
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D) TSRMLS_DC);
SAPI_API int sapi_flush(TSRMLS_D);
SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
@@ -207,7 +210,7 @@ SAPI_API int sapi_force_http_10(TSRMLS_D);
SAPI_API int sapi_get_target_uid(uid_t * TSRMLS_DC);
SAPI_API int sapi_get_target_gid(gid_t * TSRMLS_DC);
-SAPI_API time_t sapi_get_request_time(TSRMLS_D);
+SAPI_API double sapi_get_request_time(TSRMLS_D);
SAPI_API void sapi_terminate_process(TSRMLS_D);
END_EXTERN_C()
@@ -236,8 +239,8 @@ struct _sapi_module_struct {
char *(*read_cookies)(TSRMLS_D);
void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);
- void (*log_message)(char *message);
- time_t (*get_request_time)(TSRMLS_D);
+ void (*log_message)(char *message TSRMLS_DC);
+ double (*get_request_time)(TSRMLS_D);
void (*terminate_process)(TSRMLS_D);
char *php_ini_path_override;
@@ -250,6 +253,7 @@ struct _sapi_module_struct {
char *executable_location;
int php_ini_ignore;
+ int php_ini_ignore_cwd; /* don't look for php.ini in the current directory */
int (*get_fd)(int *fd TSRMLS_DC);
diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
index 1ea07e1f13..9d4a8a85c2 100644
--- a/main/fopen_wrappers.c
+++ b/main/fopen_wrappers.c
@@ -39,7 +39,6 @@
#include <sys/param.h>
#endif
-#include "safe_mode.h"
#include "ext/standard/head.h"
#include "ext/standard/php_standard.h"
#include "zend_compile.h"
@@ -338,55 +337,6 @@ PHPAPI int php_check_open_basedir_ex(const char *path, int warn TSRMLS_DC)
}
/* }}} */
-/* {{{ php_check_safe_mode_include_dir
- */
-PHPAPI int php_check_safe_mode_include_dir(const char *path TSRMLS_DC)
-{
- if (PG(safe_mode)) {
- if (PG(safe_mode_include_dir) && *PG(safe_mode_include_dir)) {
- char *pathbuf;
- char *ptr;
- char *end;
- char resolved_name[MAXPATHLEN];
-
- /* Resolve the real path into resolved_name */
- if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
- return -1;
- }
- pathbuf = estrdup(PG(safe_mode_include_dir));
- ptr = pathbuf;
-
- while (ptr && *ptr) {
- end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
- if (end != NULL) {
- *end = '\0';
- end++;
- }
-
- /* Check the path */
-#ifdef PHP_WIN32
- if (strncasecmp(ptr, resolved_name, strlen(ptr)) == 0)
-#else
- if (strncmp(ptr, resolved_name, strlen(ptr)) == 0)
-#endif
- {
- /* File is in the right directory */
- efree(pathbuf);
- return 0;
- }
-
- ptr = end;
- }
- efree(pathbuf);
- }
- return -1;
- }
-
- /* Nothing to check... */
- return 0;
-}
-/* }}} */
-
/* {{{ php_fopen_and_set_opened_path
*/
static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, char **opened_path TSRMLS_DC)
@@ -398,7 +348,7 @@ static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, c
}
fp = VCWD_FOPEN(path, mode);
if (fp && opened_path) {
- *opened_path = expand_filepath(path, NULL TSRMLS_CC);
+ *opened_path = expand_filepath_with_mode(path, NULL, NULL, 0, CWD_EXPAND TSRMLS_CC);
}
return fp;
}
@@ -408,14 +358,11 @@ static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, c
*/
PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC)
{
- FILE *fp;
-#ifndef PHP_WIN32
- struct stat st;
-#endif
char *path_info;
char *filename = NULL;
char *resolved_path = NULL;
int length;
+ zend_bool orig_display_errors;
path_info = SG(request_info).request_uri;
#if HAVE_PWD_H
@@ -496,17 +443,12 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC)
SG(request_info).path_translated = NULL;
return FAILURE;
}
- fp = VCWD_FOPEN(resolved_path, "rb");
+ efree(resolved_path);
-#ifndef PHP_WIN32
- /* refuse to open anything that is not a regular file */
- if (fp && (0 > fstat(fileno(fp), &st) || !S_ISREG(st.st_mode))) {
- fclose(fp);
- fp = NULL;
- }
-#endif
-
- if (!fp) {
+ orig_display_errors = PG(display_errors);
+ PG(display_errors) = 0;
+ if (zend_stream_open(filename, file_handle TSRMLS_CC) == FAILURE) {
+ PG(display_errors) = orig_display_errors;
if (SG(request_info).path_translated != filename) {
STR_FREE(filename);
}
@@ -514,19 +456,13 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC)
SG(request_info).path_translated = NULL;
return FAILURE;
}
-
- file_handle->opened_path = resolved_path;
+ PG(display_errors) = orig_display_errors;
if (SG(request_info).path_translated != filename) {
STR_FREE(SG(request_info).path_translated); /* for same reason as above */
SG(request_info).path_translated = filename;
}
- file_handle->filename = SG(request_info).path_translated;
- file_handle->free_filename = 0;
- file_handle->handle.fp = fp;
- file_handle->type = ZEND_HANDLE_FP;
-
return SUCCESS;
}
/* }}} */
@@ -542,11 +478,7 @@ PHPAPI char *php_resolve_path(const char *filename, int filename_length, const c
char *actual_path;
php_stream_wrapper *wrapper;
- if (!filename) {
- return NULL;
- }
-
- if (strlen(filename) != filename_length) {
+ if (!filename || CHECK_NULL_PATH(filename, filename_length)) {
return NULL;
}
@@ -633,7 +565,7 @@ PHPAPI char *php_resolve_path(const char *filename, int filename_length, const c
/* check in calling scripts' current working directory as a fall back case
*/
if (zend_is_executing(TSRMLS_C)) {
- char *exec_fname = zend_get_executed_filename(TSRMLS_C);
+ const char *exec_fname = zend_get_executed_filename(TSRMLS_C);
int exec_fname_length = strlen(exec_fname);
while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
@@ -679,9 +611,8 @@ PHPAPI char *php_resolve_path(const char *filename, int filename_length, const c
PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const char *path, char **opened_path TSRMLS_DC)
{
char *pathbuf, *ptr, *end;
- char *exec_fname;
+ const char *exec_fname;
char trypath[MAXPATHLEN];
- struct stat sb;
FILE *fp;
int path_length;
int filename_length;
@@ -698,34 +629,11 @@ PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const c
filename_length = strlen(filename);
/* Relative path open */
- if (*filename == '.') {
- if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
- return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
- }
-
- /*
- * files in safe_mode_include_dir (or subdir) are excluded from
- * safe mode GID/UID checks
- */
-
+ if ((*filename == '.')
/* Absolute path open */
- if (IS_ABSOLUTE_PATH(filename, filename_length)) {
- if (php_check_safe_mode_include_dir(filename TSRMLS_CC) == 0) {
- /* filename is in safe_mode_include_dir (or subdir) */
- return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
- }
- if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
- return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
- }
-
- if (!path || (path && !*path)) {
- if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
+ || IS_ABSOLUTE_PATH(filename, filename_length)
+ || (!path || (path && !*path))
+ ) {
return php_fopen_and_set_opened_path(filename, mode, opened_path TSRMLS_CC);
}
@@ -764,21 +672,6 @@ PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const c
if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN);
}
- if (PG(safe_mode)) {
- if (VCWD_STAT(trypath, &sb) == 0) {
- /* file exists ... check permission */
- if (php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0 ||
- php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM)
- ) {
- /* UID ok, or trypath is in safe_mode_include_dir */
- fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC);
- } else {
- fp = NULL;
- }
- efree(pathbuf);
- return fp;
- }
- }
fp = php_fopen_and_set_opened_path(trypath, mode, opened_path TSRMLS_CC);
if (fp) {
efree(pathbuf);
@@ -844,6 +737,14 @@ PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC)
*/
PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len TSRMLS_DC)
{
+ return expand_filepath_with_mode(filepath, real_path, relative_to, relative_to_len, CWD_FILEPATH TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ expand_filepath_use_realpath
+ */
+PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode TSRMLS_DC)
+{
cwd_state new_state;
char cwd[MAXPATHLEN];
int copy_len;
@@ -888,7 +789,7 @@ PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const cha
new_state.cwd = strdup(cwd);
new_state.cwd_length = strlen(cwd);
- if (virtual_file_ex(&new_state, filepath, NULL, CWD_FILEPATH)) {
+ if (virtual_file_ex(&new_state, filepath, NULL, realpath_mode TSRMLS_CC)) {
free(new_state.cwd);
return NULL;
}
diff --git a/main/fopen_wrappers.h b/main/fopen_wrappers.h
index 8f48a1c2f5..6dcc6e1ccc 100644
--- a/main/fopen_wrappers.h
+++ b/main/fopen_wrappers.h
@@ -28,13 +28,14 @@ BEGIN_EXTERN_C()
PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC);
PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC);
PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len TSRMLS_DC);
+PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode TSRMLS_DC);
PHPAPI int php_check_open_basedir(const char *path TSRMLS_DC);
PHPAPI int php_check_open_basedir_ex(const char *path, int warn TSRMLS_DC);
PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path TSRMLS_DC);
/* {{{ OPENBASEDIR_CHECKPATH(filename) to ease merge between 6.x and 5.x */
-#if (PHP_MAJOR_VERSION < 6)
+#if PHP_API_VERSION < 20100412
# define OPENBASEDIR_CHECKPATH(filename) \
(PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)
#else
diff --git a/main/main.c b/main/main.c
index 631a6a9fea..44c61c6005 100644
--- a/main/main.c
+++ b/main/main.c
@@ -82,6 +82,7 @@
#include "zend_indent.h"
#include "zend_extensions.h"
#include "zend_ini.h"
+#include "zend_dtrace.h"
#include "php_content_types.h"
#include "php_ticks.h"
@@ -125,9 +126,9 @@ PHPAPI int core_globals_id;
#ifdef PHP_WIN32
#include "win32_internal_function_disabled.h"
-static php_win32_disable_functions() {
+static php_win32_disable_functions(TSRMLS_D)
+{
int i;
- TSRMLS_FETCH();
if (EG(windows_version_info).dwMajorVersion < 5) {
for (i = 0; i < function_name_cnt_5; i++) {
@@ -254,6 +255,57 @@ static void php_disable_classes(TSRMLS_D)
}
/* }}} */
+/* {{{ php_binary_init
+ */
+static void php_binary_init(TSRMLS_D)
+{
+ char *binary_location;
+#ifdef PHP_WIN32
+ binary_location = (char *)malloc(MAXPATHLEN);
+ if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
+ free(binary_location);
+ PG(php_binary) = NULL;
+ }
+#else
+ if (sapi_module.executable_location) {
+ binary_location = (char *)malloc(MAXPATHLEN);
+ if (!strchr(sapi_module.executable_location, '/')) {
+ char *envpath, *path;
+ int found = 0;
+
+ if ((envpath = getenv("PATH")) != NULL) {
+ char *search_dir, search_path[MAXPATHLEN];
+ char *last = NULL;
+
+ path = estrdup(envpath);
+ search_dir = php_strtok_r(path, ":", &last);
+
+ while (search_dir) {
+ snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
+ if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK)) {
+ found = 1;
+ break;
+ }
+ search_dir = php_strtok_r(NULL, ":", &last);
+ }
+ efree(path);
+ }
+ if (!found) {
+ free(binary_location);
+ binary_location = NULL;
+ }
+ } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
+ free(binary_location);
+ binary_location = NULL;
+ }
+ } else {
+ binary_location = NULL;
+ }
+#endif
+ PG(php_binary) = binary_location;
+}
+/* }}} */
+
/* {{{ PHP_INI_MH
*/
static PHP_INI_MH(OnUpdateTimeout)
@@ -365,14 +417,9 @@ static PHP_INI_MH(OnUpdateErrorLog)
{
/* Only do the safemode/open_basedir check at runtime */
if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value && strcmp(new_value, "syslog")) {
- if (PG(safe_mode) && (!php_checkuid(new_value, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return FAILURE;
- }
-
if (PG(open_basedir) && php_check_open_basedir(new_value TSRMLS_CC)) {
return FAILURE;
}
-
}
OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
return SUCCESS;
@@ -385,14 +432,9 @@ static PHP_INI_MH(OnUpdateMailLog)
{
/* Only do the safemode/open_basedir check at runtime */
if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) {
- if (PG(safe_mode) && (!php_checkuid(new_value, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return FAILURE;
- }
-
if (PG(open_basedir) && php_check_open_basedir(new_value TSRMLS_CC)) {
return FAILURE;
}
-
}
OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
return SUCCESS;
@@ -414,10 +456,8 @@ static PHP_INI_MH(OnChangeMailForceExtra)
/* defined in browscap.c */
PHP_INI_MH(OnChangeBrowscap);
-/* Need to convert to strings and make use of:
- * PHP_SAFE_MODE
- *
- * Need to be read from the environment (?):
+
+/* Need to be read from the environment (?):
* PHP_AUTO_PREPEND_FILE
* PHP_AUTO_APPEND_FILE
* PHP_DOCUMENT_ROOT
@@ -425,10 +465,6 @@ PHP_INI_MH(OnChangeBrowscap);
* PHP_INCLUDE_PATH
*/
-#ifndef PHP_SAFE_MODE_EXEC_DIR
-# define PHP_SAFE_MODE_EXEC_DIR ""
-#endif
-
/* Windows and Netware use the internal mail */
#if defined(PHP_WIN32) || defined(NETWARE)
# define DEFAULT_SENDMAIL_PATH NULL
@@ -441,15 +477,12 @@ PHP_INI_MH(OnChangeBrowscap);
/* {{{ PHP_INI
*/
PHP_INI_BEGIN()
- PHP_INI_ENTRY_EX("define_syslog_variables", "0", PHP_INI_ALL, NULL, php_ini_boolean_displayer_cb)
- PHP_INI_ENTRY_EX("highlight.bg", HL_BG_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.comment", HL_COMMENT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.default", HL_DEFAULT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.html", HL_HTML_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.keyword", HL_KEYWORD_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.string", HL_STRING_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
- STD_PHP_INI_BOOLEAN("allow_call_time_pass_reference", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, allow_call_time_pass_reference, zend_compiler_globals, compiler_globals)
STD_PHP_INI_BOOLEAN("asp_tags", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, asp_tags, zend_compiler_globals, compiler_globals)
STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
STD_PHP_INI_BOOLEAN("display_startup_errors", "0", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals)
@@ -469,26 +502,13 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("ignore_repeated_source", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_source, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateBool, report_memleaks, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("report_zend_debug", "1", PHP_INI_ALL, OnUpdateBool, report_zend_debug, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("magic_quotes_gpc", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, magic_quotes_gpc, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("magic_quotes_runtime", "0", PHP_INI_ALL, OnUpdateBool, magic_quotes_runtime, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("magic_quotes_sybase", "0", PHP_INI_ALL, OnUpdateBool, magic_quotes_sybase, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateLong, output_buffering, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, output_handler, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("register_globals", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_globals, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("register_long_arrays", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_long_arrays, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
-#if PHP_SAFE_MODE
- STD_PHP_INI_BOOLEAN("safe_mode", "1", PHP_INI_SYSTEM, OnUpdateBool, safe_mode, php_core_globals, core_globals)
-#else
- STD_PHP_INI_BOOLEAN("safe_mode", "0", PHP_INI_SYSTEM, OnUpdateBool, safe_mode, php_core_globals, core_globals)
-#endif
- STD_PHP_INI_ENTRY("safe_mode_include_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, safe_mode_include_dir, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("safe_mode_gid", "0", PHP_INI_SYSTEM, OnUpdateBool, safe_mode_gid, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals)
STD_PHP_INI_BOOLEAN("sql.safe_mode", "0", PHP_INI_SYSTEM, OnUpdateBool, sql_safe_mode, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("track_errors", "0", PHP_INI_ALL, OnUpdateBool, track_errors, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("y2k_compliance", "1", PHP_INI_ALL, OnUpdateBool, y2k_compliance, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("serialize_precision", "17", PHP_INI_ALL, OnUpdateLongGEZero, serialize_precision, php_core_globals, core_globals)
@@ -505,7 +525,6 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
- STD_PHP_INI_ENTRY("safe_mode_exec_dir", PHP_SAFE_MODE_EXEC_DIR, PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals)
@@ -533,10 +552,11 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra)
PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
- PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM, NULL)
+ PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
+ STD_PHP_INI_BOOLEAN("enable_post_data_reading", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, enable_post_data_reading, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("always_populate_raw_post_data", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, always_populate_raw_post_data, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
@@ -571,6 +591,14 @@ static int php_during_module_shutdown(void)
}
/* }}} */
+/* {{{ php_get_module_initialized
+ */
+PHPAPI int php_get_module_initialized(void)
+{
+ return module_initialized;
+}
+/* }}} */
+
/* {{{ php_log_err
*/
PHPAPI void php_log_err(char *log_message TSRMLS_DC)
@@ -613,7 +641,7 @@ PHPAPI void php_log_err(char *log_message TSRMLS_DC)
#ifdef PHP_WIN32
php_flock(fd, 2);
#endif
- write(fd, tmp, len);
+ php_ignore_value(write(fd, tmp, len));
efree(tmp);
efree(error_time_str);
close(fd);
@@ -625,7 +653,7 @@ PHPAPI void php_log_err(char *log_message TSRMLS_DC)
/* Otherwise fall back to the default logging location, if we have one */
if (sapi_module.log_message) {
- sapi_module.log_message(log_message);
+ sapi_module.log_message(log_message TSRMLS_CC);
}
PG(in_error_log) = 0;
}
@@ -671,9 +699,9 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c
char *docref_target = "", *docref_root = "";
char *p;
int buffer_len = 0;
- char *space = "";
- char *class_name = "";
- char *function;
+ const char *space = "";
+ const char *class_name = "";
+ const char *function;
int origin_len;
char *origin;
char *message;
@@ -681,8 +709,9 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c
/* get error text into buffer and escape for html if necessary */
buffer_len = vspprintf(&buffer, 0, format, args);
+
if (PG(html_errors)) {
- int len;
+ size_t len;
char *replace = php_escape_html_entities(buffer, buffer_len, &len, 0, ENT_COMPAT, NULL TSRMLS_CC);
efree(buffer);
buffer = replace;
@@ -698,7 +727,7 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c
EG(current_execute_data)->opline &&
EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
) {
- switch (EG(current_execute_data)->opline->op2.u.constant.value.lval) {
+ switch (EG(current_execute_data)->opline->extended_value) {
case ZEND_EVAL:
function = "eval";
is_function = 1;
@@ -740,7 +769,7 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c
}
if (PG(html_errors)) {
- int len;
+ size_t len;
char *replace = php_escape_html_entities(origin, origin_len, &len, 0, ENT_COMPAT, NULL TSRMLS_CC);
efree(origin);
origin = replace;
@@ -767,10 +796,10 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c
}
/* we have a docref for a function AND
- * - we show erroes in html mode OR
- * - the user wants to see the links anyway
+ * - we show errors in html mode AND
+ * - the user wants to see the links
*/
- if (docref && is_function && (PG(html_errors) || strlen(PG(docref_root)))) {
+ if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
if (strncmp(docref, "http://", 7)) {
/* We don't have 'http://' so we use docref_root */
@@ -932,6 +961,9 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
/* store the error if it has changed */
if (display) {
+#ifdef ZEND_SIGNALS
+ HANDLE_BLOCK_INTERRUPTIONS();
+#endif
if (PG(last_error_message)) {
free(PG(last_error_message));
PG(last_error_message) = NULL;
@@ -940,6 +972,9 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
free(PG(last_error_file));
PG(last_error_file) = NULL;
}
+#ifdef ZEND_SIGNALS
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+#endif
if (!error_filename) {
error_filename = "Unknown";
}
@@ -1032,14 +1067,7 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
efree(log_buffer);
}
- if (PG(display_errors)
- && ((module_initialized && !PG(during_request_startup))
- || (PG(display_startup_errors)
- && (OG(php_body_write)==php_default_output_func || OG(php_body_write)==php_ub_body_write_no_header || OG(php_body_write)==php_ub_body_write)
- )
- )
- ) {
-
+ if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
if (PG(xmlrpc_errors)) {
php_printf("<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>%ld</int></value></member><member><name>faultString</name><value><string>%s:%s in %s on line %d</string></value></member></struct></value></fault></methodResponse>", PG(xmlrpc_error_number), error_type_str, buffer, error_filename, error_lineno);
} else {
@@ -1047,8 +1075,8 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
char *append_string = INI_STR("error_append_string");
if (PG(html_errors)) {
- if (type == E_ERROR) {
- int len;
+ if (type == E_ERROR || type == E_PARSE) {
+ size_t len;
char *buf = php_escape_html_entities(buffer, buffer_len, &len, 0, ENT_COMPAT, NULL TSRMLS_CC);
php_printf("%s<br />\n<b>%s</b>: %s in <b>%s</b> on line <b>%d</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, buf, error_filename, error_lineno, STR_PRINT(append_string));
efree(buf);
@@ -1061,7 +1089,7 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
) {
#ifdef PHP_WIN32
- fprintf(stderr, "%s: %s in %s on line%d\n", error_type_str, buffer, error_filename, error_lineno);
+ fprintf(stderr, "%s: %s in %s on line %d\n", error_type_str, buffer, error_filename, error_lineno);
fflush(stderr);
#else
fprintf(stderr, "%s: %s in %s on line %d\n", error_type_str, buffer, error_filename, error_lineno);
@@ -1114,11 +1142,13 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
sapi_header_line ctr = {0};
ctr.line = "HTTP/1.0 500 Internal Server Error";
- ctr.line_len = strlen(ctr.line);
+ ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
}
/* the parser would return 1 (failure), we can bail out nicely */
- if (type != E_PARSE) {
+ if (type == E_PARSE) {
+ CG(parse_error) = 0;
+ } else {
/* restore memory limit */
zend_set_memory_limit(PG(memory_limit));
efree(buffer);
@@ -1152,6 +1182,69 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
}
/* }}} */
+/* {{{ php_get_current_user
+ */
+PHPAPI char *php_get_current_user(TSRMLS_D)
+{
+ struct stat *pstat;
+
+ if (SG(request_info).current_user) {
+ return SG(request_info).current_user;
+ }
+
+ /* FIXME: I need to have this somehow handled if
+ USE_SAPI is defined, because cgi will also be
+ interfaced in USE_SAPI */
+
+ pstat = sapi_get_stat(TSRMLS_C);
+
+ if (!pstat) {
+ return "";
+ } else {
+#ifdef PHP_WIN32
+ char name[256];
+ DWORD len = sizeof(name)-1;
+
+ if (!GetUserName(name, &len)) {
+ return "";
+ }
+ name[len] = '\0';
+ SG(request_info).current_user_length = len;
+ SG(request_info).current_user = estrndup(name, len);
+ return SG(request_info).current_user;
+#else
+ struct passwd *pwd;
+#if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
+ struct passwd _pw;
+ struct passwd *retpwptr = NULL;
+ int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+ char *pwbuf;
+
+ if (pwbuflen < 1) {
+ return "";
+ }
+ pwbuf = emalloc(pwbuflen);
+ if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
+ efree(pwbuf);
+ return "";
+ }
+ pwd = &_pw;
+#else
+ if ((pwd=getpwuid(pstat->st_uid))==NULL) {
+ return "";
+ }
+#endif
+ SG(request_info).current_user_length = strlen(pwd->pw_name);
+ SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
+#if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
+ efree(pwbuf);
+#endif
+ return SG(request_info).current_user;
+#endif
+ }
+}
+/* }}} */
+
/* {{{ proto bool set_time_limit(int seconds)
Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)
@@ -1160,11 +1253,6 @@ PHP_FUNCTION(set_time_limit)
char *new_timeout_str;
int new_timeout_strlen;
- if (PG(safe_mode)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot set time limit in safe mode");
- RETURN_FALSE;
- }
-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &new_timeout) == FAILURE) {
return;
}
@@ -1184,7 +1272,7 @@ PHP_FUNCTION(set_time_limit)
*/
static FILE *php_fopen_wrapper_for_zend(const char *filename, char **opened_path TSRMLS_DC)
{
- return php_stream_open_wrapper_as_file((char *)filename, "rb", ENFORCE_SAFE_MODE|USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE, opened_path);
+ return php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE, opened_path);
}
/* }}} */
@@ -1213,7 +1301,7 @@ static size_t php_zend_stream_fsizer(void *handle TSRMLS_DC) /* {{{ */
static int php_stream_open_for_zend(const char *filename, zend_file_handle *handle TSRMLS_DC) /* {{{ */
{
- return php_stream_open_for_zend_ex(filename, handle, ENFORCE_SAFE_MODE|USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
+ return php_stream_open_for_zend_ex(filename, handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
}
/* }}} */
@@ -1283,7 +1371,7 @@ static int php_get_configuration_directive_for_zend(const char *name, uint name_
/* {{{ php_message_handler_for_zend
*/
-static void php_message_handler_for_zend(long message, void *data TSRMLS_DC)
+static void php_message_handler_for_zend(long message, const void *data TSRMLS_DC)
{
switch (message) {
case ZMSG_FAILED_INCLUDE_FOPEN:
@@ -1377,8 +1465,12 @@ void php_on_timeout(int seconds TSRMLS_DC)
*/
static void sigchld_handler(int apar)
{
+ int errno_save = errno;
+
while (waitpid(-1, NULL, WNOHANG) > 0);
signal(SIGCHLD, sigchld_handler);
+
+ errno = errno_save;
}
/* }}} */
#endif
@@ -1420,6 +1512,10 @@ int php_request_startup(TSRMLS_D)
{
int retval = SUCCESS;
+#ifdef HAVE_DTRACE
+ DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), SAFE_FILENAME(SG(request_info).request_method));
+#endif /* HAVE_DTRACE */
+
#ifdef PHP_WIN32
PG(com_initialized) = 0;
#endif
@@ -1443,14 +1539,18 @@ int php_request_startup(TSRMLS_D)
zend_activate(TSRMLS_C);
sapi_activate(TSRMLS_C);
+#ifdef ZEND_SIGNALS
+ zend_signal_activate(TSRMLS_C);
+#endif
+
if (PG(max_input_time) == -1) {
zend_set_timeout(EG(timeout_seconds), 1);
} else {
zend_set_timeout(PG(max_input_time), 1);
}
- /* Disable realpath cache if safe_mode or open_basedir are set */
- if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
+ /* Disable realpath cache if an open_basedir is set */
+ if (PG(open_basedir) && *PG(open_basedir)) {
CWDG(realpath_cache_size_limit) = 0;
}
@@ -1459,15 +1559,16 @@ int php_request_startup(TSRMLS_D)
}
if (PG(output_handler) && PG(output_handler)[0]) {
- php_start_ob_buffer_named(PG(output_handler), 0, 1 TSRMLS_CC);
+ zval *oh;
+
+ MAKE_STD_ZVAL(oh);
+ ZVAL_STRING(oh, PG(output_handler), 1);
+ php_output_start_user(oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
+ zval_ptr_dtor(&oh);
} else if (PG(output_buffering)) {
- if (PG(output_buffering)>1) {
- php_start_ob_buffer(NULL, PG(output_buffering), 1 TSRMLS_CC);
- } else {
- php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
- }
+ php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
} else if (PG(implicit_flush)) {
- php_start_implicit_flush(TSRMLS_C);
+ php_output_set_implicit_flush(1 TSRMLS_CC);
}
/* We turn this off in php_execute_script() */
@@ -1503,7 +1604,6 @@ int php_request_startup(TSRMLS_D)
zend_try {
PG(during_request_startup) = 1;
- php_output_activate(TSRMLS_C);
if (PG(expose_php)) {
sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
}
@@ -1547,6 +1647,7 @@ void php_request_shutdown_for_exec(void *dummy)
/* used to close fd's in the 3..255 range here, but it's problematic
*/
shutdown_memory_manager(1, 1 TSRMLS_CC);
+ zend_interned_strings_restore(TSRMLS_C);
}
/* }}} */
@@ -1566,6 +1667,10 @@ void php_request_shutdown_for_hook(void *dummy)
}
zend_try {
+ zend_unset_timeout(TSRMLS_C);
+ } zend_end_try();
+
+ zend_try {
int i;
for (i = 0; i < NUM_TRACK_VARS; i++) {
@@ -1589,9 +1694,13 @@ void php_request_shutdown_for_hook(void *dummy)
shutdown_memory_manager(CG(unclean_shutdown), 0 TSRMLS_CC);
} zend_end_try();
+ zend_interned_strings_restore(TSRMLS_C);
+
+#ifdef ZEND_SIGNALS
zend_try {
- zend_unset_timeout(TSRMLS_C);
+ zend_signal_deactivate(TSRMLS_C);
} zend_end_try();
+#endif
}
/* }}} */
@@ -1626,16 +1735,23 @@ void php_request_shutdown(void *dummy)
/* 3. Flush all output buffers */
zend_try {
zend_bool send_buffer = SG(request_info).headers_only ? 0 : 1;
+
if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR &&
- OG(ob_nesting_level) && !OG(active_ob_buffer).chunk_size && PG(memory_limit) < zend_memory_usage(1 TSRMLS_CC)) {
+ (size_t)PG(memory_limit) < zend_memory_usage(1 TSRMLS_CC)
+ ) {
send_buffer = 0;
}
- php_end_ob_buffers(send_buffer TSRMLS_CC);
+
+ if (!send_buffer) {
+ php_output_discard_all(TSRMLS_C);
+ } else {
+ php_output_end_all(TSRMLS_C);
+ }
} zend_end_try();
- /* 4. Send the set HTTP headers (note: This must be done AFTER php_end_ob_buffers() !!) */
+ /* 4. Reset max_execution_time (no longer executing php code after response sent) */
zend_try {
- sapi_send_headers(TSRMLS_C);
+ zend_unset_timeout(TSRMLS_C);
} zend_end_try();
/* 5. Call all extensions RSHUTDOWN functions */
@@ -1644,7 +1760,12 @@ void php_request_shutdown(void *dummy)
php_free_shutdown_functions(TSRMLS_C);
}
- /* 6. Destroy super-globals */
+ /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
+ zend_try {
+ php_output_deactivate(TSRMLS_C);
+ } zend_end_try();
+
+ /* 7. Destroy super-globals */
zend_try {
int i;
@@ -1655,7 +1776,7 @@ void php_request_shutdown(void *dummy)
}
} zend_end_try();
- /* 6.5 free last error information */
+ /* 7.5 free last error information */
if (PG(last_error_message)) {
free(PG(last_error_message));
PG(last_error_message) = NULL;
@@ -1687,6 +1808,7 @@ void php_request_shutdown(void *dummy)
zend_try {
shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0 TSRMLS_CC);
} zend_end_try();
+ zend_interned_strings_restore(TSRMLS_C);
/* 12. Reset max_execution_time */
zend_try {
@@ -1699,6 +1821,10 @@ void php_request_shutdown(void *dummy)
PG(com_initialized) = 0;
}
#endif
+
+#ifdef HAVE_DTRACE
+ DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), SAFE_FILENAME(SG(request_info).request_method));
+#endif /* HAVE_DTRACE */
}
/* }}} */
@@ -1716,12 +1842,12 @@ PHPAPI void php_com_initialize(TSRMLS_D)
}
/* }}} */
-/* {{{ php_body_write_wrapper
+/* {{{ php_output_wrapper
*/
-static int php_body_write_wrapper(const char *str, uint str_length)
+static int php_output_wrapper(const char *str, uint str_length)
{
TSRMLS_FETCH();
- return php_body_write(str, str_length TSRMLS_CC);
+ return php_output_write(str, str_length TSRMLS_CC);
}
/* }}} */
@@ -1753,6 +1879,9 @@ static void core_globals_dtor(php_core_globals *core_globals TSRMLS_DC)
if (core_globals->disable_classes) {
free(core_globals->disable_classes);
}
+ if (core_globals->php_binary) {
+ free(core_globals->php_binary);
+ }
php_shutdown_ticks(TSRMLS_C);
}
@@ -1784,7 +1913,7 @@ int php_register_extensions(zend_module_entry **ptr, int count TSRMLS_DC)
}
/* }}} */
-#if defined(PHP_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1400)
+#if defined(PHP_WIN32) && _MSC_VER >= 1400
static _invalid_parameter_handler old_invalid_parameter_handler;
void dummy_invalid_parameter_handler(
@@ -1824,7 +1953,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
{
zend_utility_functions zuf;
zend_utility_values zuv;
- int module_number=0; /* for REGISTER_INI_ENTRIES() */
+ int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */
char *php_os;
zend_module_entry *module;
#ifdef ZTS
@@ -1832,19 +1961,14 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
void ***tsrm_ls;
php_core_globals *core_globals;
#endif
+
#if defined(PHP_WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
WORD wVersionRequested = MAKEWORD(2, 0);
WSADATA wsaData;
#endif
#ifdef PHP_WIN32
- DWORD dwVersion = GetVersion();
- /* Get build numbers for Windows NT or Win95 */
- if (dwVersion < 0x80000000){
- php_os="WINNT";
- } else {
- php_os="WIN32";
- }
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+ php_os = "WINNT";
+#if _MSC_VER >= 1400
old_invalid_parameter_handler =
_set_invalid_parameter_handler(dummy_invalid_parameter_handler);
if (old_invalid_parameter_handler != NULL) {
@@ -1881,7 +2005,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
zuf.error_function = php_error_cb;
zuf.printf_function = php_printf;
- zuf.write_function = php_body_write_wrapper;
+ zuf.write_function = php_output_wrapper;
zuf.fopen_function = php_fopen_wrapper_for_zend;
zuf.message_handler = php_message_handler_for_zend;
zuf.block_interruptions = sapi_module.block_interruptions;
@@ -1991,11 +2115,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
-#ifdef ZEND_MULTIBYTE
- REGISTER_MAIN_LONG_CONSTANT("ZEND_MULTIBYTE", 1, CONST_PERSISTENT | CONST_CS);
-#else
- REGISTER_MAIN_LONG_CONSTANT("ZEND_MULTIBYTE", 0, CONST_PERSISTENT | CONST_CS);
-#endif
#ifdef PHP_WIN32
REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MAJOR", EG(windows_version_info).dwMajorVersion, CONST_PERSISTENT | CONST_CS);
@@ -2011,6 +2130,13 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_WORKSTATION", VER_NT_WORKSTATION, CONST_PERSISTENT | CONST_CS);
#endif
+ php_binary_init(TSRMLS_C);
+ if (PG(php_binary)) {
+ REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", PG(php_binary), strlen(PG(php_binary)), CONST_PERSISTENT | CONST_CS);
+ } else {
+ REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS);
+ }
+
php_output_register_constants(TSRMLS_C);
php_rfc1867_register_constants(TSRMLS_C);
@@ -2027,8 +2153,8 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
/* Register Zend ini entries */
zend_register_standard_ini_entries(TSRMLS_C);
- /* Disable realpath cache if safe_mode or open_basedir are set */
- if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
+ /* Disable realpath cache if an open_basedir is set */
+ if (PG(open_basedir) && *PG(open_basedir)) {
CWDG(realpath_cache_size_limit) = 0;
}
@@ -2076,6 +2202,8 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
/* start Zend extensions */
zend_startup_extensions();
+ zend_collect_module_handlers(TSRMLS_C);
+
/* register additional functions */
if (sapi_module.additional_functions) {
if (zend_hash_find(&module_registry, "standard", sizeof("standard"), (void**)&module)==SUCCESS) {
@@ -2098,7 +2226,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
#ifdef PHP_WIN32
/* Disable incompatible functions for the running platform */
- if (php_win32_disable_functions() == FAILURE) {
+ if (php_win32_disable_functions(TSRMLS_C) == FAILURE) {
php_printf("Unable to disable unsupported functions\n");
return FAILURE;
}
@@ -2111,41 +2239,74 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
module_initialized = 1;
/* Check for deprecated directives */
- /* NOTE: If you add anything here, remember to add it also in Makefile.global! */
+ /* NOTE: If you add anything here, remember to add it to Makefile.global! */
{
- static const char *directives[] = {
- "define_syslog_variables",
- "register_globals",
- "register_long_arrays",
- "safe_mode",
- "magic_quotes_gpc",
- "magic_quotes_runtime",
- "magic_quotes_sybase",
- NULL
+ struct {
+ const long error_level;
+ const char *phrase;
+ const char *directives[16]; /* Remember to change this if the number of directives change */
+ } directives[2] = {
+ {
+ E_DEPRECATED,
+ "Directive '%s' is deprecated in PHP 5.3 and greater",
+ {
+ NULL
+ }
+ },
+ {
+ E_CORE_ERROR,
+ "Directive '%s' is no longer available in PHP",
+ {
+ "allow_call_time_pass_reference",
+ "define_syslog_variables",
+ "highlight.bg",
+ "magic_quotes_gpc",
+ "magic_quotes_runtime",
+ "magic_quotes_sybase",
+ "register_globals",
+ "register_long_arrays",
+ "safe_mode",
+ "safe_mode_gid",
+ "safe_mode_include_dir",
+ "safe_mode_exec_dir",
+ "safe_mode_allowed_env_vars",
+ "safe_mode_protected_env_vars",
+ "zend.ze1_compatibility_mode",
+ NULL
+ }
+ }
};
- const char **p = directives;
- long val;
- while (*p) {
- if (cfg_get_long((char*)*p, &val) == SUCCESS && val) {
- zend_error(E_DEPRECATED, "Directive '%s' is deprecated in PHP 5.3 and greater", *p);
- }
- ++p;
- }
+ unsigned int i;
+
+ zend_try {
+ /* 2 = Count of deprecation structs */
+ for (i = 0; i < 2; i++) {
+ const char **p = directives[i].directives;
- /* This is not too nice, but since its the only one theres no need for extra stuff here */
- if (cfg_get_long("zend.ze1_compatibility_mode", &val) == SUCCESS && val) {
- zend_error(E_CORE_ERROR, "zend.ze1_compatibility_mode is no longer supported in PHP 5.3 and greater");
- }
+ while(*p) {
+ long value;
+
+ if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
+ zend_error(directives[i].error_level, directives[i].phrase, *p);
+ }
+
+ ++p;
+ }
+ }
+ } zend_catch {
+ retval = FAILURE;
+ } zend_end_try();
}
sapi_deactivate(TSRMLS_C);
module_startup = 0;
shutdown_memory_manager(1, 0 TSRMLS_CC);
+ zend_interned_strings_snapshot(TSRMLS_C);
/* we're done */
- return SUCCESS;
+ return retval;
}
/* }}} */
@@ -2205,17 +2366,22 @@ void php_module_shutdown(TSRMLS_D)
#ifndef ZTS
zend_ini_shutdown(TSRMLS_C);
shutdown_memory_manager(CG(unclean_shutdown), 1 TSRMLS_CC);
- core_globals_dtor(&core_globals TSRMLS_CC);
- gc_globals_dtor(TSRMLS_C);
#else
zend_ini_global_shutdown(TSRMLS_C);
- ts_free_id(core_globals_id);
#endif
+ php_output_shutdown();
php_shutdown_temporary_directory();
module_initialized = 0;
+#ifndef ZTS
+ core_globals_dtor(&core_globals TSRMLS_CC);
+ gc_globals_dtor(TSRMLS_C);
+#else
+ ts_free_id(core_globals_id);
+#endif
+
#if defined(PHP_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1400)
if (old_invalid_parameter_handler == NULL) {
_set_invalid_parameter_handler(old_invalid_parameter_handler);
@@ -2265,7 +2431,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
/* this looks nasty to me */
old_cwd_fd = open(".", 0);
#else
- VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1);
+ php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
#endif
VCWD_CHDIR_FILE(primary_file->filename);
}
@@ -2324,7 +2490,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
}
#else
if (old_cwd[0] != '\0') {
- VCWD_CHDIR(old_cwd);
+ php_ignore_value(VCWD_CHDIR(old_cwd));
}
free_alloca(old_cwd, use_heap);
#endif
@@ -2354,14 +2520,14 @@ PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval **ret
PG(during_request_startup) = 0;
if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
- VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1);
+ php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
VCWD_CHDIR_FILE(primary_file->filename);
}
zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, ret, 1, primary_file);
} zend_end_try();
if (old_cwd[0] != '\0') {
- VCWD_CHDIR(old_cwd);
+ php_ignore_value(VCWD_CHDIR(old_cwd));
}
free_alloca(old_cwd, use_heap);
@@ -2376,7 +2542,7 @@ PHPAPI void php_handle_aborted_connection(void)
TSRMLS_FETCH();
PG(connection_status) = PHP_CONNECTION_ABORTED;
- php_output_set_status(0 TSRMLS_CC);
+ php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
if (!PG(ignore_user_abort)) {
zend_bailout();
diff --git a/main/network.c b/main/network.c
index 56b08978a7..6c7031f983 100644
--- a/main/network.c
+++ b/main/network.c
@@ -148,7 +148,7 @@ static const char *php_gai_strerror(int code)
/* {{{ php_network_freeaddresses
*/
-static void php_network_freeaddresses(struct sockaddr **sal)
+PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
{
struct sockaddr **sap;
@@ -163,7 +163,7 @@ static void php_network_freeaddresses(struct sockaddr **sal)
/* {{{ php_network_getaddresses
* Returns number of addresses, 0 for none/error
*/
-static int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
+PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
{
struct sockaddr **sap;
int n;
@@ -1058,7 +1058,7 @@ PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short p
reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
- stream = php_stream_xport_create(res, reslen, ENFORCE_SAFE_MODE | REPORT_ERRORS,
+ stream = php_stream_xport_create(res, reslen, REPORT_ERRORS,
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);
efree(res);
diff --git a/main/output.c b/main/output.c
index 5a7ed7b1a2..e100057ca9 100644
--- a/main/output.c
+++ b/main/output.c
@@ -15,39 +15,83 @@
| Authors: Zeev Suraski <zeev@zend.com> |
| Thies C. Arntzen <thies@thieso.net> |
| Marcus Boerger <helly@php.net> |
+ | New API: Michael Wallner <mike@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
+#ifndef PHP_OUTPUT_DEBUG
+# define PHP_OUTPUT_DEBUG 0
+#endif
+#ifndef PHP_OUTPUT_NOINLINE
+# define PHP_OUTPUT_NOINLINE 0
+#endif
+
#include "php.h"
#include "ext/standard/head.h"
-#include "ext/standard/basic_functions.h"
#include "ext/standard/url_scanner_ex.h"
-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
-#include "ext/zlib/php_zlib.h"
-#endif
#include "SAPI.h"
+#include "zend_stack.h"
+#include "php_output.h"
-#define OB_DEFAULT_HANDLER_NAME "default output handler"
+ZEND_DECLARE_MODULE_GLOBALS(output);
-/* output functions */
-static int php_b_body_write(const char *str, uint str_length TSRMLS_DC);
+const char php_output_default_handler_name[sizeof("default output handler")] = "default output handler";
+const char php_output_devnull_handler_name[sizeof("null output handler")] = "null output handler";
-static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC);
-static void php_ob_append(const char *text, uint text_length TSRMLS_DC);
-#if 0
-static void php_ob_prepend(const char *text, uint text_length);
+#if PHP_OUTPUT_NOINLINE || PHP_OUTPUT_DEBUG
+# undef inline
+# define inline
#endif
-#ifdef ZTS
-int output_globals_id;
-#else
-php_output_globals output_globals;
-#endif
+/* {{{ aliases, conflict and reverse conflict hash tables */
+static HashTable php_output_handler_aliases;
+static HashTable php_output_handler_conflicts;
+static HashTable php_output_handler_reverse_conflicts;
+/* }}} */
+
+/* {{{ forward declarations */
+static inline int php_output_lock_error(int op TSRMLS_DC);
+static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC);
+
+static inline php_output_handler *php_output_handler_init(const char *name, size_t name_len, size_t chunk_size, int flags TSRMLS_DC);
+static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context);
+static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC);
+static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry);
+
+static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC);
+static inline void php_output_context_reset(php_output_context *context);
+static inline void php_output_context_swap(php_output_context *context);
+static inline void php_output_context_dtor(php_output_context *context);
+
+static inline int php_output_stack_pop(int flags TSRMLS_DC);
+
+static int php_output_stack_apply_op(void *h, void *c);
+static int php_output_stack_apply_clean(void *h, void *c);
+static int php_output_stack_apply_list(void *h, void *z);
+static int php_output_stack_apply_status(void *h, void *z);
-/* {{{ php_default_output_func */
-PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC)
+static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context);
+static int php_output_handler_default_func(void **handler_context, php_output_context *output_context);
+static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context);
+/* }}} */
+
+/* {{{ static void php_output_init_globals(zend_output_globals *G)
+ * Initialize the module globals on MINIT */
+static inline void php_output_init_globals(zend_output_globals *G)
+{
+ memset(G, 0, sizeof(*G));
+}
+/* }}} */
+
+/* {{{ stderr/stdout writer if not PHP_OUTPUT_ACTIVATED */
+static int php_output_stdout(const char *str, size_t str_len)
+{
+ fwrite(str, 1, str_len, stdout);
+ return str_len;
+}
+static int php_output_stderr(const char *str, size_t str_len)
{
fwrite(str, 1, str_len, stderr);
/* See http://support.microsoft.com/kb/190351 */
@@ -56,706 +100,1199 @@ PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC)
#endif
return str_len;
}
+static int (*php_output_direct)(const char *str, size_t str_len) = php_output_stderr;
/* }}} */
-/* {{{ php_output_init_globals */
-static void php_output_init_globals(php_output_globals *output_globals_p TSRMLS_DC)
+/* {{{ void php_output_header(TSRMLS_D) */
+static void php_output_header(TSRMLS_D)
{
- OG(php_body_write) = php_default_output_func;
- OG(php_header_write) = php_default_output_func;
- OG(implicit_flush) = 0;
- OG(output_start_filename) = NULL;
- OG(output_start_lineno) = 0;
+ if (!SG(headers_sent)) {
+ if (!OG(output_start_filename)) {
+ if (zend_is_compiling(TSRMLS_C)) {
+ OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C);
+ OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C);
+ } else if (zend_is_executing(TSRMLS_C)) {
+ OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C);
+ OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C);
+ }
+#if PHP_OUTPUT_DEBUG
+ fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno));
+#endif
+ }
+ if (!php_header(TSRMLS_C)) {
+ OG(flags) |= PHP_OUTPUT_DISABLED;
+ }
+ }
}
/* }}} */
-/* {{{ php_output_startup
- * Start output layer */
+/* {{{ void php_output_startup(void)
+ * Set up module globals and initalize the conflict and reverse conflict hash tables */
PHPAPI void php_output_startup(void)
{
+ ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL);
+ zend_hash_init(&php_output_handler_aliases, 0, NULL, NULL, 1);
+ zend_hash_init(&php_output_handler_conflicts, 0, NULL, NULL, 1);
+ zend_hash_init(&php_output_handler_reverse_conflicts, 0, NULL, (void (*)(void *)) zend_hash_destroy, 1);
+ php_output_direct = php_output_stdout;
+}
+/* }}} */
+
+/* {{{ void php_output_shutdown(void)
+ * Destroy module globals and the conflict and reverse conflict hash tables */
+PHPAPI void php_output_shutdown(void)
+{
+ php_output_direct = php_output_stderr;
+ zend_hash_destroy(&php_output_handler_aliases);
+ zend_hash_destroy(&php_output_handler_conflicts);
+ zend_hash_destroy(&php_output_handler_reverse_conflicts);
+}
+/* }}} */
+
+/* {{{ SUCCESS|FAILURE php_output_activate(TSRMLS_D)
+ * Reset output globals and setup the output handler stack */
+PHPAPI int php_output_activate(TSRMLS_D)
+{
#ifdef ZTS
- ts_allocate_id(&output_globals_id, sizeof(php_output_globals), (ts_allocate_ctor) php_output_init_globals, NULL);
+ memset((*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals));
#else
- php_output_init_globals(&output_globals TSRMLS_CC);
+ memset(&output_globals, 0, sizeof(zend_output_globals));
#endif
+
+ zend_stack_init(&OG(handlers));
+ OG(flags) |= PHP_OUTPUT_ACTIVATED;
+
+ return SUCCESS;
}
/* }}} */
-/* {{{ php_output_activate
- * Initilize output global for activation */
-PHPAPI void php_output_activate(TSRMLS_D)
+/* {{{ void php_output_deactivate(TSRMLS_D)
+ * Destroy the output handler stack */
+PHPAPI void php_output_deactivate(TSRMLS_D)
{
- OG(php_body_write) = php_ub_body_write;
- OG(php_header_write) = sapi_module.ub_write;
- OG(ob_nesting_level) = 0;
- OG(ob_lock) = 0;
- OG(disable_output) = 0;
- OG(output_start_filename) = NULL;
- OG(output_start_lineno) = 0;
+ php_output_handler **handler = NULL;
+
+ php_output_header(TSRMLS_C);
+
+ OG(flags) ^= PHP_OUTPUT_ACTIVATED;
+ OG(active) = NULL;
+ OG(running) = NULL;
+
+ /* release all output handlers */
+ if (OG(handlers).elements) {
+ while (SUCCESS == zend_stack_top(&OG(handlers), (void *) &handler)) {
+ php_output_handler_free(handler TSRMLS_CC);
+ zend_stack_del_top(&OG(handlers));
+ }
+ zend_stack_destroy(&OG(handlers));
+ }
+
}
/* }}} */
-/* {{{ php_output_register_constants */
-void php_output_register_constants(TSRMLS_D)
+/* {{{ void php_output_register_constants() */
+PHPAPI void php_output_register_constants(TSRMLS_D)
{
REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT);
- REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_CONT, CONST_CS | CONST_PERSISTENT);
- REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_END, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_WRITE", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSH", PHP_OUTPUT_HANDLER_FLUSH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEAN", PHP_OUTPUT_HANDLER_CLEAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FINAL", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEANABLE", PHP_OUTPUT_HANDLER_CLEANABLE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSHABLE", PHP_OUTPUT_HANDLER_FLUSHABLE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_REMOVABLE", PHP_OUTPUT_HANDLER_REMOVABLE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STDFLAGS", PHP_OUTPUT_HANDLER_STDFLAGS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STARTED", PHP_OUTPUT_HANDLER_STARTED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_DISABLED", PHP_OUTPUT_HANDLER_DISABLED, CONST_CS | CONST_PERSISTENT);
}
/* }}} */
-/* {{{ php_output_set_status
- * Toggle output status. Do NOT use in application code, only in SAPIs where appropriate. */
-PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC)
+/* {{{ void php_output_set_status(int status TSRMLS_DC)
+ * Used by SAPIs to disable output */
+PHPAPI void php_output_set_status(int status TSRMLS_DC)
{
- OG(disable_output) = !status;
+ OG(flags) = (OG(flags) & ~0xf) | (status & 0xf);
}
/* }}} */
-/* {{{ php_body_write
- * Write body part */
-PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC)
+/* {{{ int php_output_get_status(TSRMLS_C)
+ * Get output control status */
+PHPAPI int php_output_get_status(TSRMLS_D)
{
- return OG(php_body_write)(str, str_length TSRMLS_CC);
+ return (
+ OG(flags)
+ | (OG(active) ? PHP_OUTPUT_ACTIVE : 0)
+ | (OG(running)? PHP_OUTPUT_LOCKED : 0)
+ ) & 0xff;
}
/* }}} */
-/* {{{ php_header_write
- * Write HTTP header */
-PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC)
+/* {{{ int php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC)
+ * Unbuffered write */
+PHPAPI int php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC)
{
- if (OG(disable_output)) {
+ if (OG(flags) & PHP_OUTPUT_DISABLED) {
return 0;
- } else {
- return OG(php_header_write)(str, str_length TSRMLS_CC);
}
+ if (OG(flags) & PHP_OUTPUT_ACTIVATED) {
+ return sapi_module.ub_write(str, len TSRMLS_CC);
+ }
+ return php_output_direct(str, len);
}
/* }}} */
-/* {{{ php_start_ob_buffer
- * Start output buffering */
-PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
+/* {{{ int php_output_write(const char *str, size_t len TSRMLS_DC)
+ * Buffered write */
+PHPAPI int php_output_write(const char *str, size_t len TSRMLS_DC)
{
- uint initial_size, block_size;
+ if (OG(flags) & PHP_OUTPUT_DISABLED) {
+ return 0;
+ }
+ if (OG(flags) & PHP_OUTPUT_ACTIVATED) {
+ php_output_op(PHP_OUTPUT_HANDLER_WRITE, str, len TSRMLS_CC);
+ return (int) len;
+ }
+ return php_output_direct(str, len);
+}
+/* }}} */
- if (OG(ob_lock)) {
- if (SG(headers_sent) && !SG(request_info).headers_only) {
- OG(php_body_write) = php_ub_body_write_no_header;
- } else {
- OG(php_body_write) = php_ub_body_write;
+/* {{{ SUCCESS|FAILURE php_output_flush(TSRMLS_D)
+ * Flush the most recent output handlers buffer */
+PHPAPI int php_output_flush(TSRMLS_D)
+{
+ php_output_context context;
+
+ if (OG(active) && (OG(active)->flags & PHP_OUTPUT_HANDLER_FLUSHABLE)) {
+ php_output_context_init(&context, PHP_OUTPUT_HANDLER_FLUSH TSRMLS_CC);
+ php_output_handler_op(OG(active), &context);
+ if (context.out.data && context.out.used) {
+ zend_stack_del_top(&OG(handlers));
+ php_output_write(context.out.data, context.out.used TSRMLS_CC);
+ zend_stack_push(&OG(handlers), &OG(active), sizeof(php_output_handler *));
}
- OG(ob_nesting_level) = 0;
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers");
- return FAILURE;
+ php_output_context_dtor(&context);
+ return SUCCESS;
}
- if (chunk_size > 0) {
- if (chunk_size==1) {
- chunk_size = 4096;
- }
- initial_size = (chunk_size*3/2);
- block_size = chunk_size/2;
- } else {
- initial_size = 40*1024;
- block_size = 10*1024;
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ void php_output_flush_all(TSRMLS_C)
+ * Flush all output buffers subsequently */
+PHPAPI void php_output_flush_all(TSRMLS_D)
+{
+ if (OG(active)) {
+ php_output_op(PHP_OUTPUT_HANDLER_FLUSH, NULL, 0 TSRMLS_CC);
}
- return php_ob_init(initial_size, block_size, output_handler, chunk_size, erase TSRMLS_CC);
}
/* }}} */
-/* {{{ php_start_ob_buffer_named
- * Start output buffering */
-PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint chunk_size, zend_bool erase TSRMLS_DC)
+/* {{{ SUCCESS|FAILURE php_output_clean(TSRMLS_D)
+ * Cleans the most recent output handlers buffer if the handler is cleanable */
+PHPAPI int php_output_clean(TSRMLS_D)
{
- zval *output_handler;
- int result;
+ php_output_context context;
- ALLOC_INIT_ZVAL(output_handler);
- Z_STRLEN_P(output_handler) = strlen(output_handler_name); /* this can be optimized */
- Z_STRVAL_P(output_handler) = estrndup(output_handler_name, Z_STRLEN_P(output_handler));
- Z_TYPE_P(output_handler) = IS_STRING;
- result = php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC);
- zval_dtor(output_handler);
- FREE_ZVAL(output_handler);
- return result;
+ if (OG(active) && (OG(active)->flags & PHP_OUTPUT_HANDLER_CLEANABLE)) {
+ OG(active)->buffer.used = 0;
+ php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC);
+ php_output_handler_op(OG(active), &context);
+ php_output_context_dtor(&context);
+ return SUCCESS;
+ }
+ return FAILURE;
}
/* }}} */
-/* {{{ php_end_ob_buffer
- * End output buffering (one level) */
-PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC)
+/* {{{ void php_output_clean_all(TSRMLS_D)
+ * Cleans all output handler buffers, without regard whether the handler is cleanable */
+PHPAPI void php_output_clean_all(TSRMLS_D)
{
- char *final_buffer=NULL;
- unsigned int final_buffer_length=0;
- zval *alternate_buffer=NULL;
- char *to_be_destroyed_buffer, *to_be_destroyed_handler_name;
- char *to_be_destroyed_handled_output[2] = { 0, 0 };
- int status;
- php_ob_buffer *prev_ob_buffer_p=NULL;
- php_ob_buffer orig_ob_buffer;
+ php_output_context context;
- if (OG(ob_nesting_level)==0) {
- return;
- }
- status = 0;
- if (!OG(active_ob_buffer).status & PHP_OUTPUT_HANDLER_START) {
- /* our first call */
- status |= PHP_OUTPUT_HANDLER_START;
- }
- if (just_flush) {
- status |= PHP_OUTPUT_HANDLER_CONT;
- } else {
- status |= PHP_OUTPUT_HANDLER_END;
+ if (OG(active)) {
+ php_output_context_init(&context, PHP_OUTPUT_HANDLER_CLEAN TSRMLS_CC);
+ zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_clean, &context);
}
+}
-#if 0
- {
- FILE *fp;
- fp = fopen("/tmp/ob_log", "a");
- fprintf(fp, "NestLevel: %d ObStatus: %d HandlerName: %s\n", OG(ob_nesting_level), status, OG(active_ob_buffer).handler_name);
- fclose(fp);
- }
-#endif
+/* {{{ SUCCESS|FAILURE php_output_end(TSRMLS_D)
+ * Finalizes the most recent output handler at pops it off the stack if the handler is removable */
+PHPAPI int php_output_end(TSRMLS_D)
+{
+ if (php_output_stack_pop(PHP_OUTPUT_POP_TRY TSRMLS_CC)) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+/* }}} */
- if (OG(active_ob_buffer).internal_output_handler) {
- final_buffer = OG(active_ob_buffer).internal_output_handler_buffer;
- final_buffer_length = OG(active_ob_buffer).internal_output_handler_buffer_size;
- OG(active_ob_buffer).internal_output_handler(OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, &final_buffer, &final_buffer_length, status TSRMLS_CC);
- } else if (OG(active_ob_buffer).output_handler) {
- zval **params[2];
- zval *orig_buffer;
- zval *z_status;
-
- if(OG(ob_lock)) {
- if (SG(headers_sent) && !SG(request_info).headers_only) {
- OG(php_body_write) = php_ub_body_write_no_header;
- } else {
- OG(php_body_write) = php_ub_body_write;
- }
- OG(ob_nesting_level) = 0;
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers");
- return;
- }
+/* {{{ void php_output_end_all(TSRMLS_D)
+ * Finalizes all output handlers and ends output buffering without regard whether a handler is removable */
+PHPAPI void php_output_end_all(TSRMLS_D)
+{
+ while (OG(active) && php_output_stack_pop(PHP_OUTPUT_POP_FORCE TSRMLS_CC));
+}
+/* }}} */
- ALLOC_INIT_ZVAL(orig_buffer);
- ZVAL_STRINGL(orig_buffer, OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, 1);
+/* {{{ SUCCESS|FAILURE php_output_discard(TSRMLS_D)
+ * Discards the most recent output handlers buffer and pops it off the stack if the handler is removable */
+PHPAPI int php_output_discard(TSRMLS_D)
+{
+ if (php_output_stack_pop(PHP_OUTPUT_POP_DISCARD|PHP_OUTPUT_POP_TRY TSRMLS_CC)) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+/* }}} */
- ALLOC_INIT_ZVAL(z_status);
- ZVAL_LONG(z_status, status);
+/* {{{ void php_output_discard_all(TSRMLS_D)
+ * Discard all output handlers and buffers without regard whether a handler is removable */
+PHPAPI void php_output_discard_all(TSRMLS_D)
+{
+ while (OG(active)) {
+ php_output_stack_pop(PHP_OUTPUT_POP_DISCARD|PHP_OUTPUT_POP_FORCE TSRMLS_CC);
+ }
+}
+/* }}} */
- params[0] = &orig_buffer;
- params[1] = &z_status;
- OG(ob_lock) = 1;
+/* {{{ int php_output_get_level(TSRMLS_D)
+ * Get output buffering level, ie. how many output handlers the stack contains */
+PHPAPI int php_output_get_level(TSRMLS_D)
+{
+ return OG(active) ? zend_stack_count(&OG(handlers)) : 0;
+}
+/* }}} */
- if (call_user_function_ex(CG(function_table), NULL, OG(active_ob_buffer).output_handler, &alternate_buffer, 2, params, 1, NULL TSRMLS_CC)==SUCCESS) {
- if (alternate_buffer && !(Z_TYPE_P(alternate_buffer)==IS_BOOL && Z_BVAL_P(alternate_buffer)==0)) {
- convert_to_string_ex(&alternate_buffer);
- final_buffer = Z_STRVAL_P(alternate_buffer);
- final_buffer_length = Z_STRLEN_P(alternate_buffer);
- }
- }
- OG(ob_lock) = 0;
- if (!just_flush) {
- zval_ptr_dtor(&OG(active_ob_buffer).output_handler);
- }
- zval_ptr_dtor(&orig_buffer);
- zval_ptr_dtor(&z_status);
+/* {{{ SUCCESS|FAILURE php_output_get_contents(zval *z TSRMLS_DC)
+ * Get the contents of the active output handlers buffer */
+PHPAPI int php_output_get_contents(zval *p TSRMLS_DC)
+{
+ if (OG(active)) {
+ ZVAL_STRINGL(p, OG(active)->buffer.data, OG(active)->buffer.used, 1);
+ return SUCCESS;
+ } else {
+ ZVAL_NULL(p);
+ return FAILURE;
}
+}
- if (!final_buffer) {
- final_buffer = OG(active_ob_buffer).buffer;
- final_buffer_length = OG(active_ob_buffer).text_length;
+/* {{{ SUCCESS|FAILURE php_output_get_length(zval *z TSRMLS_DC)
+ * Get the length of the active output handlers buffer */
+PHPAPI int php_output_get_length(zval *p TSRMLS_DC)
+{
+ if (OG(active)) {
+ ZVAL_LONG(p, OG(active)->buffer.used);
+ return SUCCESS;
+ } else {
+ ZVAL_NULL(p);
+ return FAILURE;
}
+}
+/* }}} */
- if (OG(ob_nesting_level)==1) { /* end buffering */
- if (SG(headers_sent) && !SG(request_info).headers_only) {
- OG(php_body_write) = php_ub_body_write_no_header;
- } else {
- OG(php_body_write) = php_ub_body_write;
- }
- }
+/* {{{ php_output_handler* php_output_get_active_handler(TSRMLS_D)
+ * Get active output handler */
+PHPAPI php_output_handler* php_output_get_active_handler(TSRMLS_D)
+{
+ return OG(active);
+}
+/* }}} */
- to_be_destroyed_buffer = OG(active_ob_buffer).buffer;
- to_be_destroyed_handler_name = OG(active_ob_buffer).handler_name;
- if (OG(active_ob_buffer).internal_output_handler
- && (final_buffer != OG(active_ob_buffer).internal_output_handler_buffer)
- && (final_buffer != OG(active_ob_buffer).buffer)) {
- to_be_destroyed_handled_output[0] = final_buffer;
- }
+/* {{{ SUCCESS|FAILURE php_output_handler_start_default(TSRMLS_D)
+ * Start a "default output handler" */
+PHPAPI int php_output_start_default(TSRMLS_D)
+{
+ php_output_handler *handler;
- if (!just_flush) {
- if (OG(active_ob_buffer).internal_output_handler) {
- to_be_destroyed_handled_output[1] = OG(active_ob_buffer).internal_output_handler_buffer;
- }
+ handler = php_output_handler_create_internal(ZEND_STRL(php_output_default_handler_name), php_output_handler_default_func, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
+ if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
+ return SUCCESS;
}
- if (OG(ob_nesting_level)>1) { /* restore previous buffer */
- zend_stack_top(&OG(ob_buffers), (void **) &prev_ob_buffer_p);
- orig_ob_buffer = OG(active_ob_buffer);
- OG(active_ob_buffer) = *prev_ob_buffer_p;
- zend_stack_del_top(&OG(ob_buffers));
- if (!just_flush && OG(ob_nesting_level)==2) { /* destroy the stack */
- zend_stack_destroy(&OG(ob_buffers));
- }
- }
- OG(ob_nesting_level)--;
+ php_output_handler_free(&handler TSRMLS_CC);
+ return FAILURE;
+}
+/* }}} */
- if (send_buffer) {
- if (just_flush) { /* if flush is called prior to proper end, ensure presence of NUL */
- final_buffer[final_buffer_length] = '\0';
- }
- OG(php_body_write)(final_buffer, final_buffer_length TSRMLS_CC);
- }
+/* {{{ SUCCESS|FAILURE php_output_handler_start_devnull(TSRMLS_D)
+ * Start a "null output handler" */
+PHPAPI int php_output_start_devnull(TSRMLS_D)
+{
+ php_output_handler *handler;
- if (just_flush) { /* we restored the previous ob, return to the current */
- if (prev_ob_buffer_p) {
- zend_stack_push(&OG(ob_buffers), &OG(active_ob_buffer), sizeof(php_ob_buffer));
- OG(active_ob_buffer) = orig_ob_buffer;
- }
- OG(ob_nesting_level)++;
+ handler = php_output_handler_create_internal(ZEND_STRL(php_output_devnull_handler_name), php_output_handler_devnull_func, PHP_OUTPUT_HANDLER_DEFAULT_SIZE, 0 TSRMLS_CC);
+ if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
+ return SUCCESS;
}
+ php_output_handler_free(&handler TSRMLS_CC);
+ return FAILURE;
+}
+/* }}} */
- if (alternate_buffer) {
- zval_ptr_dtor(&alternate_buffer);
- }
+/* {{{ SUCCESS|FAILURE php_output_start_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC)
+ * Start a user level output handler */
+PHPAPI int php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC)
+{
+ php_output_handler *handler;
- if (status & PHP_OUTPUT_HANDLER_END) {
- efree(to_be_destroyed_handler_name);
- }
- if (!just_flush) {
- efree(to_be_destroyed_buffer);
+ if (output_handler) {
+ handler = php_output_handler_create_user(output_handler, chunk_size, flags TSRMLS_CC);
} else {
- OG(active_ob_buffer).text_length = 0;
- OG(active_ob_buffer).status |= PHP_OUTPUT_HANDLER_START;
- OG(php_body_write) = php_b_body_write;
- }
- if (to_be_destroyed_handled_output[0]) {
- efree(to_be_destroyed_handled_output[0]);
+ handler = php_output_handler_create_internal(ZEND_STRL(php_output_default_handler_name), php_output_handler_default_func, chunk_size, flags TSRMLS_CC);
}
- if (to_be_destroyed_handled_output[1]) {
- efree(to_be_destroyed_handled_output[1]);
+ if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
+ return SUCCESS;
}
+ php_output_handler_free(&handler TSRMLS_CC);
+ return FAILURE;
}
/* }}} */
-/* {{{ php_end_ob_buffers
- * End output buffering (all buffers) */
-PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC)
+/* {{{ SUCCESS|FAILURE php_output_start_internal(zval *name, php_output_handler_func_t handler, size_t chunk_size, int flags TSRMLS_DC)
+ * Start an internal output handler that does not have to maintain a non-global state */
+PHPAPI int php_output_start_internal(const char *name, size_t name_len, php_output_handler_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC)
{
- while (OG(ob_nesting_level)!=0) {
- php_end_ob_buffer(send_buffer, 0 TSRMLS_CC);
+ php_output_handler *handler;
+
+ handler = php_output_handler_create_internal(name, name_len, php_output_handler_compat_func, chunk_size, flags TSRMLS_CC);
+ php_output_handler_set_context(handler, output_handler, NULL TSRMLS_CC);
+ if (SUCCESS == php_output_handler_start(handler TSRMLS_CC)) {
+ return SUCCESS;
}
+ php_output_handler_free(&handler TSRMLS_CC);
+ return FAILURE;
}
/* }}} */
-/* {{{ php_start_implicit_flush
- */
-PHPAPI void php_start_implicit_flush(TSRMLS_D)
+/* {{{ php_output_handler *php_output_handler_create_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC)
+ * Create a user level output handler */
+PHPAPI php_output_handler *php_output_handler_create_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC)
{
- OG(implicit_flush) = 1;
-}
-/* }}} */
+ char *handler_name = NULL, *error = NULL;
+ php_output_handler *handler = NULL;
+ php_output_handler_alias_ctor_t *alias = NULL;
+ php_output_handler_user_func_t *user = NULL;
+
+ switch (Z_TYPE_P(output_handler)) {
+ case IS_NULL:
+ handler = php_output_handler_create_internal(ZEND_STRL(php_output_default_handler_name), php_output_handler_default_func, chunk_size, flags TSRMLS_CC);
+ break;
+ case IS_STRING:
+ if (Z_STRLEN_P(output_handler) && (alias = php_output_handler_alias(Z_STRVAL_P(output_handler), Z_STRLEN_P(output_handler) TSRMLS_CC))) {
+ handler = (*alias)(Z_STRVAL_P(output_handler), Z_STRLEN_P(output_handler), chunk_size, flags TSRMLS_CC);
+ break;
+ }
+ default:
+ user = ecalloc(1, sizeof(php_output_handler_user_func_t));
+ if (SUCCESS == zend_fcall_info_init(output_handler, 0, &user->fci, &user->fcc, &handler_name, &error TSRMLS_CC)) {
+ handler = php_output_handler_init(handler_name, strlen(handler_name), chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_USER TSRMLS_CC);
+ Z_ADDREF_P(output_handler);
+ user->zoh = output_handler;
+ handler->func.user = user;
+ } else {
+ efree(user);
+ }
+ if (error) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "%s", error);
+ efree(error);
+ }
+ if (handler_name) {
+ efree(handler_name);
+ }
+ }
-/* {{{ php_end_implicit_flush
- */
-PHPAPI void php_end_implicit_flush(TSRMLS_D)
-{
- OG(implicit_flush) = 0;
+ return handler;
}
/* }}} */
-/* {{{ char *php_get_output_start_filename(TSRMLS_D)
- * Return filename start output something */
-PHPAPI char *php_get_output_start_filename(TSRMLS_D)
+/* {{{ php_output_handler *php_output_handler_create_internal(zval *name, php_output_handler_context_func_t handler, size_t chunk_size, int flags TSRMLS_DC)
+ * Create an internal output handler that can maintain a non-global state */
+PHPAPI php_output_handler *php_output_handler_create_internal(const char *name, size_t name_len, php_output_handler_context_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC)
{
- return OG(output_start_filename);
+ php_output_handler *handler;
+
+ handler = php_output_handler_init(name, name_len, chunk_size, (flags & ~0xf) | PHP_OUTPUT_HANDLER_INTERNAL TSRMLS_CC);
+ handler->func.internal = output_handler;
+
+ return handler;
}
/* }}} */
-/* {{{ char *php_get_output_start_lineno(TSRMLS_D)
- * Return line number start output something */
-PHPAPI int php_get_output_start_lineno(TSRMLS_D)
+/* {{{ void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC)
+ * Set the context/state of an output handler. Calls the dtor of the previous context if there is one */
+PHPAPI void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC)
{
- return OG(output_start_lineno);
+ if (handler->dtor && handler->opaq) {
+ handler->dtor(handler->opaq TSRMLS_CC);
+ }
+ handler->dtor = dtor;
+ handler->opaq = opaq;
}
/* }}} */
-/* {{{ php_ob_set_internal_handler
- */
-PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_output_handler, uint buffer_size, char *handler_name, zend_bool erase TSRMLS_DC)
+/* {{{ SUCCESS|FAILURE php_output_handler_start(php_output_handler *handler TSRMLS_DC)
+ * Starts the set up output handler and pushes it on top of the stack. Checks for any conflicts regarding the output handler to start */
+PHPAPI int php_output_handler_start(php_output_handler *handler TSRMLS_DC)
{
- if (OG(ob_nesting_level) == 0 || OG(active_ob_buffer).internal_output_handler || strcmp(OG(active_ob_buffer).handler_name, OB_DEFAULT_HANDLER_NAME)) {
- php_start_ob_buffer(NULL, buffer_size, erase TSRMLS_CC);
- }
+ HashPosition pos;
+ HashTable *rconflicts;
+ php_output_handler_conflict_check_t *conflict;
- OG(active_ob_buffer).internal_output_handler = internal_output_handler;
- OG(active_ob_buffer).internal_output_handler_buffer = (char *) emalloc(buffer_size);
- OG(active_ob_buffer).internal_output_handler_buffer_size = buffer_size;
- if (OG(active_ob_buffer).handler_name) {
- efree(OG(active_ob_buffer).handler_name);
+ if (php_output_lock_error(PHP_OUTPUT_HANDLER_START TSRMLS_CC) || !handler) {
+ return FAILURE;
}
- OG(active_ob_buffer).handler_name = estrdup(handler_name);
- OG(active_ob_buffer).erase = erase;
+ if (SUCCESS == zend_hash_find(&php_output_handler_conflicts, handler->name, handler->name_len+1, (void *) &conflict)) {
+ if (SUCCESS != (*conflict)(handler->name, handler->name_len TSRMLS_CC)) {
+ return FAILURE;
+ }
+ }
+ if (SUCCESS == zend_hash_find(&php_output_handler_reverse_conflicts, handler->name, handler->name_len+1, (void *) &rconflicts)) {
+ for (zend_hash_internal_pointer_reset_ex(rconflicts, &pos);
+ zend_hash_get_current_data_ex(rconflicts, (void *) &conflict, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(rconflicts, &pos)
+ ) {
+ if (SUCCESS != (*conflict)(handler->name, handler->name_len TSRMLS_CC)) {
+ return FAILURE;
+ }
+ }
+ }
+ /* zend_stack_push never returns SUCCESS but FAILURE or stack level */
+ if (FAILURE == (handler->level = zend_stack_push(&OG(handlers), &handler, sizeof(php_output_handler *)))) {
+ return FAILURE;
+ }
+ OG(active) = handler;
+ return SUCCESS;
}
/* }}} */
-/*
- * Output buffering - implementation
- */
-
-/* {{{ php_ob_allocate
- */
-static inline void php_ob_allocate(uint text_length TSRMLS_DC)
+/* {{{ int php_output_handler_started(zval *name TSRMLS_DC)
+ * Check whether a certain output handler is in use */
+PHPAPI int php_output_handler_started(const char *name, size_t name_len TSRMLS_DC)
{
- uint new_len = OG(active_ob_buffer).text_length + text_length;
+ php_output_handler ***handlers;
+ int i, count = php_output_get_level(TSRMLS_C);
- if (OG(active_ob_buffer).size < new_len) {
- uint buf_size = OG(active_ob_buffer).size;
- while (buf_size <= new_len) {
- buf_size += OG(active_ob_buffer).block_size;
- }
+ if (count) {
+ handlers = (php_output_handler ***) zend_stack_base(&OG(handlers));
- OG(active_ob_buffer).buffer = (char *) erealloc(OG(active_ob_buffer).buffer, buf_size+1);
- OG(active_ob_buffer).size = buf_size;
+ for (i = 0; i < count; ++i) {
+ if (name_len == (*(handlers[i]))->name_len && !memcmp((*(handlers[i]))->name, name, name_len)) {
+ return 1;
+ }
+ }
}
- OG(active_ob_buffer).text_length = new_len;
+
+ return 0;
}
/* }}} */
-/* {{{ php_ob_init_conflict
- * Returns 1 if handler_set is already used and generates error message */
-PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC)
+/* {{{ int php_output_handler_conflict(zval *handler_new, zval *handler_old TSRMLS_DC)
+ * Check whether a certain handler is in use and issue a warning that the new handler would conflict with the already used one */
+PHPAPI int php_output_handler_conflict(const char *handler_new, size_t handler_new_len, const char *handler_set, size_t handler_set_len TSRMLS_DC)
{
- if (php_ob_handler_used(handler_set TSRMLS_CC)) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' conflicts with '%s'", handler_new, handler_set);
+ if (php_output_handler_started(handler_set, handler_set_len TSRMLS_CC)) {
+ if (handler_new_len != handler_set_len || memcmp(handler_new, handler_set, handler_set_len)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' conflicts with '%s'", handler_new, handler_set);
+ } else {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler '%s' cannot be used twice", handler_new);
+ }
return 1;
}
return 0;
}
/* }}} */
-/* {{{ php_ob_init_named
- */
-static int php_ob_init_named(uint initial_size, uint block_size, char *handler_name, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
+/* {{{ SUCCESS|FAILURE php_output_handler_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC)
+ * Register a conflict checking function on MINIT */
+PHPAPI int php_output_handler_conflict_register(const char *name, size_t name_len, php_output_handler_conflict_check_t check_func TSRMLS_DC)
+{
+ if (!EG(current_module)) {
+ zend_error(E_ERROR, "Cannot register an output handler conflict outside of MINIT");
+ return FAILURE;
+ }
+ return zend_hash_update(&php_output_handler_conflicts, name, name_len+1, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL);
+}
+/* }}} */
+
+/* {{{ SUCCESS|FAILURE php_output_handler_reverse_conflict_register(zval *name, php_output_handler_conflict_check_t check_func TSRMLS_DC)
+ * Register a reverse conflict checking function on MINIT */
+PHPAPI int php_output_handler_reverse_conflict_register(const char *name, size_t name_len, php_output_handler_conflict_check_t check_func TSRMLS_DC)
{
- php_ob_buffer tmp_buf;
+ HashTable rev, *rev_ptr = NULL;
- if (output_handler && !zend_is_callable(output_handler, 0, NULL TSRMLS_CC)) {
+ if (!EG(current_module)) {
+ zend_error(E_ERROR, "Cannot register a reverse output handler conflict outside of MINIT");
return FAILURE;
}
- tmp_buf.block_size = block_size;
- tmp_buf.size = initial_size;
- tmp_buf.buffer = (char *) emalloc(initial_size+1);
- tmp_buf.text_length = 0;
- tmp_buf.output_handler = output_handler;
- tmp_buf.chunk_size = chunk_size;
- tmp_buf.status = 0;
- tmp_buf.internal_output_handler = NULL;
- tmp_buf.internal_output_handler_buffer = NULL;
- tmp_buf.internal_output_handler_buffer_size = 0;
- tmp_buf.handler_name = estrdup(handler_name&&handler_name[0]?handler_name:OB_DEFAULT_HANDLER_NAME);
- tmp_buf.erase = erase;
-
- if (OG(ob_nesting_level)>0) {
-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)
- if (!strncmp(handler_name, "ob_gzhandler", sizeof("ob_gzhandler")) && php_ob_gzhandler_check(TSRMLS_C)) {
+ if (SUCCESS == zend_hash_find(&php_output_handler_reverse_conflicts, name, name_len+1, (void *) &rev_ptr)) {
+ return zend_hash_next_index_insert(rev_ptr, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL);
+ } else {
+ zend_hash_init(&rev, 1, NULL, NULL, 1);
+ if (SUCCESS != zend_hash_next_index_insert(&rev, &check_func, sizeof(php_output_handler_conflict_check_t *), NULL)) {
+ zend_hash_destroy(&rev);
return FAILURE;
}
-#endif
- if (OG(ob_nesting_level)==1) { /* initialize stack */
- zend_stack_init(&OG(ob_buffers));
+ if (SUCCESS != zend_hash_update(&php_output_handler_reverse_conflicts, name, name_len+1, &rev, sizeof(HashTable), NULL)) {
+ zend_hash_destroy(&rev);
+ return FAILURE;
}
- zend_stack_push(&OG(ob_buffers), &OG(active_ob_buffer), sizeof(php_ob_buffer));
+ return SUCCESS;
}
- OG(ob_nesting_level)++;
- OG(active_ob_buffer) = tmp_buf;
- OG(php_body_write) = php_b_body_write;
- return SUCCESS;
}
/* }}} */
-/* {{{ php_ob_handler_from_string
- * Create zval output handler from string */
-static zval* php_ob_handler_from_string(const char *handler_name, int len TSRMLS_DC)
+/* {{{ php_output_handler_alias_ctor_t php_output_handler_alias(zval *name TSRMLS_DC)
+ * Get an internal output handler for a user handler if it exists */
+PHPAPI php_output_handler_alias_ctor_t *php_output_handler_alias(const char *name, size_t name_len TSRMLS_DC)
{
- zval *output_handler;
+ php_output_handler_alias_ctor_t *func = NULL;
- ALLOC_INIT_ZVAL(output_handler);
- Z_STRLEN_P(output_handler) = len;
- Z_STRVAL_P(output_handler) = estrndup(handler_name, len);
- Z_TYPE_P(output_handler) = IS_STRING;
- return output_handler;
+ zend_hash_find(&php_output_handler_aliases, name, name_len+1, (void *) &func);
+ return func;
}
/* }}} */
-/* {{{ php_ob_init
- */
-static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
+/* {{{ SUCCESS|FAILURE php_output_handler_alias_register(zval *name, php_output_handler_alias_ctor_t func TSRMLS_DC)
+ * Registers an internal output handler as alias for a user handler */
+PHPAPI int php_output_handler_alias_register(const char *name, size_t name_len, php_output_handler_alias_ctor_t func TSRMLS_DC)
{
- int result = FAILURE, handler_len, len;
- char *handler_name, *next_handler_name;
- HashPosition pos;
- zval **tmp;
- zval *handler_zval;
-
- if (output_handler && output_handler->type == IS_STRING) {
- handler_name = Z_STRVAL_P(output_handler);
- handler_len = Z_STRLEN_P(output_handler);
-
- result = SUCCESS;
- if (handler_len && handler_name[0] != '\0') {
- while ((next_handler_name=strchr(handler_name, ',')) != NULL) {
- len = next_handler_name-handler_name;
- next_handler_name = estrndup(handler_name, len);
- handler_zval = php_ob_handler_from_string(next_handler_name, len TSRMLS_CC);
- result = php_ob_init_named(initial_size, block_size, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC);
- if (result != SUCCESS) {
- zval_dtor(handler_zval);
- FREE_ZVAL(handler_zval);
- }
- handler_name += len+1;
- handler_len -= len+1;
- efree(next_handler_name);
- }
- }
- if (result == SUCCESS) {
- handler_zval = php_ob_handler_from_string(handler_name, handler_len TSRMLS_CC);
- result = php_ob_init_named(initial_size, block_size, handler_name, handler_zval, chunk_size, erase TSRMLS_CC);
- if (result != SUCCESS) {
- zval_dtor(handler_zval);
- FREE_ZVAL(handler_zval);
- }
- }
- } else if (output_handler && output_handler->type == IS_ARRAY) {
- /* do we have array(object,method) */
- if (zend_is_callable(output_handler, 0, &handler_name TSRMLS_CC)) {
- SEPARATE_ZVAL(&output_handler);
- Z_ADDREF_P(output_handler);
- result = php_ob_init_named(initial_size, block_size, handler_name, output_handler, chunk_size, erase TSRMLS_CC);
- efree(handler_name);
- } else {
- efree(handler_name);
- /* init all array elements recursively */
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(output_handler), &pos);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(output_handler), (void **)&tmp, &pos) == SUCCESS) {
- result = php_ob_init(initial_size, block_size, *tmp, chunk_size, erase TSRMLS_CC);
- if (result == FAILURE) {
- break;
- }
- zend_hash_move_forward_ex(Z_ARRVAL_P(output_handler), &pos);
- }
- }
- } else if (output_handler && output_handler->type == IS_OBJECT) {
- /* do we have callable object */
- if (zend_is_callable(output_handler, 0, &handler_name TSRMLS_CC)) {
- SEPARATE_ZVAL(&output_handler);
- Z_ADDREF_P(output_handler);
- result = php_ob_init_named(initial_size, block_size, handler_name, output_handler, chunk_size, erase TSRMLS_CC);
- efree(handler_name);
- } else {
- efree(handler_name);
- php_error_docref(NULL TSRMLS_CC, E_ERROR, "No method name given: use ob_start(array($object,'method')) to specify instance $object and the name of a method of class %s to use as output handler", Z_OBJCE_P(output_handler)->name);
- result = FAILURE;
+ if (!EG(current_module)) {
+ zend_error(E_ERROR, "Cannot register an output handler alias outside of MINIT");
+ return FAILURE;
+ }
+ return zend_hash_update(&php_output_handler_aliases, name, name_len+1, &func, sizeof(php_output_handler_alias_ctor_t *), NULL);
+}
+/* }}} */
+
+/* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg TSMRLS_DC)
+ * Output handler hook for output handler functions to check/modify the current handlers abilities */
+PHPAPI int php_output_handler_hook(php_output_handler_hook_t type, void *arg TSRMLS_DC)
+{
+ if (OG(running)) {
+ switch (type) {
+ case PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ:
+ *(void ***) arg = &OG(running)->opaq;
+ return SUCCESS;
+ case PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS:
+ *(int *) arg = OG(running)->flags;
+ return SUCCESS;
+ case PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL:
+ *(int *) arg = OG(running)->level;
+ return SUCCESS;
+ case PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE:
+ OG(running)->flags &= ~(PHP_OUTPUT_HANDLER_REMOVABLE|PHP_OUTPUT_HANDLER_CLEANABLE);
+ return SUCCESS;
+ case PHP_OUTPUT_HANDLER_HOOK_DISABLE:
+ OG(running)->flags |= PHP_OUTPUT_HANDLER_DISABLED;
+ return SUCCESS;
+ default:
+ break;
}
+ }
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC)
+ * Destroy an output handler */
+PHPAPI void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC)
+{
+ STR_FREE(handler->name);
+ STR_FREE(handler->buffer.data);
+ if (handler->flags & PHP_OUTPUT_HANDLER_USER) {
+ zval_ptr_dtor(&handler->func.user->zoh);
+ efree(handler->func.user);
+ }
+ if (handler->dtor && handler->opaq) {
+ handler->dtor(handler->opaq TSRMLS_CC);
+ }
+ memset(handler, 0, sizeof(*handler));
+}
+/* }}} */
+
+/* {{{ void php_output_handler_free(php_output_handler **handler TSMRLS_DC)
+ * Destroy and free an output handler */
+PHPAPI void php_output_handler_free(php_output_handler **h TSRMLS_DC)
+{
+ if (*h) {
+ php_output_handler_dtor(*h TSRMLS_CC);
+ efree(*h);
+ *h = NULL;
+ }
+}
+/* }}} */
+
+/* void php_output_set_implicit_flush(int enabled TSRMLS_DC)
+ * Enable or disable implicit flush */
+PHPAPI void php_output_set_implicit_flush(int flush TSRMLS_DC)
+{
+ if (flush) {
+ OG(flags) |= PHP_OUTPUT_IMPLICITFLUSH;
} else {
- result = php_ob_init_named(initial_size, block_size, OB_DEFAULT_HANDLER_NAME, NULL, chunk_size, erase TSRMLS_CC);
+ OG(flags) &= ~PHP_OUTPUT_IMPLICITFLUSH;
}
- return result;
}
/* }}} */
-/* {{{ php_ob_list_each
- */
-static int php_ob_list_each(php_ob_buffer *ob_buffer, zval *ob_handler_array)
+/* {{{ char *php_output_get_start_filename(TSRMLS_D)
+ * Get the file name where output has started */
+PHPAPI const char *php_output_get_start_filename(TSRMLS_D)
{
- add_next_index_string(ob_handler_array, ob_buffer->handler_name, 1);
- return 0;
+ return OG(output_start_filename);
}
/* }}} */
-/* {{{ php_ob_used_each
- Sets handler_name to NULL is found */
-static int php_ob_handler_used_each(php_ob_buffer *ob_buffer, char **handler_name)
+/* {{{ int php_output_get_start_lineno(TSRMLS_D)
+ * Get the line number where output has started */
+PHPAPI int php_output_get_start_lineno(TSRMLS_D)
{
- if (!strcmp(ob_buffer->handler_name, *handler_name)) {
- *handler_name = NULL;
+ return OG(output_start_lineno);
+}
+/* }}} */
+
+/* {{{ static int php_output_lock_error(int op TSRMLS_DC)
+ * Checks whether an unallowed operation is attempted from within the output handler and issues a fatal error */
+static inline int php_output_lock_error(int op TSRMLS_DC)
+{
+ /* if there's no ob active, ob has been stopped */
+ if (op && OG(active) && OG(running)) {
+ /* fatal error */
+ php_output_deactivate(TSRMLS_C);
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_ERROR, "Cannot use output buffering in output buffering display handlers");
return 1;
}
return 0;
}
/* }}} */
-/* {{{ php_ob_used
- returns 1 if given handler_name is used as output_handler */
-PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC)
+/* {{{ static php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC)
+ * Initialize a new output context */
+static inline php_output_context *php_output_context_init(php_output_context *context, int op TSRMLS_DC)
{
- char *tmp = handler_name;
+ if (!context) {
+ context = emalloc(sizeof(php_output_context));
+ }
- if (OG(ob_nesting_level)) {
- if (!strcmp(OG(active_ob_buffer).handler_name, handler_name)) {
- return 1;
+ memset(context, 0, sizeof(php_output_context));
+ TSRMLS_SET_CTX(context->tsrm_ls);
+ context->op = op;
+
+ return context;
+}
+/* }}} */
+
+/* {{{ static void php_output_context_reset(php_output_context *context)
+ * Reset an output context */
+static inline void php_output_context_reset(php_output_context *context)
+{
+ int op = context->op;
+ php_output_context_dtor(context);
+ memset(context, 0, sizeof(php_output_context));
+ context->op = op;
+}
+/* }}} */
+
+/* {{{ static void php_output_context_feed(php_output_context *context, char *, size_t, size_t)
+ * Feed output contexts input buffer */
+static inline void php_output_context_feed(php_output_context *context, char *data, size_t size, size_t used, zend_bool free)
+{
+ if (context->in.free && context->in.data) {
+ efree(context->in.data);
+ }
+ context->in.data = data;
+ context->in.used = used;
+ context->in.free = free;
+ context->in.size = size;
+}
+/* }}} */
+
+/* {{{ static void php_output_context_swap(php_output_context *context)
+ * Swap output contexts buffers */
+static inline void php_output_context_swap(php_output_context *context)
+{
+ if (context->in.free && context->in.data) {
+ efree(context->in.data);
+ }
+ context->in.data = context->out.data;
+ context->in.used = context->out.used;
+ context->in.free = context->out.free;
+ context->in.size = context->out.size;
+ context->out.data = NULL;
+ context->out.used = 0;
+ context->out.free = 0;
+ context->out.size = 0;
+}
+/* }}} */
+
+/* {{{ static void php_output_context_pass(php_output_context *context)
+ * Pass input to output buffer */
+static inline void php_output_context_pass(php_output_context *context)
+{
+ context->out.data = context->in.data;
+ context->out.used = context->in.used;
+ context->out.size = context->in.size;
+ context->out.free = context->in.free;
+ context->in.data = NULL;
+ context->in.used = 0;
+ context->in.free = 0;
+ context->in.size = 0;
+}
+/* }}} */
+
+/* {{{ static void php_output_context_dtor(php_output_context *context)
+ * Destroy the contents of an output context */
+static inline void php_output_context_dtor(php_output_context *context)
+{
+ if (context->in.free && context->in.data) {
+ efree(context->in.data);
+ context->in.data = NULL;
+ }
+ if (context->out.free && context->out.data) {
+ efree(context->out.data);
+ context->out.data = NULL;
+ }
+}
+/* }}} */
+
+/* {{{ static php_output_handler *php_output_handler_init(zval *name, size_t chunk_size, int flags TSRMLS_DC)
+ * Allocates and initializes a php_output_handler structure */
+static inline php_output_handler *php_output_handler_init(const char *name, size_t name_len, size_t chunk_size, int flags TSRMLS_DC)
+{
+ php_output_handler *handler;
+
+ handler = ecalloc(1, sizeof(php_output_handler));
+ handler->name = estrndup(name, name_len);
+ handler->name_len = name_len;
+ handler->size = chunk_size;
+ handler->flags = flags;
+ handler->buffer.size = PHP_OUTPUT_HANDLER_INITBUF_SIZE(chunk_size);
+ handler->buffer.data = emalloc(handler->buffer.size);
+
+ return handler;
+}
+/* }}} */
+
+/* {{{ static int php_output_handler_appen(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC)
+ * Appends input to the output handlers buffer and indicates whether the buffer does not have to be processed by the output handler */
+static inline int php_output_handler_append(php_output_handler *handler, const php_output_buffer *buf TSRMLS_DC)
+{
+ if (buf->used) {
+ OG(flags) |= PHP_OUTPUT_WRITTEN;
+ /* store it away */
+ if ((handler->buffer.size - handler->buffer.used) <= buf->used) {
+ size_t grow_int = PHP_OUTPUT_HANDLER_INITBUF_SIZE(handler->size);
+ size_t grow_buf = PHP_OUTPUT_HANDLER_INITBUF_SIZE(buf->used - (handler->buffer.size - handler->buffer.used));
+ size_t grow_max = MAX(grow_int, grow_buf);
+
+ handler->buffer.data = erealloc(handler->buffer.data, handler->buffer.size + grow_max);
+ handler->buffer.size += grow_max;
}
- if (OG(ob_nesting_level)>1) {
- zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_ob_handler_used_each, &tmp);
+ memcpy(handler->buffer.data + handler->buffer.used, buf->data, buf->used);
+ handler->buffer.used += buf->used;
+
+ /* chunked buffering */
+ if (handler->size && (handler->buffer.used >= handler->size)) {
+ /* store away errors and/or any intermediate output */
+ return OG(running) ? 1 : 0;
}
}
- return tmp ? 0 : 1;
+ return 1;
}
/* }}} */
-/* {{{ php_ob_append
- */
-static inline void php_ob_append(const char *text, uint text_length TSRMLS_DC)
+/* {{{ static php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context)
+ * Output handler operation dispatcher, applying context op to the php_output_handler handler */
+static inline php_output_handler_status_t php_output_handler_op(php_output_handler *handler, php_output_context *context)
{
- char *target;
- int original_ob_text_length;
+ php_output_handler_status_t status;
+ int original_op = context->op;
+ PHP_OUTPUT_TSRMLS(context);
+
+#if PHP_OUTPUT_DEBUG
+ fprintf(stderr, ">>> op(%d, "
+ "handler=%p, "
+ "name=%s, "
+ "flags=%d, "
+ "buffer.data=%s, "
+ "buffer.used=%zu, "
+ "buffer.size=%zu, "
+ "in.data=%s, "
+ "in.used=%zu)\n",
+ context->op,
+ handler,
+ handler->name,
+ handler->flags,
+ handler->buffer.used?handler->buffer.data:"",
+ handler->buffer.used,
+ handler->buffer.size,
+ context->in.used?context->in.data:"",
+ context->in.used
+ );
+#endif
- original_ob_text_length=OG(active_ob_buffer).text_length;
+ if (php_output_lock_error(context->op TSRMLS_CC)) {
+ /* fatal error */
+ return PHP_OUTPUT_HANDLER_FAILURE;
+ }
+
+ /* storable? */
+ if (php_output_handler_append(handler, &context->in TSRMLS_CC) && !context->op) {
+ context->op = original_op;
+ return PHP_OUTPUT_HANDLER_NO_DATA;
+ } else {
+ /* need to start? */
+ if (!(handler->flags & PHP_OUTPUT_HANDLER_STARTED)) {
+ context->op |= PHP_OUTPUT_HANDLER_START;
+ }
- php_ob_allocate(text_length TSRMLS_CC);
- target = OG(active_ob_buffer).buffer+original_ob_text_length;
- memcpy(target, text, text_length);
- target[text_length]=0;
+ OG(running) = handler;
+ if (handler->flags & PHP_OUTPUT_HANDLER_USER) {
+ zval *retval = NULL, *ob_data, *ob_mode;
+
+ MAKE_STD_ZVAL(ob_data);
+ ZVAL_STRINGL(ob_data, handler->buffer.data, handler->buffer.used, 1);
+ MAKE_STD_ZVAL(ob_mode);
+ ZVAL_LONG(ob_mode, (long) context->op);
+ zend_fcall_info_argn(&handler->func.user->fci TSRMLS_CC, 2, &ob_data, &ob_mode);
+
+#define PHP_OUTPUT_USER_SUCCESS(retval) (retval && !(Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval)==0))
+ if (SUCCESS == zend_fcall_info_call(&handler->func.user->fci, &handler->func.user->fcc, &retval, NULL TSRMLS_CC) && PHP_OUTPUT_USER_SUCCESS(retval)) {
+ /* user handler may have returned TRUE */
+ status = PHP_OUTPUT_HANDLER_NO_DATA;
+ if (Z_TYPE_P(retval) != IS_BOOL) {
+ convert_to_string_ex(&retval);
+ if (Z_STRLEN_P(retval)) {
+ context->out.data = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+ context->out.used = Z_STRLEN_P(retval);
+ context->out.free = 1;
+ status = PHP_OUTPUT_HANDLER_SUCCESS;
+ }
+ }
+ } else {
+ /* call failed, pass internal buffer along */
+ status = PHP_OUTPUT_HANDLER_FAILURE;
+ }
- /* If implicit_flush is On or chunked buffering, send contents to next buffer and return. */
- if (OG(active_ob_buffer).chunk_size
- && OG(active_ob_buffer).text_length >= OG(active_ob_buffer).chunk_size) {
+ zend_fcall_info_argn(&handler->func.user->fci TSRMLS_CC, 0);
+ zval_ptr_dtor(&ob_data);
+ zval_ptr_dtor(&ob_mode);
+ if (retval) {
+ zval_ptr_dtor(&retval);
+ }
- php_end_ob_buffer(1, 1 TSRMLS_CC);
- return;
+ } else {
+
+ php_output_context_feed(context, handler->buffer.data, handler->buffer.size, handler->buffer.used, 0);
+
+ if (SUCCESS == handler->func.internal(&handler->opaq, context)) {
+ if (context->out.used) {
+ status = PHP_OUTPUT_HANDLER_SUCCESS;
+ } else {
+ status = PHP_OUTPUT_HANDLER_NO_DATA;
+ }
+ } else {
+ status = PHP_OUTPUT_HANDLER_FAILURE;
+ }
+ }
+ handler->flags |= PHP_OUTPUT_HANDLER_STARTED;
+ OG(running) = NULL;
}
+
+ switch (status) {
+ case PHP_OUTPUT_HANDLER_FAILURE:
+ /* disable this handler */
+ handler->flags |= PHP_OUTPUT_HANDLER_DISABLED;
+ /* discard any output */
+ if (context->out.data && context->out.free) {
+ efree(context->out.data);
+ }
+ /* returns handlers buffer */
+ context->out.data = handler->buffer.data;
+ context->out.used = handler->buffer.used;
+ context->out.free = 1;
+ handler->buffer.data = NULL;
+ handler->buffer.used = 0;
+ handler->buffer.size = 0;
+ break;
+ case PHP_OUTPUT_HANDLER_NO_DATA:
+ /* handler ate all */
+ php_output_context_reset(context);
+ /* no break */
+ case PHP_OUTPUT_HANDLER_SUCCESS:
+ /* no more buffered data */
+ handler->buffer.used = 0;
+ handler->flags |= PHP_OUTPUT_HANDLER_PROCESSED;
+ break;
+ }
+
+ context->op = original_op;
+ return status;
}
/* }}} */
-#if 0
-static inline void php_ob_prepend(const char *text, uint text_length)
+
+/* {{{ static void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
+ * Output op dispatcher, passes input and output handlers output through the output handler stack until it gets written to the SAPI */
+static inline void php_output_op(int op, const char *str, size_t len TSRMLS_DC)
{
- char *p, *start;
- TSRMLS_FETCH();
+ php_output_context context;
+ php_output_handler **active;
+ int obh_cnt;
+
+ if (php_output_lock_error(op TSRMLS_CC)) {
+ return;
+ }
- php_ob_allocate(text_length TSRMLS_CC);
+ php_output_context_init(&context, op TSRMLS_CC);
- /* php_ob_allocate() may change OG(ob_buffer), so we can't initialize p&start earlier */
- p = OG(ob_buffer)+OG(ob_text_length);
- start = OG(ob_buffer);
+ /*
+ * broken up for better performance:
+ * - apply op to the one active handler; note that OG(active) might be popped off the stack on a flush
+ * - or apply op to the handler stack
+ */
+ if (OG(active) && (obh_cnt = zend_stack_count(&OG(handlers)))) {
+ context.in.data = (char *) str;
+ context.in.used = len;
- while (--p>=start) {
- p[text_length] = *p;
+ if (obh_cnt > 1) {
+ zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_TOPDOWN, php_output_stack_apply_op, &context);
+ } else if ((SUCCESS == zend_stack_top(&OG(handlers), (void *) &active)) && (!((*active)->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
+ php_output_handler_op(*active, &context);
+ } else {
+ php_output_context_pass(&context);
+ }
+ } else {
+ context.out.data = (char *) str;
+ context.out.used = len;
}
- memcpy(OG(ob_buffer), text, text_length);
- OG(ob_buffer)[OG(active_ob_buffer).text_length]=0;
-}
+
+ if (context.out.data && context.out.used) {
+ php_output_header(TSRMLS_C);
+
+ if (!(OG(flags) & PHP_OUTPUT_DISABLED)) {
+#if PHP_OUTPUT_DEBUG
+ fprintf(stderr, "::: sapi_write('%s', %zu)\n", context.out.data, context.out.used);
#endif
+ sapi_module.ub_write(context.out.data, context.out.used TSRMLS_CC);
-/* {{{ php_ob_get_buffer
- * Return the current output buffer */
-PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC)
-{
- if (OG(ob_nesting_level)==0) {
- return FAILURE;
+ if (OG(flags) & PHP_OUTPUT_IMPLICITFLUSH) {
+ sapi_flush(TSRMLS_C);
+ }
+
+ OG(flags) |= PHP_OUTPUT_SENT;
+ }
}
- ZVAL_STRINGL(p, OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length, 1);
- return SUCCESS;
+ php_output_context_dtor(&context);
}
/* }}} */
-/* {{{ php_ob_get_length
- * Return the size of the current output buffer */
-PHPAPI int php_ob_get_length(zval *p TSRMLS_DC)
+/* {{{ static int php_output_stack_apply_op(void *h, void *c)
+ * Operation callback for the stack apply function */
+static int php_output_stack_apply_op(void *h, void *c)
{
- if (OG(ob_nesting_level) == 0) {
- return FAILURE;
+ int was_disabled;
+ php_output_handler_status_t status;
+ php_output_handler *handler = *(php_output_handler **) h;
+ php_output_context *context = (php_output_context *) c;
+
+ if ((was_disabled = (handler->flags & PHP_OUTPUT_HANDLER_DISABLED))) {
+ status = PHP_OUTPUT_HANDLER_FAILURE;
+ } else {
+ status = php_output_handler_op(handler, context);
+ }
+
+ /*
+ * handler ate all => break
+ * handler returned data or failed resp. is disabled => continue
+ */
+ switch (status) {
+ case PHP_OUTPUT_HANDLER_NO_DATA:
+ return 1;
+
+ case PHP_OUTPUT_HANDLER_SUCCESS:
+ /* swap contexts buffers, unless this is the last handler in the stack */
+ if (handler->level) {
+ php_output_context_swap(context);
+ }
+ return 0;
+
+ case PHP_OUTPUT_HANDLER_FAILURE:
+ default:
+ if (was_disabled) {
+ /* pass input along, if it's the last handler in the stack */
+ if (!handler->level) {
+ php_output_context_pass(context);
+ }
+ } else {
+ /* swap buffers, unless this is the last handler */
+ if (handler->level) {
+ php_output_context_swap(context);
+ }
+ }
+ return 0;
}
- ZVAL_LONG(p, OG(active_ob_buffer).text_length);
- return SUCCESS;
}
/* }}} */
-/*
- * Wrapper functions - implementation
- */
+/* {{{ static int php_output_stack_apply_clean(void *h, void *c)
+ * Clean callback for the stack apply function */
+static int php_output_stack_apply_clean(void *h, void *c)
+{
+ php_output_handler *handler = *(php_output_handler **) h;
+ php_output_context *context = (php_output_context *) c;
+
+ handler->buffer.used = 0;
+ php_output_handler_op(handler, context);
+ php_output_context_reset(context);
+ return 0;
+}
+/* }}} */
-/* buffered output function */
-static int php_b_body_write(const char *str, uint str_length TSRMLS_DC)
+/* {{{ static int php_output_stack_apply_list(void *h, void *z)
+ * List callback for the stack apply function */
+static int php_output_stack_apply_list(void *h, void *z)
{
- php_ob_append(str, str_length TSRMLS_CC);
- return str_length;
+ php_output_handler *handler = *(php_output_handler **) h;
+ zval *array = (zval *) z;
+
+ add_next_index_stringl(array, handler->name, handler->name_len, 1);
+ return 0;
}
+/* }}} */
-/* {{{ php_ub_body_write_no_header
- */
-PHPAPI int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC)
+/* {{{ static int php_output_stack_apply_status(void *h, void *z)
+ * Status callback for the stack apply function */
+static int php_output_stack_apply_status(void *h, void *z)
{
- int result;
+ php_output_handler *handler = *(php_output_handler **) h;
+ zval *array = (zval *) z;
- if (OG(disable_output)) {
- return 0;
- }
+ add_next_index_zval(array, php_output_handler_status(handler, NULL));
- result = OG(php_header_write)(str, str_length TSRMLS_CC);
+ return 0;
+}
- if (OG(implicit_flush)) {
- sapi_flush(TSRMLS_C);
+/* {{{ static zval *php_output_handler_status(php_output_handler *handler, zval *entry)
+ * Returns an array with the status of the output handler */
+static inline zval *php_output_handler_status(php_output_handler *handler, zval *entry)
+{
+ if (!entry) {
+ MAKE_STD_ZVAL(entry);
+ array_init(entry);
}
- return result;
+ add_assoc_stringl(entry, "name", handler->name, handler->name_len, 1);
+ add_assoc_long(entry, "type", (long) (handler->flags & 0xf));
+ add_assoc_long(entry, "flags", (long) handler->flags);
+ add_assoc_long(entry, "level", (long) handler->level);
+ add_assoc_long(entry, "chunk_size", (long) handler->size);
+ add_assoc_long(entry, "buffer_size", (long) handler->buffer.size);
+ add_assoc_long(entry, "buffer_used", (long) handler->buffer.used);
+
+ return entry;
}
/* }}} */
-/* {{{ php_ub_body_write
- */
-PHPAPI int php_ub_body_write(const char *str, uint str_length TSRMLS_DC)
+/* {{{ static int php_output_stack_pop(int flags TSRMLS_DC)
+ * Pops an output handler off the stack */
+static inline int php_output_stack_pop(int flags TSRMLS_DC)
{
- int result = 0;
+ php_output_context context;
+ php_output_handler **current, *orphan = OG(active);
- if (SG(request_info).headers_only) {
- if(SG(headers_sent)) {
- return 0;
+ if (!orphan) {
+ if (!(flags & PHP_OUTPUT_POP_SILENT)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to %s buffer. No buffer to %s", (flags&PHP_OUTPUT_POP_DISCARD)?"discard":"send", (flags&PHP_OUTPUT_POP_DISCARD)?"discard":"send");
+ }
+ return 0;
+ } else if (!(flags & PHP_OUTPUT_POP_FORCE) && !(orphan->flags & PHP_OUTPUT_HANDLER_REMOVABLE)) {
+ if (!(flags & PHP_OUTPUT_POP_SILENT)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to %s buffer of %s (%d)", (flags&PHP_OUTPUT_POP_DISCARD)?"discard":"send", orphan->name, orphan->level);
+ }
+ return 0;
+ } else {
+ php_output_context_init(&context, PHP_OUTPUT_HANDLER_FINAL TSRMLS_CC);
+
+ /* don't run the output handler if it's disabled */
+ if (!(orphan->flags & PHP_OUTPUT_HANDLER_DISABLED)) {
+ /* didn't it start yet? */
+ if (!(orphan->flags & PHP_OUTPUT_HANDLER_STARTED)) {
+ context.op |= PHP_OUTPUT_HANDLER_START;
+ }
+ /* signal that we're cleaning up */
+ if (flags & PHP_OUTPUT_POP_DISCARD) {
+ context.op |= PHP_OUTPUT_HANDLER_CLEAN;
+ orphan->buffer.used = 0;
+ }
+ php_output_handler_op(orphan, &context);
+ }
+
+ /* pop it off the stack */
+ zend_stack_del_top(&OG(handlers));
+ if (SUCCESS == zend_stack_top(&OG(handlers), (void *) &current)) {
+ OG(active) = *current;
+ } else {
+ OG(active) = NULL;
}
- php_header(TSRMLS_C);
- zend_bailout();
- }
- if (php_header(TSRMLS_C)) {
- if (zend_is_compiling(TSRMLS_C)) {
- OG(output_start_filename) = zend_get_compiled_filename(TSRMLS_C);
- OG(output_start_lineno) = zend_get_compiled_lineno(TSRMLS_C);
- } else if (zend_is_executing(TSRMLS_C)) {
- OG(output_start_filename) = zend_get_executed_filename(TSRMLS_C);
- OG(output_start_lineno) = zend_get_executed_lineno(TSRMLS_C);
+
+ /* pass output along */
+ if (context.out.data && context.out.used && !(flags & PHP_OUTPUT_POP_DISCARD)) {
+ php_output_write(context.out.data, context.out.used TSRMLS_CC);
}
- OG(php_body_write) = php_ub_body_write_no_header;
- result = php_ub_body_write_no_header(str, str_length TSRMLS_CC);
- }
+ /* destroy the handler (after write!) */
+ php_output_handler_free(&orphan TSRMLS_CC);
+ php_output_context_dtor(&context);
- return result;
+ return 1;
+ }
}
/* }}} */
-/* {{{ int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result)
- */
-static int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result)
+/* {{{ static SUCCESS|FAILURE php_output_handler_compat_func(void *ctx, php_output_context *)
+ * php_output_handler_context_func_t for php_output_handler_func_t output handlers */
+static int php_output_handler_compat_func(void **handler_context, php_output_context *output_context)
{
- zval *elem;
+ php_output_handler_func_t func = *(php_output_handler_func_t *) handler_context;
+ PHP_OUTPUT_TSRMLS(output_context);
- MAKE_STD_ZVAL(elem);
- array_init(elem);
+ if (func) {
+ char *out_str = NULL;
+ uint out_len = 0;
- add_assoc_long(elem, "chunk_size", ob_buffer->chunk_size);
- if (!ob_buffer->chunk_size) {
- add_assoc_long(elem, "size", ob_buffer->size);
- add_assoc_long(elem, "block_size", ob_buffer->block_size);
- }
- if (ob_buffer->internal_output_handler) {
- add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_INTERNAL);
- add_assoc_long(elem, "buffer_size", ob_buffer->internal_output_handler_buffer_size);
- } else {
- add_assoc_long(elem, "type", PHP_OUTPUT_HANDLER_USER);
+ func(output_context->in.data, output_context->in.used, &out_str, &out_len, output_context->op TSRMLS_CC);
+
+ if (out_str) {
+ output_context->out.data = out_str;
+ output_context->out.used = out_len;
+ output_context->out.free = 1;
+ } else {
+ php_output_context_pass(output_context);
+ }
+
+ return SUCCESS;
}
- add_assoc_long(elem, "status", ob_buffer->status);
- add_assoc_string(elem, "name", ob_buffer->handler_name, 1);
- add_assoc_bool(elem, "del", ob_buffer->erase);
- add_next_index_zval(result, elem);
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ static SUCCESS|FAILURE php_output_handler_default_func(void *ctx, php_output_context *)
+ * Default output handler */
+static int php_output_handler_default_func(void **handler_context, php_output_context *output_context)
+{
+ php_output_context_pass(output_context);
+ return SUCCESS;
+}
+/* }}} */
+/* {{{ static SUCCESS|FAILURE php_output_handler_devnull_func(void *ctx, php_output_context *)
+ * Null output handler */
+static int php_output_handler_devnull_func(void **handler_context, php_output_context *output_context)
+{
return SUCCESS;
}
/* }}} */
@@ -764,15 +1301,15 @@ static int php_ob_buffer_status(php_ob_buffer *ob_buffer, zval *result)
* USERLAND (nearly 1:1 of old output.c)
*/
-/* {{{ proto bool ob_start([string|array user_function [, int chunk_size [, bool erase]]])
+/* {{{ proto bool ob_start([string|array user_function [, int chunk_size [, int flags]]])
Turn on Output Buffering (specifying an optional output handler). */
PHP_FUNCTION(ob_start)
{
zval *output_handler = NULL;
long chunk_size = 0;
- zend_bool erase = 1;
+ long flags = PHP_OUTPUT_HANDLER_STDFLAGS;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/lb", &output_handler, &chunk_size, &erase) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/ll", &output_handler, &chunk_size, &flags) == FAILURE) {
return;
}
@@ -780,7 +1317,8 @@ PHP_FUNCTION(ob_start)
chunk_size = 0;
}
- if (php_start_ob_buffer(output_handler, chunk_size, erase TSRMLS_CC) == FAILURE) {
+ if (php_output_start_user(output_handler, chunk_size, flags TSRMLS_CC) == FAILURE) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to create buffer");
RETURN_FALSE;
}
RETURN_TRUE;
@@ -795,17 +1333,15 @@ PHP_FUNCTION(ob_flush)
return;
}
- if (!OG(ob_nesting_level)) {
+ if (!OG(active)) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer. No buffer to flush");
RETURN_FALSE;
}
- if (!OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer %s", OG(active_ob_buffer).handler_name);
+ if (SUCCESS != php_output_flush(TSRMLS_C)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to flush buffer of %s (%d)", OG(active)->name, OG(active)->level);
RETURN_FALSE;
}
-
- php_end_ob_buffer(1, 1 TSRMLS_CC);
RETURN_TRUE;
}
/* }}} */
@@ -818,17 +1354,15 @@ PHP_FUNCTION(ob_clean)
return;
}
- if (!OG(ob_nesting_level)) {
+ if (!OG(active)) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
RETURN_FALSE;
}
- if (!OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
+ if (SUCCESS != php_output_clean(TSRMLS_C)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer of %s (%d)", OG(active)->name, OG(active)->level);
RETURN_FALSE;
}
-
- php_end_ob_buffer(0, 1 TSRMLS_CC);
RETURN_TRUE;
}
/* }}} */
@@ -841,18 +1375,12 @@ PHP_FUNCTION(ob_end_flush)
return;
}
- if (!OG(ob_nesting_level)) {
+ if (!OG(active)) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush");
RETURN_FALSE;
}
- if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
- RETURN_FALSE;
- }
-
- php_end_ob_buffer(1, 0 TSRMLS_CC);
- RETURN_TRUE;
+ RETURN_BOOL(SUCCESS == php_output_end(TSRMLS_C));
}
/* }}} */
@@ -864,18 +1392,12 @@ PHP_FUNCTION(ob_end_clean)
return;
}
- if (!OG(ob_nesting_level)) {
+ if (!OG(active)) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
RETURN_FALSE;
}
- if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
- RETURN_FALSE;
- }
-
- php_end_ob_buffer(0, 0 TSRMLS_CC);
- RETURN_TRUE;
+ RETURN_BOOL(SUCCESS == php_output_discard(TSRMLS_C));
}
/* }}} */
@@ -887,23 +1409,14 @@ PHP_FUNCTION(ob_get_flush)
return;
}
- if (php_ob_get_buffer(return_value TSRMLS_CC) == FAILURE) {
- RETURN_FALSE;
- }
-
- if (!OG(ob_nesting_level)) {
+ if (php_output_get_contents(return_value TSRMLS_CC) == FAILURE) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete and flush buffer. No buffer to delete or flush");
- zval_dtor(return_value);
RETURN_FALSE;
}
- if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
- zval_dtor(return_value);
- RETURN_FALSE;
+ if (SUCCESS != php_output_end(TSRMLS_C)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer of %s (%d)", OG(active)->name, OG(active)->level);
}
-
- php_end_ob_buffer(1, 0 TSRMLS_CC);
}
/* }}} */
@@ -915,22 +1428,18 @@ PHP_FUNCTION(ob_get_clean)
return;
}
- if (php_ob_get_buffer(return_value TSRMLS_CC) == FAILURE) {
+ if(!OG(active)) {
RETURN_FALSE;
}
- if (!OG(ob_nesting_level)) {
+ if (php_output_get_contents(return_value TSRMLS_CC) == FAILURE) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
- zval_dtor(return_value);
- RETURN_FALSE;
- }
- if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
- php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
- zval_dtor(return_value);
RETURN_FALSE;
}
- php_end_ob_buffer(0, 0 TSRMLS_CC);
+ if (SUCCESS != php_output_discard(TSRMLS_C)) {
+ php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer of %s (%d)", OG(active)->name, OG(active)->level);
+ }
}
/* }}} */
@@ -942,7 +1451,7 @@ PHP_FUNCTION(ob_get_contents)
return;
}
- if (php_ob_get_buffer(return_value TSRMLS_CC) == FAILURE) {
+ if (php_output_get_contents(return_value TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
@@ -956,7 +1465,7 @@ PHP_FUNCTION(ob_get_level)
return;
}
- RETURN_LONG(OG(ob_nesting_level));
+ RETURN_LONG(php_output_get_level(TSRMLS_C));
}
/* }}} */
@@ -968,7 +1477,7 @@ PHP_FUNCTION(ob_get_length)
return;
}
- if (php_ob_get_length(return_value TSRMLS_CC) == FAILURE) {
+ if (php_output_get_length(return_value TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
@@ -984,12 +1493,11 @@ PHP_FUNCTION(ob_list_handlers)
array_init(return_value);
- if (OG(ob_nesting_level)) {
- if (OG(ob_nesting_level) > 1) {
- zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_ob_list_each, return_value);
- }
- php_ob_list_each(&OG(active_ob_buffer), return_value);
+ if (!OG(active)) {
+ return;
}
+
+ zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_list, return_value);
}
/* }}} */
@@ -1005,23 +1513,14 @@ PHP_FUNCTION(ob_get_status)
array_init(return_value);
+ if (!OG(active)) {
+ return;
+ }
+
if (full_status) {
- if (OG(ob_nesting_level) > 1) {
- zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *elem, void *))php_ob_buffer_status, return_value);
- }
- if (OG(ob_nesting_level) > 0 && php_ob_buffer_status(&OG(active_ob_buffer), return_value) == FAILURE) {
- RETURN_FALSE;
- }
- } else if (OG(ob_nesting_level) > 0) {
- add_assoc_long(return_value, "level", OG(ob_nesting_level));
- if (OG(active_ob_buffer).internal_output_handler) {
- add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_INTERNAL);
- } else {
- add_assoc_long(return_value, "type", PHP_OUTPUT_HANDLER_USER);
- }
- add_assoc_long(return_value, "status", OG(active_ob_buffer).status);
- add_assoc_string(return_value, "name", OG(active_ob_buffer).handler_name, 1);
- add_assoc_bool(return_value, "del", OG(active_ob_buffer).erase);
+ zend_stack_apply_with_argument(&OG(handlers), ZEND_STACK_APPLY_BOTTOMUP, php_output_stack_apply_status, return_value);
+ } else {
+ php_output_handler_status(OG(active), return_value);
}
}
/* }}} */
@@ -1036,11 +1535,7 @@ PHP_FUNCTION(ob_implicit_flush)
return;
}
- if (flag) {
- php_start_implicit_flush(TSRMLS_C);
- } else {
- php_end_implicit_flush(TSRMLS_C);
- }
+ php_output_set_implicit_flush(flag TSRMLS_CC);
}
/* }}} */
diff --git a/main/php.h b/main/php.h
index 497439d17a..2a93118ac6 100644
--- a/main/php.h
+++ b/main/php.h
@@ -26,7 +26,7 @@
#include <dmalloc.h>
#endif
-#define PHP_API_VERSION 20090626
+#define PHP_API_VERSION 20100412
#define PHP_HAVE_STREAMS
#define YYDEBUG 0
@@ -60,6 +60,7 @@
# else
# define PHPAPI
# endif
+
# define THREAD_LS
# define PHP_DIR_SEPARATOR '/'
# define PHP_EOL "\n"
@@ -142,7 +143,11 @@ END_EXTERN_C()
#endif
#ifndef HAVE_SOCKLEN_T
+# if PHP_WIN32
+typedef int socklen_t;
+# else
typedef unsigned int socklen_t;
+# endif
#endif
#define CREATE_MUTEX(a, b)
@@ -177,7 +182,6 @@ typedef unsigned int socklen_t;
#endif
#include "zend_hash.h"
-#include "php3_compat.h"
#include "zend_alloc.h"
#include "zend_stack.h"
@@ -192,8 +196,6 @@ typedef unsigned int socklen_t;
# endif
#endif
-#include "safe_mode.h"
-
#ifndef HAVE_STRERROR
char *strerror(int);
#endif
@@ -253,6 +255,11 @@ END_EXTERN_C()
# endif
#endif
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define php_ignore_value(x) (({ __typeof__ (x) __x = (x); (void) __x; }))
+#else
+# define php_ignore_value(x) ((void) (x))
+#endif
/* global variables */
#if !defined(PHP_WIN32)
@@ -274,6 +281,7 @@ void phperror(char *error);
PHPAPI int php_write(void *buf, uint size TSRMLS_DC);
PHPAPI int php_printf(const char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 1,
2);
+PHPAPI int php_get_module_initialized(void);
PHPAPI void php_log_err(char *log_message TSRMLS_DC);
int Debug(char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 1, 2);
int cfgparse(void);
@@ -327,6 +335,7 @@ PHPAPI int php_register_internal_extensions(TSRMLS_D);
PHPAPI int php_mergesort(void *base, size_t nmemb, register size_t size, int (*cmp)(const void *, const void * TSRMLS_DC) TSRMLS_DC);
PHPAPI void php_register_pre_request_shutdown(void (*func)(void *), void *userdata);
PHPAPI void php_com_initialize(TSRMLS_D);
+PHPAPI char *php_get_current_user(TSRMLS_D);
END_EXTERN_C()
/* PHP-named Zend macro wrappers */
@@ -382,20 +391,7 @@ END_EXTERN_C()
/* Output support */
#include "main/php_output.h"
-#define PHPWRITE(str, str_len) php_body_write((str), (str_len) TSRMLS_CC)
-#define PUTS(str) do { \
- const char *__str = (str); \
- php_body_write(__str, strlen(__str) TSRMLS_CC); \
-} while (0)
-
-#define PUTC(c) (php_body_write(&(c), 1 TSRMLS_CC), (c))
-#define PHPWRITE_H(str, str_len) php_header_write((str), (str_len) TSRMLS_CC)
-#define PUTS_H(str) do { \
- const char *__str = (str); \
- php_header_write(__str, strlen(__str) TSRMLS_CC); \
-} while (0)
-
-#define PUTC_H(c) (php_header_write(&(c), 1 TSRMLS_CC), (c))
+
#include "php_streams.h"
#include "php_memory_streams.h"
diff --git a/main/php3_compat.h b/main/php3_compat.h
deleted file mode 100644
index 3b9e710385..0000000000
--- a/main/php3_compat.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-#ifndef PHP3_COMPAT_H
-#define PHP3_COMPAT_H
-
-typedef zval pval;
-
-#define pval_copy_constructor zval_copy_ctor
-#define pval_destructor zval_dtor
-
-#define _php3_hash_init zend_hash_init
-#define _php3_hash_destroy zend_hash_destroy
-
-#define _php3_hash_clean zend_hash_clean
-
-#define _php3_hash_add_or_update zend_hash_add_or_update
-#define _php3_hash_add zend_hash_add
-#define _php3_hash_update zend_hash_update
-
-#define _php3_hash_quick_add_or_update zend_hash_quick_add_or_update
-#define _php3_hash_quick_add zend_hash_quick_add
-#define _php3_hash_quick_update zend_hash_quick_update
-
-#define _php3_hash_index_update_or_next_insert zend_hash_index_update_or_next_insert
-#define _php3_hash_index_update zend_hash_index_update
-#define _php3_hash_next_index_insert zend_hash_next_index_insert
-
-#define _php3_hash_pointer_update zend_hash_pointer_update
-
-#define _php3_hash_pointer_index_update_or_next_insert zend_hash_pointer_index_update_or_next_insert
-#define _php3_hash_pointer_index_update zend_hash_pointer_index_update
-#define _php3_hash_next_index_pointer_update zend_hash_next_index_pointer_update
-#define _php3_hash_next_index_pointer_insert zend_hash_next_index_pointer_insert
-
-#define _php3_hash_del_key_or_index zend_hash_del_key_or_index
-#define _php3_hash_del zend_hash_del
-#define _php3_hash_index_del zend_hash_index_del
-
-#define _php3_hash_find zend_hash_find
-#define _php3_hash_quick_find zend_hash_quick_find
-#define _php3_hash_index_find zend_hash_index_find
-
-#define _php3_hash_exists zend_hash_exists
-#define _php3_hash_index_exists zend_hash_index_exists
-#define _php3_hash_is_pointer zend_hash_is_pointer
-#define _php3_hash_index_is_pointer zend_hash_index_is_pointer
-#define _php3_hash_next_free_element zend_hash_next_free_element
-
-#define _php3_hash_move_forward zend_hash_move_forward
-#define _php3_hash_move_backwards zend_hash_move_backwards
-#define _php3_hash_get_current_key zend_hash_get_current_key
-#define _php3_hash_get_current_data zend_hash_get_current_data
-#define _php3_hash_internal_pointer_reset zend_hash_internal_pointer_reset
-#define _php3_hash_internal_pointer_end zend_hash_internal_pointer_end
-
-#define _php3_hash_copy zend_hash_copy
-#define _php3_hash_merge zend_hash_merge
-#define _php3_hash_sort zend_hash_sort
-#define _php3_hash_minmax zend_hash_minmax
-
-#define _php3_hash_num_elements zend_hash_num_elements
-
-#define _php3_hash_apply zend_hash_apply
-#define _php3_hash_apply_with_argument zend_hash_apply_with_argument
-
-
-#define php3_error php_error
-
-#define php3_printf php_printf
-#define _php3_sprintf php_sprintf
-
-
-
-#define php3_module_entry zend_module_entry
-
-#define php3_strndup zend_strndup
-#define php3_str_tolower zend_str_tolower
-#define php3_binary_strcmp zend_binary_strcmp
-
-
-#define php3_list_insert zend_list_insert
-#define php3_list_find zend_list_find
-#define php3_list_delete zend_list_delete
-
-#define php3_plist_insert zend_plist_insert
-#define php3_plist_find zend_plist_find
-#define php3_plist_delete zend_plist_delete
-
-#define zend_print_pval zend_print_zval
-#define zend_print_pval_r zend_print_zval_r
-
-
-#define function_entry zend_function_entry
-
-#define _php3_addslashes php_addslashes
-#define _php3_stripslashes php_stripslashes
-#define php3_dl php_dl
-
-#define getParameters zend_get_parameters
-#define getParametersArray zend_get_parameters_array
-
-#define list_entry zend_rsrc_list_entry
-
-#endif /* PHP3_COMPAT_H */
diff --git a/main/php_content_types.c b/main/php_content_types.c
index 97f8022e17..cca006ad6a 100644
--- a/main/php_content_types.c
+++ b/main/php_content_types.c
@@ -73,9 +73,9 @@ SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader)
*/
int php_startup_sapi_content_types(TSRMLS_D)
{
- sapi_register_default_post_reader(php_default_post_reader);
- sapi_register_treat_data(php_default_treat_data);
- sapi_register_input_filter(php_default_input_filter, NULL);
+ sapi_register_default_post_reader(php_default_post_reader TSRMLS_CC);
+ sapi_register_treat_data(php_default_treat_data TSRMLS_CC);
+ sapi_register_input_filter(php_default_input_filter, NULL TSRMLS_CC);
return SUCCESS;
}
/* }}} */
diff --git a/main/php_globals.h b/main/php_globals.h
index 70f3bbfbbe..514c27869b 100644
--- a/main/php_globals.h
+++ b/main/php_globals.h
@@ -54,19 +54,10 @@ typedef struct _arg_separators {
} arg_separators;
struct _php_core_globals {
- zend_bool magic_quotes_gpc;
- zend_bool magic_quotes_runtime;
- zend_bool magic_quotes_sybase;
-
- zend_bool safe_mode;
-
- zend_bool allow_call_time_pass_reference;
zend_bool implicit_flush;
long output_buffering;
- char *safe_mode_include_dir;
- zend_bool safe_mode_gid;
zend_bool sql_safe_mode;
zend_bool enable_dl;
@@ -75,8 +66,6 @@ struct _php_core_globals {
char *unserialize_callback_func;
long serialize_precision;
- char *safe_mode_exec_dir;
-
long memory_limit;
long max_input_time;
@@ -95,6 +84,7 @@ struct _php_core_globals {
char *include_path;
char *open_basedir;
char *extension_dir;
+ char *php_binary;
char *upload_tmp_dir;
long upload_max_filesize;
@@ -122,13 +112,9 @@ struct _php_core_globals {
zend_bool expose_php;
- zend_bool register_globals;
- zend_bool register_long_arrays;
zend_bool register_argc_argv;
zend_bool auto_globals_jit;
- zend_bool y2k_compliance;
-
char *docref_root;
char *docref_ext;
@@ -143,6 +129,7 @@ struct _php_core_globals {
zend_bool file_uploads;
zend_bool during_request_startup;
zend_bool allow_url_fopen;
+ zend_bool enable_post_data_reading;
zend_bool always_populate_raw_post_data;
zend_bool report_zend_debug;
@@ -159,6 +146,7 @@ struct _php_core_globals {
zend_bool com_initialized;
#endif
long max_input_nesting_level;
+ long max_input_vars;
zend_bool in_user_include;
char *user_ini_filename;
@@ -174,8 +162,6 @@ struct _php_core_globals {
#ifdef PHP_WIN32
zend_bool windows_show_crt_warning;
#endif
-
- long max_input_vars;
};
diff --git a/main/php_ini.c b/main/php_ini.c
index eed600f134..89a3d7e461 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -368,7 +368,6 @@ int php_init_config(TSRMLS_D)
char *php_ini_file_name = NULL;
char *php_ini_search_path = NULL;
int php_ini_scanned_path_len;
- int safe_mode_state;
char *open_basedir;
int free_ini_search_path = 0;
zend_file_handle fh;
@@ -384,7 +383,6 @@ int php_init_config(TSRMLS_D)
zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
- safe_mode_state = PG(safe_mode);
open_basedir = PG(open_basedir);
if (sapi_module.php_ini_path_override) {
@@ -395,7 +393,6 @@ int php_init_config(TSRMLS_D)
int search_path_size;
char *default_location;
char *env_location;
- char *binary_location;
static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 };
#ifdef PHP_WIN32
char *reg_location;
@@ -423,7 +420,11 @@ int php_init_config(TSRMLS_D)
env_location = "";
} else {
size = GetEnvironmentVariableA("PHPRC", phprc_path, size);
- env_location = phprc_path;
+ if (size == 0) {
+ env_location = "";
+ } else {
+ env_location = phprc_path;
+ }
}
}
}
@@ -463,58 +464,18 @@ int php_init_config(TSRMLS_D)
#endif
/* Add cwd (not with CLI) */
- if (strcmp(sapi_module.name, "cli") != 0) {
+ if (!sapi_module.php_ini_ignore_cwd) {
if (*php_ini_search_path) {
strlcat(php_ini_search_path, paths_separator, search_path_size);
}
strlcat(php_ini_search_path, ".", search_path_size);
}
- /* Add binary directory */
-#ifdef PHP_WIN32
- binary_location = (char *) emalloc(MAXPATHLEN);
- if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
- efree(binary_location);
- binary_location = NULL;
- }
-#else
- if (sapi_module.executable_location) {
- binary_location = (char *)emalloc(MAXPATHLEN);
- if (!strchr(sapi_module.executable_location, '/')) {
- char *envpath, *path;
- int found = 0;
-
- if ((envpath = getenv("PATH")) != NULL) {
- char *search_dir, search_path[MAXPATHLEN];
- char *last = NULL;
-
- path = estrdup(envpath);
- search_dir = php_strtok_r(path, ":", &last);
-
- while (search_dir) {
- snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
- if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK)) {
- found = 1;
- break;
- }
- search_dir = php_strtok_r(NULL, ":", &last);
- }
- efree(path);
- }
- if (!found) {
- efree(binary_location);
- binary_location = NULL;
- }
- } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
- efree(binary_location);
- binary_location = NULL;
- }
- } else {
- binary_location = NULL;
- }
-#endif
- if (binary_location) {
- char *separator_location = strrchr(binary_location, DEFAULT_SLASH);
+ if (PG(php_binary)) {
+ char *separator_location, *binary_location;
+
+ binary_location = estrdup(PG(php_binary));
+ separator_location = strrchr(binary_location, DEFAULT_SLASH);
if (separator_location && separator_location != binary_location) {
*(separator_location) = 0;
@@ -557,7 +518,6 @@ int php_init_config(TSRMLS_D)
#endif
}
- PG(safe_mode) = 0;
PG(open_basedir) = NULL;
/*
@@ -610,7 +570,6 @@ int php_init_config(TSRMLS_D)
efree(php_ini_search_path);
}
- PG(safe_mode) = safe_mode_state;
PG(open_basedir) = open_basedir;
if (fh.handle.fp) {
diff --git a/main/php_logos.c b/main/php_logos.c
index 55204aa816..3689f71e95 100644
--- a/main/php_logos.c
+++ b/main/php_logos.c
@@ -85,7 +85,7 @@ int php_info_logos(const char *logo_string TSRMLS_DC)
content_header[len] = '\0';
sapi_add_header(content_header, len, 0);
- PHPWRITE(logo_image->data, logo_image->size);
+ PHPWRITE((char*)logo_image->data, logo_image->size);
return 1;
}
diff --git a/main/php_main.h b/main/php_main.h
index 93ba5a32ac..124be2379a 100644
--- a/main/php_main.h
+++ b/main/php_main.h
@@ -35,6 +35,7 @@ PHPAPI void php_module_shutdown(TSRMLS_D);
PHPAPI void php_module_shutdown_for_exec(void);
PHPAPI int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals);
PHPAPI int php_request_startup_for_hook(TSRMLS_D);
+PHPAPI void php_request_shutdown_for_hook(void *dummy);
PHPAPI int php_register_extensions(zend_module_entry **ptr, int count TSRMLS_DC);
diff --git a/main/php_network.h b/main/php_network.h
index 214a66077b..6078890049 100644
--- a/main/php_network.h
+++ b/main/php_network.h
@@ -194,10 +194,12 @@ PHPAPI void _php_emit_fd_setsize_warning(int max_fd);
/* it is safe to FD_SET too many fd's under win32; the macro will simply ignore
* descriptors that go beyond the default FD_SETSIZE */
# define PHP_SAFE_FD_SET(fd, set) FD_SET(fd, set)
+# define PHP_SAFE_FD_CLR(fd, set) FD_CLR(fd, set)
# define PHP_SAFE_FD_ISSET(fd, set) FD_ISSET(fd, set)
# define PHP_SAFE_MAX_FD(m, n) do { if (n + 1 >= FD_SETSIZE) { _php_emit_fd_setsize_warning(n); }} while(0)
#else
# define PHP_SAFE_FD_SET(fd, set) do { if (fd < FD_SETSIZE) FD_SET(fd, set); } while(0)
+# define PHP_SAFE_FD_CLR(fd, set) do { if (fd < FD_SETSIZE) FD_CLR(fd, set); } while(0)
# define PHP_SAFE_FD_ISSET(fd, set) ((fd < FD_SETSIZE) && FD_ISSET(fd, set))
# define PHP_SAFE_MAX_FD(m, n) do { if (m >= FD_SETSIZE) { _php_emit_fd_setsize_warning(m); m = FD_SETSIZE - 1; }} while(0)
#endif
@@ -220,6 +222,9 @@ typedef struct {
#endif
BEGIN_EXTERN_C()
+PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC);
+PHPAPI void php_network_freeaddresses(struct sockaddr **sal);
+
PHPAPI php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
int socktype, int asynchronous, struct timeval *timeout, char **error_string,
int *error_code, char *bindto, unsigned short bindport
diff --git a/main/php_open_temporary_file.c b/main/php_open_temporary_file.c
index f6fe0ff9fd..8d5c9e9ee7 100644
--- a/main/php_open_temporary_file.c
+++ b/main/php_open_temporary_file.c
@@ -127,7 +127,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, char **
new_state.cwd = strdup(cwd);
new_state.cwd_length = strlen(cwd);
- if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH TSRMLS_CC)) {
free(new_state.cwd);
return -1;
}
diff --git a/main/php_output.h b/main/php_output.h
index cb98839de8..d050a141a1 100644
--- a/main/php_output.h
+++ b/main/php_output.h
@@ -12,7 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Zeev Suraski <zeev@zend.com> |
+ | Author: Michael Wallner <mike@php.net> |
+----------------------------------------------------------------------+
*/
@@ -21,35 +21,235 @@
#ifndef PHP_OUTPUT_H
#define PHP_OUTPUT_H
+#define PHP_OUTPUT_NEWAPI 1
+
+/* handler ops */
+#define PHP_OUTPUT_HANDLER_WRITE 0x00 /* standard passthru */
+#define PHP_OUTPUT_HANDLER_START 0x01 /* start */
+#define PHP_OUTPUT_HANDLER_CLEAN 0x02 /* restart */
+#define PHP_OUTPUT_HANDLER_FLUSH 0x04 /* pass along as much as possible */
+#define PHP_OUTPUT_HANDLER_FINAL 0x08 /* finalize */
+#define PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_WRITE
+#define PHP_OUTPUT_HANDLER_END PHP_OUTPUT_HANDLER_FINAL
+
+/* handler types */
+#define PHP_OUTPUT_HANDLER_INTERNAL 0x0000
+#define PHP_OUTPUT_HANDLER_USER 0x0001
+
+/* handler ability flags */
+#define PHP_OUTPUT_HANDLER_CLEANABLE 0x0010
+#define PHP_OUTPUT_HANDLER_FLUSHABLE 0x0020
+#define PHP_OUTPUT_HANDLER_REMOVABLE 0x0040
+#define PHP_OUTPUT_HANDLER_STDFLAGS 0x0070
+
+/* handler status flags */
+#define PHP_OUTPUT_HANDLER_STARTED 0x1000
+#define PHP_OUTPUT_HANDLER_DISABLED 0x2000
+#define PHP_OUTPUT_HANDLER_PROCESSED 0x4000
+
+/* handler op return values */
+typedef enum _php_output_handler_status_t {
+ PHP_OUTPUT_HANDLER_FAILURE,
+ PHP_OUTPUT_HANDLER_SUCCESS,
+ PHP_OUTPUT_HANDLER_NO_DATA
+} php_output_handler_status_t;
+
+/* php_output_stack_pop() flags */
+#define PHP_OUTPUT_POP_TRY 0x000
+#define PHP_OUTPUT_POP_FORCE 0x001
+#define PHP_OUTPUT_POP_DISCARD 0x010
+#define PHP_OUTPUT_POP_SILENT 0x100
+
+/* real global flags */
+#define PHP_OUTPUT_IMPLICITFLUSH 0x01
+#define PHP_OUTPUT_DISABLED 0x02
+#define PHP_OUTPUT_WRITTEN 0x04
+#define PHP_OUTPUT_SENT 0x08
+/* supplementary flags for php_output_get_status() */
+#define PHP_OUTPUT_ACTIVE 0x10
+#define PHP_OUTPUT_LOCKED 0x20
+/* output layer is ready to use */
+#define PHP_OUTPUT_ACTIVATED 0x100000
+
+/* handler hooks */
+typedef enum _php_output_handler_hook_t {
+ PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ,
+ PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS,
+ PHP_OUTPUT_HANDLER_HOOK_GET_LEVEL,
+ PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE,
+ PHP_OUTPUT_HANDLER_HOOK_DISABLE,
+ /* unused */
+ PHP_OUTPUT_HANDLER_HOOK_LAST
+} php_output_handler_hook_t;
+
+#define PHP_OUTPUT_HANDLER_INITBUF_SIZE(s) \
+( ((s) > 1) ? \
+ (s) + PHP_OUTPUT_HANDLER_ALIGNTO_SIZE - ((s) % (PHP_OUTPUT_HANDLER_ALIGNTO_SIZE)) : \
+ PHP_OUTPUT_HANDLER_DEFAULT_SIZE \
+)
+#define PHP_OUTPUT_HANDLER_ALIGNTO_SIZE 0x1000
+#define PHP_OUTPUT_HANDLER_DEFAULT_SIZE 0x4000
+
+typedef struct _php_output_buffer {
+ char *data;
+ size_t size;
+ size_t used;
+ uint free:1;
+ uint _res:31;
+} php_output_buffer;
+
+typedef struct _php_output_context {
+ int op;
+ php_output_buffer in;
+ php_output_buffer out;
+#ifdef ZTS
+ void ***tsrm_ls;
+#endif
+} php_output_context;
+
+#define PHP_OUTPUT_TSRMLS(ctx) TSRMLS_FETCH_FROM_CTX((ctx)->tsrm_ls)
+
+/* old-style, stateless callback */
typedef void (*php_output_handler_func_t)(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC);
+/* new-style, opaque context callback */
+typedef int (*php_output_handler_context_func_t)(void **handler_context, php_output_context *output_context);
+/* output handler context dtor */
+typedef void (*php_output_handler_context_dtor_t)(void *opaq TSRMLS_DC);
+/* conflict check callback */
+typedef int (*php_output_handler_conflict_check_t)(const char *handler_name, size_t handler_name_len TSRMLS_DC);
+/* ctor for aliases */
+typedef struct _php_output_handler *(*php_output_handler_alias_ctor_t)(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags TSRMLS_DC);
+
+typedef struct _php_output_handler_user_func_t {
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcc;
+ zval *zoh;
+} php_output_handler_user_func_t;
+
+typedef struct _php_output_handler {
+ char *name;
+ size_t name_len;
+ int flags;
+ int level;
+ size_t size;
+ php_output_buffer buffer;
+
+ void *opaq;
+ void (*dtor)(void *opaq TSRMLS_DC);
+
+ union {
+ php_output_handler_user_func_t *user;
+ php_output_handler_context_func_t internal;
+ } func;
+} php_output_handler;
+
+ZEND_BEGIN_MODULE_GLOBALS(output)
+ int flags;
+ zend_stack handlers;
+ php_output_handler *active;
+ php_output_handler *running;
+ const char *output_start_filename;
+ int output_start_lineno;
+ZEND_END_MODULE_GLOBALS(output)
+
+/* there should not be a need to use OG() from outside of output.c */
+#ifdef ZTS
+# define OG(v) TSRMG(output_globals_id, zend_output_globals *, v)
+#else
+# define OG(v) (output_globals.v)
+#endif
+
+/* convenience macros */
+#define PHPWRITE(str, str_len) php_output_write((str), (str_len) TSRMLS_CC)
+#define PHPWRITE_H(str, str_len) php_output_write_unbuffered((str), (str_len) TSRMLS_CC)
+
+#define PUTC(c) (php_output_write(&(c), 1 TSRMLS_CC), (c))
+#define PUTC_H(c) (php_output_write_unbuffered(&(c), 1 TSRMLS_CC), (c))
+
+#define PUTS(str) do { \
+ const char *__str = (str); \
+ php_output_write(__str, strlen(__str) TSRMLS_CC); \
+} while (0)
+#define PUTS_H(str) do { \
+ const char *__str = (str); \
+ php_output_write_unbuffered(__str, strlen(__str) TSRMLS_CC); \
+} while (0)
+
BEGIN_EXTERN_C()
+
+extern const char php_output_default_handler_name[sizeof("default output handler")];
+extern const char php_output_devnull_handler_name[sizeof("null output handler")];
+
+#define php_output_tearup() \
+ php_output_startup(); \
+ php_output_activate(TSRMLS_C)
+#define php_output_teardown() \
+ php_output_end_all(TSRMLS_C); \
+ php_output_deactivate(TSRMLS_C); \
+ php_output_shutdown()
+
+/* MINIT */
PHPAPI void php_output_startup(void);
-PHPAPI void php_output_activate(TSRMLS_D);
-PHPAPI void php_output_set_status(zend_bool status TSRMLS_DC);
+/* MSHUTDOWN */
+PHPAPI void php_output_shutdown(void);
+
PHPAPI void php_output_register_constants(TSRMLS_D);
-PHPAPI int php_default_output_func(const char *str, uint str_len TSRMLS_DC);
-PHPAPI int php_ub_body_write(const char *str, uint str_length TSRMLS_DC);
-PHPAPI int php_ub_body_write_no_header(const char *str, uint str_length TSRMLS_DC);
-PHPAPI int php_body_write(const char *str, uint str_length TSRMLS_DC);
-PHPAPI int php_header_write(const char *str, uint str_length TSRMLS_DC);
-PHPAPI int php_start_ob_buffer(zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC);
-PHPAPI int php_start_ob_buffer_named(const char *output_handler_name, uint chunk_size, zend_bool erase TSRMLS_DC);
-PHPAPI void php_end_ob_buffer(zend_bool send_buffer, zend_bool just_flush TSRMLS_DC);
-PHPAPI void php_end_ob_buffers(zend_bool send_buffer TSRMLS_DC);
-PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC);
-PHPAPI int php_ob_get_length(zval *p TSRMLS_DC);
-PHPAPI void php_start_implicit_flush(TSRMLS_D);
-PHPAPI void php_end_implicit_flush(TSRMLS_D);
-PHPAPI char *php_get_output_start_filename(TSRMLS_D);
-PHPAPI int php_get_output_start_lineno(TSRMLS_D);
-PHPAPI void php_ob_set_internal_handler(php_output_handler_func_t internal_output_handler, uint buffer_size, char *handler_name, zend_bool erase TSRMLS_DC);
-PHPAPI int php_ob_handler_used(char *handler_name TSRMLS_DC);
-PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC);
-PHPAPI int php_ob_get_buffer(zval *p TSRMLS_DC);
-PHPAPI int php_ob_get_length(zval *p TSRMLS_DC);
+
+/* RINIT */
+PHPAPI int php_output_activate(TSRMLS_D);
+/* RSHUTDOWN */
+PHPAPI void php_output_deactivate(TSRMLS_D);
+
+PHPAPI void php_output_set_status(int status TSRMLS_DC);
+PHPAPI int php_output_get_status(TSRMLS_D);
+PHPAPI void php_output_set_implicit_flush(int flush TSRMLS_DC);
+PHPAPI const char *php_output_get_start_filename(TSRMLS_D);
+PHPAPI int php_output_get_start_lineno(TSRMLS_D);
+
+PHPAPI int php_output_write_unbuffered(const char *str, size_t len TSRMLS_DC);
+PHPAPI int php_output_write(const char *str, size_t len TSRMLS_DC);
+
+PHPAPI int php_output_flush(TSRMLS_D);
+PHPAPI void php_output_flush_all(TSRMLS_D);
+PHPAPI int php_output_clean(TSRMLS_D);
+PHPAPI void php_output_clean_all(TSRMLS_D);
+PHPAPI int php_output_end(TSRMLS_D);
+PHPAPI void php_output_end_all(TSRMLS_D);
+PHPAPI int php_output_discard(TSRMLS_D);
+PHPAPI void php_output_discard_all(TSRMLS_D);
+
+PHPAPI int php_output_get_contents(zval *p TSRMLS_DC);
+PHPAPI int php_output_get_length(zval *p TSRMLS_DC);
+PHPAPI int php_output_get_level(TSRMLS_D);
+PHPAPI php_output_handler* php_output_get_active_handler(TSRMLS_D);
+
+PHPAPI int php_output_start_default(TSRMLS_D);
+PHPAPI int php_output_start_devnull(TSRMLS_D);
+
+PHPAPI int php_output_start_user(zval *output_handler, size_t chunk_size, int flags TSRMLS_DC);
+PHPAPI int php_output_start_internal(const char *name, size_t name_len, php_output_handler_func_t output_handler, size_t chunk_size, int flags TSRMLS_DC);
+
+PHPAPI php_output_handler *php_output_handler_create_user(zval *handler, size_t chunk_size, int flags TSRMLS_DC);
+PHPAPI php_output_handler *php_output_handler_create_internal(const char *name, size_t name_len, php_output_handler_context_func_t handler, size_t chunk_size, int flags TSRMLS_DC);
+
+PHPAPI void php_output_handler_set_context(php_output_handler *handler, void *opaq, void (*dtor)(void* TSRMLS_DC) TSRMLS_DC);
+PHPAPI int php_output_handler_start(php_output_handler *handler TSRMLS_DC);
+PHPAPI int php_output_handler_started(const char *name, size_t name_len TSRMLS_DC);
+PHPAPI int php_output_handler_hook(php_output_handler_hook_t type, void *arg TSRMLS_DC);
+PHPAPI void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC);
+PHPAPI void php_output_handler_free(php_output_handler **handler TSRMLS_DC);
+
+PHPAPI int php_output_handler_conflict(const char *handler_new, size_t handler_new_len, const char *handler_set, size_t handler_set_len TSRMLS_DC);
+PHPAPI int php_output_handler_conflict_register(const char *handler_name, size_t handler_name_len, php_output_handler_conflict_check_t check_func TSRMLS_DC);
+PHPAPI int php_output_handler_reverse_conflict_register(const char *handler_name, size_t handler_name_len, php_output_handler_conflict_check_t check_func TSRMLS_DC);
+
+PHPAPI php_output_handler_alias_ctor_t *php_output_handler_alias(const char *handler_name, size_t handler_name_len TSRMLS_DC);
+PHPAPI int php_output_handler_alias_register(const char *handler_name, size_t handler_name_len, php_output_handler_alias_ctor_t func TSRMLS_DC);
+
END_EXTERN_C()
+
PHP_FUNCTION(ob_start);
PHP_FUNCTION(ob_flush);
PHP_FUNCTION(ob_clean);
@@ -64,51 +264,16 @@ PHP_FUNCTION(ob_get_status);
PHP_FUNCTION(ob_implicit_flush);
PHP_FUNCTION(ob_list_handlers);
-typedef struct _php_ob_buffer {
- char *buffer;
- uint size;
- uint text_length;
- int block_size;
- uint chunk_size;
- int status;
- zval *output_handler;
- php_output_handler_func_t internal_output_handler;
- char *internal_output_handler_buffer;
- uint internal_output_handler_buffer_size;
- char *handler_name;
- zend_bool erase;
-} php_ob_buffer;
-
-typedef struct _php_output_globals {
- int (*php_body_write)(const char *str, uint str_length TSRMLS_DC); /* string output */
- int (*php_header_write)(const char *str, uint str_length TSRMLS_DC); /* unbuffer string output */
- php_ob_buffer active_ob_buffer;
- unsigned char implicit_flush;
- char *output_start_filename;
- int output_start_lineno;
- zend_stack ob_buffers;
- int ob_nesting_level;
- zend_bool ob_lock;
- zend_bool disable_output;
-} php_output_globals;
-
-#ifdef ZTS
-#define OG(v) TSRMG(output_globals_id, php_output_globals *, v)
-ZEND_API extern int output_globals_id;
-#else
-#define OG(v) (output_globals.v)
-ZEND_API extern php_output_globals output_globals;
-#endif
-
-#define PHP_OUTPUT_HANDLER_START (1<<0)
-#define PHP_OUTPUT_HANDLER_CONT (1<<1)
-#define PHP_OUTPUT_HANDLER_END (1<<2)
-
-#define PHP_OUTPUT_HANDLER_INTERNAL 0
-#define PHP_OUTPUT_HANDLER_USER 1
-
PHP_FUNCTION(output_add_rewrite_var);
PHP_FUNCTION(output_reset_rewrite_vars);
+#endif
-#endif /* PHP_OUTPUT_H */
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/main/php_streams.h b/main/php_streams.h
index 83b18c008b..82498d6619 100644
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -154,6 +154,8 @@ typedef struct _php_stream_wrapper_ops {
/* Create/Remove directory */
int (*stream_mkdir)(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC);
int (*stream_rmdir)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
+ /* Metadata handling */
+ int (*stream_metadata)(php_stream_wrapper *wrapper, char *url, int options, void *value, php_stream_context *context TSRMLS_DC);
} php_stream_wrapper_ops;
struct _php_stream_wrapper {
@@ -225,9 +227,11 @@ struct _php_stream {
int eof;
#if ZEND_DEBUG
- char *open_filename;
+ const char *open_filename;
uint open_lineno;
#endif
+
+ struct _php_stream *enclosing_stream; /* this is a private stream owned by enclosing_stream */
}; /* php_stream */
/* state definitions when closing down; these are private to streams.c */
@@ -259,6 +263,10 @@ END_EXTERN_C()
#define php_stream_from_zval_no_verify(xstr, ppzval) (xstr) = (php_stream*)zend_fetch_resource((ppzval) TSRMLS_CC, -1, "stream", NULL, 2, php_file_le_stream(), php_file_le_pstream())
BEGIN_EXTERN_C()
+PHPAPI php_stream *php_stream_encloses(php_stream *enclosing, php_stream *enclosed);
+#define php_stream_free_enclosed(stream_enclosed, close_options) _php_stream_free_enclosed((stream_enclosed), (close_options) TSRMLS_CC)
+PHPAPI int _php_stream_free_enclosed(php_stream *stream_enclosed, int close_options TSRMLS_DC);
+
PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream **stream TSRMLS_DC);
#define PHP_STREAM_PERSISTENT_SUCCESS 0 /* id exists */
#define PHP_STREAM_PERSISTENT_FAILURE 1 /* id exists but is not a stream! */
@@ -269,6 +277,7 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
#define PHP_STREAM_FREE_PRESERVE_HANDLE 4 /* tell ops->close to not close it's underlying handle */
#define PHP_STREAM_FREE_RSRC_DTOR 8 /* called from the resource list dtor */
#define PHP_STREAM_FREE_PERSISTENT 16 /* manually freeing a persistent connection */
+#define PHP_STREAM_FREE_IGNORE_ENCLOSING 32 /* don't close the enclosing stream instead */
#define PHP_STREAM_FREE_CLOSE (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)
#define PHP_STREAM_FREE_CLOSE_CASTED (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PRESERVE_HANDLE)
#define PHP_STREAM_FREE_CLOSE_PERSISTENT (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PERSISTENT)
@@ -429,7 +438,7 @@ BEGIN_EXTERN_C()
ZEND_ATTRIBUTE_DEPRECATED
PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC);
#define php_stream_copy_to_stream(src, dest, maxlen) _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC)
-PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC);
+PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC);
#define php_stream_copy_to_stream_ex(src, dest, maxlen, len) _php_stream_copy_to_stream_ex((src), (dest), (maxlen), (len) STREAMS_CC TSRMLS_CC)
@@ -484,8 +493,8 @@ END_EXTERN_C()
#define IGNORE_PATH 0x00000000
#define USE_PATH 0x00000001
#define IGNORE_URL 0x00000002
-#define ENFORCE_SAFE_MODE 0x00000004
#define REPORT_ERRORS 0x00000008
+#define ENFORCE_SAFE_MODE 0 /* for BC only */
/* If you don't need to write to the stream, but really need to
* be able to seek, use this flag in your options. */
@@ -583,6 +592,15 @@ END_EXTERN_C()
/* Definitions for user streams */
#define PHP_STREAM_IS_URL 1
+
+/* Stream metadata definitions */
+/* Create if referred resource does not exist */
+#define PHP_STREAM_META_TOUCH 1
+#define PHP_STREAM_META_OWNER_NAME 2
+#define PHP_STREAM_META_OWNER 3
+#define PHP_STREAM_META_GROUP_NAME 4
+#define PHP_STREAM_META_GROUP 5
+#define PHP_STREAM_META_ACCESS 6
/*
* Local variables:
* tab-width: 4
diff --git a/main/php_variables.c b/main/php_variables.c
index 4b97cbd85f..427966170c 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -47,11 +47,7 @@ PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zva
/* Prepare value */
Z_STRLEN(new_entry) = str_len;
- if (PG(magic_quotes_gpc)) {
- Z_STRVAL(new_entry) = php_addslashes(strval, Z_STRLEN(new_entry), &Z_STRLEN(new_entry), 0 TSRMLS_CC);
- } else {
- Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));
- }
+ Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));
Z_TYPE(new_entry) = IS_STRING;
php_register_variable_ex(var, &new_entry, track_vars_array TSRMLS_CC);
@@ -61,39 +57,38 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
{
char *p = NULL;
char *ip; /* index pointer */
- char *index, *escaped_index = NULL;
+ char *index;
char *var, *var_orig;
int var_len, index_len;
zval *gpc_element, **gpc_element_p;
zend_bool is_array = 0;
HashTable *symtable1 = NULL;
+ ALLOCA_FLAG(use_heap)
assert(var_name != NULL);
if (track_vars_array) {
symtable1 = Z_ARRVAL_P(track_vars_array);
- } else if (PG(register_globals)) {
- if (!EG(active_symbol_table)) {
- zend_rebuild_symbol_table(TSRMLS_C);
- }
- symtable1 = EG(active_symbol_table);
}
+
if (!symtable1) {
/* Nothing to do */
zval_dtor(val);
return;
}
- /*
- * Prepare variable name
- */
- var_orig = estrdup(var_name);
- var = var_orig;
/* ignore leading spaces in the variable name */
- while (*var && *var==' ') {
- var++;
+ while (*var_name && *var_name==' ') {
+ var_name++;
}
+
+ /*
+ * Prepare variable name
+ */
+ var_len = strlen(var_name);
+ var = var_orig = do_alloca(var_len + 1, use_heap);
+ memcpy(var_orig, var_name, var_len + 1);
/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
for (p = var; *p; p++) {
@@ -110,7 +105,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
if (var_len==0) { /* empty variable name, or variable name with a space in it */
zval_dtor(val);
- efree(var_orig);
+ free_alloca(var_orig, use_heap);
return;
}
@@ -119,7 +114,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
var_len == sizeof("GLOBALS")-1 &&
!memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) {
zval_dtor(val);
- efree(var_orig);
+ free_alloca(var_orig, use_heap);
return;
}
@@ -139,9 +134,6 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
if (track_vars_array) {
ht = Z_ARRVAL_P(track_vars_array);
zend_symtable_del(ht, var, var_len + 1);
- } else if (PG(register_globals)) {
- ht = EG(active_symbol_table);
- zend_symtable_del(ht, var, var_len + 1);
}
zval_dtor(val);
@@ -151,7 +143,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
if (!PG(display_errors)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variable nesting level exceeded %ld. To increase the limit change max_input_nesting_level in php.ini.", PG(max_input_nesting_level));
}
- efree(var_orig);
+ free_alloca(var_orig, use_heap);
return;
}
@@ -185,23 +177,15 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
if (zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p) == FAILURE) {
zval_ptr_dtor(&gpc_element);
zval_dtor(val);
- efree(var_orig);
+ free_alloca(var_orig, use_heap);
return;
}
} else {
- if (PG(magic_quotes_gpc)) {
- escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC);
- } else {
- escaped_index = index;
- }
- if (zend_symtable_find(symtable1, escaped_index, index_len + 1, (void **) &gpc_element_p) == FAILURE
+ if (zend_symtable_find(symtable1, index, index_len + 1, (void **) &gpc_element_p) == FAILURE
|| Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
MAKE_STD_ZVAL(gpc_element);
array_init(gpc_element);
- zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
- }
- if (index != escaped_index) {
- efree(escaped_index);
+ zend_symtable_update(symtable1, index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
}
}
symtable1 = Z_ARRVAL_PP(gpc_element_p);
@@ -227,11 +211,6 @@ plain_var:
zval_ptr_dtor(&gpc_element);
}
} else {
- if (PG(magic_quotes_gpc)) {
- escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC);
- } else {
- escaped_index = index;
- }
/*
* According to rfc2965, more specific paths are listed above the less specific ones.
* If we encounter a duplicate cookie name, we should skip it, since it is not possible
@@ -240,17 +219,14 @@ plain_var:
*/
if (PG(http_globals)[TRACK_VARS_COOKIE] &&
symtable1 == Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) &&
- zend_symtable_exists(symtable1, escaped_index, index_len + 1)) {
+ zend_symtable_exists(symtable1, index, index_len + 1)) {
zval_ptr_dtor(&gpc_element);
} else {
- zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
- }
- if (escaped_index != index) {
- efree(escaped_index);
+ zend_symtable_update(symtable1, index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
}
}
}
- efree(var_orig);
+ free_alloca(var_orig, use_heap);
}
SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
@@ -447,13 +423,6 @@ void _php_import_environment_variables(zval *array_ptr TSRMLS_DC)
size_t alloc_size = sizeof(buf);
unsigned long nlen; /* ptrdiff_t is not portable */
- /* turn off magic_quotes while importing environment variables */
- int magic_quotes_gpc = PG(magic_quotes_gpc);
-
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
-
for (env = environ; env != NULL && *env != NULL; env++) {
p = strchr(*env, '=');
if (!p) { /* malformed entry? */
@@ -471,10 +440,6 @@ void _php_import_environment_variables(zval *array_ptr TSRMLS_DC)
if (t != buf && t != NULL) {
efree(t);
}
-
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "1", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
}
zend_bool php_std_auto_global_callback(char *name, uint name_len TSRMLS_DC)
@@ -491,7 +456,7 @@ static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC)
int count = 0;
char *ss, *space;
- if (!(PG(register_globals) || SG(request_info).argc || track_vars_array)) {
+ if (!(SG(request_info).argc || track_vars_array)) {
return;
}
@@ -550,7 +515,7 @@ static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC)
}
Z_TYPE_P(argc) = IS_LONG;
- if (PG(register_globals) || SG(request_info).argc) {
+ if (SG(request_info).argc) {
Z_ADDREF_P(arr);
Z_ADDREF_P(argc);
zend_hash_update(&EG(symbol_table), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL);
@@ -588,8 +553,6 @@ PHPAPI int php_handle_special_queries(TSRMLS_D)
static inline void php_register_server_variables(TSRMLS_D)
{
zval *array_ptr = NULL;
- /* turn off magic_quotes while importing server variables */
- int magic_quotes_gpc = PG(magic_quotes_gpc);
ALLOC_ZVAL(array_ptr);
array_init(array_ptr);
@@ -598,9 +561,6 @@ static inline void php_register_server_variables(TSRMLS_D)
zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]);
}
PG(http_globals)[TRACK_VARS_SERVER] = array_ptr;
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
/* Server variables */
if (sapi_module.register_server_variables) {
@@ -619,15 +579,15 @@ static inline void php_register_server_variables(TSRMLS_D)
}
/* store request init time */
{
- zval new_entry;
- Z_TYPE(new_entry) = IS_LONG;
- Z_LVAL(new_entry) = sapi_get_request_time(TSRMLS_C);
- php_register_variable_ex("REQUEST_TIME", &new_entry, array_ptr TSRMLS_CC);
+ zval request_time_float, request_time_long;
+ Z_TYPE(request_time_float) = IS_DOUBLE;
+ Z_DVAL(request_time_float) = sapi_get_request_time(TSRMLS_C);
+ php_register_variable_ex("REQUEST_TIME_FLOAT", &request_time_float, array_ptr TSRMLS_CC);
+ Z_TYPE(request_time_long) = IS_LONG;
+ Z_LVAL(request_time_long) = zend_dval_to_lval(Z_DVAL(request_time_float));
+ php_register_variable_ex("REQUEST_TIME", &request_time_long, array_ptr TSRMLS_CC);
}
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "1", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
}
/* }}} */
@@ -641,7 +601,7 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC)
ulong num_key;
HashPosition pos;
int key_type;
- int globals_check = (PG(register_globals) && (dest == (&EG(symbol_table))));
+ int globals_check = (dest == (&EG(symbol_table)));
zend_hash_internal_pointer_reset_ex(src, &pos);
while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
@@ -650,10 +610,9 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC)
|| (key_type == HASH_KEY_IS_STRING && zend_hash_find(dest, string_key, string_key_len, (void **) &dest_entry) != SUCCESS)
|| (key_type == HASH_KEY_IS_LONG && zend_hash_index_find(dest, num_key, (void **)&dest_entry) != SUCCESS)
|| Z_TYPE_PP(dest_entry) != IS_ARRAY
- ) {
+ ) {
Z_ADDREF_PP(src_entry);
if (key_type == HASH_KEY_IS_STRING) {
- /* if register_globals is on and working with main symbol table, prevent overwriting of GLOBALS */
if (!globals_check || string_key_len != sizeof("GLOBALS") || memcmp(string_key, "GLOBALS", sizeof("GLOBALS") - 1)) {
zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
} else {
@@ -671,130 +630,116 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC)
}
/* }}} */
-static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS_DC);
-static zend_bool php_auto_globals_create_env(char *name, uint name_len TSRMLS_DC);
-static zend_bool php_auto_globals_create_request(char *name, uint name_len TSRMLS_DC);
+static zend_bool php_auto_globals_create_server(const char *name, uint name_len TSRMLS_DC);
+static zend_bool php_auto_globals_create_env(const char *name, uint name_len TSRMLS_DC);
+static zend_bool php_auto_globals_create_request(const char *name, uint name_len TSRMLS_DC);
/* {{{ php_hash_environment
*/
int php_hash_environment(TSRMLS_D)
{
- char *p;
- unsigned char _gpc_flags[5] = {0, 0, 0, 0, 0};
- zend_bool jit_initialization = (PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays));
- struct auto_global_record {
- char *name;
- uint name_len;
- char *long_name;
- uint long_name_len;
- zend_bool jit_initialization;
- } auto_global_records[] = {
- { "_POST", sizeof("_POST"), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), 0 },
- { "_GET", sizeof("_GET"), "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), 0 },
- { "_COOKIE", sizeof("_COOKIE"), "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"), 0 },
- { "_SERVER", sizeof("_SERVER"), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), 1 },
- { "_ENV", sizeof("_ENV"), "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), 1 },
- { "_FILES", sizeof("_FILES"), "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"), 0 },
- };
- size_t num_track_vars = sizeof(auto_global_records)/sizeof(struct auto_global_record);
- size_t i;
-
- /* jit_initialization = 0; */
- for (i=0; i<num_track_vars; i++) {
- PG(http_globals)[i] = NULL;
- }
-
- for (p=PG(variables_order); p && *p; p++) {
- switch(*p) {
- case 'p':
- case 'P':
- if (!_gpc_flags[0] && !SG(headers_sent) && SG(request_info).request_method && !strcasecmp(SG(request_info).request_method, "POST")) {
- sapi_module.treat_data(PARSE_POST, NULL, NULL TSRMLS_CC); /* POST Data */
- _gpc_flags[0] = 1;
- if (PG(register_globals)) {
- php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC);
- }
- }
- break;
- case 'c':
- case 'C':
- if (!_gpc_flags[1]) {
- sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC); /* Cookie Data */
- _gpc_flags[1] = 1;
- if (PG(register_globals)) {
- php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC);
- }
- }
- break;
- case 'g':
- case 'G':
- if (!_gpc_flags[2]) {
- sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC); /* GET Data */
- _gpc_flags[2] = 1;
- if (PG(register_globals)) {
- php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
- }
- }
- break;
- case 'e':
- case 'E':
- if (!jit_initialization && !_gpc_flags[3]) {
- zend_auto_global_disable_jit("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
- php_auto_globals_create_env("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
- _gpc_flags[3] = 1;
- if (PG(register_globals)) {
- php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV]) TSRMLS_CC);
- }
- }
- break;
- case 's':
- case 'S':
- if (!jit_initialization && !_gpc_flags[4]) {
- zend_auto_global_disable_jit("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
- php_register_server_variables(TSRMLS_C);
- _gpc_flags[4] = 1;
- if (PG(register_globals)) {
- php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]) TSRMLS_CC);
- }
- }
- break;
- }
- }
-
- /* argv/argc support */
+ memset(PG(http_globals), 0, sizeof(PG(http_globals)));
+ zend_activate_auto_globals(TSRMLS_C);
if (PG(register_argc_argv)) {
php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
}
+ return SUCCESS;
+}
+/* }}} */
- for (i=0; i<num_track_vars; i++) {
- if (jit_initialization && auto_global_records[i].jit_initialization) {
- continue;
+static zend_bool php_auto_globals_create_get(const char *name, uint name_len TSRMLS_DC)
+{
+ zval *vars;
+
+ if (PG(variables_order) && (strchr(PG(variables_order),'G') || strchr(PG(variables_order),'g'))) {
+ sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC);
+ vars = PG(http_globals)[TRACK_VARS_GET];
+ } else {
+ ALLOC_ZVAL(vars);
+ array_init(vars);
+ INIT_PZVAL(vars);
+ if (PG(http_globals)[TRACK_VARS_GET]) {
+ zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
}
- if (!PG(http_globals)[i]) {
- ALLOC_ZVAL(PG(http_globals)[i]);
- array_init(PG(http_globals)[i]);
- INIT_PZVAL(PG(http_globals)[i]);
+ PG(http_globals)[TRACK_VARS_GET] = vars;
+ }
+
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+
+ return 0; /* don't rearm */
+}
+
+static zend_bool php_auto_globals_create_post(const char *name, uint name_len TSRMLS_DC)
+{
+ zval *vars;
+
+ if (PG(variables_order) &&
+ (strchr(PG(variables_order),'P') || strchr(PG(variables_order),'p')) &&
+ !SG(headers_sent) &&
+ SG(request_info).request_method &&
+ !strcasecmp(SG(request_info).request_method, "POST")) {
+ sapi_module.treat_data(PARSE_POST, NULL, NULL TSRMLS_CC);
+ vars = PG(http_globals)[TRACK_VARS_POST];
+ } else {
+ ALLOC_ZVAL(vars);
+ array_init(vars);
+ INIT_PZVAL(vars);
+ if (PG(http_globals)[TRACK_VARS_POST]) {
+ zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
}
+ PG(http_globals)[TRACK_VARS_POST] = vars;
+ }
+
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+
+ return 0; /* don't rearm */
+}
+
+static zend_bool php_auto_globals_create_cookie(const char *name, uint name_len TSRMLS_DC)
+{
+ zval *vars;
- Z_ADDREF_P(PG(http_globals)[i]);
- zend_hash_update(&EG(symbol_table), auto_global_records[i].name, auto_global_records[i].name_len, &PG(http_globals)[i], sizeof(zval *), NULL);
- if (PG(register_long_arrays)) {
- zend_hash_update(&EG(symbol_table), auto_global_records[i].long_name, auto_global_records[i].long_name_len, &PG(http_globals)[i], sizeof(zval *), NULL);
- Z_ADDREF_P(PG(http_globals)[i]);
+ if (PG(variables_order) && (strchr(PG(variables_order),'C') || strchr(PG(variables_order),'c'))) {
+ sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC);
+ vars = PG(http_globals)[TRACK_VARS_COOKIE];
+ } else {
+ ALLOC_ZVAL(vars);
+ array_init(vars);
+ INIT_PZVAL(vars);
+ if (PG(http_globals)[TRACK_VARS_COOKIE]) {
+ zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
}
+ PG(http_globals)[TRACK_VARS_COOKIE] = vars;
}
- /* Create _REQUEST */
- if (!jit_initialization) {
- zend_auto_global_disable_jit("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
- php_auto_globals_create_request("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+
+ return 0; /* don't rearm */
+}
+
+static zend_bool php_auto_globals_create_files(const char *name, uint name_len TSRMLS_DC)
+{
+ zval *vars;
+
+ if (PG(http_globals)[TRACK_VARS_FILES]) {
+ vars = PG(http_globals)[TRACK_VARS_FILES];
+ } else {
+ ALLOC_ZVAL(vars);
+ array_init(vars);
+ INIT_PZVAL(vars);
+ PG(http_globals)[TRACK_VARS_FILES] = vars;
}
- return SUCCESS;
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
+ Z_ADDREF_P(vars);
+
+ return 0; /* don't rearm */
}
-/* }}} */
-static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS_DC)
+static zend_bool php_auto_globals_create_server(const char *name, uint name_len TSRMLS_DC)
{
if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) {
php_register_server_variables(TSRMLS_C);
@@ -804,7 +749,7 @@ static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS
zval **argc, **argv;
if (zend_hash_find(&EG(symbol_table), "argc", sizeof("argc"), (void**)&argc) == SUCCESS &&
- zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void**)&argv) == SUCCESS) {
+ zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void**)&argv) == SUCCESS) {
Z_ADDREF_PP(argc);
Z_ADDREF_PP(argv);
zend_hash_update(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), argv, sizeof(zval *), NULL);
@@ -828,16 +773,11 @@ static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS
zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]);
-
- if (PG(register_long_arrays)) {
- zend_hash_update(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
- Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]);
- }
return 0; /* don't rearm */
}
-static zend_bool php_auto_globals_create_env(char *name, uint name_len TSRMLS_DC)
+static zend_bool php_auto_globals_create_env(const char *name, uint name_len TSRMLS_DC)
{
zval *env_vars = NULL;
ALLOC_ZVAL(env_vars);
@@ -855,15 +795,10 @@ static zend_bool php_auto_globals_create_env(char *name, uint name_len TSRMLS_DC
zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]);
- if (PG(register_long_arrays)) {
- zend_hash_update(&EG(symbol_table), "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
- Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]);
- }
-
return 0; /* don't rearm */
}
-static zend_bool php_auto_globals_create_request(char *name, uint name_len TSRMLS_DC)
+static zend_bool php_auto_globals_create_request(const char *name, uint name_len TSRMLS_DC)
{
zval *form_variables;
unsigned char _gpc_flags[3] = {0, 0, 0};
@@ -873,7 +808,7 @@ static zend_bool php_auto_globals_create_request(char *name, uint name_len TSRML
array_init(form_variables);
INIT_PZVAL(form_variables);
- if(PG(request_order) != NULL) {
+ if (PG(request_order) != NULL) {
p = PG(request_order);
} else {
p = PG(variables_order);
@@ -905,19 +840,19 @@ static zend_bool php_auto_globals_create_request(char *name, uint name_len TSRML
}
}
- zend_hash_update(&EG(symbol_table), "_REQUEST", sizeof("_REQUEST"), &form_variables, sizeof(zval *), NULL);
+ zend_hash_update(&EG(symbol_table), name, name_len + 1, &form_variables, sizeof(zval *), NULL);
return 0;
}
void php_startup_auto_globals(TSRMLS_D)
{
- zend_register_auto_global("_GET", sizeof("_GET")-1, NULL TSRMLS_CC);
- zend_register_auto_global("_POST", sizeof("_POST")-1, NULL TSRMLS_CC);
- zend_register_auto_global("_COOKIE", sizeof("_COOKIE")-1, NULL TSRMLS_CC);
- zend_register_auto_global("_SERVER", sizeof("_SERVER")-1, php_auto_globals_create_server TSRMLS_CC);
- zend_register_auto_global("_ENV", sizeof("_ENV")-1, php_auto_globals_create_env TSRMLS_CC);
- zend_register_auto_global("_REQUEST", sizeof("_REQUEST")-1, php_auto_globals_create_request TSRMLS_CC);
- zend_register_auto_global("_FILES", sizeof("_FILES")-1, NULL TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_GET"), 0, php_auto_globals_create_get TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_POST"), 0, php_auto_globals_create_post TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_COOKIE"), 0, php_auto_globals_create_cookie TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_SERVER"), PG(auto_globals_jit), php_auto_globals_create_server TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_ENV"), PG(auto_globals_jit), php_auto_globals_create_env TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_REQUEST"), PG(auto_globals_jit), php_auto_globals_create_request TSRMLS_CC);
+ zend_register_auto_global(ZEND_STRL("_FILES"), 0, php_auto_globals_create_files TSRMLS_CC);
}
/*
diff --git a/main/php_version.h b/main/php_version.h
index e4ba15eba9..8dfe49630f 100644
--- a/main/php_version.h
+++ b/main/php_version.h
@@ -1,8 +1,8 @@
/* automatically generated by configure */
/* edit configure.in to change version number */
#define PHP_MAJOR_VERSION 5
-#define PHP_MINOR_VERSION 3
-#define PHP_RELEASE_VERSION 19
+#define PHP_MINOR_VERSION 4
+#define PHP_RELEASE_VERSION 9
#define PHP_EXTRA_VERSION "-dev"
-#define PHP_VERSION "5.3.19-dev"
-#define PHP_VERSION_ID 50319
+#define PHP_VERSION "5.4.9-dev"
+#define PHP_VERSION_ID 50409
diff --git a/main/rfc1867.c b/main/rfc1867.c
index 31605cfc17..5da3a99355 100644
--- a/main/rfc1867.c
+++ b/main/rfc1867.c
@@ -36,92 +36,24 @@
#define DEBUG_FILE_UPLOAD ZEND_DEBUG
-PHPAPI int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC) = NULL;
-
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
-#include "ext/mbstring/mbstring.h"
-
-static void safe_php_register_variable(char *var, char *strval, int val_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC);
-
-#define SAFE_RETURN { \
- php_mb_flush_gpc_variables(num_vars, val_list, len_list, array_ptr TSRMLS_CC); \
- if (lbuf) efree(lbuf); \
- if (abuf) efree(abuf); \
- if (array_index) efree(array_index); \
- zend_hash_destroy(&PG(rfc1867_protected_variables)); \
- zend_llist_destroy(&header); \
- if (mbuff->boundary_next) efree(mbuff->boundary_next); \
- if (mbuff->boundary) efree(mbuff->boundary); \
- if (mbuff->buffer) efree(mbuff->buffer); \
- if (mbuff) efree(mbuff); \
- return; }
-
-void php_mb_flush_gpc_variables(int num_vars, char **val_list, int *len_list, zval *array_ptr TSRMLS_DC) /* {{{ */
+static int dummy_encoding_translation(TSRMLS_D)
{
- int i;
- if (php_mb_encoding_translation(TSRMLS_C)) {
- if (num_vars > 0 &&
- php_mb_gpc_encoding_detector(val_list, len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) {
- php_mb_gpc_encoding_converter(val_list, len_list, num_vars, NULL, NULL TSRMLS_CC);
- }
- for (i = 0; i<num_vars; i += 2) {
- safe_php_register_variable(val_list[i], val_list[i+1], len_list[i+1], array_ptr, 0 TSRMLS_CC);
- efree(val_list[i]);
- efree(val_list[i+1]);
- }
- efree(val_list);
- efree(len_list);
- }
-}
-/* }}} */
-
-void php_mb_gpc_realloc_buffer(char ***pval_list, int **plen_list, int *num_vars_max, int inc TSRMLS_DC) /* {{{ */
-{
- /* allow only even increments */
- if (inc & 1) {
- inc++;
- }
- (*num_vars_max) += inc;
- *pval_list = (char **)erealloc(*pval_list, (*num_vars_max+2)*sizeof(char *));
- *plen_list = (int *)erealloc(*plen_list, (*num_vars_max+2)*sizeof(int));
+ return 0;
}
-/* }}} */
-void php_mb_gpc_stack_variable(char *param, char *value, char ***pval_list, int **plen_list, int *num_vars, int *num_vars_max TSRMLS_DC) /* {{{ */
-{
- char **val_list = *pval_list;
- int *len_list = *plen_list;
-
- if (*num_vars >= *num_vars_max) {
- php_mb_gpc_realloc_buffer(pval_list, plen_list, num_vars_max, 16 TSRMLS_CC);
- /* in case realloc relocated the buffer */
- val_list = *pval_list;
- len_list = *plen_list;
- }
+static char *php_ap_getword(const zend_encoding *encoding, char **line, char stop TSRMLS_DC);
+static char *php_ap_getword_conf(const zend_encoding *encoding, char *str TSRMLS_DC);
- val_list[*num_vars] = (char *)estrdup(param);
- len_list[*num_vars] = strlen(param);
- (*num_vars)++;
- val_list[*num_vars] = (char *)estrdup(value);
- len_list[*num_vars] = strlen(value);
- (*num_vars)++;
-}
-/* }}} */
+static php_rfc1867_encoding_translation_t php_rfc1867_encoding_translation = dummy_encoding_translation;
+static php_rfc1867_get_detect_order_t php_rfc1867_get_detect_order = NULL;
+static php_rfc1867_set_input_encoding_t php_rfc1867_set_input_encoding = NULL;
+static php_rfc1867_getword_t php_rfc1867_getword = php_ap_getword;
+static php_rfc1867_getword_conf_t php_rfc1867_getword_conf = php_ap_getword_conf;
+static php_rfc1867_basename_t php_rfc1867_basename = NULL;
-#else
+PHPAPI int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC) = NULL;
-#define SAFE_RETURN { \
- if (lbuf) efree(lbuf); \
- if (abuf) efree(abuf); \
- if (array_index) efree(array_index); \
- zend_hash_destroy(&PG(rfc1867_protected_variables)); \
- zend_llist_destroy(&header); \
- if (mbuff->boundary_next) efree(mbuff->boundary_next); \
- if (mbuff->boundary) efree(mbuff->boundary); \
- if (mbuff->buffer) efree(mbuff->buffer); \
- if (mbuff) efree(mbuff); \
- return; }
-#endif
+static void safe_php_register_variable(char *var, char *strval, int val_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC);
/* The longest property name we use in an uploaded file array */
#define MAX_SIZE_OF_INDEX sizeof("[tmp_name]")
@@ -139,7 +71,7 @@ void php_mb_gpc_stack_variable(char *param, char *value, char ***pval_list, int
#define UPLOAD_ERROR_F 7 /* Failed to write file to disk */
#define UPLOAD_ERROR_X 8 /* File upload stopped by extension */
-void php_rfc1867_register_constants(TSRMLS_D) /* {{{ */
+void php_rfc1867_register_constants(TSRMLS_D) /* {{{ */
{
REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_OK", UPLOAD_ERROR_OK, CONST_CS | CONST_PERSISTENT);
REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_INI_SIZE", UPLOAD_ERROR_A, CONST_CS | CONST_PERSISTENT);
@@ -208,16 +140,16 @@ static void normalize_protected_variable(char *varname TSRMLS_DC) /* {{{ */
}
*s = '\0';
}
-/* }}} */
+/* }}} */
-static void add_protected_variable(char *varname TSRMLS_DC) /* {{{ */
+static void add_protected_variable(char *varname TSRMLS_DC) /* {{{ */
{
int dummy = 1;
normalize_protected_variable(varname TSRMLS_CC);
zend_hash_add(&PG(rfc1867_protected_variables), varname, strlen(varname)+1, &dummy, sizeof(int), NULL);
}
-/* }}} */
+/* }}} */
static zend_bool is_protected_variable(char *varname TSRMLS_DC) /* {{{ */
{
@@ -226,41 +158,33 @@ static zend_bool is_protected_variable(char *varname TSRMLS_DC) /* {{{ */
}
/* }}} */
-static void safe_php_register_variable(char *var, char *strval, int val_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC) /* {{{ */
+static void safe_php_register_variable(char *var, char *strval, int val_len, zval *track_vars_array, zend_bool override_protection TSRMLS_DC) /* {{{ */
{
if (override_protection || !is_protected_variable(var TSRMLS_CC)) {
php_register_variable_safe(var, strval, val_len, track_vars_array TSRMLS_CC);
}
}
-/* }}} */
+/* }}} */
-static void safe_php_register_variable_ex(char *var, zval *val, zval *track_vars_array, zend_bool override_protection TSRMLS_DC) /* {{{ */
+static void safe_php_register_variable_ex(char *var, zval *val, zval *track_vars_array, zend_bool override_protection TSRMLS_DC) /* {{{ */
{
if (override_protection || !is_protected_variable(var TSRMLS_CC)) {
php_register_variable_ex(var, val, track_vars_array TSRMLS_CC);
}
}
-/* }}} */
+/* }}} */
-static void register_http_post_files_variable(char *strvar, char *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC) /* {{{ */
+static void register_http_post_files_variable(char *strvar, char *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC) /* {{{ */
{
- int register_globals = PG(register_globals);
-
- PG(register_globals) = 0;
safe_php_register_variable(strvar, val, strlen(val), http_post_files, override_protection TSRMLS_CC);
- PG(register_globals) = register_globals;
}
-/* }}} */
+/* }}} */
static void register_http_post_files_variable_ex(char *var, zval *val, zval *http_post_files, zend_bool override_protection TSRMLS_DC) /* {{{ */
{
- int register_globals = PG(register_globals);
-
- PG(register_globals) = 0;
safe_php_register_variable_ex(var, val, http_post_files, override_protection TSRMLS_CC);
- PG(register_globals) = register_globals;
}
-/* }}} */
+/* }}} */
static int unlink_filename(char **filename TSRMLS_DC) /* {{{ */
{
@@ -277,7 +201,7 @@ void destroy_uploaded_files_hash(TSRMLS_D) /* {{{ */
}
/* }}} */
-/* {{{ Following code is based on apache_multipart_buffer.c from libapreq-0.33 package. */
+/* {{{ Following code is based on apache_multipart_buffer.c from libapreq-0.33 package. */
#define FILLUNIT (1024 * 5)
@@ -294,6 +218,9 @@ typedef struct {
char *boundary_next;
int boundary_next_len;
+ const zend_encoding *input_encoding;
+ const zend_encoding **detect_order;
+ size_t detect_order_size;
} multipart_buffer;
typedef struct {
@@ -351,7 +278,7 @@ static int multipart_buffer_eof(multipart_buffer *self TSRMLS_DC)
}
/* create new multipart_buffer structure */
-static multipart_buffer *multipart_buffer_new(char *boundary, int boundary_len)
+static multipart_buffer *multipart_buffer_new(char *boundary, int boundary_len TSRMLS_DC)
{
multipart_buffer *self = (multipart_buffer *) ecalloc(1, sizeof(multipart_buffer));
@@ -368,6 +295,15 @@ static multipart_buffer *multipart_buffer_new(char *boundary, int boundary_len)
self->buf_begin = self->buffer;
self->bytes_in_buffer = 0;
+ if (php_rfc1867_encoding_translation(TSRMLS_C)) {
+ php_rfc1867_get_detect_order(&self->detect_order, &self->detect_order_size TSRMLS_CC);
+ } else {
+ self->detect_order = NULL;
+ self->detect_order_size = 0;
+ }
+
+ self->input_encoding = NULL;
+
return self;
}
@@ -478,6 +414,10 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T
char *key = line;
char *value = NULL;
+ if (php_rfc1867_encoding_translation(TSRMLS_C)) {
+ self->input_encoding = zend_multibyte_encoding_detector(line, strlen(line), self->detect_order, self->detect_order_size TSRMLS_CC);
+ }
+
/* space in the beginning means same header */
if (!isspace(line[0])) {
value = strchr(line, ':');
@@ -533,7 +473,7 @@ static char *php_mime_get_hdr_value(zend_llist header, char *key)
return NULL;
}
-static char *php_ap_getword(char **line, char stop)
+static char *php_ap_getword(const zend_encoding *encoding, char **line, char stop TSRMLS_DC)
{
char *pos = *line, quote;
char *res;
@@ -569,29 +509,17 @@ static char *php_ap_getword(char **line, char stop)
return res;
}
-static char *substring_conf(char *start, int len, char quote TSRMLS_DC)
+static char *substring_conf(char *start, int len, char quote)
{
- char *result = emalloc(len + 2);
+ char *result = emalloc(len + 1);
char *resp = result;
int i;
- for (i = 0; i < len; ++i) {
+ for (i = 0; i < len && start[i] != quote; ++i) {
if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
*resp++ = start[++i];
} else {
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
- if (php_mb_encoding_translation(TSRMLS_C)) {
- size_t j = php_mb_gpc_mbchar_bytes(start+i TSRMLS_CC);
- while (j-- > 0 && i < len) {
- *resp++ = start[i++];
- }
- --i;
- } else {
- *resp++ = start[i];
- }
-#else
*resp++ = start[i];
-#endif
}
}
@@ -599,65 +527,49 @@ static char *substring_conf(char *start, int len, char quote TSRMLS_DC)
return result;
}
-static char *php_ap_getword_conf(char **line TSRMLS_DC)
+static char *php_ap_getword_conf(const zend_encoding *encoding, char *str TSRMLS_DC)
{
- char *str = *line, *strend, *res, quote;
-
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
- if (php_mb_encoding_translation(TSRMLS_C)) {
- int len=strlen(str);
- php_mb_gpc_encoding_detector(&str, &len, 1, NULL TSRMLS_CC);
- }
-#endif
-
while (*str && isspace(*str)) {
++str;
}
if (!*str) {
- *line = str;
return estrdup("");
}
- if ((quote = *str) == '"' || quote == '\'') {
- strend = str + 1;
-look_for_quote:
- while (*strend && *strend != quote) {
- if (*strend == '\\' && strend[1] && strend[1] == quote) {
- strend += 2;
- } else {
- ++strend;
- }
- }
- if (*strend && *strend == quote) {
- char p = *(strend + 1);
- if (p != '\r' && p != '\n' && p != '\0') {
- strend++;
- goto look_for_quote;
- }
- }
-
- res = substring_conf(str + 1, strend - str - 1, quote TSRMLS_CC);
-
- if (*strend == quote) {
- ++strend;
- }
+ if (*str == '"' || *str == '\'') {
+ char quote = *str;
+ str++;
+ return substring_conf(str, strlen(str), quote);
} else {
+ char *strend = str;
- strend = str;
while (*strend && !isspace(*strend)) {
++strend;
}
- res = substring_conf(str, strend - str, 0 TSRMLS_CC);
+ return substring_conf(str, strend - str, 0);
}
+}
- while (*strend && isspace(*strend)) {
- ++strend;
- }
+static char *php_ap_basename(const zend_encoding *encoding, char *path TSRMLS_DC)
+{
+ char *s = strrchr(path, '\\');
+ char *s2 = strrchr(path, '/');
- *line = strend;
- return res;
+ if (s && s2) {
+ if (s > s2) {
+ ++s;
+ } else {
+ s = ++s2;
+ }
+ return s;
+ } else if (s) {
+ return ++s;
+ } else if (s2) {
+ return ++s2;
+ }
+ return path;
}
/*
@@ -760,7 +672,7 @@ static char *multipart_buffer_read_body(multipart_buffer *self, unsigned int *le
*
*/
-SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
+SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
{
char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL;
char *temp_filename = NULL, *lbuf = NULL, *abuf = NULL;
@@ -768,19 +680,29 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
int max_file_size = 0, skip_upload = 0, anonindex = 0, is_anonymous;
zval *http_post_files = NULL;
HashTable *uploaded_files = NULL;
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
- int str_len = 0, num_vars = 0, num_vars_max = 2*10, *len_list = NULL;
- char **val_list = NULL;
-#endif
multipart_buffer *mbuff;
zval *array_ptr = (zval *) arg;
int fd = -1;
zend_llist header;
void *event_extra_data = NULL;
- int llen = 0;
+ unsigned int llen = 0;
int upload_cnt = INI_INT("max_file_uploads");
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ php_rfc1867_getword_t getword;
+ php_rfc1867_getword_conf_t getword_conf;
+ php_rfc1867_basename_t _basename;
long count = 0;
+ if (php_rfc1867_encoding_translation(TSRMLS_C) && internal_encoding) {
+ getword = php_rfc1867_getword;
+ getword_conf = php_rfc1867_getword_conf;
+ _basename = php_rfc1867_basename;
+ } else {
+ getword = php_ap_getword;
+ getword_conf = php_ap_getword_conf;
+ _basename = php_ap_basename;
+ }
+
if (SG(post_max_size) > 0 && SG(request_info).content_length > SG(post_max_size)) {
sapi_module.sapi_error(E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes", SG(request_info).content_length, SG(post_max_size));
return;
@@ -825,7 +747,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
}
/* Initialize the buffer */
- if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) {
+ if (!(mbuff = multipart_buffer_new(boundary, boundary_len TSRMLS_CC))) {
sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer");
return;
}
@@ -842,12 +764,6 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
INIT_PZVAL(http_post_files);
PG(http_globals)[TRACK_VARS_FILES] = http_post_files;
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
- if (php_mb_encoding_translation(TSRMLS_C)) {
- val_list = (char **)ecalloc(num_vars_max+2, sizeof(char *));
- len_list = (int *)ecalloc(num_vars_max+2, sizeof(int));
- }
-#endif
zend_llist_init(&header, sizeof(mime_header_entry), (llist_dtor_func_t) php_free_hdr_entry, 0);
if (php_rfc1867_callback != NULL) {
@@ -880,7 +796,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
++cd;
}
- while (*cd && (pair = php_ap_getword(&cd, ';')))
+ while (*cd && (pair = getword(mbuff->input_encoding, &cd, ';' TSRMLS_CC)))
{
char *key = NULL, *word = pair;
@@ -889,18 +805,34 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
}
if (strchr(pair, '=')) {
- key = php_ap_getword(&pair, '=');
+ key = getword(mbuff->input_encoding, &pair, '=' TSRMLS_CC);
if (!strcasecmp(key, "name")) {
if (param) {
efree(param);
}
- param = php_ap_getword_conf(&pair TSRMLS_CC);
+ param = getword_conf(mbuff->input_encoding, pair TSRMLS_CC);
+ if (mbuff->input_encoding && internal_encoding) {
+ unsigned char *new_param;
+ size_t new_param_len;
+ if ((size_t)-1 != zend_multibyte_encoding_converter(&new_param, &new_param_len, (unsigned char *)param, strlen(param), internal_encoding, mbuff->input_encoding TSRMLS_CC)) {
+ efree(param);
+ param = (char *)new_param;
+ }
+ }
} else if (!strcasecmp(key, "filename")) {
if (filename) {
efree(filename);
}
- filename = php_ap_getword_conf(&pair TSRMLS_CC);
+ filename = getword_conf(mbuff->input_encoding, pair TSRMLS_CC);
+ if (mbuff->input_encoding && internal_encoding) {
+ unsigned char *new_filename;
+ size_t new_filename_len;
+ if ((size_t)-1 != zend_multibyte_encoding_converter(&new_filename, &new_filename_len, (unsigned char *)filename, strlen(filename), internal_encoding, mbuff->input_encoding TSRMLS_CC)) {
+ efree(filename);
+ filename = (char *)new_filename;
+ }
+ }
}
}
if (key) {
@@ -917,6 +849,17 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
if (!value) {
value = estrdup("");
+ value_len = 0;
+ }
+
+ if (mbuff->input_encoding && internal_encoding) {
+ unsigned char *new_value;
+ size_t new_value_len;
+ if ((size_t)-1 != zend_multibyte_encoding_converter(&new_value, &new_value_len, (unsigned char *)value, value_len, internal_encoding, mbuff->input_encoding TSRMLS_CC)) {
+ efree(value);
+ value = (char *)new_value;
+ value_len = new_value_len;
+ }
}
if (++count <= PG(max_input_vars) && sapi_module.input_filter(PARSE_POST, param, &value, value_len, &new_val_len TSRMLS_CC)) {
@@ -936,21 +879,12 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
}
new_val_len = newlength;
}
-
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
- if (php_mb_encoding_translation(TSRMLS_C)) {
- php_mb_gpc_stack_variable(param, value, &val_list, &len_list, &num_vars, &num_vars_max TSRMLS_CC);
- } else {
- safe_php_register_variable(param, value, new_val_len, array_ptr, 0 TSRMLS_CC);
- }
-#else
safe_php_register_variable(param, value, new_val_len, array_ptr, 0 TSRMLS_CC);
-#endif
} else {
if (count == PG(max_input_vars) + 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
}
-
+
if (php_rfc1867_callback != NULL) {
multipart_event_formdata event_formdata;
@@ -1054,7 +988,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
offset = 0;
end = 0;
-
+
if (!cancel_upload) {
/* only bother to open temp file if we have data */
blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC);
@@ -1089,12 +1023,12 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
}
}
- if (PG(upload_max_filesize) > 0 && (total_bytes+blen) > PG(upload_max_filesize)) {
+ if (PG(upload_max_filesize) > 0 && (long)(total_bytes+blen) > PG(upload_max_filesize)) {
#if DEBUG_FILE_UPLOAD
sapi_module.sapi_error(E_NOTICE, "upload_max_filesize of %ld bytes exceeded - file [%s=%s] not saved", PG(upload_max_filesize), param, filename);
#endif
cancel_upload = UPLOAD_ERROR_A;
- } else if (max_file_size && ((total_bytes+blen) > max_file_size)) {
+ } else if (max_file_size && ((long)(total_bytes+blen) > max_file_size)) {
#if DEBUG_FILE_UPLOAD
sapi_module.sapi_error(E_NOTICE, "MAX_FILE_SIZE of %ld bytes exceeded - file [%s=%s] not saved", max_file_size, param, filename);
#endif
@@ -1190,56 +1124,18 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
snprintf(lbuf, llen, "%s_name", param);
}
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
- if (php_mb_encoding_translation(TSRMLS_C)) {
- if (num_vars >= num_vars_max) {
- php_mb_gpc_realloc_buffer(&val_list, &len_list, &num_vars_max, 1 TSRMLS_CC);
- }
- val_list[num_vars] = filename;
- len_list[num_vars] = strlen(filename);
- num_vars++;
- if (php_mb_gpc_encoding_detector(val_list, len_list, num_vars, NULL TSRMLS_CC) == SUCCESS) {
- str_len = strlen(filename);
- php_mb_gpc_encoding_converter(&filename, &str_len, 1, NULL, NULL TSRMLS_CC);
- }
- s = php_mb_strrchr(filename, '\\' TSRMLS_CC);
- if ((tmp = php_mb_strrchr(filename, '/' TSRMLS_CC)) > s) {
- s = tmp;
- }
- num_vars--;
- goto filedone;
- }
-#endif
/* The \ check should technically be needed for win32 systems only where
* it is a valid path separator. However, IE in all it's wisdom always sends
* the full path of the file on the user's filesystem, which means that unless
* the user does basename() they get a bogus file name. Until IE's user base drops
* to nill or problem is fixed this code must remain enabled for all systems. */
- s = strrchr(filename, '\\');
- if ((tmp = strrchr(filename, '/')) > s) {
- s = tmp;
- }
-#ifdef PHP_WIN32
- if (PG(magic_quotes_gpc)) {
- if ((tmp = strrchr(s ? s : filename, '\'')) > s) {
- s = tmp;
- }
- if ((tmp = strrchr(s ? s : filename, '"')) > s) {
- s = tmp;
- }
+ s = _basename(internal_encoding, filename TSRMLS_CC);
+ if (!s) {
+ s = filename;
}
-#endif
-
-#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
-filedone:
-#endif
if (!is_anonymous) {
- if (s && s >= filename) {
- safe_php_register_variable(lbuf, s+1, strlen(s+1), NULL, 0 TSRMLS_CC);
- } else {
- safe_php_register_variable(lbuf, filename, strlen(filename), NULL, 0 TSRMLS_CC);
- }
+ safe_php_register_variable(lbuf, s, strlen(s), NULL, 0 TSRMLS_CC);
}
/* Add $foo[name] */
@@ -1248,11 +1144,7 @@ filedone:
} else {
snprintf(lbuf, llen, "%s[name]", param);
}
- if (s && s >= filename) {
- register_http_post_files_variable(lbuf, s+1, http_post_files, 0 TSRMLS_CC);
- } else {
- register_http_post_files_variable(lbuf, filename, http_post_files, 0 TSRMLS_CC);
- }
+ register_http_post_files_variable(lbuf, s, http_post_files, 0 TSRMLS_CC);
efree(filename);
s = NULL;
@@ -1292,7 +1184,7 @@ filedone:
s = "";
{
- /* store temp_filename as-is (without magic_quotes_gpc-ing it, in case upload_tmp_dir
+ /* store temp_filename as-is (in case upload_tmp_dir
* contains escapeable characters. escape only the variable name.) */
zval zfilename;
@@ -1368,7 +1260,32 @@ fileupload_done:
php_rfc1867_callback(MULTIPART_EVENT_END, &event_end, &event_extra_data TSRMLS_CC);
}
- SAFE_RETURN;
+ if (lbuf) efree(lbuf);
+ if (abuf) efree(abuf);
+ if (array_index) efree(array_index);
+ zend_hash_destroy(&PG(rfc1867_protected_variables));
+ zend_llist_destroy(&header);
+ if (mbuff->boundary_next) efree(mbuff->boundary_next);
+ if (mbuff->boundary) efree(mbuff->boundary);
+ if (mbuff->buffer) efree(mbuff->buffer);
+ if (mbuff) efree(mbuff);
+}
+/* }}} */
+
+SAPI_API void php_rfc1867_set_multibyte_callbacks(
+ php_rfc1867_encoding_translation_t encoding_translation,
+ php_rfc1867_get_detect_order_t get_detect_order,
+ php_rfc1867_set_input_encoding_t set_input_encoding,
+ php_rfc1867_getword_t getword,
+ php_rfc1867_getword_conf_t getword_conf,
+ php_rfc1867_basename_t basename) /* {{{ */
+{
+ php_rfc1867_encoding_translation = encoding_translation;
+ php_rfc1867_get_detect_order = get_detect_order;
+ php_rfc1867_set_input_encoding = set_input_encoding;
+ php_rfc1867_getword = getword;
+ php_rfc1867_getword_conf = getword_conf;
+ php_rfc1867_basename = basename;
}
/* }}} */
diff --git a/main/rfc1867.h b/main/rfc1867.h
index 7f6c48905c..618458be34 100644
--- a/main/rfc1867.h
+++ b/main/rfc1867.h
@@ -67,10 +67,25 @@ typedef struct _multipart_event_end {
size_t post_bytes_processed;
} multipart_event_end;
+typedef int (*php_rfc1867_encoding_translation_t)(TSRMLS_D);
+typedef void (*php_rfc1867_get_detect_order_t)(const zend_encoding ***list, size_t *list_size TSRMLS_DC);
+typedef void (*php_rfc1867_set_input_encoding_t)(const zend_encoding *encoding TSRMLS_DC);
+typedef char* (*php_rfc1867_getword_t)(const zend_encoding *encoding, char **line, char stop TSRMLS_DC);
+typedef char* (*php_rfc1867_getword_conf_t)(const zend_encoding *encoding, char *str TSRMLS_DC);
+typedef char* (*php_rfc1867_basename_t)(const zend_encoding *encoding, char *str TSRMLS_DC);
+
SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler);
void destroy_uploaded_files_hash(TSRMLS_D);
void php_rfc1867_register_constants(TSRMLS_D);
extern PHPAPI int (*php_rfc1867_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC);
+SAPI_API void php_rfc1867_set_multibyte_callbacks(
+ php_rfc1867_encoding_translation_t encoding_translation,
+ php_rfc1867_get_detect_order_t get_detect_order,
+ php_rfc1867_set_input_encoding_t set_input_encoding,
+ php_rfc1867_getword_t getword,
+ php_rfc1867_getword_conf_t getword_conf,
+ php_rfc1867_basename_t basename);
+
#endif /* RFC1867_H */
diff --git a/main/safe_mode.c b/main/safe_mode.c
deleted file mode 100644
index 889becb853..0000000000
--- a/main/safe_mode.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
- +----------------------------------------------------------------------+
- */
-
-/* $Id$ */
-
-#include "php.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/stat.h>
-#include "ext/standard/pageinfo.h"
-#include "safe_mode.h"
-#include "SAPI.h"
-#include "php_globals.h"
-
-/*
- * php_checkuid
- *
- * This function has six modes:
- *
- * 0 - return invalid (0) if file does not exist
- * 1 - return valid (1) if file does not exist
- * 2 - if file does not exist, check directory
- * 3 - only check directory (needed for mkdir)
- * 4 - check mode and param
- * 5 - only check file
- */
-
-PHPAPI int php_checkuid_ex(const char *filename, const char *fopen_mode, int mode, int flags)
-{
- struct stat sb;
- int ret, nofile=0;
- long uid=0L, gid=0L, duid=0L, dgid=0L;
- char path[MAXPATHLEN];
- char *s, filenamecopy[MAXPATHLEN];
- TSRMLS_FETCH();
-
- path[0] = '\0';
-
- if (!filename) {
- return 0; /* path must be provided */
- }
-
- if (strlcpy(filenamecopy, filename, MAXPATHLEN)>=MAXPATHLEN) {
- return 0;
- }
- filename=(char *)&filenamecopy;
-
- if (fopen_mode) {
- if (fopen_mode[0] == 'r') {
- mode = CHECKUID_DISALLOW_FILE_NOT_EXISTS;
- } else {
- mode = CHECKUID_CHECK_FILE_AND_DIR;
- }
- }
-
- /* First we see if the file is owned by the same user...
- * If that fails, passthrough and check directory...
- */
- if (mode != CHECKUID_ALLOW_ONLY_DIR) {
-#if HAVE_BROKEN_GETCWD
- char ftest[MAXPATHLEN];
-
- strcpy(ftest, filename);
- if (VCWD_GETCWD(ftest, sizeof(ftest)) == NULL) {
- strcpy(path, filename);
- } else
-#endif
- expand_filepath(filename, path TSRMLS_CC);
-
- ret = VCWD_STAT(path, &sb);
- if (ret < 0) {
- if (mode == CHECKUID_DISALLOW_FILE_NOT_EXISTS) {
- if ((flags & CHECKUID_NO_ERRORS) == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename);
- }
- return 0;
- } else if (mode == CHECKUID_ALLOW_FILE_NOT_EXISTS) {
- if ((flags & CHECKUID_NO_ERRORS) == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename);
- }
- return 1;
- }
- nofile = 1;
- } else {
- uid = sb.st_uid;
- gid = sb.st_gid;
- if (uid == php_getuid()) {
- return 1;
- } else if (PG(safe_mode_gid) && gid == php_getgid()) {
- return 1;
- }
- }
-
- /* Trim off filename */
- if ((s = strrchr(path, DEFAULT_SLASH))) {
- if (*(s + 1) == '\0' && s != path) { /* make sure that the / is not the last character */
- *s = '\0';
- s = strrchr(path, DEFAULT_SLASH);
- }
- if (s) {
- if (s == path) {
- path[1] = '\0';
- } else {
- *s = '\0';
- }
- }
- }
- } else { /* CHECKUID_ALLOW_ONLY_DIR */
- s = strrchr(filename, DEFAULT_SLASH);
-
- if (s == filename) {
- /* root dir */
- path[0] = DEFAULT_SLASH;
- path[1] = '\0';
- } else if (s && *(s + 1) != '\0') { /* make sure that the / is not the last character */
- *s = '\0';
- VCWD_REALPATH(filename, path);
- *s = DEFAULT_SLASH;
- } else {
- /* Under Solaris, getcwd() can fail if there are no
- * read permissions on a component of the path, even
- * though it has the required x permissions */
- path[0] = '.';
- path[1] = '\0';
- VCWD_GETCWD(path, sizeof(path));
- }
- } /* end CHECKUID_ALLOW_ONLY_DIR */
-
- if (mode != CHECKUID_ALLOW_ONLY_FILE) {
- /* check directory */
- ret = VCWD_STAT(path, &sb);
- if (ret < 0) {
- if ((flags & CHECKUID_NO_ERRORS) == 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename);
- }
- return 0;
- }
- duid = sb.st_uid;
- dgid = sb.st_gid;
- if (duid == php_getuid()) {
- return 1;
- } else if (PG(safe_mode_gid) && dgid == php_getgid()) {
- return 1;
- } else {
- if (SG(rfc1867_uploaded_files)) {
- if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, strlen(filename)+1)) {
- return 1;
- }
- }
- }
- }
-
- if (mode == CHECKUID_ALLOW_ONLY_DIR) {
- uid = duid;
- gid = dgid;
- if (s) {
- *s = 0;
- }
- }
-
- if (nofile) {
- uid = duid;
- gid = dgid;
- filename = path;
- }
-
- if ((flags & CHECKUID_NO_ERRORS) == 0) {
- if (PG(safe_mode_gid)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The script whose uid/gid is %ld/%ld is not allowed to access %s owned by uid/gid %ld/%ld", php_getuid(), php_getgid(), filename, uid, gid);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The script whose uid is %ld is not allowed to access %s owned by uid %ld", php_getuid(), filename, uid);
- }
- }
-
- return 0;
-}
-
-PHPAPI int php_checkuid(const char *filename, const char *fopen_mode, int mode)
-{
-#ifdef NETWARE
-/* NetWare don't have uid*/
- return 1;
-#else
- return php_checkuid_ex(filename, fopen_mode, mode, 0);
-#endif
-}
-
-PHPAPI char *php_get_current_user(void)
-{
- struct stat *pstat;
- TSRMLS_FETCH();
-
- if (SG(request_info).current_user) {
- return SG(request_info).current_user;
- }
-
- /* FIXME: I need to have this somehow handled if
- USE_SAPI is defined, because cgi will also be
- interfaced in USE_SAPI */
-
- pstat = sapi_get_stat(TSRMLS_C);
-
- if (!pstat) {
- return "";
- } else {
-#ifdef PHP_WIN32
- char name[256];
- DWORD len = sizeof(name)-1;
-
- if (!GetUserName(name, &len)) {
- return "";
- }
- name[len] = '\0';
- SG(request_info).current_user_length = len;
- SG(request_info).current_user = estrndup(name, len);
- return SG(request_info).current_user;
-#else
- struct passwd *pwd;
-#if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
- struct passwd _pw;
- struct passwd *retpwptr = NULL;
- int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
- char *pwbuf;
-
- if (pwbuflen < 1) {
- return "";
- }
- pwbuf = emalloc(pwbuflen);
- if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
- efree(pwbuf);
- return "";
- }
- pwd = &_pw;
-#else
- if ((pwd=getpwuid(pstat->st_uid))==NULL) {
- return "";
- }
-#endif
- SG(request_info).current_user_length = strlen(pwd->pw_name);
- SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
-#if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
- efree(pwbuf);
-#endif
- return SG(request_info).current_user;
-#endif
- }
-}
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
diff --git a/main/snprintf.c b/main/snprintf.c
index 1e0e45510d..bda110d339 100644
--- a/main/snprintf.c
+++ b/main/snprintf.c
@@ -18,7 +18,7 @@
/* $Id$ */
-
+#define _GNU_SOURCE
#include "php.h"
#include <zend_strtod.h>
@@ -1222,7 +1222,7 @@ static void strx_printv(int *ccp, char *buf, size_t len, const char *format, va_
PHPAPI int ap_php_slprintf(char *buf, size_t len, const char *format,...) /* {{{ */
{
- int cc;
+ unsigned int cc;
va_list ap;
va_start(ap, format);
@@ -1238,7 +1238,7 @@ PHPAPI int ap_php_slprintf(char *buf, size_t len, const char *format,...) /* {{{
PHPAPI int ap_php_vslprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
{
- int cc;
+ unsigned int cc;
strx_printv(&cc, buf, len, format, ap);
if (cc >= len) {
diff --git a/main/spprintf.c b/main/spprintf.c
index e3c18abe4a..ef51cc5f41 100644
--- a/main/spprintf.c
+++ b/main/spprintf.c
@@ -123,7 +123,7 @@
* NDIG = 320
* NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
*/
-#define NUM_BUF_SIZE 2048
+#define NUM_BUF_SIZE 2048
/*
* The INS_CHAR macro inserts a character in the buffer.
diff --git a/main/streams/cast.c b/main/streams/cast.c
index 0dcdddac3c..da56e86679 100644
--- a/main/streams/cast.c
+++ b/main/streams/cast.c
@@ -271,7 +271,7 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
newstream = php_stream_fopen_tmpfile();
if (newstream) {
- size_t retcopy = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL, NULL);
+ int retcopy = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL, NULL);
if (retcopy != SUCCESS) {
php_stream_close(newstream);
diff --git a/main/streams/glob_wrapper.c b/main/streams/glob_wrapper.c
index 4a35153722..7b568501ee 100644
--- a/main/streams/glob_wrapper.c
+++ b/main/streams/glob_wrapper.c
@@ -145,7 +145,7 @@ static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count T
/* avoid problems if someone mis-uses the stream */
if (count == sizeof(php_stream_dirent) && pglob) {
- if (pglob->index < pglob->glob.gl_pathc) {
+ if (pglob->index < (size_t)pglob->glob.gl_pathc) {
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path TSRMLS_CC);
PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
return sizeof(php_stream_dirent);
diff --git a/main/streams/memory.c b/main/streams/memory.c
index 7a78d55c41..9e0fae6d1e 100644
--- a/main/streams/memory.c
+++ b/main/streams/memory.c
@@ -42,7 +42,6 @@ typedef struct {
size_t fsize;
size_t smax;
int mode;
- php_stream **owner_ptr;
} php_stream_memory_data;
@@ -112,9 +111,6 @@ static int php_stream_memory_close(php_stream *stream, int close_handle TSRMLS_D
if (ms->data && close_handle && ms->mode != TEMP_STREAM_READONLY) {
efree(ms->data);
}
- if (ms->owner_ptr) {
- *ms->owner_ptr = NULL;
- }
efree(ms);
return 0;
}
@@ -301,7 +297,6 @@ PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC TSRMLS_DC)
self->fsize = 0;
self->smax = ~0u;
self->mode = mode;
- self->owner_ptr = NULL;
stream = php_stream_alloc_rel(&php_stream_memory_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
@@ -376,8 +371,9 @@ static size_t php_stream_temp_write(php_stream *stream, const char *buf, size_t
if (memsize + count >= ts->smax) {
php_stream *file = php_stream_fopen_tmpfile();
php_stream_write(file, membuf, memsize);
- php_stream_close(ts->innerstream);
+ php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE);
ts->innerstream = file;
+ php_stream_encloses(stream, ts->innerstream);
}
}
return php_stream_write(ts->innerstream, buf, count);
@@ -415,7 +411,7 @@ static int php_stream_temp_close(php_stream *stream, int close_handle TSRMLS_DC)
assert(ts != NULL);
if (ts->innerstream) {
- ret = php_stream_free(ts->innerstream, PHP_STREAM_FREE_CLOSE | (close_handle ? 0 : PHP_STREAM_FREE_PRESERVE_HANDLE));
+ ret = php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE | (close_handle ? 0 : PHP_STREAM_FREE_PRESERVE_HANDLE));
} else {
ret = 0;
}
@@ -499,9 +495,10 @@ static int php_stream_temp_cast(php_stream *stream, int castas, void **ret TSRML
file = php_stream_fopen_tmpfile();
php_stream_write(file, membuf, memsize);
pos = php_stream_tell(ts->innerstream);
-
- php_stream_close(ts->innerstream);
+
+ php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE);
ts->innerstream = file;
+ php_stream_encloses(stream, ts->innerstream);
php_stream_seek(ts->innerstream, pos, SEEK_SET);
return php_stream_cast(ts->innerstream, castas, ret, 1);
@@ -563,8 +560,7 @@ PHPAPI php_stream *_php_stream_temp_create(int mode, size_t max_memory_usage STR
stream = php_stream_alloc_rel(&php_stream_temp_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
self->innerstream = php_stream_memory_create_rel(mode);
- php_stream_auto_cleanup(self->innerstream); /* do not warn if innerstream is GC'ed before stream */
- ((php_stream_memory_data*)self->innerstream->abstract)->owner_ptr = &self->innerstream;
+ php_stream_encloses(stream, self->innerstream);
return stream;
}
diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h
index a0500db2bd..5767b74d26 100644
--- a/main/streams/php_stream_context.h
+++ b/main/streams/php_stream_context.h
@@ -33,10 +33,10 @@ typedef void (*php_stream_notification_func)(php_stream_context *context,
If no context was passed, use the default context
The default context has not yet been created, do it now. */
#define php_stream_context_from_zval(zcontext, nocontext) ( \
- (zcontext) ? zend_fetch_resource(&(zcontext) TSRMLS_CC, -1, "Stream-Context", NULL, 1, php_le_stream_context()) : \
+ (zcontext) ? zend_fetch_resource(&(zcontext) TSRMLS_CC, -1, "Stream-Context", NULL, 1, php_le_stream_context(TSRMLS_C)) : \
(nocontext) ? NULL : \
FG(default_context) ? FG(default_context) : \
- (FG(default_context) = php_stream_context_alloc()) )
+ (FG(default_context) = php_stream_context_alloc(TSRMLS_C)) )
#define php_stream_context_to_zval(context, zval) { ZVAL_RESOURCE(zval, (context)->rsrc_id); zend_list_addref((context)->rsrc_id); }
@@ -59,7 +59,7 @@ struct _php_stream_context {
BEGIN_EXTERN_C()
PHPAPI void php_stream_context_free(php_stream_context *context);
-PHPAPI php_stream_context *php_stream_context_alloc(void);
+PHPAPI php_stream_context *php_stream_context_alloc(TSRMLS_D);
PHPAPI int php_stream_context_get_option(php_stream_context *context,
const char *wrappername, const char *optionname, zval ***optionvalue);
PHPAPI int php_stream_context_set_option(php_stream_context *context,
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
index cd5f26148b..77e411377e 100644
--- a/main/streams/plain_wrapper.c
+++ b/main/streams/plain_wrapper.c
@@ -48,6 +48,11 @@
#define php_stream_fopen_from_file_int(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_CC TSRMLS_CC)
#define php_stream_fopen_from_file_int_rel(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_REL_CC TSRMLS_CC)
+#if !defined(WINDOWS) && !defined(NETWARE)
+extern int php_get_uid_by_name(const char *name, uid_t *uid TSRMLS_DC);
+extern int php_get_gid_by_name(const char *name, gid_t *gid TSRMLS_DC);
+#endif
+
/* parse standard "fopen" modes into open() flags */
PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
{
@@ -108,7 +113,7 @@ typedef struct {
unsigned is_pipe:1; /* don't try and seek */
unsigned cached_fstat:1; /* sb is valid */
unsigned _reserved:29;
-
+
int lock_flag; /* stores the lock state */
char *temp_file_name; /* if non-null, this is the path to a temporary file that
* is to be deleted when the stream is closed */
@@ -134,7 +139,7 @@ static int do_fstat(php_stdio_stream_data *d, int force)
if (!d->cached_fstat || force) {
int fd;
int r;
-
+
PHP_STDIOP_GET_FD(fd, d);
r = fstat(fd, &d->sb);
d->cached_fstat = r == 0;
@@ -147,7 +152,7 @@ static int do_fstat(php_stdio_stream_data *d, int force)
static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC)
{
php_stdio_stream_data *self;
-
+
self = pemalloc_rel_orig(sizeof(*self), persistent_id);
memset(self, 0, sizeof(*self));
self->file = NULL;
@@ -156,14 +161,14 @@ static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const
self->is_process_pipe = 0;
self->temp_file_name = NULL;
self->fd = fd;
-
+
return php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode);
}
static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode STREAMS_DC TSRMLS_DC)
{
php_stdio_stream_data *self;
-
+
self = emalloc_rel_orig(sizeof(*self));
memset(self, 0, sizeof(*self));
self->file = file;
@@ -208,7 +213,7 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC)
self->temp_file_name = opened_path;
self->lock_flag = LOCK_UN;
-
+
return stream;
}
close(fd);
@@ -241,7 +246,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
}
}
#endif
-
+
if (self->is_pipe) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
} else {
@@ -280,7 +285,7 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
}
}
#endif
-
+
if (self->is_pipe) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
} else {
@@ -349,9 +354,9 @@ static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count TSRMLS
so script can retry if desired */
ret = read(data->fd, buf, count);
}
-
+
stream->eof = (ret == 0 || (ret == (size_t)-1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF));
-
+
} else {
#if HAVE_FLUSHIO
if (!data->is_pipe && data->last_op == 'w')
@@ -388,7 +393,7 @@ static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC)
data->file_mapping = NULL;
}
#endif
-
+
if (close_handle) {
if (data->file) {
if (data->is_process_pipe) {
@@ -458,14 +463,14 @@ static int php_stdiop_seek(php_stream *stream, off_t offset, int whence, off_t *
if (data->fd >= 0) {
off_t result;
-
+
result = lseek(data->fd, offset, whence);
if (result == (off_t)-1)
return -1;
*newoffset = result;
return 0;
-
+
} else {
ret = fseek(data->file, offset, whence);
*newoffset = ftell(data->file);
@@ -479,7 +484,7 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
assert(data != NULL);
-
+
/* as soon as someone touches the stdio layer, buffering may ensue,
* so we need to stop using the fd directly in that case */
@@ -497,7 +502,7 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
return FAILURE;
}
}
-
+
*(FILE**)ret = data->file;
data->fd = -1;
}
@@ -553,9 +558,9 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
int flags;
int oldval;
#endif
-
+
PHP_STDIOP_GET_FD(fd, data);
-
+
switch(option) {
case PHP_STREAM_OPTION_BLOCKING:
if (fd == -1)
@@ -567,20 +572,20 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
flags &= ~O_NONBLOCK;
else
flags |= O_NONBLOCK;
-
+
if (-1 == fcntl(fd, F_SETFL, flags))
return -1;
return oldval;
#else
return -1; /* not yet implemented */
#endif
-
+
case PHP_STREAM_OPTION_WRITE_BUFFER:
if (data->file == NULL) {
return -1;
}
-
+
if (ptrparam)
size = *(size_t *)ptrparam;
else
@@ -588,22 +593,19 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
switch(value) {
case PHP_STREAM_BUFFER_NONE:
- stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
return setvbuf(data->file, NULL, _IONBF, 0);
-
+
case PHP_STREAM_BUFFER_LINE:
- stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER;
return setvbuf(data->file, NULL, _IOLBF, size);
-
+
case PHP_STREAM_BUFFER_FULL:
- stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER;
return setvbuf(data->file, NULL, _IOFBF, size);
default:
return -1;
}
break;
-
+
case PHP_STREAM_OPTION_LOCKING:
if (fd == -1) {
return -1;
@@ -626,7 +628,7 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
{
php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
int prot, flags;
-
+
switch (value) {
case PHP_STREAM_MMAP_SUPPORTED:
return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
@@ -791,7 +793,7 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
}
}
-
+
default:
return PHP_STREAM_OPTION_RETURN_NOTIMPL;
}
@@ -864,11 +866,7 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char
if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
return NULL;
}
-
- if (PG(safe_mode) &&(!php_checkuid(path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return NULL;
- }
-
+
dir = VCWD_OPENDIR(path);
#ifdef PHP_WIN32
@@ -886,7 +884,7 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char
if (stream == NULL)
closedir(dir);
}
-
+
return stream;
}
/* }}} */
@@ -934,7 +932,7 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, cha
return ret;
}
}
-
+
fd = open(realpath, open_flags, 0666);
if (fd != -1) {
@@ -998,28 +996,14 @@ static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, ch
return NULL;
}
- if ((php_check_safe_mode_include_dir(path TSRMLS_CC)) == 0) {
- return php_stream_fopen_rel(path, mode, opened_path, options);
- }
-
- if ((options & ENFORCE_SAFE_MODE) && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM)))
- return NULL;
-
return php_stream_fopen_rel(path, mode, opened_path, options);
}
static int php_plain_files_url_stater(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
{
- char *p;
- if ((p = strstr(url, "://")) != NULL) {
- if (p < strchr(url, '/')) {
- url = p + 3;
- }
- }
-
- if (PG(safe_mode) &&(!php_checkuid_ex(url, NULL, CHECKUID_CHECK_FILE_AND_DIR, (flags & PHP_STREAM_URL_STAT_QUIET) ? CHECKUID_NO_ERRORS : 0))) {
- return -1;
+ if (strncmp(url, "file://", sizeof("file://") - 1) == 0) {
+ url += sizeof("file://") - 1;
}
if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1 TSRMLS_CC)) {
@@ -1048,19 +1032,11 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, char *url, int op
int ret;
if ((p = strstr(url, "://")) != NULL) {
- if (p < strchr(url, '/')) {
- url = p + 3;
- }
+ url = p + 3;
}
- if (options & ENFORCE_SAFE_MODE) {
- if (PG(safe_mode) && !php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
- return 0;
- }
-
- if (php_check_open_basedir(url TSRMLS_CC)) {
- return 0;
- }
+ if (php_check_open_basedir(url TSRMLS_CC)) {
+ return 0;
}
ret = VCWD_UNLINK(url);
@@ -1098,20 +1074,11 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, char *url_from, c
#endif
if ((p = strstr(url_from, "://")) != NULL) {
- if (p < strchr(url_from, '/')) {
- url_from = p + 3;
- }
+ url_from = p + 3;
}
if ((p = strstr(url_to, "://")) != NULL) {
- if (p < strchr(url_to, '/')) {
- url_to = p + 3;
- }
- }
-
- if (PG(safe_mode) && (!php_checkuid(url_from, NULL, CHECKUID_CHECK_FILE_AND_DIR) ||
- !php_checkuid(url_to, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return 0;
+ url_to = p + 3;
}
if (php_check_open_basedir(url_from TSRMLS_CC) || php_check_open_basedir(url_to TSRMLS_CC)) {
@@ -1177,40 +1144,32 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, char *dir, int mod
char *p;
if ((p = strstr(dir, "://")) != NULL) {
- if (p < strchr(dir, '/')) {
- dir = p + 3;
- }
+ dir = p + 3;
}
if (!recursive) {
ret = php_mkdir(dir, mode TSRMLS_CC);
} else {
/* we look for directory separator from the end of string, thus hopefuly reducing our work load */
- char *e, *buf;
+ char *e;
struct stat sb;
int dir_len = strlen(dir);
int offset = 0;
+ char buf[MAXPATHLEN];
- buf = estrndup(dir, dir_len);
-
-#ifdef PHP_WIN32
- e = buf;
- while (*e) {
- if (*e == '/') {
- *e = DEFAULT_SLASH;
- }
- e++;
+ if (!expand_filepath_with_mode(dir, buf, NULL, 0, CWD_EXPAND TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path");
+ return 0;
}
-#else
- e = buf + dir_len;
-#endif
+
+ e = buf + strlen(buf);
if ((p = memchr(buf, DEFAULT_SLASH, dir_len))) {
offset = p - buf + 1;
}
if (p && dir_len == 1) {
- /* buf == "DEFAULT_SLASH" */
+ /* buf == "DEFAULT_SLASH" */
}
else {
/* find a top level directory we need to create */
@@ -1255,7 +1214,6 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, char *dir, int mod
}
}
}
- efree(buf);
}
if (ret < 0) {
/* Failure */
@@ -1271,10 +1229,6 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, char *url, int opt
#if PHP_WIN32
int url_len = strlen(url);
#endif
- if (PG(safe_mode) &&(!php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- return 0;
- }
-
if (php_check_open_basedir(url TSRMLS_CC)) {
return 0;
}
@@ -1297,6 +1251,92 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, char *url, int opt
return 1;
}
+static int php_plain_files_metadata(php_stream_wrapper *wrapper, char *url, int option, void *value, php_stream_context *context TSRMLS_DC)
+{
+ struct utimbuf *newtime;
+ char *p;
+#if !defined(WINDOWS) && !defined(NETWARE)
+ uid_t uid;
+ gid_t gid;
+#endif
+ mode_t mode;
+ int ret = 0;
+#if PHP_WIN32
+ int url_len = strlen(url);
+#endif
+
+#if PHP_WIN32
+ if (!php_win32_check_trailing_space(url, url_len)) {
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "%s", strerror(ENOENT));
+ return 0;
+ }
+#endif
+
+ if ((p = strstr(url, "://")) != NULL) {
+ url = p + 3;
+ }
+
+ if (php_check_open_basedir(url TSRMLS_CC)) {
+ return 0;
+ }
+
+ switch(option) {
+ case PHP_STREAM_META_TOUCH:
+ newtime = (struct utimbuf *)value;
+ if (VCWD_ACCESS(url, F_OK) != 0) {
+ FILE *file = VCWD_FOPEN(url, "w");
+ if (file == NULL) {
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno));
+ return 0;
+ }
+ fclose(file);
+ }
+
+ ret = VCWD_UTIME(url, newtime);
+ break;
+#if !defined(WINDOWS) && !defined(NETWARE)
+ case PHP_STREAM_META_OWNER_NAME:
+ case PHP_STREAM_META_OWNER:
+ if(option == PHP_STREAM_META_OWNER_NAME) {
+ if(php_get_uid_by_name((char *)value, &uid TSRMLS_CC) != SUCCESS) {
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "Unable to find uid for %s", (char *)value);
+ return 0;
+ }
+ } else {
+ uid = (uid_t)*(long *)value;
+ }
+ ret = VCWD_CHOWN(url, uid, -1);
+ break;
+ case PHP_STREAM_META_GROUP:
+ case PHP_STREAM_META_GROUP_NAME:
+ if(option == PHP_STREAM_META_OWNER_NAME) {
+ if(php_get_gid_by_name((char *)value, &gid TSRMLS_CC) != SUCCESS) {
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "Unable to find gid for %s", (char *)value);
+ return 0;
+ }
+ } else {
+ gid = (gid_t)*(long *)value;
+ }
+ ret = VCWD_CHOWN(url, -1, gid);
+ break;
+#endif
+ case PHP_STREAM_META_ACCESS:
+ mode = (mode_t)*(long *)value;
+ ret = VCWD_CHMOD(url, mode);
+ break;
+ default:
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "Unknown option %d for stream_metadata", option);
+ return 0;
+ }
+ if (ret == -1) {
+ php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "Operation failed: %s", strerror(errno));
+ return 0;
+ }
+ php_clear_stat_cache(0, NULL, 0 TSRMLS_CC);
+ return 1;
+}
+
+
static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
php_plain_files_stream_opener,
NULL,
@@ -1307,7 +1347,8 @@ static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
php_plain_files_unlink,
php_plain_files_rename,
php_plain_files_mkdir,
- php_plain_files_rmdir
+ php_plain_files_rmdir,
+ php_plain_files_metadata
};
php_stream_wrapper php_plain_files_wrapper = {
@@ -1321,7 +1362,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
{
/* code ripped off from fopen_wrappers.c */
char *pathbuf, *ptr, *end;
- char *exec_fname;
+ const char *exec_fname;
char trypath[MAXPATHLEN];
php_stream *stream;
int path_length;
@@ -1354,17 +1395,9 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
return NULL;
}
- if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
return php_stream_fopen_rel(filename, mode, opened_path, options);
}
- /*
- * files in safe_mode_include_dir (or subdir) are excluded from
- * safe mode GID/UID checks
- */
-
not_relative_path:
/* Absolute path open */
@@ -1374,16 +1407,9 @@ not_relative_path:
return NULL;
}
- if ((php_check_safe_mode_include_dir(filename TSRMLS_CC)) == 0)
- /* filename is in safe_mode_include_dir (or subdir) */
- return php_stream_fopen_rel(filename, mode, opened_path, options);
-
- if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM)))
- return NULL;
-
return php_stream_fopen_rel(filename, mode, opened_path, options);
}
-
+
#ifdef PHP_WIN32
if (IS_SLASH(filename[0])) {
size_t cwd_len;
@@ -1391,31 +1417,22 @@ not_relative_path:
cwd = virtual_getcwd_ex(&cwd_len TSRMLS_CC);
/* getcwd() will return always return [DRIVE_LETTER]:/) on windows. */
*(cwd+3) = '\0';
-
+
if (snprintf(trypath, MAXPATHLEN, "%s%s", cwd, filename) >= MAXPATHLEN) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", cwd, filename, MAXPATHLEN);
}
-
+
free(cwd);
-
+
if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(trypath TSRMLS_CC)) {
return NULL;
}
- if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC)) == 0) {
- return php_stream_fopen_rel(trypath, mode, opened_path, options);
- }
- if (PG(safe_mode) && (!php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
-
+
return php_stream_fopen_rel(trypath, mode, opened_path, options);
}
#endif
if (!path || (path && !*path)) {
- if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
- return NULL;
- }
return php_stream_fopen_rel(filename, mode, opened_path, options);
}
@@ -1462,24 +1479,9 @@ not_relative_path:
if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir_ex(trypath, 0 TSRMLS_CC)) {
goto stream_skip;
}
-
- if (PG(safe_mode)) {
- struct stat sb;
- if (VCWD_STAT(trypath, &sb) == 0) {
- /* file exists ... check permission */
- if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0) ||
- php_checkuid_ex(trypath, mode, CHECKUID_CHECK_MODE_PARAM, CHECKUID_NO_ERRORS)) {
- /* UID ok, or trypath is in safe_mode_include_dir */
- stream = php_stream_fopen_rel(trypath, mode, opened_path, options);
- goto stream_done;
- }
- }
- goto stream_skip;
- }
stream = php_stream_fopen_rel(trypath, mode, opened_path, options);
if (stream) {
-stream_done:
efree(pathbuf);
return stream;
}
diff --git a/main/streams/streams.c b/main/streams/streams.c
index eec9b70349..21ca72c6b5 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -105,6 +105,15 @@ PHP_RSHUTDOWN_FUNCTION(streams)
return SUCCESS;
}
+PHPAPI php_stream *php_stream_encloses(php_stream *enclosing, php_stream *enclosed)
+{
+ php_stream *orig = enclosed->enclosing_stream;
+
+ php_stream_auto_cleanup(enclosed);
+ enclosed->enclosing_stream = enclosing;
+ return orig;
+}
+
PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream **stream TSRMLS_DC)
{
zend_rsrc_list_entry *le;
@@ -324,19 +333,56 @@ fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n", ops->label, ret, persiste
ret->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ret, persistent_id ? le_pstream : le_stream);
strlcpy(ret->mode, mode, sizeof(ret->mode));
+ ret->wrapper = NULL;
+ ret->wrapperthis = NULL;
+ ret->wrapperdata = NULL;
+ ret->stdiocast = NULL;
+ ret->orig_path = NULL;
+ ret->context = NULL;
+ ret->readbuf = NULL;
+ ret->enclosing_stream = NULL;
+
return ret;
}
/* }}} */
+PHPAPI int _php_stream_free_enclosed(php_stream *stream_enclosed, int close_options TSRMLS_DC) /* {{{ */
+{
+ return _php_stream_free(stream_enclosed,
+ close_options | PHP_STREAM_FREE_IGNORE_ENCLOSING TSRMLS_CC);
+}
+/* }}} */
+
+#if STREAM_DEBUG
+static const char *_php_stream_pretty_free_options(int close_options, char *out)
+{
+ if (close_options & PHP_STREAM_FREE_CALL_DTOR)
+ strcat(out, "CALL_DTOR, ");
+ if (close_options & PHP_STREAM_FREE_RELEASE_STREAM)
+ strcat(out, "RELEASE_STREAM, ");
+ if (close_options & PHP_STREAM_FREE_PRESERVE_HANDLE)
+ strcat(out, "PREVERSE_HANDLE, ");
+ if (close_options & PHP_STREAM_FREE_RSRC_DTOR)
+ strcat(out, "RSRC_DTOR, ");
+ if (close_options & PHP_STREAM_FREE_PERSISTENT)
+ strcat(out, "PERSISTENT, ");
+ if (close_options & PHP_STREAM_FREE_IGNORE_ENCLOSING)
+ strcat(out, "IGNORE_ENCLOSING, ");
+ if (out[0] != '\0')
+ out[strlen(out) - 2] = '\0';
+ return out;
+}
+#endif
+
static int _php_stream_free_persistent(zend_rsrc_list_entry *le, void *pStream TSRMLS_DC)
{
return le->ptr == pStream;
}
+
PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* {{{ */
{
int ret = 1;
- int remove_rsrc = 1;
int preserve_handle = close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 1 : 0;
int release_cast = 1;
php_stream_context *context = NULL;
@@ -353,16 +399,40 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /*
}
#if STREAM_DEBUG
-fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%08x\n", stream->ops->label, stream, stream->orig_path, stream->in_free, close_options);
+ {
+ char out[200] = "";
+ fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%s\n",
+ stream->ops->label, stream, stream->orig_path, stream->in_free, _php_stream_pretty_free_options(close_options, out));
+ }
+
#endif
- /* recursion protection */
if (stream->in_free) {
- return 1;
+ /* hopefully called recursively from the enclosing stream; the pointer was NULLed below */
+ if ((stream->in_free == 1) && (close_options & PHP_STREAM_FREE_IGNORE_ENCLOSING) && (stream->enclosing_stream == NULL)) {
+ close_options |= PHP_STREAM_FREE_RSRC_DTOR; /* restore flag */
+ } else {
+ return 1; /* recursion protection */
+ }
}
stream->in_free++;
+ /* force correct order on enclosing/enclosed stream destruction (only from resource
+ * destructor as in when reverse destroying the resource list) */
+ if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) &&
+ !(close_options & PHP_STREAM_FREE_IGNORE_ENCLOSING) &&
+ (close_options & (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)) && /* always? */
+ (stream->enclosing_stream != NULL)) {
+ php_stream *enclosing_stream = stream->enclosing_stream;
+ stream->enclosing_stream = NULL;
+ /* we force PHP_STREAM_CALL_DTOR because that's from where the
+ * enclosing stream can free this stream. We remove rsrc_dtor because
+ * we want the enclosing stream to be deleted from the resource list */
+ return _php_stream_free(enclosing_stream,
+ (close_options | PHP_STREAM_FREE_CALL_DTOR) & ~PHP_STREAM_FREE_RSRC_DTOR TSRMLS_CC);
+ }
+
/* if we are releasing the stream only (and preserving the underlying handle),
* we need to do things a little differently.
* We are only ever called like this when the stream is cast to a FILE*
@@ -383,14 +453,15 @@ fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%08x\n", stream->ops->la
#if STREAM_DEBUG
fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remove_rsrc=%d\n",
- stream->ops->label, stream, stream->orig_path, preserve_handle, release_cast, remove_rsrc);
+ stream->ops->label, stream, stream->orig_path, preserve_handle, release_cast,
+ (close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0);
#endif
/* make sure everything is saved */
_php_stream_flush(stream, 1 TSRMLS_CC);
/* If not called from the resource dtor, remove the stream from the resource list. */
- if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0 && remove_rsrc) {
+ if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0) {
/* zend_list_delete actually only decreases the refcount; if we're
* releasing the stream, we want to actually delete the resource from
* the resource list, otherwise the resource will point to invalid memory.
@@ -1418,7 +1489,7 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen
}
/* Returns SUCCESS/FAILURE and sets *len to the number of bytes moved */
-PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC)
+PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC)
{
char buf[CHUNK_SIZE];
size_t readchunk;
@@ -1819,7 +1890,7 @@ PHPAPI int _php_stream_mkdir(char *path, int mode, int options, php_stream_conte
{
php_stream_wrapper *wrapper = NULL;
- wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC);
+ wrapper = php_stream_locate_url_wrapper(path, NULL, 0 TSRMLS_CC);
if (!wrapper || !wrapper->wops || !wrapper->wops->stream_mkdir) {
return 0;
}
@@ -1834,7 +1905,7 @@ PHPAPI int _php_stream_rmdir(char *path, int options, php_stream_context *contex
{
php_stream_wrapper *wrapper = NULL;
- wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC);
+ wrapper = php_stream_locate_url_wrapper(path, NULL, 0 TSRMLS_CC);
if (!wrapper || !wrapper->wops || !wrapper->wops->stream_rmdir) {
return 0;
}
@@ -1863,7 +1934,7 @@ PHPAPI int _php_stream_stat_path(char *path, int flags, php_stream_statbuf *ssb,
}
}
- wrapper = php_stream_locate_url_wrapper(path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC);
+ wrapper = php_stream_locate_url_wrapper(path, &path_to_open, 0 TSRMLS_CC);
if (wrapper && wrapper->wops->url_stat) {
ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context TSRMLS_CC);
if (ret == 0) {
@@ -1948,7 +2019,6 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio
char *resolved_path = NULL;
char *copy_of_path = NULL;
-
if (opened_path) {
*opened_path = NULL;
}
@@ -2125,7 +2195,7 @@ PHPAPI void php_stream_context_free(php_stream_context *context)
efree(context);
}
-PHPAPI php_stream_context *php_stream_context_alloc(void)
+PHPAPI php_stream_context *php_stream_context_alloc(TSRMLS_D)
{
php_stream_context *context;
@@ -2134,7 +2204,7 @@ PHPAPI php_stream_context *php_stream_context_alloc(void)
MAKE_STD_ZVAL(context->options);
array_init(context->options);
- context->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, context, php_le_stream_context());
+ context->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, context, php_le_stream_context(TSRMLS_C));
return context;
}
@@ -2277,7 +2347,7 @@ PHPAPI int _php_stream_scandir(char *dirname, char **namelist[], int flags, php_
return FAILURE;
}
- stream = php_stream_opendir(dirname, ENFORCE_SAFE_MODE | REPORT_ERRORS, context);
+ stream = php_stream_opendir(dirname, REPORT_ERRORS, context);
if (!stream) {
return FAILURE;
}
@@ -2300,6 +2370,11 @@ PHPAPI int _php_stream_scandir(char *dirname, char **namelist[], int flags, php_
vector[nfiles] = estrdup(sdp.d_name);
nfiles++;
+ if(vector_size < 10 || nfiles == 0) {
+ /* overflow */
+ efree(vector);
+ return FAILURE;
+ }
}
php_stream_closedir(stream);
diff --git a/main/streams/userspace.c b/main/streams/userspace.c
index 8299cba43a..3b277160d6 100644
--- a/main/streams/userspace.c
+++ b/main/streams/userspace.c
@@ -26,6 +26,15 @@
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
+#include <stddef.h>
+
+#if HAVE_UTIME
+# ifdef PHP_WIN32
+# include <sys/utime.h>
+# else
+# include <utime.h>
+# endif
+#endif
static int le_protocols;
@@ -42,6 +51,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC);
static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
+static int user_wrapper_metadata(php_stream_wrapper *wrapper, char *url, int option, void *value, php_stream_context *context TSRMLS_DC);
static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filename, char *mode,
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
@@ -55,7 +65,8 @@ static php_stream_wrapper_ops user_stream_wops = {
user_wrapper_unlink,
user_wrapper_rename,
user_wrapper_mkdir,
- user_wrapper_rmdir
+ user_wrapper_rmdir,
+ user_wrapper_metadata
};
@@ -77,7 +88,6 @@ PHP_MINIT_FUNCTION(user_streams)
REGISTER_LONG_CONSTANT("STREAM_USE_PATH", USE_PATH, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_IGNORE_URL", IGNORE_URL, CONST_CS|CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("STREAM_ENFORCE_SAFE_MODE", ENFORCE_SAFE_MODE, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_REPORT_ERRORS", REPORT_ERRORS, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_MUST_SEEK", STREAM_MUST_SEEK, CONST_CS|CONST_PERSISTENT);
@@ -99,6 +109,12 @@ PHP_MINIT_FUNCTION(user_streams)
REGISTER_LONG_CONSTANT("STREAM_CAST_AS_STREAM", PHP_STREAM_AS_STDIO, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CAST_FOR_SELECT", PHP_STREAM_AS_FD_FOR_SELECT, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_META_TOUCH", PHP_STREAM_META_TOUCH, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_META_OWNER", PHP_STREAM_META_OWNER, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_META_OWNER_NAME", PHP_STREAM_META_OWNER_NAME, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_META_GROUP", PHP_STREAM_META_GROUP, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_META_GROUP_NAME", PHP_STREAM_META_GROUP_NAME, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("STREAM_META_ACCESS", PHP_STREAM_META_ACCESS, CONST_CS|CONST_PERSISTENT);
return SUCCESS;
}
@@ -130,35 +146,37 @@ typedef struct _php_userstream_data php_userstream_data_t;
#define USERSTREAM_LOCK "stream_lock"
#define USERSTREAM_CAST "stream_cast"
#define USERSTREAM_SET_OPTION "stream_set_option"
+#define USERSTREAM_TRUNCATE "stream_truncate"
+#define USERSTREAM_METADATA "stream_metadata"
/* {{{ class should have methods like these:
-
+
function stream_open($path, $mode, $options, &$opened_path)
{
return true/false;
}
-
+
function stream_read($count)
{
return false on error;
else return string;
}
-
+
function stream_write($data)
{
return false on error;
else return count written;
}
-
+
function stream_close()
{
}
-
+
function stream_flush()
{
return true/false;
}
-
+
function stream_seek($offset, $whence)
{
return true/false;
@@ -255,74 +273,55 @@ typedef struct _php_userstream_data php_userstream_data_t;
{
return true / false;
}
-
+
+ function stream_truncate($new_size)
+ {
+ return true / false;
+ }
+
}}} **/
-static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+static zval *user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context TSRMLS_DC)
{
- struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
- php_userstream_data_t *us;
- zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
- zval **args[4];
- int call_result;
- php_stream *stream = NULL;
- zend_bool old_in_user_include;
+ zval *object;
+ /* create an instance of our class */
+ ALLOC_ZVAL(object);
+ object_init_ex(object, uwrap->ce);
+ Z_SET_REFCOUNT_P(object, 1);
+ Z_SET_ISREF_P(object);
- /* Try to catch bad usage without preventing flexibility */
- if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
- php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
- return NULL;
- }
- FG(user_stream_current_filename) = filename;
-
- /* if the user stream was registered as local and we are in include context,
- we add allow_url_include restrictions to allow_url_fopen ones */
- /* we need only is_url == 0 here since if is_url == 1 and remote wrappers
- were restricted we wouldn't get here */
- old_in_user_include = PG(in_user_include);
- if(uwrap->wrapper.is_url == 0 &&
- (options & STREAM_OPEN_FOR_INCLUDE) &&
- !PG(allow_url_include)) {
- PG(in_user_include) = 1;
+ if (context) {
+ add_property_resource(object, "context", context->rsrc_id);
+ zend_list_addref(context->rsrc_id);
+ } else {
+ add_property_null(object, "context");
}
- us = emalloc(sizeof(*us));
- us->wrapper = uwrap;
-
- /* create an instance of our class */
- ALLOC_ZVAL(us->object);
- object_init_ex(us->object, uwrap->ce);
- Z_SET_REFCOUNT_P(us->object, 1);
- Z_SET_ISREF_P(us->object);
-
if (uwrap->ce->constructor) {
zend_fcall_info fci;
zend_fcall_info_cache fcc;
zval *retval_ptr;
-
+
fci.size = sizeof(fci);
fci.function_table = &uwrap->ce->function_table;
fci.function_name = NULL;
fci.symbol_table = NULL;
- fci.object_ptr = us->object;
+ fci.object_ptr = object;
fci.retval_ptr_ptr = &retval_ptr;
fci.param_count = 0;
fci.params = NULL;
fci.no_separation = 1;
-
+
fcc.initialized = 1;
fcc.function_handler = uwrap->ce->constructor;
fcc.calling_scope = EG(scope);
- fcc.called_scope = Z_OBJCE_P(us->object);
- fcc.object_ptr = us->object;
+ fcc.called_scope = Z_OBJCE_P(object);
+ fcc.object_ptr = object;
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute %s::%s()", uwrap->ce->name, uwrap->ce->constructor->common.function_name);
- zval_dtor(us->object);
- FREE_ZVAL(us->object);
- efree(us);
- FG(user_stream_current_filename) = NULL;
- PG(in_user_include) = old_in_user_include;
+ zval_dtor(object);
+ FREE_ZVAL(object);
return NULL;
} else {
if (retval_ptr) {
@@ -330,14 +329,48 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
}
}
}
+ return object;
+}
- if (context) {
- add_property_resource(us->object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(us->object, "context");
+static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
+ php_userstream_data_t *us;
+ zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname;
+ zval **args[4];
+ int call_result;
+ php_stream *stream = NULL;
+ zend_bool old_in_user_include;
+
+ /* Try to catch bad usage without preventing flexibility */
+ if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
+ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented");
+ return NULL;
+ }
+ FG(user_stream_current_filename) = filename;
+
+ /* if the user stream was registered as local and we are in include context,
+ we add allow_url_include restrictions to allow_url_fopen ones */
+ /* we need only is_url == 0 here since if is_url == 1 and remote wrappers
+ were restricted we wouldn't get here */
+ old_in_user_include = PG(in_user_include);
+ if(uwrap->wrapper.is_url == 0 &&
+ (options & STREAM_OPEN_FOR_INCLUDE) &&
+ !PG(allow_url_include)) {
+ PG(in_user_include) = 1;
+ }
+
+ us = emalloc(sizeof(*us));
+ us->wrapper = uwrap;
+
+ us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(us->object == NULL) {
+ FG(user_stream_current_filename) = NULL;
+ PG(in_user_include) = old_in_user_include;
+ efree(us);
+ return NULL;
}
-
+
/* call it's stream_open method - set up params first */
MAKE_STD_ZVAL(zfilename);
ZVAL_STRING(zfilename, filename, 1);
@@ -359,14 +392,14 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_OPEN, 1);
-
+
call_result = call_user_function_ex(NULL,
&us->object,
zfuncname,
&zretval,
4, args,
0, NULL TSRMLS_CC);
-
+
if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) {
/* the stream is now open! */
stream = php_stream_alloc_rel(&php_stream_userspace_ops, us, 0, mode);
@@ -383,7 +416,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "\"%s::" USERSTREAM_OPEN "\" call failed",
us->wrapper->classname);
}
-
+
/* destroy everything else */
if (stream == NULL) {
zval_ptr_dtor(&us->object);
@@ -391,7 +424,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
}
if (zretval)
zval_ptr_dtor(&zretval);
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zopened);
zval_ptr_dtor(&zoptions);
@@ -399,7 +432,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena
zval_ptr_dtor(&zfilename);
FG(user_stream_current_filename) = NULL;
-
+
PG(in_user_include) = old_in_user_include;
return stream;
}
@@ -410,7 +443,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
php_userstream_data_t *us;
zval *zfilename, *zoptions, *zretval = NULL, *zfuncname;
- zval **args[2];
+ zval **args[2];
int call_result;
php_stream *stream = NULL;
@@ -420,23 +453,17 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
return NULL;
}
FG(user_stream_current_filename) = filename;
-
- us = emalloc(sizeof(*us));
- us->wrapper = uwrap;
- /* create an instance of our class */
- ALLOC_ZVAL(us->object);
- object_init_ex(us->object, uwrap->ce);
- Z_SET_REFCOUNT_P(us->object, 1);
- Z_SET_ISREF_P(us->object);
+ us = emalloc(sizeof(*us));
+ us->wrapper = uwrap;
- if (context) {
- add_property_resource(us->object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(us->object, "context");
+ us->object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(us == NULL) {
+ FG(user_stream_current_filename) = NULL;
+ efree(us);
+ return NULL;
}
-
+
/* call it's dir_open method - set up params first */
MAKE_STD_ZVAL(zfilename);
ZVAL_STRING(zfilename, filename, 1);
@@ -448,14 +475,14 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_DIR_OPEN, 1);
-
+
call_result = call_user_function_ex(NULL,
&us->object,
zfuncname,
&zretval,
2, args,
0, NULL TSRMLS_CC);
-
+
if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) {
/* the stream is now open! */
stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode);
@@ -467,7 +494,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed",
us->wrapper->classname);
}
-
+
/* destroy everything else */
if (stream == NULL) {
zval_ptr_dtor(&us->object);
@@ -475,13 +502,13 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filen
}
if (zretval)
zval_ptr_dtor(&zretval);
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zoptions);
zval_ptr_dtor(&zfilename);
FG(user_stream_current_filename) = NULL;
-
+
return stream;
}
@@ -495,11 +522,11 @@ PHP_FUNCTION(stream_wrapper_register)
struct php_user_stream_wrapper * uwrap;
int rsrc_id;
long flags = 0;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &protocol, &protocol_len, &classname, &classname_len, &flags) == FAILURE) {
RETURN_FALSE;
}
-
+
uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
uwrap->protoname = estrndup(protocol, protocol_len);
uwrap->classname = estrndup(classname, classname_len);
@@ -585,7 +612,7 @@ PHP_FUNCTION(stream_wrapper_restore)
if (php_register_url_stream_wrapper_volatile(protocol, wrapper TSRMLS_CC) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to restore original %s:// wrapper", protocol);
RETURN_FALSE;
- }
+ }
RETURN_TRUE;
}
@@ -633,10 +660,10 @@ static size_t php_userstreamop_write(php_stream *stream, const char *buf, size_t
(long)(didwrite - count), (long)didwrite, (long)count);
didwrite = count;
}
-
+
if (retval)
zval_ptr_dtor(&retval);
-
+
return didwrite;
}
@@ -721,9 +748,9 @@ static int php_userstreamop_close(php_stream *stream, int close_handle TSRMLS_DC
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
assert(us != NULL);
-
+
ZVAL_STRINGL(&func_name, USERSTREAM_CLOSE, sizeof(USERSTREAM_CLOSE)-1, 0);
-
+
call_user_function_ex(NULL,
&us->object,
&func_name,
@@ -732,11 +759,11 @@ static int php_userstreamop_close(php_stream *stream, int close_handle TSRMLS_DC
if (retval)
zval_ptr_dtor(&retval);
-
+
zval_ptr_dtor(&us->object);
efree(us);
-
+
return 0;
}
@@ -750,7 +777,7 @@ static int php_userstreamop_flush(php_stream *stream TSRMLS_DC)
assert(us != NULL);
ZVAL_STRINGL(&func_name, USERSTREAM_FLUSH, sizeof(USERSTREAM_FLUSH)-1, 0);
-
+
call_result = call_user_function_ex(NULL,
&us->object,
&func_name,
@@ -761,10 +788,10 @@ static int php_userstreamop_flush(php_stream *stream TSRMLS_DC)
call_result = 0;
else
call_result = -1;
-
+
if (retval)
zval_ptr_dtor(&retval);
-
+
return call_result;
}
@@ -803,10 +830,10 @@ static int php_userstreamop_seek(php_stream *stream, off_t offset, int whence, o
/* stream_seek is not implemented, so disable seeks for this stream */
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
/* there should be no retval to clean up */
-
- if (retval)
+
+ if (retval)
zval_ptr_dtor(&retval);
-
+
return -1;
} else if (call_result == SUCCESS && retval != NULL && zval_is_true(retval)) {
ret = 0;
@@ -890,8 +917,8 @@ static int statbuf_from_array(zval *array, php_stream_statbuf *ssb TSRMLS_DC)
STAT_PROP_ENTRY(blocks);
#endif
-#undef STAT_PROP_ENTRY
-#undef STAT_PROP_ENTRY_EX
+#undef STAT_PROP_ENTRY
+#undef STAT_PROP_ENTRY_EX
return SUCCESS;
}
@@ -921,9 +948,9 @@ static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb TSR
}
}
- if (retval)
+ if (retval)
zval_ptr_dtor(&retval);
-
+
return ret;
}
@@ -933,7 +960,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
zval *retval = NULL;
int call_result;
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
- int ret = -1;
+ int ret = PHP_STREAM_OPTION_RETURN_NOTIMPL;
zval *zvalue = NULL;
zval **args[3];
@@ -971,37 +998,83 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
}
args[0] = &zvalue;
-
+
/* TODO wouldblock */
ZVAL_STRINGL(&func_name, USERSTREAM_LOCK, sizeof(USERSTREAM_LOCK)-1, 0);
-
+
call_result = call_user_function_ex(NULL,
&us->object,
&func_name,
&retval,
1, args, 0, NULL TSRMLS_CC);
-
+
if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) == IS_BOOL) {
ret = !Z_LVAL_P(retval);
} else if (call_result == FAILURE) {
- if (value == 0) {
+ if (value == 0) {
/* lock support test (TODO: more check) */
- ret = 0;
+ ret = PHP_STREAM_OPTION_RETURN_OK;
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
us->wrapper->classname);
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
}
}
break;
-
+
+ case PHP_STREAM_OPTION_TRUNCATE_API:
+ ZVAL_STRINGL(&func_name, USERSTREAM_TRUNCATE, sizeof(USERSTREAM_TRUNCATE)-1, 0);
+
+ switch (value) {
+ case PHP_STREAM_TRUNCATE_SUPPORTED:
+ if (zend_is_callable_ex(&func_name, us->object, IS_CALLABLE_CHECK_SILENT,
+ NULL, NULL, NULL, NULL TSRMLS_CC))
+ ret = PHP_STREAM_OPTION_RETURN_OK;
+ else
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
+ break;
+
+ case PHP_STREAM_TRUNCATE_SET_SIZE: {
+ ptrdiff_t new_size = *(ptrdiff_t*) ptrparam;
+ if (new_size >= 0 && new_size <= (ptrdiff_t)LONG_MAX) {
+ MAKE_STD_ZVAL(zvalue);
+ ZVAL_LONG(zvalue, (long)new_size);
+ args[0] = &zvalue;
+ call_result = call_user_function_ex(NULL,
+ &us->object,
+ &func_name,
+ &retval,
+ 1, args, 0, NULL TSRMLS_CC);
+ if (call_result == SUCCESS && retval != NULL) {
+ if (Z_TYPE_P(retval) == IS_BOOL) {
+ ret = Z_LVAL_P(retval) ? PHP_STREAM_OPTION_RETURN_OK :
+ PHP_STREAM_OPTION_RETURN_ERR;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
+ us->wrapper->classname);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "%s::" USERSTREAM_TRUNCATE " is not implemented!",
+ us->wrapper->classname);
+ }
+ } else { /* bad new size */
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
+ }
+ break;
+ }
+ }
+ break;
+
case PHP_STREAM_OPTION_READ_BUFFER:
case PHP_STREAM_OPTION_WRITE_BUFFER:
case PHP_STREAM_OPTION_READ_TIMEOUT:
case PHP_STREAM_OPTION_BLOCKING: {
zval *zoption = NULL;
zval *zptrparam = NULL;
-
+
ZVAL_STRINGL(&func_name, USERSTREAM_SET_OPTION, sizeof(USERSTREAM_SET_OPTION)-1, 0);
ALLOC_INIT_ZVAL(zoption);
@@ -1042,17 +1115,16 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
&func_name,
&retval,
3, args, 0, NULL TSRMLS_CC);
-
- do {
- if (call_result == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
- us->wrapper->classname);
- break;
- }
- if (retval && zend_is_true(retval)) {
- ret = PHP_STREAM_OPTION_RETURN_OK;
- }
- } while (0);
+
+ if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
+ us->wrapper->classname);
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
+ } else if (retval && zend_is_true(retval)) {
+ ret = PHP_STREAM_OPTION_RETURN_OK;
+ } else {
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
+ }
if (zoption) {
zval_ptr_dtor(&zoption);
@@ -1069,7 +1141,7 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value
if (retval) {
zval_ptr_dtor(&retval);
}
-
+
if (zvalue) {
zval_ptr_dtor(&zvalue);
@@ -1089,16 +1161,9 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the unlink method */
@@ -1108,7 +1173,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_UNLINK, 1);
-
+
call_result = call_user_function_ex(NULL,
&object,
zfuncname,
@@ -1126,7 +1191,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
zval_ptr_dtor(&object);
if (zretval)
zval_ptr_dtor(&zretval);
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zfilename);
@@ -1143,16 +1208,9 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the rename method */
@@ -1166,7 +1224,7 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_RENAME, 1);
-
+
call_result = call_user_function_ex(NULL,
&object,
zfuncname,
@@ -1184,7 +1242,7 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
zval_ptr_dtor(&object);
if (zretval)
zval_ptr_dtor(&zretval);
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zold_name);
zval_ptr_dtor(&znew_name);
@@ -1202,16 +1260,9 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode,
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the mkdir method */
@@ -1229,7 +1280,7 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode,
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_MKDIR, 1);
-
+
call_result = call_user_function_ex(NULL,
&object,
zfuncname,
@@ -1248,7 +1299,7 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode,
if (zretval) {
zval_ptr_dtor(&zretval);
}
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zfilename);
zval_ptr_dtor(&zmode);
@@ -1267,16 +1318,9 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int option
int ret = 0;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call the rmdir method */
@@ -1290,7 +1334,7 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int option
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_RMDIR, 1);
-
+
call_result = call_user_function_ex(NULL,
&object,
zfuncname,
@@ -1309,7 +1353,7 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int option
if (zretval) {
zval_ptr_dtor(&zretval);
}
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zfilename);
zval_ptr_dtor(&zoptions);
@@ -1317,26 +1361,102 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int option
return ret;
}
+static int user_wrapper_metadata(php_stream_wrapper *wrapper, char *url, int option, void *value, php_stream_context *context TSRMLS_DC)
+{
+ struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
+ zval *zfilename, *zoption, *zvalue, *zfuncname, *zretval;
+ zval **args[3];
+ int call_result;
+ zval *object;
+ int ret = 0;
+
+ MAKE_STD_ZVAL(zvalue);
+ switch(option) {
+ case PHP_STREAM_META_TOUCH:
+ array_init(zvalue);
+ if(value) {
+ struct utimbuf *newtime = (struct utimbuf *)value;
+ add_index_long(zvalue, 0, newtime->modtime);
+ add_index_long(zvalue, 1, newtime->actime);
+ }
+ break;
+ case PHP_STREAM_META_GROUP:
+ case PHP_STREAM_META_OWNER:
+ case PHP_STREAM_META_ACCESS:
+ ZVAL_LONG(zvalue, *(long *)value);
+ break;
+ case PHP_STREAM_META_GROUP_NAME:
+ case PHP_STREAM_META_OWNER_NAME:
+ ZVAL_STRING(zvalue, value, 1);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option %d for " USERSTREAM_METADATA, option);
+ zval_ptr_dtor(&zvalue);
+ return ret;
+ }
+
+ /* create an instance of our class */
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ zval_ptr_dtor(&zvalue);
+ return ret;
+ }
+
+ /* call the mkdir method */
+ MAKE_STD_ZVAL(zfilename);
+ ZVAL_STRING(zfilename, url, 1);
+ args[0] = &zfilename;
+
+ MAKE_STD_ZVAL(zoption);
+ ZVAL_LONG(zoption, option);
+ args[1] = &zoption;
+
+ args[2] = &zvalue;
+
+ MAKE_STD_ZVAL(zfuncname);
+ ZVAL_STRING(zfuncname, USERSTREAM_METADATA, 1);
+
+ call_result = call_user_function_ex(NULL,
+ &object,
+ zfuncname,
+ &zretval,
+ 3, args,
+ 0, NULL TSRMLS_CC);
+
+ if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) {
+ ret = Z_LVAL_P(zretval);
+ } else if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", uwrap->classname);
+ }
+
+ /* clean up */
+ zval_ptr_dtor(&object);
+ if (zretval) {
+ zval_ptr_dtor(&zretval);
+ }
+
+ zval_ptr_dtor(&zfuncname);
+ zval_ptr_dtor(&zfilename);
+ zval_ptr_dtor(&zoption);
+ zval_ptr_dtor(&zvalue);
+
+ return ret;
+}
+
+
static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
{
struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract;
zval *zfilename, *zfuncname, *zretval, *zflags;
- zval **args[2];
+ zval **args[2];
int call_result;
zval *object;
int ret = -1;
/* create an instance of our class */
- ALLOC_ZVAL(object);
- object_init_ex(object, uwrap->ce);
- Z_SET_REFCOUNT_P(object, 1);
- Z_SET_ISREF_P(object);
-
- if (context) {
- add_property_resource(object, "context", context->rsrc_id);
- zend_list_addref(context->rsrc_id);
- } else {
- add_property_null(object, "context");
+ object = user_stream_create_object(uwrap, context TSRMLS_CC);
+ if(object == NULL) {
+ return ret;
}
/* call it's stat_url method - set up params first */
@@ -1350,14 +1470,14 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int fla
MAKE_STD_ZVAL(zfuncname);
ZVAL_STRING(zfuncname, USERSTREAM_STATURL, 1);
-
+
call_result = call_user_function_ex(NULL,
&object,
zfuncname,
&zretval,
2, args,
0, NULL TSRMLS_CC);
-
+
if (call_result == SUCCESS && zretval != NULL && Z_TYPE_P(zretval) == IS_ARRAY) {
/* We got the info we needed */
if (SUCCESS == statbuf_from_array(zretval, ssb TSRMLS_CC))
@@ -1368,16 +1488,16 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int fla
uwrap->classname);
}
}
-
+
/* clean up */
zval_ptr_dtor(&object);
if (zretval)
zval_ptr_dtor(&zretval);
-
+
zval_ptr_dtor(&zfuncname);
zval_ptr_dtor(&zfilename);
zval_ptr_dtor(&zflags);
-
+
return ret;
}
@@ -1427,9 +1547,9 @@ static int php_userstreamop_closedir(php_stream *stream, int close_handle TSRMLS
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
assert(us != NULL);
-
+
ZVAL_STRINGL(&func_name, USERSTREAM_DIR_CLOSE, sizeof(USERSTREAM_DIR_CLOSE)-1, 0);
-
+
call_user_function_ex(NULL,
&us->object,
&func_name,
@@ -1438,11 +1558,11 @@ static int php_userstreamop_closedir(php_stream *stream, int close_handle TSRMLS
if (retval)
zval_ptr_dtor(&retval);
-
+
zval_ptr_dtor(&us->object);
efree(us);
-
+
return 0;
}
@@ -1453,7 +1573,7 @@ static int php_userstreamop_rewinddir(php_stream *stream, off_t offset, int when
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
ZVAL_STRINGL(&func_name, USERSTREAM_DIR_REWIND, sizeof(USERSTREAM_DIR_REWIND)-1, 0);
-
+
call_user_function_ex(NULL,
&us->object,
&func_name,
@@ -1462,7 +1582,7 @@ static int php_userstreamop_rewinddir(php_stream *stream, off_t offset, int when
if (retval)
zval_ptr_dtor(&retval);
-
+
return 0;
}
@@ -1537,7 +1657,7 @@ php_stream_ops php_stream_userspace_ops = {
"user-space",
php_userstreamop_seek,
php_userstreamop_cast,
- php_userstreamop_stat,
+ php_userstreamop_stat,
php_userstreamop_set_option,
};
diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c
index 64555ca1df..7c3a553102 100644
--- a/main/streams/xp_socket.c
+++ b/main/streams/xp_socket.c
@@ -400,10 +400,6 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void
}
#endif
- case PHP_STREAM_OPTION_WRITE_BUFFER:
- php_stream_set_chunk_size(stream, (ptrparam ? *(size_t *)ptrparam : PHP_SOCK_CHUNK_SIZE));
- return PHP_STREAM_OPTION_RETURN_OK;
-
default:
return PHP_STREAM_OPTION_RETURN_NOTIMPL;
}
diff --git a/makedist b/makedist
index 892bab66ce..bfc8fcc44a 100755
--- a/makedist
+++ b/makedist
@@ -4,12 +4,12 @@
#
# Usage: makedist version
# Example: makedist 5.4.1
-# Example: makedist 5.3.5-RC1
+# Example: makedist 5.3.5RC1
#
# To work, this script needs a consistent tagging of all releases.
# Each release of a package should have a tag of the form
#
-# PHP-X.Y.Z[-sub]
+# php-X.Y.Z[sub]
#
# The distribution ends up in a .tar.gz file that contains the distribution
# in a directory called php-<version>.
@@ -63,8 +63,8 @@ if test -d "$DIRPATH"; then
fi
# Export PHP
-$ECHO_N "makedist: exporting tag 'PHP-$VER' from '$PHPROOT'...$ECHO_C"
-git archive --format=tar --remote=$PHPROOT refs/tags/PHP-$VER --prefix=php-$VER/ | (cd $MY_OLDPWD; tar xvf -) || exit 4
+$ECHO_N "makedist: exporting tag 'php-$VER' from '$PHPROOT'...$ECHO_C"
+git archive --format=tar --remote=$PHPROOT refs/tags/php-$VER --prefix=php-$VER/ | (cd $MY_OLDPWD; tar xvf -) || exit 4
echo ""
cd $DIR || exit 5
diff --git a/pear/Makefile.frag b/pear/Makefile.frag
index 1f6f70ec04..00bacae2df 100644
--- a/pear/Makefile.frag
+++ b/pear/Makefile.frag
@@ -3,7 +3,7 @@
peardir=$(PEAR_INSTALLDIR)
# Skip all php.ini files altogether
-PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0 -dopen_basedir= -derror_reporting=1803 -dmemory_limit=-1 -ddetect_unicode=0
+PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dopen_basedir= -derror_reporting=1803 -dmemory_limit=-1 -ddetect_unicode=0
WGET = `which wget 2>/dev/null`
FETCH = `which fetch 2>/dev/null`
diff --git a/php.ini-development b/php.ini-development
index d1fa7a35e8..4ff4192f6f 100644
--- a/php.ini-development
+++ b/php.ini-development
@@ -91,11 +91,6 @@
; Please see the actual settings later in the document for more details as to why
; we recommend these changes in PHP's behavior.
-; allow_call_time_pass_reference
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-
; display_errors
; Default Value: On
; Development Value: On
@@ -107,25 +102,20 @@
; Production Value: Off
; error_reporting
-; Default Value: E_ALL & ~E_NOTICE
-; Development Value: E_ALL | E_STRICT
-; Production Value: E_ALL & ~E_DEPRECATED
+; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
+; Development Value: E_ALL
+; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; html_errors
; Default Value: On
; Development Value: On
-; Production value: Off
+; Production value: On
; log_errors
; Default Value: Off
; Development Value: On
; Production Value: On
-; magic_quotes_gpc
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-
; max_input_time
; Default Value: -1 (Unlimited)
; Development Value: 60 (60 seconds)
@@ -141,11 +131,6 @@
; Development Value: Off
; Production Value: Off
-; register_long_arrays
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-
; request_order
; Default Value: None
; Development Value: "GP"
@@ -233,10 +218,6 @@ asp_tags = Off
; http://php.net/precision
precision = 14
-; Enforce year 2000 compliance (will cause problems with non-compliant browsers)
-; http://php.net/y2k-compliance
-y2k_compliance = On
-
; Output buffering is a mechanism for controlling how much output data
; (excluding headers and cookies) PHP should keep internally before pushing that
; data to the client. If your application's output exceeds this setting, PHP
@@ -319,58 +300,6 @@ unserialize_callback_func =
; are decoded with unserialize, the data will remain the same.
serialize_precision = 17
-; This directive allows you to enable and disable warnings which PHP will issue
-; if you pass a value by reference at function call time. Passing values by
-; reference at function call time is a deprecated feature which will be removed
-; from PHP at some point in the near future. The acceptable method for passing a
-; value by reference to a function is by declaring the reference in the functions
-; definition, not at call time. This directive does not disable this feature, it
-; only determines whether PHP will warn you about it or not. These warnings
-; should enabled in development environments only.
-; Default Value: On (Suppress warnings)
-; Development Value: Off (Issue warnings)
-; Production Value: Off (Issue warnings)
-; http://php.net/allow-call-time-pass-reference
-allow_call_time_pass_reference = Off
-
-; Safe Mode
-; http://php.net/safe-mode
-safe_mode = Off
-
-; By default, Safe Mode does a UID compare check when
-; opening files. If you want to relax this to a GID compare,
-; then turn on safe_mode_gid.
-; http://php.net/safe-mode-gid
-safe_mode_gid = Off
-
-; When safe_mode is on, UID/GID checks are bypassed when
-; including files from this directory and its subdirectories.
-; (directory must also be in include_path or full path must
-; be used when including)
-; http://php.net/safe-mode-include-dir
-safe_mode_include_dir =
-
-; When safe_mode is on, only executables located in the safe_mode_exec_dir
-; will be allowed to be executed via the exec family of functions.
-; http://php.net/safe-mode-exec-dir
-safe_mode_exec_dir =
-
-; Setting certain environment variables may be a potential security breach.
-; This directive contains a comma-delimited list of prefixes. In Safe Mode,
-; the user may only alter environment variables whose names begin with the
-; prefixes supplied here. By default, users will only be able to set
-; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR).
-; Note: If this directive is empty, PHP will let the user modify ANY
-; environment variable!
-; http://php.net/safe-mode-allowed-env-vars
-safe_mode_allowed_env_vars = PHP_
-
-; This directive contains a comma-delimited list of environment variables that
-; the end user won't be able to change using putenv(). These variables will be
-; protected even if safe_mode_allowed_env_vars is set to allow to change them.
-; http://php.net/safe-mode-protected-env-vars
-safe_mode_protected_env_vars = LD_LIBRARY_PATH
-
; open_basedir, if set, limits all file operations to the defined directory
; and below. This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file. This directive is
@@ -396,7 +325,6 @@ disable_classes =
;highlight.string = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #007700
-;highlight.bg = #FFFFFF
;highlight.default = #0000BB
;highlight.html = #000000
@@ -423,6 +351,18 @@ disable_classes =
; http://php.net/zend.enable-gc
zend.enable_gc = On
+; If enabled, scripts may be written in encodings that are incompatible with
+; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such
+; encodings. To use this feature, mbstring extension must be enabled.
+; Default: Off
+;zend.multibyte = Off
+
+; Allows to set the default encoding for the scripts. This value will be used
+; unless "declare(encoding=...)" directive appears at the top of the script.
+; Only affects if zend.multibyte is set.
+; Default: ""
+;zend.script_encoding =
+
;;;;;;;;;;;;;;;;;
; Miscellaneous ;
;;;;;;;;;;;;;;;;;
@@ -479,7 +419,7 @@ memory_limit = 128M
; recommend error reporting setting. Your production server shouldn't be wasting
; resources complaining about best practices and coding standards. That's what
; development servers and development settings are for.
-; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This
+; Note: The php.ini-development file has this setting as E_ALL. This
; means it pretty much reports everything which is exactly what you want during
; development and early testing.
;
@@ -510,15 +450,15 @@ memory_limit = 128M
; E_USER_DEPRECATED - user-generated deprecation warnings
;
; Common Values:
-; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.)
-; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices)
+; E_ALL (Show all errors, warnings and notices including coding standards.)
+; E_ALL & ~E_NOTICE (Show all errors, except for notices)
+; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.)
; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors)
-; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.)
-; Default Value: E_ALL & ~E_NOTICE
-; Development Value: E_ALL | E_STRICT
-; Production Value: E_ALL & ~E_DEPRECATED
+; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
+; Development Value: E_ALL
+; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
-error_reporting = E_ALL | E_STRICT
+error_reporting = E_ALL
; This directive controls whether or not and where PHP will output errors,
; notices and warnings too. Error output is very useful during development, but
@@ -599,23 +539,24 @@ track_errors = On
; An XML-RPC faultCode
;xmlrpc_error_number = 0
-; When PHP displays or logs an error, it has the capability of inserting html
-; links to documentation related to that error. This directive controls whether
-; those HTML links appear in error messages or not. For performance and security
-; reasons, it's recommended you disable this on production servers.
+; When PHP displays or logs an error, it has the capability of formatting the
+; error message as HTML for easier reading. This directive controls whether
+; the error message is formatted as HTML or not.
; Note: This directive is hardcoded to Off for the CLI SAPI
; Default Value: On
; Development Value: On
-; Production value: Off
+; Production value: On
; http://php.net/html-errors
html_errors = On
-; If html_errors is set On PHP produces clickable error messages that direct
-; to a page describing the error or function causing the error in detail.
+; If html_errors is set to On *and* docref_root is not empty, then PHP
+; produces clickable error messages that direct to a page describing the error
+; or function causing the error in detail.
; You can download a copy of the PHP manual from http://php.net/docs
; and change docref_root to the base URL of your local copy including the
; leading '/'. You must also specify the file extension being used including
-; the dot. PHP's default behavior is to leave these settings empty.
+; the dot. PHP's default behavior is to leave these settings empty, in which
+; case no links to documentation are generated.
; Note: Never use this feature for production boxes.
; http://php.net/docref-root
; Examples
@@ -667,13 +608,12 @@ html_errors = On
;arg_separator.input = ";&"
; This directive determines which super global arrays are registered when PHP
-; starts up. If the register_globals directive is enabled, it also determines
-; what order variables are populated into the global space. G,P,C,E & S are
-; abbreviations for the following respective super globals: GET, POST, COOKIE,
-; ENV and SERVER. There is a performance penalty paid for the registration of
-; these arrays and because ENV is not as commonly used as the others, ENV is
-; is not recommended on productions servers. You can still get access to
-; the environment variables through getenv() should you need to.
+; starts up. G,P,C,E & S are abbreviations for the following respective super
+; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty
+; paid for the registration of these arrays and because ENV is not as commonly
+; used as the others, ENV is not recommended on productions servers. You
+; can still get access to the environment variables through getenv() should you
+; need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
@@ -693,25 +633,6 @@ variables_order = "GPCS"
; http://php.net/request-order
request_order = "GP"
-; Whether or not to register the EGPCS variables as global variables. You may
-; want to turn this off if you don't want to clutter your scripts' global scope
-; with user data.
-; You should do your best to write your scripts so that they do not require
-; register_globals to be on; Using form variables as globals can easily lead
-; to possible security problems, if the code is not very well thought of.
-; http://php.net/register-globals
-register_globals = Off
-
-; Determines whether the deprecated long $HTTP_*_VARS type predefined variables
-; are registered by PHP or not. As they are deprecated, we obviously don't
-; recommend you use them. They are on by default for compatibility reasons but
-; they are not recommended on production servers.
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-; http://php.net/register-long-arrays
-register_long_arrays = Off
-
; This directive determines whether PHP registers $argv & $argc each time it
; runs. $argv contains an array of all the arguments passed to PHP when a script
; is invoked. $argc contains an integer representing the number of arguments
@@ -727,42 +648,29 @@ register_long_arrays = Off
; http://php.net/register-argc-argv
register_argc_argv = Off
-; When enabled, the SERVER and ENV variables are created when they're first
-; used (Just In Time) instead of when the script starts. If these variables
-; are not used within a script, having this directive on will result in a
-; performance gain. The PHP directives register_globals, register_long_arrays,
-; and register_argc_argv must be disabled for this directive to have any affect.
+; When enabled, the ENV, REQUEST and SERVER variables are created when they're
+; first used (Just In Time) instead of when the script starts. If these
+; variables are not used within a script, having this directive on will result
+; in a performance gain. The PHP directive register_argc_argv must be disabled
+; for this directive to have any affect.
; http://php.net/auto-globals-jit
auto_globals_jit = On
+; Whether PHP will read the POST data.
+; This option is enabled by default.
+; Most likely, you won't want to disable this option globally. It causes $_POST
+; and $_FILES to always be empty; the only way you will be able to read the
+; POST data will be through the php://input stream wrapper. This can be useful
+; to proxy requests or to process the POST data in a memory efficient fashion.
+; http://php.net/enable-post-data-reading
+;enable_post_data_reading = Off
+
; Maximum size of POST data that PHP will accept.
+; Its value may be 0 to disable the limit. It is ignored if POST data reading
+; is disabled through enable_post_data_reading.
; http://php.net/post-max-size
post_max_size = 8M
-; Magic quotes are a preprocessing feature of PHP where PHP will attempt to
-; escape any character sequences in GET, POST, COOKIE and ENV data which might
-; otherwise corrupt data being placed in resources such as databases before
-; making that data available to you. Because of character encoding issues and
-; non-standard SQL implementations across many databases, it's not currently
-; possible for this feature to be 100% accurate. PHP's default behavior is to
-; enable the feature. We strongly recommend you use the escaping mechanisms
-; designed specifically for the database your using instead of relying on this
-; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is
-; removed in PHP 5.4.
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-; http://php.net/magic-quotes-gpc
-magic_quotes_gpc = Off
-
-; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
-; http://php.net/magic-quotes-runtime
-magic_quotes_runtime = Off
-
-; Use Sybase-style magic quotes (escape ' with '' instead of \').
-; http://php.net/magic-quotes-sybase
-magic_quotes_sybase = Off
-
; Automatically add files before PHP document.
; http://php.net/auto-prepend-file
auto_prepend_file =
@@ -781,10 +689,11 @@ default_mimetype = "text/html"
; PHP's default character set is set to empty.
; http://php.net/default-charset
-;default_charset = "iso-8859-1"
+;default_charset = "UTF-8"
; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is
-; to disable this feature.
+; to disable this feature. If post reading is disabled through
+; enable_post_data_reading, $HTTP_RAW_POST_DATA is *NOT* populated.
; http://php.net/always-populate-raw-post-data
;always_populate_raw_post_data = On
@@ -974,7 +883,6 @@ default_socket_timeout = 60
;extension=php_oci8_11g.dll ; Use with Oracle 11gR2 Instant Client
;extension=php_openssl.dll
;extension=php_pdo_firebird.dll
-;extension=php_pdo_mssql.dll
;extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_odbc.dll
@@ -990,7 +898,6 @@ default_socket_timeout = 60
;extension=php_soap.dll
;extension=php_sockets.dll
-;extension=php_sqlite.dll
;extension=php_sqlite3.dll
;extension=php_sybase_ct.dll
;extension=php_tidy.dll
@@ -1002,6 +909,10 @@ default_socket_timeout = 60
; Module Settings ;
;;;;;;;;;;;;;;;;;;;
+[CLI Server]
+; Whether the CLI web server uses ANSI color coding in its terminal output.
+cli_server.color = On
+
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
@@ -1083,13 +994,6 @@ pdo_mysql.default_socket=
;phar.cache_list =
-[Syslog]
-; Whether or not to define the various syslog variables (e.g. $LOG_PID,
-; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In
-; runtime, you can define these variables by calling define_syslog_variables().
-; http://php.net/define-syslog-variables
-define_syslog_variables = Off
-
[mail function]
; For Win32 only.
; http://php.net/smtp
@@ -1116,6 +1020,8 @@ mail.add_x_header = On
; The path to a log file that will log all mail() calls. Log entries include
; the full path of the script, line number, To address and headers.
;mail.log =
+; Log mail to syslog (Event Log on NT, not valid in Windows 95).
+;mail.log = syslog
[SQL]
; http://php.net/sql.safe-mode
@@ -1571,8 +1477,8 @@ session.gc_maxlifetime = 1440
; find /path/to/sessions -cmin +24 | xargs rm
; PHP 4.2 and less have an undocumented feature/bug that allows you to
-; to initialize a session variable in the global scope, even when register_globals
-; is disabled. PHP 4.3 and later will warn you, if this feature is used.
+; to initialize a session variable in the global scope.
+; PHP 4.3 and later will warn you, if this feature is used.
; You can disable the feature and the warning separately. At this time,
; the warning is only displayed, if bug_compat_42 is enabled. This feature
; introduces some serious security problems if not handled correctly. It's
@@ -1603,12 +1509,14 @@ session.referer_check =
; How many bytes to read from the file.
; http://php.net/session.entropy-length
-session.entropy_length = 0
+;session.entropy_length = 32
; Specified here to create the session id.
; http://php.net/session.entropy-file
-; On systems that don't have /dev/urandom /dev/arandom can be used
-; On windows, setting the entropy_length setting will activate the
+; Defaults to /dev/urandom
+; On systems that don't have /dev/urandom but do have /dev/arandom, this will default to /dev/arandom
+; If neither are found at compile time, the default is no entropy file.
+; On windows, setting the entropy_length setting will activate the
; Windows random source (using the CryptoAPI)
;session.entropy_file = /dev/urandom
@@ -1666,6 +1574,51 @@ session.hash_bits_per_character = 5
; http://php.net/url-rewriter.tags
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
+; Enable upload progress tracking in $_SESSION
+; Default Value: On
+; Development Value: On
+; Production Value: On
+; http://php.net/session.upload-progress.enabled
+;session.upload_progress.enabled = On
+
+; Cleanup the progress information as soon as all POST data has been read
+; (i.e. upload completed).
+; Default Value: On
+; Development Value: On
+; Production Value: On
+; http://php.net/session.upload-progress.cleanup
+;session.upload_progress.cleanup = On
+
+; A prefix used for the upload progress key in $_SESSION
+; Default Value: "upload_progress_"
+; Development Value: "upload_progress_"
+; Production Value: "upload_progress_"
+; http://php.net/session.upload-progress.prefix
+;session.upload_progress.prefix = "upload_progress_"
+
+; The index name (concatenated with the prefix) in $_SESSION
+; containing the upload progress information
+; Default Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; Development Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; Production Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; http://php.net/session.upload-progress.name
+;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
+
+; How frequently the upload progress should be updated.
+; Given either in percentages (per-file), or in bytes
+; Default Value: "1%"
+; Development Value: "1%"
+; Production Value: "1%"
+; http://php.net/session.upload-progress.freq
+;session.upload_progress.freq = "1%"
+
+; The minimum delay between updates, in seconds
+; Default Value: 1
+; Development Value: 1
+; Production Value: 1
+; http://php.net/session.upload-progress.min-freq
+;session.upload_progress.min_freq = "1"
+
[MSSQL]
; Allow or prevent persistent links.
mssql.allow_persistent = On
@@ -1822,10 +1775,6 @@ mssql.secure_connection = Off
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
;mbstring.http_output_conv_mimetype=
-; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte
-; Default: ""
-;mbstring.script_encoding=
-
[gd]
; Tell the jpeg decode to ignore warnings and try to create
; a gd image. The warning will then be displayed as notices
@@ -1907,12 +1856,6 @@ ldap.max_links = -1
[dba]
;dba.default_handler=
-[xsl]
-; Write operations from within XSLT are disabled by default.
-; XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_WRITE_FILE = 44
-; Set it to 0 to allow all operations
-;xsl.security_prefs = 44
-
; Local Variables:
; tab-width: 4
; End:
diff --git a/php.ini-production b/php.ini-production
index 9d5861dd55..814455bbbb 100644
--- a/php.ini-production
+++ b/php.ini-production
@@ -91,11 +91,6 @@
; Please see the actual settings later in the document for more details as to why
; we recommend these changes in PHP's behavior.
-; allow_call_time_pass_reference
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-
; display_errors
; Default Value: On
; Development Value: On
@@ -107,25 +102,20 @@
; Production Value: Off
; error_reporting
-; Default Value: E_ALL & ~E_NOTICE
-; Development Value: E_ALL | E_STRICT
-; Production Value: E_ALL & ~E_DEPRECATED
+; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
+; Development Value: E_ALL
+; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; html_errors
; Default Value: On
; Development Value: On
-; Production value: Off
+; Production value: On
; log_errors
; Default Value: Off
; Development Value: On
; Production Value: On
-; magic_quotes_gpc
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-
; max_input_time
; Default Value: -1 (Unlimited)
; Development Value: 60 (60 seconds)
@@ -141,11 +131,6 @@
; Development Value: Off
; Production Value: Off
-; register_long_arrays
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-
; request_order
; Default Value: None
; Development Value: "GP"
@@ -233,10 +218,6 @@ asp_tags = Off
; http://php.net/precision
precision = 14
-; Enforce year 2000 compliance (will cause problems with non-compliant browsers)
-; http://php.net/y2k-compliance
-y2k_compliance = On
-
; Output buffering is a mechanism for controlling how much output data
; (excluding headers and cookies) PHP should keep internally before pushing that
; data to the client. If your application's output exceeds this setting, PHP
@@ -319,58 +300,6 @@ unserialize_callback_func =
; are decoded with unserialize, the data will remain the same.
serialize_precision = 17
-; This directive allows you to enable and disable warnings which PHP will issue
-; if you pass a value by reference at function call time. Passing values by
-; reference at function call time is a deprecated feature which will be removed
-; from PHP at some point in the near future. The acceptable method for passing a
-; value by reference to a function is by declaring the reference in the functions
-; definition, not at call time. This directive does not disable this feature, it
-; only determines whether PHP will warn you about it or not. These warnings
-; should enabled in development environments only.
-; Default Value: On (Suppress warnings)
-; Development Value: Off (Issue warnings)
-; Production Value: Off (Issue warnings)
-; http://php.net/allow-call-time-pass-reference
-allow_call_time_pass_reference = Off
-
-; Safe Mode
-; http://php.net/safe-mode
-safe_mode = Off
-
-; By default, Safe Mode does a UID compare check when
-; opening files. If you want to relax this to a GID compare,
-; then turn on safe_mode_gid.
-; http://php.net/safe-mode-gid
-safe_mode_gid = Off
-
-; When safe_mode is on, UID/GID checks are bypassed when
-; including files from this directory and its subdirectories.
-; (directory must also be in include_path or full path must
-; be used when including)
-; http://php.net/safe-mode-include-dir
-safe_mode_include_dir =
-
-; When safe_mode is on, only executables located in the safe_mode_exec_dir
-; will be allowed to be executed via the exec family of functions.
-; http://php.net/safe-mode-exec-dir
-safe_mode_exec_dir =
-
-; Setting certain environment variables may be a potential security breach.
-; This directive contains a comma-delimited list of prefixes. In Safe Mode,
-; the user may only alter environment variables whose names begin with the
-; prefixes supplied here. By default, users will only be able to set
-; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR).
-; Note: If this directive is empty, PHP will let the user modify ANY
-; environment variable!
-; http://php.net/safe-mode-allowed-env-vars
-safe_mode_allowed_env_vars = PHP_
-
-; This directive contains a comma-delimited list of environment variables that
-; the end user won't be able to change using putenv(). These variables will be
-; protected even if safe_mode_allowed_env_vars is set to allow to change them.
-; http://php.net/safe-mode-protected-env-vars
-safe_mode_protected_env_vars = LD_LIBRARY_PATH
-
; open_basedir, if set, limits all file operations to the defined directory
; and below. This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file. This directive is
@@ -396,7 +325,6 @@ disable_classes =
;highlight.string = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #007700
-;highlight.bg = #FFFFFF
;highlight.default = #0000BB
;highlight.html = #000000
@@ -423,6 +351,18 @@ disable_classes =
; http://php.net/zend.enable-gc
zend.enable_gc = On
+; If enabled, scripts may be written in encodings that are incompatible with
+; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such
+; encodings. To use this feature, mbstring extension must be enabled.
+; Default: Off
+;zend.multibyte = Off
+
+; Allows to set the default encoding for the scripts. This value will be used
+; unless "declare(encoding=...)" directive appears at the top of the script.
+; Only affects if zend.multibyte is set.
+; Default: ""
+;zend.script_encoding =
+
;;;;;;;;;;;;;;;;;
; Miscellaneous ;
;;;;;;;;;;;;;;;;;
@@ -479,7 +419,7 @@ memory_limit = 128M
; recommend error reporting setting. Your production server shouldn't be wasting
; resources complaining about best practices and coding standards. That's what
; development servers and development settings are for.
-; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This
+; Note: The php.ini-development file has this setting as E_ALL. This
; means it pretty much reports everything which is exactly what you want during
; development and early testing.
;
@@ -510,15 +450,15 @@ memory_limit = 128M
; E_USER_DEPRECATED - user-generated deprecation warnings
;
; Common Values:
-; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.)
-; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices)
+; E_ALL (Show all errors, warnings and notices including coding standards.)
+; E_ALL & ~E_NOTICE (Show all errors, except for notices)
+; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.)
; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors)
-; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.)
-; Default Value: E_ALL & ~E_NOTICE
-; Development Value: E_ALL | E_STRICT
-; Production Value: E_ALL & ~E_DEPRECATED
+; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
+; Development Value: E_ALL
+; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
-error_reporting = E_ALL & ~E_DEPRECATED
+error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
; This directive controls whether or not and where PHP will output errors,
; notices and warnings too. Error output is very useful during development, but
@@ -599,23 +539,24 @@ track_errors = Off
; An XML-RPC faultCode
;xmlrpc_error_number = 0
-; When PHP displays or logs an error, it has the capability of inserting html
-; links to documentation related to that error. This directive controls whether
-; those HTML links appear in error messages or not. For performance and security
-; reasons, it's recommended you disable this on production servers.
+; When PHP displays or logs an error, it has the capability of formatting the
+; error message as HTML for easier reading. This directive controls whether
+; the error message is formatted as HTML or not.
; Note: This directive is hardcoded to Off for the CLI SAPI
; Default Value: On
; Development Value: On
-; Production value: Off
+; Production value: On
; http://php.net/html-errors
-html_errors = Off
+html_errors = On
-; If html_errors is set On PHP produces clickable error messages that direct
-; to a page describing the error or function causing the error in detail.
+; If html_errors is set to On *and* docref_root is not empty, then PHP
+; produces clickable error messages that direct to a page describing the error
+; or function causing the error in detail.
; You can download a copy of the PHP manual from http://php.net/docs
; and change docref_root to the base URL of your local copy including the
; leading '/'. You must also specify the file extension being used including
-; the dot. PHP's default behavior is to leave these settings empty.
+; the dot. PHP's default behavior is to leave these settings empty, in which
+; case no links to documentation are generated.
; Note: Never use this feature for production boxes.
; http://php.net/docref-root
; Examples
@@ -667,13 +608,12 @@ html_errors = Off
;arg_separator.input = ";&"
; This directive determines which super global arrays are registered when PHP
-; starts up. If the register_globals directive is enabled, it also determines
-; what order variables are populated into the global space. G,P,C,E & S are
-; abbreviations for the following respective super globals: GET, POST, COOKIE,
-; ENV and SERVER. There is a performance penalty paid for the registration of
-; these arrays and because ENV is not as commonly used as the others, ENV is
-; is not recommended on productions servers. You can still get access to
-; the environment variables through getenv() should you need to.
+; starts up. G,P,C,E & S are abbreviations for the following respective super
+; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty
+; paid for the registration of these arrays and because ENV is not as commonly
+; used as the others, ENV is not recommended on productions servers. You
+; can still get access to the environment variables through getenv() should you
+; need to.
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS";
@@ -693,25 +633,6 @@ variables_order = "GPCS"
; http://php.net/request-order
request_order = "GP"
-; Whether or not to register the EGPCS variables as global variables. You may
-; want to turn this off if you don't want to clutter your scripts' global scope
-; with user data.
-; You should do your best to write your scripts so that they do not require
-; register_globals to be on; Using form variables as globals can easily lead
-; to possible security problems, if the code is not very well thought of.
-; http://php.net/register-globals
-register_globals = Off
-
-; Determines whether the deprecated long $HTTP_*_VARS type predefined variables
-; are registered by PHP or not. As they are deprecated, we obviously don't
-; recommend you use them. They are on by default for compatibility reasons but
-; they are not recommended on production servers.
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-; http://php.net/register-long-arrays
-register_long_arrays = Off
-
; This directive determines whether PHP registers $argv & $argc each time it
; runs. $argv contains an array of all the arguments passed to PHP when a script
; is invoked. $argc contains an integer representing the number of arguments
@@ -727,42 +648,29 @@ register_long_arrays = Off
; http://php.net/register-argc-argv
register_argc_argv = Off
-; When enabled, the SERVER and ENV variables are created when they're first
-; used (Just In Time) instead of when the script starts. If these variables
-; are not used within a script, having this directive on will result in a
-; performance gain. The PHP directives register_globals, register_long_arrays,
-; and register_argc_argv must be disabled for this directive to have any affect.
+; When enabled, the ENV, REQUEST and SERVER variables are created when they're
+; first used (Just In Time) instead of when the script starts. If these
+; variables are not used within a script, having this directive on will result
+; in a performance gain. The PHP directive register_argc_argv must be disabled
+; for this directive to have any affect.
; http://php.net/auto-globals-jit
auto_globals_jit = On
+; Whether PHP will read the POST data.
+; This option is enabled by default.
+; Most likely, you won't want to disable this option globally. It causes $_POST
+; and $_FILES to always be empty; the only way you will be able to read the
+; POST data will be through the php://input stream wrapper. This can be useful
+; to proxy requests or to process the POST data in a memory efficient fashion.
+; http://php.net/enable-post-data-reading
+;enable_post_data_reading = Off
+
; Maximum size of POST data that PHP will accept.
+; Its value may be 0 to disable the limit. It is ignored if POST data reading
+; is disabled through enable_post_data_reading.
; http://php.net/post-max-size
post_max_size = 8M
-; Magic quotes are a preprocessing feature of PHP where PHP will attempt to
-; escape any character sequences in GET, POST, COOKIE and ENV data which might
-; otherwise corrupt data being placed in resources such as databases before
-; making that data available to you. Because of character encoding issues and
-; non-standard SQL implementations across many databases, it's not currently
-; possible for this feature to be 100% accurate. PHP's default behavior is to
-; enable the feature. We strongly recommend you use the escaping mechanisms
-; designed specifically for the database your using instead of relying on this
-; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is
-; scheduled removed in PHP 5.4.
-; Default Value: On
-; Development Value: Off
-; Production Value: Off
-; http://php.net/magic-quotes-gpc
-magic_quotes_gpc = Off
-
-; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
-; http://php.net/magic-quotes-runtime
-magic_quotes_runtime = Off
-
-; Use Sybase-style magic quotes (escape ' with '' instead of \').
-; http://php.net/magic-quotes-sybase
-magic_quotes_sybase = Off
-
; Automatically add files before PHP document.
; http://php.net/auto-prepend-file
auto_prepend_file =
@@ -781,10 +689,11 @@ default_mimetype = "text/html"
; PHP's default character set is set to empty.
; http://php.net/default-charset
-;default_charset = "iso-8859-1"
+;default_charset = "UTF-8"
; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is
-; to disable this feature.
+; to disable this feature. If post reading is disabled through
+; enable_post_data_reading, $HTTP_RAW_POST_DATA is *NOT* populated.
; http://php.net/always-populate-raw-post-data
;always_populate_raw_post_data = On
@@ -974,7 +883,6 @@ default_socket_timeout = 60
;extension=php_oci8_11g.dll ; Use with Oracle 11gR2 Instant Client
;extension=php_openssl.dll
;extension=php_pdo_firebird.dll
-;extension=php_pdo_mssql.dll
;extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_odbc.dll
@@ -990,7 +898,6 @@ default_socket_timeout = 60
;extension=php_soap.dll
;extension=php_sockets.dll
-;extension=php_sqlite.dll
;extension=php_sqlite3.dll
;extension=php_sybase_ct.dll
;extension=php_tidy.dll
@@ -1002,6 +909,10 @@ default_socket_timeout = 60
; Module Settings ;
;;;;;;;;;;;;;;;;;;;
+[CLI Server]
+; Whether the CLI web server uses ANSI color coding in its terminal output.
+cli_server.color = On
+
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
@@ -1083,13 +994,6 @@ pdo_mysql.default_socket=
;phar.cache_list =
-[Syslog]
-; Whether or not to define the various syslog variables (e.g. $LOG_PID,
-; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In
-; runtime, you can define these variables by calling define_syslog_variables().
-; http://php.net/define-syslog-variables
-define_syslog_variables = Off
-
[mail function]
; For Win32 only.
; http://php.net/smtp
@@ -1116,6 +1020,8 @@ mail.add_x_header = On
; The path to a log file that will log all mail() calls. Log entries include
; the full path of the script, line number, To address and headers.
;mail.log =
+; Log mail to syslog (Event Log on NT, not valid in Windows 95).
+;mail.log = syslog
[SQL]
; http://php.net/sql.safe-mode
@@ -1571,8 +1477,8 @@ session.gc_maxlifetime = 1440
; find /path/to/sessions -cmin +24 | xargs rm
; PHP 4.2 and less have an undocumented feature/bug that allows you to
-; to initialize a session variable in the global scope, even when register_globals
-; is disabled. PHP 4.3 and later will warn you, if this feature is used.
+; to initialize a session variable in the global scope.
+; PHP 4.3 and later will warn you, if this feature is used.
; You can disable the feature and the warning separately. At this time,
; the warning is only displayed, if bug_compat_42 is enabled. This feature
; introduces some serious security problems if not handled correctly. It's
@@ -1603,12 +1509,14 @@ session.referer_check =
; How many bytes to read from the file.
; http://php.net/session.entropy-length
-session.entropy_length = 0
+;session.entropy_length = 32
; Specified here to create the session id.
; http://php.net/session.entropy-file
-; On systems that don't have /dev/urandom /dev/arandom can be used
-; On windows, setting the entropy_length setting will activate the
+; Defaults to /dev/urandom
+; On systems that don't have /dev/urandom but do have /dev/arandom, this will default to /dev/arandom
+; If neither are found at compile time, the default is no entropy file.
+; On windows, setting the entropy_length setting will activate the
; Windows random source (using the CryptoAPI)
;session.entropy_file = /dev/urandom
@@ -1666,6 +1574,51 @@ session.hash_bits_per_character = 5
; http://php.net/url-rewriter.tags
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
+; Enable upload progress tracking in $_SESSION
+; Default Value: On
+; Development Value: On
+; Production Value: On
+; http://php.net/session.upload-progress.enabled
+;session.upload_progress.enabled = On
+
+; Cleanup the progress information as soon as all POST data has been read
+; (i.e. upload completed).
+; Default Value: On
+; Development Value: On
+; Production Value: On
+; http://php.net/session.upload-progress.cleanup
+;session.upload_progress.cleanup = On
+
+; A prefix used for the upload progress key in $_SESSION
+; Default Value: "upload_progress_"
+; Development Value: "upload_progress_"
+; Production Value: "upload_progress_"
+; http://php.net/session.upload-progress.prefix
+;session.upload_progress.prefix = "upload_progress_"
+
+; The index name (concatenated with the prefix) in $_SESSION
+; containing the upload progress information
+; Default Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; Development Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; Production Value: "PHP_SESSION_UPLOAD_PROGRESS"
+; http://php.net/session.upload-progress.name
+;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
+
+; How frequently the upload progress should be updated.
+; Given either in percentages (per-file), or in bytes
+; Default Value: "1%"
+; Development Value: "1%"
+; Production Value: "1%"
+; http://php.net/session.upload-progress.freq
+;session.upload_progress.freq = "1%"
+
+; The minimum delay between updates, in seconds
+; Default Value: 1
+; Development Value: 1
+; Production Value: 1
+; http://php.net/session.upload-progress.min-freq
+;session.upload_progress.min_freq = "1"
+
[MSSQL]
; Allow or prevent persistent links.
mssql.allow_persistent = On
@@ -1822,10 +1775,6 @@ mssql.secure_connection = Off
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
;mbstring.http_output_conv_mimetype=
-; Allows to set script encoding. Only affects if PHP is compiled with --enable-zend-multibyte
-; Default: ""
-;mbstring.script_encoding=
-
[gd]
; Tell the jpeg decode to ignore warnings and try to create
; a gd image. The warning will then be displayed as notices
@@ -1907,12 +1856,6 @@ ldap.max_links = -1
[dba]
;dba.default_handler=
-[xsl]
-; Write operations from within XSLT are disabled by default.
-; XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_WRITE_FILE = 44
-; Set it to 0 to allow all operations
-;xsl.security_prefs = 44
-
; Local Variables:
; tab-width: 4
; End:
diff --git a/run-tests.php b/run-tests.php
index cfc562ebc1..a746c36965 100755
--- a/run-tests.php
+++ b/run-tests.php
@@ -632,6 +632,9 @@ if (isset($argc) && $argc > 1) {
case 'x':
$environment['SKIP_SLOW_TESTS'] = 1;
break;
+ case '--offline':
+ $environment['SKIP_ONLINE_TESTS'] = 1;
+ break;
//case 'w'
case '-':
// repeat check with full switch
@@ -689,6 +692,8 @@ Options:
-x Sets 'SKIP_SLOW_TESTS' environmental variable.
+ --offline Sets 'SKIP_ONLINE_TESTS' environmental variable.
+
--verbose
-v Verbose mode.
diff --git a/sapi/apache/mod_php5.c b/sapi/apache/mod_php5.c
index 695fd719b1..236dd6636b 100644
--- a/sapi/apache/mod_php5.c
+++ b/sapi/apache/mod_php5.c
@@ -278,9 +278,6 @@ static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_
/* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
if (track_vars_array) {
symbol_table = track_vars_array->value.ht;
- } else if (PG(register_globals)) {
- /* should never happen nowadays */
- symbol_table = EG(active_symbol_table);
} else {
symbol_table = NULL;
}
@@ -310,10 +307,8 @@ static int php_apache_startup(sapi_module_struct *sapi_module)
/* {{{ php_apache_log_message
*/
-static void php_apache_log_message(char *message)
+static void php_apache_log_message(char *message TSRMLS_DC)
{
- TSRMLS_FETCH();
-
if (SG(server_context)) {
#if MODULE_MAGIC_NUMBER >= 19970831
aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
@@ -332,7 +327,7 @@ static void php_apache_request_shutdown(void *dummy)
{
TSRMLS_FETCH();
- php_output_set_status(0 TSRMLS_CC);
+ php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
if (AP(in_request)) {
AP(in_request) = 0;
php_request_shutdown(dummy);
@@ -443,9 +438,9 @@ static int sapi_apache_get_target_gid(gid_t *obj TSRMLS_DC)
/* {{{ php_apache_get_request_time
*/
-static time_t php_apache_get_request_time(TSRMLS_D)
+static double php_apache_get_request_time(TSRMLS_D)
{
- return ((request_rec *)SG(server_context))->request_time;
+ return (double) ((request_rec *)SG(server_context))->request_time;
}
/* }}} */
@@ -504,6 +499,7 @@ static sapi_module_struct apache_sapi_module = {
NULL, /* treat data */
NULL, /* exe location */
0, /* ini ignore */
+ 0, /* ini ignore cwd */
sapi_apache_get_fd,
sapi_apache_force_http_10,
sapi_apache_get_target_uid,
@@ -545,7 +541,7 @@ static void init_request_info(TSRMLS_D)
SG(request_info).auth_password = NULL;
SG(request_info).auth_digest = NULL;
- if (authorization && (!PG(safe_mode) || (PG(safe_mode) && !auth_type(r)))) {
+ if (authorization) {
char *p = getword(r->pool, &authorization, ' ');
if (!strcasecmp(p, "Basic")) {
tmp = uudecode(r->pool, authorization);
diff --git a/sapi/apache/php_apache.c b/sapi/apache/php_apache.c
index 8081af0b42..a830de69c8 100644
--- a/sapi/apache/php_apache.c
+++ b/sapi/apache/php_apache.c
@@ -272,7 +272,7 @@ PHP_MINFO_FUNCTION(apache)
env_arr = table_elts(r->headers_in);
env = (table_entry *)env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
- if (env[i].key && (!PG(safe_mode) || (PG(safe_mode) && strncasecmp(env[i].key, "authorization", 13)))) {
+ if (env[i].key) {
php_info_print_table_row(2, env[i].key, env[i].val);
}
}
@@ -350,7 +350,7 @@ PHP_FUNCTION(virtual)
int filename_len;
request_rec *rr = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
@@ -368,7 +368,7 @@ PHP_FUNCTION(virtual)
RETURN_FALSE;
}
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
php_header(TSRMLS_C);
if (run_sub_req(rr)) {
@@ -401,9 +401,7 @@ PHP_FUNCTION(apache_request_headers)
env_arr = table_elts(((request_rec *) SG(server_context))->headers_in);
tenv = (table_entry *)env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
- if (!tenv[i].key ||
- (PG(safe_mode) &&
- !strncasecmp(tenv[i].key, "authorization", 13))) {
+ if (!tenv[i].key) {
continue;
}
if (add_assoc_string(return_value, tenv[i].key, (tenv[i].val==NULL) ? "" : tenv[i].val, 1)==FAILURE) {
@@ -533,14 +531,14 @@ PHP_FUNCTION(apache_lookup_uri)
#if 0
+/*
This function is most likely a bad idea. Just playing with it for now.
-
+*/
PHP_FUNCTION(apache_exec_uri)
{
char *filename;
int filename_len;
request_rec *rr=NULL;
- TSRMLS_FETCH();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
return;
@@ -594,11 +592,6 @@ PHP_FUNCTION(apache_get_modules)
Reset the Apache write timer */
PHP_FUNCTION(apache_reset_timeout)
{
- if (PG(safe_mode)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot reset the Apache timeout in safe mode");
- RETURN_FALSE;
- }
-
ap_reset_timeout((request_rec *)SG(server_context));
RETURN_TRUE;
}
diff --git a/sapi/apache2filter/php_functions.c b/sapi/apache2filter/php_functions.c
index 123ecdcde3..29ae2fceb9 100644
--- a/sapi/apache2filter/php_functions.c
+++ b/sapi/apache2filter/php_functions.c
@@ -63,7 +63,7 @@ PHP_FUNCTION(virtual)
int filename_len;
request_rec *rr;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
@@ -101,7 +101,7 @@ PHP_FUNCTION(apache_lookup_uri)
char *filename;
int filename_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
diff --git a/sapi/apache2filter/sapi_apache2.c b/sapi/apache2filter/sapi_apache2.c
index 0ebee17659..0b51cfbe62 100644
--- a/sapi/apache2filter/sapi_apache2.c
+++ b/sapi/apache2filter/sapi_apache2.c
@@ -282,10 +282,9 @@ php_apache_sapi_flush(void *server_context)
}
}
-static void php_apache_sapi_log_message(char *msg)
+static void php_apache_sapi_log_message(char *msg TSRMLS_DC)
{
php_struct *ctx;
- TSRMLS_FETCH();
ctx = SG(server_context);
@@ -309,10 +308,10 @@ php_apache_disable_caching(ap_filter_t *f)
return OK;
}
-static time_t php_apache_sapi_get_request_time(TSRMLS_D)
+static double php_apache_sapi_get_request_time(TSRMLS_D)
{
php_struct *ctx = SG(server_context);
- return apr_time_sec(ctx->r->request_time);
+ return ((double) apr_time_as_msec(ctx->r->request_time)) / 1000.0;
}
extern zend_module_entry php_apache_module;
@@ -426,17 +425,16 @@ static void php_apache_request_ctor(ap_filter_t *f, php_struct *ctx TSRMLS_DC)
apr_table_unset(f->r->headers_out, "Last-Modified");
apr_table_unset(f->r->headers_out, "Expires");
apr_table_unset(f->r->headers_out, "ETag");
- if (!PG(safe_mode) || (PG(safe_mode) && !ap_auth_type(f->r))) {
- auth = apr_table_get(f->r->headers_in, "Authorization");
- php_handle_auth_data(auth TSRMLS_CC);
- if (SG(request_info).auth_user == NULL && f->r->user) {
- SG(request_info).auth_user = estrdup(f->r->user);
- }
- ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
- } else {
- SG(request_info).auth_user = NULL;
- SG(request_info).auth_password = NULL;
+
+ auth = apr_table_get(f->r->headers_in, "Authorization");
+ php_handle_auth_data(auth TSRMLS_CC);
+
+ if (SG(request_info).auth_user == NULL && f->r->user) {
+ SG(request_info).auth_user = estrdup(f->r->user);
}
+
+ ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
+
php_request_startup(TSRMLS_C);
}
diff --git a/sapi/apache2handler/config.w32 b/sapi/apache2handler/config.w32
index 2f2084cb14..8d8a6c4b69 100644
--- a/sapi/apache2handler/config.w32
+++ b/sapi/apache2handler/config.w32
@@ -5,7 +5,7 @@ ARG_ENABLE('apache2handler', 'Build Apache 2.x handler', 'no');
if (PHP_APACHE2HANDLER != "no") {
if (PHP_ZTS == "no") {
- WARNING("Apache2 module requires an --enable-zts build of PHP on windows");
+ WARNING("Apache 2.0 module requires an --enable-zts build of PHP on windows");
} else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2HANDLER", PHP_PHP_BUILD + "\\include\\apache2") &&
CHECK_LIB("libhttpd.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2") &&
CHECK_LIB("libapr.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2") &&
@@ -23,7 +23,7 @@ ARG_ENABLE('apache2-2handler', 'Build Apache 2.2.x handler', 'no');
if (PHP_APACHE2_2HANDLER != "no") {
if (PHP_ZTS == "no") {
- WARNING("Apache2 module requires an --enable-zts build of PHP on windows");
+ WARNING("Apache 2.2 module requires an --enable-zts build of PHP on windows");
} else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2_2HANDLER", PHP_PHP_BUILD + "\\include\\apache2_2") &&
CHECK_LIB("libhttpd.lib", "apache2_2handler", PHP_PHP_BUILD + "\\lib\\apache2_2") &&
CHECK_LIB("libapr-1.lib", "apache2_2handler", PHP_PHP_BUILD + "\\lib\\apache2_2") &&
@@ -37,3 +37,22 @@ if (PHP_APACHE2_2HANDLER != "no") {
WARNING("Could not find apache2.2 libraries/headers");
}
}
+
+ARG_ENABLE('apache2-3handler', 'Build Apache 2.3.x handler', 'no');
+if (PHP_APACHE2_3HANDLER != "no") {
+ if (PHP_ZTS == "no") {
+ WARNING("Apache 2.3 module requires an --enable-zts build of PHP on windows");
+ } else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2_3HANDLER", PHP_PHP_BUILD + "\\include\\apache2_3") &&
+ CHECK_LIB("libhttpd.lib", "apache2_3handler", PHP_PHP_BUILD + "\\lib\\apache2_3") &&
+ CHECK_LIB("libapr-1.lib", "apache2_3handler", PHP_PHP_BUILD + "\\lib\\apache2_3") &&
+ CHECK_LIB("libaprutil-1.lib", "apache2_3handler", PHP_PHP_BUILD + "\\lib\\apache2_3")
+ ) {
+ SAPI('apache2_3handler', 'mod_php5.c sapi_apache2.c apache_config.c php_functions.c',
+ 'php' + PHP_VERSION + 'apache2_3.dll',
+ '/D PHP_APACHE2_EXPORTS /I win32',
+ 'sapi\\apache2handler');
+ } else {
+ WARNING("Could not find apache2.3 libraries/headers");
+ }
+}
+
diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c
index 103d0d0793..3c1f9a17fa 100644
--- a/sapi/apache2handler/php_functions.c
+++ b/sapi/apache2handler/php_functions.c
@@ -75,7 +75,7 @@ PHP_FUNCTION(virtual)
int filename_len;
request_rec *rr;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
@@ -91,7 +91,7 @@ PHP_FUNCTION(virtual)
}
/* Flush everything. */
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
php_header(TSRMLS_C);
/* Ensure that the ap_r* layer for the main request is flushed, to
@@ -121,7 +121,7 @@ PHP_FUNCTION(apache_lookup_uri)
char *filename;
int filename_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
return;
}
diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c
index 8586a0c2af..900a3a425b 100644
--- a/sapi/apache2handler/sapi_apache2.c
+++ b/sapi/apache2handler/sapi_apache2.c
@@ -313,10 +313,9 @@ php_apache_sapi_flush(void *server_context)
}
}
-static void php_apache_sapi_log_message(char *msg)
+static void php_apache_sapi_log_message(char *msg TSRMLS_DC)
{
php_struct *ctx;
- TSRMLS_FETCH();
ctx = SG(server_context);
@@ -327,19 +326,19 @@ static void php_apache_sapi_log_message(char *msg)
}
}
-static void php_apache_sapi_log_message_ex(char *msg, request_rec *r)
+static void php_apache_sapi_log_message_ex(char *msg, request_rec *r TSRMLS_DC)
{
if (r) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, msg, r->filename);
} else {
- php_apache_sapi_log_message(msg);
+ php_apache_sapi_log_message(msg TSRMLS_CC);
}
}
-static time_t php_apache_sapi_get_request_time(TSRMLS_D)
+static double php_apache_sapi_get_request_time(TSRMLS_D)
{
php_struct *ctx = SG(server_context);
- return apr_time_sec(ctx->r->request_time);
+ return ((double) apr_time_as_msec(ctx->r->request_time)) / 1000.0;
}
extern zend_module_entry php_apache_module;
@@ -490,17 +489,16 @@ static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC)
apr_table_unset(r->headers_out, "Last-Modified");
apr_table_unset(r->headers_out, "Expires");
apr_table_unset(r->headers_out, "ETag");
- if (!PG(safe_mode) || (PG(safe_mode) && !ap_auth_type(r))) {
- auth = apr_table_get(r->headers_in, "Authorization");
- php_handle_auth_data(auth TSRMLS_CC);
- if (SG(request_info).auth_user == NULL && r->user) {
- SG(request_info).auth_user = estrdup(r->user);
- }
- ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
- } else {
- SG(request_info).auth_user = NULL;
- SG(request_info).auth_password = NULL;
+
+ auth = apr_table_get(r->headers_in, "Authorization");
+ php_handle_auth_data(auth TSRMLS_CC);
+
+ if (SG(request_info).auth_user == NULL && r->user) {
+ SG(request_info).auth_user = estrdup(r->user);
}
+
+ ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
+
return php_request_startup(TSRMLS_C);
}
@@ -590,12 +588,12 @@ normal:
}
if (r->finfo.filetype == 0) {
- php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r);
+ php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r TSRMLS_CC);
PHPAP_INI_OFF;
return HTTP_NOT_FOUND;
}
if (r->finfo.filetype == APR_DIR) {
- php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r);
+ php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r TSRMLS_CC);
PHPAP_INI_OFF;
return HTTP_FORBIDDEN;
}
@@ -672,7 +670,7 @@ zend_first_try {
}
apr_table_set(r->notes, "mod_php_memory_usage",
- apr_psprintf(ctx->r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
+ apr_psprintf(ctx->r->pool, "%zu", zend_memory_peak_usage(1 TSRMLS_CC)));
}
} zend_end_try();
diff --git a/sapi/apache_hooks/mod_php5.c b/sapi/apache_hooks/mod_php5.c
index 23d04426e6..67b5a3aa66 100644
--- a/sapi/apache_hooks/mod_php5.c
+++ b/sapi/apache_hooks/mod_php5.c
@@ -1,20 +1,20 @@
/*
+----------------------------------------------------------------------+
- | PHP Version 5 |
+ | PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2012 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available at through the world-wide-web at |
- | http://www.php.net/license/3_01.txt |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Rasmus Lerdorf <rasmus@php.net> |
- | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> |
- | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> |
+ | Authors: Rasmus Lerdorf <rasmus@php.net> |
+ | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> |
+ | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
@@ -403,9 +403,6 @@ static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_
/* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
if (track_vars_array) {
symbol_table = track_vars_array->value.ht;
- } else if (PG(register_globals)) {
- /* should never happen nowadays */
- symbol_table = EG(active_symbol_table);
} else {
symbol_table = NULL;
}
@@ -433,10 +430,8 @@ static int php_apache_startup(sapi_module_struct *sapi_module)
/* {{{ php_apache_log_message
*/
-static void php_apache_log_message(char *message)
+static void php_apache_log_message(char *message TSRMLS_DC)
{
- TSRMLS_FETCH();
-
if (SG(server_context)) {
#if MODULE_MAGIC_NUMBER >= 19970831
aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
@@ -456,7 +451,7 @@ static void php_apache_request_shutdown(void *dummy)
{
TSRMLS_FETCH();
AP(current_hook) = AP_CLEANUP;
- php_output_set_status(0 TSRMLS_CC);
+ php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */
if(SG(sapi_started)) {
php_request_shutdown(dummy);
diff --git a/sapi/apache_hooks/php_apache.c b/sapi/apache_hooks/php_apache.c
index 04dd30e906..830902310a 100644
--- a/sapi/apache_hooks/php_apache.c
+++ b/sapi/apache_hooks/php_apache.c
@@ -44,7 +44,7 @@ extern module **ap_loaded_modules;
static int le_apachereq;
static zend_class_entry *apacherequest_class_entry;
-static void apache_table_to_zval(table *, int safe_mode, zval *return_value);
+static void apache_table_to_zval(table *, zval *return_value);
PHP_FUNCTION(virtual);
PHP_FUNCTION(apache_request_headers);
@@ -567,7 +567,7 @@ PHP_FUNCTION(apache_request_headers_in)
APREQ_GET_REQUEST(id, r);
- apache_table_to_zval(r->headers_in, 0, return_value);
+ apache_table_to_zval(r->headers_in, return_value);
}
/* }}} */
@@ -664,7 +664,7 @@ PHP_FUNCTION(apache_request_headers_out)
add_header_to_table(r->headers_out, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
- apache_table_to_zval(r->headers_out, 0, return_value);
+ apache_table_to_zval(r->headers_out, return_value);
}
/* }}} */
@@ -683,7 +683,7 @@ PHP_FUNCTION(apache_request_err_headers_out)
add_header_to_table(r->err_headers_out, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
- apache_table_to_zval(r->err_headers_out, 0, return_value);
+ apache_table_to_zval(r->err_headers_out, return_value);
}
/* }}} */
@@ -1683,7 +1683,7 @@ PHP_MINFO_FUNCTION(apache)
env_arr = table_elts(r->headers_in);
env = (table_entry *)env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
- if (env[i].key && (!PG(safe_mode) || (PG(safe_mode) && strncasecmp(env[i].key, "authorization", 13)))) {
+ if (env[i].key) {
php_info_print_table_row(2, env[i].key, env[i].val);
}
}
@@ -1734,7 +1734,7 @@ PHP_FUNCTION(virtual)
RETURN_FALSE;
}
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
php_header(TSRMLS_C);
if (run_sub_req(rr)) {
@@ -1751,9 +1751,9 @@ PHP_FUNCTION(virtual)
/* }}} */
-/* {{{ apache_table_to_zval(table *, int safe_mode, zval *return_value)
+/* {{{ apache_table_to_zval(table *, zval *return_value)
Fetch all HTTP request headers */
-static void apache_table_to_zval(table *t, int safe_mode, zval *return_value)
+static void apache_table_to_zval(table *t, zval *return_value)
{
array_header *env_arr;
table_entry *tenv;
@@ -1763,8 +1763,7 @@ static void apache_table_to_zval(table *t, int safe_mode, zval *return_value)
env_arr = table_elts(t);
tenv = (table_entry *)env_arr->elts;
for (i = 0; i < env_arr->nelts; ++i) {
- if (!tenv[i].key ||
- (safe_mode && !strncasecmp(tenv[i].key, "authorization", 13))) {
+ if (!tenv[i].key) {
continue;
}
if (add_assoc_string(return_value, tenv[i].key, (tenv[i].val==NULL) ? "" : tenv[i].val, 1)==FAILURE) {
@@ -1789,7 +1788,7 @@ PHP_FUNCTION(apache_request_headers)
return;
}
- apache_table_to_zval(((request_rec *)SG(server_context))->headers_in, PG(safe_mode), return_value);
+ apache_table_to_zval(((request_rec *)SG(server_context))->headers_in, return_value);
}
/* }}} */
@@ -1801,7 +1800,7 @@ PHP_FUNCTION(apache_response_headers)
return;
}
- apache_table_to_zval(((request_rec *) SG(server_context))->headers_out, 0, return_value);
+ apache_table_to_zval(((request_rec *) SG(server_context))->headers_out, return_value);
}
/* }}} */
@@ -1906,13 +1905,14 @@ PHP_FUNCTION(apache_lookup_uri)
#if 0
+/*
This function is most likely a bad idea. Just playing with it for now.
+*/
PHP_FUNCTION(apache_exec_uri)
{
zval **filename;
request_rec *rr=NULL;
- TSRMLS_FETCH();
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) {
WRONG_PARAM_COUNT;
diff --git a/sapi/apache_hooks/sapi_apache.c b/sapi/apache_hooks/sapi_apache.c
index 7372cb7e28..e45f579a6e 100644
--- a/sapi/apache_hooks/sapi_apache.c
+++ b/sapi/apache_hooks/sapi_apache.c
@@ -78,13 +78,9 @@ int apache_php_module_hook(request_rec *r, php_handler *handler, zval **ret TSRM
return FAILURE;
}
- req = php_apache_request_new(r);
- if(PG(register_globals)) {
- php_register_variable_ex("request", req, NULL TSRMLS_CC);
- }
- else {
- php_register_variable_ex("request", req, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
- }
+ req = php_apache_request_new(r);
+ php_register_variable_ex("request", req, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
+
switch(handler->type) {
case AP_HANDLER_TYPE_FILE:
php_register_variable("PHP_SELF_HOOK", handler->name, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
diff --git a/sapi/cgi/Makefile.frag b/sapi/cgi/Makefile.frag
index 57a3b2937c..505119e572 100644
--- a/sapi/cgi/Makefile.frag
+++ b/sapi/cgi/Makefile.frag
@@ -1,2 +1,9 @@
-$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
+cgi: $(SAPI_CGI_PATH)
+
+$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CGI_OBJS)
$(BUILD_CGI)
+
+install-cgi: $(SAPI_CGI_PATH)
+ @echo "Installing PHP CGI binary: $(INSTALL_ROOT)$(bindir)/"
+ @$(INSTALL) -m 0755 $(SAPI_CGI_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)php-cgi$(program_suffix)$(EXEEXT)
+
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index a7ac26f0d0..7856e0c581 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -106,6 +106,7 @@ static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC);
*/
static int children = 0;
+
/**
* Set to non-zero if we are the parent process
*/
@@ -268,41 +269,30 @@ static void print_extensions(TSRMLS_D)
#define STDOUT_FILENO 1
#endif
-static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC)
+static inline size_t sapi_cgi_single_write(const char *str, uint str_length TSRMLS_DC)
{
#ifdef PHP_WRITE_STDOUT
long ret;
-#else
- size_t ret;
-#endif
-
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
- if (ret <= 0) {
- return 0;
- }
- return ret;
- }
-#ifdef PHP_WRITE_STDOUT
ret = write(STDOUT_FILENO, str, str_length);
if (ret <= 0) return 0;
return ret;
#else
+ size_t ret;
+
ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
return ret;
#endif
}
-static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
+static int sapi_cgi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
const char *ptr = str;
uint remaining = str_length;
size_t ret;
while (remaining > 0) {
- ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC);
+ ret = sapi_cgi_single_write(ptr, remaining TSRMLS_CC);
if (!ret) {
php_handle_aborted_connection();
return str_length - remaining;
@@ -314,21 +304,43 @@ static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
return str_length;
}
+static int sapi_fcgi_ub_write(const char *str, uint str_length TSRMLS_DC)
+{
+ const char *ptr = str;
+ uint remaining = str_length;
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ while (remaining > 0) {
+ long ret = fcgi_write(request, FCGI_STDOUT, ptr, remaining);
+
+ if (ret <= 0) {
+ php_handle_aborted_connection();
+ return str_length - remaining;
+ }
+ ptr += ret;
+ remaining -= ret;
+ }
+
+ return str_length;
+}
+
+static void sapi_cgi_flush(void *server_context)
+{
+ if (fflush(stdout) == EOF) {
+ php_handle_aborted_connection();
+ }
+}
-static void sapi_cgibin_flush(void *server_context)
+static void sapi_fcgi_flush(void *server_context)
{
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) server_context;
- if (
+ fcgi_request *request = (fcgi_request*) server_context;
+
+ if (
#ifndef PHP_WIN32
!parent &&
#endif
request && !fcgi_flush(request, 0)) {
- php_handle_aborted_connection();
- }
- return;
- }
- if (fflush(stdout) == EOF) {
+
php_handle_aborted_connection();
}
}
@@ -494,12 +506,24 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
while (read_bytes < count_bytes) {
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
- } else {
- tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
+ tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
+ if (tmp_read_bytes <= 0) {
+ break;
}
+ read_bytes += tmp_read_bytes;
+ }
+ return read_bytes;
+}
+
+static int sapi_fcgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
+{
+ uint read_bytes = 0;
+ int tmp_read_bytes;
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
+ while (read_bytes < count_bytes) {
+ tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
if (tmp_read_bytes <= 0) {
break;
}
@@ -508,43 +532,33 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
return read_bytes;
}
-static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC)
+static char *sapi_cgi_getenv(char *name, size_t name_len TSRMLS_DC)
+{
+ return getenv(name);
+}
+
+static char *sapi_fcgi_getenv(char *name, size_t name_len TSRMLS_DC)
{
/* when php is started by mod_fastcgi, no regular environment
* is provided to PHP. It is always sent to PHP at the start
* of a request. So we have to do our own lookup to get env
* vars. This could probably be faster somehow. */
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- return fcgi_getenv(request, name, name_len);
- }
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+ char *ret = fcgi_getenv(request, name, name_len);
+
+ if (ret) return ret;
/* if cgi, or fastcgi and not found in fcgi env
check the regular environment */
return getenv(name);
}
-static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
+static char *_sapi_cgi_putenv(char *name, int name_len, char *value)
{
- int name_len;
#if !HAVE_SETENV || !HAVE_UNSETENV
int len;
char *buf;
#endif
- if (!name) {
- return NULL;
- }
- name_len = strlen(name);
-
- /* when php is started by mod_fastcgi, no regular environment
- * is provided to PHP. It is always sent to PHP at the start
- * of a request. So we have to do our own lookup to get env
- * vars. This could probably be faster somehow. */
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- return fcgi_putenv(request, name, name_len, value);
- }
-
#if HAVE_SETENV
if (value) {
setenv(name, value, 1);
@@ -585,10 +599,28 @@ static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
static char *sapi_cgi_read_cookies(TSRMLS_D)
{
- return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC);
+ return getenv("HTTP_COOKIE");
+}
+
+static char *sapi_fcgi_read_cookies(TSRMLS_D)
+{
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ return FCGI_GETENV(request, "HTTP_COOKIE");
+}
+
+static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC)
+{
+ zval *array_ptr = (zval*)arg;
+ int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
+ unsigned int new_val_len;
+
+ if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len TSRMLS_CC)) {
+ php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
+ }
}
-void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
+static void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
{
if (PG(http_globals)[TRACK_VARS_ENV] &&
array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
@@ -617,31 +649,7 @@ void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
if (fcgi_is_fastcgi()) {
fcgi_request *request = (fcgi_request*) SG(server_context);
- HashPosition pos;
- int magic_quotes_gpc = PG(magic_quotes_gpc);
- char *var, **val;
- uint var_len;
- ulong idx;
- int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
-
- /* turn off magic_quotes while importing environment variables */
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
- for (zend_hash_internal_pointer_reset_ex(request->env, &pos);
- zend_hash_get_current_key_ex(request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
- zend_hash_get_current_data_ex(request->env, (void **) &val, &pos) == SUCCESS;
- zend_hash_move_forward_ex(request->env, &pos)
- ) {
- unsigned int new_val_len;
-
- if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) {
- php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
- }
- }
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "1", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
+ fcgi_loadenv(request, cgi_php_load_env_var, array_ptr TSRMLS_CC);
}
}
@@ -657,25 +665,51 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
if (CGIG(fix_pathinfo)) {
char *script_name = SG(request_info).request_uri;
- unsigned int script_name_len = script_name ? strlen(script_name) : 0;
- char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
- unsigned int path_info_len = path_info ? strlen(path_info) : 0;
+ char *path_info;
+ int free_php_self;
+ ALLOCA_FLAG(use_heap)
- php_self_len = script_name_len + path_info_len;
- php_self = emalloc(php_self_len + 1);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
- if (script_name) {
- memcpy(php_self, script_name, script_name_len + 1);
+ path_info = FCGI_GETENV(request, "PATH_INFO");
+ } else {
+ path_info = getenv("PATH_INFO");
}
+
if (path_info) {
- memcpy(php_self + script_name_len, path_info, path_info_len + 1);
+ unsigned int path_info_len = strlen(path_info);
+
+ if (script_name) {
+ unsigned int script_name_len = strlen(script_name);
+
+ php_self_len = script_name_len + path_info_len;
+ php_self = do_alloca(php_self_len + 1, use_heap);
+ memcpy(php_self, script_name, script_name_len + 1);
+ memcpy(php_self + script_name_len, path_info, path_info_len + 1);
+ free_php_self = 1;
+ } else {
+ php_self = path_info;
+ php_self_len = path_info_len;
+ free_php_self = 0;
+ }
+ } else if (script_name) {
+ php_self = script_name;
+ php_self_len = strlen(script_name);
+ free_php_self = 0;
+ } else {
+ php_self = "";
+ php_self_len = 0;
+ free_php_self = 0;
}
/* Build the special-case PHP_SELF variable for the CGI version */
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) {
php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC);
}
- efree(php_self);
+ if (free_php_self) {
+ free_alloca(php_self, use_heap);
+ }
} else {
php_self = SG(request_info).request_uri ? SG(request_info).request_uri : "";
php_self_len = strlen(php_self);
@@ -685,10 +719,8 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
}
}
-static void sapi_cgi_log_message(char *message)
+static void sapi_cgi_log_message(char *message TSRMLS_DC)
{
- TSRMLS_FETCH();
-
if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
fcgi_request *request;
@@ -740,7 +772,6 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha
if (!IS_ABSOLUTE_PATH(path, path_len)) {
real_path = tsrm_realpath(path, NULL TSRMLS_CC);
- /* see #51688, looks like we may get invalid path as doc root using cgi with apache */
if (real_path == NULL) {
return;
}
@@ -802,7 +833,13 @@ static int sapi_cgi_activate(TSRMLS_D)
if (php_ini_has_per_host_config()) {
/* Activate per-host-system-configuration defined in php.ini and stored into configuration_hash during startup */
- server_name = sapi_cgibin_getenv("SERVER_NAME", sizeof("SERVER_NAME") - 1 TSRMLS_CC);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ server_name = FCGI_GETENV(request, "SERVER_NAME");
+ } else {
+ server_name = getenv("SERVER_NAME");
+ }
/* SERVER_NAME should also be defined at this stage..but better check it anyway */
if (server_name) {
server_name_len = strlen(server_name);
@@ -836,7 +873,14 @@ static int sapi_cgi_activate(TSRMLS_D)
/* Load and activate user ini files in path starting from DOCUMENT_ROOT */
if (PG(user_ini_filename) && *PG(user_ini_filename)) {
- doc_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT");
+ } else {
+ doc_root = getenv("DOCUMENT_ROOT");
+ }
+
/* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */
if (doc_root) {
doc_root_len = strlen(doc_root);
@@ -878,7 +922,7 @@ static int sapi_cgi_deactivate(TSRMLS_D)
php_handle_aborted_connection();
}
} else {
- sapi_cgibin_flush(SG(server_context));
+ sapi_cgi_flush(SG(server_context));
}
}
return SUCCESS;
@@ -904,10 +948,10 @@ static sapi_module_struct cgi_sapi_module = {
sapi_cgi_activate, /* activate */
sapi_cgi_deactivate, /* deactivate */
- sapi_cgibin_ub_write, /* unbuffered write */
- sapi_cgibin_flush, /* flush */
+ sapi_cgi_ub_write, /* unbuffered write */
+ sapi_cgi_flush, /* flush */
NULL, /* get uid */
- sapi_cgibin_getenv, /* getenv */
+ sapi_cgi_getenv, /* getenv */
php_error, /* error handler */
@@ -982,34 +1026,43 @@ static void php_cgi_usage(char *argv0)
*/
static int is_valid_path(const char *path)
{
- const char *p;
+ const char *p = path;
- if (!path) {
+ if (UNEXPECTED(!p)) {
return 0;
}
- p = strstr(path, "..");
- if (p) {
- if ((p == path || IS_SLASH(*(p-1))) &&
- (*(p+2) == 0 || IS_SLASH(*(p+2)))
- ) {
- return 0;
- }
- while (1) {
- p = strstr(p+1, "..");
- if (!p) {
- break;
- }
- if (IS_SLASH(*(p-1)) &&
- (*(p+2) == 0 || IS_SLASH(*(p+2)))
- ) {
- return 0;
+ if (UNEXPECTED(*p == '.') && *(p+1) == '.' && (!*(p+2) || IS_SLASH(*(p+2)))) {
+ return 0;
+ }
+ while (*p) {
+ if (IS_SLASH(*p)) {
+ p++;
+ if (UNEXPECTED(*p == '.')) {
+ p++;
+ if (UNEXPECTED(*p == '.')) {
+ p++;
+ if (UNEXPECTED(!*p) || UNEXPECTED(IS_SLASH(*p))) {
+ return 0;
+ }
+ }
}
}
+ p++;
}
return 1;
}
/* }}} */
+#define CGI_GETENV(name) \
+ ((request) ? \
+ FCGI_GETENV(request, name) : \
+ getenv(name))
+
+#define CGI_PUTENV(name, value) \
+ ((request) ? \
+ FCGI_PUTENV(request, name, value) : \
+ _sapi_cgi_putenv(name, sizeof(name)-1, value))
+
/* {{{ init_request_info
initializes request_info structure
@@ -1076,10 +1129,10 @@ static int is_valid_path(const char *path)
Comments in the code below refer to using the above URL in a request
*/
-static void init_request_info(TSRMLS_D)
+static void init_request_info(fcgi_request *request TSRMLS_DC)
{
- char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC);
- char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC);
+ char *env_script_filename = CGI_GETENV("SCRIPT_FILENAME");
+ char *env_path_translated = CGI_GETENV("PATH_TRANSLATED");
char *script_path_translated = env_script_filename;
/* some broken servers do not have script_filename or argv0
@@ -1105,32 +1158,35 @@ static void init_request_info(TSRMLS_D)
* of the script will be retreived later via argc/argv */
if (script_path_translated) {
const char *auth;
- char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC);
- char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC);
- char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
- char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC);
+ char *content_length = CGI_GETENV("CONTENT_LENGTH");
+ char *content_type = CGI_GETENV("CONTENT_TYPE");
+ char *env_path_info = CGI_GETENV("PATH_INFO");
+ char *env_script_name = CGI_GETENV("SCRIPT_NAME");
+#ifdef PHP_WIN32
/* Hack for buggy IIS that sets incorrect PATH_INFO */
- char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC);
+ char *env_server_software = CGI_GETENV("SERVER_SOFTWARE");
+
if (env_server_software &&
env_script_name &&
env_path_info &&
strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 &&
strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0
) {
- env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC);
+ env_path_info = CGI_PUTENV("ORIG_PATH_INFO", env_path_info);
env_path_info += strlen(env_script_name);
if (*env_path_info == 0) {
env_path_info = NULL;
}
- env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info TSRMLS_CC);
+ env_path_info = CGI_PUTENV("PATH_INFO", env_path_info);
}
+#endif
if (CGIG(fix_pathinfo)) {
struct stat st;
char *real_path = NULL;
- char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC);
- char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
+ char *env_redirect_url = CGI_GETENV("REDIRECT_URL");
+ char *env_document_root = CGI_GETENV("DOCUMENT_ROOT");
char *orig_path_translated = env_path_translated;
char *orig_path_info = env_path_info;
char *orig_script_name = env_script_name;
@@ -1138,7 +1194,7 @@ static void init_request_info(TSRMLS_D)
int script_path_translated_len;
if (!env_document_root && PG(doc_root)) {
- env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC);
+ env_document_root = CGI_PUTENV("DOCUMENT_ROOT", PG(doc_root));
/* fix docroot */
TRANSLATE_SLASHES(env_document_root);
}
@@ -1205,28 +1261,28 @@ static void init_request_info(TSRMLS_D)
if (orig_path_info) {
char old;
- _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
old = path_info[0];
path_info[0] = 0;
if (!orig_script_name ||
strcmp(orig_script_name, env_path_info) != 0) {
if (orig_script_name) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
}
- SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info TSRMLS_CC);
+ SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_path_info);
} else {
SG(request_info).request_uri = orig_script_name;
}
path_info[0] = old;
}
- env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC);
+ env_path_info = CGI_PUTENV("PATH_INFO", path_info);
}
if (!orig_script_filename ||
strcmp(orig_script_filename, pt) != 0) {
if (orig_script_filename) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
}
- script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC);
+ script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", pt);
}
TRANSLATE_SLASHES(pt);
@@ -1256,9 +1312,9 @@ static void init_request_info(TSRMLS_D)
}
path_translated[path_translated_len] = '\0';
if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
}
- env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
+ env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
efree(path_translated);
} else if ( env_script_name &&
strstr(pt, env_script_name)
@@ -1275,9 +1331,9 @@ static void init_request_info(TSRMLS_D)
}
path_translated[path_translated_len] = '\0';
if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
}
- env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC);
+ env_path_translated = CGI_PUTENV("PATH_TRANSLATED", path_translated);
efree(path_translated);
}
break;
@@ -1290,18 +1346,18 @@ static void init_request_info(TSRMLS_D)
* have failed anyway... we output 'no input file' now.
*/
if (orig_script_filename) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
}
- script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC);
+ script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", NULL);
SG(sapi_headers).http_response_code = 404;
}
if (!SG(request_info).request_uri) {
if (!orig_script_name ||
strcmp(orig_script_name, env_script_name) != 0) {
if (orig_script_name) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
}
- SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
+ SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
} else {
SG(request_info).request_uri = orig_script_name;
}
@@ -1315,25 +1371,25 @@ static void init_request_info(TSRMLS_D)
(script_path_translated != orig_script_filename &&
strcmp(script_path_translated, orig_script_filename) != 0)) {
if (orig_script_filename) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_FILENAME", orig_script_filename);
}
- script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC);
+ script_path_translated = CGI_PUTENV("SCRIPT_FILENAME", script_path_translated);
}
if (env_redirect_url) {
if (orig_path_info) {
- _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
- _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_INFO", orig_path_info);
+ CGI_PUTENV("PATH_INFO", NULL);
}
if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
- _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC);
+ CGI_PUTENV("ORIG_PATH_TRANSLATED", orig_path_translated);
+ CGI_PUTENV("PATH_TRANSLATED", NULL);
}
}
if (env_script_name != orig_script_name) {
if (orig_script_name) {
- _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
+ CGI_PUTENV("ORIG_SCRIPT_NAME", orig_script_name);
}
- SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC);
+ SG(request_info).request_uri = CGI_PUTENV("SCRIPT_NAME", env_script_name);
} else {
SG(request_info).request_uri = env_script_name;
}
@@ -1355,14 +1411,14 @@ static void init_request_info(TSRMLS_D)
SG(request_info).path_translated = estrdup(script_path_translated);
}
- SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC);
+ SG(request_info).request_method = CGI_GETENV("REQUEST_METHOD");
/* FIXME - Work out proto_num here */
- SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC);
+ SG(request_info).query_string = CGI_GETENV("QUERY_STRING");
SG(request_info).content_type = (content_type ? content_type : "" );
SG(request_info).content_length = (content_length ? atol(content_length) : 0);
/* The CGI RFC allows servers to pass on unvalidated Authorization data */
- auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC);
+ auth = CGI_GETENV("HTTP_AUTHORIZATION");
php_handle_auth_data(auth TSRMLS_CC);
}
}
@@ -1457,10 +1513,205 @@ static PHP_MINFO_FUNCTION(cgi)
}
/* }}} */
+PHP_FUNCTION(apache_child_terminate) /* {{{ */
+{
+ if (ZEND_NUM_ARGS() > 0) {
+ WRONG_PARAM_COUNT;
+ }
+ if (fcgi_is_fastcgi()) {
+ fcgi_terminate();
+ }
+}
+/* }}} */
+
+static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) /* {{{ */
+{
+ zval *return_value = (zval*)arg;
+ char *str = NULL;
+ char *p;
+ ALLOCA_FLAG(use_heap)
+
+ if (var_len > 5 &&
+ var[0] == 'H' &&
+ var[1] == 'T' &&
+ var[2] == 'T' &&
+ var[3] == 'P' &&
+ var[4] == '_') {
+
+ var_len -= 5;
+ p = var + 5;
+ var = str = do_alloca(var_len + 1, use_heap);
+ *str++ = *p++;
+ while (*p) {
+ if (*p == '_') {
+ *str++ = '-';
+ p++;
+ if (*p) {
+ *str++ = *p++;
+ }
+ } else if (*p >= 'A' && *p <= 'Z') {
+ *str++ = (*p++ - 'A' + 'a');
+ } else {
+ *str++ = *p++;
+ }
+ }
+ *str = 0;
+ } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
+ memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
+ var = "Content-Type";
+ } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
+ memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
+ var = "Content-Length";
+ } else {
+ return;
+ }
+ add_assoc_stringl_ex(return_value, var, var_len+1, val, val_len, 1);
+ if (str) {
+ free_alloca(var, use_heap);
+ }
+}
+/* }}} */
+
+PHP_FUNCTION(apache_request_headers) /* {{{ */
+{
+ if (ZEND_NUM_ARGS() > 0) {
+ WRONG_PARAM_COUNT;
+ }
+ array_init(return_value);
+ if (fcgi_is_fastcgi()) {
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+
+ fcgi_loadenv(request, add_request_header, return_value TSRMLS_CC);
+ } else {
+ char buf[128];
+ char **env, *p, *q, *var, *val, *t = buf;
+ size_t alloc_size = sizeof(buf);
+ unsigned long var_len;
+
+ for (env = environ; env != NULL && *env != NULL; env++) {
+ val = strchr(*env, '=');
+ if (!val) { /* malformed entry? */
+ continue;
+ }
+ var_len = val - *env;
+ if (var_len >= alloc_size) {
+ alloc_size = var_len + 64;
+ t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
+ }
+ var = *env;
+ if (var_len > 5 &&
+ var[0] == 'H' &&
+ var[1] == 'T' &&
+ var[2] == 'T' &&
+ var[3] == 'P' &&
+ var[4] == '_') {
+
+ var_len -= 5;
+
+ if (var_len >= alloc_size) {
+ alloc_size = var_len + 64;
+ t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
+ }
+ p = var + 5;
+
+ var = q = t;
+ /* First char keep uppercase */
+ *q++ = *p++;
+ while (*p) {
+ if (*p == '=') {
+ /* End of name */
+ break;
+ } else if (*p == '_') {
+ *q++ = '-';
+ p++;
+ /* First char after - keep uppercase */
+ if (*p && *p!='=') {
+ *q++ = *p++;
+ }
+ } else if (*p >= 'A' && *p <= 'Z') {
+ /* lowercase */
+ *q++ = (*p++ - 'A' + 'a');
+ } else {
+ *q++ = *p++;
+ }
+ }
+ *q = 0;
+ } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
+ memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
+ var = "Content-Type";
+ } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
+ memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
+ var = "Content-Length";
+ } else {
+ continue;
+ }
+ val++;
+ add_assoc_string_ex(return_value, var, var_len+1, val, 1);
+ }
+ if (t != buf && t != NULL) {
+ efree(t);
+ }
+ }
+}
+/* }}} */
+
+static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC) /* {{{ */
+{
+ char *s, *p;
+ int len;
+ ALLOCA_FLAG(use_heap)
+
+ if (h->header_len > 0) {
+ p = strchr(h->header, ':');
+ len = p - h->header;
+ if (p && (len > 0)) {
+ while (len > 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')) {
+ len--;
+ }
+ if (len) {
+ s = do_alloca(len + 1, use_heap);
+ memcpy(s, h->header, len);
+ s[len] = 0;
+ do {
+ p++;
+ } while (*p == ' ' || *p == '\t');
+ add_assoc_stringl_ex(return_value, s, len+1, p, h->header_len - (p - h->header), 1);
+ free_alloca(s, use_heap);
+ }
+ }
+ }
+}
+/* }}} */
+
+PHP_FUNCTION(apache_response_headers) /* {{{ */
+{
+ if (ZEND_NUM_ARGS() > 0) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (!&SG(sapi_headers).headers) {
+ RETURN_FALSE;
+ }
+ array_init(return_value);
+ zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC);
+}
+/* }}} */
+
+ZEND_BEGIN_ARG_INFO(arginfo_no_args, 0)
+ZEND_END_ARG_INFO()
+
+const zend_function_entry cgi_functions[] = {
+ PHP_FE(apache_child_terminate, arginfo_no_args)
+ PHP_FE(apache_request_headers, arginfo_no_args)
+ PHP_FE(apache_response_headers, arginfo_no_args)
+ PHP_FALIAS(getallheaders, apache_request_headers, arginfo_no_args)
+ {NULL, NULL, NULL}
+};
+
static zend_module_entry cgi_module_entry = {
STANDARD_MODULE_HEADER,
"cgi-fcgi",
- NULL,
+ cgi_functions,
PHP_MINIT(cgi),
PHP_MSHUTDOWN(cgi),
NULL,
@@ -1495,10 +1746,10 @@ int main(int argc, char *argv[])
int max_requests = 500;
int requests = 0;
- int fastcgi = fcgi_is_fastcgi();
+ int fastcgi;
char *bindpath = NULL;
int fcgi_fd = 0;
- fcgi_request request;
+ fcgi_request *request = NULL;
int repeats = 1;
int benchmark = 0;
#if HAVE_GETTIMEOFDAY
@@ -1540,6 +1791,7 @@ int main(int argc, char *argv[])
#endif
sapi_startup(&cgi_sapi_module);
+ fastcgi = fcgi_is_fastcgi();
cgi_sapi_module.php_ini_path_override = NULL;
#ifdef PHP_WIN32
@@ -1633,6 +1885,15 @@ int main(int argc, char *argv[])
php_optind = orig_optind;
php_optarg = orig_optarg;
+ if (fastcgi || bindpath) {
+ /* Override SAPI callbacks */
+ cgi_sapi_module.ub_write = sapi_fcgi_ub_write;
+ cgi_sapi_module.flush = sapi_fcgi_flush;
+ cgi_sapi_module.read_post = sapi_fcgi_read_post;
+ cgi_sapi_module.getenv = sapi_fcgi_getenv;
+ cgi_sapi_module.read_cookies = sapi_fcgi_read_cookies;
+ }
+
#ifdef ZTS
SG(request_info).path_translated = NULL;
#endif
@@ -1716,7 +1977,7 @@ consult the installation file that came with this distribution, or visit \n\
php_import_environment_variables = cgi_php_import_environment_variables;
/* library is already initialized, now init our request */
- fcgi_init_request(&request, fcgi_fd);
+ request = fcgi_init_request(fcgi_fd);
#ifndef PHP_WIN32
/* Pre-fork, if required */
@@ -1837,13 +2098,14 @@ consult the installation file that came with this distribution, or visit \n\
break;
case 'h':
case '?':
+ if (request) {
+ fcgi_destroy_request(request);
+ }
fcgi_shutdown();
no_headers = 1;
- php_output_startup();
- php_output_activate(TSRMLS_C);
SG(headers_sent) = 1;
php_cgi_usage(argv[0]);
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
exit_status = 0;
goto out;
}
@@ -1860,9 +2122,9 @@ consult the installation file that came with this distribution, or visit \n\
fcgi_impersonate();
}
#endif
- while (!fastcgi || fcgi_accept_request(&request) >= 0) {
- SG(server_context) = (void *) &request;
- init_request_info(TSRMLS_C);
+ while (!fastcgi || fcgi_accept_request(request) >= 0) {
+ SG(server_context) = fastcgi ? (void *) request : (void *) 1;
+ init_request_info(request TSRMLS_CC);
CG(interactive) = 0;
if (!cgi && !fastcgi) {
@@ -1918,15 +2180,13 @@ consult the installation file that came with this distribution, or visit \n\
if (script_file) {
efree(script_file);
}
- php_output_startup();
- php_output_activate(TSRMLS_C);
SG(headers_sent) = 1;
php_printf("[PHP Modules]\n");
print_modules(TSRMLS_C);
php_printf("\n[Zend Modules]\n");
print_extensions(TSRMLS_C);
php_printf("\n");
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
fcgi_shutdown();
exit_status = 0;
goto out;
@@ -2057,7 +2317,7 @@ consult the installation file that came with this distribution, or visit \n\
* get path_translated */
if (php_request_startup(TSRMLS_C) == FAILURE) {
if (fastcgi) {
- fcgi_finish_request(&request, 1);
+ fcgi_finish_request(request, 1);
}
SG(server_context) = NULL;
php_module_shutdown(TSRMLS_C);
@@ -2110,23 +2370,75 @@ consult the installation file that came with this distribution, or visit \n\
}
}
- if (CGIG(check_shebang_line) && file_handle.handle.fp && (file_handle.handle.fp != stdin)) {
+ if (CGIG(check_shebang_line)) {
/* #!php support */
- c = fgetc(file_handle.handle.fp);
- if (c == '#') {
- while (c != '\n' && c != '\r' && c != EOF) {
- c = fgetc(file_handle.handle.fp); /* skip to end of line */
- }
- /* handle situations where line is terminated by \r\n */
- if (c == '\r') {
- if (fgetc(file_handle.handle.fp) != '\n') {
- long pos = ftell(file_handle.handle.fp);
- fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
+ switch (file_handle.type) {
+ case ZEND_HANDLE_FD:
+ if (file_handle.handle.fd < 0) {
+ break;
}
- }
- CG(start_lineno) = 2;
- } else {
- rewind(file_handle.handle.fp);
+ file_handle.type = ZEND_HANDLE_FP;
+ file_handle.handle.fp = fdopen(file_handle.handle.fd, "rb");
+ /* break missing intentionally */
+ case ZEND_HANDLE_FP:
+ if (!file_handle.handle.fp ||
+ (file_handle.handle.fp == stdin)) {
+ break;
+ }
+ c = fgetc(file_handle.handle.fp);
+ if (c == '#') {
+ while (c != '\n' && c != '\r' && c != EOF) {
+ c = fgetc(file_handle.handle.fp); /* skip to end of line */
+ }
+ /* handle situations where line is terminated by \r\n */
+ if (c == '\r') {
+ if (fgetc(file_handle.handle.fp) != '\n') {
+ long pos = ftell(file_handle.handle.fp);
+ fseek(file_handle.handle.fp, pos - 1, SEEK_SET);
+ }
+ }
+ CG(start_lineno) = 2;
+ } else {
+ rewind(file_handle.handle.fp);
+ }
+ break;
+ case ZEND_HANDLE_STREAM:
+ c = php_stream_getc((php_stream*)file_handle.handle.stream.handle);
+ if (c == '#') {
+ while (c != '\n' && c != '\r' && c != EOF) {
+ c = php_stream_getc((php_stream*)file_handle.handle.stream.handle); /* skip to end of line */
+ }
+ /* handle situations where line is terminated by \r\n */
+ if (c == '\r') {
+ if (php_stream_getc((php_stream*)file_handle.handle.stream.handle) != '\n') {
+ long pos = php_stream_tell((php_stream*)file_handle.handle.stream.handle);
+ php_stream_seek((php_stream*)file_handle.handle.stream.handle, pos - 1, SEEK_SET);
+ }
+ }
+ CG(start_lineno) = 2;
+ } else {
+ php_stream_rewind((php_stream*)file_handle.handle.stream.handle);
+ }
+ break;
+ case ZEND_HANDLE_MAPPED:
+ if (file_handle.handle.stream.mmap.buf[0] == '#') {
+ int i = 1;
+
+ c = file_handle.handle.stream.mmap.buf[i++];
+ while (c != '\n' && c != '\r' && c != EOF) {
+ c = file_handle.handle.stream.mmap.buf[i++];
+ }
+ if (c == '\r') {
+ if (file_handle.handle.stream.mmap.buf[i] == '\n') {
+ i++;
+ }
+ }
+ file_handle.handle.stream.mmap.buf += i;
+ file_handle.handle.stream.mmap.len -= i;
+ }
+ break;
+ default:
+ break;
}
}
@@ -2147,7 +2459,7 @@ consult the installation file that came with this distribution, or visit \n\
if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) {
zend_strip(TSRMLS_C);
zend_file_handle_dtor(&file_handle TSRMLS_CC);
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_teardown();
}
return SUCCESS;
break;
@@ -2162,7 +2474,7 @@ consult the installation file that came with this distribution, or visit \n\
goto fastcgi_request_done;
}
zend_file_handle_dtor(&file_handle TSRMLS_CC);
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_teardown();
}
return SUCCESS;
}
@@ -2173,6 +2485,7 @@ consult the installation file that came with this distribution, or visit \n\
open_file_for_scanning(&file_handle TSRMLS_CC);
zend_indent();
zend_file_handle_dtor(&file_handle TSRMLS_CC);
+ php_output_teardown();
return SUCCESS;
break;
#endif
@@ -2210,7 +2523,7 @@ fastcgi_request_done:
/* only fastcgi will get here */
requests++;
if (max_requests && (requests == max_requests)) {
- fcgi_finish_request(&request, 1);
+ fcgi_finish_request(request, 1);
if (bindpath) {
free(bindpath);
}
@@ -2222,6 +2535,9 @@ fastcgi_request_done:
}
/* end of fastcgi loop */
}
+ if (request) {
+ fcgi_destroy_request(request);
+ }
fcgi_shutdown();
if (cgi_sapi_module.php_ini_path_override) {
diff --git a/sapi/cgi/config9.m4 b/sapi/cgi/config9.m4
index 9df454a556..67251aeb58 100644
--- a/sapi/cgi/config9.m4
+++ b/sapi/cgi/config9.m4
@@ -8,11 +8,9 @@ PHP_ARG_ENABLE(cgi,,
dnl
dnl CGI setup
dnl
-if test "$PHP_SAPI" = "default"; then
- AC_MSG_CHECKING(whether to build CGI binary)
- if test "$PHP_CGI" != "no"; then
+AC_MSG_CHECKING(for CGI build)
+if test "$PHP_CGI" != "no"; then
AC_MSG_RESULT(yes)
-
AC_MSG_CHECKING([for socklen_t in sys/socket.h])
AC_EGREP_HEADER([socklen_t], [sys/socket.h],
[AC_MSG_RESULT([yes])
@@ -50,31 +48,29 @@ if test "$PHP_SAPI" = "default"; then
SAPI_CGI_PATH=sapi/cgi/php-cgi
;;
esac
- PHP_SUBST(SAPI_CGI_PATH)
- dnl Set install target and select SAPI
- INSTALL_IT="@echo \"Installing PHP CGI binary: \$(INSTALL_ROOT)\$(bindir)/\"; \$(INSTALL) -m 0755 \$(SAPI_CGI_PATH) \$(INSTALL_ROOT)\$(bindir)/\$(program_prefix)php-cgi\$(program_suffix)\$(EXEEXT)"
+ dnl Select SAPI
PHP_SELECT_SAPI(cgi, program, cgi_main.c fastcgi.c,, '$(SAPI_CGI_PATH)')
case $host_alias in
*aix*)
- BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ if test "$php_sapi_module" = "shared"; then
+ BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ else
+ BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ fi
;;
*darwin*)
- BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
;;
*)
- BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
;;
esac
+ dnl Expose to Makefile
+ PHP_SUBST(SAPI_CGI_PATH)
PHP_SUBST(BUILD_CGI)
-
- elif test "$PHP_CLI" != "no"; then
- AC_MSG_RESULT(no)
- OVERALL_TARGET=
- PHP_SAPI=cli
- else
- AC_MSG_ERROR([No SAPIs selected.])
- fi
+else
+ AC_MSG_RESULT(yes)
fi
diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c
index 3c47f85c1a..c9c8da9ab8 100644
--- a/sapi/cgi/fastcgi.c
+++ b/sapi/cgi/fastcgi.c
@@ -67,6 +67,7 @@
# include <sys/socket.h>
# include <sys/un.h>
# include <netinet/in.h>
+# include <netinet/tcp.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <signal.h>
@@ -140,6 +141,224 @@ static int is_fastcgi = 0;
static int in_shutdown = 0;
static in_addr_t *allowed_clients = NULL;
+/* hash table */
+
+#define FCGI_HASH_TABLE_SIZE 128
+#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
+#define FCGI_HASH_SEG_SIZE 4096
+
+typedef struct _fcgi_hash_bucket {
+ unsigned int hash_value;
+ unsigned int var_len;
+ char *var;
+ unsigned int val_len;
+ char *val;
+ struct _fcgi_hash_bucket *next;
+ struct _fcgi_hash_bucket *list_next;
+} fcgi_hash_bucket;
+
+typedef struct _fcgi_hash_buckets {
+ unsigned int idx;
+ struct _fcgi_hash_buckets *next;
+ struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
+} fcgi_hash_buckets;
+
+typedef struct _fcgi_data_seg {
+ char *pos;
+ char *end;
+ struct _fcgi_data_seg *next;
+ char data[1];
+} fcgi_data_seg;
+
+typedef struct _fcgi_hash {
+ fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
+ fcgi_hash_bucket *list;
+ fcgi_hash_buckets *buckets;
+ fcgi_data_seg *data;
+} fcgi_hash;
+
+static void fcgi_hash_init(fcgi_hash *h)
+{
+ memset(h->hash_table, 0, sizeof(h->hash_table));
+ h->list = NULL;
+ h->buckets = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
+ h->buckets->idx = 0;
+ h->buckets->next = NULL;
+ h->data = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + FCGI_HASH_SEG_SIZE);
+ h->data->pos = h->data->data;
+ h->data->end = h->data->pos + FCGI_HASH_SEG_SIZE;
+ h->data->next = NULL;
+}
+
+static void fcgi_hash_destroy(fcgi_hash *h)
+{
+ fcgi_hash_buckets *b;
+ fcgi_data_seg *p;
+
+ b = h->buckets;
+ while (b) {
+ fcgi_hash_buckets *q = b;
+ b = b->next;
+ free(q);
+ }
+ p = h->data;
+ while (p) {
+ fcgi_data_seg *q = p;
+ p = p->next;
+ free(q);
+ }
+}
+
+static void fcgi_hash_clean(fcgi_hash *h)
+{
+ memset(h->hash_table, 0, sizeof(h->hash_table));
+ h->list = NULL;
+ /* delete all bucket blocks except the first one */
+ while (h->buckets->next) {
+ fcgi_hash_buckets *q = h->buckets;
+
+ h->buckets = h->buckets->next;
+ free(q);
+ }
+ h->buckets->idx = 0;
+ /* delete all data segments except the first one */
+ while (h->data->next) {
+ fcgi_data_seg *q = h->data;
+
+ h->data = h->data->next;
+ free(q);
+ }
+ h->data->pos = h->data->data;
+}
+
+static inline char* fcgi_hash_strndup(fcgi_hash *h, char *str, unsigned int str_len)
+{
+ char *ret;
+
+ if (UNEXPECTED(h->data->pos + str_len + 1 >= h->data->end)) {
+ unsigned int seg_size = (str_len + 1 > FCGI_HASH_SEG_SIZE) ? str_len + 1 : FCGI_HASH_SEG_SIZE;
+ fcgi_data_seg *p = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + seg_size);
+
+ p->pos = p->data;
+ p->end = p->pos + seg_size;
+ p->next = h->data;
+ h->data = p;
+ }
+ ret = h->data->pos;
+ memcpy(ret, str, str_len);
+ ret[str_len] = 0;
+ h->data->pos += str_len + 1;
+ return ret;
+}
+
+static char* fcgi_hash_set(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, char *val, unsigned int val_len)
+{
+ unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
+ fcgi_hash_bucket *p = h->hash_table[idx];
+
+ while (UNEXPECTED(p != NULL)) {
+ if (UNEXPECTED(p->hash_value == hash_value) &&
+ p->var_len == var_len &&
+ memcmp(p->var, var, var_len) == 0) {
+
+ p->val_len = val_len;
+ p->val = fcgi_hash_strndup(h, val, val_len);
+ return p->val;
+ }
+ p = p->next;
+ }
+
+ if (UNEXPECTED(h->buckets->idx >= FCGI_HASH_TABLE_SIZE)) {
+ fcgi_hash_buckets *b = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
+ b->idx = 0;
+ b->next = h->buckets;
+ h->buckets = b;
+ }
+ p = h->buckets->data + h->buckets->idx;
+ h->buckets->idx++;
+ p->next = h->hash_table[idx];
+ h->hash_table[idx] = p;
+ p->list_next = h->list;
+ h->list = p;
+ p->hash_value = hash_value;
+ p->var_len = var_len;
+ p->var = fcgi_hash_strndup(h, var, var_len);
+ p->val_len = val_len;
+ p->val = fcgi_hash_strndup(h, val, val_len);
+ return p->val;
+}
+
+static void fcgi_hash_del(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len)
+{
+ unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
+ fcgi_hash_bucket **p = &h->hash_table[idx];
+
+ while (*p != NULL) {
+ if ((*p)->hash_value == hash_value &&
+ (*p)->var_len == var_len &&
+ memcmp((*p)->var, var, var_len) == 0) {
+
+ (*p)->val = NULL; /* NULL value means deleted */
+ (*p)->val_len = 0;
+ *p = (*p)->next;
+ return;
+ }
+ p = &(*p)->next;
+ }
+}
+
+static char *fcgi_hash_get(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, unsigned int *val_len)
+{
+ unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
+ fcgi_hash_bucket *p = h->hash_table[idx];
+
+ while (p != NULL) {
+ if (p->hash_value == hash_value &&
+ p->var_len == var_len &&
+ memcmp(p->var, var, var_len) == 0) {
+ *val_len = p->val_len;
+ return p->val;
+ }
+ p = p->next;
+ }
+ return NULL;
+}
+
+static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg TSRMLS_DC)
+{
+ fcgi_hash_bucket *p = h->list;
+
+ while (p) {
+ if (EXPECTED(p->val != NULL)) {
+ func(p->var, p->var_len, p->val, p->val_len, arg TSRMLS_CC);
+ }
+ p = p->list_next;
+ }
+}
+
+struct _fcgi_request {
+ int listen_socket;
+ int tcp;
+ int fd;
+ int id;
+ int keep;
+#ifdef TCP_NODELAY
+ int nodelay;
+#endif
+ int closed;
+
+ int in_len;
+ int in_pad;
+
+ fcgi_header *out_hdr;
+ unsigned char *out_pos;
+ unsigned char out_buf[1024*8];
+ unsigned char reserved[sizeof(fcgi_end_request_rec)];
+
+ int has_env;
+ fcgi_hash env;
+};
+
#ifdef _WIN32
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
@@ -180,6 +399,11 @@ int fcgi_in_shutdown(void)
return in_shutdown;
}
+void fcgi_terminate(void)
+{
+ in_shutdown = 1;
+}
+
int fcgi_init(void)
{
if (!is_initialized) {
@@ -417,7 +641,7 @@ int fcgi_listen(const char *path, int backlog)
8192, 8192, 0, &saw);
if (namedPipe == INVALID_HANDLE_VALUE) {
return -1;
- }
+ }
listen_socket = _open_osfhandle((long)namedPipe, 0);
if (!is_initialized) {
fcgi_init();
@@ -459,35 +683,35 @@ int fcgi_listen(const char *path, int backlog)
if (!tcp) {
chmod(path, 0777);
} else {
- char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
- char *cur, *end;
- int n;
-
- if (ip) {
- ip = strdup(ip);
- cur = ip;
- n = 0;
- while (*cur) {
- if (*cur == ',') n++;
- cur++;
+ char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
+ char *cur, *end;
+ int n;
+
+ if (ip) {
+ ip = strdup(ip);
+ cur = ip;
+ n = 0;
+ while (*cur) {
+ if (*cur == ',') n++;
+ cur++;
+ }
+ allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
+ n = 0;
+ cur = ip;
+ while (cur) {
+ end = strchr(cur, ',');
+ if (end) {
+ *end = 0;
+ end++;
}
- allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
- n = 0;
- cur = ip;
- while (cur) {
- end = strchr(cur, ',');
- if (end) {
- *end = 0;
- end++;
- }
- allowed_clients[n] = inet_addr(cur);
- if (allowed_clients[n] == INADDR_NONE) {
+ allowed_clients[n] = inet_addr(cur);
+ if (allowed_clients[n] == INADDR_NONE) {
fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
- }
- n++;
- cur = end;
}
- allowed_clients[n] = INADDR_NONE;
+ n++;
+ cur = end;
+ }
+ allowed_clients[n] = INADDR_NONE;
free(ip);
}
}
@@ -507,9 +731,9 @@ int fcgi_listen(const char *path, int backlog)
return listen_socket;
}
-void fcgi_init_request(fcgi_request *req, int listen_socket)
+fcgi_request *fcgi_init_request(int listen_socket)
{
- memset(req, 0, sizeof(fcgi_request));
+ fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
req->listen_socket = listen_socket;
req->fd = -1;
req->id = -1;
@@ -523,6 +747,20 @@ void fcgi_init_request(fcgi_request *req, int listen_socket)
#ifdef _WIN32
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif
+
+#ifdef TCP_NODELAY
+ req->nodelay = 0;
+#endif
+
+ fcgi_hash_init(&req->env);
+
+ return req;
+}
+
+void fcgi_destroy_request(fcgi_request *req)
+{
+ fcgi_hash_destroy(&req->env);
+ free(req);
}
static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
@@ -603,64 +841,34 @@ static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int
static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end)
{
- char buf[128];
- char *tmp = buf;
- size_t buf_size = sizeof(buf);
unsigned int name_len, val_len;
- char *s;
- int ret = 1;
while (p < end) {
name_len = *p++;
- if (name_len >= 128) {
- if (p + 3 >= end) {
- ret = 0;
- break;
- }
+ if (UNEXPECTED(name_len >= 128)) {
+ if (UNEXPECTED(p + 3 >= end)) return 0;
name_len = ((name_len & 0x7f) << 24);
name_len |= (*p++ << 16);
name_len |= (*p++ << 8);
name_len |= *p++;
}
- if (p >= end) {
- ret = 0;
- break;
- }
+ if (UNEXPECTED(p >= end)) return 0;
val_len = *p++;
- if (val_len >= 128) {
- if (p + 3 >= end) {
- ret = 0;
- break;
- }
+ if (UNEXPECTED(val_len >= 128)) {
+ if (UNEXPECTED(p + 3 >= end)) return 0;
val_len = ((val_len & 0x7f) << 24);
val_len |= (*p++ << 16);
val_len |= (*p++ << 8);
val_len |= *p++;
}
- if (name_len + val_len > end - p) {
+ if (UNEXPECTED(name_len + val_len > (unsigned int) (end - p))) {
/* Malformated request */
- ret = 0;
- break;
- }
- if (name_len+1 >= buf_size) {
- buf_size = name_len + 64;
- tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size));
+ return 0;
}
- memcpy(tmp, p, name_len);
- tmp[name_len] = 0;
- s = estrndup((char*)p + name_len, val_len);
- zend_hash_update(req->env, tmp, name_len+1, &s, sizeof(char*), NULL);
+ fcgi_hash_set(&req->env, FCGI_HASH_FUNC(p, name_len), (char*)p, name_len, (char*)p + name_len, val_len);
p += name_len + val_len;
}
- if (tmp != buf && tmp != NULL) {
- efree(tmp);
- }
- return ret;
-}
-
-static void fcgi_free_var(char **s)
-{
- efree(*s);
+ return 1;
}
static int fcgi_read_request(fcgi_request *req)
@@ -674,8 +882,7 @@ static int fcgi_read_request(fcgi_request *req)
req->in_len = 0;
req->out_hdr = NULL;
req->out_pos = req->out_buf;
- ALLOC_HASHTABLE(req->env);
- zend_hash_init(req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 0);
+ req->has_env = 1;
if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
hdr.version < FCGI_VERSION_1) {
@@ -702,25 +909,32 @@ static int fcgi_read_request(fcgi_request *req)
req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;
if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
- char *val;
-
if (safe_read(req, buf, len+padding) != len+padding) {
return 0;
}
req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);
+#ifdef TCP_NODELAY
+ if (req->keep && req->tcp && !req->nodelay) {
+# ifdef _WIN32
+ BOOL on = 1;
+# else
+ int on = 1;
+# endif
+
+ setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
+ req->nodelay = 1;
+ }
+#endif
switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
case FCGI_RESPONDER:
- val = estrdup("RESPONDER");
- zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
+ fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1);
break;
case FCGI_AUTHORIZER:
- val = estrdup("AUTHORIZER");
- zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
+ fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1);
break;
case FCGI_FILTER:
- val = estrdup("FILTER");
- zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL);
+ fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1);
break;
default:
return 0;
@@ -759,12 +973,9 @@ static int fcgi_read_request(fcgi_request *req)
}
} else if (hdr.type == FCGI_GET_VALUES) {
unsigned char *p = buf + sizeof(fcgi_header);
- HashPosition pos;
- char * str_index;
- uint str_length;
- ulong num_index;
- int key_type;
zval ** value;
+ unsigned int zlen;
+ fcgi_hash_bucket *q;
if (safe_read(req, buf, len+padding) != len+padding) {
req->keep = 0;
@@ -776,28 +987,22 @@ static int fcgi_read_request(fcgi_request *req)
return 0;
}
- zend_hash_internal_pointer_reset_ex(req->env, &pos);
- while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
- int zlen;
- zend_hash_move_forward_ex(req->env, &pos);
- if (key_type != HASH_KEY_IS_STRING) {
- continue;
- }
- if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) {
+ q = req->env.list;
+ while (q != NULL) {
+ if (zend_hash_find(&fcgi_mgmt_vars, q->var, q->var_len, (void**) &value) != SUCCESS) {
continue;
}
- --str_length;
zlen = Z_STRLEN_PP(value);
- if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) {
+ if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) {
break;
}
- if (str_length < 0x80) {
- *p++ = str_length;
+ if (q->var_len < 0x80) {
+ *p++ = q->var_len;
} else {
- *p++ = ((str_length >> 24) & 0xff) | 0x80;
- *p++ = (str_length >> 16) & 0xff;
- *p++ = (str_length >> 8) & 0xff;
- *p++ = str_length & 0xff;
+ *p++ = ((q->var_len >> 24) & 0xff) | 0x80;
+ *p++ = (q->var_len >> 16) & 0xff;
+ *p++ = (q->var_len >> 8) & 0xff;
+ *p++ = q->var_len & 0xff;
}
if (zlen < 0x80) {
*p++ = zlen;
@@ -807,8 +1012,8 @@ static int fcgi_read_request(fcgi_request *req)
*p++ = (zlen >> 8) & 0xff;
*p++ = zlen & 0xff;
}
- memcpy(p, str_index, str_length);
- p += str_length;
+ memcpy(p, q->var, q->var_len);
+ p += q->var_len;
memcpy(p, Z_STRVAL_PP(value), zlen);
p += zlen;
}
@@ -881,10 +1086,9 @@ int fcgi_read(fcgi_request *req, char *str, int len)
static inline void fcgi_close(fcgi_request *req, int force, int destroy)
{
- if (destroy && req->env) {
- zend_hash_destroy(req->env);
- FREE_HASHTABLE(req->env);
- req->env = NULL;
+ if (destroy && req->has_env) {
+ fcgi_hash_clean(&req->env);
+ req->has_env = 0;
}
#ifdef _WIN32
@@ -904,22 +1108,27 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
DisconnectNamedPipe(pipe);
} else {
if (!force) {
- char buf[8];
+ fcgi_header buf;
shutdown(req->fd, 1);
- while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
+ /* read the last FCGI_STDIN header (it may be omitted) */
+ recv(req->fd, &buf, sizeof(buf), 0);
}
closesocket(req->fd);
}
#else
if (!force) {
- char buf[8];
+ fcgi_header buf;
shutdown(req->fd, 1);
- while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
+ /* read the last FCGI_STDIN header (it may be omitted) */
+ recv(req->fd, &buf, sizeof(buf), 0);
}
close(req->fd);
#endif
+#ifdef TCP_NODELAY
+ req->nodelay = 0;
+#endif
req->fd = -1;
}
}
@@ -970,22 +1179,33 @@ int fcgi_accept_request(fcgi_request *req)
FCGI_LOCK(req->listen_socket);
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
FCGI_UNLOCK(req->listen_socket);
- if (req->fd >= 0 && allowed_clients) {
- int n = 0;
- int allowed = 0;
-
- while (allowed_clients[n] != INADDR_NONE) {
- if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
- allowed = 1;
- break;
+ if (req->fd >= 0) {
+ if (((struct sockaddr *)&sa)->sa_family == AF_INET) {
+#ifndef _WIN32
+ req->tcp = 1;
+#endif
+ if (allowed_clients) {
+ int n = 0;
+ int allowed = 0;
+
+ while (allowed_clients[n] != INADDR_NONE) {
+ if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
+ allowed = 1;
+ break;
+ }
+ n++;
+ }
+ if (!allowed) {
+ fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
+ closesocket(req->fd);
+ req->fd = -1;
+ continue;
}
- n++;
}
- if (!allowed) {
- fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
- closesocket(req->fd);
- req->fd = -1;
- continue;
+#ifndef _WIN32
+ } else {
+ req->tcp = 0;
+#endif
}
}
}
@@ -1195,8 +1415,8 @@ int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int l
return -1;
}
pos += 0xfff8;
- }
-
+ }
+
pad = (((len - pos) + 7) & ~7) - (len - pos);
rest = pad ? 8 - pad : 0;
@@ -1236,31 +1456,44 @@ int fcgi_finish_request(fcgi_request *req, int force_close)
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len)
{
- char **val;
+ unsigned int val_len;
if (!req) return NULL;
- if (zend_hash_find(req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) {
- return *val;
- }
- return NULL;
+ return fcgi_hash_get(&req->env, FCGI_HASH_FUNC(var, var_len), (char*)var, var_len, &val_len);
+}
+
+char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value)
+{
+ unsigned int val_len;
+
+ return fcgi_hash_get(&req->env, hash_value, (char*)var, var_len, &val_len);
}
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val)
{
- if (var && req) {
- if (val == NULL) {
- zend_hash_del(req->env, var, var_len+1);
- } else {
- char **ret;
+ if (!req) return NULL;
+ if (val == NULL) {
+ fcgi_hash_del(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len);
+ return NULL;
+ } else {
+ return fcgi_hash_set(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len, val, strlen(val));
+ }
+}
- val = estrdup(val);
- if (zend_hash_update(req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) {
- return *ret;
- }
- }
+char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val)
+{
+ if (val == NULL) {
+ fcgi_hash_del(&req->env, hash_value, var, var_len);
+ return NULL;
+ } else {
+ return fcgi_hash_set(&req->env, hash_value, var, var_len, val, strlen(val));
}
- return NULL;
+}
+
+void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array TSRMLS_DC)
+{
+ fcgi_hash_apply(&req->env, func, array TSRMLS_CC);
}
#ifdef _WIN32
@@ -1282,7 +1515,7 @@ void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, s
Z_TYPE_P(zvalue) = IS_STRING;
Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1);
Z_STRLEN_P(zvalue) = value_len;
- zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL);
+ zend_hash_add(&fcgi_mgmt_vars, name, name_len, &zvalue, sizeof(zvalue), NULL);
}
void fcgi_free_mgmt_var_cb(void * ptr)
diff --git a/sapi/cgi/fastcgi.h b/sapi/cgi/fastcgi.h
index 3fcc0da084..18a63c7c1f 100644
--- a/sapi/cgi/fastcgi.h
+++ b/sapi/cgi/fastcgi.h
@@ -26,6 +26,23 @@
#define FCGI_KEEP_CONN 1
+/* this is near the perfect hash function for most useful FastCGI variables
+ * which combines efficiency and minimal hash collisions
+ */
+
+#define FCGI_HASH_FUNC(var, var_len) \
+ (UNEXPECTED(var_len < 3) ? var_len : \
+ (((unsigned int)var[3]) << 2) + \
+ (((unsigned int)var[var_len-2]) << 4) + \
+ (((unsigned int)var[var_len-1]) << 2) + \
+ var_len)
+
+#define FCGI_GETENV(request, name) \
+ fcgi_quick_getenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1))
+
+#define FCGI_PUTENV(request, name, value) \
+ fcgi_quick_putenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1), value)
+
typedef enum _fcgi_role {
FCGI_RESPONDER = 1,
FCGI_AUTHORIZER = 2,
@@ -91,38 +108,26 @@ typedef struct _fcgi_end_request_rec {
/* FastCGI client API */
-typedef struct _fcgi_request {
- int listen_socket;
-#ifdef _WIN32
- int tcp;
-#endif
- int fd;
- int id;
- int keep;
- int closed;
-
- int in_len;
- int in_pad;
-
- fcgi_header *out_hdr;
- unsigned char *out_pos;
- unsigned char out_buf[1024*8];
- unsigned char reserved[sizeof(fcgi_end_request_rec)];
+typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC);
- HashTable *env;
-} fcgi_request;
+typedef struct _fcgi_request fcgi_request;
int fcgi_init(void);
void fcgi_shutdown(void);
int fcgi_is_fastcgi(void);
int fcgi_in_shutdown(void);
+void fcgi_terminate(void);
int fcgi_listen(const char *path, int backlog);
-void fcgi_init_request(fcgi_request *req, int listen_socket);
+fcgi_request* fcgi_init_request(int listen_socket);
+void fcgi_destroy_request(fcgi_request *req);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
+char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value);
+char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val);
+void fcgi_loadenv(fcgi_request *req, fcgi_apply_func load_func, zval *array TSRMLS_DC);
int fcgi_read(fcgi_request *req, char *str, int len);
diff --git a/sapi/cgi/tests/apache_request_headers.phpt b/sapi/cgi/tests/apache_request_headers.phpt
new file mode 100644
index 0000000000..fd36e3024f
--- /dev/null
+++ b/sapi/cgi/tests/apache_request_headers.phpt
@@ -0,0 +1,51 @@
+--TEST--
+apache_request_headers() stack overflow.
+--INI--
+default_charset="UTF-8"
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "include.inc";
+
+$php = get_cgi_path();
+reset_env_vars();
+
+$file = dirname(__FILE__)."/012.test.php";
+
+file_put_contents($file, '<?php print_r(apache_request_headers()); ?>');
+
+passthru("$php -n $file");
+
+$names = array('HTTP_X_TEST', 'HTTP_X__TEST', 'HTTP_X_');
+foreach ($names as $name) {
+ putenv($name."=".str_repeat("A", 256));
+ passthru("$php -n -q $file");
+ putenv($name);
+}
+unlink($file);
+
+echo "Done\n";
+?>
+--EXPECTF--
+X-Powered-By: PHP/%s
+Content-type: text/%s
+
+Array
+(
+)
+Array
+(
+ [X-Test] => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+)
+Array
+(
+ [X-_test] => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+)
+Array
+(
+ [X-] => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+)
+Done
diff --git a/sapi/cli/CREDITS b/sapi/cli/CREDITS
index 5f3b0fbe39..463d20a0f0 100644
--- a/sapi/cli/CREDITS
+++ b/sapi/cli/CREDITS
@@ -1,2 +1,2 @@
CLI
-Edin Kadribasic, Marcus Boerger, Johannes Schlueter
+Edin Kadribasic, Marcus Boerger, Johannes Schlueter, Moriyoshi Koizumi, Xinchen Hui
diff --git a/sapi/cli/Makefile.frag b/sapi/cli/Makefile.frag
index 6903ca1fc0..8f4f400401 100644
--- a/sapi/cli/Makefile.frag
+++ b/sapi/cli/Makefile.frag
@@ -1,11 +1,13 @@
cli: $(SAPI_CLI_PATH)
-$(SAPI_CLI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_CLI_OBJS)
+$(SAPI_CLI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CLI_OBJS)
$(BUILD_CLI)
install-cli: $(SAPI_CLI_PATH)
@echo "Installing PHP CLI binary: $(INSTALL_ROOT)$(bindir)/"
- @$(INSTALL_CLI)
+ @$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
+ @$(INSTALL) -m 0755 $(SAPI_CLI_PATH) $(INSTALL_ROOT)$(bindir)/$(program_prefix)php$(program_suffix)$(EXEEXT)
@echo "Installing PHP CLI man page: $(INSTALL_ROOT)$(mandir)/man1/"
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
- @$(INSTALL_DATA) $(builddir)/php.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)php$(program_suffix).1
+ @$(INSTALL_DATA) sapi/cli/php.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)php$(program_suffix).1
+
diff --git a/sapi/cli/README b/sapi/cli/README
index 9e519e9bd0..8720250f6a 100644
--- a/sapi/cli/README
+++ b/sapi/cli/README
@@ -11,8 +11,8 @@ The main differences between the two:
* It does not change the working directory to that of the script.
(-C switch kept for compatibility)
* Plain text error message
-* $argc and $argv registered irrespective of register_globals
- and register_argc_argv php.ini settings.
+* $argc and $argv registered irrespective of the register_argc_argv
+ php.ini setting.
* implicit_flush always on
* -r option which allows execution of PHP code directly from
the command line (e.g. php -r 'echo md5("test");' )
diff --git a/sapi/cli/cli.h b/sapi/cli/cli.h
new file mode 100644
index 0000000000..3e9ca43084
--- /dev/null
+++ b/sapi/cli/cli.h
@@ -0,0 +1,52 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Johannes Schlueter <johannes@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef CLI_H
+#define CLI_H
+
+#ifdef PHP_WIN32
+# define PHP_CLI_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define PHP_CLI_API __attribute__ ((visibility("default")))
+#else
+# define PHP_CLI_API
+#endif
+
+
+extern PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC);
+
+typedef struct {
+ size_t (*cli_shell_write)(const char *str, uint str_length TSRMLS_DC);
+ int (*cli_shell_ub_write)(const char *str, uint str_length TSRMLS_DC);
+ int (*cli_shell_run)(TSRMLS_D);
+} cli_shell_callbacks_t;
+
+extern PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks();
+
+#endif /* CLI_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/sapi/cli/config.m4 b/sapi/cli/config.m4
index 1a6fdbf645..cdfa1f7daf 100644
--- a/sapi/cli/config.m4
+++ b/sapi/cli/config.m4
@@ -8,32 +8,43 @@ PHP_ARG_ENABLE(cli,,
AC_MSG_CHECKING(for CLI build)
if test "$PHP_CLI" != "no"; then
- PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cli/Makefile.frag,$abs_srcdir/sapi/cli,sapi/cli)
+ PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cli/Makefile.frag)
+
+ dnl Set filename
SAPI_CLI_PATH=sapi/cli/php
- PHP_SUBST(SAPI_CLI_PATH)
+
+ dnl Select SAPI
+ PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c,, '$(SAPI_CLI_PATH)')
case $host_alias in
*aix*)
- if test "$php_build_target" = "shared"; then
- BUILD_CLI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
+ if test "$php_sapi_module" = "shared"; then
+ BUILD_CLI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
else
- BUILD_CLI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
+ BUILD_CLI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
fi
;;
*darwin*)
- BUILD_CLI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_CLI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
+ BUILD_CLI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CLI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
;;
*netware*)
- BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp5lib -o \$(SAPI_CLI_PATH)"
+ BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp5lib -o \$(SAPI_CLI_PATH)"
;;
*)
- BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
+ BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
;;
esac
- INSTALL_CLI="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(bindir); \$(INSTALL) -m 0755 \$(SAPI_CLI_PATH) \$(INSTALL_ROOT)\$(bindir)/\$(program_prefix)php\$(program_suffix)\$(EXEEXT)"
+ dnl Set executable for tests
+ PHP_EXECUTABLE="\$(top_builddir)/\$(SAPI_CLI_PATH)"
+ PHP_SUBST(PHP_EXECUTABLE)
+
+ dnl Expose to Makefile
+ PHP_SUBST(SAPI_CLI_PATH)
PHP_SUBST(BUILD_CLI)
- PHP_SUBST(INSTALL_CLI)
+
PHP_OUTPUT(sapi/cli/php.1)
+
+ PHP_INSTALL_HEADERS([sapi/cli/cli.h])
fi
AC_MSG_RESULT($PHP_CLI)
diff --git a/sapi/cli/config.w32 b/sapi/cli/config.w32
index 923aa399e5..4d0dad58e8 100644
--- a/sapi/cli/config.w32
+++ b/sapi/cli/config.w32
@@ -6,7 +6,8 @@ ARG_ENABLE('crt-debug', 'Enable CRT memory dumps for debugging sent to STDERR',
ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no');
if (PHP_CLI == "yes") {
- SAPI('cli', 'php_cli.c php_cli_readline.c', 'php.exe');
+ SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c', 'php.exe');
+ ADD_FLAG("LIBS_CLI", "ws2_32.lib");
if (PHP_CRT_DEBUG == "yes") {
ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP");
}
@@ -14,7 +15,7 @@ if (PHP_CLI == "yes") {
}
if (PHP_CLI_WIN32 == "yes") {
- SAPI('cli_win32', 'cli_win32.c php_cli_readline.c', 'php-win.exe');
+ SAPI('cli_win32', 'cli_win32.c', 'php-win.exe');
ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:8388608");
}
diff --git a/sapi/cli/php.1.in b/sapi/cli/php.1.in
index c1fcb27e51..186b128f89 100644
--- a/sapi/cli/php.1.in
+++ b/sapi/cli/php.1.in
@@ -323,6 +323,16 @@ Shows information about extension
.B name
.TP
.PD 0
+.B \-\-rzendextension
+.IR name
+.TP
+.PD 1
+.B \-\-rz
+.IR name
+Shows information about Zend extension
+.B name
+.TP
+.PD 0
.B \-\-rextinfo
.IR name
.TP
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index d63ee1ae84..f9bf3ee60b 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -59,6 +59,7 @@
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
+#include "cli.h"
#ifdef PHP_WIN32
#include <io.h>
#include <fcntl.h>
@@ -73,16 +74,6 @@
#include <unixlib/local.h>
#endif
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
-#if HAVE_LIBEDIT
-#include <editline/readline.h>
-#else
-#include <readline/readline.h>
-#include <readline/history.h>
-#endif
-#include "php_cli_readline.h"
-#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
-
#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
@@ -91,6 +82,10 @@
#include "php_getopt.h"
+#ifndef PHP_CLI_WIN32_NO_CONSOLE
+#include "php_cli_server.h"
+#endif
+
#ifndef PHP_WIN32
# define php_select(m, r, w, e, t) select(m, r, w, e, t)
#else
@@ -116,7 +111,14 @@ PHPAPI extern char *php_ini_scanned_files;
#define PHP_MODE_REFLECTION_CLASS 9
#define PHP_MODE_REFLECTION_EXTENSION 10
#define PHP_MODE_REFLECTION_EXT_INFO 11
-#define PHP_MODE_SHOW_INI_CONFIG 12
+#define PHP_MODE_REFLECTION_ZEND_EXTENSION 12
+#define PHP_MODE_SHOW_INI_CONFIG 13
+
+cli_shell_callbacks_t cli_shell_callbacks = { NULL, NULL, NULL };
+PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks()
+{
+ return &cli_shell_callbacks;
+}
const char HARDCODED_INI[] =
"html_errors=0\n"
@@ -126,13 +128,8 @@ const char HARDCODED_INI[] =
"max_execution_time=0\n"
"max_input_time=-1\n\0";
-static char *php_optarg = NULL;
-static int php_optind = 1;
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
-static char php_last_char = '\0';
-#endif
-static const opt_struct OPTIONS[] = {
+const opt_struct OPTIONS[] = {
{'a', 0, "interactive"},
{'B', 1, "process-begin"},
{'C', 0, "no-chdir"}, /* for compatibility with CGI (do not chdir to script directory) */
@@ -153,6 +150,8 @@ static const opt_struct OPTIONS[] = {
{'r', 1, "run"},
{'s', 0, "syntax-highlight"},
{'s', 0, "syntax-highlighting"},
+ {'S', 1, "server"},
+ {'t', 1, "docroot"},
{'w', 0, "strip"},
{'?', 0, "usage"},/* help alias (both '?' and 'usage') */
{'v', 0, "version"},
@@ -163,9 +162,11 @@ static const opt_struct OPTIONS[] = {
{11, 1, "rclass"},
{12, 1, "re"},
{12, 1, "rextension"},
- {13, 1, "ri"},
- {13, 1, "rextinfo"},
- {14, 0, "ini"},
+ {13, 1, "rz"},
+ {13, 1, "rzendextension"},
+ {14, 1, "ri"},
+ {14, 1, "rextinfo"},
+ {15, 0, "ini"},
{'-', 0, NULL} /* end of args */
};
@@ -248,11 +249,23 @@ static inline int sapi_cli_select(int fd TSRMLS_DC)
return ret != -1;
}
-static inline size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
{
#ifdef PHP_WRITE_STDOUT
long ret;
+#else
+ size_t ret;
+#endif
+
+ if (cli_shell_callbacks.cli_shell_write) {
+ size_t shell_wrote;
+ shell_wrote = cli_shell_callbacks.cli_shell_write(str, str_length TSRMLS_CC);
+ if (shell_wrote > -1) {
+ return shell_wrote;
+ }
+ }
+#ifdef PHP_WRITE_STDOUT
do {
ret = write(STDOUT_FILENO, str, str_length);
} while (ret <= 0 && errno == EAGAIN && sapi_cli_select(STDOUT_FILENO TSRMLS_CC));
@@ -263,8 +276,6 @@ static inline size_t sapi_cli_single_write(const char *str, uint str_length TSRM
return ret;
#else
- size_t ret;
-
ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
return ret;
#endif
@@ -277,12 +288,17 @@ static int sapi_cli_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{
uint remaining = str_length;
size_t ret;
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
if (!str_length) {
return 0;
}
- php_last_char = str[str_length-1];
-#endif
+
+ if (cli_shell_callbacks.cli_shell_ub_write) {
+ int ub_wrote;
+ ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length TSRMLS_CC);
+ if (ub_wrote > -1) {
+ return ub_wrote;
+ }
+ }
while (remaining > 0)
{
@@ -351,7 +367,7 @@ static void sapi_cli_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{
}
/* }}} */
-static void sapi_cli_log_message(char *message) /* {{{ */
+static void sapi_cli_log_message(char *message TSRMLS_DC) /* {{{ */
{
fprintf(stderr, "%s\n", message);
}
@@ -449,7 +465,7 @@ static sapi_module_struct cli_sapi_module = {
sapi_cli_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
-
+
STANDARD_SAPI_MODULE_PROPERTIES
};
/* }}} */
@@ -478,13 +494,13 @@ static void php_cli_usage(char *argv0)
prog = "php";
}
- php_printf( "Usage: %s [options] [-f] <file> [--] [args...]\n"
- " %s [options] -r <code> [--] [args...]\n"
- " %s [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]\n"
- " %s [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]\n"
- " %s [options] -- [args...]\n"
- " %s [options] -a\n"
- "\n"
+ printf( "Usage: %s [options] [-f] <file> [--] [args...]\n"
+ " %s [options] -r <code> [--] [args...]\n"
+ " %s [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]\n"
+ " %s [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]\n"
+ " %s [options] -- [args...]\n"
+ " %s [options] -a\n"
+ "\n"
#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
" -a Run as interactive shell\n"
#else
@@ -505,6 +521,8 @@ static void php_cli_usage(char *argv0)
" -F <file> Parse and execute <file> for every input line\n"
" -E <end_code> Run PHP <end_code> after processing all input lines\n"
" -H Hide any passed arguments from external tools.\n"
+ " -S <addr>:<port> Run with built-in web server.\n"
+ " -t <docroot> Specify document root <docroot> for built-in web server.\n"
" -s Output HTML syntax highlighted source.\n"
" -v Version number\n"
" -w Output source with stripped comments and whitespace.\n"
@@ -518,6 +536,7 @@ static void php_cli_usage(char *argv0)
" --rf <name> Show information about function <name>.\n"
" --rc <name> Show information about class <name>.\n"
" --re <name> Show information about extension <name>.\n"
+ " --rz <name> Show information about Zend extension <name>.\n"
" --ri <name> Show configuration for extension <name>.\n"
"\n"
, prog, prog, prog, prog, prog, prog);
@@ -631,203 +650,45 @@ static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file,
}
/* }}} */
-/* {{{ main
- */
-#ifdef PHP_CLI_WIN32_NO_CONSOLE
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
-#else
-int main(int argc, char *argv[])
-#endif
+static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */
{
- volatile int exit_status = SUCCESS;
int c;
zend_file_handle file_handle;
-/* temporary locals */
- int behavior=PHP_MODE_STANDARD;
+ int behavior = PHP_MODE_STANDARD;
char *reflection_what = NULL;
- int orig_optind=php_optind;
- char *orig_optarg=php_optarg;
+ volatile int request_started = 0;
+ volatile int exit_status = 0;
+ char *php_optarg = NULL, *orig_optarg = NULL;
+ int php_optind = 1, orig_optind = 1;
+ char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL;
char *arg_free=NULL, **arg_excp=&arg_free;
char *script_file=NULL, *translated_path = NULL;
int interactive=0;
- volatile int module_started = 0;
- volatile int request_started = 0;
int lineno = 0;
- char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL;
const char *param_error=NULL;
int hide_argv = 0;
-/* end of temporary locals */
-#ifdef ZTS
- void ***tsrm_ls;
-#endif
-#ifdef PHP_CLI_WIN32_NO_CONSOLE
- int argc = __argc;
- char **argv = __argv;
-#endif
- int ini_entries_len = 0;
-
-#if defined(PHP_WIN32) && defined(_DEBUG) && defined(PHP_WIN32_DEBUG_HEAP)
- {
- int tmp_flag;
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- tmp_flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
- tmp_flag |= _CRTDBG_DELAY_FREE_MEM_DF;
- tmp_flag |= _CRTDBG_LEAK_CHECK_DF;
-
- _CrtSetDbgFlag(tmp_flag);
- }
-#endif
-
-#ifdef HAVE_SIGNAL_H
-#if defined(SIGPIPE) && defined(SIG_IGN)
- signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
- that sockets created via fsockopen()
- don't kill PHP if the remote site
- closes it. in apache|apxs mode apache
- does that for us! thies@thieso.net
- 20000419 */
-#endif
-#endif
-
-
-#ifdef ZTS
- tsrm_startup(1, 1, 0, NULL);
- tsrm_ls = ts_resource(0);
-#endif
-
- cli_sapi_module.ini_defaults = sapi_cli_ini_defaults;
- cli_sapi_module.php_ini_path_override = NULL;
- cli_sapi_module.phpinfo_as_text = 1;
- sapi_startup(&cli_sapi_module);
-#ifdef PHP_WIN32
- _fmode = _O_BINARY; /*sets default for file streams to binary */
- setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
- setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
- setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
-#endif
-
- ini_entries_len = sizeof(HARDCODED_INI)-2;
- cli_sapi_module.ini_entries = malloc(sizeof(HARDCODED_INI));
- memcpy(cli_sapi_module.ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI));
-
- while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2))!=-1) {
- switch (c) {
- case 'c':
- if (cli_sapi_module.php_ini_path_override) {
- free(cli_sapi_module.php_ini_path_override);
- }
- cli_sapi_module.php_ini_path_override = strdup(php_optarg);
- break;
- case 'n':
- cli_sapi_module.php_ini_ignore = 1;
- break;
- case 'd': {
- /* define ini entries on command line */
- int len = strlen(php_optarg);
- char *val;
-
- if ((val = strchr(php_optarg, '='))) {
- val++;
- if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
- cli_sapi_module.ini_entries = realloc(cli_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
- memcpy(cli_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
- ini_entries_len += (val - php_optarg);
- memcpy(cli_sapi_module.ini_entries + ini_entries_len, "\"", 1);
- ini_entries_len++;
- memcpy(cli_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg));
- ini_entries_len += len - (val - php_optarg);
- memcpy(cli_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
- ini_entries_len += sizeof("\n\0\"") - 2;
- } else {
- cli_sapi_module.ini_entries = realloc(cli_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0"));
- memcpy(cli_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
- memcpy(cli_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
- ini_entries_len += len + sizeof("\n\0") - 2;
- }
- } else {
- cli_sapi_module.ini_entries = realloc(cli_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
- memcpy(cli_sapi_module.ini_entries + ini_entries_len, php_optarg, len);
- memcpy(cli_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
- ini_entries_len += len + sizeof("=1\n\0") - 2;
- }
- break;
- }
- }
- }
- php_optind = orig_optind;
- php_optarg = orig_optarg;
-
- cli_sapi_module.executable_location = argv[0];
- cli_sapi_module.additional_functions = additional_functions;
-
- /* startup after we get the above ini override se we get things right */
- if (cli_sapi_module.startup(&cli_sapi_module)==FAILURE) {
- /* there is no way to see if we must call zend_ini_deactivate()
- * since we cannot check if EG(ini_directives) has been initialised
- * because the executor's constructor does not set initialize it.
- * Apart from that there seems no need for zend_ini_deactivate() yet.
- * So we goto out_err.*/
- exit_status = 1;
- goto out_err;
- }
- module_started = 1;
-
- zend_first_try {
+ zend_try {
+
CG(in_compilation) = 0; /* not initialized but needed for several options */
EG(uninitialized_zval_ptr) = NULL;
while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
switch (c) {
- case 'h': /* help & quit */
- case '?':
- if (php_request_startup(TSRMLS_C)==FAILURE) {
- goto err;
- }
- request_started = 1;
- php_cli_usage(argv[0]);
- php_end_ob_buffers(1 TSRMLS_CC);
- exit_status = (c == '?' && argc > 1 && !strchr(argv[1], c));
- goto out;
-
case 'i': /* php info & quit */
if (php_request_startup(TSRMLS_C)==FAILURE) {
goto err;
}
request_started = 1;
php_print_info(0xFFFFFFFF TSRMLS_CC);
- php_end_ob_buffers(1 TSRMLS_CC);
- exit_status=0;
- goto out;
-
- case 'm': /* list compiled in modules */
- if (php_request_startup(TSRMLS_C)==FAILURE) {
- goto err;
- }
- request_started = 1;
- php_printf("[PHP Modules]\n");
- print_modules(TSRMLS_C);
- php_printf("\n[Zend Modules]\n");
- print_extensions(TSRMLS_C);
- php_printf("\n");
- php_end_ob_buffers(1 TSRMLS_CC);
- exit_status=0;
+ php_output_end_all(TSRMLS_C);
+ exit_status = (c == '?' && argc > 1 && !strchr(argv[1], c));
goto out;
case 'v': /* show php version & quit */
- if (php_request_startup(TSRMLS_C) == FAILURE) {
- goto err;
- }
-
- request_started = 1;
php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2012 The PHP Group\n%s",
- PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
+ PHP_VERSION, cli_sapi_module.name, __DATE__, __TIME__,
#if ZEND_DEBUG && defined(HAVE_GCOV)
"(DEBUG GCOV)",
#elif ZEND_DEBUG
@@ -839,7 +700,20 @@ int main(int argc, char *argv[])
#endif
get_zend_version()
);
- php_end_ob_buffers(1 TSRMLS_CC);
+ sapi_deactivate(TSRMLS_C);
+ goto out;
+
+ case 'm': /* list compiled in modules */
+ if (php_request_startup(TSRMLS_C)==FAILURE) {
+ goto err;
+ }
+ request_started = 1;
+ php_printf("[PHP Modules]\n");
+ print_modules(TSRMLS_C);
+ php_printf("\n[Zend Modules]\n");
+ print_extensions(TSRMLS_C);
+ php_printf("\n");
+ php_output_end_all(TSRMLS_C);
exit_status=0;
goto out;
@@ -871,10 +745,6 @@ int main(int argc, char *argv[])
/* This is default so NOP */
break;
- case 'e': /* enable extended info output */
- CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
- break;
-
case 'F':
if (behavior == PHP_MODE_PROCESS_STDIN) {
if (exec_run || script_file) {
@@ -1012,10 +882,14 @@ int main(int argc, char *argv[])
reflection_what = php_optarg;
break;
case 13:
- behavior=PHP_MODE_REFLECTION_EXT_INFO;
+ behavior=PHP_MODE_REFLECTION_ZEND_EXTENSION;
reflection_what = php_optarg;
break;
case 14:
+ behavior=PHP_MODE_REFLECTION_EXT_INFO;
+ reflection_what = php_optarg;
+ break;
+ case 15:
behavior = PHP_MODE_SHOW_INI_CONFIG;
break;
default:
@@ -1071,15 +945,15 @@ int main(int argc, char *argv[])
file_handle.type = ZEND_HANDLE_FP;
file_handle.opened_path = NULL;
file_handle.free_filename = 0;
- php_self = file_handle.filename;
+ php_self = (char*)file_handle.filename;
/* before registering argv to module exchange the *new* argv[0] */
/* we can achieve this without allocating more memory */
SG(request_info).argc=argc-php_optind+1;
arg_excp = argv+php_optind-1;
arg_free = argv[php_optind-1];
- SG(request_info).path_translated = translated_path? translated_path : file_handle.filename;
- argv[php_optind-1] = file_handle.filename;
+ SG(request_info).path_translated = translated_path? translated_path: (char*)file_handle.filename;
+ argv[php_optind-1] = (char*)file_handle.filename;
SG(request_info).argv=argv+php_optind-1;
if (php_request_startup(TSRMLS_C)==FAILURE) {
@@ -1108,86 +982,12 @@ int main(int argc, char *argv[])
cli_register_file_handles(TSRMLS_C);
}
-#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
- if (interactive) {
- char *line;
- size_t size = 4096, pos = 0, len;
- char *code = emalloc(size);
- char *prompt = "php > ";
- char *history_file;
-
- if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
- zend_file_handle *prepend_file_p;
- zend_file_handle prepend_file = {0};
-
- prepend_file.filename = PG(auto_prepend_file);
- prepend_file.opened_path = NULL;
- prepend_file.free_filename = 0;
- prepend_file.type = ZEND_HANDLE_FILENAME;
- prepend_file_p = &prepend_file;
-
- zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, NULL, 1, prepend_file_p);
- }
-
- history_file = tilde_expand("~/.php_history");
- rl_attempted_completion_function = cli_code_completion;
- rl_special_prefixes = "$";
- read_history(history_file);
-
- EG(exit_status) = 0;
- while ((line = readline(prompt)) != NULL) {
- if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
- free(line);
- break;
- }
-
- if (!pos && !*line) {
- free(line);
- continue;
- }
-
- len = strlen(line);
- if (pos + len + 2 > size) {
- size = pos + len + 2;
- code = erealloc(code, size);
- }
- memcpy(&code[pos], line, len);
- pos += len;
- code[pos] = '\n';
- code[++pos] = '\0';
-
- if (*line) {
- add_history(line);
- }
-
- free(line);
-
- if (!cli_is_valid_code(code, pos, &prompt TSRMLS_CC)) {
- continue;
- }
-
- zend_eval_stringl(code, pos, NULL, "php shell code" TSRMLS_CC);
- pos = 0;
-
- if (php_last_char != '\0' && php_last_char != '\n') {
- sapi_cli_single_write("\n", 1 TSRMLS_CC);
- }
-
- if (EG(exception)) {
- zend_exception_error(EG(exception), E_WARNING TSRMLS_CC);
- }
-
- php_last_char = '\0';
- }
- write_history(history_file);
- free(history_file);
- efree(code);
+ if (interactive && cli_shell_callbacks.cli_shell_run) {
+ exit_status = cli_shell_callbacks.cli_shell_run(TSRMLS_C);
+ } else {
+ php_execute_script(&file_handle TSRMLS_CC);
exit_status = EG(exit_status);
- break;
}
-#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
- php_execute_script(&file_handle TSRMLS_CC);
- exit_status = EG(exit_status);
break;
case PHP_MODE_LINT:
exit_status = php_lint_script(&file_handle TSRMLS_CC);
@@ -1237,7 +1037,7 @@ int main(int argc, char *argv[])
zval *argn, *argi;
cli_register_file_handles(TSRMLS_C);
-
+
if (exec_begin && zend_eval_string_ex(exec_begin, NULL, "Command line begin code", 1 TSRMLS_CC) == FAILURE) {
exit_status=254;
}
@@ -1284,6 +1084,7 @@ int main(int argc, char *argv[])
case PHP_MODE_REFLECTION_FUNCTION:
case PHP_MODE_REFLECTION_CLASS:
case PHP_MODE_REFLECTION_EXTENSION:
+ case PHP_MODE_REFLECTION_ZEND_EXTENSION:
{
zend_class_entry *pce = NULL;
zval *arg, *ref;
@@ -1305,6 +1106,9 @@ int main(int argc, char *argv[])
case PHP_MODE_REFLECTION_EXTENSION:
pce = reflection_extension_ptr;
break;
+ case PHP_MODE_REFLECTION_ZEND_EXTENSION:
+ pce = reflection_zend_extension_ptr;
+ break;
}
MAKE_STD_ZVAL(arg);
@@ -1355,12 +1159,11 @@ int main(int argc, char *argv[])
{
zend_printf("Configuration File (php.ini) Path: %s\n", PHP_CONFIG_FILE_PATH);
zend_printf("Loaded Configuration File: %s\n", php_ini_opened_path ? php_ini_opened_path : "(none)");
- zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path ? php_ini_scanned_path : "(none)");
+ zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path ? php_ini_scanned_path : "(none)");
zend_printf("Additional .ini files parsed: %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)");
break;
}
}
-
} zend_end_try();
out:
@@ -1373,29 +1176,216 @@ out:
if (exit_status == 0) {
exit_status = EG(exit_status);
}
-out_err:
- if (cli_sapi_module.php_ini_path_override) {
- free(cli_sapi_module.php_ini_path_override);
+ return exit_status;
+err:
+ sapi_deactivate(TSRMLS_C);
+ zend_ini_deactivate(TSRMLS_C);
+ exit_status = 1;
+ goto out;
+}
+/* }}} */
+
+/* {{{ main
+ */
+#ifdef PHP_CLI_WIN32_NO_CONSOLE
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+#else
+int main(int argc, char *argv[])
+#endif
+{
+#ifdef ZTS
+ void ***tsrm_ls;
+#endif
+#ifdef PHP_CLI_WIN32_NO_CONSOLE
+ int argc = __argc;
+ char **argv = __argv;
+#endif
+ int c;
+ int exit_status = SUCCESS;
+ int module_started = 0, sapi_started = 0;
+ char *php_optarg = NULL;
+ int php_optind = 1, use_extended_info = 0;
+ char *ini_path_override = NULL;
+ char *ini_entries = NULL;
+ int ini_entries_len = 0;
+ int ini_ignore = 0;
+ sapi_module_struct *sapi_module = &cli_sapi_module;
+
+ cli_sapi_module.additional_functions = additional_functions;
+
+#if defined(PHP_WIN32) && defined(_DEBUG) && defined(PHP_WIN32_DEBUG_HEAP)
+ {
+ int tmp_flag;
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+ tmp_flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+ tmp_flag |= _CRTDBG_DELAY_FREE_MEM_DF;
+ tmp_flag |= _CRTDBG_LEAK_CHECK_DF;
+
+ _CrtSetDbgFlag(tmp_flag);
+ }
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#if defined(SIGPIPE) && defined(SIG_IGN)
+ signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
+ that sockets created via fsockopen()
+ don't kill PHP if the remote site
+ closes it. in apache|apxs mode apache
+ does that for us! thies@thieso.net
+ 20000419 */
+#endif
+#endif
+
+
+#ifdef ZTS
+ tsrm_startup(1, 1, 0, NULL);
+ tsrm_ls = ts_resource(0);
+#endif
+
+#ifdef PHP_WIN32
+ _fmode = _O_BINARY; /*sets default for file streams to binary */
+ setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
+ setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
+ setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
+#endif
+
+ while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2))!=-1) {
+ switch (c) {
+ case 'c':
+ if (ini_path_override) {
+ free(ini_path_override);
+ }
+ ini_path_override = strdup(php_optarg);
+ break;
+ case 'n':
+ ini_ignore = 1;
+ break;
+ case 'd': {
+ /* define ini entries on command line */
+ int len = strlen(php_optarg);
+ char *val;
+
+ if ((val = strchr(php_optarg, '='))) {
+ val++;
+ if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') {
+ ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0"));
+ memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg));
+ ini_entries_len += (val - php_optarg);
+ memcpy(ini_entries + ini_entries_len, "\"", 1);
+ ini_entries_len++;
+ memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg));
+ ini_entries_len += len - (val - php_optarg);
+ memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0"));
+ ini_entries_len += sizeof("\n\0\"") - 2;
+ } else {
+ ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\n\0"));
+ memcpy(ini_entries + ini_entries_len, php_optarg, len);
+ memcpy(ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0"));
+ ini_entries_len += len + sizeof("\n\0") - 2;
+ }
+ } else {
+ ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("=1\n\0"));
+ memcpy(ini_entries + ini_entries_len, php_optarg, len);
+ memcpy(ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0"));
+ ini_entries_len += len + sizeof("=1\n\0") - 2;
+ }
+ break;
+ }
+#ifndef PHP_CLI_WIN32_NO_CONSOLE
+ case 'S':
+ sapi_module = &cli_server_sapi_module;
+ break;
+#endif
+ case 'h': /* help & quit */
+ case '?':
+ php_cli_usage(argv[0]);
+ goto out;
+ case 'i': case 'v': case 'm':
+ sapi_module = &cli_sapi_module;
+ goto exit_loop;
+ case 'e': /* enable extended info output */
+ use_extended_info = 1;
+ break;
+ }
+ }
+exit_loop:
+
+ sapi_module->ini_defaults = sapi_cli_ini_defaults;
+ sapi_module->php_ini_path_override = ini_path_override;
+ sapi_module->phpinfo_as_text = 1;
+ sapi_module->php_ini_ignore_cwd = 1;
+ sapi_startup(sapi_module);
+ sapi_started = 1;
+
+ sapi_module->php_ini_ignore = ini_ignore;
+
+ sapi_module->executable_location = argv[0];
+
+ if (sapi_module == &cli_sapi_module) {
+ if (ini_entries) {
+ ini_entries = realloc(ini_entries, ini_entries_len + sizeof(HARDCODED_INI));
+ memmove(ini_entries + sizeof(HARDCODED_INI) - 2, ini_entries, ini_entries_len + 1);
+ memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI) - 2);
+ } else {
+ ini_entries = malloc(sizeof(HARDCODED_INI));
+ memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI));
+ }
+ ini_entries_len += sizeof(HARDCODED_INI) - 2;
+ }
+
+ sapi_module->ini_entries = ini_entries;
+
+ /* startup after we get the above ini override se we get things right */
+ if (sapi_module->startup(sapi_module) == FAILURE) {
+ /* there is no way to see if we must call zend_ini_deactivate()
+ * since we cannot check if EG(ini_directives) has been initialised
+ * because the executor's constructor does not set initialize it.
+ * Apart from that there seems no need for zend_ini_deactivate() yet.
+ * So we goto out_err.*/
+ exit_status = 1;
+ goto out;
}
- if (cli_sapi_module.ini_entries) {
- free(cli_sapi_module.ini_entries);
+ module_started = 1;
+
+ /* -e option */
+ if (use_extended_info) {
+ CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
}
+ zend_first_try {
+#ifndef PHP_CLI_WIN32_NO_CONSOLE
+ if (sapi_module == &cli_sapi_module) {
+#endif
+ exit_status = do_cli(argc, argv TSRMLS_CC);
+#ifndef PHP_CLI_WIN32_NO_CONSOLE
+ } else {
+ exit_status = do_cli_server(argc, argv TSRMLS_CC);
+ }
+#endif
+ } zend_end_try();
+out:
+ if (ini_path_override) {
+ free(ini_path_override);
+ }
+ if (ini_entries) {
+ free(ini_entries);
+ }
if (module_started) {
php_module_shutdown(TSRMLS_C);
}
- sapi_shutdown();
+ if (sapi_started) {
+ sapi_shutdown();
+ }
#ifdef ZTS
tsrm_shutdown();
#endif
exit(exit_status);
-
-err:
- sapi_deactivate(TSRMLS_C);
- zend_ini_deactivate(TSRMLS_C);
- exit_status = 1;
- goto out_err;
}
/* }}} */
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
new file mode 100644
index 0000000000..5f263cb322
--- /dev/null
+++ b/sapi/cli/php_cli_server.c
@@ -0,0 +1,2422 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Moriyoshi Koizumi <moriyoshi@php.net> |
+ | Xinchen Hui <laruence@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: php_cli.c 306938 2011-01-01 02:17:06Z felipe $ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#ifdef PHP_WIN32
+#include <process.h>
+#include <io.h>
+#include "win32/time.h"
+#include "win32/signal.h"
+#include "win32/php_registry.h"
+#else
+# include "php_config.h"
+#endif
+
+#ifdef __riscos__
+#include <unixlib/local.h>
+#endif
+
+
+#if HAVE_TIME_H
+#include <time.h>
+#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if HAVE_SETLOCALE
+#include <locale.h>
+#endif
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include "SAPI.h"
+#include "php.h"
+#include "php_ini.h"
+#include "php_main.h"
+#include "php_globals.h"
+#include "php_variables.h"
+#include "zend_hash.h"
+#include "zend_modules.h"
+#include "fopen_wrappers.h"
+
+#include "zend_compile.h"
+#include "zend_execute.h"
+#include "zend_highlight.h"
+#include "zend_indent.h"
+#include "zend_exceptions.h"
+
+#include "php_getopt.h"
+
+#ifndef PHP_WIN32
+# define php_select(m, r, w, e, t) select(m, r, w, e, t)
+# define SOCK_EINVAL EINVAL
+# define SOCK_EAGAIN EAGAIN
+# define SOCK_EINTR EINTR
+# define SOCK_EADDRINUSE EADDRINUSE
+#else
+# include "win32/select.h"
+# define SOCK_EINVAL WSAEINVAL
+# define SOCK_EAGAIN WSAEWOULDBLOCK
+# define SOCK_EINTR WSAEINTR
+# define SOCK_EADDRINUSE WSAEADDRINUSE
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
+#endif
+
+#include "ext/standard/file.h" /* for php_set_sock_blocking() :-( */
+#include "ext/standard/php_smart_str.h"
+#include "ext/standard/html.h"
+#include "ext/standard/url.h" /* for php_url_decode() */
+#include "ext/standard/php_string.h" /* for php_dirname() */
+#include "php_network.h"
+
+#include "php_http_parser.h"
+#include "php_cli_server.h"
+
+#define OUTPUT_NOT_CHECKED -1
+#define OUTPUT_IS_TTY 1
+#define OUTPUT_NOT_TTY 0
+
+typedef struct php_cli_server_poller {
+ fd_set rfds, wfds;
+ struct {
+ fd_set rfds, wfds;
+ } active;
+ php_socket_t max_fd;
+} php_cli_server_poller;
+
+typedef struct php_cli_server_request {
+ enum php_http_method request_method;
+ int protocol_version;
+ char *request_uri;
+ size_t request_uri_len;
+ char *vpath;
+ size_t vpath_len;
+ char *path_translated;
+ size_t path_translated_len;
+ char *path_info;
+ size_t path_info_len;
+ char *query_string;
+ size_t query_string_len;
+ HashTable headers;
+ char *content;
+ size_t content_len;
+ const char *ext;
+ size_t ext_len;
+ struct stat sb;
+} php_cli_server_request;
+
+typedef struct php_cli_server_chunk {
+ struct php_cli_server_chunk *next;
+ enum php_cli_server_chunk_type {
+ PHP_CLI_SERVER_CHUNK_HEAP,
+ PHP_CLI_SERVER_CHUNK_IMMORTAL
+ } type;
+ union {
+ struct { void *block; char *p; size_t len; } heap;
+ struct { const char *p; size_t len; } immortal;
+ } data;
+} php_cli_server_chunk;
+
+typedef struct php_cli_server_buffer {
+ php_cli_server_chunk *first;
+ php_cli_server_chunk *last;
+} php_cli_server_buffer;
+
+typedef struct php_cli_server_content_sender {
+ php_cli_server_buffer buffer;
+} php_cli_server_content_sender;
+
+typedef struct php_cli_server_client {
+ struct php_cli_server *server;
+ php_socket_t sock;
+ struct sockaddr *addr;
+ socklen_t addr_len;
+ char *addr_str;
+ size_t addr_str_len;
+ php_http_parser parser;
+ unsigned int request_read:1;
+ char *current_header_name;
+ size_t current_header_name_len;
+ unsigned int current_header_name_allocated:1;
+ size_t post_read_offset;
+ php_cli_server_request request;
+ unsigned int content_sender_initialized:1;
+ php_cli_server_content_sender content_sender;
+ int file_fd;
+} php_cli_server_client;
+
+typedef struct php_cli_server {
+ php_socket_t server_sock;
+ php_cli_server_poller poller;
+ int is_running;
+ char *host;
+ int port;
+ int address_family;
+ char *document_root;
+ size_t document_root_len;
+ char *router;
+ size_t router_len;
+ socklen_t socklen;
+ HashTable clients;
+} php_cli_server;
+
+typedef struct php_cli_server_http_reponse_status_code_pair {
+ int code;
+ const char *str;
+} php_cli_server_http_reponse_status_code_pair;
+
+typedef struct php_cli_server_ext_mime_type_pair {
+ const char *ext;
+ const char *mime_type;
+} php_cli_server_ext_mime_type_pair;
+
+static php_cli_server_http_reponse_status_code_pair status_map[] = {
+ { 100, "Continue" },
+ { 101, "Switching Protocols" },
+ { 200, "OK" },
+ { 201, "Created" },
+ { 202, "Accepted" },
+ { 203, "Non-Authoritative Information" },
+ { 204, "No Content" },
+ { 205, "Reset Content" },
+ { 206, "Partial Content" },
+ { 300, "Multiple Choices" },
+ { 301, "Moved Permanently" },
+ { 302, "Found" },
+ { 303, "See Other" },
+ { 304, "Not Modified" },
+ { 305, "Use Proxy" },
+ { 307, "Temporary Redirect" },
+ { 400, "Bad Request" },
+ { 401, "Unauthorized" },
+ { 402, "Payment Required" },
+ { 403, "Forbidden" },
+ { 404, "Not Found" },
+ { 405, "Method Not Allowed" },
+ { 406, "Not Acceptable" },
+ { 407, "Proxy Authentication Required" },
+ { 408, "Request Timeout" },
+ { 409, "Conflict" },
+ { 410, "Gone" },
+ { 411, "Length Required" },
+ { 412, "Precondition Failed" },
+ { 413, "Request Entity Too Large" },
+ { 414, "Request-URI Too Long" },
+ { 415, "Unsupported Media Type" },
+ { 416, "Requested Range Not Satisfiable" },
+ { 417, "Expectation Failed" },
+ { 500, "Internal Server Error" },
+ { 501, "Not Implemented" },
+ { 502, "Bad Gateway" },
+ { 503, "Service Unavailable" },
+ { 504, "Gateway Timeout" },
+ { 505, "HTTP Version Not Supported" },
+};
+
+static php_cli_server_http_reponse_status_code_pair template_map[] = {
+ { 400, "<h1>%s</h1><p>Your browser sent a request that this server could not understand.</p>" },
+ { 404, "<h1>%s</h1><p>The requested resource %s was not found on this server.</p>" },
+ { 500, "<h1>%s</h1><p>The server is temporarily unavailable.</p>" },
+ { 501, "<h1>%s</h1><p>Request method not supported.</p>" }
+};
+
+static php_cli_server_ext_mime_type_pair mime_type_map[] = {
+ { "html", "text/html" },
+ { "htm", "text/html" },
+ { "js", "text/javascript" },
+ { "css", "text/css" },
+ { "gif", "image/gif" },
+ { "jpg", "image/jpeg" },
+ { "jpeg", "image/jpeg" },
+ { "png", "image/png" },
+ { "jpe", "image/jpeg" },
+ { "svg", "image/svg+xml" },
+ { "txt", "text/plain" },
+ { NULL, NULL }
+};
+
+static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED;
+
+static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len);
+static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len);
+static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk);
+static void php_cli_server_logf(const char *format TSRMLS_DC, ...);
+static void php_cli_server_log_response(php_cli_server_client *client, int status, const char *message TSRMLS_DC);
+
+ZEND_DECLARE_MODULE_GLOBALS(cli_server);
+
+/* {{{ static char php_cli_server_css[]
+ * copied from ext/standard/info.c
+ */
+static const char php_cli_server_css[] = "<style>\n" \
+ "body { background-color: #ffffff; color: #000000; }\n" \
+ "h1 { font-family: sans-serif; font-size: 150%; background-color: #9999cc; font-weight: bold; color: #000000; margin-top: 0;}\n" \
+ "</style>\n";
+/* }}} */
+
+static void char_ptr_dtor_p(char **p) /* {{{ */
+{
+ pefree(*p, 1);
+} /* }}} */
+
+static char *get_last_error() /* {{{ */
+{
+ return pestrdup(strerror(errno), 1);
+} /* }}} */
+
+static const char *get_status_string(int code) /* {{{ */
+{
+ size_t e = (sizeof(status_map) / sizeof(php_cli_server_http_reponse_status_code_pair));
+ size_t s = 0;
+
+ while (e != s) {
+ size_t c = MIN((e + s + 1) / 2, e - 1);
+ int d = status_map[c].code;
+ if (d > code) {
+ e = c;
+ } else if (d < code) {
+ s = c;
+ } else {
+ return status_map[c].str;
+ }
+ }
+ return NULL;
+} /* }}} */
+
+static const char *get_template_string(int code) /* {{{ */
+{
+ size_t e = (sizeof(template_map) / sizeof(php_cli_server_http_reponse_status_code_pair));
+ size_t s = 0;
+
+ while (e != s) {
+ size_t c = MIN((e + s + 1) / 2, e - 1);
+ int d = template_map[c].code;
+ if (d > code) {
+ e = c;
+ } else if (d < code) {
+ s = c;
+ } else {
+ return template_map[c].str;
+ }
+ }
+ return NULL;
+} /* }}} */
+
+static void append_http_status_line(smart_str *buffer, int protocol_version, int response_code, int persistent) /* {{{ */
+{
+ if (!response_code) {
+ response_code = 200;
+ }
+ smart_str_appendl_ex(buffer, "HTTP", 4, persistent);
+ smart_str_appendc_ex(buffer, '/', persistent);
+ smart_str_append_generic_ex(buffer, protocol_version / 100, persistent, int, _unsigned);
+ smart_str_appendc_ex(buffer, '.', persistent);
+ smart_str_append_generic_ex(buffer, protocol_version % 100, persistent, int, _unsigned);
+ smart_str_appendc_ex(buffer, ' ', persistent);
+ smart_str_append_generic_ex(buffer, response_code, persistent, int, _unsigned);
+ smart_str_appendc_ex(buffer, ' ', persistent);
+ smart_str_appends_ex(buffer, get_status_string(response_code), persistent);
+ smart_str_appendl_ex(buffer, "\r\n", 2, persistent);
+} /* }}} */
+
+static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, int persistent) /* {{{ */
+{
+ {
+ char **val;
+ if (SUCCESS == zend_hash_find(&client->request.headers, "Host", sizeof("Host"), (void**)&val)) {
+ smart_str_appendl_ex(buffer, "Host", sizeof("Host") - 1, persistent);
+ smart_str_appendl_ex(buffer, ": ", sizeof(": ") - 1, persistent);
+ smart_str_appends_ex(buffer, *val, persistent);
+ smart_str_appendl_ex(buffer, "\r\n", 2, persistent);
+ }
+ }
+ smart_str_appendl_ex(buffer, "Connection: close\r\n", sizeof("Connection: close\r\n") - 1, persistent);
+} /* }}} */
+
+static const char *get_mime_type(const char *ext, size_t ext_len) /* {{{ */
+{
+ php_cli_server_ext_mime_type_pair *pair;
+ for (pair = mime_type_map; pair->ext; pair++) {
+ size_t len = strlen(pair->ext);
+ if (len == ext_len && memcmp(pair->ext, ext, len) == 0) {
+ return pair->mime_type;
+ }
+ }
+ return NULL;
+} /* }}} */
+
+/* {{{ cli_server module
+ */
+
+static void cli_server_init_globals(zend_cli_server_globals *cg TSRMLS_DC)
+{
+ cg->color = 0;
+}
+
+PHP_INI_BEGIN()
+ STD_PHP_INI_BOOLEAN("cli_server.color", "0", PHP_INI_ALL, OnUpdateBool, color, zend_cli_server_globals, cli_server_globals)
+PHP_INI_END()
+
+static PHP_MINIT_FUNCTION(cli_server)
+{
+ ZEND_INIT_MODULE_GLOBALS(cli_server, cli_server_init_globals, NULL);
+ REGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+
+static PHP_MSHUTDOWN_FUNCTION(cli_server)
+{
+ UNREGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+
+static PHP_MINFO_FUNCTION(cli_server)
+{
+ DISPLAY_INI_ENTRIES();
+}
+
+zend_module_entry cli_server_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "cli_server",
+ NULL,
+ PHP_MINIT(cli_server),
+ PHP_MSHUTDOWN(cli_server),
+ NULL,
+ NULL,
+ PHP_MINFO(cli_server),
+ PHP_VERSION,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+static int sapi_cli_server_startup(sapi_module_struct *sapi_module) /* {{{ */
+{
+ if (php_module_startup(sapi_module, &cli_server_module_entry, 1) == FAILURE) {
+ return FAILURE;
+ }
+ return SUCCESS;
+} /* }}} */
+
+static int sapi_cli_server_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
+{
+ php_cli_server_client *client = SG(server_context);
+ if (!client) {
+ return 0;
+ }
+ return php_cli_server_client_send_through(client, str, str_length);
+} /* }}} */
+
+static void sapi_cli_server_flush(void *server_context) /* {{{ */
+{
+ php_cli_server_client *client = server_context;
+ TSRMLS_FETCH();
+
+ if (!client) {
+ return;
+ }
+
+ if (client->sock < 0) {
+ php_handle_aborted_connection();
+ return;
+ }
+
+ if (!SG(headers_sent)) {
+ sapi_send_headers(TSRMLS_C);
+ SG(headers_sent) = 1;
+ }
+} /* }}} */
+
+static int sapi_cli_server_discard_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */{
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
+}
+/* }}} */
+
+static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */
+{
+ php_cli_server_client *client = SG(server_context);
+ smart_str buffer = { 0 };
+ sapi_header_struct *h;
+ zend_llist_position pos;
+
+ if (client == NULL || SG(request_info).no_headers) {
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
+ }
+
+ if (SG(sapi_headers).http_status_line) {
+ smart_str_appends(&buffer, SG(sapi_headers).http_status_line);
+ smart_str_appendl(&buffer, "\r\n", 2);
+ } else {
+ append_http_status_line(&buffer, client->request.protocol_version, SG(sapi_headers).http_response_code, 0);
+ }
+
+ append_essential_headers(&buffer, client, 0);
+
+ h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
+ while (h) {
+ if (!h->header_len) {
+ continue;
+ }
+ smart_str_appendl(&buffer, h->header, h->header_len);
+ smart_str_appendl(&buffer, "\r\n", 2);
+ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ }
+ smart_str_appendl(&buffer, "\r\n", 2);
+
+ php_cli_server_client_send_through(client, buffer.c, buffer.len);
+
+ smart_str_free(&buffer);
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
+}
+/* }}} */
+
+static char *sapi_cli_server_read_cookies(TSRMLS_D) /* {{{ */
+{
+ php_cli_server_client *client = SG(server_context);
+ char **val;
+ if (FAILURE == zend_hash_find(&client->request.headers, "Cookie", sizeof("Cookie"), (void**)&val)) {
+ return NULL;
+ }
+ return *val;
+} /* }}} */
+
+static int sapi_cli_server_read_post(char *buf, uint count_bytes TSRMLS_DC) /* {{{ */
+{
+ php_cli_server_client *client = SG(server_context);
+ if (client->request.content) {
+ size_t content_len = client->request.content_len;
+ size_t nbytes_copied = MIN(client->post_read_offset + count_bytes, content_len) - client->post_read_offset;
+ memmove(buf, client->request.content + client->post_read_offset, nbytes_copied);
+ client->post_read_offset += nbytes_copied;
+ return nbytes_copied;
+ }
+ return 0;
+} /* }}} */
+
+static void sapi_cli_server_register_variable(zval *track_vars_array, const char *key, const char *val TSRMLS_DC) /* {{{ */
+{
+ char *new_val = (char *)val;
+ uint new_val_len;
+ if (sapi_module.input_filter(PARSE_SERVER, (char*)key, &new_val, strlen(val), &new_val_len TSRMLS_CC)) {
+ php_register_variable_safe((char *)key, new_val, new_val_len, track_vars_array TSRMLS_CC);
+ }
+} /* }}} */
+
+static int sapi_cli_server_register_entry_cb(char **entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ {
+ zval *track_vars_array = va_arg(args, zval *);
+ if (hash_key->nKeyLength) {
+ char *real_key, *key;
+ uint i;
+ key = estrndup(hash_key->arKey, hash_key->nKeyLength);
+ for(i=0; i<hash_key->nKeyLength; i++) {
+ if (key[i] == '-') {
+ key[i] = '_';
+ } else {
+ key[i] = toupper(key[i]);
+ }
+ }
+ spprintf(&real_key, 0, "%s_%s", "HTTP", key);
+ sapi_cli_server_register_variable(track_vars_array, real_key, *entry TSRMLS_CC);
+ efree(key);
+ efree(real_key);
+ }
+
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+static void sapi_cli_server_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{ */
+{
+ php_cli_server_client *client = SG(server_context);
+ sapi_cli_server_register_variable(track_vars_array, "DOCUMENT_ROOT", client->server->document_root TSRMLS_CC);
+ {
+ char *tmp;
+ if ((tmp = strrchr(client->addr_str, ':'))) {
+ char addr[64], port[8];
+ strncpy(port, tmp + 1, 8);
+ port[7] = '\0';
+ strncpy(addr, client->addr_str, tmp - client->addr_str);
+ addr[tmp - client->addr_str] = '\0';
+ sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", addr TSRMLS_CC);
+ sapi_cli_server_register_variable(track_vars_array, "REMOTE_PORT", port TSRMLS_CC);
+ } else {
+ sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", client->addr_str TSRMLS_CC);
+ }
+ }
+ {
+ char *tmp;
+ spprintf(&tmp, 0, "PHP %s Development Server", PHP_VERSION);
+ sapi_cli_server_register_variable(track_vars_array, "SERVER_SOFTWARE", tmp TSRMLS_CC);
+ efree(tmp);
+ }
+ {
+ char *tmp;
+ spprintf(&tmp, 0, "HTTP/%d.%d", client->request.protocol_version / 100, client->request.protocol_version % 100);
+ sapi_cli_server_register_variable(track_vars_array, "SERVER_PROTOCOL", tmp TSRMLS_CC);
+ efree(tmp);
+ }
+ sapi_cli_server_register_variable(track_vars_array, "SERVER_NAME", client->server->host TSRMLS_CC);
+ {
+ char *tmp;
+ spprintf(&tmp, 0, "%i", client->server->port);
+ sapi_cli_server_register_variable(track_vars_array, "SERVER_PORT", tmp TSRMLS_CC);
+ efree(tmp);
+ }
+
+ sapi_cli_server_register_variable(track_vars_array, "REQUEST_URI", client->request.request_uri TSRMLS_CC);
+ sapi_cli_server_register_variable(track_vars_array, "REQUEST_METHOD", SG(request_info).request_method TSRMLS_CC);
+ sapi_cli_server_register_variable(track_vars_array, "SCRIPT_NAME", client->request.vpath TSRMLS_CC);
+ if (SG(request_info).path_translated) {
+ sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", SG(request_info).path_translated TSRMLS_CC);
+ } else if (client->server->router) {
+ char *temp;
+ spprintf(&temp, 0, "%s/%s", client->server->document_root, client->server->router);
+ sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", temp TSRMLS_CC);
+ efree(temp);
+ }
+ if (client->request.path_info) {
+ sapi_cli_server_register_variable(track_vars_array, "PATH_INFO", client->request.path_info TSRMLS_CC);
+ }
+ if (client->request.path_info_len) {
+ char *tmp;
+ spprintf(&tmp, 0, "%s%s", client->request.vpath, client->request.path_info);
+ sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", tmp TSRMLS_CC);
+ efree(tmp);
+ } else {
+ sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", client->request.vpath TSRMLS_CC);
+ }
+ if (client->request.query_string) {
+ sapi_cli_server_register_variable(track_vars_array, "QUERY_STRING", client->request.query_string TSRMLS_CC);
+ }
+ zend_hash_apply_with_arguments(&client->request.headers TSRMLS_CC, (apply_func_args_t)sapi_cli_server_register_entry_cb, 1, track_vars_array);
+} /* }}} */
+
+static void sapi_cli_server_log_message(char *msg TSRMLS_DC) /* {{{ */
+{
+ struct timeval tv;
+ struct tm tm;
+ char buf[52];
+ gettimeofday(&tv, NULL);
+ php_localtime_r(&tv.tv_sec, &tm);
+ php_asctime_r(&tm, buf);
+ {
+ size_t l = strlen(buf);
+ if (l > 0) {
+ buf[l - 1] = '\0';
+ } else {
+ memmove(buf, "unknown", sizeof("unknown"));
+ }
+ }
+ fprintf(stderr, "[%s] %s\n", buf, msg);
+} /* }}} */
+
+/* {{{ sapi_module_struct cli_server_sapi_module
+ */
+sapi_module_struct cli_server_sapi_module = {
+ "cli-server", /* name */
+ "Built-in HTTP server", /* pretty name */
+
+ sapi_cli_server_startup, /* startup */
+ php_module_shutdown_wrapper, /* shutdown */
+
+ NULL, /* activate */
+ NULL, /* deactivate */
+
+ sapi_cli_server_ub_write, /* unbuffered write */
+ sapi_cli_server_flush, /* flush */
+ NULL, /* get uid */
+ NULL, /* getenv */
+
+ php_error, /* error handler */
+
+ NULL, /* header handler */
+ sapi_cli_server_send_headers, /* send headers handler */
+ NULL, /* send header handler */
+
+ sapi_cli_server_read_post, /* read POST data */
+ sapi_cli_server_read_cookies, /* read Cookies */
+
+ sapi_cli_server_register_variables, /* register server variables */
+ sapi_cli_server_log_message, /* Log message */
+ NULL, /* Get request time */
+ NULL, /* Child terminate */
+
+ STANDARD_SAPI_MODULE_PROPERTIES
+}; /* }}} */
+
+static int php_cli_server_poller_ctor(php_cli_server_poller *poller) /* {{{ */
+{
+ FD_ZERO(&poller->rfds);
+ FD_ZERO(&poller->wfds);
+ poller->max_fd = -1;
+ return SUCCESS;
+} /* }}} */
+
+static void php_cli_server_poller_add(php_cli_server_poller *poller, int mode, int fd) /* {{{ */
+{
+ if (mode & POLLIN) {
+ PHP_SAFE_FD_SET(fd, &poller->rfds);
+ }
+ if (mode & POLLOUT) {
+ PHP_SAFE_FD_SET(fd, &poller->wfds);
+ }
+ if (fd > poller->max_fd) {
+ poller->max_fd = fd;
+ }
+} /* }}} */
+
+static void php_cli_server_poller_remove(php_cli_server_poller *poller, int mode, int fd) /* {{{ */
+{
+ if (mode & POLLIN) {
+ PHP_SAFE_FD_CLR(fd, &poller->rfds);
+ }
+ if (mode & POLLOUT) {
+ PHP_SAFE_FD_CLR(fd, &poller->wfds);
+ }
+#ifndef PHP_WIN32
+ if (fd == poller->max_fd) {
+ while (fd > 0) {
+ fd--;
+ if (((unsigned int *)&poller->rfds)[fd / (8 * sizeof(unsigned int))] || ((unsigned int *)&poller->wfds)[fd / (8 * sizeof(unsigned int))]) {
+ break;
+ }
+ fd -= fd % (8 * sizeof(unsigned int));
+ }
+ poller->max_fd = fd;
+ }
+#endif
+} /* }}} */
+
+static int php_cli_server_poller_poll(php_cli_server_poller *poller, const struct timeval *tv) /* {{{ */
+{
+ memmove(&poller->active.rfds, &poller->rfds, sizeof(poller->rfds));
+ memmove(&poller->active.wfds, &poller->wfds, sizeof(poller->wfds));
+ return php_select(poller->max_fd + 1, &poller->active.rfds, &poller->active.wfds, NULL, (struct timeval *)tv);
+} /* }}} */
+
+static int php_cli_server_poller_iter_on_active(php_cli_server_poller *poller, void *opaque, int(*callback)(void *, int fd, int events)) /* {{{ */
+{
+ int retval = SUCCESS;
+#ifdef PHP_WIN32
+ struct socket_entry {
+ SOCKET fd;
+ int events;
+ } entries[FD_SETSIZE * 2];
+ php_socket_t fd = 0;
+ size_t i;
+ struct socket_entry *n = entries, *m;
+
+ for (i = 0; i < poller->active.rfds.fd_count; i++) {
+ n->events = POLLIN;
+ n->fd = poller->active.rfds.fd_array[i];
+ n++;
+ }
+
+ m = n;
+ for (i = 0; i < poller->active.wfds.fd_count; i++) {
+ struct socket_entry *e;
+ SOCKET fd = poller->active.wfds.fd_array[i];
+ for (e = entries; e < m; e++) {
+ if (e->fd == fd) {
+ e->events |= POLLOUT;
+ }
+ }
+ if (e == m) {
+ assert(n < entries + FD_SETSIZE * 2);
+ n->events = POLLOUT;
+ n->fd = fd;
+ n++;
+ }
+ }
+
+ {
+ struct socket_entry *e = entries;
+ for (; e < n; e++) {
+ if (SUCCESS != callback(opaque, e->fd, e->events)) {
+ retval = FAILURE;
+ }
+ }
+ }
+
+#else
+ php_socket_t fd = 0;
+ const php_socket_t max_fd = poller->max_fd;
+ const unsigned int *pr = (unsigned int *)&poller->active.rfds,
+ *pw = (unsigned int *)&poller->active.wfds,
+ *e = pr + (max_fd + (8 * sizeof(unsigned int)) - 1) / (8 * sizeof(unsigned int));
+ unsigned int mask;
+ while (pr < e && fd <= max_fd) {
+ for (mask = 1; mask; mask <<= 1, fd++) {
+ int events = (*pr & mask ? POLLIN: 0) | (*pw & mask ? POLLOUT: 0);
+ if (events) {
+ if (SUCCESS != callback(opaque, fd, events)) {
+ retval = FAILURE;
+ }
+ }
+ }
+ pr++;
+ pw++;
+ }
+#endif
+ return retval;
+} /* }}} */
+
+static size_t php_cli_server_chunk_size(const php_cli_server_chunk *chunk) /* {{{ */
+{
+ switch (chunk->type) {
+ case PHP_CLI_SERVER_CHUNK_HEAP:
+ return chunk->data.heap.len;
+ case PHP_CLI_SERVER_CHUNK_IMMORTAL:
+ return chunk->data.immortal.len;
+ }
+ return 0;
+} /* }}} */
+
+static void php_cli_server_chunk_dtor(php_cli_server_chunk *chunk) /* {{{ */
+{
+ switch (chunk->type) {
+ case PHP_CLI_SERVER_CHUNK_HEAP:
+ if (chunk->data.heap.block != chunk) {
+ pefree(chunk->data.heap.block, 1);
+ }
+ break;
+ case PHP_CLI_SERVER_CHUNK_IMMORTAL:
+ break;
+ }
+} /* }}} */
+
+static void php_cli_server_buffer_dtor(php_cli_server_buffer *buffer) /* {{{ */
+{
+ php_cli_server_chunk *chunk, *next;
+ for (chunk = buffer->first; chunk; chunk = next) {
+ next = chunk->next;
+ php_cli_server_chunk_dtor(chunk);
+ pefree(chunk, 1);
+ }
+} /* }}} */
+
+static void php_cli_server_buffer_ctor(php_cli_server_buffer *buffer) /* {{{ */
+{
+ buffer->first = NULL;
+ buffer->last = NULL;
+} /* }}} */
+
+static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk) /* {{{ */
+{
+ php_cli_server_chunk *last;
+ for (last = chunk; last->next; last = last->next);
+ if (!buffer->last) {
+ buffer->first = chunk;
+ } else {
+ buffer->last->next = chunk;
+ }
+ buffer->last = last;
+} /* }}} */
+
+static void php_cli_server_buffer_prepend(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk) /* {{{ */
+{
+ php_cli_server_chunk *last;
+ for (last = chunk; last->next; last = last->next);
+ last->next = buffer->first;
+ if (!buffer->last) {
+ buffer->last = last;
+ }
+ buffer->first = chunk;
+} /* }}} */
+
+static size_t php_cli_server_buffer_size(const php_cli_server_buffer *buffer) /* {{{ */
+{
+ php_cli_server_chunk *chunk;
+ size_t retval = 0;
+ for (chunk = buffer->first; chunk; chunk = chunk->next) {
+ retval += php_cli_server_chunk_size(chunk);
+ }
+ return retval;
+} /* }}} */
+
+static php_cli_server_chunk *php_cli_server_chunk_immortal_new(const char *buf, size_t len) /* {{{ */
+{
+ php_cli_server_chunk *chunk = pemalloc(sizeof(php_cli_server_chunk), 1);
+ if (!chunk) {
+ return NULL;
+ }
+
+ chunk->type = PHP_CLI_SERVER_CHUNK_IMMORTAL;
+ chunk->next = NULL;
+ chunk->data.immortal.p = buf;
+ chunk->data.immortal.len = len;
+ return chunk;
+} /* }}} */
+
+static php_cli_server_chunk *php_cli_server_chunk_heap_new(char *block, char *buf, size_t len) /* {{{ */
+{
+ php_cli_server_chunk *chunk = pemalloc(sizeof(php_cli_server_chunk), 1);
+ if (!chunk) {
+ return NULL;
+ }
+
+ chunk->type = PHP_CLI_SERVER_CHUNK_HEAP;
+ chunk->next = NULL;
+ chunk->data.heap.block = block;
+ chunk->data.heap.p = buf;
+ chunk->data.heap.len = len;
+ return chunk;
+} /* }}} */
+
+static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len) /* {{{ */
+{
+ php_cli_server_chunk *chunk = pemalloc(sizeof(php_cli_server_chunk) + len, 1);
+ if (!chunk) {
+ return NULL;
+ }
+
+ chunk->type = PHP_CLI_SERVER_CHUNK_HEAP;
+ chunk->next = NULL;
+ chunk->data.heap.block = chunk;
+ chunk->data.heap.p = (char *)(chunk + 1);
+ chunk->data.heap.len = len;
+ return chunk;
+} /* }}} */
+
+static void php_cli_server_content_sender_dtor(php_cli_server_content_sender *sender) /* {{{ */
+{
+ php_cli_server_buffer_dtor(&sender->buffer);
+} /* }}} */
+
+static void php_cli_server_content_sender_ctor(php_cli_server_content_sender *sender) /* {{{ */
+{
+ php_cli_server_buffer_ctor(&sender->buffer);
+} /* }}} */
+
+static int php_cli_server_content_sender_send(php_cli_server_content_sender *sender, php_socket_t fd, size_t *nbytes_sent_total) /* {{{ */
+{
+ php_cli_server_chunk *chunk, *next;
+ size_t _nbytes_sent_total = 0;
+
+ for (chunk = sender->buffer.first; chunk; chunk = next) {
+ ssize_t nbytes_sent;
+ next = chunk->next;
+
+ switch (chunk->type) {
+ case PHP_CLI_SERVER_CHUNK_HEAP:
+ nbytes_sent = send(fd, chunk->data.heap.p, chunk->data.heap.len, 0);
+ if (nbytes_sent < 0) {
+ *nbytes_sent_total = _nbytes_sent_total;
+ return php_socket_errno();
+ } else if (nbytes_sent == chunk->data.heap.len) {
+ php_cli_server_chunk_dtor(chunk);
+ pefree(chunk, 1);
+ sender->buffer.first = next;
+ if (!next) {
+ sender->buffer.last = NULL;
+ }
+ } else {
+ chunk->data.heap.p += nbytes_sent;
+ chunk->data.heap.len -= nbytes_sent;
+ }
+ _nbytes_sent_total += nbytes_sent;
+ break;
+
+ case PHP_CLI_SERVER_CHUNK_IMMORTAL:
+ nbytes_sent = send(fd, chunk->data.immortal.p, chunk->data.immortal.len, 0);
+ if (nbytes_sent < 0) {
+ *nbytes_sent_total = _nbytes_sent_total;
+ return php_socket_errno();
+ } else if (nbytes_sent == chunk->data.immortal.len) {
+ php_cli_server_chunk_dtor(chunk);
+ pefree(chunk, 1);
+ sender->buffer.first = next;
+ if (!next) {
+ sender->buffer.last = NULL;
+ }
+ } else {
+ chunk->data.immortal.p += nbytes_sent;
+ chunk->data.immortal.len -= nbytes_sent;
+ }
+ _nbytes_sent_total += nbytes_sent;
+ break;
+ }
+ }
+ *nbytes_sent_total = _nbytes_sent_total;
+ return 0;
+} /* }}} */
+
+static int php_cli_server_content_sender_pull(php_cli_server_content_sender *sender, int fd, size_t *nbytes_read) /* {{{ */
+{
+ ssize_t _nbytes_read;
+ php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(131072);
+
+ _nbytes_read = read(fd, chunk->data.heap.p, chunk->data.heap.len);
+ if (_nbytes_read < 0) {
+ char *errstr = get_last_error();
+ TSRMLS_FETCH();
+ php_cli_server_logf("%s" TSRMLS_CC, errstr);
+ pefree(errstr, 1);
+ php_cli_server_chunk_dtor(chunk);
+ pefree(chunk, 1);
+ return 1;
+ }
+ chunk->data.heap.len = _nbytes_read;
+ php_cli_server_buffer_append(&sender->buffer, chunk);
+ *nbytes_read = _nbytes_read;
+ return 0;
+} /* }}} */
+
+#if HAVE_UNISTD_H
+static int php_cli_is_output_tty() /* {{{ */
+{
+ if (php_cli_output_is_tty == OUTPUT_NOT_CHECKED) {
+ php_cli_output_is_tty = isatty(STDOUT_FILENO);
+ }
+ return php_cli_output_is_tty;
+} /* }}} */
+#endif
+
+static void php_cli_server_log_response(php_cli_server_client *client, int status, const char *message TSRMLS_DC) /* {{{ */
+{
+ int color = 0, effective_status = status;
+ char *basic_buf, *message_buf = "", *error_buf = "";
+ zend_bool append_error_message = 0;
+
+ if (PG(last_error_message)) {
+ switch (PG(last_error_type)) {
+ case E_ERROR:
+ case E_CORE_ERROR:
+ case E_COMPILE_ERROR:
+ case E_USER_ERROR:
+ case E_PARSE:
+ if (status == 200) {
+ /* the status code isn't changed by a fatal error, so fake it */
+ effective_status = 500;
+ }
+
+ append_error_message = 1;
+ break;
+ }
+ }
+
+#if HAVE_UNISTD_H
+ if (CLI_SERVER_G(color) && php_cli_is_output_tty() == OUTPUT_IS_TTY) {
+ if (effective_status >= 500) {
+ /* server error: red */
+ color = 1;
+ } else if (effective_status >= 400) {
+ /* client error: yellow */
+ color = 3;
+ } else if (effective_status >= 200) {
+ /* success: green */
+ color = 2;
+ }
+ }
+#endif
+
+ /* basic */
+ spprintf(&basic_buf, 0, "%s [%d]: %s", client->addr_str, status, client->request.request_uri);
+ if (!basic_buf) {
+ return;
+ }
+
+ /* message */
+ if (message) {
+ spprintf(&message_buf, 0, " - %s", message);
+ if (!message_buf) {
+ efree(basic_buf);
+ return;
+ }
+ }
+
+ /* error */
+ if (append_error_message) {
+ spprintf(&error_buf, 0, " - %s in %s on line %d", PG(last_error_message), PG(last_error_file), PG(last_error_lineno));
+ if (!error_buf) {
+ efree(basic_buf);
+ if (message) {
+ efree(message_buf);
+ }
+ return;
+ }
+ }
+
+ if (color) {
+ php_cli_server_logf("\x1b[3%dm%s%s%s\x1b[0m" TSRMLS_CC, color, basic_buf, message_buf, error_buf);
+ } else {
+ php_cli_server_logf("%s%s%s" TSRMLS_CC, basic_buf, message_buf, error_buf);
+ }
+
+ efree(basic_buf);
+ if (message) {
+ efree(message_buf);
+ }
+ if (append_error_message) {
+ efree(error_buf);
+ }
+} /* }}} */
+
+static void php_cli_server_logf(const char *format TSRMLS_DC, ...) /* {{{ */
+{
+ char *buf = NULL;
+ va_list ap;
+#ifdef ZTS
+ va_start(ap, tsrm_ls);
+#else
+ va_start(ap, format);
+#endif
+ vspprintf(&buf, 0, format, ap);
+ va_end(ap);
+
+ if (!buf) {
+ return;
+ }
+
+ if (sapi_module.log_message) {
+ sapi_module.log_message(buf TSRMLS_CC);
+ }
+
+ efree(buf);
+} /* }}} */
+
+static int php_network_listen_socket(const char *host, int *port, int socktype, int *af, socklen_t *socklen, char **errstr TSRMLS_DC) /* {{{ */
+{
+ int retval = SOCK_ERR;
+ int err = 0;
+ struct sockaddr *sa = NULL, **p, **sal;
+
+ int num_addrs = php_network_getaddresses(host, socktype, &sal, errstr TSRMLS_CC);
+ if (num_addrs == 0) {
+ return -1;
+ }
+ for (p = sal; *p; p++) {
+ if (sa) {
+ pefree(sa, 1);
+ sa = NULL;
+ }
+
+ retval = socket((*p)->sa_family, socktype, 0);
+ if (retval == SOCK_ERR) {
+ continue;
+ }
+
+ switch ((*p)->sa_family) {
+#if HAVE_GETADDRINFO && HAVE_IPV6
+ case AF_INET6:
+ sa = pemalloc(sizeof(struct sockaddr_in6), 1);
+ if (!sa) {
+ closesocket(retval);
+ retval = SOCK_ERR;
+ *errstr = NULL;
+ goto out;
+ }
+ *(struct sockaddr_in6 *)sa = *(struct sockaddr_in6 *)*p;
+ ((struct sockaddr_in6 *)sa)->sin6_port = htons(*port);
+ *socklen = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ case AF_INET:
+ sa = pemalloc(sizeof(struct sockaddr_in), 1);
+ if (!sa) {
+ closesocket(retval);
+ retval = SOCK_ERR;
+ *errstr = NULL;
+ goto out;
+ }
+ *(struct sockaddr_in *)sa = *(struct sockaddr_in *)*p;
+ ((struct sockaddr_in *)sa)->sin_port = htons(*port);
+ *socklen = sizeof(struct sockaddr_in);
+ break;
+ default:
+ /* Unknown family */
+ *socklen = 0;
+ closesocket(retval);
+ continue;
+ }
+
+#ifdef SO_REUSEADDR
+ {
+ int val = 1;
+ setsockopt(retval, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
+ }
+#endif
+
+ if (bind(retval, sa, *socklen) == SOCK_CONN_ERR) {
+ err = php_socket_errno();
+ if (err == SOCK_EINVAL || err == SOCK_EADDRINUSE) {
+ goto out;
+ }
+ closesocket(retval);
+ retval = SOCK_ERR;
+ continue;
+ }
+ err = 0;
+
+ *af = sa->sa_family;
+ if (*port == 0) {
+ if (getsockname(retval, sa, socklen)) {
+ err = php_socket_errno();
+ goto out;
+ }
+ switch (sa->sa_family) {
+#if HAVE_GETADDRINFO && HAVE_IPV6
+ case AF_INET6:
+ *port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+ break;
+#endif
+ case AF_INET:
+ *port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ if (retval == SOCK_ERR) {
+ goto out;
+ }
+
+ if (listen(retval, SOMAXCONN)) {
+ err = php_socket_errno();
+ goto out;
+ }
+
+out:
+ if (sa) {
+ pefree(sa, 1);
+ }
+ if (sal) {
+ php_network_freeaddresses(sal);
+ }
+ if (err) {
+ if (retval >= 0) {
+ closesocket(retval);
+ }
+ if (errstr) {
+ *errstr = php_socket_strerror(err, NULL, 0);
+ }
+ return SOCK_ERR;
+ }
+ return retval;
+} /* }}} */
+
+static int php_cli_server_request_ctor(php_cli_server_request *req) /* {{{ */
+{
+ req->protocol_version = 0;
+ req->request_uri = NULL;
+ req->request_uri_len = 0;
+ req->vpath = NULL;
+ req->vpath_len = 0;
+ req->path_translated = NULL;
+ req->path_translated_len = 0;
+ req->path_info = NULL;
+ req->path_info_len = 0;
+ req->query_string = NULL;
+ req->query_string_len = 0;
+ zend_hash_init(&req->headers, 0, NULL, (void(*)(void*))char_ptr_dtor_p, 1);
+ req->content = NULL;
+ req->content_len = 0;
+ req->ext = NULL;
+ req->ext_len = 0;
+ return SUCCESS;
+} /* }}} */
+
+static void php_cli_server_request_dtor(php_cli_server_request *req) /* {{{ */
+{
+ if (req->request_uri) {
+ pefree(req->request_uri, 1);
+ }
+ if (req->vpath) {
+ pefree(req->vpath, 1);
+ }
+ if (req->path_translated) {
+ pefree(req->path_translated, 1);
+ }
+ if (req->path_info) {
+ pefree(req->path_info, 1);
+ }
+ if (req->query_string) {
+ pefree(req->query_string, 1);
+ }
+ zend_hash_destroy(&req->headers);
+ if (req->content) {
+ pefree(req->content, 1);
+ }
+} /* }}} */
+
+static void php_cli_server_request_translate_vpath(php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */
+{
+ struct stat sb;
+ static const char *index_files[] = { "index.php", "index.html", NULL };
+ char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1);
+ char *p = buf, *prev_path = NULL, *q, *vpath;
+ size_t prev_path_len;
+ int is_static_file = 0;
+
+ if (!buf) {
+ return;
+ }
+
+ memmove(p, document_root, document_root_len);
+ p += document_root_len;
+ vpath = p;
+ if (request->vpath_len > 0 && request->vpath[0] != '/') {
+ *p++ = DEFAULT_SLASH;
+ }
+ q = request->vpath + request->vpath_len;
+ while (q > request->vpath) {
+ if (*q-- == '.') {
+ is_static_file = 1;
+ break;
+ }
+ }
+ memmove(p, request->vpath, request->vpath_len);
+#ifdef PHP_WIN32
+ q = p + request->vpath_len;
+ do {
+ if (*q == '/') {
+ *q = '\\';
+ }
+ } while (q-- > p);
+#endif
+ p += request->vpath_len;
+ *p = '\0';
+ q = p;
+ while (q > buf) {
+ if (!stat(buf, &sb)) {
+ if (sb.st_mode & S_IFDIR) {
+ const char **file = index_files;
+ if (q[-1] != DEFAULT_SLASH) {
+ *q++ = DEFAULT_SLASH;
+ }
+ while (*file) {
+ size_t l = strlen(*file);
+ memmove(q, *file, l + 1);
+ if (!stat(buf, &sb) && (sb.st_mode & S_IFREG)) {
+ q += l;
+ break;
+ }
+ file++;
+ }
+ if (!*file || is_static_file) {
+ if (prev_path) {
+ pefree(prev_path, 1);
+ }
+ pefree(buf, 1);
+ return;
+ }
+ }
+ break; /* regular file */
+ }
+ if (prev_path) {
+ pefree(prev_path, 1);
+ *q = DEFAULT_SLASH;
+ }
+ while (q > buf && *(--q) != DEFAULT_SLASH);
+ prev_path_len = p - q;
+ prev_path = pestrndup(q, prev_path_len, 1);
+ *q = '\0';
+ }
+ if (prev_path) {
+ request->path_info_len = prev_path_len;
+#ifdef PHP_WIN32
+ while (prev_path_len--) {
+ if (prev_path[prev_path_len] == '\\') {
+ prev_path[prev_path_len] = '/';
+ }
+ }
+#endif
+ request->path_info = prev_path;
+ pefree(request->vpath, 1);
+ request->vpath = pestrndup(vpath, q - vpath, 1);
+ request->vpath_len = q - vpath;
+ request->path_translated = buf;
+ request->path_translated_len = q - buf;
+ } else {
+ pefree(request->vpath, 1);
+ request->vpath = pestrndup(vpath, q - vpath, 1);
+ request->vpath_len = q - vpath;
+ request->path_translated = buf;
+ request->path_translated_len = q - buf;
+ }
+#ifdef PHP_WIN32
+ {
+ uint i = 0;
+ for (;i<request->vpath_len;i++) {
+ if (request->vpath[i] == '\\') {
+ request->vpath[i] = '/';
+ }
+ }
+ }
+#endif
+ request->sb = sb;
+} /* }}} */
+
+static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath, size_t vpath_len, int persistent) /* {{{ */
+{
+ char *decoded_vpath = NULL;
+ char *decoded_vpath_end;
+ char *p;
+
+ *retval = NULL;
+
+ decoded_vpath = pestrndup(vpath, vpath_len, persistent);
+ if (!decoded_vpath) {
+ return;
+ }
+
+ decoded_vpath_end = decoded_vpath + php_url_decode(decoded_vpath, vpath_len);
+
+ p = decoded_vpath;
+
+ if (p < decoded_vpath_end && *p == '/') {
+ char *n = p;
+ while (n < decoded_vpath_end && *n == '/') n++;
+ memmove(++p, n, decoded_vpath_end - n);
+ decoded_vpath_end -= n - p;
+ }
+
+ while (p < decoded_vpath_end) {
+ char *n = p;
+ while (n < decoded_vpath_end && *n != '/') n++;
+ if (n - p == 2 && p[0] == '.' && p[1] == '.') {
+ if (p > decoded_vpath) {
+ --p;
+ for (;;) {
+ if (p == decoded_vpath) {
+ if (*p == '/') {
+ p++;
+ }
+ break;
+ }
+ if (*(--p) == '/') {
+ p++;
+ break;
+ }
+ }
+ }
+ while (n < decoded_vpath_end && *n == '/') n++;
+ memmove(p, n, decoded_vpath_end - n);
+ decoded_vpath_end -= n - p;
+ } else if (n - p == 1 && p[0] == '.') {
+ while (n < decoded_vpath_end && *n == '/') n++;
+ memmove(p, n, decoded_vpath_end - n);
+ decoded_vpath_end -= n - p;
+ } else {
+ if (n < decoded_vpath_end) {
+ char *nn = n;
+ while (nn < decoded_vpath_end && *nn == '/') nn++;
+ p = n + 1;
+ memmove(p, nn, decoded_vpath_end - nn);
+ decoded_vpath_end -= nn - p;
+ } else {
+ p = n;
+ }
+ }
+ }
+
+ *decoded_vpath_end = '\0';
+ *retval = decoded_vpath;
+ *retval_len = decoded_vpath_end - decoded_vpath;
+} /* }}} */
+
+/* {{{ php_cli_server_client_read_request */
+static int php_cli_server_client_read_request_on_message_begin(php_http_parser *parser)
+{
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_path(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ {
+ char *vpath;
+ size_t vpath_len;
+ normalize_vpath(&vpath, &vpath_len, at, length, 1);
+ client->request.vpath = vpath;
+ client->request.vpath_len = vpath_len;
+ }
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_query_string(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ client->request.query_string = pestrndup(at, length, 1);
+ client->request.query_string_len = length;
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_url(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ client->request.request_method = parser->method;
+ client->request.request_uri = pestrndup(at, length, 1);
+ client->request.request_uri_len = length;
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_fragment(php_http_parser *parser, const char *at, size_t length)
+{
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ if (client->current_header_name_allocated) {
+ pefree(client->current_header_name, 1);
+ client->current_header_name_allocated = 0;
+ }
+ client->current_header_name = (char *)at;
+ client->current_header_name_len = length;
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_header_value(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ char *value = pestrndup(at, length, 1);
+ if (!value) {
+ return 1;
+ }
+ {
+ char *header_name = client->current_header_name;
+ size_t header_name_len = client->current_header_name_len;
+ char c = header_name[header_name_len];
+ header_name[header_name_len] = '\0';
+ zend_hash_add(&client->request.headers, header_name, header_name_len + 1, &value, sizeof(char *), NULL);
+ header_name[header_name_len] = c;
+ }
+
+ if (client->current_header_name_allocated) {
+ pefree(client->current_header_name, 1);
+ client->current_header_name_allocated = 0;
+ }
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_headers_complete(php_http_parser *parser)
+{
+ php_cli_server_client *client = parser->data;
+ if (client->current_header_name_allocated) {
+ pefree(client->current_header_name, 1);
+ client->current_header_name_allocated = 0;
+ }
+ client->current_header_name = NULL;
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_body(php_http_parser *parser, const char *at, size_t length)
+{
+ php_cli_server_client *client = parser->data;
+ if (!client->request.content) {
+ client->request.content = pemalloc(parser->content_length, 1);
+ if (!client->request.content) {
+ return -1;
+ }
+ client->request.content_len = 0;
+ }
+ memmove(client->request.content + client->request.content_len, at, length);
+ client->request.content_len += length;
+ return 0;
+}
+
+static int php_cli_server_client_read_request_on_message_complete(php_http_parser *parser)
+{
+ php_cli_server_client *client = parser->data;
+ client->request.protocol_version = parser->http_major * 100 + parser->http_minor;
+ php_cli_server_request_translate_vpath(&client->request, client->server->document_root, client->server->document_root_len);
+ {
+ const char *vpath = client->request.vpath, *end = vpath + client->request.vpath_len, *p = end;
+ client->request.ext = end;
+ client->request.ext_len = 0;
+ while (p > vpath) {
+ --p;
+ if (*p == '.') {
+ ++p;
+ client->request.ext = p;
+ client->request.ext_len = end - p;
+ break;
+ }
+ }
+ }
+ client->request_read = 1;
+ return 0;
+}
+
+static int php_cli_server_client_read_request(php_cli_server_client *client, char **errstr TSRMLS_DC)
+{
+ char buf[16384];
+ static const php_http_parser_settings settings = {
+ php_cli_server_client_read_request_on_message_begin,
+ php_cli_server_client_read_request_on_path,
+ php_cli_server_client_read_request_on_query_string,
+ php_cli_server_client_read_request_on_url,
+ php_cli_server_client_read_request_on_fragment,
+ php_cli_server_client_read_request_on_header_field,
+ php_cli_server_client_read_request_on_header_value,
+ php_cli_server_client_read_request_on_headers_complete,
+ php_cli_server_client_read_request_on_body,
+ php_cli_server_client_read_request_on_message_complete
+ };
+ size_t nbytes_consumed;
+ int nbytes_read;
+ if (client->request_read) {
+ return 1;
+ }
+ nbytes_read = recv(client->sock, buf, sizeof(buf) - 1, 0);
+ if (nbytes_read < 0) {
+ int err = php_socket_errno();
+ if (err == SOCK_EAGAIN) {
+ return 0;
+ }
+ *errstr = php_socket_strerror(err, NULL, 0);
+ return -1;
+ } else if (nbytes_read == 0) {
+ *errstr = estrdup("Unexpected EOF");
+ return -1;
+ }
+ client->parser.data = client;
+ nbytes_consumed = php_http_parser_execute(&client->parser, &settings, buf, nbytes_read);
+ if (nbytes_consumed != nbytes_read) {
+ if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
+ *errstr = estrdup("Unsupported SSL request");
+ } else {
+ *errstr = estrdup("Malformed HTTP request");
+ }
+ return -1;
+ }
+ if (client->current_header_name) {
+ char *header_name = safe_pemalloc(client->current_header_name_len, 1, 1, 1);
+ if (!header_name) {
+ return -1;
+ }
+ memmove(header_name, client->current_header_name, client->current_header_name_len);
+ client->current_header_name = header_name;
+ client->current_header_name_allocated = 1;
+ }
+ return client->request_read ? 1: 0;
+}
+/* }}} */
+
+static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len) /* {{{ */
+{
+ struct timeval tv = { 10, 0 };
+ ssize_t nbytes_left = str_len;
+ do {
+ ssize_t nbytes_sent = send(client->sock, str + str_len - nbytes_left, nbytes_left, 0);
+ if (nbytes_sent < 0) {
+ int err = php_socket_errno();
+ if (err == SOCK_EAGAIN) {
+ int nfds = php_pollfd_for(client->sock, POLLOUT, &tv);
+ if (nfds > 0) {
+ continue;
+ } else if (nfds < 0) {
+ /* error */
+ php_handle_aborted_connection();
+ return nbytes_left;
+ } else {
+ /* timeout */
+ php_handle_aborted_connection();
+ return nbytes_left;
+ }
+ } else {
+ php_handle_aborted_connection();
+ return nbytes_left;
+ }
+ }
+ nbytes_left -= nbytes_sent;
+ } while (nbytes_left > 0);
+
+ return str_len;
+} /* }}} */
+
+static void php_cli_server_client_populate_request_info(const php_cli_server_client *client, sapi_request_info *request_info) /* {{{ */
+{
+ char **val;
+
+ request_info->request_method = php_http_method_str(client->request.request_method);
+ request_info->proto_num = client->request.protocol_version;
+ request_info->request_uri = client->request.request_uri;
+ request_info->path_translated = client->request.path_translated;
+ request_info->query_string = client->request.query_string;
+ request_info->post_data = client->request.content;
+ request_info->content_length = request_info->post_data_length = client->request.content_len;
+ request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL;
+ if (SUCCESS == zend_hash_find(&client->request.headers, "Content-Type", sizeof("Content-Type"), (void**)&val)) {
+ request_info->content_type = *val;
+ }
+} /* }}} */
+
+static void destroy_request_info(sapi_request_info *request_info) /* {{{ */
+{
+} /* }}} */
+
+static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_server *server, int client_sock, struct sockaddr *addr, socklen_t addr_len TSRMLS_DC) /* {{{ */
+{
+ client->server = server;
+ client->sock = client_sock;
+ client->addr = addr;
+ client->addr_len = addr_len;
+ {
+ char *addr_str = 0;
+ long addr_str_len = 0;
+ php_network_populate_name_from_sockaddr(addr, addr_len, &addr_str, &addr_str_len, NULL, 0 TSRMLS_CC);
+ client->addr_str = pestrndup(addr_str, addr_str_len, 1);
+ client->addr_str_len = addr_str_len;
+ efree(addr_str);
+ }
+ php_http_parser_init(&client->parser, PHP_HTTP_REQUEST);
+ client->request_read = 0;
+ client->current_header_name = NULL;
+ client->current_header_name_len = 0;
+ client->current_header_name_allocated = 0;
+ client->post_read_offset = 0;
+ if (FAILURE == php_cli_server_request_ctor(&client->request)) {
+ return FAILURE;
+ }
+ client->content_sender_initialized = 0;
+ client->file_fd = -1;
+ return SUCCESS;
+} /* }}} */
+
+static void php_cli_server_client_dtor(php_cli_server_client *client) /* {{{ */
+{
+ php_cli_server_request_dtor(&client->request);
+ if (client->file_fd >= 0) {
+ close(client->file_fd);
+ client->file_fd = -1;
+ }
+ pefree(client->addr, 1);
+ pefree(client->addr_str, 1);
+ if (client->content_sender_initialized) {
+ php_cli_server_content_sender_dtor(&client->content_sender);
+ }
+} /* }}} */
+
+static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+#ifdef DEBUG
+ php_cli_server_logf("%s Closing" TSRMLS_CC, client->addr_str);
+#endif
+ zend_hash_index_del(&server->clients, client->sock);
+} /* }}} */
+
+static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server_client *client, int status TSRMLS_DC) /* {{{ */
+{
+ char *escaped_request_uri = NULL;
+ size_t escaped_request_uri_len;
+ const char *status_string = get_status_string(status);
+ const char *content_template = get_template_string(status);
+ char *errstr = get_last_error();
+ assert(status_string && content_template);
+
+ php_cli_server_content_sender_ctor(&client->content_sender);
+ client->content_sender_initialized = 1;
+
+ escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, &escaped_request_uri_len, 0, ENT_QUOTES, NULL, 0 TSRMLS_CC);
+
+ {
+ static const char prologue_template[] = "<!doctype html><html><head><title>%d %s</title>";
+ php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1);
+ if (!chunk) {
+ goto fail;
+ }
+ snprintf(chunk->data.heap.p, chunk->data.heap.len, prologue_template, status, status_string, escaped_request_uri);
+ chunk->data.heap.len = strlen(chunk->data.heap.p);
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
+ }
+ {
+ php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(php_cli_server_css, sizeof(php_cli_server_css) - 1);
+ if (!chunk) {
+ goto fail;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
+ }
+ {
+ static const char template[] = "</head><body>";
+ php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(template, sizeof(template) - 1);
+ if (!chunk) {
+ goto fail;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
+ }
+ {
+ php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(content_template) + escaped_request_uri_len + 3 + strlen(status_string) + 1);
+ if (!chunk) {
+ goto fail;
+ }
+ snprintf(chunk->data.heap.p, chunk->data.heap.len, content_template, status_string, escaped_request_uri);
+ chunk->data.heap.len = strlen(chunk->data.heap.p);
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
+ }
+ {
+ static const char epilogue_template[] = "</body></html>";
+ php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(epilogue_template, sizeof(epilogue_template) - 1);
+ if (!chunk) {
+ goto fail;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
+ }
+
+ {
+ php_cli_server_chunk *chunk;
+ smart_str buffer = { 0 };
+ append_http_status_line(&buffer, client->request.protocol_version, status, 1);
+ if (!buffer.c) {
+ /* out of memory */
+ goto fail;
+ }
+ append_essential_headers(&buffer, client, 1);
+ smart_str_appends_ex(&buffer, "Content-Type: text/html; charset=UTF-8\r\n", 1);
+ smart_str_appends_ex(&buffer, "Content-Length: ", 1);
+ smart_str_append_generic_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1, size_t, _unsigned);
+ smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+ smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+
+ chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len);
+ if (!chunk) {
+ smart_str_free_ex(&buffer, 1);
+ goto fail;
+ }
+ php_cli_server_buffer_prepend(&client->content_sender.buffer, chunk);
+ }
+
+ php_cli_server_log_response(client, status, errstr ? errstr : "?" TSRMLS_CC);
+ php_cli_server_poller_add(&server->poller, POLLOUT, client->sock);
+ if (errstr) {
+ pefree(errstr, 1);
+ }
+ efree(escaped_request_uri);
+ return SUCCESS;
+
+fail:
+ if (errstr) {
+ pefree(errstr, 1);
+ }
+ efree(escaped_request_uri);
+ return FAILURE;
+} /* }}} */
+
+static int php_cli_server_dispatch_script(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+ if (strlen(client->request.path_translated) != client->request.path_translated_len) {
+ /* can't handle paths that contain nul bytes */
+ return php_cli_server_send_error_page(server, client, 400 TSRMLS_CC);
+ }
+ {
+ zend_file_handle zfd;
+ zfd.type = ZEND_HANDLE_FILENAME;
+ zfd.filename = SG(request_info).path_translated;
+ zfd.handle.fp = NULL;
+ zfd.free_filename = 0;
+ zfd.opened_path = NULL;
+ zend_try {
+ php_execute_script(&zfd TSRMLS_CC);
+ } zend_end_try();
+ }
+
+ php_cli_server_log_response(client, SG(sapi_headers).http_response_code, NULL TSRMLS_CC);
+ return SUCCESS;
+} /* }}} */
+
+static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+ int fd;
+ int status = 200;
+
+ if (client->request.path_translated && strlen(client->request.path_translated) != client->request.path_translated_len) {
+ /* can't handle paths that contain nul bytes */
+ return php_cli_server_send_error_page(server, client, 400 TSRMLS_CC);
+ }
+
+ fd = client->request.path_translated ? open(client->request.path_translated, O_RDONLY): -1;
+ if (fd < 0) {
+ return php_cli_server_send_error_page(server, client, 404 TSRMLS_CC);
+ }
+
+ php_cli_server_content_sender_ctor(&client->content_sender);
+ client->content_sender_initialized = 1;
+ client->file_fd = fd;
+
+ {
+ php_cli_server_chunk *chunk;
+ smart_str buffer = { 0 };
+ const char *mime_type = get_mime_type(client->request.ext, client->request.ext_len);
+ if (!mime_type) {
+ mime_type = "application/octet-stream";
+ }
+
+ append_http_status_line(&buffer, client->request.protocol_version, status, 1);
+ if (!buffer.c) {
+ /* out of memory */
+ php_cli_server_log_response(client, 500, NULL TSRMLS_CC);
+ return FAILURE;
+ }
+ append_essential_headers(&buffer, client, 1);
+ smart_str_appendl_ex(&buffer, "Content-Type: ", sizeof("Content-Type: ") - 1, 1);
+ smart_str_appends_ex(&buffer, mime_type, 1);
+ if (strncmp(mime_type, "text/", 5) == 0) {
+ smart_str_appends_ex(&buffer, "; charset=UTF-8", 1);
+ }
+ smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+ smart_str_appends_ex(&buffer, "Content-Length: ", 1);
+ smart_str_append_generic_ex(&buffer, client->request.sb.st_size, 1, size_t, _unsigned);
+ smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+ smart_str_appendl_ex(&buffer, "\r\n", 2, 1);
+ chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len);
+ if (!chunk) {
+ smart_str_free_ex(&buffer, 1);
+ php_cli_server_log_response(client, 500, NULL TSRMLS_CC);
+ return FAILURE;
+ }
+ php_cli_server_buffer_append(&client->content_sender.buffer, chunk);
+ }
+ php_cli_server_log_response(client, 200, NULL TSRMLS_CC);
+ php_cli_server_poller_add(&server->poller, POLLOUT, client->sock);
+ return SUCCESS;
+}
+/* }}} */
+
+static int php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) { /* {{{ */
+ char **auth;
+ php_cli_server_client_populate_request_info(client, &SG(request_info));
+ if (SUCCESS == zend_hash_find(&client->request.headers, "Authorization", sizeof("Authorization"), (void**)&auth)) {
+ php_handle_auth_data(*auth TSRMLS_CC);
+ }
+ SG(sapi_headers).http_response_code = 200;
+ if (FAILURE == php_request_startup(TSRMLS_C)) {
+ /* should never be happen */
+ destroy_request_info(&SG(request_info));
+ return FAILURE;
+ }
+ PG(during_request_startup) = 0;
+
+ return SUCCESS;
+}
+/* }}} */
+
+static int php_cli_server_request_shutdown(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) { /* {{{ */
+ php_request_shutdown(0);
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ destroy_request_info(&SG(request_info));
+ SG(server_context) = NULL;
+ SG(rfc1867_uploaded_files) = NULL;
+ return SUCCESS;
+}
+/* }}} */
+
+static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+ int decline = 0;
+ if (!php_handle_special_queries(TSRMLS_C)) {
+ zend_file_handle zfd;
+ char *old_cwd;
+
+ ALLOCA_FLAG(use_heap)
+ old_cwd = do_alloca(MAXPATHLEN, use_heap);
+ old_cwd[0] = '\0';
+ php_ignore_value(VCWD_GETCWD(old_cwd, MAXPATHLEN - 1));
+
+ zfd.type = ZEND_HANDLE_FILENAME;
+ zfd.filename = server->router;
+ zfd.handle.fp = NULL;
+ zfd.free_filename = 0;
+ zfd.opened_path = NULL;
+
+ zend_try {
+ zval *retval = NULL;
+ if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, &retval, 1, &zfd)) {
+ if (retval) {
+ decline = Z_TYPE_P(retval) == IS_BOOL && !Z_LVAL_P(retval);
+ zval_ptr_dtor(&retval);
+ }
+ } else {
+ decline = 1;
+ }
+ } zend_end_try();
+
+ if (old_cwd[0] != '\0') {
+ php_ignore_value(VCWD_CHDIR(old_cwd));
+ }
+
+ free_alloca(old_cwd, use_heap);
+ }
+
+ return decline;
+}
+/* }}} */
+
+static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+ int is_static_file = 0;
+
+ SG(server_context) = client;
+ if (client->request.ext_len != 3 || memcmp(client->request.ext, "php", 3) || !client->request.path_translated) {
+ is_static_file = 1;
+ }
+
+ if (server->router || !is_static_file) {
+ if (FAILURE == php_cli_server_request_startup(server, client TSRMLS_CC)) {
+ SG(server_context) = NULL;
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ destroy_request_info(&SG(request_info));
+ return SUCCESS;
+ }
+ }
+
+ if (server->router) {
+ if (!php_cli_server_dispatch_router(server, client TSRMLS_CC)) {
+ php_cli_server_request_shutdown(server, client TSRMLS_CC);
+ return SUCCESS;
+ }
+ }
+
+ if (!is_static_file) {
+ if (SUCCESS == php_cli_server_dispatch_script(server, client TSRMLS_CC)
+ || SUCCESS != php_cli_server_send_error_page(server, client, 500 TSRMLS_CC)) {
+ php_cli_server_request_shutdown(server, client TSRMLS_CC);
+ return SUCCESS;
+ }
+ } else {
+ if (server->router) {
+ static int (*send_header_func)(sapi_headers_struct * TSRMLS_DC);
+ send_header_func = sapi_module.send_headers;
+ /* do not generate default content type header */
+ SG(sapi_headers).send_default_content_type = 0;
+ /* we don't want headers to be sent */
+ sapi_module.send_headers = sapi_cli_server_discard_headers;
+ php_request_shutdown(0);
+ sapi_module.send_headers = send_header_func;
+ SG(sapi_headers).send_default_content_type = 1;
+ SG(rfc1867_uploaded_files) = NULL;
+ }
+ if (SUCCESS != php_cli_server_begin_send_static(server, client TSRMLS_CC)) {
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ }
+ SG(server_context) = NULL;
+ return SUCCESS;
+ }
+
+ SG(server_context) = NULL;
+ destroy_request_info(&SG(request_info));
+ return SUCCESS;
+}
+/* }}} */
+
+static void php_cli_server_dtor(php_cli_server *server TSRMLS_DC) /* {{{ */
+{
+ zend_hash_destroy(&server->clients);
+ if (server->server_sock >= 0) {
+ closesocket(server->server_sock);
+ }
+ if (server->host) {
+ pefree(server->host, 1);
+ }
+ if (server->document_root) {
+ pefree(server->document_root, 1);
+ }
+ if (server->router) {
+ pefree(server->router, 1);
+ }
+} /* }}} */
+
+static void php_cli_server_client_dtor_wrapper(php_cli_server_client **p) /* {{{ */
+{
+ closesocket((*p)->sock);
+ php_cli_server_poller_remove(&(*p)->server->poller, POLLIN | POLLOUT, (*p)->sock);
+ php_cli_server_client_dtor(*p);
+ pefree(*p, 1);
+} /* }}} */
+
+static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router TSRMLS_DC) /* {{{ */
+{
+ int retval = SUCCESS;
+ char *host = NULL;
+ char *errstr = NULL;
+ char *_document_root = NULL;
+ char *_router = NULL;
+ int err = 0;
+ int port = 3000;
+ php_socket_t server_sock = SOCK_ERR;
+ char *p = NULL;
+
+ if (addr[0] == '[') {
+ host = pestrdup(addr + 1, 1);
+ if (!host) {
+ return FAILURE;
+ }
+ p = strchr(host, ']');
+ if (p) {
+ *p++ = '\0';
+ if (*p == ':') {
+ port = strtol(p + 1, &p, 10);
+ if (port <= 0) {
+ p = NULL;
+ }
+ } else if (*p != '\0') {
+ p = NULL;
+ }
+ }
+ } else {
+ host = pestrdup(addr, 1);
+ if (!host) {
+ return FAILURE;
+ }
+ p = strchr(host, ':');
+ if (p) {
+ *p++ = '\0';
+ port = strtol(p, &p, 10);
+ if (port <= 0) {
+ p = NULL;
+ }
+ }
+ }
+ if (!p) {
+ fprintf(stderr, "Invalid address: %s\n", addr);
+ retval = FAILURE;
+ goto out;
+ }
+
+ server_sock = php_network_listen_socket(host, &port, SOCK_STREAM, &server->address_family, &server->socklen, &errstr TSRMLS_CC);
+ if (server_sock == SOCK_ERR) {
+ php_cli_server_logf("Failed to listen on %s:%d (reason: %s)" TSRMLS_CC, host, port, errstr ? errstr: "?");
+ efree(errstr);
+ retval = FAILURE;
+ goto out;
+ }
+ server->server_sock = server_sock;
+
+ err = php_cli_server_poller_ctor(&server->poller);
+ if (SUCCESS != err) {
+ goto out;
+ }
+
+ php_cli_server_poller_add(&server->poller, POLLIN, server_sock);
+
+ server->host = host;
+ server->port = port;
+
+ zend_hash_init(&server->clients, 0, NULL, (void(*)(void*))php_cli_server_client_dtor_wrapper, 1);
+
+ {
+ size_t document_root_len = strlen(document_root);
+ _document_root = pestrndup(document_root, document_root_len, 1);
+ if (!_document_root) {
+ retval = FAILURE;
+ goto out;
+ }
+ server->document_root = _document_root;
+ server->document_root_len = document_root_len;
+ }
+
+ if (router) {
+ size_t router_len = strlen(router);
+ _router = pestrndup(router, router_len, 1);
+ if (!_router) {
+ retval = FAILURE;
+ goto out;
+ }
+ server->router = _router;
+ server->router_len = router_len;
+ } else {
+ server->router = NULL;
+ server->router_len = 0;
+ }
+
+ server->is_running = 1;
+out:
+ if (retval != SUCCESS) {
+ if (host) {
+ pefree(host, 1);
+ }
+ if (_document_root) {
+ pefree(_document_root, 1);
+ }
+ if (_router) {
+ pefree(_router, 1);
+ }
+ if (server_sock >= -1) {
+ closesocket(server_sock);
+ }
+ }
+ return retval;
+} /* }}} */
+
+static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+ char *errstr = NULL;
+ int status = php_cli_server_client_read_request(client, &errstr TSRMLS_CC);
+ if (status < 0) {
+ php_cli_server_logf("%s Invalid request (%s)" TSRMLS_CC, client->addr_str, errstr);
+ efree(errstr);
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ return FAILURE;
+ } else if (status == 1 && client->request.request_method == PHP_HTTP_NOT_IMPLEMENTED) {
+ return php_cli_server_send_error_page(server, client, 501 TSRMLS_CC);
+ } else if (status == 1) {
+ php_cli_server_poller_remove(&server->poller, POLLIN, client->sock);
+ php_cli_server_dispatch(server, client TSRMLS_CC);
+ } else {
+ php_cli_server_poller_add(&server->poller, POLLIN, client->sock);
+ }
+
+ return SUCCESS;
+} /* }}} */
+
+static int php_cli_server_send_event(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */
+{
+ if (client->content_sender_initialized) {
+ if (client->file_fd >= 0 && !client->content_sender.buffer.first) {
+ size_t nbytes_read;
+ if (php_cli_server_content_sender_pull(&client->content_sender, client->file_fd, &nbytes_read)) {
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ return FAILURE;
+ }
+ if (nbytes_read == 0) {
+ close(client->file_fd);
+ client->file_fd = -1;
+ }
+ }
+ {
+ size_t nbytes_sent;
+ int err = php_cli_server_content_sender_send(&client->content_sender, client->sock, &nbytes_sent);
+ if (err && err != SOCK_EAGAIN) {
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ return FAILURE;
+ }
+ }
+ if (!client->content_sender.buffer.first && client->file_fd < 0) {
+ php_cli_server_close_connection(server, client TSRMLS_CC);
+ }
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+typedef struct php_cli_server_do_event_for_each_fd_callback_params {
+#ifdef ZTS
+ void ***tsrm_ls;
+#endif
+ php_cli_server *server;
+ int(*rhandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC);
+ int(*whandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC);
+} php_cli_server_do_event_for_each_fd_callback_params;
+
+static int php_cli_server_do_event_for_each_fd_callback(void *_params, int fd, int event) /* {{{ */
+{
+ php_cli_server_do_event_for_each_fd_callback_params *params = _params;
+#ifdef ZTS
+ void ***tsrm_ls = params->tsrm_ls;
+#endif
+ php_cli_server *server = params->server;
+ if (server->server_sock == fd) {
+ php_cli_server_client *client = NULL;
+ php_socket_t client_sock;
+ socklen_t socklen = server->socklen;
+ struct sockaddr *sa = pemalloc(server->socklen, 1);
+ if (!sa) {
+ return FAILURE;
+ }
+ client_sock = accept(server->server_sock, sa, &socklen);
+ if (client_sock < 0) {
+ char *errstr;
+ errstr = php_socket_strerror(php_socket_errno(), NULL, 0);
+ php_cli_server_logf("Failed to accept a client (reason: %s)" TSRMLS_CC, errstr);
+ efree(errstr);
+ pefree(sa, 1);
+ return SUCCESS;
+ }
+ if (SUCCESS != php_set_sock_blocking(client_sock, 0 TSRMLS_CC)) {
+ pefree(sa, 1);
+ closesocket(client_sock);
+ return SUCCESS;
+ }
+ if (!(client = pemalloc(sizeof(php_cli_server_client), 1)) || FAILURE == php_cli_server_client_ctor(client, server, client_sock, sa, socklen TSRMLS_CC)) {
+ php_cli_server_logf("Failed to create a new request object" TSRMLS_CC);
+ pefree(sa, 1);
+ closesocket(client_sock);
+ return SUCCESS;
+ }
+#ifdef DEBUG
+ php_cli_server_logf("%s Accepted" TSRMLS_CC, client->addr_str);
+#endif
+ zend_hash_index_update(&server->clients, client_sock, &client, sizeof(client), NULL);
+ php_cli_server_recv_event_read_request(server, client TSRMLS_CC);
+ } else {
+ php_cli_server_client **client;
+ if (SUCCESS == zend_hash_index_find(&server->clients, fd, (void **)&client)) {
+ if (event & POLLIN) {
+ params->rhandler(server, *client TSRMLS_CC);
+ }
+ if (event & POLLOUT) {
+ params->whandler(server, *client TSRMLS_CC);
+ }
+ }
+ }
+ return SUCCESS;
+} /* }}} */
+
+static void php_cli_server_do_event_for_each_fd(php_cli_server *server, int(*rhandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC), int(*whandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC) TSRMLS_DC) /* {{{ */
+{
+ php_cli_server_do_event_for_each_fd_callback_params params = {
+#ifdef ZTS
+ tsrm_ls,
+#endif
+ server,
+ rhandler,
+ whandler
+ };
+
+ php_cli_server_poller_iter_on_active(&server->poller, &params, php_cli_server_do_event_for_each_fd_callback);
+} /* }}} */
+
+static int php_cli_server_do_event_loop(php_cli_server *server TSRMLS_DC) /* {{{ */
+{
+ int retval = SUCCESS;
+ while (server->is_running) {
+ static const struct timeval tv = { 1, 0 };
+ int n = php_cli_server_poller_poll(&server->poller, &tv);
+ if (n > 0) {
+ php_cli_server_do_event_for_each_fd(server,
+ php_cli_server_recv_event_read_request,
+ php_cli_server_send_event TSRMLS_CC);
+ } else if (n == 0) {
+ /* do nothing */
+ } else {
+ int err = php_socket_errno();
+ if (err != SOCK_EINTR) {
+ char *errstr = php_socket_strerror(err, NULL, 0);
+ php_cli_server_logf("%s" TSRMLS_CC, errstr);
+ efree(errstr);
+ retval = FAILURE;
+ goto out;
+ }
+ }
+ }
+out:
+ return retval;
+} /* }}} */
+
+static php_cli_server server;
+
+static void php_cli_server_sigint_handler(int sig) /* {{{ */
+{
+ server.is_running = 0;
+}
+/* }}} */
+
+int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */
+{
+ char *php_optarg = NULL;
+ int php_optind = 1;
+ int c;
+ const char *server_bind_address = NULL;
+ extern const opt_struct OPTIONS[];
+ const char *document_root = NULL;
+ const char *router = NULL;
+ char document_root_buf[MAXPATHLEN];
+
+ while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2))!=-1) {
+ switch (c) {
+ case 'S':
+ server_bind_address = php_optarg;
+ break;
+ case 't':
+ document_root = php_optarg;
+ break;
+ }
+ }
+
+ if (document_root) {
+ struct stat sb;
+
+ if (stat(document_root, &sb)) {
+ fprintf(stderr, "Directory %s does not exist.\n", document_root);
+ return 1;
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ fprintf(stderr, "%s is not a directory.\n", document_root);
+ return 1;
+ }
+ if (VCWD_REALPATH(document_root, document_root_buf)) {
+ document_root = document_root_buf;
+ }
+ } else {
+ char *ret = NULL;
+
+#if HAVE_GETCWD
+ ret = VCWD_GETCWD(document_root_buf, MAXPATHLEN);
+#elif HAVE_GETWD
+ ret = VCWD_GETWD(document_root_buf);
+#endif
+ document_root = ret ? document_root_buf: ".";
+ }
+
+ if (argc > php_optind) {
+ router = argv[php_optind];
+ }
+
+ if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root, router TSRMLS_CC)) {
+ return 1;
+ }
+ sapi_module.phpinfo_as_text = 0;
+
+ {
+ struct timeval tv;
+ struct tm tm;
+ char buf[52];
+ gettimeofday(&tv, NULL);
+ php_localtime_r(&tv.tv_sec, &tm);
+ php_asctime_r(&tm, buf);
+ printf("PHP %s Development Server started at %s"
+ "Listening on http://%s\n"
+ "Document root is %s\n"
+ "Press Ctrl-C to quit.\n",
+ PHP_VERSION, buf, server_bind_address, document_root);
+ }
+
+#if defined(HAVE_SIGNAL_H) && defined(SIGINT)
+ signal(SIGINT, php_cli_server_sigint_handler);
+#endif
+ php_cli_server_do_event_loop(&server TSRMLS_CC);
+ php_cli_server_dtor(&server TSRMLS_CC);
+ return 0;
+} /* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/hash/php_hash_salsa.h b/sapi/cli/php_cli_server.h
index 10921597c2..889ebf6f74 100644
--- a/ext/hash/php_hash_salsa.h
+++ b/sapi/cli/php_cli_server.h
@@ -12,40 +12,37 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Michael Wallner <mike@php.net> |
+ | Author: Moriyoshi Koizumi <moriyoshi@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id$ */
+/* $Id: php_cli.c 306938 2011-01-01 02:17:06Z felipe $ */
-#ifndef PHP_HASH_SALSA_H
-#define PHP_HASH_SALSA_H
+#ifndef PHP_CLI_SERVER_H
+#define PHP_CLI_SERVER_H
-#include "ext/standard/basic_functions.h"
+#include "SAPI.h"
-/* SALSA context */
-typedef struct {
- php_hash_uint32 state[16];
- unsigned char init:1;
- unsigned char length:7;
- unsigned char buffer[64];
- void (*Transform)(php_hash_uint32 state[16], php_hash_uint32 data[16]);
-} PHP_SALSA_CTX;
+extern sapi_module_struct cli_server_sapi_module;
+extern int do_cli_server(int argc, char **argv TSRMLS_DC);
-#define PHP_SALSAInit PHP_SALSA20Init
-PHP_HASH_API void PHP_SALSA10Init(PHP_SALSA_CTX *);
-PHP_HASH_API void PHP_SALSA20Init(PHP_SALSA_CTX *);
-
-PHP_HASH_API void PHP_SALSAUpdate(PHP_SALSA_CTX *, const unsigned char *, size_t);
-PHP_HASH_API void PHP_SALSAFinal(unsigned char[64], PHP_SALSA_CTX *);
+ZEND_BEGIN_MODULE_GLOBALS(cli_server)
+ short color;
+ZEND_END_MODULE_GLOBALS(cli_server)
+#ifdef ZTS
+#define CLI_SERVER_G(v) TSRMG(cli_server_globals_id, zend_cli_server_globals *, v)
+#else
+#define CLI_SERVER_G(v) (cli_server_globals.v)
#endif
+#endif /* PHP_CLI_SERVER_H */
+
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
*/
diff --git a/sapi/cli/php_http_parser.c b/sapi/cli/php_http_parser.c
new file mode 100644
index 0000000000..d3bc496f4e
--- /dev/null
+++ b/sapi/cli/php_http_parser.c
@@ -0,0 +1,1608 @@
+/* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <assert.h>
+#include <stddef.h>
+#include "php_http_parser.h"
+
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#define CALLBACK2(FOR) \
+do { \
+ if (settings->on_##FOR) { \
+ if (0 != settings->on_##FOR(parser)) return (p - data); \
+ } \
+} while (0)
+
+
+#define MARK(FOR) \
+do { \
+ FOR##_mark = p; \
+} while (0)
+
+#define CALLBACK_NOCLEAR(FOR) \
+do { \
+ if (FOR##_mark) { \
+ if (settings->on_##FOR) { \
+ if (0 != settings->on_##FOR(parser, \
+ FOR##_mark, \
+ p - FOR##_mark)) \
+ { \
+ return (p - data); \
+ } \
+ } \
+ } \
+} while (0)
+
+#ifdef PHP_WIN32
+# undef CALLBACK
+#endif
+#define CALLBACK(FOR) \
+do { \
+ CALLBACK_NOCLEAR(FOR); \
+ FOR##_mark = NULL; \
+} while (0)
+
+
+#define PROXY_CONNECTION "proxy-connection"
+#define CONNECTION "connection"
+#define CONTENT_LENGTH "content-length"
+#define TRANSFER_ENCODING "transfer-encoding"
+#define UPGRADE "upgrade"
+#define CHUNKED "chunked"
+#define KEEP_ALIVE "keep-alive"
+#define CLOSE "close"
+
+
+static const char *method_strings[] =
+ { "DELETE"
+ , "GET"
+ , "HEAD"
+ , "POST"
+ , "PUT"
+ , "PATCH"
+ , "CONNECT"
+ , "OPTIONS"
+ , "TRACE"
+ , "COPY"
+ , "LOCK"
+ , "MKCOL"
+ , "MOVE"
+ , "PROPFIND"
+ , "PROPPATCH"
+ , "UNLOCK"
+ , "REPORT"
+ , "MKACTIVITY"
+ , "CHECKOUT"
+ , "MERGE"
+ , "M-SEARCH"
+ , "NOTIFY"
+ , "SUBSCRIBE"
+ , "UNSUBSCRIBE"
+ , "NOTIMPLEMENTED"
+ };
+
+
+/* Tokens as defined by rfc 2616. Also lowercases them.
+ * token = 1*<any CHAR except CTLs or separators>
+ * separators = "(" | ")" | "<" | ">" | "@"
+ * | "," | ";" | ":" | "\" | <">
+ * | "/" | "[" | "]" | "?" | "="
+ * | "{" | "}" | SP | HT
+ */
+static const char tokens[256] = {
+/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+ 0, 0, '*', '+', 0, '-', '.', '/',
+/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+ '0', '1', '2', '3', '4', '5', '6', '7',
+/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+ '8', '9', 0, 0, 0, 0, 0, 0,
+/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+ 'x', 'y', 'z', 0, 0, 0, '^', '_',
+/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+ 'x', 'y', 'z', 0, '|', '}', '~', 0 };
+
+
+static const int8_t unhex[256] =
+ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+ };
+
+
+static const uint8_t normal_url_char[256] = {
+/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+ 0, 1, 1, 0, 1, 1, 1, 1,
+/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+ 1, 1, 1, 1, 1, 1, 1, 0,
+/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+ 1, 1, 1, 1, 1, 1, 1, 1,
+/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+ 1, 1, 1, 1, 1, 1, 1, 0 };
+
+
+enum state
+ { s_dead = 1 /* important that this is > 0 */
+
+ , s_start_req_or_res
+ , s_res_or_resp_H
+ , s_start_res
+ , s_res_H
+ , s_res_HT
+ , s_res_HTT
+ , s_res_HTTP
+ , s_res_first_http_major
+ , s_res_http_major
+ , s_res_first_http_minor
+ , s_res_http_minor
+ , s_res_first_status_code
+ , s_res_status_code
+ , s_res_status
+ , s_res_line_almost_done
+
+ , s_start_req
+
+ , s_req_method
+ , s_req_spaces_before_url
+ , s_req_schema
+ , s_req_schema_slash
+ , s_req_schema_slash_slash
+ , s_req_host
+ , s_req_port
+ , s_req_path
+ , s_req_query_string_start
+ , s_req_query_string
+ , s_req_fragment_start
+ , s_req_fragment
+ , s_req_http_start
+ , s_req_http_H
+ , s_req_http_HT
+ , s_req_http_HTT
+ , s_req_http_HTTP
+ , s_req_first_http_major
+ , s_req_http_major
+ , s_req_first_http_minor
+ , s_req_http_minor
+ , s_req_line_almost_done
+
+ , s_header_field_start
+ , s_header_field
+ , s_header_value_start
+ , s_header_value
+
+ , s_header_almost_done
+
+ , s_headers_almost_done
+ /* Important: 's_headers_almost_done' must be the last 'header' state. All
+ * states beyond this must be 'body' states. It is used for overflow
+ * checking. See the PARSING_HEADER() macro.
+ */
+ , s_chunk_size_start
+ , s_chunk_size
+ , s_chunk_size_almost_done
+ , s_chunk_parameters
+ , s_chunk_data
+ , s_chunk_data_almost_done
+ , s_chunk_data_done
+
+ , s_body_identity
+ , s_body_identity_eof
+ };
+
+
+#define PARSING_HEADER(state) (state <= s_headers_almost_done && 0 == (parser->flags & F_TRAILING))
+
+
+enum header_states
+ { h_general = 0
+ , h_C
+ , h_CO
+ , h_CON
+
+ , h_matching_connection
+ , h_matching_proxy_connection
+ , h_matching_content_length
+ , h_matching_transfer_encoding
+ , h_matching_upgrade
+
+ , h_connection
+ , h_content_length
+ , h_transfer_encoding
+ , h_upgrade
+
+ , h_matching_transfer_encoding_chunked
+ , h_matching_connection_keep_alive
+ , h_matching_connection_close
+
+ , h_transfer_encoding_chunked
+ , h_connection_keep_alive
+ , h_connection_close
+ };
+
+
+enum flags
+ { F_CHUNKED = 1 << 0
+ , F_CONNECTION_KEEP_ALIVE = 1 << 1
+ , F_CONNECTION_CLOSE = 1 << 2
+ , F_TRAILING = 1 << 3
+ , F_UPGRADE = 1 << 4
+ , F_SKIPBODY = 1 << 5
+ };
+
+
+#define CR '\r'
+#define LF '\n'
+#define LOWER(c) (unsigned char)(c | 0x20)
+#define TOKEN(c) tokens[(unsigned char)c]
+
+
+#define start_state (parser->type == PHP_HTTP_REQUEST ? s_start_req : s_start_res)
+
+
+#if HTTP_PARSER_STRICT
+# define STRICT_CHECK(cond) if (cond) goto error
+# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
+#else
+# define STRICT_CHECK(cond)
+# define NEW_MESSAGE() start_state
+#endif
+
+
+size_t php_http_parser_execute (php_http_parser *parser,
+ const php_http_parser_settings *settings,
+ const char *data,
+ size_t len)
+{
+ char c, ch;
+ const char *p = data, *pe;
+ size_t to_read;
+
+ enum state state = (enum state) parser->state;
+ enum header_states header_state = (enum header_states) parser->header_state;
+ uint32_t index = parser->index;
+ uint32_t nread = parser->nread;
+
+ /* technically we could combine all of these (except for url_mark) into one
+ variable, saving stack space, but it seems more clear to have them
+ separated. */
+ const char *header_field_mark = 0;
+ const char *header_value_mark = 0;
+ const char *fragment_mark = 0;
+ const char *query_string_mark = 0;
+ const char *path_mark = 0;
+ const char *url_mark = 0;
+
+ if (len == 0) {
+ if (state == s_body_identity_eof) {
+ CALLBACK2(message_complete);
+ }
+ return 0;
+ }
+
+ if (state == s_header_field)
+ header_field_mark = data;
+ if (state == s_header_value)
+ header_value_mark = data;
+ if (state == s_req_fragment)
+ fragment_mark = data;
+ if (state == s_req_query_string)
+ query_string_mark = data;
+ if (state == s_req_path)
+ path_mark = data;
+ if (state == s_req_path || state == s_req_schema || state == s_req_schema_slash
+ || state == s_req_schema_slash_slash || state == s_req_port
+ || state == s_req_query_string_start || state == s_req_query_string
+ || state == s_req_host
+ || state == s_req_fragment_start || state == s_req_fragment)
+ url_mark = data;
+
+ for (p=data, pe=data+len; p != pe; p++) {
+ ch = *p;
+
+ if (PARSING_HEADER(state)) {
+ ++nread;
+ /* Buffer overflow attack */
+ if (nread > PHP_HTTP_MAX_HEADER_SIZE) goto error;
+ }
+
+ switch (state) {
+
+ case s_dead:
+ /* this state is used after a 'Connection: close' message
+ * the parser will error out if it reads another message
+ */
+ goto error;
+
+ case s_start_req_or_res:
+ {
+ if (ch == CR || ch == LF)
+ break;
+ parser->flags = 0;
+ parser->content_length = -1;
+
+ CALLBACK2(message_begin);
+
+ if (ch == 'H')
+ state = s_res_or_resp_H;
+ else {
+ parser->type = PHP_HTTP_REQUEST;
+ goto start_req_method_assign;
+ }
+ break;
+ }
+
+ case s_res_or_resp_H:
+ if (ch == 'T') {
+ parser->type = PHP_HTTP_RESPONSE;
+ state = s_res_HT;
+ } else {
+ if (ch != 'E') goto error;
+ parser->type = PHP_HTTP_REQUEST;
+ parser->method = PHP_HTTP_HEAD;
+ index = 2;
+ state = s_req_method;
+ }
+ break;
+
+ case s_start_res:
+ {
+ parser->flags = 0;
+ parser->content_length = -1;
+
+ CALLBACK2(message_begin);
+
+ switch (ch) {
+ case 'H':
+ state = s_res_H;
+ break;
+
+ case CR:
+ case LF:
+ break;
+
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_res_H:
+ STRICT_CHECK(ch != 'T');
+ state = s_res_HT;
+ break;
+
+ case s_res_HT:
+ STRICT_CHECK(ch != 'T');
+ state = s_res_HTT;
+ break;
+
+ case s_res_HTT:
+ STRICT_CHECK(ch != 'P');
+ state = s_res_HTTP;
+ break;
+
+ case s_res_HTTP:
+ STRICT_CHECK(ch != '/');
+ state = s_res_first_http_major;
+ break;
+
+ case s_res_first_http_major:
+ if (ch < '1' || ch > '9') goto error;
+ parser->http_major = ch - '0';
+ state = s_res_http_major;
+ break;
+
+ /* major HTTP version or dot */
+ case s_res_http_major:
+ {
+ if (ch == '.') {
+ state = s_res_first_http_minor;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') goto error;
+
+ parser->http_major *= 10;
+ parser->http_major += ch - '0';
+
+ if (parser->http_major > 999) goto error;
+ break;
+ }
+
+ /* first digit of minor HTTP version */
+ case s_res_first_http_minor:
+ if (ch < '0' || ch > '9') goto error;
+ parser->http_minor = ch - '0';
+ state = s_res_http_minor;
+ break;
+
+ /* minor HTTP version or end of request line */
+ case s_res_http_minor:
+ {
+ if (ch == ' ') {
+ state = s_res_first_status_code;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') goto error;
+
+ parser->http_minor *= 10;
+ parser->http_minor += ch - '0';
+
+ if (parser->http_minor > 999) goto error;
+ break;
+ }
+
+ case s_res_first_status_code:
+ {
+ if (ch < '0' || ch > '9') {
+ if (ch == ' ') {
+ break;
+ }
+ goto error;
+ }
+ parser->status_code = ch - '0';
+ state = s_res_status_code;
+ break;
+ }
+
+ case s_res_status_code:
+ {
+ if (ch < '0' || ch > '9') {
+ switch (ch) {
+ case ' ':
+ state = s_res_status;
+ break;
+ case CR:
+ state = s_res_line_almost_done;
+ break;
+ case LF:
+ state = s_header_field_start;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ parser->status_code *= 10;
+ parser->status_code += ch - '0';
+
+ if (parser->status_code > 999) goto error;
+ break;
+ }
+
+ case s_res_status:
+ /* the human readable status. e.g. "NOT FOUND"
+ * we are not humans so just ignore this */
+ if (ch == CR) {
+ state = s_res_line_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ state = s_header_field_start;
+ break;
+ }
+ break;
+
+ case s_res_line_almost_done:
+ STRICT_CHECK(ch != LF);
+ state = s_header_field_start;
+ break;
+
+ case s_start_req:
+ {
+ if (ch == CR || ch == LF)
+ break;
+ parser->flags = 0;
+ parser->content_length = -1;
+
+ CALLBACK2(message_begin);
+
+ if (ch < 'A' || 'Z' < ch) goto error;
+
+ start_req_method_assign:
+ parser->method = (enum php_http_method) 0;
+ index = 1;
+ switch (ch) {
+ case 'C': parser->method = PHP_HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
+ case 'D': parser->method = PHP_HTTP_DELETE; break;
+ case 'G': parser->method = PHP_HTTP_GET; break;
+ case 'H': parser->method = PHP_HTTP_HEAD; break;
+ case 'L': parser->method = PHP_HTTP_LOCK; break;
+ case 'M': parser->method = PHP_HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break;
+ case 'N': parser->method = PHP_HTTP_NOTIFY; break;
+ case 'O': parser->method = PHP_HTTP_OPTIONS; break;
+ case 'P': parser->method = PHP_HTTP_POST; /* or PROPFIND or PROPPATCH or PUT */ break;
+ case 'R': parser->method = PHP_HTTP_REPORT; break;
+ case 'S': parser->method = PHP_HTTP_SUBSCRIBE; break;
+ case 'T': parser->method = PHP_HTTP_TRACE; break;
+ case 'U': parser->method = PHP_HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;
+ default: parser->method = PHP_HTTP_NOT_IMPLEMENTED; break;
+ }
+ state = s_req_method;
+ break;
+ }
+
+ case s_req_method:
+ {
+ const char *matcher;
+ if (ch == '\0')
+ goto error;
+
+ matcher = method_strings[parser->method];
+ if (ch == ' ' && (matcher[index] == '\0' || parser->method == PHP_HTTP_NOT_IMPLEMENTED)) {
+ state = s_req_spaces_before_url;
+ } else if (ch == matcher[index]) {
+ ; /* nada */
+ } else if (parser->method == PHP_HTTP_CONNECT) {
+ if (index == 1 && ch == 'H') {
+ parser->method = PHP_HTTP_CHECKOUT;
+ } else if (index == 2 && ch == 'P') {
+ parser->method = PHP_HTTP_COPY;
+ }
+ } else if (parser->method == PHP_HTTP_MKCOL) {
+ if (index == 1 && ch == 'O') {
+ parser->method = PHP_HTTP_MOVE;
+ } else if (index == 1 && ch == 'E') {
+ parser->method = PHP_HTTP_MERGE;
+ } else if (index == 1 && ch == '-') {
+ parser->method = PHP_HTTP_MSEARCH;
+ } else if (index == 2 && ch == 'A') {
+ parser->method = PHP_HTTP_MKACTIVITY;
+ }
+ } else if (index == 1 && parser->method == PHP_HTTP_POST && ch == 'R') {
+ parser->method = PHP_HTTP_PROPFIND; /* or HTTP_PROPPATCH */
+ } else if (index == 1 && parser->method == PHP_HTTP_POST && ch == 'U') {
+ parser->method = PHP_HTTP_PUT;
+ } else if (index == 1 && parser->method == PHP_HTTP_POST && ch == 'A') {
+ parser->method = PHP_HTTP_PATCH;
+ } else if (index == 2 && parser->method == PHP_HTTP_UNLOCK && ch == 'S') {
+ parser->method = PHP_HTTP_UNSUBSCRIBE;
+ } else if (index == 4 && parser->method == PHP_HTTP_PROPFIND && ch == 'P') {
+ parser->method = PHP_HTTP_PROPPATCH;
+ } else {
+ parser->method = PHP_HTTP_NOT_IMPLEMENTED;
+ }
+
+ ++index;
+ break;
+ }
+ case s_req_spaces_before_url:
+ {
+ if (ch == ' ') break;
+
+ if (ch == '/' || ch == '*') {
+ MARK(url);
+ MARK(path);
+ state = s_req_path;
+ break;
+ }
+
+ c = LOWER(ch);
+
+ if (c >= 'a' && c <= 'z') {
+ MARK(url);
+ state = s_req_schema;
+ break;
+ }
+
+ goto error;
+ }
+
+ case s_req_schema:
+ {
+ c = LOWER(ch);
+
+ if (c >= 'a' && c <= 'z') break;
+
+ if (ch == ':') {
+ state = s_req_schema_slash;
+ break;
+ } else if (ch == '.') {
+ state = s_req_host;
+ break;
+ } else if ('0' <= ch && ch <= '9') {
+ state = s_req_host;
+ break;
+ }
+
+ goto error;
+ }
+
+ case s_req_schema_slash:
+ STRICT_CHECK(ch != '/');
+ state = s_req_schema_slash_slash;
+ break;
+
+ case s_req_schema_slash_slash:
+ STRICT_CHECK(ch != '/');
+ state = s_req_host;
+ break;
+
+ case s_req_host:
+ {
+ c = LOWER(ch);
+ if (c >= 'a' && c <= 'z') break;
+ if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') break;
+ switch (ch) {
+ case ':':
+ state = s_req_port;
+ break;
+ case '/':
+ MARK(path);
+ state = s_req_path;
+ break;
+ case ' ':
+ /* The request line looks like:
+ * "GET http://foo.bar.com HTTP/1.1"
+ * That is, there is no path.
+ */
+ CALLBACK(url);
+ state = s_req_http_start;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_port:
+ {
+ if (ch >= '0' && ch <= '9') break;
+ switch (ch) {
+ case '/':
+ MARK(path);
+ state = s_req_path;
+ break;
+ case ' ':
+ /* The request line looks like:
+ * "GET http://foo.bar.com:1234 HTTP/1.1"
+ * That is, there is no path.
+ */
+ CALLBACK(url);
+ state = s_req_http_start;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_path:
+ {
+ if (normal_url_char[(unsigned char)ch]) break;
+
+ switch (ch) {
+ case ' ':
+ CALLBACK(url);
+ CALLBACK(path);
+ state = s_req_http_start;
+ break;
+ case CR:
+ CALLBACK(url);
+ CALLBACK(path);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_req_line_almost_done;
+ break;
+ case LF:
+ CALLBACK(url);
+ CALLBACK(path);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_header_field_start;
+ break;
+ case '?':
+ CALLBACK(path);
+ state = s_req_query_string_start;
+ break;
+ case '#':
+ CALLBACK(path);
+ state = s_req_fragment_start;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_query_string_start:
+ {
+ if (normal_url_char[(unsigned char)ch]) {
+ MARK(query_string);
+ state = s_req_query_string;
+ break;
+ }
+
+ switch (ch) {
+ case '?':
+ break; /* XXX ignore extra '?' ... is this right? */
+ case ' ':
+ CALLBACK(url);
+ state = s_req_http_start;
+ break;
+ case CR:
+ CALLBACK(url);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_req_line_almost_done;
+ break;
+ case LF:
+ CALLBACK(url);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_header_field_start;
+ break;
+ case '#':
+ state = s_req_fragment_start;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_query_string:
+ {
+ if (normal_url_char[(unsigned char)ch]) break;
+
+ switch (ch) {
+ case '?':
+ /* allow extra '?' in query string */
+ break;
+ case ' ':
+ CALLBACK(url);
+ CALLBACK(query_string);
+ state = s_req_http_start;
+ break;
+ case CR:
+ CALLBACK(url);
+ CALLBACK(query_string);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_req_line_almost_done;
+ break;
+ case LF:
+ CALLBACK(url);
+ CALLBACK(query_string);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_header_field_start;
+ break;
+ case '#':
+ CALLBACK(query_string);
+ state = s_req_fragment_start;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_fragment_start:
+ {
+ if (normal_url_char[(unsigned char)ch]) {
+ MARK(fragment);
+ state = s_req_fragment;
+ break;
+ }
+
+ switch (ch) {
+ case ' ':
+ CALLBACK(url);
+ state = s_req_http_start;
+ break;
+ case CR:
+ CALLBACK(url);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_req_line_almost_done;
+ break;
+ case LF:
+ CALLBACK(url);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_header_field_start;
+ break;
+ case '?':
+ MARK(fragment);
+ state = s_req_fragment;
+ break;
+ case '#':
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_fragment:
+ {
+ if (normal_url_char[(unsigned char)ch]) break;
+
+ switch (ch) {
+ case ' ':
+ CALLBACK(url);
+ CALLBACK(fragment);
+ state = s_req_http_start;
+ break;
+ case CR:
+ CALLBACK(url);
+ CALLBACK(fragment);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_req_line_almost_done;
+ break;
+ case LF:
+ CALLBACK(url);
+ CALLBACK(fragment);
+ parser->http_major = 0;
+ parser->http_minor = 9;
+ state = s_header_field_start;
+ break;
+ case '?':
+ case '#':
+ break;
+ default:
+ goto error;
+ }
+ break;
+ }
+
+ case s_req_http_start:
+ switch (ch) {
+ case 'H':
+ state = s_req_http_H;
+ break;
+ case ' ':
+ break;
+ default:
+ goto error;
+ }
+ break;
+
+ case s_req_http_H:
+ STRICT_CHECK(ch != 'T');
+ state = s_req_http_HT;
+ break;
+
+ case s_req_http_HT:
+ STRICT_CHECK(ch != 'T');
+ state = s_req_http_HTT;
+ break;
+
+ case s_req_http_HTT:
+ STRICT_CHECK(ch != 'P');
+ state = s_req_http_HTTP;
+ break;
+
+ case s_req_http_HTTP:
+ STRICT_CHECK(ch != '/');
+ state = s_req_first_http_major;
+ break;
+
+ /* first digit of major HTTP version */
+ case s_req_first_http_major:
+ if (ch < '1' || ch > '9') goto error;
+ parser->http_major = ch - '0';
+ state = s_req_http_major;
+ break;
+
+ /* major HTTP version or dot */
+ case s_req_http_major:
+ {
+ if (ch == '.') {
+ state = s_req_first_http_minor;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') goto error;
+
+ parser->http_major *= 10;
+ parser->http_major += ch - '0';
+
+ if (parser->http_major > 999) goto error;
+ break;
+ }
+
+ /* first digit of minor HTTP version */
+ case s_req_first_http_minor:
+ if (ch < '0' || ch > '9') goto error;
+ parser->http_minor = ch - '0';
+ state = s_req_http_minor;
+ break;
+
+ /* minor HTTP version or end of request line */
+ case s_req_http_minor:
+ {
+ if (ch == CR) {
+ state = s_req_line_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ state = s_header_field_start;
+ break;
+ }
+
+ /* XXX allow spaces after digit? */
+
+ if (ch < '0' || ch > '9') goto error;
+
+ parser->http_minor *= 10;
+ parser->http_minor += ch - '0';
+
+ if (parser->http_minor > 999) goto error;
+ break;
+ }
+
+ /* end of request line */
+ case s_req_line_almost_done:
+ {
+ if (ch != LF) goto error;
+ state = s_header_field_start;
+ break;
+ }
+
+ case s_header_field_start:
+ {
+ if (ch == CR) {
+ state = s_headers_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ /* they might be just sending \n instead of \r\n so this would be
+ * the second \n to denote the end of headers*/
+ state = s_headers_almost_done;
+ goto headers_almost_done;
+ }
+
+ c = TOKEN(ch);
+
+ if (!c) goto error;
+
+ MARK(header_field);
+
+ index = 0;
+ state = s_header_field;
+
+ switch (c) {
+ case 'c':
+ header_state = h_C;
+ break;
+
+ case 'p':
+ header_state = h_matching_proxy_connection;
+ break;
+
+ case 't':
+ header_state = h_matching_transfer_encoding;
+ break;
+
+ case 'u':
+ header_state = h_matching_upgrade;
+ break;
+
+ default:
+ header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_field:
+ {
+ c = TOKEN(ch);
+
+ if (c) {
+ switch (header_state) {
+ case h_general:
+ break;
+
+ case h_C:
+ index++;
+ header_state = (c == 'o' ? h_CO : h_general);
+ break;
+
+ case h_CO:
+ index++;
+ header_state = (c == 'n' ? h_CON : h_general);
+ break;
+
+ case h_CON:
+ index++;
+ switch (c) {
+ case 'n':
+ header_state = h_matching_connection;
+ break;
+ case 't':
+ header_state = h_matching_content_length;
+ break;
+ default:
+ header_state = h_general;
+ break;
+ }
+ break;
+
+ /* connection */
+
+ case h_matching_connection:
+ index++;
+ if (index > sizeof(CONNECTION)-1
+ || c != CONNECTION[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(CONNECTION)-2) {
+ header_state = h_connection;
+ }
+ break;
+
+ /* proxy-connection */
+
+ case h_matching_proxy_connection:
+ index++;
+ if (index > sizeof(PROXY_CONNECTION)-1
+ || c != PROXY_CONNECTION[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(PROXY_CONNECTION)-2) {
+ header_state = h_connection;
+ }
+ break;
+
+ /* content-length */
+
+ case h_matching_content_length:
+ index++;
+ if (index > sizeof(CONTENT_LENGTH)-1
+ || c != CONTENT_LENGTH[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(CONTENT_LENGTH)-2) {
+ header_state = h_content_length;
+ }
+ break;
+
+ /* transfer-encoding */
+
+ case h_matching_transfer_encoding:
+ index++;
+ if (index > sizeof(TRANSFER_ENCODING)-1
+ || c != TRANSFER_ENCODING[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(TRANSFER_ENCODING)-2) {
+ header_state = h_transfer_encoding;
+ }
+ break;
+
+ /* upgrade */
+
+ case h_matching_upgrade:
+ index++;
+ if (index > sizeof(UPGRADE)-1
+ || c != UPGRADE[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(UPGRADE)-2) {
+ header_state = h_upgrade;
+ }
+ break;
+
+ case h_connection:
+ case h_content_length:
+ case h_transfer_encoding:
+ case h_upgrade:
+ if (ch != ' ') header_state = h_general;
+ break;
+
+ default:
+ assert(0 && "Unknown header_state");
+ break;
+ }
+ break;
+ }
+
+ if (ch == ':') {
+ CALLBACK(header_field);
+ state = s_header_value_start;
+ break;
+ }
+
+ if (ch == CR) {
+ state = s_header_almost_done;
+ CALLBACK(header_field);
+ break;
+ }
+
+ if (ch == LF) {
+ CALLBACK(header_field);
+ state = s_header_field_start;
+ break;
+ }
+
+ goto error;
+ }
+
+ case s_header_value_start:
+ {
+ if (ch == ' ') break;
+
+ MARK(header_value);
+
+ state = s_header_value;
+ index = 0;
+
+ c = LOWER(ch);
+
+ if (ch == CR) {
+ CALLBACK(header_value);
+ header_state = h_general;
+ state = s_header_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ CALLBACK(header_value);
+ state = s_header_field_start;
+ break;
+ }
+
+ switch (header_state) {
+ case h_upgrade:
+ parser->flags |= F_UPGRADE;
+ header_state = h_general;
+ break;
+
+ case h_transfer_encoding:
+ /* looking for 'Transfer-Encoding: chunked' */
+ if ('c' == c) {
+ header_state = h_matching_transfer_encoding_chunked;
+ } else {
+ header_state = h_general;
+ }
+ break;
+
+ case h_content_length:
+ if (ch < '0' || ch > '9') goto error;
+ parser->content_length = ch - '0';
+ break;
+
+ case h_connection:
+ /* looking for 'Connection: keep-alive' */
+ if (c == 'k') {
+ header_state = h_matching_connection_keep_alive;
+ /* looking for 'Connection: close' */
+ } else if (c == 'c') {
+ header_state = h_matching_connection_close;
+ } else {
+ header_state = h_general;
+ }
+ break;
+
+ default:
+ header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_value:
+ {
+ c = LOWER(ch);
+
+ if (ch == CR) {
+ CALLBACK(header_value);
+ state = s_header_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ CALLBACK(header_value);
+ goto header_almost_done;
+ }
+
+ switch (header_state) {
+ case h_general:
+ break;
+
+ case h_connection:
+ case h_transfer_encoding:
+ assert(0 && "Shouldn't get here.");
+ break;
+
+ case h_content_length:
+ if (ch == ' ') break;
+ if (ch < '0' || ch > '9') goto error;
+ parser->content_length *= 10;
+ parser->content_length += ch - '0';
+ break;
+
+ /* Transfer-Encoding: chunked */
+ case h_matching_transfer_encoding_chunked:
+ index++;
+ if (index > sizeof(CHUNKED)-1
+ || c != CHUNKED[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(CHUNKED)-2) {
+ header_state = h_transfer_encoding_chunked;
+ }
+ break;
+
+ /* looking for 'Connection: keep-alive' */
+ case h_matching_connection_keep_alive:
+ index++;
+ if (index > sizeof(KEEP_ALIVE)-1
+ || c != KEEP_ALIVE[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(KEEP_ALIVE)-2) {
+ header_state = h_connection_keep_alive;
+ }
+ break;
+
+ /* looking for 'Connection: close' */
+ case h_matching_connection_close:
+ index++;
+ if (index > sizeof(CLOSE)-1 || c != CLOSE[index]) {
+ header_state = h_general;
+ } else if (index == sizeof(CLOSE)-2) {
+ header_state = h_connection_close;
+ }
+ break;
+
+ case h_transfer_encoding_chunked:
+ case h_connection_keep_alive:
+ case h_connection_close:
+ if (ch != ' ') header_state = h_general;
+ break;
+
+ default:
+ state = s_header_value;
+ header_state = h_general;
+ break;
+ }
+ break;
+ }
+
+ case s_header_almost_done:
+ header_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+
+ state = s_header_field_start;
+
+ switch (header_state) {
+ case h_connection_keep_alive:
+ parser->flags |= F_CONNECTION_KEEP_ALIVE;
+ break;
+ case h_connection_close:
+ parser->flags |= F_CONNECTION_CLOSE;
+ break;
+ case h_transfer_encoding_chunked:
+ parser->flags |= F_CHUNKED;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case s_headers_almost_done:
+ headers_almost_done:
+ {
+ STRICT_CHECK(ch != LF);
+
+ if (parser->flags & F_TRAILING) {
+ /* End of a chunked request */
+ CALLBACK2(message_complete);
+ state = NEW_MESSAGE();
+ break;
+ }
+
+ nread = 0;
+
+ if (parser->flags & F_UPGRADE || parser->method == PHP_HTTP_CONNECT) {
+ parser->upgrade = 1;
+ }
+
+ /* Here we call the headers_complete callback. This is somewhat
+ * different than other callbacks because if the user returns 1, we
+ * will interpret that as saying that this message has no body. This
+ * is needed for the annoying case of recieving a response to a HEAD
+ * request.
+ */
+ if (settings->on_headers_complete) {
+ switch (settings->on_headers_complete(parser)) {
+ case 0:
+ break;
+
+ case 1:
+ parser->flags |= F_SKIPBODY;
+ break;
+
+ default:
+ return p - data; /* Error */
+ }
+ }
+
+ /* Exit, the rest of the connect is in a different protocol. */
+ if (parser->upgrade) {
+ CALLBACK2(message_complete);
+ return (p - data);
+ }
+
+ if (parser->flags & F_SKIPBODY) {
+ CALLBACK2(message_complete);
+ state = NEW_MESSAGE();
+ } else if (parser->flags & F_CHUNKED) {
+ /* chunked encoding - ignore Content-Length header */
+ state = s_chunk_size_start;
+ } else {
+ if (parser->content_length == 0) {
+ /* Content-Length header given but zero: Content-Length: 0\r\n */
+ CALLBACK2(message_complete);
+ state = NEW_MESSAGE();
+ } else if (parser->content_length > 0) {
+ /* Content-Length header given and non-zero */
+ state = s_body_identity;
+ } else {
+ if (parser->type == PHP_HTTP_REQUEST || php_http_should_keep_alive(parser)) {
+ /* Assume content-length 0 - read the next */
+ CALLBACK2(message_complete);
+ state = NEW_MESSAGE();
+ } else {
+ /* Read body until EOF */
+ state = s_body_identity_eof;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case s_body_identity:
+ to_read = MIN(pe - p, (size_t)parser->content_length);
+ if (to_read > 0) {
+ if (settings->on_body) settings->on_body(parser, p, to_read);
+ p += to_read - 1;
+ parser->content_length -= to_read;
+ if (parser->content_length == 0) {
+ CALLBACK2(message_complete);
+ state = NEW_MESSAGE();
+ }
+ }
+ break;
+
+ /* read until EOF */
+ case s_body_identity_eof:
+ to_read = pe - p;
+ if (to_read > 0) {
+ if (settings->on_body) settings->on_body(parser, p, to_read);
+ p += to_read - 1;
+ }
+ break;
+
+ case s_chunk_size_start:
+ {
+ assert(parser->flags & F_CHUNKED);
+
+ c = unhex[(unsigned char)ch];
+ if (c == -1) goto error;
+ parser->content_length = c;
+ state = s_chunk_size;
+ break;
+ }
+
+ case s_chunk_size:
+ {
+ assert(parser->flags & F_CHUNKED);
+
+ if (ch == CR) {
+ state = s_chunk_size_almost_done;
+ break;
+ }
+
+ c = unhex[(unsigned char)ch];
+
+ if (c == -1) {
+ if (ch == ';' || ch == ' ') {
+ state = s_chunk_parameters;
+ break;
+ }
+ goto error;
+ }
+
+ parser->content_length *= 16;
+ parser->content_length += c;
+ break;
+ }
+
+ case s_chunk_parameters:
+ {
+ assert(parser->flags & F_CHUNKED);
+ /* just ignore this shit. TODO check for overflow */
+ if (ch == CR) {
+ state = s_chunk_size_almost_done;
+ break;
+ }
+ break;
+ }
+
+ case s_chunk_size_almost_done:
+ {
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != LF);
+
+ if (parser->content_length == 0) {
+ parser->flags |= F_TRAILING;
+ state = s_header_field_start;
+ } else {
+ state = s_chunk_data;
+ }
+ break;
+ }
+
+ case s_chunk_data:
+ {
+ assert(parser->flags & F_CHUNKED);
+
+ to_read = MIN(pe - p, (size_t)(parser->content_length));
+
+ if (to_read > 0) {
+ if (settings->on_body) settings->on_body(parser, p, to_read);
+ p += to_read - 1;
+ }
+
+ if (to_read == parser->content_length) {
+ state = s_chunk_data_almost_done;
+ }
+
+ parser->content_length -= to_read;
+ break;
+ }
+
+ case s_chunk_data_almost_done:
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != CR);
+ state = s_chunk_data_done;
+ break;
+
+ case s_chunk_data_done:
+ assert(parser->flags & F_CHUNKED);
+ STRICT_CHECK(ch != LF);
+ state = s_chunk_size_start;
+ break;
+
+ default:
+ assert(0 && "unhandled state");
+ goto error;
+ }
+ }
+
+ CALLBACK_NOCLEAR(header_field);
+ CALLBACK_NOCLEAR(header_value);
+ CALLBACK_NOCLEAR(fragment);
+ CALLBACK_NOCLEAR(query_string);
+ CALLBACK_NOCLEAR(path);
+ CALLBACK_NOCLEAR(url);
+
+ parser->state = state;
+ parser->header_state = header_state;
+ parser->index = index;
+ parser->nread = nread;
+
+ return len;
+
+error:
+ parser->state = s_dead;
+ return (p - data);
+}
+
+
+int
+php_http_should_keep_alive (php_http_parser *parser)
+{
+ if (parser->http_major > 0 && parser->http_minor > 0) {
+ /* HTTP/1.1 */
+ if (parser->flags & F_CONNECTION_CLOSE) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ /* HTTP/1.0 or earlier */
+ if (parser->flags & F_CONNECTION_KEEP_ALIVE) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+const char * php_http_method_str (enum php_http_method m)
+{
+ return method_strings[m];
+}
+
+
+void
+php_http_parser_init (php_http_parser *parser, enum php_http_parser_type t)
+{
+ parser->type = t;
+ parser->state = (t == PHP_HTTP_REQUEST ? s_start_req : (t == PHP_HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
+ parser->nread = 0;
+ parser->upgrade = 0;
+ parser->flags = 0;
+ parser->method = 0;
+}
diff --git a/sapi/cli/php_http_parser.h b/sapi/cli/php_http_parser.h
new file mode 100644
index 0000000000..2bf2356725
--- /dev/null
+++ b/sapi/cli/php_http_parser.h
@@ -0,0 +1,180 @@
+/* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* modified by Moriyoshi Koizumi <moriyoshi@php.net> to make it fit to PHP source tree. */
+#ifndef php_http_parser_h
+#define php_http_parser_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <sys/types.h>
+#if defined(_WIN32) && !defined(__MINGW32__)
+# include <windows.h>
+# include "win32/php_stdint.h"
+# include "config.w32.h"
+#else
+# include "php_config.h"
+# ifdef HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+
+/* Compile with -DPHP_HTTP_PARSER_STRICT=0 to make less checks, but run
+ * faster
+ */
+#ifndef PHP_HTTP_PARSER_STRICT
+# define PHP_HTTP_PARSER_STRICT 1
+#else
+# define PHP_HTTP_PARSER_STRICT 0
+#endif
+
+
+/* Maximium header size allowed */
+#define PHP_HTTP_MAX_HEADER_SIZE (80*1024)
+
+
+typedef struct php_http_parser php_http_parser;
+typedef struct php_http_parser_settings php_http_parser_settings;
+
+
+/* Callbacks should return non-zero to indicate an error. The parser will
+ * then halt execution.
+ *
+ * The one exception is on_headers_complete. In a PHP_HTTP_RESPONSE parser
+ * returning '1' from on_headers_complete will tell the parser that it
+ * should not expect a body. This is used when receiving a response to a
+ * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
+ * chunked' headers that indicate the presence of a body.
+ *
+ * http_data_cb does not return data chunks. It will be call arbitrarally
+ * many times for each string. E.G. you might get 10 callbacks for "on_path"
+ * each providing just a few characters more data.
+ */
+typedef int (*php_http_data_cb) (php_http_parser*, const char *at, size_t length);
+typedef int (*php_http_cb) (php_http_parser*);
+
+
+/* Request Methods */
+enum php_http_method
+ { PHP_HTTP_DELETE = 0
+ , PHP_HTTP_GET
+ , PHP_HTTP_HEAD
+ , PHP_HTTP_POST
+ , PHP_HTTP_PUT
+ , PHP_HTTP_PATCH
+ /* pathological */
+ , PHP_HTTP_CONNECT
+ , PHP_HTTP_OPTIONS
+ , PHP_HTTP_TRACE
+ /* webdav */
+ , PHP_HTTP_COPY
+ , PHP_HTTP_LOCK
+ , PHP_HTTP_MKCOL
+ , PHP_HTTP_MOVE
+ , PHP_HTTP_PROPFIND
+ , PHP_HTTP_PROPPATCH
+ , PHP_HTTP_UNLOCK
+ /* subversion */
+ , PHP_HTTP_REPORT
+ , PHP_HTTP_MKACTIVITY
+ , PHP_HTTP_CHECKOUT
+ , PHP_HTTP_MERGE
+ /* upnp */
+ , PHP_HTTP_MSEARCH
+ , PHP_HTTP_NOTIFY
+ , PHP_HTTP_SUBSCRIBE
+ , PHP_HTTP_UNSUBSCRIBE
+ /* unknown, not implemented */
+ , PHP_HTTP_NOT_IMPLEMENTED
+ };
+
+
+enum php_http_parser_type { PHP_HTTP_REQUEST, PHP_HTTP_RESPONSE, PHP_HTTP_BOTH };
+
+
+struct php_http_parser {
+ /** PRIVATE **/
+ unsigned char type : 2;
+ unsigned char flags : 6;
+ unsigned char state;
+ unsigned char header_state;
+ unsigned char index;
+
+ uint32_t nread;
+ ssize_t content_length;
+
+ /** READ-ONLY **/
+ unsigned short http_major;
+ unsigned short http_minor;
+ unsigned short status_code; /* responses only */
+ unsigned char method; /* requests only */
+
+ /* 1 = Upgrade header was present and the parser has exited because of that.
+ * 0 = No upgrade header present.
+ * Should be checked when http_parser_execute() returns in addition to
+ * error checking.
+ */
+ char upgrade;
+
+ /** PUBLIC **/
+ void *data; /* A pointer to get hook to the "connection" or "socket" object */
+};
+
+
+struct php_http_parser_settings {
+ php_http_cb on_message_begin;
+ php_http_data_cb on_path;
+ php_http_data_cb on_query_string;
+ php_http_data_cb on_url;
+ php_http_data_cb on_fragment;
+ php_http_data_cb on_header_field;
+ php_http_data_cb on_header_value;
+ php_http_cb on_headers_complete;
+ php_http_data_cb on_body;
+ php_http_cb on_message_complete;
+};
+
+
+void php_http_parser_init(php_http_parser *parser, enum php_http_parser_type type);
+
+
+size_t php_http_parser_execute(php_http_parser *parser,
+ const php_http_parser_settings *settings,
+ const char *data,
+ size_t len);
+
+
+/* If php_http_should_keep_alive() in the on_headers_complete or
+ * on_message_complete callback returns true, then this will be should be
+ * the last message on the connection.
+ * If you are the server, respond with the "Connection: close" header.
+ * If you are the client, close the connection.
+ */
+int php_http_should_keep_alive(php_http_parser *parser);
+
+/* Returns a string version of the HTTP method. */
+const char *php_http_method_str(enum php_http_method);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/sapi/cli/tests/007.phpt b/sapi/cli/tests/007.phpt
index 12fddee01d..0bf40703d9 100644
--- a/sapi/cli/tests/007.phpt
+++ b/sapi/cli/tests/007.phpt
@@ -45,8 +45,8 @@ string(81) "
<?php
class test { public $var = "test"; private $pri; function foo() { } } ?>
"
-Could not open input file: wrong
-NULL
+string(33) "Could not open input file: wrong
+"
string(43) "<?php class test { function foo() {} } ?>
"
Done
diff --git a/sapi/cli/tests/008.phpt b/sapi/cli/tests/008.phpt
index a833043096..e14338f5f5 100644
--- a/sapi/cli/tests/008.phpt
+++ b/sapi/cli/tests/008.phpt
@@ -38,6 +38,6 @@ string(%d) "
Fatal error: Cannot access private property test::$pri in %s on line %d
"
-Could not open input file: wrong
-NULL
+string(33) "Could not open input file: wrong
+"
Done
diff --git a/sapi/cli/tests/009.phpt b/sapi/cli/tests/009.phpt
index a881a0730e..33f859fb38 100644
--- a/sapi/cli/tests/009.phpt
+++ b/sapi/cli/tests/009.phpt
@@ -13,8 +13,8 @@ var_dump(`$php -n -r "echo hello;" -a`);
echo "Done\n";
?>
--EXPECTF--
-Either execute direct code, process stdin or use a file.
-NULL
-Either execute direct code, process stdin or use a file.
-NULL
+string(57) "Either execute direct code, process stdin or use a file.
+"
+string(57) "Either execute direct code, process stdin or use a file.
+"
Done
diff --git a/sapi/cli/tests/011.phpt b/sapi/cli/tests/011.phpt
index ef49666d3a..6154693517 100644
--- a/sapi/cli/tests/011.phpt
+++ b/sapi/cli/tests/011.phpt
@@ -49,8 +49,8 @@ echo "Done\n";
--EXPECTF--
string(%d) "No syntax errors detected in %s011.test.php
"
-Could not open input file: some.unknown
-NULL
+string(40) "Could not open input file: some.unknown
+"
string(%d) "
Parse error: %s expecting %s{%s in %s on line %d
Errors parsing %s011.test.php
diff --git a/sapi/cli/tests/012.phpt b/sapi/cli/tests/012.phpt
index 137e0bd781..c1e4f6a63a 100644
--- a/sapi/cli/tests/012.phpt
+++ b/sapi/cli/tests/012.phpt
@@ -19,20 +19,20 @@ var_dump(`"$php" -n -r '' -r ''`);
echo "Done\n";
?>
--EXPECTF--
-You can use -R or -F only once.
-NULL
-You can use -R or -F only once.
-NULL
-You can use -R or -F only once.
-NULL
-You can use -R or -F only once.
-NULL
-You can use -f only once.
-NULL
-You can use -B only once.
-NULL
-You can use -E only once.
-NULL
-You can use -r only once.
-NULL
+string(32) "You can use -R or -F only once.
+"
+string(32) "You can use -R or -F only once.
+"
+string(32) "You can use -R or -F only once.
+"
+string(32) "You can use -R or -F only once.
+"
+string(26) "You can use -f only once.
+"
+string(26) "You can use -B only once.
+"
+string(26) "You can use -E only once.
+"
+string(26) "You can use -r only once.
+"
Done
diff --git a/sapi/cli/tests/014.phpt b/sapi/cli/tests/014.phpt
index b20478a03d..e8c5203f67 100644
--- a/sapi/cli/tests/014.phpt
+++ b/sapi/cli/tests/014.phpt
@@ -39,6 +39,6 @@ string(1478) "<code><span style="color: #000000">
<br /><span style="color: #0000BB">&lt;?php<br />$test&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">"var"</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//var<br />/*&nbsp;test&nbsp;class&nbsp;*/<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">test&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;</span><span style="color: #0000BB">$var&nbsp;</span><span style="color: #007700">=&nbsp;array();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;function&nbsp;</span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">Test&nbsp;$arg</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"hello"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000BB">$o&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">test</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;<br /></span>
</span>
</code>"
-Could not open input file: unknown
-NULL
+string(35) "Could not open input file: unknown
+"
Done
diff --git a/sapi/cli/tests/016.phpt b/sapi/cli/tests/016.phpt
index 9c28d15a30..31c1a40e4a 100644
--- a/sapi/cli/tests/016.phpt
+++ b/sapi/cli/tests/016.phpt
@@ -59,6 +59,8 @@ foreach ($codes as $key => $code) {
echo "\nDone\n";
?>
+--XFAIL--
+https://bugs.php.net/bug.php?id=55496
--EXPECTF--
--------------
Snippet no. 1:
diff --git a/sapi/cli/tests/bug61679.phpt b/sapi/cli/tests/bug61679.phpt
new file mode 100644
index 0000000000..819ce2fa89
--- /dev/null
+++ b/sapi/cli/tests/bug61679.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #61679 (Error on non-standard HTTP methods)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start(<<<'PHP'
+echo "This should never echo";
+PHP
+);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+// Send a request with a fictitious request method,
+// I like smurfs, the smurf everything.
+if(fwrite($fp, <<<HEADER
+SMURF / HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ // Only echo the first line from the response,
+ // the rest is not interesting
+ break;
+ }
+}
+
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 501 Not Implemented
diff --git a/sapi/cli/tests/bug61977.phpt b/sapi/cli/tests/bug61977.phpt
new file mode 100644
index 0000000000..2f198060f5
--- /dev/null
+++ b/sapi/cli/tests/bug61977.phpt
@@ -0,0 +1,157 @@
+--TEST--
+Bug #61977 (Need CLI web-server support for files with .htm & svg extensions)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('<?php ?>', true);
+$doc_root = __DIR__;
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+file_put_contents($doc_root . '/foo.html', '');
+if(fwrite($fp, <<<HEADER
+GET /foo.html HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $text = fgets($fp);
+ if (strncasecmp("Content-type:", $text, 13) == 0) {
+ echo "foo.html => ", $text;
+ }
+ }
+}
+@unlink($doc_root . '/foo.html');
+fclose($fp);
+
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+file_put_contents($doc_root . '/foo.htm', '');
+if(fwrite($fp, <<<HEADER
+GET /foo.htm HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $text = fgets($fp);
+ if (strncasecmp("Content-type:", $text, 13) == 0) {
+ echo "foo.htm => ", $text;
+ }
+ }
+}
+@unlink($doc_root . '/foo.htm');
+fclose($fp);
+
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+file_put_contents($doc_root . '/foo.svg', '');
+if(fwrite($fp, <<<HEADER
+GET /foo.svg HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $text = fgets($fp);
+ if (strncasecmp("Content-type:", $text, 13) == 0) {
+ echo "foo.svg => ", $text;
+ }
+ }
+}
+@unlink($doc_root . '/foo.svg');
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+file_put_contents($doc_root . '/foo.css', '');
+if(fwrite($fp, <<<HEADER
+GET /foo.css HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $text = fgets($fp);
+ if (strncasecmp("Content-type:", $text, 13) == 0) {
+ echo "foo.css => ", $text;
+ }
+ }
+}
+@unlink($doc_root . '/foo.css');
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+file_put_contents($doc_root . '/foo.js', '');
+if(fwrite($fp, <<<HEADER
+GET /foo.js HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $text = fgets($fp);
+ if (strncasecmp("Content-type:", $text, 13) == 0) {
+ echo "foo.js => ", $text;
+ }
+ }
+}
+@unlink($doc_root . '/foo.js');
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+file_put_contents($doc_root . '/foo.png', '');
+if(fwrite($fp, <<<HEADER
+GET /foo.png HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $text = fgets($fp);
+ if (strncasecmp("Content-type:", $text, 13) == 0) {
+ echo "foo.png => ", $text;
+ }
+ }
+}
+@unlink($doc_root . '/foo.png');
+fclose($fp);
+?>
+--EXPECTF--
+foo.html => Content-Type: text/html; charset=UTF-8
+foo.htm => Content-Type: text/html; charset=UTF-8
+foo.svg => Content-Type: image/svg+xml
+foo.css => Content-Type: text/css; charset=UTF-8
+foo.js => Content-Type: text/javascript; charset=UTF-8
+foo.png => Content-Type: image/png
diff --git a/sapi/cli/tests/php_cli_server.inc b/sapi/cli/tests/php_cli_server.inc
new file mode 100644
index 0000000000..40c5361995
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server.inc
@@ -0,0 +1,62 @@
+<?php
+define ("PHP_CLI_SERVER_HOSTNAME", "localhost");
+define ("PHP_CLI_SERVER_PORT", 8964);
+define ("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT);
+
+function php_cli_server_start($code = 'echo "Hello world";', $no_router = FALSE) {
+ $php_executable = getenv('TEST_PHP_EXECUTABLE');
+ $doc_root = __DIR__;
+ $router = "index.php";
+
+ if ($code) {
+ file_put_contents($doc_root . '/' . $router, '<?php ' . $code . ' ?>');
+ }
+
+ $descriptorspec = array(
+ 0 => STDIN,
+ 1 => STDOUT,
+ 2 => STDERR,
+ );
+
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
+ $cmd = "{$php_executable} -t {$doc_root} -n -S " . PHP_CLI_SERVER_ADDRESS;
+ if (!$no_router) {
+ $cmd .= " {$router}";
+ }
+
+ $handle = proc_open(addslashes($cmd), $descriptorspec, $pipes, $doc_root, NULL, array("bypass_shell" => true, "suppress_errors" => true));
+ } else {
+ $cmd = "exec {$php_executable} -t {$doc_root} -n -S " . PHP_CLI_SERVER_ADDRESS;
+ if (!$no_router) {
+ $cmd .= " {$router}";
+ }
+ $cmd .= " 2>/dev/null";
+
+ $handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root);
+ }
+
+ // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.'
+ // it might not be listening yet...need to wait until fsockopen() call returns
+ $i = 0;
+ while (($i++ < 30) && !($fp = @fsockopen(PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT))) {
+ usleep(10000);
+ }
+
+ if ($fp) {
+ fclose($fp);
+ }
+
+ register_shutdown_function(
+ function($handle) use($router) {
+ proc_terminate($handle);
+ @unlink(__DIR__ . "/{$router}");
+ },
+ $handle
+ );
+ // don't bother sleeping, server is already up
+ // server can take a variable amount of time to be up, so just sleeping a guessed amount of time
+ // does not work. this is why tests sometimes pass and sometimes fail. to get a reliable pass
+ // sleeping doesn't work.
+}
+?>
+
diff --git a/sapi/cli/tests/php_cli_server_001.phpt b/sapi/cli/tests/php_cli_server_001.phpt
new file mode 100644
index 0000000000..3f1083e7ac
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_001.phpt
@@ -0,0 +1,16 @@
+--TEST--
+basic function
+--INI--
+allow_url_fopen=1
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start();
+var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS));
+?>
+--EXPECT--
+string(11) "Hello world"
diff --git a/sapi/cli/tests/php_cli_server_002.phpt b/sapi/cli/tests/php_cli_server_002.phpt
new file mode 100644
index 0000000000..93151c15d4
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_002.phpt
@@ -0,0 +1,20 @@
+--TEST--
+$_SERVER variable
+--INI--
+allow_url_fopen=1
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('var_dump($_SERVER["DOCUMENT_ROOT"], $_SERVER["SERVER_SOFTWARE"], $_SERVER["SERVER_NAME"], $_SERVER["SERVER_PORT"]);');
+var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS));
+?>
+--EXPECTF--
+string(%d) "string(%d) "%stests"
+string(%d) "PHP %s Development Server"
+string(%d) "localhost"
+string(%d) "8964"
+"
diff --git a/sapi/cli/tests/php_cli_server_003.phpt b/sapi/cli/tests/php_cli_server_003.phpt
new file mode 100644
index 0000000000..d1e95fe6aa
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_003.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #55726 (Changing the working directory makes router script inaccessible)
+--INI--
+allow_url_fopen=1
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('chdir(__DIR__); echo "okey";');
+var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS));
+var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS));
+?>
+--EXPECTF--
+string(4) "okey"
+string(4) "okey"
diff --git a/sapi/cli/tests/php_cli_server_004.phpt b/sapi/cli/tests/php_cli_server_004.phpt
new file mode 100644
index 0000000000..b61f88637e
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_004.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #55747 (request headers missed in $_SERVER)
+--INI--
+allow_url_fopen=1
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('foreach($_SERVER as $k=>$v) { if (!strncmp($k, "HTTP", 4)) var_dump( $k . ":" . $v); }');
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET / HTTP/1.1
+Host:{$host}
+User-Agent:dummy
+Custom:foo
+Referer:http://www.php.net/
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(19) "HTTP_HOST:localhost"
+string(21) "HTTP_USER_AGENT:dummy"
+string(15) "HTTP_CUSTOM:foo"
+string(32) "HTTP_REFERER:http://www.php.net/"
diff --git a/sapi/cli/tests/php_cli_server_005.phpt b/sapi/cli/tests/php_cli_server_005.phpt
new file mode 100644
index 0000000000..ccc0f8f3ab
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_005.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Post a file
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('var_dump($_FILES);');
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+$post_data = <<<POST
+-----------------------------114782935826962
+Content-Disposition: form-data; name="userfile"; filename="laruence.txt"
+Content-Type: text/plain
+
+I am not sure about this.
+
+-----------------------------114782935826962--
+
+
+POST;
+
+$post_len = strlen($post_data);
+
+if(fwrite($fp, <<<HEADER
+POST / HTTP/1.1
+Host: {$host}
+Content-Type: multipart/form-data; boundary=---------------------------114782935826962
+Content-Length: {$post_len}
+
+
+{$post_data}
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+array(1) {
+ ["userfile"]=>
+ array(5) {
+ ["name"]=>
+ string(12) "laruence.txt"
+ ["type"]=>
+ string(10) "text/plain"
+ ["tmp_name"]=>
+ string(%d) "%s"
+ ["error"]=>
+ int(0)
+ ["size"]=>
+ int(26)
+ }
+}
diff --git a/sapi/cli/tests/php_cli_server_006.phpt b/sapi/cli/tests/php_cli_server_006.phpt
new file mode 100644
index 0000000000..09e7ab07a5
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_006.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Bug #55755 (SegFault when outputting header WWW-Authenticate)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('var_dump($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);');
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET / HTTP/1.1
+Host: {$host}
+Authorization: Basic Zm9vOmJhcg==
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(3) "foo"
+string(3) "bar"
diff --git a/sapi/cli/tests/php_cli_server_007.phpt b/sapi/cli/tests/php_cli_server_007.phpt
new file mode 100644
index 0000000000..64d4df0ed7
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_007.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Bug #55758 (Digest Authenticate missed in 5.4)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('header(\'WWW-Authenticate: Digest realm="foo",qop="auth",nonce="XXXXX",opaque="'.md5("foo").'"\');');
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET / HTTP/1.1
+Host: {$host}
+Authorization: Basic Zm9vOmJhcg==
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+?>
+--EXPECTF--
+HTTP/1.1 401 Unauthorized
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+WWW-Authenticate: Digest realm="foo",qop="auth",nonce="XXXXX",opaque="acbd18db4cc2f85cedef654fccc4a4d8"
+Content-type: text/html
diff --git a/sapi/cli/tests/php_cli_server_008.phpt b/sapi/cli/tests/php_cli_server_008.phpt
new file mode 100644
index 0000000000..2e68e24059
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_008.phpt
@@ -0,0 +1,68 @@
+--TEST--
+SERVER_PROTOCOL header availability
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('var_dump($_SERVER["SERVER_PROTOCOL"]);');
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET / HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+
+if(fwrite($fp, <<<HEADER
+GET / HTTP/1.0
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(8) "HTTP/1.1"
+HTTP/1.0 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(8) "HTTP/1.0"
diff --git a/sapi/cli/tests/php_cli_server_009.phpt b/sapi/cli/tests/php_cli_server_009.phpt
new file mode 100644
index 0000000000..2beaeedab6
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_009.phpt
@@ -0,0 +1,93 @@
+--TEST--
+PATH_INFO (relevant to #60112)
+--DESCRIPTION--
+After this fix(#60112), previously 404 request like "localhost/foo/bar"
+now could serve correctly with request_uri "index.php" and PATH_INFO "/foo/bar/"
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('var_dump($_SERVER["PATH_INFO"]);', TRUE);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET /foo/bar HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+
+if(fwrite($fp, <<<HEADER
+GET /foo/bar/ HTTP/1.0
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+
+if(fwrite($fp, <<<HEADER
+GET /foo/bar.js HTTP/1.0
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ break;
+ }
+}
+
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(8) "/foo/bar"
+HTTP/1.0 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(9) "/foo/bar/"
+HTTP/1.0 404 Not Found
diff --git a/sapi/cli/tests/php_cli_server_010.phpt b/sapi/cli/tests/php_cli_server_010.phpt
new file mode 100644
index 0000000000..2ef018b857
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_010.phpt
@@ -0,0 +1,75 @@
+--TEST--
+Bug #60180 ($_SERVER["PHP_SELF"] incorrect)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('var_dump($_SERVER["PHP_SELF"], $_SERVER["SCRIPT_NAME"], $_SERVER["PATH_INFO"], $_SERVER["QUERY_STRING"]);', TRUE);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET /foo/bar?foo=bar HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+
+if(fwrite($fp, <<<HEADER
+GET /index.php/foo/bar/?foo=bar HTTP/1.0
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(18) "/index.php/foo/bar"
+string(10) "/index.php"
+string(8) "/foo/bar"
+string(7) "foo=bar"
+HTTP/1.0 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+string(19) "/index.php/foo/bar/"
+string(10) "/index.php"
+string(9) "/foo/bar/"
+string(7) "foo=bar"
diff --git a/sapi/cli/tests/php_cli_server_011.phpt b/sapi/cli/tests/php_cli_server_011.phpt
new file mode 100644
index 0000000000..a957a8ed4c
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_011.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Bug #60180 ($_SERVER["PHP_SELF"] incorrect)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('sytanx error;', TRUE);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+$logo_id = php_logo_guid();
+
+if(fwrite($fp, <<<HEADER
+GET /?={$logo_id} HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ if (("Content-Type: image/gif") == trim(fgets($fp))) {
+ echo "okey";
+ break;
+ }
+ }
+}
+
+fclose($fp);
+
+?>
+--EXPECTF--
+okey
diff --git a/sapi/cli/tests/php_cli_server_012.phpt b/sapi/cli/tests/php_cli_server_012.phpt
new file mode 100644
index 0000000000..9a1e60c48b
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_012.phpt
@@ -0,0 +1,55 @@
+--TEST--
+Bug #60159 (Router returns false, but POST is not passed to requested resource)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('print_r($_REQUEST); $_REQUEST["foo"] = "bar"; return FALSE;');
+$doc_root = __DIR__;
+file_put_contents($doc_root . '/request.php', '<?php print_r($_REQUEST); ?>');
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+POST /request.php HTTP/1.1
+Host: {$host}
+Content-Type: application/x-www-form-urlencoded
+Content-Length: 3
+
+a=b
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+@unlink($doc_root . '/request.php');
+
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+Array
+(
+ [a] => b
+)
+Array
+(
+ [a] => b
+ [foo] => bar
+)
diff --git a/sapi/cli/tests/php_cli_server_013.phpt b/sapi/cli/tests/php_cli_server_013.phpt
new file mode 100644
index 0000000000..570798a880
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_013.phpt
@@ -0,0 +1,108 @@
+--TEST--
+No router, no script
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start(NULL, TRUE);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+$output = '';
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+
+if(fwrite($fp, <<<HEADER
+POST / HTTP/1.1
+Host: {$host}
+Content-Type: application/x-www-form-urlencoded
+Content-Length: 3
+
+a=b
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+
+echo preg_replace("/<style>(.*?)<\/style>/s", "<style>AAA</style>", $output), "\n";
+fclose($fp);
+
+
+$output = '';
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET /main/style.css HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+
+echo preg_replace("/<style>(.*?)<\/style>/s", "<style>AAA</style>", $output), "\n";
+fclose($fp);
+
+$output = '';
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+HEAD /main/foo/bar HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+
+echo preg_replace("/<style>(.*?)<\/style>/s", "<style>AAA</style>", $output), "\n";
+fclose($fp);
+?>
+--EXPECTF--
+
+HTTP/1.1 404 Not Found
+Host: %s
+Connection: close
+Content-Type: text/html; charset=UTF-8
+Content-Length: %d
+
+<!doctype html><html><head><title>404 Not Found</title><style>AAA</style>
+</head><body><h1>Not Found</h1><p>The requested resource / was not found on this server.</p></body></html>
+HTTP/1.1 404 Not Found
+Host: %s
+Connection: close
+Content-Type: text/html; charset=UTF-8
+Content-Length: %d
+
+<!doctype html><html><head><title>404 Not Found</title><style>AAA</style>
+</head><body><h1>Not Found</h1><p>The requested resource /main/style.css was not found on this server.</p></body></html>
+HTTP/1.1 404 Not Found
+Host: %s
+Connection: close
+Content-Type: text/html; charset=UTF-8
+Content-Length: %d
+
+<!doctype html><html><head><title>404 Not Found</title><style>AAA</style>
+</head><body><h1>Not Found</h1><p>The requested resource /main/foo/bar was not found on this server.</p></body></html>
+
diff --git a/sapi/cli/tests/php_cli_server_014.phpt b/sapi/cli/tests/php_cli_server_014.phpt
new file mode 100644
index 0000000000..f8a9905613
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_014.phpt
@@ -0,0 +1,80 @@
+--TEST--
+Bug #60477: Segfault after two multipart/form-data POST requestes
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('echo done, "\n";', TRUE);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+$output = '';
+
+// note: select() on Windows (& some other platforms) has historical issues with
+// timeouts less than 1000 millis(0.5). it may be better to increase these
+// timeouts to 1000 millis(1.0) (fsockopen eventually calls select()).
+// see articles like: http://support.microsoft.com/kb/257821
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+POST /index.php HTTP/1.1
+Host: {$host}
+Content-Type: multipart/form-data; boundary=---------123456789
+Content-Length: 70
+
+---------123456789
+Content-Type: application/x-www-form-urlencoded
+a=b
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+
+fclose($fp);
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if(fwrite($fp, <<<HEADER
+POST /main/no-exists.php HTTP/1.1
+Host: {$host}
+Content-Type: multipart/form-data; boundary=---------123456789
+Content-Length: 70
+
+---------123456789
+Content-Type: application/x-www-form-urlencoded
+a=b
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+
+echo preg_replace("/<style>(.*?)<\/style>/s", "<style>AAA</style>", $output), "\n";
+fclose($fp);
+
+?>
+--EXPECTF--
+
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: %s
+Content-type: %s
+
+done
+HTTP/1.1 404 Not Found
+Host: %s
+Connection: close
+Content-Type: %s
+Content-Length: %d
+
+<!doctype html><html><head><title>404 Not Found</title><style>AAA</style>
+</head><body><h1>Not Found</h1><p>The requested resource /main/no-exists.php was not found on this server.</p></body></html>
diff --git a/sapi/cli/tests/php_cli_server_015.phpt b/sapi/cli/tests/php_cli_server_015.phpt
new file mode 100644
index 0000000000..6fb0169244
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_015.phpt
@@ -0,0 +1,49 @@
+--TEST--
+Bug #60523 (PHP Errors are not reported in browsers using built-in SAPI)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--INI--
+display_errors=1
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start('require("syntax_error.php");');
+$dir = realpath(dirname(__FILE__));
+
+file_put_contents($dir . "/syntax_error.php", "<?php non_exists_function(); ?>");
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+$output = '';
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+GET /index.php HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ $output .= fgets($fp);
+ }
+}
+echo $output;
+@unlink($dir . "/syntax_error.php");
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: PHP/%s
+Content-type: text/html
+
+<br />
+<b>Fatal error</b>: Call to undefined function non_exists_function() in <b>%ssyntax_error.php</b> on line <b>%s</b><br />
diff --git a/sapi/cli/tests/php_cli_server_016.phpt b/sapi/cli/tests/php_cli_server_016.phpt
new file mode 100644
index 0000000000..f15aff1240
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_016.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #60591 (Memory leak when access a non-exists file)
+--DESCRIPTION--
+this is an indirect test for bug 60591, since mem leak is reproted in the server side
+and require php compiled with --enable-debug
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start(<<<'PHP'
+if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"]))
+ return false; // serve the requested resource as-is.
+else {
+ echo "here";
+}
+PHP
+);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+POST /no-exists.jpg HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ break;
+ }
+}
+
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 404 Not Found
diff --git a/sapi/cli/tests/php_cli_server_017.phpt b/sapi/cli/tests/php_cli_server_017.phpt
new file mode 100644
index 0000000000..73530af480
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_017.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Implement Req #60850 (Built in web server does not set $_SERVER['SCRIPT_FILENAME'] when using router)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start(<<<'PHP'
+var_dump($_SERVER['SCRIPT_FILENAME']);
+PHP
+);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+POST / HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: %s
+Content-type: text/html
+
+string(%d) "%sindex.php"
diff --git a/sapi/cli/tests/php_cli_server_018.phpt b/sapi/cli/tests/php_cli_server_018.phpt
new file mode 100644
index 0000000000..deb9348768
--- /dev/null
+++ b/sapi/cli/tests/php_cli_server_018.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Implement Req #61679 (Support HTTP PATCH method)
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+include "php_cli_server.inc";
+php_cli_server_start(<<<'PHP'
+var_dump($_SERVER['REQUEST_METHOD']);
+PHP
+);
+
+list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS);
+$port = intval($port)?:80;
+
+$fp = fsockopen($host, $port, $errno, $errstr, 0.5);
+if (!$fp) {
+ die("connect failed");
+}
+
+if(fwrite($fp, <<<HEADER
+PATCH / HTTP/1.1
+Host: {$host}
+
+
+HEADER
+)) {
+ while (!feof($fp)) {
+ echo fgets($fp);
+ }
+}
+
+fclose($fp);
+?>
+--EXPECTF--
+HTTP/1.1 200 OK
+Host: %s
+Connection: close
+X-Powered-By: %s
+Content-type: text/html
+
+string(5) "PATCH"
diff --git a/sapi/continuity/capi.c b/sapi/continuity/capi.c
index cdf7283bd8..96c39230af 100644
--- a/sapi/continuity/capi.c
+++ b/sapi/continuity/capi.c
@@ -343,9 +343,8 @@ static void sapi_capi_register_server_variables(zval * track_vars_array TSRMLS_D
}
-static void capi_log_message(char *message)
+static void capi_log_message(char *message TSRMLS_DC)
{
- TSRMLS_FETCH();
capi_request_context *rc = (capi_request_context *) SG(server_context);
logFmsg(0, "mod/php: %s", message);
}
diff --git a/sapi/embed/config.w32 b/sapi/embed/config.w32
index 8ea0781ed3..f3cc60d600 100644
--- a/sapi/embed/config.w32
+++ b/sapi/embed/config.w32
@@ -5,4 +5,5 @@ ARG_ENABLE('embed', 'Embedded SAPI library', 'no');
if (PHP_EMBED != "no") {
SAPI('embed', 'php_embed.c', 'php' + PHP_VERSION + 'embed.lib');
+ PHP_INSTALL_HEADERS("sapi/embed", "php_embed.h");
}
diff --git a/sapi/embed/php_embed.c b/sapi/embed/php_embed.c
index 8e61e2c3d6..52a5668835 100644
--- a/sapi/embed/php_embed.c
+++ b/sapi/embed/php_embed.c
@@ -90,7 +90,7 @@ static void php_embed_send_header(sapi_header_struct *sapi_header, void *server_
{
}
-static void php_embed_log_message(char *message)
+static void php_embed_log_message(char *message TSRMLS_DC)
{
fprintf (stderr, "%s\n", message);
}
diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag
index c5cea7e523..6ed9e4a249 100644
--- a/sapi/fpm/Makefile.frag
+++ b/sapi/fpm/Makefile.frag
@@ -1,17 +1,9 @@
fpm: $(SAPI_FPM_PATH)
-$(builddir)/fpm:
- @mkdir -p $(builddir)/fpm
- @mkdir -p $(builddir)/fpm/events
-
-$(SAPI_FPM_PATH): $(builddir)/fpm $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(SAPI_EXTRA_DEPS)
+$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FPM_OBJS)
$(BUILD_FPM)
-$(builddir)/fpm/fpm_conf.lo: $(builddir)/../../main/build-defs.h
-
-install-build: install-fpm
-
-install-fpm: install-sapi
+install-fpm: $(SAPI_FPM_PATH)
@echo "Installing PHP FPM binary: $(INSTALL_ROOT)$(sbindir)/"
@$(mkinstalldirs) $(INSTALL_ROOT)$(sbindir)
@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/log
@@ -20,7 +12,6 @@ install-fpm: install-sapi
@echo "Installing PHP FPM config: $(INSTALL_ROOT)$(sysconfdir)/" && \
$(mkinstalldirs) $(INSTALL_ROOT)$(sysconfdir) || :
-
@$(INSTALL_DATA) sapi/fpm/php-fpm.conf $(INSTALL_ROOT)$(sysconfdir)/php-fpm.conf.default || :
@echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man8/"
diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index 768766056e..6191c329ba 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -3,7 +3,7 @@ dnl $Id$
dnl
PHP_ARG_ENABLE(fpm,,
-[ --enable-fpm EXPERIMENTAL: Enable building of the fpm SAPI executable], no, no)
+[ --enable-fpm Enable building of the fpm SAPI executable], no, no)
dnl configure checks {{{
AC_DEFUN([AC_FPM_STDLIBS],
@@ -193,6 +193,8 @@ AC_DEFUN([AC_FPM_TRACE],
have_ptrace=no
have_broken_ptrace=yes
AC_MSG_RESULT([no])
+ ], [
+ AC_MSG_RESULT([skipped (cross compiling)])
])
fi
@@ -265,6 +267,8 @@ AC_DEFUN([AC_FPM_TRACE],
], [
proc_mem_file=""
AC_MSG_RESULT([no])
+ ], [
+ AC_MSG_RESULT([skipped (cross compiling)])
])
fi
@@ -583,11 +587,16 @@ if test "$PHP_FPM" != "no"; then
AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name])
AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name])
+ AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name])
+ AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name])
+
+ PHP_ADD_BUILD_DIR(sapi/fpm/fpm)
+ PHP_ADD_BUILD_DIR(sapi/fpm/fpm/events)
PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.service sapi/fpm/php-fpm.8 sapi/fpm/status.html)
- PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/fpm/Makefile.frag], [$abs_srcdir/sapi/fpm], [sapi/fpm])
+ PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/fpm/Makefile.frag])
SAPI_FPM_PATH=sapi/fpm/php-fpm
- PHP_SUBST(SAPI_FPM_PATH)
+
if test "$fpm_trace_type" && test -f "$abs_srcdir/sapi/fpm/fpm/fpm_trace_$fpm_trace_type.c"; then
PHP_FPM_TRACE_FILES="fpm/fpm_trace.c fpm/fpm_trace_$fpm_trace_type.c"
@@ -595,7 +604,6 @@ if test "$PHP_FPM" != "no"; then
PHP_FPM_CFLAGS="-I$abs_srcdir/sapi/fpm"
- INSTALL_IT=":"
PHP_FPM_FILES="fpm/fastcgi.c \
fpm/fpm.c \
fpm/fpm_children.c \
@@ -631,17 +639,19 @@ if test "$PHP_FPM" != "no"; then
case $host_alias in
*aix*)
- BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+ BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
;;
*darwin*)
- BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+ BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
;;
*)
- BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+ BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
;;
esac
+ PHP_SUBST(SAPI_FPM_PATH)
PHP_SUBST(BUILD_FPM)
+
else
AC_MSG_RESULT(no)
fi
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index 3faf308667..edd75be5ae 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -561,7 +561,6 @@ void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
{
fcgi_request *request;
HashPosition pos;
- int magic_quotes_gpc;;
char *var, **val;
uint var_len;
ulong idx;
@@ -594,13 +593,8 @@ void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
php_php_import_environment_variables(array_ptr TSRMLS_CC);
request = (fcgi_request*) SG(server_context);
- magic_quotes_gpc = PG(magic_quotes_gpc);
filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
- /* turn off magic_quotes while importing environment variables */
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
for (zend_hash_internal_pointer_reset_ex(request->env, &pos);
zend_hash_get_current_key_ex(request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
zend_hash_get_current_data_ex(request->env, (void **) &val, &pos) == SUCCESS;
@@ -612,9 +606,6 @@ void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
}
}
- if (magic_quotes_gpc) {
- zend_alter_ini_entry_ex("magic_quotes_gpc", sizeof("magic_quotes_gpc"), "1", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_ACTIVATE, 1 TSRMLS_CC);
- }
}
static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
@@ -944,7 +935,6 @@ static void php_cgi_usage(char *argv0)
" force to stay in foreground, and ignore daemonize option from config file\n"
" -R, --allow-to-run-as-root\n"
" Allow pool to run as root (disabled by default)\n",
-
prog, PHP_PREFIX);
}
/* }}} */
@@ -1508,7 +1498,7 @@ PHP_FUNCTION(fastcgi_finish_request) /* {{{ */
if (request->fd >= 0) {
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
php_header(TSRMLS_C);
fcgi_flush(request, 1);
@@ -1544,7 +1534,7 @@ static zend_module_entry cgi_module_entry = {
int main(int argc, char *argv[])
{
int exit_status = FPM_EXIT_OK;
- int cgi = 0, c;
+ int cgi = 0, c, use_extended_info = 0;
zend_file_handle file_handle;
/* temporary locals */
@@ -1569,8 +1559,6 @@ int main(int argc, char *argv[])
int php_information = 0;
int php_allow_to_run_as_root = 0;
- fcgi_init();
-
#ifdef HAVE_SIGNAL_H
#if defined(SIGPIPE) && defined(SIG_IGN)
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so
@@ -1589,6 +1577,9 @@ int main(int argc, char *argv[])
sapi_startup(&cgi_sapi_module);
cgi_sapi_module.php_ini_path_override = NULL;
+ cgi_sapi_module.php_ini_ignore_cwd = 1;
+
+ fcgi_init();
#ifdef PHP_WIN32
_fmode = _O_BINARY; /* sets default for file streams to binary */
@@ -1655,7 +1646,7 @@ int main(int argc, char *argv[])
break;
case 'e': /* enable extended info output */
- CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
+ use_extended_info = 1;
break;
case 't':
@@ -1664,7 +1655,6 @@ int main(int argc, char *argv[])
case 'm': /* list compiled in modules */
cgi_sapi_module.startup(&cgi_sapi_module);
- php_output_startup();
php_output_activate(TSRMLS_C);
SG(headers_sent) = 1;
php_printf("[PHP Modules]\n");
@@ -1672,7 +1662,8 @@ int main(int argc, char *argv[])
php_printf("\n[Zend Modules]\n");
print_extensions(TSRMLS_C);
php_printf("\n");
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
+ php_output_deactivate(TSRMLS_C);
fcgi_shutdown();
exit_status = FPM_EXIT_OK;
goto out;
@@ -1697,11 +1688,11 @@ int main(int argc, char *argv[])
case 'h':
case '?':
cgi_sapi_module.startup(&cgi_sapi_module);
- php_output_startup();
php_output_activate(TSRMLS_C);
SG(headers_sent) = 1;
php_cgi_usage(argv[0]);
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
+ php_output_deactivate(TSRMLS_C);
fcgi_shutdown();
exit_status = (c == 'h') ? FPM_EXIT_OK : FPM_EXIT_USAGE;
goto out;
@@ -1745,16 +1736,16 @@ int main(int argc, char *argv[])
goto out;
}
- /* No other args are permitted here as there is not interactive mode */
+ /* No other args are permitted here as there is no interactive mode */
if (argc != php_optind) {
cgi_sapi_module.startup(&cgi_sapi_module);
- php_output_startup();
php_output_activate(TSRMLS_C);
SG(headers_sent) = 1;
php_cgi_usage(argv[0]);
- php_end_ob_buffers(1 TSRMLS_CC);
- exit_status = FPM_EXIT_USAGE;
+ php_output_end_all(TSRMLS_C);
+ php_output_deactivate(TSRMLS_C);
fcgi_shutdown();
+ exit_status = FPM_EXIT_USAGE;
goto out;
}
@@ -1775,6 +1766,10 @@ int main(int argc, char *argv[])
#endif
return FPM_EXIT_SOFTWARE;
}
+
+ if (use_extended_info) {
+ CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
+ }
/* check force_cgi after startup, so we have proper output */
if (cgi && CGIG(force_redirect)) {
diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c
index cd97aebb33..d95d66a754 100644
--- a/sapi/fpm/fpm/fpm_php_trace.c
+++ b/sapi/fpm/fpm/fpm_php_trace.c
@@ -26,6 +26,7 @@
#include "fpm_children.h"
#include "fpm_worker_pool.h"
#include "fpm_process_ctl.h"
+#include "fpm_scoreboard.h"
#include "zlog.h"
@@ -137,6 +138,7 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
void fpm_php_trace(struct fpm_child_s *child) /* {{{ */
{
TSRMLS_FETCH();
+ fpm_scoreboard_update(0, 0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_SET, child->wp->scoreboard);
FILE *slowlog;
zlog(ZLOG_NOTICE, "about to trace %d", (int) child->pid);
diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c
index 7840d17f8b..76ea4d358e 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.c
+++ b/sapi/fpm/fpm/fpm_process_ctl.c
@@ -353,7 +353,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
#endif
}
}
- fpm_scoreboard_update(idle, active, cur_lq, -1, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
+ fpm_scoreboard_update(idle, active, cur_lq, -1, -1, -1, 0, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
/* this is specific to PM_STYLE_ONDEMAND */
if (wp->config->pm == PM_STYLE_ONDEMAND) {
@@ -388,7 +388,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
if (idle < wp->config->pm_min_spare_servers) {
if (wp->running_children >= wp->config->pm_max_children) {
if (!wp->warn_max_children) {
- fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
+ fpm_scoreboard_update(0, 0, 0, 0, 0, 1, 0, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
zlog(ZLOG_WARNING, "[pool %s] server reached pm.max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
wp->warn_max_children = 1;
}
@@ -407,7 +407,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
children_to_fork = MIN(children_to_fork, wp->config->pm_max_children - wp->running_children);
if (children_to_fork <= 0) {
if (!wp->warn_max_children) {
- fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
+ fpm_scoreboard_update(0, 0, 0, 0, 0, 1, 0, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
zlog(ZLOG_WARNING, "[pool %s] server reached pm.max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
wp->warn_max_children = 1;
}
@@ -511,7 +511,7 @@ void fpm_pctl_on_socket_accept(struct fpm_event_s *ev, short which, void *arg) /
if (wp->running_children >= wp->config->pm_max_children) {
if (!wp->warn_max_children) {
- fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
+ fpm_scoreboard_update(0, 0, 0, 0, 0, 1, 0, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
zlog(ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
wp->warn_max_children = 1;
}
diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
index 28332d0a92..bf431a08d0 100644
--- a/sapi/fpm/fpm/fpm_request.c
+++ b/sapi/fpm/fpm/fpm_request.c
@@ -54,7 +54,7 @@ void fpm_request_accepting() /* {{{ */
fpm_scoreboard_proc_release(proc);
/* idle++, active-- */
- fpm_scoreboard_update(1, -1, 0, 0, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL);
+ fpm_scoreboard_update(1, -1, 0, 0, 0, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL);
}
/* }}} */
@@ -98,7 +98,7 @@ void fpm_request_reading_headers() /* {{{ */
fpm_scoreboard_proc_release(proc);
/* idle--, active++, request++ */
- fpm_scoreboard_update(-1, 1, 0, 0, 1, 0, FPM_SCOREBOARD_ACTION_INC, NULL);
+ fpm_scoreboard_update(-1, 1, 0, 0, 1, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL);
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c
index 4222f6037c..24463a90dd 100644
--- a/sapi/fpm/fpm/fpm_scoreboard.c
+++ b/sapi/fpm/fpm/fpm_scoreboard.c
@@ -73,7 +73,7 @@ int fpm_scoreboard_init_main() /* {{{ */
}
/* }}} */
-void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int action, struct fpm_scoreboard_s *scoreboard) /* {{{ */
+void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard) /* {{{ */
{
if (!scoreboard) {
scoreboard = fpm_scoreboard;
@@ -110,6 +110,9 @@ void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int request
if (max_children_reached >= 0) {
scoreboard->max_children_reached = max_children_reached;
}
+ if (slow_rq > 0) {
+ scoreboard->slow_rq += slow_rq;
+ }
} else {
if (scoreboard->idle + idle > 0) {
scoreboard->idle += idle;
diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h
index 136ea481a4..f58a28737d 100644
--- a/sapi/fpm/fpm/fpm_scoreboard.h
+++ b/sapi/fpm/fpm/fpm_scoreboard.h
@@ -64,13 +64,14 @@ struct fpm_scoreboard_s {
unsigned int lq_len;
unsigned int nprocs;
int free_proc;
+ unsigned long int slow_rq;
struct fpm_scoreboard_proc_s *procs[];
};
int fpm_scoreboard_init_main();
int fpm_scoreboard_init_child(struct fpm_worker_pool_s *wp);
-void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int action, struct fpm_scoreboard_s *scoreboard);
+void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard);
struct fpm_scoreboard_s *fpm_scoreboard_get();
struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index);
diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c
index f56b9cfbd1..76759e7f25 100644
--- a/sapi/fpm/fpm/fpm_sockets.c
+++ b/sapi/fpm/fpm/fpm_sockets.c
@@ -356,7 +356,7 @@ int fpm_sockets_init_main() /* {{{ */
}
if (wp->listen_address_domain == FPM_AF_INET && fpm_socket_get_listening_queue(wp->listening_socket, NULL, &lq_len) >= 0) {
- fpm_scoreboard_update(-1, -1, -1, (int)lq_len, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
+ fpm_scoreboard_update(-1, -1, -1, (int)lq_len, -1, -1, 0, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
}
}
diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c
index 7bad5951d8..2363b57f80 100644
--- a/sapi/fpm/fpm/fpm_status.c
+++ b/sapi/fpm/fpm/fpm_status.c
@@ -158,6 +158,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"<tr><th>total processes</th><td>%d</td></tr>\n"
"<tr><th>max active processes</th><td>%d</td></tr>\n"
"<tr><th>max children reached</th><td>%u</td></tr>\n"
+ "<tr><th>slow requests</th><td>%lu</td></tr>\n"
"</table>\n";
if (!full) {
@@ -228,7 +229,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"<active-processes>%d</active-processes>\n"
"<total-processes>%d</total-processes>\n"
"<max-active-processes>%d</max-active-processes>\n"
- "<max-children-reached>%u</max-children-reached>\n";
+ "<max-children-reached>%u</max-children-reached>\n"
+ "<slow-requests>%lu</slow-requests>\n";
if (!full) {
short_post = "</status>";
@@ -277,7 +279,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"\"active processes\":%d,"
"\"total processes\":%d,"
"\"max active processes\":%d,"
- "\"max children reached\":%u";
+ "\"max children reached\":%u,"
+ "\"slow requests\":%lu";
if (!full) {
short_post = "}";
@@ -326,7 +329,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"active processes: %d\n"
"total processes: %d\n"
"max active processes: %d\n"
- "max children reached: %u\n";
+ "max children reached: %u\n"
+ "slow requests: %lu\n";
if (full) {
full_syntax =
@@ -367,7 +371,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
scoreboard.active,
scoreboard.idle + scoreboard.active,
scoreboard.active_max,
- scoreboard.max_children_reached);
+ scoreboard.max_children_reached,
+ scoreboard.slow_rq);
PUTS(buffer);
efree(buffer);
@@ -378,7 +383,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
/* no need to test the var 'full' */
if (full_syntax) {
- int i, len, first;
+ int i, first;
+ size_t len;
char *query_string;
struct timeval duration, now;
#ifdef HAVE_FPM_LQ
diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in
index 44e4dbac08..a63dec7098 100644
--- a/sapi/fpm/php-fpm.conf.in
+++ b/sapi/fpm/php-fpm.conf.in
@@ -150,9 +150,9 @@ group = @php_fpm_group@
; Note: This value is mandatory.
listen = 127.0.0.1:9000
-; Set listen(2) backlog. A value of '-1' means unlimited.
+; Set listen(2) backlog.
; Default Value: 128 (-1 on FreeBSD and OpenBSD)
-;listen.backlog = -1
+;listen.backlog = 128
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
diff --git a/sapi/litespeed/Makefile.frag b/sapi/litespeed/Makefile.frag
index e1af2b90ca..b70e5e8702 100644
--- a/sapi/litespeed/Makefile.frag
+++ b/sapi/litespeed/Makefile.frag
@@ -1,3 +1,9 @@
-$(SAPI_LITESPEED_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
+litespeed: $(SAPI_LITESPEED_PATH)
+
+$(SAPI_LITESPEED_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_LITESPEED_OBJS)
$(BUILD_LITESPEED)
+install-litespeed: $(SAPI_LITESPEED_PATH)
+ @echo "Installing PHP LitSpeed binary: $(INSTALL_ROOT)$(bindir)/"
+ @$(INSTALL) -m 0755 $(SAPI_LITESPEED_PATH) $(INSTALL_ROOT)$(bindir)/lsphp
+
diff --git a/sapi/litespeed/config.m4 b/sapi/litespeed/config.m4
index 2b9522a821..268b9aecde 100644
--- a/sapi/litespeed/config.m4
+++ b/sapi/litespeed/config.m4
@@ -10,22 +10,21 @@ PHP_ARG_WITH(litespeed,,
if test "$PHP_LITESPEED" != "no"; then
PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/litespeed/Makefile.frag,$abs_srcdir/sapi/litespeed,sapi/litespeed)
SAPI_LITESPEED_PATH=sapi/litespeed/php
- PHP_SUBST(SAPI_LITESPEED_PATH)
PHP_SELECT_SAPI(litespeed, program, lsapi_main.c lsapilib.c, "", '$(SAPI_LITESPEED_PATH)')
- INSTALL_IT="@echo \"Installing PHP LiteSpeed into: \$(INSTALL_ROOT)\$(bindir)/\"; \$(INSTALL) -m 0755 \$(SAPI_LITESPEED_PATH) \$(INSTALL_ROOT)\$(bindir)/lsphp"
case $host_alias in
*darwin*)
- BUILD_LITESPEED="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
+ BUILD_LITESPEED="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_LITESPEED_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
;;
*cygwin*)
SAPI_LITESPEED_PATH=sapi/litespeed/php.exe
- BUILD_LITESPEED="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
+ BUILD_LITESPEED="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_LITESPEED_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
;;
*)
- BUILD_LITESPEED="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
+ BUILD_LITESPEED="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_LITESPEED_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
;;
esac
+ PHP_SUBST(SAPI_LITESPEED_PATH)
PHP_SUBST(BUILD_LITESPEED)
fi
diff --git a/sapi/milter/Makefile.frag b/sapi/milter/Makefile.frag
index 8dbdf7a8fd..26200a196c 100644
--- a/sapi/milter/Makefile.frag
+++ b/sapi/milter/Makefile.frag
@@ -1,2 +1,8 @@
-$(SAPI_MILTER_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
+milter: $(SAPI_MILTER_PATH)
+
+$(SAPI_MILTER_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_SAPI_OBJS)
$(BUILD_MILTER)
+
+install-milter: $(SAPI_MILTER_PATH)
+ @$(INSTALL) -m 0755 $(SAPI_MILTER_PATH) $(bindir)/php-milter
+
diff --git a/sapi/milter/config.m4 b/sapi/milter/config.m4
index e314551857..48c7a5d804 100644
--- a/sapi/milter/config.m4
+++ b/sapi/milter/config.m4
@@ -25,8 +25,7 @@ if test "$PHP_MILTER" != "no"; then
PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/milter/Makefile.frag)
PHP_SELECT_SAPI(milter, program, php_milter.c getopt.c,,'$(SAPI_MILTER_PATH)')
PHP_ADD_LIBRARY_WITH_PATH(milter, $MILTERPATH,)
- BUILD_MILTER="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MILTER_PATH)"
- INSTALL_IT="\$(INSTALL) -m 0755 \$(SAPI_MILTER_PATH) \$(bindir)/php-milter"
+ BUILD_MILTER="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MILTER_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MILTER_PATH)"
PHP_SUBST(SAPI_MILTER_PATH)
PHP_SUBST(BUILD_MILTER)
fi
diff --git a/sapi/milter/php_milter.c b/sapi/milter/php_milter.c
index 84121bebb5..43e1f2345a 100644
--- a/sapi/milter/php_milter.c
+++ b/sapi/milter/php_milter.c
@@ -1040,11 +1040,10 @@ int main(int argc, char *argv[])
while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) {
switch (c) {
case '?':
- php_output_startup();
- php_output_activate(TSRMLS_C);
+ php_output_tearup();
SG(headers_sent) = 1;
php_milter_usage(argv[0]);
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_teardown();
exit(1);
break;
}
@@ -1088,11 +1087,10 @@ int main(int argc, char *argv[])
case 'h': /* help & quit */
case '?':
- php_output_startup();
- php_output_activate(TSRMLS_C);
+ php_output_tearup();
SG(headers_sent) = 1;
php_milter_usage(argv[0]);
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_teardown();
exit(1);
break;
@@ -1112,7 +1110,7 @@ int main(int argc, char *argv[])
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_teardown();
exit(1);
break;
diff --git a/sapi/nsapi/nsapi.c b/sapi/nsapi/nsapi.c
index 202bf54bcf..1579ef78c8 100644
--- a/sapi/nsapi/nsapi.c
+++ b/sapi/nsapi/nsapi.c
@@ -347,7 +347,7 @@ PHP_FUNCTION(nsapi_virtual)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests do not work with zlib.output_compression", uri);
RETURN_FALSE;
} else {
- php_end_ob_buffers(1 TSRMLS_CC);
+ php_output_end_all(TSRMLS_C);
php_header(TSRMLS_C);
/* do the sub-request */
@@ -414,9 +414,7 @@ PHP_FUNCTION(nsapi_request_headers)
for (i=0; i < rc->rq->headers->hsize; i++) {
entry=rc->rq->headers->ht[i];
while (entry) {
- if (!PG(safe_mode) || strncasecmp(entry->param->name, "authorization", 13)) {
- add_assoc_string(return_value, entry->param->name, entry->param->value, 1);
- }
+ add_assoc_string(return_value, entry->param->name, entry->param->value, 1);
entry=entry->next;
}
}
@@ -676,24 +674,22 @@ static void sapi_nsapi_register_server_variables(zval *track_vars_array TSRMLS_D
for (i=0; i < rc->rq->headers->hsize; i++) {
entry=rc->rq->headers->ht[i];
while (entry) {
- if (!PG(safe_mode) || strncasecmp(entry->param->name, "authorization", 13)) {
- if (strcasecmp(entry->param->name, "content-length")==0 || strcasecmp(entry->param->name, "content-type")==0) {
- value=estrdup(entry->param->name);
- pos = 0;
- } else {
- spprintf(&value, 0, "HTTP_%s", entry->param->name);
- pos = 5;
- }
- if (value) {
- for(p = value + pos; *p; p++) {
- *p = toupper(*p);
- if (!isalnum(*p)) {
- *p = '_';
- }
+ if (strcasecmp(entry->param->name, "content-length")==0 || strcasecmp(entry->param->name, "content-type")==0) {
+ value=estrdup(entry->param->name);
+ pos = 0;
+ } else {
+ spprintf(&value, 0, "HTTP_%s", entry->param->name);
+ pos = 5;
+ }
+ if (value) {
+ for(p = value + pos; *p; p++) {
+ *p = toupper(*p);
+ if (!isalnum(*p)) {
+ *p = '_';
}
- php_register_variable(value, entry->param->value, track_vars_array TSRMLS_CC);
- efree(value);
}
+ php_register_variable(value, entry->param->value, track_vars_array TSRMLS_CC);
+ efree(value);
}
entry=entry->next;
}
@@ -779,9 +775,8 @@ static void sapi_nsapi_register_server_variables(zval *track_vars_array TSRMLS_D
}
}
-static void nsapi_log_message(char *message)
+static void nsapi_log_message(char *message TSRMLS_DC)
{
- TSRMLS_FETCH();
nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
if (rc) {
@@ -791,7 +786,7 @@ static void nsapi_log_message(char *message)
}
}
-static time_t sapi_nsapi_get_request_time(TSRMLS_D)
+static double sapi_nsapi_get_request_time(TSRMLS_D)
{
return REQ_TIME( ((nsapi_request_context *)SG(server_context))->rq );
}
@@ -1035,7 +1030,7 @@ int NSAPI_PUBLIC php5_execute(pblock *pb, Session *sn, Request *rq)
nsapi_php_ini_entries(NSLS_C TSRMLS_CC);
- if (!PG(safe_mode)) php_handle_auth_data(pblock_findval("authorization", rq->headers) TSRMLS_CC);
+ php_handle_auth_data(pblock_findval("authorization", rq->headers) TSRMLS_CC);
file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.filename = SG(request_info).path_translated;
diff --git a/sapi/phttpd/phttpd.c b/sapi/phttpd/phttpd.c
index 3aa1964463..5930a1942f 100644
--- a/sapi/phttpd/phttpd.c
+++ b/sapi/phttpd/phttpd.c
@@ -71,7 +71,6 @@ php_phttpd_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_str
{
char *header_name, *header_content;
char *p;
- TSRMLS_FETCH();
http_sendheaders(PHG(cip)->fd, PHG(cip), SG(sapi_headers).http_response_code, NULL);
@@ -97,8 +96,6 @@ php_phttpd_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_str
static int
php_phttpd_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
- TSRMLS_FETCH();
-
if (SG(sapi_headers).send_default_content_type) {
fd_printf(PHG(cip)->fd,"Content-Type: text/html\n");
}
@@ -115,7 +112,6 @@ php_phttpd_sapi_read_cookies(TSRMLS_D)
/*
int i;
char *http_cookie = NULL;
- NTSRMLS_FETCH();
i = Ns_SetIFind(NSG(conn->headers), "cookie");
if(i != -1) {
@@ -135,7 +131,6 @@ php_phttpd_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
/*
uint max_read;
uint total_read = 0;
- NTSRMLS_FETCH();
max_read = MIN(NSG(data_avail), count_bytes);
@@ -243,12 +238,11 @@ php_phttpd_request_dtor(TSRMLS_D TSRMLS_DC)
}
-int php_doit(TSRMLS_D TSRMLS_DC)
+int php_doit(TSRMLS_D)
{
struct stat sb;
zend_file_handle file_handle;
struct httpinfo *hip = PHG(cip)->hip;
- TSRMLS_FETCH();
if (php_request_startup(TSRMLS_C) == FAILURE) {
return -1;
diff --git a/scripts/php-config.in b/scripts/php-config.in
index 13c25f2904..d6c62ccf39 100644
--- a/scripts/php-config.in
+++ b/scripts/php-config.in
@@ -2,6 +2,7 @@
SED="@SED@"
prefix="@prefix@"
+datarootdir="@datarootdir@"
exec_prefix="@exec_prefix@"
version="@PHP_VERSION@"
vernum="@PHP_VERSION_ID@"
diff --git a/scripts/phpize.in b/scripts/phpize.in
index 40ccc77b1f..43cd8d30ff 100644
--- a/scripts/phpize.in
+++ b/scripts/phpize.in
@@ -2,6 +2,7 @@
# Variable declaration
prefix='@prefix@'
+datarootdir='@datarootdir@'
exec_prefix="`eval echo @exec_prefix@`"
phpdir="`eval echo @libdir@`/build"
includedir="`eval echo @includedir@`/php"
diff --git a/scripts/phpize.m4 b/scripts/phpize.m4
index e3a30a50c5..d745ca7443 100644
--- a/scripts/phpize.m4
+++ b/scripts/phpize.m4
@@ -1,9 +1,8 @@
dnl This file becomes configure.in for self-contained extensions.
-divert(1)
-
-AC_PREREQ(2.13)
+AC_PREREQ(2.59)
AC_INIT(config.m4)
+ifdef([AC_PRESERVE_HELP_ORDER], [AC_PRESERVE_HELP_ORDER], [])
PHP_CONFIG_NICE(config.nice)
diff --git a/tests/basic/011.phpt b/tests/basic/011.phpt
index 2ec7a6ed12..79256746fe 100644
--- a/tests/basic/011.phpt
+++ b/tests/basic/011.phpt
@@ -6,11 +6,8 @@ register_argc_argv=1
ab+cd+ef+123+test
--FILE--
<?php
-
-if (!ini_get('register_globals')) {
- $argc = $_SERVER['argc'];
- $argv = $_SERVER['argv'];
-}
+$argc = $_SERVER['argc'];
+$argv = $_SERVER['argv'];
for ($i=0; $i<$argc; $i++) {
echo "$i: ".$argv[$i]."\n";
diff --git a/tests/basic/012.phpt b/tests/basic/012.phpt
index 3297853286..5c10c7c222 100644
--- a/tests/basic/012.phpt
+++ b/tests/basic/012.phpt
@@ -9,11 +9,8 @@ variables_order=GPS
ab cd ef 123 test
--FILE--
<?php
-
-if (!ini_get('register_globals')) {
- $argc = $_SERVER['argc'];
- $argv = $_SERVER['argv'];
-}
+$argc = $_SERVER['argc'];
+$argv = $_SERVER['argv'];
for ($i=1; $i<$argc; $i++) {
echo ($i-1).": ".$argv[$i]."\n";
diff --git a/tests/basic/022.phpt b/tests/basic/022.phpt
index 64314ee9ee..0ab70d4be7 100644
--- a/tests/basic/022.phpt
+++ b/tests/basic/022.phpt
@@ -2,6 +2,7 @@
Cookies test#1
--INI--
max_input_vars=1000
+filter.default=unsafe_raw
--COOKIE--
cookie1=val1 ; cookie2=val2%20; cookie3=val 3.; cookie 4= value 4 %3B; cookie1=bogus; %20cookie1=ignore;+cookie1=ignore;cookie1;cookie 5=%20 value; cookie%206=þæö;cookie+7=;$cookie.8;cookie-9=1;;;- & % $cookie 10=10
--FILE--
diff --git a/tests/basic/023.phpt b/tests/basic/023.phpt
index ddbcbae005..ca5f1dcfbb 100644
--- a/tests/basic/023.phpt
+++ b/tests/basic/023.phpt
@@ -1,8 +1,8 @@
--TEST--
Cookies test#2
--INI--
-magic_quotes_gpc=0
max_input_vars=1000
+filter.default=unsafe_raw
--COOKIE--
c o o k i e=value; c o o k i e= v a l u e ;;c%20o+o k+i%20e=v;name="value","value",UEhQIQ==;UEhQIQ==foo
--FILE--
diff --git a/tests/basic/024.phpt b/tests/basic/024.phpt
index a28470914b..bf8a206b3a 100644
--- a/tests/basic/024.phpt
+++ b/tests/basic/024.phpt
@@ -1,7 +1,6 @@
--TEST--
Test HTTP_RAW_POST_DATA creation
--INI--
-magic_quotes_gpc=0
always_populate_raw_post_data=1
max_input_vars=1000
--POST--
diff --git a/tests/basic/025.phpt b/tests/basic/025.phpt
index bafcac8091..58191bcd61 100644
--- a/tests/basic/025.phpt
+++ b/tests/basic/025.phpt
@@ -1,7 +1,6 @@
--TEST--
Test HTTP_RAW_POST_DATA with excessive post length
--INI--
-magic_quotes_gpc=0
always_populate_raw_post_data=1
post_max_size=1K
--POST--
diff --git a/tests/basic/026.phpt b/tests/basic/026.phpt
index 957aa1972c..b98a31f430 100644
--- a/tests/basic/026.phpt
+++ b/tests/basic/026.phpt
@@ -1,7 +1,6 @@
--TEST--
Registration of HTTP_RAW_POST_DATA due to unknown content-type
--INI--
-magic_quotes_gpc=0
always_populate_raw_post_data=0
--POST_RAW--
Content-Type: unknown/type
diff --git a/tests/basic/027.phpt b/tests/basic/027.phpt
index db8efbf95a..0528e835a1 100644
--- a/tests/basic/027.phpt
+++ b/tests/basic/027.phpt
@@ -1,7 +1,6 @@
--TEST--
Handling of max_input_nesting_level being reached
--INI--
-magic_quotes_gpc=0
always_populate_raw_post_data=0
display_errors=0
max_input_nesting_level=10
diff --git a/tests/basic/028.phpt b/tests/basic/028.phpt
new file mode 100644
index 0000000000..37d6f21a06
--- /dev/null
+++ b/tests/basic/028.phpt
@@ -0,0 +1,105 @@
+--TEST--
+RFC1867 character quotting
+--INI--
+file_uploads=1
+max_input_vars=1000
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name=name1
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name='name2'
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="name3"
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name=name\4
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name=name\\5
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name=name\'6
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name=name\"7
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name='name\8'
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name='name\\9'
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name='name\'10'
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name='name\"11'
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="name\12"
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="name\\13"
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="name\'14"
+
+testname
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="name\"15"
+
+testname
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+var_dump($_POST);
+?>
+--EXPECT--
+array(15) {
+ ["name1"]=>
+ string(8) "testname"
+ ["name2"]=>
+ string(8) "testname"
+ ["name3"]=>
+ string(8) "testname"
+ ["name\4"]=>
+ string(8) "testname"
+ ["name\5"]=>
+ string(8) "testname"
+ ["name\'6"]=>
+ string(8) "testname"
+ ["name\"7"]=>
+ string(8) "testname"
+ ["name\8"]=>
+ string(8) "testname"
+ ["name\9"]=>
+ string(8) "testname"
+ ["name'10"]=>
+ string(8) "testname"
+ ["name\"11"]=>
+ string(8) "testname"
+ ["name\12"]=>
+ string(8) "testname"
+ ["name\13"]=>
+ string(8) "testname"
+ ["name\'14"]=>
+ string(8) "testname"
+ ["name"15"]=>
+ string(8) "testname"
+}
diff --git a/tests/basic/029.phpt b/tests/basic/029.phpt
new file mode 100644
index 0000000000..6d95c0771d
--- /dev/null
+++ b/tests/basic/029.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Shift_JIS request
+--SKIPIF--
+<?php
+if (!extension_loaded("mbstring")) {
+ die("skip Requires mbstring extension");
+}
+?>
+--INI--
+file_uploads=1
+mbstring.encoding_translation=1
+mbstring.http_input=Shift_JIS
+mbstring.internal_encoding=UTF-8
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="—\Ž\”\"
+
+ƒhƒŒƒ~ƒtƒ@ƒ\
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="pics"; filename="file1.txt"
+Content-Type: text/plain
+
+file1
+
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+var_dump($_FILES);
+var_dump($_POST);
+?>
+--EXPECTF--
+array(1) {
+ ["pics"]=>
+ array(5) {
+ ["name"]=>
+ string(9) "file1.txt"
+ ["type"]=>
+ string(10) "text/plain"
+ ["tmp_name"]=>
+ string(%d) "%s"
+ ["error"]=>
+ int(0)
+ ["size"]=>
+ int(6)
+ }
+}
+array(1) {
+ ["予蚕能"]=>
+ string(18) "ドレミファソ"
+}
diff --git a/tests/basic/bug46313-win.phpt b/tests/basic/bug46313-win.phpt
deleted file mode 100644
index 350134e1c9..0000000000
--- a/tests/basic/bug46313-win.phpt
+++ /dev/null
@@ -1,65 +0,0 @@
---TEST--
-Bug #46313 (Magic quotes broke $_FILES)
---SKIPIF--
-<?php if(substr(PHP_OS, 0, 3) != "WIN") die("skip Windows-only test"); ?>
---INI--
-magic_quotes_gpc=1
-file_uploads=1
-register_globals=1
-display_errors=0
---POST_RAW--
-Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
------------------------------20896060251896012921717172737
-Content-Disposition: form-data; name="o1'file"; filename="o1'file.png"
-Content-Type: text/plain-file1
-
-1
------------------------------20896060251896012921717172737
-Content-Disposition: form-data; name="o2'file"; filename="o2'file2.txt"
-Content-Type: text/plain-file2
-
-2
------------------------------20896060251896012921717172737--
---FILE--
-<?php
-var_dump($_FILES);
-var_dump($GLOBALS["o1\'file_name"]);
-var_dump($GLOBALS["o1\'file_name"] === $_FILES["o1\'file"]["name"]);
-var_dump($GLOBALS["o1\'file"]);
-var_dump($GLOBALS["o1\'file"] === $_FILES["o1\'file"]["tmp_name"]);
-/* The windows policy is walking to the last (single)quote in a file name and taking the remain.
- This way some'file.gif becomes file.gif */
-?>
---EXPECTF--
-array(2) {
- ["o1\'file"]=>
- array(5) {
- ["name"]=>
- string(8) "file.png"
- ["type"]=>
- string(16) "text/plain-file1"
- ["tmp_name"]=>
- string(%d) "%s.tmp"
- ["error"]=>
- int(0)
- ["size"]=>
- int(1)
- }
- ["o2\'file"]=>
- array(5) {
- ["name"]=>
- string(9) "file2.txt"
- ["type"]=>
- string(16) "text/plain-file2"
- ["tmp_name"]=>
- string(%d) "%s.tmp"
- ["error"]=>
- int(0)
- ["size"]=>
- int(1)
- }
-}
-string(8) "file.png"
-bool(true)
-string(%d) "%s"
-bool(true)
diff --git a/tests/basic/bug46313.phpt b/tests/basic/bug46313.phpt
deleted file mode 100644
index 924114161e..0000000000
--- a/tests/basic/bug46313.phpt
+++ /dev/null
@@ -1,63 +0,0 @@
---TEST--
-Bug #46313 (Magic quotes broke $_FILES)
---SKIPIF--
-<?php if(substr(PHP_OS, 0, 3) == "WIN") die("skip non-Windows test"); ?>
---INI--
-magic_quotes_gpc=1
-file_uploads=1
-register_globals=1
-display_errors=0
---POST_RAW--
-Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
------------------------------20896060251896012921717172737
-Content-Disposition: form-data; name="o1'file"; filename="o1'file.png"
-Content-Type: text/plain-file1
-
-1
------------------------------20896060251896012921717172737
-Content-Disposition: form-data; name="o2'file"; filename="o2'file2.txt"
-Content-Type: text/plain-file2
-
-2
------------------------------20896060251896012921717172737--
---FILE--
-<?php
-var_dump($_FILES);
-var_dump($GLOBALS["o1\'file_name"]);
-var_dump($GLOBALS["o1\'file_name"] === $_FILES["o1\'file"]["name"]);
-var_dump($GLOBALS["o1\'file"]);
-var_dump($GLOBALS["o1\'file"] === $_FILES["o1\'file"]["tmp_name"]);
-?>
---EXPECTF--
-array(2) {
- ["o1\'file"]=>
- array(5) {
- ["name"]=>
- string(12) "o1\'file.png"
- ["type"]=>
- string(16) "text/plain-file1"
- ["tmp_name"]=>
- string(%d) "%s"
- ["error"]=>
- int(0)
- ["size"]=>
- int(1)
- }
- ["o2\'file"]=>
- array(5) {
- ["name"]=>
- string(13) "o2\'file2.txt"
- ["type"]=>
- string(16) "text/plain-file2"
- ["tmp_name"]=>
- string(%d) "%s"
- ["error"]=>
- int(0)
- ["size"]=>
- int(1)
- }
-}
-string(12) "o1\'file.png"
-bool(true)
-string(%d) "%s"
-bool(true)
diff --git a/tests/basic/bug46759.phpt b/tests/basic/bug46759.phpt
deleted file mode 100644
index d35cd534c2..0000000000
--- a/tests/basic/bug46759.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Testing magic_quotes_gpc
---INI--
-display_errors=0
-magic_quotes_gpc=1
---GET--
-a='&b="&c=\"
---FILE--
-<?php
-
-foreach ($_GET AS $key => $value)
-{
- echo $key . ": " . $value . "\n";
-}
-
-?>
---EXPECT--
-a: \'
-b: \"
-c: \\\"
diff --git a/tests/basic/bug51709_1.phpt b/tests/basic/bug51709_1.phpt
index 8abb92555d..3f2d544e54 100644
--- a/tests/basic/bug51709_1.phpt
+++ b/tests/basic/bug51709_1.phpt
@@ -13,4 +13,4 @@ class foo {
===DONE===
<?php exit(0); ?>
--EXPECTF--
-Parse error: syntax error, unexpected T_FOR, expecting T_STRING in %sbug51709_1.php on line %d
+Parse error: syntax error, unexpected %s, expecting %s in %sbug51709_1.php on line %d
diff --git a/tests/basic/bug51709_2.phpt b/tests/basic/bug51709_2.phpt
index 7763cafe52..bb1f91cc4c 100644
--- a/tests/basic/bug51709_2.phpt
+++ b/tests/basic/bug51709_2.phpt
@@ -13,4 +13,4 @@ class foo {
===DONE===
<?php exit(0); ?>
--EXPECTF--
-Parse error: syntax error, unexpected T_GOTO, expecting T_STRING in %sbug51709_2.php on line %d
+Parse error: syntax error, unexpected %s, expecting %s in %sbug51709_2.php on line %d
diff --git a/tests/basic/bug54514.phpt b/tests/basic/bug54514.phpt
new file mode 100644
index 0000000000..0c5595e3f7
--- /dev/null
+++ b/tests/basic/bug54514.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Req #54514 (Get php binary path during script execution)
+--FILE--
+<?php
+if(realpath(getenv('TEST_PHP_EXECUTABLE')) === realpath(PHP_BINARY)) {
+ echo "done";
+} else {
+ var_dump(getenv('TEST_PHP_EXECUTABLE'));
+ var_dump(PHP_BINARY);
+}
+--EXPECT--
+done
diff --git a/tests/basic/enable_post_data_reading_01.phpt b/tests/basic/enable_post_data_reading_01.phpt
new file mode 100644
index 0000000000..1a0e33f617
--- /dev/null
+++ b/tests/basic/enable_post_data_reading_01.phpt
@@ -0,0 +1,22 @@
+--TEST--
+enable_post_data_reading: basic test
+--INI--
+enable_post_data_reading=0
+--POST_RAW--
+Content-Type: application/x-www-form-urlencoded
+a=1&b=ZYX
+--FILE--
+<?php
+var_dump($_FILES);
+var_dump($_POST);
+var_dump($HTTP_RAW_POST_DATA);
+var_dump(file_get_contents("php://input"));
+--EXPECTF--
+array(0) {
+}
+array(0) {
+}
+
+Notice: Undefined variable: HTTP_RAW_POST_DATA in %s on line %d
+NULL
+string(9) "a=1&b=ZYX"
diff --git a/tests/basic/enable_post_data_reading_02.phpt b/tests/basic/enable_post_data_reading_02.phpt
new file mode 100644
index 0000000000..dc7f6b127a
--- /dev/null
+++ b/tests/basic/enable_post_data_reading_02.phpt
@@ -0,0 +1,28 @@
+--TEST--
+enable_post_data_reading: rfc1867
+--INI--
+enable_post_data_reading=0
+--POST_RAW--
+Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
+-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+Content-Type: text/plain-file
+
+1
+-----------------------------20896060251896012921717172737--
+--FILE--
+<?php
+var_dump($_FILES);
+var_dump($_POST);
+var_dump(file_get_contents("php://input"));
+--EXPECTF--
+array(0) {
+}
+array(0) {
+}
+string(%d) "-----------------------------20896060251896012921717172737
+Content-Disposition: form-data; name="file1"; filename="file1.txt"
+Content-Type: text/plain-file
+
+1
+-----------------------------20896060251896012921717172737--"
diff --git a/tests/basic/enable_post_data_reading_03.phpt b/tests/basic/enable_post_data_reading_03.phpt
new file mode 100644
index 0000000000..cdabe910ca
--- /dev/null
+++ b/tests/basic/enable_post_data_reading_03.phpt
@@ -0,0 +1,23 @@
+--TEST--
+enable_post_data_reading: always_populate_raw_post_data has no effect (1)
+--INI--
+enable_post_data_reading=0
+always_populate_raw_post_data=1
+--POST_RAW--
+Content-Type: application/x-www-form-urlencoded
+a=1&b=ZYX
+--FILE--
+<?php
+var_dump($_FILES);
+var_dump($_POST);
+var_dump($HTTP_RAW_POST_DATA);
+var_dump(file_get_contents("php://input"));
+--EXPECTF--
+array(0) {
+}
+array(0) {
+}
+
+Notice: Undefined variable: HTTP_RAW_POST_DATA in %s on line %d
+NULL
+string(9) "a=1&b=ZYX"
diff --git a/tests/basic/enable_post_data_reading_04.phpt b/tests/basic/enable_post_data_reading_04.phpt
new file mode 100644
index 0000000000..a1685040bb
--- /dev/null
+++ b/tests/basic/enable_post_data_reading_04.phpt
@@ -0,0 +1,23 @@
+--TEST--
+enable_post_data_reading: always_populate_raw_post_data has no effect (2)
+--INI--
+enable_post_data_reading=0
+always_populate_raw_post_data=1
+--POST_RAW--
+Content-Type: application/unknown
+a=1&b=ZYX
+--FILE--
+<?php
+var_dump($_FILES);
+var_dump($_POST);
+var_dump($HTTP_RAW_POST_DATA);
+var_dump(file_get_contents("php://input"));
+--EXPECTF--
+array(0) {
+}
+array(0) {
+}
+
+Notice: Undefined variable: HTTP_RAW_POST_DATA in %s on line %d
+NULL
+string(9) "a=1&b=ZYX"
diff --git a/tests/basic/magic_quotes_gpc.phpt b/tests/basic/magic_quotes_gpc.phpt
deleted file mode 100644
index 0be6533b78..0000000000
--- a/tests/basic/magic_quotes_gpc.phpt
+++ /dev/null
@@ -1,11 +0,0 @@
---TEST--
-Bug #61043 (Regression in magic_quotes_gpc fix for CVE-2012-0831)
---INI--
-error_reporting=E_ALL & ~E_DEPRECATED
-magic_quotes_gpc=On
---FILE--
-<?php
-var_dump(ini_get("magic_quotes_gpc"));
-?>
---EXPECT--
-string(1) "1"
diff --git a/tests/basic/req44164.phpt b/tests/basic/req44164.phpt
new file mode 100644
index 0000000000..d0082861f2
--- /dev/null
+++ b/tests/basic/req44164.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Req #44164 (Handle "Content-Length" HTTP header when zlib.output_compression active)
+--SKIPIF--
+<?php
+if (!function_exists('gzdeflate'))
+ die("skip zlib extension required");
+?>
+--INI--
+zlib.output_compression=On
+--ENV--
+HTTP_ACCEPT_ENCODING=gzip
+--FILE--
+<?php
+header("Content-length: 200");
+echo str_repeat("a", 200);
+--EXPECT--
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/tests/classes/array_access_010.phpt b/tests/classes/array_access_010.phpt
index e60716dc1b..ad374d278c 100644
--- a/tests/classes/array_access_010.phpt
+++ b/tests/classes/array_access_010.phpt
@@ -12,7 +12,7 @@ class ArrayReferenceProxy implements ArrayAccess
function __construct(ArrayAccess $object, array &$element)
{
- echo __METHOD__ . "($element)\n";
+ echo __METHOD__ . "(Array)\n";
$this->object = $object;
$this->element = &$element;
}
@@ -23,17 +23,17 @@ class ArrayReferenceProxy implements ArrayAccess
}
function offsetGet($index) {
- echo __METHOD__ . "($this->element, $index)\n";
+ echo __METHOD__ . "(Array, $index)\n";
return isset($this->element[$index]) ? $this->element[$index] : NULL;
}
function offsetSet($index, $value) {
- echo __METHOD__ . "($this->element, $index, $value)\n";
+ echo __METHOD__ . "(Array, $index, $value)\n";
$this->element[$index] = $value;
}
function offsetUnset($index) {
- echo __METHOD__ . "($this->element, $index)\n";
+ echo __METHOD__ . "(Array, $index)\n";
unset($this->element[$index]);
}
}
diff --git a/tests/classes/ctor_in_interface_01.phpt b/tests/classes/ctor_in_interface_01.phpt
index f6f9b66eab..e5ad30ebcd 100644
--- a/tests/classes/ctor_in_interface_01.phpt
+++ b/tests/classes/ctor_in_interface_01.phpt
@@ -16,4 +16,4 @@ class implem implements constr
?>
--EXPECTF--
-Fatal error: Declaration of implem::__construct() must be compatible with that of constr::__construct() in %s on line %d
+Fatal error: Declaration of implem::__construct() must be compatible with constr::__construct() in %s on line %d
diff --git a/tests/classes/ctor_in_interface_02.phpt b/tests/classes/ctor_in_interface_02.phpt
index ad9fac3892..08e6f36e0e 100644
--- a/tests/classes/ctor_in_interface_02.phpt
+++ b/tests/classes/ctor_in_interface_02.phpt
@@ -29,7 +29,6 @@ class implem13 implements constr1, constr3
{
}
}
-
?>
--EXPECTF--
-Fatal error: Declaration of implem13::__construct() must be compatible with that of constr3::__construct() in %sctor_in_interface_02.php on line %d
+Fatal error: Declaration of implem13::__construct() must be compatible with constr3::__construct($a) in %s on line %d
diff --git a/tests/classes/ctor_in_interface_03.phpt b/tests/classes/ctor_in_interface_03.phpt
index 953d6822fd..ac73331207 100644
--- a/tests/classes/ctor_in_interface_03.phpt
+++ b/tests/classes/ctor_in_interface_03.phpt
@@ -20,4 +20,4 @@ class derived extends implem
?>
--EXPECTF--
-Fatal error: Declaration of derived::__construct() must be compatible with that of constr::__construct() in %s on line %d
+Fatal error: Declaration of derived::__construct() must be compatible with constr::__construct() in %s on line %d
diff --git a/tests/classes/ctor_in_interface_04.phpt b/tests/classes/ctor_in_interface_04.phpt
index 0016244c18..94be655b83 100644
--- a/tests/classes/ctor_in_interface_04.phpt
+++ b/tests/classes/ctor_in_interface_04.phpt
@@ -23,4 +23,4 @@ class derived extends implem
?>
--EXPECTF--
-Fatal error: Declaration of derived::__construct() must be compatible with that of constr::__construct() in %s on line %d
+Fatal error: Declaration of derived::__construct() must be compatible with constr::__construct() in %s on line %d
diff --git a/tests/classes/implicit_instantiation_001.phpt b/tests/classes/implicit_instantiation_001.phpt
index 460cdc97f2..8d2f32da21 100644
--- a/tests/classes/implicit_instantiation_001.phpt
+++ b/tests/classes/implicit_instantiation_001.phpt
@@ -39,43 +39,43 @@ var_dump($c);
---( $c->boolFalse )---
--> Attempting implicit conversion to object using increment...
-Strict Standards: Creating default object from empty value in %s on line 18
+Warning: Creating default object from empty value in %s on line 18
--> Attempting implicit conversion to object using assignment...
-Strict Standards: Creating default object from empty value in %s on line 22
+Warning: Creating default object from empty value in %s on line 22
--> Attempting implicit conversion to object using combined assignment...
-Strict Standards: Creating default object from empty value in %s on line 26
+Warning: Creating default object from empty value in %s on line 26
---( $c->emptyString )---
--> Attempting implicit conversion to object using increment...
-Strict Standards: Creating default object from empty value in %s on line 18
+Warning: Creating default object from empty value in %s on line 18
--> Attempting implicit conversion to object using assignment...
-Strict Standards: Creating default object from empty value in %s on line 22
+Warning: Creating default object from empty value in %s on line 22
--> Attempting implicit conversion to object using combined assignment...
-Strict Standards: Creating default object from empty value in %s on line 26
+Warning: Creating default object from empty value in %s on line 26
---( $c->null )---
--> Attempting implicit conversion to object using increment...
-Strict Standards: Creating default object from empty value in %s on line 18
+Warning: Creating default object from empty value in %s on line 18
--> Attempting implicit conversion to object using assignment...
-Strict Standards: Creating default object from empty value in %s on line 22
+Warning: Creating default object from empty value in %s on line 22
--> Attempting implicit conversion to object using combined assignment...
-Strict Standards: Creating default object from empty value in %s on line 26
+Warning: Creating default object from empty value in %s on line 26
---( $c->boolTrue )---
diff --git a/tests/classes/inheritance_003.phpt b/tests/classes/inheritance_003.phpt
index a22e5cce58..1f4eafa537 100644
--- a/tests/classes/inheritance_003.phpt
+++ b/tests/classes/inheritance_003.phpt
@@ -17,5 +17,5 @@ class B extends A
===DONE===
--EXPECTF--
-Strict Standards: Declaration of B::f() should be compatible with that of A::f() in %sinheritance_003.php on line %d
+Strict Standards: Declaration of B::f() should be compatible with A::f($x) in %sinheritance_003.php on line %d
===DONE===
diff --git a/tests/classes/inheritance_004.phpt b/tests/classes/inheritance_004.phpt
index 9c81970cc2..d1f5faf5da 100644
--- a/tests/classes/inheritance_004.phpt
+++ b/tests/classes/inheritance_004.phpt
@@ -17,5 +17,5 @@ class B extends A
===DONE===
--EXPECTF--
-Strict Standards: Declaration of B::f() should be compatible with that of A::f() in %sinheritance_004.php on line %d
+Strict Standards: Declaration of B::f() should be compatible with A::f() in %sinheritance_004.php on line %d
===DONE===
diff --git a/tests/classes/is_a.phpt b/tests/classes/is_a.phpt
deleted file mode 100644
index 832d5550f1..0000000000
--- a/tests/classes/is_a.phpt
+++ /dev/null
@@ -1,378 +0,0 @@
---TEST--
-is_a and is_subclass_of behaviour (with and without autoload)
---SKIPIF--
-<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?>
---FILE--
-<?php
-
-interface if_a {
- function f_a();
-}
-
-interface if_b extends if_a {
- function f_b();
-}
-
-class base {
- function _is_a($sub) {
-
- echo "\n>>> With Defined class\n";
- echo str_pad('is_a( OBJECT:'.get_class($this).', '.$sub.') = ', 60) . (is_a($this, $sub) ? 'yes' : 'no')."\n";
- echo str_pad('is_a( STRING:'.get_class($this).', '.$sub.') = ', 60). (is_a(get_class($this), $sub) ? 'yes' : 'no')."\n";
- echo str_pad('is_a( STRING:'.get_class($this).', '.$sub.', true) = ', 60). (is_a(get_class($this), $sub, true) ? 'yes' : 'no')."\n";
- echo str_pad('is_subclass_of( OBJECT:'.get_class($this).', '.$sub.') = ', 60). (is_subclass_of($this, $sub) ? 'yes' : 'no')."\n";
- echo str_pad('is_subclass_of( STRING:'.get_class($this).', '.$sub.') = ', 60). (is_subclass_of(get_class($this), $sub) ? 'yes' : 'no')."\n";
- echo str_pad('is_subclass_of( STRING:'.get_class($this).', '.$sub.',false) = ', 60). (is_subclass_of(get_class($this), $sub , false) ? 'yes' : 'no')."\n";
-
- // with autoload options..
- echo ">>> With Undefined\n";
- echo str_pad('is_a( STRING:undefB, '.$sub.',true) = ', 60). (is_a('undefB', $sub, true) ? 'yes' : 'no')."\n";
- echo str_pad('is_a( STRING:undefB, '.$sub.') = ', 60). (is_a('undefB', $sub) ? 'yes' : 'no')."\n";
- echo str_pad('is_subclass_of( STRING:undefB, '.$sub.',false) = ', 60). (is_subclass_of('undefB', $sub, false) ? 'yes' : 'no')."\n";
- echo str_pad('is_subclass_of( STRING:undefB, '.$sub.') = ', 60). (is_subclass_of('undefB', $sub) ? 'yes' : 'no')."\n";
- }
- function test() {
- echo $this->_is_a('base');
- echo $this->_is_a('derived_a');
- echo $this->_is_a('if_a');
- echo $this->_is_a('undefA');
- echo "\n";
- }
-}
-
-class derived_a extends base implements if_a {
- function f_a() {}
-}
-
-class derived_b extends base implements if_a, if_b {
- function f_a() {}
- function f_b() {}
-}
-
-class derived_c extends derived_a implements if_b {
- function f_b() {}
-}
-
-class derived_d extends derived_c {
-}
-
-$t = new base();
-$t->test();
-
-$t = new derived_a();
-$t->test();
-
-eval('
- function __autoload($name)
- {
- echo ">>>> In __autoload: ";
- var_dump($name);
- }
-');
-
-echo "NOW WITH AUTOLOAD\n\n";
-
-$t = new base();
-$t->test();
-
-$t = new derived_a();
-$t->test();
-
-$t = new derived_b();
-$t->test();
-
-
-
-
-
-?>
---EXPECTF--
->>> With Defined class
-is_a( OBJECT:base, base) = yes
-is_a( STRING:base, base) = no
-is_a( STRING:base, base, true) = yes
-is_subclass_of( OBJECT:base, base) = no
-is_subclass_of( STRING:base, base) = no
-is_subclass_of( STRING:base, base,false) = no
->>> With Undefined
-is_a( STRING:undefB, base,true) = no
-is_a( STRING:undefB, base) = no
-is_subclass_of( STRING:undefB, base,false) = no
-is_subclass_of( STRING:undefB, base) = no
-
->>> With Defined class
-is_a( OBJECT:base, derived_a) = no
-is_a( STRING:base, derived_a) = no
-is_a( STRING:base, derived_a, true) = no
-is_subclass_of( OBJECT:base, derived_a) = no
-is_subclass_of( STRING:base, derived_a) = no
-is_subclass_of( STRING:base, derived_a,false) = no
->>> With Undefined
-is_a( STRING:undefB, derived_a,true) = no
-is_a( STRING:undefB, derived_a) = no
-is_subclass_of( STRING:undefB, derived_a,false) = no
-is_subclass_of( STRING:undefB, derived_a) = no
-
->>> With Defined class
-is_a( OBJECT:base, if_a) = no
-is_a( STRING:base, if_a) = no
-is_a( STRING:base, if_a, true) = no
-is_subclass_of( OBJECT:base, if_a) = no
-is_subclass_of( STRING:base, if_a) = no
-is_subclass_of( STRING:base, if_a,false) = no
->>> With Undefined
-is_a( STRING:undefB, if_a,true) = no
-is_a( STRING:undefB, if_a) = no
-is_subclass_of( STRING:undefB, if_a,false) = no
-is_subclass_of( STRING:undefB, if_a) = no
-
->>> With Defined class
-is_a( OBJECT:base, undefA) = no
-is_a( STRING:base, undefA) = no
-is_a( STRING:base, undefA, true) = no
-is_subclass_of( OBJECT:base, undefA) = no
-is_subclass_of( STRING:base, undefA) = no
-is_subclass_of( STRING:base, undefA,false) = no
->>> With Undefined
-is_a( STRING:undefB, undefA,true) = no
-is_a( STRING:undefB, undefA) = no
-is_subclass_of( STRING:undefB, undefA,false) = no
-is_subclass_of( STRING:undefB, undefA) = no
-
-
->>> With Defined class
-is_a( OBJECT:derived_a, base) = yes
-is_a( STRING:derived_a, base) = no
-is_a( STRING:derived_a, base, true) = yes
-is_subclass_of( OBJECT:derived_a, base) = yes
-is_subclass_of( STRING:derived_a, base) = yes
-is_subclass_of( STRING:derived_a, base,false) = no
->>> With Undefined
-is_a( STRING:undefB, base,true) = no
-is_a( STRING:undefB, base) = no
-is_subclass_of( STRING:undefB, base,false) = no
-is_subclass_of( STRING:undefB, base) = no
-
->>> With Defined class
-is_a( OBJECT:derived_a, derived_a) = yes
-is_a( STRING:derived_a, derived_a) = no
-is_a( STRING:derived_a, derived_a, true) = yes
-is_subclass_of( OBJECT:derived_a, derived_a) = no
-is_subclass_of( STRING:derived_a, derived_a) = no
-is_subclass_of( STRING:derived_a, derived_a,false) = no
->>> With Undefined
-is_a( STRING:undefB, derived_a,true) = no
-is_a( STRING:undefB, derived_a) = no
-is_subclass_of( STRING:undefB, derived_a,false) = no
-is_subclass_of( STRING:undefB, derived_a) = no
-
->>> With Defined class
-is_a( OBJECT:derived_a, if_a) = yes
-is_a( STRING:derived_a, if_a) = no
-is_a( STRING:derived_a, if_a, true) = yes
-is_subclass_of( OBJECT:derived_a, if_a) = yes
-is_subclass_of( STRING:derived_a, if_a) = yes
-is_subclass_of( STRING:derived_a, if_a,false) = no
->>> With Undefined
-is_a( STRING:undefB, if_a,true) = no
-is_a( STRING:undefB, if_a) = no
-is_subclass_of( STRING:undefB, if_a,false) = no
-is_subclass_of( STRING:undefB, if_a) = no
-
->>> With Defined class
-is_a( OBJECT:derived_a, undefA) = no
-is_a( STRING:derived_a, undefA) = no
-is_a( STRING:derived_a, undefA, true) = no
-is_subclass_of( OBJECT:derived_a, undefA) = no
-is_subclass_of( STRING:derived_a, undefA) = no
-is_subclass_of( STRING:derived_a, undefA,false) = no
->>> With Undefined
-is_a( STRING:undefB, undefA,true) = no
-is_a( STRING:undefB, undefA) = no
-is_subclass_of( STRING:undefB, undefA,false) = no
-is_subclass_of( STRING:undefB, undefA) = no
-
-NOW WITH AUTOLOAD
-
-
->>> With Defined class
-is_a( OBJECT:base, base) = yes
-is_a( STRING:base, base) = no
-is_a( STRING:base, base, true) = yes
-is_subclass_of( OBJECT:base, base) = no
-is_subclass_of( STRING:base, base) = no
-is_subclass_of( STRING:base, base,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, base,true) = no
-is_a( STRING:undefB, base) = no
-is_subclass_of( STRING:undefB, base,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, base) = no
-
->>> With Defined class
-is_a( OBJECT:base, derived_a) = no
-is_a( STRING:base, derived_a) = no
-is_a( STRING:base, derived_a, true) = no
-is_subclass_of( OBJECT:base, derived_a) = no
-is_subclass_of( STRING:base, derived_a) = no
-is_subclass_of( STRING:base, derived_a,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, derived_a,true) = no
-is_a( STRING:undefB, derived_a) = no
-is_subclass_of( STRING:undefB, derived_a,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, derived_a) = no
-
->>> With Defined class
-is_a( OBJECT:base, if_a) = no
-is_a( STRING:base, if_a) = no
-is_a( STRING:base, if_a, true) = no
-is_subclass_of( OBJECT:base, if_a) = no
-is_subclass_of( STRING:base, if_a) = no
-is_subclass_of( STRING:base, if_a,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, if_a,true) = no
-is_a( STRING:undefB, if_a) = no
-is_subclass_of( STRING:undefB, if_a,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, if_a) = no
-
->>> With Defined class
-is_a( OBJECT:base, undefA) = no
-is_a( STRING:base, undefA) = no
-is_a( STRING:base, undefA, true) = no
-is_subclass_of( OBJECT:base, undefA) = no
-is_subclass_of( STRING:base, undefA) = no
-is_subclass_of( STRING:base, undefA,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, undefA,true) = no
-is_a( STRING:undefB, undefA) = no
-is_subclass_of( STRING:undefB, undefA,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, undefA) = no
-
-
->>> With Defined class
-is_a( OBJECT:derived_a, base) = yes
-is_a( STRING:derived_a, base) = no
-is_a( STRING:derived_a, base, true) = yes
-is_subclass_of( OBJECT:derived_a, base) = yes
-is_subclass_of( STRING:derived_a, base) = yes
-is_subclass_of( STRING:derived_a, base,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, base,true) = no
-is_a( STRING:undefB, base) = no
-is_subclass_of( STRING:undefB, base,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, base) = no
-
->>> With Defined class
-is_a( OBJECT:derived_a, derived_a) = yes
-is_a( STRING:derived_a, derived_a) = no
-is_a( STRING:derived_a, derived_a, true) = yes
-is_subclass_of( OBJECT:derived_a, derived_a) = no
-is_subclass_of( STRING:derived_a, derived_a) = no
-is_subclass_of( STRING:derived_a, derived_a,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, derived_a,true) = no
-is_a( STRING:undefB, derived_a) = no
-is_subclass_of( STRING:undefB, derived_a,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, derived_a) = no
-
->>> With Defined class
-is_a( OBJECT:derived_a, if_a) = yes
-is_a( STRING:derived_a, if_a) = no
-is_a( STRING:derived_a, if_a, true) = yes
-is_subclass_of( OBJECT:derived_a, if_a) = yes
-is_subclass_of( STRING:derived_a, if_a) = yes
-is_subclass_of( STRING:derived_a, if_a,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, if_a,true) = no
-is_a( STRING:undefB, if_a) = no
-is_subclass_of( STRING:undefB, if_a,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, if_a) = no
-
->>> With Defined class
-is_a( OBJECT:derived_a, undefA) = no
-is_a( STRING:derived_a, undefA) = no
-is_a( STRING:derived_a, undefA, true) = no
-is_subclass_of( OBJECT:derived_a, undefA) = no
-is_subclass_of( STRING:derived_a, undefA) = no
-is_subclass_of( STRING:derived_a, undefA,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, undefA,true) = no
-is_a( STRING:undefB, undefA) = no
-is_subclass_of( STRING:undefB, undefA,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, undefA) = no
-
-
->>> With Defined class
-is_a( OBJECT:derived_b, base) = yes
-is_a( STRING:derived_b, base) = no
-is_a( STRING:derived_b, base, true) = yes
-is_subclass_of( OBJECT:derived_b, base) = yes
-is_subclass_of( STRING:derived_b, base) = yes
-is_subclass_of( STRING:derived_b, base,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, base,true) = no
-is_a( STRING:undefB, base) = no
-is_subclass_of( STRING:undefB, base,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, base) = no
-
->>> With Defined class
-is_a( OBJECT:derived_b, derived_a) = no
-is_a( STRING:derived_b, derived_a) = no
-is_a( STRING:derived_b, derived_a, true) = no
-is_subclass_of( OBJECT:derived_b, derived_a) = no
-is_subclass_of( STRING:derived_b, derived_a) = no
-is_subclass_of( STRING:derived_b, derived_a,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, derived_a,true) = no
-is_a( STRING:undefB, derived_a) = no
-is_subclass_of( STRING:undefB, derived_a,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, derived_a) = no
-
->>> With Defined class
-is_a( OBJECT:derived_b, if_a) = yes
-is_a( STRING:derived_b, if_a) = no
-is_a( STRING:derived_b, if_a, true) = yes
-is_subclass_of( OBJECT:derived_b, if_a) = yes
-is_subclass_of( STRING:derived_b, if_a) = yes
-is_subclass_of( STRING:derived_b, if_a,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, if_a,true) = no
-is_a( STRING:undefB, if_a) = no
-is_subclass_of( STRING:undefB, if_a,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, if_a) = no
-
->>> With Defined class
-is_a( OBJECT:derived_b, undefA) = no
-is_a( STRING:derived_b, undefA) = no
-is_a( STRING:derived_b, undefA, true) = no
-is_subclass_of( OBJECT:derived_b, undefA) = no
-is_subclass_of( STRING:derived_b, undefA) = no
-is_subclass_of( STRING:derived_b, undefA,false) = no
->>> With Undefined
->>>> In __autoload: string(6) "undefB"
-is_a( STRING:undefB, undefA,true) = no
-is_a( STRING:undefB, undefA) = no
-is_subclass_of( STRING:undefB, undefA,false) = no
->>>> In __autoload: string(6) "undefB"
-is_subclass_of( STRING:undefB, undefA) = no
diff --git a/tests/classes/method_override_optional_arg_001.phpt b/tests/classes/method_override_optional_arg_001.phpt
index 53272fff73..333c29d128 100644
--- a/tests/classes/method_override_optional_arg_001.phpt
+++ b/tests/classes/method_override_optional_arg_001.phpt
@@ -28,6 +28,6 @@ $b->foo(1);
?>
--EXPECTF--
-Strict Standards: Declaration of C::foo() should be compatible with that of A::foo() in %s on line %d
+Strict Standards: Declaration of C::foo() should be compatible with A::foo($arg1 = 1) in %s on line %d
int(1)
int(3)
diff --git a/tests/classes/method_override_optional_arg_002.phpt b/tests/classes/method_override_optional_arg_002.phpt
index c212b8260d..669a8ca836 100644
--- a/tests/classes/method_override_optional_arg_002.phpt
+++ b/tests/classes/method_override_optional_arg_002.phpt
@@ -18,5 +18,5 @@ $b->foo();
?>
--EXPECTF--
-Strict Standards: Declaration of B::foo() should be compatible with that of A::foo() in %s on line %d
+Strict Standards: Declaration of B::foo() should be compatible with A::foo($arg = 1) in %s on line %d
foo
diff --git a/tests/classes/type_hinting_003.phpt b/tests/classes/type_hinting_003.phpt
index 431d66eabc..a966210fba 100644
--- a/tests/classes/type_hinting_003.phpt
+++ b/tests/classes/type_hinting_003.phpt
@@ -57,4 +57,4 @@ array(1) {
int(25)
}
-Catchable fatal error: Argument 1 passed to Test::f1() must be an array, integer given, called in %stype_hinting_003.php on line %d and defined in %stype_hinting_003.php on line %d
+Catchable fatal error: Argument 1 passed to Test::f1() must be of the type array, integer given, called in %s on line %d and defined in %s on line %d
diff --git a/tests/classes/type_hinting_005a.phpt b/tests/classes/type_hinting_005a.phpt
index d487a44611..5e4c43b8af 100644
--- a/tests/classes/type_hinting_005a.phpt
+++ b/tests/classes/type_hinting_005a.phpt
@@ -12,7 +12,7 @@ Class D2 extends C { function f(SomeClass $a) {} }
?>
==DONE==
--EXPECTF--
-Strict Standards: Declaration of D2::f() should be compatible with that of C::f() in %s on line 8
+Strict Standards: Declaration of D2::f() should be compatible with C::f(array $a) in %s on line 8
Compatible hint.
Class hint, should be array.
-==DONE== \ No newline at end of file
+==DONE==
diff --git a/tests/classes/type_hinting_005b.phpt b/tests/classes/type_hinting_005b.phpt
index bc0d7686b5..f13ab957bb 100644
--- a/tests/classes/type_hinting_005b.phpt
+++ b/tests/classes/type_hinting_005b.phpt
@@ -9,6 +9,6 @@ Class D extends C { function f($a) {} }
?>
==DONE==
--EXPECTF--
-Strict Standards: Declaration of D::f() should be compatible with that of C::f() in %s on line 5
+Strict Standards: Declaration of D::f() should be compatible with C::f(array $a) in %s on line 5
No hint, should be array.
-==DONE== \ No newline at end of file
+==DONE==
diff --git a/tests/classes/type_hinting_005c.phpt b/tests/classes/type_hinting_005c.phpt
index d3b72412cd..30a114e2a4 100644
--- a/tests/classes/type_hinting_005c.phpt
+++ b/tests/classes/type_hinting_005c.phpt
@@ -9,6 +9,6 @@ Class D extends C { function f(array $a) {} }
?>
==DONE==
--EXPECTF--
-Strict Standards: Declaration of D::f() should be compatible with that of C::f() in %s on line 5
+Strict Standards: Declaration of D::f() should be compatible with C::f(SomeClass $a) in %s on line 5
Array hint, should be class.
-==DONE== \ No newline at end of file
+==DONE==
diff --git a/tests/classes/type_hinting_005d.phpt b/tests/classes/type_hinting_005d.phpt
index 60dda0ff24..830054d03d 100644
--- a/tests/classes/type_hinting_005d.phpt
+++ b/tests/classes/type_hinting_005d.phpt
@@ -9,6 +9,6 @@ Class D extends C { function f(array $a) {} }
?>
==DONE==
--EXPECTF--
-Strict Standards: Declaration of D::f() should be compatible with that of C::f() in %s on line 5
+Strict Standards: Declaration of D::f() should be compatible with C::f($a) in %s on line 5
Array hint, should be nothing.
-==DONE== \ No newline at end of file
+==DONE==
diff --git a/tests/lang/019.phpt b/tests/lang/019.phpt
index 2db29ad22b..c9b5e5f3b5 100644
--- a/tests/lang/019.phpt
+++ b/tests/lang/019.phpt
@@ -35,4 +35,4 @@ hey, this is a function inside an eval()!
hey, this is a regular echo'd eval()
hey, this is a function inside an eval()!
-Parse error: syntax error, unexpected $end in %s019.php(12) : eval()'d code on line 1
+Parse error: syntax error, unexpected %s in %s019.php(12) : eval()'d code on line 1
diff --git a/tests/lang/array_shortcut_001.phpt b/tests/lang/array_shortcut_001.phpt
new file mode 100644
index 0000000000..18a10ea09b
--- /dev/null
+++ b/tests/lang/array_shortcut_001.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Square bracket array shortcut test
+--FILE--
+<?php
+print_r([1, 2, 3]);
+?>
+--EXPECT--
+Array
+(
+ [0] => 1
+ [1] => 2
+ [2] => 3
+)
diff --git a/tests/lang/array_shortcut_002.phpt b/tests/lang/array_shortcut_002.phpt
new file mode 100644
index 0000000000..25aee9ba39
--- /dev/null
+++ b/tests/lang/array_shortcut_002.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Square bracket associative array shortcut test
+--FILE--
+<?php
+print_r(["foo" => "orange", "bar" => "apple", "baz" => "lemon"]);
+?>
+--EXPECT--
+Array
+(
+ [foo] => orange
+ [bar] => apple
+ [baz] => lemon
+)
diff --git a/tests/lang/array_shortcut_003.phpt b/tests/lang/array_shortcut_003.phpt
new file mode 100644
index 0000000000..75e428b63e
--- /dev/null
+++ b/tests/lang/array_shortcut_003.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Testing array shortcut and bracket operator
+--FILE--
+<?php
+$a = [1, 2, 3, 4, 5];
+print_r([$a[1], $a[3]]);
+?>
+--EXPECT--
+Array
+(
+ [0] => 2
+ [1] => 4
+)
diff --git a/tests/lang/array_shortcut_005.phpt b/tests/lang/array_shortcut_005.phpt
new file mode 100644
index 0000000000..7cc7386f83
--- /dev/null
+++ b/tests/lang/array_shortcut_005.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Testing nested array shortcut
+--FILE--
+<?php
+print_r([1, 2, 3, ["foo" => "orange", "bar" => "apple", "baz" => "lemon"]]);
+?>
+--EXPECT--
+Array
+(
+ [0] => 1
+ [1] => 2
+ [2] => 3
+ [3] => Array
+ (
+ [foo] => orange
+ [bar] => apple
+ [baz] => lemon
+ )
+
+)
diff --git a/tests/lang/bug19943.phpt b/tests/lang/bug19943.phpt
index 294a320bf7..c951190511 100644
--- a/tests/lang/bug19943.phpt
+++ b/tests/lang/bug19943.phpt
@@ -5,11 +5,11 @@ Bug #19943 (memleaks)
$ar = array();
for ($count = 0; $count < 10; $count++) {
$ar[$count] = "$count";
- $ar[$count]['idx'] = "$count";
+ @$ar[$count]['idx'] = "$count";
}
for ($count = 0; $count < 10; $count++) {
- echo $ar[$count]." -- ".$ar[$count]['idx']."\n";
+ echo $ar[$count]." -- ".@$ar[$count]['idx']."\n";
}
$a = "0123456789";
$a[9] = $a[0];
diff --git a/tests/lang/bug21820.phpt b/tests/lang/bug21820.phpt
index 0ca233ea84..cbf466eea7 100644
--- a/tests/lang/bug21820.phpt
+++ b/tests/lang/bug21820.phpt
@@ -9,5 +9,5 @@ $arr = array('foo' => 'bar');
echo "$arr['foo']";
?>
---EXPECTREGEX--
-Parse error: (parse|syntax) error, .*expecting `?T_STRING'? or `?T_VARIABLE'? or `?T_NUM_STRING'? in .*bug21820.php on line .*
+--EXPECTF--
+Parse error: %s error, %s(T_STRING)%s(T_VARIABLE)%s(T_NUM_STRING)%sin %sbug21820.php on line %d
diff --git a/tests/lang/bug29566.phpt b/tests/lang/bug29566.phpt
index 5f292bd759..16aec8fc73 100644
--- a/tests/lang/bug29566.phpt
+++ b/tests/lang/bug29566.phpt
@@ -12,5 +12,7 @@ foreach($var['nosuchkey'] as $v) {
?>
===DONE===
--EXPECTF--
+Warning: Illegal string offset 'nosuchkey' in %sbug29566.php on line %d
+
Warning: Invalid argument supplied for foreach() in %sbug29566.php on line %d
===DONE===
diff --git a/tests/lang/bug35176.phpt b/tests/lang/bug35176.phpt
index dd56c76a68..2928f7ec45 100644
--- a/tests/lang/bug35176.phpt
+++ b/tests/lang/bug35176.phpt
@@ -2,6 +2,7 @@
Bug #35176 (include()/require()/*_once() produce wrong error messages about main())
--INI--
html_errors=1
+docref_root="/"
error_reporting=4095
--FILE--
<?php
@@ -9,6 +10,6 @@ require_once('nonexisiting.php');
?>
--EXPECTF--
<br />
-<b>Warning</b>: require_once(nonexisiting.php) [<a href='function.require-once.html'>function.require-once.html</a>]: failed to open stream: No such file or directory in <b>%sbug35176.php</b> on line <b>2</b><br />
+<b>Warning</b>: require_once(nonexisiting.php) [<a href='/function.require-once.html'>function.require-once.html</a>]: failed to open stream: No such file or directory in <b>%sbug35176.php</b> on line <b>2</b><br />
<br />
-<b>Fatal error</b>: require_once() [<a href='function.require.html'>function.require.html</a>]: Failed opening required 'nonexisiting.php' (%s) in <b>%sbug35176.php</b> on line <b>2</b><br />
+<b>Fatal error</b>: require_once() [<a href='/function.require.html'>function.require.html</a>]: Failed opening required 'nonexisiting.php' (%s) in <b>%sbug35176.php</b> on line <b>2</b><br />
diff --git a/tests/lang/bug55754.phpt b/tests/lang/bug55754.phpt
new file mode 100644
index 0000000000..c58ec9175a
--- /dev/null
+++ b/tests/lang/bug55754.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #55754 (Only variables should be passed by reference for ZEND_SEND_PREFER_REF params)
+--FILE--
+<?php
+
+current($arr = array(0 => "a"));
+current(array(0 => "a"));
+current($arr);
+
+echo "DONE";
+
+?>
+--EXPECT--
+DONE
diff --git a/tests/lang/bug7515.phpt b/tests/lang/bug7515.phpt
index b33ae24c89..ea58061db0 100644
--- a/tests/lang/bug7515.phpt
+++ b/tests/lang/bug7515.phpt
@@ -32,5 +32,6 @@ y=$y
";
}
?>
---EXPECT--
+--EXPECTF--
+Warning: Creating default object from empty value in %s on line %d
success
diff --git a/tests/lang/engine_assignExecutionOrder_008.phpt b/tests/lang/engine_assignExecutionOrder_008.phpt
index 0d699bc649..1333bcda8a 100644
--- a/tests/lang/engine_assignExecutionOrder_008.phpt
+++ b/tests/lang/engine_assignExecutionOrder_008.phpt
@@ -66,10 +66,16 @@ $$x=f(): good
${'i'}=f(): good
$i[0]=f(): good
$i[0][0]=f(): good
-$i->p=f(): good
-$i->p->q=f(): good
+$i->p=f():
+Warning: Creating default object from empty value in %s on line %d
+good
+$i->p->q=f():
+Warning: Creating default object from empty value in %s on line %d
+good
$i->p[0]=f(): good
-$i->p[0]->p=f(): good
+$i->p[0]->p=f():
+Warning: Creating default object from empty value in %s on line %d
+good
C::$p=f(): good
C::$p[0]=f(): good
-C::$p->q=f(): good \ No newline at end of file
+C::$p->q=f(): good
diff --git a/tests/lang/foreachLoop.016.phpt b/tests/lang/foreachLoop.016.phpt
index dc31a5072e..d570aba316 100644
--- a/tests/lang/foreachLoop.016.phpt
+++ b/tests/lang/foreachLoop.016.phpt
@@ -150,12 +150,16 @@ array(1) {
}
$a->b
+
+Warning: Creating default object from empty value in %s on line %d
array(1) {
[0]=>
string(8) "original"
}
$a->b->c
+
+Warning: Creating default object from empty value in %s on line %d
array(1) {
[0]=>
string(8) "original"
@@ -174,6 +178,8 @@ array(1) {
}
$a->b[0]->c
+
+Warning: Creating default object from empty value in %s on line %d
array(1) {
[0]=>
string(8) "original"
@@ -192,7 +198,9 @@ array(1) {
}
C::$a[0]->b
+
+Warning: Creating default object from empty value in %s on line %d
array(1) {
[0]=>
string(8) "original"
-} \ No newline at end of file
+}
diff --git a/tests/lang/short_tags.004.phpt b/tests/lang/short_tags.004.phpt
index d80e7481a1..ff3308733a 100644
--- a/tests/lang/short_tags.004.phpt
+++ b/tests/lang/short_tags.004.phpt
@@ -4,8 +4,6 @@ short_open_tag: Off, asp_tags: Off
short_open_tag=off
asp_tags=off
--FILE--
-<?='this should get echoed'?>
-
<%= 'so should this' %>
<?php
@@ -21,17 +19,17 @@ $a = 'This gets echoed twice';
<?php
echo "{$b}";
?>
+<?= "{$b}"?>
--EXPECTF--
-<?='this should get echoed'?>
-
<%= 'so should this' %>
-<?= $a?>
-
+This gets echoed twice
<%= $a%>
<? $b=3; ?>
Notice: Undefined variable: b in %s on line %d
+
+Notice: Undefined variable: b in %s on line %d
diff --git a/tests/output/bug46897.phpt b/tests/output/bug46897.phpt
index a77db91d34..8fe80bcb65 100644
--- a/tests/output/bug46897.phpt
+++ b/tests/output/bug46897.phpt
@@ -18,10 +18,10 @@ echo 'Done';
?>
--EXPECTF--
[callback:1]Attempt to flush unerasable buffer - should fail...
-Notice: ob_flush(): failed to flush buffer callback in %s on line %d
+Notice: ob_flush(): failed to flush buffer of callback (0) in %s on line %d
bool(false)
string(%d) "Attempt to flush unerasable buffer - should fail...
-Notice: ob_flush(): failed to flush buffer callback in %s on line %d
+Notice: ob_flush(): failed to flush buffer of callback (0) in %s on line %d
bool(false)
"
Done
diff --git a/tests/output/bug60282.phpt b/tests/output/bug60282.phpt
new file mode 100644
index 0000000000..08bcc0f201
--- /dev/null
+++ b/tests/output/bug60282.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #60282 (Segfault when using ob_gzhandler() with open buffers)
+--SKIPIF--
+<?php if (!extension_loaded("zlib")) print "skip Zlib extension required"; ?>
+--FILE--
+<?php
+ob_start();
+ob_start();
+ob_start('ob_gzhandler');
+echo "done";
+--EXPECT--
+done
diff --git a/tests/output/bug60321.phpt b/tests/output/bug60321.phpt
new file mode 100644
index 0000000000..9802a57ccd
--- /dev/null
+++ b/tests/output/bug60321.phpt
@@ -0,0 +1,9 @@
+--TEST--
+Bug #60321 (ob_get_status(true) no longer returns an array when buffer is empty)
+--FILE--
+<?php
+$return = ob_get_status(true);
+var_dump($return);
+--EXPECT--
+array(0) {
+}
diff --git a/tests/output/bug60322.phpt b/tests/output/bug60322.phpt
new file mode 100644
index 0000000000..c28ab4d617
--- /dev/null
+++ b/tests/output/bug60322.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #60322 (ob_get_clean() now raises an E_NOTICE if no buffers exist)
+--FILE--
+<?php
+while(ob_get_clean()) ;
+var_dump(ob_get_clean());
+--EXPECT--
+bool(false)
diff --git a/tests/output/bug60768.phpt b/tests/output/bug60768.phpt
new file mode 100644
index 0000000000..2527e8e84a
--- /dev/null
+++ b/tests/output/bug60768.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #60768 Output buffer not discarded
+--FILE--
+<?php
+
+global $storage;
+
+ob_start(function($buffer) use (&$storage) { $storage .= $buffer; }, 20);
+
+echo str_repeat("0", 20); // fill in the buffer
+
+for($i = 0; $i < 10; $i++) {
+ echo str_pad($i, 9, ' ', STR_PAD_LEFT) . "\n"; // full buffer dumped every time
+}
+
+ob_end_flush();
+
+printf("Output size: %d, expected %d\n", strlen($storage), 20 + 10 * 10);
+
+?>
+DONE
+--EXPECT--
+Output size: 120, expected 120
+DONE
+
diff --git a/tests/output/ob_013.phpt b/tests/output/ob_013.phpt
index ce5b5e5455..ad2e36d47f 100644
--- a/tests/output/ob_013.phpt
+++ b/tests/output/ob_013.phpt
@@ -37,67 +37,69 @@ Array
)
Array
(
- [level] => 5
- [type] => 1
- [status] => 1
[name] => d
- [del] => 1
+ [type] => 1
+ [flags] => 20593
+ [level] => 4
+ [chunk_size] => %d
+ [buffer_size] => 16384
+ [buffer_used] => 96
)
Array
(
[0] => Array
(
- [chunk_size] => 0
- [size] => 40960
- [block_size] => 10240
- [type] => 1
- [status] => 0
[name] => default output handler
- [del] => 1
+ [type] => 0
+ [flags] => 112
+ [level] => 0
+ [chunk_size] => %d
+ [buffer_size] => 16384
+ [buffer_used] => 0
)
[1] => Array
(
- [chunk_size] => 0
- [size] => 40960
- [block_size] => 10240
- [type] => 1
- [status] => 0
[name] => a
- [del] => 1
+ [type] => 1
+ [flags] => 113
+ [level] => 1
+ [chunk_size] => %d
+ [buffer_size] => 16384
+ [buffer_used] => 0
)
[2] => Array
(
- [chunk_size] => 0
- [size] => 40960
- [block_size] => 10240
- [type] => 1
- [status] => 0
[name] => b
- [del] => 1
+ [type] => 1
+ [flags] => 113
+ [level] => 2
+ [chunk_size] => %d
+ [buffer_size] => 16384
+ [buffer_used] => 0
)
[3] => Array
(
- [chunk_size] => 0
- [size] => 40960
- [block_size] => 10240
- [type] => 1
- [status] => 0
[name] => c
- [del] => 1
+ [type] => 1
+ [flags] => 113
+ [level] => 3
+ [chunk_size] => %d
+ [buffer_size] => 16384
+ [buffer_used] => 4
)
[4] => Array
(
- [chunk_size] => 0
- [size] => 40960
- [block_size] => 10240
- [type] => 1
- [status] => 1
[name] => d
- [del] => 1
+ [type] => 1
+ [flags] => 20593
+ [level] => 4
+ [chunk_size] => %d
+ [buffer_size] => 16384
+ [buffer_used] => %d
)
-) \ No newline at end of file
+)
diff --git a/tests/output/ob_017.phpt b/tests/output/ob_017.phpt
index fc50e2f4ad..070df603fc 100644
--- a/tests/output/ob_017.phpt
+++ b/tests/output/ob_017.phpt
@@ -24,11 +24,11 @@ yes!
yes!
Array
(
- [0] => 3: yes
- [1] => 2: !
+ [0] => 1: yes
+ [1] => 4: !
- [2] => 2: no
- [3] => 2: yes!
+ [2] => 2:
+ [3] => 0: yes!
- [4] => 4: no
-) \ No newline at end of file
+ [4] => 10:
+)
diff --git a/tests/output/ob_get_clean_basic_001.phpt b/tests/output/ob_get_clean_basic_001.phpt
index 07673dfac4..635b58abf9 100644
--- a/tests/output/ob_get_clean_basic_001.phpt
+++ b/tests/output/ob_get_clean_basic_001.phpt
@@ -15,4 +15,4 @@ var_dump(ob_get_clean());
?>
--EXPECTF--
bool(false)
-string(11) "Hello World" \ No newline at end of file
+string(11) "Hello World"
diff --git a/tests/output/ob_get_status.phpt b/tests/output/ob_get_status.phpt
index a6a3498ca3..95807293b5 100644
--- a/tests/output/ob_get_status.phpt
+++ b/tests/output/ob_get_status.phpt
@@ -15,20 +15,19 @@ var_dump($status);
array(1) {
[0]=>
array(7) {
+ ["name"]=>
+ string(22) "default output handler"
+ ["type"]=>
+ int(0)
+ ["flags"]=>
+ int(112)
+ ["level"]=>
+ int(0)
["chunk_size"]=>
int(0)
- ["size"]=>
- int(40960)
- ["block_size"]=>
- int(10240)
- ["type"]=>
- int(1)
- ["status"]=>
+ ["buffer_size"]=>
+ int(16384)
+ ["buffer_used"]=>
int(0)
- ["name"]=>
- string(22) "default output handler"
- ["del"]=>
- bool(true)
}
}
-
diff --git a/tests/output/ob_start_basic_004.phpt b/tests/output/ob_start_basic_004.phpt
index 39d3aadc49..16f09e8a9a 100644
--- a/tests/output/ob_start_basic_004.phpt
+++ b/tests/output/ob_start_basic_004.phpt
@@ -1,12 +1,12 @@
--TEST--
-ob_start() chunk_size: confirm buffer is flushed after any output call that causes its length to equal or exceed chunk_size.
+ob_start() chunk_size: confirm buffer is flushed after any output call that causes its length to equal or exceed chunk_size.
--FILE--
<?php
/*
* proto bool ob_start([ string|array user_function [, int chunk_size [, bool erase]]])
* Function is implemented in main/output.c
*/
-
+// In HEAD, $chunk_size value of 1 should not have any special behaviour (http://marc.info/?l=php-internals&m=123476465621346&w=2).
function callback($string) {
global $callback_invocations;
$callback_invocations++;
@@ -40,7 +40,15 @@ f[call:1; len:8]12345678
f[call:1; len:8]12345678
----( chunk_size: 1, output append size: 1 )----
-f[call:1; len:8]12345678
+f[call:1; len:1]1
+f[call:2; len:1]2
+f[call:3; len:1]3
+f[call:4; len:1]4
+f[call:5; len:1]5
+f[call:6; len:1]6
+f[call:7; len:1]7
+f[call:8; len:1]8
+f[call:9; len:0]
----( chunk_size: 2, output append size: 1 )----
f[call:1; len:2]12
@@ -85,7 +93,9 @@ f[call:1; len:8]12345678
f[call:1; len:8]12345678
----( chunk_size: 1, output append size: 4 )----
-f[call:1; len:8]12345678
+f[call:1; len:4]1234
+f[call:2; len:4]5678
+f[call:3; len:0]
----( chunk_size: 2, output append size: 4 )----
f[call:1; len:4]1234
diff --git a/tests/output/ob_start_basic_005.phpt b/tests/output/ob_start_basic_005.phpt
index cd2b2e07e5..4048ad25a2 100644
--- a/tests/output/ob_start_basic_005.phpt
+++ b/tests/output/ob_start_basic_005.phpt
@@ -25,9 +25,9 @@ checkAndClean();
?>
--EXPECTF--
-Strict Standards: Non-static method C::h() should not be called statically in %s on line 20
+Warning: ob_start(): non-static method C::h() should not be called statically in %s on line 20
bool(true)
Array
(
[0] => C::h
-) \ No newline at end of file
+)
diff --git a/tests/output/ob_start_basic_006.phpt b/tests/output/ob_start_basic_006.phpt
index e24ebd61c3..464e71be33 100644
--- a/tests/output/ob_start_basic_006.phpt
+++ b/tests/output/ob_start_basic_006.phpt
@@ -1,5 +1,5 @@
--TEST--
-ob_start(): multiple buffer initialization with a single call, using arrays.
+ob_start(): ensure multiple buffer initialization with a single call using arrays is not supported on PHP6 (http://bugs.php.net/42641)
--FILE--
<?php
/*
@@ -72,46 +72,47 @@ var_dump(ob_start(array('f', 'C::g', array(array($c, "g"), array($c, "h")))));
checkAndClean();
?>
--EXPECTF--
-
---> Test arrays:
-f[call:1; len:34] - bool(true)
+
+Warning: ob_start(): array must have exactly two members in %s on line 44
+
+Notice: ob_start(): failed to create buffer in %s on line 44
+bool(false)
Array
(
- [0] => f
)
-f[call:3; len:68] - f[call:2; len:47] - bool(true)
+Warning: ob_start(): class 'f' not found in %s on line 47
+
+Notice: ob_start(): failed to create buffer in %s on line 47
+bool(false)
Array
(
- [0] => f
- [1] => f
)
+Warning: ob_start(): array must have exactly two members in %s on line 50
-f[call:5; len:150] - C::g[call:2; len:125] - f[call:4; len:103] - C::g[call:1; len:79] - bool(true)
+Notice: ob_start(): failed to create buffer in %s on line 50
+bool(false)
Array
(
- [0] => f
- [1] => C::g
- [2] => f
- [3] => C::g
)
+Warning: ob_start(): array must have exactly two members in %s on line 53
-
-
-f[call:6; len:35] - bool(false)
+Notice: ob_start(): failed to create buffer in %s on line 53
+bool(false)
Array
(
- [0] => f
)
-f[call:7; len:35] - bool(false)
+Warning: ob_start(): array must have exactly two members in %s on line 56
+
+Notice: ob_start(): failed to create buffer in %s on line 56
+bool(false)
Array
(
- [0] => f
)
-
C::h[call:1; len:37; id:originalID] - bool(true)
Array
(
@@ -124,11 +125,11 @@ Array
[0] => C::h
)
-f[call:8; len:175] - C::g[call:4; len:150] - C::g[call:3; len:125] - C::h[call:3; len:82; id:changedIDagain] - bool(true)
+
+Warning: ob_start(): array must have exactly two members in %s on line 68
+
+Notice: ob_start(): failed to create buffer in %s on line 68
+bool(false)
Array
(
- [0] => f
- [1] => C::g
- [2] => C::g
- [3] => C::h
-) \ No newline at end of file
+)
diff --git a/tests/output/ob_start_basic_unerasable_002.phpt b/tests/output/ob_start_basic_unerasable_002.phpt
index 3b8bd637ee..21db1f326c 100644
--- a/tests/output/ob_start_basic_unerasable_002.phpt
+++ b/tests/output/ob_start_basic_unerasable_002.phpt
@@ -21,13 +21,13 @@ var_dump(ob_get_level());
--EXPECTF--
[callback:1]All of the following calls will fail to clean/remove the topmost buffer:
-Notice: ob_clean(): failed to delete buffer callback in %s on line 11
+Notice: ob_clean(): failed to delete buffer of callback (0) in %s on line 11
bool(false)
-Notice: ob_end_clean(): failed to delete buffer callback in %s on line 12
+Notice: ob_end_clean(): failed to discard buffer of callback (0) in %s on line 12
bool(false)
-Notice: ob_end_flush(): failed to delete buffer callback in %s on line 13
+Notice: ob_end_flush(): failed to send buffer of callback (0) in %s on line 13
bool(false)
The OB nesting will still be 1 level deep:
-int(1)
+int(1) \ No newline at end of file
diff --git a/tests/output/ob_start_basic_unerasable_003.phpt b/tests/output/ob_start_basic_unerasable_003.phpt
index e35902c89b..6eb6418388 100644
--- a/tests/output/ob_start_basic_unerasable_003.phpt
+++ b/tests/output/ob_start_basic_unerasable_003.phpt
@@ -10,12 +10,13 @@ function callback($string) {
ob_start('callback', 0, false);
-echo "This call will fail to obtain the content, since it is also requesting a clean:\n";
+echo "This call will obtain the content, but will not clean the buffer.";
$str = ob_get_clean();
var_dump($str);
?>
--EXPECTF--
-[callback:1]This call will fail to obtain the content, since it is also requesting a clean:
+[callback:1]This call will obtain the content, but will not clean the buffer.
+Notice: ob_get_clean(): failed to discard buffer of callback (0) in %s on line 11
-Notice: ob_get_clean(): failed to delete buffer callback in %s on line 11
-bool(false)
+Notice: ob_get_clean(): failed to delete buffer of callback (0) in %s on line 11
+string(65) "This call will obtain the content, but will not clean the buffer." \ No newline at end of file
diff --git a/tests/output/ob_start_basic_unerasable_004.phpt b/tests/output/ob_start_basic_unerasable_004.phpt
index 081875a788..62d9756e3f 100644
--- a/tests/output/ob_start_basic_unerasable_004.phpt
+++ b/tests/output/ob_start_basic_unerasable_004.phpt
@@ -10,12 +10,13 @@ function callback($string) {
ob_start('callback', 0, false);
-echo "This call will fail to flush and fail to obtain the content:\n";
+echo "This call will obtain the content, but will not flush the buffer.";
$str = ob_get_flush();
var_dump($str);
?>
--EXPECTF--
-[callback:1]This call will fail to flush and fail to obtain the content:
+[callback:1]This call will obtain the content, but will not flush the buffer.
+Notice: ob_get_flush(): failed to send buffer of callback (0) in %s on line 11
-Notice: ob_get_flush(): failed to delete buffer callback in %s on line 11
-bool(false)
+Notice: ob_get_flush(): failed to delete buffer of callback (0) in %s on line 11
+string(65) "This call will obtain the content, but will not flush the buffer." \ No newline at end of file
diff --git a/tests/output/ob_start_basic_unerasable_005.phpt b/tests/output/ob_start_basic_unerasable_005.phpt
index f1af201e67..2c52f00c24 100644
--- a/tests/output/ob_start_basic_unerasable_005.phpt
+++ b/tests/output/ob_start_basic_unerasable_005.phpt
@@ -17,9 +17,9 @@ var_dump(ob_get_contents());
?>
--EXPECTF--
[callback:1]Attempt to flush unerasable buffer - should fail...
-Notice: ob_flush(): failed to flush buffer callback in %s on line 11
+Notice: ob_flush(): failed to flush buffer of callback (0) in %s on line 11
bool(false)
string(%d) "Attempt to flush unerasable buffer - should fail...
-Notice: ob_flush(): failed to flush buffer callback in %s on line 11
+Notice: ob_flush(): failed to flush buffer of callback (0) in %s on line 11
bool(false)
"
diff --git a/tests/output/ob_start_error_001.phpt b/tests/output/ob_start_error_001.phpt
index ca028018bd..b45de831df 100644
--- a/tests/output/ob_start_error_001.phpt
+++ b/tests/output/ob_start_error_001.phpt
@@ -30,14 +30,17 @@ var_dump(ob_start("justPrint", 0, "this should be a bool"));
?>
--EXPECTF--
-
- Too many arguments
Warning: ob_start() expects at most 3 parameters, 4 given in %s on line 17
NULL
- Arg 1 wrong type
-bool(true)
+
+Warning: ob_start(): no array or string given in %s on line 20
+
+Notice: ob_start(): failed to create buffer in %s on line 20
+bool(false)
- Arg 2 wrong type
@@ -45,4 +48,6 @@ Warning: ob_start() expects parameter 2 to be long, string given in %s on line 2
NULL
- Arg 3 wrong type
-bool(true) \ No newline at end of file
+
+Warning: ob_start() expects parameter 3 to be long, string given in %s on line 26
+NULL
diff --git a/tests/output/ob_start_error_002.phpt b/tests/output/ob_start_error_002.phpt
index aca2ad9d2c..38c789908d 100644
--- a/tests/output/ob_start_error_002.phpt
+++ b/tests/output/ob_start_error_002.phpt
@@ -20,8 +20,23 @@ var_dump(ob_start("no"));
echo "done"
?>
--EXPECTF--
+Warning: ob_start(): class 'nonExistent' not found in %s on line 13
+
+Notice: ob_start(): failed to create buffer in %s on line 13
bool(false)
+
+Warning: ob_start(): class 'C' does not have a method 'nonExistent' in %s on line 14
+
+Notice: ob_start(): failed to create buffer in %s on line 14
bool(false)
+
+Warning: ob_start(): class 'C' does not have a method 'no' in %s on line 15
+
+Notice: ob_start(): failed to create buffer in %s on line 15
bool(false)
+
+Warning: ob_start(): function 'no' not found or invalid function name in %s on line 16
+
+Notice: ob_start(): failed to create buffer in %s on line 16
bool(false)
-done \ No newline at end of file
+done
diff --git a/tests/output/ob_start_error_003.phpt b/tests/output/ob_start_error_003.phpt
index ce2a2495d9..7fa292a739 100644
--- a/tests/output/ob_start_error_003.phpt
+++ b/tests/output/ob_start_error_003.phpt
@@ -15,4 +15,8 @@ var_dump(ob_start(array($c)));
echo "done"
?>
--EXPECTF--
-Catchable fatal error: Object of class C could not be converted to string in %s on line 11 \ No newline at end of file
+Warning: ob_start(): array must have exactly two members in %s on line %d
+
+Notice: ob_start(): failed to create buffer in %s on line 11
+bool(false)
+done
diff --git a/tests/output/ob_start_error_004.phpt b/tests/output/ob_start_error_004.phpt
index ec6d44d091..7ddf998557 100644
--- a/tests/output/ob_start_error_004.phpt
+++ b/tests/output/ob_start_error_004.phpt
@@ -15,4 +15,8 @@ var_dump(ob_start(array($c, 'f')));
echo "done"
?>
--EXPECTF--
-Catchable fatal error: Object of class C could not be converted to string in %s on line 11 \ No newline at end of file
+Warning: ob_start(): class 'C' does not have a method 'f' in %s on line %d
+
+Notice: ob_start(): failed to create buffer in %s on line 11
+bool(false)
+done
diff --git a/tests/security/magic_quotes_gpc.phpt b/tests/security/magic_quotes_gpc.phpt
deleted file mode 100644
index 382ab94d2d..0000000000
--- a/tests/security/magic_quotes_gpc.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Test if magic_quotes_gpc works as expected
---INI--
-display_errors=0
-magic_quotes_gpc=1
---GET--
-a=abc'"%00123
---FILE--
-<?php
-echo $_GET['a'],"\n";
-?>
---EXPECT--
-abc\'\"\0123
diff --git a/tests/security/open_basedir_linkinfo.phpt b/tests/security/open_basedir_linkinfo.phpt
index 5c930dddce..f8be45305e 100644
--- a/tests/security/open_basedir_linkinfo.phpt
+++ b/tests/security/open_basedir_linkinfo.phpt
@@ -6,10 +6,13 @@ if (substr(PHP_OS, 0, 3) == 'WIN') {
die('skip no symlinks on Windows');
}
?>
---INI--
-open_basedir=.
+--XFAIL--
+BUG: open_basedir cannot delete symlink to prohibited file. See also
+bugs 48111 and 52176.
--FILE--
<?php
+chdir(__DIR__);
+ini_set("open_basedir", ".");
require_once "open_basedir.inc";
$initdir = getcwd();
test_open_basedir_before("linkinfo", FALSE);
@@ -57,8 +60,6 @@ int(%d)
Warning: symlink(): open_basedir restriction in effect. File(%s/test/bad/bad.txt) is not within the allowed path(s): (.) in %s on line %d
bool(false)
int(%d)
-
-Warning: unlink(): open_basedir restriction in effect. File(%s/test/ok/symlink.txt) is not within the allowed path(s): (.) in %s on line %d
-bool(false)
+bool(true)
*** Finished testing open_basedir configuration [linkinfo] ***
diff --git a/tests/security/open_basedir_readlink.phpt b/tests/security/open_basedir_readlink.phpt
index a632dce243..b102ee9d9c 100644
--- a/tests/security/open_basedir_readlink.phpt
+++ b/tests/security/open_basedir_readlink.phpt
@@ -6,10 +6,10 @@ if (substr(PHP_OS, 0, 3) == 'WIN') {
die('skip no symlinks on Windows');
}
?>
---INI--
-open_basedir=.
--FILE--
<?php
+chdir(__DIR__);
+ini_set("open_basedir", ".");
require_once "open_basedir.inc";
$initdir = getcwd();
test_open_basedir_before("readlink", FALSE);
@@ -32,7 +32,6 @@ $target = ($initdir."/test/ok/ok.txt");
$symlink = ($initdir."/test/ok/symlink.txt");
var_dump(symlink($target, $symlink));
var_dump(readlink($symlink));
-var_dump(unlink($symlink));
test_open_basedir_after("readlink");
?>
@@ -69,8 +68,5 @@ bool(false)
Warning: readlink(): open_basedir restriction in effect. File(%s/test/ok/symlink.txt) is not within the allowed path(s): (.) in %s on line %d
bool(false)
-
-Warning: unlink(): open_basedir restriction in effect. File(%s/test/ok/symlink.txt) is not within the allowed path(s): (.) in %s on line %d
-bool(false)
*** Finished testing open_basedir configuration [readlink] ***
diff --git a/tests/strings/004.phpt b/tests/strings/004.phpt
index a283fda699..7bcb452937 100644
--- a/tests/strings/004.phpt
+++ b/tests/strings/004.phpt
@@ -4,7 +4,6 @@ highlight_string() buffering
highlight.string=#DD0000
highlight.comment=#FF9900
highlight.keyword=#007700
-highlight.bg=#FFFFFF
highlight.default=#0000BB
highlight.html=#000000
--FILE--
diff --git a/tests/strings/bug26703.phpt b/tests/strings/bug26703.phpt
index ef2d81de4a..bea8fb1214 100644
--- a/tests/strings/bug26703.phpt
+++ b/tests/strings/bug26703.phpt
@@ -4,7 +4,6 @@ Bug #26703 (Certain characters inside strings incorrectly treated as keywords)
highlight.string=#DD0000
highlight.comment=#FF9900
highlight.keyword=#007700
-highlight.bg=#FFFFFF
highlight.default=#0000BB
highlight.html=#000000
--FILE--
diff --git a/tests/strings/offsets_chaining_1.phpt b/tests/strings/offsets_chaining_1.phpt
index 3aae90747c..eecdfb9637 100644
--- a/tests/strings/offsets_chaining_1.phpt
+++ b/tests/strings/offsets_chaining_1.phpt
@@ -8,4 +8,5 @@ $string = "foobar";
var_dump($string[0][0][0][0]);
?>
--EXPECTF--
-Fatal error: Cannot use string offset as an array in %s on line %d
+string(1) "f"
+
diff --git a/tests/strings/offsets_chaining_2.phpt b/tests/strings/offsets_chaining_2.phpt
index 7a567cd125..07f67f0fd0 100644
--- a/tests/strings/offsets_chaining_2.phpt
+++ b/tests/strings/offsets_chaining_2.phpt
@@ -8,4 +8,5 @@ $string = "foobar";
var_dump($string{0}{0}[0][0]);
?>
--EXPECTF--
-Fatal error: Cannot use string offset as an array in %s on line %d
+string(1) "f"
+
diff --git a/tests/strings/offsets_chaining_3.phpt b/tests/strings/offsets_chaining_3.phpt
index a5d1233a4c..23b8e70179 100644
--- a/tests/strings/offsets_chaining_3.phpt
+++ b/tests/strings/offsets_chaining_3.phpt
@@ -8,4 +8,5 @@ $string = "foobar";
var_dump(isset($string[0][0][0][0]));
?>
--EXPECTF--
-Fatal error: Cannot use string offset as an array in %s on line %d
+bool(true)
+
diff --git a/tests/strings/offsets_chaining_4.phpt b/tests/strings/offsets_chaining_4.phpt
index 8049f66a09..79b95c135b 100644
--- a/tests/strings/offsets_chaining_4.phpt
+++ b/tests/strings/offsets_chaining_4.phpt
@@ -8,4 +8,5 @@ $string = "foobar";
var_dump(isset($string{0}{0}[0][0]));
?>
--EXPECTF--
-Fatal error: Cannot use string offset as an array in %s on line %d
+bool(true)
+
diff --git a/tests/strings/offsets_chaining_5.phpt b/tests/strings/offsets_chaining_5.phpt
index bb811326f8..efcf2f3074 100644
--- a/tests/strings/offsets_chaining_5.phpt
+++ b/tests/strings/offsets_chaining_5.phpt
@@ -15,9 +15,13 @@ var_dump($array['expected_array']['foo']['bar']);
--EXPECTF--
bool(true)
string(6) "foobar"
-bool(true)
+bool(false)
+
+Warning: Illegal string offset 'foo' in %soffsets_chaining_5.php on line %d
string(1) "f"
bool(false)
-Fatal error: Cannot use string offset as an array in %s on line %d
+Warning: Illegal string offset 'foo' in %soffsets_chaining_5.php on line %d
+Warning: Illegal string offset 'bar' in %soffsets_chaining_5.php on line %d
+string(1) "f"
diff --git a/tests/strings/offsets_general.phpt b/tests/strings/offsets_general.phpt
index effe9dd1d2..9d69ea2bf5 100644
--- a/tests/strings/offsets_general.phpt
+++ b/tests/strings/offsets_general.phpt
@@ -18,16 +18,21 @@ var_dump(isset($string{0}{0}));
var_dump($string{"foo"});
var_dump(isset($string{"foo"}{"bar"}));
?>
---EXPECT--
+--EXPECTF--
string(1) "f"
string(1) "o"
bool(true)
-bool(false)
+bool(true)
+
+Warning: Illegal string offset 'foo' in %s line %d
string(1) "f"
bool(false)
string(1) "f"
string(1) "o"
bool(true)
-bool(false)
+bool(true)
+
+Warning: Illegal string offset 'foo' in %s line %d
string(1) "f"
bool(false)
+
diff --git a/win32/build/Makefile b/win32/build/Makefile
index 5770e89cc1..e2d62545b8 100644
--- a/win32/build/Makefile
+++ b/win32/build/Makefile
@@ -22,6 +22,7 @@ LD="$(LINK)"
MC="$(MC)"
MT="$(MT)"
RE2C="$(RE2C)"
+PGOMGR="$(PGOMGR)"
PHP_BUILD=$(PHP_BUILD)
MCFILE=$(BUILD_DIR)\wsyslog.rc
@@ -60,6 +61,12 @@ Zend\zend_language_scanner.c: Zend\zend_language_scanner.l
$(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l
!endif
+!if $(PGOMGR) != ""
+PHP5_PGD_OPTION=/PGD:$(PGOPGD_DIR)\php5.pgd
+!else
+PHP5_PGD_OPTION=
+!endif
+
PHPDLL_RES=$(BUILD_DIR)\$(PHPDLL).res
$(MCFILE): win32\build\wsyslog.mc
@@ -82,7 +89,7 @@ $(PHPDLL_RES): win32\build\template.rc
win32\build\template.rc
$(BUILD_DIR)\$(PHPDLL): generated_files $(PHPDEF) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(PHPDLL_RES) $(MCFILE)
- @$(CC) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) /link /out:$(BUILD_DIR)\$(PHPDLL) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS)
+ @$(CC) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) /link /out:$(BUILD_DIR)\$(PHPDLL) $(PHP5_PGD_OPTION) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS)
-@$(_VC_MANIFEST_EMBED_DLL)
$(BUILD_DIR)\$(PHPLIB): $(BUILD_DIR)\$(PHPDLL)
@@ -120,7 +127,16 @@ clean-all:
@cd $(BUILD_DIR)
@for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @rd /s /q %D
@cd "$(PHP_SRC_DIR)"
- -@del /f /q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\*.rc $(BUILD_DIR)\*.dbg $(BUILD_DIR)\*.bin $(BUILD_DIR)\php*.dll $(BUILD_DIR)\php*.exe > NUL
+ -@del /f /q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\*.rc $(BUILD_DIR)\*.manifest $(BUILD_DIR)\*.dbg $(BUILD_DIR)\*.bin $(BUILD_DIR)\php*.dll $(BUILD_DIR)\php*.exe > NUL
+
+clean-pgo: clean-all
+ -rd /s /q $(BUILD_DIR)\php-$(PHP_VERSION_STRING)
+ -rd /s /q $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)
+ -rd /s /q $(BUILD_DIR)\php-test-pack-$(PHP_VERSION_STRING)
+ -del /f /q $(BUILD_DIR)\php-$(PHP_VERSION_STRING)$(PHP_ZTS_ARCHIVE_POSTFIX)-Win32-$(PHP_COMPILER_SHORT)-$(PHP_ARCHITECTURE).zip
+ -del /f /q $(BUILD_DIR)\php-debug-pack-$(PHP_VERSION_STRING)$(PHP_ZTS_ARCHIVE_POSTFIX)-Win32-$(PHP_COMPILER_SHORT)-$(PHP_ARCHITECTURE).zip
+ -del /f /q $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)$(PHP_ZTS_ARCHIVE_POSTFIX)-Win32-$(PHP_COMPILER_SHORT)-$(PHP_ARCHITECTURE).zip
+ -del /f /q $(BUILD_DIR)\php-test-pack-$(PHP_VERSION_STRING).zip
test:
"$(BUILD_DIR)\php.exe" -d open_basedir= -d output_buffering=0 run-tests.php $(TESTS) -p "$(BUILD_DIR)\php.exe"
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index 92347e76b5..1a4b834be4 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -19,6 +19,11 @@ if (!PHP_CL) {
// Which version of the compiler do we have?
VCVERS = probe_binary(PHP_CL).substr(0, 5).replace('.', '');
STDOUT.WriteLine(" Detected compiler " + VC_VERSIONS[VCVERS]);
+
+if (VCVERS < 1500) {
+ ERROR("Unsupported MS C++ Compiler, VC9 (2008) minimum is required");
+}
+
AC_DEFINE('COMPILER', VC_VERSIONS[VCVERS], "Detected compiler version");
DEFINE("PHP_COMPILER_SHORT", VC_VERSIONS_SHORT[VCVERS]);
AC_DEFINE('PHP_COMPILER_ID', VC_VERSIONS_SHORT[VCVERS], "Compiler compatibility ID");
@@ -100,6 +105,19 @@ ARG_ENABLE('debug-pack', 'Release binaries with external debug symbols (--enable
if (PHP_DEBUG == "yes" && PHP_DEBUG_PACK == "yes") {
ERROR("Use of both --enable-debug and --enable-debug-pack not allowed.");
}
+
+ARG_ENABLE('pgi', 'Generate PGO instrumented binaries', 'no');
+ARG_WITH('pgo', 'Compile optimized binaries using training data from folder', 'no');
+if (PHP_PGI == "yes" || PHP_PGO != "no") {
+ PGOMGR = PATH_PROG('pgomgr', WshShell.Environment("Process").Item("PATH"));
+ if (!PGOMGR) {
+ ERROR("--enable-pgi and --with-pgo options can only be used if PGO capable compiler is present.");
+ }
+ if (PHP_PGI == "yes" && PHP_PGO != "no") {
+ ERROR("Use of both --enable-pgi and --with-pgo not allowed.");
+ }
+}
+
ARG_ENABLE('zts', 'Thread safety', 'yes');
// Configures the hard-coded installation dir
ARG_WITH('prefix', 'where PHP will be installed', '');
@@ -229,6 +247,19 @@ if (PHP_DEBUG == "yes" && PHP_ZTS == "yes") {
DEFINE("PHPLIB", "php" + PHP_VERSION + ".lib");
}
+// CFLAGS, LDFLAGS and BUILD_DIR are defined
+// Add compiler and link flags if PGO options are selected
+if (PHP_DEBUG != "yes" && PHP_PGI == "yes") {
+ ADD_FLAG('CFLAGS', "/GL /O2");
+ ADD_FLAG('LDFLAGS', "/LTCG:PGINSTRUMENT");
+ DEFINE("PGOPGD_DIR", "$(BUILD_DIR)");
+}
+else if (PHP_DEBUG != "yes" && PHP_PGO != "no") {
+ ADD_FLAG('CFLAGS', "/GL /O2");
+ ADD_FLAG('LDFLAGS', "/LTCG:PGUPDATE");
+ DEFINE("PGOPGD_DIR", ((PHP_PGO.length == 0 || PHP_PGO == "yes") ? "$(BUILD_DIR)" : PHP_PGO));
+}
+
// Find the php_build dir - it contains headers and libraries
// that we need
ARG_WITH('php-build', 'Path to where you extracted the development libraries (http://wiki.php.net/internals/windows/libs). Assumes that it is a sibling of this source dir (..\\deps) if not specified', 'no');
@@ -328,13 +359,13 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \
zend_object_handlers.c zend_objects_API.c \
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \
- zend_float.c");
+ zend_float.c zend_string.c");
if (VCVERS == 1200) {
AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1);
}
-ADD_SOURCES("main", "main.c snprintf.c spprintf.c safe_mode.c getopt.c fopen_wrappers.c \
+ADD_SOURCES("main", "main.c snprintf.c spprintf.c getopt.c fopen_wrappers.c \
php_scandir.c php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c network.c \
php_open_temporary_file.c php_logos.c output.c internal_functions.c php_sprintf.c");
@@ -358,6 +389,7 @@ PHP_INSTALL_HEADERS("", "Zend/ TSRM/ main/ main/streams/ win32/");
STDOUT.WriteBlankLines(1);
+
/* Can we build with IPv6 support? */
ARG_ENABLE("ipv6", "Disable IPv6 support (default is turn it on if available)", "yes");
@@ -377,12 +409,6 @@ AC_DEFINE('HAVE_IPV6', main_network_has_ipv6);
ARG_ENABLE('fd-setsize', "Set maximum number of sockets for select(2)", "256");
ADD_FLAG("CFLAGS", "/D FD_SETSIZE=" + parseInt(PHP_FD_SETSIZE));
-ARG_ENABLE("zend-multibyte", "Enable Zend multibyte encoding support", "no");
-if (PHP_ZEND_MULTIBYTE == "yes") {
- STDOUT.WriteLine("Enabling Zend multibyte encoding support");
- AC_DEFINE('ZEND_MULTIBYTE', 1);
-}
-
AC_DEFINE('HAVE_USLEEP', 1);
AC_DEFINE('HAVE_STRCOLL', 1);
@@ -408,7 +434,7 @@ if (PHP_DSP != "no") {
FSO.CreateFolder("tmp");
}
-ARG_ENABLE("security-flags", "Enable the compiler security flags", "no");
+ARG_ENABLE("security-flags", "Disable the compiler security flags", "yes");
if (PHP_SECURITY_FLAGS == "yes") {
ADD_FLAG("LDFLAGS", "/NXCOMPAT /DYNAMICBASE ");
}
diff --git a/win32/build/config.w32.h.in b/win32/build/config.w32.h.in
index 3b636e195b..c6cf076bab 100644
--- a/win32/build/config.w32.h.in
+++ b/win32/build/config.w32.h.in
@@ -33,8 +33,6 @@
/* PHP Runtime Configuration */
#define PHP_URL_FOPEN 1
-#define PHP_SAFE_MODE 0
-#define MAGIC_QUOTES 0
#define USE_CONFIG_FILE 1
#define DEFAULT_SHORT_OPEN_TAG "1"
diff --git a/win32/build/config.w32.phpize.in b/win32/build/config.w32.phpize.in
index 0f88620a71..b8bf45ea57 100644
--- a/win32/build/config.w32.phpize.in
+++ b/win32/build/config.w32.phpize.in
@@ -1,5 +1,5 @@
// vim:ft=javascript
-// $Id: config.w32 305923 2010-12-02 23:23:14Z pajoye $
+// $Id: config.w32 306241 2010-12-11 22:18:10Z pajoye $
// "Master" config file; think of it as a configure.in
// equivalent.
@@ -18,6 +18,11 @@ if (!PHP_CL) {
// Which version of the compiler do we have?
VCVERS = probe_binary(PHP_CL).substr(0, 5).replace('.', '');
STDOUT.WriteLine(" Detected compiler " + VC_VERSIONS[VCVERS]);
+
+if (VCVERS < 1500) {
+ ERROR("Unsupported MS C++ Compiler, VC9 (2008) minimum is required");
+}
+
AC_DEFINE('COMPILER', VC_VERSIONS[VCVERS], "Detected compiler version");
DEFINE("PHP_COMPILER_SHORT", VC_VERSIONS_SHORT[VCVERS]);
AC_DEFINE('PHP_COMPILER_ID', VC_VERSIONS_SHORT[VCVERS], "Compiler compatibility ID");
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index d1f7eca57d..c0a1ce895b 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -414,7 +414,8 @@ can be built that way. \
'php-build', 'snapshot-template', 'ereg',
'pcre-regex', 'fastcgi', 'force-cgi-redirect',
'path-info-check', 'zts', 'ipv6', 'memory-limit',
- 'zend-multibyte', 'fd-setsize', 'memory-manager', 't1lib'
+ 'zend-multibyte', 'fd-setsize', 'memory-manager',
+ 't1lib', 'pgi', 'pgo'
);
var force;
@@ -1060,6 +1061,10 @@ function SAPI(sapiname, file_list, makefiletarget, cflags, obj_dir)
ldflags = "$(LDFLAGS)";
manifest = "-@$(_VC_MANIFEST_EMBED_EXE)";
}
+
+ if(PHP_PGI == "yes" || PHP_PGO != "no") {
+ ldflags += " /PGD:$(PGOPGD_DIR)\\" + makefiletarget.substring(0, makefiletarget.indexOf(".")) + ".pgd";
+ }
if (MODE_PHPIZE) {
if (ld) {
@@ -1199,6 +1204,7 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir)
var objs = null;
var EXT = extname.toUpperCase();
var extname_for_printing;
+ var ldflags;
if (shared == null) {
eval("shared = PHP_" + EXT + "_SHARED;");
@@ -1228,7 +1234,6 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir)
MFO.WriteLine("# objects for EXT " + extname);
MFO.WriteBlankLines(1);
-
ADD_SOURCES(configure_module_dirname, file_list, extname, obj_dir);
MFO.WriteBlankLines(1);
@@ -1242,6 +1247,11 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir)
var resname = generate_version_info_resource(dllname, extname, configure_module_dirname, false);
var ld = "@$(CC)";
+ ldflags = "";
+ if (PHP_PGI == "yes" || PHP_PGO != "no") {
+ ldflags = " /PGD:$(PGOPGD_DIR)\\" + dllname.substring(0, dllname.indexOf(".")) + ".pgd";
+ }
+
MFO.WriteLine("$(BUILD_DIR)\\" + libname + ": $(BUILD_DIR)\\" + dllname);
MFO.WriteBlankLines(1);
if (MODE_PHPIZE) {
@@ -1249,7 +1259,7 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir)
MFO.WriteLine("\t" + ld + " $(" + EXT + "_GLOBAL_OBJS) $(PHPLIB) $(LIBS_" + EXT + ") $(LIBS) $(BUILD_DIR)\\" + resname + " /link /out:$(BUILD_DIR)\\" + dllname + " $(DLL_LDFLAGS) $(LDFLAGS) $(LDFLAGS_" + EXT + ")");
} else {
MFO.WriteLine("$(BUILD_DIR)\\" + dllname + ": $(DEPS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(BUILD_DIR)\\" + resname);
- MFO.WriteLine("\t" + ld + " $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(LIBS_" + EXT + ") $(LIBS) $(BUILD_DIR)\\" + resname + " /link /out:$(BUILD_DIR)\\" + dllname + " $(DLL_LDFLAGS) $(LDFLAGS) $(LDFLAGS_" + EXT + ")");
+ MFO.WriteLine("\t" + ld + " $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(LIBS_" + EXT + ") $(LIBS) $(BUILD_DIR)\\" + resname + " /link /out:$(BUILD_DIR)\\" + dllname + ldflags + " $(DLL_LDFLAGS) $(LDFLAGS) $(LDFLAGS_" + EXT + ")");
}
MFO.WriteLine("\t-@$(_VC_MANIFEST_EMBED_DLL)");
MFO.WriteBlankLines(1);
diff --git a/win32/build/libs_version.txt b/win32/build/libs_version.txt
index 5895e7bc9d..922245d858 100644
--- a/win32/build/libs_version.txt
+++ b/win32/build/libs_version.txt
@@ -6,7 +6,7 @@ jpeglib-6b
libcurl-7.27.0
libiconv-1.14
libmcrypt-2.5.8
-libmpir-1.3.1
+libmpir-2.5.1
libpng-1.2.46
libpq-8.3.6
libssh2-1.4.2
@@ -14,4 +14,3 @@ libtidy-20090325
libxslt-1.1.27
libxml-2.7.8
openssl-0.9.8x
-
diff --git a/win32/install.txt b/win32/install.txt
index 12d109b513..b1d4ee5148 100644
--- a/win32/install.txt
+++ b/win32/install.txt
@@ -947,14 +947,6 @@ CGI environment and recommended modifications in php.ini
the web server not from the administration server. Use the command
line as root user and start it manually - you will see there are no
CGI-like environment variables.
-
- Simply change your scripts to get CGI variables in the correct way for
- PHP 5.x by using the superglobal $_SERVER. If you have older scripts
- which use $HTTP_HOST, etc., you should turn on register_globals in
- php.ini and change the variable order too (important: remove "E" from
- it, because you do not need the environment here):
-variables_order = "GPCS"
-register_globals = On
__________________________________________________________________
Special use for error pages or self-made directory listings (PHP >= 4.3.3)
@@ -1436,7 +1428,7 @@ The configuration file
; Boolean values can be set to either:
; true, on, yes
; or false, off, no, none
-register_globals = off
+html_errors = off
track_errors = yes
; you can enclose strings in double-quotes
@@ -1496,7 +1488,7 @@ Running PHP as an Apache module
Example 5-2. Apache configuration example
<IfModule mod_php5.c>
php_value include_path ".:/usr/local/lib/php"
- php_admin_flag safe_mode on
+ php_admin_flag engine on
</IfModule>
Caution
diff --git a/win32/php5dll.dsp b/win32/php5dll.dsp
index 335a0d874f..2216d7dfe6 100644
--- a/win32/php5dll.dsp
+++ b/win32/php5dll.dsp
@@ -276,10 +276,6 @@ SOURCE=..\main\php.h
# End Source File
# Begin Source File
-SOURCE=..\main\php3_compat.h
-# End Source File
-# Begin Source File
-
SOURCE=..\main\php_content_types.h
# End Source File
# Begin Source File
diff --git a/win32/php5dllts.dsp b/win32/php5dllts.dsp
index 8471418ec7..a8e93ec5e7 100644
--- a/win32/php5dllts.dsp
+++ b/win32/php5dllts.dsp
@@ -301,10 +301,6 @@ SOURCE=..\main\php.h
# End Source File
# Begin Source File
-SOURCE=..\main\php3_compat.h
-# End Source File
-# Begin Source File
-
SOURCE=..\main\php_compat.h
# End Source File
# Begin Source File
diff --git a/win32/syslog.reg b/win32/syslog.reg
index 0de1dd7f3c..4d3e273970 100644
--- a/win32/syslog.reg
+++ b/win32/syslog.reg
@@ -1,5 +1,5 @@
REGEDIT4
-[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\PHP-5.3.5-dev]
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\PHP-5.3.99-dev]
"TypesSupported"=dword:00000007
-"EventMessageFile"="g:\\test\\php53install\\php5ts.dll"
+"EventMessageFile"="g:\\test\\srcinstall6\\php5ts_debug.dll"
diff --git a/win32/winutil.c b/win32/winutil.c
index 878e95ca89..d9609f7987 100644
--- a/win32/winutil.c
+++ b/win32/winutil.c
@@ -22,7 +22,7 @@
#include "php.h"
#include <wincrypt.h>
-PHPAPI char *php_win_err(int error)
+PHPAPI char *php_win32_error_to_msg(int error)
{
char *buf = NULL;
diff --git a/win32/winutil.h b/win32/winutil.h
index d1033d475b..6cb90f7bf2 100644
--- a/win32/winutil.h
+++ b/win32/winutil.h
@@ -16,9 +16,9 @@
+----------------------------------------------------------------------+
*/
-PHPAPI char *php_win_err(int error);
+PHPAPI char *php_win32_error_to_msg(int error);
-#define php_win_err() php_win_err(GetLastError())
+#define php_win_err() php_win32_error_to_msg(GetLastError())
int php_win32_check_trailing_space(const char * path, const int path_len);
PHPAPI php_win32_get_random_bytes(unsigned char *buf, size_t size);